[Pkg-cmake-commits] [cmake] 01/10: New upstream version 3.9.0

Felix Geyer fgeyer at moszumanska.debian.org
Sat Jul 22 10:10:37 UTC 2017


This is an automated email from the git hooks/post-receive script.

fgeyer pushed a commit to branch master
in repository cmake.

commit 18330eafcdca65ddb4becfbd2b26aa69db124d5e
Author: Felix Geyer <fgeyer at debian.org>
Date:   Thu Jul 20 19:35:53 2017 +0200

    New upstream version 3.9.0
---
 .clang-tidy                                        |   30 +
 Auxiliary/cmake.m4                                 |    4 +-
 Auxiliary/vim/cmake.vim.in                         |   48 +-
 Auxiliary/vim/extract-upper-case.pl                |   27 +-
 Auxiliary/vim/indent/cmake.vim                     |    1 +
 Auxiliary/vim/syntax/cmake.vim                     |  411 +-
 CMakeLists.txt                                     |   78 +-
 CONTRIBUTING.rst                                   |   24 +-
 CompileFlags.cmake                                 |   16 +-
 Help/command/FIND_XXX.txt                          |   35 +-
 Help/command/add_custom_command.rst                |    2 +-
 Help/command/add_executable.rst                    |    3 +
 Help/command/add_library.rst                       |   15 +-
 Help/command/ctest_memcheck.rst                    |    3 +
 Help/command/ctest_submit.rst                      |   10 +-
 Help/command/ctest_test.rst                        |   17 +
 Help/command/find_file.rst                         |    3 +
 Help/command/find_library.rst                      |   18 +
 Help/command/find_package.rst                      |   30 +-
 Help/command/find_path.rst                         |    3 +
 Help/command/find_program.rst                      |    2 +
 Help/command/if.rst                                |    3 +-
 Help/command/include_external_msproject.rst        |    4 +
 Help/command/install.rst                           |   23 +-
 Help/command/project.rst                           |    5 +
 Help/command/separate_arguments.rst                |    9 +-
 Help/command/string.rst                            |   52 +-
 Help/dev/README.rst                                |   49 +
 Help/dev/maint.rst                                 |  171 +
 Help/dev/review.rst                                |  350 ++
 Help/dev/source.rst                                |   60 +
 Help/dev/testing.rst                               |   42 +
 Help/generator/VS_TOOLSET_HOST_ARCH.txt            |    8 +-
 Help/generator/Visual Studio 15 2017.rst           |   12 +
 Help/generator/Visual Studio 7 .NET 2003.rst       |   10 +-
 Help/generator/Visual Studio 8 2005.rst            |    9 +-
 Help/generator/Xcode.rst                           |    2 +
 Help/manual/OPTIONS_BUILD.txt                      |   24 +-
 Help/manual/cmake-buildsystem.7.rst                |   12 +-
 Help/manual/cmake-commands.7.rst                   |  133 +-
 Help/manual/cmake-compile-features.7.rst           |   22 +-
 Help/manual/cmake-developer.7.rst                  |   24 -
 Help/manual/cmake-generator-expressions.7.rst      |   15 +-
 Help/manual/cmake-modules.7.rst                    |    3 +
 Help/manual/cmake-policies.7.rst                   |    9 +
 Help/manual/cmake-properties.7.rst                 |   14 +
 Help/manual/cmake-qt.7.rst                         |   37 +-
 Help/manual/cmake-toolchains.7.rst                 |    5 +
 Help/manual/cmake-variables.7.rst                  |   68 +-
 Help/manual/cmake.1.rst                            |    5 +-
 Help/manual/ctest.1.rst                            |   17 +
 Help/module/CPackArchive.rst                       |    1 +
 Help/module/CheckIPOSupported.rst                  |    1 +
 Help/module/GoogleTest.rst                         |    1 +
 Help/policy/CMP0068.rst                            |   35 +
 Help/policy/CMP0069.rst                            |   92 +
 Help/prop_dir/VS_GLOBAL_SECTION_POST_section.rst   |    6 +-
 Help/prop_dir/VS_GLOBAL_SECTION_PRE_section.rst    |    2 +-
 Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst             |   15 +
 Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst           |    4 +-
 Help/prop_gbl/AUTOMOC_SOURCE_GROUP.rst             |    7 +
 Help/prop_gbl/AUTORCC_SOURCE_GROUP.rst             |    7 +
 Help/prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst     |    2 +
 Help/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst     |    2 +
 Help/prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS.rst    |   12 +
 Help/prop_gbl/GENERATOR_IS_MULTI_CONFIG.rst        |    9 +
 Help/prop_sf/HEADER_FILE_ONLY.rst                  |   15 +
 Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst           |    7 +
 Help/prop_test/DISABLED.rst                        |   15 +
 Help/prop_tgt/AUTOGEN_BUILD_DIR.rst                |   17 +
 Help/prop_tgt/AUTOMOC.rst                          |   68 +-
 Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst           |   45 +
 Help/prop_tgt/AUTORCC.rst                          |    3 +
 Help/prop_tgt/AUTOUIC.rst                          |   11 +-
 Help/prop_tgt/AUTOUIC_OPTIONS.rst                  |    2 +-
 Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst             |   12 +
 Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst      |   13 +
 Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst         |   18 +-
 Help/prop_tgt/CUDA_PTX_COMPILATION.rst             |   12 +
 Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst      |   15 +
 Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst       |    2 +-
 Help/prop_tgt/IMPORTED_OBJECTS.rst                 |   11 +
 Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst          |    7 +
 Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst     |    4 +
 .../INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst        |    4 +
 Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst       |   45 +
 Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst       |    7 +
 Help/release/3.9.rst                               |  328 +
 Help/release/index.rst                             |    1 +
 .../CMAKE_ANDROID_NDK_DEPRECATED_HEADERS.rst       |    9 +
 Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst     |   12 +
 Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst       |   11 +
 .../variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst |    7 +
 Help/variable/CMAKE_CFG_INTDIR.rst                 |    2 +-
 .../CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX.rst       |   12 +
 Help/variable/CMAKE_GENERATOR_PLATFORM.rst         |   15 +-
 Help/variable/CMAKE_GENERATOR_TOOLSET.rst          |   45 +-
 Help/variable/CMAKE_HOST_WIN32.rst                 |    4 +-
 .../CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst         |    8 +
 .../CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst  |    8 +
 Help/variable/CMAKE_LANG_COMPILER_AR.rst           |    7 +
 Help/variable/CMAKE_LANG_COMPILER_RANLIB.rst       |    7 +
 Help/variable/CMAKE_LANG_COMPILER_VERSION.rst      |    4 +
 Help/variable/CMAKE_MATCH_COUNT.rst                |    7 +-
 Help/variable/CMAKE_MATCH_n.rst                    |   10 +
 Help/variable/CMAKE_MFC_FLAG.rst                   |    2 +-
 Help/variable/CMAKE_PROJECT_DESCRIPTION.rst        |    7 +
 Help/variable/CMAKE_SYSROOT.rst                    |    3 +
 Help/variable/CMAKE_SYSROOT_COMPILE.rst            |    9 +
 Help/variable/CMAKE_SYSROOT_LINK.rst               |    9 +
 Help/variable/CMAKE_VS_DEVENV_COMMAND.rst          |    2 +-
 .../CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst     |    2 +-
 Help/variable/CMAKE_VS_PLATFORM_NAME.rst           |    1 +
 Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst        |    2 +
 Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst   |   12 +
 .../CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst   |    5 +
 Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst      |   11 +
 Help/variable/PROJECT_DESCRIPTION.rst              |    6 +
 Modules/AutogenInfo.cmake.in                       |   37 +-
 Modules/BundleUtilities.cmake                      |   13 +-
 Modules/CMakeASMCompiler.cmake.in                  |    2 +
 Modules/CMakeASMInformation.cmake                  |    6 +-
 Modules/CMakeBackwardCompatibilityC.cmake          |    6 -
 Modules/CMakeCCompiler.cmake.in                    |    3 +
 Modules/CMakeCInformation.cmake                    |    6 +-
 Modules/CMakeCSharpInformation.cmake               |   22 +-
 Modules/CMakeCUDAInformation.cmake                 |   17 +-
 Modules/CMakeCXXCompiler.cmake.in                  |    3 +
 Modules/CMakeCheckCompilerFlagCommonPatterns.cmake |    1 +
 Modules/CMakeCommonLanguageInclude.cmake           |    6 +-
 Modules/CMakeCompilerABI.h                         |    4 +
 Modules/CMakeCompilerIdDetection.cmake             |    8 +-
 Modules/CMakeDetermineASMCompiler.cmake            |   16 +-
 Modules/CMakeDetermineASM_NASMCompiler.cmake       |   17 +-
 Modules/CMakeDetermineCCompiler.cmake              |    9 +
 Modules/CMakeDetermineCSharpCompiler.cmake         |    2 +-
 Modules/CMakeDetermineCUDACompiler.cmake           |   58 +-
 Modules/CMakeDetermineCXXCompiler.cmake            |    9 +
 Modules/CMakeDetermineCompilerId.cmake             |   85 +-
 Modules/CMakeDetermineFortranCompiler.cmake        |    7 +-
 Modules/CMakeDetermineSystem.cmake                 |   18 +-
 Modules/CMakeFindBinUtils.cmake                    |    4 +
 Modules/CMakeFindDependencyMacro.cmake             |   38 +-
 Modules/CMakeFortranCompiler.cmake.in              |    2 +
 Modules/CMakeFortranCompilerId.F.in                |    5 +
 Modules/CMakeParseImplicitLinkInfo.cmake           |   23 +-
 Modules/CMakeVS7BackwardCompatibility.cmake        |   16 -
 Modules/CPack.cmake                                |   16 +-
 Modules/CPackArchive.cmake                         |   39 +
 Modules/CPackComponent.cmake                       |   69 +-
 Modules/CPackIFW.cmake                             |  162 +-
 Modules/CPackProductBuild.cmake                    |    8 +
 Modules/CPackRPM.cmake                             |   74 +-
 Modules/CPackWIX.cmake                             |   35 +-
 Modules/CTest.cmake                                |    6 +-
 Modules/CheckIPOSupported.cmake                    |  232 +
 Modules/CheckIPOSupported/CMakeLists-C.txt.in      |    8 +
 Modules/CheckIPOSupported/CMakeLists-CXX.txt.in    |    8 +
 .../CheckIPOSupported/CMakeLists-Fortran.txt.in    |    8 +
 Modules/CheckIPOSupported/foo.c                    |    4 +
 Modules/CheckIPOSupported/foo.cpp                  |    4 +
 Modules/CheckIPOSupported/foo.f                    |    2 +
 Modules/CheckIPOSupported/main.c                   |    6 +
 Modules/CheckIPOSupported/main.cpp                 |    6 +
 Modules/CheckIPOSupported/main.f                   |    3 +
 Modules/CheckLanguage.cmake                        |    2 +
 Modules/CheckSymbolExists.cmake                    |   73 +-
 Modules/CheckTypeSize.cmake                        |    4 +-
 Modules/Compiler/AppleClang-C.cmake                |   27 +-
 Modules/Compiler/AppleClang-CXX.cmake              |   31 +-
 Modules/Compiler/CMakeCommonCompilerMacros.cmake   |   93 +
 Modules/Compiler/Clang-C.cmake                     |   31 +-
 Modules/Compiler/Clang-CXX.cmake                   |   30 +-
 Modules/Compiler/Clang-FindBinUtils.cmake          |   27 +
 Modules/Compiler/Clang.cmake                       |   52 +
 Modules/Compiler/Cray-C.cmake                      |   21 +
 Modules/Compiler/Cray-CXX.cmake                    |   19 +
 Modules/Compiler/Cray.cmake                        |   10 +
 Modules/Compiler/GNU-C.cmake                       |   31 +-
 Modules/Compiler/GNU-CXX.cmake                     |   33 +-
 Modules/Compiler/GNU-FindBinUtils.cmake            |   35 +
 Modules/Compiler/GNU.cmake                         |   41 +
 Modules/Compiler/IAR-C.cmake                       |    2 +-
 Modules/Compiler/IAR-CXX.cmake                     |    2 +-
 Modules/Compiler/Intel-C.cmake                     |   59 +-
 Modules/Compiler/Intel-CXX.cmake                   |   79 +-
 Modules/Compiler/Intel.cmake                       |    4 +
 Modules/Compiler/MSVC-CXX.cmake                    |   32 +-
 Modules/Compiler/NVIDIA-CUDA.cmake                 |    6 +
 Modules/Compiler/PGI-C.cmake                       |   13 +
 Modules/Compiler/PGI-CXX.cmake                     |   19 +
 Modules/Compiler/PGI.cmake                         |   12 +-
 Modules/Compiler/QCC.cmake                         |    8 +
 Modules/Compiler/SunPro-C-FeatureTests.cmake       |   14 +
 Modules/Compiler/SunPro-C.cmake                    |   21 +
 Modules/Compiler/SunPro-CXX-FeatureTests.cmake     |    4 +
 Modules/Compiler/SunPro-CXX.cmake                  |   38 +-
 Modules/Compiler/SunPro-Fortran.cmake              |    4 +-
 Modules/Compiler/SunPro.cmake                      |   10 +
 Modules/Compiler/XL-C.cmake                        |   39 +-
 Modules/Compiler/XL-CXX.cmake                      |   44 +-
 Modules/Compiler/XL.cmake                          |    2 +
 Modules/CompilerId/VS-10.vcxproj.in                |   12 +-
 Modules/CompilerId/Xcode-1.pbxproj.in              |  120 -
 Modules/CompilerId/Xcode-2.pbxproj.in              |  119 -
 Modules/CompilerId/Xcode-3.pbxproj.in              |    2 +-
 Modules/ExternalData.cmake                         |    2 +-
 Modules/ExternalProject.cmake                      |   27 +-
 Modules/FeatureSummary.cmake                       |   61 +-
 Modules/FindBoost.cmake                            |  111 +-
 Modules/FindCUDA.cmake                             |   23 +-
 Modules/FindCygwin.cmake                           |    4 +-
 Modules/FindDevIL.cmake                            |   10 +-
 Modules/FindDoxygen.cmake                          | 1137 +++-
 Modules/FindGLEW.cmake                             |    2 +-
 Modules/FindGLUT.cmake                             |    8 +-
 Modules/FindGSL.cmake                              |   11 +-
 Modules/FindGTK2.cmake                             |    2 +
 Modules/FindGTest.cmake                            |   60 +-
 Modules/FindHDF5.cmake                             |   93 +-
 Modules/FindIce.cmake                              |    2 +-
 Modules/FindImageMagick.cmake                      |   23 +-
 Modules/FindJava.cmake                             |    3 +
 Modules/FindKDE3.cmake                             |    2 +
 Modules/FindMPI.cmake                              |  127 +-
 Modules/FindMatlab.cmake                           |    1 +
 Modules/FindOpenAL.cmake                           |    2 +-
 Modules/FindOpenCL.cmake                           |    7 +-
 Modules/FindOpenGL.cmake                           |    4 +-
 Modules/FindOpenMP.cmake                           |  541 +-
 Modules/FindOpenSSL.cmake                          |    9 +-
 Modules/FindPackageHandleStandardArgs.cmake        |    4 +-
 Modules/FindPkgConfig.cmake                        |   51 +-
 Modules/FindProtobuf.cmake                         |  129 +-
 Modules/FindPythonInterp.cmake                     |    7 +-
 Modules/FindXCTest.cmake                           |    4 +
 Modules/FindXMLRPC.cmake                           |   30 +-
 Modules/FindwxWidgets.cmake                        |   22 +
 Modules/FortranCInterface/CMakeLists.txt           |   11 +-
 Modules/FortranCInterface/Detect.cmake             |    5 +-
 Modules/FortranCInterface/MYMODULE.c               |    3 +
 Modules/FortranCInterface/MY_MODULE.c              |    3 +
 Modules/GNUInstallDirs.cmake                       |   44 +-
 Modules/GenerateExportHeader.cmake                 |    8 +-
 Modules/GetPrerequisites.cmake                     |   15 +-
 Modules/GoogleTest.cmake                           |  226 +
 Modules/InstallRequiredSystemLibraries.cmake       |    6 +
 Modules/Internal/FeatureTesting.cmake              |   10 +
 Modules/MacOSXBundleInfo.plist.in                  |    4 +
 Modules/Platform/AIX-GNU.cmake                     |    2 +-
 Modules/Platform/AIX-XL-C.cmake                    |    3 +
 Modules/Platform/AIX-XL-CXX.cmake                  |    3 +
 Modules/Platform/Android-Common.cmake              |   15 +-
 Modules/Platform/Android-Determine.cmake           |   91 +-
 Modules/Platform/Android-Initialize.cmake          |    3 +
 Modules/Platform/Android/abi-common.cmake          |    4 +
 Modules/Platform/Android/ndk-stl-c++_shared.cmake  |    1 +
 Modules/Platform/BlueGeneP-dynamic-XL-C.cmake      |    3 +
 Modules/Platform/BlueGeneP-dynamic-XL-CXX.cmake    |    3 +
 Modules/Platform/BlueGeneP-static-XL-C.cmake       |    3 +
 Modules/Platform/BlueGeneP-static-XL-CXX.cmake     |    3 +
 Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake      |    3 +
 Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake    |    3 +
 Modules/Platform/BlueGeneQ-static-XL-C.cmake       |    3 +
 Modules/Platform/BlueGeneQ-static-XL-CXX.cmake     |    3 +
 Modules/Platform/CYGWIN-GNU.cmake                  |    2 +-
 Modules/Platform/CYGWIN.cmake                      |   10 +
 Modules/Platform/Darwin-XL-C.cmake                 |    3 +
 Modules/Platform/Darwin-XL-CXX.cmake               |    3 +
 Modules/Platform/HP-UX-GNU.cmake                   |    2 +-
 Modules/Platform/Linux-GNU.cmake                   |    1 +
 Modules/Platform/Linux-Intel.cmake                 |    6 +
 Modules/Platform/Linux-PGI.cmake                   |    1 +
 Modules/Platform/Linux-TinyCC-C.cmake              |    1 +
 Modules/Platform/SunOS.cmake                       |    5 +
 Modules/Platform/UnixPaths.cmake                   |   32 +-
 Modules/Platform/Windows-GNU.cmake                 |   17 +
 Modules/Platform/Windows-MSVC.cmake                |    4 +-
 Modules/Platform/Windows-NVIDIA-CUDA.cmake         |   12 +-
 Modules/Platform/Windows-PGI-C.cmake               |    2 +
 Modules/Platform/Windows-PGI-Fortran.cmake         |    2 +
 Modules/Platform/Windows-PGI.cmake                 |   48 +
 Modules/Platform/Windows-df.cmake                  |    2 +-
 Modules/TestBigEndian.cmake                        |   26 +-
 Modules/UseEcos.cmake                              |    4 +-
 Modules/UseJava.cmake                              |   38 +-
 Modules/UseSWIG.cmake                              |    3 +
 Modules/WriteCompilerDetectionHeader.cmake         |   23 +-
 README.rst                                         |    8 +-
 Source/.gitattributes                              |   19 -
 Source/CMakeLists.txt                              |  125 +-
 Source/CMakeVersion.cmake                          |    2 +-
 Source/CPack/IFW/cmCPackIFWCommon.cxx              |  137 +
 Source/CPack/IFW/cmCPackIFWCommon.h                |   81 +
 Source/CPack/IFW/cmCPackIFWGenerator.cxx           |  340 +-
 Source/CPack/IFW/cmCPackIFWGenerator.h             |   34 +-
 Source/CPack/IFW/cmCPackIFWInstaller.cxx           |  388 +-
 Source/CPack/IFW/cmCPackIFWInstaller.h             |   19 +-
 Source/CPack/IFW/cmCPackIFWPackage.cxx             |  531 +-
 Source/CPack/IFW/cmCPackIFWPackage.h               |   27 +-
 Source/CPack/IFW/cmCPackIFWRepository.cxx          |  220 +-
 Source/CPack/IFW/cmCPackIFWRepository.h            |   18 +-
 Source/CPack/OSXScriptLauncher.cxx                 |    9 +-
 Source/CPack/WiX/cmCPackWIXGenerator.cxx           |   56 +-
 Source/CPack/WiX/cmCPackWIXGenerator.h             |    6 +-
 Source/CPack/WiX/cmWIXAccessControlList.cxx        |    4 +-
 Source/CPack/WiX/cmWIXAccessControlList.h          |    4 +-
 Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h    |    2 +-
 Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx     |    4 +-
 Source/CPack/WiX/cmWIXFeaturesSourceWriter.h       |    2 +-
 Source/CPack/WiX/cmWIXFilesSourceWriter.cxx        |   14 +-
 Source/CPack/WiX/cmWIXFilesSourceWriter.h          |    2 +-
 Source/CPack/WiX/cmWIXPatch.cxx                    |    8 +-
 Source/CPack/WiX/cmWIXPatchParser.cxx              |   30 +-
 Source/CPack/WiX/cmWIXPatchParser.h                |   10 +-
 Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx     |    2 +-
 Source/CPack/WiX/cmWIXRichTextFormatWriter.h       |    4 +-
 Source/CPack/WiX/cmWIXShortcut.h                   |    2 +-
 Source/CPack/WiX/cmWIXSourceWriter.cxx             |    4 +-
 Source/CPack/WiX/cmWIXSourceWriter.h               |    4 +-
 Source/CPack/cmCPack7zGenerator.h                  |    2 +-
 Source/CPack/cmCPackArchiveGenerator.cxx           |   67 +-
 Source/CPack/cmCPackArchiveGenerator.h             |    7 +-
 Source/CPack/cmCPackBundleGenerator.h              |    3 +-
 Source/CPack/cmCPackComponentGroup.h               |    6 +-
 Source/CPack/cmCPackCygwinBinaryGenerator.cxx      |    2 +-
 Source/CPack/cmCPackCygwinSourceGenerator.cxx      |    4 +-
 Source/CPack/cmCPackDebGenerator.cxx               |    4 +-
 Source/CPack/cmCPackDebGenerator.h                 |    2 +-
 Source/CPack/cmCPackDragNDropGenerator.cxx         |   49 +-
 Source/CPack/cmCPackDragNDropGenerator.h           |    3 +-
 Source/CPack/cmCPackGenerator.cxx                  |   28 +-
 Source/CPack/cmCPackGenerator.h                    |   31 +-
 Source/CPack/cmCPackGeneratorFactory.cxx           |    2 +-
 Source/CPack/cmCPackGeneratorFactory.h             |    2 +-
 Source/CPack/cmCPackLog.cxx                        |    2 +-
 Source/CPack/cmCPackLog.h                          |   14 +-
 Source/CPack/cmCPackNSISGenerator.cxx              |    8 +-
 Source/CPack/cmCPackNSISGenerator.h                |    2 +-
 Source/CPack/cmCPackOSXX11Generator.cxx            |    2 +-
 Source/CPack/cmCPackOSXX11Generator.h              |    3 +-
 Source/CPack/cmCPackPKGGenerator.h                 |    3 +-
 Source/CPack/cmCPackPackageMakerGenerator.cxx      |    4 +-
 Source/CPack/cmCPackPackageMakerGenerator.h        |    2 +-
 Source/CPack/cmCPackProductBuildGenerator.cxx      |   21 +-
 Source/CPack/cmCPackProductBuildGenerator.h        |    3 +-
 Source/CPack/cmCPackRPMGenerator.h                 |    2 +-
 Source/CPack/cmCPackSTGZGenerator.cxx              |    7 +-
 Source/CPack/cmCPackSTGZGenerator.h                |    2 +-
 Source/CPack/cmCPackTGZGenerator.h                 |    2 +-
 Source/CPack/cmCPackTXZGenerator.h                 |    2 +-
 Source/CPack/cmCPackTarBZip2Generator.h            |    2 +-
 Source/CPack/cmCPackTarCompressGenerator.h         |    2 +-
 Source/CPack/cmCPackZIPGenerator.h                 |    2 +-
 Source/CPack/cpack.cxx                             |   12 +-
 Source/CTest/cmCTestBZR.cxx                        |   18 +-
 Source/CTest/cmCTestBZR.h                          |   10 +-
 Source/CTest/cmCTestBatchTestHandler.h             |    6 +-
 Source/CTest/cmCTestBuildAndTestHandler.cxx        |   18 +-
 Source/CTest/cmCTestBuildAndTestHandler.h          |    4 +-
 Source/CTest/cmCTestBuildCommand.h                 |    2 +-
 Source/CTest/cmCTestBuildHandler.cxx               |   10 +-
 Source/CTest/cmCTestBuildHandler.h                 |    6 +-
 Source/CTest/cmCTestCVS.cxx                        |    4 +-
 Source/CTest/cmCTestCVS.h                          |    2 +-
 Source/CTest/cmCTestConfigureCommand.h             |    2 +-
 Source/CTest/cmCTestConfigureHandler.h             |    2 +-
 Source/CTest/cmCTestCoverageCommand.h              |    2 +-
 Source/CTest/cmCTestCoverageHandler.cxx            |   49 +-
 Source/CTest/cmCTestCoverageHandler.h              |    4 +-
 Source/CTest/cmCTestCurl.cxx                       |   27 +-
 Source/CTest/cmCTestCurl.h                         |    9 +-
 Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h  |   10 +-
 Source/CTest/cmCTestGIT.cxx                        |   20 +-
 Source/CTest/cmCTestGIT.h                          |   10 +-
 Source/CTest/cmCTestGenericHandler.cxx             |    2 +-
 Source/CTest/cmCTestGenericHandler.h               |    2 +-
 Source/CTest/cmCTestGlobalVC.cxx                   |    7 +-
 Source/CTest/cmCTestGlobalVC.h                     |    6 +-
 Source/CTest/cmCTestHG.cxx                         |   14 +-
 Source/CTest/cmCTestHG.h                           |   10 +-
 Source/CTest/cmCTestHandlerCommand.cxx             |    9 +-
 Source/CTest/cmCTestHandlerCommand.h               |    7 +-
 Source/CTest/cmCTestLaunch.cxx                     |   13 +-
 Source/CTest/cmCTestLaunch.h                       |    4 +-
 Source/CTest/cmCTestMemCheckCommand.cxx            |    1 +
 Source/CTest/cmCTestMemCheckCommand.h              |    9 +-
 Source/CTest/cmCTestMemCheckHandler.cxx            |   10 +-
 Source/CTest/cmCTestMemCheckHandler.h              |    2 +-
 Source/CTest/cmCTestMultiProcessHandler.cxx        |   31 +-
 Source/CTest/cmCTestMultiProcessHandler.h          |    4 +-
 Source/CTest/cmCTestP4.cxx                         |   18 +-
 Source/CTest/cmCTestP4.h                           |   10 +-
 Source/CTest/cmCTestReadCustomFilesCommand.h       |    7 +-
 Source/CTest/cmCTestRunScriptCommand.h             |    7 +-
 Source/CTest/cmCTestRunTest.cxx                    |   75 +-
 Source/CTest/cmCTestRunTest.h                      |    2 +-
 Source/CTest/cmCTestSVN.cxx                        |   47 +-
 Source/CTest/cmCTestSVN.h                          |   17 +-
 Source/CTest/cmCTestScriptHandler.cxx              |   51 +-
 Source/CTest/cmCTestScriptHandler.h                |    4 +-
 Source/CTest/cmCTestSleepCommand.h                 |    7 +-
 Source/CTest/cmCTestStartCommand.h                 |    7 +-
 Source/CTest/cmCTestSubmitCommand.cxx              |   16 +
 Source/CTest/cmCTestSubmitCommand.h                |    4 +-
 Source/CTest/cmCTestSubmitHandler.cxx              |   39 +-
 Source/CTest/cmCTestSubmitHandler.h                |    8 +-
 Source/CTest/cmCTestTestCommand.cxx                |   18 +-
 Source/CTest/cmCTestTestCommand.h                  |    5 +-
 Source/CTest/cmCTestTestHandler.cxx                |  333 +-
 Source/CTest/cmCTestTestHandler.h                  |    8 +-
 Source/CTest/cmCTestUpdateCommand.h                |    2 +-
 Source/CTest/cmCTestUpdateHandler.cxx              |    6 +-
 Source/CTest/cmCTestUpdateHandler.h                |    2 +-
 Source/CTest/cmCTestUploadCommand.h                |    2 +-
 Source/CTest/cmCTestUploadHandler.h                |    2 +-
 Source/CTest/cmCTestVC.cxx                         |   14 +-
 Source/CTest/cmCTestVC.h                           |    6 +-
 Source/CTest/cmParseBlanketJSCoverage.cxx          |   38 +-
 Source/CTest/cmParseBlanketJSCoverage.h            |    2 +-
 Source/CTest/cmParseCacheCoverage.cxx              |    4 +-
 Source/CTest/cmParseCacheCoverage.h                |    2 +-
 Source/CTest/cmParseCoberturaCoverage.cxx          |    4 +-
 Source/CTest/cmParseCoberturaCoverage.h            |    2 +-
 Source/CTest/cmParseDelphiCoverage.cxx             |   83 +-
 Source/CTest/cmParseDelphiCoverage.h               |    2 +-
 Source/CTest/cmParseGTMCoverage.cxx                |    8 +-
 Source/CTest/cmParseGTMCoverage.h                  |    2 +-
 Source/CTest/cmParseJacocoCoverage.cxx             |    8 +-
 Source/CTest/cmParseJacocoCoverage.h               |    2 +-
 Source/CTest/cmParseMumpsCoverage.cxx              |    6 +-
 Source/CTest/cmParseMumpsCoverage.h                |    2 +-
 Source/CTest/cmParsePHPCoverage.cxx                |    4 +-
 Source/CTest/cmParsePHPCoverage.h                  |    2 +-
 Source/CTest/cmProcess.cxx                         |    6 +-
 Source/CTest/cmProcess.h                           |    4 +-
 Source/Checks/cm_cxx_attribute_fallthrough.cxx     |   11 +
 Source/Checks/cm_cxx_eq_delete.cxx                 |   14 +
 Source/Checks/cm_cxx_fallthrough.cxx               |   11 +
 Source/Checks/cm_cxx_features.cmake                |   37 +-
 Source/Checks/cm_cxx_gnu_fallthrough.cxx           |   11 +
 Source/CursesDialog/ccmake.cxx                     |    6 +-
 Source/CursesDialog/cmCursesBoolWidget.h           |    8 +-
 .../CursesDialog/cmCursesCacheEntryComposite.cxx   |    1 -
 Source/CursesDialog/cmCursesCacheEntryComposite.h  |    7 +-
 Source/CursesDialog/cmCursesDummyWidget.h          |    8 +-
 Source/CursesDialog/cmCursesFilePathWidget.h       |    8 +-
 Source/CursesDialog/cmCursesForm.cxx               |    2 -
 Source/CursesDialog/cmCursesForm.h                 |    9 +-
 Source/CursesDialog/cmCursesLabelWidget.h          |    8 +-
 Source/CursesDialog/cmCursesLongMessageForm.cxx    |    3 +-
 Source/CursesDialog/cmCursesLongMessageForm.h      |    7 +-
 Source/CursesDialog/cmCursesMainForm.cxx           |    9 +-
 Source/CursesDialog/cmCursesMainForm.h             |    7 +-
 Source/CursesDialog/cmCursesOptionsWidget.h        |    6 +-
 Source/CursesDialog/cmCursesPathWidget.h           |    7 +-
 Source/CursesDialog/cmCursesStandardIncludes.h     |    2 +-
 Source/CursesDialog/cmCursesStringWidget.h         |    7 +-
 Source/CursesDialog/cmCursesWidget.cxx             |    2 -
 Source/CursesDialog/cmCursesWidget.h               |    7 +-
 Source/CursesDialog/form/form.h                    |    2 +-
 Source/LexerParser/.clang-tidy                     |    6 +
 Source/LexerParser/.gitattributes                  |   17 +
 .../{ => LexerParser}/cmCommandArgumentLexer.cxx   |    0
 Source/{ => LexerParser}/cmCommandArgumentLexer.h  |    0
 .../{ => LexerParser}/cmCommandArgumentLexer.in.l  |    0
 Source/LexerParser/cmCommandArgumentParser.cxx     | 1723 ++++++
 Source/LexerParser/cmCommandArgumentParser.y       |  191 +
 Source/LexerParser/cmCommandArgumentParserTokens.h |   82 +
 Source/{ => LexerParser}/cmDependsJavaLexer.cxx    |    0
 Source/{ => LexerParser}/cmDependsJavaLexer.h      |    0
 Source/{ => LexerParser}/cmDependsJavaLexer.in.l   |    0
 Source/LexerParser/cmDependsJavaParser.cxx         | 6421 ++++++++++++++++++++
 Source/LexerParser/cmDependsJavaParser.y           | 3214 ++++++++++
 Source/LexerParser/cmDependsJavaParserTokens.h     |  264 +
 Source/{ => LexerParser}/cmExprLexer.cxx           |    0
 Source/{ => LexerParser}/cmExprLexer.h             |    0
 Source/{ => LexerParser}/cmExprLexer.in.l          |    0
 Source/LexerParser/cmExprParser.cxx                | 1698 ++++++
 Source/LexerParser/cmExprParser.y                  |  164 +
 Source/{ => LexerParser}/cmExprParserTokens.h      |    0
 Source/{ => LexerParser}/cmFortranLexer.cxx        |    0
 Source/{ => LexerParser}/cmFortranLexer.h          |    0
 Source/{ => LexerParser}/cmFortranLexer.in.l       |    0
 Source/LexerParser/cmFortranParser.cxx             | 1988 ++++++
 Source/LexerParser/cmFortranParser.y               |  247 +
 Source/LexerParser/cmFortranParserTokens.h         |  149 +
 Source/LexerParser/cmListFileLexer.c               | 2688 ++++++++
 Source/LexerParser/cmListFileLexer.in.l            |  564 ++
 Source/Modules/FindLibUV.cmake                     |    2 +-
 Source/QtDialog/CMakeLists.txt                     |   21 +-
 Source/QtDialog/CMakeSetup.cxx                     |   10 +-
 Source/QtDialog/CMakeSetupDialog.cxx               |   15 +-
 Source/QtDialog/Compilers.h                        |    2 +-
 Source/QtDialog/FirstConfigure.cxx                 |    2 +-
 Source/QtDialog/QCMake.cxx                         |    6 +-
 Source/QtDialog/QCMake.h                           |    2 +-
 Source/QtDialog/QCMakeCacheView.cxx                |   26 +-
 Source/QtDialog/QCMakeWidgets.cxx                  |    8 +-
 Source/QtDialog/QCMakeWidgets.h                    |    2 +-
 Source/QtDialog/RegexExplorer.h                    |    2 +-
 .../QtDialog/{CMake.desktop => cmake-gui.desktop}  |    0
 Source/bindexplib.cxx                              |  505 +-
 Source/bindexplib.h                                |    4 +-
 Source/cmAddCompileOptionsCommand.h                |    8 +-
 Source/cmAddCustomCommandCommand.cxx               |    2 +-
 Source/cmAddCustomCommandCommand.h                 |    8 +-
 Source/cmAddCustomTargetCommand.cxx                |    6 +-
 Source/cmAddCustomTargetCommand.h                  |    8 +-
 Source/cmAddDefinitionsCommand.h                   |    8 +-
 Source/cmAddDependenciesCommand.cxx                |    2 +-
 Source/cmAddDependenciesCommand.h                  |    8 +-
 Source/cmAddExecutableCommand.cxx                  |    2 +-
 Source/cmAddExecutableCommand.h                    |    8 +-
 Source/cmAddLibraryCommand.cxx                     |   15 +-
 Source/cmAddLibraryCommand.h                       |    8 +-
 Source/cmAddSubDirectoryCommand.cxx                |    5 +-
 Source/cmAddSubDirectoryCommand.h                  |    8 +-
 Source/cmAddTestCommand.h                          |    8 +-
 Source/cmAlgorithms.h                              |   13 +-
 Source/cmArchiveWrite.cxx                          |    8 +-
 Source/cmArchiveWrite.h                            |    2 +-
 Source/cmAuxSourceDirectoryCommand.cxx             |    8 +-
 Source/cmAuxSourceDirectoryCommand.h               |    8 +-
 Source/cmBase32.cxx                                |    2 +-
 Source/cmBase32.h                                  |    2 +-
 Source/cmBreakCommand.cxx                          |    2 +-
 Source/cmBreakCommand.h                            |   13 +-
 Source/cmBuildCommand.cxx                          |    4 +-
 Source/cmBuildCommand.h                            |    8 +-
 Source/cmBuildNameCommand.cxx                      |    8 +-
 Source/cmBuildNameCommand.h                        |    5 +-
 Source/cmCLocaleEnvironmentScope.h                 |    4 +-
 Source/cmCMakeHostSystemInformationCommand.cxx     |    4 +-
 Source/cmCMakeHostSystemInformationCommand.h       |   16 +-
 Source/cmCMakeMinimumRequired.h                    |   13 +-
 Source/cmCMakePolicyCommand.h                      |   13 +-
 Source/cmCPackPropertiesGenerator.cxx              |    2 +-
 Source/cmCPackPropertiesGenerator.h                |    6 +-
 Source/cmCTest.cxx                                 |   69 +-
 Source/cmCTest.h                                   |   39 +-
 Source/cmCacheManager.cxx                          |   11 +-
 Source/cmCacheManager.h                            |    4 +-
 Source/cmCallVisualStudioMacro.h                   |    2 +-
 Source/cmCommand.cxx                               |   25 +-
 Source/cmCommand.h                                 |   28 +-
 Source/cmCommandArgumentParser.cxx                 | 1811 ------
 Source/cmCommandArgumentParser.y                   |  231 -
 Source/cmCommandArgumentParserHelper.cxx           |    3 -
 Source/cmCommandArgumentParserHelper.h             |   26 +-
 Source/cmCommandArgumentParserTokens.h             |   83 -
 Source/cmCommandArgumentsHelper.h                  |    2 +-
 Source/cmCommands.cxx                              |  344 +-
 Source/cmCommands.h                                |   11 +-
 Source/cmCommonTargetGenerator.cxx                 |   33 +-
 Source/cmCommonTargetGenerator.h                   |   10 +-
 Source/cmComputeComponentGraph.h                   |    2 +-
 Source/cmComputeLinkDepends.cxx                    |    2 +-
 Source/cmComputeLinkDepends.h                      |    4 +-
 Source/cmComputeLinkInformation.cxx                |   32 +-
 Source/cmComputeLinkInformation.h                  |   10 +-
 Source/cmComputeTargetDepends.cxx                  |   18 +-
 Source/cmComputeTargetDepends.h                    |    3 +-
 Source/cmConditionEvaluator.cxx                    |    8 +-
 Source/cmConditionEvaluator.h                      |    2 +-
 Source/cmConfigure.cmake.h.in                      |   26 +-
 Source/cmConfigureFileCommand.cxx                  |    4 +-
 Source/cmConfigureFileCommand.h                    |   13 +-
 Source/cmContinueCommand.cxx                       |    2 +-
 Source/cmContinueCommand.h                         |   13 +-
 Source/cmCoreTryCompile.cxx                        |   15 +-
 Source/cmCoreTryCompile.h                          |    2 +-
 Source/cmCreateTestSourceList.h                    |    7 +-
 Source/cmCryptoHash.cxx                            |    6 +-
 Source/cmCryptoHash.h                              |    4 +-
 Source/cmCurl.h                                    |    4 +-
 Source/cmCustomCommand.cxx                         |    2 +-
 Source/cmCustomCommand.h                           |    2 +-
 Source/cmCustomCommandGenerator.cxx                |    2 +-
 Source/cmCustomCommandGenerator.h                  |    2 +-
 Source/cmCustomCommandLines.h                      |    2 +-
 Source/cmDefinePropertyCommand.cxx                 |   18 +-
 Source/cmDefinePropertyCommand.h                   |    8 +-
 Source/cmDefinitions.cxx                           |    2 +-
 Source/cmDefinitions.h                             |    8 +-
 Source/cmDepends.cxx                               |   16 +-
 Source/cmDepends.h                                 |    8 +-
 Source/cmDependsC.cxx                              |    6 +-
 Source/cmDependsC.h                                |   10 +-
 Source/cmDependsFortran.cxx                        |    2 +-
 Source/cmDependsFortran.h                          |    8 +-
 Source/cmDependsJava.h                             |    8 +-
 Source/cmDependsJavaParser.cxx                     | 6006 ------------------
 Source/cmDependsJavaParser.y                       | 3212 ----------
 Source/cmDependsJavaParserHelper.cxx               |    4 +-
 Source/cmDependsJavaParserHelper.h                 |   19 +-
 Source/cmDependsJavaParserTokens.h                 |  254 -
 Source/cmDisallowedCommand.cxx                     |   31 +
 Source/cmDisallowedCommand.h                       |   51 +
 Source/cmDocumentation.cxx                         |   21 +-
 Source/cmDocumentation.h                           |    2 +-
 Source/cmDocumentationEntry.h                      |    2 +-
 Source/cmDocumentationFormatter.h                  |    2 +-
 Source/cmDocumentationSection.h                    |    2 +-
 Source/cmDynamicLoader.cxx                         |   10 +-
 Source/cmDynamicLoader.h                           |   10 +-
 Source/cmELF.cxx                                   |   21 +-
 Source/cmELF.h                                     |    2 +-
 Source/cmEnableLanguageCommand.h                   |    8 +-
 Source/cmEnableTestingCommand.h                    |    8 +-
 Source/cmExecProgramCommand.cxx                    |    2 +-
 Source/cmExecProgramCommand.h                      |   13 +-
 Source/cmExecuteProcessCommand.cxx                 |    2 +-
 Source/cmExecuteProcessCommand.h                   |   13 +-
 Source/cmExecutionStatus.h                         |   31 +-
 Source/cmExpandedCommandArgument.h                 |    2 +-
 Source/cmExportBuildAndroidMKGenerator.h           |    2 +-
 Source/cmExportBuildFileGenerator.cxx              |   65 +-
 Source/cmExportBuildFileGenerator.h                |    2 +-
 Source/cmExportCommand.cxx                         |   17 +-
 Source/cmExportCommand.h                           |    9 +-
 Source/cmExportFileGenerator.cxx                   |   34 +-
 Source/cmExportFileGenerator.h                     |    2 +-
 Source/cmExportInstallAndroidMKGenerator.h         |    2 +-
 Source/cmExportInstallFileGenerator.cxx            |   26 +-
 Source/cmExportInstallFileGenerator.h              |    2 +-
 Source/cmExportLibraryDependenciesCommand.cxx      |    9 +-
 Source/cmExportLibraryDependenciesCommand.h        |    7 +-
 Source/cmExportSet.h                               |    2 +-
 Source/cmExportSetMap.h                            |    2 +-
 Source/cmExportTryCompileFileGenerator.h           |    2 +-
 Source/cmExprParser.cxx                            | 1696 ------
 Source/cmExprParser.y                              |  162 -
 Source/cmExprParserHelper.cxx                      |    2 +-
 Source/cmExprParserHelper.h                        |   21 +-
 Source/cmExternalMakefileProjectGenerator.h        |    2 +-
 Source/cmExtraCodeBlocksGenerator.cxx              |    8 +-
 Source/cmExtraCodeBlocksGenerator.h                |    2 +-
 Source/cmExtraCodeLiteGenerator.cxx                |  109 +-
 Source/cmExtraCodeLiteGenerator.h                  |    6 +-
 Source/cmExtraEclipseCDT4Generator.cxx             |    6 +-
 Source/cmExtraEclipseCDT4Generator.h               |    2 +-
 Source/cmExtraKateGenerator.h                      |    2 +-
 Source/cmExtraSublimeTextGenerator.cxx             |    2 +-
 Source/cmExtraSublimeTextGenerator.h               |    2 +-
 Source/cmFLTKWrapUICommand.h                       |    8 +-
 Source/cmFileCommand.cxx                           |  182 +-
 Source/cmFileCommand.h                             |   14 +-
 Source/cmFileLock.h                                |    7 +-
 Source/cmFileLockPool.h                            |   18 +-
 Source/cmFileLockResult.h                          |    2 +-
 Source/cmFileMonitor.cxx                           |   20 +-
 Source/cmFileMonitor.h                             |    4 +
 Source/cmFilePathChecksum.cxx                      |    4 +-
 Source/cmFilePathChecksum.h                        |    6 +-
 Source/cmFileTimeComparison.cxx                    |    4 +-
 Source/cmFileTimeComparison.h                      |    2 +-
 Source/cmFindBase.cxx                              |   26 +-
 Source/cmFindBase.h                                |    3 +-
 Source/cmFindCommon.cxx                            |   52 +-
 Source/cmFindCommon.h                              |   12 +-
 Source/cmFindFileCommand.h                         |    4 +-
 Source/cmFindLibraryCommand.cxx                    |   39 +-
 Source/cmFindLibraryCommand.h                      |   13 +-
 Source/cmFindPackageCommand.cxx                    |  259 +-
 Source/cmFindPackageCommand.h                      |   16 +-
 Source/cmFindPathCommand.cxx                       |    6 +-
 Source/cmFindPathCommand.h                         |   13 +-
 Source/cmFindProgramCommand.cxx                    |    3 +-
 Source/cmFindProgramCommand.h                      |   15 +-
 Source/cmForEachCommand.cxx                        |    2 +-
 Source/cmForEachCommand.h                          |   13 +-
 Source/cmFortranParser.cxx                         | 1984 ------
 Source/cmFortranParser.h                           |    9 +-
 Source/cmFortranParser.y                           |  243 -
 Source/cmFortranParserImpl.cxx                     |    3 +-
 Source/cmFortranParserTokens.h                     |  149 -
 Source/cmFunctionCommand.cxx                       |   23 +-
 Source/cmFunctionCommand.h                         |   13 +-
 Source/cmGeneratedFileStream.cxx                   |    2 +-
 Source/cmGeneratedFileStream.h                     |    6 +-
 Source/cmGeneratorExpression.cxx                   |    8 +-
 Source/cmGeneratorExpression.h                     |   14 +-
 Source/cmGeneratorExpressionDAGChecker.h           |    2 +-
 Source/cmGeneratorExpressionEvaluationFile.cxx     |   10 +-
 Source/cmGeneratorExpressionEvaluationFile.h       |    9 +-
 Source/cmGeneratorExpressionEvaluator.h            |    5 +-
 Source/cmGeneratorExpressionLexer.h                |    2 +-
 Source/cmGeneratorExpressionNode.cxx               |  171 +-
 Source/cmGeneratorExpressionNode.h                 |    2 +-
 Source/cmGeneratorExpressionParser.h               |    2 +-
 Source/cmGeneratorTarget.cxx                       | 1203 ++--
 Source/cmGeneratorTarget.h                         |  217 +-
 Source/cmGetCMakePropertyCommand.cxx               |    2 +-
 Source/cmGetCMakePropertyCommand.h                 |   13 +-
 Source/cmGetDirectoryPropertyCommand.cxx           |    3 +-
 Source/cmGetDirectoryPropertyCommand.h             |   13 +-
 Source/cmGetFilenameComponentCommand.cxx           |    6 +-
 Source/cmGetFilenameComponentCommand.h             |   13 +-
 Source/cmGetPropertyCommand.cxx                    |    1 +
 Source/cmGetPropertyCommand.h                      |   13 +-
 Source/cmGetSourceFilePropertyCommand.cxx          |    4 +-
 Source/cmGetSourceFilePropertyCommand.h            |   11 +-
 Source/cmGetTargetPropertyCommand.cxx              |    4 +-
 Source/cmGetTargetPropertyCommand.h                |    8 +-
 Source/cmGetTestPropertyCommand.cxx                |    4 +-
 Source/cmGetTestPropertyCommand.h                  |    8 +-
 Source/cmGhsMultiGpj.h                             |    2 +-
 Source/cmGhsMultiTargetGenerator.cxx               |    8 +-
 Source/cmGlobalCommonGenerator.h                   |    2 +-
 Source/cmGlobalGenerator.cxx                       |   95 +-
 Source/cmGlobalGenerator.h                         |   28 +-
 Source/cmGlobalGeneratorFactory.h                  |    2 +-
 Source/cmGlobalGhsMultiGenerator.cxx               |    2 +-
 Source/cmGlobalKdevelopGenerator.cxx               |    6 +-
 Source/cmGlobalKdevelopGenerator.h                 |    2 +-
 Source/cmGlobalMSYSMakefileGenerator.cxx           |    2 +-
 Source/cmGlobalNinjaGenerator.cxx                  |   71 +-
 Source/cmGlobalNinjaGenerator.h                    |   17 +-
 Source/cmGlobalUnixMakefileGenerator3.h            |    4 +-
 Source/cmGlobalVisualStudio10Generator.cxx         |  392 +-
 Source/cmGlobalVisualStudio10Generator.h           |   33 +-
 Source/cmGlobalVisualStudio11Generator.h           |    2 +-
 Source/cmGlobalVisualStudio12Generator.cxx         |   16 +-
 Source/cmGlobalVisualStudio12Generator.h           |    6 +-
 Source/cmGlobalVisualStudio14Generator.cxx         |   53 +-
 Source/cmGlobalVisualStudio14Generator.h           |    2 +-
 Source/cmGlobalVisualStudio15Generator.cxx         |    4 +-
 Source/cmGlobalVisualStudio15Generator.h           |    2 +-
 Source/cmGlobalVisualStudio71Generator.cxx         |   83 +-
 Source/cmGlobalVisualStudio71Generator.h           |   33 +-
 Source/cmGlobalVisualStudio7Generator.cxx          |   54 +-
 Source/cmGlobalVisualStudio7Generator.h            |    6 +-
 Source/cmGlobalVisualStudio8Generator.cxx          |   24 +-
 Source/cmGlobalVisualStudio8Generator.h            |    7 +-
 Source/cmGlobalVisualStudioGenerator.cxx           |  102 +-
 Source/cmGlobalVisualStudioGenerator.h             |    4 +-
 Source/cmGlobalWatcomWMakeGenerator.h              |    2 +-
 Source/cmGlobalXCodeGenerator.cxx                  |  883 +--
 Source/cmGlobalXCodeGenerator.h                    |   22 +-
 Source/cmGraphAdjacencyList.h                      |   19 +-
 Source/cmGraphVizWriter.cxx                        |    4 +-
 Source/cmGraphVizWriter.h                          |    4 +-
 Source/cmHexFileConverter.cxx                      |    2 +-
 Source/cmIDEFlagTable.h                            |    3 +
 Source/cmIDEOptions.cxx                            |   10 +-
 Source/cmIDEOptions.h                              |   16 +-
 Source/cmIfCommand.cxx                             |   26 +-
 Source/cmIfCommand.h                               |   15 +-
 Source/cmIncludeCommand.h                          |   13 +-
 Source/cmIncludeDirectoryCommand.cxx               |    2 +-
 Source/cmIncludeDirectoryCommand.h                 |    8 +-
 Source/cmIncludeExternalMSProjectCommand.h         |   11 +-
 Source/cmIncludeRegularExpressionCommand.h         |   11 +-
 Source/cmInstallCommand.cxx                        |   86 +-
 Source/cmInstallCommand.h                          |    8 +-
 Source/cmInstallCommandArguments.cxx               |    2 +-
 Source/cmInstallCommandArguments.h                 |    2 +-
 Source/cmInstallDirectoryGenerator.cxx             |    6 +-
 Source/cmInstallDirectoryGenerator.h               |   10 +-
 Source/cmInstallExportGenerator.cxx                |    4 +-
 Source/cmInstallExportGenerator.h                  |    8 +-
 Source/cmInstallFilesCommand.cxx                   |    6 +-
 Source/cmInstallFilesCommand.h                     |    8 +-
 Source/cmInstallFilesGenerator.cxx                 |    6 +-
 Source/cmInstallFilesGenerator.h                   |    9 +-
 Source/cmInstallGenerator.cxx                      |    2 +-
 Source/cmInstallGenerator.h                        |    6 +-
 Source/cmInstallProgramsCommand.h                  |    8 +-
 Source/cmInstallScriptGenerator.h                  |    2 +-
 Source/cmInstallTargetGenerator.cxx                |  115 +-
 Source/cmInstallTargetGenerator.h                  |   37 +-
 Source/cmInstallTargetsCommand.h                   |    8 +-
 Source/cmInstalledFile.cxx                         |    2 +-
 Source/cmInstalledFile.h                           |    2 +
 Source/cmLinkDirectoriesCommand.cxx                |    1 +
 Source/cmLinkDirectoriesCommand.h                  |    8 +-
 Source/cmLinkItem.h                                |   13 +-
 Source/cmLinkLibrariesCommand.h                    |    8 +-
 Source/cmLinkLineComputer.cxx                      |    2 +-
 Source/cmLinkLineComputer.h                        |    6 +-
 Source/cmLinkLineDeviceComputer.cxx                |   34 +-
 Source/cmLinkLineDeviceComputer.h                  |   17 +-
 Source/cmLinkedTree.h                              |    2 +-
 Source/cmListCommand.cxx                           |    2 +-
 Source/cmListCommand.h                             |   13 +-
 Source/cmListFileCache.cxx                         |   22 +-
 Source/cmListFileCache.h                           |   14 +-
 Source/cmListFileLexer.c                           | 2684 --------
 Source/cmListFileLexer.h                           |    1 +
 Source/cmListFileLexer.in.l                        |  564 --
 Source/cmLoadCacheCommand.cxx                      |    2 +-
 Source/cmLoadCacheCommand.h                        |    8 +-
 Source/cmLoadCommandCommand.cxx                    |   25 +-
 Source/cmLoadCommandCommand.h                      |    4 +-
 Source/cmLocalCommonGenerator.cxx                  |   12 +-
 Source/cmLocalCommonGenerator.h                    |    3 +-
 Source/cmLocalGenerator.cxx                        |  188 +-
 Source/cmLocalGenerator.h                          |   21 +-
 Source/cmLocalNinjaGenerator.cxx                   |   30 +-
 Source/cmLocalNinjaGenerator.h                     |    6 +-
 Source/cmLocalUnixMakefileGenerator3.cxx           |   44 +-
 Source/cmLocalUnixMakefileGenerator3.h             |    2 +-
 Source/cmLocalVisualStudio10Generator.cxx          |    2 +-
 Source/cmLocalVisualStudio10Generator.h            |    2 +-
 Source/cmLocalVisualStudio7Generator.cxx           |  206 +-
 Source/cmLocalVisualStudio7Generator.h             |    6 +-
 Source/cmLocalVisualStudioGenerator.cxx            |   24 +-
 Source/cmLocalVisualStudioGenerator.h              |    2 +-
 Source/cmLocalXCodeGenerator.h                     |    3 +-
 Source/cmLocale.h                                  |    7 +-
 Source/cmMSVC60LinkLineComputer.cxx                |    6 +-
 Source/cmMSVC60LinkLineComputer.h                  |    6 +-
 Source/cmMachO.cxx                                 |    2 +-
 Source/cmMachO.h                                   |    2 +-
 Source/cmMacroCommand.cxx                          |   26 +-
 Source/cmMacroCommand.h                            |   13 +-
 Source/cmMakeDirectoryCommand.h                    |   13 +-
 Source/cmMakefile.cxx                              |  142 +-
 Source/cmMakefile.h                                |   33 +-
 Source/cmMakefileExecutableTargetGenerator.cxx     |   25 +-
 Source/cmMakefileExecutableTargetGenerator.h       |    4 +-
 Source/cmMakefileLibraryTargetGenerator.cxx        |   80 +-
 Source/cmMakefileLibraryTargetGenerator.h          |    2 +-
 Source/cmMakefileTargetGenerator.cxx               |  103 +-
 Source/cmMakefileTargetGenerator.h                 |    7 +-
 Source/cmMakefileUtilityTargetGenerator.h          |    2 +-
 Source/cmMarkAsAdvancedCommand.cxx                 |    2 +-
 Source/cmMarkAsAdvancedCommand.h                   |   16 +-
 Source/cmMathCommand.h                             |   13 +-
 Source/cmMessageCommand.h                          |   13 +-
 Source/cmMessenger.cxx                             |    2 +-
 Source/cmMessenger.h                               |    2 +-
 Source/cmNewLineStyle.cxx                          |    2 +-
 Source/cmNewLineStyle.h                            |    2 +-
 Source/cmNinjaLinkLineComputer.cxx                 |    3 +-
 Source/cmNinjaLinkLineComputer.h                   |    6 +-
 Source/cmNinjaNormalTargetGenerator.cxx            |  170 +-
 Source/cmNinjaNormalTargetGenerator.h              |    2 +-
 Source/cmNinjaTargetGenerator.cxx                  |  103 +-
 Source/cmNinjaTargetGenerator.h                    |    5 +-
 Source/cmNinjaTypes.h                              |    8 +-
 Source/cmNinjaUtilityTargetGenerator.h             |    2 +-
 Source/cmOSXBundleGenerator.cxx                    |   35 +-
 Source/cmOSXBundleGenerator.h                      |    2 +-
 Source/cmOptionCommand.h                           |   13 +-
 Source/cmOrderDirectories.cxx                      |    2 +-
 Source/cmOrderDirectories.h                        |    4 +-
 Source/cmOutputConverter.cxx                       |    4 +-
 Source/cmOutputConverter.h                         |    6 +-
 Source/cmOutputRequiredFilesCommand.cxx            |   13 +-
 Source/cmOutputRequiredFilesCommand.h              |    4 +-
 Source/cmParseArgumentsCommand.h                   |   13 +-
 Source/cmPathLabel.h                               |    2 +-
 Source/cmPolicies.cxx                              |   18 +-
 Source/cmPolicies.h                                |   15 +-
 Source/cmProcessOutput.h                           |    2 +-
 Source/cmProcessTools.cxx                          |    2 +-
 Source/cmProcessTools.h                            |    2 +-
 Source/cmProjectCommand.cxx                        |   74 +-
 Source/cmProjectCommand.h                          |    8 +-
 Source/cmProperty.cxx                              |    2 +-
 Source/cmProperty.h                                |    2 +-
 Source/cmPropertyDefinition.h                      |    2 +-
 Source/cmPropertyDefinitionMap.h                   |    2 +-
 Source/cmPropertyMap.cxx                           |    2 +-
 Source/cmPropertyMap.h                             |    2 +-
 Source/cmQTWrapCPPCommand.h                        |    8 +-
 Source/cmQTWrapUICommand.h                         |    8 +-
 Source/cmQtAutoGeneratorCommon.cxx                 |  216 +
 Source/cmQtAutoGeneratorCommon.h                   |   39 +
 Source/cmQtAutoGeneratorInitializer.cxx            | 1295 ++--
 Source/cmQtAutoGeneratorInitializer.h              |    2 +-
 Source/cmQtAutoGenerators.cxx                      | 2326 ++++---
 Source/cmQtAutoGenerators.h                        |  255 +-
 Source/cmRST.cxx                                   |   22 +-
 Source/cmRST.h                                     |    4 +-
 Source/cmRemoveCommand.cxx                         |    2 +-
 Source/cmRemoveCommand.h                           |   13 +-
 Source/cmRemoveDefinitionsCommand.h                |    8 +-
 Source/cmReturnCommand.cxx                         |    2 +-
 Source/cmReturnCommand.h                           |   13 +-
 Source/cmRulePlaceholderExpander.cxx               |   26 +-
 Source/cmRulePlaceholderExpander.h                 |    5 +-
 Source/cmScriptGenerator.cxx                       |   14 +-
 Source/cmScriptGenerator.h                         |   18 +-
 Source/cmSearchPath.h                              |    2 +-
 Source/cmSeparateArgumentsCommand.cxx              |    7 +
 Source/cmSeparateArgumentsCommand.h                |   13 +-
 Source/cmServer.cxx                                |   21 +-
 Source/cmServer.h                                  |    7 +-
 Source/cmServerConnection.cxx                      |    3 +-
 Source/cmServerConnection.h                        |   12 +-
 Source/cmServerProtocol.cxx                        |   58 +-
 Source/cmServerProtocol.h                          |   16 +-
 Source/cmSetCommand.h                              |   13 +-
 Source/cmSetDirectoryPropertiesCommand.h           |   16 +-
 Source/cmSetPropertyCommand.cxx                    |   12 +-
 Source/cmSetPropertyCommand.h                      |   13 +-
 Source/cmSetSourceFilesPropertiesCommand.h         |   11 +-
 Source/cmSetTargetPropertiesCommand.cxx            |    3 +-
 Source/cmSetTargetPropertiesCommand.h              |    8 +-
 Source/cmSetTestsPropertiesCommand.cxx             |    3 +-
 Source/cmSetTestsPropertiesCommand.h               |    8 +-
 Source/cmSiteNameCommand.cxx                       |    2 +-
 Source/cmSiteNameCommand.h                         |   13 +-
 Source/cmSourceFile.h                              |    2 +-
 Source/cmSourceFileLocation.cxx                    |    2 +-
 Source/cmSourceFileLocation.h                      |    2 +-
 Source/cmSourceGroup.h                             |    4 +-
 Source/cmSourceGroupCommand.cxx                    |   79 +-
 Source/cmSourceGroupCommand.h                      |    8 +-
 Source/cmStandardIncludes.h                        |   53 -
 Source/cmStandardLexer.h                           |    4 +-
 Source/cmState.cxx                                 |  158 +-
 Source/cmState.h                                   |   44 +-
 Source/cmStateDirectory.h                          |    2 +-
 Source/cmStatePrivate.h                            |    7 +-
 Source/cmStateSnapshot.cxx                         |   12 +-
 Source/cmStateSnapshot.h                           |    4 +-
 Source/cmStateTypes.h                              |   11 +-
 Source/cmStringCommand.cxx                         |   24 +-
 Source/cmStringCommand.h                           |   13 +-
 Source/cmSubdirCommand.h                           |    8 +-
 Source/cmSubdirDependsCommand.cxx                  |    5 -
 Source/cmSubdirDependsCommand.h                    |    4 +-
 Source/cmSystemTools.cxx                           |  163 +-
 Source/cmSystemTools.h                             |   26 +-
 Source/cmTarget.cxx                                |  199 +-
 Source/cmTarget.h                                  |   10 +-
 Source/cmTargetCompileDefinitionsCommand.h         |   11 +-
 Source/cmTargetCompileFeaturesCommand.h            |    5 +-
 Source/cmTargetCompileOptionsCommand.h             |    8 +-
 Source/cmTargetDepend.h                            |    4 +-
 Source/cmTargetExport.h                            |    3 +-
 Source/cmTargetIncludeDirectoriesCommand.h         |   11 +-
 Source/cmTargetLinkLibrariesCommand.h              |    8 +-
 Source/cmTargetPropCommandBase.cxx                 |    2 +-
 Source/cmTargetPropCommandBase.h                   |    2 +-
 Source/cmTargetPropertyComputer.h                  |    2 +-
 Source/cmTargetSourcesCommand.h                    |    8 +-
 Source/cmTest.h                                    |    2 +-
 Source/cmTestGenerator.cxx                         |   14 +-
 Source/cmTestGenerator.h                           |   17 +-
 Source/cmTimestamp.cxx                             |    2 +-
 Source/cmTimestamp.h                               |    2 +-
 Source/cmTryCompileCommand.h                       |    8 +-
 Source/cmTryRunCommand.cxx                         |    2 +-
 Source/cmTryRunCommand.h                           |    8 +-
 Source/cmUnexpectedCommand.h                       |    7 +-
 Source/cmUnsetCommand.h                            |   13 +-
 Source/cmUseMangledMesaCommand.cxx                 |   10 +-
 Source/cmUseMangledMesaCommand.h                   |    6 +-
 Source/cmUtilitySourceCommand.cxx                  |   12 +-
 Source/cmUtilitySourceCommand.h                    |    4 +-
 Source/cmUtils.hxx                                 |    2 +-
 Source/cmUuid.h                                    |    2 +-
 Source/cmVS10CudaFlagTable.h                       |   51 +
 Source/cmVS10CudaHostFlagTable.h                   |   35 +
 Source/cmVS10MASMFlagTable.h                       |   76 +-
 Source/cmVS10NASMFlagTable.h                       |   50 +
 Source/cmVS10RCFlagTable.h                         |    1 +
 Source/cmVS11MASMFlagTable.h                       |   76 +-
 Source/cmVS11RCFlagTable.h                         |    1 +
 Source/cmVS12MASMFlagTable.h                       |   76 +-
 Source/cmVS12RCFlagTable.h                         |    1 +
 Source/cmVS140LinkFlagTable.h                      |  282 +
 Source/cmVS141LinkFlagTable.h                      |  283 +
 Source/cmVS14LinkFlagTable.h                       |  280 -
 Source/cmVS14MASMFlagTable.h                       |   76 +-
 Source/cmVS14RCFlagTable.h                         |    1 +
 Source/cmVSSetupHelper.cxx                         |   28 +
 Source/cmVariableRequiresCommand.cxx               |   10 +-
 Source/cmVariableRequiresCommand.h                 |    4 +-
 Source/cmVariableWatch.cxx                         |    2 +-
 Source/cmVariableWatch.h                           |    2 +-
 Source/cmVariableWatchCommand.cxx                  |    2 +-
 Source/cmVariableWatchCommand.h                    |   13 +-
 Source/cmVersion.h                                 |    2 +-
 Source/cmVisualStudio10TargetGenerator.cxx         |  833 ++-
 Source/cmVisualStudio10TargetGenerator.h           |   25 +-
 Source/cmVisualStudio10ToolsetOptions.cxx          |    9 +-
 Source/cmVisualStudio10ToolsetOptions.h            |    2 +-
 Source/cmVisualStudioGeneratorOptions.cxx          |  177 +-
 Source/cmVisualStudioGeneratorOptions.h            |   29 +-
 Source/cmVisualStudioSlnData.h                     |    2 +-
 Source/cmVisualStudioSlnParser.cxx                 |    2 +-
 Source/cmVisualStudioSlnParser.h                   |    2 +-
 Source/cmVisualStudioWCEPlatformParser.h           |    2 +-
 Source/cmWhileCommand.cxx                          |    2 +-
 Source/cmWhileCommand.h                            |   13 +-
 Source/cmWorkingDirectory.cxx                      |   24 +
 Source/cmWorkingDirectory.h                        |   25 +
 Source/cmWriteFileCommand.cxx                      |    9 +-
 Source/cmWriteFileCommand.h                        |   13 +-
 Source/cmXCode21Object.h                           |    2 +-
 Source/cmXCodeObject.cxx                           |    4 +-
 Source/cmXCodeObject.h                             |    2 +-
 Source/cmXCodeScheme.cxx                           |  227 +
 Source/cmXCodeScheme.h                             |   50 +
 Source/cmXMLParser.cxx                             |    4 +-
 Source/cmXMLParser.h                               |    2 +-
 Source/cmXMLSafe.h                                 |    2 +-
 Source/cmXMLWriter.cxx                             |   13 +-
 Source/cmXMLWriter.h                               |   10 +-
 Source/cm_auto_ptr.hxx                             |   12 +-
 Source/cm_codecvt.cxx                              |  290 +-
 Source/cm_codecvt.hxx                              |   30 +-
 Source/cm_sys_stat.h                               |   14 +
 Source/cm_unordered_map.hxx                        |    4 +-
 Source/cm_unordered_set.hxx                        |    4 +-
 Source/cm_utf8.c                                   |    2 +-
 Source/cmake.cxx                                   |   85 +-
 Source/cmake.h                                     |   22 +-
 Source/cmakemain.cxx                               |   45 +-
 Source/cmakexbuild.cxx                             |    9 +-
 Source/cmcldeps.cxx                                |    4 +-
 Source/cmcmd.cxx                                   |   74 +-
 Source/cmcmd.h                                     |    2 +-
 Source/ctest.cxx                                   |   24 +-
 Source/kwsys/.gitattributes                        |   17 +-
 Source/kwsys/Base64.c                              |   10 -
 Source/kwsys/CMakeLists.txt                        |   21 +-
 Source/kwsys/CONTRIBUTING.rst                      |   10 +-
 Source/kwsys/CommandLineArguments.cxx              |   88 +-
 Source/kwsys/ConsoleBuf.hxx.in                     |   12 +-
 Source/kwsys/Directory.cxx                         |    9 +-
 Source/kwsys/DynamicLoader.cxx                     |   34 -
 Source/kwsys/Encoding.hxx.in                       |   13 +-
 Source/kwsys/EncodingCXX.cxx                       |   66 +-
 Source/kwsys/FStream.hxx.in                        |   10 +-
 Source/kwsys/Glob.cxx                              |   12 -
 Source/kwsys/MD5.c                                 |   10 -
 Source/kwsys/Process.h.in                          |   73 +-
 Source/kwsys/ProcessUNIX.c                         |  233 +-
 Source/kwsys/ProcessWin32.c                        |  253 +-
 Source/kwsys/SharedForward.h.in                    |   18 -
 Source/kwsys/System.c                              |    4 -
 Source/kwsys/SystemInformation.cxx                 |  423 +-
 Source/kwsys/SystemInformation.hxx.in              |   30 +-
 Source/kwsys/SystemTools.cxx                       |  247 +-
 Source/kwsys/SystemTools.hxx.in                    |   41 +-
 Source/kwsys/Terminal.c                            |   10 -
 Source/kwsys/kwsysPlatformTestsC.c                 |    3 -
 Source/kwsys/testConsoleBuf.cxx                    |   23 +-
 Source/kwsys/testConsoleBufChild.cxx               |    1 -
 Source/kwsys/testEncoding.cxx                      |   86 +-
 Source/kwsys/testFStream.cxx                       |    3 -
 Source/kwsys/testSystemInformation.cxx             |    2 +-
 Source/kwsys/testSystemTools.cxx                   |  107 +-
 Templates/MSBuild/nasm.props.in                    |   17 +
 Templates/MSBuild/nasm.targets                     |   41 +
 Templates/MSBuild/nasm.xml                         |  110 +
 Templates/TestDriver.cxx.in                        |    6 +-
 Tests/BuildDepends/CMakeLists.txt                  |    2 +-
 .../target_compile_features/CMakeLists.txt         |   70 +-
 .../target_compile_features/dummy.cpp              |    5 -
 .../CMakeCommands/target_link_libraries/empty.cpp  |    4 +-
 Tests/CMakeLib/CMakeLists.txt                      |   10 -
 Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt       |   15 -
 Tests/CMakeLib/PseudoMemcheck/NoLog/CMakeLists.txt |    8 -
 Tests/CMakeLib/PseudoMemcheck/memtester.cxx.in     |    2 +-
 Tests/CMakeLib/run_compile_commands.cxx            |    2 +-
 Tests/CMakeLib/testEncoding.cxx                    |    8 +-
 Tests/CMakeLib/testRST.cxx                         |    2 +-
 Tests/CMakeLists.txt                               |   64 +-
 Tests/CMakeOnly/AllFindModules/CMakeLists.txt      |   11 +-
 Tests/CMakeOnly/CMakeLists.txt                     |   17 +-
 Tests/CMakeOnly/find_library/CMakeLists.txt        |   31 +-
 .../find_library/lib/A/libXYZ/libtest2.a}          |    0
 .../find_library/lib/A/libx32/libtest3.a}          |    0
 .../find_library/lib/XYZ/libtest1.a}               |    0
 .../find_library/lib/x32/libtest2.a}               |    0
 .../find_library/libXYZ/A/lib/libtest4.a}          |    0
 .../find_library/libXYZ/A/libXYZ/libtest5.a}       |    0
 .../find_library/libXYZ/A/libtest6.a}              |    0
 .../find_library/libXYZ/libtest7.a}                |    0
 .../find_library/libx32/A/lib/libtest2.a}          |    0
 .../find_library/libx32/A/libtest1.a}              |    0
 .../find_library/libx32/A/libx32/libtest1.a}       |    0
 .../find_library/libx32/libtest1.a}                |    0
 Tests/CMakeTestAllGenerators/RunCMake.cmake        |   57 +-
 Tests/CMakeTests/CMakeLists.txt                    |    6 +-
 Tests/CMakeTests/CompilerIdVendorTest.cmake.in     |    4 +-
 Tests/CMakeTests/FileDownloadBadHashTest.cmake.in  |    5 +-
 Tests/CMakeTests/FileDownloadTest.cmake.in         |    5 +-
 Tests/CMakeTests/FileUploadTest.cmake.in           |    5 +-
 Tests/CMakeTests/GetPrerequisitesTest.cmake.in     |    7 +-
 Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in     |  105 +-
 Tests/CMakeTests/SeparateArgumentsTest.cmake.in    |   25 -
 Tests/CMakeTests/ToolchainTest.cmake.in            |    1 -
 Tests/CPackComponents/CMakeLists.txt               |    2 +-
 Tests/CSharpLinkToCxx/CMakeLists.txt               |   17 +
 Tests/CSharpLinkToCxx/cli.cpp                      |   10 +
 Tests/CSharpLinkToCxx/cli.hpp                      |   10 +
 Tests/CSharpLinkToCxx/csharp.cs                    |   16 +
 Tests/CheckFortran.cmake                           |    2 +
 Tests/CompileFeatures/CMakeLists.txt               |   33 +-
 Tests/CompileFeatures/default_dialect.c            |    3 +-
 Tests/Cuda/Complex/CMakeLists.txt                  |    8 +
 Tests/Cuda/Complex/dynamic.cu                      |   43 +-
 Tests/Cuda/Complex/file3.cu                        |   36 +-
 Tests/Cuda/Complex/main.cpp                        |   12 +-
 Tests/Cuda/Complex/mixed.cu                        |   36 +-
 Tests/Cuda/ObjectLibrary/CMakeLists.txt            |    5 +
 Tests/Cuda/ObjectLibrary/main.cpp                  |    8 +-
 Tests/Cuda/ObjectLibrary/static.cu                 |    4 +-
 Tests/CudaOnly/CMakeLists.txt                      |    2 +
 Tests/CudaOnly/ExportPTX/CMakeLists.txt            |   82 +
 Tests/CudaOnly/ExportPTX/bin2c_wrapper.cmake       |   19 +
 Tests/CudaOnly/ExportPTX/kernelA.cu                |    7 +
 Tests/CudaOnly/ExportPTX/kernelB.cu                |    8 +
 Tests/CudaOnly/ExportPTX/main.cu                   |   28 +
 Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt |   52 +
 Tests/CudaOnly/ResolveDeviceSymbols/file1.cu       |   10 +
 Tests/CudaOnly/ResolveDeviceSymbols/file1.h        |    7 +
 Tests/CudaOnly/ResolveDeviceSymbols/file2.cu       |   25 +
 Tests/CudaOnly/ResolveDeviceSymbols/file2.h        |   10 +
 Tests/CudaOnly/ResolveDeviceSymbols/main.cu        |   85 +
 Tests/CudaOnly/ResolveDeviceSymbols/verify.cmake   |   14 +
 Tests/CudaOnly/SeparateCompilation/CMakeLists.txt  |   42 +-
 Tests/CudaOnly/SeparateCompilation/main.cu         |   53 +
 Tests/CudaOnly/WithDefs/CMakeLists.txt             |   12 +-
 Tests/CudaOnly/WithDefs/main.notcu                 |    4 +
 Tests/CudaOnly/WithDefs/main_for_vs.cu             |    1 +
 Tests/CustomCommandByproducts/ninja-check.cmake    |    2 +-
 Tests/CustomCommandWorkingDirectory/CMakeLists.txt |    2 +
 Tests/ExportImport/Export/CMakeLists.txt           |   13 +-
 Tests/ExportImport/Export/sub/testLib8C.c          |    4 +
 Tests/ExportImport/Export/testLib8A.c              |    4 +
 Tests/ExportImport/Export/testLib8B.c              |    4 +
 Tests/ExportImport/Export/testLibNoSONAME.c        |    2 +-
 Tests/ExportImport/Import/A/CMakeLists.txt         |   10 +
 Tests/ExportImport/Import/A/imp_testExe1.c         |   24 +-
 Tests/ExportImport/Import/A/imp_testLib8.c         |    8 +
 Tests/ExternalProject/CMakeLists.txt               |   10 +
 Tests/FindDoxygen/CMakeLists.txt                   |   20 +
 .../DotComponentTestTest/CMakeLists.txt            |   18 +
 Tests/FindDoxygen/SimpleTest/CMakeLists.txt        |   59 +
 Tests/FindDoxygen/SimpleTest/main.cpp              |    4 +
 Tests/FindDoxygen/SimpleTest/spaces_in_name.cpp.in |    4 +
 Tests/FindGTest/Test/CMakeLists.txt                |    3 -
 Tests/FindMPI/CMakeLists.txt                       |   21 +
 Tests/FindMPI/Test/CMakeLists.txt                  |   41 +
 Tests/FindMPI/Test/main.c                          |    7 +
 Tests/FindMPI/Test/main.f90                        |    7 +
 Tests/FindModulesExecuteAll/CMakeLists.txt         |    2 +-
 Tests/FindOpenMP/CMakeLists.txt                    |   21 +
 Tests/FindOpenMP/Test/CMakeLists.txt               |   69 +
 Tests/FindOpenMP/Test/main.c                       |    7 +
 Tests/FindOpenMP/Test/main.f90.in                  |    5 +
 Tests/FindOpenMP/Test/scalprod.c                   |   16 +
 Tests/FindOpenMP/Test/scalprod.f90.in              |   19 +
 Tests/FindOpenMP/Test/scaltest.c                   |   20 +
 Tests/FindOpenMP/Test/scaltest.f90.in              |   21 +
 Tests/FindProtobuf/CMakeLists.txt                  |   10 +
 Tests/FindProtobuf/Test/CMakeLists.txt             |   32 +
 Tests/FindProtobuf/Test/main-protoc.cxx            |    8 +
 Tests/FindProtobuf/Test/main.cxx                   |    8 +
 Tests/FindTIFF/Test/CMakeLists.txt                 |    3 -
 Tests/FindXalanC/Test/CMakeLists.txt               |    3 -
 Tests/FindXercesC/Test/CMakeLists.txt              |    3 -
 Tests/GeneratorExpression/CMakeLists.txt           |   16 +
 Tests/GeneratorExpression/check_object_files.cmake |   26 +
 Tests/GeneratorExpression/objlib1.c                |    4 +
 Tests/GeneratorExpression/objlib2.c                |    4 +
 Tests/GoogleTest/CMakeLists.txt                    |   10 +
 Tests/GoogleTest/Test/CMakeLists.txt               |   95 +
 Tests/GoogleTest/Test/main1.cxx                    |   30 +
 Tests/GoogleTest/Test/main2.cxx                    |    1 +
 Tests/GoogleTest/Test/main2.h                      |   21 +
 Tests/GoogleTest/Test/main3.cxx                    |   11 +
 Tests/GoogleTest/Test/main4.cxx                    |    1 +
 Tests/GoogleTest/Test/main4.h                      |    6 +
 Tests/JavaExportImport/BuildExport/CMakeLists.txt  |    5 +-
 Tests/JavaExportImport/Import/CMakeLists.txt       |    2 +-
 .../JavaExportImport/InstallExport/CMakeLists.txt  |    1 +
 Tests/Module/CheckIPOSupported-C/CMakeLists.txt    |   19 +
 Tests/Module/CheckIPOSupported-C/foo.c             |    4 +
 Tests/Module/CheckIPOSupported-C/main.c            |    9 +
 Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt  |   19 +
 Tests/Module/CheckIPOSupported-CXX/foo.cpp         |    4 +
 Tests/Module/CheckIPOSupported-CXX/main.cpp        |    9 +
 .../CheckIPOSupported-Fortran/CMakeLists.txt       |   19 +
 Tests/Module/CheckIPOSupported-Fortran/foo.f       |    2 +
 Tests/Module/CheckIPOSupported-Fortran/main.f      |    3 +
 .../WriteCompilerDetectionHeader/CMakeLists.txt    |   13 +-
 Tests/Module/WriteCompilerDetectionHeader/main.cpp |    3 +
 .../WriteCompilerDetectionHeader/multi_files.cpp   |    3 +
 Tests/ModuleDefinition/CMakeLists.txt              |    9 +-
 Tests/ModuleDefinition/example_exe.c               |    6 +-
 Tests/ModuleDefinition/split_dll.c                 |    9 +
 Tests/ModuleDefinition/split_dll_1.def             |    2 +
 Tests/ModuleDefinition/split_dll_2.def             |    2 +
 Tests/ObjectLibrary/CMakeLists.txt                 |    6 +-
 Tests/Plugin/CMakeLists.txt                        |    6 +-
 Tests/Preprocess/CMakeLists.txt                    |   10 +-
 Tests/QtAutoUicInterface/CMakeLists.txt            |   10 +-
 Tests/QtAutogen/CMakeLists.txt                     |  248 +-
 Tests/QtAutogen/automoc_rerun/CMakeLists.txt       |   27 -
 Tests/QtAutogen/automoc_rerun/test1.cpp            |    5 -
 Tests/QtAutogen/automoc_rerun/test1.h.in1          |    8 -
 Tests/QtAutogen/automoc_rerun/test1.h.in2          |    7 -
 Tests/QtAutogen/autorcc_depends/CMakeLists.txt     |   27 -
 Tests/QtAutogen/autorcc_depends/res1.qrc.in        |    5 -
 Tests/QtAutogen/mocDepends/CMakeLists.txt          |   47 +
 Tests/QtAutogen/mocDepends/invalid.hpp.in          |    1 +
 Tests/QtAutogen/mocDepends/object.hpp.in           |   14 +
 Tests/QtAutogen/mocDepends/simpleLib.cpp.in        |    9 +
 Tests/QtAutogen/mocDepends/simpleLib.hpp.in        |   11 +
 Tests/QtAutogen/mocDepends/test1.cpp               |    9 +
 Tests/QtAutogen/mocDepends/test2.cpp               |   10 +
 Tests/QtAutogen/mocDepends/test2.hpp               |   16 +
 Tests/QtAutogen/mocInclude/ObjA.cpp                |   24 +
 Tests/QtAutogen/mocInclude/ObjA.hpp                |   13 +
 Tests/QtAutogen/mocInclude/ObjB.cpp                |   25 +
 Tests/QtAutogen/mocInclude/ObjB.hpp                |   13 +
 Tests/QtAutogen/mocInclude/ObjC.cpp                |   26 +
 Tests/QtAutogen/mocInclude/ObjC.hpp                |   13 +
 Tests/QtAutogen/mocInclude/ObjD.cpp                |   26 +
 Tests/QtAutogen/mocInclude/ObjD.hpp                |   13 +
 Tests/QtAutogen/mocInclude/subA/SubObjA.cpp        |   27 +
 Tests/QtAutogen/mocInclude/subA/SubObjA.hpp        |   16 +
 Tests/QtAutogen/mocInclude/subB/SubObjB.cpp        |   27 +
 Tests/QtAutogen/mocInclude/subB/SubObjB.hpp        |   16 +
 Tests/QtAutogen/mocInclude/subC/SubObjC.cpp        |   27 +
 Tests/QtAutogen/mocInclude/subC/SubObjC.hpp        |   16 +
 Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt   |   18 +
 Tests/QtAutogen/mocIncludeRelaxed/main.cpp         |   14 +
 Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt    |   18 +
 Tests/QtAutogen/mocIncludeStrict/main.cpp          |   14 +
 Tests/QtAutogen/mocPlugin/CMakeLists.txt           |   33 +
 Tests/QtAutogen/mocPlugin/StyleA.cpp               |    6 +
 Tests/QtAutogen/mocPlugin/StyleA.hpp               |   17 +
 Tests/QtAutogen/mocPlugin/StyleA.json              |    1 +
 Tests/QtAutogen/mocPlugin/StyleA_Custom.json       |    1 +
 Tests/QtAutogen/mocPlugin/StyleB.cpp               |    6 +
 Tests/QtAutogen/mocPlugin/StyleB.hpp               |   17 +
 Tests/QtAutogen/mocPlugin/StyleC.cpp               |    6 +
 Tests/QtAutogen/mocPlugin/StyleC.hpp               |   17 +
 Tests/QtAutogen/mocPlugin/StyleCommon.hpp          |    7 +
 Tests/QtAutogen/mocPlugin/StyleD.cpp               |    6 +
 Tests/QtAutogen/mocPlugin/StyleD.hpp               |   17 +
 Tests/QtAutogen/mocPlugin/StyleE.cpp               |    6 +
 Tests/QtAutogen/mocPlugin/StyleE.hpp               |   17 +
 Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json       |    1 +
 .../QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json  |    1 +
 Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json       |    1 +
 Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json       |    1 +
 Tests/QtAutogen/mocPlugin/main.cpp                 |    6 +
 Tests/QtAutogen/mocRerun/CMakeLists.txt            |   35 +
 .../{automoc_rerun => mocRerun}/input.txt          |    0
 Tests/QtAutogen/mocRerun/main.cpp.in               |   18 +
 .../QtAutogen/{automoc_rerun => mocRerun}/res1.qrc |    0
 Tests/QtAutogen/mocRerun/test1a.h.in               |    8 +
 Tests/QtAutogen/mocRerun/test1b.h.in               |    7 +
 Tests/QtAutogen/rccDepends/CMakeLists.txt          |   35 +
 .../test_res1.cpp => rccDepends/main.cpp}          |    0
 .../input.txt.in => rccDepends/res/input1.txt.in}  |    0
 Tests/QtAutogen/rccDepends/res/input2.txt.in       |    1 +
 Tests/QtAutogen/rccDepends/res1a.qrc.in            |    5 +
 Tests/QtAutogen/rccDepends/res1b.qrc.in            |    6 +
 Tests/QtAutogen/rccDepends/res2a.qrc.in            |    5 +
 Tests/QtAutogen/rccDepends/res2b.qrc.in            |    6 +
 Tests/QtAutogen/sameName/CMakeLists.txt            |   11 +
 Tests/QtAutogen/uicInclude/CMakeLists.txt          |    8 +
 Tests/QtAutogen/uicInclude/PageC.ui                |   24 +
 Tests/QtAutogen/uicInclude/dirA/PageA.ui           |   24 +
 Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui       |   24 +
 Tests/QtAutogen/uicInclude/main.cpp                |   10 +
 Tests/QtAutogen/uicInclude/main.hpp                |    6 +
 Tests/RunCMake/Android/android_sysinc.c            |    7 +
 Tests/RunCMake/Android/android_sysinc.cxx          |    7 +
 Tests/RunCMake/Android/common.cmake                |   16 +
 Tests/RunCMake/Android/sysinc/dlfcn.h              |    1 +
 Tests/RunCMake/AutoExportDll/AutoExport.cmake      |    6 +
 Tests/RunCMake/AutoExportDll/nop.asm               |   12 +
 Tests/RunCMake/AutoExportDll/say.cxx               |    4 +
 .../RunCMake/BuildDepends/MakeCustomIncludes.cmake |   13 +
 Tests/RunCMake/BuildDepends/MakeCustomIncludes.cxx |    6 +
 .../BuildDepends/MakeCustomIncludes.step1.cmake    |    3 +
 .../BuildDepends/MakeCustomIncludes.step2.cmake    |    3 +
 Tests/RunCMake/BuildDepends/RunCMakeTest.cmake     |   10 +-
 Tests/RunCMake/CMP0019/CMP0019-OLD-stderr.txt      |   10 +
 Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt |    4 +-
 Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake      |    2 +
 .../CMP0026/CMP0026-CONFIG-LOCATION-OLD-stderr.txt |   10 +
 .../CMP0026/CMP0026-LOCATION-CONFIG-OLD-stderr.txt |   10 +
 Tests/RunCMake/CMP0026/CMP0026-OLD-stderr.txt      |   10 +
 Tests/RunCMake/CMP0026/CMP0026-OLD.cmake           |   12 +
 Tests/RunCMake/CMP0026/RunCMakeTest.cmake          |    1 +
 .../CMP0026/clear-cached-information-stderr.txt    |   10 +
 .../RunCMake/CMP0028/CMP0028-OLD-iface-stderr.txt  |   10 +
 Tests/RunCMake/CMP0028/CMP0028-OLD-stderr.txt      |   10 +
 Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt      |    1 +
 Tests/RunCMake/CMP0068/CMP0068-NEW.cmake           |    6 +
 Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt      |    1 +
 Tests/RunCMake/CMP0068/CMP0068-OLD.cmake           |    6 +
 Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt     |    1 +
 Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt     |   12 +
 Tests/RunCMake/CMP0068/CMP0068-WARN.cmake          |   12 +
 Tests/RunCMake/CMP0068/CMakeLists.txt              |    3 +
 Tests/RunCMake/CMP0068/RunCMakeTest.cmake          |    5 +
 Tests/RunCMake/CMP0068/empty.cpp                   |    7 +
 .../CMP0069-NEW-cmake-result.txt}                  |    0
 .../RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt  |    4 +
 Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake     |    6 +
 .../CMP0069-NEW-compiler-result.txt}               |    0
 .../CMP0069/CMP0069-NEW-compiler-stderr.txt        |    4 +
 Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake  |    7 +
 .../CMP0069-NEW-generator-result.txt}              |    0
 .../CMP0069/CMP0069-NEW-generator-stderr.txt       |    4 +
 Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake |    7 +
 Tests/RunCMake/CMP0069/CMP0069-OLD.cmake           |    4 +
 Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt     |    9 +
 Tests/RunCMake/CMP0069/CMP0069-WARN.cmake          |    4 +
 Tests/RunCMake/CMP0069/CMakeLists.txt              |    3 +
 Tests/RunCMake/CMP0069/RunCMakeTest.cmake          |   10 +
 Tests/RunCMake/CMP0069/main.cpp                    |    3 +
 Tests/RunCMake/CMakeLists.txt                      |   44 +-
 .../CPack/ArchiveCommon/common_helpers.cmake       |    2 +-
 Tests/RunCMake/CPack/RunCMakeTest.cmake            |    4 +-
 Tests/RunCMake/CPack/STGZ/Helpers.cmake            |    2 +-
 Tests/RunCMake/CPack/VerifyResult.cmake            |    6 +-
 .../CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake   |    3 +
 Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake |    3 +
 .../CPack/tests/DEBUGINFO/ExpectedFiles.cmake      |    8 +-
 Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake    |   10 +
 .../tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake  |   16 +
 .../tests/EXTRA_SLASH_IN_PATH/VerifyResult.cmake   |    7 +
 .../CPack/tests/EXTRA_SLASH_IN_PATH/test.cmake     |   37 +
 .../CPack/tests/SYMLINKS/ExpectedFiles.cmake       |   13 +
 .../CPack/tests/SYMLINKS/TGZ-Prerequirements.cmake |    5 +
 .../CPack/tests/SYMLINKS/VerifyResult.cmake        |   26 +
 Tests/RunCMake/CPack/tests/SYMLINKS/test.cmake     |   14 +
 Tests/RunCMake/CheckIPOSupported/CMakeLists.txt    |    7 +
 .../RunCMake/CheckIPOSupported/RunCMakeTest.cmake  |   13 +
 .../cmp0069-is-old-result.txt}                     |    0
 .../CheckIPOSupported/cmp0069-is-old-stderr.txt    |    5 +
 .../CheckIPOSupported/cmp0069-is-old.cmake         |    6 +
 .../default-lang-none-result.txt}                  |    0
 .../CheckIPOSupported/default-lang-none-stderr.txt |    7 +
 .../CheckIPOSupported/default-lang-none.cmake      |    1 +
 .../not-supported-by-cmake-result.txt}             |    0
 .../not-supported-by-cmake-stderr.txt              |    6 +
 .../CheckIPOSupported/not-supported-by-cmake.cmake |    3 +
 .../not-supported-by-compiler-result.txt}          |    0
 .../not-supported-by-compiler-stderr.txt           |    6 +
 .../not-supported-by-compiler.cmake                |    4 +
 .../not-supported-by-generator-result.txt}         |    0
 .../not-supported-by-generator-stderr.txt          |    6 +
 .../not-supported-by-generator.cmake               |    6 +
 .../CheckIPOSupported/save-to-result.cmake         |   22 +
 .../unparsed-arguments-result.txt}                 |    0
 .../unparsed-arguments-stderr.txt                  |    5 +
 .../CheckIPOSupported/unparsed-arguments.cmake     |    1 +
 .../user-lang-unknown-result.txt}                  |    0
 .../CheckIPOSupported/user-lang-unknown-stderr.txt |    6 +
 .../CheckIPOSupported/user-lang-unknown.cmake      |    1 +
 .../CommandLine/DeprecateVS71-WARN-ON-stderr.txt   |    5 -
 ...-WARN-OFF.cmake => DeprecateVS8-WARN-OFF.cmake} |    0
 .../CommandLine/DeprecateVS8-WARN-ON-stderr.txt    |    5 +
 ...1-WARN-OFF.cmake => DeprecateVS8-WARN-ON.cmake} |    0
 Tests/RunCMake/CommandLine/RunCMakeTest.cmake      |   23 +-
 .../reject_fifo-result.txt}                        |    0
 Tests/RunCMake/CommandLine/reject_fifo-stderr.txt  |    2 +
 .../LinkImplementationFeatureCycle.cmake           |    5 +-
 Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake  |    5 +-
 .../DisallowedCommands/CMP0029-OLD-stderr.txt      |   10 +
 .../DisallowedCommands/CMP0030-OLD-stderr.txt      |   13 +-
 .../FeatureSummaryCustomDescription-stdout.txt     |   91 +
 .../FeatureSummaryCustomDescription.cmake          |  158 +
 .../FeatureSummaryDefaultDescription-stdout.txt    |   46 +
 .../FeatureSummaryDefaultDescription.cmake         |   82 +
 Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake   |    2 +
 .../File_Generate/OutputConflict-stderr.txt        |    5 +-
 .../OutputNameMatchesObjects-stderr.txt            |    7 +-
 .../File_Generate/OutputNameMatchesObjects.cmake   |    1 +
 Tests/RunCMake/File_Generate/RunCMakeTest.cmake    |    2 +-
 .../FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake       |    5 +-
 .../FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake       |    5 +-
 .../FindPkgConfig_PKGCONFIG_PATH.cmake             |    5 +-
 ..._PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake |    5 +-
 ...indPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake |    5 +-
 Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat  |   11 +-
 Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh   |   32 +-
 .../pc-bar/libx32/pkgconfig/.placeholder}          |    0
 .../pc-foo/libx32/pkgconfig/.placeholder}          |    0
 Tests/RunCMake/Framework/FrameworkLayout.cmake     |   13 +-
 .../Framework/FrameworkTypeSHARED-build-stdout.txt |    4 +-
 .../Framework/FrameworkTypeSTATIC-build-stdout.txt |    3 +-
 .../Framework/OSXFrameworkLayout-build-check.cmake |   17 +-
 Tests/RunCMake/Framework/RunCMakeTest.cmake        |   11 +-
 .../deepresource.txt}                              |    0
 .../flatresource.txt}                              |    0
 .../Framework/iOSFrameworkLayout-build-check.cmake |   17 +-
 .../some.txt}                                      |    0
 Tests/RunCMake/GNUInstallDirs/Common.cmake         |    4 +-
 Tests/RunCMake/GNUInstallDirs/Opt-BSD-stderr.txt   |   30 +
 Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt       |    2 +
 Tests/RunCMake/GNUInstallDirs/Root-BSD-stderr.txt  |   30 +
 Tests/RunCMake/GNUInstallDirs/Root-stderr.txt      |    2 +
 Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake   |   19 +-
 Tests/RunCMake/GNUInstallDirs/Usr-BSD-stderr.txt   |   30 +
 Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt       |    2 +
 .../GNUInstallDirs/UsrLocal-BSD-stderr.txt         |   30 +
 Tests/RunCMake/GNUInstallDirs/UsrLocal-stderr.txt  |    2 +
 Tests/RunCMake/GenerateExportHeader/GEH.cmake      |    2 +-
 ...tedTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt} |    0
 ...rtedTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt |    8 +
 .../ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake |    2 +
 .../ImportedTarget-TARGET_BUNDLE_DIR-result.txt}   |    0
 .../ImportedTarget-TARGET_BUNDLE_DIR-stderr.txt    |    8 +
 .../ImportedTarget-TARGET_BUNDLE_DIR.cmake         |    2 +
 ...lidTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt} |    0
 ...alidTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt |    8 +
 .../NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake |    9 +
 .../NonValidTarget-TARGET_BUNDLE_DIR-result.txt}   |    0
 .../NonValidTarget-TARGET_BUNDLE_DIR-stderr.txt    |    8 +
 .../NonValidTarget-TARGET_BUNDLE_DIR.cmake         |    9 +
 .../GeneratorExpression/RunCMakeTest.cmake         |    4 +
 .../BadToolsetFormat-result.txt}                   |    0
 .../GeneratorToolset/BadToolsetFormat-stderr.txt   |   10 +
 .../GeneratorToolset/BadToolsetFormat.cmake        |    1 +
 .../GeneratorToolset/BadToolsetHostArch-stderr.txt |    4 +-
 .../BadToolsetHostArchTwice-result.txt}            |    0
 .../BadToolsetHostArchTwice-stderr.txt             |   10 +
 .../GeneratorToolset/BadToolsetHostArchTwice.cmake |    1 +
 .../BadToolsetHostArchXcode-result.txt}            |    0
 ...derr.txt => BadToolsetHostArchXcode-stderr.txt} |    0
 .../GeneratorToolset/BadToolsetHostArchXcode.cmake |    1 +
 Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake |   19 +-
 .../TestToolsetCudaBoth-stdout.txt                 |    2 +
 .../GeneratorToolset/TestToolsetCudaBoth.cmake     |    2 +
 .../TestToolsetCudaOnly-stdout.txt                 |    2 +
 .../GeneratorToolset/TestToolsetCudaOnly.cmake     |    2 +
 Tests/RunCMake/Ninja/AssumedSources.cmake          |   20 +
 Tests/RunCMake/Ninja/CommandConcat.cmake           |   14 +
 Tests/RunCMake/Ninja/LooseObjectDepends.cmake      |   26 +
 Tests/RunCMake/Ninja/RunCMakeTest.cmake            |   45 +-
 Tests/RunCMake/Ninja/dep.c                         |    4 +
 Tests/RunCMake/Ninja/top.c                         |    7 +
 Tests/RunCMake/ObjectLibrary/Dependencies.cmake    |    7 +
 Tests/RunCMake/ObjectLibrary/Export-stderr.txt     |    4 -
 ...rt-result.txt => ExportNotSupported-result.txt} |    0
 .../ObjectLibrary/ExportNotSupported-stderr.txt    |    5 +
 .../ObjectLibrary/ExportNotSupported.cmake         |    2 +
 Tests/RunCMake/ObjectLibrary/Import-stderr.txt     |    4 -
 Tests/RunCMake/ObjectLibrary/Import.cmake          |   11 +
 ...rt-result.txt => ImportNotSupported-result.txt} |    0
 .../ObjectLibrary/ImportNotSupported-stderr.txt    |    5 +
 .../{Import.cmake => ImportNotSupported.cmake}     |    0
 Tests/RunCMake/ObjectLibrary/Install-stderr.txt    |    4 -
 ...t-result.txt => InstallNotSupported-result.txt} |    0
 .../ObjectLibrary/InstallNotSupported-stderr.txt   |    5 +
 .../ObjectLibrary/InstallNotSupported.cmake        |    2 +
 .../{Export-result.txt => OwnSources-result.txt}   |    0
 Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt |    5 +
 Tests/RunCMake/ObjectLibrary/OwnSources.cmake      |    2 +
 Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake    |   38 +-
 Tests/RunCMake/ObjectLibrary/b.c                   |    4 +
 Tests/RunCMake/ObjectLibrary/depends_lib.c         |    7 +
 Tests/RunCMake/ObjectLibrary/depends_main.c        |    7 +
 Tests/RunCMake/ObjectLibrary/depends_obj0.c        |    4 +
 Tests/RunCMake/ObjectLibrary/depends_obj1.c        |    4 +
 Tests/RunCMake/RunCMake.cmake                      |    6 +-
 Tests/RunCMake/TargetObjects/BadContext-stderr.txt |   27 -
 .../NoTarget-result.txt}                           |    0
 Tests/RunCMake/TargetObjects/NoTarget-stderr.txt   |   24 +
 .../{BadContext.cmake => NoTarget.cmake}           |    0
 .../NotObjlibTarget-result.txt}                    |    0
 .../TargetObjects/NotObjlibTarget-stderr.txt       |    8 +
 Tests/RunCMake/TargetObjects/NotObjlibTarget.cmake |    3 +
 Tests/RunCMake/TargetObjects/RunCMakeTest.cmake    |    3 +-
 Tests/RunCMake/TargetObjects/empty.cpp             |    4 +
 .../RunCMake/TargetPolicies/PolicyList-stderr.txt  |    2 +
 .../TargetSources/CMP0026-LOCATION-stderr.txt      |   10 +
 Tests/RunCMake/TargetSources/RunCMakeTest.cmake    |    2 +-
 Tests/RunCMake/VSSolution/MorePost-check.cmake     |    2 +-
 Tests/RunCMake/VSSolution/MorePre-check.cmake      |    2 +-
 Tests/RunCMake/VSSolution/OnePost-check.cmake      |    2 +-
 Tests/RunCMake/VSSolution/OnePre-check.cmake       |    2 +-
 Tests/RunCMake/VSSolution/Override1-check.cmake    |    2 +-
 Tests/RunCMake/VSSolution/Override2-check.cmake    |    2 +-
 Tests/RunCMake/VSSolution/Override3-check.cmake    |    3 +
 Tests/RunCMake/VSSolution/Override3.cmake          |    4 +
 Tests/RunCMake/VSSolution/PrePost-check.cmake      |    2 +-
 Tests/RunCMake/VSSolution/RunCMakeTest.cmake       |    3 +-
 Tests/RunCMake/VSSolution/solution_parsing.cmake   |    3 +
 Tests/RunCMake/XcodeProject/RunCMakeTest.cmake     |   16 +
 Tests/RunCMake/XcodeProject/XcodeBundles.cmake     |   24 +
 .../XcodeProject/XcodeSchemaGeneration.cmake       |    5 +
 .../RunCMake/ctest_disabled_test/CMakeLists.txt.in |    6 +
 .../ctest_disabled_test/CTestConfig.cmake.in       |    1 +
 .../ctest_disabled_test/DisableAllTests-result.txt |    1 +
 .../ctest_disabled_test/DisableAllTests-stderr.txt |    1 +
 .../ctest_disabled_test/DisableAllTests-stdout.txt |    2 +
 .../DisableCleanupTest-stdout.txt                  |   11 +
 .../DisableFailingTest-stdout.txt                  |    9 +
 .../DisableNotRunTest-result.txt                   |    1 +
 .../DisableNotRunTest-stderr.txt                   |    1 +
 .../DisableNotRunTest-stdout.txt                   |   17 +
 .../DisableRequiredTest-stdout.txt                 |   13 +
 .../DisableSetupTest-stdout.txt                    |   13 +
 .../ctest_disabled_test/DisabledTest-result.txt    |    1 +
 .../ctest_disabled_test/DisabledTest-stderr.txt    |    1 +
 .../ctest_disabled_test/DisabledTest-stdout.txt    |   17 +
 .../ctest_disabled_test/RunCMakeTest.cmake         |   89 +
 Tests/RunCMake/ctest_disabled_test/test.cmake.in   |   16 +
 Tests/RunCMake/ctest_fixtures/CMakeLists.txt.in    |    2 +-
 Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake   |   50 +
 .../ctest_fixtures/exclude_any_bar-stdout.txt      |   15 +
 .../ctest_fixtures/exclude_any_foo-stdout.txt      |   13 +
 .../ctest_fixtures/exclude_any_foobar-stdout.txt   |    9 +
 .../ctest_fixtures/exclude_cleanup_bar-stdout.txt  |   15 +
 .../ctest_fixtures/exclude_cleanup_foo-stdout.txt  |   15 +
 .../ctest_fixtures/exclude_setup_bar-stdout.txt    |   17 +
 .../ctest_fixtures/exclude_setup_foo-stdout.txt    |   15 +
 Tests/RunCMake/ctest_fixtures/test.cmake.in        |    2 +-
 .../RunCMake/ctest_skipped_test/CMakeLists.txt.in  |   12 +
 .../ctest_skipped_test/CTestConfig.cmake.in        |    1 +
 .../RunCMake/ctest_skipped_test/RunCMakeTest.cmake |   51 +
 .../ctest_skipped_test/SkipCleanupTest-stdout.txt  |   11 +
 .../ctest_skipped_test/SkipRequiredTest-stdout.txt |   13 +
 .../ctest_skipped_test/SkipSetupTest-stdout.txt    |   13 +
 .../ctest_skipped_test/SkipTest-stdout.txt         |   11 +
 Tests/RunCMake/ctest_skipped_test/skip.bat         |    1 +
 Tests/RunCMake/ctest_skipped_test/skip.sh          |    3 +
 Tests/RunCMake/ctest_skipped_test/test.cmake.in    |   16 +
 .../ctest_submit/CDashSubmitHeaders-result.txt     |    1 +
 .../ctest_submit/CDashSubmitHeaders-stderr.txt     |    3 +
 .../ctest_submit/CDashSubmitHeaders-stdout.txt     |    1 +
 .../ctest_submit/CDashUploadHeaders-result.txt     |    1 +
 .../ctest_submit/CDashUploadHeaders-stderr.txt     |    1 +
 .../ctest_submit/CDashUploadHeaders-stdout.txt     |    1 +
 Tests/RunCMake/ctest_submit/RunCMakeTest.cmake     |    2 +
 Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake   |    5 +-
 Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake |    5 +-
 .../INSTALL-FILES_FROM_DIR-bad-result.txt}         |    0
 .../file/INSTALL-FILES_FROM_DIR-bad-stderr.txt     |   15 +
 .../RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake |    5 +
 .../file/INSTALL-FILES_FROM_DIR-stdout.txt         |    8 +
 Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake   |    7 +
 Tests/RunCMake/file/INSTALL-SYMLINK-stdout.txt     |    3 +
 Tests/RunCMake/file/INSTALL-SYMLINK.cmake          |   13 +
 .../Export-result.txt => file/READ_ELF-result.txt} |    0
 Tests/RunCMake/file/READ_ELF-stderr.txt            |    2 +
 Tests/RunCMake/file/READ_ELF.cmake                 |    2 +
 Tests/RunCMake/file/RunCMakeTest.cmake             |    4 +
 Tests/RunCMake/file/UPLOAD-unused-argument.cmake   |    5 +-
 .../from/a.txt}                                    |    0
 .../from/a/b.txt}                                  |    0
 .../from/a/b/c.txt}                                |    0
 Tests/RunCMake/find_dependency/CMakeLists.txt      |    1 -
 .../find_dependency/EXACT-no-version-stderr.txt    |    6 -
 .../find_dependency/EXACT-no-version.cmake         |    4 -
 Tests/RunCMake/find_dependency/RunCMakeTest.cmake  |   13 +-
 .../bad-version-exact-result.txt}                  |    0
 .../find_dependency/bad-version-exact-stderr.txt   |   11 +
 .../find_dependency/bad-version-exact.cmake        |    5 +
 .../bad-version-fuzzy-result.txt}                  |    0
 .../find_dependency/bad-version-fuzzy-stderr.txt   |   11 +
 .../find_dependency/bad-version-fuzzy.cmake        |    5 +
 Tests/RunCMake/find_dependency/basic.cmake         |    5 +
 .../find_dependency/empty-arg-3-stderr.txt         |    5 -
 Tests/RunCMake/find_dependency/empty-arg-3.cmake   |    4 -
 .../find_dependency/empty-version-stderr.txt       |    5 -
 Tests/RunCMake/find_dependency/empty-version.cmake |    4 -
 .../RunCMake/find_dependency/extra-args-stderr.txt |    5 -
 Tests/RunCMake/find_dependency/extra-args.cmake    |    4 -
 .../find_dependency/invalid-arg-3-stderr.txt       |    5 -
 Tests/RunCMake/find_dependency/invalid-arg-3.cmake |    4 -
 .../invalid-arg-result.txt}                        |    0
 .../find_dependency/invalid-arg-stderr.txt         |    5 +
 Tests/RunCMake/find_dependency/invalid-arg.cmake   |    5 +
 Tests/RunCMake/find_dependency/realistic.cmake     |    3 +
 .../{ => share/cmake}/Pack1/Pack1Config.cmake      |    0
 .../cmake}/Pack1/Pack1ConfigVersion.cmake          |    0
 .../share/cmake/Pack2/Pack2Config.cmake            |    6 +
 .../cmake/Pack2/Pack2ConfigVersion.cmake}          |    0
 .../RunCMake/find_package/MissingConfig-stderr.txt |   15 -
 .../RunCMake/find_package/MissingConfig-stdout.txt |    1 +
 .../find_package/MissingConfigNormal-stdout.txt    |    1 +
 .../find_package/MissingConfigOneName-stderr.txt   |   10 -
 .../find_package/MissingConfigOneName-stdout.txt   |    1 +
 .../find_package/MissingConfigVersion-stderr.txt   |   13 -
 .../find_package/MissingConfigVersion-stdout.txt   |    1 +
 Tests/RunCMake/find_package/PackageRoot-stderr.txt |  383 ++
 Tests/RunCMake/find_package/PackageRoot.cmake      |  147 +
 .../find_package/PackageRoot/FindBar.cmake         |    8 +
 .../find_package/PackageRoot/FindFoo.cmake         |    9 +
 .../PackageRoot/bar/cmake_root/bin/bar.exe}        |    0
 .../PackageRoot/bar/cmake_root/include/bar.h}      |    0
 .../PackageRoot/bar/cmake_root/include/zot/zot.h}  |    0
 .../PackageRoot/bar/env_root/bin/bar.exe}          |    0
 .../PackageRoot/bar/env_root/include/bar.h}        |    0
 .../PackageRoot/bar/env_root/include/zot/zot.h}    |    0
 .../PackageRoot/foo/cmake_root/bin/bar.exe}        |    0
 .../PackageRoot/foo/cmake_root/bin/foo.exe}        |    0
 .../PackageRoot/foo/cmake_root/include/bar.h}      |    0
 .../PackageRoot/foo/cmake_root/include/foo.h}      |    0
 .../PackageRoot/foo/cmake_root/include/zot/zot.h}  |    0
 .../PackageRoot/foo/env_root/bin/bar.exe}          |    0
 .../PackageRoot/foo/env_root/bin/foo.exe}          |    0
 .../PackageRoot/foo/env_root/include/bar.h}        |    0
 .../PackageRoot/foo/env_root/include/foo.h}        |    0
 .../PackageRoot/foo/env_root/include/zot/zot.h}    |    0
 Tests/RunCMake/find_package/RunCMakeTest.cmake     |    3 +
 .../VersionedA-1/VersionedAConfig.cmake}           |    0
 .../VersionedA-1/VersionedAConfigVersion.cmake     |    4 +
 .../VersionedA-2/VersionedAConfig.cmake}           |    0
 .../VersionedA-2/VersionedAConfigVersion.cmake     |    4 +
 .../RunCMake/find_package/WrongVersion-stderr.txt  |   11 +
 Tests/RunCMake/find_package/WrongVersion.cmake     |    2 +
 .../find_package/WrongVersionConfig-stderr.txt     |   11 +
 .../RunCMake/find_package/WrongVersionConfig.cmake |    2 +
 .../RunCMake/get_property/IsMultiConfig-stdout.txt |    1 +
 Tests/RunCMake/get_property/IsMultiConfig.cmake    |    2 +
 .../get_property/NotMultiConfig-stdout.txt         |    1 +
 Tests/RunCMake/get_property/NotMultiConfig.cmake   |    1 +
 Tests/RunCMake/get_property/RunCMakeTest.cmake     |    6 +
 Tests/RunCMake/if/RunCMakeTest.cmake               |    4 +
 .../duplicate-deep-else-result.txt}                |    0
 Tests/RunCMake/if/duplicate-deep-else-stderr.txt   |    4 +
 Tests/RunCMake/if/duplicate-deep-else.cmake        |    7 +
 .../duplicate-else-after-elseif-result.txt}        |    0
 .../if/duplicate-else-after-elseif-stderr.txt      |    4 +
 .../RunCMake/if/duplicate-else-after-elseif.cmake  |    5 +
 .../duplicate-else-result.txt}                     |    0
 Tests/RunCMake/if/duplicate-else-stderr.txt        |    4 +
 Tests/RunCMake/if/duplicate-else.cmake             |    4 +
 .../misplaced-elseif-result.txt}                   |    0
 Tests/RunCMake/if/misplaced-elseif-stderr.txt      |    4 +
 Tests/RunCMake/if/misplaced-elseif.cmake           |    4 +
 .../CustomConfig-check.cmake                       |    1 +
 .../include_external_msproject/CustomConfig.cmake  |    3 +
 .../CustomGuid-check.cmake                         |    2 +-
 .../CustomGuidTypePlatform-check.cmake             |    2 +-
 .../CustomTypePlatform-check.cmake                 |    2 +-
 .../include_external_msproject/RunCMakeTest.cmake  |    1 +
 .../include_external_msproject/check_utils.cmake   |   27 +-
 Tests/RunCMake/install/EXPORT-OldIFace.cmake       |    1 +
 .../install/FILES-TARGET_OBJECTS-all-check.cmake   |    1 +
 Tests/RunCMake/install/FILES-TARGET_OBJECTS.cmake  |    3 +
 Tests/RunCMake/install/RunCMakeTest.cmake          |   20 +-
 Tests/RunCMake/install/obj1.c                      |    4 +
 Tests/RunCMake/install/obj2.c                      |    4 +
 .../RunCMake/project/ProjectDescription-stdout.txt |    1 +
 Tests/RunCMake/project/ProjectDescription.cmake    |    6 +
 .../ProjectDescription2-result.txt}                |    0
 .../project/ProjectDescription2-stderr.txt         |    1 +
 Tests/RunCMake/project/ProjectDescription2.cmake   |    2 +
 Tests/RunCMake/project/RunCMakeTest.cmake          |    2 +
 Tests/RunCMake/separate_arguments/CMakeLists.txt   |    3 +
 .../RunCMake/separate_arguments/EmptyCommand.cmake |    6 +
 .../separate_arguments/NativeCommand.cmake         |   19 +
 .../RunCMake/separate_arguments/PlainCommand.cmake |    8 +
 .../RunCMake/separate_arguments/RunCMakeTest.cmake |    7 +
 .../RunCMake/separate_arguments/UnixCommand.cmake  |    8 +
 .../separate_arguments/WindowsCommand.cmake        |    8 +
 .../target_compile_features/CMakeLists.txt         |    2 +-
 .../target_compile_features/RunCMakeTest.cmake     |    1 +
 .../alias_target-stderr.txt                        |    2 +-
 .../target_compile_features/alias_target.cmake     |    1 +
 .../cxx_not_enabled-result.txt}                    |    0
 .../cxx_not_enabled-stderr.txt                     |    4 +
 .../target_compile_features/cxx_not_enabled.cmake  |    2 +
 .../imported_target-stderr.txt                     |    2 +-
 .../target_compile_features/imported_target.cmake  |    1 +
 .../invalid_args-stderr.txt                        |    2 +-
 .../target_compile_features/invalid_args.cmake     |    1 +
 .../invalid_args_on_interface-stderr.txt           |    2 +-
 .../invalid_args_on_interface.cmake                |    1 +
 .../no_matching_c_feature-stderr.txt               |    2 +-
 .../no_matching_c_feature.cmake                    |    1 +
 .../no_matching_cxx_feature-stderr.txt             |    2 +-
 .../no_matching_cxx_feature.cmake                  |    1 +
 .../target_compile_features/no_target-stderr.txt   |    2 +-
 .../target_compile_features/no_target.cmake        |    1 +
 .../not_a_c_feature-stderr.txt                     |    2 +-
 .../target_compile_features/not_a_c_feature.cmake  |    1 +
 .../not_a_cxx_feature-stderr.txt                   |    2 +-
 .../not_a_cxx_feature.cmake                        |    1 +
 .../not_enough_args-stderr.txt                     |    2 +-
 .../target_compile_features/not_enough_args.cmake  |    1 +
 .../utility_target-stderr.txt                      |    2 +-
 Tests/Server/cmakelib.py                           |    5 +-
 Tests/Server/server-test.py                        |    1 +
 Tests/SimpleInstall/CMakeLists.txt                 |    1 +
 Tests/SourceGroups/CMakeLists.txt                  |    9 +-
 Tests/SourceGroups/main.c                          |    9 +-
 Tests/SourceGroups/tree_foo.c                      |    4 -
 Tests/SourceGroups/tree_prefix_bar.c               |    4 +
 Tests/SourceGroups/tree_prefix_foo.c               |    4 +
 Tests/VSNASM/CMakeLists.txt                        |   10 +
 Tests/VSNASM/foo.asm                               |    7 +
 Tests/VSNASM/include/foo-proc.asm                  |    7 +
 Tests/VSNASM/main.c                                |    5 +
 Tests/VSResource/CMakeLists.txt                    |    9 +-
 Tests/Wrapping/fakefluid.cxx                       |    4 +-
 Tests/XCTest/CMakeLists.txt                        |   16 +
 Tests/XCTest/StaticLibExample/StaticLibExample.c   |    6 +
 Tests/XCTest/StaticLibExample/StaticLibExample.h   |    1 +
 Tests/XCTest/StaticLibExampleTests/Info.plist      |   24 +
 .../StaticLibExampleTests/StaticLibExampleTests.m  |   16 +
 Utilities/.clang-tidy                              |    6 +
 Utilities/CMakeLists.txt                           |    3 +
 Utilities/GitSetup/config                          |    9 +-
 Utilities/IWYU/mapping.imp                         |  161 +
 Utilities/KWIML/test/CMakeLists.txt                |    2 +
 Utilities/Release/consolidate-relnotes.bash        |   27 +
 Utilities/Release/hythloth_release.cmake           |   10 -
 Utilities/Release/linux64_release.cmake            |    1 +
 Utilities/Release/osx_release.cmake                |    2 +-
 Utilities/Release/release_cmake.cmake              |    9 +-
 Utilities/Release/release_cmake.sh.in              |    6 +-
 Utilities/Release/upload_release.cmake             |    2 +-
 Utilities/Scripts/update-curl.bash                 |    3 +-
 Utilities/Scripts/update-expat.bash                |    5 +-
 Utilities/Scripts/update-kwsys.bash                |    2 +
 Utilities/Scripts/update-libarchive.bash           |    2 +-
 Utilities/Scripts/update-third-party.bash          |    8 +
 Utilities/SetupForDevelopment.sh                   |    5 +-
 Utilities/Sphinx/CMakeLists.txt                    |   26 +-
 Utilities/Sphinx/conf.py.in                        |   24 +-
 Utilities/Sphinx/templates/layout.html             |   12 +
 Utilities/cmcurl/CMake/CurlTests.c                 |   16 +
 Utilities/cmcurl/CMake/FindGSS.cmake               |    2 +-
 Utilities/cmcurl/CMake/FindMbedTLS.cmake           |   13 +
 Utilities/cmcurl/CMake/OtherTests.cmake            |   25 +-
 Utilities/cmcurl/CMake/Utilities.cmake             |   13 +
 Utilities/cmcurl/CMakeLists.txt                    |  302 +-
 Utilities/cmcurl/COPYING                           |    2 +-
 Utilities/cmcurl/include/curl/curl.h               |  123 +-
 Utilities/cmcurl/include/curl/curlrules.h          |   25 +-
 Utilities/cmcurl/include/curl/curlver.h            |   18 +-
 Utilities/cmcurl/include/curl/easy.h               |    4 +-
 Utilities/cmcurl/include/curl/stdcheaders.h        |    6 +-
 Utilities/cmcurl/include/curl/system.h             |  484 ++
 Utilities/cmcurl/include/curl/typecheck-gcc.h      |  188 +-
 Utilities/cmcurl/lib/Makefile.inc                  |    4 +-
 Utilities/cmcurl/lib/asyn-ares.c                   |   47 +-
 Utilities/cmcurl/lib/asyn-thread.c                 |   38 +-
 Utilities/cmcurl/lib/conncache.c                   |   67 +-
 Utilities/cmcurl/lib/conncache.h                   |    4 +-
 Utilities/cmcurl/lib/connect.c                     |  109 +-
 Utilities/cmcurl/lib/connect.h                     |   19 +-
 Utilities/cmcurl/lib/content_encoding.c            |   28 +-
 Utilities/cmcurl/lib/cookie.c                      |   60 +-
 Utilities/cmcurl/lib/curl_addrinfo.c               |   62 +-
 Utilities/cmcurl/lib/curl_addrinfo.h               |    2 +-
 Utilities/cmcurl/lib/curl_config.h.cmake           |   12 +
 Utilities/cmcurl/lib/curl_des.c                    |    2 +-
 Utilities/cmcurl/lib/curl_endian.c                 |  120 +-
 Utilities/cmcurl/lib/curl_endian.h                 |   32 +-
 Utilities/cmcurl/lib/curl_fnmatch.c                |    8 +-
 Utilities/cmcurl/lib/curl_gethostname.c            |    8 +-
 Utilities/cmcurl/lib/curl_gssapi.c                 |    2 +-
 Utilities/cmcurl/lib/curl_hmac.h                   |   26 +-
 Utilities/cmcurl/lib/curl_md4.h                    |    8 +-
 Utilities/cmcurl/lib/curl_memory.h                 |    4 +-
 Utilities/cmcurl/lib/curl_ntlm_core.c              |   24 +-
 Utilities/cmcurl/lib/curl_ntlm_core.h              |   27 +-
 Utilities/cmcurl/lib/curl_ntlm_wb.c                |   15 +-
 Utilities/cmcurl/lib/curl_rtmp.c                   |    1 +
 Utilities/cmcurl/lib/curl_sasl.c                   |   29 +-
 Utilities/cmcurl/lib/curl_sec.h                    |   16 +-
 Utilities/cmcurl/lib/curl_setup.h                  |   31 +-
 Utilities/cmcurl/lib/curl_setup_once.h             |    2 +-
 Utilities/cmcurl/lib/curl_threads.c                |    5 +-
 Utilities/cmcurl/lib/curl_threads.h                |    5 +-
 Utilities/cmcurl/lib/dict.c                        |    2 +-
 Utilities/cmcurl/lib/dotdot.c                      |    3 +-
 Utilities/cmcurl/lib/easy.c                        |   74 +-
 Utilities/cmcurl/lib/escape.c                      |   13 +-
 Utilities/cmcurl/lib/file.c                        |   32 +-
 Utilities/cmcurl/lib/fileinfo.c                    |   14 +-
 Utilities/cmcurl/lib/fileinfo.h                    |   12 +-
 Utilities/cmcurl/lib/formdata.c                    |  201 +-
 Utilities/cmcurl/lib/formdata.h                    |    2 +-
 Utilities/cmcurl/lib/ftp.c                         |  331 +-
 Utilities/cmcurl/lib/ftp.h                         |    2 +-
 Utilities/cmcurl/lib/ftplistparser.c               |   67 +-
 Utilities/cmcurl/lib/getinfo.c                     |   29 +-
 Utilities/cmcurl/lib/gopher.c                      |    6 +-
 Utilities/cmcurl/lib/hash.c                        |   88 +-
 Utilities/cmcurl/lib/hash.h                        |   20 +-
 Utilities/cmcurl/lib/hmac.c                        |   10 +-
 Utilities/cmcurl/lib/hostcheck.c                   |   11 +-
 Utilities/cmcurl/lib/hostip.c                      |   18 +-
 Utilities/cmcurl/lib/hostip.h                      |   10 +-
 Utilities/cmcurl/lib/hostip4.c                     |    2 +-
 Utilities/cmcurl/lib/http.c                        |  287 +-
 Utilities/cmcurl/lib/http.h                        |    4 +
 Utilities/cmcurl/lib/http2.c                       |  324 +-
 Utilities/cmcurl/lib/http2.h                       |    8 +
 Utilities/cmcurl/lib/http_chunks.c                 |   14 +-
 Utilities/cmcurl/lib/http_digest.c                 |   20 +-
 Utilities/cmcurl/lib/http_negotiate.c              |   16 +-
 Utilities/cmcurl/lib/http_ntlm.c                   |    6 +-
 Utilities/cmcurl/lib/http_proxy.c                  |  609 +-
 Utilities/cmcurl/lib/http_proxy.h                  |   11 +-
 Utilities/cmcurl/lib/if2ip.c                       |    4 +-
 Utilities/cmcurl/lib/imap.c                        |   15 +-
 Utilities/cmcurl/lib/inet_ntop.c                   |    6 +-
 Utilities/cmcurl/lib/inet_pton.c                   |    8 +-
 Utilities/cmcurl/lib/krb5.c                        |   16 +-
 Utilities/cmcurl/lib/ldap.c                        |  147 +-
 Utilities/cmcurl/lib/libcurl.rc                    |    4 +-
 Utilities/cmcurl/lib/llist.c                       |   57 +-
 Utilities/cmcurl/lib/llist.h                       |   19 +-
 Utilities/cmcurl/lib/md4.c                         |   15 +-
 Utilities/cmcurl/lib/md5.c                         |    9 +-
 Utilities/cmcurl/lib/memdebug.c                    |   28 +-
 Utilities/cmcurl/lib/mprintf.c                     |   33 +-
 Utilities/cmcurl/lib/multi.c                       |  413 +-
 Utilities/cmcurl/lib/multihandle.h                 |   21 +-
 Utilities/cmcurl/lib/multiif.h                     |    7 +-
 Utilities/cmcurl/lib/non-ascii.c                   |    4 +-
 Utilities/cmcurl/lib/nonblock.c                    |    3 +-
 Utilities/cmcurl/lib/nwlib.c                       |   10 +-
 Utilities/cmcurl/lib/nwos.c                        |    8 +-
 Utilities/cmcurl/lib/pingpong.c                    |   35 +-
 Utilities/cmcurl/lib/pingpong.h                    |    8 +-
 Utilities/cmcurl/lib/pipeline.c                    |  123 +-
 Utilities/cmcurl/lib/pipeline.h                    |    6 +-
 Utilities/cmcurl/lib/pop3.c                        |   17 +-
 Utilities/cmcurl/lib/progress.c                    |   58 +-
 Utilities/cmcurl/lib/rand.c                        |  179 +
 Utilities/cmcurl/lib/rand.h                        |   47 +
 Utilities/cmcurl/lib/rtsp.c                        |   94 +-
 Utilities/cmcurl/lib/security.c                    |   17 +-
 Utilities/cmcurl/lib/select.c                      |   10 +-
 Utilities/cmcurl/lib/select.h                      |    8 +-
 Utilities/cmcurl/lib/sendf.c                       |  195 +-
 Utilities/cmcurl/lib/sendf.h                       |    2 +
 Utilities/cmcurl/lib/setup-os400.h                 |   52 +-
 Utilities/cmcurl/lib/setup-vms.h                   |  139 +-
 Utilities/cmcurl/lib/share.h                       |    8 +-
 Utilities/cmcurl/lib/smb.c                         |   49 +-
 Utilities/cmcurl/lib/smtp.c                        |   17 +-
 Utilities/cmcurl/lib/socks.c                       |   55 +-
 Utilities/cmcurl/lib/socks.h                       |    5 +-
 Utilities/cmcurl/lib/socks_gssapi.c                |   24 +-
 Utilities/cmcurl/lib/socks_sspi.c                  |   11 +-
 Utilities/cmcurl/lib/speedcheck.c                  |   61 +-
 Utilities/cmcurl/lib/splay.c                       |  110 +-
 Utilities/cmcurl/lib/splay.h                       |    3 +-
 Utilities/cmcurl/lib/ssh.c                         |  377 +-
 Utilities/cmcurl/lib/strcase.c                     |   12 +-
 Utilities/cmcurl/lib/strcase.h                     |    1 +
 Utilities/cmcurl/lib/strdup.c                      |   23 +
 Utilities/cmcurl/lib/strdup.h                      |    1 +
 Utilities/cmcurl/lib/strerror.c                    |   32 +-
 Utilities/cmcurl/lib/strtoofft.c                   |    4 +-
 Utilities/cmcurl/lib/system_win32.c                |    4 +-
 Utilities/cmcurl/lib/telnet.c                      |  154 +-
 Utilities/cmcurl/lib/tftp.c                        |   22 +-
 Utilities/cmcurl/lib/timeval.c                     |   13 +-
 Utilities/cmcurl/lib/timeval.h                     |    6 +-
 Utilities/cmcurl/lib/transfer.c                    |  187 +-
 Utilities/cmcurl/lib/url.c                         | 1586 +++--
 Utilities/cmcurl/lib/url.h                         |   13 +
 Utilities/cmcurl/lib/urldata.h                     |  251 +-
 Utilities/cmcurl/lib/vauth/cleartext.c             |   24 +-
 Utilities/cmcurl/lib/vauth/digest.c                |   36 +-
 Utilities/cmcurl/lib/vauth/digest_sspi.c           |  290 +-
 Utilities/cmcurl/lib/vauth/krb5_gssapi.c           |    4 +-
 Utilities/cmcurl/lib/vauth/krb5_sspi.c             |    4 +-
 Utilities/cmcurl/lib/vauth/ntlm.c                  |   44 +-
 Utilities/cmcurl/lib/vauth/ntlm.h                  |    2 +-
 Utilities/cmcurl/lib/vauth/spnego_sspi.c           |    5 +-
 Utilities/cmcurl/lib/version.c                     |    3 +
 Utilities/cmcurl/lib/vtls/axtls.c                  |  105 +-
 Utilities/cmcurl/lib/vtls/axtls.h                  |    8 +-
 Utilities/cmcurl/lib/vtls/cyassl.c                 |  212 +-
 Utilities/cmcurl/lib/vtls/cyassl.h                 |   10 +-
 Utilities/cmcurl/lib/vtls/darwinssl.c              |  722 ++-
 Utilities/cmcurl/lib/vtls/darwinssl.h              |   30 +-
 Utilities/cmcurl/lib/vtls/gskit.c                  |  400 +-
 Utilities/cmcurl/lib/vtls/gskit.h                  |    7 +-
 Utilities/cmcurl/lib/vtls/gtls.c                   |  465 +-
 Utilities/cmcurl/lib/vtls/gtls.h                   |   15 +-
 Utilities/cmcurl/lib/vtls/mbedtls.c                |  263 +-
 Utilities/cmcurl/lib/vtls/mbedtls.h                |   12 +-
 Utilities/cmcurl/lib/vtls/nss.c                    |  522 +-
 Utilities/cmcurl/lib/vtls/nssg.h                   |   11 +-
 Utilities/cmcurl/lib/vtls/openssl.c                |  706 ++-
 Utilities/cmcurl/lib/vtls/openssl.h                |    9 +-
 Utilities/cmcurl/lib/vtls/polarssl.c               |  173 +-
 Utilities/cmcurl/lib/vtls/polarssl.h               |    3 +-
 Utilities/cmcurl/lib/vtls/schannel.c               |  226 +-
 Utilities/cmcurl/lib/vtls/schannel.h               |    4 +-
 Utilities/cmcurl/lib/vtls/vtls.c                   |  313 +-
 Utilities/cmcurl/lib/vtls/vtls.h                   |   48 +-
 Utilities/cmcurl/lib/warnless.c                    |    5 +-
 Utilities/cmcurl/lib/wildcard.c                    |   18 +-
 Utilities/cmcurl/lib/wildcard.h                    |    9 +-
 Utilities/cmcurl/lib/x509asn1.c                    |  195 +-
 Utilities/cmcurl/lib/x509asn1.h                    |   26 +-
 Utilities/cmexpat/COPYING                          |    5 +-
 Utilities/cmexpat/README                           |    4 +-
 Utilities/cmexpat/lib/expat.h                      |   30 +-
 Utilities/cmexpat/lib/expat_external.h             |    5 +-
 Utilities/cmexpat/lib/siphash.h                    |  354 ++
 Utilities/cmexpat/lib/winconfig.h                  |   19 +-
 Utilities/cmexpat/lib/xmlparse.c                   |  611 +-
 Utilities/cmexpat/lib/xmlrole.c                    |   10 +-
 Utilities/cmexpat/lib/xmltok.c                     |   34 +-
 Utilities/cmexpat/lib/xmltok_impl.c                |    4 +
 Utilities/cmjsoncpp/CMakeLists.txt                 |    1 +
 Utilities/cmlibarchive/CMakeLists.txt              |  145 +-
 .../build/cmake/CheckStructMember.cmake            |   43 -
 Utilities/cmlibarchive/build/cmake/FindLZMA.cmake  |   48 -
 Utilities/cmlibarchive/build/cmake/config.h.in     |   21 +
 Utilities/cmlibarchive/build/version               |    2 +-
 Utilities/cmlibarchive/libarchive/CMakeLists.txt   |   18 +
 Utilities/cmlibarchive/libarchive/archive.h        |   20 +-
 Utilities/cmlibarchive/libarchive/archive_acl.c    | 1639 +++--
 .../cmlibarchive/libarchive/archive_acl_private.h  |   22 +-
 .../cmlibarchive/libarchive/archive_cryptor.c      |    3 +-
 .../libarchive/archive_digest_private.h            |    1 +
 Utilities/cmlibarchive/libarchive/archive_entry.c  |  234 +-
 Utilities/cmlibarchive/libarchive/archive_entry.h  |   91 +-
 .../cmlibarchive/libarchive/archive_entry_acl.3    |  335 +-
 .../cmlibarchive/libarchive/archive_entry_locale.h |   10 +-
 .../libarchive/archive_entry_strmode.c             |    2 +-
 Utilities/cmlibarchive/libarchive/archive_hmac.c   |    4 +
 Utilities/cmlibarchive/libarchive/archive_match.c  |   14 +-
 .../libarchive/archive_openssl_evp_private.h       |    5 +-
 .../libarchive/archive_openssl_hmac_private.h      |    6 +-
 .../cmlibarchive/libarchive/archive_options.c      |   11 +-
 .../cmlibarchive/libarchive/archive_platform.h     |   28 +-
 .../libarchive/archive_ppmd7_private.h             |    2 +-
 Utilities/cmlibarchive/libarchive/archive_random.c |    2 +-
 Utilities/cmlibarchive/libarchive/archive_rb.c     |    2 +-
 Utilities/cmlibarchive/libarchive/archive_read.c   |   16 +-
 .../libarchive/archive_read_add_passphrase.c       |   22 +-
 .../libarchive/archive_read_append_filter.c        |    2 -
 .../cmlibarchive/libarchive/archive_read_disk.3    |    6 +-
 .../libarchive/archive_read_disk_entry_from_file.c | 1090 +++-
 .../libarchive/archive_read_disk_posix.c           |  135 +-
 .../libarchive/archive_read_disk_private.h         |   12 +-
 .../archive_read_disk_set_standard_lookup.c        |    2 +
 .../libarchive/archive_read_disk_windows.c         |   59 +-
 .../libarchive/archive_read_extract2.c             |    3 +-
 .../libarchive/archive_read_open_filename.c        |   20 +-
 .../libarchive/archive_read_open_memory.c          |    3 +-
 .../cmlibarchive/libarchive/archive_read_private.h |    3 +-
 .../libarchive/archive_read_support_filter_lz4.c   |   13 +-
 .../libarchive/archive_read_support_filter_lzop.c  |    2 +-
 .../archive_read_support_filter_program.c          |    2 +
 .../libarchive/archive_read_support_filter_uu.c    |   44 +-
 .../libarchive/archive_read_support_filter_xz.c    |  194 +-
 .../libarchive/archive_read_support_format_7zip.c  |   39 +-
 .../libarchive/archive_read_support_format_ar.c    |   22 +-
 .../libarchive/archive_read_support_format_cab.c   |   15 +-
 .../libarchive/archive_read_support_format_cpio.c  |   17 +-
 .../archive_read_support_format_iso9660.c          |   40 +-
 .../libarchive/archive_read_support_format_lha.c   |   13 +-
 .../libarchive/archive_read_support_format_mtree.c |   71 +-
 .../libarchive/archive_read_support_format_rar.c   |    5 +-
 .../libarchive/archive_read_support_format_tar.c   |  281 +-
 .../libarchive/archive_read_support_format_warc.c  |  241 +-
 .../libarchive/archive_read_support_format_xar.c   |   87 +-
 .../libarchive/archive_read_support_format_zip.c   |  122 +-
 Utilities/cmlibarchive/libarchive/archive_string.c |  117 +-
 Utilities/cmlibarchive/libarchive/archive_string.h |    8 +-
 .../libarchive/archive_string_composition.h        |    2 +-
 Utilities/cmlibarchive/libarchive/archive_util.c   |    2 +-
 .../cmlibarchive/libarchive/archive_windows.c      |    4 +-
 .../cmlibarchive/libarchive/archive_windows.h      |    4 +
 Utilities/cmlibarchive/libarchive/archive_write.c  |    8 +-
 .../libarchive/archive_write_add_filter_lz4.c      |    4 +-
 .../libarchive/archive_write_add_filter_program.c  |    1 +
 .../libarchive/archive_write_add_filter_xz.c       |    2 +-
 .../libarchive/archive_write_disk_acl.c            |  545 +-
 .../libarchive/archive_write_disk_posix.c          |  588 +-
 .../archive_write_disk_set_standard_lookup.c       |    6 +-
 .../libarchive/archive_write_disk_windows.c        |    7 +-
 .../cmlibarchive/libarchive/archive_write_open.3   |   11 +
 .../libarchive/archive_write_open_memory.c         |    3 +-
 .../libarchive/archive_write_set_format_7zip.c     |    4 +-
 .../libarchive/archive_write_set_format_ar.c       |    3 +-
 .../libarchive/archive_write_set_format_cpio.c     |    2 +-
 .../archive_write_set_format_cpio_newc.c           |    5 +-
 .../libarchive/archive_write_set_format_gnutar.c   |   14 +-
 .../libarchive/archive_write_set_format_iso9660.c  |   60 +-
 .../libarchive/archive_write_set_format_mtree.c    |    4 +-
 .../libarchive/archive_write_set_format_pax.c      |  183 +-
 .../libarchive/archive_write_set_format_shar.c     |    3 +-
 .../libarchive/archive_write_set_format_ustar.c    |   11 +-
 .../libarchive/archive_write_set_format_v7tar.c    |    9 +-
 .../libarchive/archive_write_set_format_warc.c     |    2 +-
 .../libarchive/archive_write_set_format_xar.c      |   21 +-
 .../libarchive/archive_write_set_format_zip.c      |   12 +-
 Utilities/cmlibarchive/libarchive/config_freebsd.h |    2 +
 .../cmlibarchive/libarchive/libarchive-formats.5   |    4 +-
 Utilities/cmlibarchive/libarchive/tar.5            |   11 +-
 Utilities/cmlibarchive/libarchive/xxhash.c         |    6 +-
 Utilities/cmliblzma/CMakeLists.txt                 |    4 +-
 Utilities/cmlibuv/CMakeLists.txt                   |   45 +
 Utilities/cmlibuv/include/pthread-barrier.h        |    2 +
 Utilities/cmlibuv/include/uv-os390.h               |    3 +
 Utilities/cmlibuv/include/uv-posix.h               |   31 +
 Utilities/cmlibuv/include/uv-unix.h                |   21 +-
 Utilities/cmlibuv/include/uv-version.h             |    4 +-
 Utilities/cmlibuv/include/uv-win.h                 |    1 +
 Utilities/cmlibuv/include/uv.h                     |   12 +
 Utilities/cmlibuv/src/threadpool.c                 |   35 +-
 Utilities/cmlibuv/src/unix/aix.c                   |   93 +-
 Utilities/cmlibuv/src/unix/async.c                 |  121 +-
 Utilities/cmlibuv/src/unix/atomic-ops.h            |   27 +-
 Utilities/cmlibuv/src/unix/bsd-ifaddrs.c           |  139 +
 Utilities/cmlibuv/src/unix/core.c                  |  102 +-
 Utilities/cmlibuv/src/unix/cygwin.c                |   54 +
 Utilities/cmlibuv/src/unix/darwin.c                |  104 -
 Utilities/cmlibuv/src/unix/freebsd.c               |  114 -
 Utilities/cmlibuv/src/unix/fs.c                    |   69 +-
 Utilities/cmlibuv/src/unix/fsevents.c              |    3 -
 Utilities/cmlibuv/src/unix/internal.h              |   34 +-
 Utilities/cmlibuv/src/unix/kqueue.c                |   36 +-
 Utilities/cmlibuv/src/unix/linux-core.c            |  102 +-
 Utilities/cmlibuv/src/unix/linux-inotify.c         |   67 +
 Utilities/cmlibuv/src/unix/loop.c                  |   38 +-
 Utilities/cmlibuv/src/unix/netbsd.c                |  108 -
 Utilities/cmlibuv/src/unix/no-fsevents.c           |   42 +
 Utilities/cmlibuv/src/unix/no-proctitle.c          |   42 +
 Utilities/cmlibuv/src/unix/openbsd.c               |  114 +-
 Utilities/cmlibuv/src/unix/os390-syscalls.c        |  334 +
 Utilities/cmlibuv/src/unix/os390-syscalls.h        |   69 +
 Utilities/cmlibuv/src/unix/os390.c                 |  807 +++
 Utilities/cmlibuv/src/unix/pipe.c                  |   15 +-
 Utilities/cmlibuv/src/unix/poll.c                  |    4 +-
 Utilities/cmlibuv/src/unix/posix-hrtime.c          |   35 +
 Utilities/cmlibuv/src/unix/posix-poll.c            |  324 +
 Utilities/cmlibuv/src/unix/process.c               |    4 +-
 Utilities/cmlibuv/src/unix/procfs-exepath.c        |   45 +
 Utilities/cmlibuv/src/unix/proctitle.c             |    6 +
 Utilities/cmlibuv/src/unix/pthread-barrier.c       |    3 +-
 Utilities/cmlibuv/src/unix/signal.c                |  108 +-
 Utilities/cmlibuv/src/unix/stream.c                |   47 +-
 Utilities/cmlibuv/src/unix/sunos.c                 |   72 +-
 Utilities/cmlibuv/src/unix/sysinfo-loadavg.c       |   36 +
 Utilities/cmlibuv/src/unix/sysinfo-memory.c        |   42 +
 Utilities/cmlibuv/src/unix/thread.c                |   32 +-
 Utilities/cmlibuv/src/unix/udp.c                   |   33 +-
 Utilities/cmlibuv/src/uv-common.c                  |   12 +-
 Utilities/cmlibuv/src/uv-common.h                  |   35 +-
 Utilities/cmlibuv/src/win/async.c                  |    3 +-
 Utilities/cmlibuv/src/win/atomicops-inl.h          |    3 +-
 Utilities/cmlibuv/src/win/core.c                   |   25 +-
 Utilities/cmlibuv/src/win/detect-wakeup.c          |    6 +-
 Utilities/cmlibuv/src/win/error.c                  |    1 +
 Utilities/cmlibuv/src/win/fs-event.c               |   36 +-
 Utilities/cmlibuv/src/win/fs.c                     |   14 +-
 Utilities/cmlibuv/src/win/getaddrinfo.c            |    7 +-
 Utilities/cmlibuv/src/win/getnameinfo.c            |    3 +-
 Utilities/cmlibuv/src/win/internal.h               |   23 +-
 Utilities/cmlibuv/src/win/pipe.c                   |   17 +-
 Utilities/cmlibuv/src/win/poll.c                   |   10 +-
 Utilities/cmlibuv/src/win/process-stdio.c          |    1 +
 Utilities/cmlibuv/src/win/process.c                |    5 +-
 Utilities/cmlibuv/src/win/req-inl.h                |    9 +-
 Utilities/cmlibuv/src/win/signal.c                 |  161 +-
 Utilities/cmlibuv/src/win/stream-inl.h             |    3 +-
 Utilities/cmlibuv/src/win/stream.c                 |    3 +-
 Utilities/cmlibuv/src/win/tcp.c                    |   13 +-
 Utilities/cmlibuv/src/win/tty.c                    |   96 +-
 Utilities/cmlibuv/src/win/udp.c                    |    6 +-
 Utilities/cmlibuv/src/win/util.c                   |  195 +-
 Utilities/cmlibuv/src/win/winapi.c                 |    2 +-
 Utilities/cmlibuv/src/win/winapi.h                 |    4 +
 Utilities/cmlibuv/src/win/winsock.c                |    2 +-
 bootstrap                                          |  193 +-
 2075 files changed, 64110 insertions(+), 40819 deletions(-)

diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000..a9d121a
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,30 @@
+---
+Checks: "-*,\
+misc-*,\
+-misc-incorrect-roundings,\
+-misc-macro-parentheses,\
+-misc-misplaced-widening-cast,\
+-misc-static-assert,\
+modernize-make-shared,\
+modernize-make-unique,\
+modernize-redundant-void-arg,\
+modernize-use-bool-literals,\
+modernize-use-nullptr,\
+modernize-use-override,\
+performance-*,\
+-performance-inefficient-string-concatenation,\
+readability-*,\
+-readability-function-size,\
+-readability-identifier-naming,\
+-readability-implicit-bool-cast,\
+-readability-inconsistent-declaration-parameter-name,\
+-readability-named-parameter,\
+-readability-redundant-declaration,\
+-readability-redundant-member-init,\
+-readability-simplify-boolean-expr,\
+"
+HeaderFilterRegex: 'Source/cm[^/]*\.(h|hxx|cxx)$'
+CheckOptions:
+  - key:    modernize-use-nullptr.NullMacros
+    value:  'CM_NULLPTR'
+...
diff --git a/Auxiliary/cmake.m4 b/Auxiliary/cmake.m4
index 3ef4c16..7beff41 100644
--- a/Auxiliary/cmake.m4
+++ b/Auxiliary/cmake.m4
@@ -24,10 +24,10 @@ AC_ARG_VAR([$1][_LIBS], [linker flags for $1. This overrides the cmake output])d
 
 failed=false
 AC_MSG_CHECKING([for $1])
-if test -n "$1[]_$2[]FLAGS"; then
+if test -z "${$1[]_$2[]FLAGS}"; then
     $1[]_$2[]FLAGS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=COMPILE $4` || failed=true
 fi
-if test -n "$1[]_LIBS"; then
+if test -z "${$1[]_LIBS}"; then
     $1[]_LIBS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=LINK $4` || failed=true
 fi
 
diff --git a/Auxiliary/vim/cmake.vim.in b/Auxiliary/vim/cmake.vim.in
index 89ece66..389d9e4 100644
--- a/Auxiliary/vim/cmake.vim.in
+++ b/Auxiliary/vim/cmake.vim.in
@@ -14,54 +14,56 @@ if exists("b:current_syntax")
   finish
 endif
 
-syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained
 syn region cmakeComment start="#" end="$" contains=cmakeTodo, at Spell
 syn region cmakeLuaComment start="\[\z(=*\)\[" end="\]\z1\]" contains=cmakeTodo, at Spell
-syn region cmakeGeneratorExpression start=/$</ end=/>/
-            \ contained oneline contains=CONTAINED,cmakeTodo,cmakeVariable,cmakeProperty,cmakeGeneratorExpressions
-syn region cmakeRegistry start=/\[/ end=/]/
-            \ contained oneline contains=CONTAINED,cmakeTodo,cmakeEscaped
-syn region cmakeVariableValue start=/\${/ end=/}/
-            \ contained oneline contains=CONTAINED,cmakeTodo,cmakeVariable
-syn region cmakeEnvironment start=/\$ENV{/ end=/}/
-            \ contained oneline contains=CONTAINED,cmakeTodo
-syn region cmakeString start=/"/ end=/"/
-            \ contains=CONTAINED,cmakeTodo
-syn region cmakeArguments start=/(/ end=/)/
-            \ contains=ALLBUT,cmakeArguments,cmakeTodo
+
+syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained
+syn region cmakeRegistry start="\[" end="]" contained oneline contains=cmakeTodo,cmakeEscaped
+
+syn region cmakeGeneratorExpression start="$<" end=">" contained oneline contains=cmakeVariableValue,cmakeProperty,cmakeGeneratorExpressions,cmakeTodo
+
+syn region cmakeString start='"' end='"' contained contains=cmakeTodo,cmakeVariableValue
+
+syn region cmakeVariableValue start="${" end="}" contained oneline contains=cmakeVariable,cmakeTodo
+
+syn region cmakeEnvironment start="$ENV{" end="}" contained oneline contains=cmakeTodo
+
+syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeArguments,cmakeTodo
 
 syn case match
-syn keyword cmakeProperty
+
+syn keyword cmakeProperty contained
             \ ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ADVANCED ALIASED_TARGET ALLOW_DUPLICATE_CUSTOM_TARGETS ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_API ANDROID_API_MIN ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES ANDROID_GUI ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE ARCHIVE_ [...]
-            \ contained
 
-syn keyword cmakeVariable
+syn keyword cmakeVariable contained
 @VARIABLE_LIST@
-            \ contained
 
-syn keyword cmakeModule
+syn keyword cmakeModule contained
 @MODULES@
-            \ contained
 
 @KEYWORDS@
 
-syn keyword cmakeGeneratorExpressions
+syn keyword cmakeGeneratorExpressions contained
 @GENERATOR_EXPRESSIONS@
-            \ contained
 
 syn case ignore
+
 syn keyword cmakeCommand
 @COMMAND_LIST@
             \ nextgroup=cmakeArguments
+
 syn keyword cmakeCommandConditional
 @CONDITIONALS@
             \ nextgroup=cmakeArguments
+
 syn keyword cmakeCommandRepeat
 @LOOPS@
             \ nextgroup=cmakeArguments
+
 syn keyword cmakeCommandDeprecated
 @DEPRECATED@
             \ nextgroup=cmakeArguments
+
 syn case match
 
 syn keyword cmakeTodo
@@ -76,15 +78,15 @@ hi def link cmakeComment Comment
 hi def link cmakeEnvironment Special
 hi def link cmakeEscaped Special
 hi def link cmakeGeneratorExpression WarningMsg
-hi def link cmakeGeneratorExpressions ModeMsg
+hi def link cmakeGeneratorExpressions Constant
 hi def link cmakeLuaComment Comment
 hi def link cmakeModule Include
 hi def link cmakeProperty Constant
 hi def link cmakeRegistry Underlined
 hi def link cmakeString String
 hi def link cmakeTodo TODO
-hi def link cmakeVariable Identifier
 hi def link cmakeVariableValue Type
+hi def link cmakeVariable Identifier
 
 @KEYWORDS_HIGHLIGHT@
 
diff --git a/Auxiliary/vim/extract-upper-case.pl b/Auxiliary/vim/extract-upper-case.pl
index e945d52..ea77cbb 100755
--- a/Auxiliary/vim/extract-upper-case.pl
+++ b/Auxiliary/vim/extract-upper-case.pl
@@ -3,6 +3,9 @@
 use strict;
 use warnings;
 
+#my $cmake = "/home/pboettch/devel/upstream/cmake/build/bin/cmake";
+my $cmake = "cmake";
+
 my @variables;
 my @commands;
 my @properties;
@@ -10,7 +13,7 @@ my @modules;
 my %keywords; # command => keyword-list
 
 # unwanted upper-cases
-my %unwanted = map { $_ => 1 } qw(VS CXX IDE NOTFOUND NO_ DFOO DBAR);
+my %unwanted = map { $_ => 1 } qw(VS CXX IDE NOTFOUND NO_ DFOO DBAR NEW);
 	# cannot remove ALL - exists for add_custom_command
 
 # control-statements
@@ -24,9 +27,10 @@ my %deprecated = map { $_ => 1 } qw(build_name exec_program export_library_depen
 push @modules, "ExternalProject";
 
 # variables
-open(CMAKE, "cmake --help-variable-list|") or die "could not run cmake";
+open(CMAKE, "$cmake --help-variable-list|") or die "could not run cmake";
 while (<CMAKE>) {
 	chomp;
+	next if /\</; # skip VARIABLES which contained <>-"templates"
 	push @variables, $_;
 }
 close(CMAKE);
@@ -35,17 +39,16 @@ close(CMAKE);
 my %variables = map { $_ => 1 } @variables;
 
 # commands
-open(CMAKE, "cmake --help-command-list|");
+open(CMAKE, "$cmake --help-command-list|");
 while (my $cmd = <CMAKE>) {
 	chomp $cmd;
-
 	push @commands, $cmd;
 }
 close(CMAKE);
 
 # now generate a keyword-list per command
 foreach my $cmd (@commands) {
-	my @word = extract_upper("cmake --help-command $cmd|");
+	my @word = extract_upper("$cmake --help-command $cmd|");
 
 	next if scalar @word == 0;
 
@@ -54,7 +57,7 @@ foreach my $cmd (@commands) {
 
 # and now for modules
 foreach my $mod (@modules) {
-	my @word = extract_upper("cmake --help-module $mod|");
+	my @word = extract_upper("$cmake --help-module $mod|");
 
 	next if scalar @word == 0;
 
@@ -62,10 +65,10 @@ foreach my $mod (@modules) {
 }
 
 # and now for generator-expressions
-my @generator_expr = extract_upper("cmake --help-manual cmake-generator-expressions |");
+my @generator_expr = extract_upper("$cmake --help-manual cmake-generator-expressions |");
 
 # properties
-open(CMAKE, "cmake --help-property-list|");
+open(CMAKE, "$cmake --help-property-list|");
 while (<CMAKE>) {
 	chomp;
 	push @properties, $_;
@@ -88,7 +91,7 @@ while(<IN>)
 			                 ! exists $deprecated{$_} } @commands;
 			print OUT " " x 12 , "\\ ", join(" ", @tmp), "\n";
 		} elsif ($1 eq "VARIABLE_LIST") {
-			print OUT " " x 12 , "\\ ", join(" ", @variables), "\n";
+			print OUT " " x 12 , "\\ ", join(" ", sort keys %variables), "\n";
 		} elsif ($1 eq "MODULES") {
 			print OUT " " x 12 , "\\ ", join("\n", @modules), "\n";
 		} elsif ($1 eq "GENERATOR_EXPRESSIONS") {
@@ -101,9 +104,8 @@ while(<IN>)
 			print OUT " " x 12 , "\\ ", join(" ", sort keys %deprecated), "\n";
 		} elsif ($1 eq "KEYWORDS") {
 			foreach my $k (sort keys %keywords) {
-				print OUT "syn keyword cmakeKW$k\n";
+				print OUT "syn keyword cmakeKW$k contained\n";
 				print OUT " " x 12, "\\ ", join(" ", @{$keywords{$k}}), "\n";
-				print OUT " " x 12, "\\ contained\n";
 				print OUT "\n";
 				push @keyword_hi, "hi def link cmakeKW$k ModeMsg";
 			}
@@ -130,7 +132,8 @@ sub extract_upper
 		foreach my $w (m/\b([A-Z_]{2,})\b/g) {
 			next
 				if exists $variables{$w} or  # skip if it is a variable
-				   exists $unwanted{$w};     # skip if not wanted
+				   exists $unwanted{$w} or   # skip if not wanted
+				   grep(/$w/, @word);     # skip if already in array
 
 			push @word, $w;
 		}
diff --git a/Auxiliary/vim/indent/cmake.vim b/Auxiliary/vim/indent/cmake.vim
index 76aff64..6063e43 100644
--- a/Auxiliary/vim/indent/cmake.vim
+++ b/Auxiliary/vim/indent/cmake.vim
@@ -14,6 +14,7 @@ if exists("b:did_indent")
 endif
 let b:did_indent = 1
 
+setlocal et
 setlocal indentexpr=CMakeGetIndent(v:lnum)
 setlocal indentkeys+==ENDIF(,ENDFOREACH(,ENDMACRO(,ELSE(,ELSEIF(,ENDWHILE(
 
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index 1f19cb7..a191c18 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -14,425 +14,334 @@ if exists("b:current_syntax")
   finish
 endif
 
-syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained
 syn region cmakeComment start="#" end="$" contains=cmakeTodo, at Spell
 syn region cmakeLuaComment start="\[\z(=*\)\[" end="\]\z1\]" contains=cmakeTodo, at Spell
-syn region cmakeGeneratorExpression start=/$</ end=/>/
-            \ contained oneline contains=CONTAINED,cmakeTodo,cmakeVariable,cmakeProperty,cmakeGeneratorExpressions
-syn region cmakeRegistry start=/\[/ end=/]/
-            \ contained oneline contains=CONTAINED,cmakeTodo,cmakeEscaped
-syn region cmakeVariableValue start=/\${/ end=/}/
-            \ contained oneline contains=CONTAINED,cmakeTodo,cmakeVariable
-syn region cmakeEnvironment start=/\$ENV{/ end=/}/
-            \ contained oneline contains=CONTAINED,cmakeTodo
-syn region cmakeString start=/"/ end=/"/
-            \ contains=CONTAINED,cmakeTodo
-syn region cmakeArguments start=/(/ end=/)/
-            \ contains=ALLBUT,cmakeArguments,cmakeTodo
+
+syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained
+syn region cmakeRegistry start="\[" end="]" contained oneline contains=cmakeTodo,cmakeEscaped
+
+syn region cmakeGeneratorExpression start="$<" end=">" contained oneline contains=cmakeVariableValue,cmakeProperty,cmakeGeneratorExpressions,cmakeTodo
+
+syn region cmakeString start='"' end='"' contained contains=cmakeTodo,cmakeVariableValue
+
+syn region cmakeVariableValue start="${" end="}" contained oneline contains=cmakeVariable,cmakeTodo
+
+syn region cmakeEnvironment start="$ENV{" end="}" contained oneline contains=cmakeTodo
+
+syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeArguments,cmakeTodo
 
 syn case match
-syn keyword cmakeProperty
-            \ ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ADVANCED ALIASED_TARGET ALLOW_DUPLICATE_CUSTOM_TARGETS ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_API ANDROID_API_MIN ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES ANDROID_GUI ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE ARCHIVE_ [...]
-            \ contained
 
-syn keyword cmakeVariable
-            \ <PROJECT-NAME>_BINARY_DIR <PROJECT-NAME>_SOURCE_DIR <PROJECT-NAME>_VERSION <PROJECT-NAME>_VERSION_MAJOR <PROJECT-NAME>_VERSION_MINOR <PROJECT-NAME>_VERSION_PATCH <PROJECT-NAME>_VERSION_TWEAK APPLE BORLAND BUILD_SHARED_LIBS CMAKE_<CONFIG>_POSTFIX CMAKE_<LANG>_ARCHIVE_APPEND CMAKE_<LANG>_ARCHIVE_CREATE CMAKE_<LANG>_ARCHIVE_FINISH CMAKE_<LANG>_COMPILER CMAKE_<LANG>_COMPILER_ABI CMAKE_<LANG>_COMPILER_EXTERNAL_TOOLCHAIN CMAKE_<LANG>_COMPILER_ID CMAKE_<LANG>_COMPILER_LAUNCHER CMA [...]
-            \ contained
+syn keyword cmakeProperty contained
+            \ ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ADVANCED ALIASED_TARGET ALLOW_DUPLICATE_CUSTOM_TARGETS ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_API ANDROID_API_MIN ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES ANDROID_GUI ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE ARCHIVE_ [...]
 
-syn keyword cmakeModule
+syn keyword cmakeVariable contained
+            \ ANDROID APPLE BORLAND BUILD_SHARED_LIBS CMAKE_ABSOLUTE_DESTINATION_FILES CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS CMAKE_ANDROID_API CMAKE_ANDROID_API_MIN CMAKE_ANDROID_ARCH CMAKE_ANDROID_ARCH_ABI CMAKE_ANDROID_ARM_MODE CMAKE_ANDROID_ARM_NEON CMAKE_ANDROID_ASSETS_DIRECTORIES CMAKE_ANDROID_GUI CMAKE_ANDROID_JAR_DEPENDENCIES CMAKE_ANDROID_JAR_DIRECTORIES CMAKE_ANDROID_JAVA_SOURCE_DIR CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES CMAKE_ANDROID_NDK CMAKE [...]
+
+syn keyword cmakeModule contained
             \ ExternalProject
-            \ contained
 
-syn keyword cmakeKWExternalProject
-            \ ALGO ALWAYS BINARY_DIR BUILD_ALWAYS BUILD_BYPRODUCTS BUILD_COMMAND BUILD_IN_SOURCE BYPRODUCTS CMAKE_ARGS CMAKE_CACHE_ARGS CMAKE_CACHE_DEFAULT_ARGS COMMAND COMMENT CONFIGURE_COMMAND CVS CVSROOT CVS_ CVS_MODULE CVS_REPOSITORY CVS_TAG DEPENDEES DEPENDERS DEPENDS DIRECTORY DOWNLOAD_COMMAND DOWNLOAD_DIR DOWNLOAD_NAME DOWNLOAD_NO_PROGRESS EP_BASE EP_INDEPENDENT_STEP_TARGETS EP_PREFIX EP_STEP_TARGETS EP_UPDATE_DISCONNECTED EXCLUDE_FROM_ALL EXCLUDE_FROM_MAIN FORCE GIT_REMOTE_NAME G [...]
-            \ contained
+syn keyword cmakeKWExternalProject contained
+            \ ALGO BINARY_DIR BUILD_ALWAYS BUILD_BYPRODUCTS BUILD_COMMAND BUILD_IN_SOURCE CMAKE_ARGS CMAKE_CACHE_ARGS CMAKE_CACHE_DEFAULT_ARGS COMMENT CONFIGURE_COMMAND CVSROOT CVS_MODULE CVS_REPOSITORY CVS_TAG DEPENDEES DEPENDERS DEPENDS DOWNLOADED_FILE DOWNLOAD_COMMAND DOWNLOAD_DIR DOWNLOAD_NAME DOWNLOAD_NO_EXTRACT DOWNLOAD_NO_PROGRESS EP_BASE EP_INDEPENDENT_STEP_TARGETS EP_PREFIX EP_STEP_TARGETS EP_UPDATE_DISCONNECTED EXCLUDE_FROM_ALL FORCE GIT_CONFIG GIT_PROGRESS GIT_REMOTE_NAME GIT_ [...]
 
-syn keyword cmakeKWadd_compile_options
+syn keyword cmakeKWadd_compile_options contained
             \ COMPILE_OPTIONS
-            \ contained
 
-syn keyword cmakeKWadd_custom_command
-            \ APPEND ARGS BYPRODUCTS COMMAND COMMENT DEPENDS GENERATE GENERATED IMPLICIT_DEPENDS MAIN_DEPENDENCY NOT OUTPUT POST_BUILD PRE_BUILD PRE_LINK SYMBOLIC TARGET TARGET_FILE USES_TERMINAL VERBATIM WORKING_DIRECTORY
-            \ contained
+syn keyword cmakeKWadd_custom_command contained
+            \ APPEND ARGS BYPRODUCTS CC COMMAND COMMAND_EXPAND_LISTS COMMENT CROSSCOMPILING_EMULATOR DEPENDS DEPFILE GENERATED IMPLICIT_DEPENDS INCLUDE_DIRECTORIES JOIN MAIN_DEPENDENCY NOT OUTPUT POST_BUILD PRE_BUILD PRE_LINK SYMBOLIC TARGET_FILE TARGET_PROPERTY USES_TERMINAL VERBATIM WORKING_DIRECTORY
 
-syn keyword cmakeKWadd_custom_target
-            \ ALL BYPRODUCTS COMMAND COMMENT DEPENDS GENERATE GENERATED SOURCES USES_TERMINAL VERBATIM WORKING_DIRECTORY
-            \ contained
+syn keyword cmakeKWadd_custom_target contained
+            \ ALL BYPRODUCTS CC COMMAND COMMAND_EXPAND_LISTS COMMENT CROSSCOMPILING_EMULATOR DEPENDS GENERATED INCLUDE_DIRECTORIES JOIN SOURCES TARGET_PROPERTY USES_TERMINAL VERBATIM WORKING_DIRECTORY
 
-syn keyword cmakeKWadd_definitions
+syn keyword cmakeKWadd_definitions contained
             \ COMPILE_DEFINITIONS
-            \ contained
 
-syn keyword cmakeKWadd_dependencies
+syn keyword cmakeKWadd_dependencies contained
             \ DEPENDS OBJECT_DEPENDS
-            \ contained
 
-syn keyword cmakeKWadd_executable
+syn keyword cmakeKWadd_executable contained
             \ ALIAS CONFIG EXCLUDE_FROM_ALL GLOBAL IMPORTED IMPORTED_ IMPORTED_LOCATION IMPORTED_LOCATION_ MACOSX_BUNDLE OUTPUT_NAME RUNTIME_OUTPUT_DIRECTORY TARGET
-            \ contained
 
-syn keyword cmakeKWadd_library
-            \ ALIAS ARCHIVE_OUTPUT_DIRECTORY CLI CONFIG DLL EXCLUDE_FROM_ALL FRAMEWORK GLOBAL IMPORTED IMPORTED_ IMPORTED_LOCATION IMPORTED_LOCATION_ INTERFACE INTERFACE_ LIBRARY_OUTPUT_DIRECTORY MODULE OBJECT ON OS OUTPUT_NAME POSITION_INDEPENDENT_CODE POST_BUILD PRE_BUILD PRE_LINK RUNTIME_OUTPUT_DIRECTORY SHARED STATIC TARGET TARGET_OBJECTS UNKNOWN
-            \ contained
+syn keyword cmakeKWadd_library contained
+            \ ALIAS ARCHIVE_OUTPUT_DIRECTORY CLI CONFIG DLL EXCLUDE_FROM_ALL FRAMEWORK GLOBAL IMPORTED IMPORTED_ IMPORTED_LOCATION IMPORTED_LOCATION_ INTERFACE_ LIBRARY_OUTPUT_DIRECTORY MODULE OBJECT ON OUTPUT_NAME POSITION_INDEPENDENT_CODE POST_BUILD PRE_BUILD PRE_LINK RUNTIME_OUTPUT_DIRECTORY SHARED STATIC TARGET_OBJECTS UNKNOWN
 
-syn keyword cmakeKWadd_subdirectory
-            \ ALL EXCLUDE_FROM_ALL
-            \ contained
+syn keyword cmakeKWadd_subdirectory contained
+            \ EXCLUDE_FROM_ALL
 
-syn keyword cmakeKWadd_test
-            \ BUILD_TESTING COMMAND CONFIGURATION CONFIGURATIONS FAIL_REGULAR_EXPRESSION NAME ON PASS_REGULAR_EXPRESSION TARGET_FILE WILL_FAIL WORKING_DIRECTORY
-            \ contained
+syn keyword cmakeKWadd_test contained
+            \ BUILD_TESTING COMMAND CONFIGURATIONS FAIL_REGULAR_EXPRESSION NAME PASS_REGULAR_EXPRESSION TARGET_FILE WILL_FAIL WORKING_DIRECTORY
 
-syn keyword cmakeKWbuild_command
-            \ CONFIGURATION NEW TARGET
-            \ contained
+syn keyword cmakeKWbuild_command contained
+            \ CONFIGURATION TARGET
 
-syn keyword cmakeKWbuild_name
+syn keyword cmakeKWbuild_name contained
             \ CMAKE_CXX_COMPILER
-            \ contained
 
-syn keyword cmakeKWcmake_host_system_information
+syn keyword cmakeKWcmake_host_system_information contained
             \ AVAILABLE_PHYSICAL_MEMORY AVAILABLE_VIRTUAL_MEMORY FQDN HOSTNAME NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES QUERY RESULT TOTAL_PHYSICAL_MEMORY TOTAL_VIRTUAL_MEMORY
-            \ contained
 
-syn keyword cmakeKWcmake_minimum_required
+syn keyword cmakeKWcmake_minimum_required contained
             \ FATAL_ERROR VERSION
-            \ contained
 
-syn keyword cmakeKWcmake_parse_arguments
-            \ ARGN CONFIGURATIONS DESTINATION FALSE FAST FILES MY_INSTALL MY_INSTALL_CONFIGURATIONS MY_INSTALL_DESTINATION MY_INSTALL_FAST MY_INSTALL_OPTIONAL MY_INSTALL_RENAME MY_INSTALL_TARGETS MY_INSTALL_UNPARSED_ARGUMENTS OPTIONAL RENAME TARGETS TRUE _UNPARSED_ARGUMENTS
-            \ contained
+syn keyword cmakeKWcmake_parse_arguments contained
+            \ ARGN CONFIGURATIONS DESTINATION FALSE FAST FILES MY_INSTALL MY_INSTALL_CONFIGURATIONS MY_INSTALL_DESTINATION MY_INSTALL_FAST MY_INSTALL_OPTIONAL MY_INSTALL_RENAME MY_INSTALL_TARGETS MY_INSTALL_UNPARSED_ARGUMENTS OPTIONAL PARSE_ARGV RENAME TARGETS TRUE _UNPARSED_ARGUMENTS
 
-syn keyword cmakeKWcmake_policy
-            \ CMAKE_POLICY_DEFAULT_CMP CMP GET NEW NNNN NO_POLICY_SCOPE OLD POP PUSH SET VERSION
-            \ contained
+syn keyword cmakeKWcmake_policy contained
+            \ CMAKE_POLICY_DEFAULT_CMP CMP GET NNNN NO_POLICY_SCOPE OLD POP PUSH SET VERSION
 
-syn keyword cmakeKWconfigure_file
-            \ COPYONLY CRLF DOS ESCAPE_QUOTES FOO_ENABLE FOO_STRING LF NEWLINE_STYLE ON ONLY VAR
-            \ contained
+syn keyword cmakeKWconfigure_file contained
+            \ COPYONLY CRLF DOS ESCAPE_QUOTES FOO_ENABLE FOO_STRING LF NEWLINE_STYLE VAR
 
-syn keyword cmakeKWcreate_test_sourcelist
+syn keyword cmakeKWcreate_test_sourcelist contained
             \ CMAKE_TESTDRIVER_AFTER_TESTMAIN CMAKE_TESTDRIVER_BEFORE_TESTMAIN EXTRA_INCLUDE FUNCTION
-            \ contained
 
-syn keyword cmakeKWctest_build
-            \ ALL_BUILD APPEND BUILD CONFIGURATION CTEST_BUILD_CONFIGURATION CTEST_BUILD_FLAGS CTEST_BUILD_TARGET CTEST_PROJECT_NAME FLAGS NUMBER_ERRORS NUMBER_WARNINGS QUIET RETURN_VALUE TARGET
-            \ contained
+syn keyword cmakeKWctest_build contained
+            \ ALL_BUILD APPEND BUILD CAPTURE_CMAKE_ERROR CONFIGURATION CTEST_BUILD_CONFIGURATION CTEST_BUILD_FLAGS CTEST_BUILD_TARGET CTEST_PROJECT_NAME FLAGS NUMBER_ERRORS NUMBER_WARNINGS QUIET RETURN_VALUE TARGET
 
-syn keyword cmakeKWctest_configure
-            \ APPEND BUILD OPTIONS QUIET RETURN_VALUE SOURCE
-            \ contained
+syn keyword cmakeKWctest_configure contained
+            \ APPEND BUILD CAPTURE_CMAKE_ERROR OPTIONS QUIET RETURN_VALUE SOURCE
 
-syn keyword cmakeKWctest_coverage
-            \ APPEND BUILD LABELS QUIET RETURN_VALUE
-            \ contained
+syn keyword cmakeKWctest_coverage contained
+            \ APPEND BUILD CAPTURE_CMAKE_ERROR LABELS QUIET RETURN_VALUE
 
-syn keyword cmakeKWctest_memcheck
-            \ APPEND BUILD DEFECT_COUNT END EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD
-            \ contained
+syn keyword cmakeKWctest_memcheck contained
+            \ APPEND BUILD DEFECT_COUNT EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD
 
-syn keyword cmakeKWctest_run_script
+syn keyword cmakeKWctest_run_script contained
             \ NEW_PROCESS RETURN_VALUE
-            \ contained
 
-syn keyword cmakeKWctest_start
+syn keyword cmakeKWctest_start contained
             \ APPEND QUIET TAG TRACK
-            \ contained
 
-syn keyword cmakeKWctest_submit
+syn keyword cmakeKWctest_submit contained
             \ API CDASH_UPLOAD CDASH_UPLOAD_TYPE CTEST_EXTRA_SUBMIT_FILES CTEST_NOTES_FILES FILES PARTS QUIET RETRY_COUNT RETRY_DELAY RETURN_VALUE
-            \ contained
 
-syn keyword cmakeKWctest_test
-            \ APPEND BUILD CPU END EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD
-            \ contained
+syn keyword cmakeKWctest_test contained
+            \ APPEND BUILD CAPTURE_CMAKE_ERROR CPU EXCLUDE EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD
 
-syn keyword cmakeKWctest_update
+syn keyword cmakeKWctest_update contained
             \ QUIET RETURN_VALUE SOURCE
-            \ contained
 
-syn keyword cmakeKWctest_upload
-            \ FILES QUIET
-            \ contained
+syn keyword cmakeKWctest_upload contained
+            \ CAPTURE_CMAKE_ERROR FILES QUIET
 
-syn keyword cmakeKWdefine_property
+syn keyword cmakeKWdefine_property contained
             \ BRIEF_DOCS CACHED_VARIABLE DIRECTORY FULL_DOCS GLOBAL INHERITED PROPERTY SOURCE TARGET TEST VARIABLE
-            \ contained
 
-syn keyword cmakeKWenable_language
+syn keyword cmakeKWenable_language contained
             \ OPTIONAL
-            \ contained
 
-syn keyword cmakeKWexec_program
+syn keyword cmakeKWexec_program contained
             \ ARGS OUTPUT_VARIABLE RETURN_VALUE
-            \ contained
 
-syn keyword cmakeKWexecute_process
-            \ COMMAND ERROR_ ERROR_FILE ERROR_QUIET ERROR_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE INPUT_ INPUT_FILE OUTPUT_ OUTPUT_FILE OUTPUT_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE RESULT_VARIABLE TIMEOUT VERBATIM WORKING_DIRECTORY
-            \ contained
+syn keyword cmakeKWexecute_process contained
+            \ ANSI AUTO COMMAND ENCODING ERROR_FILE ERROR_QUIET ERROR_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE INPUT_FILE NONE OEM OUTPUT_FILE OUTPUT_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE RESULT_VARIABLE TIMEOUT UTF VERBATIM WORKING_DIRECTORY
 
-syn keyword cmakeKWexport
-            \ APPEND CONFIG EXPORT EXPORT_LINK_INTERFACE_LIBRARIES FILE IMPORTED IMPORTED_ LINK_INTERFACE_LIBRARIES NAMESPACE NEW PACKAGE TARGETS
-            \ contained
+syn keyword cmakeKWexport contained
+            \ ANDROID_MK APPEND CONFIG EXPORT EXPORT_LINK_INTERFACE_LIBRARIES FILE IMPORTED IMPORTED_ NAMESPACE NDK OLD PACKAGE TARGETS
 
-syn keyword cmakeKWexport_library_dependencies
+syn keyword cmakeKWexport_library_dependencies contained
             \ APPEND EXPORT INCLUDE LINK_INTERFACE_LIBRARIES SET
-            \ contained
 
-syn keyword cmakeKWfile
-            \ ALGO APPEND ASCII CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY CONDITION CONFIG CONTENT COPY CR DESTINATION DIRECTORY DIRECTORY_PERMISSIONS DOWNLOAD ENCODING EXCLUDE EXPECTED_HASH FILE FILES_MATCHING FILE_PERMISSIONS FOLLOW_SYMLINKS FUNCTION GENERATE GLOB GLOB_RECURSE GUARD HEX INACTIVITY_TIMEOUT INPUT INSTALL LENGTH_MAXIMUM LENGTH_MINIMUM LF LIMIT LIMIT_COUNT LIMIT_INPUT LIMIT_OUTPUT LIST_DIRECTORIES LOCK LOG MAKE_DIRECTORY NEW NEWLINE_CONSUME NO_HEX_CONVERSION NO_SOURCE_PERMISSIONS  [...]
-            \ contained
+syn keyword cmakeKWfile contained
+            \ ALGO APPEND ASCII CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY CONDITION CONFIG CONTENT COPY CR DESTINATION DIRECTORY_PERMISSIONS DOWNLOAD ENCODING EXCLUDE EXPECTED_HASH FILES_MATCHING FILE_PERMISSIONS FOLLOW_SYMLINKS FUNCTION GENERATE GLOB GLOB_RECURSE GUARD HASH HEX HTTPHEADER INACTIVITY_TIMEOUT INSTALL LENGTH_MAXIMUM LENGTH_MINIMUM LF LIMIT LIMIT_COUNT LIMIT_INPUT LIMIT_OUTPUT LIST_DIRECTORIES LOCK LOG MAKE_DIRECTORY NEWLINE_CONSUME NO_HEX_CONVERSION NO_SOURCE_PERMISSIONS OFFSET OL [...]
 
-syn keyword cmakeKWfind_file
-            \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATH PATHS PATH_SUFFIXES VAR
-            \ contained
+syn keyword cmakeKWfind_file contained
+            \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR
 
-syn keyword cmakeKWfind_library
-            \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS LIB NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATH PATHS PATH_SUFFIXES VAR
-            \ contained
+syn keyword cmakeKWfind_library contained
+            \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS LIB NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR
 
-syn keyword cmakeKWfind_package
-            \ CMAKE_DISABLE_FIND_PACKAGE_ CMAKE_FIND_ROOT_PATH_BOTH COMPONENTS CONFIG CONFIGS DVAR EXACT HINTS MODULE NAMES NO_CMAKE_BUILDS_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_PATH NO_CMAKE_SYSTEM_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_MODULE NO_POLICY_SCOPE NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OPTIONAL_COMPONENTS OS PACKAGE_FIND_NAME PACKAGE_FIND_VERSION PACKAGE_FIND_VERSION_COUNT PACKAGE_FIND_VERSIO [...]
-            \ contained
+syn keyword cmakeKWfind_package contained
+            \ CMAKE_DISABLE_FIND_PACKAGE_ CMAKE_FIND_ROOT_PATH_BOTH COMPONENTS CONFIG CONFIGS DEC DVAR EXACT HINTS MODULE NAMES NATURAL NO_CMAKE_BUILDS_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_PATH NO_CMAKE_SYSTEM_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_MODULE NO_POLICY_SCOPE NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OPTIONAL_COMPONENTS OS PACKAGE_FIND_NAME PACKAGE_FIND_VERSION PACKAGE_FIND_VERSION_COUNT PACKAGE [...]
 
-syn keyword cmakeKWfind_path
-            \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATH PATHS PATH_SUFFIXES VAR
-            \ contained
+syn keyword cmakeKWfind_path contained
+            \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR
 
-syn keyword cmakeKWfind_program
-            \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATH PATHS PATH_SUFFIXES VAR
-            \ contained
+syn keyword cmakeKWfind_program contained
+            \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR
 
-syn keyword cmakeKWfltk_wrap_ui
+syn keyword cmakeKWfltk_wrap_ui contained
             \ FLTK
-            \ contained
 
-syn keyword cmakeKWforeach
+syn keyword cmakeKWforeach contained
             \ ARGS IN ITEMS LISTS RANGE
-            \ contained
 
-syn keyword cmakeKWfunction
+syn keyword cmakeKWfunction contained
             \ ARGC ARGN ARGS ARGV PARENT_SCOPE
-            \ contained
 
-syn keyword cmakeKWget_cmake_property
-            \ VAR
-            \ contained
+syn keyword cmakeKWget_cmake_property contained
+            \ COMPONENTS GLOBAL MACROS VAR VARIABLES
 
-syn keyword cmakeKWget_directory_property
+syn keyword cmakeKWget_directory_property contained
             \ DEFINITION DIRECTORY
-            \ contained
 
-syn keyword cmakeKWget_filename_component
+syn keyword cmakeKWget_filename_component contained
             \ ABSOLUTE ARG_VAR BASE_DIR CACHE COMP DIRECTORY EXT NAME NAME_WE PATH PROGRAM PROGRAM_ARGS REALPATH VAR
-            \ contained
 
-syn keyword cmakeKWget_property
+syn keyword cmakeKWget_property contained
             \ BRIEF_DOCS CACHE DEFINED DIRECTORY FULL_DOCS GLOBAL INSTALL PROPERTY SET SOURCE TARGET TEST VARIABLE
-            \ contained
 
-syn keyword cmakeKWget_source_file_property
+syn keyword cmakeKWget_source_file_property contained
             \ LOCATION VAR
-            \ contained
 
-syn keyword cmakeKWget_target_property
+syn keyword cmakeKWget_target_property contained
             \ VAR
-            \ contained
 
-syn keyword cmakeKWget_test_property
+syn keyword cmakeKWget_test_property contained
             \ VAR
-            \ contained
 
-syn keyword cmakeKWif
-            \ AND ARGS CMP COMMAND DEFINED EQUAL EXISTS FALSE GREATER IGNORE IN_LIST IS_ABSOLUTE IS_DIRECTORY IS_NEWER_THAN IS_SYMLINK LESS MATCHES NNNN NO NOT OFF ON OR POLICY STREQUAL STRGREATER STRLESS TARGET TEST THEN TRUE VERSION_EQUAL VERSION_GREATER VERSION_LESS YES
-            \ contained
+syn keyword cmakeKWif contained
+            \ ARGS CMAKE_MATCH_ CMP COMMAND DEFINED EQUAL EXISTS FALSE GREATER GREATER_EQUAL IGNORE IN_LIST IS_ABSOLUTE IS_DIRECTORY IS_NEWER_THAN IS_SYMLINK LESS LESS_EQUAL MATCHES NNNN NOT OFF OR POLICY STREQUAL STRGREATER STRGREATER_EQUAL STRLESS STRLESS_EQUAL TARGET TEST THEN TRUE VERSION_EQUAL VERSION_GREATER VERSION_GREATER_EQUAL VERSION_LESS VERSION_LESS_EQUAL YES
 
-syn keyword cmakeKWinclude
-            \ NO_POLICY_SCOPE OPTIONAL RESULT_VARIABLE VAR
-            \ contained
+syn keyword cmakeKWinclude contained
+            \ NO_POLICY_SCOPE OPTIONAL RESULT_VARIABLE
 
-syn keyword cmakeKWinclude_directories
+syn keyword cmakeKWinclude_directories contained
             \ AFTER BEFORE INCLUDE_DIRECTORIES ON SYSTEM
-            \ contained
 
-syn keyword cmakeKWinclude_external_msproject
-            \ GUID PLATFORM TYPE WIX
-            \ contained
+syn keyword cmakeKWinclude_external_msproject contained
+            \ GUID MAP_IMPORTED_CONFIG_ PLATFORM TYPE WIX
 
-syn keyword cmakeKWinstall
-            \ ARCHIVE BUNDLE CODE COMPONENT CONFIG CONFIGURATIONS CVS DESTDIR DESTINATION DIRECTORY DIRECTORY_PERMISSIONS DLL EXCLUDE EXCLUDE_FROM_ALL EXPORT EXPORT_LINK_INTERFACE_LIBRARIES FILE FILES FILES_MATCHING FILE_PERMISSIONS FRAMEWORK GROUP_EXECUTE GROUP_READ GROUP_WRITE IMPORTED_ INCLUDES INSTALL_PREFIX INTERFACE_INCLUDE_DIRECTORIES LIBRARY LINK_INTERFACE_LIBRARIES MACOSX_BUNDLE MESSAGE MESSAGE_NEVER NAMELINK_ONLY NAMELINK_SKIP NAMESPACE NEW OPTIONAL OS OWNER_EXECUTE OWNER_READ  [...]
-            \ contained
+syn keyword cmakeKWinstall contained
+            \ ARCHIVE BUNDLE CODE COMPONENT CONFIGURATIONS CVS DESTDIR DESTINATION DIRECTORY DIRECTORY_PERMISSIONS DLL EXCLUDE_FROM_ALL EXPORT EXPORT_ANDROID_MK EXPORT_LINK_INTERFACE_LIBRARIES FILES FILES_MATCHING FILE_PERMISSIONS FRAMEWORK GROUP_EXECUTE GROUP_READ GROUP_WRITE IMPORTED_ INCLUDES INSTALL_PREFIX INTERFACE_INCLUDE_DIRECTORIES LIBRARY MACOSX_BUNDLE MESSAGE_NEVER NAMELINK_ONLY NAMELINK_SKIP NAMESPACE NDK OBJECTS OPTIONAL OWNER_EXECUTE OWNER_READ OWNER_WRITE PATTERN PERMISSION [...]
 
-syn keyword cmakeKWinstall_files
+syn keyword cmakeKWinstall_files contained
             \ FILES GLOB
-            \ contained
 
-syn keyword cmakeKWinstall_programs
+syn keyword cmakeKWinstall_programs contained
             \ FILES GLOB PROGRAMS TARGETS
-            \ contained
 
-syn keyword cmakeKWinstall_targets
+syn keyword cmakeKWinstall_targets contained
             \ DLL RUNTIME_DIRECTORY TARGETS
-            \ contained
 
-syn keyword cmakeKWlist
-            \ APPEND CACHE FIND GET INSERT INTERNAL LENGTH LIST NOTES PARENT_SCOPE REMOVE_AT REMOVE_DUPLICATES REMOVE_ITEM REVERSE SORT
-            \ contained
+syn keyword cmakeKWlist contained
+            \ APPEND CACHE EXCLUDE FILTER FIND GET INCLUDE INSERT INTERNAL LENGTH LIST NOTES PARENT_SCOPE REGEX REMOVE_AT REMOVE_DUPLICATES REMOVE_ITEM REVERSE SORT
 
-syn keyword cmakeKWload_cache
+syn keyword cmakeKWload_cache contained
             \ EXCLUDE INCLUDE_INTERNALS READ_WITH_PREFIX
-            \ contained
 
-syn keyword cmakeKWload_command
+syn keyword cmakeKWload_command contained
             \ CMAKE_LOADED_COMMAND_ COMMAND_NAME
-            \ contained
 
-syn keyword cmakeKWmacro
-            \ ARGC ARGN ARGS ARGV DEFINED GREATER IN LISTS NOT _BAR _FOO
-            \ contained
+syn keyword cmakeKWmacro contained
+            \ ARGC ARGN ARGS ARGV DEFINED GREATER LISTS NOT _BAR _FOO
 
-syn keyword cmakeKWmake_directory
+syn keyword cmakeKWmake_directory contained
             \ MAKE_DIRECTORY
-            \ contained
 
-syn keyword cmakeKWmark_as_advanced
+syn keyword cmakeKWmark_as_advanced contained
             \ CLEAR FORCE VAR
-            \ contained
 
-syn keyword cmakeKWmath
+syn keyword cmakeKWmath contained
             \ EXPR
-            \ contained
 
-syn keyword cmakeKWmessage
+syn keyword cmakeKWmessage contained
             \ AUTHOR_WARNING DEPRECATION FATAL_ERROR GUI SEND_ERROR STATUS WARNING
-            \ contained
 
-syn keyword cmakeKWoption
+syn keyword cmakeKWoption contained
             \ OFF ON
-            \ contained
 
-syn keyword cmakeKWproject
-            \ CMAKE_PROJECT_ LANGUAGES NAME NEW NONE PROJECT VERSION _BINARY_DIR _INCLUDE _SOURCE_DIR _VERSION _VERSION_MAJOR _VERSION_MINOR _VERSION_PATCH _VERSION_TWEAK
-            \ contained
+syn keyword cmakeKWproject contained
+            \ CMAKE_PROJECT_ DESCRIPTION LANGUAGES NAME NONE PROJECT VERSION _BINARY_DIR _INCLUDE _SOURCE_DIR _VERSION _VERSION_MAJOR _VERSION_MINOR _VERSION_PATCH _VERSION_TWEAK
 
-syn keyword cmakeKWremove
+syn keyword cmakeKWremove contained
             \ REMOVE_ITEM VALUE VAR
-            \ contained
 
-syn keyword cmakeKWseparate_arguments
-            \ MSDN UNIX_COMMAND VARIABLE WINDOWS WINDOWS_COMMAND _COMMAND
-            \ contained
+syn keyword cmakeKWseparate_arguments contained
+            \ MSDN NATIVE NATIVE_COMMAND UNIX_COMMAND WINDOWS WINDOWS_COMMAND _COMMAND
 
-syn keyword cmakeKWset
-            \ BOOL CACHE FILEPATH FORCE INTERNAL OFF ON PARENT_SCOPE PATH STRING STRINGS
-            \ contained
+syn keyword cmakeKWset contained
+            \ BOOL CACHE FILEPATH FORCE INTERNAL OFF ON PARENT_SCOPE STRING STRINGS
 
-syn keyword cmakeKWset_directory_properties
+syn keyword cmakeKWset_directory_properties contained
             \ PROPERTIES
-            \ contained
 
-syn keyword cmakeKWset_property
+syn keyword cmakeKWset_property contained
             \ APPEND APPEND_STRING CACHE DIRECTORY GLOBAL INSTALL PROPERTY SOURCE TARGET TEST WIX
-            \ contained
 
-syn keyword cmakeKWset_source_files_properties
+syn keyword cmakeKWset_source_files_properties contained
             \ PROPERTIES
-            \ contained
 
-syn keyword cmakeKWset_target_properties
+syn keyword cmakeKWset_target_properties contained
             \ PROPERTIES
-            \ contained
 
-syn keyword cmakeKWset_tests_properties
+syn keyword cmakeKWset_tests_properties contained
             \ PROPERTIES
-            \ contained
 
-syn keyword cmakeKWsource_group
-            \ FILES REGULAR_EXPRESSION
-            \ contained
+syn keyword cmakeKWsource_group contained
+            \ FILES PREFIX REGULAR_EXPRESSION TREE
 
-syn keyword cmakeKWstring
-            \ ALPHABET APPEND ASCII CMAKE_MATCH_ COMPARE CONCAT CONFIGURE EQUAL ESCAPE_QUOTES FIND GENEX_STRIP GREATER GUID LENGTH LESS MAKE_C_IDENTIFIER MATCH MATCHALL MATCHES NAME NAMESPACE NOTEQUAL ONLY RANDOM RANDOM_SEED REGEX REPLACE REVERSE STRIP SUBSTRING SZ TIMESTAMP TOLOWER TOUPPER TYPE UPPER UTC UUID
-            \ contained
+syn keyword cmakeKWstring contained
+            \ ALPHABET APPEND ASCII CMAKE_MATCH_ COMPARE CONCAT CONFIGURE EQUAL ESCAPE_QUOTES FIND GENEX_STRIP GREATER GREATER_EQUAL GUID HASH LENGTH LESS LESS_EQUAL MAKE_C_IDENTIFIER MATCH MATCHALL MATCHES NAMESPACE NOTEQUAL ONLY RANDOM RANDOM_SEED REGEX REPLACE REVERSE RFC SHA SOURCE_DATE_EPOCH STRIP SUBSTRING SZ TIMESTAMP TOLOWER TOUPPER TYPE US UTC UUID
 
-syn keyword cmakeKWsubdirs
+syn keyword cmakeKWsubdirs contained
             \ EXCLUDE_FROM_ALL PREORDER
-            \ contained
 
-syn keyword cmakeKWtarget_compile_definitions
+syn keyword cmakeKWtarget_compile_definitions contained
             \ COMPILE_DEFINITIONS INTERFACE INTERFACE_COMPILE_DEFINITIONS PRIVATE PUBLIC
-            \ contained
 
-syn keyword cmakeKWtarget_compile_features
+syn keyword cmakeKWtarget_compile_features contained
             \ COMPILE_FEATURES IMPORTED INTERFACE INTERFACE_COMPILE_FEATURES PRIVATE PUBLIC
-            \ contained
 
-syn keyword cmakeKWtarget_compile_options
+syn keyword cmakeKWtarget_compile_options contained
             \ BEFORE COMPILE_OPTIONS IMPORTED INTERFACE INTERFACE_COMPILE_OPTIONS PRIVATE PUBLIC
-            \ contained
 
-syn keyword cmakeKWtarget_include_directories
+syn keyword cmakeKWtarget_include_directories contained
             \ BEFORE BUILD_INTERFACE IMPORTED INCLUDE_DIRECTORIES INSTALL_INTERFACE INTERFACE INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES PRIVATE PUBLIC SYSTEM
-            \ contained
 
-syn keyword cmakeKWtarget_link_libraries
-            \ ALIAS DAG DEBUG_CONFIGURATIONS IMPORTED IMPORTED_NO_SONAME INTERFACE INTERFACE_LINK_LIBRARIES LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_DEBUG LINK_INTERFACE_MULTIPLICITY LINK_PRIVATE LINK_PUBLIC NEW OLD OSX PRIVATE PUBLIC SONAME STATIC
-            \ contained
+syn keyword cmakeKWtarget_link_libraries contained
+            \ ALIAS DAG DEBUG_CONFIGURATIONS IMPORTED IMPORTED_NO_SONAME INTERFACE INTERFACE_LINK_LIBRARIES LINK_FLAGS LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_DEBUG LINK_INTERFACE_MULTIPLICITY LINK_PRIVATE LINK_PUBLIC OLD OSX PRIVATE PUBLIC STATIC
 
-syn keyword cmakeKWtarget_sources
+syn keyword cmakeKWtarget_sources contained
             \ IMPORTED INTERFACE INTERFACE_SOURCES PRIVATE PUBLIC SOURCES
-            \ contained
 
-syn keyword cmakeKWtry_compile
-            \ ALL_BUILD CMAKE_FLAGS COMPILE_DEFINITIONS COPY_FILE COPY_FILE_ERROR DEFINED DLINK_LIBRARIES DVAR FALSE INCLUDE_DIRECTORIES LINK_DIRECTORIES LINK_LIBRARIES NEW NOT OUTPUT_VARIABLE RESULT_VAR SOURCES TRUE TYPE VALUE
-            \ contained
+syn keyword cmakeKWtry_compile contained
+            \ ALL_BUILD CMAKE_FLAGS COMPILE_DEFINITIONS COPY_FILE COPY_FILE_ERROR CUDA_EXTENSIONS CUDA_STANDARD CUDA_STANDARD_REQUIRED CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEFINED DLINK_LIBRARIES DVAR FALSE INCLUDE_DIRECTORIES LANG LINK_DIRECTORIES LINK_LIBRARIES NOT OUTPUT_VARIABLE RESULT_VAR SOURCES TRUE TYPE VALUE _EXTENSIONS _STANDARD _STANDARD_REQUIRED
 
-syn keyword cmakeKWtry_run
-            \ ARGS CMAKE_FLAGS COMPILE_DEFINITIONS COMPILE_OUTPUT_VARIABLE COMPILE_RESULT_VAR DLINK_LIBRARIES DVAR FAILED_TO_RUN FALSE INCLUDE_DIRECTORIES LINK_DIRECTORIES LINK_LIBRARIES OUTPUT_VARIABLE RUN_OUTPUT_VARIABLE RUN_RESULT_VAR TRUE TYPE VALUE __TRYRUN_OUTPUT
-            \ contained
+syn keyword cmakeKWtry_run contained
+            \ ARGS CMAKE_FLAGS COMPILE_DEFINITIONS COMPILE_OUTPUT_VARIABLE COMPILE_RESULT_VAR DLINK_LIBRARIES DVAR FAILED_TO_RUN FALSE INCLUDE_DIRECTORIES LINK_DIRECTORIES LINK_LIBRARIES RUN_OUTPUT_VARIABLE RUN_RESULT_VAR TRUE TYPE VALUE __TRYRUN_OUTPUT
 
-syn keyword cmakeKWunset
+syn keyword cmakeKWunset contained
             \ CACHE LD_LIBRARY_PATH PARENT_SCOPE
-            \ contained
 
-syn keyword cmakeKWuse_mangled_mesa
+syn keyword cmakeKWuse_mangled_mesa contained
             \ GL OUTPUT_DIRECTORY PATH_TO_MESA
-            \ contained
 
-syn keyword cmakeKWvariable_requires
+syn keyword cmakeKWvariable_requires contained
             \ RESULT_VARIABLE TEST_VARIABLE
-            \ contained
 
-syn keyword cmakeKWvariable_watch
+syn keyword cmakeKWvariable_watch contained
             \ COMMAND
-            \ contained
 
-syn keyword cmakeKWwhile
+syn keyword cmakeKWwhile contained
             \ ARGS
-            \ contained
 
-syn keyword cmakeKWwrite_file
+syn keyword cmakeKWwrite_file contained
             \ APPEND CONFIGURE_FILE NOTE WRITE
-            \ contained
 
 
-syn keyword cmakeGeneratorExpressions
-            \ LINK_LIBRARIES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS CONFIG DEBUG_MODE DEBUG_MODE BOOL AND OR NOT STREQUAL STREQUAL EQUAL EQUAL CONFIG MAP_IMPORTED_CONFIG_ CONFIG IMPORTED PLATFORM_ID C_COMPILER_ID CXX_COMPILER_ID VERSION_GREATER VERSION_LESS VERSION_EQUAL C_COMPILER_VERSION CXX_COMPILER_VERSION TARGET_POLICY NEW COMPILE_FEATURES C_STANDARD CXX_STANDARD COMPILE_LANGUAGE PRIVATE COMPILE_LANGUAGE PUBLIC PRIVATE COMPILE_LANGUAGE COMPILING_CXX PRIVATE COMPILE_LANGUAGE CXX_COM [...]
-            \ contained
+syn keyword cmakeGeneratorExpressions contained
+            \ LINK_LIBRARIES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS CONFIG DEBUG_MODE BOOL AND NOT IF STREQUAL MAP_IMPORTED_CONFIG_ PLATFORM_ID C_COMPILER_ID CXX_COMPILER_ID VERSION_LESS VERSION_GREATER VERSION_EQUAL VERSION_LESS_EQUAL VERSION_GREATER_EQUAL C_COMPILER_VERSION CXX_COMPILER_VERSION TARGET_POLICY COMPILE_FEATURES C_STANDARD CXX_STANDARD COMPILE_LANGUAGE PRIVATE PUBLIC COMPILING_CXX GNU OLD_COMPILER CMAKE_CXX_COMPILER_VERSION CONFIGURATION TARGET_FILE TARGET_FILE_NAME TARGE [...]
 
 syn case ignore
+
 syn keyword cmakeCommand
             \ add_compile_options add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_subdirectory add_test aux_source_directory break build_command cmake_host_system_information cmake_minimum_required cmake_parse_arguments cmake_policy configure_file continue create_test_sourcelist ctest_build ctest_configure ctest_coverage ctest_empty_binary_directory ctest_memcheck ctest_read_custom_files ctest_run_script ctest_sleep ctest_start ctest_s [...]
             \ nextgroup=cmakeArguments
+
 syn keyword cmakeCommandConditional
             \ else elseif endif if
             \ nextgroup=cmakeArguments
+
 syn keyword cmakeCommandRepeat
             \ endforeach endwhile foreach while
             \ nextgroup=cmakeArguments
+
 syn keyword cmakeCommandDeprecated
             \ build_name exec_program export_library_dependencies install_files install_programs install_targets link_libraries make_directory output_required_files remove subdir_depends subdirs use_mangled_mesa utility_source variable_requires write_file
             \ nextgroup=cmakeArguments
+
 syn case match
 
 syn keyword cmakeTodo
@@ -447,15 +356,15 @@ hi def link cmakeComment Comment
 hi def link cmakeEnvironment Special
 hi def link cmakeEscaped Special
 hi def link cmakeGeneratorExpression WarningMsg
-hi def link cmakeGeneratorExpressions ModeMsg
+hi def link cmakeGeneratorExpressions Constant
 hi def link cmakeLuaComment Comment
 hi def link cmakeModule Include
 hi def link cmakeProperty Constant
 hi def link cmakeRegistry Underlined
 hi def link cmakeString String
 hi def link cmakeTodo TODO
-hi def link cmakeVariable Identifier
 hi def link cmakeVariableValue Type
+hi def link cmakeVariable Identifier
 
 hi def link cmakeKWExternalProject ModeMsg
 hi def link cmakeKWadd_compile_options ModeMsg
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bec81a3..ed924eb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,14 +55,22 @@ if(NOT DEFINED CMAKE_C_STANDARD AND NOT CMake_NO_C_STANDARD)
   endif()
 endif()
 if(NOT DEFINED CMAKE_CXX_STANDARD AND NOT CMake_NO_CXX_STANDARD)
-  include(${CMake_SOURCE_DIR}/Source/Checks/cm_cxx14_cstdio.cmake)
-  if(NOT CMake_CXX14_CSTDIO_BROKEN)
-    set(CMAKE_CXX_STANDARD 14)
+  if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.14)
+    set(CMAKE_CXX_STANDARD 98)
   else()
-    set(CMAKE_CXX_STANDARD 11)
+    include(${CMake_SOURCE_DIR}/Source/Checks/cm_cxx14_cstdio.cmake)
+    if(NOT CMake_CXX14_CSTDIO_BROKEN)
+      set(CMAKE_CXX_STANDARD 14)
+    else()
+      set(CMAKE_CXX_STANDARD 11)
+    endif()
   endif()
 endif()
 if(NOT CMake_TEST_EXTERNAL_CMAKE)
+  # include special compile flags for some compilers
+  include(CompileFlags.cmake)
+
+  # check for available C++ features
   include(${CMake_SOURCE_DIR}/Source/Checks/cm_cxx_features.cmake)
 endif()
 
@@ -226,6 +234,31 @@ option(CMAKE_USE_FOLDERS "Enable folder grouping of projects in IDEs." ON)
 mark_as_advanced(CMAKE_USE_FOLDERS)
 
 
+option(CMake_RUN_CLANG_TIDY "Run clang-tidy with the compiler." OFF)
+if(CMake_RUN_CLANG_TIDY)
+  if(CMake_SOURCE_DIR STREQUAL CMake_BINARY_DIR)
+    message(FATAL_ERROR "CMake_RUN_CLANG_TIDY requires an out-of-source build!")
+  endif()
+  find_program(CLANG_TIDY_COMMAND NAMES clang-tidy)
+  if(NOT CLANG_TIDY_COMMAND)
+    message(FATAL_ERROR "CMake_RUN_CLANG_TIDY is ON but clang-tidy is not found!")
+  endif()
+  set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")
+endif()
+configure_file(.clang-tidy .clang-tidy COPYONLY)
+
+
+option(CMake_RUN_IWYU "Run include-what-you-use with the compiler." OFF)
+if(CMake_RUN_IWYU)
+  find_program(IWYU_COMMAND NAMES include-what-you-use iwyu)
+  if(NOT IWYU_COMMAND)
+    message(FATAL_ERROR "CMake_RUN_IWYU is ON but include-what-you-use is not found!")
+  endif()
+  set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
+    "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp")
+endif()
+
+
 #-----------------------------------------------------------------------
 # a macro that only sets the FOLDER target property if it's
 # "appropriate"
@@ -421,14 +454,15 @@ macro (CMAKE_BUILD_UTILITIES)
       if(NOT LIBLZMA_FOUND)
         message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!")
       endif()
-      set(LZMA_INCLUDE_DIR ${LIBLZMA_INCLUDE_DIRS})
-      set(LZMA_LIBRARY ${LIBLZMA_LIBRARIES})
     else()
       add_subdirectory(Utilities/cmliblzma)
       CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty")
-      set(LZMA_INCLUDE_DIR
+      set(LIBLZMA_HAS_AUTO_DECODER 1)
+      set(LIBLZMA_HAS_EASY_ENCODER 1)
+      set(LIBLZMA_HAS_LZMA_PRESET 1)
+      set(LIBLZMA_INCLUDE_DIR
         "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api")
-      set(LZMA_LIBRARY cmliblzma)
+      set(LIBLZMA_LIBRARY cmliblzma)
     endif()
   endif()
 
@@ -449,13 +483,14 @@ macro (CMAKE_BUILD_UTILITIES)
     add_definitions(-DLIBARCHIVE_STATIC)
     set(ENABLE_NETTLE OFF CACHE INTERNAL "Enable use of Nettle")
     set(ENABLE_OPENSSL ${CMAKE_USE_OPENSSL} CACHE INTERNAL "Enable use of OpenSSL")
-    set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system found LZMA library if found")
-    set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system found ZLIB library if found")
-    set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system found BZip2 library if found")
-    set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system found libxml2 library if found")
-    set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system found EXPAT library if found")
-    set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system found PCREPOSIX library if found")
-    set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system found LibGCC library if found")
+    set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system LZMA library if found")
+    set(ENABLE_LZO OFF CACHE INTERNAL "Enable the use of the system LZO library if found")
+    set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system ZLIB library if found")
+    set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system BZip2 library if found")
+    set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system libxml2 library if found")
+    set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system EXPAT library if found")
+    set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system PCREPOSIX library if found")
+    set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system LibGCC library if found")
     set(ENABLE_XATTR OFF CACHE INTERNAL "Enable extended attribute support")
     set(ENABLE_ACL OFF CACHE INTERNAL "Enable ACL support")
     set(ENABLE_ICONV OFF CACHE INTERNAL "Enable iconv support")
@@ -501,18 +536,9 @@ int main(void) { return 0; }
       if(NOT HAVE_CoreServices_OS_X_10_5)
         set(CMAKE_USE_LIBUV 0)
       endif()
-    elseif(CYGWIN)
-      # libuv does not support Cygwin
-      set(CMAKE_USE_LIBUV 0)
     elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
       # Disable until it can be ported.
       set(CMAKE_USE_LIBUV 0)
-    elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "sparc")
-      # Disable until it can be ported.
-      set(CMAKE_USE_LIBUV 0)
-    elseif(CMAKE_SYSTEM STREQUAL "SunOS-5.10")
-      # Disable until it can be ported.
-      set(CMAKE_USE_LIBUV 0)
     endif()
   endif()
   if(CMAKE_USE_LIBUV)
@@ -627,9 +653,6 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
     include(${CMake_SOURCE_DIR}/Tests/CMakeInstall.cmake)
   endif()
 
-  # include special compile flags for some compilers
-  include(CompileFlags.cmake)
-
   # no clue why we are testing for this here
   include(CheckSymbolExists)
   CHECK_SYMBOL_EXISTS(unsetenv "stdlib.h" HAVE_UNSETENV)
@@ -810,6 +833,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
     PATTERN "*.sh*" PERMISSIONS OWNER_READ OWNER_EXECUTE OWNER_WRITE
                                 GROUP_READ GROUP_EXECUTE
                                 WORLD_READ WORLD_EXECUTE
+    REGEX "Help/dev($|/)" EXCLUDE
     )
 
   # Install auxiliary files integrating with other tools.
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 921ba7c..e219763 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -1,6 +1,11 @@
 Contributing to CMake
 *********************
 
+The following summarizes the process for contributing changes.
+See documentation on `CMake Development`_ for more information.
+
+.. _`CMake Development`: Help/dev/README.rst
+
 Community
 =========
 
@@ -19,25 +24,20 @@ CMake uses `Kitware's GitLab Instance`_ to manage development and code review.
 To contribute patches:
 
 #. Fork the upstream `CMake Repository`_ into a personal account.
+#. Run `Utilities/SetupForDevelopment.sh`_ for local configuration.
+#. See the `CMake Source Code Guide`_ for coding guidelines.
 #. Base all new work on the upstream ``master`` branch.
 #. Create commits making incremental, distinct, logically complete changes.
 #. Push a topic branch to a personal repository fork on GitLab.
 #. Create a GitLab Merge Request targeting the upstream ``master`` branch.
 
+The merge request will enter the `CMake Review Process`_ for consideration.
+
 .. _`Kitware's GitLab Instance`: https://gitlab.kitware.com
 .. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake
-
-Code Style
-==========
-
-We use `clang-format`_ to define our style for C++ code in the CMake source
-tree.  See the `.clang-format`_ configuration file for our style settings.
-Use ``clang-format`` version 3.8 or higher to format source files.
-See also the `Utilities/Scripts/clang-format.bash`_ script.
-
-.. _`clang-format`: http://clang.llvm.org/docs/ClangFormat.html
-.. _`.clang-format`: .clang-format
-.. _`Utilities/Scripts/clang-format.bash`: Utilities/Scripts/clang-format.bash
+.. _`Utilities/SetupForDevelopment.sh`: Utilities/SetupForDevelopment.sh
+.. _`CMake Source Code Guide`: Help/dev/source.rst
+.. _`CMake Review Process`: Help/dev/review.rst
 
 License
 =======
diff --git a/CompileFlags.cmake b/CompileFlags.cmake
index c875e6f..7a9d4cd 100644
--- a/CompileFlags.cmake
+++ b/CompileFlags.cmake
@@ -4,10 +4,6 @@
 #-----------------------------------------------------------------------------
 # set some special flags for different compilers
 #
-if(CMAKE_GENERATOR MATCHES "Visual Studio 7")
-  set(CMAKE_SKIP_COMPATIBILITY_TESTS 1)
-endif()
-
 if(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "Intel")
   set(_INTEL_WINDOWS 1)
 endif()
@@ -63,9 +59,17 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^parisc")
   endif()
 endif()
 
-if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro)
+if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND
+    NOT DEFINED CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION)
   if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03")
+    if (NOT CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD EQUAL 98)
+      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++03")
+    elseif(CMAKE_VERSION VERSION_LESS 3.8.20170502)
+      # CMake knows how to add this flag for compilation as C++11,
+      # but has not been taught that SunPro needs it for linking too.
+      # Add it in a place that will be used for both.
+      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+    endif()
   else()
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -library=stlport4")
   endif()
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index bd4d295..8a0fc8d 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -16,8 +16,9 @@ The general signature is:
              [PATH_SUFFIXES suffix1 [suffix2 ...]]
              [DOC "cache documentation string"]
              [NO_DEFAULT_PATH]
-             [NO_CMAKE_ENVIRONMENT_PATH]
+             [NO_PACKAGE_ROOT_PATH]
              [NO_CMAKE_PATH]
+             [NO_CMAKE_ENVIRONMENT_PATH]
              [NO_SYSTEM_ENVIRONMENT_PATH]
              [NO_CMAKE_SYSTEM_PATH]
              [CMAKE_FIND_ROOT_PATH_BOTH |
@@ -60,6 +61,10 @@ If ``NO_DEFAULT_PATH`` is specified, then no additional paths are
 added to the search.
 If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
 
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| replace::
+   |prefix_XXX_SUBDIR| for each ``<prefix>`` in ``PackageName_ROOT`` if called
+   from within a find module
+
 .. |CMAKE_PREFIX_PATH_XXX_SUBDIR| replace::
    |prefix_XXX_SUBDIR| for each ``<prefix>`` in :variable:`CMAKE_PREFIX_PATH`
 
@@ -71,33 +76,47 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
    |prefix_XXX_SUBDIR| for each ``<prefix>`` in
    :variable:`CMAKE_SYSTEM_PREFIX_PATH`
 
-1. Search paths specified in cmake-specific cache variables.
+1. If called from within a find module, search prefix paths unique to the
+   current package being found.  Specifically look in the ``PackageName_ROOT``
+   CMake and environment variables.  The package root variables are maintained
+   as a stack so if called from nested find modules, root paths from the
+   parent's find module will be searchd after paths from the current module,
+   i.e. ``CurrentPackage_ROOT``, ``ENV{CurrentPackage_ROOT}``,
+   ``ParentPackage_ROOT``, ``ENV{ParentPacakge_ROOT}``, etc.
+   This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed.
+
+   * |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX|
+
+2. Search paths specified in cmake-specific cache variables.
    These are intended to be used on the command line with a ``-DVAR=value``.
+   The values are interpreted as :ref:`;-lists <CMake Language Lists>`.
    This can be skipped if ``NO_CMAKE_PATH`` is passed.
 
    * |CMAKE_PREFIX_PATH_XXX|
    * |CMAKE_XXX_PATH|
    * |CMAKE_XXX_MAC_PATH|
 
-2. Search paths specified in cmake-specific environment variables.
-   These are intended to be set in the user's shell configuration.
+3. Search paths specified in cmake-specific environment variables.
+   These are intended to be set in the user's shell configuration,
+   and therefore use the host's native path separator
+   (``;`` on Windows and ``:`` on UNIX).
    This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed.
 
    * |CMAKE_PREFIX_PATH_XXX|
    * |CMAKE_XXX_PATH|
    * |CMAKE_XXX_MAC_PATH|
 
-3. Search the paths specified by the ``HINTS`` option.
+4. Search the paths specified by the ``HINTS`` option.
    These should be paths computed by system introspection, such as a
    hint provided by the location of another item already found.
    Hard-coded guesses should be specified with the ``PATHS`` option.
 
-4. Search the standard system environment variables.
+5. Search the standard system environment variables.
    This can be skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is an argument.
 
    * |SYSTEM_ENVIRONMENT_PATH_XXX|
 
-5. Search cmake variables defined in the Platform files
+6. Search cmake variables defined in the Platform files
    for the current system.  This can be skipped if ``NO_CMAKE_SYSTEM_PATH``
    is passed.
 
@@ -105,7 +124,7 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
    * |CMAKE_SYSTEM_XXX_PATH|
    * |CMAKE_SYSTEM_XXX_MAC_PATH|
 
-6. Search the paths specified by the PATHS option
+7. Search the paths specified by the PATHS option
    or in the short-hand version of the command.
    These are typically hard-coded guesses.
 
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst
index 80e7edf..d038406 100644
--- a/Help/command/add_custom_command.rst
+++ b/Help/command/add_custom_command.rst
@@ -215,7 +215,7 @@ of the following is specified:
 
 ``PRE_BUILD``
   Run before any other rules are executed within the target.
-  This is supported only on Visual Studio 7 or later.
+  This is supported only on Visual Studio 8 or later.
   For all other generators ``PRE_BUILD`` will be treated as
   ``PRE_LINK``.
 ``PRE_LINK``
diff --git a/Help/command/add_executable.rst b/Help/command/add_executable.rst
index 19ca658..c088796 100644
--- a/Help/command/add_executable.rst
+++ b/Help/command/add_executable.rst
@@ -40,6 +40,9 @@ the syntax ``$<...>``.  See the :manual:`cmake-generator-expressions(7)`
 manual for available expressions.  See the :manual:`cmake-buildsystem(7)`
 manual for more on defining buildsystem properties.
 
+See also :prop_sf:`HEADER_FILE_ONLY` on what to do if some sources are
+pre-processed, and you want to have the original sources reachable from
+within IDE.
 
 --------------------------------------------------------------------------
 
diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst
index af75a39..de5335e 100644
--- a/Help/command/add_library.rst
+++ b/Help/command/add_library.rst
@@ -59,12 +59,16 @@ the syntax ``$<...>``.  See the :manual:`cmake-generator-expressions(7)`
 manual for available expressions.  See the :manual:`cmake-buildsystem(7)`
 manual for more on defining buildsystem properties.
 
+See also :prop_sf:`HEADER_FILE_ONLY` on what to do if some sources are
+pre-processed, and you want to have the original sources reachable from
+within IDE.
+
 Imported Libraries
 ^^^^^^^^^^^^^^^^^^
 
 ::
 
-  add_library(<name> <SHARED|STATIC|MODULE|UNKNOWN> IMPORTED
+  add_library(<name> <SHARED|STATIC|MODULE|OBJECT|UNKNOWN> IMPORTED
               [GLOBAL])
 
 An :ref:`IMPORTED library target <Imported Targets>` references a library
@@ -106,10 +110,9 @@ may contain only sources that compile, header files, and other files
 that would not affect linking of a normal library (e.g. ``.txt``).
 They may contain custom commands generating such sources, but not
 ``PRE_BUILD``, ``PRE_LINK``, or ``POST_BUILD`` commands.  Object libraries
-cannot be imported, exported, installed, or linked.  Some native build
-systems may not like targets that have only object files, so consider
-adding at least one real source file to any target that references
-``$<TARGET_OBJECTS:objlib>``.
+cannot be linked.  Some native build systems may not like targets that
+have only object files, so consider adding at least one real source file
+to any target that references ``$<TARGET_OBJECTS:objlib>``.
 
 Alias Libraries
 ^^^^^^^^^^^^^^^
@@ -120,7 +123,7 @@ Alias Libraries
 
 Creates an :ref:`Alias Target <Alias Targets>`, such that ``<name>`` can be
 used to refer to ``<target>`` in subsequent commands.  The ``<name>`` does
-not appear in the generatedbuildsystem as a make target.  The ``<target>``
+not appear in the generated buildsystem as a make target.  The ``<target>``
 may not be an :ref:`Imported Target <Imported Targets>` or an ``ALIAS``.
 ``ALIAS`` targets can be used as linkable targets and as targets to
 read properties from.  They can also be tested for existence with the
diff --git a/Help/command/ctest_memcheck.rst b/Help/command/ctest_memcheck.rst
index a983d68..288b65a 100644
--- a/Help/command/ctest_memcheck.rst
+++ b/Help/command/ctest_memcheck.rst
@@ -13,6 +13,9 @@ Perform the :ref:`CTest MemCheck Step` as a :ref:`Dashboard Client`.
                  [INCLUDE <include-regex>]
                  [EXCLUDE_LABEL <label-exclude-regex>]
                  [INCLUDE_LABEL <label-include-regex>]
+                 [EXCLUDE_FIXTURE <regex>]
+                 [EXCLUDE_FIXTURE_SETUP <regex>]
+                 [EXCLUDE_FIXTURE_CLEANUP <regex>]
                  [PARALLEL_LEVEL <level>]
                  [TEST_LOAD <threshold>]
                  [SCHEDULE_RANDOM <ON|OFF>]
diff --git a/Help/command/ctest_submit.rst b/Help/command/ctest_submit.rst
index a7d9708..6b49da3 100644
--- a/Help/command/ctest_submit.rst
+++ b/Help/command/ctest_submit.rst
@@ -6,6 +6,7 @@ Perform the :ref:`CTest Submit Step` as a :ref:`Dashboard Client`.
 ::
 
   ctest_submit([PARTS <part>...] [FILES <file>...]
+               [HTTPHEADER <header>]
                [RETRY_COUNT <count>]
                [RETRY_DELAY <delay>]
                [RETURN_VALUE <result-var>]
@@ -36,6 +37,10 @@ The options are:
   Specify an explicit list of specific files to be submitted.
   Each individual file must exist at the time of the call.
 
+``HTTPHEADER <HTTP-header>``
+  Specify HTTP header to be included in the request to CDash during submission.
+  This suboption can be repeated several times.
+
 ``RETRY_COUNT <count>``
   Specify how many times to retry a timed-out submission.
 
@@ -57,6 +62,7 @@ Submit to CDash Upload API
 ::
 
   ctest_submit(CDASH_UPLOAD <file> [CDASH_UPLOAD_TYPE <type>]
+               [HTTPHEADER <header>]
                [RETRY_COUNT <count>]
                [RETRY_DELAY <delay>]
                [QUIET])
@@ -67,5 +73,5 @@ with a content hash of the file. If CDash does not already have the file,
 then it is uploaded. Along with the file, a CDash type string is specified
 to tell CDash which handler to use to process the data.
 
-This signature accepts the ``RETRY_COUNT``, ``RETRY_DELAY``, and ``QUIET``
-options as described above.
+This signature accepts the ``HTTPHEADER``, ``RETRY_COUNT``, ``RETRY_DELAY``, and
+``QUIET`` options as described above.
diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst
index ce50d42..4a69491 100644
--- a/Help/command/ctest_test.rst
+++ b/Help/command/ctest_test.rst
@@ -13,6 +13,9 @@ Perform the :ref:`CTest Test Step` as a :ref:`Dashboard Client`.
              [INCLUDE <include-regex>]
              [EXCLUDE_LABEL <label-exclude-regex>]
              [INCLUDE_LABEL <label-include-regex>]
+             [EXCLUDE_FIXTURE <regex>]
+             [EXCLUDE_FIXTURE_SETUP <regex>]
+             [EXCLUDE_FIXTURE_CLEANUP <regex>]
              [PARALLEL_LEVEL <level>]
              [TEST_LOAD <threshold>]
              [SCHEDULE_RANDOM <ON|OFF>]
@@ -61,6 +64,20 @@ The options are:
   Specify a regular expression matching test labels to include.
   Tests not matching this expression are excluded.
 
+``EXCLUDE_FIXTURE <regex>``
+  If a test in the set of tests to be executed requires a particular fixture,
+  that fixture's setup and cleanup tests would normally be added to the test
+  set automatically. This option prevents adding setup or cleanup tests for
+  fixtures matching the ``<regex>``. Note that all other fixture behavior is
+  retained, including test dependencies and skipping tests that have fixture
+  setup tests that fail.
+
+``EXCLUDE_FIXTURE_SETUP <regex>``
+  Same as ``EXCLUDE_FIXTURE`` except only matching setup tests are excluded.
+
+``EXCLUDE_FIXTURE_CLEANUP <regex>``
+  Same as ``EXCLUDE_FIXTURE`` except only matching cleanup tests are excluded.
+
 ``PARALLEL_LEVEL <level>``
   Specify a positive number representing the number of tests to
   be run in parallel.
diff --git a/Help/command/find_file.rst b/Help/command/find_file.rst
index e56097b..2a14ad7 100644
--- a/Help/command/find_file.rst
+++ b/Help/command/find_file.rst
@@ -8,6 +8,9 @@ find_file
 .. |prefix_XXX_SUBDIR| replace:: ``<prefix>/include``
 .. |entry_XXX_SUBDIR| replace:: ``<entry>/include``
 
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+   ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
+   is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
 .. |CMAKE_PREFIX_PATH_XXX| replace::
    ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
    is set, and |CMAKE_PREFIX_PATH_XXX_SUBDIR|
diff --git a/Help/command/find_library.rst b/Help/command/find_library.rst
index 1eb50f7..0861d67 100644
--- a/Help/command/find_library.rst
+++ b/Help/command/find_library.rst
@@ -8,6 +8,9 @@ find_library
 .. |prefix_XXX_SUBDIR| replace:: ``<prefix>/lib``
 .. |entry_XXX_SUBDIR| replace:: ``<entry>/lib``
 
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+   ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set,
+   and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
 .. |CMAKE_PREFIX_PATH_XXX| replace::
    ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set,
    and |CMAKE_PREFIX_PATH_XXX_SUBDIR|
@@ -49,6 +52,14 @@ path to the framework ``<fullPath>/A.framework``.  When a full path to a
 framework is used as a library, CMake will use a ``-framework A``, and a
 ``-F<fullPath>`` to link the framework to the target.
 
+If the :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable is set all
+search paths will be tested as normal, with the suffix appended, and with
+all matches of ``lib/`` replaced with
+``lib${CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX}/``.  This variable overrides
+the :prop_gbl:`FIND_LIBRARY_USE_LIB32_PATHS`,
+:prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS`,
+and :prop_gbl:`FIND_LIBRARY_USE_LIB64_PATHS` global properties.
+
 If the :prop_gbl:`FIND_LIBRARY_USE_LIB32_PATHS` global property is set
 all search paths will be tested as normal, with ``32/`` appended, and
 with all matches of ``lib/`` replaced with ``lib32/``.  This property is
@@ -56,6 +67,13 @@ automatically set for the platforms that are known to need it if at
 least one of the languages supported by the :command:`project` command
 is enabled.
 
+If the :prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS` global property is set
+all search paths will be tested as normal, with ``x32/`` appended, and
+with all matches of ``lib/`` replaced with ``libx32/``.  This property is
+automatically set for the platforms that are known to need it if at
+least one of the languages supported by the :command:`project` command
+is enabled.
+
 If the :prop_gbl:`FIND_LIBRARY_USE_LIB64_PATHS` global property is set
 all search paths will be tested as normal, with ``64/`` appended, and
 with all matches of ``lib/`` replaced with ``lib64/``.  This property is
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst
index 2cb1e5f..08c6ccd 100644
--- a/Help/command/find_package.rst
+++ b/Help/command/find_package.rst
@@ -64,8 +64,9 @@ The complete Config mode command signature is::
                [PATHS path1 [path2 ... ]]
                [PATH_SUFFIXES suffix1 [suffix2 ...]]
                [NO_DEFAULT_PATH]
-               [NO_CMAKE_ENVIRONMENT_PATH]
+               [NO_PACAKGE_ROOT_PATH]
                [NO_CMAKE_PATH]
+               [NO_CMAKE_ENVIRONMENT_PATH]
                [NO_SYSTEM_ENVIRONMENT_PATH]
                [NO_CMAKE_PACKAGE_REGISTRY]
                [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
@@ -249,16 +250,25 @@ The set of installation prefixes is constructed using the following
 steps.  If ``NO_DEFAULT_PATH`` is specified all ``NO_*`` options are
 enabled.
 
-1. Search paths specified in cmake-specific cache variables.  These
+1. Search paths specified in the ``PackageName_ROOT`` CMake and environment
+   variables.  The package root variables are maintained as a stack so if
+   called from within a find module, root paths from the parent's find
+   module will also be searched after paths for the current package.  This can
+   be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed.
+
+2. Search paths specified in cmake-specific cache variables.  These
    are intended to be used on the command line with a ``-DVAR=value``.
+   The values are interpreted as :ref:`;-lists <CMake Language Lists>`.
    This can be skipped if ``NO_CMAKE_PATH`` is passed::
 
      CMAKE_PREFIX_PATH
      CMAKE_FRAMEWORK_PATH
      CMAKE_APPBUNDLE_PATH
 
-2. Search paths specified in cmake-specific environment variables.
-   These are intended to be set in the user's shell configuration.
+3. Search paths specified in cmake-specific environment variables.
+   These are intended to be set in the user's shell configuration,
+   and therefore use the host's native path separator
+   (``;`` on Windows and ``:`` on UNIX).
    This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed::
 
      <package>_DIR
@@ -266,26 +276,26 @@ enabled.
      CMAKE_FRAMEWORK_PATH
      CMAKE_APPBUNDLE_PATH
 
-3. Search paths specified by the ``HINTS`` option.  These should be paths
+4. Search paths specified by the ``HINTS`` option.  These should be paths
    computed by system introspection, such as a hint provided by the
    location of another item already found.  Hard-coded guesses should
    be specified with the ``PATHS`` option.
 
-4. Search the standard system environment variables.  This can be
+5. Search the standard system environment variables.  This can be
    skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed.  Path entries
    ending in ``/bin`` or ``/sbin`` are automatically converted to their
    parent directories::
 
      PATH
 
-5. Search paths stored in the CMake :ref:`User Package Registry`.
+6. Search paths stored in the CMake :ref:`User Package Registry`.
    This can be skipped if ``NO_CMAKE_PACKAGE_REGISTRY`` is passed or by
    setting the :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`
    to ``TRUE``.
    See the :manual:`cmake-packages(7)` manual for details on the user
    package registry.
 
-6. Search cmake variables defined in the Platform files for the
+7. Search cmake variables defined in the Platform files for the
    current system.  This can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is
    passed::
 
@@ -293,14 +303,14 @@ enabled.
      CMAKE_SYSTEM_FRAMEWORK_PATH
      CMAKE_SYSTEM_APPBUNDLE_PATH
 
-7. Search paths stored in the CMake :ref:`System Package Registry`.
+8. Search paths stored in the CMake :ref:`System Package Registry`.
    This can be skipped if ``NO_CMAKE_SYSTEM_PACKAGE_REGISTRY`` is passed
    or by setting the
    :variable:`CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY` to ``TRUE``.
    See the :manual:`cmake-packages(7)` manual for details on the system
    package registry.
 
-8. Search paths specified by the ``PATHS`` option.  These are typically
+9. Search paths specified by the ``PATHS`` option.  These are typically
    hard-coded guesses.
 
 .. |FIND_XXX| replace:: find_package
diff --git a/Help/command/find_path.rst b/Help/command/find_path.rst
index 76342d0..988a3fa 100644
--- a/Help/command/find_path.rst
+++ b/Help/command/find_path.rst
@@ -8,6 +8,9 @@ find_path
 .. |prefix_XXX_SUBDIR| replace:: ``<prefix>/include``
 .. |entry_XXX_SUBDIR| replace:: ``<entry>/include``
 
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+   ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
+   is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
 .. |CMAKE_PREFIX_PATH_XXX| replace::
    ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
    is set, and |CMAKE_PREFIX_PATH_XXX_SUBDIR|
diff --git a/Help/command/find_program.rst b/Help/command/find_program.rst
index d3430c0..4f00773 100644
--- a/Help/command/find_program.rst
+++ b/Help/command/find_program.rst
@@ -8,6 +8,8 @@ find_program
 .. |prefix_XXX_SUBDIR| replace:: ``<prefix>/[s]bin``
 .. |entry_XXX_SUBDIR| replace:: ``<entry>/[s]bin``
 
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+   |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
 .. |CMAKE_PREFIX_PATH_XXX| replace::
    |CMAKE_PREFIX_PATH_XXX_SUBDIR|
 .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_PROGRAM_PATH`
diff --git a/Help/command/if.rst b/Help/command/if.rst
index 2a087d0..edd343d 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -103,7 +103,8 @@ Possible expressions are:
 
 ``if(<variable|string> MATCHES regex)``
  True if the given string or variable's value matches the given regular
- expression.
+ expression.  See :ref:`Regex Specification` for regex format.
+ ``()`` groups are captured in :variable:`CMAKE_MATCH_<n>` variables.
 
 ``if(<variable|string> LESS <variable|string>)``
  True if the given string or variable's value is a valid number and less
diff --git a/Help/command/include_external_msproject.rst b/Help/command/include_external_msproject.rst
index 18a2b50..335282a 100644
--- a/Help/command/include_external_msproject.rst
+++ b/Help/command/include_external_msproject.rst
@@ -20,3 +20,7 @@ command to make things depend on the external project.
 specify the type of project, id (GUID) of the project and the name of
 the target platform.  This is useful for projects requiring values
 other than the default (e.g.  WIX projects).
+
+If the imported project has different configuration names than the
+current project, set the :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>`
+target property to specify the mapping.
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 70087a4..58438b7 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -73,7 +73,7 @@ Installing Targets
 ::
 
   install(TARGETS targets... [EXPORT <export-name>]
-          [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|
+          [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
             PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
            [DESTINATION <dir>]
            [PERMISSIONS permissions...]
@@ -86,10 +86,10 @@ Installing Targets
           )
 
 The ``TARGETS`` form specifies rules for installing targets from a
-project.  There are five kinds of target files that may be installed:
-``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``FRAMEWORK``, and ``BUNDLE``.
-Executables are treated as ``RUNTIME`` targets, except that those
-marked with the ``MACOSX_BUNDLE`` property are treated as ``BUNDLE``
+project.  There are six kinds of target files that may be installed:
+``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``OBJECTS``, ``FRAMEWORK``, and
+``BUNDLE``. Executables are treated as ``RUNTIME`` targets, except that
+those marked with the ``MACOSX_BUNDLE`` property are treated as ``BUNDLE``
 targets on OS X.  Static libraries are treated as ``ARCHIVE`` targets,
 except that those marked with the ``FRAMEWORK`` property are treated
 as ``FRAMEWORK`` targets on OS X.
@@ -99,10 +99,11 @@ targets, except that those marked with the ``FRAMEWORK`` property are
 treated as ``FRAMEWORK`` targets on OS X.  For DLL platforms the DLL
 part of a shared library is treated as a ``RUNTIME`` target and the
 corresponding import library is treated as an ``ARCHIVE`` target.
-All Windows-based systems including Cygwin are DLL platforms.
-The ``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, and ``FRAMEWORK`` arguments
-change the type of target to which the subsequent properties apply.
-If none is given the installation properties apply to all target
+All Windows-based systems including Cygwin are DLL platforms. Object
+libraries are always treated as ``OBJECTS`` targets.
+The ``ARCHIVE``, ``LIBRARY``, ``RUNTIME``, ``OBJECTS``, and ``FRAMEWORK``
+arguments change the type of target to which the subsequent properties
+apply. If none is given the installation properties apply to all target
 types.  If only one is given then only targets of that type will be
 installed (which can be used to install just a DLL or just an import
 library).
@@ -165,8 +166,8 @@ the ``mySharedLib`` DLL will be installed to ``<prefix>/bin`` and
 
 The ``EXPORT`` option associates the installed target files with an
 export called ``<export-name>``.  It must appear before any ``RUNTIME``,
-``LIBRARY``, or ``ARCHIVE`` options.  To actually install the export
-file itself, call ``install(EXPORT)``, documented below.
+``LIBRARY``, ``ARCHIVE``, or ``OBJECTS`` options.  To actually install the
+export file itself, call ``install(EXPORT)``, documented below.
 
 Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property
 set to ``TRUE`` has undefined behavior.
diff --git a/Help/command/project.rst b/Help/command/project.rst
index 6c5ace7..139f69c 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -8,6 +8,7 @@ Set a name, version, and enable languages for the entire project.
  project(<PROJECT-NAME> [LANGUAGES] [<language-name>...])
  project(<PROJECT-NAME>
          [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
+         [DESCRIPTION <project-description-string>]
          [LANGUAGES <language-name>...])
 
 Sets the name of the project and stores the name in the
@@ -40,6 +41,10 @@ in variables
 Variables corresponding to unspecified versions are set to the empty string
 (if policy :policy:`CMP0048` is set to ``NEW``).
 
+If optional ``DESCRIPTION`` is given, then additional :variable:`PROJECT_DESCRIPTION`
+variable will be set to its argument. The argument must be a string with short
+description of the project (only a few words).
+
 Optionally you can specify which languages your project supports.
 Example languages are ``C``, ``CXX`` (i.e.  C++), ``Fortran``, etc.
 By default ``C`` and ``CXX`` are enabled if no language options are
diff --git a/Help/command/separate_arguments.rst b/Help/command/separate_arguments.rst
index 1fd3cd1..47982a5 100644
--- a/Help/command/separate_arguments.rst
+++ b/Help/command/separate_arguments.rst
@@ -5,9 +5,9 @@ Parse space-separated arguments into a semicolon-separated list.
 
 ::
 
-  separate_arguments(<var> <UNIX|WINDOWS>_COMMAND "<args>")
+  separate_arguments(<var> <NATIVE|UNIX|WINDOWS>_COMMAND "<args>")
 
-Parses a unix- or windows-style command-line string "<args>" and
+Parses a UNIX- or Windows-style command-line string "<args>" and
 stores a semicolon-separated list of the arguments in ``<var>``.  The
 entire command line must be given in one "<args>" argument.
 
@@ -16,12 +16,15 @@ recognizes both single-quote and double-quote pairs.  A backslash
 escapes the next literal character (``\"`` is ``"``); there are no special
 escapes (``\n`` is just ``n``).
 
-The ``WINDOWS_COMMAND`` mode parses a windows command-line using the same
+The ``WINDOWS_COMMAND`` mode parses a Windows command-line using the same
 syntax the runtime library uses to construct argv at startup.  It
 separates arguments by whitespace that is not double-quoted.
 Backslashes are literal unless they precede double-quotes.  See the
 MSDN article `Parsing C Command-Line Arguments`_ for details.
 
+The ``NATIVE_COMMAND`` mode parses a Windows command-line if the host
+system is Windows, and a UNIX command-line otherwise.
+
 .. _`Parsing C Command-Line Arguments`: https://msdn.microsoft.com/library/a1y7w461.aspx
 
 ::
diff --git a/Help/command/string.rst b/Help/command/string.rst
index 698a91d..4f0c45c 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -77,31 +77,43 @@ The replace expression may refer to paren-delimited subexpressions of the
 match using ``\1``, ``\2``, ..., ``\9``.  Note that two backslashes (``\\1``)
 are required in CMake code to get a backslash through argument parsing.
 
+.. _`Regex Specification`:
+
 Regex Specification
 """""""""""""""""""
 
 The following characters have special meaning in regular expressions:
 
-::
-
-   ^         Matches at beginning of input
-   $         Matches at end of input
-   .         Matches any single character
-   [ ]       Matches any character(s) inside the brackets
-   [^ ]      Matches any character(s) not inside the brackets
-    -        Inside brackets, specifies an inclusive range between
-             characters on either side e.g. [a-f] is [abcdef]
-             To match a literal - using brackets, make it the first
-             or the last character e.g. [+*/-] matches basic
-             mathematical operators.
-   *         Matches preceding pattern zero or more times
-   +         Matches preceding pattern one or more times
-   ?         Matches preceding pattern zero or once only
-   |         Matches a pattern on either side of the |
-   ()        Saves a matched subexpression, which can be referenced
-             in the REGEX REPLACE operation. Additionally it is saved
-             by all regular expression-related commands, including
-             e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).
+``^``
+  Matches at beginning of input
+``$``
+  Matches at end of input
+``.``
+  Matches any single character
+``[ ]``
+  Matches any character(s) inside the brackets
+``[^ ]``
+  Matches any character(s) not inside the brackets
+``-``
+  Inside brackets, specifies an inclusive range between
+  characters on either side e.g. ``[a-f]`` is ``[abcdef]``
+  To match a literal ``-`` using brackets, make it the first
+  or the last character e.g. ``[+*/-]`` matches basic
+  mathematical operators.
+``*``
+  Matches preceding pattern zero or more times
+``+``
+  Matches preceding pattern one or more times
+``?``
+  Matches preceding pattern zero or once only
+``|``
+  Matches a pattern on either side of the ``|``
+``()``
+  Saves a matched subexpression, which can be referenced
+  in the ``REGEX REPLACE`` operation. Additionally it is saved
+  by all regular expression-related commands, including
+  e.g. :command:`if(MATCHES)`, in the variables
+  :variable:`CMAKE_MATCH_<n>` for ``<n>`` 0..9.
 
 ``*``, ``+`` and ``?`` have higher precedence than concatenation.  ``|``
 has lower precedence than concatenation.  This means that the regular
diff --git a/Help/dev/README.rst b/Help/dev/README.rst
new file mode 100644
index 0000000..ce62abc
--- /dev/null
+++ b/Help/dev/README.rst
@@ -0,0 +1,49 @@
+CMake Development
+*****************
+
+This directory contains documentation about development of CMake itself.
+It is not part of the user documentation distributed with CMake.
+
+Contributor Instructions
+========================
+
+See `CONTRIBUTING.rst`_ for instructions to contribute changes.
+
+The process for contributing changes is the same whether or not one
+has been invited to participate directly in upstream development.
+
+.. _`CONTRIBUTING.rst`: ../../CONTRIBUTING.rst
+
+Upstream Development
+====================
+
+CMake uses `Kitware's GitLab Instance`_ to manage development, review, and
+integration of changes.  The `CMake Repository`_ holds the integration
+branches and tags.  Upstream development processes are covered by the
+following documents:
+
+* The `CMake Review Process`_ manages integration of changes.
+* The `CMake Testing Process`_ drives integration testing.
+
+.. _`Kitware's GitLab Instance`: https://gitlab.kitware.com
+.. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake
+.. _`CMake Review Process`: review.rst
+.. _`CMake Testing Process`: testing.rst
+
+Developer Documentation
+=======================
+
+CMake developer documentation is provided by the following documents:
+
+* The `CMake Source Code Guide`_.
+
+.. _`CMake Source Code Guide`: source.rst
+
+Maintainer Documentation
+========================
+
+CMake maintainer documentation is provided by the following documents:
+
+* The `CMake Maintainer Guide`_.
+
+.. _`CMake Maintainer Guide`: maint.rst
diff --git a/Help/dev/maint.rst b/Help/dev/maint.rst
new file mode 100644
index 0000000..78c06df
--- /dev/null
+++ b/Help/dev/maint.rst
@@ -0,0 +1,171 @@
+CMake Maintainer Guide
+**********************
+
+The following is a guide to CMake maintenance processes.
+See documentation on `CMake Development`_ for more information.
+
+.. _`CMake Development`: README.rst
+
+.. contents:: Maintainer Processes:
+
+Branch a New Release
+====================
+
+This section covers how to start a new ``release`` branch for a major or
+minor version bump (patch releases remain on their existing branch).
+
+In the following we use the placeholder ``$ver`` to represent the
+version number of the new release with the form ``$major.$minor``,
+and ``$prev`` to represent the version number of the prior release.
+
+Review Prior Release
+--------------------
+
+Review the history around the prior release branch:
+
+.. code-block:: shell
+
+  git log --graph --boundary \
+   ^$(git rev-list --grep="Merge topic 'doc-.*-relnotes'" -n 1 master)~1 \
+   $(git rev-list --grep="Begin post-.* development" -n 1 master) \
+   $(git tag --list *-rc1| tail -1)
+
+Consolidate Release Notes
+-------------------------
+
+Starting from a clean work tree on ``master``, create a topic branch to
+use for consolidating the release notes:
+
+.. code-block:: shell
+
+  git checkout -b doc-$ver-relnotes
+
+Run the `consolidate-relnotes.bash`_ script:
+
+.. code-block:: shell
+
+  Utilities/Release/consolidate-relnotes.bash $ver $prev
+
+.. _`consolidate-relnotes.bash`: ../../Utilities/Release/consolidate-relnotes.bash
+
+This moves notes from the ``Help/release/dev/*.rst`` files into a versioned
+``Help/release/$ver.rst`` file and updates ``Help/release/index.rst`` to
+link to the new document.  Commit the changes with a message such as::
+
+  Help: Consolidate $ver release notes
+
+  Run the `Utilities/Release/consolidate-relnotes.bash` script to move
+  notes from `Help/release/dev/*` into `Help/release/$ver.rst`.
+
+Manually edit ``Help/release/$ver.rst`` to add section headers, organize
+the notes, and revise wording.  Then commit with a message such as::
+
+  Help: Organize and revise $ver release notes
+
+  Add section headers similar to the $prev release notes and move each
+  individual bullet into an appropriate section.  Revise a few bullets.
+
+Open a merge request with the ``doc-$ver-relnotes`` branch for review
+and integration.  Further steps may proceed after this has been merged
+to ``master``.
+
+Update 'release' Branch
+-----------------------
+
+Starting from a clean work tree on ``master``, create a new ``release-$ver``
+branch locally:
+
+.. code-block:: shell
+
+  git checkout -b release-$ver origin/master
+
+Remove the development branch release note infrastructure:
+
+.. code-block:: shell
+
+  git rm Help/release/dev/0-sample-topic.rst
+  sed -i '/^\.\. include:: dev.txt/ {N;d}' Help/release/index.rst
+
+Commit with a message such as::
+
+  Help: Drop development topic notes to prepare release
+
+  Release versions do not have the development topic section of
+  the CMake Release Notes index page.
+
+Update ``Source/CMakeVersion.cmake`` to set the version to
+``$major.$minor.0-rc1``:
+
+.. code-block:: cmake
+
+  # CMake version number components.
+  set(CMake_VERSION_MAJOR $major)
+  set(CMake_VERSION_MINOR $minor)
+  set(CMake_VERSION_PATCH 0)
+  set(CMake_VERSION_RC 1)
+
+Update ``Utilities/Release/upload_release.cmake``:
+
+.. code-block:: cmake
+
+  set(VERSION $ver)
+
+Update uses of ``DEVEL_CMAKE_VERSION`` in the source tree to mention the
+actual version number:
+
+.. code-block:: shell
+
+  $EDITOR $(git grep -l DEVEL_CMAKE_VERSION)
+
+Commit with a message such as::
+
+  CMake $major.$minor.0-rc1 version update
+
+Merge the ``release-$ver`` branch to ``master``:
+
+.. code-block:: shell
+
+  git checkout master
+  git pull
+  git merge --no-ff release-$ver
+
+Begin post-release development by restoring the development branch release
+note infrastructure and the version date from ``origin/master``:
+
+.. code-block:: shell
+
+  git checkout origin/master -- \
+    Source/CMakeVersion.cmake Help/release/dev/0-sample-topic.rst
+  sed -i $'/^Releases/ i\\\n.. include:: dev.txt\\\n' Help/release/index.rst
+
+Update ``Source/CMakeVersion.cmake`` to set the version to
+``$major.$minor.$date``:
+
+.. code-block:: cmake
+
+  # CMake version number components.
+  set(CMake_VERSION_MAJOR $major)
+  set(CMake_VERSION_MINOR $minor)
+  set(CMake_VERSION_PATCH $date)
+  #set(CMake_VERSION_RC 1)
+
+Commit with a message such as::
+
+  Begin post-$ver development
+
+Push the update to the ``master`` and ``release`` branches:
+
+.. code-block:: shell
+
+  git push --atomic origin master release-$ver:release
+
+Announce 'release' Branch
+-------------------------
+
+Send email to the ``cmake-developers at cmake.org`` mailing list (perhaps
+in reply to a release preparation thread) announcing that post-release
+development is open::
+
+  I've branched 'release' for $ver.  The repository is now open for
+  post-$ver development.  Please rebase open merge requests on 'master'
+  before staging or merging.
diff --git a/Help/dev/review.rst b/Help/dev/review.rst
new file mode 100644
index 0000000..9450bf0
--- /dev/null
+++ b/Help/dev/review.rst
@@ -0,0 +1,350 @@
+CMake Review Process
+********************
+
+The following documents the process for reviewing and integrating changes.
+See `CONTRIBUTING.rst`_ for instructions to contribute changes.
+See documentation on `CMake Development`_ for more information.
+
+.. _`CONTRIBUTING.rst`: ../../CONTRIBUTING.rst
+.. _`CMake Development`: README.rst
+
+.. contents:: The review process consists of the following steps:
+
+Merge Request
+=============
+
+A user initiates the review process for a change by pushing a *topic
+branch* to his or her own fork of the `CMake Repository`_ on GitLab and
+creating a *merge request* ("MR").  The new MR will appear on the
+`CMake Merge Requests Page`_.  The rest of the review and integration
+process is managed by the merge request page for the change.
+
+During the review process, the MR submitter should address review comments
+or test failures by updating the MR with a (force-)push of the topic
+branch.  The update initiates a new round of review.
+
+We recommend that users enable the "Remove source branch when merge
+request is accepted" option when creating the MR or by editing it.
+This will cause the MR topic branch to be automatically removed from
+the user's fork during the `Merge`_ step.
+
+.. _`CMake Merge Requests Page`: https://gitlab.kitware.com/cmake/cmake/merge_requests
+.. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake
+
+Workflow Status
+---------------
+
+`CMake GitLab Project Developers`_ may set one of the following labels
+in GitLab to track the state of a MR:
+
+* ``workflow:wip`` indicates that the MR needs additional updates from
+  the MR submitter before further review.  Use this label after making
+  comments that require such updates.
+
+* ``workflow:in-review`` indicates that the MR awaits feedback from a
+  human reviewer or from `Topic Testing`_.  Use this label after making
+  comments requesting such feedback.
+
+* ``workflow:nightly-testing`` indicates that the MR awaits results
+  of `Integration Testing`_.  Use this label after making comments
+  requesting such staging.
+
+* ``workflow:expired`` indicates that the MR has been closed due
+  to a period of inactivity.  See the `Expire`_ step.  Use this label
+  after closing a MR for this reason.
+
+The workflow status labels are intended to be mutually exclusive,
+so please remove any existing workflow label when adding one.
+
+.. _`CMake GitLab Project Developers`: https://gitlab.kitware.com/cmake/cmake/settings/members
+
+Robot Review
+============
+
+The "Kitware Robot" (``@kwrobot``) automatically performs basic checks on
+the commits proposed in a MR.  If all is well the robot silently reports
+a successful "build" status to GitLab.  Otherwise the robot posts a comment
+with its diagnostics.  **A topic may not be merged until the automatic
+review succeeds.**
+
+Note that the MR submitter is expected to address the robot's comments by
+*rewriting* the commits named by the robot's diagnostics (e.g., via
+``git rebase -i``). This is because the robot checks each commit individually,
+not the topic as a whole. This is done in order to ensure that commits in the
+middle of a topic do not, for example, add a giant file which is then later
+removed in the topic.
+
+Automatic Check
+---------------
+
+The automatic check is repeated whenever the topic branch is updated.
+One may explicitly request a re-check by adding a comment with the
+following command among the `comment trailing lines`_::
+
+  Do: check
+
+``@kwrobot`` will add an award emoji to the comment to indicate that it
+was processed and also run its checks again.
+
+Automatic Format
+----------------
+
+The automatic check will reject commits introducing source code not
+formatted according to ``clang-format``.  One may ask the robot to
+automatically rewrite the MR topic branch with expected formatting
+by adding a comment with the following command among the
+`comment trailing lines`_::
+
+  Do: reformat
+
+``@kwrobot`` will add an award emoji to the comment to indicate that it
+was processed and also rewrite the MR topic branch and force-push an
+updated version with every commit formatted as expected by the check.
+
+Human Review
+============
+
+Anyone is welcome to review merge requests and make comments!
+
+Please make comments directly on the MR page Discussion and Changes tabs
+and not on individual commits.  Comments on a commit may disappear
+from the MR page if the commit is rewritten in response.
+
+Reviewers may add comments providing feedback or to acknowledge their
+approval.  Lines of specific forms will be extracted during the `merge`_
+step and included as trailing lines of the generated merge commit message.
+Each review comment consists of up to two parts which must be specified
+in the following order: `comment body`_, then `comment trailing lines`_.
+Each part is optional, but they must be specified in this order.
+
+Comment Body
+------------
+
+The body of a comment may be free-form `GitLab Flavored Markdown`_.
+See GitLab documentation on `Special GitLab References`_ to add links to
+things like issues, commits, or other merge requests (even across projects).
+
+Additionally, a line in the comment body may start with one of the
+following votes:
+
+* ``-1`` or ``:-1:`` indicates "the change is not ready for integration".
+
+* ``+1`` or ``:+1:`` indicates "I like the change".
+  This adds an ``Acked-by:`` trailer to the `merge`_ commit message.
+
+* ``+2`` indicates "the change is ready for integration".
+  This adds a ``Reviewed-by:`` trailer to the `merge`_ commit message.
+
+* ``+3`` indicates "I have tested the change and verified it works".
+  This adds a ``Tested-by:`` trailer to the `merge`_ commit message.
+
+.. _`GitLab Flavored Markdown`: https://gitlab.kitware.com/help/user/markdown.md
+.. _`Special GitLab References`: https://gitlab.kitware.com/help/user/markdown.md#special-gitlab-references
+
+Comment Trailing Lines
+----------------------
+
+Zero or more *trailing* lines in the last section of a comment may appear
+with the form ``Key: Value``.  The first such line should be separated
+from a preceding `comment body`_ by a blank line.  Any key-value pair(s)
+may be specified for human reference.  A few specific keys have meaning to
+``@kwrobot`` as follows.
+
+Comment Trailer Votes
+^^^^^^^^^^^^^^^^^^^^^
+
+Among the `comment trailing lines`_ one may cast a vote using one of the
+following pairs followed by nothing but whitespace before the end of the line:
+
+* ``Rejected-by: me`` indicates "the change is not ready for integration".
+* ``Acked-by: me`` indicates "I like the change".
+  This adds an ``Acked-by:`` trailer to the `merge`_ commit message.
+* ``Reviewed-by: me`` indicates "the change is ready for integration".
+  This adds a ``Reviewed-by:`` trailer to the `merge`_ commit message.
+* ``Tested-by: me`` indicates "I have tested the change and verified it works".
+  This adds a ``Tested-by:`` trailer to the `merge`_ commit message.
+
+Each ``me`` reference may instead be an ``@username`` reference or a full
+``Real Name <user at domain>`` reference to credit someone else for performing
+the review.  References to ``me`` and ``@username`` will automatically be
+transformed into a real name and email address according to the user's
+GitLab account profile.
+
+Comment Trailer Commands
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Among the `comment trailing lines`_ authorized users may issue special
+commands to ``@kwrobot`` using the form ``Do: ...``:
+
+* ``Do: check`` explicitly re-runs the robot `Automatic Check`_.
+* ``Do: reformat`` rewrites the MR topic for `Automatic Format`_.
+* ``Do: test`` submits the MR for `Topic Testing`_.
+* ``Do: stage`` submits the MR for `Integration Testing`_.
+* ``Do: merge`` submits the MR for `Merge`_.
+
+See the corresponding sections for details on permissions and options
+for each command.
+
+Topic Testing
+=============
+
+CMake has a `buildbot`_ instance watching for merge requests to test.
+`CMake GitLab Project Developers`_ may activate buildbot on a MR by
+adding a comment with a command among the `comment trailing lines`_::
+
+  Do: test
+
+``@kwrobot`` will add an award emoji to the comment to indicate that it
+was processed and also inform buildbot about the request.  The buildbot
+user (``@buildbot``) will schedule builds and respond with a comment
+linking to the `CMake CDash Page`_ with a filter for results associated
+with the topic test request.  If the MR topic branch is updated by a
+push a new ``Do: test`` command is needed to activate testing again.
+
+The ``Do: test`` command accepts the following arguments:
+
+* ``--stop``: clear the list of commands for the merge request
+* ``--clear``: clear previous commands before adding this command
+* ``--regex-include <arg>`` or ``-i <arg>``: only build on builders
+  matching ``<arg>`` (a Python regular expression)
+* ``--regex-exclude <arg>`` or ``-e <arg>``: exclude builds on builders
+  matching ``<arg>`` (a Python regular expression)
+
+Builder names follow the pattern ``project-host-os-buildtype-generator``:
+
+* ``project``: always ``cmake`` for CMake builds
+* ``host``: the buildbot host
+* ``os``: one of ``windows``, ``osx``, or ``linux``
+* ``buildtype``: ``release`` or ``debug``
+* ``generator``: ``ninja``, ``makefiles``, ``vs<year>``,
+  or ``lint-iwyu-tidy``
+
+The special ``lint-<tools>`` generator name is a builder that builds
+CMake using lint tools but does not run the test suite (so the actual
+generator does not matter).
+
+.. _`buildbot`: http://buildbot.net
+.. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake
+
+Integration Testing
+===================
+
+The above `topic testing`_ tests the MR topic independent of other
+merge requests and on only a few key platforms and configurations.
+The `CMake Testing Process`_ also has a large number of machines
+provided by Kitware and generous volunteers that cover nearly all
+supported platforms, generators, and configurations.  In order to
+avoid overwhelming these resources, they do not test every MR
+individually.  Instead, these machines follow an *integration branch*,
+run tests on a nightly basis (or continuously during the day), and
+post to the `CMake CDash Page`_.  Some follow ``master``.  Most follow
+a special integration branch, the *topic stage*.
+
+The topic stage is a special branch maintained by the "Kitware Robot"
+(``@kwrobot``).  It consists of the head of the MR target integration
+branch (e.g. ``master``) branch followed by a sequence of merges each
+integrating changes from an open MR that has been staged for integration
+testing.  Each time the target integration branch is updated the stage
+is rebuilt automatically by merging the staged MR topics again.
+
+`CMake GitLab Project Developers`_ may stage a MR for integration testing
+by adding a comment with a command among the `comment trailing lines`_::
+
+  Do: stage
+
+``@kwrobot`` will add an award emoji to the comment to indicate that it
+was processed and also attempt to add the MR topic branch to the topic
+stage.  If the MR cannot be added (e.g. due to conflicts) the robot will
+post a comment explaining what went wrong.
+
+Once a MR has been added to the topic stage it will remain on the stage
+until one of the following occurs:
+
+* The MR topic branch is updated by a push.
+
+* The MR target integration branch (e.g. ``master``) branch is updated
+  and the MR cannot be merged into the topic stage again due to conflicts.
+
+* A developer or the submitter posts an explicit ``Do: unstage`` command.
+  This is useful to remove a MR from the topic stage when one is not ready
+  to push an update to the MR topic branch.  It is unnecessary to explicitly
+  unstage just before or after pushing an update because the push will cause
+  the MR to be unstaged automatically.
+
+* The MR is closed.
+
+* The MR is merged.
+
+Once a MR has been removed from the topic stage a new ``Do: stage``
+command is needed to stage it again.
+
+.. _`CMake Testing Process`: testing.rst
+
+Resolve
+=======
+
+A MR may be resolved in one of the following ways.
+
+Merge
+-----
+
+Once review has concluded that the MR topic is ready for integration,
+`CMake GitLab Project Masters`_ may merge the topic by adding a comment
+with a command among the `comment trailing lines`_::
+
+  Do: merge
+
+``@kwrobot`` will add an award emoji to the comment to indicate that it
+was processed and also attempt to merge the MR topic branch to the MR
+target integration branch (e.g. ``master``).  If the MR cannot be merged
+(e.g. due to conflicts) the robot will post a comment explaining what
+went wrong.  If the MR is merged the robot will also remove the source
+branch from the user's fork if the corresponding MR option was checked.
+
+The robot automatically constructs a merge commit message of the following
+form::
+
+  Merge topic 'mr-topic-branch-name'
+
+  00000000 commit message subject line (one line per commit)
+
+  Acked-by: Kitware Robot <kwrobot at kitware.com>
+  Merge-request: !0000
+
+Mention of the commit short sha1s and MR number helps GitLab link the
+commits back to the merge request and indicates when they were merged.
+The ``Acked-by:`` trailer shown indicates that `Robot Review`_ passed.
+Additional ``Acked-by:``, ``Reviewed-by:``, and similar trailers may be
+collected from `Human Review`_ comments that have been made since the
+last time the MR topic branch was updated with a push.
+
+The ``Do: merge`` command accepts the following arguments:
+
+* ``-t <topic>``: substitute ``<topic>`` for the name of the MR topic
+  branch in the constructed merge commit message.
+
+Additionally, ``Do: merge`` extracts configuration from trailing lines
+in the MR description:
+
+* ``Topic-rename: <topic>``: substitute ``<topic>`` for the name of
+  the MR topic branch in the constructed merge commit message.
+  The ``-t`` option overrides this.
+
+.. _`CMake GitLab Project Masters`: https://gitlab.kitware.com/cmake/cmake/settings/members
+
+Close
+-----
+
+If review has concluded that the MR should not be integrated then it
+may be closed through GitLab.
+
+Expire
+------
+
+If progress on a MR has stalled for a while, it may be closed with a
+``workflow:expired`` label and a comment indicating that the MR has
+been closed due to inactivity.
+
+Contributors are welcome to re-open an expired MR when they are ready
+to continue work.  Please re-open *before* pushing an update to the
+MR topic branch to ensure GitLab will still act on the association.
diff --git a/Help/dev/source.rst b/Help/dev/source.rst
new file mode 100644
index 0000000..7e44995
--- /dev/null
+++ b/Help/dev/source.rst
@@ -0,0 +1,60 @@
+CMake Source Code Guide
+***********************
+
+The following is a guide to the CMake source code for developers.
+See documentation on `CMake Development`_ for more information.
+
+.. _`CMake Development`: README.rst
+
+C++ Code Style
+==============
+
+We use `clang-format`_ version **3.8** to define our style for C++ code in
+the CMake source tree.  See the `.clang-format`_ configuration file for our
+style settings.  Use the `Utilities/Scripts/clang-format.bash`_ script to
+format source code.  It automatically runs ``clang-format`` on the set of
+source files for which we enforce style.  The script also has options to
+format only a subset of files, such as those that are locally modified.
+
+.. _`clang-format`: http://clang.llvm.org/docs/ClangFormat.html
+.. _`.clang-format`: ../../.clang-format
+.. _`Utilities/Scripts/clang-format.bash`: ../../Utilities/Scripts/clang-format.bash
+
+C++ Subset Permitted
+====================
+
+CMake supports compiling as C++98 in addition to C++11 and C++14.
+In order to support building on older toolchains some constructs
+need to be handled with care:
+
+* Use ``CM_AUTO_PTR`` instead of ``std::auto_ptr``.
+
+  The ``std::auto_ptr`` template is deprecated in C++11.  We want to use it
+  so we can build on C++98 compilers but we do not want to turn off compiler
+  warnings about deprecated interfaces in general.  Use the ``CM_AUTO_PTR``
+  macro instead.
+
+* Use ``CM_EQ_DELETE;`` instead of ``= delete;``.
+
+  Defining functions as *deleted* is not supported in C++98.  Using
+  ``CM_EQ_DELETE`` will delete the functions if the compiler supports it and
+  give them no implementation otherwise.  Calling such a function will lead
+  to compiler errors if the compiler supports *deleted* functions and linker
+  errors otherwise.
+
+* Use ``CM_DISABLE_COPY(Class)`` to mark classes as non-copyable.
+
+  The ``CM_DISABLE_COPY`` macro should be used in the private section of a
+  class to make sure that attempts to copy or assign an instance of the class
+  lead to compiler errors even if the compiler does not support *deleted*
+  functions.  As a guideline, all polymorphic classes should be made
+  non-copyable in order to avoid slicing.  Classes that are composed of or
+  derived from non-copyable classes must also be made non-copyable explicitly
+  with ``CM_DISABLE_COPY``.
+
+* Use ``size_t`` instead of ``std::size_t``.
+
+  Various implementations have differing implementation of ``size_t``.
+  When assigning the result of ``.size()`` on a container for example,
+  the result should be assigned to ``size_t`` not to ``std::size_t``,
+  ``unsigned int`` or similar types.
diff --git a/Help/dev/testing.rst b/Help/dev/testing.rst
new file mode 100644
index 0000000..731930c
--- /dev/null
+++ b/Help/dev/testing.rst
@@ -0,0 +1,42 @@
+CMake Testing Process
+*********************
+
+The following documents the process for running integration testing builds.
+See documentation on `CMake Development`_ for more information.
+
+.. _`CMake Development`: README.rst
+
+CMake Dashboard Scripts
+=======================
+
+The *integration testing* step of the `CMake Review Process`_ uses a set of
+testing machines that follow an integration branch on their own schedule to
+drive testing and submit results to the `CMake CDash Page`_.  Anyone is
+welcome to provide testing machines in order to help keep support for their
+platforms working.
+
+The `CMake Dashboard Scripts Repository`_ provides CTest scripts to drive
+nightly, continous, and experimental testing of CMake.  Use the following
+commands to set up a new integration testing client:
+
+.. code-block:: console
+
+  $ mkdir -p ~/Dashboards
+  $ cd ~/Dashboards
+  $ git clone https://gitlab.kitware.com/cmake/dashboard-scripts.git CMakeScripts
+  $ cd CMakeScripts
+
+The ``cmake_common.cmake`` script contains comments at the top with
+instructions to set up a testing client.  As it instructs, create a
+CTest script with local settings and include ``cmake_common.cmake``.
+
+.. _`CMake Review Process`: review.rst
+.. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake
+.. _`CMake Dashboard Scripts Repository`: https://gitlab.kitware.com/cmake/dashboard-scripts
+
+Nightly Start Time
+------------------
+
+The ``cmake_common.cmake`` script expects its includer to be run from a
+nightly scheduled task (cron job).  Schedule such tasks for sometime after
+``1:00am UTC``, the time at which our nightly testing branches fast-forward.
diff --git a/Help/generator/VS_TOOLSET_HOST_ARCH.txt b/Help/generator/VS_TOOLSET_HOST_ARCH.txt
index 58e9223..5d13e77 100644
--- a/Help/generator/VS_TOOLSET_HOST_ARCH.txt
+++ b/Help/generator/VS_TOOLSET_HOST_ARCH.txt
@@ -2,9 +2,5 @@ For each toolset that comes with this version of Visual Studio, there are
 variants that are themselves compiled for 32-bit (x86) and 64-bit (x64) hosts
 (independent of the architecture they target).  By default Visual Studio
 chooses the 32-bit variant even on a 64-bit host.  One may request use of the
-64-bit host tools by adding ``host=x64`` to the toolset specification:
-
-``host=x64``
-  Select the 64-bit variant of the default toolset.
-``<toolset>,host=x64``
-  Select the 64-bit variant of the ``<toolset>`` toolset.
+64-bit host tools by adding a ``host=x64`` option to the toolset specification.
+See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details.
diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst
index a88f8bc..2ac0449 100644
--- a/Help/generator/Visual Studio 15 2017.rst	
+++ b/Help/generator/Visual Studio 15 2017.rst	
@@ -15,6 +15,18 @@ a target platform name optionally at the end of this generator name:
 ``Visual Studio 15 2017 ARM``
   Specify target platform ``ARM``.
 
+Instance Selection
+^^^^^^^^^^^^^^^^^^
+
+VS 2017 supports multiple installations on the same machine.
+CMake queries the Visual Studio Installer to locate VS instances.
+If more than one instance is installed we do not define which one
+is chosen by default.  If the ``VS150COMNTOOLS`` environment variable
+is set and points to the ``Common7/Tools`` directory within one of
+the instances, that instance will be used.  The environment variable
+must remain consistently set whenever CMake is re-run within a given
+build tree.
+
 Toolset Selection
 ^^^^^^^^^^^^^^^^^
 
diff --git a/Help/generator/Visual Studio 7 .NET 2003.rst b/Help/generator/Visual Studio 7 .NET 2003.rst
index 1c086a0..d4c7869 100644
--- a/Help/generator/Visual Studio 7 .NET 2003.rst	
+++ b/Help/generator/Visual Studio 7 .NET 2003.rst	
@@ -1,10 +1,6 @@
 Visual Studio 7 .NET 2003
 -------------------------
 
-Deprecated.  Generates Visual Studio .NET 2003 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 7.1 tools using the
-  :generator:`NMake Makefiles` generator.
+Removed.  This once generated Visual Studio .NET 2003 project files, but
+the generator has been removed since CMake 3.9.  It is still possible to
+build with VS 7.1 tools using the :generator:`NMake Makefiles` generator.
diff --git a/Help/generator/Visual Studio 8 2005.rst b/Help/generator/Visual Studio 8 2005.rst
index 29012c3..acbbf01 100644
--- a/Help/generator/Visual Studio 8 2005.rst	
+++ b/Help/generator/Visual Studio 8 2005.rst	
@@ -1,7 +1,14 @@
 Visual Studio 8 2005
 --------------------
 
-Generates Visual Studio 8 2005 project files.
+Deprecated.  Generates Visual Studio 8 2005 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 8 2005 tools
+  using the :generator:`Visual Studio 10 2010` (or above) generator
+  with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v80``, or by
+  using the :generator:`NMake Makefiles` generator.
 
 The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set
 to specify a target platform name.
diff --git a/Help/generator/Xcode.rst b/Help/generator/Xcode.rst
index 25ff4c7..968c26a 100644
--- a/Help/generator/Xcode.rst
+++ b/Help/generator/Xcode.rst
@@ -3,6 +3,8 @@ Xcode
 
 Generate Xcode project files.
 
+This supports Xcode 3.0 and above.
+
 Toolset Selection
 ^^^^^^^^^^^^^^^^^
 
diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt
index 9b3f717..e8b87c9 100644
--- a/Help/manual/OPTIONS_BUILD.txt
+++ b/Help/manual/OPTIONS_BUILD.txt
@@ -48,31 +48,19 @@
  build system.  Possible generator names are specified in the
  :manual:`cmake-generators(7)` manual.
 
-``-T <toolset-name>``
- Specify toolset name if supported by generator.
+``-T <toolset-spec>``
+ Toolset specification for the generator, if supported.
 
- Some CMake generators support a toolset name to be given to the
- native build system to choose a compiler.
- See the :variable:`CMAKE_GENERATOR_TOOLSET` variable.
- This is supported only on specific generators:
-
- * :ref:`Visual Studio Generators` for VS 2010 and above
- * The :generator:`Xcode` generator for Xcode 3.0 and above
-
- See native build system documentation for allowed toolset names.
+ Some CMake generators support a toolset specification to tell
+ the native build system how to choose a compiler.  See the
+ :variable:`CMAKE_GENERATOR_TOOLSET` variable for details.
 
 ``-A <platform-name>``
  Specify platform name if supported by generator.
 
  Some CMake generators support a platform name to be given to the
  native build system to choose a compiler or SDK.  See the
- :variable:`CMAKE_GENERATOR_PLATFORM` variable.
- This is supported only on specific generators:
-
- * For :ref:`Visual Studio Generators` with VS 2005 and above this
-   specifies the target architecture.
-
- See native build system documentation for allowed platform names.
+ :variable:`CMAKE_GENERATOR_PLATFORM` variable for details.
 
 ``-Wno-dev``
  Suppress developer warnings.
diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst
index 2e6a803..95f5b87 100644
--- a/Help/manual/cmake-buildsystem.7.rst
+++ b/Help/manual/cmake-buildsystem.7.rst
@@ -125,10 +125,10 @@ The object files collection can be used as source inputs to other targets:
 
   add_executable(test_exe $<TARGET_OBJECTS:archive> test.cpp)
 
-``OBJECT`` libraries may only be used locally as sources in a buildsystem --
-they may not be installed, exported, or used in the right hand side of
+``OBJECT`` libraries may not be used in the right hand side of
 :command:`target_link_libraries`.  They also may not be used as the ``TARGET``
-in a use of the :command:`add_custom_command(TARGET)` command signature.
+in a use of the :command:`add_custom_command(TARGET)` command signature.  They
+may be installed, and will be exported as an INTERFACE library.
 
 Although object libraries may not be named directly in calls to
 the :command:`target_link_libraries` command, they can be "linked"
@@ -136,6 +136,12 @@ indirectly by using an :ref:`Interface Library <Interface Libraries>`
 whose :prop_tgt:`INTERFACE_SOURCES` target property is set to name
 ``$<TARGET_OBJECTS:objlib>``.
 
+Although object libraries may not be used as the ``TARGET``
+in a use of the :command:`add_custom_command(TARGET)` command signature,
+the list of objects can be used by :command:`add_custom_command(OUTPUT)` or
+:command:`file(GENERATE)` by using ``$<TARGET_OBJECTS:objlib>``.
+
+
 Build Specification and Usage Requirements
 ==========================================
 
diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst
index d0c2986..611c989 100644
--- a/Help/manual/cmake-commands.7.rst
+++ b/Help/manual/cmake-commands.7.rst
@@ -7,91 +7,103 @@ cmake-commands(7)
 
    .. contents::
 
-Normal Commands
-===============
+Scripting Commands
+==================
 
-These commands may be used freely in CMake projects.
+These commands are always available.
 
 .. toctree::
    :maxdepth: 1
 
-   /command/add_compile_options
-   /command/add_custom_command
-   /command/add_custom_target
-   /command/add_definitions
-   /command/add_dependencies
-   /command/add_executable
-   /command/add_library
-   /command/add_subdirectory
-   /command/add_test
-   /command/aux_source_directory
    /command/break
-   /command/build_command
    /command/cmake_host_system_information
    /command/cmake_minimum_required
    /command/cmake_parse_arguments
    /command/cmake_policy
    /command/configure_file
    /command/continue
-   /command/create_test_sourcelist
-   /command/define_property
    /command/elseif
    /command/else
-   /command/enable_language
-   /command/enable_testing
    /command/endforeach
    /command/endfunction
    /command/endif
    /command/endmacro
    /command/endwhile
    /command/execute_process
-   /command/export
    /command/file
    /command/find_file
    /command/find_library
    /command/find_package
    /command/find_path
    /command/find_program
-   /command/fltk_wrap_ui
    /command/foreach
    /command/function
    /command/get_cmake_property
    /command/get_directory_property
    /command/get_filename_component
    /command/get_property
+   /command/if
+   /command/include
+   /command/list
+   /command/macro
+   /command/mark_as_advanced
+   /command/math
+   /command/message
+   /command/option
+   /command/return
+   /command/separate_arguments
+   /command/set_directory_properties
+   /command/set_property
+   /command/set
+   /command/site_name
+   /command/string
+   /command/unset
+   /command/variable_watch
+   /command/while
+
+Project Commands
+================
+
+These commands are available only in CMake projects.
+
+.. toctree::
+   :maxdepth: 1
+
+   /command/add_compile_options
+   /command/add_custom_command
+   /command/add_custom_target
+   /command/add_definitions
+   /command/add_dependencies
+   /command/add_executable
+   /command/add_library
+   /command/add_subdirectory
+   /command/add_test
+   /command/aux_source_directory
+   /command/build_command
+   /command/create_test_sourcelist
+   /command/define_property
+   /command/enable_language
+   /command/enable_testing
+   /command/export
+   /command/fltk_wrap_ui
    /command/get_source_file_property
    /command/get_target_property
    /command/get_test_property
-   /command/if
    /command/include_directories
    /command/include_external_msproject
    /command/include_regular_expression
-   /command/include
    /command/install
    /command/link_directories
    /command/link_libraries
-   /command/list
    /command/load_cache
-   /command/macro
-   /command/mark_as_advanced
-   /command/math
-   /command/message
-   /command/option
    /command/project
    /command/qt_wrap_cpp
    /command/qt_wrap_ui
    /command/remove_definitions
-   /command/return
-   /command/separate_arguments
-   /command/set_directory_properties
-   /command/set_property
-   /command/set
    /command/set_source_files_properties
    /command/set_target_properties
    /command/set_tests_properties
-   /command/site_name
    /command/source_group
-   /command/string
    /command/target_compile_definitions
    /command/target_compile_features
    /command/target_compile_options
@@ -100,9 +112,30 @@ These commands may be used freely in CMake projects.
    /command/target_sources
    /command/try_compile
    /command/try_run
-   /command/unset
-   /command/variable_watch
-   /command/while
+
+.. _`CTest Commands`:
+
+CTest Commands
+==============
+
+These commands are available only in CTest scripts.
+
+.. toctree::
+   :maxdepth: 1
+
+   /command/ctest_build
+   /command/ctest_configure
+   /command/ctest_coverage
+   /command/ctest_empty_binary_directory
+   /command/ctest_memcheck
+   /command/ctest_read_custom_files
+   /command/ctest_run_script
+   /command/ctest_sleep
+   /command/ctest_start
+   /command/ctest_submit
+   /command/ctest_test
+   /command/ctest_update
+   /command/ctest_upload
 
 Deprecated Commands
 ===================
@@ -129,27 +162,3 @@ versions of CMake.  Do not use them in new code.
    /command/utility_source
    /command/variable_requires
    /command/write_file
-
-.. _`CTest Commands`:
-
-CTest Commands
-==============
-
-These commands are available only in ctest scripts.
-
-.. toctree::
-   :maxdepth: 1
-
-   /command/ctest_build
-   /command/ctest_configure
-   /command/ctest_coverage
-   /command/ctest_empty_binary_directory
-   /command/ctest_memcheck
-   /command/ctest_read_custom_files
-   /command/ctest_run_script
-   /command/ctest_sleep
-   /command/ctest_start
-   /command/ctest_submit
-   /command/ctest_test
-   /command/ctest_update
-   /command/ctest_upload
diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst
index 448fe9a..0124395 100644
--- a/Help/manual/cmake-compile-features.7.rst
+++ b/Help/manual/cmake-compile-features.7.rst
@@ -334,8 +334,8 @@ versions specified for each:
 * ``AppleClang``: Apple Clang for Xcode versions 4.4 though 6.2.
 * ``Clang``: Clang compiler versions 2.9 through 3.4.
 * ``GNU``: GNU compiler versions 4.4 through 5.0.
-* ``MSVC``: Microsoft Visual Studio versions 2010 through 2015.
-* ``SunPro``: Oracle SolarisStudio version 12.4.
+* ``MSVC``: Microsoft Visual Studio versions 2010 through 2017.
+* ``SunPro``: Oracle SolarisStudio versions 12.4 through 12.5.
 * ``Intel``: Intel compiler versions 12.1 through 17.0.
 
 CMake is currently aware of the :prop_tgt:`C standards <C_STANDARD>`
@@ -343,9 +343,25 @@ and :prop_gbl:`compile features <CMAKE_C_KNOWN_FEATURES>` available from
 the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
 versions specified for each:
 
-* all compilers and versions listed above for C++
+* all compilers and versions listed above for C++.
 * ``GNU``: GNU compiler versions 3.4 through 5.0.
 
+CMake is currently aware of the :prop_tgt:`C++ standards <CXX_STANDARD>` and
+their associated meta-features (e.g. ``cxx_std_11``) available from the
+following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
+versions specified for each:
+
+* ``Cray``: Cray Compiler Environment version 8.1 through 8.5.8.
+* ``PGI``: PGI version 12.10 through 17.5.
+* ``XL``: IBM XL version 10.1 through 13.1.5.
+
+CMake is currently aware of the :prop_tgt:`C standards <C_STANDARD>` and
+their associated meta-features (e.g. ``c_std_99``) available from the
+following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
+versions specified for each:
+
+* all compilers and versions listed above with only meta-features for C++.
+
 CMake is currently aware of the :prop_tgt:`CUDA standards <CUDA_STANDARD>`
 from the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
 versions specified for each:
diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst
index f77d8c0..cd509ac 100644
--- a/Help/manual/cmake-developer.7.rst
+++ b/Help/manual/cmake-developer.7.rst
@@ -13,30 +13,6 @@ Introduction
 This manual is intended for reference by developers modifying the CMake
 source tree itself, and by those authoring externally-maintained modules.
 
-
-Permitted C++ Subset
-====================
-
-CMake is required to build with ancient C++ compilers and standard library
-implementations.  Some common C++ constructs may not be used in CMake in order
-to build with such toolchains.
-
-std::auto_ptr
--------------
-
-The ``std::auto_ptr`` template is deprecated in C++11.  We want to use it
-so we can build on C++98 compilers but we do not want to turn off compiler
-warnings about deprecated interfaces in general.  Use the ``CM_AUTO_PTR``
-macro instead.
-
-size_t
-------
-
-Various implementations have differing implementation of ``size_t``.  When
-assigning the result of ``.size()`` on a container for example, the result
-should be assigned to ``size_t`` not to ``std::size_t``, ``unsigned int`` or
-similar types.
-
 Adding Compile Features
 =======================
 
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 3a225ad..bddb174 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -117,7 +117,7 @@ Available logical expressions are:
   .. code-block:: cmake
 
     add_library(myapp_c foo.c)
-    add_library(myapp_cxx foo.c)
+    add_library(myapp_cxx bar.cpp)
     target_compile_options(myapp_cxx PUBLIC -fno-exceptions)
     add_executable(myapp main.cpp)
     target_link_libraries(myapp myapp_c myapp_cxx)
@@ -205,6 +205,15 @@ Available informational expressions are:
   Name of the linker generated program database file (.pdb).
 ``$<TARGET_PDB_FILE_DIR:tgt>``
   Directory of the linker generated program database file (.pdb).
+``$<TARGET_BUNDLE_DIR:tgt>``
+  Full path to the bundle directory (``my.app``, ``my.framework``, or
+  ``my.bundle``) where ``tgt`` is the name of a target.
+``$<TARGET_BUNDLE_CONTENT_DIR:tgt>``
+  Full path to the bundle content directory where ``tgt`` is the name of a
+  target. For the macOS SDK it leads to ``my.app/Contents``, ``my.framework``,
+  or ``my.bundle/Contents``. For all other SDKs (e.g. iOS) it leads to
+  ``my.app``, ``my.framework``, or ``my.bundle`` due to the flat bundle
+  structure.
 ``$<TARGET_PROPERTY:tgt,prop>``
   Value of the property ``prop`` on the target ``tgt``.
 
@@ -281,9 +290,7 @@ Available output expressions are:
   Content of ``...`` converted to a C identifier.
 ``$<TARGET_OBJECTS:objLib>``
   List of objects resulting from build of ``objLib``. ``objLib`` must be an
-  object of type ``OBJECT_LIBRARY``.  This expression may only be used in
-  the sources of :command:`add_library` and :command:`add_executable`
-  commands.
+  object of type ``OBJECT_LIBRARY``.
 ``$<SHELL_PATH:...>``
   Content of ``...`` converted to shell path style. For example, slashes are
   converted to backslashes in Windows shells and drive letters are converted
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index c478a1b..4a03b7a 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -27,6 +27,7 @@ All Modules
    /module/CheckFortranFunctionExists
    /module/CheckFortranSourceCompiles
    /module/CheckFunctionExists
+   /module/CheckIPOSupported
    /module/CheckIncludeFileCXX
    /module/CheckIncludeFile
    /module/CheckIncludeFiles
@@ -53,6 +54,7 @@ All Modules
    /module/CMakePrintSystemInformation
    /module/CMakePushCheckState
    /module/CMakeVerifyManifest
+   /module/CPackArchive
    /module/CPackBundle
    /module/CPackComponent
    /module/CPackCygwin
@@ -229,6 +231,7 @@ All Modules
    /module/GenerateExportHeader
    /module/GetPrerequisites
    /module/GNUInstallDirs
+   /module/GoogleTest
    /module/InstallRequiredSystemLibraries
    /module/MacroAddFileDependencies
    /module/ProcessorCount
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index 3266958..7b85817 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,15 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
 to determine whether to report an error on use of deprecated macros or
 functions.
 
+Policies Introduced by CMake 3.9
+================================
+
+.. toctree::
+   :maxdepth: 1
+
+   CMP0069: INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. </policy/CMP0069>
+   CMP0068: RPATH settings on macOS do not affect install_name. </policy/CMP0068>
+
 Policies Introduced by CMake 3.8
 ================================
 
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 0e3eb86..ec25596 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -16,8 +16,11 @@ Properties of Global Scope
    :maxdepth: 1
 
    /prop_gbl/ALLOW_DUPLICATE_CUSTOM_TARGETS
+   /prop_gbl/AUTOGEN_SOURCE_GROUP
    /prop_gbl/AUTOGEN_TARGETS_FOLDER
+   /prop_gbl/AUTOMOC_SOURCE_GROUP
    /prop_gbl/AUTOMOC_TARGETS_FOLDER
+   /prop_gbl/AUTORCC_SOURCE_GROUP
    /prop_gbl/CMAKE_C_KNOWN_FEATURES
    /prop_gbl/CMAKE_CXX_KNOWN_FEATURES
    /prop_gbl/DEBUG_CONFIGURATIONS
@@ -26,7 +29,9 @@ Properties of Global Scope
    /prop_gbl/ENABLED_LANGUAGES
    /prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS
    /prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS
+   /prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS
    /prop_gbl/FIND_LIBRARY_USE_OPENBSD_VERSIONING
+   /prop_gbl/GENERATOR_IS_MULTI_CONFIG
    /prop_gbl/GLOBAL_DEPENDS_DEBUG_MODE
    /prop_gbl/GLOBAL_DEPENDS_NO_CYCLES
    /prop_gbl/IN_TRY_COMPILE
@@ -114,15 +119,19 @@ Properties on Targets
    /prop_tgt/ARCHIVE_OUTPUT_DIRECTORY
    /prop_tgt/ARCHIVE_OUTPUT_NAME_CONFIG
    /prop_tgt/ARCHIVE_OUTPUT_NAME
+   /prop_tgt/AUTOGEN_BUILD_DIR
    /prop_tgt/AUTOGEN_TARGET_DEPENDS
+   /prop_tgt/AUTOMOC_DEPEND_FILTERS
    /prop_tgt/AUTOMOC_MOC_OPTIONS
    /prop_tgt/AUTOMOC
    /prop_tgt/AUTOUIC
    /prop_tgt/AUTOUIC_OPTIONS
+   /prop_tgt/AUTOUIC_SEARCH_PATHS
    /prop_tgt/AUTORCC
    /prop_tgt/AUTORCC_OPTIONS
    /prop_tgt/BINARY_DIR
    /prop_tgt/BUILD_RPATH
+   /prop_tgt/BUILD_WITH_INSTALL_NAME_DIR
    /prop_tgt/BUILD_WITH_INSTALL_RPATH
    /prop_tgt/BUNDLE_EXTENSION
    /prop_tgt/BUNDLE
@@ -144,7 +153,9 @@ Properties on Targets
    /prop_tgt/CONFIG_OUTPUT_NAME
    /prop_tgt/CONFIG_POSTFIX
    /prop_tgt/CROSSCOMPILING_EMULATOR
+   /prop_tgt/CUDA_PTX_COMPILATION
    /prop_tgt/CUDA_SEPARABLE_COMPILATION
+   /prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS
    /prop_tgt/CUDA_EXTENSIONS
    /prop_tgt/CUDA_STANDARD
    /prop_tgt/CUDA_STANDARD_REQUIRED
@@ -186,6 +197,8 @@ Properties on Targets
    /prop_tgt/IMPORTED_LOCATION
    /prop_tgt/IMPORTED_NO_SONAME_CONFIG
    /prop_tgt/IMPORTED_NO_SONAME
+   /prop_tgt/IMPORTED_OBJECTS_CONFIG
+   /prop_tgt/IMPORTED_OBJECTS
    /prop_tgt/IMPORTED
    /prop_tgt/IMPORTED_SONAME_CONFIG
    /prop_tgt/IMPORTED_SONAME
@@ -318,6 +331,7 @@ Properties on Tests
    /prop_test/ATTACHED_FILES
    /prop_test/COST
    /prop_test/DEPENDS
+   /prop_test/DISABLED
    /prop_test/ENVIRONMENT
    /prop_test/FAIL_REGULAR_EXPRESSION
    /prop_test/FIXTURES_CLEANUP
diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst
index 56d4ca7..00d6e6e 100644
--- a/Help/manual/cmake-qt.7.rst
+++ b/Help/manual/cmake-qt.7.rst
@@ -63,26 +63,37 @@ If a ``Q_OBJECT`` or ``Q_GADGET`` macro is found in a header file, ``moc``
 will be run on the file.  The result will be put into a file named according
 to ``moc_<basename>.cpp``.  If the macro is found in a C++ implementation
 file, the moc output will be put into a file named according to
-``<basename>.moc``, following the Qt conventions.  The ``moc file`` may be
-included by the user in the C++ implementation file with a preprocessor
-``#include``.  If it is not so included, it will be added to a separate file
-which is compiled into the target.
+``<basename>.moc``, following the Qt conventions.  The ``<basename>.moc`` must
+be included by the user in the C++ implementation file with a preprocessor
+``#include``.
+
+Included ``moc_*.cpp`` and ``*.moc`` files will be generated in the
+``<AUTOGEN_BUILD_DIR>/include`` directory which is
+automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
+(This differs from CMake 3.7 and below; see their documentation for details.)
+
+* See :prop_tgt:`AUTOGEN_BUILD_DIR`.
+
+Not included ``moc_<basename>.cpp`` files will be generated in custom
+folders to avoid name collisions and included in a separate
+``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp`` file which is compiled
+into the target.
+
+* See :prop_tgt:`AUTOGEN_BUILD_DIR`.
 
 The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and
 :prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being
 invoked for, and for the appropriate build configuration.
 
-The generated ``moc_*.cpp`` and ``*.moc`` files are placed in the
-``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/include`` directory which is
-automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
-(This differs from CMake 3.7 and below; see their documentation for details.)
-
 The :prop_tgt:`AUTOMOC` target property may be pre-set for all
 following targets by setting the :variable:`CMAKE_AUTOMOC` variable.  The
 :prop_tgt:`AUTOMOC_MOC_OPTIONS` target property may be populated to set
 options to pass to ``moc``. The :variable:`CMAKE_AUTOMOC_MOC_OPTIONS`
 variable may be populated to pre-set the options for all following targets.
 
+Additional ``moc`` dependency file names can be extracted from source code
+by using :prop_tgt:`AUTOMOC_DEPEND_FILTERS`.
+
 Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by
 enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`.
 
@@ -97,13 +108,17 @@ be run, and to create rules to execute ``uic`` at the appropriate time.
 
 If a preprocessor ``#include`` directive is found which matches
 ``ui_<basename>.h``, and a ``<basename>.ui`` file exists, then ``uic`` will
-be executed to generate the appropriate file.
+be executed to generate the appropriate file. The ``<basename>.ui`` file is
+searched for first in the vicinity of including file and afterwards in the
+optional :prop_tgt:`AUTOUIC_SEARCH_PATHS` of the target.
 
 The generated generated ``ui_*.h`` files are placed in the
-``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/include`` directory which is
+``<AUTOGEN_BUILD_DIR>/include`` directory which is
 automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
 (This differs from CMake 3.7 and below; see their documentation for details.)
 
+* See :prop_tgt:`AUTOGEN_BUILD_DIR`.
+
 The :prop_tgt:`AUTOUIC` target property may be pre-set for all following
 targets by setting the :variable:`CMAKE_AUTOUIC` variable.  The
 :prop_tgt:`AUTOUIC_OPTIONS` target property may be populated to set options
diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst
index 64abe9a..8554e87 100644
--- a/Help/manual/cmake-toolchains.7.rst
+++ b/Help/manual/cmake-toolchains.7.rst
@@ -385,6 +385,11 @@ Configure use of an Android NDK with the following variables:
   If not specified, a default for this variable will be chosen
   as specified :ref:`above <Cross Compiling for Android>`.
 
+:variable:`CMAKE_ANDROID_NDK_DEPRECATED_HEADERS`
+  Set to a true value to use the deprecated per-api-level headers
+  instead of the unified headers.  If not specified, the default will
+  be false unless using a NDK that does not provide unified headers.
+
 :variable:`CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION`
   Set to the version of the NDK toolchain to be selected as the compiler.
   If not specified, the default will be the latest available GCC toolchain.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 38444d1..1a2726d 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -13,9 +13,9 @@ Variables that Provide Information
 .. toctree::
    :maxdepth: 1
 
+   /variable/CMAKE_AR
    /variable/CMAKE_ARGC
    /variable/CMAKE_ARGV0
-   /variable/CMAKE_AR
    /variable/CMAKE_BINARY_DIR
    /variable/CMAKE_BUILD_TOOL
    /variable/CMAKE_CACHEFILE_DIR
@@ -48,16 +48,20 @@ Variables that Provide Information
    /variable/CMAKE_IMPORT_LIBRARY_SUFFIX
    /variable/CMAKE_JOB_POOL_COMPILE
    /variable/CMAKE_JOB_POOL_LINK
+   /variable/CMAKE_LANG_COMPILER_AR
+   /variable/CMAKE_LANG_COMPILER_RANLIB
    /variable/CMAKE_LINK_LIBRARY_SUFFIX
    /variable/CMAKE_LINK_SEARCH_END_STATIC
    /variable/CMAKE_LINK_SEARCH_START_STATIC
    /variable/CMAKE_MAJOR_VERSION
    /variable/CMAKE_MAKE_PROGRAM
    /variable/CMAKE_MATCH_COUNT
+   /variable/CMAKE_MATCH_n
    /variable/CMAKE_MINIMUM_REQUIRED_VERSION
    /variable/CMAKE_MINOR_VERSION
    /variable/CMAKE_PARENT_LIST_FILE
    /variable/CMAKE_PATCH_VERSION
+   /variable/CMAKE_PROJECT_DESCRIPTION
    /variable/CMAKE_PROJECT_NAME
    /variable/CMAKE_RANLIB
    /variable/CMAKE_ROOT
@@ -82,18 +86,21 @@ Variables that Provide Information
    /variable/CMAKE_VS_NsightTegra_VERSION
    /variable/CMAKE_VS_PLATFORM_NAME
    /variable/CMAKE_VS_PLATFORM_TOOLSET
+   /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA
    /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
    /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
+   /variable/CMAKE_XCODE_GENERATE_SCHEME
    /variable/CMAKE_XCODE_PLATFORM_TOOLSET
-   /variable/PROJECT_BINARY_DIR
    /variable/PROJECT-NAME_BINARY_DIR
-   /variable/PROJECT_NAME
    /variable/PROJECT-NAME_SOURCE_DIR
    /variable/PROJECT-NAME_VERSION
    /variable/PROJECT-NAME_VERSION_MAJOR
    /variable/PROJECT-NAME_VERSION_MINOR
    /variable/PROJECT-NAME_VERSION_PATCH
    /variable/PROJECT-NAME_VERSION_TWEAK
+   /variable/PROJECT_BINARY_DIR
+   /variable/PROJECT_DESCRIPTION
+   /variable/PROJECT_NAME
    /variable/PROJECT_SOURCE_DIR
    /variable/PROJECT_VERSION
    /variable/PROJECT_VERSION_MAJOR
@@ -127,9 +134,9 @@ Variables that Change Behavior
    /variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
    /variable/CMAKE_EXPORT_COMPILE_COMMANDS
    /variable/CMAKE_EXPORT_NO_PACKAGE_REGISTRY
-   /variable/CMAKE_SYSROOT
    /variable/CMAKE_FIND_APPBUNDLE
    /variable/CMAKE_FIND_FRAMEWORK
+   /variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX
    /variable/CMAKE_FIND_LIBRARY_PREFIXES
    /variable/CMAKE_FIND_LIBRARY_SUFFIXES
    /variable/CMAKE_FIND_NO_INSTALL_PREFIX
@@ -143,9 +150,9 @@ Variables that Change Behavior
    /variable/CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
    /variable/CMAKE_FRAMEWORK_PATH
    /variable/CMAKE_IGNORE_PATH
-   /variable/CMAKE_INCLUDE_PATH
    /variable/CMAKE_INCLUDE_DIRECTORIES_BEFORE
    /variable/CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
+   /variable/CMAKE_INCLUDE_PATH
    /variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME
    /variable/CMAKE_INSTALL_MESSAGE
    /variable/CMAKE_INSTALL_PREFIX
@@ -163,6 +170,9 @@ Variables that Change Behavior
    /variable/CMAKE_STAGING_PREFIX
    /variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS
    /variable/CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE
+   /variable/CMAKE_SYSROOT
+   /variable/CMAKE_SYSROOT_COMPILE
+   /variable/CMAKE_SYSROOT_LINK
    /variable/CMAKE_SYSTEM_APPBUNDLE_PATH
    /variable/CMAKE_SYSTEM_FRAMEWORK_PATH
    /variable/CMAKE_SYSTEM_IGNORE_PATH
@@ -187,23 +197,24 @@ Variables that Describe the System
    /variable/CMAKE_COMPILER_2005
    /variable/CMAKE_HOST_APPLE
    /variable/CMAKE_HOST_SOLARIS
+   /variable/CMAKE_HOST_SYSTEM
    /variable/CMAKE_HOST_SYSTEM_NAME
    /variable/CMAKE_HOST_SYSTEM_PROCESSOR
-   /variable/CMAKE_HOST_SYSTEM
    /variable/CMAKE_HOST_SYSTEM_VERSION
    /variable/CMAKE_HOST_UNIX
    /variable/CMAKE_HOST_WIN32
-   /variable/CMAKE_LIBRARY_ARCHITECTURE_REGEX
    /variable/CMAKE_LIBRARY_ARCHITECTURE
+   /variable/CMAKE_LIBRARY_ARCHITECTURE_REGEX
    /variable/CMAKE_OBJECT_PATH_MAX
+   /variable/CMAKE_SYSTEM
    /variable/CMAKE_SYSTEM_NAME
    /variable/CMAKE_SYSTEM_PROCESSOR
-   /variable/CMAKE_SYSTEM
    /variable/CMAKE_SYSTEM_VERSION
    /variable/CYGWIN
    /variable/ENV
    /variable/GHS-MULTI
    /variable/MINGW
+   /variable/MSVC
    /variable/MSVC10
    /variable/MSVC11
    /variable/MSVC12
@@ -214,7 +225,6 @@ Variables that Describe the System
    /variable/MSVC80
    /variable/MSVC90
    /variable/MSVC_IDE
-   /variable/MSVC
    /variable/MSVC_VERSION
    /variable/UNIX
    /variable/WIN32
@@ -245,6 +255,7 @@ Variables that Control the Build
    /variable/CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES
    /variable/CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES
    /variable/CMAKE_ANDROID_NDK
+   /variable/CMAKE_ANDROID_NDK_DEPRECATED_HEADERS
    /variable/CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG
    /variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION
    /variable/CMAKE_ANDROID_PROCESS_MAX
@@ -256,31 +267,36 @@ Variables that Control the Build
    /variable/CMAKE_ANDROID_STL_TYPE
    /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY_CONFIG
-   /variable/CMAKE_AUTOMOC_MOC_OPTIONS
    /variable/CMAKE_AUTOMOC
+   /variable/CMAKE_AUTOMOC_DEPEND_FILTERS
+   /variable/CMAKE_AUTOMOC_MOC_OPTIONS
    /variable/CMAKE_AUTORCC
    /variable/CMAKE_AUTORCC_OPTIONS
    /variable/CMAKE_AUTOUIC
    /variable/CMAKE_AUTOUIC_OPTIONS
+   /variable/CMAKE_AUTOUIC_SEARCH_PATHS
    /variable/CMAKE_BUILD_RPATH
+   /variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR
    /variable/CMAKE_BUILD_WITH_INSTALL_RPATH
    /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY
    /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG
    /variable/CMAKE_CONFIG_POSTFIX
    /variable/CMAKE_DEBUG_POSTFIX
    /variable/CMAKE_ENABLE_EXPORTS
+   /variable/CMAKE_EXE_LINKER_FLAGS
    /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG
    /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT
-   /variable/CMAKE_EXE_LINKER_FLAGS
    /variable/CMAKE_EXE_LINKER_FLAGS_INIT
    /variable/CMAKE_Fortran_FORMAT
    /variable/CMAKE_Fortran_MODULE_DIRECTORY
    /variable/CMAKE_GNUtoMS
-   /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE
    /variable/CMAKE_INCLUDE_CURRENT_DIR
+   /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE
    /variable/CMAKE_INSTALL_NAME_DIR
    /variable/CMAKE_INSTALL_RPATH
    /variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH
+   /variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION
+   /variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG
    /variable/CMAKE_IOS_INSTALL_COMBINED
    /variable/CMAKE_LANG_CLANG_TIDY
    /variable/CMAKE_LANG_COMPILER_LAUNCHER
@@ -299,9 +315,9 @@ Variables that Control the Build
    /variable/CMAKE_MACOSX_BUNDLE
    /variable/CMAKE_MACOSX_RPATH
    /variable/CMAKE_MAP_IMPORTED_CONFIG_CONFIG
+   /variable/CMAKE_MODULE_LINKER_FLAGS
    /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG
    /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG_INIT
-   /variable/CMAKE_MODULE_LINKER_FLAGS
    /variable/CMAKE_MODULE_LINKER_FLAGS_INIT
    /variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX
    /variable/CMAKE_NO_BUILTIN_CHRPATH
@@ -314,15 +330,15 @@ Variables that Control the Build
    /variable/CMAKE_POSITION_INDEPENDENT_CODE
    /variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY
    /variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY_CONFIG
+   /variable/CMAKE_SHARED_LINKER_FLAGS
    /variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG
    /variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG_INIT
-   /variable/CMAKE_SHARED_LINKER_FLAGS
    /variable/CMAKE_SHARED_LINKER_FLAGS_INIT
    /variable/CMAKE_SKIP_BUILD_RPATH
    /variable/CMAKE_SKIP_INSTALL_RPATH
+   /variable/CMAKE_STATIC_LINKER_FLAGS
    /variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG
    /variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG_INIT
-   /variable/CMAKE_STATIC_LINKER_FLAGS
    /variable/CMAKE_STATIC_LINKER_FLAGS_INIT
    /variable/CMAKE_TRY_COMPILE_CONFIGURATION
    /variable/CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
@@ -331,8 +347,8 @@ Variables that Control the Build
    /variable/CMAKE_VISIBILITY_INLINES_HIDDEN
    /variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD
    /variable/CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD
-   /variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
    /variable/CMAKE_WIN32_EXECUTABLE
+   /variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
    /variable/CMAKE_XCODE_ATTRIBUTE_an-attribute
    /variable/EXECUTABLE_OUTPUT_PATH
    /variable/LIBRARY_OUTPUT_PATH
@@ -346,10 +362,6 @@ Variables for Languages
    /variable/CMAKE_COMPILER_IS_GNUCC
    /variable/CMAKE_COMPILER_IS_GNUCXX
    /variable/CMAKE_COMPILER_IS_GNUG77
-   /variable/CMAKE_C_COMPILE_FEATURES
-   /variable/CMAKE_C_EXTENSIONS
-   /variable/CMAKE_C_STANDARD
-   /variable/CMAKE_C_STANDARD_REQUIRED
    /variable/CMAKE_CUDA_EXTENSIONS
    /variable/CMAKE_CUDA_STANDARD
    /variable/CMAKE_CUDA_STANDARD_REQUIRED
@@ -358,6 +370,10 @@ Variables for Languages
    /variable/CMAKE_CXX_EXTENSIONS
    /variable/CMAKE_CXX_STANDARD
    /variable/CMAKE_CXX_STANDARD_REQUIRED
+   /variable/CMAKE_C_COMPILE_FEATURES
+   /variable/CMAKE_C_EXTENSIONS
+   /variable/CMAKE_C_STANDARD
+   /variable/CMAKE_C_STANDARD_REQUIRED
    /variable/CMAKE_Fortran_MODDIR_DEFAULT
    /variable/CMAKE_Fortran_MODDIR_FLAG
    /variable/CMAKE_Fortran_MODOUT_FLAG
@@ -368,27 +384,27 @@ Variables for Languages
    /variable/CMAKE_LANG_ARCHIVE_APPEND
    /variable/CMAKE_LANG_ARCHIVE_CREATE
    /variable/CMAKE_LANG_ARCHIVE_FINISH
-   /variable/CMAKE_LANG_COMPILE_OBJECT
+   /variable/CMAKE_LANG_COMPILER
    /variable/CMAKE_LANG_COMPILER_ABI
+   /variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN
    /variable/CMAKE_LANG_COMPILER_ID
    /variable/CMAKE_LANG_COMPILER_LOADED
-   /variable/CMAKE_LANG_COMPILER
-   /variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN
    /variable/CMAKE_LANG_COMPILER_TARGET
    /variable/CMAKE_LANG_COMPILER_VERSION
+   /variable/CMAKE_LANG_COMPILE_OBJECT
    /variable/CMAKE_LANG_CREATE_SHARED_LIBRARY
    /variable/CMAKE_LANG_CREATE_SHARED_MODULE
    /variable/CMAKE_LANG_CREATE_STATIC_LIBRARY
+   /variable/CMAKE_LANG_FLAGS
    /variable/CMAKE_LANG_FLAGS_DEBUG
    /variable/CMAKE_LANG_FLAGS_DEBUG_INIT
+   /variable/CMAKE_LANG_FLAGS_INIT
    /variable/CMAKE_LANG_FLAGS_MINSIZEREL
    /variable/CMAKE_LANG_FLAGS_MINSIZEREL_INIT
    /variable/CMAKE_LANG_FLAGS_RELEASE
    /variable/CMAKE_LANG_FLAGS_RELEASE_INIT
    /variable/CMAKE_LANG_FLAGS_RELWITHDEBINFO
    /variable/CMAKE_LANG_FLAGS_RELWITHDEBINFO_INIT
-   /variable/CMAKE_LANG_FLAGS
-   /variable/CMAKE_LANG_FLAGS_INIT
    /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_DEBUG
    /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_MINSIZEREL
    /variable/CMAKE_LANG_GHS_KERNEL_FLAGS_RELEASE
@@ -399,8 +415,8 @@ Variables for Languages
    /variable/CMAKE_LANG_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
    /variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES
    /variable/CMAKE_LANG_LIBRARY_ARCHITECTURE
-   /variable/CMAKE_LANG_LINKER_PREFERENCE_PROPAGATES
    /variable/CMAKE_LANG_LINKER_PREFERENCE
+   /variable/CMAKE_LANG_LINKER_PREFERENCE_PROPAGATES
    /variable/CMAKE_LANG_LINK_EXECUTABLE
    /variable/CMAKE_LANG_OUTPUT_EXTENSION
    /variable/CMAKE_LANG_PLATFORM_ID
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 37e50d2..ba925e8 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -227,7 +227,7 @@ Available commands are:
 ``copy <file>... <destination>``
   Copy files to ``<destination>`` (either file or directory).
   If multiple files are specified, the ``<destination>`` must be
-  directory and it must exist.
+  directory and it must exist. Wildcards are not supported.
 
 ``copy_directory <dir>... <destination>``
   Copy directories to ``<destination>`` directory.
@@ -317,6 +317,9 @@ The following ``cmake -E`` commands are available only on UNIX:
 ``create_symlink <old> <new>``
   Create a symbolic link ``<new>`` naming ``<old>``.
 
+.. note::
+  Path to where ``<new>`` symbolic link will be created has to exist beforehand.
+
 Windows-specific Command-Line Tools
 -----------------------------------
 
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index ce81578..a89c4e9 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -117,6 +117,23 @@ Options
  This option tells ctest to NOT run the tests whose labels match the
  given regular expression.
 
+``-FA <regex>, --fixture-exclude-any <regex>``
+ Exclude fixtures matching ``<regex>`` from automatically adding any tests to
+ the test set.
+
+ If a test in the set of tests to be executed requires a particular fixture,
+ that fixture's setup and cleanup tests would normally be added to the test set
+ automatically. This option prevents adding setup or cleanup tests for fixtures
+ matching the ``<regex>``. Note that all other fixture behavior is retained,
+ including test dependencies and skipping tests that have fixture setup tests
+ that fail.
+
+``-FS <regex>, --fixture-exclude-setup <regex>``
+ Same as ``-FA`` except only matching setup tests are excluded.
+
+``-FC <regex>, --fixture-exclude-cleanup <regex>``
+ Same as ``-FA`` except only matching cleanup tests are excluded.
+
 ``-D <dashboard>, --dashboard <dashboard>``
  Execute dashboard test.
 
diff --git a/Help/module/CPackArchive.rst b/Help/module/CPackArchive.rst
new file mode 100644
index 0000000..eb8d9d2
--- /dev/null
+++ b/Help/module/CPackArchive.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CPackArchive.cmake
diff --git a/Help/module/CheckIPOSupported.rst b/Help/module/CheckIPOSupported.rst
new file mode 100644
index 0000000..9c8a77b
--- /dev/null
+++ b/Help/module/CheckIPOSupported.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckIPOSupported.cmake
diff --git a/Help/module/GoogleTest.rst b/Help/module/GoogleTest.rst
new file mode 100644
index 0000000..3d4cc97
--- /dev/null
+++ b/Help/module/GoogleTest.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/GoogleTest.cmake
diff --git a/Help/policy/CMP0068.rst b/Help/policy/CMP0068.rst
new file mode 100644
index 0000000..978a6e3
--- /dev/null
+++ b/Help/policy/CMP0068.rst
@@ -0,0 +1,35 @@
+CMP0068
+-------
+
+``RPATH`` settings on macOS do not affect ``install_name``.
+
+CMake 3.9 and newer remove any effect the following settings may have on the
+``install_name`` of a target on macOS:
+
+* :prop_tgt:`BUILD_WITH_INSTALL_RPATH` target property
+* :prop_tgt:`SKIP_BUILD_RPATH` target property
+* :variable:`CMAKE_SKIP_RPATH` variable
+* :variable:`CMAKE_SKIP_INSTALL_RPATH` variable
+
+Previously, setting :prop_tgt:`BUILD_WITH_INSTALL_RPATH` had the effect of
+setting both the ``install_name`` of a target to :prop_tgt:`INSTALL_NAME_DIR`
+and the ``RPATH`` to :prop_tgt:`INSTALL_RPATH`.  In CMake 3.9, it only affects
+setting of ``RPATH``.  However, if one wants :prop_tgt:`INSTALL_NAME_DIR` to
+apply to the target in the build tree, one may set
+:prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR`.
+
+If :prop_tgt:`SKIP_BUILD_RPATH`, :variable:`CMAKE_SKIP_RPATH` or
+:variable:`CMAKE_SKIP_INSTALL_RPATH` were used to strip the directory portion
+of the ``install_name`` of a target, one may set ``INSTALL_NAME_DIR=""``
+instead.
+
+The ``OLD`` behavior of this policy is to use the ``RPATH`` settings for
+``install_name`` on macOS.  The ``NEW`` behavior of this policy is to ignore
+the ``RPATH`` settings for ``install_name`` on macOS.
+
+This policy was introduced in CMake version 3.9.  CMake version
+|release| warns when the policy is not set and uses ``OLD`` behavior.
+Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
+explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0069.rst b/Help/policy/CMP0069.rst
new file mode 100644
index 0000000..b8f5d80
--- /dev/null
+++ b/Help/policy/CMP0069.rst
@@ -0,0 +1,92 @@
+CMP0069
+-------
+
+:prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` is enforced when enabled.
+
+CMake 3.9 and newer prefer to add IPO flags whenever the
+:prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property is enabled and
+produce an error if flags are not known to CMake for the current compiler.
+Since a given compiler may not support IPO flags in all environments in which
+it is used, it is now the project's responsibility to use the
+:module:`CheckIPOSupported` module to check for support before enabling the
+:prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property.  This approach
+allows a project to conditionally activate IPO when supported.  It also
+allows an end user to set the :variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION`
+variable in an environment known to support IPO even if the project does
+not enable the property.
+
+Since CMake 3.8 and lower only honored :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION`
+for the Intel compiler on Linux, some projects may unconditionally enable the
+target property.  Policy ``CMP0069`` provides compatibility with such projects.
+
+This policy takes effect whenever the IPO property is enabled.  The ``OLD``
+behavior for this policy is to add IPO flags only for Intel compiler on Linux.
+The ``NEW`` behavior for this policy is to add IPO flags for the current
+compiler or produce an error if CMake does not know the flags.
+
+This policy was introduced in CMake version 3.9.  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
+
+Examples
+^^^^^^^^
+
+Behave like CMake 3.8 and do not apply any IPO flags except for Intel compiler
+on Linux:
+
+.. code-block:: cmake
+
+  cmake_minimum_required(VERSION 3.8)
+  project(foo)
+
+  # ...
+
+  set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+
+Use the :module:`CheckIPOSupported` module to detect whether IPO is
+supported by the current compiler, environment, and CMake version.
+Produce a fatal error if support is not available:
+
+.. code-block:: cmake
+
+  cmake_minimum_required(VERSION 3.9) # CMP0069 NEW
+  project(foo)
+
+  include(CheckIPOSupport)
+  check_ipo_support()
+
+  # ...
+
+  set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+
+Apply IPO flags only if compiler supports it:
+
+.. code-block:: cmake
+
+  cmake_minimum_required(VERSION 3.9) # CMP0069 NEW
+  project(foo)
+
+  include(CheckIPOSupport)
+
+  # ...
+
+  check_ipo_support(RESULT result)
+  if(result)
+    set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+  endif()
+
+Apply IPO flags without any checks.  This may lead to build errors if IPO
+is not supported by the compiler in the current environment.  Produce an
+error if CMake does not know IPO flags for the current compiler:
+
+.. code-block:: cmake
+
+  cmake_minimum_required(VERSION 3.9) # CMP0069 NEW
+  project(foo)
+
+  # ...
+
+  set_property(TARGET ... PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Help/prop_dir/VS_GLOBAL_SECTION_POST_section.rst b/Help/prop_dir/VS_GLOBAL_SECTION_POST_section.rst
index eb91832..a316abe 100644
--- a/Help/prop_dir/VS_GLOBAL_SECTION_POST_section.rst
+++ b/Help/prop_dir/VS_GLOBAL_SECTION_POST_section.rst
@@ -17,7 +17,7 @@ pairs.  Each such pair will be transformed into an entry in the
 solution global section.  Whitespace around key and value is ignored.
 List elements which do not contain an equal sign are skipped.
 
-This property only works for Visual Studio 7 and above; it is ignored
+This property only works for Visual Studio 8 and above; it is ignored
 on other generators.  The property only applies when set on a
 directory whose CMakeLists.txt contains a project() command.
 
@@ -26,4 +26,6 @@ and ExtensibilityAddIns by default.  If you set the corresponding
 property, it will override the default section.  For example, setting
 VS_GLOBAL_SECTION_POST_ExtensibilityGlobals will override the default
 contents of the ExtensibilityGlobals section, while keeping
-ExtensibilityAddIns on its default.
+ExtensibilityAddIns on its default.  However, CMake will always
+add a ``SolutionGuid`` to the ``ExtensibilityGlobals`` section
+if it is not specified explicitly.
diff --git a/Help/prop_dir/VS_GLOBAL_SECTION_PRE_section.rst b/Help/prop_dir/VS_GLOBAL_SECTION_PRE_section.rst
index fbcd9e6..200e8e6 100644
--- a/Help/prop_dir/VS_GLOBAL_SECTION_PRE_section.rst
+++ b/Help/prop_dir/VS_GLOBAL_SECTION_PRE_section.rst
@@ -17,6 +17,6 @@ pairs.  Each such pair will be transformed into an entry in the
 solution global section.  Whitespace around key and value is ignored.
 List elements which do not contain an equal sign are skipped.
 
-This property only works for Visual Studio 7 and above; it is ignored
+This property only works for Visual Studio 8 and above; it is ignored
 on other generators.  The property only applies when set on a
 directory whose CMakeLists.txt contains a project() command.
diff --git a/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst
new file mode 100644
index 0000000..d294eb1
--- /dev/null
+++ b/Help/prop_gbl/AUTOGEN_SOURCE_GROUP.rst
@@ -0,0 +1,15 @@
+AUTOGEN_SOURCE_GROUP
+--------------------
+
+Name of the  :command:`source_group` for :prop_tgt:`AUTOMOC` and
+:prop_tgt:`AUTORCC` generated files.
+
+Files generated by :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` are not always
+known at configure time and therefore can't be passed to
+:command:`source_group`.
+:prop_gbl:`AUTOGEN_SOURCE_GROUP` an be used instead to generate or select
+a source group for :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` generated files.
+
+For :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTORCC` specific overrides see
+:prop_gbl:`AUTOMOC_SOURCE_GROUP` and :prop_gbl:`AUTORCC_SOURCE_GROUP`
+respectively.
diff --git a/Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst b/Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst
index fae5626..0b747b2 100644
--- a/Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst
+++ b/Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst
@@ -1,8 +1,8 @@
 AUTOGEN_TARGETS_FOLDER
 ----------------------
 
-Name of :prop_tgt:`FOLDER` for ``*_autogen`` targets that are added automatically by
-CMake for targets for which :prop_tgt:`AUTOMOC` is enabled.
+Name of :prop_tgt:`FOLDER` for ``*_autogen`` targets that are added
+automatically by CMake for targets for which :prop_tgt:`AUTOMOC` is enabled.
 
 If not set, CMake uses the :prop_tgt:`FOLDER` property of the parent target as a
 default value for this property.  See also the documentation for the
diff --git a/Help/prop_gbl/AUTOMOC_SOURCE_GROUP.rst b/Help/prop_gbl/AUTOMOC_SOURCE_GROUP.rst
new file mode 100644
index 0000000..2455dc7
--- /dev/null
+++ b/Help/prop_gbl/AUTOMOC_SOURCE_GROUP.rst
@@ -0,0 +1,7 @@
+AUTOMOC_SOURCE_GROUP
+--------------------
+
+Name of the  :command:`source_group` for :prop_tgt:`AUTOMOC` generated files.
+
+When set this is used instead of :prop_gbl:`AUTOGEN_SOURCE_GROUP` for
+files generated by :prop_tgt:`AUTOMOC`.
diff --git a/Help/prop_gbl/AUTORCC_SOURCE_GROUP.rst b/Help/prop_gbl/AUTORCC_SOURCE_GROUP.rst
new file mode 100644
index 0000000..65ea95b
--- /dev/null
+++ b/Help/prop_gbl/AUTORCC_SOURCE_GROUP.rst
@@ -0,0 +1,7 @@
+AUTORCC_SOURCE_GROUP
+--------------------
+
+Name of the  :command:`source_group` for :prop_tgt:`AUTORCC` generated files.
+
+When set this is used instead of :prop_gbl:`AUTOGEN_SOURCE_GROUP` for
+files generated by :prop_tgt:`AUTORCC`.
diff --git a/Help/prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst b/Help/prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst
index ce18b65..8396026 100644
--- a/Help/prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst
+++ b/Help/prop_gbl/FIND_LIBRARY_USE_LIB32_PATHS.rst
@@ -8,3 +8,5 @@ Whether the :command:`find_library` command should automatically search
 :command:`find_library` command should automatically search the ``lib32``
 variant of directories called ``lib`` in the search path when building 32-bit
 binaries.
+
+See also the :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable.
diff --git a/Help/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst b/Help/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst
index e52f8eb..ed343ba 100644
--- a/Help/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst
+++ b/Help/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.rst
@@ -8,3 +8,5 @@ FIND_LIBRARY_USE_LIB64_PATHS is a boolean specifying whether the
 :command:`find_library` command should automatically search the lib64
 variant of directories called lib in the search path when building
 64-bit binaries.
+
+See also the :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable.
diff --git a/Help/prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS.rst b/Help/prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS.rst
new file mode 100644
index 0000000..b87b09b
--- /dev/null
+++ b/Help/prop_gbl/FIND_LIBRARY_USE_LIBX32_PATHS.rst
@@ -0,0 +1,12 @@
+FIND_LIBRARY_USE_LIBX32_PATHS
+-----------------------------
+
+Whether the :command:`find_library` command should automatically search
+``libx32`` directories.
+
+``FIND_LIBRARY_USE_LIBX32_PATHS`` is a boolean specifying whether the
+:command:`find_library` command should automatically search the ``libx32``
+variant of directories called ``lib`` in the search path when building
+x32-abi binaries.
+
+See also the :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable.
diff --git a/Help/prop_gbl/GENERATOR_IS_MULTI_CONFIG.rst b/Help/prop_gbl/GENERATOR_IS_MULTI_CONFIG.rst
new file mode 100644
index 0000000..b8ec8a6
--- /dev/null
+++ b/Help/prop_gbl/GENERATOR_IS_MULTI_CONFIG.rst
@@ -0,0 +1,9 @@
+GENERATOR_IS_MULTI_CONFIG
+-------------------------
+
+Read-only property that is true on multi-configuration generators.
+
+True when using a multi-configuration generator
+(such as :ref:`Visual Studio Generators` or :generator:`Xcode`).
+Multi-config generators use :variable:`CMAKE_CONFIGURATION_TYPES`
+as the set of configurations and ignore :variable:`CMAKE_BUILD_TYPE`.
diff --git a/Help/prop_sf/HEADER_FILE_ONLY.rst b/Help/prop_sf/HEADER_FILE_ONLY.rst
index b4fb2db..71d62ae 100644
--- a/Help/prop_sf/HEADER_FILE_ONLY.rst
+++ b/Help/prop_sf/HEADER_FILE_ONLY.rst
@@ -7,3 +7,18 @@ A property on a source file that indicates if the source file is a
 header file with no associated implementation.  This is set
 automatically based on the file extension and is used by CMake to
 determine if certain dependency information should be computed.
+
+By setting this property to ``ON``, you can disable compilation of
+the given source file, even if it should be compiled because it is
+part of the library's/executable's sources.
+
+This is useful if you have some source files which you somehow
+pre-process, and then add these pre-processed sources via
+:command:`add_library` or :command:`add_executable`. Normally, in IDE,
+there would be no reference of the original sources, only of these
+pre-processed sources. So by setting this property for all the original
+source files to ``ON``, and then either calling :command:`add_library`
+or :command:`add_executable` while passing both the pre-processed
+sources and the original sources, or by using :command:`target_sources`
+to add original source files will do exactly what would one expect, i.e.
+the original source files would be visible in IDE, and will not be built.
diff --git a/Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst b/Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst
index 69cdcb7..a064afa 100644
--- a/Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst
+++ b/Help/prop_sf/MACOSX_PACKAGE_LOCATION.rst
@@ -21,3 +21,10 @@ extension is changed).  See the :prop_tgt:`PUBLIC_HEADER`,
 :prop_tgt:`PRIVATE_HEADER`, and :prop_tgt:`RESOURCE` target properties for
 specifying files meant for ``Headers``, ``PrivateHeaders``, or
 ``Resources`` directories.
+
+If the specified location is equal to ``Resources``, the resulting location
+will be the same as if the :prop_tgt:`RESOURCE` property had been used. If
+the specified location is a sub-folder of ``Resources``, it will be placed
+into the respective sub-folder. Note: For iOS Apple uses a flat bundle layout
+where no ``Resources`` folder exist. Therefore CMake strips the ``Resources``
+folder name from the specified location.
diff --git a/Help/prop_test/DISABLED.rst b/Help/prop_test/DISABLED.rst
new file mode 100644
index 0000000..c18ae7f
--- /dev/null
+++ b/Help/prop_test/DISABLED.rst
@@ -0,0 +1,15 @@
+DISABLED
+--------
+
+If set to true, the test will be skipped and its status will be 'Not Run'. A
+DISABLED test will not be counted in the total number of tests and its
+completion status will be reported to CDash as 'Disabled'.
+
+A DISABLED test does not participate in test fixture dependency resolution.
+If a DISABLED test has fixture requirements defined in its
+:prop_test:`FIXTURES_REQUIRED` property, it will not cause setup or cleanup
+tests for those fixtures to be added to the test set.
+
+If a test with the :prop_test:`FIXTURES_SETUP` property set is DISABLED, the
+fixture behavior will be as though that setup test was passing and any test
+case requiring that fixture will still run.
diff --git a/Help/prop_tgt/AUTOGEN_BUILD_DIR.rst b/Help/prop_tgt/AUTOGEN_BUILD_DIR.rst
new file mode 100644
index 0000000..8db6ede
--- /dev/null
+++ b/Help/prop_tgt/AUTOGEN_BUILD_DIR.rst
@@ -0,0 +1,17 @@
+AUTOGEN_BUILD_DIR
+-----------------
+
+Directory where :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTOUIC` and :prop_tgt:`AUTORCC`
+generate files for the target.
+
+The directory is created on demand and automatically added to the
+:prop_dir:`ADDITIONAL_MAKE_CLEAN_FILES`.
+
+When unset or empty the directory ``<dir>/<target-name>_autogen`` is used where
+``<dir>`` is :variable:`CMAKE_CURRENT_BINARY_DIR` and ``<target-name>``
+is :prop_tgt:`NAME`.
+
+By default :prop_tgt:`AUTOGEN_BUILD_DIR` is unset.
+
+See the :manual:`cmake-qt(7)` manual for more information on using CMake
+with Qt.
diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst
index b42643f..0171d20 100644
--- a/Help/prop_tgt/AUTOMOC.rst
+++ b/Help/prop_tgt/AUTOMOC.rst
@@ -8,31 +8,47 @@ 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.
 
-When this property is set ``ON``, CMake will scan the
+When this property is set ``ON``, CMake will scan the header and
 source files at build time and invoke moc accordingly.
 
-* If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found,
-  the ``Q_OBJECT`` class declaration is expected in the header, and
-  ``moc`` is run on the header file.  A ``moc_foo.cpp`` file will be
-  generated from the source's header into the
-  ``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/include``
-  directory which is automatically added to the target's
-  :prop_tgt:`INCLUDE_DIRECTORIES`.  This allows the compiler to find the
-  included ``moc_foo.cpp`` file regardless of the location the original source.
-  However, if multiple source files in different directories do this then their
-  generated moc files would collide.  In this case a diagnostic will be issued.
-
-* If an ``#include`` statement like ``#include "foo.moc"`` is found,
-  then a ``Q_OBJECT`` is expected in the current source file and ``moc``
-  is run on the file itself.  Additionally, header files with the same
-  base name (like ``foo.h``) or ``_p`` appended to the base name (like
-  ``foo_p.h``) are parsed for ``Q_OBJECT`` macros, and if found, ``moc``
-  is also executed on those files.  ``AUTOMOC`` checks multiple header
-  alternative extensions, such as ``hpp``, ``hxx`` etc when searching
-  for headers.  The resulting moc files, which are not included as shown
-  above in any of the source files are included in a generated
-  ``moc_compilation.cpp`` file, which is compiled as part of the
-  target.
+* If an ``#include`` statement like ``#include "moc_<basename>.cpp"`` is found,
+  the ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in an otherwise empty
+  line of the ``<basename>.h(xx)`` header file. ``moc`` is run on the header
+  file to generate ``moc_<basename>.cpp`` in the
+  ``<AUTOGEN_BUILD_DIR>/include`` directory which is automatically added
+  to the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
+  This allows the compiler to find the included ``moc_<basename>.cpp`` file
+  regardless of the location the original source.
+
+  * See :prop_tgt:`AUTOGEN_BUILD_DIR`.
+
+* If an ``#include`` statement like ``#include "<basename>.moc"`` is found,
+  then ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in the current source
+  file and ``moc`` is run on the source file itself.
+
+* Header files that are not included by an ``#include "moc_<basename>.cpp"``
+  statement are nonetheless scanned for ``Q_OBJECT`` or ``Q_GADGET`` macros.
+  The resulting ``moc_<basename>.cpp`` files are generated in custom
+  directories and automatically included in a generated
+  ``<AUTOGEN_BUILD_DIR>/mocs_compilation.cpp`` file,
+  which is compiled as part of the target.
+
+  * The custom directories with checksum
+    based names help to avoid name collisions for moc files with the same
+    ``<basename>``.
+
+  * See :prop_tgt:`AUTOGEN_BUILD_DIR`.
+
+* Additionally, header files with the same base name as a source file,
+  (like ``<basename>.h``) or ``_p`` appended to the base name (like
+  ``<basename>_p.h``), are parsed for ``Q_OBJECT`` or ``Q_GADGET`` macros,
+  and if found, ``moc`` is also executed on those files.
+
+* ``AUTOMOC`` always checks multiple header alternative extensions,
+  such as ``hpp``, ``hxx``, etc. when searching for headers.
+
+* ``AUTOMOC`` looks for the ``Q_PLUGIN_METADATA`` macro and reruns the
+  ``moc`` when the file addressed by the ``FILE`` argument of the macro changes.
 
 This property is initialized by the value of the :variable:`CMAKE_AUTOMOC`
 variable if it is set when a target is created.
@@ -47,6 +63,12 @@ See the documentation for this variable for more details.
 The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group the
 automoc targets together in an IDE, e.g.  in MSVS.
 
+The global property :prop_gbl:`AUTOGEN_SOURCE_GROUP` can be used to group
+files generated by :prop_tgt:`AUTOMOC` together in an IDE, e.g.  in MSVS.
+
+Additional ``moc`` dependency file names can be extracted from source code
+by using :prop_tgt:`AUTOMOC_DEPEND_FILTERS`.
+
 Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by
 enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`.
 
diff --git a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
new file mode 100644
index 0000000..810cbf4
--- /dev/null
+++ b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst
@@ -0,0 +1,45 @@
+AUTOMOC_DEPEND_FILTERS
+----------------------
+
+Filter definitions used by :prop_tgt:`AUTOMOC` to extract file names from
+source code as additional dependencies for the ``moc`` file.
+
+This property is only used if the :prop_tgt:`AUTOMOC` property is ``ON``
+for this target.
+
+Filters are defined as ``KEYWORD;REGULAR_EXPRESSION`` pairs. First the file
+content is searched for ``KEYWORD``. If it is found at least once, then file
+names are extracted by successively searching for ``REGULAR_EXPRESSION`` and
+taking the first match group.
+
+Consider a filter extracts the file name ``DEP`` from the content of a file
+``FOO``. If ``DEP`` changes, then the ``moc`` file for ``FOO`` gets rebuilt.
+The file ``DEP`` is searched for first in the vicinity
+of ``FOO`` and afterwards in the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
+
+By default :prop_tgt:`AUTOMOC_DEPEND_FILTERS` is initialized from
+:variable:`CMAKE_AUTOMOC_DEPEND_FILTERS`, which is empty by default.
+
+See the :manual:`cmake-qt(7)` manual for more information on using CMake
+with Qt.
+
+
+Example
+-------
+
+Consider a file ``FOO.hpp`` holds a custom macro ``OBJ_JSON_FILE`` and we
+want the ``moc`` file to depend on the macro`s file name argument::
+
+  class My_Class : public QObject
+  {
+    Q_OBJECT
+    OBJ_JSON_FILE ( "DEP.json" )
+  ...
+  };
+
+Then we might use :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` to
+define a filter like this::
+
+  set(CMAKE_AUTOMOC_DEPEND_FILTERS
+    "OBJ_JSON_FILE" "[\n][ \t]*OBJ_JSON_FILE[ \t]*\\([ \t]*\"([^\"]+)\""
+  )
diff --git a/Help/prop_tgt/AUTORCC.rst b/Help/prop_tgt/AUTORCC.rst
index 1ad0895..c0f6a26 100644
--- a/Help/prop_tgt/AUTORCC.rst
+++ b/Help/prop_tgt/AUTORCC.rst
@@ -19,6 +19,9 @@ Additional command line options for rcc can be set via the
 The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group
 the autorcc targets together in an IDE, e.g. in MSVS.
 
+The global property :prop_gbl:`AUTOGEN_SOURCE_GROUP` can be used to group
+files generated by :prop_tgt:`AUTORCC` together in an IDE, e.g.  in MSVS.
+
 When there are multiple ``.qrc`` files with the same name, CMake will
 generate unspecified unique names for ``rcc``.  Therefore if
 ``Q_INIT_RESOURCE()`` or ``Q_CLEANUP_RESOURCE()`` need to be used the
diff --git a/Help/prop_tgt/AUTOUIC.rst b/Help/prop_tgt/AUTOUIC.rst
index fbf24c3..6493bbc 100644
--- a/Help/prop_tgt/AUTOUIC.rst
+++ b/Help/prop_tgt/AUTOUIC.rst
@@ -10,8 +10,15 @@ Qt4 and Qt5 are supported.
 
 When this property is ``ON``, CMake will scan the source files at build time
 and invoke ``uic`` accordingly.  If an ``#include`` statement like
-``#include "ui_foo.h"`` is found in ``foo.cpp``, a ``foo.ui`` file is
-expected next to ``foo.cpp``, and ``uic`` is run on the ``foo.ui`` file.
+``#include "ui_foo.h"`` is found in ``source.cpp``, a ``foo.ui`` file is
+searched for first in the vicinity of ``source.cpp`` and afterwards in the
+optional :prop_tgt:`AUTOUIC_SEARCH_PATHS` of the target.
+``uic`` is run on the ``foo.ui`` file to generate ``ui_foo.h`` in the directory
+``<AUTOGEN_BUILD_DIR>/include``,
+which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
+
+* See :prop_tgt:`AUTOGEN_BUILD_DIR`.
+
 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/AUTOUIC_OPTIONS.rst b/Help/prop_tgt/AUTOUIC_OPTIONS.rst
index dc3bee5..9fb042e 100644
--- a/Help/prop_tgt/AUTOUIC_OPTIONS.rst
+++ b/Help/prop_tgt/AUTOUIC_OPTIONS.rst
@@ -1,7 +1,7 @@
 AUTOUIC_OPTIONS
 ---------------
 
-Additional options for uic when using :prop_tgt:`AUTOUIC`
+Additional options for ``uic`` when using :prop_tgt:`AUTOUIC`
 
 This property holds additional command line options which will be used when
 ``uic`` is executed during the build via :prop_tgt:`AUTOUIC`, i.e. it is
diff --git a/Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst b/Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst
new file mode 100644
index 0000000..96d9f89
--- /dev/null
+++ b/Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst
@@ -0,0 +1,12 @@
+AUTOUIC_SEARCH_PATHS
+--------------------
+
+Search path list used by :prop_tgt:`AUTOUIC` to find included
+``.ui`` files.
+
+This property is initialized by the value of the
+:variable:`CMAKE_AUTOUIC_SEARCH_PATHS` variable if it is set
+when a target is created. Otherwise it is empty.
+
+See the :manual:`cmake-qt(7)` manual for more information on using CMake
+with Qt.
diff --git a/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst b/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst
new file mode 100644
index 0000000..bbb9a24
--- /dev/null
+++ b/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst
@@ -0,0 +1,13 @@
+BUILD_WITH_INSTALL_NAME_DIR
+---------------------------
+
+``BUILD_WITH_INSTALL_NAME_DIR`` is a boolean specifying whether the macOS
+``install_name`` of a target in the build tree uses the directory given by
+:prop_tgt:`INSTALL_NAME_DIR`.  This setting only applies to targets on macOS.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_BUILD_WITH_INSTALL_NAME_DIR` if it is set when a target is
+created.
+
+If this property is not set and policy :policy:`CMP0068` is not ``NEW``, the
+value of :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is used in its place.
diff --git a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst
index abcf28f..0244351 100644
--- a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst
+++ b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst
@@ -1,11 +1,15 @@
 BUILD_WITH_INSTALL_RPATH
 ------------------------
 
-Should build tree targets have install tree rpaths.
+``BUILD_WITH_INSTALL_RPATH`` is a boolean specifying whether to link the target
+in the build tree with the :prop_tgt:`INSTALL_RPATH`.  This takes precedence
+over :prop_tgt:`SKIP_BUILD_RPATH` and avoids the need for relinking before
+installation.
 
-BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link the
-target in the build tree with the INSTALL_RPATH.  This takes
-precedence over SKIP_BUILD_RPATH and avoids the need for relinking
-before installation.  This property is initialized by the value of the
-variable CMAKE_BUILD_WITH_INSTALL_RPATH if it is set when a target is
-created.
+This property is initialized by the value of the
+:variable:`CMAKE_BUILD_WITH_INSTALL_RPATH` variable if it is set when a target
+is created.
+
+If policy :policy:`CMP0068` is not ``NEW``, this property also controls use of
+:prop_tgt:`INSTALL_NAME_DIR` in the build tree on macOS.  Either way, the
+:prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target property takes precedence.
diff --git a/Help/prop_tgt/CUDA_PTX_COMPILATION.rst b/Help/prop_tgt/CUDA_PTX_COMPILATION.rst
new file mode 100644
index 0000000..0ee372b
--- /dev/null
+++ b/Help/prop_tgt/CUDA_PTX_COMPILATION.rst
@@ -0,0 +1,12 @@
+CUDA_PTX_COMPILATION
+--------------------
+
+Compile CUDA sources to ``.ptx`` files instead of ``.obj`` files
+within :ref:`Object Libraries`.
+
+For example:
+
+.. code-block:: cmake
+
+  add_library(myptx OBJECT a.cu b.cu)
+  set_property(TARGET myptx PROPERTY CUDA_PTX_COMPILATION ON)
diff --git a/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst b/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst
new file mode 100644
index 0000000..127d79f
--- /dev/null
+++ b/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst
@@ -0,0 +1,15 @@
+CUDA_RESOLVE_DEVICE_SYMBOLS
+---------------------------
+
+CUDA only: Enables device linking for the specific static library target
+
+If set this will enable device linking on this static library target. Normally
+device linking is deferred until a shared library or executable is generated,
+allowing for multiple static libraries to resolve device symbols at the same
+time.
+
+For instance:
+
+.. code-block:: cmake
+
+  set_property(TARGET mystaticlib PROPERTY CUDA_RESOLVE_DEVICE_SYMBOLS ON)
diff --git a/Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst b/Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst
index 19270a5..a14e48c 100644
--- a/Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst
+++ b/Help/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD.rst
@@ -3,6 +3,6 @@ EXCLUDE_FROM_DEFAULT_BUILD
 
 Exclude target from "Build Solution".
 
-This property is only used by Visual Studio generators 7 and above.
+This property is only used by Visual Studio generators.
 When set to TRUE, the target will not be built when you press "Build
 Solution".
diff --git a/Help/prop_tgt/IMPORTED_OBJECTS.rst b/Help/prop_tgt/IMPORTED_OBJECTS.rst
new file mode 100644
index 0000000..222e6cc
--- /dev/null
+++ b/Help/prop_tgt/IMPORTED_OBJECTS.rst
@@ -0,0 +1,11 @@
+IMPORTED_OBJECTS
+----------------
+
+:ref:`;-list <CMake Language Lists>` of absolute paths to the object
+files on disk for an :ref:`imported <Imported targets>`
+:ref:`object library <object libraries>`.
+
+Ignored for non-imported targets.
+
+Projects may skip ``IMPORTED_OBJECTS`` if the configuration-specific
+property :prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` is set instead.
diff --git a/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst b/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst
new file mode 100644
index 0000000..4419ed1
--- /dev/null
+++ b/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst
@@ -0,0 +1,7 @@
+IMPORTED_OBJECTS_<CONFIG>
+-------------------------
+
+<CONFIG>-specific version of :prop_tgt:`IMPORTED_OBJECTS` property.
+
+Configuration names correspond to those provided by the project from
+which the target is imported.
diff --git a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst
index effa3b0..3f68c31 100644
--- a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst
+++ b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst
@@ -5,3 +5,7 @@ Enable interprocedural optimization for a target.
 
 If set to true, enables interprocedural optimizations if they are
 known to be supported by the compiler.
+
+This property is initialized by the
+:variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable if it is set when a
+target is created.
diff --git a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst
index 492fee0..782b0f0 100644
--- a/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst
+++ b/Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst
@@ -6,3 +6,7 @@ Per-configuration interprocedural optimization for a target.
 This is a per-configuration version of INTERPROCEDURAL_OPTIMIZATION.
 If set, this property overrides the generic property for the named
 configuration.
+
+This property is initialized by the
+:variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION_<CONFIG>` variable if it is set
+when a target is created.
diff --git a/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst b/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst
index 4da855b..266ccf0 100644
--- a/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst
+++ b/Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst
@@ -23,3 +23,48 @@ is ignored for non-imported targets.
 This property is initialized by the value of the
 :variable:`CMAKE_MAP_IMPORTED_CONFIG_<CONFIG>` variable if it is set when a
 target is created.
+
+Example
+^^^^^^^
+
+For example creating imported C++ library ``foo``:
+
+.. code-block:: cmake
+
+  add_library(foo STATIC IMPORTED)
+
+Use ``foo_debug`` path for ``Debug`` build type:
+
+.. code-block:: cmake
+
+  set_property(
+    TARGET foo APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG
+    )
+
+  set_target_properties(foo PROPERTIES
+    IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX"
+    IMPORTED_LOCATION_DEBUG "${foo_debug}"
+    )
+
+Use ``foo_release`` path for ``Release`` build type:
+
+.. code-block:: cmake
+
+  set_property(
+    TARGET foo APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE
+    )
+
+  set_target_properties(foo PROPERTIES
+    IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
+    IMPORTED_LOCATION_RELEASE "${foo_release}"
+    )
+
+Use ``Release`` version of library for ``MinSizeRel`` and ``RelWithDebInfo``
+build types:
+
+.. code-block:: cmake
+
+  set_target_properties(foo PROPERTIES
+    MAP_IMPORTED_CONFIG_MINSIZEREL Release
+    MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release
+    )
diff --git a/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst b/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst
index 06c3e6d..86711bf 100644
--- a/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst
+++ b/Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst
@@ -14,6 +14,13 @@ be automatically exported and imported by callers.  This simplifies porting
 projects to Windows by reducing the need for explicit ``dllexport`` markup,
 even in ``C++`` classes.
 
+When this property is enabled, zero or more ``.def`` files may also be
+specified as source files of the target.  The exports named by these files
+will be merged with those detected from the object files to generate a
+single module definition file to be passed to the linker.  This can be
+used to export symbols from a ``.dll`` that are not in any of its object
+files but are added by the linker from dependencies (e.g. ``msvcrt.lib``).
+
 This property is initialized by the value of
 the :variable:`CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS` variable if it is set
 when a target is created.
diff --git a/Help/release/3.9.rst b/Help/release/3.9.rst
new file mode 100644
index 0000000..14e8699
--- /dev/null
+++ b/Help/release/3.9.rst
@@ -0,0 +1,328 @@
+CMake 3.9 Release Notes
+***********************
+
+.. only:: html
+
+  .. contents::
+
+Changes made since CMake 3.8 include the following.
+
+New Features
+============
+
+Languages
+---------
+
+* ``CUDA`` is now supported by the :ref:`Visual Studio Generators`
+  for VS 2010 and above.  This complements the existing support by the
+  :ref:`Makefile Generators` and the :generator:`Ninja` generator.
+  CUDA 8.0.61 or higher is recommended due to known bugs in the VS
+  integration by earlier versions.
+
+* CMake is now aware of the :prop_tgt:`C++ standards <CXX_STANDARD>` and
+  :prop_tgt:`C standards <C_STANDARD>` and their associated meta-features for
+  the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>`: ``Cray``,
+  ``PGI``, and ``XL``.
+
+Generators
+----------
+
+* :ref:`Visual Studio Generators` for VS 2010 and above learned to support
+  the ``ASM_NASM`` language when ``nasm`` is installed.
+
+* The :generator:`Xcode` generator learned to create Xcode schema files.
+  This is an experimental feature and can be activated by setting the
+  :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable to a ``TRUE`` value.
+
+* The :generator:`Xcode` generator now supports Xcode 9.
+
+Commands
+--------
+
+* The :command:`add_library` command ``IMPORTED`` option learned to support
+  :ref:`Object Libraries`.
+
+* All ``find_`` commands now have a ``PACKAGE_ROOT`` search path group that
+  is first in the search heuristics.  If a ``find_`` command is called from
+  inside a find module, then the CMake variable and environment variable named
+  ``<PackageName>_ROOT`` are used as prefixes and are the first set of paths
+  to be searched.
+
+* The :command:`find_library` command learned to search ``libx32`` paths
+  when the build targets the ``x32`` ABI.  See the
+  :prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS` global property.
+
+* The :command:`include_external_msproject` command learned to use
+  the :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` target property
+  to map current configurations to the external configurations.
+
+* The :command:`install(TARGETS)` command learned a new ``OBJECTS`` option to
+  specify where to install :ref:`Object Libraries`.
+
+* The :command:`install(EXPORT)` command learned how to export
+  :ref:`Object Libraries`.
+
+* The :command:`project` command learned an optional ``DESCRIPTION``
+  parameter to set the :variable:`PROJECT_DESCRIPTION` variable.
+
+* The :command:`separate_arguments` command gained a ``NATIVE_COMMAND`` mode
+  that performs argument separation depending on the host operating system.
+
+Variables
+---------
+
+* A :variable:`CMAKE_ANDROID_NDK_DEPRECATED_HEADERS` variable was added
+  for use when :ref:`Cross Compiling for Android with the NDK` to request
+  use of the deprecated headers even when unified headers are available.
+  The default is now to use unified headers if available.
+
+* A :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` variable was introduced to
+  allow :variable:`CMAKE_AUTOMOC` to extract additional dependency file names
+  for ``moc`` from the contents of source files.
+
+* A :variable:`CMAKE_AUTOUIC_SEARCH_PATHS` variable was introduced to
+  allow :variable:`CMAKE_AUTOUIC` to search for ``foo.ui`` in more
+  places than the vicinity of the file including ``ui_foo.h``.
+
+* A :variable:`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variable was added to
+  tell the :command:`find_library` command to search in a ``lib<suffix>``
+  directory before each ``lib`` directory that would normally be searched.
+
+* A :variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable was added to
+  initialize the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` property on all
+  targets.
+
+* A :variable:`CMAKE_<LANG>_COMPILER_AR` variable was added to hold
+  the path to the GCC/Clang wrapper of ``ar``.
+
+* A :variable:`CMAKE_<LANG>_COMPILER_RANLIB` variable was added to hold
+  the path to the GCC/Clang wrapper of ``ranlib``.
+
+* The :variable:`CMAKE_SYSROOT_COMPILE` and :variable:`CMAKE_SYSROOT_LINK`
+  variables were added to use separate sysroots for compiling and linking.
+
+Properties
+----------
+
+* A new :prop_tgt:`AUTOGEN_BUILD_DIR` target property was introduced to set
+  a custom output directory for :prop_tgt:`AUTOMOC`, :prop_tgt:`AUTOUIC`,
+  and :prop_tgt:`AUTORCC`.
+
+* A new :prop_tgt:`AUTOMOC_DEPEND_FILTERS` target property was introduced to
+  allow :prop_tgt:`AUTOMOC` to extract additional dependency file names
+  for ``moc`` from the contents of source files.
+
+* A new :prop_tgt:`AUTOUIC_SEARCH_PATHS` target property was introduced to
+  allow :prop_tgt:`AUTOUIC` to search for ``foo.ui`` in more
+  places than the vicinity of the file including ``ui_foo.h``.
+
+* Global properties :prop_gbl:`AUTOGEN_SOURCE_GROUP`,
+  :prop_gbl:`AUTOMOC_SOURCE_GROUP` and
+  :prop_gbl:`AUTORCC_SOURCE_GROUP` were
+  introduced to allow files generated by :prop_tgt:`AUTOMOC` or
+  :prop_tgt:`AUTORCC` to be placed in a :command:`source_group`.
+
+* A :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target property and corresponding
+  :variable:`CMAKE_BUILD_WITH_INSTALL_NAME_DIR` variable were added to
+  control whether to use the :prop_tgt:`INSTALL_NAME_DIR` target property
+  value for binaries in the build tree.  This is for macOS ``install_name``
+  as :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is for ``RPATH``.
+
+* A :prop_tgt:`CUDA_PTX_COMPILATION` target property was added to
+  :ref:`Object Libraries` to support compiling to ``.ptx`` files
+  instead of host object files.
+
+* A :prop_gbl:`GENERATOR_IS_MULTI_CONFIG` global property was
+  added to determine whether the current generator is a multi-configuration
+  generator (such as :ref:`Visual Studio Generators` or :generator:`Xcode`).
+
+* The :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property is now enforced
+  when enabled.  CMake will add IPO flags unconditionally or produce an error
+  if it does not know the flags for the current compiler.  The project is now
+  responsible to use the :module:`CheckIPOSupported` module to check for IPO
+  support before enabling the target property.  See policy :policy:`CMP0069`.
+
+* The :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property may now
+  be used in combination with explicit ``.def`` files in order to
+  export all symbols from the object files within a target plus
+  an explicit list of symbols that the linker finds in dependencies
+  (e.g. ``msvcrt.lib``).
+
+Modules
+-------
+
+* A :module:`CheckIPOSupported` module was added to help projects
+  check whether interprocedural optimization (IPO) is supported by
+  the current toolchain and CMake version.
+
+* The :module:`CMakeFindDependencyMacro` module ``find_dependency`` macro
+  now forwards all arguments to the underlying :command:`find_package`
+  call.  Existing uses will continue to function as before, but callers can
+  now access the full suite of arguments that ``find_package`` accepts.
+
+* The :module:`FeatureSummary` module :command:`feature_summary` command now
+  accepts the new ``DEFAULT_DESCRIPTION`` option that will print the default
+  title for the selected package type.
+
+* The :module:`FeatureSummary` module gained a new
+  :variable:`FeatureSummary_<TYPE>_DESCRIPTION` variable that can be defined
+  for each ``<TYPE>`` to replace the type name with the specified string
+  whenever the package type is used in an output string by the module.
+
+* The :module:`FindDoxygen` module learned to control Doxygen behavior using
+  CMake variables and generate documentation via the newly added
+  :command:`doxygen_add_docs` function. The Doxygen input file (``Doxyfile``)
+  is automatically generated and doxygen is run as part of a custom target.
+  Additional components can be specified to find optional tools: ``dot``,
+  ``mscgen`` and ``dia``.
+
+* The :module:`FindMPI` module now provides imported targets.
+
+* The :module:`FindProtobuf` module :command:`protobuf_generate_cpp`
+  command gained an ``EXPORT_MACRO`` option to specify the name of
+  a DLL export markup macro.
+
+* The :module:`FindProtobuf` module now supports usage of static libraries
+  for Unix via a new ``Protobuf_USE_STATIC_LIBS`` input variable.
+
+* The :module:`FindProtobuf` module now provides imported targets
+  when the libraries are found.
+
+* A new :module:`GoogleTest` module was added to provide the
+  :command:`gtest_add_tests` function independently of the :module:`FindGTest`
+  module. The function was also updated to support keyword arguments, with
+  functionality expanded to allow a test name prefix and suffix to be
+  specified, the dependency on the source files to be optional and the list of
+  discovered test cases to be returned to the caller.
+
+CTest
+-----
+
+* The :command:`ctest_submit` command gained a ``HTTPHEADER`` option
+  to specify custom headers to send during submission.
+
+* The :manual:`ctest(1)` executable gained new options which allow the
+  developer to disable automatically adding tests to the test set to satisfy
+  fixture dependencies. ``-FS`` prevents adding setup tests for fixtures
+  matching the provided regular expression, ``-FC`` prevents adding cleanup
+  tests for matching fixtures and ``-FA`` prevents adding any test for matching
+  fixtures.
+
+* A :prop_test:`DISABLED` test property was added to mark tests that
+  are configured but explicitly disabled so they do not run.
+
+CPack
+-----
+
+* The :module:`CPackArchive` module learned to modify the filename
+  per-component.  See the :variable:`CPACK_ARCHIVE_FILE_NAME` variable and
+  its per-component version :variable:`CPACK_ARCHIVE_<component>_FILE_NAME`.
+
+* The :module:`CPackComponent` module :command:`cpack_add_component` command
+  gained a new ``PLIST <filename>`` option to specify the ``pkgbuild``
+  ``--component-plist`` argument when using the
+  :module:`productbuild <CPackProductBuild>` generator.
+
+* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` and
+  :command:`cpack_ifw_configure_component_group` commands gained
+  internationalization support for ``DISPLAY_NAME`` and ``DESCRIPTION``
+  options.
+
+* The :module:`CPackIFW` module learned the new hint :variable:`CPACK_IFW_ROOT`
+  variable for finding the QtIFW tool suite installed in a non-standard place.
+
+* The :module:`CPackProductBuild` module gained a new
+  :variable:`CPACK_PRODUCTBUILD_RESOURCES_DIR` variable to
+  specify resources to be copied into the ``Resources``
+  directory.
+
+* The :module:`CPackRPM` module learned to modify the ``debuginfo`` package
+  name.  See the :variable:`CPACK_RPM_DEBUGINFO_FILE_NAME` variable.
+
+* The :module:`CPackWIX` module patching system now has the ability to set
+  additional attributes.  This can be done by specifying attributes with
+  the ``CPackWiXFragment`` XML tag after the ``Id`` attribute.
+  See the :variable:`CPACK_WIX_PATCH_FILE` variable.
+
+* The CPack WIX generator implemented a new
+  :variable:`CPACK_WIX_ROOT_FOLDER_ID` variable which allows
+  using a custom root folder ID instead of the default
+  ``ProgramFilesFolder`` / ``ProgramFiles64Folder``.
+
+Other
+-----
+
+* Interprocedural optimization (IPO) is now supported for GNU and Clang
+  compilers using link time optimization (LTO) flags.  See the
+  :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property and
+  :module:`CheckIPOSupported` module.
+
+* The ``TARGET_OBJECTS``
+  :manual:`generator expression <cmake-generator-expressions(7)>`
+  is now supported by the :command:`add_custom_command` and
+  :command:`file(GENERATE)` commands.
+
+* Two new informational generator expressions to retrieve Apple Bundle
+  directories have been added. The first one ``$<TARGET_BUNDLE_DIR:tgt>``
+  outputs the full path to the Bundle directory, the other one
+  ``$<TARGET_BUNDLE_CONTENT_DIR:tgt>`` outputs the full path to the
+  ``Contents`` directory of macOS Bundles and App Bundles. For all other
+  bundle types and SDKs it is identical with ``$<TARGET_BUNDLE_DIR:tgt>``.
+  The new expressions are helpful to query Bundle locations independent of
+  the different Bundle types and layouts on macOS and iOS.
+
+Deprecated and Removed Features
+===============================
+
+* An explicit deprecation diagnostic was added for policies ``CMP0036``
+  and below.  The :manual:`cmake-policies(7)` manual explains that the
+  OLD behaviors of all policies are deprecated and that projects should
+  always port to the NEW behaviors as soon as possible.
+
+* The :generator:`Visual Studio 8 2005` generator is now deprecated
+  and will be removed in a future version of CMake.
+
+* The :generator:`Visual Studio 7 .NET 2003` generator has been removed.
+
+* The :generator:`Xcode` generator dropped support for Xcode versions
+  older than 3.
+
+* The :module:`FindDoxygen` module has deprecated several variables.
+
+* The version of curl bundled with CMake no longer accepts URLs of the form
+  ``file://c:/...`` on Windows due to a change in upstream curl 7.52.  Use
+  the form ``file:///c:/...`` instead to work on all versions.
+
+Other Changes
+=============
+
+* When using :prop_tgt:`AUTOMOC`, CMake now scans for the presence of the
+  ``Q_PLUGIN_METADATA`` macro and reruns moc when the file from the
+  macro's ``FILE`` argument changes.
+
+* When :prop_tgt:`AUTOMOC` detects an include statement of the form
+  ``#include "moc_<basename>.cpp"`` the search for the respective header file
+  now looks in the :prop_tgt:`INCLUDE_DIRECTORIES` of the target as well.
+
+* When running tests, CTest learned to treat skipped tests (using the
+  :prop_test:`SKIP_RETURN_CODE` property) the same as tests with the new
+  :prop_test:`DISABLED` property. Due to this change, CTest will not indicate
+  failure when all tests are either skipped or pass.
+
+* The :generator:`Ninja` generator has loosened the dependencies of object
+  compilation.  Object compilation now depends only on custom targets
+  and custom commands associated with libraries on which the object's target
+  depends and no longer depends on the libraries themselves.  Source files
+  in dependent targets may now compile without waiting for their targets'
+  dependencies to link.
+
+* On macOS, the default application bundle ``Info.plist`` file now enables
+  Hi-DPI support.
+
+* On macOS, ``RPATH`` settings such as :prop_tgt:`BUILD_WITH_INSTALL_RPATH`
+  no longer affect the ``install_name`` field.  See policy :policy:`CMP0068`.
+
+* The :generator:`Visual Studio 14 2015` generator has been taught about
+  a change to the ``v140`` toolset made by a VS 2015 update.  VS changed
+  the set of values it understands for the ``GenerateDebugInformation``
+  linker setting that produces the ``-DEBUG`` linker flag variants.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 8f0f252..8222d0c 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -11,6 +11,7 @@ Releases
 .. toctree::
    :maxdepth: 1
 
+   3.9 <3.9>
    3.8 <3.8>
    3.7 <3.7>
    3.6 <3.6>
diff --git a/Help/variable/CMAKE_ANDROID_NDK_DEPRECATED_HEADERS.rst b/Help/variable/CMAKE_ANDROID_NDK_DEPRECATED_HEADERS.rst
new file mode 100644
index 0000000..8ea1257
--- /dev/null
+++ b/Help/variable/CMAKE_ANDROID_NDK_DEPRECATED_HEADERS.rst
@@ -0,0 +1,9 @@
+CMAKE_ANDROID_NDK_DEPRECATED_HEADERS
+------------------------------------
+
+When :ref:`Cross Compiling for Android with the NDK`, this variable
+may be set to specify whether to use the deprecated per-api-level
+headers instead of the unified headers.
+
+If not specified, the default will be *false* if using a NDK version
+that provides the unified headers and *true* otherwise.
diff --git a/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst b/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst
new file mode 100644
index 0000000..5c3662d
--- /dev/null
+++ b/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst
@@ -0,0 +1,12 @@
+CMAKE_AUTOMOC_DEPEND_FILTERS
+----------------------------
+
+Filter definitions used by :variable:`CMAKE_AUTOMOC`
+to extract file names from source code as additional dependencies
+for the ``moc`` file.
+
+This variable is used to initialize the :prop_tgt:`AUTOMOC_DEPEND_FILTERS`
+property on all the targets. See that target property for additional
+information.
+
+By default it is empty.
diff --git a/Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst b/Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst
new file mode 100644
index 0000000..aa132bf
--- /dev/null
+++ b/Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst
@@ -0,0 +1,11 @@
+CMAKE_AUTOUIC_SEARCH_PATHS
+--------------------------
+
+Search path list used by :variable:`CMAKE_AUTOUIC` to find included
+``.ui`` files.
+
+This variable is used to initialize the :prop_tgt:`AUTOUIC_SEARCH_PATHS`
+property on all the targets. See that target property for additional
+information.
+
+By default it is empty.
diff --git a/Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst b/Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst
new file mode 100644
index 0000000..30d5d3b
--- /dev/null
+++ b/Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst
@@ -0,0 +1,7 @@
+CMAKE_BUILD_WITH_INSTALL_NAME_DIR
+---------------------------------
+
+Whether to use :prop_tgt:`INSTALL_NAME_DIR` on targets in the build tree.
+
+This variable is used to initialize the :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR`
+property on all targets.
diff --git a/Help/variable/CMAKE_CFG_INTDIR.rst b/Help/variable/CMAKE_CFG_INTDIR.rst
index ba25a35..c36599a 100644
--- a/Help/variable/CMAKE_CFG_INTDIR.rst
+++ b/Help/variable/CMAKE_CFG_INTDIR.rst
@@ -12,7 +12,7 @@ Example values:
 
 ::
 
-  $(ConfigurationName) = Visual Studio 7, 8, 9
+  $(ConfigurationName) = Visual Studio 8, 9
   $(Configuration)     = Visual Studio 10
   $(CONFIGURATION)     = Xcode
   .                    = Make-based tools
diff --git a/Help/variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX.rst b/Help/variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX.rst
new file mode 100644
index 0000000..ada8955
--- /dev/null
+++ b/Help/variable/CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX.rst
@@ -0,0 +1,12 @@
+CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX
+------------------------------------
+
+Specify a ``<suffix>`` to tell the :command:`find_library` command to
+search in a ``lib<suffix>`` directory before each ``lib`` directory that
+would normally be searched.
+
+This overrides the behavior of related global properties:
+
+* :prop_gbl:`FIND_LIBRARY_USE_LIB32_PATHS`
+* :prop_gbl:`FIND_LIBRARY_USE_LIB64_PATHS`
+* :prop_gbl:`FIND_LIBRARY_USE_LIBX32_PATHS`
diff --git a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst
index a5c284a..50412ff 100644
--- a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst
+++ b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst
@@ -1,7 +1,7 @@
 CMAKE_GENERATOR_PLATFORM
 ------------------------
 
-Generator-specific target platform name specified by user.
+Generator-specific target platform specification provided by user.
 
 Some CMake generators support a target platform name to be given
 to the native build system to choose a compiler toolchain.
@@ -13,3 +13,16 @@ A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE`
 variable may initialize ``CMAKE_GENERATOR_PLATFORM``.  Once a given
 build tree has been initialized with a particular value for this
 variable, changing the value has undefined behavior.
+
+Platform specification is supported only on specific generators:
+
+* For :ref:`Visual Studio Generators` with VS 2005 and above this
+  specifies the target architecture.
+
+See native build system documentation for allowed platform names.
+
+Visual Studio Platform Selection
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+On :ref:`Visual Studio Generators` the selected platform name
+is provided in the :variable:`CMAKE_VS_PLATFORM_NAME` variable.
diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst
index 89abe54..11c37d7 100644
--- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst
+++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst
@@ -1,15 +1,50 @@
 CMAKE_GENERATOR_TOOLSET
 -----------------------
 
-Native build system toolset name specified by user.
+Native build system toolset specification provided by user.
 
-Some CMake generators support a toolset name to be given to the native
-build system to choose a compiler.  If the user specifies a toolset
-name (e.g.  via the :manual:`cmake(1)` ``-T`` option) the value will be
-available in this variable.
+Some CMake generators support a toolset specification to tell the
+native build system how to choose a compiler.  If the user specifies
+a toolset (e.g.  via the :manual:`cmake(1)` ``-T`` option) the value
+will be available in this variable.
 
 The value of this variable should never be modified by project code.
 A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE`
 variable may initialize ``CMAKE_GENERATOR_TOOLSET``.  Once a given
 build tree has been initialized with a particular value for this
 variable, changing the value has undefined behavior.
+
+Toolset specification is supported only on specific generators:
+
+* :ref:`Visual Studio Generators` for VS 2010 and above
+* The :generator:`Xcode` generator for Xcode 3.0 and above
+
+See native build system documentation for allowed toolset names.
+
+Visual Studio Toolset Selection
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The :ref:`Visual Studio Generators` support toolset specification
+using one of these forms:
+
+* ``toolset``
+* ``toolset[,key=value]*``
+* ``key=value[,key=value]*``
+
+The ``toolset`` specifies the toolset name.  The selected toolset name
+is provided in the :variable:`CMAKE_VS_PLATFORM_TOOLSET` variable.
+
+The ``key=value`` pairs form a comma-separated list of options to
+specify generator-specific details of the toolset selection.
+Supported pairs are:
+
+``cuda=<version>``
+  Specify the CUDA toolkit version to use.  Supported by VS 2010
+  and above with the CUDA toolkit VS integration installed.
+  See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_CUDA` variable.
+
+``host=x64``
+  Request use of the native ``x64`` toolchain on ``x64`` hosts.
+  Supported by VS 2013 and above.
+  See the :variable:`CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE`
+  variable.
diff --git a/Help/variable/CMAKE_HOST_WIN32.rst b/Help/variable/CMAKE_HOST_WIN32.rst
index 0e4c891..876b34c 100644
--- a/Help/variable/CMAKE_HOST_WIN32.rst
+++ b/Help/variable/CMAKE_HOST_WIN32.rst
@@ -1,6 +1,6 @@
 CMAKE_HOST_WIN32
 ----------------
 
-``True`` on Windows systems, including Win64.
+``True`` if the host system is running Windows, including Windows 64-bit and MSYS.
 
-Set to ``true`` when the host system is Windows and on Cygwin.
+Set to ``false`` on Cygwin.
diff --git a/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst
new file mode 100644
index 0000000..b0cbb62
--- /dev/null
+++ b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst
@@ -0,0 +1,8 @@
+CMAKE_INTERPROCEDURAL_OPTIMIZATION
+----------------------------------
+
+Default value for :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` of targets.
+
+This variable is used to initialize the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION`
+property on all the targets.  See that target property for additional
+information.
diff --git a/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst
new file mode 100644
index 0000000..b291102
--- /dev/null
+++ b/Help/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst
@@ -0,0 +1,8 @@
+CMAKE_INTERPROCEDURAL_OPTIMIZATION_<CONFIG>
+-------------------------------------------
+
+Default value for :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION_<CONFIG>` of targets.
+
+This variable is used to initialize the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION_<CONFIG>`
+property on all the targets.  See that target property for additional
+information.
diff --git a/Help/variable/CMAKE_LANG_COMPILER_AR.rst b/Help/variable/CMAKE_LANG_COMPILER_AR.rst
new file mode 100644
index 0000000..b83a1d4
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_COMPILER_AR.rst
@@ -0,0 +1,7 @@
+CMAKE_<LANG>_COMPILER_AR
+------------------------
+
+A wrapper around ``ar`` adding the appropriate ``--plugin`` option for the
+compiler.
+
+See also :variable:`CMAKE_AR`.
diff --git a/Help/variable/CMAKE_LANG_COMPILER_RANLIB.rst b/Help/variable/CMAKE_LANG_COMPILER_RANLIB.rst
new file mode 100644
index 0000000..945160b
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_COMPILER_RANLIB.rst
@@ -0,0 +1,7 @@
+CMAKE_<LANG>_COMPILER_RANLIB
+----------------------------
+
+A wrapper around ``ranlib`` adding the appropriate ``--plugin`` option for the
+compiler.
+
+See also :variable:`CMAKE_RANLIB`.
diff --git a/Help/variable/CMAKE_LANG_COMPILER_VERSION.rst b/Help/variable/CMAKE_LANG_COMPILER_VERSION.rst
index 50e77eb..27b0cad 100644
--- a/Help/variable/CMAKE_LANG_COMPILER_VERSION.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER_VERSION.rst
@@ -6,3 +6,7 @@ Compiler version string.
 Compiler version in major[.minor[.patch[.tweak]]] format.  This
 variable is not guaranteed to be defined for all compilers or
 languages.
+
+For example ``CMAKE_C_COMPILER_VERSION`` and
+``CMAKE_CXX_COMPILER_VERSION`` might indicate the respective C and C++
+compiler version.
diff --git a/Help/variable/CMAKE_MATCH_COUNT.rst b/Help/variable/CMAKE_MATCH_COUNT.rst
index 8b1c036..355e834 100644
--- a/Help/variable/CMAKE_MATCH_COUNT.rst
+++ b/Help/variable/CMAKE_MATCH_COUNT.rst
@@ -3,6 +3,7 @@ CMAKE_MATCH_COUNT
 
 The number of matches with the last regular expression.
 
-When a regular expression match is used, CMake fills in ``CMAKE_MATCH_<n>``
-variables with the match contents. The ``CMAKE_MATCH_COUNT`` variable holds
-the number of match expressions when these are filled.
+When a regular expression match is used, CMake fills in
+:variable:`CMAKE_MATCH_<n>` variables with the match contents.
+The ``CMAKE_MATCH_COUNT`` variable holds the number of match
+expressions when these are filled.
diff --git a/Help/variable/CMAKE_MATCH_n.rst b/Help/variable/CMAKE_MATCH_n.rst
new file mode 100644
index 0000000..c7dd623
--- /dev/null
+++ b/Help/variable/CMAKE_MATCH_n.rst
@@ -0,0 +1,10 @@
+CMAKE_MATCH_<n>
+---------------
+
+Capture group ``<n>`` matched by the last regular expression, for groups
+0 through 9.  Group 0 is the entire match.  Groups 1 through 9 are the
+subexpressions captured by ``()`` syntax.
+
+When a regular expression match is used, CMake fills in ``CMAKE_MATCH_<n>``
+variables with the match contents.  The :variable:`CMAKE_MATCH_COUNT`
+variable holds the number of match expressions when these are filled.
diff --git a/Help/variable/CMAKE_MFC_FLAG.rst b/Help/variable/CMAKE_MFC_FLAG.rst
index 1543677..5a392bf 100644
--- a/Help/variable/CMAKE_MFC_FLAG.rst
+++ b/Help/variable/CMAKE_MFC_FLAG.rst
@@ -5,7 +5,7 @@ Tell cmake to use MFC for an executable or dll.
 
 This can be set in a ``CMakeLists.txt`` file and will enable MFC in the
 application.  It should be set to ``1`` for the static MFC library, and ``2``
-for the shared MFC library.  This is used in Visual Studio 7
+for the shared MFC library.  This is used in Visual Studio
 project files.  The CMakeSetup dialog used MFC and the ``CMakeLists.txt``
 looks like this:
 
diff --git a/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst b/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst
new file mode 100644
index 0000000..f1911ec
--- /dev/null
+++ b/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst
@@ -0,0 +1,7 @@
+CMAKE_PROJECT_DESCRIPTION
+-------------------------
+
+The description of the current project.
+
+This specifies description of the current project from the closest inherited
+:command:`project` command.
diff --git a/Help/variable/CMAKE_SYSROOT.rst b/Help/variable/CMAKE_SYSROOT.rst
index 7aa0450..64f81bb 100644
--- a/Help/variable/CMAKE_SYSROOT.rst
+++ b/Help/variable/CMAKE_SYSROOT.rst
@@ -10,3 +10,6 @@ paths searched by the ``find_*`` commands.
 
 This variable may only be set in a toolchain file specified by
 the :variable:`CMAKE_TOOLCHAIN_FILE` variable.
+
+See also the :variable:`CMAKE_SYSROOT_COMPILE` and
+:variable:`CMAKE_SYSROOT_LINK` variables.
diff --git a/Help/variable/CMAKE_SYSROOT_COMPILE.rst b/Help/variable/CMAKE_SYSROOT_COMPILE.rst
new file mode 100644
index 0000000..e96c62b
--- /dev/null
+++ b/Help/variable/CMAKE_SYSROOT_COMPILE.rst
@@ -0,0 +1,9 @@
+CMAKE_SYSROOT_COMPILE
+---------------------
+
+Path to pass to the compiler in the ``--sysroot`` flag when compiling source
+files.  This is the same as :variable:`CMAKE_SYSROOT` but is used only for
+compiling sources and not linking.
+
+This variable may only be set in a toolchain file specified by
+the :variable:`CMAKE_TOOLCHAIN_FILE` variable.
diff --git a/Help/variable/CMAKE_SYSROOT_LINK.rst b/Help/variable/CMAKE_SYSROOT_LINK.rst
new file mode 100644
index 0000000..88b48ef
--- /dev/null
+++ b/Help/variable/CMAKE_SYSROOT_LINK.rst
@@ -0,0 +1,9 @@
+CMAKE_SYSROOT_LINK
+------------------
+
+Path to pass to the compiler in the ``--sysroot`` flag when linking.  This is
+the same as :variable:`CMAKE_SYSROOT` but is used only for linking and not
+compiling sources.
+
+This variable may only be set in a toolchain file specified by
+the :variable:`CMAKE_TOOLCHAIN_FILE` variable.
diff --git a/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst b/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst
index 14cc50a..51b42dd 100644
--- a/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst
+++ b/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst
@@ -1,7 +1,7 @@
 CMAKE_VS_DEVENV_COMMAND
 -----------------------
 
-The generators for :generator:`Visual Studio 7` and above set this
+The generators for :generator:`Visual Studio 8 2005` and above set this
 variable to the ``devenv.com`` command installed with the corresponding
 Visual Studio version.  Note that this variable may be empty on
 Visual Studio Express editions because they do not provide this tool.
diff --git a/Help/variable/CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst b/Help/variable/CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst
index 0be10e5..6d196f9 100644
--- a/Help/variable/CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst
+++ b/Help/variable/CMAKE_VS_INTEL_Fortran_PROJECT_VERSION.rst
@@ -1,7 +1,7 @@
 CMAKE_VS_INTEL_Fortran_PROJECT_VERSION
 --------------------------------------
 
-When generating for :generator:`Visual Studio 7` or greater with the Intel
+When generating for :generator:`Visual Studio 8 2005` or greater with the Intel
 Fortran plugin installed, this specifies the ``.vfproj`` project file format
 version.  This is intended for internal use by CMake and should not be
 used by project code.
diff --git a/Help/variable/CMAKE_VS_PLATFORM_NAME.rst b/Help/variable/CMAKE_VS_PLATFORM_NAME.rst
index c6f8d41..a532743 100644
--- a/Help/variable/CMAKE_VS_PLATFORM_NAME.rst
+++ b/Help/variable/CMAKE_VS_PLATFORM_NAME.rst
@@ -5,3 +5,4 @@ Visual Studio target platform name.
 
 VS 8 and above allow project files to specify a target platform.
 CMake provides the name of the chosen platform in this variable.
+See the :variable:`CMAKE_GENERATOR_PLATFORM` variable for details.
diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst
index 144a41d..ed2d3f3 100644
--- a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst
+++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET.rst
@@ -8,3 +8,5 @@ compiler toolchains.  CMake may specify a toolset explicitly, such as
 ``v110`` for VS 11 or ``Windows7.1SDK`` for 64-bit support in VS 10
 Express.  CMake provides the name of the chosen toolset in this
 variable.
+
+See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details.
diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst
new file mode 100644
index 0000000..1604a76
--- /dev/null
+++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst
@@ -0,0 +1,12 @@
+CMAKE_VS_PLATFORM_TOOLSET_CUDA
+------------------------------
+
+NVIDIA CUDA Toolkit version whose Visual Studio toolset to use.
+
+The :ref:`Visual Studio Generators` for VS 2010 and above support using
+a CUDA toolset provided by a CUDA Toolkit.  The toolset version number
+may be specified by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of
+the form ``cuda=8.0``.  If none is specified CMake will choose a default
+version.  CMake provides the selected CUDA toolset version in this variable.
+The value may be empty if no CUDA Toolkit with Visual Studio integration
+is installed.
diff --git a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst
index e0be3a4..83b9bc1 100644
--- a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst
+++ b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst
@@ -10,3 +10,8 @@ version.  Otherwise CMake computes a default version based on the Windows
 SDK versions available.  The chosen Windows target version number is provided
 in ``CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION``.  If no Windows 10 SDK
 is available this value will be empty.
+
+One may set a ``CMAKE_WINDOWS_KITS_10_DIR`` *environment variable*
+to an absolute path to tell CMake to look for Windows 10 SDKs in
+a custom location.  The specified directory is expected to contain
+``Include/10.0.*`` directories.
diff --git a/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst
new file mode 100644
index 0000000..c9fcc92
--- /dev/null
+++ b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst
@@ -0,0 +1,11 @@
+CMAKE_XCODE_GENERATE_SCHEME
+---------------------------
+
+If enabled, the Xcode generator will generate schema files. Those are
+are useful to invoke analyze, archive, build-for-testing and test
+actions from the command line.
+
+.. note::
+
+  The Xcode Schema Generator is still experimental and subject to
+  change.
diff --git a/Help/variable/PROJECT_DESCRIPTION.rst b/Help/variable/PROJECT_DESCRIPTION.rst
new file mode 100644
index 0000000..05ede8f
--- /dev/null
+++ b/Help/variable/PROJECT_DESCRIPTION.rst
@@ -0,0 +1,6 @@
+PROJECT_DESCRIPTION
+-------------------
+
+Short project description given to the project command.
+
+This is the description given to the most recent :command:`project` command.
diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 3fafaff..4e85474 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -1,25 +1,32 @@
-set(AM_SOURCES @_moc_uic_sources@)
-set(AM_HEADERS @_moc_uic_headers@)
-set(AM_SKIP_MOC @_skip_moc@)
-set(AM_SKIP_UIC @_skip_uic@)
-set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@)
-set(AM_MOC_INCLUDES @_moc_incs@)
-set(AM_MOC_OPTIONS @_moc_options@)
-set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@")
-set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@")
+# Directories and files
 set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
 set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/")
-set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@")
-set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@")
-set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@")
 set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
 set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
-set(AM_QT_VERSION_MAJOR "@_target_qt_version@")
-set(AM_TARGET_NAME @_moc_target_name@)
-set(AM_ORIGIN_TARGET_NAME @_origin_target_name@)
+set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@")
+set(AM_BUILD_DIR @_autogen_build_dir@)
+set(AM_SOURCES @_sources@)
+set(AM_HEADERS @_headers@)
+# Qt environment
+set(AM_QT_VERSION_MAJOR @_qt_version_major@)
+set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@)
+set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@)
+set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@)
+# MOC settings
+set(AM_MOC_SKIP @_moc_skip@)
+set(AM_MOC_DEFINITIONS @_moc_compile_defs@)
+set(AM_MOC_INCLUDES @_moc_incs@)
+set(AM_MOC_OPTIONS @_moc_options@)
+set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@)
+set(AM_MOC_DEPEND_FILTERS @_moc_depend_filters@)
+set(AM_MOC_PREDEFS_CMD @_moc_predefs_cmd@)
+# UIC settings
+set(AM_UIC_SKIP @_uic_skip@)
 set(AM_UIC_TARGET_OPTIONS @_uic_target_options@)
 set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@)
 set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@)
+set(AM_UIC_SEARCH_PATHS @_uic_search_paths@)
+# RCC settings
 set(AM_RCC_SOURCES @_rcc_files@ )
 set(AM_RCC_INPUTS @_rcc_inputs@)
 set(AM_RCC_OPTIONS_FILES @_rcc_options_files@)
diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake
index 5d6f402..121a8f0 100644
--- a/Modules/BundleUtilities.cmake
+++ b/Modules/BundleUtilities.cmake
@@ -432,6 +432,16 @@ function(get_item_rpaths item rpaths_var)
     endif()
   endif()
 
+  if(UNIX AND NOT APPLE)
+    file(READ_ELF ${item} RPATH rpath_var RUNPATH runpath_var CAPTURE_ERROR error_var)
+    get_filename_component(item_dir ${item} DIRECTORY)
+    foreach(rpath ${rpath_var} ${runpath_var})
+      # Substitute $ORIGIN with the exepath and add to the found rpaths
+      string(REPLACE "$ORIGIN" "${item_dir}" rpath "${rpath}")
+      gp_append_unique(${rpaths_var} "${rpath}")
+    endforeach()
+  endif()
+
   set(${rpaths_var} ${${rpaths_var}} PARENT_SCOPE)
 endfunction()
 
@@ -998,7 +1008,8 @@ function(verify_bundle_prerequisites bundle result_var info_var)
       endif()
 
       if(NOT ignoreFile)
-        get_prerequisites("${f}" prereqs 1 1 "${exepath}" "")
+        get_item_rpaths(${f} _main_exe_rpaths)
+        get_prerequisites("${f}" prereqs 1 1 "${exepath}" "${_main_exe_rpaths}")
 
         # On the Mac,
         # "embedded" and "system" prerequisites are fine... anything else means
diff --git a/Modules/CMakeASMCompiler.cmake.in b/Modules/CMakeASMCompiler.cmake.in
index 8e58307..7b94d0f 100644
--- a/Modules/CMakeASMCompiler.cmake.in
+++ b/Modules/CMakeASMCompiler.cmake.in
@@ -1,7 +1,9 @@
 set(CMAKE_ASM at ASM_DIALECT@_COMPILER "@_CMAKE_ASM_COMPILER@")
 set(CMAKE_ASM at ASM_DIALECT@_COMPILER_ARG1 "@_CMAKE_ASM_COMPILER_ARG1@")
 set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_ASM at ASM_DIALECT@_COMPILER_AR "@_CMAKE_ASM_COMPILER_AR@")
 set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_ASM at ASM_DIALECT@_COMPILER_RANLIB "@_CMAKE_ASM_COMPILER_RANLIB@")
 set(CMAKE_LINKER "@CMAKE_LINKER@")
 set(CMAKE_ASM at ASM_DIALECT@_COMPILER_LOADED 1)
 set(CMAKE_ASM at ASM_DIALECT@_COMPILER_ID "@_CMAKE_ASM_COMPILER_ID@")
diff --git a/Modules/CMakeASMInformation.cmake b/Modules/CMakeASMInformation.cmake
index 01355ff..f7cf900 100644
--- a/Modules/CMakeASMInformation.cmake
+++ b/Modules/CMakeASMInformation.cmake
@@ -75,11 +75,13 @@ set (CMAKE_ASM${ASM_DIALECT}_FLAGS "${CMAKE_ASM${ASM_DIALECT}_FLAGS_INIT}" CACHE
      "Flags used by the assembler during all build types.")
 
 if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
-# default build type is none
-  if(NOT CMAKE_NO_BUILD_TYPE)
+  get_property(_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+  # default build type is none
+  if(NOT _GENERATOR_IS_MULTI_CONFIG AND NOT CMAKE_NO_BUILD_TYPE)
     set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING
       "Choose the type of build, options are: None, Debug Release RelWithDebInfo MinSizeRel.")
   endif()
+  unset(_GENERATOR_IS_MULTI_CONFIG)
   set (CMAKE_ASM${ASM_DIALECT}_FLAGS_DEBUG "${CMAKE_ASM${ASM_DIALECT}_FLAGS_DEBUG_INIT}" CACHE STRING
     "Flags used by the assembler during debug builds.")
   set (CMAKE_ASM${ASM_DIALECT}_FLAGS_MINSIZEREL "${CMAKE_ASM${ASM_DIALECT}_FLAGS_MINSIZEREL_INIT}" CACHE STRING
diff --git a/Modules/CMakeBackwardCompatibilityC.cmake b/Modules/CMakeBackwardCompatibilityC.cmake
index 228e063..5d86d73 100644
--- a/Modules/CMakeBackwardCompatibilityC.cmake
+++ b/Modules/CMakeBackwardCompatibilityC.cmake
@@ -2,12 +2,6 @@
 # file Copyright.txt or https://cmake.org/licensing for details.
 
 
-# Nothing here yet
-if(CMAKE_GENERATOR MATCHES "Visual Studio 7")
-  include(CMakeVS7BackwardCompatibility)
-  set(CMAKE_SKIP_COMPATIBILITY_TESTS 1)
-endif()
-
 if(NOT CMAKE_SKIP_COMPATIBILITY_TESTS)
   # Old CMake versions did not support OS X universal binaries anyway,
   # so just get through this with at least some size for the types.
diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in
index 50b12f2..974a579 100644
--- a/Modules/CMakeCCompiler.cmake.in
+++ b/Modules/CMakeCCompiler.cmake.in
@@ -13,8 +13,11 @@ set(CMAKE_C_PLATFORM_ID "@CMAKE_C_PLATFORM_ID@")
 set(CMAKE_C_SIMULATE_ID "@CMAKE_C_SIMULATE_ID@")
 set(CMAKE_C_SIMULATE_VERSION "@CMAKE_C_SIMULATE_VERSION@")
 @SET_MSVC_C_ARCHITECTURE_ID@
+ at SET_CMAKE_XCODE_CURRENT_ARCH@
 set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_C_COMPILER_AR "@CMAKE_C_COMPILER_AR@")
 set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_C_COMPILER_RANLIB "@CMAKE_C_COMPILER_RANLIB@")
 set(CMAKE_LINKER "@CMAKE_LINKER@")
 set(CMAKE_COMPILER_IS_GNUCC @CMAKE_COMPILER_IS_GNUCC@)
 set(CMAKE_C_COMPILER_LOADED 1)
diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake
index 709e316..71aadb4 100644
--- a/Modules/CMakeCInformation.cmake
+++ b/Modules/CMakeCInformation.cmake
@@ -110,11 +110,13 @@ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_INIT}" CACHE STRING
      "Flags used by the compiler during all build types.")
 
 if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
-# default build type is none
-  if(NOT CMAKE_NO_BUILD_TYPE)
+  get_property(_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+  # default build type is none
+  if(NOT _GENERATOR_IS_MULTI_CONFIG AND NOT CMAKE_NO_BUILD_TYPE)
     set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING
       "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
   endif()
+  unset(_GENERATOR_IS_MULTI_CONFIG)
   set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_INIT}" CACHE STRING
     "Flags used by the compiler during debug builds.")
   set (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL_INIT}" CACHE STRING
diff --git a/Modules/CMakeCSharpInformation.cmake b/Modules/CMakeCSharpInformation.cmake
index dc775bd..cd86016 100644
--- a/Modules/CMakeCSharpInformation.cmake
+++ b/Modules/CMakeCSharpInformation.cmake
@@ -68,38 +68,38 @@ if(CMAKE_CSharp_STANDARD_LIBRARIES_INIT)
   mark_as_advanced(CMAKE_CSharp_STANDARD_LIBRARIES)
 endif()
 
-# set missing flags (if they do not exist). This is needed in the
+# set missing flags (if they are not defined). This is needed in the
 # unlikely case that you have only C# and no C/C++ targets in your
 # project.
-if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS)
+if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS)
     set(CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "" FORCE)
 endif()
-if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_DEBUG)
+if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS_DEBUG)
     set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "" CACHE STRING "" FORCE)
 endif()
-if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_RELEASE)
+if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS_RELEASE)
     set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "" CACHE STRING "" FORCE)
 endif()
-if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL)
+if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL)
     set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "" CACHE STRING "" FORCE)
 endif()
-if(NOT EXISTS CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO)
+if(NOT DEFINED CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO)
     set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "" CACHE STRING "" FORCE)
 endif()
 
-if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS)
+if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS)
     set(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "" FORCE)
 endif()
-if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_DEBUG)
+if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS_DEBUG)
     set(CMAKE_EXE_LINKER_FLAGS_DEBUG "" CACHE STRING "" FORCE)
 endif()
-if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_RELEASE)
+if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS_RELEASE)
     set(CMAKE_EXE_LINKER_FLAGS_RELEASE "" CACHE STRING "" FORCE)
 endif()
-if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_MINSIZEREL)
+if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS_MINSIZEREL)
     set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "" CACHE STRING "" FORCE)
 endif()
-if(NOT EXISTS CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO)
+if(NOT DEFINED CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO)
     set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "" CACHE STRING "" FORCE)
 endif()
 
diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
index 1c48159..9bba847 100644
--- a/Modules/CMakeCUDAInformation.cmake
+++ b/Modules/CMakeCUDAInformation.cmake
@@ -104,7 +104,9 @@ include(CMakeCommonLanguageInclude)
 # now define the following rules:
 # CMAKE_CUDA_CREATE_SHARED_LIBRARY
 # CMAKE_CUDA_CREATE_SHARED_MODULE
-# CMAKE_CUDA_COMPILE_OBJECT
+# CMAKE_CUDA_COMPILE_WHOLE_COMPILATION
+# CMAKE_CUDA_COMPILE_PTX_COMPILATION
+# CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION
 # CMAKE_CUDA_LINK_EXECUTABLE
 
 if(CMAKE_CUDA_HOST_COMPILER)
@@ -186,16 +188,25 @@ if(NOT CMAKE_CUDA_LINK_EXECUTABLE)
     "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
 endif()
 
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0")
+  set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets")
+else()
+  set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
+endif()
+
+
 #These are used when linking relocatable (dc) cuda code
 if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY)
   set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
-    "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+    "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
 endif()
 if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE)
   set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
-    "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+    "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
 endif()
 
+unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
+
 mark_as_advanced(
 CMAKE_CUDA_FLAGS
 CMAKE_CUDA_FLAGS_RELEASE
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index 6d56488..fda7950 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -14,8 +14,11 @@ set(CMAKE_CXX_PLATFORM_ID "@CMAKE_CXX_PLATFORM_ID@")
 set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@")
 set(CMAKE_CXX_SIMULATE_VERSION "@CMAKE_CXX_SIMULATE_VERSION@")
 @SET_MSVC_CXX_ARCHITECTURE_ID@
+ at SET_CMAKE_XCODE_CURRENT_ARCH@
 set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_CXX_COMPILER_AR "@CMAKE_CXX_COMPILER_AR@")
 set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_CXX_COMPILER_RANLIB "@CMAKE_CXX_COMPILER_RANLIB@")
 set(CMAKE_LINKER "@CMAKE_LINKER@")
 set(CMAKE_COMPILER_IS_GNUCXX @CMAKE_COMPILER_IS_GNUCXX@)
 set(CMAKE_CXX_COMPILER_LOADED 1)
diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
index 1b5178d..e60ffe0 100644
--- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
+++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
@@ -22,6 +22,7 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR)
      FAIL_REGEX "[Ww]arning: [Oo]ption"                     # SunPro
      FAIL_REGEX "command option .* is not recognized"       # XL
      FAIL_REGEX "command option .* contains an incorrect subargument" # XL
+     FAIL_REGEX "Option .* is not recognized.  Option will be ignored." # XL
      FAIL_REGEX "not supported in this configuration. ignored"       # AIX
      FAIL_REGEX "File with unknown suffix passed to linker" # PGI
      FAIL_REGEX "[Uu]nknown switch"                         # PGI
diff --git a/Modules/CMakeCommonLanguageInclude.cmake b/Modules/CMakeCommonLanguageInclude.cmake
index 418860e..43b5da0 100644
--- a/Modules/CMakeCommonLanguageInclude.cmake
+++ b/Modules/CMakeCommonLanguageInclude.cmake
@@ -17,11 +17,13 @@ foreach(t EXE SHARED MODULE STATIC)
 endforeach()
 
 if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
-# default build type is none
-  if(NOT CMAKE_NO_BUILD_TYPE)
+  get_property(_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+  # default build type is none
+  if(NOT _GENERATOR_IS_MULTI_CONFIG AND NOT CMAKE_NO_BUILD_TYPE)
     set (CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING
       "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
   endif()
+  unset(_GENERATOR_IS_MULTI_CONFIG)
 
   set (CMAKE_EXE_LINKER_FLAGS_DEBUG ${CMAKE_EXE_LINKER_FLAGS_DEBUG_INIT} CACHE STRING
      "Flags used by the linker during debug builds.")
diff --git a/Modules/CMakeCompilerABI.h b/Modules/CMakeCompilerABI.h
index f2714b4..ad481d6 100644
--- a/Modules/CMakeCompilerABI.h
+++ b/Modules/CMakeCompilerABI.h
@@ -25,6 +25,10 @@ const char info_sizeof_dptr[] = {
 #elif defined(__GNU__) && defined(__ELF__) && defined(__ARMEL__)
 #define ABI_ID "ELF ARM"
 
+#elif defined(__linux__) && defined(__ELF__) && defined(__amd64__) &&         \
+  defined(__ILP32__)
+#define ABI_ID "ELF X32"
+
 #elif defined(__ELF__)
 #define ABI_ID "ELF"
 #endif
diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake
index 7ca79bd..f2d43b6 100644
--- a/Modules/CMakeCompilerIdDetection.cmake
+++ b/Modules/CMakeCompilerIdDetection.cmake
@@ -95,13 +95,13 @@ function(compiler_id_detection outvar lang)
 
     if(CID_ID_DEFINE)
       foreach(Id ${ordered_compilers})
-        set(CMAKE_${lang}_COMPILER_ID_CONTENT "${CMAKE_${lang}_COMPILER_ID_CONTENT}# define ${CID_PREFIX}COMPILER_IS_${Id} 0\n")
+        string(APPEND CMAKE_${lang}_COMPILER_ID_CONTENT "# define ${CID_PREFIX}COMPILER_IS_${Id} 0\n")
       endforeach()
     endif()
 
     set(pp_if "#if")
     if (CID_VERSION_STRINGS)
-      set(CMAKE_${lang}_COMPILER_ID_CONTENT "${CMAKE_${lang}_COMPILER_ID_CONTENT}\n/* Version number components: V=Version, R=Revision, P=Patch
+      string(APPEND CMAKE_${lang}_COMPILER_ID_CONTENT "\n/* Version number components: V=Version, R=Revision, P=Patch
    Version date components:   YYYY=Year, MM=Month,   DD=Day  */\n")
     endif()
 
@@ -126,7 +126,7 @@ function(compiler_id_detection outvar lang)
         string(CONFIGURE "${_compiler_id_version_compute_${Id}}" VERSION_BLOCK @ONLY)
         string(APPEND id_content "${VERSION_BLOCK}\n")
       endif()
-      set(CMAKE_${lang}_COMPILER_ID_CONTENT "${CMAKE_${lang}_COMPILER_ID_CONTENT}\n${id_content}")
+      string(APPEND CMAKE_${lang}_COMPILER_ID_CONTENT "\n${id_content}")
       set(pp_if "#elif")
     endforeach()
 
@@ -145,7 +145,7 @@ function(compiler_id_detection outvar lang)
 # define ${CID_PREFIX}COMPILER_ID \"\"")
     endif()
 
-    set(CMAKE_${lang}_COMPILER_ID_CONTENT "${CMAKE_${lang}_COMPILER_ID_CONTENT}\n${platform_compiler_detection}\n#endif")
+    string(APPEND CMAKE_${lang}_COMPILER_ID_CONTENT "\n${platform_compiler_detection}\n#endif")
   endif()
 
   set(${outvar} ${CMAKE_${lang}_COMPILER_ID_CONTENT} PARENT_SCOPE)
diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake
index 4162726..87c6b28 100644
--- a/Modules/CMakeDetermineASMCompiler.cmake
+++ b/Modules/CMakeDetermineASMCompiler.cmake
@@ -92,9 +92,17 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
   set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_ARMCC )
   set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_ARMCC "(ARM Compiler)|(ARM Assembler)")
 
-  include(CMakeDetermineCompilerId)
-  CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT})
+  list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS NASM)
+  set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_NASM "-v")
+  set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_NASM "(NASM version)")
+
+  list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS YASM)
+  set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_YASM "--version")
+  set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_YASM "(yasm)")
 
+  include(CMakeDetermineCompilerId)
+  set(userflags)
+  CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT} "${userflags}")
 endif()
 
 if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
@@ -149,6 +157,8 @@ set(_CMAKE_ASM_COMPILER "${CMAKE_ASM${ASM_DIALECT}_COMPILER}")
 set(_CMAKE_ASM_COMPILER_ID "${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}")
 set(_CMAKE_ASM_COMPILER_ARG1 "${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARG1}")
 set(_CMAKE_ASM_COMPILER_ENV_VAR "${CMAKE_ASM${ASM_DIALECT}_COMPILER_ENV_VAR}")
+set(_CMAKE_ASM_COMPILER_AR "${CMAKE_ASM${ASM_DIALECT}_COMPILER_AR}")
+set(_CMAKE_ASM_COMPILER_RANLIB "${CMAKE_ASM${ASM_DIALECT}_COMPILER_RANLIB}")
 
 # configure variables set in this file for fast reload later on
 configure_file(${CMAKE_ROOT}/Modules/CMakeASMCompiler.cmake.in
@@ -157,3 +167,5 @@ configure_file(${CMAKE_ROOT}/Modules/CMakeASMCompiler.cmake.in
 set(_CMAKE_ASM_COMPILER)
 set(_CMAKE_ASM_COMPILER_ARG1)
 set(_CMAKE_ASM_COMPILER_ENV_VAR)
+set(_CMAKE_ASM_COMPILER_AR)
+set(_CMAKE_ASM_COMPILER_RANLIB)
diff --git a/Modules/CMakeDetermineASM_NASMCompiler.cmake b/Modules/CMakeDetermineASM_NASMCompiler.cmake
index 4c8e422..dd75310 100644
--- a/Modules/CMakeDetermineASM_NASMCompiler.cmake
+++ b/Modules/CMakeDetermineASM_NASMCompiler.cmake
@@ -7,8 +7,21 @@
 set(CMAKE_ASM_NASM_COMPILER_LIST nasm yasm)
 
 if(NOT CMAKE_ASM_NASM_COMPILER)
-  find_program(CMAKE_ASM_NASM_COMPILER nasm
-    "$ENV{ProgramFiles}/NASM")
+  set(_CMAKE_ENV_VARX86 "ProgramFiles(x86)")
+  set(_CMAKE_ASM_NASM_COMPILER_PATHS
+    "[HKEY_CURRENT_USER\\SOFTWARE\\nasm]"
+    "$ENV{ProgramFiles}/NASM"
+    "$ENV{${ENV_VARX86}}/NASM"
+    "$ENV{LOCALAPPDATA}/NASM"
+    )
+  find_program(CMAKE_ASM_NASM_COMPILER
+    NAMES ${CMAKE_ASM_NASM_COMPILER_LIST}
+    PATHS ${_CMAKE_ASM_NASM_COMPILER_PATHS}
+    NO_DEFAULT_PATH
+    DOC "NASM compiler"
+  )
+  unset(_CMAKE_ENV_VARX86)
+  unset(_CMAKE_ASM_NASM_COMPILER_PATHS)
 endif()
 
 # Load the generic DetermineASM compiler file with the DIALECT set properly:
diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake
index 4a315e0..3caccde 100644
--- a/Modules/CMakeDetermineCCompiler.cmake
+++ b/Modules/CMakeDetermineCCompiler.cmake
@@ -166,11 +166,20 @@ if (CMAKE_CROSSCOMPILING  AND NOT _CMAKE_TOOLCHAIN_PREFIX)
 endif ()
 
 include(CMakeFindBinUtils)
+set(_CMAKE_PROCESSING_LANGUAGE "C")
+include(Compiler/${CMAKE_C_COMPILER_ID}-FindBinUtils OPTIONAL)
+unset(_CMAKE_PROCESSING_LANGUAGE)
+
 if(MSVC_C_ARCHITECTURE_ID)
   set(SET_MSVC_C_ARCHITECTURE_ID
     "set(MSVC_C_ARCHITECTURE_ID ${MSVC_C_ARCHITECTURE_ID})")
 endif()
 
+if(CMAKE_C_XCODE_CURRENT_ARCH)
+  set(SET_CMAKE_XCODE_CURRENT_ARCH
+    "set(CMAKE_XCODE_CURRENT_ARCH ${CMAKE_C_XCODE_CURRENT_ARCH})")
+endif()
+
 # configure variables set in this file for fast reload later on
 configure_file(${CMAKE_ROOT}/Modules/CMakeCCompiler.cmake.in
   ${CMAKE_PLATFORM_INFO_DIR}/CMakeCCompiler.cmake
diff --git a/Modules/CMakeDetermineCSharpCompiler.cmake b/Modules/CMakeDetermineCSharpCompiler.cmake
index 1b8dd02..55b2fb3 100644
--- a/Modules/CMakeDetermineCSharpCompiler.cmake
+++ b/Modules/CMakeDetermineCSharpCompiler.cmake
@@ -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.
 
-if(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio ([^789]|[789][0-9])")
+if(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
    message(FATAL_ERROR
     "C# is currently only supported for Microsoft Visual Studio 2010 and later.")
 endif()
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index 7b6d17b..89ac9fa 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -5,36 +5,40 @@ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
 include(${CMAKE_ROOT}/Modules//CMakeParseImplicitLinkInfo.cmake)
 
 if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR
-          ("${CMAKE_GENERATOR}" MATCHES "Ninja") ) )
+          ("${CMAKE_GENERATOR}" MATCHES "Ninja") OR
+          ("${CMAKE_GENERATOR}" MATCHES "Visual Studio (1|[89][0-9])") ) )
   message(FATAL_ERROR "CUDA language not currently supported by \"${CMAKE_GENERATOR}\" generator")
 endif()
 
-if(NOT CMAKE_CUDA_COMPILER)
-  set(CMAKE_CUDA_COMPILER_INIT NOTFOUND)
-
-    # prefer the environment variable CUDACXX
-    if(NOT $ENV{CUDACXX} STREQUAL "")
-      get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT)
-      if(CMAKE_CUDA_FLAGS_ENV_INIT)
-        set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler")
-      endif()
-      if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT})
-        message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}")
+if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
+else()
+  if(NOT CMAKE_CUDA_COMPILER)
+    set(CMAKE_CUDA_COMPILER_INIT NOTFOUND)
+
+      # prefer the environment variable CUDACXX
+      if(NOT $ENV{CUDACXX} STREQUAL "")
+        get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT)
+        if(CMAKE_CUDA_FLAGS_ENV_INIT)
+          set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler")
+        endif()
+        if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT})
+          message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}")
+        endif()
       endif()
+
+    # finally list compilers to try
+    if(NOT CMAKE_CUDA_COMPILER_INIT)
+      set(CMAKE_CUDA_COMPILER_LIST nvcc)
     endif()
 
-  # finally list compilers to try
-  if(NOT CMAKE_CUDA_COMPILER_INIT)
-    set(CMAKE_CUDA_COMPILER_LIST nvcc)
+    _cmake_find_compiler(CUDA)
+  else()
+    _cmake_find_compiler_path(CUDA)
   endif()
 
-  _cmake_find_compiler(CUDA)
-else()
-  _cmake_find_compiler_path(CUDA)
+  mark_as_advanced(CMAKE_CUDA_COMPILER)
 endif()
 
-mark_as_advanced(CMAKE_CUDA_COMPILER)
-
 #Allow the user to specify a host compiler
 set(CMAKE_CUDA_HOST_COMPILER "" CACHE FILEPATH "Host compiler to be used by nvcc")
 if(NOT $ENV{CUDAHOSTCXX} STREQUAL "")
@@ -75,14 +79,12 @@ if(MSVC_CUDA_ARCHITECTURE_ID)
     "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})")
 endif()
 
-#if this compiler vendor is matches NVIDIA we can determine
-#what the host compiler is. This only needs to be done if the CMAKE_CUDA_HOST_COMPILER
-#has NOT been explicitly set
-#
-#Find the line from compiler ID that contains a.out ( or last line )
-#We also need to find the implicit link lines. Which can be done by replacing
-#the compiler with cuda-fake-ld  and pass too CMAKE_PARSE_IMPLICIT_LINK_INFO
-if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA)
+if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
+  set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")
+  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "")
+  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "")
+  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
+elseif(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA)
   set(_nvcc_log "")
   string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}")
   if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n")
diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake
index f2e0bb2..9150962 100644
--- a/Modules/CMakeDetermineCXXCompiler.cmake
+++ b/Modules/CMakeDetermineCXXCompiler.cmake
@@ -161,11 +161,20 @@ if (CMAKE_CROSSCOMPILING  AND NOT  _CMAKE_TOOLCHAIN_PREFIX)
 endif ()
 
 include(CMakeFindBinUtils)
+set(_CMAKE_PROCESSING_LANGUAGE "CXX")
+include(Compiler/${CMAKE_CXX_COMPILER_ID}-FindBinUtils OPTIONAL)
+unset(_CMAKE_PROCESSING_LANGUAGE)
+
 if(MSVC_CXX_ARCHITECTURE_ID)
   set(SET_MSVC_CXX_ARCHITECTURE_ID
     "set(MSVC_CXX_ARCHITECTURE_ID ${MSVC_CXX_ARCHITECTURE_ID})")
 endif()
 
+if(CMAKE_CXX_XCODE_CURRENT_ARCH)
+  set(SET_CMAKE_XCODE_CURRENT_ARCH
+    "set(CMAKE_XCODE_CURRENT_ARCH ${CMAKE_CXX_XCODE_CURRENT_ARCH})")
+endif()
+
 # configure all variables set in this file
 configure_file(${CMAKE_ROOT}/Modules/CMakeCXXCompiler.cmake.in
   ${CMAKE_PLATFORM_INFO_DIR}/CMakeCXXCompiler.cmake
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index c41a986..eeb806f 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -24,16 +24,21 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
 
   # Try building with no extra flags and then try each set
   # of helper flags.  Stop when the compiler is identified.
-  foreach(flags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST}
-                ""
-                ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
-    CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${flags}" "${src}")
-    CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}")
-    if(CMAKE_${lang}_COMPILER_ID)
-      break()
-    endif()
-    foreach(file ${COMPILER_${lang}_PRODUCED_FILES})
-      CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}")
+  foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
+    foreach(testflags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST}
+                      ""
+                      ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
+      CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${testflags}" "${userflags}" "${src}")
+      CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}")
+      if(CMAKE_${lang}_COMPILER_ID)
+        break()
+      endif()
+      foreach(file ${COMPILER_${lang}_PRODUCED_FILES})
+        CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}")
+      endforeach()
+      if(CMAKE_${lang}_COMPILER_ID)
+        break()
+      endif()
     endforeach()
     if(CMAKE_${lang}_COMPILER_ID)
       break()
@@ -42,7 +47,9 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
 
   # If the compiler is still unknown, try to query its vendor.
   if(CMAKE_${lang}_COMPILER AND NOT CMAKE_${lang}_COMPILER_ID)
-    CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang})
+    foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
+      CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang} "${userflags}")
+    endforeach()
   endif()
 
   if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU")
@@ -66,7 +73,9 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
   endif()
 
   if(CMAKE_GENERATOR STREQUAL "Ninja" AND MSVC_${lang}_ARCHITECTURE_ID)
-    CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang})
+    foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
+      CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang} "${userflags}")
+    endforeach()
   else()
     set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "")
   endif()
@@ -95,6 +104,7 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
   set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
   set(MSVC_${lang}_ARCHITECTURE_ID "${MSVC_${lang}_ARCHITECTURE_ID}"
     PARENT_SCOPE)
+  set(CMAKE_${lang}_XCODE_CURRENT_ARCH "${CMAKE_${lang}_XCODE_CURRENT_ARCH}" PARENT_SCOPE)
   set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX}" PARENT_SCOPE)
   set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}" PARENT_SCOPE)
   set(CMAKE_${lang}_COMPILER_WRAPPER "${CMAKE_${lang}_COMPILER_WRAPPER}" PARENT_SCOPE)
@@ -127,7 +137,7 @@ endfunction()
 #-----------------------------------------------------------------------------
 # Function to build the compiler id source file and look for output
 # files.
-function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src)
+function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags userflags src)
   # Create a clean working directory.
   file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR})
   file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR})
@@ -137,7 +147,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src)
   # Construct a description of this test case.
   set(COMPILER_DESCRIPTION
     "Compiler: ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_ARG1}
-Build flags: ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
+Build flags: ${userflags}
 Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
 ")
 
@@ -226,6 +236,26 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
     endif()
     set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR})
     set(id_src "${src}")
+    set(id_compile "ClCompile")
+    set(id_PostBuildEvent_Command "for %%i in (${id_cl}) do %40echo CMAKE_${lang}_COMPILER=%%~$PATH:i")
+    set(id_Import_props "")
+    set(id_Import_targets "")
+    set(id_ItemDefinitionGroup_entry "")
+    set(id_Link_AdditionalDependencies "")
+    if(lang STREQUAL CUDA)
+      if(NOT CMAKE_VS_PLATFORM_TOOLSET_CUDA)
+        message(FATAL_ERROR "No CUDA toolset found.")
+      endif()
+      set(cuda_tools "CUDA ${CMAKE_VS_PLATFORM_TOOLSET_CUDA}")
+      set(id_compile "CudaCompile")
+      set(id_PostBuildEvent_Command [[echo CMAKE_CUDA_COMPILER=$(CudaToolkitBinDir)\nvcc.exe]])
+      string(CONCAT id_Import_props [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.props" />]])
+      string(CONCAT id_Import_targets [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.targets" />]])
+      if(CMAKE_VS_PLATFORM_NAME STREQUAL x64)
+        set(id_ItemDefinitionGroup_entry "<CudaCompile><TargetMachinePlatform>64</TargetMachinePlatform></CudaCompile>")
+      endif()
+      set(id_Link_AdditionalDependencies "<AdditionalDependencies>cudart.lib</AdditionalDependencies>")
+    endif()
     configure_file(${CMAKE_ROOT}/Modules/CompilerId/VS-${v}.${ext}.in
       ${id_dir}/CompilerId${lang}.${ext} @ONLY)
     if(CMAKE_VS_MSBUILD_COMMAND AND NOT lang STREQUAL "Fortran")
@@ -294,18 +324,8 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
     else()
       set(id_sdkroot "")
     endif()
-    if(NOT ${XCODE_VERSION} VERSION_LESS 3)
-      set(v 3)
-      set(ext xcodeproj)
-    elseif(NOT ${XCODE_VERSION} VERSION_LESS 2)
-      set(v 2)
-      set(ext xcodeproj)
-    else()
-      set(v 1)
-      set(ext xcode)
-    endif()
-    configure_file(${CMAKE_ROOT}/Modules/CompilerId/Xcode-${v}.pbxproj.in
-      ${id_dir}/CompilerId${lang}.${ext}/project.pbxproj @ONLY)
+    configure_file(${CMAKE_ROOT}/Modules/CompilerId/Xcode-3.pbxproj.in
+      ${id_dir}/CompilerId${lang}.xcodeproj/project.pbxproj @ONLY)
     unset(_ENV_MACOSX_DEPLOYMENT_TARGET)
     if(DEFINED ENV{MACOSX_DEPLOYMENT_TARGET})
       set(_ENV_MACOSX_DEPLOYMENT_TARGET "$ENV{MACOSX_DEPLOYMENT_TARGET}")
@@ -329,11 +349,14 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
         endif()
       endif()
     endif()
+    if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "CURRENT_ARCH=([^%\r\n]+)[\r\n]")
+      set(CMAKE_${lang}_XCODE_CURRENT_ARCH "${CMAKE_MATCH_1}" PARENT_SCOPE)
+    endif()
   else()
     execute_process(
       COMMAND "${CMAKE_${lang}_COMPILER}"
               ${CMAKE_${lang}_COMPILER_ID_ARG1}
-              ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
+              ${userflags}
               ${testflags}
               ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
               "${src}"
@@ -621,7 +644,7 @@ endfunction()
 #   set(CMAKE_${lang}_COMPILER_ID_VENDOR_REGEX_${vendor} "Some Vendor Output")
 # We try running the compiler with the flag for each vendor and
 # matching its regular expression in the output.
-function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang)
+function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang userflags)
 
   if(NOT CMAKE_${lang}_COMPILER_ID_DIR)
     # We get here when this function is called not from within CMAKE_DETERMINE_COMPILER_ID()
@@ -639,7 +662,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang)
     execute_process(
       COMMAND "${CMAKE_${lang}_COMPILER}"
       ${CMAKE_${lang}_COMPILER_ID_ARG1}
-      ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
+      ${userflags}
       ${flags}
       WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}
       OUTPUT_VARIABLE output ERROR_VARIABLE output
@@ -667,7 +690,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang)
   endforeach()
 endfunction()
 
-function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang)
+function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang userflags)
   # Run this MSVC-compatible compiler to detect what the /showIncludes
   # option displays.  We can use a C source even with the C++ compiler
   # because MSVC-compatible compilers handle both and show the same output.
@@ -677,7 +700,7 @@ function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang)
   execute_process(
     COMMAND "${CMAKE_${lang}_COMPILER}"
             ${CMAKE_${lang}_COMPILER_ID_ARG1}
-            ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
+            ${userflags}
             /nologo /showIncludes /c main.c
     WORKING_DIRECTORY ${showdir}
     OUTPUT_VARIABLE out
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index 484fa66..d5220b4 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -60,6 +60,7 @@ else()
       #  fort: Compaq (now HP) Fortran 90/95 compiler for Tru64 and Linux/Alpha
       #  ifc: Intel Fortran 95 compiler for Linux/x86
       #  efc: Intel Fortran 95 compiler for IA64
+      #  nagfor: NAG Fortran compiler
       #
       #  The order is 95 or newer compilers first, then 90,
       #  then 77 or older compilers, gnu is always last in the group,
@@ -68,7 +69,7 @@ else()
         ftn
         ifort ifc af95 af90 efc f95 pathf2003 pathf95 pgf95 pgfortran lf95 xlf95
         fort gfortran gfortran-4 g95 f90 pathf90 pgf90 xlf90 epcf90 fort77
-        frt pgf77 xlf fl32 af77 g77 f77
+        frt pgf77 xlf fl32 af77 g77 f77 nag
         )
 
       # Vendor-specific compiler names.
@@ -79,6 +80,7 @@ else()
       set(_Fortran_COMPILER_NAMES_PathScale pathf2003 pathf95 pathf90)
       set(_Fortran_COMPILER_NAMES_XL        xlf)
       set(_Fortran_COMPILER_NAMES_VisualAge xlf95 xlf90 xlf)
+      set(_Fortran_COMPILER_NAMES_NAG nagfor)
     endif()
 
     _cmake_find_compiler(Fortran)
@@ -255,6 +257,9 @@ if (CMAKE_CROSSCOMPILING  AND NOT _CMAKE_TOOLCHAIN_PREFIX)
 endif ()
 
 include(CMakeFindBinUtils)
+set(_CMAKE_PROCESSING_LANGUAGE "Fortran")
+include(Compiler/${CMAKE_Fortran_COMPILER_ID}-FindBinUtils OPTIONAL)
+unset(_CMAKE_PROCESSING_LANGUAGE)
 
 if(MSVC_Fortran_ARCHITECTURE_ID)
   set(SET_MSVC_Fortran_ARCHITECTURE_ID
diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake
index 8675553..20dcf1b 100644
--- a/Modules/CMakeDetermineSystem.cmake
+++ b/Modules/CMakeDetermineSystem.cmake
@@ -35,10 +35,17 @@
 if(CMAKE_HOST_UNIX)
   find_program(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin )
   if(CMAKE_UNAME)
-    exec_program(uname ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_NAME)
-    exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
+    if(CMAKE_HOST_SYSTEM_NAME STREQUAL "AIX")
+      exec_program(${CMAKE_UNAME} ARGS -v OUTPUT_VARIABLE _CMAKE_HOST_SYSTEM_MAJOR_VERSION)
+      exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE _CMAKE_HOST_SYSTEM_MINOR_VERSION)
+      set(CMAKE_HOST_SYSTEM_VERSION "${_CMAKE_HOST_SYSTEM_MAJOR_VERSION}.${_CMAKE_HOST_SYSTEM_MINOR_VERSION}")
+      unset(_CMAKE_HOST_SYSTEM_MAJOR_VERSION)
+      unset(_CMAKE_HOST_SYSTEM_MINOR_VERSION)
+    else()
+      exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
+    endif()
     if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|Darwin|^GNU$")
-      exec_program(uname ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
+      exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
         RETURN_VALUE val)
       if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND
          CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "Power Macintosh")
@@ -49,10 +56,10 @@ if(CMAKE_HOST_UNIX)
       exec_program(arch ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
         RETURN_VALUE val)
     else()
-      exec_program(uname ARGS -p OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
+      exec_program(${CMAKE_UNAME} ARGS -p OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
         RETURN_VALUE val)
       if("${val}" GREATER 0)
-        exec_program(uname ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
+        exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
           RETURN_VALUE val)
       endif()
     endif()
@@ -67,7 +74,6 @@ if(CMAKE_HOST_UNIX)
   endif()
 else()
   if(CMAKE_HOST_WIN32)
-    set (CMAKE_HOST_SYSTEM_NAME "Windows")
     if (DEFINED ENV{PROCESSOR_ARCHITEW6432})
       set (CMAKE_HOST_SYSTEM_PROCESSOR "$ENV{PROCESSOR_ARCHITEW6432}")
     else()
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index 4c0486e..e4103d0 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -26,6 +26,10 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC"
    OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC"
    OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC"
    OR "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC"
+   OR (CMAKE_HOST_WIN32 AND (
+        "x${CMAKE_C_COMPILER_ID}" STREQUAL "xPGI"
+         OR "x${CMAKE_Fortran_COMPILER_ID}" STREQUAL "xPGI"
+   ))
    OR (CMAKE_GENERATOR MATCHES "Visual Studio"
        AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android"))
 
diff --git a/Modules/CMakeFindDependencyMacro.cmake b/Modules/CMakeFindDependencyMacro.cmake
index 61f74ef..81606ce 100644
--- a/Modules/CMakeFindDependencyMacro.cmake
+++ b/Modules/CMakeFindDependencyMacro.cmake
@@ -7,38 +7,20 @@
 #
 # ::
 #
-#     find_dependency(<dep> [<version> [EXACT]])
+#     find_dependency(<dep> [...])
 #
 #
 # ``find_dependency()`` wraps a :command:`find_package` call for a package
 # dependency. It is designed to be used in a <package>Config.cmake file, and it
-# forwards the correct parameters for EXACT, QUIET and REQUIRED which were
-# passed to the original :command:`find_package` call.  It also sets an
-# informative diagnostic message if the dependency could not be found.
+# forwards the correct parameters for QUIET and REQUIRED which were passed to
+# the original :command:`find_package` call.  It also sets an informative
+# diagnostic message if the dependency could not be found.
+#
+# Any additional arguments specified are forwarded to :command:`find_package`.
 #
 
 macro(find_dependency dep)
   if (NOT ${dep}_FOUND)
-    set(cmake_fd_version)
-    if (${ARGC} GREATER 1)
-      if ("${ARGV1}" STREQUAL "")
-        message(FATAL_ERROR "Invalid arguments to find_dependency. VERSION is empty")
-      endif()
-      if ("${ARGV1}" STREQUAL EXACT)
-        message(FATAL_ERROR "Invalid arguments to find_dependency. EXACT may only be specified if a VERSION is specified")
-      endif()
-      set(cmake_fd_version ${ARGV1})
-    endif()
-    set(cmake_fd_exact_arg)
-    if(${ARGC} GREATER 2)
-      if (NOT "${ARGV2}" STREQUAL EXACT)
-        message(FATAL_ERROR "Invalid arguments to find_dependency")
-      endif()
-      set(cmake_fd_exact_arg EXACT)
-    endif()
-    if(${ARGC} GREATER 3)
-      message(FATAL_ERROR "Invalid arguments to find_dependency")
-    endif()
     set(cmake_fd_quiet_arg)
     if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
       set(cmake_fd_quiet_arg QUIET)
@@ -52,10 +34,9 @@ macro(find_dependency dep)
       _CMAKE_${dep}_TRANSITIVE_DEPENDENCY
     )
 
-    find_package(${dep} ${cmake_fd_version}
-        ${cmake_fd_exact_arg}
-        ${cmake_fd_quiet_arg}
-        ${cmake_fd_required_arg}
+    find_package(${dep} ${ARGN}
+      ${cmake_fd_quiet_arg}
+      ${cmake_fd_required_arg}
     )
 
     if(NOT DEFINED cmake_fd_alreadyTransitive OR cmake_fd_alreadyTransitive)
@@ -67,7 +48,6 @@ macro(find_dependency dep)
       set(${CMAKE_FIND_PACKAGE_NAME}_FOUND False)
       return()
     endif()
-    set(cmake_fd_version)
     set(cmake_fd_required_arg)
     set(cmake_fd_quiet_arg)
     set(cmake_fd_exact_arg)
diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in
index 69800d7..d521190 100644
--- a/Modules/CMakeFortranCompiler.cmake.in
+++ b/Modules/CMakeFortranCompiler.cmake.in
@@ -8,7 +8,9 @@ set(CMAKE_Fortran_SIMULATE_ID "@CMAKE_Fortran_SIMULATE_ID@")
 set(CMAKE_Fortran_SIMULATE_VERSION "@CMAKE_Fortran_SIMULATE_VERSION@")
 @SET_MSVC_Fortran_ARCHITECTURE_ID@
 set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_Fortran_COMPILER_AR "@CMAKE_Fortran_COMPILER_AR@")
 set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_Fortran_COMPILER_RANLIB "@CMAKE_Fortran_COMPILER_RANLIB@")
 set(CMAKE_COMPILER_IS_GNUG77 @CMAKE_COMPILER_IS_GNUG77@)
 set(CMAKE_Fortran_COMPILER_LOADED 1)
 set(CMAKE_Fortran_COMPILER_WORKS @CMAKE_Fortran_COMPILER_WORKS@)
diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in
index 67cda3b..26b2ed6 100644
--- a/Modules/CMakeFortranCompilerId.F.in
+++ b/Modules/CMakeFortranCompilerId.F.in
@@ -103,6 +103,11 @@
         PRINT *, 'INFO:compiler[MIPSpro]'
 #elif defined(__hpux) || defined(__hpux__)
         PRINT *, 'INFO:compiler[HP]'
+#elif defined(NAGFOR)
+        PRINT *, 'INFO:compiler[NAG]'
+#define COMPILER_VERSION_MAJOR DEC(__NAG_COMPILER_RELEASE/10)
+#define COMPILER_VERSION_MINOR DEC(__NAG_COMPILER_RELEASE % 10)
+#define COMPILER_VERSION_PATCH DEC(__NAG_COMPILER_BUILD)
 #elif 1
 #       if 0
 !       The above 'elif 1' instead of 'else' is to work around a bug in the
diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake
index 3273443..3b77278 100644
--- a/Modules/CMakeParseImplicitLinkInfo.cmake
+++ b/Modules/CMakeParseImplicitLinkInfo.cmake
@@ -18,9 +18,13 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
     get_filename_component(linker ${CMAKE_LINKER} NAME)
     string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" linker "${linker}")
   endif()
+  set(startfile "CMAKE_LINK_STARTFILE-NOTFOUND")
+  if(CMAKE_LINK_STARTFILE)
+    set(startfile "${CMAKE_LINK_STARTFILE}")
+  endif()
   # Construct a regex to match linker lines.  It must match both the
   # whole line and just the command (argv[0]).
-  set(linker_regex "^( *|.*[/\\])(${linker}|([^/\\]+-)?ld|collect2)[^/\\]*( |$)")
+  set(linker_regex "^( *|.*[/\\])(${linker}|${startfile}|([^/\\]+-)?ld|collect2)[^/\\]*( |$)")
   set(linker_exclude_regex "collect2 version |^[A-Za-z0-9_]+=|/ldfe ")
   string(APPEND log "  link line regex: [${linker_regex}]\n")
   string(REGEX REPLACE "\r?\n" ";" output_lines "${text}")
@@ -38,11 +42,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
           set(line "${xline}")
         endif()
       endif()
-      if(UNIX)
-        separate_arguments(args UNIX_COMMAND "${line}")
-      else()
-        separate_arguments(args WINDOWS_COMMAND "${line}")
-      endif()
+      separate_arguments(args NATIVE_COMMAND "${line}")
       list(GET args 0 cmd)
     endif()
     set(is_msvc 0)
@@ -59,9 +59,9 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
           string(REGEX REPLACE "^-L" "" dir "${arg}")
           list(APPEND implicit_dirs_tmp ${dir})
           string(APPEND log "    arg [${arg}] ==> dir [${dir}]\n")
-        elseif("${arg}" MATCHES "^[-/]LIBPATH:(.+)")
+        elseif("${arg}" MATCHES "^[-/](LIBPATH|libpath):(.+)")
           # MSVC search path.
-          set(dir "${CMAKE_MATCH_1}")
+          set(dir "${CMAKE_MATCH_2}")
           list(APPEND implicit_dirs_tmp ${dir})
           string(APPEND log "    arg [${arg}] ==> dir [${dir}]\n")
         elseif(is_msvc AND "${arg}" STREQUAL "-link")
@@ -83,6 +83,11 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
           # Unix library full path.
           list(APPEND implicit_libs_tmp ${arg})
           string(APPEND log "    arg [${arg}] ==> lib [${arg}]\n")
+        elseif("${arg}" MATCHES "^[-/](DEFAULTLIB|defaultlib):(.+)")
+          # Windows library.
+          set(lib "${CMAKE_MATCH_2}")
+          list(APPEND implicit_libs_tmp ${lib})
+          string(APPEND log "    arg [${arg}] ==> lib [${lib}]\n")
         elseif("${arg}" MATCHES "^(.:)?[/\\].*\\.o$"
             AND obj_regex AND "${arg}" MATCHES "${obj_regex}")
           # Object file full path.
@@ -137,7 +142,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj
   # We remove items that are not language-specific.
   set(implicit_libs "")
   foreach(lib IN LISTS implicit_libs_tmp)
-    if("x${lib}" MATCHES "^x(crt.*\\.o|gcc.*|System.*|.*libclang_rt.*)$")
+    if("x${lib}" MATCHES "^x(crt.*\\.o|System.*|.*libclang_rt.*|msvcrt.*|libvcruntime.*|libucrt.*|libcmt.*)$")
       string(APPEND log "  remove lib [${lib}]\n")
     elseif(IS_ABSOLUTE "${lib}")
       get_filename_component(abs "${lib}" ABSOLUTE)
diff --git a/Modules/CMakeVS7BackwardCompatibility.cmake b/Modules/CMakeVS7BackwardCompatibility.cmake
deleted file mode 100644
index cf477c8..0000000
--- a/Modules/CMakeVS7BackwardCompatibility.cmake
+++ /dev/null
@@ -1,16 +0,0 @@
-# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-
-# hard code these for fast backwards compatibility tests
-set (CMAKE_SIZEOF_INT       4   CACHE INTERNAL "Size of int data type")
-set (CMAKE_SIZEOF_LONG      4   CACHE INTERNAL "Size of long data type")
-set (CMAKE_SIZEOF_VOID_P    4   CACHE INTERNAL "Size of void* data type")
-set (CMAKE_SIZEOF_CHAR      1   CACHE INTERNAL "Size of char data type")
-set (CMAKE_SIZEOF_SHORT     2   CACHE INTERNAL "Size of short data type")
-set (CMAKE_SIZEOF_FLOAT     4   CACHE INTERNAL "Size of float data type")
-set (CMAKE_SIZEOF_DOUBLE    8   CACHE INTERNAL "Size of double data type")
-set (CMAKE_NO_ANSI_FOR_SCOPE 0 CACHE INTERNAL
-         "Does the compiler support ansi for scope.")
-set (CMAKE_USE_WIN32_THREADS  TRUE CACHE BOOL    "Use the win32 thread library.")
-set (CMAKE_WORDS_BIGENDIAN 0 CACHE INTERNAL "endianness of bytes")
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index 4e7546b..a63fc83 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -98,7 +98,12 @@
 #
 # .. variable:: CPACK_PACKAGE_DESCRIPTION_SUMMARY
 #
-#  Short description of the project (only a few words).
+#  Short description of the project (only a few words). Default value is::
+#
+#    ${PROJECT_DESCRIPTION}
+#
+#  if DESCRIPTION has given to the project() call or
+#  CMake generated string with PROJECT_NAME otherwise.
 #
 # .. variable:: CPACK_PACKAGE_FILE_NAME
 #
@@ -360,8 +365,13 @@ _cpack_set_default(CPACK_PACKAGE_VERSION_PATCH "1")
 _cpack_set_default(CPACK_PACKAGE_VERSION
   "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
 _cpack_set_default(CPACK_PACKAGE_VENDOR "Humanity")
-_cpack_set_default(CPACK_PACKAGE_DESCRIPTION_SUMMARY
-  "${CMAKE_PROJECT_NAME} built using CMake")
+if(CMAKE_PROJECT_DESCRIPTION)
+  _cpack_set_default(CPACK_PACKAGE_DESCRIPTION_SUMMARY
+    "${CMAKE_PROJECT_DESCRIPTION}")
+else()
+  _cpack_set_default(CPACK_PACKAGE_DESCRIPTION_SUMMARY
+    "${CMAKE_PROJECT_NAME} built using CMake")
+endif()
 
 _cpack_set_default(CPACK_PACKAGE_DESCRIPTION_FILE
   "${CMAKE_ROOT}/Templates/CPack.GenericDescription.txt")
diff --git a/Modules/CPackArchive.cmake b/Modules/CPackArchive.cmake
new file mode 100644
index 0000000..741fb1f
--- /dev/null
+++ b/Modules/CPackArchive.cmake
@@ -0,0 +1,39 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#.rst:
+# CPackArchive
+# ------------
+#
+# Archive CPack generator that supports packaging of sources and binaries in
+# different formats:
+#
+#   - 7Z - 7zip - (.7z)
+#   - TBZ2 (.tar.bz2)
+#   - TGZ (.tar.gz)
+#   - TXZ (.tar.xz)
+#   - TZ (.tar.Z)
+#   - ZIP (.zip)
+#
+# Variables specific to CPack Archive generator
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# .. variable:: CPACK_ARCHIVE_FILE_NAME
+#               CPACK_ARCHIVE_<component>_FILE_NAME
+#
+#  Package file name without extension which is added automatically depending
+#  on the archive format.
+#
+#  * Mandatory : YES
+#  * Default   : ``<CPACK_PACKAGE_FILE_NAME>[-<component>].<extension>`` with
+#                spaces replaced by '-'
+#
+# .. variable:: CPACK_ARCHIVE_COMPONENT_INSTALL
+#
+#  Enable component packaging for CPackArchive
+#
+#  * Mandatory : NO
+#  * Default   : OFF
+#
+#  If enabled (ON) multiple packages are generated. By default a single package
+#  containing files of all components is generated.
diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake
index 188dde3..3a10b99 100644
--- a/Modules/CPackComponent.cmake
+++ b/Modules/CPackComponent.cmake
@@ -105,7 +105,8 @@
 #                       [DEPENDS comp1 comp2 ... ]
 #                       [INSTALL_TYPES type1 type2 ... ]
 #                       [DOWNLOADED]
-#                       [ARCHIVE_FILE filename])
+#                       [ARCHIVE_FILE filename]
+#                       [PLIST filename])
 #
 #
 #
@@ -163,6 +164,9 @@
 # a file with some name based on CPACK_PACKAGE_FILE_NAME and the name of
 # the component.  See cpack_configure_downloads for more information.
 #
+# PLIST gives a filename that is passed to pkgbuild with the
+# ``--component-plist`` argument when using the productbuild generator.
+#
 # .. command:: cpack_add_component_group
 #
 # Describes a group of related CPack installation components.
@@ -299,49 +303,17 @@
 if(NOT CPackComponent_CMake_INCLUDED)
 set(CPackComponent_CMake_INCLUDED 1)
 
-# Argument-parsing macro from https://cmake.org/Wiki/CMakeMacroParseArguments
-macro(cpack_parse_arguments prefix arg_names option_names)
-  set(${prefix}_DEFAULT_ARGS)
-  foreach(arg_name ${arg_names})
-    set(${prefix}_${arg_name})
-  endforeach()
-  foreach(option ${option_names})
-    set(${prefix}_${option} FALSE)
-  endforeach()
-
-  set(current_arg_name DEFAULT_ARGS)
-  set(current_arg_list)
-  foreach(arg ${ARGN})
-    set(larg_names ${arg_names})
-    list(FIND larg_names "${arg}" is_arg_name)
-    if (is_arg_name GREATER -1)
-      set(${prefix}_${current_arg_name} ${current_arg_list})
-      set(current_arg_name ${arg})
-      set(current_arg_list)
-    else ()
-      set(loption_names ${option_names})
-      list(FIND loption_names "${arg}" is_option)
-      if (is_option GREATER -1)
-        set(${prefix}_${arg} TRUE)
-      else ()
-        set(current_arg_list ${current_arg_list} ${arg})
-      endif ()
-    endif ()
-  endforeach()
-  set(${prefix}_${current_arg_name} ${current_arg_list})
-endmacro()
-
 # Macro that appends a SET command for the given variable name (var)
 # to the macro named strvar, but only if the variable named "var"
 # has been defined. The string will eventually be appended to a CPack
 # configuration file.
 macro(cpack_append_variable_set_command var strvar)
   if (DEFINED ${var})
-    set(${strvar} "${${strvar}}set(${var}")
+    string(APPEND ${strvar} "set(${var}")
     foreach(APPENDVAL ${${var}})
-      set(${strvar} "${${strvar}} ${APPENDVAL}")
+      string(APPEND ${strvar} " ${APPENDVAL}")
     endforeach()
-    set(${strvar} "${${strvar}})\n")
+    string(APPEND ${strvar} ")\n")
   endif ()
 endmacro()
 
@@ -353,7 +325,7 @@ macro(cpack_append_string_variable_set_command var strvar)
   if (DEFINED ${var})
     list(LENGTH ${var} CPACK_APP_VALUE_LEN)
     if(${CPACK_APP_VALUE_LEN} EQUAL 1)
-      set(${strvar} "${${strvar}}set(${var} \"${${var}}\")\n")
+      string(APPEND ${strvar} "set(${var} \"${${var}}\")\n")
     endif()
   endif ()
 endmacro()
@@ -380,7 +352,7 @@ macro(cpack_append_option_set_command var strvar)
   if (${var})
     list(LENGTH ${var} CPACK_APP_VALUE_LEN)
     if(${CPACK_APP_VALUE_LEN} EQUAL 1)
-      set(${strvar} "${${strvar}}set(${var} TRUE)\n")
+      string(APPEND ${strvar} "set(${var} TRUE)\n")
     endif()
   endif ()
 endmacro()
@@ -388,9 +360,10 @@ endmacro()
 # Macro that adds a component to the CPack installer
 macro(cpack_add_component compname)
   string(TOUPPER ${compname} _CPACK_ADDCOMP_UNAME)
-  cpack_parse_arguments(CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME}
-    "DISPLAY_NAME;DESCRIPTION;GROUP;DEPENDS;INSTALL_TYPES;ARCHIVE_FILE"
+  cmake_parse_arguments(CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME}
     "HIDDEN;REQUIRED;DISABLED;DOWNLOADED"
+    "DISPLAY_NAME;DESCRIPTION;GROUP;ARCHIVE_FILE;PLIST"
+    "DEPENDS;INSTALL_TYPES"
     ${ARGN}
     )
 
@@ -445,6 +418,9 @@ macro(cpack_add_component compname)
   cpack_append_option_set_command(
     CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME}_DOWNLOADED
     _CPACK_ADDCOMP_STR)
+  cpack_append_string_variable_set_command(
+    CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME}_PLIST
+    _CPACK_ADDCOMP_STR)
   # Backward compatibility issue.
   # Write to config iff the macros is used after CPack.cmake has been
   # included, other it's not necessary because the variables
@@ -457,9 +433,10 @@ endmacro()
 # Macro that adds a component group to the CPack installer
 macro(cpack_add_component_group grpname)
   string(TOUPPER ${grpname} _CPACK_ADDGRP_UNAME)
-  cpack_parse_arguments(CPACK_COMPONENT_GROUP_${_CPACK_ADDGRP_UNAME}
-    "DISPLAY_NAME;DESCRIPTION;PARENT_GROUP"
+  cmake_parse_arguments(CPACK_COMPONENT_GROUP_${_CPACK_ADDGRP_UNAME}
     "EXPANDED;BOLD_TITLE"
+    "DISPLAY_NAME;DESCRIPTION;PARENT_GROUP"
+    ""
     ${ARGN}
     )
 
@@ -491,7 +468,8 @@ endmacro()
 # Macro that adds an installation type to the CPack installer
 macro(cpack_add_install_type insttype)
   string(TOUPPER ${insttype} _CPACK_INSTTYPE_UNAME)
-  cpack_parse_arguments(CPACK_INSTALL_TYPE_${_CPACK_INSTTYPE_UNAME}
+  cmake_parse_arguments(CPACK_INSTALL_TYPE_${_CPACK_INSTTYPE_UNAME}
+    ""
     "DISPLAY_NAME"
     ""
     ${ARGN}
@@ -514,9 +492,10 @@ macro(cpack_add_install_type insttype)
 endmacro()
 
 macro(cpack_configure_downloads site)
-  cpack_parse_arguments(CPACK_DOWNLOAD
-    "UPLOAD_DIRECTORY"
+  cmake_parse_arguments(CPACK_DOWNLOAD
     "ALL;ADD_REMOVE;NO_ADD_REMOVE"
+    "UPLOAD_DIRECTORY"
+    ""
     ${ARGN}
     )
 
diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake
index deb724c..c1cb52f 100644
--- a/Modules/CPackIFW.cmake
+++ b/Modules/CPackIFW.cmake
@@ -28,8 +28,59 @@
 # and Mac OS X.
 #
 # You should also install QtIFW_ to use CPack ``IFW`` generator.
-# If you don't use a default path for the installation, please set
-# the used path in the variable ``QTIFWDIR``.
+#
+# Hints
+# ^^^^^
+#
+# Generally, the CPack ``IFW`` generator automatically finds QtIFW_ tools,
+# but if you don't use a default path for installation of the QtIFW_ tools,
+# the path may be specified in either a CMake or an environment variable:
+#
+# .. variable:: CPACK_IFW_ROOT
+#
+#  An CMake variable which specifies the location of the QtIFW_ tool suite.
+#
+#  The variable will be cached in the ``CPackConfig.cmake`` file and used at
+#  CPack runtime.
+#
+# .. variable:: QTIFWDIR
+#
+#  An environment variable which specifies the location of the QtIFW_ tool
+#  suite.
+#
+# .. note::
+#   The specified path should not contain "bin" at the end
+#   (for example: "D:\\DevTools\\QtIFW2.0.5").
+#
+# The :variable:`CPACK_IFW_ROOT` variable has a higher priority and overrides
+# the value of the :variable:`QTIFWDIR` variable.
+#
+# Internationalization
+# ^^^^^^^^^^^^^^^^^^^^
+#
+# Some variables and command arguments support internationalization via
+# CMake script. This is an optional feature.
+#
+# Installers created by QtIFW_ tools have built-in support for
+# internationalization and many phrases are localized to many languages,
+# but this does not apply to the description of the your components and groups
+# that will be distributed.
+#
+# Localization of the description of your components and groups is useful for
+# users of your installers.
+#
+# A localized variable or argument can contain a single default value, and a
+# set of pairs the name of the locale and the localized value.
+#
+# For example:
+#
+# .. code-block:: cmake
+#
+#    set(LOCALIZABLE_VARIABLE "Default value"
+#      en "English value"
+#      en_US "American value"
+#      en_GB "Great Britain value"
+#      )
 #
 # Variables
 # ^^^^^^^^^
@@ -197,7 +248,7 @@
 #  dependent components.
 #
 # Tools
-# """"""""
+# """""
 #
 # .. variable:: CPACK_IFW_FRAMEWORK_VERSION
 #
@@ -207,13 +258,25 @@
 #
 #  The path to "binarycreator" command line client.
 #
-#  This variable is cached and can be configured user if need.
+#  This variable is cached and may be configured if needed.
 #
 # .. variable:: CPACK_IFW_REPOGEN_EXECUTABLE
 #
 #  The path to "repogen" command line client.
 #
-#  This variable is cached and can be configured user if need.
+#  This variable is cached and may be configured if needed.
+#
+# .. variable:: CPACK_IFW_INSTALLERBASE_EXECUTABLE
+#
+#  The path to "installerbase" installer executable base.
+#
+#  This variable is cached and may be configured if needed.
+#
+# .. variable:: CPACK_IFW_DEVTOOL_EXECUTABLE
+#
+#  The path to "devtool" command line client.
+#
+#  This variable is cached and may be configured if needed.
 #
 # Commands
 # ^^^^^^^^^
@@ -229,8 +292,8 @@
 #     cpack_ifw_configure_component(<compname> [COMMON] [ESSENTIAL] [VIRTUAL]
 #                         [FORCED_INSTALLATION] [REQUIRES_ADMIN_RIGHTS]
 #                         [NAME <name>]
-#                         [DISPLAY_NAME <display_name>]
-#                         [DESCRIPTION <description>]
+#                         [DISPLAY_NAME <display_name>] # Note: Internationalization supported
+#                         [DESCRIPTION <description>] # Note: Internationalization supported
 #                         [UPDATE_TEXT <update_text>]
 #                         [VERSION <version>]
 #                         [RELEASE_DATE <release_date>]
@@ -332,8 +395,8 @@
 #     cpack_ifw_configure_component_group(<groupname> [VIRTUAL]
 #                         [FORCED_INSTALLATION] [REQUIRES_ADMIN_RIGHTS]
 #                         [NAME <name>]
-#                         [DISPLAY_NAME <display_name>]
-#                         [DESCRIPTION <description>]
+#                         [DISPLAY_NAME <display_name>] # Note: Internationalization supported
+#                         [DESCRIPTION <description>] # Note: Internationalization supported
 #                         [UPDATE_TEXT <update_text>]
 #                         [VERSION <version>]
 #                         [RELEASE_DATE <release_date>]
@@ -510,8 +573,9 @@
 #
 #    cpack_add_component(myapp
 #        DISPLAY_NAME "MyApp"
-#        DESCRIPTION "My Application")
+#        DESCRIPTION "My Application") # Default description
 #    cpack_ifw_configure_component(myapp
+#        DESCRIPTION ru_RU "Мое Приложение" # Localized description
 #        VERSION "1.2.3" # Version of component
 #        SCRIPT "operations.qs")
 #    cpack_add_component(mybigplugin
@@ -568,7 +632,7 @@
 
 # Default path
 
-foreach(_CPACK_IFW_PATH_VAR "QTIFWDIR" "QTDIR")
+foreach(_CPACK_IFW_PATH_VAR "CPACK_IFW_ROOT" "QTIFWDIR" "QTDIR")
   if(DEFINED ${_CPACK_IFW_PATH_VAR}
     AND NOT "${${_CPACK_IFW_PATH_VAR}}" STREQUAL "")
     list(APPEND _CPACK_IFW_PATHS "${${_CPACK_IFW_PATH_VAR}}")
@@ -597,6 +661,10 @@ set(_CPACK_IFW_PREFIXES
   "QtIFW-")
 
 set(_CPACK_IFW_VERSIONS
+  "3.1"
+  "3.1.0"
+  "3.0"
+  "3.0.0"
   "2.3"
   "2.3.0"
   "2.2"
@@ -604,6 +672,7 @@ set(_CPACK_IFW_VERSIONS
   "2.1"
   "2.1.0"
   "2.0"
+  "2.0.5"
   "2.0.3"
   "2.0.2"
   "2.0.1"
@@ -676,21 +745,58 @@ set(CPackIFW_CMake_INCLUDED 1)
 # Framework version
 #=============================================================================
 
-if(CPACK_IFW_INSTALLERBASE_EXECUTABLE AND CPACK_IFW_DEVTOOL_EXECUTABLE)
-  execute_process(COMMAND
-    "${CPACK_IFW_INSTALLERBASE_EXECUTABLE}" --framework-version
-    OUTPUT_VARIABLE CPACK_IFW_FRAMEWORK_VERSION)
-  if(CPACK_IFW_FRAMEWORK_VERSION)
-    string(REPLACE " " ""
-      CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION}")
-    string(REPLACE "\t" ""
-      CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION}")
-    string(REPLACE "\n" ""
-      CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION}")
-    if(CPACK_IFW_VERBOSE)
-      message(STATUS "Found QtIFW ${CPACK_IFW_FRAMEWORK_VERSION} version")
+set(CPACK_IFW_FRAMEWORK_VERSION_FORCED ""
+  CACHE STRING "The forced version of used QtIFW tools")
+mark_as_advanced(CPACK_IFW_FRAMEWORK_VERSION_FORCED)
+set(CPACK_IFW_FRAMEWORK_VERSION_TIMEOUT 1
+  CACHE STRING "The timeout to return QtIFW framework version string from \"installerbase\" executable")
+mark_as_advanced(CPACK_IFW_FRAMEWORK_VERSION_TIMEOUT)
+if(CPACK_IFW_INSTALLERBASE_EXECUTABLE AND NOT CPACK_IFW_FRAMEWORK_VERSION_FORCED)
+  set(CPACK_IFW_FRAMEWORK_VERSION)
+  # Invoke version from "installerbase" executable
+  foreach(_ifw_version_argument --framework-version --version)
+    if(NOT CPACK_IFW_FRAMEWORK_VERSION)
+      execute_process(COMMAND
+        "${CPACK_IFW_INSTALLERBASE_EXECUTABLE}" ${_ifw_version_argument}
+        TIMEOUT ${CPACK_IFW_FRAMEWORK_VERSION_TIMEOUT}
+        RESULT_VARIABLE CPACK_IFW_FRAMEWORK_VERSION_RESULT
+        OUTPUT_VARIABLE CPACK_IFW_FRAMEWORK_VERSION_OUTPUT
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+        ENCODING UTF8)
+      if(NOT CPACK_IFW_FRAMEWORK_VERSION_RESULT AND CPACK_IFW_FRAMEWORK_VERSION_OUTPUT)
+        string(REGEX MATCH "[0-9]+(\\.[0-9]+)*"
+          CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_FRAMEWORK_VERSION_OUTPUT}")
+        if(CPACK_IFW_FRAMEWORK_VERSION)
+          if("${_ifw_version_argument}" STREQUAL "--framework-version")
+            set(CPACK_IFW_FRAMEWORK_VERSION_SOURCE "INSTALLERBASE_FRAMEWORK_VERSION")
+          elseif("${_ifw_version_argument}" STREQUAL "--version")
+            set(CPACK_IFW_FRAMEWORK_VERSION_SOURCE "INSTALLERBASE_FRAMEWORK_VERSION")
+          endif()
+        endif()
+      endif()
+    endif()
+  endforeach()
+  # Finaly try to get version from executable path
+  if(NOT CPACK_IFW_FRAMEWORK_VERSION)
+    string(REGEX MATCH "[0-9]+(\\.[0-9]+)*"
+      CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_INSTALLERBASE_EXECUTABLE}")
+    if(CPACK_IFW_FRAMEWORK_VERSION)
+      set(CPACK_IFW_FRAMEWORK_VERSION_SOURCE "INSTALLERBASE_PATH")
     endif()
   endif()
+elseif(CPACK_IFW_FRAMEWORK_VERSION_FORCED)
+  set(CPACK_IFW_FRAMEWORK_VERSION ${CPACK_IFW_FRAMEWORK_VERSION_FORCED})
+  set(CPACK_IFW_FRAMEWORK_VERSION_SOURCE "FORCED")
+endif()
+if(CPACK_IFW_VERBOSE)
+  if(CPACK_IFW_FRAMEWORK_VERSION AND CPACK_IFW_FRAMEWORK_VERSION_FORCED)
+    message(STATUS "Found QtIFW ${CPACK_IFW_FRAMEWORK_VERSION} (forced) version")
+  elseif(CPACK_IFW_FRAMEWORK_VERSION)
+    message(STATUS "Found QtIFW ${CPACK_IFW_FRAMEWORK_VERSION} version")
+  endif()
+endif()
+if(CPACK_IFW_INSTALLERBASE_EXECUTABLE AND NOT CPACK_IFW_FRAMEWORK_VERSION)
+  message(WARNING "Could not detect QtIFW tools version. Set used version to variable \"CPACK_IFW_FRAMEWORK_VERSION_FORCED\" manualy.")
 endif()
 
 #=============================================================================
@@ -757,8 +863,8 @@ macro(cpack_ifw_configure_component compname)
   string(TOUPPER ${compname} _CPACK_IFWCOMP_UNAME)
 
   set(_IFW_OPT COMMON ESSENTIAL VIRTUAL FORCED_INSTALLATION REQUIRES_ADMIN_RIGHTS)
-  set(_IFW_ARGS NAME DISPLAY_NAME DESCRIPTION VERSION RELEASE_DATE SCRIPT PRIORITY SORTING_PRIORITY UPDATE_TEXT DEFAULT)
-  set(_IFW_MULTI_ARGS DEPENDS DEPENDENCIES AUTO_DEPEND_ON LICENSES USER_INTERFACES TRANSLATIONS)
+  set(_IFW_ARGS NAME VERSION RELEASE_DATE SCRIPT PRIORITY SORTING_PRIORITY UPDATE_TEXT DEFAULT)
+  set(_IFW_MULTI_ARGS DISPLAY_NAME DESCRIPTION DEPENDS DEPENDENCIES AUTO_DEPEND_ON LICENSES USER_INTERFACES TRANSLATIONS)
   cmake_parse_arguments(CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME} "${_IFW_OPT}" "${_IFW_ARGS}" "${_IFW_MULTI_ARGS}" ${ARGN})
 
   _cpack_ifw_resolve_script(CPACK_IFW_COMPONENT_${_CPACK_IFWCOMP_UNAME}_SCRIPT)
@@ -798,8 +904,8 @@ macro(cpack_ifw_configure_component_group grpname)
   string(TOUPPER ${grpname} _CPACK_IFWGRP_UNAME)
 
   set(_IFW_OPT VIRTUAL FORCED_INSTALLATION REQUIRES_ADMIN_RIGHTS)
-  set(_IFW_ARGS NAME DISPLAY_NAME DESCRIPTION VERSION RELEASE_DATE SCRIPT PRIORITY SORTING_PRIORITY UPDATE_TEXT DEFAULT)
-  set(_IFW_MULTI_ARGS DEPENDS DEPENDENCIES AUTO_DEPEND_ON LICENSES USER_INTERFACES TRANSLATIONS)
+  set(_IFW_ARGS NAME VERSION RELEASE_DATE SCRIPT PRIORITY SORTING_PRIORITY UPDATE_TEXT DEFAULT)
+  set(_IFW_MULTI_ARGS DISPLAY_NAME DESCRIPTION DEPENDS DEPENDENCIES AUTO_DEPEND_ON LICENSES USER_INTERFACES TRANSLATIONS)
   cmake_parse_arguments(CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME} "${_IFW_OPT}" "${_IFW_ARGS}" "${_IFW_MULTI_ARGS}" ${ARGN})
 
   _cpack_ifw_resolve_script(CPACK_IFW_COMPONENT_GROUP_${_CPACK_IFWGRP_UNAME}_SCRIPT)
diff --git a/Modules/CPackProductBuild.cmake b/Modules/CPackProductBuild.cmake
index d545d3e..4779b95 100644
--- a/Modules/CPackProductBuild.cmake
+++ b/Modules/CPackProductBuild.cmake
@@ -46,3 +46,11 @@
 #
 #  Specify a specific keychain to search for the signing identity.
 #
+#
+# .. variable:: CPACK_PRODUCTBUILD_RESOURCES_DIR
+#
+#  If specified the productbuild generator copies files from this directory
+#  (including subdirectories) to the ``Resources`` directory. This is done
+#  before the :variable:`CPACK_RESOURCE_FILE_WELCOME`,
+#  :variable:`CPACK_RESOURCE_FILE_README`, and
+#  :variable:`CPACK_RESOURCE_FILE_LICENSE` files are copied.
diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake
index e905bc6..fa2a6e4 100644
--- a/Modules/CPackRPM.cmake
+++ b/Modules/CPackRPM.cmake
@@ -817,6 +817,30 @@
 #  is set then :variable:`CPACK_RPM_DEBUGINFO_PACKAGE` is automatically set to
 #  ``ON`` when :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` is set.
 #
+# .. variable:: CPACK_RPM_DEBUGINFO_FILE_NAME
+#               CPACK_RPM_<component>_DEBUGINFO_FILE_NAME
+#
+#  Debuginfo package file name.
+#
+#  * Mandatory : NO
+#  * Default   : rpmbuild tool generated package file name
+#
+#  Alternatively provided debuginfo package file name must end with ``.rpm``
+#  suffix and should differ from file names of other generated packages.
+#
+#  Variable may contain ``@cpack_component@`` placeholder which will be
+#  replaced by component name if component packaging is enabled otherwise it
+#  deletes the placeholder.
+#
+#  Setting the variable to ``RPM-DEFAULT`` may be used to explicitly set
+#  filename generation to default.
+#
+# .. note::
+#
+#  :variable:`CPACK_RPM_FILE_NAME` also supports rpmbuild tool generated package
+#  file name - disabled by default but can be enabled by setting the variable to
+#  ``RPM-DEFAULT``.
+#
 # Packaging of sources (SRPM)
 # ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 #
@@ -887,6 +911,19 @@
 #
 #  * Mandatory : YES
 #  * Default   : "/"
+#
+# .. VARIABLE:: CPACK_RPM_BUILDREQUIRES
+#
+#  List of source rpm build dependencies.
+#
+#  * Mandatory : NO
+#  * Default   : -
+#
+#  May be used to set source RPM build dependencies (BuildRequires). Note that
+#  you must enclose the complete build requirements string between quotes, for
+#  example::
+#
+#   set(CPACK_RPM_BUILDREQUIRES "python >= 2.5.0, cmake >= 2.8")
 
 # Author: Eric Noulard with the help of Alexander Neundorf.
 
@@ -950,10 +987,20 @@ function(cpack_rpm_prepare_relocation_paths)
   foreach(RELOCATION_PATH ${RPM_RELOCATION_PATHS})
     if(IS_ABSOLUTE "${RELOCATION_PATH}")
       set(PREPARED_RELOCATION_PATH "${RELOCATION_PATH}")
+    elseif(PATH_PREFIX STREQUAL "/")
+      # don't prefix path with a second slash as "//" is treated as network path
+      # by get_filename_component() so it remains in path even inside rpm
+      # package where it may cause problems with relocation
+      set(PREPARED_RELOCATION_PATH "/${RELOCATION_PATH}")
     else()
       set(PREPARED_RELOCATION_PATH "${PATH_PREFIX}/${RELOCATION_PATH}")
     endif()
 
+    # handle cases where path contains extra slashes (e.g. /a//b/ instead of
+    # /a/b)
+    get_filename_component(PREPARED_RELOCATION_PATH
+      "${PREPARED_RELOCATION_PATH}" ABSOLUTE)
+
     if(EXISTS "${WDIR}/${PREPARED_RELOCATION_PATH}")
       string(APPEND TMP_RPM_PREFIXES "Prefix: ${PREPARED_RELOCATION_PATH}\n")
       list(APPEND RPM_USED_PACKAGE_PREFIXES "${PREPARED_RELOCATION_PATH}")
@@ -1036,7 +1083,7 @@ function(cpack_rpm_prepare_content_list)
   endif()
 
   if(NOT DEFINED CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST)
-    set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST /etc /etc/init.d /usr /usr/share /usr/share/doc /usr/bin /usr/lib /usr/lib64 /usr/include)
+    set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST /etc /etc/init.d /usr /usr/share /usr/share/doc /usr/bin /usr/lib /usr/lib64 /usr/libx32 /usr/include)
     if(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION)
       if(CPACK_RPM_PACKAGE_DEBUG)
         message("CPackRPM:Debug: Adding ${CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION} to builtin omit list.")
@@ -2122,6 +2169,11 @@ function(cpack_rpm_generate_package)
       set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/usr/src/debug/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}")
     endif()
 
+    # handle cases where path contains extra slashes (e.g. /a//b/ instead of
+    # /a/b)
+    get_filename_component(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX
+      "${CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX}" ABSOLUTE)
+
     if(CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE AND GENERATE_SPEC_PARTS)
       file(WRITE "${CPACK_RPM_ROOTDIR}/SPECS/${CPACK_RPM_PACKAGE_COMPONENT}.files"
         "${CPACK_RPM_INSTALL_FILES}")
@@ -2625,11 +2677,27 @@ mv %_topdir/tmpBBroot $RPM_BUILD_ROOT
     unset(expected_filenames_)
     unset(filenames_)
     if(CPACK_RPM_DEBUGINFO_PACKAGE AND NOT CPACK_RPM_FILE_NAME STREQUAL "RPM-DEFAULT")
-      string(TOLOWER "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm" efn_)
-      list(APPEND expected_filenames_ "${efn_}")
+      list(APPEND expected_filenames_
+        "${CPACK_RPM_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.*\\.rpm")
       list(APPEND filenames_ "${CPACK_RPM_FILE_NAME}")
     endif()
 
+    if(CPACK_RPM_DEBUGINFO_PACKAGE)
+      cpack_rpm_variable_fallback("CPACK_RPM_DEBUGINFO_FILE_NAME"
+        "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_DEBUGINFO_FILE_NAME"
+        "CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT_UPPER}_DEBUGINFO_FILE_NAME"
+        "CPACK_RPM_DEBUGINFO_FILE_NAME")
+
+      if(CPACK_RPM_DEBUGINFO_FILE_NAME AND
+        NOT CPACK_RPM_DEBUGINFO_FILE_NAME STREQUAL "RPM-DEFAULT")
+        list(APPEND expected_filenames_
+          "${CPACK_RPM_PACKAGE_NAME}-debuginfo-${CPACK_PACKAGE_VERSION}.*\\.rpm")
+        string(REPLACE "@cpack_component@" "${CPACK_RPM_PACKAGE_COMPONENT}"
+          CPACK_RPM_DEBUGINFO_FILE_NAME "${CPACK_RPM_DEBUGINFO_FILE_NAME}")
+        list(APPEND filenames_ "${CPACK_RPM_DEBUGINFO_FILE_NAME}")
+      endif()
+    endif()
+
     # check if other files have to be renamed
     file(GLOB rename_files_ "${CPACK_RPM_DIRECTORY}/SPECS/*.rpm_name")
     if(rename_files_)
diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake
index 0f2278f..1dc37d4 100644
--- a/Modules/CPackWIX.cmake
+++ b/Modules/CPackWIX.cmake
@@ -243,20 +243,20 @@
 #
 # .. variable:: CPACK_WIX_ROOT_FEATURE_TITLE
 #
-# Sets the name of the root install feature in the WIX installer. Same as
-# CPACK_COMPONENT_<compName>_DISPLAY_NAME for components.
+#  Sets the name of the root install feature in the WIX installer. Same as
+#  CPACK_COMPONENT_<compName>_DISPLAY_NAME for components.
 #
 # .. variable:: CPACK_WIX_ROOT_FEATURE_DESCRIPTION
 #
-# Sets the description of the root install feature in the WIX installer. Same as
-# CPACK_COMPONENT_<compName>_DESCRIPTION for components.
+#  Sets the description of the root install feature in the WIX installer. Same as
+#  CPACK_COMPONENT_<compName>_DESCRIPTION for components.
 #
 # .. variable:: CPACK_WIX_SKIP_PROGRAM_FOLDER
 #
-# If this variable is set to true, the default install location
-# of the generated package will be CPACK_PACKAGE_INSTALL_DIRECTORY directly.
-# The install location will not be located relatively below
-# ProgramFiles or ProgramFiles64.
+#  If this variable is set to true, the default install location
+#  of the generated package will be CPACK_PACKAGE_INSTALL_DIRECTORY directly.
+#  The install location will not be located relatively below
+#  ProgramFiles or ProgramFiles64.
 #
 #   .. note::
 #     Installers created with this feature do not take differences
@@ -268,6 +268,25 @@
 #     follow the localization or convention of the system on which the
 #     installation is performed.
 #
+# .. variable:: CPACK_WIX_ROOT_FOLDER_ID
+#
+#  This variable allows specification of a custom root folder ID.
+#  The generator specific ``<64>`` token can be used for
+#  folder IDs that come in 32-bit and 64-bit variants.
+#  In 32-bit builds the token will expand empty while in 64-bit builds
+#  it will expand to ``64``.
+#
+#  When unset generated installers will default installing to
+#  ``ProgramFiles<64>Folder``.
+#
+# .. variable:: CPACK_WIX_ROOT
+#
+#  This variable can optionally be set to the root directory
+#  of a custom WiX Toolset installation.
+#
+#  When unspecified CPack will try to locate a WiX Toolset
+#  installation via the ``WIX`` environment variable instead.
+#
 
 if(NOT CPACK_WIX_ROOT)
   file(TO_CMAKE_PATH "$ENV{WIX}" CPACK_WIX_ROOT)
diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake
index 7aeb5be..9370596 100644
--- a/Modules/CTest.cmake
+++ b/Modules/CTest.cmake
@@ -54,15 +54,11 @@ in the ``CTestConfig.cmake`` file.
 option(BUILD_TESTING "Build the testing tree." ON)
 
 # function to turn generator name into a version string
-# like vs7 vs71 vs8 vs9
+# like vs8 vs9
 function(GET_VS_VERSION_STRING generator var)
   string(REGEX REPLACE "Visual Studio ([0-9][0-9]?)($|.*)" "\\1"
     NUMBER "${generator}")
-  if("${generator}" MATCHES "Visual Studio 7 .NET 2003")
-    set(ver_string "vs71")
-  else()
     set(ver_string "vs${NUMBER}")
-  endif()
   set(${var} ${ver_string} PARENT_SCOPE)
 endfunction()
 
diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake
new file mode 100644
index 0000000..e04ab1c
--- /dev/null
+++ b/Modules/CheckIPOSupported.cmake
@@ -0,0 +1,232 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckIPOSupported
+-----------------
+
+Check whether the compiler supports an interprocedural optimization (IPO/LTO).
+Use this before enabling the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target
+property.
+
+.. command:: check_ipo_supported
+
+  ::
+
+    check_ipo_supported([RESULT <result>] [OUTPUT <output>]
+                        [LANGUAGES <lang>...])
+
+  Options are:
+
+  ``RESULT <result>``
+    Set ``<result>`` variable to ``YES`` if IPO is supported by the
+    compiler and ``NO`` otherwise.  If this option is not given then
+    the command will issue a fatal error if IPO is not supported.
+  ``OUTPUT <output>``
+    Set ``<output>`` variable with details about any error.
+  ``LANGUAGES <lang>...``
+    Specify languages whose compilers to check.
+    Languages ``C`` and ``CXX`` are supported.
+
+It makes no sense to use this module when :policy:`CMP0069` is set to ``OLD`` so
+module will return error in this case. See policy :policy:`CMP0069` for details.
+
+Examples
+^^^^^^^^
+
+.. code-block:: cmake
+
+  check_ipo_supported() # fatal error if IPO is not supported
+  set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+
+.. code-block:: cmake
+
+  # Optional IPO. Do not use IPO if it's not supported by compiler.
+  check_ipo_supported(RESULT result OUTPUT output)
+  if(result)
+    set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+  else()
+    message(WARNING "IPO is not supported: ${output}")
+  endif()
+
+#]=======================================================================]
+
+include(CMakeParseArguments) # cmake_parse_arguments
+
+# X_RESULT - name of the final result variable
+# X_OUTPUT - name of the variable with information about error
+macro(_ipo_not_supported output)
+  string(COMPARE EQUAL "${X_RESULT}" "" is_empty)
+  if(is_empty)
+    message(FATAL_ERROR "IPO is not supported (${output}).")
+  endif()
+
+  set("${X_RESULT}" NO PARENT_SCOPE)
+  set("${X_OUTPUT}" "${output}" PARENT_SCOPE)
+endmacro()
+
+# Run IPO/LTO test
+macro(_ipo_run_language_check language)
+  set(testdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/_CMakeLTOTest-${language}")
+
+  file(REMOVE_RECURSE "${testdir}")
+  file(MAKE_DIRECTORY "${testdir}")
+
+  set(bindir "${testdir}/bin")
+  set(srcdir "${testdir}/src")
+
+  file(MAKE_DIRECTORY "${bindir}")
+  file(MAKE_DIRECTORY "${srcdir}")
+
+  set(TRY_COMPILE_PROJECT_NAME "lto-test")
+
+  set(try_compile_src "${CMAKE_ROOT}/Modules/CheckIPOSupported")
+
+  # Use:
+  # * TRY_COMPILE_PROJECT_NAME
+  # * CMAKE_VERSION
+  configure_file(
+      "${try_compile_src}/CMakeLists-${language}.txt.in"
+      "${srcdir}/CMakeLists.txt"
+      @ONLY
+  )
+
+  string(COMPARE EQUAL "${language}" "C" is_c)
+  string(COMPARE EQUAL "${language}" "CXX" is_cxx)
+  string(COMPARE EQUAL "${language}" "Fortran" is_fortran)
+
+  if(is_c)
+    set(copy_sources foo.c main.c)
+  elseif(is_cxx)
+    set(copy_sources foo.cpp main.cpp)
+  elseif(is_fortran)
+    set(copy_sources foo.f main.f)
+  else()
+    message(FATAL_ERROR "Language not supported")
+  endif()
+
+  foreach(x ${copy_sources})
+    configure_file(
+        "${try_compile_src}/${x}"
+        "${srcdir}/${x}"
+        COPYONLY
+    )
+  endforeach()
+
+  try_compile(
+      result
+      "${bindir}"
+      "${srcdir}"
+      "${TRY_COMPILE_PROJECT_NAME}"
+      CMAKE_FLAGS
+      "-DCMAKE_VERBOSE_MAKEFILE=ON"
+      "-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON"
+      OUTPUT_VARIABLE output
+  )
+
+  if(NOT result)
+    _ipo_not_supported("${output}")
+    return()
+  endif()
+endmacro()
+
+function(check_ipo_supported)
+  cmake_policy(GET CMP0069 x)
+
+  string(COMPARE EQUAL "${x}" "" not_set)
+  if(not_set)
+    message(FATAL_ERROR "Policy CMP0069 is not set")
+  endif()
+
+  string(COMPARE EQUAL "${x}" "OLD" is_old)
+  if(is_old)
+    message(FATAL_ERROR "Policy CMP0069 set to OLD")
+  endif()
+
+  set(optional)
+  set(one RESULT OUTPUT)
+  set(multiple LANGUAGES)
+
+  # Introduce:
+  # * X_RESULT
+  # * X_OUTPUT
+  # * X_LANGUAGES
+  cmake_parse_arguments(X "${optional}" "${one}" "${multiple}" "${ARGV}")
+
+  string(COMPARE NOTEQUAL "${X_UNPARSED_ARGUMENTS}" "" has_unparsed)
+  if(has_unparsed)
+    message(FATAL_ERROR "Unparsed arguments: ${X_UNPARSED_ARGUMENTS}")
+  endif()
+
+  string(COMPARE EQUAL "${X_LANGUAGES}" "" no_languages)
+  if(no_languages)
+    # User did not set any languages, use defaults
+    get_property(enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
+    string(COMPARE EQUAL "${enabled_languages}" "" no_languages)
+    if(no_languages)
+      _ipo_not_supported(
+          "no languages found in ENABLED_LANGUAGES global property"
+      )
+      return()
+    endif()
+
+    set(languages "")
+    list(FIND enabled_languages "CXX" result)
+    if(NOT result EQUAL -1)
+      list(APPEND languages "CXX")
+    endif()
+
+    list(FIND enabled_languages "C" result)
+    if(NOT result EQUAL -1)
+      list(APPEND languages "C")
+    endif()
+
+    list(FIND enabled_languages "Fortran" result)
+    if(NOT result EQUAL -1)
+      list(APPEND languages "Fortran")
+    endif()
+
+    string(COMPARE EQUAL "${languages}" "" no_languages)
+    if(no_languages)
+      _ipo_not_supported(
+          "no C/CXX/Fortran languages found in ENABLED_LANGUAGES global property"
+      )
+      return()
+    endif()
+  else()
+    set(languages "${X_LANGUAGES}")
+
+    set(unsupported_languages "${languages}")
+    list(REMOVE_ITEM unsupported_languages "C" "CXX" "Fortran")
+    string(COMPARE NOTEQUAL "${unsupported_languages}" "" has_unsupported)
+    if(has_unsupported)
+      _ipo_not_supported(
+          "language(s) '${unsupported_languages}' not supported"
+      )
+      return()
+    endif()
+  endif()
+
+  foreach(lang ${languages})
+    if(NOT _CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE)
+      _ipo_not_supported("CMake doesn't support IPO for current ${lang} compiler")
+      return()
+    endif()
+
+    if(NOT _CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER)
+      _ipo_not_supported("${lang} compiler doesn't support IPO")
+      return()
+    endif()
+  endforeach()
+
+  if(CMAKE_GENERATOR MATCHES "^Visual Studio ")
+    _ipo_not_supported("CMake doesn't support IPO for current generator")
+    return()
+  endif()
+
+  foreach(x ${languages})
+    _ipo_run_language_check(${x})
+  endforeach()
+
+  set("${X_RESULT}" YES PARENT_SCOPE)
+endfunction()
diff --git a/Modules/CheckIPOSupported/CMakeLists-C.txt.in b/Modules/CheckIPOSupported/CMakeLists-C.txt.in
new file mode 100644
index 0000000..5a3b8ee
--- /dev/null
+++ b/Modules/CheckIPOSupported/CMakeLists-C.txt.in
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION "@CMAKE_VERSION@")
+project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES C)
+
+cmake_policy(SET CMP0069 NEW)
+
+add_library(foo foo.c)
+add_executable(boo main.c)
+target_link_libraries(boo PUBLIC foo)
diff --git a/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in b/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in
new file mode 100644
index 0000000..30993fa
--- /dev/null
+++ b/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION "@CMAKE_VERSION@")
+project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES CXX)
+
+cmake_policy(SET CMP0069 NEW)
+
+add_library(foo foo.cpp)
+add_executable(boo main.cpp)
+target_link_libraries(boo PUBLIC foo)
diff --git a/Modules/CheckIPOSupported/CMakeLists-Fortran.txt.in b/Modules/CheckIPOSupported/CMakeLists-Fortran.txt.in
new file mode 100644
index 0000000..9fab077
--- /dev/null
+++ b/Modules/CheckIPOSupported/CMakeLists-Fortran.txt.in
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION "@CMAKE_VERSION@")
+project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES Fortran)
+
+cmake_policy(SET CMP0069 NEW)
+
+add_library(foo foo.f)
+add_executable(boo main.f)
+target_link_libraries(boo PUBLIC foo)
diff --git a/Modules/CheckIPOSupported/foo.c b/Modules/CheckIPOSupported/foo.c
new file mode 100644
index 0000000..1e56597
--- /dev/null
+++ b/Modules/CheckIPOSupported/foo.c
@@ -0,0 +1,4 @@
+int foo()
+{
+  return 0x42;
+}
diff --git a/Modules/CheckIPOSupported/foo.cpp b/Modules/CheckIPOSupported/foo.cpp
new file mode 100644
index 0000000..1e56597
--- /dev/null
+++ b/Modules/CheckIPOSupported/foo.cpp
@@ -0,0 +1,4 @@
+int foo()
+{
+  return 0x42;
+}
diff --git a/Modules/CheckIPOSupported/foo.f b/Modules/CheckIPOSupported/foo.f
new file mode 100644
index 0000000..945d2d5
--- /dev/null
+++ b/Modules/CheckIPOSupported/foo.f
@@ -0,0 +1,2 @@
+	SUBROUTINE FOO
+	END
diff --git a/Modules/CheckIPOSupported/main.c b/Modules/CheckIPOSupported/main.c
new file mode 100644
index 0000000..5be0864
--- /dev/null
+++ b/Modules/CheckIPOSupported/main.c
@@ -0,0 +1,6 @@
+int foo();
+
+int main()
+{
+  return foo();
+}
diff --git a/Modules/CheckIPOSupported/main.cpp b/Modules/CheckIPOSupported/main.cpp
new file mode 100644
index 0000000..5be0864
--- /dev/null
+++ b/Modules/CheckIPOSupported/main.cpp
@@ -0,0 +1,6 @@
+int foo();
+
+int main()
+{
+  return foo();
+}
diff --git a/Modules/CheckIPOSupported/main.f b/Modules/CheckIPOSupported/main.f
new file mode 100644
index 0000000..9d1de9f
--- /dev/null
+++ b/Modules/CheckIPOSupported/main.f
@@ -0,0 +1,3 @@
+	PROGRAM BOO
+	CALL FOO()
+	END
diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake
index 6b4a9e4..1ea91d2 100644
--- a/Modules/CheckLanguage.cmake
+++ b/Modules/CheckLanguage.cmake
@@ -46,6 +46,8 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
     execute_process(
       WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}
       COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
+                                 -A "${CMAKE_GENERATOR_PLATFORM}"
+                                 -T "${CMAKE_GENERATOR_TOOLSET}"
       OUTPUT_VARIABLE output
       ERROR_VARIABLE output
       RESULT_VARIABLE result
diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake
index 8fecc57..6f1afcf 100644
--- a/Modules/CheckSymbolExists.cmake
+++ b/Modules/CheckSymbolExists.cmake
@@ -1,38 +1,47 @@
 # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 # file Copyright.txt or https://cmake.org/licensing for details.
 
-#.rst:
-# CheckSymbolExists
-# -----------------
-#
-# Check if a symbol exists as a function, variable, or macro
-#
-# CHECK_SYMBOL_EXISTS(<symbol> <files> <variable>)
-#
-# Check that the <symbol> is available after including given header
-# <files> and store the result in a <variable>.  Specify the list of
-# files in one argument as a semicolon-separated list.
-# <variable> will be created as an internal cache variable.
-#
-# If the header files define the symbol as a macro it is considered
-# 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.  If the symbol is a type or enum value it will not be
-# recognized (consider using CheckTypeSize or CheckCSourceCompiles).  If
-# the check needs to be done in C++, consider using
-# CHECK_CXX_SYMBOL_EXISTS(), which does the same as
-# CHECK_SYMBOL_EXISTS(), but in C++.
-#
-# The following variables may be set before calling this macro to modify
-# the way the check is run:
-#
-# ::
-#
-#   CMAKE_REQUIRED_FLAGS = string of compile command line flags
-#   CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
-#   CMAKE_REQUIRED_INCLUDES = list of include directories
-#   CMAKE_REQUIRED_LIBRARIES = list of libraries to link
-#   CMAKE_REQUIRED_QUIET = execute quietly without messages
+#[=======================================================================[.rst:
+CheckSymbolExists
+-----------------
+
+Provides a macro to check if a symbol exists as a function, variable,
+or macro in ``C``.
+
+.. command:: check_symbol_exists
+
+  ::
+
+    check_symbol_exists(<symbol> <files> <variable>)
+
+  Check that the ``<symbol>`` is available after including given header
+  ``<files>`` and store the result in a ``<variable>``.  Specify the list
+  of files in one argument as a semicolon-separated list.
+  ``<variable>`` will be created as an internal cache variable.
+
+If the header files define the symbol as a macro it is considered
+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`).
+If the check needs to be done in C++, consider using
+:module:`CheckCXXSymbolExists` instead.
+
+The following variables may be set before calling this macro to modify
+the way the check is run:
+
+``CMAKE_REQUIRED_FLAGS``
+  string of compile command line flags
+``CMAKE_REQUIRED_DEFINITIONS``
+  list of macros to define (-DFOO=bar)
+``CMAKE_REQUIRED_INCLUDES``
+  list of include directories
+``CMAKE_REQUIRED_LIBRARIES``
+  list of libraries to link
+``CMAKE_REQUIRED_QUIET``
+  execute quietly without messages
+#]=======================================================================]
 
 macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE)
   if(CMAKE_C_COMPILER_LOADED)
diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake
index 4b3e223..fcf1df7 100644
--- a/Modules/CheckTypeSize.cmake
+++ b/Modules/CheckTypeSize.cmake
@@ -247,10 +247,10 @@ macro(CHECK_TYPE_SIZE TYPE VARIABLE)
     set(${VARIABLE}_CODE)
     set(_if if)
     foreach(key ${${VARIABLE}_KEYS})
-      set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#${_if} defined(${key})\n# define ${VARIABLE} ${${VARIABLE}-${key}}\n")
+      string(APPEND ${VARIABLE}_CODE "#${_if} defined(${key})\n# define ${VARIABLE} ${${VARIABLE}-${key}}\n")
       set(_if elif)
     endforeach()
-    set(${VARIABLE}_CODE "${${VARIABLE}_CODE}#else\n# error ${VARIABLE} unknown\n#endif")
+    string(APPEND ${VARIABLE}_CODE "#else\n# error ${VARIABLE} unknown\n#endif")
     set(_if)
   elseif(${VARIABLE})
     set(${VARIABLE}_CODE "#define ${VARIABLE} ${${VARIABLE}}")
diff --git a/Modules/Compiler/AppleClang-C.cmake b/Modules/Compiler/AppleClang-C.cmake
index f874e74..a48adec 100644
--- a/Modules/Compiler/AppleClang-C.cmake
+++ b/Modules/Compiler/AppleClang-C.cmake
@@ -12,29 +12,4 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0)
   set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
 endif()
 
-if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0)
-  if (NOT CMAKE_C_COMPILER_FORCED)
-    if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT)
-      message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}")
-    endif()
-    set(CMAKE_C_STANDARD_DEFAULT ${CMAKE_C_STANDARD_COMPUTED_DEFAULT})
-  elseif(NOT DEFINED CMAKE_C_STANDARD_DEFAULT)
-    # Compiler id was forced so just guess the default standard level.
-    set(CMAKE_C_STANDARD_DEFAULT 99)
-  endif()
-endif()
-
-macro(cmake_record_c_compile_features)
-  set(_result 0)
-  if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0)
-    if (_result EQUAL 0)
-      _record_compiler_features_c(11)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_c(99)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_c(90)
-    endif()
-  endif()
-endmacro()
+__compiler_check_default_language_standard(C 4.0 99)
diff --git a/Modules/Compiler/AppleClang-CXX.cmake b/Modules/Compiler/AppleClang-CXX.cmake
index ee900ae..e5fd647 100644
--- a/Modules/Compiler/AppleClang-CXX.cmake
+++ b/Modules/Compiler/AppleClang-CXX.cmake
@@ -27,33 +27,4 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.1)
   set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
 endif()
 
-if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0)
-  if (NOT CMAKE_CXX_COMPILER_FORCED)
-    if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT)
-      message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}")
-    endif()
-    set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT})
-  elseif(NOT DEFINED CMAKE_CXX_STANDARD_DEFAULT)
-    # Compiler id was forced so just guess the default standard level.
-    set(CMAKE_CXX_STANDARD_DEFAULT 98)
-  endif()
-endif()
-
-
-macro(cmake_record_cxx_compile_features)
-  set(_result 0)
-  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0)
-    if(_result EQUAL 0 AND CMAKE_CXX17_STANDARD_COMPILE_OPTION)
-      _record_compiler_features_cxx(17)
-    endif()
-    if(_result EQUAL 0 AND CMAKE_CXX14_STANDARD_COMPILE_OPTION)
-      _record_compiler_features_cxx(14)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_cxx(11)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_cxx(98)
-    endif()
-  endif()
-endmacro()
+__compiler_check_default_language_standard(CXX 4.0 98)
diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake
new file mode 100644
index 0000000..684fd30
--- /dev/null
+++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake
@@ -0,0 +1,93 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# This module is shared by multiple languages and compilers; use include guard
+if (__COMPILER_CMAKE_COMMON_COMPILER_MACROS)
+  return()
+endif ()
+set(__COMPILER_CMAKE_COMMON_COMPILER_MACROS 1)
+
+
+# Check that a compiler's language standard is properly detected
+# Parameters:
+#   lang   - Language to check
+#   stdver1 - Minimum version to set a given default for
+#   std1    - Default to use for compiler ver >= stdver1
+#   stdverN - Minimum version to set a given default for
+#   stdN    - Default to use for compiler ver >= stdverN
+#
+#   The order of stdverN stdN pairs passed as arguments is expected to be in
+#   monotonically increasing version order.
+#
+# Note:
+#   This macro can be called with multiple version / std pairs to convey that
+#   newer compiler versions may use a newer standard default.
+#
+# Example:
+#   To specify that compiler version 6.1 and newer defaults to C++11 while
+#   4.8 <= ver < 6.1 default to C++98, you would call:
+#
+# __compiler_check_default_language_standard(CXX 4.8 98 6.1 11)
+#
+macro(__compiler_check_default_language_standard lang stdver1 std1)
+  set(__std_ver_pairs "${stdver1};${std1};${ARGN}")
+  string(REGEX REPLACE " *; *" " " __std_ver_pairs "${__std_ver_pairs}")
+  string(REGEX MATCHALL "[^ ]+ [^ ]+" __std_ver_pairs "${__std_ver_pairs}")
+
+  # If the compiler version is below the threshold of even having CMake
+  # support for language standards, then don't bother.
+  if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL "${stdver1}")
+    if (NOT CMAKE_${lang}_COMPILER_FORCED)
+      if (NOT CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT)
+        message(FATAL_ERROR "CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_${lang}_COMPILER_ID} (${CMAKE_${lang}_COMPILER}) version ${CMAKE_${lang}_COMPILER_VERSION}")
+      endif ()
+      set(CMAKE_${lang}_STANDARD_DEFAULT ${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT})
+    else ()
+      list(REVERSE __std_ver_pairs)
+      foreach (__std_ver_pair IN LISTS __std_ver_pairs)
+        string(REGEX MATCH "([^ ]+) (.+)" __std_ver_pair "${__std_ver_pair}")
+        set(__stdver ${CMAKE_MATCH_1})
+        set(__std ${CMAKE_MATCH_2})
+        if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL __stdver AND
+          NOT DEFINED CMAKE_${lang}_STANDARD_DEFAULT)
+          # Compiler id was forced so just guess the default standard level.
+          set(CMAKE_${lang}_STANDARD_DEFAULT ${__std})
+        endif ()
+        unset(__std)
+        unset(__stdver)
+      endforeach ()
+    endif ()
+  endif ()
+  unset(__std_ver_pairs)
+endmacro()
+
+# Define to allow compile features to be automatically determined
+macro(cmake_record_c_compile_features)
+  set(_result 0)
+  if(_result EQUAL 0 AND DEFINED CMAKE_C11_STANDARD_COMPILE_OPTION)
+    _record_compiler_features_c(11)
+  endif()
+  if(_result EQUAL 0 AND DEFINED CMAKE_C99_STANDARD_COMPILE_OPTION)
+    _record_compiler_features_c(99)
+  endif()
+  if(_result EQUAL 0 AND DEFINED CMAKE_C90_STANDARD_COMPILE_OPTION)
+    _record_compiler_features_c(90)
+  endif()
+endmacro()
+
+# Define to allow compile features to be automatically determined
+macro(cmake_record_cxx_compile_features)
+  set(_result 0)
+  if(_result EQUAL 0 AND DEFINED CMAKE_CXX17_STANDARD_COMPILE_OPTION)
+    _record_compiler_features_cxx(17)
+  endif()
+  if(_result EQUAL 0 AND DEFINED CMAKE_CXX14_STANDARD_COMPILE_OPTION)
+    _record_compiler_features_cxx(14)
+  endif()
+  if(_result EQUAL 0 AND DEFINED CMAKE_CXX11_STANDARD_COMPILE_OPTION)
+    _record_compiler_features_cxx(11)
+  endif()
+  if(_result EQUAL 0 AND DEFINED CMAKE_CXX98_STANDARD_COMPILE_OPTION)
+    _record_compiler_features_cxx(98)
+  endif()
+endmacro()
diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake
index bcd9218..b881e2b 100644
--- a/Modules/Compiler/Clang-C.cmake
+++ b/Modules/Compiler/Clang-C.cmake
@@ -17,33 +17,4 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
   set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
 endif()
 
-if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
-  if (NOT CMAKE_C_COMPILER_FORCED)
-    if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT)
-      message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}")
-    endif()
-    set(CMAKE_C_STANDARD_DEFAULT ${CMAKE_C_STANDARD_COMPUTED_DEFAULT})
-  elseif(NOT DEFINED CMAKE_C_STANDARD_DEFAULT)
-    # Compiler id was forced so just guess the default standard level.
-    if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6)
-      set(CMAKE_C_STANDARD_DEFAULT 11)
-    else()
-      set(CMAKE_C_STANDARD_DEFAULT 99)
-    endif()
-  endif()
-endif()
-
-macro(cmake_record_c_compile_features)
-  set(_result 0)
-  if (UNIX AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
-    if (_result EQUAL 0)
-      _record_compiler_features_c(11)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_c(99)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_c(90)
-    endif()
-  endif()
-endmacro()
+__compiler_check_default_language_standard(C 3.4 99 3.6 11)
diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake
index 8ed3695..d3707ee 100644
--- a/Modules/Compiler/Clang-CXX.cmake
+++ b/Modules/Compiler/Clang-CXX.cmake
@@ -36,32 +36,4 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
   set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
 endif()
 
-if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1)
-  if (NOT CMAKE_CXX_COMPILER_FORCED)
-    if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT)
-      message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}")
-    endif()
-    set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT})
-  elseif(NOT DEFINED CMAKE_CXX_STANDARD_DEFAULT)
-    # Compiler id was forced so just guess the default standard level.
-    set(CMAKE_CXX_STANDARD_DEFAULT 98)
-  endif()
-endif()
-
-macro(cmake_record_cxx_compile_features)
-  set(_result 0)
-  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1)
-    if(_result EQUAL 0 AND CMAKE_CXX17_STANDARD_COMPILE_OPTION)
-      _record_compiler_features_cxx(17)
-    endif()
-    if(_result EQUAL 0 AND CMAKE_CXX14_STANDARD_COMPILE_OPTION)
-      _record_compiler_features_cxx(14)
-    endif()
-    if (_result EQUAL 0 AND CMAKE_CXX11_STANDARD_COMPILE_OPTION)
-      _record_compiler_features_cxx(11)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_cxx(98)
-    endif()
-  endif()
-endmacro()
+__compiler_check_default_language_standard(CXX 2.1 98)
diff --git a/Modules/Compiler/Clang-FindBinUtils.cmake b/Modules/Compiler/Clang-FindBinUtils.cmake
new file mode 100644
index 0000000..e2822a1
--- /dev/null
+++ b/Modules/Compiler/Clang-FindBinUtils.cmake
@@ -0,0 +1,27 @@
+if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "")
+  message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
+endif()
+
+# Try to find tools in the same directory as Clang itself
+get_filename_component(__clang_hint_1 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" REALPATH)
+get_filename_component(__clang_hint_1 "${__clang_hint_1}" DIRECTORY)
+
+get_filename_component(__clang_hint_2 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY)
+
+set(__clang_hints ${__clang_hint_1} ${__clang_hint_2})
+
+# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ar.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar"
+    HINTS ${__clang_hints}
+    DOC "LLVM archiver"
+)
+mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR)
+
+# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ranlib.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib"
+    HINTS ${__clang_hints}
+    DOC "Generate index for LLVM archive"
+)
+mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB)
diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake
index 96263fc..7d476f9 100644
--- a/Modules/Compiler/Clang.cmake
+++ b/Modules/Compiler/Clang.cmake
@@ -8,6 +8,8 @@ if(__COMPILER_CLANG)
 endif()
 set(__COMPILER_CLANG 1)
 
+include(Compiler/CMakeCommonCompilerMacros)
+
 if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC"
     OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
   macro(__compiler_clang lang)
@@ -27,5 +29,55 @@ else()
       set(CMAKE_${lang}_COMPILE_OPTIONS_TARGET "--target=")
       set(CMAKE_${lang}_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "--gcc-toolchain=")
     endif()
+
+    set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+    set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+
+    string(COMPARE EQUAL "${CMAKE_${lang}_COMPILER_ID}" "AppleClang" __is_apple_clang)
+
+    # '-flto=thin' available since Clang 3.9 and Xcode 8
+    # * http://clang.llvm.org/docs/ThinLTO.html#clang-llvm
+    # * https://trac.macports.org/wiki/XcodeVersionInfo
+    set(_CMAKE_LTO_THIN TRUE)
+    if(__is_apple_clang)
+      if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 8.0)
+        set(_CMAKE_LTO_THIN FALSE)
+      endif()
+    else()
+      if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.9)
+        set(_CMAKE_LTO_THIN FALSE)
+      endif()
+    endif()
+
+    if(_CMAKE_LTO_THIN)
+      set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin")
+    else()
+      set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto")
+    endif()
+
+    if(ANDROID)
+      # https://github.com/android-ndk/ndk/issues/242
+      set(CMAKE_${lang}_LINK_OPTIONS_IPO "-fuse-ld=gold")
+    endif()
+
+    if(ANDROID OR __is_apple_clang)
+      set(__ar "${CMAKE_AR}")
+      set(__ranlib "${CMAKE_RANLIB}")
+    else()
+      set(__ar "${CMAKE_${lang}_COMPILER_AR}")
+      set(__ranlib "${CMAKE_${lang}_COMPILER_RANLIB}")
+    endif()
+
+    set(CMAKE_${lang}_ARCHIVE_CREATE_IPO
+      "${__ar} cr <TARGET> <LINK_FLAGS> <OBJECTS>"
+    )
+
+    set(CMAKE_${lang}_ARCHIVE_APPEND_IPO
+      "${__ar} r <TARGET> <LINK_FLAGS> <OBJECTS>"
+    )
+
+    set(CMAKE_${lang}_ARCHIVE_FINISH_IPO
+      "${__ranlib} <TARGET>"
+    )
   endmacro()
 endif()
diff --git a/Modules/Compiler/Cray-C.cmake b/Modules/Compiler/Cray-C.cmake
index 675560c..87ce20f 100644
--- a/Modules/Compiler/Cray-C.cmake
+++ b/Modules/Compiler/Cray-C.cmake
@@ -1 +1,22 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+include(Compiler/Cray)
+
 set(CMAKE_C_VERBOSE_FLAG "-v")
+
+string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
+string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG")
+
+if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1)
+  set(CMAKE_C90_STANDARD_COMPILE_OPTION  -h noc99,conform)
+  set(CMAKE_C90_EXTENSION_COMPILE_OPTION -h noc99,gnu)
+  set(CMAKE_C99_STANDARD_COMPILE_OPTION  -h c99,conform)
+  set(CMAKE_C99_EXTENSION_COMPILE_OPTION -h c99,gnu)
+  if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.5)
+    set(CMAKE_C11_STANDARD_COMPILE_OPTION  -h std=c11,conform)
+    set(CMAKE_C11_EXTENSION_COMPILE_OPTION -h std=c11,gnu)
+  endif ()
+endif ()
+
+__compiler_check_default_language_standard(C 8.1 99)
diff --git a/Modules/Compiler/Cray-CXX.cmake b/Modules/Compiler/Cray-CXX.cmake
index 9fb191c..8506c09 100644
--- a/Modules/Compiler/Cray-CXX.cmake
+++ b/Modules/Compiler/Cray-CXX.cmake
@@ -1 +1,20 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+include(Compiler/Cray)
+
 set(CMAKE_CXX_VERBOSE_FLAG "-v")
+
+string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
+string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -DNDEBUG")
+
+if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.1)
+  set(CMAKE_CXX98_STANDARD_COMPILE_OPTION  -h conform)
+  set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION -h gnu)
+  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.4)
+    set(CMAKE_CXX11_STANDARD_COMPILE_OPTION  -h std=c++11)
+    set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION -h std=c++11,gnu)
+  endif ()
+endif ()
+
+__compiler_check_default_language_standard(CXX 8.1 98)
diff --git a/Modules/Compiler/Cray.cmake b/Modules/Compiler/Cray.cmake
new file mode 100644
index 0000000..8fe8eeb
--- /dev/null
+++ b/Modules/Compiler/Cray.cmake
@@ -0,0 +1,10 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# This module is shared by multiple languages; use include blocker.
+if(__COMPILER_CRAY)
+  return()
+endif()
+set(__COMPILER_CRAY 1)
+
+include(Compiler/CMakeCommonCompilerMacros)
diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake
index 3f02618..f072c54 100644
--- a/Modules/Compiler/GNU-C.cmake
+++ b/Modules/Compiler/GNU-C.cmake
@@ -22,33 +22,4 @@ elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6)
   set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x")
 endif()
 
-if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
-  if (NOT CMAKE_C_COMPILER_FORCED)
-    if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT)
-      message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}")
-    endif()
-    set(CMAKE_C_STANDARD_DEFAULT ${CMAKE_C_STANDARD_COMPUTED_DEFAULT})
-  elseif(NOT DEFINED CMAKE_C_STANDARD_DEFAULT)
-    # Compiler id was forced so just guess the default standard level.
-    if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0)
-      set(CMAKE_C_STANDARD_DEFAULT 11)
-    else()
-      set(CMAKE_C_STANDARD_DEFAULT 90)
-    endif()
-  endif()
-endif()
-
-macro(cmake_record_c_compile_features)
-  set(_result 0)
-  if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
-    if(_result EQUAL 0 AND CMAKE_C11_STANDARD_COMPILE_OPTION)
-      _record_compiler_features_c(11)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_c(99)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_c(90)
-    endif()
-  endif()
-endmacro()
+__compiler_check_default_language_standard(C 3.4 90 5.0 11)
diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake
index c007c98..4f1f30e 100644
--- a/Modules/Compiler/GNU-CXX.cmake
+++ b/Modules/Compiler/GNU-CXX.cmake
@@ -11,8 +11,7 @@ else()
   endif()
 endif()
 
-if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4)
-  # Supported since 4.3
+if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4)
   set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98")
   set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
 endif()
@@ -39,32 +38,4 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1)
   set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
 endif()
 
-if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4)
-  if (NOT CMAKE_CXX_COMPILER_FORCED)
-    if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT)
-      message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}")
-    endif()
-    set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT})
-  elseif(NOT DEFINED CMAKE_CXX_STANDARD_DEFAULT)
-    # Compiler id was forced so just guess the default standard level.
-    set(CMAKE_CXX_STANDARD_DEFAULT 98)
-  endif()
-endif()
-
-macro(cmake_record_cxx_compile_features)
-  set(_result 0)
-  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4)
-    if(_result EQUAL 0 AND CMAKE_CXX17_STANDARD_COMPILE_OPTION)
-      _record_compiler_features_cxx(17)
-    endif()
-    if(_result EQUAL 0 AND CMAKE_CXX14_STANDARD_COMPILE_OPTION)
-      _record_compiler_features_cxx(14)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_cxx(11)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_cxx(98)
-    endif()
-  endif()
-endmacro()
+__compiler_check_default_language_standard(CXX 3.4 98 6.0 14)
diff --git a/Modules/Compiler/GNU-FindBinUtils.cmake b/Modules/Compiler/GNU-FindBinUtils.cmake
new file mode 100644
index 0000000..16b7bbd
--- /dev/null
+++ b/Modules/Compiler/GNU-FindBinUtils.cmake
@@ -0,0 +1,35 @@
+if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "")
+  message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
+endif()
+
+# Ubuntu 16.04:
+# * /usr/bin/gcc-ar-5
+# * /usr/bin/gcc-ranlib-5
+string(REGEX MATCH "^([0-9]+)" __version_x
+    "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}")
+
+string(REGEX MATCH "^([0-9]+\\.[0-9]+)" __version_x_y
+    "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}")
+
+# Try to find tools in the same directory as GCC itself
+get_filename_component(__gcc_hints "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY)
+
+# http://manpages.ubuntu.com/manpages/wily/en/man1/gcc-ar.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x_y}"
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x}"
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar"
+    HINTS ${__gcc_hints}
+    DOC "A wrapper around 'ar' adding the appropriate '--plugin' option for the GCC compiler"
+)
+mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR)
+
+# http://manpages.ubuntu.com/manpages/wily/en/man1/gcc-ranlib.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x_y}"
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x}"
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib"
+    HINTS ${__gcc_hints}
+    DOC "A wrapper around 'ranlib' adding the appropriate '--plugin' option for the GCC compiler"
+)
+mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB)
diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
index b67002c..675e505 100644
--- a/Modules/Compiler/GNU.cmake
+++ b/Modules/Compiler/GNU.cmake
@@ -8,6 +8,8 @@ if(__COMPILER_GNU)
 endif()
 set(__COMPILER_GNU 1)
 
+include(Compiler/CMakeCommonCompilerMacros)
+
 macro(__compiler_gnu lang)
   # Feature flags.
   set(CMAKE_${lang}_VERBOSE_FLAG "-v")
@@ -45,4 +47,43 @@ macro(__compiler_gnu lang)
   if(NOT APPLE OR NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4) # work around #4462
     set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
   endif()
+
+  set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+  set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+
+  # '-flto' introduced since GCC 4.5:
+  # * https://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Option-Summary.html (no)
+  # * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Option-Summary.html (yes)
+  if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.5)
+    set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+    set(__lto_flags -flto)
+
+    if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.7)
+      # '-ffat-lto-objects' introduced since GCC 4.7:
+      # * https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Option-Summary.html (no)
+      # * https://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/Option-Summary.html (yes)
+      list(APPEND __lto_flags -fno-fat-lto-objects)
+    endif()
+
+    set(CMAKE_${lang}_COMPILE_OPTIONS_IPO ${__lto_flags})
+
+    # Need to use version of 'ar'/'ranlib' with plugin support.
+    # Quote from [documentation][1]:
+    #
+    #   To create static libraries suitable for LTO,
+    #   use gcc-ar and gcc-ranlib instead of ar and ranlib
+    #
+    # [1]: https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Optimize-Options.html
+    set(CMAKE_${lang}_ARCHIVE_CREATE_IPO
+      "${CMAKE_${lang}_COMPILER_AR} cr <TARGET> <LINK_FLAGS> <OBJECTS>"
+    )
+
+    set(CMAKE_${lang}_ARCHIVE_APPEND_IPO
+      "${CMAKE_${lang}_COMPILER_AR} r <TARGET> <LINK_FLAGS> <OBJECTS>"
+    )
+
+    set(CMAKE_${lang}_ARCHIVE_FINISH_IPO
+      "${CMAKE_${lang}_COMPILER_RANLIB} <TARGET>"
+    )
+  endif()
 endmacro()
diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake
index f1b6ff7..f65b0c7 100644
--- a/Modules/Compiler/IAR-C.cmake
+++ b/Modules/Compiler/IAR-C.cmake
@@ -7,7 +7,7 @@ set(CMAKE_C_COMPILE_OBJECT             "<CMAKE_C_COMPILER> <SOURCE> <DEFINES> <I
 set(CMAKE_C_CREATE_PREPROCESSED_SOURCE "<CMAKE_C_COMPILER> <SOURCE> <DEFINES> <INCLUDES> <FLAGS> --preprocess=cnl <PREPROCESSED_SOURCE>")
 set(CMAKE_C_CREATE_ASSEMBLY_SOURCE     "<CMAKE_C_COMPILER> <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -lAH <ASSEMBLY_SOURCE> -o <OBJECT>.dummy")
 
-set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "-f")
+set(CMAKE_C_RESPONSE_FILE_LINK_FLAG "-f ")
 set(CMAKE_DEPFILE_FLAGS_C "--dependencies=ns <DEPFILE>")
 
 # The toolchains for ARM and AVR are quite different:
diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake
index ffb144f..f49968e 100644
--- a/Modules/Compiler/IAR-CXX.cmake
+++ b/Modules/Compiler/IAR-CXX.cmake
@@ -7,7 +7,7 @@ set(CMAKE_CXX_COMPILE_OBJECT  "<CMAKE_CXX_COMPILER> <SOURCE> <DEFINES> <INCLUDES
 set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> <SOURCE> <DEFINES> <INCLUDES> <FLAGS> --preprocess=cnl <PREPROCESSED_SOURCE>")
 set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE     "<CMAKE_CXX_COMPILER> <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -lAH <ASSEMBLY_SOURCE> -o <OBJECT>.dummy")
 
-set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "-f")
+set(CMAKE_CXX_RESPONSE_FILE_LINK_FLAG "-f ")
 set(CMAKE_DEPFILE_FLAGS_CXX "--dependencies=ns <DEPFILE>")
 
 if("${IAR_TARGET_ARCHITECTURE}" STREQUAL "ARM")
diff --git a/Modules/Compiler/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake
index 9c67fbd..4e4af29 100644
--- a/Modules/Compiler/Intel-C.cmake
+++ b/Modules/Compiler/Intel-C.cmake
@@ -8,61 +8,36 @@ string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG")
 set(CMAKE_DEPFILE_FLAGS_C "-MD -MT <OBJECT> -MF <DEPFILE>")
 
 if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
-  set(_std -Qstd)
-  set(_ext c)
+
   if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 16.0.0)
     set(CMAKE_C11_STANDARD_COMPILE_OPTION "-Qstd=c11")
     set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-Qstd=c11")
   endif()
+
+  if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0)
+    set(CMAKE_C90_STANDARD_COMPILE_OPTION "-Qstd=c89")
+    set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-Qstd=c89")
+    set(CMAKE_C99_STANDARD_COMPILE_OPTION "-Qstd=c99")
+    set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-Qstd=c99")
+  endif()
+
 else()
-  set(_std -std)
-  set(_ext gnu)
+
   if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15.0.0)
     set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
     set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
   endif()
-endif()
 
-if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0)
-  set(CMAKE_C90_STANDARD_COMPILE_OPTION "${_std}=c89")
-  set(CMAKE_C90_EXTENSION_COMPILE_OPTION "${_std}=${_ext}89")
-  set(CMAKE_C99_STANDARD_COMPILE_OPTION "${_std}=c99")
-  set(CMAKE_C99_EXTENSION_COMPILE_OPTION "${_std}=${_ext}99")
-endif()
-
-if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.1)
-  if (NOT CMAKE_C_COMPILER_FORCED)
-    if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT)
-      message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}")
-    endif()
-    set(CMAKE_C_STANDARD_DEFAULT ${CMAKE_C_STANDARD_COMPUTED_DEFAULT})
-  elseif(NOT DEFINED CMAKE_C_STANDARD_DEFAULT)
-    # Compiler id was forced so just guess the default standard level.
-    if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15.0.0)
-      set(CMAKE_C_STANDARD_DEFAULT 11)
-    else()
-      set(CMAKE_C_STANDARD_DEFAULT 90)
-    endif()
+  if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0)
+    set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89")
+    set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu89")
+    set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99")
+    set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99")
   endif()
-endif()
 
-unset(_std)
-unset(_ext)
+endif()
 
-macro(cmake_record_c_compile_features)
-  set(_result 0)
-  if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.1)
-    if (_result EQUAL 0 AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15.0.0)
-      _record_compiler_features_C(11)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_C(99)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_C(90)
-    endif()
-  endif()
-endmacro()
+__compiler_check_default_language_standard(C 12.0 90 15.0.0 11)
 
 set(CMAKE_C_CREATE_PREPROCESSED_SOURCE "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
 set(CMAKE_C_CREATE_ASSEMBLY_SOURCE "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
diff --git a/Modules/Compiler/Intel-CXX.cmake b/Modules/Compiler/Intel-CXX.cmake
index 9c39236..0eb9e1f 100644
--- a/Modules/Compiler/Intel-CXX.cmake
+++ b/Modules/Compiler/Intel-CXX.cmake
@@ -8,16 +8,27 @@ string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG")
 set(CMAKE_DEPFILE_FLAGS_CXX "-MD -MT <OBJECT> -MF <DEPFILE>")
 
 if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
-  set(_std -Qstd)
-  set(_ext c++)
+
   if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
     set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-Qstd=c++14")
-    # todo: there is no gnu++14 value supported; figure out what to do
     set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-Qstd=c++14")
   endif()
+
+  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0)
+    set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-Qstd=c++11")
+    set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-Qstd=c++11")
+  elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1)
+    set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-Qstd=c++0x")
+    set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-Qstd=c++0x")
+  endif()
+
+  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1)
+    set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
+    set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "")
+  endif()
+
 else()
-  set(_std -std)
-  set(_ext gnu++)
+
   if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0.2)
     set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14")
     # todo: there is no gnu++14 value supported; figure out what to do
@@ -27,59 +38,23 @@ else()
     # todo: there is no gnu++14 value supported; figure out what to do
     set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=c++1y")
   endif()
-endif()
-
-if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0)
-  set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "${_std}=c++11")
-  set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "${_std}=${_ext}11")
-elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1)
-  set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "${_std}=c++0x")
-  set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "${_std}=${_ext}0x")
-endif()
 
-if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1)
-  if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
-    set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
-    set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "")
-  else()
-    set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "${_std}=c++98")
-    set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "${_std}=gnu++98")
+  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0)
+    set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11")
+    set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
+  elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1)
+    set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++0x")
+    set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x")
   endif()
-endif()
 
-if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1)
-  if (NOT CMAKE_CXX_COMPILER_FORCED)
-    if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT)
-      message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}")
-    else()
-      set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT})
-    endif()
-  elseif (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT)
-    # Compiler id was forced so just guess the default standard level.
-    set(CMAKE_CXX_STANDARD_DEFAULT 98)
+  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1)
+    set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98")
+    set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
   endif()
-endif()
 
-unset(_std)
-unset(_ext)
+endif()
 
-macro(cmake_record_cxx_compile_features)
-  set(_result 0)
-  if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.1)
-    if (_result EQUAL 0 AND
-        (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0
-         OR (NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC" AND
-             NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0)))
-      _record_compiler_features_cxx(14)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_cxx(11)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_cxx(98)
-    endif()
-  endif()
-endmacro()
+__compiler_check_default_language_standard(CXX 12.1 98)
 
 set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
 set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
diff --git a/Modules/Compiler/Intel.cmake b/Modules/Compiler/Intel.cmake
index 02968b4..635ac4d 100644
--- a/Modules/Compiler/Intel.cmake
+++ b/Modules/Compiler/Intel.cmake
@@ -8,6 +8,8 @@ if(__COMPILER_INTEL)
 endif()
 set(__COMPILER_INTEL 1)
 
+include(Compiler/CMakeCommonCompilerMacros)
+
 if(CMAKE_HOST_WIN32)
   # MSVC-like
   macro(__compiler_intel lang)
@@ -22,5 +24,7 @@ else()
     string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os")
     string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3")
     string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
+
+    set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-QdM" "-P" "-Za" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
   endmacro()
 endif()
diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake
index 8fcfa0f..9371301 100644
--- a/Modules/Compiler/MSVC-CXX.cmake
+++ b/Modules/Compiler/MSVC-CXX.cmake
@@ -1,17 +1,21 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
 
-if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
-  # MSVC has no specific language level or flags to change it.
+include(Compiler/CMakeCommonCompilerMacros)
+
+if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)
+  # MSVC has no specific options to set language standards, but set them as
+  # empty strings anyways so the feature test infrastructure can at least check
+  # to see if they are defined.
+  set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "")
+  set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "")
+  set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "")
+  set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "")
+
+  # There is no meaningful default for this
   set(CMAKE_CXX_STANDARD_DEFAULT "")
 endif()
-
-macro(cmake_record_cxx_compile_features)
-  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
-    list(APPEND CMAKE_CXX_COMPILE_FEATURES
-      cxx_std_98
-      cxx_std_11
-      cxx_std_14
-      cxx_std_17
-      )
-    _record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES)
-  endif()
-endmacro()
diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake
index 316cab8..785e269 100644
--- a/Modules/Compiler/NVIDIA-CUDA.cmake
+++ b/Modules/Compiler/NVIDIA-CUDA.cmake
@@ -24,4 +24,10 @@ else()
   set(CMAKE_CUDA98_EXTENSION_COMPILE_OPTION "")
   set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "-std=c++11")
   set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "-std=c++11")
+
+  if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 9.0)
+    set(CMAKE_CUDA14_STANDARD_COMPILE_OPTION "-std=c++14")
+    set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "-std=c++14")
+  endif()
+
 endif()
diff --git a/Modules/Compiler/PGI-C.cmake b/Modules/Compiler/PGI-C.cmake
index 85d6e7e..3b3848a 100644
--- a/Modules/Compiler/PGI-C.cmake
+++ b/Modules/Compiler/PGI-C.cmake
@@ -2,3 +2,16 @@ include(Compiler/PGI)
 __compiler_pgi(C)
 string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
 string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG")
+
+if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.10)
+  set(CMAKE_C90_STANDARD_COMPILE_OPTION -c89)
+  set(CMAKE_C90_EXTENSION_COMPILE_OPTION -c89)
+  set(CMAKE_C99_STANDARD_COMPILE_OPTION -c99)
+  set(CMAKE_C99_EXTENSION_COMPILE_OPTION -c99)
+  if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15.3)
+    set(CMAKE_C11_STANDARD_COMPILE_OPTION -c11)
+    set(CMAKE_C11_EXTENSION_COMPILE_OPTION -c11)
+  endif ()
+endif ()
+
+__compiler_check_default_language_standard(C 12.10 90)
diff --git a/Modules/Compiler/PGI-CXX.cmake b/Modules/Compiler/PGI-CXX.cmake
index 896e298..35076bb 100644
--- a/Modules/Compiler/PGI-CXX.cmake
+++ b/Modules/Compiler/PGI-CXX.cmake
@@ -2,3 +2,22 @@ include(Compiler/PGI)
 __compiler_pgi(CXX)
 string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
 string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -DNDEBUG")
+
+if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.10)
+  set(CMAKE_CXX98_STANDARD_COMPILE_OPTION  -A)
+  set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION --gnu_extensions)
+  if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.10)
+    set(CMAKE_CXX11_STANDARD_COMPILE_OPTION  --c++11 -A)
+    set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION --c++11 --gnu_extensions)
+    if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15.7)
+      set(CMAKE_CXX14_STANDARD_COMPILE_OPTION  --c++14 -A)
+      set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION --c++14 --gnu_extensions)
+      if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 17.1)
+        set(CMAKE_CXX17_STANDARD_COMPILE_OPTION  --c++17 -A)
+        set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION --c++17 --gnu_extensions)
+      endif()
+    endif()
+  endif()
+endif()
+
+__compiler_check_default_language_standard(CXX 12.10 98)
diff --git a/Modules/Compiler/PGI.cmake b/Modules/Compiler/PGI.cmake
index cc76deb..0cbfd8a 100644
--- a/Modules/Compiler/PGI.cmake
+++ b/Modules/Compiler/PGI.cmake
@@ -8,6 +8,8 @@ if(__COMPILER_PGI)
 endif()
 set(__COMPILER_PGI 1)
 
+include(Compiler/CMakeCommonCompilerMacros)
+
 macro(__compiler_pgi lang)
   # Feature flags.
   set(CMAKE_${lang}_VERBOSE_FLAG "-v")
@@ -16,9 +18,17 @@ macro(__compiler_pgi lang)
   string(APPEND CMAKE_${lang}_FLAGS_INIT " ")
   string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g -O0")
   string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -O2 -s")
-  string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -fast -O3 -Mipa=fast")
+  string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -fast -O3")
+  # -Mipa was dropped with PGI 16.3 from Windows versions
+  if(NOT CMAKE_HOST_WIN32 OR CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 16.3)
+    string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -Mipa=fast")
+  endif()
   string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -gopt")
 
+  if(CMAKE_HOST_WIN32)
+    string(APPEND CMAKE_${lang}_FLAGS_INIT " -Bdynamic")
+  endif()
+
   # Preprocessing and assembly rules.
   set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
   set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
diff --git a/Modules/Compiler/QCC.cmake b/Modules/Compiler/QCC.cmake
index 2d7e881..0da7050 100644
--- a/Modules/Compiler/QCC.cmake
+++ b/Modules/Compiler/QCC.cmake
@@ -12,4 +12,12 @@ macro(__compiler_qcc lang)
 
   set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-Wp,-isystem,")
   set(CMAKE_DEPFILE_FLAGS_${lang} "-Wc,-MD,<DEPFILE>,-MT,<OBJECT>,-MF,<DEPFILE>")
+
+  set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE NO)
+  set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+
+  unset(CMAKE_${lang}_COMPILE_OPTIONS_IPO)
+  unset(CMAKE_${lang}_ARCHIVE_CREATE_IPO)
+  unset(CMAKE_${lang}_ARCHIVE_APPEND_IPO)
+  unset(CMAKE_${lang}_ARCHIVE_FINISH_IPO)
 endmacro()
diff --git a/Modules/Compiler/SunPro-C-FeatureTests.cmake b/Modules/Compiler/SunPro-C-FeatureTests.cmake
new file mode 100644
index 0000000..cccf3ae
--- /dev/null
+++ b/Modules/Compiler/SunPro-C-FeatureTests.cmake
@@ -0,0 +1,14 @@
+set(_cmake_oldestSupported "__SUNPRO_C >= 0x5130")
+
+set(SunPro_C11 "${_cmake_oldestSupported} && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L || __STDC_VERSION__ >= 199901L && defined(__C11FEATURES__))")
+set(_cmake_feature_test_c_static_assert "${SunPro_C11}")
+unset(SunPro_C11)
+
+set(SunPro_C99 "${_cmake_oldestSupported} && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L")
+set(_cmake_feature_test_c_restrict "${SunPro_C99}")
+set(_cmake_feature_test_c_variadic_macros "${SunPro_C99}")
+unset(SunPro_C99)
+
+set(SunPro_C90 "${_cmake_oldestSupported}")
+set(_cmake_feature_test_c_function_prototypes "${SunPro_C90}")
+unset(SunPro_C90)
diff --git a/Modules/Compiler/SunPro-C.cmake b/Modules/Compiler/SunPro-C.cmake
index 503684a..29c2f22 100644
--- a/Modules/Compiler/SunPro-C.cmake
+++ b/Modules/Compiler/SunPro-C.cmake
@@ -1,3 +1,8 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+include(Compiler/SunPro)
+
 set(CMAKE_C_VERBOSE_FLAG "-#")
 
 set(CMAKE_C_COMPILE_OPTIONS_PIC -KPIC)
@@ -22,5 +27,21 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
   set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Bdynamic")
 endforeach()
 
+if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 5.13)
+  set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89")
+  set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=c89")
+  set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99")
+  set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=c99")
+  set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
+  set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=c11")
+elseif (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 5.11)
+  set(CMAKE_C90_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_C90_EXTENSION_COMPILE_OPTION "")
+  set(CMAKE_C99_STANDARD_COMPILE_OPTION "-xc99")
+  set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-xc99")
+endif()
+
+__compiler_check_default_language_standard(C 5.11 90 5.14 11)
+
 set(CMAKE_C_CREATE_PREPROCESSED_SOURCE "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
 set(CMAKE_C_CREATE_ASSEMBLY_SOURCE "<CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
diff --git a/Modules/Compiler/SunPro-CXX-FeatureTests.cmake b/Modules/Compiler/SunPro-CXX-FeatureTests.cmake
index 8e97e1d..60280ca 100644
--- a/Modules/Compiler/SunPro-CXX-FeatureTests.cmake
+++ b/Modules/Compiler/SunPro-CXX-FeatureTests.cmake
@@ -5,6 +5,10 @@
 
 set(_cmake_oldestSupported "__SUNPRO_CC >= 0x5130")
 
+set(SolarisStudio125_CXX11 "(__SUNPRO_CC >= 0x5140) && __cplusplus >= 201103L")
+set(_cmake_feature_test_cxx_binary_literals "${SolarisStudio125_CXX11}")
+set(_cmake_feature_test_cxx_reference_qualified_functions "${SolarisStudio125_CXX11}")
+
 set(SolarisStudio124_CXX11 "(__SUNPRO_CC >= 0x5130) && __cplusplus >= 201103L")
 set(_cmake_feature_test_cxx_alignas "${SolarisStudio124_CXX11}")
 set(_cmake_feature_test_cxx_alignof "${SolarisStudio124_CXX11}")
diff --git a/Modules/Compiler/SunPro-CXX.cmake b/Modules/Compiler/SunPro-CXX.cmake
index f4345b8..5cb7edc 100644
--- a/Modules/Compiler/SunPro-CXX.cmake
+++ b/Modules/Compiler/SunPro-CXX.cmake
@@ -1,3 +1,8 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+include(Compiler/SunPro)
+
 set(CMAKE_CXX_VERBOSE_FLAG "-v")
 
 set(CMAKE_CXX_COMPILE_OPTIONS_PIC -KPIC)
@@ -32,32 +37,15 @@ set(CMAKE_CXX_CREATE_STATIC_LIBRARY
   "<CMAKE_RANLIB> <TARGET> ")
 
 if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13)
-  set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
-  set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "")
+  set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++03")
+  set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=c++03")
   set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11")
   set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=c++11")
+  set(CMAKE_CXX_LINK_WITH_STANDARD_COMPILE_OPTION 1)
+else()
+  set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-library=stlport4")
+  set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-library=stlport4")
+  set(CMAKE_CXX_LINK_WITH_STANDARD_COMPILE_OPTION 1)
 endif()
 
-if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13)
-  if (NOT CMAKE_CXX_COMPILER_FORCED)
-    if (NOT CMAKE_CXX_STANDARD_COMPUTED_DEFAULT)
-      message(FATAL_ERROR "CMAKE_CXX_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) version ${CMAKE_CXX_COMPILER_VERSION}")
-    endif()
-    set(CMAKE_CXX_STANDARD_DEFAULT ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT})
-  elseif(NOT DEFINED CMAKE_CXX_STANDARD_DEFAULT)
-    # Compiler id was forced so just guess the default standard level.
-    set(CMAKE_CXX_STANDARD_DEFAULT 98)
-  endif()
-endif()
-
-macro(cmake_record_cxx_compile_features)
-  set(_result 0)
-  if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.13)
-    if (_result EQUAL 0)
-      _record_compiler_features_cxx(11)
-    endif()
-    if (_result EQUAL 0)
-      _record_compiler_features_cxx(98)
-    endif()
-  endif()
-endmacro()
+__compiler_check_default_language_standard(CXX 1 98)
diff --git a/Modules/Compiler/SunPro-Fortran.cmake b/Modules/Compiler/SunPro-Fortran.cmake
index 6607926..9b25c0b 100644
--- a/Modules/Compiler/SunPro-Fortran.cmake
+++ b/Modules/Compiler/SunPro-Fortran.cmake
@@ -19,7 +19,7 @@ set(CMAKE_Fortran_MODDIR_FLAG "-moddir=")
 set(CMAKE_Fortran_MODPATH_FLAG "-M")
 
 set(CMAKE_Fortran_PREPROCESS_SOURCE
-  "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -F <SOURCE> -o <PREPROCESSED_SOURCE>")
+  "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -F -fpp <SOURCE> -o <PREPROCESSED_SOURCE>")
 
-set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -F <SOURCE> -o <PREPROCESSED_SOURCE>")
+set(CMAKE_Fortran_CREATE_PREPROCESSED_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -F -fpp <SOURCE> -o <PREPROCESSED_SOURCE>")
 set(CMAKE_Fortran_CREATE_ASSEMBLY_SOURCE "<CMAKE_Fortran_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
diff --git a/Modules/Compiler/SunPro.cmake b/Modules/Compiler/SunPro.cmake
new file mode 100644
index 0000000..52da39a
--- /dev/null
+++ b/Modules/Compiler/SunPro.cmake
@@ -0,0 +1,10 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# This module is shared by multiple languages; use include blocker.
+if(__COMPILER_SUNPRO)
+  return()
+endif()
+set(__COMPILER_SUNPRO 1)
+
+include(Compiler/CMakeCommonCompilerMacros)
diff --git a/Modules/Compiler/XL-C.cmake b/Modules/Compiler/XL-C.cmake
index f976c99..5dc8bc1 100644
--- a/Modules/Compiler/XL-C.cmake
+++ b/Modules/Compiler/XL-C.cmake
@@ -3,6 +3,39 @@ __compiler_xl(C)
 string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG")
 string(APPEND CMAKE_C_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
 
-# -qthreaded     = Ensures that all optimizations will be thread-safe
-# -qhalt=e       = Halt on error messages (rather than just severe errors)
-string(APPEND CMAKE_C_FLAGS_INIT " -qthreaded -qhalt=e")
+# -qthreaded = Ensures that all optimizations will be thread-safe
+string(APPEND CMAKE_C_FLAGS_INIT " -qthreaded")
+
+# XL v13.1.1 for Linux ppc64 little-endian switched to using a clang based
+# front end and accepts the -std= option while only reserving -qlanglevel= for
+# compatibility.  All other versions (previous versions on Linux ppc64
+# little-endian, all versions on Linux ppc64 big-endian, all versions on AIX
+# and BGQ, etc) are derived from the UNIX compiler and only accept the
+# -qlanglvl option.
+if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.1)
+  if (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND
+      CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1.1)
+    set(CMAKE_C90_STANDARD_COMPILE_OPTION  "-std=c89")
+    set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu89")
+    set(CMAKE_C99_STANDARD_COMPILE_OPTION  "-std=c99")
+    set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99")
+    if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1.2)
+      set(CMAKE_C11_STANDARD_COMPILE_OPTION  "-std=c11")
+      set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
+    else ()
+      set(CMAKE_C11_STANDARD_COMPILE_OPTION "-qlanglvl=extc1x")
+      set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-qlanglvl=extc1x")
+    endif ()
+  else ()
+    set(CMAKE_C90_STANDARD_COMPILE_OPTION "-qlanglvl=stdc89")
+    set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-qlanglvl=extc89")
+    set(CMAKE_C99_STANDARD_COMPILE_OPTION "-qlanglvl=stdc99")
+    set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-qlanglvl=extc99")
+    if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.1)
+      set(CMAKE_C11_STANDARD_COMPILE_OPTION "-qlanglvl=extc1x")
+      set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-qlanglvl=extc1x")
+    endif ()
+  endif ()
+endif()
+
+__compiler_check_default_language_standard(C 10.1 90)
diff --git a/Modules/Compiler/XL-CXX.cmake b/Modules/Compiler/XL-CXX.cmake
index 545d657..b87e923 100644
--- a/Modules/Compiler/XL-CXX.cmake
+++ b/Modules/Compiler/XL-CXX.cmake
@@ -3,9 +3,47 @@ __compiler_xl(CXX)
 string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -DNDEBUG")
 string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
 
-# -qthreaded     = Ensures that all optimizations will be thread-safe
-# -qhalt=e       = Halt on error messages (rather than just severe errors)
-string(APPEND CMAKE_CXX_FLAGS_INIT " -qthreaded -qhalt=e")
+# -qthreaded = Ensures that all optimizations will be thread-safe
+string(APPEND CMAKE_CXX_FLAGS_INIT " -qthreaded")
+
+# XL v13.1.1 for Linux ppc64 little-endian switched to using a clang based
+# front end and accepts the -std= option while only reserving -qlanglevel= for
+# compatibility.  All other versions (previous versions on Linux ppc64
+# little-endian, all versions on Linux ppc64 big-endian, all versions on AIX
+# and BGQ, etc) are derived from the UNIX compiler and only accept the
+# -qlanglvl option.
+if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10.1)
+  if (CMAKE_SYSTEM MATCHES "Linux.*ppc64")
+    if (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND
+        CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1.1)
+      set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98")
+      set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
+      if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13.1.2)
+        set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11")
+        set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
+        set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++1y")
+        set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-qlanglvl=extended1y")
+      else ()
+        set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-qlanglvl=extended0x")
+        set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-qlanglvl=extended0x")
+      endif ()
+    else ()
+      # The non-clang based Linux ppc64 compiler, both big-endian and
+      # little-endian lacks, the non-extension language level flags
+      set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-qlanglvl=extended")
+      set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-qlanglvl=extended")
+      set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-qlanglvl=extended0x")
+      set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-qlanglvl=extended0x")
+    endif ()
+  else ()
+    set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-qlanglvl=strict98")
+    set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-qlanglvl=extended")
+    set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-qlanglvl=extended0x")
+    set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-qlanglvl=extended0x")
+  endif ()
+endif ()
+
+__compiler_check_default_language_standard(CXX 10.1 98)
 
 set(CMAKE_CXX_COMPILE_OBJECT
   "<CMAKE_CXX_COMPILER> -+ <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
diff --git a/Modules/Compiler/XL.cmake b/Modules/Compiler/XL.cmake
index 55f71bd..4783785 100644
--- a/Modules/Compiler/XL.cmake
+++ b/Modules/Compiler/XL.cmake
@@ -8,6 +8,8 @@ if(__COMPILER_XL)
 endif()
 set(__COMPILER_XL 1)
 
+include(Compiler/CMakeCommonCompilerMacros)
+
 # Find the CreateExportList program that comes with this toolchain.
 find_program(CMAKE_XL_CreateExportList
   NAMES CreateExportList
diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in
index 50be9cb..6b9b361 100644
--- a/Modules/CompilerId/VS-10.vcxproj.in
+++ b/Modules/CompilerId/VS-10.vcxproj.in
@@ -25,6 +25,9 @@
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+    @id_Import_props@
+  </ImportGroup>
   <PropertyGroup>
     <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">.\</OutDir>
@@ -44,16 +47,21 @@
       <DebugInformationFormat>
       </DebugInformationFormat>
     </ClCompile>
+    @id_ItemDefinitionGroup_entry@
     <Link>
       <GenerateDebugInformation>false</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
+      @id_Link_AdditionalDependencies@
     </Link>
     <PostBuildEvent>
-      <Command>for %%i in (@id_cl@) do %40echo CMAKE_ at id_lang@_COMPILER=%%~$PATH:i</Command>
+      <Command>@id_PostBuildEvent_Command@</Command>
     </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClCompile Include="@id_src@" />
+    <@id_compile@ Include="@id_src@" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+    @id_Import_targets@
+  </ImportGroup>
 </Project>
diff --git a/Modules/CompilerId/Xcode-1.pbxproj.in b/Modules/CompilerId/Xcode-1.pbxproj.in
deleted file mode 100644
index 793ad02..0000000
--- a/Modules/CompilerId/Xcode-1.pbxproj.in
+++ /dev/null
@@ -1,120 +0,0 @@
-// !$*UTF8*$!
-{
-	archiveVersion = 1;
-	classes = {
-	};
-	objectVersion = 39;
-	objects = {
-		014CEA460018CE2711CA2923 = {
-			buildSettings = {
-			};
-			isa = PBXBuildStyle;
-			name = Development;
-		};
-		08FB7793FE84155DC02AAC07 = {
-			buildSettings = {
-			};
-			buildStyles = (
-				014CEA460018CE2711CA2923,
-			);
-			hasScannedForEncodings = 1;
-			isa = PBXProject;
-			mainGroup = 08FB7794FE84155DC02AAC07;
-			projectDirPath = "";
-			targets = (
-				8DD76FA90486AB0100D96B5E,
-			);
-		};
-		08FB7794FE84155DC02AAC07 = {
-			children = (
-				08FB7795FE84155DC02AAC07,
-				1AB674ADFE9D54B511CA2CBB,
-			);
-			isa = PBXGroup;
-			name = CompilerId at id_lang@;
-			refType = 4;
-			sourceTree = "<group>";
-		};
-		08FB7795FE84155DC02AAC07 = {
-			children = (
-				2C18F0B415DC1DC700593670,
-			);
-			isa = PBXGroup;
-			name = Source;
-			refType = 4;
-			sourceTree = "<group>";
-		};
-		1AB674ADFE9D54B511CA2CBB = {
-			children = (
-				8DD76F6C0486A84900D96B5E,
-			);
-			isa = PBXGroup;
-			name = Products;
-			refType = 4;
-			sourceTree = "<group>";
-		};
-		2C18F0B415DC1DC700593670 = {
-			fileEncoding = 30;
-			isa = PBXFileReference;
-			explicitFileType = @id_type@;
-			path = @id_src@;
-			refType = 4;
-			sourceTree = "<group>";
-		};
-		2C18F0B615DC1E0300593670 = {
-			fileRef = 2C18F0B415DC1DC700593670;
-			isa = PBXBuildFile;
-			settings = {
-			};
-		};
-		2C8FEB8E15DC1A1A00E56A5D = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "echo \"GCC_VERSION=$GCC_VERSION\"";
-		};
-		8DD76FA90486AB0100D96B5E = {
-			buildPhases = (
-				2C18F0B515DC1DCE00593670,
-				2C8FEB8E15DC1A1A00E56A5D,
-			);
-			buildRules = (
-			);
-			buildSettings = {
-				PRODUCT_NAME = CompilerId at id_lang@;
-				SYMROOT = .;
-			};
-			dependencies = (
-			);
-			isa = PBXNativeTarget;
-			name = CompilerId at id_lang@;
-			productName = CompilerId at id_lang@;
-			productReference = 8DD76F6C0486A84900D96B5E;
-			productType = "com.apple.product-type.tool";
-		};
-		2C18F0B515DC1DCE00593670 = {
-			buildActionMask = 2147483647;
-			files = (
-				2C18F0B615DC1E0300593670,
-			);
-			isa = PBXSourcesBuildPhase;
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		8DD76F6C0486A84900D96B5E = {
-			explicitFileType = "compiled.mach-o.executable";
-			includeInIndex = 0;
-			isa = PBXFileReference;
-			path = CompilerId at id_lang@;
-			refType = 3;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-	};
-	rootObject = 08FB7793FE84155DC02AAC07;
-}
diff --git a/Modules/CompilerId/Xcode-2.pbxproj.in b/Modules/CompilerId/Xcode-2.pbxproj.in
deleted file mode 100644
index 226b413..0000000
--- a/Modules/CompilerId/Xcode-2.pbxproj.in
+++ /dev/null
@@ -1,119 +0,0 @@
-// !$*UTF8*$!
-{
-	archiveVersion = 1;
-	classes = {
-	};
-	objectVersion = 42;
-	objects = {
-
-		2C18F0B615DC1E0300593670 = {isa = PBXBuildFile; fileRef = 2C18F0B415DC1DC700593670; };
-		2C18F0B415DC1DC700593670 = {isa = PBXFileReference; fileEncoding = 4; explicitFileType = @id_type@; path = @id_src@; sourceTree = "<group>"; };
-		8DD76F6C0486A84900D96B5E = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CompilerId at id_lang@; sourceTree = BUILT_PRODUCTS_DIR; };
-
-		08FB7794FE84155DC02AAC07 = {
-			isa = PBXGroup;
-			children = (
-				08FB7795FE84155DC02AAC07,
-				1AB674ADFE9D54B511CA2CBB,
-			);
-			name = CompilerId at id_lang@;
-			sourceTree = "<group>";
-		};
-		08FB7795FE84155DC02AAC07 = {
-			isa = PBXGroup;
-			children = (
-				2C18F0B415DC1DC700593670,
-			);
-			name = Source;
-			sourceTree = "<group>";
-		};
-		1AB674ADFE9D54B511CA2CBB = {
-			isa = PBXGroup;
-			children = (
-				8DD76F6C0486A84900D96B5E,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-
-		8DD76FA90486AB0100D96B5E = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 1DEB928508733DD80010E9CD;
-			buildPhases = (
-				2C18F0B515DC1DCE00593670,
-				2C8FEB8E15DC1A1A00E56A5D,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = CompilerId at id_lang@;
-			productName = CompilerId at id_lang@;
-			productReference = 8DD76F6C0486A84900D96B5E;
-			productType = "com.apple.product-type.tool";
-		};
-		08FB7793FE84155DC02AAC07 = {
-			isa = PBXProject;
-			buildConfigurationList = 1DEB928908733DD80010E9CD;
-			hasScannedForEncodings = 1;
-			mainGroup = 08FB7794FE84155DC02AAC07;
-			projectDirPath = "";
-			targets = (
-				8DD76FA90486AB0100D96B5E,
-			);
-		};
-		2C8FEB8E15DC1A1A00E56A5D = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "echo \"GCC_VERSION=$GCC_VERSION\"";
-		};
-		2C18F0B515DC1DCE00593670 = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				2C18F0B615DC1E0300593670,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		1DEB928608733DD80010E9CD = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				PRODUCT_NAME = CompilerId at id_lang@;
-			};
-			name = Debug;
-		};
-		1DEB928A08733DD80010E9CD = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
-				SYMROOT = .;
-			};
-			name = Debug;
-		};
-		1DEB928508733DD80010E9CD = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				1DEB928608733DD80010E9CD,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Debug;
-		};
-		1DEB928908733DD80010E9CD = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				1DEB928A08733DD80010E9CD,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Debug;
-		};
-	};
-	rootObject = 08FB7793FE84155DC02AAC07;
-}
diff --git a/Modules/CompilerId/Xcode-3.pbxproj.in b/Modules/CompilerId/Xcode-3.pbxproj.in
index 22ad4f6..84f48ae 100644
--- a/Modules/CompilerId/Xcode-3.pbxproj.in
+++ b/Modules/CompilerId/Xcode-3.pbxproj.in
@@ -58,7 +58,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "echo \"GCC_VERSION=$GCC_VERSION\"";
+			shellScript = "echo \"GCC_VERSION=$GCC_VERSION\" ; echo \"CURRENT_ARCH=$CURRENT_ARCH\"";
 			showEnvVarsInLog = 0;
 		};
 		2C18F0B515DC1DCE00593670 = {
diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 873f88d..7331fb2 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -1111,7 +1111,7 @@ if("${ExternalData_ACTION}" STREQUAL "fetch")
       list(GET algo_list ${ii} algo)
       _ExternalData_download_object("${name}" "${hash}" "${algo}"
         obj succeeded algoErrorMsg)
-      set(errorMsg "${errorMsg}\n${algoErrorMsg}")
+      string(APPEND errorMsg "\n${algoErrorMsg}")
       if(succeeded)
         break()
       endif()
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index b42d2dd..2495736 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -415,7 +415,7 @@ file(STRINGS "${CMAKE_CURRENT_LIST_FILE}" lines
 foreach(line IN LISTS lines)
   if("${line}" MATCHES "^\\.\\. command:: ([A-Za-z0-9_]+)")
     if(_ep_func)
-      set(_ep_keywords_${_ep_func} "${_ep_keywords_${_ep_func}})$")
+      string(APPEND _ep_keywords_${_ep_func} ")$")
     endif()
     set(_ep_func "${CMAKE_MATCH_1}")
     #message("function [${_ep_func}]")
@@ -424,13 +424,13 @@ foreach(line IN LISTS lines)
   elseif("${line}" MATCHES "^  ``([A-Z0-9_]+) .*``$")
     set(_ep_key "${CMAKE_MATCH_1}")
     #message("  keyword [${_ep_key}]")
-    set(_ep_keywords_${_ep_func}
-      "${_ep_keywords_${_ep_func}}${_ep_keyword_sep}${_ep_key}")
+    string(APPEND _ep_keywords_${_ep_func}
+      "${_ep_keyword_sep}${_ep_key}")
     set(_ep_keyword_sep "|")
   endif()
 endforeach()
 if(_ep_func)
-  set(_ep_keywords_${_ep_func} "${_ep_keywords_${_ep_func}})$")
+  string(APPEND _ep_keywords_${_ep_func} ")$")
 endif()
 
 # Save regex matching supported hash algorithm names.
@@ -531,6 +531,15 @@ function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git
   else()
     set(git_clone_shallow_options "--depth 1")
   endif()
+  if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5)
+    # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path.
+    set(git_checkout_explicit-- "--")
+  else()
+    # Use `git checkout <branch>` even though this risks ambiguity with a
+    # local path.  Unfortunately we cannot use `git checkout <tree-ish> --`
+    # because that will not search for remote branch names, a common use case.
+    set(git_checkout_explicit-- "")
+  endif()
   file(WRITE ${script_filename}
 "if(\"${git_tag}\" STREQUAL \"\")
   message(FATAL_ERROR \"Tag for git checkout should not be empty.\")
@@ -600,11 +609,8 @@ if(error_code)
   message(FATAL_ERROR \"Failed to clone repository: '${git_repository}'\")
 endif()
 
-# Use `git checkout <branch>` even though this risks ambiguity with a
-# local path.  Unfortunately we cannot use `git checkout <tree-ish> --`
-# because that will not search for remote branch names, a common use case.
 execute_process(
-  COMMAND \"${git_EXECUTABLE}\" \${git_options} checkout ${git_tag}
+  COMMAND \"${git_EXECUTABLE}\" \${git_options} checkout ${git_tag} ${git_checkout_explicit--}
   WORKING_DIRECTORY \"${work_dir}/${src_name}\"
   RESULT_VARIABLE error_code
   )
@@ -1990,11 +1996,10 @@ function(_ep_add_download_command name)
         set(comment "Performing download step (${steps}) for '${name}'")
         _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}")
       endif()
-      list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake
-        COMMAND)
+      list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake)
       if (NOT no_extract)
         _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}")
-        list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake)
+        list(APPEND cmd COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake)
       else ()
         set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file})
       endif ()
diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake
index f29a5f0..1b93304 100644
--- a/Modules/FeatureSummary.cmake
+++ b/Modules/FeatureSummary.cmake
@@ -63,6 +63,16 @@ is set for all the packages.
 
 The default value for this global property is ``OPTIONAL``.
 
+
+.. variable:: FeatureSummary_<TYPE>_DESCRIPTION
+
+The global property :variable:`FeatureSummary_<TYPE>_DESCRIPTION` can be defined
+for each type to replace the type name with the specified string whenever the
+package type is used in an output string.
+
+If not set, the string "``<TYPE>`` packages" is used.
+
+
 #]=======================================================================]
 
 get_property(_fsPkgTypeIsSet GLOBAL PROPERTY FeatureSummary_PKG_TYPES SET)
@@ -196,7 +206,7 @@ endfunction()
                      [VAR <variable_name>]
                      [INCLUDE_QUIET_PACKAGES]
                      [FATAL_ON_MISSING_REQUIRED_PACKAGES]
-                     [DESCRIPTION "<description>"]
+                     [DESCRIPTION "<description>" | DEFAULT_DESCRIPTION]
                      [QUIET_ON_EMPTY]
                      WHAT (ALL
                           | PACKAGES_FOUND | PACKAGES_NOT_FOUND
@@ -247,7 +257,10 @@ endfunction()
   information is "printed" into the specified variable.  If ``FILENAME`` is
   not used, the information is printed to the terminal.  Using the
   ``DESCRIPTION`` option a description or headline can be set which will be
-  printed above the actual content.
+  printed above the actual content.  If only one type of
+  package was requested, no title is printed, unless it is explicitly set using
+  either ``DESCRIPTION`` to use a custom string, or ``DEFAULT_DESCRIPTION`` to
+  use a default title for the requested type.
   If ``INCLUDE_QUIET_PACKAGES`` is given, packages which have been searched with
   ``find_package(... QUIET)`` will also be listed. By default they are skipped.
   If ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` is given, CMake will abort if a
@@ -306,8 +319,14 @@ endfunction()
 
 function(FEATURE_SUMMARY)
 # CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...)
-  set(options APPEND INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES QUIET_ON_EMPTY)
-  set(oneValueArgs FILENAME VAR DESCRIPTION)
+  set(options APPEND
+              INCLUDE_QUIET_PACKAGES
+              FATAL_ON_MISSING_REQUIRED_PACKAGES
+              QUIET_ON_EMPTY
+              DEFAULT_DESCRIPTION)
+  set(oneValueArgs FILENAME
+                   VAR
+                   DESCRIPTION)
   set(multiValueArgs WHAT)
 
   CMAKE_PARSE_ARGUMENTS(_FS "${options}" "${oneValueArgs}" "${multiValueArgs}"  ${_FIRST_ARG} ${ARGN})
@@ -320,6 +339,11 @@ function(FEATURE_SUMMARY)
     message(FATAL_ERROR "The call to FEATURE_SUMMARY() doesn't set the required WHAT argument.")
   endif()
 
+  if(_FS_DEFAULT_DESCRIPTION AND DEFINED _FS_DESCRIPTION)
+    message(WARNING "DEFAULT_DESCRIPTION option discarded since DESCRIPTION is set.")
+    set(_FS_DEFAULT_DESCRIPTION 0)
+  endif()
+
   set(validWhatParts "ENABLED_FEATURES"
                      "DISABLED_FEATURES"
                      "PACKAGES_FOUND"
@@ -332,11 +356,29 @@ function(FEATURE_SUMMARY)
                                "${_fsPkgType}_PACKAGES_NOT_FOUND")
   endforeach()
 
+  set(title_ENABLED_FEATURES               "The following features have been enabled:")
+  set(title_DISABLED_FEATURES              "The following features have been disabled:")
+  set(title_PACKAGES_FOUND                 "The following packages have been found:")
+  set(title_PACKAGES_NOT_FOUND             "The following packages have not been found:")
+  foreach(_fsPkgType ${_fsPkgTypes})
+    set(_fsPkgTypeDescription "${_fsPkgType} packages")
+    get_property(_fsPkgTypeDescriptionIsSet GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION SET)
+    if(_fsPkgTypeDescriptionIsSet)
+      get_property(_fsPkgTypeDescription GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION )
+    endif()
+    set(title_${_fsPkgType}_PACKAGES_FOUND     "The following ${_fsPkgTypeDescription} have been found:")
+    set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgTypeDescription} have not been found:")
+  endforeach()
+
   list(FIND validWhatParts "${_FS_WHAT}" indexInList)
   if(NOT "${indexInList}" STREQUAL "-1")
     _FS_GET_FEATURE_SUMMARY( ${_FS_WHAT} _featureSummary ${_FS_INCLUDE_QUIET_PACKAGES} )
     if(_featureSummary OR NOT _FS_QUIET_ON_EMPTY)
-      set(_fullText "${_FS_DESCRIPTION}${_featureSummary}\n")
+      if(_FS_DEFAULT_DESCRIPTION)
+        set(_fullText "${title_${_FS_WHAT}}\n${_featureSummary}\n")
+      else()
+        set(_fullText "${_FS_DESCRIPTION}${_featureSummary}\n")
+      endif()
     endif()
 
     if(_featureSummary)
@@ -375,15 +417,6 @@ function(FEATURE_SUMMARY)
       endforeach()
     endif()
 
-    set(title_ENABLED_FEATURES               "The following features have been enabled:")
-    set(title_DISABLED_FEATURES              "The following features have been disabled:")
-    set(title_PACKAGES_FOUND                 "The following packages have been found:")
-    set(title_PACKAGES_NOT_FOUND             "The following packages have not been found:")
-    foreach(_fsPkgType ${_fsPkgTypes})
-      set(title_${_fsPkgType}_PACKAGES_FOUND     "The following ${_fsPkgType} packages have been found:")
-      set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgType} packages have not been found:")
-    endforeach()
-
     set(_fullText "${_FS_DESCRIPTION}")
     foreach(part ${allWhatParts})
       set(_tmp)
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index 2dd08e1..cc273e0 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -127,7 +127,10 @@
 #                              ('n' tag).  Default is OFF.
 #   Boost_COMPILER           - Set to the compiler-specific library suffix
 #                              (e.g. "-gcc43").  Default is auto-computed
-#                              for the C++ compiler in use.
+#                              for the C++ compiler in use.  A list may be
+#                              used if multiple compatible suffixes should
+#                              be tested for, in decreasing order of
+#                              preference.
 #   Boost_THREADAPI          - Suffix for "thread" component library name,
 #                              such as "pthread" or "win32".  Names with
 #                              and without this suffix will both be tried.
@@ -205,6 +208,10 @@
 #
 # Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake.
 
+# Save project's policies
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
 #-------------------------------------------------------------------------------
 # Before we go searching, check whether boost-cmake is available, unless the
 # user specifically asked NOT to search for boost-cmake.
@@ -428,7 +435,7 @@ function(_Boost_GUESS_COMPILER_PREFIX _ret)
     set(_boost_COMPILER "-ghs")
   elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
     if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10)
-      set(_boost_COMPILER "-vc141")
+      set(_boost_COMPILER "-vc141;-vc140")
     elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19)
       set(_boost_COMPILER "-vc140")
     elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18)
@@ -862,14 +869,12 @@ function(_Boost_MISSING_DEPENDENCIES componentvar extravar)
     list(APPEND _boost_processed_components ${_boost_unprocessed_components})
     foreach(component ${_boost_unprocessed_components})
       string(TOUPPER ${component} uppercomponent)
-  set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE)
+      set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE)
       _Boost_COMPONENT_DEPENDENCIES("${component}" _Boost_${uppercomponent}_DEPENDENCIES)
       set(_Boost_${uppercomponent}_DEPENDENCIES ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE)
       set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE)
       foreach(componentdep ${_Boost_${uppercomponent}_DEPENDENCIES})
-        list(FIND _boost_processed_components "${componentdep}" _boost_component_found)
-        list(FIND _boost_new_components "${componentdep}" _boost_component_new)
-        if (_boost_component_found EQUAL -1 AND _boost_component_new EQUAL -1)
+        if (NOT ("${componentdep}" IN_LIST _boost_processed_components OR "${componentdep}" IN_LIST _boost_new_components))
           list(APPEND _boost_new_components ${componentdep})
         endif()
       endforeach()
@@ -886,6 +891,33 @@ function(_Boost_MISSING_DEPENDENCIES componentvar extravar)
 endfunction()
 
 #
+# Some boost libraries may require particular set of compler features.
+# The very first one was `boost::fiber` introduced in Boost 1.62.
+# One can check required compiler features of it in
+# `${Boost_ROOT}/libs/fiber/build/Jamfile.v2`.
+#
+function(_Boost_COMPILER_FEATURES component _ret)
+  # Boost >= 1.62 and < 1.65
+  if(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106500)
+    set(_Boost_FIBER_COMPILER_FEATURES
+        cxx_alias_templates
+        cxx_auto_type
+        cxx_constexpr
+        cxx_defaulted_functions
+        cxx_final
+        cxx_lambdas
+        cxx_noexcept
+        cxx_nullptr
+        cxx_rvalue_references
+        cxx_thread_local
+        cxx_variadic_templates
+    )
+  endif()
+  string(TOUPPER ${component} uppercomponent)
+  set(${_ret} ${_Boost_${uppercomponent}_COMPILER_FEATURES} PARENT_SCOPE)
+endfunction()
+
+#
 # Update library search directory hint variable with paths used by prebuilt boost binaries.
 #
 # Prebuilt windows binaries (https://sourceforge.net/projects/boost/files/boost-binaries/)
@@ -893,7 +925,7 @@ endfunction()
 # This function would append corresponding directories if MSVC is a current compiler,
 # so having `BOOST_ROOT` would be enough to specify to find everything.
 #
-macro(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir)
+function(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir)
   if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
     if(CMAKE_SIZEOF_VOID_P EQUAL 8)
       set(_arch_suffix 64)
@@ -901,7 +933,8 @@ macro(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlib
       set(_arch_suffix 32)
     endif()
     if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10)
-      list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-15.0)
+      list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.1)
+      list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0)
     elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19)
       list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0)
     elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18)
@@ -915,8 +948,9 @@ macro(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlib
     elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14)
       list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-8.0)
     endif()
+    set(${componentlibvar} ${${componentlibvar}} PARENT_SCOPE)
   endif()
-endmacro()
+endfunction()
 
 #
 # End functions/macros
@@ -1119,6 +1153,12 @@ if(NOT Boost_INCLUDE_DIR)
   if( Boost_NO_SYSTEM_PATHS)
     list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH)
   else()
+    if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
+      foreach(ver ${_Boost_KNOWN_VERSIONS})
+        string(REPLACE "." "_" ver "${ver}")
+        list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS "C:/local/boost_${ver}")
+      endforeach()
+    endif()
     list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS
       C:/boost/include
       C:/boost
@@ -1392,12 +1432,16 @@ foreach(c DEBUG RELEASE)
     if( Boost_NO_SYSTEM_PATHS )
       list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH)
     else()
+      foreach(ver ${_Boost_KNOWN_VERSIONS})
+        string(REPLACE "." "_" ver "${ver}")
+        _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/local/boost_${ver}")
+      endforeach()
+      _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost")
       list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} PATHS
         C:/boost/lib
         C:/boost
         /sw/local/lib
         )
-      _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost")
     endif()
   endif()
 endforeach()
@@ -1457,8 +1501,7 @@ endif()
 _Boost_MISSING_DEPENDENCIES(Boost_FIND_COMPONENTS _Boost_EXTRA_FIND_COMPONENTS)
 
 # If thread is required, get the thread libs as a dependency
-list(FIND Boost_FIND_COMPONENTS thread _Boost_THREAD_DEPENDENCY_LIBS)
-if(NOT _Boost_THREAD_DEPENDENCY_LIBS EQUAL -1)
+if("thread" IN_LIST Boost_FIND_COMPONENTS)
   include(CMakeFindDependencyMacro)
   find_dependency(Threads)
 endif()
@@ -1524,17 +1567,24 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS})
   #
   # Find RELEASE libraries
   #
-  set(_boost_RELEASE_NAMES
-    ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION}
-    ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}
+  unset(_boost_RELEASE_NAMES)
+  foreach(compiler IN LISTS _boost_COMPILER)
+    list(APPEND _boost_RELEASE_NAMES
+      ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION}
+      ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} )
+  endforeach()
+  list(APPEND _boost_RELEASE_NAMES
     ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION}
     ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}
     ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} )
   if(_boost_STATIC_RUNTIME_WORKAROUND)
     set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}")
+    foreach(compiler IN LISTS _boost_COMPILER)
+      list(APPEND _boost_RELEASE_NAMES
+        ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
+        ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} )
+    endforeach()
     list(APPEND _boost_RELEASE_NAMES
-      ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
-      ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}
       ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
       ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} )
   endif()
@@ -1565,18 +1615,25 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS})
   #
   # Find DEBUG libraries
   #
-  set(_boost_DEBUG_NAMES
-    ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION}
-    ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}
+  unset(_boost_DEBUG_NAMES)
+  foreach(compiler IN LISTS _boost_COMPILER)
+    list(APPEND _boost_DEBUG_NAMES
+      ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION}
+      ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} )
+  endforeach()
+  list(APPEND _boost_DEBUG_NAMES
     ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION}
     ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}
     ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}
     ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} )
   if(_boost_STATIC_RUNTIME_WORKAROUND)
     set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}")
+    foreach(compiler IN LISTS _boost_COMPILER)
+      list(APPEND _boost_DEBUG_NAMES
+        ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
+        ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} )
+    endforeach()
     list(APPEND _boost_DEBUG_NAMES
-      ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
-      ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}
       ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION}
       ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} )
   endif()
@@ -1611,6 +1668,9 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS})
 
   _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT})
 
+  # Check if component requires some compiler features
+  _Boost_COMPILER_FEATURES(${COMPONENT} _Boost_${UPPERCOMPONENT}_COMPILER_FEATURES)
+
 endforeach()
 
 # Restore the original find library ordering
@@ -1782,6 +1842,10 @@ if(Boost_FOUND)
           set_target_properties(Boost::${COMPONENT} PROPERTIES
             INTERFACE_LINK_LIBRARIES "${_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES}")
         endif()
+        if(_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES)
+          set_target_properties(Boost::${COMPONENT} PROPERTIES
+            INTERFACE_COMPILE_FEATURES "${_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES}")
+        endif()
       endif()
     endif()
   endforeach()
@@ -1862,3 +1926,6 @@ list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED)
 list(SORT _Boost_COMPONENTS_SEARCHED)
 set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}"
   CACHE INTERNAL "Components requested for this build tree.")
+
+# Restore project's policies
+cmake_policy(POP)
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index 6b76c25..a4dca54 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -67,6 +67,13 @@
 #   -- Set to ON for Emulation mode. -D_DEVICEEMU is defined for CUDA C files
 #      when CUDA_BUILD_EMULATION is TRUE.
 #
+#   CUDA_LINK_LIBRARIES_KEYWORD (Default "")
+#    -- The <PRIVATE|PUBLIC|INTERFACE> keyword to use for internal
+#       target_link_libraries calls. The default is to use no keyword which
+#       uses the old "plain" form of target_link_libraries. Note that is matters
+#       because whatever is used inside the FindCUDA module must also be used
+#       outside - the two forms of target_link_libraries cannot be mixed.
+#
 #   CUDA_GENERATED_OUTPUT_DIR (Default CMAKE_CURRENT_BINARY_DIR)
 #   -- Set to the path you wish to have the generated files placed.  If it is
 #      blank output files will be placed in CMAKE_CURRENT_BINARY_DIR.
@@ -1740,12 +1747,12 @@ macro(CUDA_ADD_LIBRARY cuda_target)
   # variable will have been defined.
   CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS("${link_file}" ${cuda_target} "${_options}" "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}")
 
-  target_link_libraries(${cuda_target}
+  target_link_libraries(${cuda_target} ${CUDA_LINK_LIBRARIES_KEYWORD}
     ${CUDA_LIBRARIES}
     )
 
   if(CUDA_SEPARABLE_COMPILATION)
-    target_link_libraries(${cuda_target}
+    target_link_libraries(${cuda_target} ${CUDA_LINK_LIBRARIES_KEYWORD}
       ${CUDA_cudadevrt_LIBRARY}
       )
   endif()
@@ -1790,7 +1797,7 @@ macro(CUDA_ADD_EXECUTABLE cuda_target)
   # variable will have been defined.
   CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS("${link_file}" ${cuda_target} "${_options}" "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}")
 
-  target_link_libraries(${cuda_target}
+  target_link_libraries(${cuda_target} ${CUDA_LINK_LIBRARIES_KEYWORD}
     ${CUDA_LIBRARIES}
     )
 
@@ -1818,7 +1825,7 @@ macro(cuda_compile_base cuda_target format generated_files)
   else()
     set(_counter 1)
   endif()
-  set(_cuda_target "${_cuda_target}_${_counter}")
+  string(APPEND _cuda_target "_${_counter}")
   set_property(DIRECTORY PROPERTY _cuda_internal_phony_counter ${_counter})
 
   # Separate the sources from the options
@@ -1876,9 +1883,9 @@ endmacro()
 ###############################################################################
 macro(CUDA_ADD_CUFFT_TO_TARGET target)
   if (CUDA_BUILD_EMULATION)
-    target_link_libraries(${target} ${CUDA_cufftemu_LIBRARY})
+    target_link_libraries(${target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_cufftemu_LIBRARY})
   else()
-    target_link_libraries(${target} ${CUDA_cufft_LIBRARY})
+    target_link_libraries(${target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_cufft_LIBRARY})
   endif()
 endmacro()
 
@@ -1889,9 +1896,9 @@ endmacro()
 ###############################################################################
 macro(CUDA_ADD_CUBLAS_TO_TARGET target)
   if (CUDA_BUILD_EMULATION)
-    target_link_libraries(${target} ${CUDA_cublasemu_LIBRARY})
+    target_link_libraries(${target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_cublasemu_LIBRARY})
   else()
-    target_link_libraries(${target} ${CUDA_cublas_LIBRARY} ${CUDA_cublas_device_LIBRARY})
+    target_link_libraries(${target} ${CUDA_LINK_LIBRARIES_KEYWORD} ${CUDA_cublas_LIBRARY} ${CUDA_cublas_device_LIBRARY})
   endif()
 endmacro()
 
diff --git a/Modules/FindCygwin.cmake b/Modules/FindCygwin.cmake
index 90cbd52..b2ed703 100644
--- a/Modules/FindCygwin.cmake
+++ b/Modules/FindCygwin.cmake
@@ -8,13 +8,13 @@
 # this module looks for Cygwin
 
 if (WIN32)
-  find_path(CYGWIN_INSTALL_PATH
+  find_program(CYGWIN_INSTALL_PATH
     cygwin.bat
     "C:/Cygwin"
     "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Cygwin\\setup;rootdir]"
     "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\/;native]"
   )
-
+  get_filename_component(CYGWIN_INSTALL_PATH "${CYGWIN_INSTALL_PATH}" DIRECTORY)
   mark_as_advanced(
     CYGWIN_INSTALL_PATH
   )
diff --git a/Modules/FindDevIL.cmake b/Modules/FindDevIL.cmake
index 45fab82..f6c8e3f 100644
--- a/Modules/FindDevIL.cmake
+++ b/Modules/FindDevIL.cmake
@@ -25,7 +25,7 @@
 #                     library interfaces with OpenGL. It is not strictly needed
 #                     in applications.
 #    IL_INCLUDE_DIR - where to find the il.h, ilu.h and ilut.h files.
-#    IL_FOUND -       this is set to TRUE if all the above variables were set.
+#    DevIL_FOUND    - this is set to TRUE if all the above variables were set.
 #                     This will be set to false if ILU or ILUT are not found,
 #                     even if they are not needed. In most systems, if one
 #                     library is found all the others are as well. That's the
@@ -45,7 +45,7 @@ find_path(IL_INCLUDE_DIR il.h
 
 find_library(IL_LIBRARIES
   NAMES IL DEVIL
-  PATH_SUFFIXES lib64 lib lib32
+  PATH_SUFFIXES libx32 lib64 lib lib32
   DOC "The file that corresponds to the base il library."
 )
 
@@ -53,7 +53,7 @@ find_library(IL_LIBRARIES
 
 find_library(ILUT_LIBRARIES
   NAMES ILUT
-  PATH_SUFFIXES lib64 lib lib32
+  PATH_SUFFIXES libx32 lib64 lib lib32
   DOC "The file that corresponds to the il (system?) utility library."
 )
 
@@ -61,7 +61,7 @@ find_library(ILUT_LIBRARIES
 
 find_library(ILU_LIBRARIES
   NAMES ILU
-  PATH_SUFFIXES lib64 lib lib32
+  PATH_SUFFIXES libx32 lib64 lib lib32
   DOC "The file that corresponds to the il utility library."
 )
 
@@ -70,3 +70,5 @@ find_library(ILU_LIBRARIES
 FIND_PACKAGE_HANDLE_STANDARD_ARGS(DevIL DEFAULT_MSG
                                   IL_LIBRARIES ILU_LIBRARIES
                                   IL_INCLUDE_DIR)
+# provide legacy variable for compatiblity
+set(IL_FOUND ${DevIL_FOUND})
diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake
index 8275ac8..46bf340 100644
--- a/Modules/FindDoxygen.cmake
+++ b/Modules/FindDoxygen.cmake
@@ -1,161 +1,1050 @@
 # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 # file Copyright.txt or https://cmake.org/licensing for details.
 
-#.rst:
-# FindDoxygen
-# -----------
-#
-# This module looks for Doxygen and the path to Graphviz's dot
-#
-# Doxygen is a documentation generation tool.  Please see
-# http://www.doxygen.org
-#
-# This module accepts the following optional variables:
-#
-# ::
-#
-#    DOXYGEN_SKIP_DOT       = If true this module will skip trying to find Dot
-#                             (an optional component often used by Doxygen)
-#
-#
-#
-# This modules defines the following variables:
-#
-# ::
-#
-#    DOXYGEN_EXECUTABLE     = The path to the doxygen command.
-#    DOXYGEN_FOUND          = Was Doxygen found or not?
-#    DOXYGEN_VERSION        = The version reported by doxygen --version
-#
-#
-#
-# ::
-#
-#    DOXYGEN_DOT_EXECUTABLE = The path to the dot program used by doxygen.
-#    DOXYGEN_DOT_FOUND      = Was Dot found or not?
-#
-# For compatibility with older versions of CMake, the now-deprecated
-# variable ``DOXYGEN_DOT_PATH`` is set to the path to the directory
-# containing ``dot`` as reported in ``DOXYGEN_DOT_EXECUTABLE``.
-# The path may have forward slashes even on Windows and is not
-# suitable for direct substitution into a ``Doxyfile.in`` template.
-# If you need this value, use :command:`get_filename_component`
-# to compute it from ``DOXYGEN_DOT_EXECUTABLE`` directly, and
-# perhaps the :command:`file(TO_NATIVE_PATH)` command to prepare
-# the path for a Doxygen configuration file.
+#[=======================================================================[.rst:
+FindDoxygen
+-----------
+
+Doxygen is a documentation generation tool (see http://www.doxygen.org).
+This module looks for Doxygen and some optional tools it supports. These
+tools are enabled as components in the :command:`find_package` command:
+
+``dot``
+  `Graphviz <http://graphviz.org>`_ ``dot`` utility used to render various
+  graphs.
+``mscgen``
+  `Message Chart Generator <http://www.mcternan.me.uk/mscgen/>`_ utility used
+  by Doxygen's ``\msc`` and ``\mscfile`` commands.
+``dia``
+  `Dia <https://wiki.gnome.org/Apps/Dia>`_ the diagram editor used by Doxygen's
+  ``\diafile`` command.
+
+Examples:
+
+.. code-block:: cmake
+
+  # Require dot, treat the other components as optional
+  find_package(Doxygen
+               REQUIRED dot
+               OPTIONAL_COMPONENTS mscgen dia)
+
+The following variables are defined by this module:
+
+.. variable:: DOXYGEN_FOUND
+
+  True if the ``doxygen`` executable was found.
+
+.. variable:: DOXYGEN_VERSION
+
+  The version reported by ``doxygen --version``.
+
+The module defines ``IMPORTED`` targets for Doxygen and each component found.
+These can be used as part of custom commands, etc. and should be preferred over
+old-style (and now deprecated) variables like ``DOXYGEN_EXECUTABLE``. The
+following import targets are defined if their corresponding executable could be
+found (the component import targets will only be defined if that component was
+requested):
+
+::
+
+  Doxygen::doxygen
+  Doxygen::dot
+  Doxygen::mscgen
+  Doxygen::dia
+
+
+Functions
+^^^^^^^^^
+
+.. command:: doxygen_add_docs
+
+  This function is intended as a convenience for adding a target for generating
+  documentation with Doxygen. It aims to provide sensible defaults so that
+  projects can generally just provide the input files and directories and that
+  will be sufficient to give sensible results. The function supports the
+  ability to customize the Doxygen configuration used to build the
+  documentation.
+
+  ::
+
+    doxygen_add_docs(targetName
+        [filesOrDirs...]
+        [WORKING_DIRECTORY dir]
+        [COMMENT comment])
+
+  The function constructs a ``Doxyfile`` and defines a custom target that runs
+  Doxygen on that generated file. The listed files and directories are used as
+  the ``INPUT`` of the generated ``Doxyfile`` and they can contain wildcards.
+  Any files that are listed explicitly will also be added as ``SOURCES`` of the
+  custom target so they will show up in an IDE project's source list.
+
+  So that relative input paths work as expected, by default the working
+  directory of the Doxygen command will be the current source directory (i.e.
+  :variable:`CMAKE_CURRENT_SOURCE_DIR`). This can be overridden with the
+  ``WORKING_DIRECTORY`` option to change the directory used as the relative
+  base point. Note also that Doxygen's default behavior is to strip the working
+  directory from relative paths in the generated documentation (see the
+  ``STRIP_FROM_PATH`` `Doxygen config option
+  <http://www.doxygen.org/manual/config.html>`_ for details).
+
+  If provided, the optional ``comment`` will be passed as the ``COMMENT`` for
+  the :command:`add_custom_target` command used to create the custom target
+  internally.
+
+  The contents of the generated ``Doxyfile`` can be customized by setting CMake
+  variables before calling ``doxygen_add_docs()``. Any variable with a name of
+  the form ``DOXYGEN_<tag>`` will have its value substituted for the
+  corresponding ``<tag>`` configuration option in the ``Doxyfile``. See the
+  `Doxygen documentation <http://www.doxygen.org/manual/config.html>`_ for the
+  full list of supported configuration options.
+
+  Some of Doxygen's defaults are overridden to provide more appropriate
+  behavior for a CMake project. Each of the following will be explicitly set
+  unless the variable already has a value before ``doxygen_add_docs()`` is
+  called (with some exceptions noted):
+
+  .. variable:: DOXYGEN_HAVE_DOT
+
+    Set to ``YES`` if the ``dot`` component was requested and it was found,
+    ``NO`` otherwise. Any existing value of ``DOXYGEN_HAVE_DOT`` is ignored.
+
+  .. variable:: DOXYGEN_DOT_MULTI_TARGETS
+
+    Set to ``YES`` by this module (note that this requires a ``dot`` version
+    newer than 1.8.10). This option is only meaningful if ``DOXYGEN_HAVE_DOT``
+    is also set to ``YES``.
+
+  .. variable:: DOXYGEN_GENERATE_LATEX
+
+    Set to ``NO`` by this module.
+
+  .. variable:: DOXYGEN_WARN_FORMAT
+
+    For Visual Studio based generators, this is set to the form recognized by
+    the Visual Studio IDE: ``$file($line) : $text``. For all other generators,
+    Doxygen's default value is not overridden.
+
+  .. variable:: DOXYGEN_PROJECT_NAME
+
+    Populated with the name of the current project (i.e.
+    :variable:`PROJECT_NAME`).
+
+  .. variable:: DOXYGEN_PROJECT_NUMBER
+
+    Populated with the version of the current project (i.e.
+    :variable:`PROJECT_VERSION`).
+
+  .. variable:: DOXYGEN_PROJECT_BRIEF
+
+    Populated with the description of the current project (i.e.
+    :variable:`PROJECT_DESCRIPTION`).
+
+  .. variable:: DOXYGEN_INPUT
+
+    Projects should not set this variable. It will be populated with the set of
+    files and directories passed to ``doxygen_add_docs()``, thereby providing
+    consistent behavior with the other built-in commands like
+    :command:`add_executable`, :command:`add_library` and
+    :command:`add_custom_target`. If a variable named ``DOXYGEN_INPUT`` is set
+    by the project, it will be ignored and a warning will be issued.
+
+  .. variable:: DOXYGEN_RECURSIVE
+
+    Set to ``YES`` by this module.
+
+  .. variable:: DOXYGEN_EXCLUDE_PATTERNS
+
+    If the set of inputs includes directories, this variable will specify
+    patterns used to exclude files from them. The following patterns are added
+    by ``doxygen_add_docs()`` to ensure CMake-specific files and directories
+    are not included in the input. If the project sets
+    ``DOXYGEN_EXCLUDE_PATTERNS``, those contents are merged with these
+    additional patterns rather than replacing them:
+
+    ::
+
+      */.git/*
+      */.svn/*
+      */.hg/*
+      */CMakeFiles/*
+      */_CPack_Packages/*
+      DartConfiguration.tcl
+      CMakeLists.txt
+      CMakeCache.txt
+
+  .. variable:: DOXYGEN_OUTPUT_DIRECTORY
+
+    Set to :variable:`CMAKE_CURRENT_BINARY_DIR` by this module. Note that if
+    the project provides its own value for this and it is a relative path, it
+    will be converted to an absolute path relative to the current binary
+    directory. This is necessary because doxygen will normally be run from a
+    directory within the source tree so that relative source paths work as
+    expected. If this directory does not exist, it will be recursively created
+    prior to executing the doxygen commands.
+
+To change any of these defaults or override any other Doxygen config option,
+set relevant variables before calling ``doxygen_add_docs()``. For example:
+
+  .. code-block:: cmake
+
+    set(DOXYGEN_GENERATE_HTML NO)
+    set(DOXYGEN_GENERATE_MAN YES)
+
+    doxygen_add_docs(
+        doxygen
+        ${PROJECT_SOURCE_DIR}
+        COMMENT "Generate man pages"
+    )
+
+A number of Doxygen config options accept lists of values, but Doxygen requires
+them to be separated by whitespace. CMake variables hold lists as a string with
+items separated by semi-colons, so a conversion needs to be performed. The
+``doxygen_add_docs()`` command specifically checks the following Doxygen config
+options and will convert their associated CMake variable's contents into the
+required form if set.
+
+::
+
+  ABBREVIATE_BRIEF
+  ALIASES
+  CITE_BIB_FILES
+  DIAFILE_DIRS
+  DOTFILE_DIRS
+  DOT_FONTPATH
+  ENABLED_SECTIONS
+  EXAMPLE_PATH
+  EXAMPLE_PATTERNS
+  EXCLUDE
+  EXCLUDE_PATTERNS
+  EXCLUDE_SYMBOLS
+  EXPAND_AS_DEFINED
+  EXTENSION_MAPPING
+  EXTRA_PACKAGES
+  EXTRA_SEARCH_MAPPINGS
+  FILE_PATTERNS
+  FILTER_PATTERNS
+  FILTER_SOURCE_PATTERNS
+  HTML_EXTRA_FILES
+  HTML_EXTRA_STYLESHEET
+  IGNORE_PREFIX
+  IMAGE_PATH
+  INCLUDE_FILE_PATTERNS
+  INCLUDE_PATH
+  INPUT
+  LATEX_EXTRA_FILES
+  LATEX_EXTRA_STYLESHEET
+  MATHJAX_EXTENSIONS
+  MSCFILE_DIRS
+  PLANTUML_INCLUDE_PATH
+  PREDEFINED
+  QHP_CUST_FILTER_ATTRS
+  QHP_SECT_FILTER_ATTRS
+  STRIP_FROM_INC_PATH
+  STRIP_FROM_PATH
+  TAGFILES
+  TCL_SUBST
+
+The following single value Doxygen options would be quoted automatically
+if they contain at least one space:
+
+::
+
+  CHM_FILE
+  DIA_PATH
+  DOCBOOK_OUTPUT
+  DOCSET_FEEDNAME
+  DOCSET_PUBLISHER_NAME
+  DOT_FONTNAME
+  DOT_PATH
+  EXTERNAL_SEARCH_ID
+  FILE_VERSION_FILTER
+  GENERATE_TAGFILE
+  HHC_LOCATION
+  HTML_FOOTER
+  HTML_HEADER
+  HTML_OUTPUT
+  HTML_STYLESHEET
+  INPUT_FILTER
+  LATEX_FOOTER
+  LATEX_HEADER
+  LATEX_OUTPUT
+  LAYOUT_FILE
+  MAN_OUTPUT
+  MAN_SUBDIR
+  MATHJAX_CODEFILE
+  MSCGEN_PATH
+  OUTPUT_DIRECTORY
+  PERL_PATH
+  PLANTUML_JAR_PATH
+  PROJECT_BRIEF
+  PROJECT_LOGO
+  PROJECT_NAME
+  QCH_FILE
+  QHG_LOCATION
+  QHP_CUST_FILTER_NAME
+  QHP_VIRTUAL_FOLDER
+  RTF_EXTENSIONS_FILE
+  RTF_OUTPUT
+  RTF_STYLESHEET_FILE
+  SEARCHDATA_FILE
+  USE_MDFILE_AS_MAINPAGE
+  WARN_FORMAT
+  WARN_LOGFILE
+  XML_OUTPUT
+
+Deprecated Result Variables
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For compatibility with previous versions of CMake, the following variables
+are also defined but they are deprecated and should no longer be used:
+
+.. variable:: DOXYGEN_EXECUTABLE
+
+  The path to the ``doxygen`` command. If projects need to refer to the
+  ``doxygen`` executable directly, they should use the ``Doxygen::doxygen``
+  import target instead.
+
+.. variable:: DOXYGEN_DOT_FOUND
+
+  True if the ``dot`` executable was found.
+
+.. variable:: DOXYGEN_DOT_EXECUTABLE
+
+  The path to the ``dot`` command. If projects need to refer to the ``dot``
+  executable directly, they should use the ``Doxygen::dot`` import target
+  instead.
+
+.. variable:: DOXYGEN_DOT_PATH
+
+  The path to the directory containing the ``dot`` executable as reported in
+  ``DOXYGEN_DOT_EXECUTABLE``. The path may have forward slashes even on Windows
+  and is not suitable for direct substitution into a ``Doxyfile.in`` template.
+  If you need this value, get the :prop_tgt:`IMPORTED_LOCATION` property of the
+  ``Doxygen::dot`` target and use :command:`get_filename_component` to extract
+  the directory part of that path. You may also want to consider using
+  :command:`file(TO_NATIVE_PATH)` to prepare the path for a Doxygen
+  configuration file.
+
+
+Deprecated Hint Variables
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. variable:: DOXYGEN_SKIP_DOT
+
+  This variable has no any effect for component form of ``find_package``.
+  In backward compatibility mode (i.e. without components list) it prevents
+  the finder module from searching for Graphviz's ``dot`` utility.
+
+#]=======================================================================]
 
 # For backwards compatibility support
 if(Doxygen_FIND_QUIETLY)
-  set(DOXYGEN_FIND_QUIETLY TRUE)
+    set(DOXYGEN_FIND_QUIETLY TRUE)
 endif()
 
 # ===== Rationale for OS X AppBundle mods below =====
-#     With the OS X GUI version, Doxygen likes to be installed to /Applications and
-#     it contains the doxygen executable in the bundle. In the versions I've
-#     seen, it is located in Resources, but in general, more often binaries are
-#     located in MacOS.
-#
-#     NOTE: The official Doxygen.app that is distributed for OS X uses non-standard
-#     conventions.  Instead of the command-line "doxygen" tool being placed in
-#     Doxygen.app/Contents/MacOS, "Doxywizard" is placed there instead and
-#     "doxygen" is placed in Contents/Resources.  This is most likely done
-#     so that something happens when people double-click on the Doxygen.app
-#     package.  Unfortunately, CMake gets confused by this as when it sees the
-#     bundle it uses "Doxywizard" as the executable to use instead of
-#     "doxygen".  Therefore to work-around this issue we temporarily disable
-#     the app-bundle feature, just for this CMake module:
+#  With the OS X GUI version, Doxygen likes to be installed to /Applications
+#  and it contains the doxygen executable in the bundle. In the versions I've
+#  seen, it is located in Resources, but in general, more often binaries are
+#  located in MacOS.
+#
+#  NOTE: The official Doxygen.app distributed for OS X uses non-standard
+#  conventions. Instead of the command-line "doxygen" tool being placed in
+#  Doxygen.app/Contents/MacOS, "Doxywizard" is placed there instead and
+#  "doxygen" is placed in Contents/Resources.  This is most likely done
+#  so that something happens when people double-click on the Doxygen.app
+#  package. Unfortunately, CMake gets confused by this as when it sees the
+#  bundle it uses "Doxywizard" as the executable to use instead of
+#  "doxygen". Therefore to work-around this issue we temporarily disable
+#  the app-bundle feature, just for this CMake module:
+#
 if(APPLE)
-    #  Save the old setting
+    # Save the old setting
     set(TEMP_DOXYGEN_SAVE_CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE})
     # Disable the App-bundle detection feature
     set(CMAKE_FIND_APPBUNDLE "NEVER")
 endif()
-#     FYI:
-#     In the older versions of OS X Doxygen, dot was included with the
-#     Doxygen bundle. But the new versions require you to download
-#     Graphviz.app which contains "dot" in it's bundle.
+# FYI:
+# In older versions of OS X Doxygen, dot was included with the Doxygen bundle,
+# but newer versions require you to download Graphviz.app which contains "dot"
+# or use something like homebrew.
 # ============== End OSX stuff ================
 
 #
 # Find Doxygen...
 #
+macro(_Doxygen_find_doxygen)
+    find_program(
+        DOXYGEN_EXECUTABLE
+        NAMES doxygen
+        PATHS
+            "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\doxygen_is1;Inno Setup: App Path]/bin"
+            /Applications/Doxygen.app/Contents/Resources
+            /Applications/Doxygen.app/Contents/MacOS
+        DOC "Doxygen documentation generation tool (http://www.doxygen.org)"
+    )
+    mark_as_advanced(DOXYGEN_EXECUTABLE)
 
-find_program(DOXYGEN_EXECUTABLE
-  NAMES doxygen
-  PATHS
-    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\doxygen_is1;Inno Setup: App Path]/bin"
-    /Applications/Doxygen.app/Contents/Resources
-    /Applications/Doxygen.app/Contents/MacOS
-  DOC "Doxygen documentation generation tool (http://www.doxygen.org)"
-)
+    if(DOXYGEN_EXECUTABLE)
+        execute_process(
+            COMMAND "${DOXYGEN_EXECUTABLE}" --version
+            OUTPUT_VARIABLE DOXYGEN_VERSION
+            OUTPUT_STRIP_TRAILING_WHITESPACE
+            RESULT_VARIABLE _Doxygen_version_result
+        )
+        if(_Doxygen_version_result)
+            message(WARNING "Unable to determine doxygen version: ${_Doxygen_version_result}")
+        endif()
 
-if(DOXYGEN_EXECUTABLE)
-  execute_process(COMMAND ${DOXYGEN_EXECUTABLE} "--version" OUTPUT_VARIABLE DOXYGEN_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
-endif()
+        # Create an imported target for Doxygen
+        if(NOT TARGET Doxygen::doxygen)
+            add_executable(Doxygen::doxygen IMPORTED GLOBAL)
+            set_target_properties(Doxygen::doxygen PROPERTIES
+                IMPORTED_LOCATION "${DOXYGEN_EXECUTABLE}"
+            )
+        endif()
+    endif()
+endmacro()
 
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(Doxygen REQUIRED_VARS DOXYGEN_EXECUTABLE VERSION_VAR DOXYGEN_VERSION)
-
-#
-# Find Dot...
-#
-
-set(_x86 "(x86)")
-file(GLOB _Doxygen_GRAPHVIZ_BIN_DIRS
-  "$ENV{ProgramFiles}/Graphviz*/bin"
-  "$ENV{ProgramFiles${_x86}}/Graphviz*/bin"
-  )
-unset(_x86)
-
-if(NOT DOXYGEN_SKIP_DOT)
-  find_program(DOXYGEN_DOT_EXECUTABLE
-    NAMES dot
-    PATHS
-      ${_Doxygen_GRAPHVIZ_BIN_DIRS}
-      "$ENV{ProgramFiles}/ATT/Graphviz/bin"
-      "C:/Program Files/ATT/Graphviz/bin"
-      [HKEY_LOCAL_MACHINE\\SOFTWARE\\ATT\\Graphviz;InstallPath]/bin
-      /Applications/Graphviz.app/Contents/MacOS
-      /Applications/Doxygen.app/Contents/Resources
-      /Applications/Doxygen.app/Contents/MacOS
-    DOC "Graphviz Dot tool for using Doxygen"
-  )
-
-  if(DOXYGEN_DOT_EXECUTABLE)
-    set(DOXYGEN_DOT_FOUND TRUE)
-    # The Doxyfile wants the path to Dot, not the entire path and executable
-    get_filename_component(DOXYGEN_DOT_PATH "${DOXYGEN_DOT_EXECUTABLE}" PATH)
-  endif()
+#
+# Find Diagram Editor...
+#
+macro(_Doxygen_find_dia)
+    set(_x86 "(x86)")
+    find_program(
+        DOXYGEN_DIA_EXECUTABLE
+        NAMES dia
+        PATHS
+            "$ENV{ProgramFiles}/Dia"
+            "$ENV{ProgramFiles${_x86}}/Dia"
+        DOC "Diagram Editor tool for use with Doxygen"
+    )
+    mark_as_advanced(DOXYGEN_DIA_EXECUTABLE)
+
+    if(DOXYGEN_DIA_EXECUTABLE)
+        # The Doxyfile wants the path to the utility, not the entire path
+        # including file name
+        get_filename_component(DOXYGEN_DIA_PATH
+                              "${DOXYGEN_DIA_EXECUTABLE}"
+                              DIRECTORY)
+        if(WIN32)
+            file(TO_NATIVE_PATH "${DOXYGEN_DIA_PATH}" DOXYGEN_DIA_PATH)
+        endif()
+
+        # Create an imported target for component
+        if(NOT TARGET Doxygen::dia)
+            add_executable(Doxygen::dia IMPORTED GLOBAL)
+            set_target_properties(Doxygen::dia PROPERTIES
+                IMPORTED_LOCATION "${DOXYGEN_DIA_EXECUTABLE}"
+            )
+        endif()
+    endif()
+
+    unset(_x86)
+endmacro()
+
+#
+# Find Graphviz Dot...
+#
+macro(_Doxygen_find_dot)
+    set(_x86 "(x86)")
+    file(
+        GLOB _Doxygen_GRAPHVIZ_BIN_DIRS
+        "$ENV{ProgramFiles}/Graphviz*/bin"
+        "$ENV{ProgramFiles${_x86}}/Graphviz*/bin"
+    )
+    find_program(
+        DOXYGEN_DOT_EXECUTABLE
+        NAMES dot
+        PATHS
+            ${_Doxygen_GRAPHVIZ_BIN_DIRS}
+            "$ENV{ProgramFiles}/ATT/Graphviz/bin"
+            "C:/Program Files/ATT/Graphviz/bin"
+            [HKEY_LOCAL_MACHINE\\SOFTWARE\\ATT\\Graphviz;InstallPath]/bin
+            /Applications/Graphviz.app/Contents/MacOS
+            /Applications/Doxygen.app/Contents/Resources
+            /Applications/Doxygen.app/Contents/MacOS
+        DOC "Dot tool for use with Doxygen"
+    )
+    mark_as_advanced(DOXYGEN_DOT_EXECUTABLE)
+
+    if(DOXYGEN_DOT_EXECUTABLE)
+        # The Doxyfile wants the path to the utility, not the entire path
+        # including file name
+        get_filename_component(DOXYGEN_DOT_PATH
+                               "${DOXYGEN_DOT_EXECUTABLE}"
+                               DIRECTORY)
+        if(WIN32)
+            file(TO_NATIVE_PATH "${DOXYGEN_DOT_PATH}" DOXYGEN_DOT_PATH)
+        endif()
+
+        # Create an imported target for component
+        if(NOT TARGET Doxygen::dot)
+            add_executable(Doxygen::dot IMPORTED GLOBAL)
+            set_target_properties(Doxygen::dot PROPERTIES
+                IMPORTED_LOCATION "${DOXYGEN_DOT_EXECUTABLE}"
+            )
+        endif()
+    endif()
+
+    unset(_Doxygen_GRAPHVIZ_BIN_DIRS)
+    unset(_x86)
+endmacro()
 
+#
+# Find Message Sequence Chart...
+#
+macro(_Doxygen_find_mscgen)
+    set(_x86 "(x86)")
+    find_program(
+        DOXYGEN_MSCGEN_EXECUTABLE
+        NAMES mscgen
+        PATHS
+            "$ENV{ProgramFiles}/Mscgen"
+            "$ENV{ProgramFiles${_x86}}/Mscgen"
+        DOC "Message sequence chart tool for use with Doxygen"
+    )
+    mark_as_advanced(DOXYGEN_MSCGEN_EXECUTABLE)
+
+    if(DOXYGEN_MSCGEN_EXECUTABLE)
+        # The Doxyfile wants the path to the utility, not the entire path
+        # including file name
+        get_filename_component(DOXYGEN_MSCGEN_PATH
+                               "${DOXYGEN_MSCGEN_EXECUTABLE}"
+                               DIRECTORY)
+        if(WIN32)
+            file(TO_NATIVE_PATH "${DOXYGEN_MSCGEN_PATH}" DOXYGEN_MSCGEN_PATH)
+        endif()
+
+        # Create an imported target for component
+        if(NOT TARGET Doxygen::mscgen)
+            add_executable(Doxygen::mscgen IMPORTED GLOBAL)
+            set_target_properties(Doxygen::mscgen PROPERTIES
+                IMPORTED_LOCATION "${DOXYGEN_MSCGEN_EXECUTABLE}"
+            )
+        endif()
+    endif()
+
+    unset(_x86)
+endmacro()
+
+# Make sure `doxygen` is one of the components to find
+set(_Doxygen_keep_backward_compat FALSE)
+if(NOT Doxygen_FIND_COMPONENTS)
+    # Search at least for `doxygen` executable
+    set(Doxygen_FIND_COMPONENTS doxygen)
+    # Preserve backward compatibility:
+    # search for `dot` also if `DOXYGEN_SKIP_DOT` is not explicitly disable this.
+    if(NOT DOXYGEN_SKIP_DOT)
+        list(APPEND Doxygen_FIND_COMPONENTS dot)
+    endif()
+    set(_Doxygen_keep_backward_compat TRUE)
+elseif(NOT doxygen IN_LIST Doxygen_FIND_COMPONENTS)
+    list(INSERT Doxygen_FIND_COMPONENTS 0 doxygen)
 endif()
 
 #
-# Backwards compatibility...
+# Find all requested components of Doxygen...
 #
+foreach(_comp IN LISTS Doxygen_FIND_COMPONENTS)
+    if(_comp STREQUAL "doxygen")
+        _Doxygen_find_doxygen()
+    elseif(_comp STREQUAL "dia")
+        _Doxygen_find_dia()
+    elseif(_comp STREQUAL "dot")
+        _Doxygen_find_dot()
+    elseif(_comp STREQUAL "mscgen")
+        _Doxygen_find_mscgen()
+    else()
+        message(WARNING "${_comp} is not a valid Doxygen component")
+        set(Doxygen_${_comp}_FOUND FALSE)
+        continue()
+    endif()
+
+    if(TARGET Doxygen::${_comp})
+        set(Doxygen_${_comp}_FOUND TRUE)
+    else()
+        set(Doxygen_${_comp}_FOUND FALSE)
+    endif()
+endforeach()
+unset(_comp)
+
+# Verify find results
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(
+    Doxygen
+    REQUIRED_VARS DOXYGEN_EXECUTABLE
+    VERSION_VAR DOXYGEN_VERSION
+    HANDLE_COMPONENTS
+)
 
+#
+# Backwards compatibility...
+#
 if(APPLE)
-  # Restore the old app-bundle setting setting
-  set(CMAKE_FIND_APPBUNDLE ${TEMP_DOXYGEN_SAVE_CMAKE_FIND_APPBUNDLE})
+    # Restore the old app-bundle setting
+    set(CMAKE_FIND_APPBUNDLE ${TEMP_DOXYGEN_SAVE_CMAKE_FIND_APPBUNDLE})
 endif()
 
-# Maintain the _FOUND variables as "YES" or "NO" for backwards compatibility
-# (allows people to stuff them directly into Doxyfile with configure_file())
+# Maintain the _FOUND variables as "YES" or "NO" for backwards
+# compatibility. This allows people to substitute them directly into
+# Doxyfile with configure_file().
 if(DOXYGEN_FOUND)
-  set(DOXYGEN_FOUND "YES")
+    set(DOXYGEN_FOUND "YES")
 else()
-  set(DOXYGEN_FOUND "NO")
+    set(DOXYGEN_FOUND "NO")
 endif()
-if(DOXYGEN_DOT_FOUND)
-  set(DOXYGEN_DOT_FOUND "YES")
-else()
-  set(DOXYGEN_DOT_FOUND "NO")
+if(_Doxygen_keep_backward_compat)
+    if(Doxygen_dot_FOUND)
+        set(DOXYGEN_DOT_FOUND "YES")
+    else()
+        set(DOXYGEN_DOT_FOUND "NO")
+    endif()
+
+    # For backwards compatibility support for even older CMake versions
+    set(DOXYGEN ${DOXYGEN_EXECUTABLE})
+    set(DOT ${DOXYGEN_DOT_EXECUTABLE})
+
+    # No need to keep any backward compatibility for `DOXYGEN_MSCGEN_XXX`
+    # and `DOXYGEN_DIA_XXX` since they were not supported before component
+    # support was added
 endif()
+unset(_Doxygen_keep_backward_compat)
 
-# For backwards compatibility support
-set (DOXYGEN ${DOXYGEN_EXECUTABLE} )
-set (DOT ${DOXYGEN_DOT_EXECUTABLE} )
+#
+# Allow full control of Doxygen from CMakeLists.txt
+#
+
+# Prepare a template Doxyfile and Doxygen's default values CMake file
+if(TARGET Doxygen::doxygen)
+    # If doxygen was found, use it to generate a minimal default Doxyfile.
+    # We will delete this file after we have finished using it below to
+    # generate the other files that doxygen_add_docs() will use.
+    set(_Doxygen_tpl "${CMAKE_BINARY_DIR}/CMakeDoxyfile.tpl")
+    execute_process(
+        COMMAND "${DOXYGEN_EXECUTABLE}" -s -g "${_Doxygen_tpl}"
+        OUTPUT_QUIET
+        RESULT_VARIABLE _Doxygen_tpl_result
+    )
+    if(_Doxygen_tpl_result)
+        message(FATAL_ERROR
+                "Unable to generate Doxyfile template: ${_Doxygen_tpl_result}")
+    elseif(NOT EXISTS "${_Doxygen_tpl}")
+        message(FATAL_ERROR
+                "Doxygen has failed to generate a Doxyfile template")
+    endif()
+
+    # Write a do-not-edit header to files we are going to generate...
+    set(_Doxygen_dne_header
+[[
+#
+# DO NOT EDIT! THIS FILE WAS GENERATED BY CMAKE!
+#
+
+]]
+    )
+    # We only need one copy of these across the whole build, since their
+    # content is only dependent on the version of Doxygen being used. Therefore
+    # we always put them at the top of the build tree so that they are in a
+    # predictable location.
+    set(_doxyfile_in       "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in")
+    set(_doxyfile_defaults "${CMAKE_BINARY_DIR}/CMakeDoxygenDefaults.cmake")
+
+    file(WRITE "${_doxyfile_in}"       ${_Doxygen_dne_header})
+    file(WRITE "${_doxyfile_defaults}" ${_Doxygen_dne_header})
+
+    # Get strings containing a configuration key from the template Doxyfile
+    # we obtained from this version of Doxygen. Because some options are split
+    # across multiple lines by ending lines with backslashes, we cannot just
+    # use file(STRINGS...) with a REGEX. Instead, read lines without a REGEX
+    # so that file(STRINGS...) handles the trailing backslash as a line
+    # continuation. It stores multi-lines as lists, so we then have to replace
+    # the ";" list separator with backslashed newlines again so that we get the
+    # original content stored back as the value part.
+    file(STRINGS "${_Doxygen_tpl}" _file_lines)
+    unset(_Doxygen_tpl_params)
+    foreach(_line IN LISTS _file_lines)
+        if(_line MATCHES "([A-Z][A-Z0-9_]+)( *=)(.*)")
+            set(_key "${CMAKE_MATCH_1}")
+            set(_eql "${CMAKE_MATCH_2}")
+            string(REPLACE ";" "\\\n" _value "${CMAKE_MATCH_3}")
+            list(APPEND _Doxygen_tpl_params "${_key}${_eql}${_value}")
+        endif()
+    endforeach()
+
+    # Build up a Doxyfile that provides @configVar@ substitutions for each
+    # Doxygen config option as well as a separate CMake script which provides
+    # the default value for each of those options if the project doesn't supply
+    # them. Each config option will support substitution of a CMake variable
+    # of the same name except with DOXYGEN_ prepended.
+    foreach(_Doxygen_param IN LISTS _Doxygen_tpl_params)
+        if(_Doxygen_param MATCHES "([A-Z][A-Z0-9_]+)( *)=( (.*))?")
+            # Ok, this is a config key with a value
+            if(CMAKE_MATCH_COUNT EQUAL 4)
+                file(APPEND "${_doxyfile_in}"
+                    "${CMAKE_MATCH_1}${CMAKE_MATCH_2}= @DOXYGEN_${CMAKE_MATCH_1}@\n")
+                # Remove the backslashes we had to preserve to handle newlines
+                string(REPLACE "\\\n" "\n" _value "${CMAKE_MATCH_4}")
+                file(APPEND "${_doxyfile_defaults}"
+"if(NOT DEFINED DOXYGEN_${CMAKE_MATCH_1})
+    set(DOXYGEN_${CMAKE_MATCH_1} ${_value})
+endif()
+")
+            # Ok, this is a config key with empty default value
+            elseif(CMAKE_MATCH_COUNT EQUAL 2)
+                file(APPEND "${_doxyfile_in}"
+                    "${CMAKE_MATCH_1}${CMAKE_MATCH_2}= @DOXYGEN_${CMAKE_MATCH_1}@\n")
+            else()
+                message(AUTHOR_WARNING
+"Unexpected line format! Code review required!\nFault line: ${_Doxygen_param}")
+            endif()
+        else()
+            message(AUTHOR_WARNING
+"Unexpected line format! Code review required!\nFault line: ${_Doxygen_param}")
+        endif()
+    endforeach()
+
+    # Ok, dumped defaults are not needed anymore...
+    file(REMOVE "${_Doxygen_tpl}")
+
+    unset(_Doxygen_param)
+    unset(_Doxygen_tpl_params)
+    unset(_Doxygen_dne_header)
+    unset(_Doxygen_tpl)
+
+endif()
+
+function(doxygen_quote_value VARIABLE)
+    # Quote a value of the given variable if:
+    # - variable parameter was really given
+    # - a variable it points is defined
+    # - a value doesn't quoted already
+    # - and it has spaces
+    if(VARIABLE AND DEFINED ${VARIABLE} AND
+       NOT ${VARIABLE} MATCHES "^\".* .*\"$" AND ${VARIABLE} MATCHES " ")
+        set(${VARIABLE} "\"${${VARIABLE}}\"" PARENT_SCOPE)
+    endif()
+endfunction()
+
+function(doxygen_list_to_quoted_strings LIST_VARIABLE)
+    if(LIST_VARIABLE AND DEFINED ${LIST_VARIABLE})
+        unset(_inputs)
+        unset(_sep)
+        foreach(_in IN LISTS ${LIST_VARIABLE})
+            doxygen_quote_value(_in)
+            string(APPEND _inputs "${_sep}${_in}")
+            set(_sep " ")
+        endforeach()
+        set(${LIST_VARIABLE} "${_inputs}" PARENT_SCOPE)
+    endif()
+endfunction()
+
+function(doxygen_add_docs targetName)
+    set(_options)
+    set(_one_value_args WORKING_DIRECTORY COMMENT)
+    set(_multi_value_args)
+    cmake_parse_arguments(_args
+                          "${_options}"
+                          "${_one_value_args}"
+                          "${_multi_value_args}"
+                          ${ARGN})
+
+    if(NOT _args_COMMENT)
+        set(_args_COMMENT "Generate API documentation for ${targetName}")
+    endif()
+
+    if(NOT _args_WORKING_DIRECTORY)
+        set(_args_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+    endif()
+
+    if(DEFINED DOXYGEN_INPUT)
+        message(WARNING
+"DOXYGEN_INPUT is set but it will be ignored. Pass the files and directories \
+directly to the doxygen_add_docs() command instead.")
+    endif()
+    set(DOXYGEN_INPUT ${_args_UNPARSED_ARGUMENTS})
+
+    if(NOT TARGET Doxygen::doxygen)
+        message(FATAL_ERROR "Doxygen was not found, needed by \
+doxygen_add_docs() for target ${targetName}")
+    endif()
+
+    # If not already defined, set some relevant defaults based on the
+    # assumption that the documentation is for the whole project. Details
+    # specified in the project() command will be used to populate a number of
+    # these defaults.
+
+    if(NOT DEFINED DOXYGEN_PROJECT_NAME)
+        # The PROJECT_NAME tag is a single word (or a sequence of words
+        # surrounded by double-quotes, unless you are using Doxywizard) that
+        # should identify the project for which the documentation is generated.
+        # This name is used in the title of most generated pages and in a few
+        # other places. The default value is: My Project.
+        set(DOXYGEN_PROJECT_NAME ${PROJECT_NAME})
+    endif()
+
+    if(NOT DEFINED DOXYGEN_PROJECT_NUMBER)
+        # The PROJECT_NUMBER tag can be used to enter a project or revision
+        # number. This could be handy for archiving the generated documentation
+        # or if some version control system is used.
+        set(DOXYGEN_PROJECT_NUMBER ${PROJECT_VERSION})
+    endif()
+
+    if(NOT DEFINED DOXYGEN_PROJECT_BRIEF)
+        # Using the PROJECT_BRIEF tag one can provide an optional one line
+        # description for a project that appears at the top of each page and
+        # should give viewer a quick idea about the purpose of the project.
+        # Keep the description short.
+        set(DOXYGEN_PROJECT_BRIEF "${PROJECT_DESCRIPTION}")
+    endif()
+
+    if(NOT DEFINED DOXYGEN_RECURSIVE)
+        # The RECURSIVE tag can be used to specify whether or not
+        # subdirectories should be searched for input files as well. CMake
+        # projects generally evolve to span multiple directories, so it makes
+        # more sense for this to be on by default. Doxygen's default value
+        # has this setting turned off, so we override it.
+        set(DOXYGEN_RECURSIVE YES)
+    endif()
+
+    if(NOT DEFINED DOXYGEN_OUTPUT_DIRECTORY)
+        # The OUTPUT_DIRECTORY tag is used to specify the (relative or
+        # absolute) path into which the generated documentation will be
+        # written. If a relative path is used, Doxygen will interpret it as
+        # being relative to the location where doxygen was started, but we need
+        # to run Doxygen in the source tree so that relative input paths work
+        # intuitively. Therefore, we ensure that the output directory is always
+        # an absolute path and if the project provided a relative path, we
+        # treat it as relative to the current BINARY directory so that output
+        # is not generated inside the source tree.
+        set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+    elseif(NOT IS_ABSOLUTE "${DOXYGEN_OUTPUT_DIRECTORY}")
+        get_filename_component(DOXYGEN_OUTPUT_DIRECTORY
+                               "${DOXYGEN_OUTPUT_DIRECTORY}"
+                               ABSOLUTE
+                               BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+    endif()
+
+    if(NOT DEFINED DOXYGEN_HAVE_DOT)
+        # If you set the HAVE_DOT tag to YES then doxygen will assume the dot
+        # tool is available from the path. This tool is part of Graphviz (see:
+        # http://www.graphviz.org/), a graph visualization toolkit from AT&T
+        # and Lucent Bell Labs. The other options in this section have no
+        # effect if this option is set to NO.
+        # Doxygen's default value is: NO.
+        set(DOXYGEN_HAVE_DOT ${DOXYGEN_DOT_FOUND})
+    endif()
+
+    if(NOT DEFINED DOXYGEN_DOT_MULTI_TARGETS)
+        # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate
+        # multiple output files in one run (i.e. multiple -o and -T options on
+        # the command line). This makes dot run faster, but since only newer
+        # versions of dot (>1.8.10) support this, Doxygen disables this feature
+        # by default.
+        # This tag requires that the tag HAVE_DOT is set to YES.
+        set(DOXYGEN_DOT_MULTI_TARGETS YES)
+    endif()
+
+    if(NOT DEFINED DOXYGEN_GENERATE_LATEX)
+        # If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX
+        # output. We only want the HTML output enabled by default, so we turn
+        # this off if the project hasn't specified it.
+        set(DOXYGEN_GENERATE_LATEX NO)
+    endif()
+
+    if(NOT DEFINED DOXYGEN_WARN_FORMAT)
+        if(CMAKE_VS_MSBUILD_COMMAND OR CMAKE_VS_DEVENV_COMMAND)
+            # The WARN_FORMAT tag determines the format of the warning messages
+            # that doxygen can produce. The string should contain the $file,
+            # $line and $text tags, which will be replaced by the file and line
+            # number from which the warning originated and the warning text.
+            # Optionally, the format may contain $version, which will be
+            # replaced by the version of the file (if it could be obtained via
+            # FILE_VERSION_FILTER).
+            # Doxygen's default value is: $file:$line: $text
+            set(DOXYGEN_WARN_FORMAT "$file($line) : $text ")
+        endif()
+    endif()
+
+    if(DEFINED DOXYGEN_WARN_LOGFILE AND NOT IS_ABSOLUTE "${DOXYGEN_WARN_LOGFILE}")
+        # The WARN_LOGFILE tag can be used to specify a file to which warning and error
+        # messages should be written. If left blank the output is written to standard
+        # error (stderr).
+        get_filename_component(DOXYGEN_WARN_LOGFILE
+                               "${DOXYGEN_WARN_LOGFILE}"
+                               ABSOLUTE
+                               BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+    endif()
+
+    # Any files from the INPUT that match any of the EXCLUDE_PATTERNS will be
+    # excluded from the set of input files. We provide some additional patterns
+    # to prevent commonly unwanted things from CMake builds being pulled in.
+    #
+    # Note that the wildcards are matched against the file with absolute path,
+    # so to exclude all test directories for example use the pattern */test/*
+    list(
+        APPEND
+        DOXYGEN_EXCLUDE_PATTERNS
+        "*/.git/*"
+        "*/.svn/*"
+        "*/.hg/*"
+        "*/CMakeFiles/*"
+        "*/_CPack_Packages/*"
+        "DartConfiguration.tcl"
+        "CMakeLists.txt"
+        "CMakeCache.txt"
+    )
+
+    # Now bring in Doxgen's defaults for those things the project has not
+    # already set and we have not provided above
+    include("${CMAKE_BINARY_DIR}/CMakeDoxygenDefaults.cmake" OPTIONAL)
+
+    # Cleanup built HTMLs on "make clean"
+    # TODO Any other dirs?
+    if(DOXYGEN_GENERATE_HTML)
+        if(IS_ABSOLUTE "${DOXYGEN_HTML_OUTPUT}")
+            set(_args_clean_html_dir "${DOXYGEN_HTML_OUTPUT}")
+        else()
+            set(_args_clean_html_dir
+                "${DOXYGEN_OUTPUT_DIRECTORY}/${DOXYGEN_HTML_OUTPUT}")
+        endif()
+        set_property(DIRECTORY APPEND PROPERTY
+            ADDITIONAL_MAKE_CLEAN_FILES "${_args_clean_html_dir}")
+    endif()
+
+    # Build up a list of files we can identify from the inputs so we can list
+    # them as SOURCES in the custom target (makes them display in IDEs). We
+    # must do this before we transform the various DOXYGEN_... variables below
+    # because we need to process DOXYGEN_INPUT as a list first.
+    unset(_sources)
+    foreach(_item IN LISTS DOXYGEN_INPUT)
+        get_filename_component(_abs_item "${_item}" ABSOLUTE
+                               BASE_DIR "${_args_WORKING_DIRECTORY}")
+        if(EXISTS "${_abs_item}" AND
+           NOT IS_DIRECTORY "${_abs_item}" AND
+           NOT IS_SYMLINK "${_abs_item}")
+            list(APPEND _sources "${_abs_item}")
+        endif()
+    endforeach()
+    if(_sources)
+        list(INSERT _sources 0 SOURCES)
+    endif()
+
+    # Transform known list type options into space separated strings.
+    set(_doxygen_list_options
+        ABBREVIATE_BRIEF
+        ALIASES
+        CITE_BIB_FILES
+        DIAFILE_DIRS
+        DOTFILE_DIRS
+        DOT_FONTPATH
+        ENABLED_SECTIONS
+        EXAMPLE_PATH
+        EXAMPLE_PATTERNS
+        EXCLUDE
+        EXCLUDE_PATTERNS
+        EXCLUDE_SYMBOLS
+        EXPAND_AS_DEFINED
+        EXTENSION_MAPPING
+        EXTRA_PACKAGES
+        EXTRA_SEARCH_MAPPINGS
+        FILE_PATTERNS
+        FILTER_PATTERNS
+        FILTER_SOURCE_PATTERNS
+        HTML_EXTRA_FILES
+        HTML_EXTRA_STYLESHEET
+        IGNORE_PREFIX
+        IMAGE_PATH
+        INCLUDE_FILE_PATTERNS
+        INCLUDE_PATH
+        INPUT
+        LATEX_EXTRA_FILES
+        LATEX_EXTRA_STYLESHEET
+        MATHJAX_EXTENSIONS
+        MSCFILE_DIRS
+        PLANTUML_INCLUDE_PATH
+        PREDEFINED
+        QHP_CUST_FILTER_ATTRS
+        QHP_SECT_FILTER_ATTRS
+        STRIP_FROM_INC_PATH
+        STRIP_FROM_PATH
+        TAGFILES
+        TCL_SUBST
+    )
+    foreach(_item IN LISTS _doxygen_list_options)
+        doxygen_list_to_quoted_strings(DOXYGEN_${_item})
+    endforeach()
+
+    # Transform known single value variables which may contain spaces, such as
+    # paths or description strings.
+    set(_doxygen_quoted_options
+        CHM_FILE
+        DIA_PATH
+        DOCBOOK_OUTPUT
+        DOCSET_FEEDNAME
+        DOCSET_PUBLISHER_NAME
+        DOT_FONTNAME
+        DOT_PATH
+        EXTERNAL_SEARCH_ID
+        FILE_VERSION_FILTER
+        GENERATE_TAGFILE
+        HHC_LOCATION
+        HTML_FOOTER
+        HTML_HEADER
+        HTML_OUTPUT
+        HTML_STYLESHEET
+        INPUT_FILTER
+        LATEX_FOOTER
+        LATEX_HEADER
+        LATEX_OUTPUT
+        LAYOUT_FILE
+        MAN_OUTPUT
+        MAN_SUBDIR
+        MATHJAX_CODEFILE
+        MSCGEN_PATH
+        OUTPUT_DIRECTORY
+        PERL_PATH
+        PLANTUML_JAR_PATH
+        PROJECT_BRIEF
+        PROJECT_LOGO
+        PROJECT_NAME
+        QCH_FILE
+        QHG_LOCATION
+        QHP_CUST_FILTER_NAME
+        QHP_VIRTUAL_FOLDER
+        RTF_EXTENSIONS_FILE
+        RTF_OUTPUT
+        RTF_STYLESHEET_FILE
+        SEARCHDATA_FILE
+        USE_MDFILE_AS_MAINPAGE
+        WARN_FORMAT
+        WARN_LOGFILE
+        XML_OUTPUT
+    )
+
+    # Store the unmodified value of DOXYGEN_OUTPUT_DIRECTORY prior to invoking
+    # doxygen_quote_value() below. This will mutate the string specifically for
+    # consumption by Doxygen's config file, which we do not want when we use it
+    # later in the custom target's commands.
+    set( _original_doxygen_output_dir ${DOXYGEN_OUTPUT_DIRECTORY} )
+
+    foreach(_item IN LISTS _doxygen_quoted_options)
+        doxygen_quote_value(DOXYGEN_${_item})
+    endforeach()
+
+    # Prepare doxygen configuration file
+    set(_doxyfile_template "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in")
+    set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.${targetName}")
+    configure_file("${_doxyfile_template}" "${_target_doxyfile}")
+
+    # Add the target
+    add_custom_target( ${targetName} VERBATIM
+        COMMAND ${CMAKE_COMMAND} -E make_directory ${_original_doxygen_output_dir}
+        COMMAND "${DOXYGEN_EXECUTABLE}" "${_target_doxyfile}"
+        WORKING_DIRECTORY "${_args_WORKING_DIRECTORY}"
+        DEPENDS "${_target_doxyfile}"
+        COMMENT "${_args_COMMENT}"
+        ${_sources}
+    )
 
-mark_as_advanced(
-  DOXYGEN_EXECUTABLE
-  DOXYGEN_DOT_EXECUTABLE
-  )
+endfunction()
diff --git a/Modules/FindGLEW.cmake b/Modules/FindGLEW.cmake
index d8609e6..11e8724 100644
--- a/Modules/FindGLEW.cmake
+++ b/Modules/FindGLEW.cmake
@@ -27,7 +27,7 @@
 find_path(GLEW_INCLUDE_DIR GL/glew.h)
 
 if(NOT GLEW_LIBRARY)
-  find_library(GLEW_LIBRARY_RELEASE NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64)
+  find_library(GLEW_LIBRARY_RELEASE NAMES GLEW glew32 glew glew32s PATH_SUFFIXES lib64 libx32)
   find_library(GLEW_LIBRARY_DEBUG NAMES GLEWd glew32d glewd PATH_SUFFIXES lib64)
 
   include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake
index 02e6df0..88d4b29 100644
--- a/Modules/FindGLUT.cmake
+++ b/Modules/FindGLUT.cmake
@@ -120,10 +120,12 @@ if (GLUT_FOUND)
   # If not, we need some way to figure out what platform we are on.
   set( GLUT_LIBRARIES
     ${GLUT_glut_LIBRARY}
-    ${GLUT_Xmu_LIBRARY}
-    ${GLUT_Xi_LIBRARY}
-    ${GLUT_cocoa_LIBRARY}
     )
+  foreach(v GLUT_Xmu_LIBRARY GLUT_Xi_LIBRARY GLUT_cocoa_LIBRARY)
+    if(${v})
+      list(APPEND GLUT_LIBRARIES ${${v}})
+    endif()
+  endforeach()
 
   if(NOT TARGET GLUT::GLUT)
     add_library(GLUT::GLUT UNKNOWN IMPORTED)
diff --git a/Modules/FindGSL.cmake b/Modules/FindGSL.cmake
index 76059b3..8d10b6c 100644
--- a/Modules/FindGSL.cmake
+++ b/Modules/FindGSL.cmake
@@ -37,9 +37,10 @@
 #
 # This script expects to find libraries at ``$GSL_ROOT_DIR/lib`` and the GSL
 # headers at ``$GSL_ROOT_DIR/include/gsl``.  The library directory may
-# optionally provide Release and Debug folders.  For Unix-like systems, this
-# script will use ``$GSL_ROOT_DIR/bin/gsl-config`` (if found) to aid in the
-# discovery GSL.
+# optionally provide Release and Debug folders. If available, the libraries
+# named ``gsld``, ``gslblasd`` or ``cblasd`` are recognized as debug libraries.
+# For Unix-like systems, this script will use ``$GSL_ROOT_DIR/bin/gsl-config``
+# (if found) to aid in the discovery of GSL.
 #
 # Cache Variables
 # ^^^^^^^^^^^^^^^
@@ -105,12 +106,12 @@ find_library( GSL_CBLAS_LIBRARY
 )
 # Do we also have debug versions?
 find_library( GSL_LIBRARY_DEBUG
-  NAMES gsl
+  NAMES gsld gsl
   HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR}
   PATH_SUFFIXES Debug
 )
 find_library( GSL_CBLAS_LIBRARY_DEBUG
-  NAMES gslcblas cblas
+  NAMES gslcblasd cblasd gslcblas cblas
   HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR}
   PATH_SUFFIXES Debug
 )
diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake
index fd179a8..b87b9f3 100644
--- a/Modules/FindGTK2.cmake
+++ b/Modules/FindGTK2.cmake
@@ -292,8 +292,10 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr)
     find_path(GTK2_${_var}_INCLUDE_DIR ${_hdr}
         PATHS
             ${_gtk2_arch_dir}
+            /usr/local/libx32
             /usr/local/lib64
             /usr/local/lib
+            /usr/libx32
             /usr/lib64
             /usr/lib
             /usr/X11R6/include
diff --git a/Modules/FindGTest.cmake b/Modules/FindGTest.cmake
index 6540171..c4b4535 100644
--- a/Modules/FindGTest.cmake
+++ b/Modules/FindGTest.cmake
@@ -70,64 +70,10 @@
 # Deeper integration with CTest
 # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 #
-# If you would like each Google test to show up in CTest as a test you
-# may use the following macro::
-#
-#     GTEST_ADD_TESTS(executable extra_args files...)
-#
-# ``executable``
-#   the path to the test executable
-# ``extra_args``
-#   a list of extra arguments to be passed to executable enclosed in
-#   quotes (or ``""`` for none)
-# ``files...``
-#   a list of source files to search for tests and test fixtures.  Or
-#   ``AUTO`` to find them from executable target
-#
-# However, note that this macro will slow down your tests by running
-# an executable for each test and test fixture.
-#
-# Example usage::
-#
-#      set(FooTestArgs --foo 1 --bar 2)
-#      add_executable(FooTest FooUnitTest.cc)
-#      GTEST_ADD_TESTS(FooTest "${FooTestArgs}" AUTO)
-
-#
-# Thanks to Daniel Blezek <blezek at gmail.com> for the GTEST_ADD_TESTS code
-
-function(GTEST_ADD_TESTS executable extra_args)
-    if(NOT ARGN)
-        message(FATAL_ERROR "Missing ARGN: Read the documentation for GTEST_ADD_TESTS")
-    endif()
-    if(ARGN STREQUAL "AUTO")
-        # obtain sources used for building that executable
-        get_property(ARGN TARGET ${executable} PROPERTY SOURCES)
-    endif()
-    set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*")
-    set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)")
-    foreach(source ${ARGN})
-        set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source})
-        file(READ "${source}" contents)
-        string(REGEX MATCHALL "${gtest_test_type_regex} *\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents})
-        foreach(hit ${found_tests})
-          string(REGEX MATCH "${gtest_test_type_regex}" test_type ${hit})
+# See :module:`GoogleTest` for information on the :command:`gtest_add_tests`
+# command.
 
-          # Parameterized tests have a different signature for the filter
-          if("x${test_type}" STREQUAL "xTEST_P")
-            string(REGEX REPLACE ${gtest_case_name_regex}  "*/\\1.\\2/*" test_name ${hit})
-          elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST")
-            string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" test_name ${hit})
-          elseif("x${test_type}" STREQUAL "xTYPED_TEST")
-            string(REGEX REPLACE ${gtest_case_name_regex} "\\1/*.\\2" test_name ${hit})
-          else()
-            message(WARNING "Could not parse GTest ${hit} for adding to CTest.")
-            continue()
-          endif()
-          add_test(NAME ${test_name} COMMAND ${executable} --gtest_filter=${test_name} ${extra_args})
-        endforeach()
-    endforeach()
-endfunction()
+include(${CMAKE_CURRENT_LIST_DIR}/GoogleTest.cmake)
 
 function(_gtest_append_debugs _endvar _library)
     if(${_library} AND ${_library}_DEBUG)
diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake
index 2a81da6..5962c5b 100644
--- a/Modules/FindHDF5.cmake
+++ b/Modules/FindHDF5.cmake
@@ -59,12 +59,19 @@
 #                       bindings, if the HL component is enabled
 #
 # Available components are: C CXX Fortran and HL.  For each enabled language
-# binding, a corresponding HDF5_${LANG}_LIBRARIES variable will be defined.
+# binding, a corresponding HDF5_${LANG}_LIBRARIES variable, and potentially
+# HDF5_${LANG}_DEFINITIONS, will be defined.
 # If the HL component is enabled, then an HDF5_${LANG}_HL_LIBRARIES will
 # also be defined.  With all components enabled, the following variables will be defined:
 #
 # ::
 #
+#   HDF5_C_DEFINITIONS -- Required compiler definitions for HDF5 C bindings
+#   HDF5_CXX_DEFINITIONS -- Required compiler definitions for HDF5 C++ bindings
+#   HDF5_Fortran_DEFINITIONS -- Required compiler definitions for HDF5 Fortran bindings
+#   HDF5_C_INCLUDE_DIRS -- Required include directories for HDF5 C bindings
+#   HDF5_CXX_INCLUDE_DIRS -- Required include directories for HDF5 C++ bindings
+#   HDF5_Fortran_INCLUDE_DIRS -- Required include directories for HDF5 Fortran bindings
 #   HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings
 #   HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings
 #   HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings
@@ -92,6 +99,9 @@
 # ``HDF5_ROOT``
 #   Specify the path to the HDF5 installation to use.
 #
+# ``HDF5_FIND_DEBUG``
+#   Set to a true value to get some extra debugging output.
+#
 # ``HDF5_NO_FIND_PACKAGE_CONFIG_FILE``
 #   Set to a true value to skip trying to find ``hdf5-config.cmake``.
 
@@ -344,11 +354,7 @@ macro( _HDF5_parse_compile_line
     libraries
     libraries_hl)
 
-  if(UNIX)
-    separate_arguments(_HDF5_COMPILE_ARGS UNIX_COMMAND "${${compile_line_var}}")
-  else()
-    separate_arguments(_HDF5_COMPILE_ARGS WINDOWS_COMMAND "${${compile_line_var}}")
-  endif()
+  separate_arguments(_HDF5_COMPILE_ARGS NATIVE_COMMAND "${${compile_line_var}}")
 
   foreach(arg IN LISTS _HDF5_COMPILE_ARGS)
     if("${arg}" MATCHES "^-I(.*)$")
@@ -400,15 +406,23 @@ if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE)
       ${_HDF5_SEARCH_OPTS}
       )
     if( HDF5_FOUND)
+        if(HDF5_FIND_DEBUG)
+            message(STATUS "Found HDF5 at ${HDF5_DIR} via NO_MODULE. Now trying to extract locations etc.")
+        endif()
         set(HDF5_IS_PARALLEL ${HDF5_ENABLE_PARALLEL})
         set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR})
         set(HDF5_LIBRARIES)
-        set(HDF5_C_TARGET hdf5)
-        set(HDF5_C_HL_TARGET hdf5_hl)
-        set(HDF5_CXX_TARGET hdf5_cpp)
-        set(HDF5_CXX_HL_TARGET hdf5_hl_cpp)
-        set(HDF5_Fortran_TARGET hdf5_fortran)
-        set(HDF5_Fortran_HL_TARGET hdf5_hl_fortran)
+        if (NOT TARGET hdf5 AND NOT TARGET hdf5-static AND NOT TARGET hdf5-shared)
+            # Some HDF5 versions (e.g. 1.8.18) used hdf5::hdf5 etc
+            set(_target_prefix "hdf5::")
+        endif()
+        set(HDF5_C_TARGET ${_target_prefix}hdf5)
+        set(HDF5_C_HL_TARGET ${_target_prefix}hdf5_hl)
+        set(HDF5_CXX_TARGET ${_target_prefix}hdf5_cpp)
+        set(HDF5_CXX_HL_TARGET ${_target_prefix}hdf5_hl_cpp)
+        set(HDF5_Fortran_TARGET ${_target_prefix}hdf5_fortran)
+        set(HDF5_Fortran_HL_TARGET ${_target_prefix}hdf5_hl_fortran)
+        set(HDF5_DEFINITIONS "")
         if(HDF5_USE_STATIC_LIBRARIES)
             set(_suffix "-static")
         else()
@@ -420,7 +434,7 @@ if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE)
             #if we detect that occurrence clear the suffix
             if(_suffix AND NOT TARGET ${HDF5_${_lang}_TARGET}${_suffix})
               if(NOT TARGET ${HDF5_${_lang}_TARGET})
-                #cant find this component with our without the suffix
+                #cant find this component with or without the suffix
                 #so bail out, and let the following locate HDF5
                 set(HDF5_FOUND FALSE)
                 break()
@@ -428,21 +442,29 @@ if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE)
               set(_suffix "")
             endif()
 
-            get_target_property(_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION)
+            if(HDF5_FIND_DEBUG)
+                message(STATUS "Trying to get properties of target ${HDF5_${_lang}_TARGET}${_suffix}")
+            endif()
+            # Find library for this target. Complicated as on Windows with a DLL, we need to search for the import-lib.
+            get_target_property(_imported_conf ${HDF5_${_lang}_TARGET}${_suffix} IMPORTED_CONFIGURATIONS)
+            get_target_property(_lang_location ${HDF5_${_lang}_TARGET}${_suffix} IMPORTED_IMPLIB_${_imported_conf} )
+            if (NOT _lang_location)
+                # no import lib, just try LOCATION
+                get_target_property(_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION)
+            endif()
             if( _lang_location )
-                set(HDF5_${_lang}_LIBRARY ${_lang_location} CACHE PATH
-                    "HDF5 ${_lang} library" )
-                mark_as_advanced(HDF5_${_lang}_LIBRARY)
+                set(HDF5_${_lang}_LIBRARY ${_lang_location})
                 list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
                 set(HDF5_${_lang}_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
                 set(HDF5_${_lang}_FOUND True)
             endif()
             if(FIND_HL)
-                get_target_property(_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION)
+                get_target_property(__lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_imported_conf} )
+                if (NOT _lang_hl_location)
+                    get_target_property(_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION)
+                endif()
                 if( _lang_hl_location )
-                    set(HDF5_${_lang}_HL_LIBRARY ${_lang_hl_location} CACHE PATH
-                        "HDF5 ${_lang} HL library" )
-                    mark_as_advanced(HDF5_${_lang}_HL_LIBRARY)
+                    set(HDF5_${_lang}_HL_LIBRARY ${_lang_hl_location})
                     list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
                     set(HDF5_${_lang}_HL_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
                     set(HDF5_HL_FOUND True)
@@ -487,10 +509,6 @@ if(NOT HDF5_FOUND)
       set(HDF5_${__lang}_HL_LIBRARIES)
 
       mark_as_advanced(HDF5_${__lang}_COMPILER_EXECUTABLE_NO_INTERROGATE)
-      mark_as_advanced(HDF5_${__lang}_DEFINITIONS)
-      mark_as_advanced(HDF5_${__lang}_INCLUDE_DIRS)
-      mark_as_advanced(HDF5_${__lang}_LIBRARIES)
-      mark_as_advanced(HDF5_${__lang}_HL_LIBRARIES)
 
       set(HDF5_${__lang}_FOUND True)
       set(HDF5_HL_FOUND True)
@@ -580,9 +598,6 @@ if(NOT HDF5_FOUND)
           endif()
 
           set(HDF5_${__lang}_FOUND True)
-          mark_as_advanced(HDF5_${__lang}_DEFINITIONS)
-          mark_as_advanced(HDF5_${__lang}_INCLUDE_DIRS)
-          mark_as_advanced(HDF5_${__lang}_LIBRARIES)
           _HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_DEFINITIONS)
           _HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_INCLUDE_DIRS)
           _HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_LIBRARIES)
@@ -685,6 +700,8 @@ if( NOT HDF5_FOUND )
             ${_HDF5_SEARCH_OPTS}
         )
         mark_as_advanced(HDF5_${__lang}_INCLUDE_DIR)
+        # set the _DIRS variable as this is what the user will normally use
+        set(HDF5_${__lang}_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR})
         list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR})
 
         # find the HDF5 libraries
@@ -826,3 +843,23 @@ find_package_handle_standard_args(HDF5
 )
 
 unset(_HDF5_SEARCH_OPTS)
+
+if( HDF5_FOUND AND NOT HDF5_DIR)
+  # hide HDF5_DIR for the non-advanced user to avoid confusion with
+  # HDF5_DIR-NOT_FOUND while HDF5 was found.
+  mark_as_advanced(HDF5_DIR)
+endif()
+
+if (HDF5_FIND_DEBUG)
+  message(STATUS "HDF5_DIR: ${HDF5_DIR}")
+  message(STATUS "HDF5_DEFINITIONS: ${HDF5_DEFINITIONS}")
+  message(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}")
+  message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}")
+  foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS)
+    message(STATUS "HDF5_${__lang}_DEFINITIONS: ${HDF5_${__lang}_DEFINITIONS}")
+    message(STATUS "HDF5_${__lang}_INCLUDE_DIR: ${HDF5_${__lang}_INCLUDE_DIR}")
+    message(STATUS "HDF5_${__lang}_INCLUDE_DIRS: ${HDF5_${__lang}_INCLUDE_DIRS}")
+    message(STATUS "HDF5_${__lang}_LIBRARY: ${HDF5_${__lang}_LIBRARY}")
+    message(STATUS "HDF5_${__lang}_LIBRARIES: ${HDF5_${__lang}_LIBRARIES}")
+  endforeach()
+endif()
diff --git a/Modules/FindIce.cmake b/Modules/FindIce.cmake
index a61d4a8..e0286ee 100644
--- a/Modules/FindIce.cmake
+++ b/Modules/FindIce.cmake
@@ -198,7 +198,7 @@ function(_Ice_FIND)
   endif()
   # Generic 64-bit and 32-bit directories
   list(APPEND ice_binary_suffixes "bin${_x64}" "bin")
-  list(APPEND ice_library_suffixes "${_lib64}" "lib${_x64}" "lib")
+  list(APPEND ice_library_suffixes "libx32" "${_lib64}" "lib${_x64}" "lib")
   list(APPEND ice_include_suffixes "include")
   list(APPEND ice_slice_suffixes "slice")
 
diff --git a/Modules/FindImageMagick.cmake b/Modules/FindImageMagick.cmake
index 0561a3d..7d5534b 100644
--- a/Modules/FindImageMagick.cmake
+++ b/Modules/FindImageMagick.cmake
@@ -102,7 +102,7 @@ function(FIND_IMAGEMAGICK_API component header)
       ${ImageMagick_INCLUDE_DIRS}
       "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include"
     PATH_SUFFIXES
-      ImageMagick ImageMagick-6
+      ImageMagick ImageMagick-6 ImageMagick-7
     DOC "Path to the ImageMagick arch-independent include dir."
     )
   find_path(ImageMagick_${component}_ARCH_INCLUDE_DIR
@@ -114,7 +114,7 @@ function(FIND_IMAGEMAGICK_API component header)
       ${ImageMagick_INCLUDE_DIRS}
       "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include"
     PATH_SUFFIXES
-      ImageMagick ImageMagick-6
+      ImageMagick ImageMagick-6 ImageMagick-7
     DOC "Path to the ImageMagick arch-specific include dir."
     )
   find_library(ImageMagick_${component}_LIBRARY
@@ -195,17 +195,26 @@ foreach(component ${ImageMagick_FIND_COMPONENTS}
     )
   if(component STREQUAL "Magick++")
     FIND_IMAGEMAGICK_API(Magick++ Magick++.h
-      Magick++ CORE_RL_Magick++_ Magick++-6.Q16 Magick++-Q16 Magick++-6.Q8 Magick++-Q8 Magick++-6.Q16HDRI Magick++-Q16HDRI Magick++-6.Q8HDRI Magick++-Q8HDRI
+      Magick++ CORE_RL_Magick++_
+      Magick++-Q8 Magick++-Q16 Magick++-Q16HDRI Magick++-Q8HDRI
+      Magick++-6.Q16 Magick++-6.Q8 Magick++-6.Q16HDRI Magick++-6.Q8HDRI
+      Magick++-7.Q16 Magick++-7.Q8 Magick++-7.Q16HDRI Magick++-7.Q8HDRI
       )
     list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_Magick++_LIBRARY)
   elseif(component STREQUAL "MagickWand")
-    FIND_IMAGEMAGICK_API(MagickWand wand/MagickWand.h
-      Wand MagickWand CORE_RL_wand_ MagickWand-6.Q16 MagickWand-Q16 MagickWand-6.Q8 MagickWand-Q8 MagickWand-6.Q16HDRI MagickWand-Q16HDRI MagickWand-6.Q8HDRI MagickWand-Q8HDRI
+    FIND_IMAGEMAGICK_API(MagickWand "wand/MagickWand.h;MagickWand/MagickWand.h"
+      Wand MagickWand CORE_RL_wand_
+      MagickWand-Q16 MagickWand-Q8 MagickWand-Q16HDRI MagickWand-Q8HDRI
+      MagickWand-6.Q16 MagickWand-6.Q8 MagickWand-6.Q16HDRI MagickWand-6.Q8HDRI
+      MagickWand-7.Q16 MagickWand-7.Q8 MagickWand-7.Q16HDRI MagickWand-7.Q8HDRI
       )
     list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickWand_LIBRARY)
   elseif(component STREQUAL "MagickCore")
-    FIND_IMAGEMAGICK_API(MagickCore magick/MagickCore.h
-      Magick MagickCore CORE_RL_magick_ MagickCore-6.Q16 MagickCore-Q16 MagickCore-6.Q8 MagickCore-Q8 MagickCore-6.Q16HDRI MagickCore-Q16HDRI MagickCore-6.Q8HDRI MagickCore-Q8HDRI
+    FIND_IMAGEMAGICK_API(MagickCore "magick/MagickCore.h;MagickCore/MagickCore.h"
+      Magick MagickCore CORE_RL_magick_
+      MagickCore-Q16 MagickCore-Q8 MagickCore-Q16HDRI MagickCore-Q8HDRI
+      MagickCore-6.Q16 MagickCore-6.Q8 MagickCore-6.Q16HDRI MagickCore-6.Q8HDRI
+      MagickCore-7.Q16 MagickCore-7.Q8 MagickCore-7.Q16HDRI MagickCore-7.Q8HDRI
       )
     list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickCore_LIBRARY)
   else()
diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake
index 4265a97..3d32560 100644
--- a/Modules/FindJava.cmake
+++ b/Modules/FindJava.cmake
@@ -143,6 +143,9 @@ if(Java_JAVA_EXECUTABLE)
       if(var MATCHES "java version \"([0-9]+\\.[0-9]+\\.[0-9_.]+.*)\"")
         # This is most likely Sun / OpenJDK, or maybe GCJ-java compat layer
         set(Java_VERSION_STRING "${CMAKE_MATCH_1}")
+      elseif(var MATCHES "openjdk version \"([0-9]+)-[a-z]+\"")
+        # OpenJDK 9 early access builds or locally built
+        set(Java_VERSION_STRING "1.${CMAKE_MATCH_1}.0")
       elseif(var MATCHES "java full version \"kaffe-([0-9]+\\.[0-9]+\\.[0-9_]+)\"")
         # Kaffe style
         set(Java_VERSION_STRING "${CMAKE_MATCH_1}")
diff --git a/Modules/FindKDE3.cmake b/Modules/FindKDE3.cmake
index 62e2a50..03216a5 100644
--- a/Modules/FindKDE3.cmake
+++ b/Modules/FindKDE3.cmake
@@ -221,6 +221,8 @@ get_filename_component(KDE3_LIB_DIR ${KDE3_KDECORE_LIBRARY} PATH )
 if(NOT KDE3_LIBTOOL_DIR)
    if(KDE3_KDECORE_LIBRARY MATCHES lib64)
      set(KDE3_LIBTOOL_DIR /lib64/kde3)
+   elseif(KDE3_KDECORE_LIBRARY MATCHES libx32)
+     set(KDE3_LIBTOOL_DIR /libx32/kde3)
    else()
      set(KDE3_LIBTOOL_DIR /lib/kde3)
    endif()
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index ff2c4de..37f3255 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -10,71 +10,78 @@
 # The Message Passing Interface (MPI) is a library used to write
 # high-performance distributed-memory parallel applications, and is
 # typically deployed on a cluster.  MPI is a standard interface (defined
-# by the MPI forum) for which many implementations are available.  All
-# of them have somewhat different include paths, libraries to link
-# against, etc., and this module tries to smooth out those differences.
+# by the MPI forum) for which many implementations are available.
 #
 # Variables
 # ^^^^^^^^^
 #
 # This module will set the following variables per language in your
-# project, where <lang> is one of C, CXX, or Fortran:
-#
-# ::
-#
-#    MPI_<lang>_FOUND           TRUE if FindMPI found MPI flags for <lang>
-#    MPI_<lang>_COMPILER        MPI Compiler wrapper for <lang>
-#    MPI_<lang>_COMPILE_FLAGS   Compilation flags for MPI programs
-#    MPI_<lang>_INCLUDE_PATH    Include path(s) for MPI header
-#    MPI_<lang>_LINK_FLAGS      Linking flags for MPI programs
-#    MPI_<lang>_LIBRARIES       All libraries to link MPI programs against
+# project, where ``<lang>`` is one of C, CXX, or Fortran:
+#
+# ``MPI_<lang>_FOUND``
+#   Variable indicating the MPI settings for ``<lang>`` were found.
+# ``MPI_<lang>_COMPILER``
+#   MPI Compiler wrapper for ``<lang>``.
+# ``MPI_<lang>_COMPILE_FLAGS``
+#   Compilation flags for MPI programs, separated by spaces.
+#   This is *not* a :ref:`;-list <CMake Language Lists>`.
+# ``MPI_<lang>_INCLUDE_PATH``
+#   Include path(s) for MPI header.
+# ``MPI_<lang>_LINK_FLAGS``
+#   Linker flags for MPI programs.
+# ``MPI_<lang>_LIBRARIES``
+#   All libraries to link MPI programs against.
+#
+# Additionally, the following :prop_tgt:`IMPORTED` targets are defined:
+#
+# ``MPI::MPI_<lang>``
+#   Target for using MPI from ``<lang>``.
 #
 # Additionally, FindMPI sets the following variables for running MPI
 # programs from the command line:
 #
-# ::
-#
-#    MPIEXEC                    Executable for running MPI programs
-#    MPIEXEC_NUMPROC_FLAG       Flag to pass to MPIEXEC before giving
-#                               it the number of processors to run on
-#    MPIEXEC_PREFLAGS           Flags to pass to MPIEXEC directly
-#                               before the executable to run.
-#    MPIEXEC_POSTFLAGS          Flags to pass to MPIEXEC after other flags
+# ``MPIEXEC``
+#   Executable for running MPI programs, if provided.
+# ``MPIEXEC_NUMPROC_FLAG``
+#   Flag to pass to ``MPIEXEC`` before giving it the number of processors to run on.
+# ``MPIEXEC_MAX_NUMPROCS``
+#   Number of MPI processors to utilize. Defaults to the number
+#   of processors detected on the host system.
+# ``MPIEXEC_PREFLAGS``
+#   Flags to pass to ``MPIEXEC`` directly before the executable to run.
+# ``MPIEXEC_POSTFLAGS``
+#   Flags to pass to ``MPIEXEC`` after other flags.
 #
 # Usage
 # ^^^^^
 #
-# To use this module, simply call FindMPI from a CMakeLists.txt file, or
-# run ``find_package(MPI)``, then run CMake.  If you are happy with the
+# To use this module, call ``find_package(MPI)``.  If you are happy with the
 # auto-detected configuration for your language, then you're done.  If
 # not, you have two options:
 #
-# ::
-#
-#    1. Set MPI_<lang>_COMPILER to the MPI wrapper (mpicc, etc.) of your
-#       choice and reconfigure.  FindMPI will attempt to determine all the
-#       necessary variables using THAT compiler's compile and link flags.
-#    2. If this fails, or if your MPI implementation does not come with
-#       a compiler wrapper, then set both MPI_<lang>_LIBRARIES and
-#       MPI_<lang>_INCLUDE_PATH.  You may also set any other variables
-#       listed above, but these two are required.  This will circumvent
-#       autodetection entirely.
+# 1. Set ``MPI_<lang>_COMPILER`` to the MPI wrapper (e.g. ``mpicc``) of your
+#    choice and reconfigure.  FindMPI will attempt to determine all the
+#    necessary variables using *that* compiler's compile and link flags.
+# 2. If this fails, or if your MPI implementation does not come with
+#    a compiler wrapper, then set both ``MPI_<lang>_LIBRARIES`` and
+#    ``MPI_<lang>_INCLUDE_PATH``.  You may also set any other variables
+#    listed above, but these two are required.  This will circumvent
+#    autodetection entirely.
 #
 # When configuration is successful, ``MPI_<lang>_COMPILER`` will be set to
-# the compiler wrapper for <lang>, if it was found.  ``MPI_<lang>_FOUND``
+# the compiler wrapper for ``<lang>``, if it was found. ``MPI_<lang>_FOUND``
 # and other variables above will be set if any MPI implementation was
-# found for <lang>, regardless of whether a compiler was found.
+# found for ``<lang>``, regardless of whether a compiler was found.
 #
 # When using ``MPIEXEC`` to execute MPI applications, you should typically
 # use all of the ``MPIEXEC`` flags as follows:
 #
 # ::
 #
-#    ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} PROCS
+#    ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_MAX_NUMPROCS}
 #      ${MPIEXEC_PREFLAGS} EXECUTABLE ${MPIEXEC_POSTFLAGS} ARGS
 #
-# where ``PROCS`` is the number of processors on which to execute the
-# program, ``EXECUTABLE`` is the MPI program, and ``ARGS`` are the arguments to
+# where ``EXECUTABLE`` is the MPI program, and ``ARGS`` are the arguments to
 # pass to the MPI program.
 #
 # Backward Compatibility
@@ -100,12 +107,12 @@ include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
 # The compilers are detected in this order:
 #
 # 1. Try to find the most generic available MPI compiler, as this is usually set up by
-#    cluster admins.  e.g., if plain old mpicc is available, we'll use it and assume it's
+#    cluster admins, e.g. if plain old mpicc is available, we'll use it and assume it's
 #    the right compiler.
 #
 # 2. If a generic mpicc is NOT found, then we attempt to find one that matches
 #    CMAKE_<lang>_COMPILER_ID. e.g. if you are using XL compilers, we'll try to find mpixlc
-#    and company, but not mpiicc.  This hopefully prevents toolchain mismatches.
+#    and company, but not mpiicc. This hopefully prevents toolchain mismatches.
 #
 # If you want to force a particular MPI compiler other than what we autodetect (e.g. if you
 # want to compile regular stuff with GNU and parallel stuff with Intel), you can always set
@@ -476,7 +483,7 @@ function (interrogate_mpi_compiler lang try_libs)
     set(MPI_${lang}_LIBRARIES     ${MPI_LIBRARIES_WORK}     CACHE STRING "MPI ${lang} libraries to link against" FORCE)
     mark_as_advanced(MPI_${lang}_COMPILE_FLAGS MPI_${lang}_INCLUDE_PATH MPI_${lang}_LINK_FLAGS MPI_${lang}_LIBRARIES)
 
-    # clear out our temporary lib/header detectionv variable here.
+    # clear out our temporary lib/header detection variable here.
     set(MPI_LIB         "MPI_LIB-NOTFOUND"         CACHE INTERNAL "Scratch variable for MPI lib detection"    FORCE)
     set(MPI_HEADER_PATH "MPI_HEADER_PATH-NOTFOUND" CACHE INTERNAL "Scratch variable for MPI header detection" FORCE)
   endif()
@@ -546,10 +553,21 @@ find_program(MPIEXEC
 get_filename_component(_MPI_BASE_DIR "${MPIEXEC}" PATH)
 get_filename_component(_MPI_BASE_DIR "${_MPI_BASE_DIR}" PATH)
 
-set(MPIEXEC_NUMPROC_FLAG "-np" CACHE STRING "Flag used by MPI to specify the number of processes for MPIEXEC; the next option will be the number of processes.")
+# According to the MPI standard, section 8.8 -n is a guaranteed, and the only guaranteed way to
+# launch an MPI process using mpiexec if such a program exists.
+set(MPIEXEC_NUMPROC_FLAG "-n"  CACHE STRING "Flag used by MPI to specify the number of processes for MPIEXEC; the next option will be the number of processes.")
 set(MPIEXEC_PREFLAGS     ""    CACHE STRING "These flags will be directly before the executable that is being run by MPIEXEC.")
 set(MPIEXEC_POSTFLAGS    ""    CACHE STRING "These flags will come after all flags given to MPIEXEC.")
-set(MPIEXEC_MAX_NUMPROCS "2"   CACHE STRING "Maximum number of processors available to run MPI applications.")
+
+# Set the number of processes to the processor count and the previous default
+# of 2 if that couldn't be determined.
+include(${CMAKE_CURRENT_LIST_DIR}/ProcessorCount.cmake)
+ProcessorCount(_MPIEXEC_NUMPROCS)
+if("${_MPIEXEC_NUMPROCS}" EQUAL "0")
+  set(_MPIEXEC_NUMPROCS 2)
+endif()
+set(MPIEXEC_MAX_NUMPROCS "${_MPIEXEC_NUMPROCS}"   CACHE STRING "Maximum number of processors available to run MPI applications.")
+unset(_MPIEXEC_NUMPROCS)
 mark_as_advanced(MPIEXEC MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS)
 
 
@@ -621,6 +639,28 @@ foreach (lang C CXX Fortran)
     else()
       find_package_handle_standard_args(MPI_${lang} DEFAULT_MSG MPI_${lang}_LIBRARIES MPI_${lang}_INCLUDE_PATH)
     endif()
+
+    if(MPI_${lang}_FOUND)
+      if(NOT TARGET MPI::MPI_${lang})
+        add_library(MPI::MPI_${lang} INTERFACE IMPORTED)
+      endif()
+      if(MPI_${lang}_COMPILE_FLAGS)
+        separate_arguments(_MPI_${lang}_COMPILE_OPTIONS NATIVE_COMMAND "${MPI_${lang}_COMPILE_FLAGS}")
+        set_property(TARGET MPI::MPI_${lang} PROPERTY
+          INTERFACE_COMPILE_OPTIONS "${_MPI_${lang}_COMPILE_OPTIONS}")
+      endif()
+
+      unset(_MPI_${lang}_LINK_LINE)
+      if(MPI_${lang}_LINK_FLAGS)
+        list(APPEND _MPI_${lang}_LINK_LINE "${MPI_${lang}_LINK_FLAGS}")
+      endif()
+      list(APPEND _MPI_${lang}_LINK_LINE "${MPI_${lang}_LIBRARIES}")
+      set_property(TARGET MPI::MPI_${lang} PROPERTY
+        INTERFACE_LINK_LIBRARIES "${_MPI_${lang}_LINK_LINE}")
+
+      set_property(TARGET MPI::MPI_${lang} PROPERTY
+        INTERFACE_INCLUDE_DIRECTORIES "${MPI_${lang}_INCLUDE_PATH}")
+    endif()
   endif()
 endforeach()
 
@@ -660,6 +700,7 @@ if (MPI_NUMLIBS GREATER 1)
 else()
   set(MPI_EXTRA_LIBRARY "MPI_EXTRA_LIBRARY-NOTFOUND" CACHE STRING "Extra MPI libraries to link against" FORCE)
 endif()
+mark_as_advanced(MPI_LIBRARY MPI_EXTRA_LIBRARY)
 #=============================================================================
 
 # unset these vars to cleanup namespace
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index eae1585..80bcda3 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -225,6 +225,7 @@ if(NOT MATLAB_ADDITIONAL_VERSIONS)
 endif()
 
 set(MATLAB_VERSIONS_MAPPING
+  "R2017a=9.2"
   "R2016b=9.1"
   "R2016a=9.0"
   "R2015b=8.6"
diff --git a/Modules/FindOpenAL.cmake b/Modules/FindOpenAL.cmake
index 8622b4c..c3d202e 100644
--- a/Modules/FindOpenAL.cmake
+++ b/Modules/FindOpenAL.cmake
@@ -79,7 +79,7 @@ find_library(OPENAL_LIBRARY
   NAMES OpenAL al openal OpenAL32
   HINTS
     ENV OPENALDIR
-  PATH_SUFFIXES lib64 lib libs64 libs ${_OpenAL_ARCH_DIR}
+  PATH_SUFFIXES libx32 lib64 lib libs64 libs ${_OpenAL_ARCH_DIR}
   PATHS
   ~/Library/Frameworks
   /Library/Frameworks
diff --git a/Modules/FindOpenCL.cmake b/Modules/FindOpenCL.cmake
index 3eca5e1..b8a7d82 100644
--- a/Modules/FindOpenCL.cmake
+++ b/Modules/FindOpenCL.cmake
@@ -117,7 +117,12 @@ if(WIN32)
   endif()
 else()
   find_library(OpenCL_LIBRARY
-    NAMES OpenCL)
+    NAMES OpenCL
+    PATHS
+      ENV AMDAPPSDKROOT
+    PATH_SUFFIXES
+      lib/x86_64
+      lib/x64)
 endif()
 
 set(OpenCL_LIBRARIES ${OpenCL_LIBRARY})
diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake
index 503d955..af83fb7 100644
--- a/Modules/FindOpenGL.cmake
+++ b/Modules/FindOpenGL.cmake
@@ -178,7 +178,7 @@ if(OPENGL_FOUND)
       if(OPENGL_gl_LIBRARY MATCHES "/([^/]+)\\.framework$")
         set(_gl_fw "${OPENGL_gl_LIBRARY}/${CMAKE_MATCH_1}")
         if(EXISTS "${_gl_fw}.tbd")
-          set(_gl_fw "${_gl_fw}.tbd")
+          string(APPEND _gl_fw ".tbd")
         endif()
         set_target_properties(OpenGL::GL PROPERTIES
           IMPORTED_LOCATION "${_gl_fw}")
@@ -201,7 +201,7 @@ if(OPENGL_FOUND)
       if(OPENGL_glu_LIBRARY MATCHES "/([^/]+)\\.framework$")
         set(_glu_fw "${OPENGL_glu_LIBRARY}/${CMAKE_MATCH_1}")
         if(EXISTS "${_glu_fw}.tbd")
-          set(_glu_fw "${_glu_fw}.tbd")
+          string(APPEND _glu_fw ".tbd")
         endif()
         set_target_properties(OpenGL::GLU PROPERTIES
           IMPORTED_LOCATION "${_glu_fw}")
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index 2ee9439..1093be0 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -13,111 +13,219 @@
 # The variables may be empty if the compiler does not need a special
 # flag to support OpenMP.
 #
-# The following variables are set:
+# Variables
+# ^^^^^^^^^
 #
-# ``OpenMP_C_FLAGS``
-#   Flags to add to the C compiler for OpenMP support.
-# ``OpenMP_CXX_FLAGS``
-#   Flags to add to the CXX compiler for OpenMP support.
-# ``OpenMP_Fortran_FLAGS``
-#   Flags to add to the Fortran compiler for OpenMP support.
-# ``OPENMP_FOUND``
-#   True if openmp is detected.
+# This module will set the following variables per language in your
+# project, where ``<lang>`` is one of C, CXX, or Fortran:
 #
-# The following internal variables are set, if detected:
+# ``OpenMP_<lang>_FOUND``
+#   Variable indicating if OpenMP support for ``<lang>`` was detected.
+# ``OpenMP_<lang>_FLAGS``
+#   OpenMP compiler flags for ``<lang>``, separated by spaces.
 #
-# ``OpenMP_C_SPEC_DATE``
-#   Specification date of OpenMP version of C compiler.
-# ``OpenMP_CXX_SPEC_DATE``
-#   Specification date of OpenMP version of CXX compiler.
-# ``OpenMP_Fortran_SPEC_DATE``
-#   Specification date of OpenMP version of Fortran compiler.
+# For linking with OpenMP code written in ``<lang>``, the following
+# variables are provided:
 #
-# The specification dates are formatted as integers of the form
-# ``CCYYMM`` where these represent the decimal digits of the century,
-# year, and month.
+# ``OpenMP_<lang>_LIB_NAMES``
+#   :ref:`;-list <CMake Language Lists>` of libraries for OpenMP programs for ``<lang>``.
+# ``OpenMP_<libname>_LIBRARY``
+#   Location of the individual libraries needed for OpenMP support in ``<lang>``.
+# ``OpenMP_<lang>_LIBRARIES``
+#   A list of libraries needed to link with OpenMP code written in ``<lang>``.
+#
+# Additionally, the module provides :prop_tgt:`IMPORTED` targets:
+#
+# ``OpenMP::OpenMP_<lang>``
+#   Target for using OpenMP from ``<lang>``.
+#
+# Specifically for Fortran, the module sets the following variables:
+#
+# ``OpenMP_Fortran_HAVE_OMPLIB_HEADER``
+#   Boolean indicating if OpenMP is accessible through ``omp_lib.h``.
+# ``OpenMP_Fortran_HAVE_OMPLIB_MODULE``
+#   Boolean indicating if OpenMP is accessible through the ``omp_lib`` Fortran module.
+#
+# The module will also try to provide the OpenMP version variables:
+#
+# ``OpenMP_<lang>_SPEC_DATE``
+#   Date of the OpenMP specification implemented by the ``<lang>`` compiler.
+# ``OpenMP_<lang>_VERSION_MAJOR``
+#   Major version of OpenMP implemented by the ``<lang>`` compiler.
+# ``OpenMP_<lang>_VERSION_MINOR``
+#   Minor version of OpenMP implemented by the ``<lang>`` compiler.
+# ``OpenMP_<lang>_VERSION``
+#   OpenMP version implemented by the ``<lang>`` compiler.
+#
+# The specification date is formatted as given in the OpenMP standard:
+# ``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of
+# the OpenMP specification implemented by the ``<lang>`` compiler.
+#
+# Backward Compatibility
+# ^^^^^^^^^^^^^^^^^^^^^^
+#
+# For backward compatibility with older versions of FindOpenMP, these
+# variables are set, but deprecated::
+#
+#   OpenMP_FOUND
+#
+# In new projects, please use the ``OpenMP_<lang>_XXX`` equivalents.
 
-set(_OPENMP_REQUIRED_VARS)
-set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
-set(CMAKE_REQUIRED_QUIET ${OpenMP_FIND_QUIETLY})
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
 
 function(_OPENMP_FLAG_CANDIDATES LANG)
-  set(OpenMP_FLAG_CANDIDATES
-    #Empty, if compiler automatically accepts openmp
-    " "
-    #GNU
-    "-fopenmp"
-    #Clang
-    "-fopenmp=libomp"
-    #Microsoft Visual Studio
-    "/openmp"
-    #Intel windows
-    "-Qopenmp"
-    #PathScale, Intel
-    "-openmp"
-    #Sun
-    "-xopenmp"
-    #HP
-    "+Oopenmp"
-    #IBM XL C/c++
-    "-qsmp"
-    #Portland Group, MIPSpro
-    "-mp"
-  )
-
-  set(OMP_FLAG_GNU "-fopenmp")
-  set(OMP_FLAG_Clang "-fopenmp=libomp")
-  set(OMP_FLAG_HP "+Oopenmp")
-  if(WIN32)
-    set(OMP_FLAG_Intel "-Qopenmp")
-  elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND
-         "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528")
-    set(OMP_FLAG_Intel "-openmp")
+  if(NOT OpenMP_${LANG}_FLAG)
+    unset(OpenMP_FLAG_CANDIDATES)
+
+    set(OMP_FLAG_GNU "-fopenmp")
+    set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp")
+    set(OMP_FLAG_HP "+Oopenmp")
+    if(WIN32)
+      set(OMP_FLAG_Intel "-Qopenmp")
+    elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND
+           "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528")
+      set(OMP_FLAG_Intel "-openmp")
+    else()
+      set(OMP_FLAG_Intel "-qopenmp")
+    endif()
+    set(OMP_FLAG_MIPSpro "-mp")
+    set(OMP_FLAG_MSVC "-openmp")
+    set(OMP_FLAG_PathScale "-openmp")
+    set(OMP_FLAG_NAG "-openmp")
+    set(OMP_FLAG_Absoft "-openmp")
+    set(OMP_FLAG_PGI "-mp")
+    set(OMP_FLAG_SunPro "-xopenmp")
+    set(OMP_FLAG_XL "-qsmp=omp")
+    # Cray compiles with OpenMP automatically
+    set(OMP_FLAG_Cray " ")
+
+    # If we know the correct flags, use those
+    if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID})
+      set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}")
+    # Fall back to reasonable default tries otherwise
+    else()
+      set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ")
+    endif()
+    set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE)
   else()
-    set(OMP_FLAG_Intel "-qopenmp")
-  endif()
-  set(OMP_FLAG_MIPSpro "-mp")
-  set(OMP_FLAG_MSVC "/openmp")
-  set(OMP_FLAG_PathScale "-openmp")
-  set(OMP_FLAG_PGI "-mp")
-  set(OMP_FLAG_SunPro "-xopenmp")
-  set(OMP_FLAG_XL "-qsmp")
-  set(OMP_FLAG_Cray " ")
-
-  # Move the flag that matches the compiler to the head of the list,
-  # this is faster and doesn't clutter the output that much. If that
-  # flag doesn't work we will still try all.
-  if(OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID})
-    list(REMOVE_ITEM OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}")
-    list(INSERT OpenMP_FLAG_CANDIDATES 0 "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}")
+    set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE)
   endif()
-
-  set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE)
 endfunction()
 
 # sample openmp source code to test
-set(OpenMP_C_TEST_SOURCE
+set(OpenMP_C_CXX_TEST_SOURCE
 "
 #include <omp.h>
 int main() {
-#ifdef _OPENMP
-  return 0;
-#else
+#ifndef _OPENMP
   breaks_on_purpose
 #endif
 }
 ")
 
-# same in Fortran
+# in Fortran, an implementation may provide an omp_lib.h header
+# or omp_lib module, or both (OpenMP standard, section 3.1)
+# Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2)
+# Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code
+# while not actually enabling OpenMP, building code sequentially
 set(OpenMP_Fortran_TEST_SOURCE
   "
       program test
-      use omp_lib
-      integer :: n
+      @OpenMP_Fortran_INCLUDE_LINE@
+  !$  integer :: n
       n = omp_get_num_threads()
       end program test
   "
-  )
+)
+
+function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH)
+  set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP)
+  if("${LANG}" STREQUAL "C")
+    set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c")
+    file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+  elseif("${LANG}" STREQUAL "CXX")
+    set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp")
+    file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+  elseif("${LANG}" STREQUAL "Fortran")
+    set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90")
+    file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}")
+    configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY)
+  endif()
+  set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
+endfunction()
+
+include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
+
+function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
+  _OPENMP_FLAG_CANDIDATES("${LANG}")
+  _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC)
+
+  foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES)
+    set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}")
+    if(CMAKE_${LANG}_VERBOSE_FLAG)
+      string(APPEND OPENMP_FLAGS_TEST " ${CMAKE_${LANG}_VERBOSE_FLAG}")
+    endif()
+    string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
+    try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+      CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+      OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+    )
+
+    if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+      set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
+
+      if(CMAKE_${LANG}_VERBOSE_FLAG)
+        unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES)
+        unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS)
+        unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS)
+        unset(OpenMP_${LANG}_LOG_VAR)
+
+        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+        "Detecting ${LANG} OpenMP compiler ABI info compiled with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
+
+        cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}"
+          OpenMP_${LANG}_IMPLICIT_LIBRARIES
+          OpenMP_${LANG}_IMPLICIT_LINK_DIRS
+          OpenMP_${LANG}_IMPLICIT_FWK_DIRS
+          OpenMP_${LANG}_LOG_VAR
+          "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}"
+        )
+
+        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+        "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n")
+
+        unset(_OPENMP_LIB_NAMES)
+        foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES)
+          if(NOT "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES)
+            find_library(OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY
+              NAMES "${_OPENMP_IMPLICIT_LIB}"
+              HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
+            )
+            mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY)
+            list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB})
+          endif()
+        endforeach()
+        set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE)
+      else()
+        # The Intel compiler on windows has no verbose mode, so we need to treat it explicitly
+        if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Intel" AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
+          set("${OPENMP_LIB_NAMES_VAR}" "libiomp5md" PARENT_SCOPE)
+          find_library(OpenMP_libiomp5md_LIBRARY
+            NAMES "libiomp5md"
+            HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
+          )
+          mark_as_advanced(OpenMP_libiomp5md_LIBRARY)
+        else()
+          set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
+        endif()
+      endif()
+      break()
+    endif()
+    set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
+    set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
+  endforeach()
+endfunction()
 
 set(OpenMP_C_CXX_CHECK_VERSION_SOURCE
 "
@@ -132,17 +240,16 @@ const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M',
                             ('0' + ((_OPENMP/10)%10)),
                             ('0' + ((_OPENMP/1)%10)),
                             ']', '\\0' };
-int main(int argc, char *argv[])
+int main()
 {
-  printf(\"%s\\n\", ompver_str);
-  return 0;
+  puts(ompver_str);
 }
 ")
 
 set(OpenMP_Fortran_CHECK_VERSION_SOURCE
 "
       program omp_ver
-      use omp_lib
+      @OpenMP_Fortran_INCLUDE_LINE@
       integer, parameter :: zero = ichar('0')
       integer, parameter :: ompv = openmp_version
       character, dimension(24), parameter :: ompver_str =&
@@ -159,172 +266,186 @@ set(OpenMP_Fortran_CHECK_VERSION_SOURCE
 ")
 
 function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
-  set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP)
-  if("${LANG}" STREQUAL "C")
-    set(SRC_FILE ${WORK_DIR}/ompver.c)
-    file(WRITE ${SRC_FILE} "${OpenMP_C_CXX_CHECK_VERSION_SOURCE}")
-  elseif("${LANG}" STREQUAL "CXX")
-    set(SRC_FILE ${WORK_DIR}/ompver.cpp)
-    file(WRITE ${SRC_FILE} "${OpenMP_C_CXX_CHECK_VERSION_SOURCE}")
-  else() # ("${LANG}" STREQUAL "Fortran")
-    set(SRC_FILE ${WORK_DIR}/ompver.f90)
-    file(WRITE ${SRC_FILE} "${OpenMP_Fortran_CHECK_VERSION_SOURCE}")
-  endif()
+  _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC)
 
-  set(BIN_FILE ${WORK_DIR}/ompver_${LANG}.bin)
-  try_compile(OpenMP_TRY_COMPILE_RESULT ${CMAKE_BINARY_DIR} ${SRC_FILE}
+  set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin")
+  string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
+  try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}"
               CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}"
               COPY_FILE ${BIN_FILE})
 
-  if(${OpenMP_TRY_COMPILE_RESULT})
+  if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}})
     file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
     set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*")
     if("${specstr}" MATCHES "${regex_spec_date}")
       set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
     endif()
   endif()
-
-  unset(OpenMP_TRY_COMPILE_RESULT CACHE)
 endfunction()
 
+macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG)
+  set(OpenMP_SPEC_DATE_MAP
+    # Combined versions, 2.5 onwards
+    "201511=4.5"
+    "201307=4.0"
+    "201107=3.1"
+    "200805=3.0"
+    "200505=2.5"
+    # C/C++ version 2.0
+    "200203=2.0"
+    # Fortran version 2.0
+    "200011=2.0"
+    # Fortran version 1.1
+    "199911=1.1"
+    # C/C++ version 1.0 (there's no 1.1 for C/C++)
+    "199810=1.0"
+    # Fortran version 1.0
+    "199710=1.0"
+  )
 
-# check c compiler
-if(CMAKE_C_COMPILER_LOADED)
-  # if these are set then do not try to find them again,
-  # by avoiding any try_compiles for the flags
-  if(OpenMP_C_FLAGS)
-    unset(OpenMP_C_FLAG_CANDIDATES)
+  string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}")
+  if(NOT _version_match STREQUAL "")
+    set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1})
+    set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2})
+    set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}")
   else()
-    _OPENMP_FLAG_CANDIDATES("C")
-    include(${CMAKE_CURRENT_LIST_DIR}/CheckCSourceCompiles.cmake)
+    unset(OpenMP_${LANG}_VERSION_MAJOR)
+    unset(OpenMP_${LANG}_VERSION_MINOR)
+    unset(OpenMP_${LANG}_VERSION)
   endif()
-
-  foreach(FLAG IN LISTS OpenMP_C_FLAG_CANDIDATES)
-    set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
-    set(CMAKE_REQUIRED_FLAGS "${FLAG}")
-    unset(OpenMP_FLAG_DETECTED CACHE)
-    if(NOT CMAKE_REQUIRED_QUIET)
-      message(STATUS "Try OpenMP C flag = [${FLAG}]")
+  unset(_version_match)
+  unset(OpenMP_SPEC_DATE_MAP)
+endmacro()
+
+foreach(LANG IN ITEMS C CXX)
+  if(CMAKE_${LANG}_COMPILER_LOADED)
+    if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND"
+      OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
+      _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK)
     endif()
-    check_c_source_compiles("${OpenMP_C_TEST_SOURCE}" OpenMP_FLAG_DETECTED)
-    set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
-    if(OpenMP_FLAG_DETECTED)
-      set(OpenMP_C_FLAGS_INTERNAL "${FLAG}")
-      break()
-    endif()
-  endforeach()
-
-  set(OpenMP_C_FLAGS "${OpenMP_C_FLAGS_INTERNAL}"
-    CACHE STRING "C compiler flags for OpenMP parallization")
-
-  list(APPEND _OPENMP_REQUIRED_VARS OpenMP_C_FLAGS)
-  unset(OpenMP_C_FLAG_CANDIDATES)
 
-  if (NOT OpenMP_C_SPEC_DATE)
-    _OPENMP_GET_SPEC_DATE("C" OpenMP_C_SPEC_DATE_INTERNAL)
-    set(OpenMP_C_SPEC_DATE "${OpenMP_C_SPEC_DATE_INTERNAL}" CACHE
-      INTERNAL "C compiler's OpenMP specification date")
+    set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
+      CACHE STRING "${LANG} compiler flags for OpenMP parallelization")
+    set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
+      CACHE STRING "${LANG} compiler libraries for OpenMP parallelization")
+    mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES)
   endif()
-endif()
+endforeach()
 
-# check cxx compiler
-if(CMAKE_CXX_COMPILER_LOADED)
-  # if these are set then do not try to find them again,
-  # by avoiding any try_compiles for the flags
-  if(OpenMP_CXX_FLAGS)
-    unset(OpenMP_CXX_FLAG_CANDIDATES)
-  else()
-    _OPENMP_FLAG_CANDIDATES("CXX")
-    include(${CMAKE_CURRENT_LIST_DIR}/CheckCXXSourceCompiles.cmake)
+if(CMAKE_Fortran_COMPILER_LOADED)
+  if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
+    OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
+    OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+    set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n      implicit none")
+    _OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
+    if(OpenMP_Fortran_FLAGS_WORK)
+      set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "")
+    endif()
 
-    # use the same source for CXX as C for now
-    set(OpenMP_CXX_TEST_SOURCE ${OpenMP_C_TEST_SOURCE})
+    set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+      CACHE STRING "Fortran compiler flags for OpenMP parallelization")
+    set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
+      CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
+    mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES)
   endif()
 
-  foreach(FLAG IN LISTS OpenMP_CXX_FLAG_CANDIDATES)
-    set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
-    set(CMAKE_REQUIRED_FLAGS "${FLAG}")
-    unset(OpenMP_FLAG_DETECTED CACHE)
-    if(NOT CMAKE_REQUIRED_QUIET)
-      message(STATUS "Try OpenMP CXX flag = [${FLAG}]")
+  if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
+    OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
+    OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
+    set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n      include 'omp_lib.h'")
+    _OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
+    if(OpenMP_Fortran_FLAGS_WORK)
+      set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "")
     endif()
-    check_cxx_source_compiles("${OpenMP_CXX_TEST_SOURCE}" OpenMP_FLAG_DETECTED)
-    set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
-    if(OpenMP_FLAG_DETECTED)
-      set(OpenMP_CXX_FLAGS_INTERNAL "${FLAG}")
-      break()
-    endif()
-  endforeach()
 
-  set(OpenMP_CXX_FLAGS "${OpenMP_CXX_FLAGS_INTERNAL}"
-    CACHE STRING "C++ compiler flags for OpenMP parallization")
+    set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+      CACHE STRING "Fortran compiler flags for OpenMP parallelization")
 
-  list(APPEND _OPENMP_REQUIRED_VARS OpenMP_CXX_FLAGS)
-  unset(OpenMP_CXX_FLAG_CANDIDATES)
-
-  if (NOT OpenMP_CXX_SPEC_DATE)
-    _OPENMP_GET_SPEC_DATE("CXX" OpenMP_CXX_SPEC_DATE_INTERNAL)
-    set(OpenMP_CXX_SPEC_DATE "${OpenMP_CXX_SPEC_DATE_INTERNAL}" CACHE
-      INTERNAL "C++ compiler's OpenMP specification date")
+    set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}"
+      CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
   endif()
-endif()
 
-# check Fortran compiler
-if(CMAKE_Fortran_COMPILER_LOADED)
-  # if these are set then do not try to find them again,
-  # by avoiding any try_compiles for the flags
-  if(OpenMP_Fortran_FLAGS)
-    unset(OpenMP_Fortran_FLAG_CANDIDATES)
+  if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+    set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n      implicit none")
   else()
-    _OPENMP_FLAG_CANDIDATES("Fortran")
-    include(${CMAKE_CURRENT_LIST_DIR}/CheckFortranSourceCompiles.cmake)
+    set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n      include 'omp_lib.h'")
   endif()
+endif()
 
-  foreach(FLAG IN LISTS OpenMP_Fortran_FLAG_CANDIDATES)
-    set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
-    set(CMAKE_REQUIRED_FLAGS "${FLAG}")
-    unset(OpenMP_FLAG_DETECTED CACHE)
-    if(NOT CMAKE_REQUIRED_QUIET)
-      message(STATUS "Try OpenMP Fortran flag = [${FLAG}]")
-    endif()
-    check_fortran_source_compiles("${OpenMP_Fortran_TEST_SOURCE}" OpenMP_FLAG_DETECTED)
-    set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
-    if(OpenMP_FLAG_DETECTED)
-      set(OpenMP_Fortran_FLAGS_INTERNAL "${FLAG}")
-      break()
-    endif()
-  endforeach()
+set(OPENMP_FOUND TRUE)
 
-  set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_INTERNAL}"
-    CACHE STRING "Fortran compiler flags for OpenMP parallization")
+foreach(LANG IN ITEMS C CXX Fortran)
+  if(CMAKE_${LANG}_COMPILER_LOADED)
+    if (NOT OpenMP_${LANG}_SPEC_DATE)
+      _OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL)
+      set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE
+        INTERNAL "${LANG} compiler's OpenMP specification date")
+      _OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}")
+    endif()
 
-  list(APPEND _OPENMP_REQUIRED_VARS OpenMP_Fortran_FLAGS)
-  unset(OpenMP_Fortran_FLAG_CANDIDATES)
+    include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
 
-  if (NOT OpenMP_Fortran_SPEC_DATE)
-    _OPENMP_GET_SPEC_DATE("Fortran" OpenMP_Fortran_SPEC_DATE_INTERNAL)
-    set(OpenMP_Fortran_SPEC_DATE "${OpenMP_Fortran_SPEC_DATE_INTERNAL}" CACHE
-      INTERNAL "Fortran compiler's OpenMP specification date")
-  endif()
-endif()
+    set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY})
+    set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED})
+    set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION})
+    set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT})
 
-set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE})
-
-if(_OPENMP_REQUIRED_VARS)
-  include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+    set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS)
+    if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
+      set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES)
+    else()
+      foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
+        list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY)
+      endforeach()
+    endif()
 
-  find_package_handle_standard_args(OpenMP
-                                    REQUIRED_VARS ${_OPENMP_REQUIRED_VARS})
+    find_package_handle_standard_args(OpenMP_${LANG}
+      REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS}
+      VERSION_VAR OpenMP_${LANG}_VERSION
+    )
+
+    if(OpenMP_${LANG}_FOUND)
+      set(OpenMP_${LANG}_LIBRARIES "")
+      foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
+        list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}")
+      endforeach()
+
+      if(NOT TARGET OpenMP::OpenMP_${LANG})
+        add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED)
+      endif()
+      if(OpenMP_${LANG}_FLAGS)
+        separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}")
+        set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
+          INTERFACE_COMPILE_OPTIONS "${_OpenMP_${LANG}_OPTIONS}")
+        unset(_OpenMP_${LANG}_OPTIONS)
+      endif()
+      if(OpenMP_${LANG}_LIBRARIES)
+        set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
+          INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}")
+      endif()
+    else()
+      set(OPENMP_FOUND FALSE)
+    endif()
+  endif()
+endforeach()
 
-  mark_as_advanced(${_OPENMP_REQUIRED_VARS})
+if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND)
+  if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+    set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "")
+  endif()
+  if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
+    set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "")
+  endif()
+endif()
 
-  unset(_OPENMP_REQUIRED_VARS)
-else()
-  message(SEND_ERROR "FindOpenMP requires C or CXX language to be enabled")
+if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED ))
+  message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled")
 endif()
 
-unset(OpenMP_C_TEST_SOURCE)
-unset(OpenMP_CXX_TEST_SOURCE)
+unset(OpenMP_C_CXX_TEST_SOURCE)
 unset(OpenMP_Fortran_TEST_SOURCE)
 unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE)
 unset(OpenMP_Fortran_CHECK_VERSION_SOURCE)
+unset(OpenMP_Fortran_INCLUDE_LINE)
+
+cmake_policy(POP)
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index 6259ce1..f32eb50 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -145,6 +145,7 @@ if(WIN32 AND NOT CYGWIN)
     find_library(LIB_EAY_DEBUG
       NAMES
         libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
+        libcrypto${_OPENSSL_MSVC_RT_MODE}d
         libcryptod
         libeay32${_OPENSSL_MSVC_RT_MODE}d
         libeay32d
@@ -157,9 +158,11 @@ if(WIN32 AND NOT CYGWIN)
     find_library(LIB_EAY_RELEASE
       NAMES
         libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
+        libcrypto${_OPENSSL_MSVC_RT_MODE}
         libcrypto
         libeay32${_OPENSSL_MSVC_RT_MODE}
         libeay32
+        crypto
       NAMES_PER_DIR
       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
       PATH_SUFFIXES
@@ -169,6 +172,7 @@ if(WIN32 AND NOT CYGWIN)
     find_library(SSL_EAY_DEBUG
       NAMES
         libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
+        libssl${_OPENSSL_MSVC_RT_MODE}d
         libssld
         ssleay32${_OPENSSL_MSVC_RT_MODE}d
         ssleay32d
@@ -181,6 +185,7 @@ if(WIN32 AND NOT CYGWIN)
     find_library(SSL_EAY_RELEASE
       NAMES
         libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
+        libssl${_OPENSSL_MSVC_RT_MODE}
         libssl
         ssleay32${_OPENSSL_MSVC_RT_MODE}
         ssleay32
@@ -371,7 +376,7 @@ set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} )
 if (OPENSSL_VERSION)
   find_package_handle_standard_args(OpenSSL
     REQUIRED_VARS
-      OPENSSL_SSL_LIBRARY
+      #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request?
       OPENSSL_CRYPTO_LIBRARY
       OPENSSL_INCLUDE_DIR
     VERSION_VAR
@@ -381,7 +386,7 @@ if (OPENSSL_VERSION)
   )
 else ()
   find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
-    OPENSSL_SSL_LIBRARY
+    #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request?
     OPENSSL_CRYPTO_LIBRARY
     OPENSSL_INCLUDE_DIR
   )
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index b77925d..b851a90 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -147,7 +147,7 @@ endmacro()
 macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
   # <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
   if(${_NAME}_CONFIG)
-    _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
+    _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
   else()
     # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
     # List them all in the error message:
@@ -374,7 +374,7 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
       if(NOT VERSION_OK)
         _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
       else()
-        _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
+        _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}")
       endif()
     endif()
 
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index 1958f4b..a5357fa 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -65,7 +65,7 @@ macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp)
     set(_pkgconfig_${_varname} "")
     _pkgconfig_unset(${_prefix}_${_varname})
   else()
-    string(REGEX REPLACE "[\r\n]"                  " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
+    string(REGEX REPLACE "[\r\n]"       " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
 
     if (NOT ${_regexp} STREQUAL "")
       string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
@@ -86,6 +86,9 @@ endmacro()
 
     pkg_get_variable(<RESULT> <MODULE> <VARIABLE>)
 
+  If multiple values are returned variable will contain a
+  :ref:`;-list <CMake Language Lists>`.
+
   For example:
 
   .. code-block:: cmake
@@ -190,10 +193,12 @@ function(_pkg_create_imp_target _prefix _no_cmake_path _no_cmake_environment_pat
     string(APPEND _find_opts " NO_CMAKE_ENVIRONMENT_PATH")
   endif()
 
+  unset(_search_paths)
   foreach (flag IN LISTS ${_prefix}_LDFLAGS)
     if (flag MATCHES "^-L(.*)")
       # only look into the given paths from now on
-      set(_find_opts HINTS ${CMAKE_MATCH_1} NO_DEFAULT_PATH)
+      list(APPEND _search_paths ${CMAKE_MATCH_1})
+      set(_find_opts HINTS ${_search_paths} NO_DEFAULT_PATH)
       continue()
     endif()
     if (flag MATCHES "^-l(.*)")
@@ -312,6 +317,10 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma
           if(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
             list(APPEND _lib_dirs "lib64/pkgconfig")
           endif()
+          get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS)
+          if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32")
+            list(APPEND _lib_dirs "libx32/pkgconfig")
+          endif()
         endif()
       endif()
       list(APPEND _lib_dirs "lib/pkgconfig")
@@ -360,38 +369,25 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma
         set(_pkg_check_modules_pkg_ver)
       endif()
 
-      # handle the operands
-      if (_pkg_check_modules_pkg_op STREQUAL ">=")
-        list(APPEND _pkg_check_modules_exist_query --atleast-version)
-      endif()
-
-      if (_pkg_check_modules_pkg_op STREQUAL "=")
-        list(APPEND _pkg_check_modules_exist_query --exact-version)
-      endif()
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION)
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX)
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR)
+      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR)
 
-      if (_pkg_check_modules_pkg_op STREQUAL "<=")
-        list(APPEND _pkg_check_modules_exist_query --max-version)
-      endif()
+      list(APPEND _pkg_check_modules_packages    "${_pkg_check_modules_pkg_name}")
 
       # create the final query which is of the format:
-      # * --atleast-version <version> <pkg-name>
-      # * --exact-version <version> <pkg-name>
-      # * --max-version <version> <pkg-name>
+      # * <pkg-name> >= <version>
+      # * <pkg-name> = <version>
+      # * <pkg-name> <= <version>
       # * --exists <pkg-name>
+      list(APPEND _pkg_check_modules_exist_query --print-errors --short-errors)
       if (_pkg_check_modules_pkg_op)
-        list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}")
+        list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name} ${_pkg_check_modules_pkg_op} ${_pkg_check_modules_pkg_ver}")
       else()
         list(APPEND _pkg_check_modules_exist_query --exists)
+        list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}")
       endif()
-      list(APPEND _pkg_check_modules_exist_query --print-errors --short-errors)
-
-      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION)
-      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX)
-      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR)
-      _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR)
-
-      list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}")
-      list(APPEND _pkg_check_modules_packages    "${_pkg_check_modules_pkg_name}")
 
       # execute the query
       execute_process(
@@ -531,6 +527,9 @@ endmacro()
     <XPREFIX> = <PREFIX>        for common case
     <XPREFIX> = <PREFIX>_STATIC for static linking
 
+ Every variable containing multiple values will be a
+ :ref:`;-list <CMake Language Lists>`.
+
  There are some special variables whose prefix depends on the count of
  given modules.  When there is only one module, <PREFIX> stays
  unchanged.  When there are multiple modules, the prefix will be
diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake
index 3ffd5a7..33262f3 100644
--- a/Modules/FindProtobuf.cmake
+++ b/Modules/FindProtobuf.cmake
@@ -20,6 +20,9 @@
 #   imported .proto files.
 # ``Protobuf_DEBUG``
 #   Show debug messages.
+# ``Protobuf_USE_STATIC_LIBS``
+#   Set to ON to force the use of the static libraries.
+#   Default is OFF.
 #
 # Defines the following variables:
 #
@@ -37,6 +40,15 @@
 # ``Protobuf_LITE_LIBRARIES``
 #   The protobuf-lite libraries
 #
+# The following :prop_tgt:`IMPORTED` targets are also defined:
+#
+# ``protobuf::libprotobuf``
+#   The protobuf library.
+# ``protobuf::libprotobuf-lite``
+#   The protobuf lite library.
+# ``protobuf::libprotoc``
+#   The protoc library.
+#
 # The following cache variables are also available to set or use:
 #
 # ``Protobuf_LIBRARY``
@@ -64,6 +76,7 @@
 #   include_directories(${Protobuf_INCLUDE_DIRS})
 #   include_directories(${CMAKE_CURRENT_BINARY_DIR})
 #   protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS foo.proto)
+#   protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS EXPORT_MACRO DLL_EXPORT foo.proto)
 #   protobuf_generate_python(PROTO_PY foo.proto)
 #   add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
 #   target_link_libraries(bar ${Protobuf_LIBRARIES})
@@ -77,12 +90,15 @@
 #
 #   Add custom commands to process ``.proto`` files to C++::
 #
-#     protobuf_generate_cpp (<SRCS> <HDRS> [<ARGN>...])
+#     protobuf_generate_cpp (<SRCS> <HDRS> [EXPORT_MACRO <MACRO>] [<ARGN>...])
 #
 #   ``SRCS``
 #     Variable to define with autogenerated source files
 #   ``HDRS``
 #     Variable to define with autogenerated header files
+#   ``EXPORT_MACRO``
+#     is a macro which should expand to ``__declspec(dllexport)`` or
+#     ``__declspec(dllimport)`` depending on what is being compiled.
 #   ``ARGN``
 #     ``.proto`` files
 #
@@ -98,14 +114,21 @@
 #     ``.proto`` filess
 
 function(PROTOBUF_GENERATE_CPP SRCS HDRS)
-  if(NOT ARGN)
+  cmake_parse_arguments(protobuf "" "EXPORT_MACRO" "" ${ARGN})
+
+  set(PROTO_FILES "${protobuf_UNPARSED_ARGUMENTS}")
+  if(NOT PROTO_FILES)
     message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
     return()
   endif()
 
+  if(protobuf_EXPORT_MACRO)
+    set(DLL_EXPORT_DECL "dllexport_decl=${protobuf_EXPORT_MACRO}:")
+  endif()
+
   if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
     # Create an include path for each file specified
-    foreach(FIL ${ARGN})
+    foreach(FIL ${PROTO_FILES})
       get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
       get_filename_component(ABS_PATH ${ABS_FIL} PATH)
       list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
@@ -133,7 +156,7 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS)
 
   set(${SRCS})
   set(${HDRS})
-  foreach(FIL ${ARGN})
+  foreach(FIL ${PROTO_FILES})
     get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
     get_filename_component(FIL_WE ${FIL} NAME_WE)
     if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)
@@ -150,7 +173,7 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS)
       OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
              "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
       COMMAND  ${Protobuf_PROTOC_EXECUTABLE}
-      ARGS --cpp_out  ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
+      ARGS "--cpp_out=${DLL_EXPORT_DECL}${CMAKE_CURRENT_BINARY_DIR}" ${_protobuf_include_path} ${ABS_FIL}
       DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE}
       COMMENT "Running C++ protocol buffer compiler on ${FIL}"
       VERBATIM )
@@ -218,6 +241,14 @@ function(PROTOBUF_GENERATE_PYTHON SRCS)
   set(${SRCS} ${${SRCS}} PARENT_SCOPE)
 endfunction()
 
+
+if(Protobuf_DEBUG)
+  # Output some of their choices
+  message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
+                 "Protobuf_USE_STATIC_LIBS = ${Protobuf_USE_STATIC_LIBS}")
+endif()
+
+
 # Backwards compatibility
 # Define camel case versions of input variables
 foreach(UPPER
@@ -245,6 +276,17 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
   set(_PROTOBUF_ARCH_DIR x64/)
 endif()
 
+
+# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
+if( Protobuf_USE_STATIC_LIBS )
+  set( _protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+  if(WIN32)
+    set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+  else()
+    set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
+  endif()
+endif()
+
 include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
 
 # Internal function: search for normal library as well as a debug one
@@ -387,6 +429,78 @@ if(Protobuf_INCLUDE_DIR)
       message(WARNING "Protobuf compiler version ${_PROTOBUF_PROTOC_EXECUTABLE_VERSION}"
           " doesn't match library version ${Protobuf_VERSION}")
   endif()
+
+  if(Protobuf_LIBRARY)
+      if(NOT TARGET protobuf::libprotobuf)
+          add_library(protobuf::libprotobuf UNKNOWN IMPORTED)
+          set_target_properties(protobuf::libprotobuf PROPERTIES
+            INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
+          if(EXISTS "${Protobuf_LIBRARY}")
+            set_target_properties(protobuf::libprotobuf PROPERTIES
+              IMPORTED_LOCATION "${Protobuf_LIBRARY}")
+          endif()
+          if(EXISTS "${Protobuf_LIBRARY_RELEASE}")
+            set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
+              IMPORTED_CONFIGURATIONS RELEASE)
+            set_target_properties(protobuf::libprotobuf PROPERTIES
+              IMPORTED_LOCATION_RELEASE "${Protobuf_LIBRARY_RELEASE}")
+          endif()
+          if(EXISTS "${Protobuf_LIBRARY_DEBUG}")
+            set_property(TARGET protobuf::libprotobuf APPEND PROPERTY
+              IMPORTED_CONFIGURATIONS DEBUG)
+            set_target_properties(protobuf::libprotobuf PROPERTIES
+              IMPORTED_LOCATION_DEBUG "${Protobuf_LIBRARY_DEBUG}")
+          endif()
+      endif()
+  endif()
+
+  if(Protobuf_LITE_LIBRARY)
+      if(NOT TARGET protobuf::libprotobuf-lite)
+          add_library(protobuf::libprotobuf-lite UNKNOWN IMPORTED)
+          set_target_properties(protobuf::libprotobuf-lite PROPERTIES
+            INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
+          if(EXISTS "${Protobuf_LITE_LIBRARY}")
+            set_target_properties(protobuf::libprotobuf-lite PROPERTIES
+              IMPORTED_LOCATION "${Protobuf_LITE_LIBRARY}")
+          endif()
+          if(EXISTS "${Protobuf_LITE_LIBRARY_RELEASE}")
+            set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
+              IMPORTED_CONFIGURATIONS RELEASE)
+            set_target_properties(protobuf::libprotobuf-lite PROPERTIES
+              IMPORTED_LOCATION_RELEASE "${Protobuf_LITE_LIBRARY_RELEASE}")
+          endif()
+          if(EXISTS "${Protobuf_LITE_LIBRARY_DEBUG}")
+            set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY
+              IMPORTED_CONFIGURATIONS DEBUG)
+            set_target_properties(protobuf::libprotobuf-lite PROPERTIES
+              IMPORTED_LOCATION_DEBUG "${Protobuf_LITE_LIBRARY_DEBUG}")
+          endif()
+      endif()
+  endif()
+
+  if(Protobuf_PROTOC_LIBRARY)
+      if(NOT TARGET protobuf::libprotoc)
+          add_library(protobuf::libprotoc UNKNOWN IMPORTED)
+          set_target_properties(protobuf::libprotoc PROPERTIES
+            INTERFACE_INCLUDE_DIRECTORIES "${Protobuf_INCLUDE_DIR}")
+          if(EXISTS "${Protobuf_PROTOC_LIBRARY}")
+            set_target_properties(protobuf::libprotoc PROPERTIES
+              IMPORTED_LOCATION "${Protobuf_PROTOC_LIBRARY}")
+          endif()
+          if(EXISTS "${Protobuf_PROTOC_LIBRARY_RELEASE}")
+            set_property(TARGET protobuf::libprotoc APPEND PROPERTY
+              IMPORTED_CONFIGURATIONS RELEASE)
+            set_target_properties(protobuf::libprotoc PROPERTIES
+              IMPORTED_LOCATION_RELEASE "${Protobuf_PROTOC_LIBRARY_RELEASE}")
+          endif()
+          if(EXISTS "${Protobuf_PROTOC_LIBRARY_DEBUG}")
+            set_property(TARGET protobuf::libprotoc APPEND PROPERTY
+              IMPORTED_CONFIGURATIONS DEBUG)
+            set_target_properties(protobuf::libprotoc PROPERTIES
+              IMPORTED_LOCATION_DEBUG "${Protobuf_PROTOC_LIBRARY_DEBUG}")
+          endif()
+      endif()
+  endif()
 endif()
 
 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
@@ -399,6 +513,11 @@ if(Protobuf_FOUND)
     set(Protobuf_INCLUDE_DIRS ${Protobuf_INCLUDE_DIR})
 endif()
 
+# Restore the original find library ordering
+if( Protobuf_USE_STATIC_LIBS )
+  set(CMAKE_FIND_LIBRARY_SUFFIXES ${_protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
+endif()
+
 # Backwards compatibility
 # Define upper case versions of output variables
 foreach(Camel
diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake
index f255246..64b98a8 100644
--- a/Modules/FindPythonInterp.cmake
+++ b/Modules/FindPythonInterp.cmake
@@ -91,12 +91,15 @@ unset(_PYTHON3_VERSIONS)
 if(NOT PYTHON_EXECUTABLE)
     foreach(_CURRENT_VERSION IN LISTS _Python_VERSIONS)
       set(_Python_NAMES python${_CURRENT_VERSION})
-      if(WIN32)
+      if(CMAKE_HOST_WIN32)
         list(APPEND _Python_NAMES python)
       endif()
       find_program(PYTHON_EXECUTABLE
         NAMES ${_Python_NAMES}
-        PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]
+        PATHS
+            [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]
+            [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-32\\InstallPath]
+            [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-64\\InstallPath]
         )
     endforeach()
 endif()
diff --git a/Modules/FindXCTest.cmake b/Modules/FindXCTest.cmake
index a97bb1b..ffdf677 100644
--- a/Modules/FindXCTest.cmake
+++ b/Modules/FindXCTest.cmake
@@ -123,6 +123,10 @@ function(xctest_add_bundle target testee)
     # testee is a Framework
     target_link_libraries(${target} PRIVATE ${testee})
 
+  elseif(_testee_type STREQUAL "STATIC_LIBRARY")
+    # testee is a static library
+    target_link_libraries(${target} PRIVATE ${testee})
+
   elseif(_testee_type STREQUAL "EXECUTABLE" AND _testee_macosx_bundle)
     # testee is an App Bundle
     add_dependencies(${target} ${testee})
diff --git a/Modules/FindXMLRPC.cmake b/Modules/FindXMLRPC.cmake
index dd9dffc..f0b2583 100644
--- a/Modules/FindXMLRPC.cmake
+++ b/Modules/FindXMLRPC.cmake
@@ -36,13 +36,13 @@ find_program(XMLRPC_C_CONFIG NAMES xmlrpc-c-config)
 
 # Check whether we found anything.
 if(XMLRPC_C_CONFIG)
-  set(XMLRPC_FOUND 1)
+  set(XMLRPC_C_FOUND 1)
 else()
-  set(XMLRPC_FOUND 0)
+  set(XMLRPC_C_FOUND 0)
 endif()
 
 # Lookup the include directories needed for the components requested.
-if(XMLRPC_FOUND)
+if(XMLRPC_C_FOUND)
   # Use the newer EXECUTE_PROCESS command if it is available.
   if(COMMAND EXECUTE_PROCESS)
     execute_process(
@@ -74,12 +74,12 @@ if(XMLRPC_FOUND)
     endforeach()
   else()
     message("Error running ${XMLRPC_C_CONFIG}: [${XMLRPC_C_CONFIG_RESULT}]")
-    set(XMLRPC_FOUND 0)
+    set(XMLRPC_C_FOUND 0)
   endif()
 endif()
 
 # Lookup the libraries needed for the components requested.
-if(XMLRPC_FOUND)
+if(XMLRPC_C_FOUND)
   # Use the newer EXECUTE_PROCESS command if it is available.
   if(COMMAND EXECUTE_PROCESS)
     execute_process(
@@ -123,7 +123,7 @@ if(XMLRPC_FOUND)
 
       # If any library is not found then the whole package is not found.
       if(NOT XMLRPC_${name}_LIBRARY)
-        set(XMLRPC_FOUND 0)
+        set(XMLRPC_C_FOUND 0)
       endif()
 
       # Build an ordered list of all the libraries needed.
@@ -131,19 +131,13 @@ if(XMLRPC_FOUND)
     endforeach()
   else()
     message("Error running ${XMLRPC_C_CONFIG}: [${XMLRPC_C_CONFIG_RESULT}]")
-    set(XMLRPC_FOUND 0)
+    set(XMLRPC_C_FOUND 0)
   endif()
 endif()
 
 # Report the results.
-if(NOT XMLRPC_FOUND)
-  set(XMLRPC_DIR_MESSAGE
-    "XMLRPC was not found. Make sure the entries XMLRPC_* are set.")
-  if(NOT XMLRPC_FIND_QUIETLY)
-    message(STATUS "${XMLRPC_DIR_MESSAGE}")
-  else()
-    if(XMLRPC_FIND_REQUIRED)
-      message(FATAL_ERROR "${XMLRPC_DIR_MESSAGE}")
-    endif()
-  endif()
-endif()
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(
+    XMLRPC
+    REQUIRED_VARS XMLRPC_C_FOUND XMLRPC_LIBRARIES XMLRPC_INCLUDE_DIRS
+    FAIL_MESSAGE "XMLRPC was not found. Make sure the entries XMLRPC_* are set.")
diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index bc906e5..af4daf0 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -893,6 +893,28 @@ else()
   endif()
 endif()
 
+# Check that all libraries are present, as wx-config does not check it
+set(_wx_lib_missing "")
+foreach(_wx_lib_ ${wxWidgets_LIBRARIES})
+  if("${_wx_lib_}" MATCHES "^-l(.*)")
+    set(_wx_lib_name "${CMAKE_MATCH_1}")
+    unset(_wx_lib_found CACHE)
+    find_library(_wx_lib_found NAMES ${_wx_lib_name} HINTS ${wxWidgets_LIBRARY_DIRS})
+    if(_wx_lib_found STREQUAL _wx_lib_found-NOTFOUND)
+      list(APPEND _wx_lib_missing ${_wx_lib_name})
+    endif()
+    unset(_wx_lib_found CACHE)
+  endif()
+endforeach()
+
+if (_wx_lib_missing)
+  string(REPLACE ";" " " _wx_lib_missing "${_wx_lib_missing}")
+  DBG_MSG_V("wxWidgets not found due to following missing libraries: ${_wx_lib_missing}")
+  set(wxWidgets_FOUND FALSE)
+  unset(wxWidgets_LIBRARIES)
+endif()
+unset(_wx_lib_missing)
+
 # Check if a specfic version was requested by find_package().
 if(wxWidgets_FOUND)
   find_file(_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH)
diff --git a/Modules/FortranCInterface/CMakeLists.txt b/Modules/FortranCInterface/CMakeLists.txt
index 3a66f68..e3b81d7 100644
--- a/Modules/FortranCInterface/CMakeLists.txt
+++ b/Modules/FortranCInterface/CMakeLists.txt
@@ -15,11 +15,11 @@ int main() { return 0; }
 # List manglings of global symbol names to try.
 set(global_symbols
   my_sub    # VisualAge
-  my_sub_   # GNU, Intel, HP, SunPro, MIPSpro
+  my_sub_   # GNU, Intel, HP, SunPro, MIPSpro, PGI
   my_sub__  # GNU g77
   MY_SUB    # Intel on Windows
   mysub     # VisualAge
-  mysub_    # GNU, Intel, HP, SunPro, MIPSpro
+  mysub_    # GNU, Intel, HP, SunPro, MIPSpro, PGI
   MYSUB     # Intel on Windows
   ${FortranCInterface_GLOBAL_SYMBOLS}
   )
@@ -71,7 +71,7 @@ if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "^(PathScale|Cray)$")
   #    use '.in.' so we cannot provide them anyway.
   #  - Cray Fortran >= 7.3.2 uses module init symbols but module symbols
   #    use 'mysub$mymodule_' so we cannot provide them anyway.
-  list(APPEND symbol_sources mymodule_.c my_module_.c)
+  list(APPEND symbol_sources mymodule_.c my_module_.c MY_MODULE.c MYMODULE.c)
 endif()
 foreach(symbol IN LISTS global_symbols module_symbols)
   # Skip symbols with '$' if C cannot handle them.
@@ -93,11 +93,12 @@ add_library(myfort STATIC mysub.f my_sub.f ${myfort_modules})
 
 # Provide symbols through C but fall back to Fortran.
 add_library(symbols STATIC ${symbol_sources})
-target_link_libraries(symbols myfort)
+target_link_libraries(symbols PUBLIC myfort)
+
 # In case the Fortran compiler produces PIC by default make sure
 # the C compiler produces PIC even if it is not its default.
 set_property(TARGET symbols PROPERTY POSITION_INDEPENDENT_CODE 1)
 
 # Require symbols through Fortran.
 add_executable(FortranCInterface main.F call_sub.f ${call_mod})
-target_link_libraries(FortranCInterface symbols)
+target_link_libraries(FortranCInterface PUBLIC symbols)
diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake
index 7612890..7789785 100644
--- a/Modules/FortranCInterface/Detect.cmake
+++ b/Modules/FortranCInterface/Detect.cmake
@@ -27,6 +27,7 @@ unset(FortranCInterface_VERIFIED_CXX CACHE)
 set(_result)
 
 # Build a sample project which reports symbols.
+set(CMAKE_TRY_COMPILE_CONFIGURATION Release)
 try_compile(FortranCInterface_COMPILED
   ${FortranCInterface_BINARY_DIR}
   ${FortranCInterface_SOURCE_DIR}
@@ -35,6 +36,8 @@ try_compile(FortranCInterface_COMPILED
   CMAKE_FLAGS
     "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}"
     "-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}"
+    "-DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE}"
+    "-DCMAKE_Fortran_FLAGS_RELEASE:STRING=${CMAKE_Fortran_FLAGS_RELEASE}"
   OUTPUT_VARIABLE FortranCInterface_OUTPUT)
 set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED})
 unset(FortranCInterface_COMPILED CACHE)
@@ -43,7 +46,7 @@ unset(FortranCInterface_COMPILED CACHE)
 if(FortranCInterface_COMPILED)
   find_program(FortranCInterface_EXE
     NAMES FortranCInterface${CMAKE_EXECUTABLE_SUFFIX}
-    PATHS ${FortranCInterface_BINARY_DIR} ${FortranCInterface_BINARY_DIR}/Debug
+    PATHS ${FortranCInterface_BINARY_DIR} ${FortranCInterface_BINARY_DIR}/Release
     NO_DEFAULT_PATH
     )
   set(FortranCInterface_EXE ${FortranCInterface_EXE})
diff --git a/Modules/FortranCInterface/MYMODULE.c b/Modules/FortranCInterface/MYMODULE.c
new file mode 100644
index 0000000..19b51fb
--- /dev/null
+++ b/Modules/FortranCInterface/MYMODULE.c
@@ -0,0 +1,3 @@
+void MYMODULE(void)
+{
+}
diff --git a/Modules/FortranCInterface/MY_MODULE.c b/Modules/FortranCInterface/MY_MODULE.c
new file mode 100644
index 0000000..87b3071
--- /dev/null
+++ b/Modules/FortranCInterface/MY_MODULE.c
@@ -0,0 +1,3 @@
+void MY_MODULE(void)
+{
+}
diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake
index 9599f27..64bd09e 100644
--- a/Modules/GNUInstallDirs.cmake
+++ b/Modules/GNUInstallDirs.cmake
@@ -45,6 +45,8 @@
 #   modifiable architecture-independent data (``com``)
 # ``LOCALSTATEDIR``
 #   modifiable single-machine data (``var``)
+# ``RUNSTATEDIR``
+#   run-time variable data (``LOCALSTATEDIR/run``)
 # ``LIBDIR``
 #   object code libraries (``lib`` or ``lib64``
 #   or ``lib/<multiarch-tuple>`` on Debian)
@@ -75,10 +77,10 @@
 #
 # ``/``
 #
-#   For ``<dir>`` other than the ``SYSCONFDIR`` and ``LOCALSTATEDIR``,
-#   the value of ``CMAKE_INSTALL_<dir>`` is prefixed with ``usr/`` if
-#   it is not user-specified as an absolute path.  For example, the
-#   ``INCLUDEDIR`` value ``include`` becomes ``usr/include``.
+#   For ``<dir>`` other than the ``SYSCONFDIR``, ``LOCALSTATEDIR`` and
+#   ``RUNSTATEDIR``, the value of ``CMAKE_INSTALL_<dir>`` is prefixed
+#   with ``usr/`` if it is not user-specified as an absolute path.
+#   For example, the ``INCLUDEDIR`` value ``include`` becomes ``usr/include``.
 #   This is required by the `GNU Coding Standards`_, which state:
 #
 #     When building the complete GNU system, the prefix will be empty
@@ -86,20 +88,21 @@
 #
 # ``/usr``
 #
-#   For ``<dir>`` equal to ``SYSCONFDIR`` or ``LOCALSTATEDIR``, the
-#   ``CMAKE_INSTALL_FULL_<dir>`` is computed by prepending just ``/``
-#   to the value of ``CMAKE_INSTALL_<dir>`` if it is not user-specified
-#   as an absolute path.  For example, the ``SYSCONFDIR`` value ``etc``
-#   becomes ``/etc``.  This is required by the `GNU Coding Standards`_.
+#   For ``<dir>`` equal to ``SYSCONFDIR``, ``LOCALSTATEDIR`` or
+#   ``RUNSTATEDIR``, the ``CMAKE_INSTALL_FULL_<dir>`` is computed by
+#   prepending just ``/`` to the value of ``CMAKE_INSTALL_<dir>``
+#   if it is not user-specified as an absolute path.
+#   For example, the ``SYSCONFDIR`` value ``etc`` becomes ``/etc``.
+#   This is required by the `GNU Coding Standards`_.
 #
 # ``/opt/...``
 #
-#   For ``<dir>`` equal to ``SYSCONFDIR`` or ``LOCALSTATEDIR``, the
-#   ``CMAKE_INSTALL_FULL_<dir>`` is computed by *appending* the prefix
-#   to the value of ``CMAKE_INSTALL_<dir>`` if it is not user-specified
-#   as an absolute path.  For example, the ``SYSCONFDIR`` value ``etc``
-#   becomes ``/etc/opt/...``.  This is defined by the
-#   `Filesystem Hierarchy Standard`_.
+#   For ``<dir>`` equal to ``SYSCONFDIR``, ``LOCALSTATEDIR`` or
+#   ``RUNSTATEDIR``, the ``CMAKE_INSTALL_FULL_<dir>`` is computed by
+#   *appending* the prefix to the value of ``CMAKE_INSTALL_<dir>``
+#   if it is not user-specified as an absolute path.
+#   For example, the ``SYSCONFDIR`` value ``etc`` becomes ``/etc/opt/...``.
+#   This is defined by the `Filesystem Hierarchy Standard`_.
 #
 # .. _`Filesystem Hierarchy Standard`: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
 #
@@ -287,6 +290,9 @@ _GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DAT
 _GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}"
   "Documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
 
+_GNUInstallDirs_cache_path_fallback(CMAKE_INSTALL_RUNSTATEDIR "${CMAKE_INSTALL_LOCALSTATEDIR}/run"
+  "Run-time variable data (LOCALSTATEDIR/run)")
+
 #-----------------------------------------------------------------------------
 
 mark_as_advanced(
@@ -296,6 +302,7 @@ mark_as_advanced(
   CMAKE_INSTALL_SYSCONFDIR
   CMAKE_INSTALL_SHAREDSTATEDIR
   CMAKE_INSTALL_LOCALSTATEDIR
+  CMAKE_INSTALL_RUNSTATEDIR
   CMAKE_INSTALL_LIBDIR
   CMAKE_INSTALL_INCLUDEDIR
   CMAKE_INSTALL_OLDINCLUDEDIR
@@ -314,7 +321,7 @@ macro(GNUInstallDirs_get_absolute_install_dir absvar var)
     # - CMAKE_INSTALL_PREFIX == /usr
     # - CMAKE_INSTALL_PREFIX == /opt/...
     if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/")
-      if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR")
+      if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR" OR "${dir}" STREQUAL "RUNSTATEDIR")
         set(${absvar} "/${${var}}")
       else()
         if (NOT "${${var}}" MATCHES "^usr/")
@@ -323,13 +330,13 @@ macro(GNUInstallDirs_get_absolute_install_dir absvar var)
         set(${absvar} "/${${var}}")
       endif()
     elseif("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
-      if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR")
+      if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR" OR "${dir}" STREQUAL "RUNSTATEDIR")
         set(${absvar} "/${${var}}")
       else()
         set(${absvar} "${CMAKE_INSTALL_PREFIX}/${${var}}")
       endif()
     elseif("${CMAKE_INSTALL_PREFIX}" MATCHES "^/opt/.*")
-      if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR")
+      if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR" OR "${dir}" STREQUAL "RUNSTATEDIR")
         set(${absvar} "/${${var}}${CMAKE_INSTALL_PREFIX}")
       else()
         set(${absvar} "${CMAKE_INSTALL_PREFIX}/${${var}}")
@@ -351,6 +358,7 @@ foreach(dir
     SYSCONFDIR
     SHAREDSTATEDIR
     LOCALSTATEDIR
+    RUNSTATEDIR
     LIBDIR
     INCLUDEDIR
     OLDINCLUDEDIR
diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake
index 6d1b4ed..4573c2e 100644
--- a/Modules/GenerateExportHeader.cmake
+++ b/Modules/GenerateExportHeader.cmake
@@ -215,9 +215,6 @@ macro(_test_compiler_hidden_visibility)
     check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
     check_cxx_compiler_flag(-fvisibility-inlines-hidden
       COMPILER_HAS_HIDDEN_INLINE_VISIBILITY)
-    option(USE_COMPILER_HIDDEN_VISIBILITY
-      "Use HIDDEN visibility support if available." ON)
-    mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY)
   endif()
 endmacro()
 
@@ -267,7 +264,7 @@ macro(_DO_SET_MACRO_VALUES TARGET_LIBRARY)
     if(WIN32 OR CYGWIN)
       set(DEFINE_EXPORT "__declspec(dllexport)")
       set(DEFINE_IMPORT "__declspec(dllimport)")
-    elseif(COMPILER_HAS_HIDDEN_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY)
+    elseif(COMPILER_HAS_HIDDEN_VISIBILITY)
       set(DEFINE_EXPORT "__attribute__((visibility(\"default\")))")
       set(DEFINE_IMPORT "__attribute__((visibility(\"default\")))")
       set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))")
@@ -388,6 +385,9 @@ function(add_compiler_export_flags)
   _test_compiler_hidden_visibility()
   _test_compiler_has_deprecated()
 
+  option(USE_COMPILER_HIDDEN_VISIBILITY
+    "Use HIDDEN visibility support if available." ON)
+  mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY)
   if(NOT (USE_COMPILER_HIDDEN_VISIBILITY AND COMPILER_HAS_HIDDEN_VISIBILITY))
     # Just return if there are no flags to add.
     return()
diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake
index 1b23800..4e52cb3 100644
--- a/Modules/GetPrerequisites.cmake
+++ b/Modules/GetPrerequisites.cmake
@@ -399,6 +399,11 @@ function(gp_resolve_item context item exepath dirs resolved_item_var)
     set(ri "ri-NOTFOUND")
     find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
     find_file(ri "${item}" ${exepath} ${dirs} /usr/lib)
+
+    get_filename_component(basename_item "${item}" NAME)
+    find_file(ri "${basename_item}" PATHS ${exepath} ${dirs} NO_DEFAULT_PATH)
+    find_file(ri "${basename_item}" PATHS /usr/lib)
+
     if(ri)
       #message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
       set(resolved 1)
@@ -516,7 +521,7 @@ function(gp_resolved_file_type original_file file exepath dirs type_var)
     string(TOLOWER "${resolved_file}" lower)
 
     if(UNIX)
-      if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/|/usr/bin/)")
+      if(resolved_file MATCHES "^(/lib/|/lib32/|/libx32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/libx32/|/usr/lib64/|/usr/X11R6/|/usr/bin/)")
         set(is_system 1)
       endif()
     endif()
@@ -604,7 +609,7 @@ function(gp_resolved_file_type original_file file exepath dirs type_var)
 
   if(NOT is_embedded)
     if(NOT IS_ABSOLUTE "${resolved_file}")
-      if(lower MATCHES "^msvc[^/]+dll" AND is_system)
+      if(lower MATCHES "^(msvc|api-ms-win-)[^/]+dll" AND is_system)
         message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'")
       else()
         message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect")
@@ -938,7 +943,11 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa
         #
         if(NOT list_length_before_append EQUAL list_length_after_append)
           gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item "${rpaths}")
-          set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
+          if(EXISTS "${resolved_item}")
+            # Recurse only if we could resolve the item.
+            # Otherwise the prerequisites_var list will be cleared
+            set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
+          endif()
         endif()
       endif()
     endif()
diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake
new file mode 100644
index 0000000..7415e06
--- /dev/null
+++ b/Modules/GoogleTest.cmake
@@ -0,0 +1,226 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+GoogleTest
+----------
+
+This module defines functions to help use the Google Test infrastructure.
+
+.. command:: gtest_add_tests
+
+  Automatically add tests with CTest by scanning source code for Google Test
+  macros::
+
+    gtest_add_tests(TARGET target
+                    [SOURCES src1...]
+                    [EXTRA_ARGS arg1...]
+                    [WORKING_DIRECTORY dir]
+                    [TEST_PREFIX prefix]
+                    [TEST_SUFFIX suffix]
+                    [SKIP_DEPENDENCY]
+                    [TEST_LIST outVar]
+    )
+
+  ``TARGET target``
+    This must be a known CMake target. CMake will substitute the location of
+    the built executable when running the test.
+
+  ``SOURCES src1...``
+    When provided, only the listed files will be scanned for test cases. If
+    this option is not given, the :prop_tgt:`SOURCES` property of the
+    specified ``target`` will be used to obtain the list of sources.
+
+  ``EXTRA_ARGS arg1...``
+    Any extra arguments to pass on the command line to each test case.
+
+  ``WORKING_DIRECTORY dir``
+    Specifies the directory in which to run the discovered test cases. If this
+    option is not provided, the current binary directory is used.
+
+  ``TEST_PREFIX prefix``
+    Allows the specified ``prefix`` to be prepended to the name of each
+    discovered test case. This can be useful when the same source files are
+    being used in multiple calls to ``gtest_add_test()`` but with different
+    ``EXTRA_ARGS``.
+
+  ``TEST_SUFFIX suffix``
+    Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of
+    every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` can be
+    specified.
+
+  ``SKIP_DEPENDENCY``
+    Normally, the function creates a dependency which will cause CMake to be
+    re-run if any of the sources being scanned are changed. This is to ensure
+    that the list of discovered tests is updated. If this behavior is not
+    desired (as may be the case while actually writing the test cases), this
+    option can be used to prevent the dependency from being added.
+
+  ``TEST_LIST outVar``
+    The variable named by ``outVar`` will be populated in the calling scope
+    with the list of discovered test cases. This allows the caller to do things
+    like manipulate test properties of the discovered tests.
+
+  .. code-block:: cmake
+
+    include(GoogleTest)
+    add_executable(FooTest FooUnitTest.cxx)
+    gtest_add_tests(TARGET      FooTest
+                    TEST_SUFFIX .noArgs
+                    TEST_LIST   noArgsTests
+    )
+    gtest_add_tests(TARGET      FooTest
+                    EXTRA_ARGS  --someArg someValue
+                    TEST_SUFFIX .withArgs
+                    TEST_LIST   withArgsTests
+    )
+    set_tests_properties(${noArgsTests}   PROPERTIES TIMEOUT 10)
+    set_tests_properties(${withArgsTests} PROPERTIES TIMEOUT 20)
+
+  For backward compatibility reasons, the following form is also supported::
+
+    gtest_add_tests(exe args files...)
+
+  ``exe``
+    The path to the test executable or the name of a CMake target.
+  ``args``
+    A ;-list of extra arguments to be passed to executable.  The entire
+    list must be passed as a single argument.  Enclose it in quotes,
+    or pass ``""`` for no arguments.
+  ``files...``
+    A list of source files to search for tests and test fixtures.
+    Alternatively, use ``AUTO`` to specify that ``exe`` is the name
+    of a CMake executable target whose sources should be scanned.
+
+  .. code-block:: cmake
+
+    include(GoogleTest)
+    set(FooTestArgs --foo 1 --bar 2)
+    add_executable(FooTest FooUnitTest.cxx)
+    gtest_add_tests(FooTest "${FooTestArgs}" AUTO)
+
+#]=======================================================================]
+
+function(gtest_add_tests)
+
+  if (ARGC LESS 1)
+    message(FATAL_ERROR "No arguments supplied to gtest_add_tests()")
+  endif()
+
+  set(options
+      SKIP_DEPENDENCY
+  )
+  set(oneValueArgs
+      TARGET
+      WORKING_DIRECTORY
+      TEST_PREFIX
+      TEST_SUFFIX
+      TEST_LIST
+  )
+  set(multiValueArgs
+      SOURCES
+      EXTRA_ARGS
+  )
+  set(allKeywords ${options} ${oneValueArgs} ${multiValueArgs})
+
+  unset(sources)
+  if("${ARGV0}" IN_LIST allKeywords)
+    cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+    set(autoAddSources YES)
+  else()
+    # Non-keyword syntax, convert to keyword form
+    if (ARGC LESS 3)
+      message(FATAL_ERROR "gtest_add_tests() without keyword options requires at least 3 arguments")
+    endif()
+    set(ARGS_TARGET     "${ARGV0}")
+    set(ARGS_EXTRA_ARGS "${ARGV1}")
+    if(NOT "${ARGV2}" STREQUAL "AUTO")
+      set(ARGS_SOURCES "${ARGV}")
+      list(REMOVE_AT ARGS_SOURCES 0 1)
+    endif()
+  endif()
+
+  # The non-keyword syntax allows the first argument to be an arbitrary
+  # executable rather than a target if source files are also provided. In all
+  # other cases, both forms require a target.
+  if(NOT TARGET "${ARGS_TARGET}" AND NOT ARGS_SOURCES)
+    message(FATAL_ERROR "${ARGS_TARGET} does not define an existing CMake target")
+  endif()
+  if(NOT ARGS_WORKING_DIRECTORY)
+    unset(workDir)
+  else()
+    set(workDir WORKING_DIRECTORY "${ARGS_WORKING_DIRECTORY}")
+  endif()
+
+  if(NOT ARGS_SOURCES)
+    get_property(ARGS_SOURCES TARGET ${ARGS_TARGET} PROPERTY SOURCES)
+  endif()
+
+  unset(testList)
+
+  set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*")
+  set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)")
+
+  foreach(source IN LISTS ARGS_SOURCES)
+    if(NOT ARGS_SKIP_DEPENDENCY)
+      set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source})
+    endif()
+    file(READ "${source}" contents)
+    string(REGEX MATCHALL "${gtest_test_type_regex} *\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents})
+    foreach(hit ${found_tests})
+      string(REGEX MATCH "${gtest_test_type_regex}" test_type ${hit})
+
+      # Parameterized tests have a different signature for the filter
+      if("x${test_type}" STREQUAL "xTEST_P")
+        string(REGEX REPLACE ${gtest_case_name_regex}  "*/\\1.\\2/*" gtest_test_name ${hit})
+      elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST")
+        string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" gtest_test_name ${hit})
+      elseif("x${test_type}" STREQUAL "xTYPED_TEST")
+        string(REGEX REPLACE ${gtest_case_name_regex} "\\1/*.\\2" gtest_test_name ${hit})
+      else()
+        message(WARNING "Could not parse GTest ${hit} for adding to CTest.")
+        continue()
+      endif()
+
+      # Make sure tests disabled in GTest get disabled in CTest
+      if(gtest_test_name MATCHES "(^|\\.)DISABLED_")
+        # Add the disabled test if CMake is new enough
+        # Note that this check is to allow backwards compatibility so this
+        # module can be copied locally in projects to use with older CMake
+        # versions
+        if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.8.20170401)
+          string(REGEX REPLACE
+                 "(^|\\.)DISABLED_" "\\1"
+                 orig_test_name "${gtest_test_name}"
+          )
+          set(ctest_test_name
+              ${ARGS_TEST_PREFIX}${orig_test_name}${ARGS_TEST_SUFFIX}
+          )
+          add_test(NAME ${ctest_test_name}
+                   ${workDir}
+                   COMMAND ${ARGS_TARGET}
+                     --gtest_also_run_disabled_tests
+                     --gtest_filter=${gtest_test_name}
+                     ${ARGS_EXTRA_ARGS}
+          )
+          set_tests_properties(${ctest_test_name} PROPERTIES DISABLED TRUE)
+          list(APPEND testList ${ctest_test_name})
+        endif()
+      else()
+        set(ctest_test_name ${ARGS_TEST_PREFIX}${gtest_test_name}${ARGS_TEST_SUFFIX})
+        add_test(NAME ${ctest_test_name}
+                 ${workDir}
+                 COMMAND ${ARGS_TARGET}
+                   --gtest_filter=${gtest_test_name}
+                   ${ARGS_EXTRA_ARGS}
+        )
+        list(APPEND testList ${ctest_test_name})
+      endif()
+    endforeach()
+  endforeach()
+
+  if(ARGS_TEST_LIST)
+    set(${ARGS_TEST_LIST} ${testList} PARENT_SCOPE)
+  endif()
+
+endfunction()
diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake
index a3478a3..6d33fc6 100644
--- a/Modules/InstallRequiredSystemLibraries.cmake
+++ b/Modules/InstallRequiredSystemLibraries.cmake
@@ -31,6 +31,11 @@
 #   app-local deployment (e.g. to Windows XP).  This is meaningful
 #   only with MSVC from Visual Studio 2015 or higher.
 #
+#   One may set a ``CMAKE_WINDOWS_KITS_10_DIR`` *environment variable*
+#   to an absolute path to tell CMake to look for Windows 10 SDKs in
+#   a custom location.  The specified directory is expected to contain
+#   ``Redist/ucrt/DLLs/*`` directories.
+#
 # ``CMAKE_INSTALL_MFC_LIBRARIES``
 #   Set to TRUE to install the MSVC MFC runtime libraries.
 #
@@ -258,6 +263,7 @@ if(MSVC)
       set(programfilesx86 "ProgramFiles(x86)")
       find_path(WINDOWS_KITS_DIR NAMES Redist/ucrt/DLLs/${CMAKE_MSVC_ARCH}/ucrtbase.dll
         PATHS
+        $ENV{CMAKE_WINDOWS_KITS_10_DIR}
         "${windows_kits_dir}"
         "$ENV{ProgramFiles}/Windows Kits/10"
         "$ENV{${programfilesx86}}/Windows Kits/10"
diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake
index 50b8526..de336e7 100644
--- a/Modules/Internal/FeatureTesting.cmake
+++ b/Modules/Internal/FeatureTesting.cmake
@@ -22,9 +22,18 @@ macro(_record_compiler_features lang compile_flags feature_list)
   file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}"
     "\n};\n\nint main(int argc, char** argv) { (void)argv; return features[argc]; }\n")
 
+  if(CMAKE_${lang}_LINK_WITH_STANDARD_COMPILE_OPTION)
+    # This toolchain requires use of the language standard flag
+    # when linking in order to use the matching standard library.
+    set(compile_flags_for_link "${compile_flags}")
+  else()
+    set(compile_flags_for_link "")
+  endif()
+
   try_compile(CMAKE_${lang}_FEATURE_TEST
     ${CMAKE_BINARY_DIR} "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}"
     COMPILE_DEFINITIONS "${compile_flags}"
+    LINK_LIBRARIES "${compile_flags_for_link}"
     OUTPUT_VARIABLE _output
     COPY_FILE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin"
     COPY_FILE_ERROR _copy_error
@@ -35,6 +44,7 @@ macro(_record_compiler_features lang compile_flags feature_list)
     set(_result 255)
   endif()
   unset(CMAKE_${lang}_FEATURE_TEST CACHE)
+  unset(compile_flags_for_link)
 
   if (_result EQUAL 0)
     file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
diff --git a/Modules/MacOSXBundleInfo.plist.in b/Modules/MacOSXBundleInfo.plist.in
index a4009bc..e06b17e 100644
--- a/Modules/MacOSXBundleInfo.plist.in
+++ b/Modules/MacOSXBundleInfo.plist.in
@@ -30,5 +30,9 @@
 	<true/>
 	<key>NSHumanReadableCopyright</key>
 	<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+	<key>NSHighResolutionCapable</key>
+	<string>True</string>
 </dict>
 </plist>
diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake
index ca6e97c..7f08c4a 100644
--- a/Modules/Platform/AIX-GNU.cmake
+++ b/Modules/Platform/AIX-GNU.cmake
@@ -19,7 +19,7 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,-brtl")
 macro(__aix_compiler_gnu lang)
   set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-blibpath:")
   set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":")
-  set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS} -Wl,-G,-bnoipath")
+  string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-G,-bnoipath")
   set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall")
   set(CMAKE_${lang}_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH 1)
 
diff --git a/Modules/Platform/AIX-XL-C.cmake b/Modules/Platform/AIX-XL-C.cmake
index 5e437fa..cbfd58b 100644
--- a/Modules/Platform/AIX-XL-C.cmake
+++ b/Modules/Platform/AIX-XL-C.cmake
@@ -1,2 +1,5 @@
 include(Platform/AIX-XL)
 __aix_compiler_xl(C)
+
+# -qhalt=e       = Halt on error messages (rather than just severe errors)
+string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e")
diff --git a/Modules/Platform/AIX-XL-CXX.cmake b/Modules/Platform/AIX-XL-CXX.cmake
index ef38a5f..78baef5 100644
--- a/Modules/Platform/AIX-XL-CXX.cmake
+++ b/Modules/Platform/AIX-XL-CXX.cmake
@@ -1,2 +1,5 @@
 include(Platform/AIX-XL)
 __aix_compiler_xl(CXX)
+
+# -qhalt=s       = Halt on severe error messages
+string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s")
diff --git a/Modules/Platform/Android-Common.cmake b/Modules/Platform/Android-Common.cmake
index cf2785a..5faada3 100644
--- a/Modules/Platform/Android-Common.cmake
+++ b/Modules/Platform/Android-Common.cmake
@@ -156,6 +156,17 @@ macro(__android_compiler_common lang)
   # necessary so that Android API-version-specific headers are preferred
   # over those in the toolchain's `include-fixed` directory (which cannot
   # possibly match all versions).
-  list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${CMAKE_SYSROOT}/usr/include")
-  list(REMOVE_ITEM CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES "/usr/include")
+  #
+  # Do not do this for a standalone toolchain because it is already
+  # tied to a specific API version.
+  if(CMAKE_ANDROID_NDK)
+    if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
+      list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES
+        "${CMAKE_SYSROOT_COMPILE}/usr/include"
+        "${CMAKE_SYSROOT_COMPILE}/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}"
+        )
+    else()
+      list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${CMAKE_SYSROOT}/usr/include")
+    endif()
+  endif()
 endmacro()
diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake
index 6d370ab..add1dc1 100644
--- a/Modules/Platform/Android-Determine.cmake
+++ b/Modules/Platform/Android-Determine.cmake
@@ -100,11 +100,34 @@ endif()
 
 set(_ANDROID_STANDALONE_TOOLCHAIN_API "")
 if(CMAKE_ANDROID_STANDALONE_TOOLCHAIN)
-  set(_ANDROID_API_LEVEL_H_REGEX "^[\t ]*#[\t ]*define[\t ]+__ANDROID_API__[\t ]+([0-9]+)")
-  file(STRINGS "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h"
-    _ANDROID_API_LEVEL_H_CONTENT REGEX "${_ANDROID_API_LEVEL_H_REGEX}")
-  if(_ANDROID_API_LEVEL_H_CONTENT MATCHES "${_ANDROID_API_LEVEL_H_REGEX}")
-    set(_ANDROID_STANDALONE_TOOLCHAIN_API "${CMAKE_MATCH_1}")
+  # Try to read the API level from the toolchain launcher.
+  if(EXISTS "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/bin/clang")
+    set(_ANDROID_API_LEVEL_CLANG_REGEX "__ANDROID_API__=([0-9]+)")
+    file(STRINGS "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/bin/clang" _ANDROID_STANDALONE_TOOLCHAIN_BIN_CLANG
+      REGEX "${_ANDROID_API_LEVEL_CLANG_REGEX}" LIMIT_COUNT 1 LIMIT_INPUT 65536)
+    if(_ANDROID_STANDALONE_TOOLCHAIN_BIN_CLANG MATCHES "${_ANDROID_API_LEVEL_CLANG_REGEX}")
+      set(_ANDROID_STANDALONE_TOOLCHAIN_API "${CMAKE_MATCH_1}")
+    endif()
+    unset(_ANDROID_STANDALONE_TOOLCHAIN_BIN_CLANG)
+    unset(_ANDROID_API_LEVEL_CLANG_REGEX)
+  endif()
+  if(NOT _ANDROID_STANDALONE_TOOLCHAIN_API)
+    # The compiler launcher does not know __ANDROID_API__.  Assume this
+    # is not unified headers and look for it in the api-level.h header.
+    set(_ANDROID_API_LEVEL_H_REGEX "^[\t ]*#[\t ]*define[\t ]+__ANDROID_API__[\t ]+([0-9]+)")
+    file(STRINGS "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h"
+      _ANDROID_API_LEVEL_H_CONTENT REGEX "${_ANDROID_API_LEVEL_H_REGEX}")
+    if(_ANDROID_API_LEVEL_H_CONTENT MATCHES "${_ANDROID_API_LEVEL_H_REGEX}")
+      set(_ANDROID_STANDALONE_TOOLCHAIN_API "${CMAKE_MATCH_1}")
+    endif()
+  endif()
+  if(NOT _ANDROID_STANDALONE_TOOLCHAIN_API)
+    message(WARNING
+      "Android: Did not detect API level from\n"
+      "  ${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/bin/clang\n"
+      "or\n"
+      "  ${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h\n"
+      )
   endif()
 endif()
 
@@ -174,22 +197,30 @@ endif()
 
 # https://developer.android.com/ndk/guides/abis.html
 
-set(_ANDROID_ABI_arm64-v8a_PROC   "aarch64")
-set(_ANDROID_ABI_arm64-v8a_ARCH   "arm64")
-set(_ANDROID_ABI_armeabi-v7a_PROC "armv7-a")
-set(_ANDROID_ABI_armeabi-v7a_ARCH "arm")
-set(_ANDROID_ABI_armeabi-v6_PROC  "armv6")
-set(_ANDROID_ABI_armeabi-v6_ARCH  "arm")
-set(_ANDROID_ABI_armeabi_PROC     "armv5te")
-set(_ANDROID_ABI_armeabi_ARCH     "arm")
-set(_ANDROID_ABI_mips_PROC        "mips")
-set(_ANDROID_ABI_mips_ARCH        "mips")
-set(_ANDROID_ABI_mips64_PROC      "mips64")
-set(_ANDROID_ABI_mips64_ARCH      "mips64")
-set(_ANDROID_ABI_x86_PROC         "i686")
-set(_ANDROID_ABI_x86_ARCH         "x86")
-set(_ANDROID_ABI_x86_64_PROC      "x86_64")
-set(_ANDROID_ABI_x86_64_ARCH      "x86_64")
+set(_ANDROID_ABI_arm64-v8a_PROC     "aarch64")
+set(_ANDROID_ABI_arm64-v8a_ARCH     "arm64")
+set(_ANDROID_ABI_arm64-v8a_HEADER   "aarch64-linux-android")
+set(_ANDROID_ABI_armeabi-v7a_PROC   "armv7-a")
+set(_ANDROID_ABI_armeabi-v7a_ARCH   "arm")
+set(_ANDROID_ABI_armeabi-v7a_HEADER "arm-linux-androideabi")
+set(_ANDROID_ABI_armeabi-v6_PROC    "armv6")
+set(_ANDROID_ABI_armeabi-v6_ARCH    "arm")
+set(_ANDROID_ABI_armeabi-v6_HEADER  "arm-linux-androideabi")
+set(_ANDROID_ABI_armeabi_PROC       "armv5te")
+set(_ANDROID_ABI_armeabi_ARCH       "arm")
+set(_ANDROID_ABI_armeabi_HEADER     "arm-linux-androideabi")
+set(_ANDROID_ABI_mips_PROC          "mips")
+set(_ANDROID_ABI_mips_ARCH          "mips")
+set(_ANDROID_ABI_mips_HEADER        "mipsel-linux-android")
+set(_ANDROID_ABI_mips64_PROC        "mips64")
+set(_ANDROID_ABI_mips64_ARCH        "mips64")
+set(_ANDROID_ABI_mips64_HEADER      "mips64el-linux-android")
+set(_ANDROID_ABI_x86_PROC           "i686")
+set(_ANDROID_ABI_x86_ARCH           "x86")
+set(_ANDROID_ABI_x86_HEADER         "i686-linux-android")
+set(_ANDROID_ABI_x86_64_PROC        "x86_64")
+set(_ANDROID_ABI_x86_64_ARCH        "x86_64")
+set(_ANDROID_ABI_x86_64_HEADER      "x86_64-linux-android")
 
 set(_ANDROID_PROC_aarch64_ARCH_ABI "arm64-v8a")
 set(_ANDROID_PROC_armv7-a_ARCH_ABI "armeabi-v7a")
@@ -241,6 +272,7 @@ if(_ANDROID_SYSROOT_ARCH AND NOT "x${_ANDROID_SYSROOT_ARCH}" STREQUAL "x${CMAKE_
     "does not match architecture '${CMAKE_ANDROID_ARCH}' for the ABI '${CMAKE_ANDROID_ARCH_ABI}'."
     )
 endif()
+set(CMAKE_ANDROID_ARCH_HEADER_TRIPLE "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_HEADER}")
 
 # Select a processor.
 if(NOT CMAKE_SYSTEM_PROCESSOR)
@@ -252,6 +284,16 @@ if(NOT _ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC STREQUAL CMAKE_SYSTEM_PROCESS
   message(FATAL_ERROR "Android: The specified CMAKE_ANDROID_ARCH_ABI='${CMAKE_ANDROID_ARCH_ABI}' and CMAKE_SYSTEM_PROCESSOR='${CMAKE_SYSTEM_PROCESSOR}' is not a valid combination.")
 endif()
 
+if(CMAKE_ANDROID_NDK AND NOT DEFINED CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
+  if(IS_DIRECTORY "${CMAKE_ANDROID_NDK}/sysroot/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}")
+    # Unified headers exist so we use them by default.
+    set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS 0)
+  else()
+    # Unified headers do not exist so use the deprecated headers.
+    set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS 1)
+  endif()
+endif()
+
 # Save the Android-specific information in CMakeSystem.cmake.
 set(CMAKE_SYSTEM_CUSTOM_CODE "
 set(CMAKE_ANDROID_NDK \"${CMAKE_ANDROID_NDK}\")
@@ -260,6 +302,13 @@ set(CMAKE_ANDROID_ARCH \"${CMAKE_ANDROID_ARCH}\")
 set(CMAKE_ANDROID_ARCH_ABI \"${CMAKE_ANDROID_ARCH_ABI}\")
 ")
 
+if(CMAKE_ANDROID_NDK)
+  string(APPEND CMAKE_SYSTEM_CUSTOM_CODE
+    "set(CMAKE_ANDROID_ARCH_HEADER_TRIPLE \"${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}\")\n"
+    "set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS \"${CMAKE_ANDROID_NDK_DEPRECATED_HEADERS}\")\n"
+    )
+endif()
+
 # Select an ARM variant.
 if(CMAKE_ANDROID_ARCH_ABI MATCHES "^armeabi")
   if(CMAKE_ANDROID_ARM_MODE)
diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake
index a327223..a434f90 100644
--- a/Modules/Platform/Android-Initialize.cmake
+++ b/Modules/Platform/Android-Initialize.cmake
@@ -20,6 +20,9 @@ endif()
 if(NOT CMAKE_SYSROOT)
   if(CMAKE_ANDROID_NDK)
     set(CMAKE_SYSROOT "${CMAKE_ANDROID_NDK}/platforms/android-${CMAKE_SYSTEM_VERSION}/arch-${CMAKE_ANDROID_ARCH}")
+    if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
+      set(CMAKE_SYSROOT_COMPILE "${CMAKE_ANDROID_NDK}/sysroot")
+    endif()
   elseif(CMAKE_ANDROID_STANDALONE_TOOLCHAIN)
     set(CMAKE_SYSROOT "${CMAKE_ANDROID_STANDALONE_TOOLCHAIN}/sysroot")
   endif()
diff --git a/Modules/Platform/Android/abi-common.cmake b/Modules/Platform/Android/abi-common.cmake
index 3b0eb01..10fb897 100644
--- a/Modules/Platform/Android/abi-common.cmake
+++ b/Modules/Platform/Android/abi-common.cmake
@@ -3,6 +3,10 @@ string(APPEND _ANDROID_ABI_INIT_CFLAGS
   " -no-canonical-prefixes"
   )
 
+if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
+  string(APPEND _ANDROID_ABI_INIT_CFLAGS " -D__ANDROID_API__=${CMAKE_SYSTEM_VERSION}")
+endif()
+
 if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE
     AND NOT CMAKE_SYSTEM_VERSION VERSION_LESS 16)
   set(CMAKE_POSITION_INDEPENDENT_CODE ON)
diff --git a/Modules/Platform/Android/ndk-stl-c++_shared.cmake b/Modules/Platform/Android/ndk-stl-c++_shared.cmake
index f585adb..3389408 100644
--- a/Modules/Platform/Android/ndk-stl-c++_shared.cmake
+++ b/Modules/Platform/Android/ndk-stl-c++_shared.cmake
@@ -1,4 +1,5 @@
 include(Platform/Android/ndk-stl-c++)
 macro(__android_stl lang)
   __android_stl_cxx(${lang} libc++_shared.so)
+  __android_stl_lib(${lang} "${CMAKE_ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${CMAKE_ANDROID_ARCH_ABI}/libandroid_support.a" 0)
 endmacro()
diff --git a/Modules/Platform/BlueGeneP-dynamic-XL-C.cmake b/Modules/Platform/BlueGeneP-dynamic-XL-C.cmake
index f13b517..918ee70 100644
--- a/Modules/Platform/BlueGeneP-dynamic-XL-C.cmake
+++ b/Modules/Platform/BlueGeneP-dynamic-XL-C.cmake
@@ -3,3 +3,6 @@
 
 
 __BlueGeneP_set_dynamic_flags(XL C)
+
+# -qhalt=e       = Halt on error messages (rather than just severe errors)
+string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e")
diff --git a/Modules/Platform/BlueGeneP-dynamic-XL-CXX.cmake b/Modules/Platform/BlueGeneP-dynamic-XL-CXX.cmake
index 80c05a1..cfefb0b 100644
--- a/Modules/Platform/BlueGeneP-dynamic-XL-CXX.cmake
+++ b/Modules/Platform/BlueGeneP-dynamic-XL-CXX.cmake
@@ -3,3 +3,6 @@
 
 
 __BlueGeneP_set_dynamic_flags(XL CXX)
+
+# -qhalt=s       = Halt on severe error messages
+string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s")
diff --git a/Modules/Platform/BlueGeneP-static-XL-C.cmake b/Modules/Platform/BlueGeneP-static-XL-C.cmake
index a990b5c..7d4fc13 100644
--- a/Modules/Platform/BlueGeneP-static-XL-C.cmake
+++ b/Modules/Platform/BlueGeneP-static-XL-C.cmake
@@ -3,3 +3,6 @@
 
 
 __BlueGeneP_set_static_flags(XL C)
+
+# -qhalt=e       = Halt on error messages (rather than just severe errors)
+string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e")
diff --git a/Modules/Platform/BlueGeneP-static-XL-CXX.cmake b/Modules/Platform/BlueGeneP-static-XL-CXX.cmake
index 116c0bb..1df276e 100644
--- a/Modules/Platform/BlueGeneP-static-XL-CXX.cmake
+++ b/Modules/Platform/BlueGeneP-static-XL-CXX.cmake
@@ -3,3 +3,6 @@
 
 
 __BlueGeneP_set_static_flags(XL CXX)
+
+# -qhalt=s       = Halt on severe error messages
+string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s")
diff --git a/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake b/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake
index f46fa95..c51dacb 100644
--- a/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake
+++ b/Modules/Platform/BlueGeneQ-dynamic-XL-C.cmake
@@ -3,3 +3,6 @@
 
 
 __BlueGeneQ_setup_dynamic(XL C)
+
+# -qhalt=e       = Halt on error messages (rather than just severe errors)
+string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e")
diff --git a/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake b/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake
index c463379..5dbc836 100644
--- a/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake
+++ b/Modules/Platform/BlueGeneQ-dynamic-XL-CXX.cmake
@@ -3,3 +3,6 @@
 
 
 __BlueGeneQ_setup_dynamic(XL CXX)
+
+# -qhalt=s       = Halt on severe error messages
+string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s")
diff --git a/Modules/Platform/BlueGeneQ-static-XL-C.cmake b/Modules/Platform/BlueGeneQ-static-XL-C.cmake
index 465128f..67cd57d 100644
--- a/Modules/Platform/BlueGeneQ-static-XL-C.cmake
+++ b/Modules/Platform/BlueGeneQ-static-XL-C.cmake
@@ -3,3 +3,6 @@
 
 
 __BlueGeneQ_setup_static(XL C)
+
+# -qhalt=e       = Halt on error messages (rather than just severe errors)
+string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e")
diff --git a/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake b/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake
index abd4ebf..a171e7f 100644
--- a/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake
+++ b/Modules/Platform/BlueGeneQ-static-XL-CXX.cmake
@@ -3,3 +3,6 @@
 
 
 __BlueGeneQ_setup_static(XL CXX)
+
+# -qhalt=s       = Halt on severe error messages
+string(APPEND CMAKE_CXX_FLAGS_INIT " -qhalt=s")
diff --git a/Modules/Platform/CYGWIN-GNU.cmake b/Modules/Platform/CYGWIN-GNU.cmake
index d08dc81..784c8c6 100644
--- a/Modules/Platform/CYGWIN-GNU.cmake
+++ b/Modules/Platform/CYGWIN-GNU.cmake
@@ -40,7 +40,7 @@ macro(__cygwin_compiler_gnu lang)
 
   set(CMAKE_EXE_EXPORTS_${lang}_FLAG "-Wl,--export-all-symbols")
   # TODO: Is -Wl,--enable-auto-import now always default?
-  set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS} -Wl,--enable-auto-import")
+  string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,--enable-auto-import")
   set(CMAKE_SHARED_MODULE_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS}")
 
   if(NOT CMAKE_RC_COMPILER_INIT)
diff --git a/Modules/Platform/CYGWIN.cmake b/Modules/Platform/CYGWIN.cmake
index 22816e7..9b897bd 100644
--- a/Modules/Platform/CYGWIN.cmake
+++ b/Modules/Platform/CYGWIN.cmake
@@ -62,3 +62,13 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".a")
 set(CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION 1)
 
 include(Platform/UnixPaths)
+
+# Windows API on Cygwin
+list(APPEND CMAKE_SYSTEM_INCLUDE_PATH
+  /usr/include/w32api
+  )
+
+# Windows API on Cygwin
+list(APPEND CMAKE_SYSTEM_LIBRARY_PATH
+  /usr/lib/w32api
+  )
diff --git a/Modules/Platform/Darwin-XL-C.cmake b/Modules/Platform/Darwin-XL-C.cmake
index 42e94a9..2aeb132 100644
--- a/Modules/Platform/Darwin-XL-C.cmake
+++ b/Modules/Platform/Darwin-XL-C.cmake
@@ -3,3 +3,6 @@ set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle")
 
 # Enable shared library versioning.
 set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-install_name")
+
+# -qhalt=e       = Halt on error messages (rather than just severe errors)
+string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e")
diff --git a/Modules/Platform/Darwin-XL-CXX.cmake b/Modules/Platform/Darwin-XL-CXX.cmake
index 65c76f8..f8e1906 100644
--- a/Modules/Platform/Darwin-XL-CXX.cmake
+++ b/Modules/Platform/Darwin-XL-CXX.cmake
@@ -3,3 +3,6 @@ set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "-bundle")
 
 # Enable shared library versioning.
 set(CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG "-Wl,-install_name")
+
+# -qhalt=e       = Halt on error messages (rather than just severe errors)
+string(APPEND CMAKE_C_FLAGS_INIT " -qhalt=e")
diff --git a/Modules/Platform/HP-UX-GNU.cmake b/Modules/Platform/HP-UX-GNU.cmake
index 7ac804b..699c4aa 100644
--- a/Modules/Platform/HP-UX-GNU.cmake
+++ b/Modules/Platform/HP-UX-GNU.cmake
@@ -9,7 +9,7 @@ endif()
 set(__HPUX_COMPILER_GNU 1)
 
 macro(__hpux_compiler_gnu lang)
-  set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS} -Wl,-E,-b,+nodefaultrpath")
+  string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-E,-b,+nodefaultrpath")
   set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-E")
   set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,+b")
   set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":")
diff --git a/Modules/Platform/Linux-GNU.cmake b/Modules/Platform/Linux-GNU.cmake
index 6878254..ce30a26 100644
--- a/Modules/Platform/Linux-GNU.cmake
+++ b/Modules/Platform/Linux-GNU.cmake
@@ -12,4 +12,5 @@ macro(__linux_compiler_gnu lang)
   # We pass this for historical reasons.  Projects may have
   # executables that use dlopen but do not set ENABLE_EXPORTS.
   set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
+  set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}" "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
 endmacro()
diff --git a/Modules/Platform/Linux-Intel.cmake b/Modules/Platform/Linux-Intel.cmake
index 85a0772..ee9aac2 100644
--- a/Modules/Platform/Linux-Intel.cmake
+++ b/Modules/Platform/Linux-Intel.cmake
@@ -30,12 +30,18 @@ macro(__linux_compiler_intel lang)
   # executables that use dlopen but do not set ENABLE_EXPORTS.
   set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
 
+  set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+
   if(XIAR)
     # INTERPROCEDURAL_OPTIMIZATION
     set(CMAKE_${lang}_COMPILE_OPTIONS_IPO -ipo)
     set(CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO
       "${XIAR} cr <TARGET> <LINK_FLAGS> <OBJECTS> "
       "${XIAR} -s <TARGET> ")
+    set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+    set(_CMAKE_${lang}_IPO_LEGACY_BEHAVIOR YES)
+  else()
+    set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
   endif()
 
   if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 12.0)
diff --git a/Modules/Platform/Linux-PGI.cmake b/Modules/Platform/Linux-PGI.cmake
index a407e43..db032c2 100644
--- a/Modules/Platform/Linux-PGI.cmake
+++ b/Modules/Platform/Linux-PGI.cmake
@@ -14,4 +14,5 @@ macro(__linux_compiler_pgi lang)
   set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "")
   set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
   set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
+  set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS " ")
 endmacro()
diff --git a/Modules/Platform/Linux-TinyCC-C.cmake b/Modules/Platform/Linux-TinyCC-C.cmake
index f78e708..9409d8b 100644
--- a/Modules/Platform/Linux-TinyCC-C.cmake
+++ b/Modules/Platform/Linux-TinyCC-C.cmake
@@ -2,3 +2,4 @@ set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "")
 set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP "")
 set(CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG "")
 set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-soname ")
+set(CMAKE_EXE_EXPORTS_C_FLAG "-rdynamic ")
diff --git a/Modules/Platform/SunOS.cmake b/Modules/Platform/SunOS.cmake
index 58398c0..e19e89a 100644
--- a/Modules/Platform/SunOS.cmake
+++ b/Modules/Platform/SunOS.cmake
@@ -9,6 +9,11 @@ endif()
 
 include(Platform/UnixPaths)
 
+list(APPEND CMAKE_SYSTEM_PREFIX_PATH
+  /opt/csw
+  /opt/openwin
+  )
+
 # The Sun linker needs to find transitive shared library dependencies
 # in the -L path.
 set(CMAKE_LINK_DEPENDENT_LIBRARY_DIRS 1)
diff --git a/Modules/Platform/UnixPaths.cmake b/Modules/Platform/UnixPaths.cmake
index b216d03..5687653 100644
--- a/Modules/Platform/UnixPaths.cmake
+++ b/Modules/Platform/UnixPaths.cmake
@@ -41,35 +41,22 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX)
   endif()
 endif()
 
+# Non "standard" but common install prefixes
+list(APPEND CMAKE_SYSTEM_PREFIX_PATH
+  /usr/X11R6
+  /usr/pkg
+  /opt
+  )
+
 # List common include file locations not under the common prefixes.
 list(APPEND CMAKE_SYSTEM_INCLUDE_PATH
-  # Windows API on Cygwin
-  /usr/include/w32api
-
   # X11
-  /usr/X11R6/include /usr/include/X11
-
-  # Other
-  /usr/pkg/include
-  /opt/csw/include /opt/include
-  /usr/openwin/include
+  /usr/include/X11
   )
 
 list(APPEND CMAKE_SYSTEM_LIBRARY_PATH
-  # Windows API on Cygwin
-  /usr/lib/w32api
-
   # X11
-  /usr/X11R6/lib /usr/lib/X11
-
-  # Other
-  /usr/pkg/lib
-  /opt/csw/lib /opt/lib
-  /usr/openwin/lib
-  )
-
-list(APPEND CMAKE_SYSTEM_PROGRAM_PATH
-  /usr/pkg/bin
+  /usr/lib/X11
   )
 
 list(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
@@ -86,3 +73,4 @@ list(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES
 # Enable use of lib32 and lib64 search path variants by default.
 set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS TRUE)
 set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)
+set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS TRUE)
diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake
index 22daa62..cfb325b 100644
--- a/Modules/Platform/Windows-GNU.cmake
+++ b/Modules/Platform/Windows-GNU.cmake
@@ -144,10 +144,24 @@ macro(__windows_compiler_gnu_abi lang)
 
   if(CMAKE_GNUtoMS AND NOT CMAKE_GNUtoMS_LIB)
     # Find MS development environment setup script for this architecture.
+    # We need to use the MS Librarian tool (lib.exe).
+    # Find the most recent version available.
+
+    # Query the VS Installer tool for locations of VS 2017 and above.
+    set(_vs_installer_paths "")
+    foreach(vs RANGE 15 15 -1) # change the first number to the largest supported version
+      cmake_host_system_information(RESULT _vs_dir QUERY VS_${vs}_DIR)
+      if(_vs_dir)
+        list(APPEND _vs_installer_paths "${_vs_dir}/VC/Auxiliary/Build")
+      endif()
+    endforeach(vs)
+
     if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4)
       find_program(CMAKE_GNUtoMS_VCVARS NAMES vcvars32.bat
         DOC "Visual Studio vcvars32.bat"
         PATHS
+        ${_vs_installer_paths}
+        "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\Setup\\VC;ProductDir]/bin"
         "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0\\Setup\\VC;ProductDir]/bin"
         "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0\\Setup\\VC;ProductDir]/bin"
         "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0\\Setup\\VC;ProductDir]/bin"
@@ -161,6 +175,8 @@ macro(__windows_compiler_gnu_abi lang)
       find_program(CMAKE_GNUtoMS_VCVARS NAMES vcvars64.bat vcvarsamd64.bat
         DOC "Visual Studio vcvarsamd64.bat"
         PATHS
+        ${_vs_installer_paths}
+        "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0\\Setup\\VC;ProductDir]/bin/amd64"
         "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0\\Setup\\VC;ProductDir]/bin/amd64"
         "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0\\Setup\\VC;ProductDir]/bin/amd64"
         "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0\\Setup\\VC;ProductDir]/bin/amd64"
@@ -169,6 +185,7 @@ macro(__windows_compiler_gnu_abi lang)
         )
       set(CMAKE_GNUtoMS_ARCH amd64)
     endif()
+    unset(_vs_installer_paths)
     set_property(CACHE CMAKE_GNUtoMS_VCVARS PROPERTY ADVANCED 1)
     if(CMAKE_GNUtoMS_VCVARS)
       # Create helper script to run lib.exe from MS environment.
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index e4aca6e..cfe6e1c 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -152,9 +152,9 @@ if(WINCE)
 
   foreach(lang C CXX)
     if(_MSVC_${lang}_ARCHITECTURE_FAMILY STREQUAL "ARM")
-      set(_PLATFORM_DEFINES_${lang} "${_PLATFORM_DEFINES_${lang}} /D${MSVC_${lang}_ARCHITECTURE_ID}")
+      string(APPEND _PLATFORM_DEFINES_${lang} " /D${MSVC_${lang}_ARCHITECTURE_ID}")
       if(MSVC_${lang}_ARCHITECTURE_ID MATCHES "^ARMV([45])I$")
-        set(_FLAGS_${lang} "${_FLAGS_${lang}} /QRarch${CMAKE_MATCH_1}T")
+        string(APPEND _FLAGS_${lang} " /QRarch${CMAKE_MATCH_1}T")
       endif()
     endif()
   endforeach()
diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
index 845fa4b..970c2c6 100644
--- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake
+++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
@@ -30,10 +30,18 @@ set(CMAKE_CUDA_LINK_EXECUTABLE
 unset(_CMAKE_VS_LINK_EXE)
 unset(_CMAKE_VS_LINK_EXE)
 
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0")
+  set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets")
+else()
+  set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
+endif()
+
 set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
-  "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+  "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
 set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
-  "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+  "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+
+unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
 
 string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}")
 
diff --git a/Modules/Platform/Windows-PGI-C.cmake b/Modules/Platform/Windows-PGI-C.cmake
new file mode 100644
index 0000000..0495b93
--- /dev/null
+++ b/Modules/Platform/Windows-PGI-C.cmake
@@ -0,0 +1,2 @@
+include(Platform/Windows-PGI)
+__windows_compiler_pgi(C)
diff --git a/Modules/Platform/Windows-PGI-Fortran.cmake b/Modules/Platform/Windows-PGI-Fortran.cmake
new file mode 100644
index 0000000..2222e33
--- /dev/null
+++ b/Modules/Platform/Windows-PGI-Fortran.cmake
@@ -0,0 +1,2 @@
+include(Platform/Windows-PGI)
+__windows_compiler_pgi(Fortran)
diff --git a/Modules/Platform/Windows-PGI.cmake b/Modules/Platform/Windows-PGI.cmake
new file mode 100644
index 0000000..ad77e8a
--- /dev/null
+++ b/Modules/Platform/Windows-PGI.cmake
@@ -0,0 +1,48 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# This module is shared by multiple languages; use include blocker.
+if(__WINDOWS_COMPILER_PGI)
+  return()
+endif()
+set(__WINDOWS_COMPILER_PGI 1)
+
+# PGI on Windows doesn't support parallel compile processes
+if(NOT DEFINED CMAKE_JOB_POOL_LINK OR NOT DEFINED CMAKE_JOB_POOL_COMPILE)
+  set(CMAKE_JOB_POOL_LINK PGITaskPool)
+  set(CMAKE_JOB_POOL_COMPILE PGITaskPool)
+  get_property(_pgijp GLOBAL PROPERTY JOB_POOLS)
+  if(NOT _pgijp MATCHES "PGITaskPool=")
+      set_property(GLOBAL APPEND PROPERTY JOB_POOLS PGITaskPool=1)
+  endif()
+  unset(_pgijp)
+endif()
+
+set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 1)
+set(CMAKE_LINK_DEF_FILE_FLAG "-def:")
+# The link flags for PGI are the raw filename to add a file
+# and the UNIX -L syntax to link directories.
+set(CMAKE_LINK_LIBRARY_FLAG "")
+set(CMAKE_LINK_STARTFILE "pgimain[mx][xpt]+[.]obj")
+
+# Default to Debug builds, mirroring Windows-MSVC behavior
+set(CMAKE_BUILD_TYPE_INIT Debug)
+
+if(CMAKE_VERBOSE_MAKEFILE)
+  set(CMAKE_CL_NOLOGO)
+else()
+  set(CMAKE_CL_NOLOGO "/nologo")
+endif()
+
+macro(__windows_compiler_pgi lang)
+  # Shared library compile and link rules.
+  set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
+  set(CMAKE_${lang}_CREATE_SHARED_LIBRARY "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} -Mmakedll -implib:<TARGET_IMPLIB> -Xlinker -pdb:<TARGET_PDB> -Xlinker -version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
+  set(CMAKE_${lang}_CREATE_SHARED_MODULE "${CMAKE_${lang}_CREATE_SHARED_LIBRARY}")
+  set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} -implib:<TARGET_IMPLIB> -Xlinker -pdb:<TARGET_PDB> -Xlinker -version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
+
+  if("${lang}" MATCHES "C|CXX")
+    set(CMAKE_${lang}_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib")
+  endif()
+endmacro()
diff --git a/Modules/Platform/Windows-df.cmake b/Modules/Platform/Windows-df.cmake
index b31cb11..c59be45 100644
--- a/Modules/Platform/Windows-df.cmake
+++ b/Modules/Platform/Windows-df.cmake
@@ -30,7 +30,7 @@ set(CMAKE_Fortran_LINK_EXECUTABLE
 set(CMAKE_CREATE_WIN32_EXE /winapp)
 set(CMAKE_CREATE_CONSOLE_EXE )
 
-if(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR CMAKE_GENERATOR MATCHES "Visual Studio 8")
+if(CMAKE_GENERATOR MATCHES "Visual Studio 8")
   set (CMAKE_NO_BUILD_TYPE 1)
 endif()
 # does the compiler support pdbtype and is it the newer compiler
diff --git a/Modules/TestBigEndian.cmake b/Modules/TestBigEndian.cmake
index 085be22..cc627d0 100644
--- a/Modules/TestBigEndian.cmake
+++ b/Modules/TestBigEndian.cmake
@@ -19,21 +19,29 @@ macro(TEST_BIG_ENDIAN VARIABLE)
     message(STATUS "Check if the system is big endian")
     message(STATUS "Searching 16 bit integer")
 
+    if(CMAKE_C_COMPILER_LOADED)
+      set(_test_language "C")
+    elseif(CMAKE_CXX_COMPILER_LOADED)
+      set(_test_language "CXX")
+    else()
+      message(FATAL_ERROR "TEST_BIG_ENDIAN needs either C or CXX language enabled")
+    endif()
+
     include(CheckTypeSize)
 
-    CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT)
+    CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT LANGUAGE ${_test_language})
     if(CMAKE_SIZEOF_UNSIGNED_SHORT EQUAL 2)
       message(STATUS "Using unsigned short")
       set(CMAKE_16BIT_TYPE "unsigned short")
     else()
-      CHECK_TYPE_SIZE("unsigned int"   CMAKE_SIZEOF_UNSIGNED_INT)
+      CHECK_TYPE_SIZE("unsigned int"   CMAKE_SIZEOF_UNSIGNED_INT LANGUAGE ${_test_language})
       if(CMAKE_SIZEOF_UNSIGNED_INT)
         message(STATUS "Using unsigned int")
         set(CMAKE_16BIT_TYPE "unsigned int")
 
       else()
 
-        CHECK_TYPE_SIZE("unsigned long"  CMAKE_SIZEOF_UNSIGNED_LONG)
+        CHECK_TYPE_SIZE("unsigned long"  CMAKE_SIZEOF_UNSIGNED_LONG LANGUAGE ${_test_language})
         if(CMAKE_SIZEOF_UNSIGNED_LONG)
           message(STATUS "Using unsigned long")
           set(CMAKE_16BIT_TYPE "unsigned long")
@@ -45,17 +53,21 @@ macro(TEST_BIG_ENDIAN VARIABLE)
 
     endif()
 
+    if(_test_language STREQUAL "CXX")
+      set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.cpp")
+    else()
+      set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c")
+    endif()
 
     configure_file("${CMAKE_ROOT}/Modules/TestEndianess.c.in"
-                   "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c"
+                   ${_test_file}
                    @ONLY)
 
-     file(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c"
-          TEST_ENDIANESS_FILE_CONTENT)
+     file(READ ${_test_file} TEST_ENDIANESS_FILE_CONTENT)
 
      try_compile(HAVE_${VARIABLE}
       "${CMAKE_BINARY_DIR}"
-      "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c"
+      ${_test_file}
       OUTPUT_VARIABLE OUTPUT
       COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianess.bin" )
 
diff --git a/Modules/UseEcos.cmake b/Modules/UseEcos.cmake
index be1dfd1..942bc38 100644
--- a/Modules/UseEcos.cmake
+++ b/Modules/UseEcos.cmake
@@ -184,8 +184,8 @@ macro(ECOS_ADD_EXECUTABLE _exe_NAME )
 # when using nmake makefiles, the custom buildtype supresses the default cl.exe flags
 # and the rules for creating objects are adjusted for gcc
    set(CMAKE_BUILD_TYPE CUSTOM_ECOS_BUILD)
-   set(CMAKE_C_COMPILE_OBJECT     "<CMAKE_C_COMPILER>   <FLAGS> -o <OBJECT> -c <SOURCE>")
-   set(CMAKE_CXX_COMPILE_OBJECT   "<CMAKE_CXX_COMPILER> <FLAGS> -o <OBJECT> -c <SOURCE>")
+   set(CMAKE_C_COMPILE_OBJECT     "<CMAKE_C_COMPILER>   <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
+   set(CMAKE_CXX_COMPILE_OBJECT   "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
 # special link commands for ecos-executables
    set(CMAKE_CXX_LINK_EXECUTABLE  "<CMAKE_CXX_COMPILER> <CMAKE_CXX_LINK_FLAGS> <OBJECTS>  -o <TARGET> ${_ecos_EXTRA_LIBS} -nostdlib  -nostartfiles -L${CMAKE_CURRENT_BINARY_DIR}/ecos/install/lib -Ttarget.ld ${ECOS_LD_MCPU}")
    set(CMAKE_C_LINK_EXECUTABLE    "<CMAKE_C_COMPILER>   <CMAKE_C_LINK_FLAGS>   <OBJECTS>  -o <TARGET> ${_ecos_EXTRA_LIBS} -nostdlib  -nostartfiles -L${CMAKE_CURRENT_BINARY_DIR}/ecos/install/lib -Ttarget.ld ${ECOS_LD_MCPU}")
diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake
index 93255ae..1182875 100644
--- a/Modules/UseJava.cmake
+++ b/Modules/UseJava.cmake
@@ -244,21 +244,23 @@
 #
 # ::
 #
-#  install_jar_exports(TARGETS jar1 [jar2 ...]
-#                      FILE export_filename
-#                      DESTINATION destination [COMPONENT component])
+#  install_jar_exports(TARGETS jars...
+#                      [NAMESPACE <namespace>]
+#                      FILE <filename>
+#                      DESTINATION <dir> [COMPONENT <component>])
 #
-# This command installs a target export file export_filename for the named jar
-# targets to the given DESTINATION. Its function is similar to that of
-# install(EXPORTS).
+# This command installs a target export file ``<filename>`` for the named jar
+# targets to the given ``DESTINATION``. Its function is similar to that of
+# :command:`install(EXPORTS ...)`.
 #
 # ::
 #
-#  export_jars(TARGETS jar1 [jar2 ...]
-#              FILE export_filename)
+#  export_jars(TARGETS jars...
+#              [NAMESPACE <namespace>]
+#              FILE <filename>)
 #
-# This command writes a target export file export_filename for the named jar
-# targets. Its function is similar to that of export().
+# This command writes a target export file ``<filename>`` for the named jar
+# targets. Its function is similar to that of :command:`export(...)`.
 #
 # ::
 #
@@ -415,7 +417,7 @@ endfunction ()
 
 function(__java_lcat VAR)
     foreach(_line ${ARGN})
-        set(${VAR} "${${VAR}}${_line}\n")
+        string(APPEND ${VAR} "${_line}\n")
     endforeach()
 
     set(${VAR} "${${VAR}}" PARENT_SCOPE)
@@ -424,10 +426,12 @@ endfunction()
 function(__java_export_jar VAR TARGET PATH)
     get_target_property(_jarpath ${TARGET} JAR_FILE)
     get_filename_component(_jarname ${_jarpath} NAME)
+    set(_target "${_jar_NAMESPACE}${TARGET}")
     __java_lcat(${VAR}
-      "# Create imported target ${TARGET}"
-      "add_custom_target(${TARGET})"
-      "set_target_properties(${TARGET} PROPERTIES"
+      "# Create imported target ${_target}"
+      "add_library(${_target} IMPORTED STATIC)"
+      "set_target_properties(${_target} PROPERTIES"
+      "  IMPORTED_LOCATION \"${PATH}/${_jarname}\""
       "  JAR_FILE \"${PATH}/${_jarname}\")"
       ""
     )
@@ -1341,7 +1345,7 @@ function(export_jars)
     # Parse and validate arguments
     cmake_parse_arguments(_export_jars
       ""
-      "FILE"
+      "FILE;NAMESPACE"
       "TARGETS"
       ${ARGN}
     )
@@ -1351,6 +1355,7 @@ function(export_jars)
     if (NOT _export_jars_TARGETS)
       message(SEND_ERROR "export_jars: TARGETS must be specified.")
     endif()
+    set(_jar_NAMESPACE "${_export_jars_NAMESPACE}")
 
     # Set content of generated exports file
     string(REPLACE ";" " " __targets__ "${_export_jars_TARGETS}")
@@ -1373,7 +1378,7 @@ function(install_jar_exports)
     # Parse and validate arguments
     cmake_parse_arguments(_install_jar_exports
       ""
-      "FILE;DESTINATION;COMPONENT"
+      "FILE;DESTINATION;COMPONENT;NAMESPACE"
       "TARGETS"
       ${ARGN}
     )
@@ -1386,6 +1391,7 @@ function(install_jar_exports)
     if (NOT _install_jar_exports_TARGETS)
       message(SEND_ERROR "install_jar_exports: TARGETS must be specified.")
     endif()
+    set(_jar_NAMESPACE "${_install_jar_exports_NAMESPACE}")
 
     if (_install_jar_exports_COMPONENT)
       set (_COMPONENT COMPONENT ${_install_jar_exports_COMPONENT})
diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake
index 277f4ca..bfe1a6f 100644
--- a/Modules/UseSWIG.cmake
+++ b/Modules/UseSWIG.cmake
@@ -326,6 +326,9 @@ macro(SWIG_ADD_LIBRARY name)
     if (APPLE)
       set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".bundle")
     endif ()
+  else()
+    # assume empty prefix because we expect the module to be dynamically loaded
+    set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
   endif ()
 endmacro()
 
diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake
index 0b16aa4..e7f9912 100644
--- a/Modules/WriteCompilerDetectionHeader.cmake
+++ b/Modules/WriteCompilerDetectionHeader.cmake
@@ -447,7 +447,7 @@ function(write_compiler_detection_header
       endif()
 
       if(NOT _WCD_ALLOW_UNKNOWN_COMPILER_VERSIONS)
-        set(${compiler_file_content} "${${compiler_file_content}}
+        string(APPEND ${compiler_file_content} "
 #    if !(${_cmake_oldestSupported_${compiler}})
 #      error Unsupported compiler version
 #    endif\n")
@@ -462,7 +462,7 @@ function(write_compiler_detection_header
         set(MACRO_HEX)
       endif()
       string(CONFIGURE "${_compiler_id_version_compute_${compiler}}" VERSION_BLOCK @ONLY)
-      set(${compiler_file_content} "${${compiler_file_content}}${VERSION_BLOCK}\n")
+      string(APPEND ${compiler_file_content} "${VERSION_BLOCK}\n")
       set(PREFIX)
       set(MACRO_DEC)
       set(MACRO_HEX)
@@ -478,7 +478,7 @@ function(write_compiler_detection_header
           set(_define_item "\n#      define ${prefix_arg}_${feature_PP} 0\n")
           set(_define_item "\n#    if ${_cmake_feature_test_${compiler}_${feature}}\n#      define ${prefix_arg}_${feature_PP} 1\n#    else${_define_item}#    endif\n")
         endif()
-        set(${compiler_file_content} "${${compiler_file_content}}${_define_item}")
+        string(APPEND ${compiler_file_content} "${_define_item}")
       endforeach()
     endforeach()
     if(pp_if STREQUAL "elif")
@@ -503,10 +503,19 @@ function(write_compiler_detection_header
       if (feature STREQUAL cxx_static_assert)
         set(def_value "${prefix_arg}_STATIC_ASSERT(X)")
         set(def_value_msg "${prefix_arg}_STATIC_ASSERT_MSG(X, MSG)")
-        set(static_assert_struct "template<bool> struct ${prefix_arg}StaticAssert;\ntemplate<> struct ${prefix_arg}StaticAssert<true>{};\n")
-        set(def_standard "#    define ${def_value} static_assert(X, #X)\n#    define ${def_value_msg} static_assert(X, MSG)")
-        set(def_alternative "${static_assert_struct}#    define ${def_value} sizeof(${prefix_arg}StaticAssert<X>)\n#    define ${def_value_msg} sizeof(${prefix_arg}StaticAssert<X>)")
-        string(APPEND file_content "#  if defined(${def_name}) && ${def_name}\n${def_standard}\n#  else\n${def_alternative}\n#  endif\n\n")
+        set(def_fallback "enum { ${prefix_arg}_STATIC_ASSERT_JOIN(${prefix_arg}StaticAssertEnum, __LINE__) = sizeof(${prefix_arg}StaticAssert<X>) }")
+        string(APPEND file_content "#  if defined(${def_name}) && ${def_name}
+#    define ${def_value} static_assert(X, #X)
+#    define ${def_value_msg} static_assert(X, MSG)
+#  else
+#    define ${prefix_arg}_STATIC_ASSERT_JOIN(X, Y) ${prefix_arg}_STATIC_ASSERT_JOIN_IMPL(X, Y)
+#    define ${prefix_arg}_STATIC_ASSERT_JOIN_IMPL(X, Y) X##Y
+template<bool> struct ${prefix_arg}StaticAssert;
+template<> struct ${prefix_arg}StaticAssert<true>{};
+#    define ${def_value} ${def_fallback}
+#    define ${def_value_msg} ${def_fallback}
+#  endif
+\n")
       endif()
       if (feature STREQUAL cxx_alignas)
         set(def_value "${prefix_arg}_ALIGNAS(X)")
diff --git a/README.rst b/README.rst
index 4188ea0..d5acd4a 100644
--- a/README.rst
+++ b/README.rst
@@ -30,7 +30,13 @@ Building CMake
 Supported Platforms
 -------------------
 
-MS Windows, Mac OS X, Linux, FreeBSD, Solaris, HP-UX, IRIX, BeOS, QNX
+* Microsoft Windows
+* Apple macOS
+* Linux
+* FreeBSD
+* OpenBSD
+* Solaris
+* HP-UX
 
 Other UNIX-like operating systems may work too out of the box, if not
 it should not be a major problem to port CMake to this platform.
diff --git a/Source/.gitattributes b/Source/.gitattributes
index 1cec8a3..0f829a3 100644
--- a/Source/.gitattributes
+++ b/Source/.gitattributes
@@ -1,21 +1,2 @@
-/cmCommandArgumentLexer.cxx        generated
-/cmCommandArgumentLexer.h          generated
-/cmCommandArgumentParser.cxx       generated
-/cmCommandArgumentParserTokens.h   generated
-/cmDependsJavaLexer.cxx            generated
-/cmDependsJavaLexer.h              generated
-/cmDependsJavaParser.cxx           generated
-/cmDependsJavaParserTokens.h       generated
-/cmExprLexer.cxx                   generated
-/cmExprLexer.h                     generated
-/cmExprParser.cxx                  generated
-/cmExprParserTokens.h              generated
-/cmFortranLexer.cxx                generated
-/cmFortranLexer.h                  generated
-/cmFortranParser.cxx               generated
-/cmFortranParserTokens.h           generated
-/cmListFileLexer.c                 generated
-
 # Do not format third-party sources.
-/bindexplib.*                              -format.clang-format
 /kwsys/**                                  -format.clang-format
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 2835ee6..40403ca 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -78,6 +78,7 @@ configure_file(
 include_directories(
   "${CMake_BINARY_DIR}/Source"
   "${CMake_SOURCE_DIR}/Source"
+  "${CMake_SOURCE_DIR}/Source/LexerParser"
   ${CMAKE_ZLIB_INCLUDES}
   ${CMAKE_EXPAT_INCLUDES}
   ${CMAKE_TAR_INCLUDES}
@@ -88,61 +89,6 @@ include_directories(
 # let cmake know it is supposed to use it
 add_definitions(-DCMAKE_BUILD_WITH_CMAKE)
 
-option(CMAKE_REGENERATE_YACCLEX
-  "Regenerate YACC and LEXX files" OFF)
-mark_as_advanced(CMAKE_REGENERATE_YACCLEX)
-if(CMAKE_REGENERATE_YACCLEX)
-  set(parsersLexers cmFortran cmCommandArgument cmExpr)
-  find_program(YACC_EXECUTABLE
-    NAMES yacc bison
-    PATHS /usr/bin
-    DOC "Yacc or Bison executable")
-  find_program(FLEX_EXECUTABLE
-    NAMES flex
-    PATHS /usr/bin
-    DOC "Flex executable")
-  mark_as_advanced(YACC_EXECUTABLE FLEX_EXECUTABLE)
-  if(YACC_EXECUTABLE)
-    set(BISON_FLAGS)
-    if(YACC_EXECUTABLE MATCHES "bison")
-      set(BISON_FLAGS "--yacc")
-    endif()
-    set(yacc_files)
-    foreach(name ${parsersLexers})
-      set(src "${CMAKE_CURRENT_SOURCE_DIR}/${name}Parser.y")
-      set(dst "${CMAKE_CURRENT_BINARY_DIR}/${name}Parser.cxx")
-      set(hdr "${CMAKE_CURRENT_BINARY_DIR}/${name}ParserTokens.h")
-      add_custom_command(
-        OUTPUT "${dst}"
-        DEPENDS "${src}"
-        COMMAND
-        ${YACC_EXECUTABLE}
-        --name-prefix=${name}_yy --defines=${hdr} -o${dst} ${src}
-        )
-      set(yacc_files ${yacc_files} "${dst}")
-    endforeach()
-    add_custom_target(RerunYacc DEPENDS ${yacc_files})
-  endif()
-  if(FLEX_EXECUTABLE)
-    set(lex_files)
-    foreach(name ${parsersLexers})
-      set(src "${CMAKE_CURRENT_SOURCE_DIR}/${name}Lexer.in.l")
-      set(dst "${CMAKE_CURRENT_BINARY_DIR}/${name}Lexer.cxx")
-      set(hdr "${CMAKE_CURRENT_BINARY_DIR}/${name}Lexer.h")
-      add_custom_command(
-        OUTPUT "${dst}"
-        DEPENDS "${src}"
-        COMMAND
-        ${FLEX_EXECUTABLE}
-        --prefix=${name}_yy --header-file=${hdr} -o${dst} ${src}
-        )
-      set(lex_files ${lex_files} "${dst}")
-    endforeach()
-    add_custom_target(RerunLex DEPENDS ${lex_files})
-  endif()
-
-endif()
-
 # Check if we can build the ELF parser.
 if(CMAKE_USE_ELF_PARSER)
   set(ELF_SRCS cmELF.h cmELF.cxx)
@@ -157,14 +103,40 @@ endif()
 # Sources for CMakeLib
 #
 set(SRCS
+  # Lexers/Parsers
+  LexerParser/cmCommandArgumentLexer.cxx
+  LexerParser/cmCommandArgumentLexer.h
+  LexerParser/cmCommandArgumentLexer.in.l
+  LexerParser/cmCommandArgumentParser.cxx
+  LexerParser/cmCommandArgumentParserTokens.h
+  LexerParser/cmCommandArgumentParser.y
+  LexerParser/cmDependsJavaLexer.cxx
+  LexerParser/cmDependsJavaLexer.h
+  LexerParser/cmDependsJavaLexer.in.l
+  LexerParser/cmDependsJavaParser.cxx
+  LexerParser/cmDependsJavaParserTokens.h
+  LexerParser/cmDependsJavaParser.y
+  LexerParser/cmExprLexer.cxx
+  LexerParser/cmExprLexer.h
+  LexerParser/cmExprLexer.in.l
+  LexerParser/cmExprParser.cxx
+  LexerParser/cmExprParserTokens.h
+  LexerParser/cmExprParser.y
+  LexerParser/cmFortranLexer.cxx
+  LexerParser/cmFortranLexer.h
+  LexerParser/cmFortranLexer.in.l
+  LexerParser/cmFortranParser.cxx
+  LexerParser/cmFortranParserTokens.h
+  LexerParser/cmFortranParser.y
+  LexerParser/cmListFileLexer.c
+  LexerParser/cmListFileLexer.in.l
+
   cmArchiveWrite.cxx
   cmBase32.cxx
   cmCacheManager.cxx
   cmCacheManager.h
   cmCLocaleEnvironmentScope.h
   cmCLocaleEnvironmentScope.cxx
-  cmCommandArgumentLexer.cxx
-  cmCommandArgumentParser.cxx
   cmCommandArgumentParserHelper.cxx
   cmCommonTargetGenerator.cxx
   cmCommonTargetGenerator.h
@@ -196,8 +168,6 @@ set(SRCS
   cmDependsFortran.h
   cmDependsJava.cxx
   cmDependsJava.h
-  cmDependsJavaLexer.cxx
-  cmDependsJavaParser.cxx
   cmDependsJavaParserHelper.cxx
   cmDependsJavaParserHelper.h
   cmDocumentation.cxx
@@ -206,8 +176,6 @@ set(SRCS
   cmDynamicLoader.cxx
   cmDynamicLoader.h
   ${ELF_SRCS}
-  cmExprLexer.cxx
-  cmExprParser.cxx
   cmExprParserHelper.cxx
   cmExportBuildAndroidMKGenerator.h
   cmExportBuildAndroidMKGenerator.cxx
@@ -247,10 +215,6 @@ set(SRCS
   cmFilePathChecksum.h
   cmFileTimeComparison.cxx
   cmFileTimeComparison.h
-  cmFortranLexer.cxx
-  cmFortranLexer.h
-  cmFortranParser.cxx
-  cmFortranParser.h
   cmFortranParserImpl.cxx
   cmGeneratedFileStream.cxx
   cmGeneratorExpressionContext.cxx
@@ -302,7 +266,6 @@ set(SRCS
   cmLinkLineDeviceComputer.h
   cmListFileCache.cxx
   cmListFileCache.h
-  cmListFileLexer.c
   cmLocalCommonGenerator.cxx
   cmLocalCommonGenerator.h
   cmLocalGenerator.cxx
@@ -344,6 +307,8 @@ set(SRCS
   cmPropertyDefinitionMap.h
   cmPropertyMap.cxx
   cmPropertyMap.h
+  cmQtAutoGeneratorCommon.cxx
+  cmQtAutoGeneratorCommon.h
   cmQtAutoGeneratorInitializer.cxx
   cmQtAutoGeneratorInitializer.h
   cmQtAutoGenerators.cxx
@@ -381,6 +346,8 @@ set(SRCS
   cmVariableWatch.h
   cmVersion.cxx
   cmVersion.h
+  cmWorkingDirectory.cxx
+  cmWorkingDirectory.h
   cmXMLParser.cxx
   cmXMLParser.h
   cmXMLSafe.cxx
@@ -440,6 +407,8 @@ set(SRCS
   cmCreateTestSourceList.h
   cmDefinePropertyCommand.cxx
   cmDefinePropertyCommand.h
+  cmDisallowedCommand.cxx
+  cmDisallowedCommand.h
   cmEnableLanguageCommand.cxx
   cmEnableLanguageCommand.h
   cmEnableTestingCommand.cxx
@@ -637,6 +606,7 @@ if(APPLE)
   set(SRCS ${SRCS}
     cmXCodeObject.cxx
     cmXCode21Object.cxx
+    cmXCodeScheme.cxx
     cmGlobalXCodeGenerator.cxx
     cmGlobalXCodeGenerator.h
     cmLocalXCodeGenerator.cxx
@@ -882,6 +852,12 @@ add_library(CTestLib ${CTEST_SRCS})
 target_link_libraries(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES} ${CMAKE_XMLRPC_LIBRARIES})
 
 #
+# CPack
+#
+include_directories(
+  "${CMake_SOURCE_DIR}/Source/CPack"
+  )
+#
 # Sources for CPack
 #
 set(CPACK_SRCS
@@ -891,10 +867,6 @@ set(CPACK_SRCS
   CPack/cmCPackGenerator.cxx
   CPack/cmCPackLog.cxx
   CPack/cmCPackNSISGenerator.cxx
-  CPack/IFW/cmCPackIFWPackage.cxx
-  CPack/IFW/cmCPackIFWInstaller.cxx
-  CPack/IFW/cmCPackIFWRepository.cxx
-  CPack/IFW/cmCPackIFWGenerator.cxx
   CPack/cmCPackSTGZGenerator.cxx
   CPack/cmCPackTGZGenerator.cxx
   CPack/cmCPackTXZGenerator.cxx
@@ -903,6 +875,19 @@ set(CPACK_SRCS
   CPack/cmCPackZIPGenerator.cxx
   CPack/cmCPack7zGenerator.cxx
   )
+# CPack IFW generator
+set(CPACK_SRCS ${CPACK_SRCS}
+  CPack/IFW/cmCPackIFWCommon.cxx
+  CPack/IFW/cmCPackIFWCommon.h
+  CPack/IFW/cmCPackIFWGenerator.cxx
+  CPack/IFW/cmCPackIFWGenerator.h
+  CPack/IFW/cmCPackIFWInstaller.cxx
+  CPack/IFW/cmCPackIFWInstaller.h
+  CPack/IFW/cmCPackIFWPackage.cxx
+  CPack/IFW/cmCPackIFWPackage.h
+  CPack/IFW/cmCPackIFWRepository.cxx
+  CPack/IFW/cmCPackIFWRepository.h
+  )
 
 if(CYGWIN)
   set(CPACK_SRCS ${CPACK_SRCS}
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 65e7b5d..0f5201b 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
-set(CMake_VERSION_MINOR 8)
+set(CMake_VERSION_MINOR 9)
 set(CMake_VERSION_PATCH 0)
 #set(CMake_VERSION_RC 0)
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx
new file mode 100644
index 0000000..e8f05bd
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx
@@ -0,0 +1,137 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmCPackIFWCommon.h"
+
+#include "cmCPackGenerator.h"
+#include "cmCPackIFWGenerator.h"
+#include "cmCPackLog.h" // IWYU pragma: keep
+#include "cmSystemTools.h"
+#include "cmTimestamp.h"
+#include "cmVersionConfig.h"
+#include "cmXMLWriter.h"
+
+#include <sstream>
+#include <utility>
+#include <vector>
+
+cmCPackIFWCommon::cmCPackIFWCommon()
+  : Generator(CM_NULLPTR)
+{
+}
+
+const char* cmCPackIFWCommon::GetOption(const std::string& op) const
+{
+  return this->Generator ? this->Generator->cmCPackGenerator::GetOption(op)
+                         : CM_NULLPTR;
+}
+
+bool cmCPackIFWCommon::IsOn(const std::string& op) const
+{
+  return this->Generator ? this->Generator->cmCPackGenerator::IsOn(op) : false;
+}
+
+bool cmCPackIFWCommon::IsSetToOff(const std::string& op) const
+{
+  return this->Generator ? this->Generator->cmCPackGenerator::IsSetToOff(op)
+                         : false;
+}
+
+bool cmCPackIFWCommon::IsSetToEmpty(const std::string& op) const
+{
+  return this->Generator ? this->Generator->cmCPackGenerator::IsSetToEmpty(op)
+                         : false;
+}
+
+bool cmCPackIFWCommon::IsVersionLess(const char* version)
+{
+  if (!this->Generator) {
+    return false;
+  }
+
+  return cmSystemTools::VersionCompare(
+    cmSystemTools::OP_LESS, this->Generator->FrameworkVersion.data(), version);
+}
+
+bool cmCPackIFWCommon::IsVersionGreater(const char* version)
+{
+  if (!this->Generator) {
+    return false;
+  }
+
+  return cmSystemTools::VersionCompare(
+    cmSystemTools::OP_GREATER, this->Generator->FrameworkVersion.data(),
+    version);
+}
+
+bool cmCPackIFWCommon::IsVersionEqual(const char* version)
+{
+  if (!this->Generator) {
+    return false;
+  }
+
+  return cmSystemTools::VersionCompare(
+    cmSystemTools::OP_EQUAL, this->Generator->FrameworkVersion.data(),
+    version);
+}
+
+void cmCPackIFWCommon::ExpandListArgument(
+  const std::string& arg, std::map<std::string, std::string>& argsOut)
+{
+  std::vector<std::string> args;
+  cmSystemTools::ExpandListArgument(arg, args, false);
+  if (args.empty()) {
+    return;
+  }
+
+  std::size_t i = 0;
+  std::size_t c = args.size();
+  if (c % 2) {
+    argsOut[""] = args[i];
+    ++i;
+  }
+
+  --c;
+  for (; i < c; i += 2) {
+    argsOut[args[i]] = args[i + 1];
+  }
+}
+
+void cmCPackIFWCommon::ExpandListArgument(
+  const std::string& arg, std::multimap<std::string, std::string>& argsOut)
+{
+  std::vector<std::string> args;
+  cmSystemTools::ExpandListArgument(arg, args, false);
+  if (args.empty()) {
+    return;
+  }
+
+  std::size_t i = 0;
+  std::size_t c = args.size();
+  if (c % 2) {
+    argsOut.insert(std::pair<std::string, std::string>("", args[i]));
+    ++i;
+  }
+
+  --c;
+  for (; i < c; i += 2) {
+    argsOut.insert(std::pair<std::string, std::string>(args[i], args[i + 1]));
+  }
+}
+
+void cmCPackIFWCommon::WriteGeneratedByToStrim(cmXMLWriter& xout)
+{
+  if (!this->Generator) {
+    return;
+  }
+
+  std::ostringstream comment;
+  comment << "Generated by CPack " << CMake_VERSION << " IFW generator "
+          << "for QtIFW ";
+  if (this->IsVersionEqual("1.9.9")) {
+    comment << "less 2.0";
+  } else {
+    comment << this->Generator->FrameworkVersion;
+  }
+  comment << " tools at " << cmTimestamp().CurrentTime("", true);
+  xout.Comment(comment.str().c_str());
+}
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.h b/Source/CPack/IFW/cmCPackIFWCommon.h
new file mode 100644
index 0000000..354d849
--- /dev/null
+++ b/Source/CPack/IFW/cmCPackIFWCommon.h
@@ -0,0 +1,81 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmCPackIFWCommon_h
+#define cmCPackIFWCommon_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+
+class cmCPackIFWGenerator;
+class cmXMLWriter;
+
+/** \class cmCPackIFWCommon
+ * \brief A base class for CPack IFW generator implementation subclasses
+ */
+class cmCPackIFWCommon
+{
+public:
+  // Constructor
+
+  /**
+   * Construct Part
+   */
+  cmCPackIFWCommon();
+
+public:
+  // Internal implementation
+
+  const char* 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;
+
+  /**
+   * Compare \a version with QtIFW framework version
+   */
+  bool IsVersionLess(const char* version);
+
+  /**
+   * Compare \a version with QtIFW framework version
+   */
+  bool IsVersionGreater(const char* version);
+
+  /**
+   * Compare \a version with QtIFW framework version
+   */
+  bool IsVersionEqual(const char* version);
+
+  /** Expand the list argument containing the map of the key-value pairs.
+   *  If the number of elements is odd, then the first value is used as the
+   *  default value with an empty key.
+   *  Any values with the same keys will be permanently overwritten.
+   */
+  static void ExpandListArgument(const std::string& arg,
+                                 std::map<std::string, std::string>& argsOut);
+
+  /** Expand the list argument containing the multimap of the key-value pairs.
+   *  If the number of elements is odd, then the first value is used as the
+   *  default value with an empty key.
+   */
+  static void ExpandListArgument(
+    const std::string& arg, std::multimap<std::string, std::string>& argsOut);
+
+  cmCPackIFWGenerator* Generator;
+
+protected:
+  void WriteGeneratedByToStrim(cmXMLWriter& xout);
+};
+
+#define cmCPackIFWLogger(logType, msg)                                        \
+  do {                                                                        \
+    std::ostringstream cmCPackLog_msg;                                        \
+    cmCPackLog_msg << msg;                                                    \
+    if (Generator) {                                                          \
+      Generator->Logger->Log(cmCPackLog::LOG_##logType, __FILE__, __LINE__,   \
+                             cmCPackLog_msg.str().c_str());                   \
+    }                                                                         \
+  } while (false)
+
+#endif // cmCPackIFWCommon_h
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
index ee46d86..226ea0a 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -2,94 +2,76 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackIFWGenerator.h"
 
-#include "CPack/cmCPackComponentGroup.h"
-#include "CPack/cmCPackGenerator.h"
-#include "CPack/cmCPackLog.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
+#include "cmCPackIFWCommon.h"
 #include "cmCPackIFWInstaller.h"
 #include "cmCPackIFWPackage.h"
 #include "cmCPackIFWRepository.h"
+#include "cmCPackLog.h" // IWYU pragma: keep
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
-#include "cmTimestamp.h"
-#include "cmVersionConfig.h"
-#include "cmXMLWriter.h"
 
 #include <sstream>
 #include <utility>
 
 cmCPackIFWGenerator::cmCPackIFWGenerator()
 {
+  this->Generator = this;
 }
 
 cmCPackIFWGenerator::~cmCPackIFWGenerator()
 {
 }
 
-bool cmCPackIFWGenerator::IsVersionLess(const char* version)
-{
-  return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
-                                       FrameworkVersion.data(), version);
-}
-
-bool cmCPackIFWGenerator::IsVersionGreater(const char* version)
-{
-  return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
-                                       FrameworkVersion.data(), version);
-}
-
-bool cmCPackIFWGenerator::IsVersionEqual(const char* version)
-{
-  return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
-                                       FrameworkVersion.data(), version);
-}
-
 int cmCPackIFWGenerator::PackageFiles()
 {
-  cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl);
+  cmCPackIFWLogger(OUTPUT, "- Configuration" << std::endl);
 
   // Installer configuragion
-  Installer.GenerateInstallerFile();
+  this->Installer.GenerateInstallerFile();
 
   // Packages configuration
-  Installer.GeneratePackageFiles();
+  this->Installer.GeneratePackageFiles();
 
   std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
   std::string ifwTmpFile = ifwTLD;
   ifwTmpFile += "/IFWOutput.log";
 
   // Run repogen
-  if (!Installer.RemoteRepositories.empty()) {
-    std::string ifwCmd = RepoGen;
+  if (!this->Installer.RemoteRepositories.empty()) {
+    std::string ifwCmd = this->RepoGen;
 
-    if (IsVersionLess("2.0.0")) {
+    if (this->IsVersionLess("2.0.0")) {
       ifwCmd += " -c " + this->toplevel + "/config/config.xml";
     }
 
     ifwCmd += " -p " + this->toplevel + "/packages";
 
-    if (!PkgsDirsVector.empty()) {
-      for (std::vector<std::string>::iterator it = PkgsDirsVector.begin();
-           it != PkgsDirsVector.end(); ++it) {
+    if (!this->PkgsDirsVector.empty()) {
+      for (std::vector<std::string>::iterator it =
+             this->PkgsDirsVector.begin();
+           it != this->PkgsDirsVector.end(); ++it) {
         ifwCmd += " -p " + *it;
       }
     }
 
-    if (!OnlineOnly && !DownloadedPackages.empty()) {
+    if (!this->OnlineOnly && !this->DownloadedPackages.empty()) {
       ifwCmd += " -i ";
-      std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin();
+      std::set<cmCPackIFWPackage*>::iterator it =
+        this->DownloadedPackages.begin();
       ifwCmd += (*it)->Name;
       ++it;
-      while (it != DownloadedPackages.end()) {
+      while (it != this->DownloadedPackages.end()) {
         ifwCmd += "," + (*it)->Name;
         ++it;
       }
     }
     ifwCmd += " " + this->toplevel + "/repository";
-    cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl);
+    cmCPackIFWLogger(VERBOSE, "Execute: " << ifwCmd << std::endl);
     std::string output;
     int retVal = 1;
-    cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate repository"
-                    << std::endl);
+    cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl);
     bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
                                                &output, &retVal, CM_NULLPTR,
                                                this->GeneratorVerbose, 0);
@@ -98,36 +80,39 @@ int cmCPackIFWGenerator::PackageFiles()
       ofs << "# Run command: " << ifwCmd << std::endl
           << "# Output:" << std::endl
           << output << std::endl;
-      cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: "
-                      << ifwCmd << std::endl
-                      << "Please check " << ifwTmpFile << " for errors"
-                      << std::endl);
+      cmCPackIFWLogger(ERROR, "Problem running IFW command: "
+                         << ifwCmd << std::endl
+                         << "Please check " << ifwTmpFile << " for errors"
+                         << std::endl);
       return 0;
     }
 
-    if (!Repository.RepositoryUpdate.empty() &&
-        !Repository.PatchUpdatesXml()) {
-      cmCPackLogger(cmCPackLog::LOG_WARNING, "Problem patch IFW \"Updates\" "
-                      << "file: " << this->toplevel + "/repository/Updates.xml"
-                      << std::endl);
+    if (!this->Repository.RepositoryUpdate.empty() &&
+        !this->Repository.PatchUpdatesXml()) {
+      cmCPackIFWLogger(WARNING, "Problem patch IFW \"Updates\" "
+                         << "file: "
+                         << this->toplevel + "/repository/Updates.xml"
+                         << std::endl);
     }
 
-    cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- repository: "
-                    << this->toplevel << "/repository generated" << std::endl);
+    cmCPackIFWLogger(OUTPUT, "- repository: " << this->toplevel
+                                              << "/repository generated"
+                                              << std::endl);
   }
 
   // Run binary creator
   {
-    std::string ifwCmd = BinCreator;
+    std::string ifwCmd = this->BinCreator;
     ifwCmd += " -c " + this->toplevel + "/config/config.xml";
 
-    if (!Installer.Resources.empty()) {
+    if (!this->Installer.Resources.empty()) {
       ifwCmd += " -r ";
-      std::vector<std::string>::iterator it = Installer.Resources.begin();
+      std::vector<std::string>::iterator it =
+        this->Installer.Resources.begin();
       std::string path = this->toplevel + "/resources/";
       ifwCmd += path + *it;
       ++it;
-      while (it != Installer.Resources.end()) {
+      while (it != this->Installer.Resources.end()) {
         ifwCmd += "," + path + *it;
         ++it;
       }
@@ -135,52 +120,55 @@ int cmCPackIFWGenerator::PackageFiles()
 
     ifwCmd += " -p " + this->toplevel + "/packages";
 
-    if (!PkgsDirsVector.empty()) {
-      for (std::vector<std::string>::iterator it = PkgsDirsVector.begin();
-           it != PkgsDirsVector.end(); ++it) {
+    if (!this->PkgsDirsVector.empty()) {
+      for (std::vector<std::string>::iterator it =
+             this->PkgsDirsVector.begin();
+           it != this->PkgsDirsVector.end(); ++it) {
         ifwCmd += " -p " + *it;
       }
     }
 
-    if (OnlineOnly) {
+    if (this->OnlineOnly) {
       ifwCmd += " --online-only";
-    } else if (!DownloadedPackages.empty() &&
-               !Installer.RemoteRepositories.empty()) {
+    } else if (!this->DownloadedPackages.empty() &&
+               !this->Installer.RemoteRepositories.empty()) {
       ifwCmd += " -e ";
-      std::set<cmCPackIFWPackage*>::iterator it = DownloadedPackages.begin();
+      std::set<cmCPackIFWPackage*>::iterator it =
+        this->DownloadedPackages.begin();
       ifwCmd += (*it)->Name;
       ++it;
-      while (it != DownloadedPackages.end()) {
+      while (it != this->DownloadedPackages.end()) {
         ifwCmd += "," + (*it)->Name;
         ++it;
       }
-    } else if (!DependentPackages.empty()) {
+    } else if (!this->DependentPackages.empty()) {
       ifwCmd += " -i ";
       // Binary
-      std::set<cmCPackIFWPackage*>::iterator bit = BinaryPackages.begin();
-      while (bit != BinaryPackages.end()) {
+      std::set<cmCPackIFWPackage*>::iterator bit =
+        this->BinaryPackages.begin();
+      while (bit != this->BinaryPackages.end()) {
         ifwCmd += (*bit)->Name + ",";
         ++bit;
       }
       // Depend
-      DependenceMap::iterator it = DependentPackages.begin();
+      DependenceMap::iterator it = this->DependentPackages.begin();
       ifwCmd += it->second.Name;
       ++it;
-      while (it != DependentPackages.end()) {
+      while (it != this->DependentPackages.end()) {
         ifwCmd += "," + it->second.Name;
         ++it;
       }
     }
     // TODO: set correct name for multipackages
     if (!this->packageFileNames.empty()) {
-      ifwCmd += " " + packageFileNames[0];
+      ifwCmd += " " + this->packageFileNames[0];
     } else {
       ifwCmd += " installer";
     }
-    cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ifwCmd << std::endl);
+    cmCPackIFWLogger(VERBOSE, "Execute: " << ifwCmd << std::endl);
     std::string output;
     int retVal = 1;
-    cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Generate package" << std::endl);
+    cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl);
     bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
                                                &output, &retVal, CM_NULLPTR,
                                                this->GeneratorVerbose, 0);
@@ -189,10 +177,10 @@ int cmCPackIFWGenerator::PackageFiles()
       ofs << "# Run command: " << ifwCmd << std::endl
           << "# Output:" << std::endl
           << output << std::endl;
-      cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running IFW command: "
-                      << ifwCmd << std::endl
-                      << "Please check " << ifwTmpFile << " for errors"
-                      << std::endl);
+      cmCPackIFWLogger(ERROR, "Problem running IFW command: "
+                         << ifwCmd << std::endl
+                         << "Please check " << ifwTmpFile << " for errors"
+                         << std::endl);
       return 0;
     }
   }
@@ -202,12 +190,12 @@ int cmCPackIFWGenerator::PackageFiles()
 
 const char* cmCPackIFWGenerator::GetPackagingInstallPrefix()
 {
-  const char* defPrefix = cmCPackGenerator::GetPackagingInstallPrefix();
+  const char* defPrefix = this->cmCPackGenerator::GetPackagingInstallPrefix();
 
   std::string tmpPref = defPrefix ? defPrefix : "";
 
   if (this->Components.empty()) {
-    tmpPref += "packages/" + GetRootPackageName() + "/data";
+    tmpPref += "packages/" + this->GetRootPackageName() + "/data";
   }
 
   this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str());
@@ -217,7 +205,7 @@ const char* cmCPackIFWGenerator::GetPackagingInstallPrefix()
 
 const char* cmCPackIFWGenerator::GetOutputExtension()
 {
-  return ExecutableSuffix.c_str();
+  return this->ExecutableSuffix.c_str();
 }
 
 int cmCPackIFWGenerator::InitializeInternal()
@@ -237,16 +225,15 @@ int cmCPackIFWGenerator::InitializeInternal()
 
   const char* BinCreatorStr = this->GetOption(BinCreatorOpt);
   if (!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) {
-    BinCreator = "";
+    this->BinCreator = "";
   } else {
-    BinCreator = BinCreatorStr;
+    this->BinCreator = BinCreatorStr;
   }
 
-  if (BinCreator.empty()) {
-    cmCPackLogger(cmCPackLog::LOG_ERROR,
-                  "Cannot find QtIFW compiler \"binarycreator\": "
-                  "likely it is not installed, or not in your PATH"
-                    << std::endl);
+  if (this->BinCreator.empty()) {
+    cmCPackIFWLogger(ERROR, "Cannot find QtIFW compiler \"binarycreator\": "
+                            "likely it is not installed, or not in your PATH"
+                       << std::endl);
     return 0;
   }
 
@@ -254,39 +241,40 @@ int cmCPackIFWGenerator::InitializeInternal()
 
   const char* RepoGenStr = this->GetOption(RepoGenOpt);
   if (!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) {
-    RepoGen = "";
+    this->RepoGen = "";
   } else {
-    RepoGen = RepoGenStr;
+    this->RepoGen = RepoGenStr;
   }
 
   // Framework version
   if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) {
-    FrameworkVersion = FrameworkVersionSrt;
+    this->FrameworkVersion = FrameworkVersionSrt;
   } else {
-    FrameworkVersion = "1.9.9";
+    this->FrameworkVersion = "1.9.9";
   }
 
   // Variables that Change Behavior
 
   // Resolve duplicate names
-  ResolveDuplicateNames = this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES");
+  this->ResolveDuplicateNames =
+    this->IsOn("CPACK_IFW_RESOLVE_DUPLICATE_NAMES");
 
   // Additional packages dirs
-  PkgsDirsVector.clear();
+  this->PkgsDirsVector.clear();
   if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) {
-    cmSystemTools::ExpandListArgument(dirs, PkgsDirsVector);
+    cmSystemTools::ExpandListArgument(dirs, this->PkgsDirsVector);
   }
 
   // Installer
-  Installer.Generator = this;
-  Installer.ConfigureFromOptions();
+  this->Installer.Generator = this;
+  this->Installer.ConfigureFromOptions();
 
   // Repository
-  Repository.Generator = this;
-  Repository.Name = "Unspecified";
+  this->Repository.Generator = this;
+  this->Repository.Name = "Unspecified";
   if (const char* site = this->GetOption("CPACK_DOWNLOAD_SITE")) {
-    Repository.Url = site;
-    Installer.RemoteRepositories.push_back(&Repository);
+    this->Repository.Url = site;
+    this->Installer.RemoteRepositories.push_back(&this->Repository);
   }
 
   // Repositories
@@ -295,38 +283,38 @@ int cmCPackIFWGenerator::InitializeInternal()
     cmSystemTools::ExpandListArgument(RepoAllStr, RepoAllVector);
     for (std::vector<std::string>::iterator rit = RepoAllVector.begin();
          rit != RepoAllVector.end(); ++rit) {
-      GetRepository(*rit);
+      this->GetRepository(*rit);
     }
   }
 
   if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) {
-    OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll);
+    this->OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll);
   } else if (const char* cpackDownloadAll =
                this->GetOption("CPACK_DOWNLOAD_ALL")) {
-    OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll);
+    this->OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll);
   } else {
-    OnlineOnly = false;
+    this->OnlineOnly = false;
   }
 
-  if (!Installer.RemoteRepositories.empty() && RepoGen.empty()) {
-    cmCPackLogger(cmCPackLog::LOG_ERROR,
-                  "Cannot find QtIFW repository generator \"repogen\": "
-                  "likely it is not installed, or not in your PATH"
-                    << std::endl);
+  if (!this->Installer.RemoteRepositories.empty() && this->RepoGen.empty()) {
+    cmCPackIFWLogger(ERROR,
+                     "Cannot find QtIFW repository generator \"repogen\": "
+                     "likely it is not installed, or not in your PATH"
+                       << std::endl);
     return 0;
   }
 
   // Executable suffix
   if (const char* optExeSuffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX")) {
-    ExecutableSuffix = optExeSuffix;
-    if (ExecutableSuffix.empty()) {
+    this->ExecutableSuffix = optExeSuffix;
+    if (this->ExecutableSuffix.empty()) {
       std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME"));
       if (sysName == "Linux") {
-        ExecutableSuffix = ".run";
+        this->ExecutableSuffix = ".run";
       }
     }
   } else {
-    ExecutableSuffix = cmCPackGenerator::GetOutputExtension();
+    this->ExecutableSuffix = this->cmCPackGenerator::GetOutputExtension();
   }
 
   return this->Superclass::InitializeInternal();
@@ -338,52 +326,53 @@ std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix(
   const std::string prefix = "packages/";
   const std::string suffix = "/data";
 
-  if (componentPackageMethod == ONE_PACKAGE) {
-    return std::string(prefix + GetRootPackageName() + suffix);
+  if (this->componentPackageMethod == this->ONE_PACKAGE) {
+    return std::string(prefix + this->GetRootPackageName() + suffix);
   }
 
-  return prefix + GetComponentPackageName(&Components[componentName]) + suffix;
+  return prefix +
+    this->GetComponentPackageName(&this->Components[componentName]) + suffix;
 }
 
 cmCPackComponent* cmCPackIFWGenerator::GetComponent(
   const std::string& projectName, const std::string& componentName)
 {
-  ComponentsMap::iterator cit = Components.find(componentName);
-  if (cit != Components.end()) {
+  ComponentsMap::iterator cit = this->Components.find(componentName);
+  if (cit != this->Components.end()) {
     return &(cit->second);
   }
 
   cmCPackComponent* component =
-    cmCPackGenerator::GetComponent(projectName, componentName);
+    this->cmCPackGenerator::GetComponent(projectName, componentName);
   if (!component) {
     return component;
   }
 
-  std::string name = GetComponentPackageName(component);
-  PackagesMap::iterator pit = Packages.find(name);
-  if (pit != Packages.end()) {
+  std::string name = this->GetComponentPackageName(component);
+  PackagesMap::iterator pit = this->Packages.find(name);
+  if (pit != this->Packages.end()) {
     return component;
   }
 
-  cmCPackIFWPackage* package = &Packages[name];
+  cmCPackIFWPackage* package = &this->Packages[name];
   package->Name = name;
   package->Generator = this;
   if (package->ConfigureFromComponent(component)) {
-    package->Installer = &Installer;
-    Installer.Packages.insert(
+    package->Installer = &this->Installer;
+    this->Installer.Packages.insert(
       std::pair<std::string, cmCPackIFWPackage*>(name, package));
-    ComponentPackages.insert(
+    this->ComponentPackages.insert(
       std::pair<cmCPackComponent*, cmCPackIFWPackage*>(component, package));
     if (component->IsDownloaded) {
-      DownloadedPackages.insert(package);
+      this->DownloadedPackages.insert(package);
     } else {
-      BinaryPackages.insert(package);
+      this->BinaryPackages.insert(package);
     }
   } else {
-    Packages.erase(name);
-    cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \""
-                    << name << "\" for component \"" << component->Name << "\""
-                    << std::endl);
+    this->Packages.erase(name);
+    cmCPackIFWLogger(ERROR, "Cannot configure package \""
+                       << name << "\" for component \"" << component->Name
+                       << "\"" << std::endl);
   }
 
   return component;
@@ -393,32 +382,32 @@ cmCPackComponentGroup* cmCPackIFWGenerator::GetComponentGroup(
   const std::string& projectName, const std::string& groupName)
 {
   cmCPackComponentGroup* group =
-    cmCPackGenerator::GetComponentGroup(projectName, groupName);
+    this->cmCPackGenerator::GetComponentGroup(projectName, groupName);
   if (!group) {
     return group;
   }
 
-  std::string name = GetGroupPackageName(group);
-  PackagesMap::iterator pit = Packages.find(name);
-  if (pit != Packages.end()) {
+  std::string name = this->GetGroupPackageName(group);
+  PackagesMap::iterator pit = this->Packages.find(name);
+  if (pit != this->Packages.end()) {
     return group;
   }
 
-  cmCPackIFWPackage* package = &Packages[name];
+  cmCPackIFWPackage* package = &this->Packages[name];
   package->Name = name;
   package->Generator = this;
   if (package->ConfigureFromGroup(group)) {
-    package->Installer = &Installer;
-    Installer.Packages.insert(
+    package->Installer = &this->Installer;
+    this->Installer.Packages.insert(
       std::pair<std::string, cmCPackIFWPackage*>(name, package));
-    GroupPackages.insert(
+    this->GroupPackages.insert(
       std::pair<cmCPackComponentGroup*, cmCPackIFWPackage*>(group, package));
-    BinaryPackages.insert(package);
+    this->BinaryPackages.insert(package);
   } else {
-    Packages.erase(name);
-    cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot configure package \""
-                    << name << "\" for component group \"" << group->Name
-                    << "\"" << std::endl);
+    this->Packages.erase(name);
+    cmCPackIFWLogger(ERROR, "Cannot configure package \""
+                       << name << "\" for component group \"" << group->Name
+                       << "\"" << std::endl);
   }
   return group;
 }
@@ -441,7 +430,7 @@ bool cmCPackIFWGenerator::SupportsComponentInstallation() const
 
 bool cmCPackIFWGenerator::IsOnePackage() const
 {
-  return componentPackageMethod == ONE_PACKAGE;
+  return this->componentPackageMethod == cmCPackGenerator::ONE_PACKAGE;
 }
 
 std::string cmCPackIFWGenerator::GetRootPackageName()
@@ -474,16 +463,16 @@ std::string cmCPackIFWGenerator::GetGroupPackageName(
   if (!group) {
     return name;
   }
-  if (cmCPackIFWPackage* package = GetGroupPackage(group)) {
+  if (cmCPackIFWPackage* package = this->GetGroupPackage(group)) {
     return package->Name;
   }
   const char* option =
-    GetOption("CPACK_IFW_COMPONENT_GROUP_" +
-              cmsys::SystemTools::UpperCase(group->Name) + "_NAME");
+    this->GetOption("CPACK_IFW_COMPONENT_GROUP_" +
+                    cmsys::SystemTools::UpperCase(group->Name) + "_NAME");
   name = option ? option : group->Name;
   if (group->ParentGroup) {
-    cmCPackIFWPackage* package = GetGroupPackage(group->ParentGroup);
-    bool dot = !ResolveDuplicateNames;
+    cmCPackIFWPackage* package = this->GetGroupPackage(group->ParentGroup);
+    bool dot = !this->ResolveDuplicateNames;
     if (dot && name.substr(0, package->Name.size()) == package->Name) {
       dot = false;
     }
@@ -501,20 +490,21 @@ std::string cmCPackIFWGenerator::GetComponentPackageName(
   if (!component) {
     return name;
   }
-  if (cmCPackIFWPackage* package = GetComponentPackage(component)) {
+  if (cmCPackIFWPackage* package = this->GetComponentPackage(component)) {
     return package->Name;
   }
   std::string prefix = "CPACK_IFW_COMPONENT_" +
     cmsys::SystemTools::UpperCase(component->Name) + "_";
-  const char* option = GetOption(prefix + "NAME");
+  const char* option = this->GetOption(prefix + "NAME");
   name = option ? option : component->Name;
   if (component->Group) {
-    cmCPackIFWPackage* package = GetGroupPackage(component->Group);
-    if ((componentPackageMethod == ONE_PACKAGE_PER_GROUP) ||
-        IsOn(prefix + "COMMON")) {
+    cmCPackIFWPackage* package = this->GetGroupPackage(component->Group);
+    if ((this->componentPackageMethod ==
+         cmCPackGenerator::ONE_PACKAGE_PER_GROUP) ||
+        this->IsOn(prefix + "COMMON")) {
       return package->Name;
     }
-    bool dot = !ResolveDuplicateNames;
+    bool dot = !this->ResolveDuplicateNames;
     if (dot && name.substr(0, package->Name.size()) == package->Name) {
       dot = false;
     }
@@ -529,56 +519,42 @@ cmCPackIFWPackage* cmCPackIFWGenerator::GetGroupPackage(
   cmCPackComponentGroup* group) const
 {
   std::map<cmCPackComponentGroup*, cmCPackIFWPackage*>::const_iterator pit =
-    GroupPackages.find(group);
-  return pit != GroupPackages.end() ? pit->second : CM_NULLPTR;
+    this->GroupPackages.find(group);
+  return pit != this->GroupPackages.end() ? pit->second : CM_NULLPTR;
 }
 
 cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage(
   cmCPackComponent* component) const
 {
   std::map<cmCPackComponent*, cmCPackIFWPackage*>::const_iterator pit =
-    ComponentPackages.find(component);
-  return pit != ComponentPackages.end() ? pit->second : CM_NULLPTR;
+    this->ComponentPackages.find(component);
+  return pit != this->ComponentPackages.end() ? pit->second : CM_NULLPTR;
 }
 
 cmCPackIFWRepository* cmCPackIFWGenerator::GetRepository(
   const std::string& repositoryName)
 {
-  RepositoriesMap::iterator rit = Repositories.find(repositoryName);
-  if (rit != Repositories.end()) {
+  RepositoriesMap::iterator rit = this->Repositories.find(repositoryName);
+  if (rit != this->Repositories.end()) {
     return &(rit->second);
   }
 
-  cmCPackIFWRepository* repository = &Repositories[repositoryName];
+  cmCPackIFWRepository* repository = &this->Repositories[repositoryName];
   repository->Name = repositoryName;
   repository->Generator = this;
   if (repository->ConfigureFromOptions()) {
     if (repository->Update == cmCPackIFWRepository::None) {
-      Installer.RemoteRepositories.push_back(repository);
+      this->Installer.RemoteRepositories.push_back(repository);
     } else {
-      Repository.RepositoryUpdate.push_back(repository);
+      this->Repository.RepositoryUpdate.push_back(repository);
     }
   } else {
-    Repositories.erase(repositoryName);
+    this->Repositories.erase(repositoryName);
     repository = CM_NULLPTR;
-    cmCPackLogger(cmCPackLog::LOG_WARNING, "Invalid repository \""
-                    << repositoryName << "\""
-                    << " configuration. Repository will be skipped."
-                    << std::endl);
+    cmCPackIFWLogger(WARNING, "Invalid repository \""
+                       << repositoryName << "\""
+                       << " configuration. Repository will be skipped."
+                       << std::endl);
   }
   return repository;
 }
-
-void cmCPackIFWGenerator::WriteGeneratedByToStrim(cmXMLWriter& xout)
-{
-  std::ostringstream comment;
-  comment << "Generated by CPack " << CMake_VERSION << " IFW generator "
-          << "for QtIFW ";
-  if (IsVersionLess("2.0")) {
-    comment << "less 2.0";
-  } else {
-    comment << FrameworkVersion;
-  }
-  comment << " tools at " << cmTimestamp().CurrentTime("", true);
-  xout.Comment(comment.str().c_str());
-}
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h
index d656063..8348cee 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.h
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.h
@@ -3,10 +3,11 @@
 #ifndef cmCPackIFWGenerator_h
 #define cmCPackIFWGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h" // IWYU pragma: keep
 
-#include "CPack/cmCPackComponentGroup.h"
-#include "CPack/cmCPackGenerator.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackGenerator.h"
+#include "cmCPackIFWCommon.h"
 #include "cmCPackIFWInstaller.h"
 #include "cmCPackIFWPackage.h"
 #include "cmCPackIFWRepository.h"
@@ -16,14 +17,12 @@
 #include <string>
 #include <vector>
 
-class cmXMLWriter;
-
 /** \class cmCPackIFWGenerator
  * \brief A generator for Qt Installer Framework tools
  *
  * http://qt-project.org/doc/qtinstallerframework/index.html
  */
-class cmCPackIFWGenerator : public cmCPackGenerator
+class cmCPackIFWGenerator : public cmCPackGenerator, public cmCPackIFWCommon
 {
 public:
   cmCPackTypeMacro(cmCPackIFWGenerator, cmCPackGenerator);
@@ -35,6 +34,11 @@ public:
   typedef std::map<std::string, cmCPackIFWPackage::DependenceStruct>
     DependenceMap;
 
+  using cmCPackIFWCommon::GetOption;
+  using cmCPackIFWCommon::IsOn;
+  using cmCPackIFWCommon::IsSetToOff;
+  using cmCPackIFWCommon::IsSetToEmpty;
+
   /**
    * Construct IFW generator
    */
@@ -45,21 +49,6 @@ public:
    */
   ~cmCPackIFWGenerator() CM_OVERRIDE;
 
-  /**
-   * Compare \a version with QtIFW framework version
-   */
-  bool IsVersionLess(const char* version);
-
-  /**
-   * Compare \a version with QtIFW framework version
-   */
-  bool IsVersionGreater(const char* version);
-
-  /**
-   * Compare \a version with QtIFW framework version
-   */
-  bool IsVersionEqual(const char* version);
-
 protected:
   // cmCPackGenerator reimplementation
 
@@ -124,12 +113,11 @@ protected:
 
   cmCPackIFWRepository* GetRepository(const std::string& repositoryName);
 
-  void WriteGeneratedByToStrim(cmXMLWriter& xout);
-
 protected:
   // Data
 
   friend class cmCPackIFWPackage;
+  friend class cmCPackIFWCommon;
   friend class cmCPackIFWInstaller;
   friend class cmCPackIFWRepository;
 
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
index d8bafee..288e924 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -2,69 +2,29 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackIFWInstaller.h"
 
-#include <cmConfigure.h>
-#include <sstream>
-#include <stddef.h>
-#include <utility>
-
-#include "CPack/cmCPackGenerator.h"
-#include "CPack/cmCPackLog.h"
+#include "cmCPackIFWCommon.h"
 #include "cmCPackIFWGenerator.h"
 #include "cmCPackIFWPackage.h"
 #include "cmCPackIFWRepository.h"
+#include "cmCPackLog.h" // IWYU pragma: keep
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 #include "cmXMLWriter.h"
 
-#ifdef cmCPackLogger
-#undef cmCPackLogger
-#endif
-#define cmCPackLogger(logType, msg)                                           \
-  do {                                                                        \
-    std::ostringstream cmCPackLog_msg;                                        \
-    cmCPackLog_msg << msg;                                                    \
-    if (Generator) {                                                          \
-      Generator->Logger->Log(logType, __FILE__, __LINE__,                     \
-                             cmCPackLog_msg.str().c_str());                   \
-    }                                                                         \
-  } while (false)
+#include <sstream>
+#include <stddef.h>
+#include <utility>
 
 cmCPackIFWInstaller::cmCPackIFWInstaller()
-  : Generator(CM_NULLPTR)
-{
-}
-
-const char* cmCPackIFWInstaller::GetOption(const std::string& op) const
-{
-  return Generator ? Generator->GetOption(op) : CM_NULLPTR;
-}
-
-bool cmCPackIFWInstaller::IsOn(const std::string& op) const
-{
-  return Generator ? Generator->IsOn(op) : false;
-}
-
-bool cmCPackIFWInstaller::IsVersionLess(const char* version)
-{
-  return Generator ? Generator->IsVersionLess(version) : false;
-}
-
-bool cmCPackIFWInstaller::IsVersionGreater(const char* version)
 {
-  return Generator ? Generator->IsVersionGreater(version) : false;
-}
-
-bool cmCPackIFWInstaller::IsVersionEqual(const char* version)
-{
-  return Generator ? Generator->IsVersionEqual(version) : false;
 }
 
 void cmCPackIFWInstaller::printSkippedOptionWarning(
   const std::string& optionName, const std::string& optionValue)
 {
-  cmCPackLogger(
-    cmCPackLog::LOG_WARNING, "Option "
+  cmCPackIFWLogger(
+    WARNING, "Option "
       << optionName << " is set to \"" << optionValue
       << "\" but will be skipped because the specified file does not exist."
       << std::endl);
@@ -75,198 +35,199 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
   // Name;
   if (const char* optIFW_PACKAGE_NAME =
         this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
-    Name = optIFW_PACKAGE_NAME;
+    this->Name = optIFW_PACKAGE_NAME;
   } else if (const char* optPACKAGE_NAME =
                this->GetOption("CPACK_PACKAGE_NAME")) {
-    Name = optPACKAGE_NAME;
+    this->Name = optPACKAGE_NAME;
   } else {
-    Name = "Your package";
+    this->Name = "Your package";
   }
 
   // Title;
   if (const char* optIFW_PACKAGE_TITLE =
-        GetOption("CPACK_IFW_PACKAGE_TITLE")) {
-    Title = optIFW_PACKAGE_TITLE;
+        this->GetOption("CPACK_IFW_PACKAGE_TITLE")) {
+    this->Title = optIFW_PACKAGE_TITLE;
   } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY =
-               GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
-    Title = optPACKAGE_DESCRIPTION_SUMMARY;
+               this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
+    this->Title = optPACKAGE_DESCRIPTION_SUMMARY;
   } else {
-    Title = "Your package description";
+    this->Title = "Your package description";
   }
 
   // Version;
-  if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) {
-    Version = option;
+  if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) {
+    this->Version = option;
   } else {
-    Version = "1.0.0";
+    this->Version = "1.0.0";
   }
 
   // Publisher
   if (const char* optIFW_PACKAGE_PUBLISHER =
-        GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) {
-    Publisher = optIFW_PACKAGE_PUBLISHER;
+        this->GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) {
+    this->Publisher = optIFW_PACKAGE_PUBLISHER;
   } else if (const char* optPACKAGE_VENDOR =
                GetOption("CPACK_PACKAGE_VENDOR")) {
-    Publisher = optPACKAGE_VENDOR;
+    this->Publisher = optPACKAGE_VENDOR;
   }
 
   // ProductUrl
-  if (const char* option = GetOption("CPACK_IFW_PRODUCT_URL")) {
-    ProductUrl = option;
+  if (const char* option = this->GetOption("CPACK_IFW_PRODUCT_URL")) {
+    this->ProductUrl = option;
   }
 
   // ApplicationIcon
-  if (const char* option = GetOption("CPACK_IFW_PACKAGE_ICON")) {
+  if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) {
     if (cmSystemTools::FileExists(option)) {
-      InstallerApplicationIcon = option;
+      this->InstallerApplicationIcon = option;
     } else {
-      printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option);
+      this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option);
     }
   }
 
   // WindowIcon
-  if (const char* option = GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) {
+  if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) {
     if (cmSystemTools::FileExists(option)) {
-      InstallerWindowIcon = option;
+      this->InstallerWindowIcon = option;
     } else {
-      printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option);
+      this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option);
     }
   }
 
   // Logo
-  if (const char* option = GetOption("CPACK_IFW_PACKAGE_LOGO")) {
+  if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) {
     if (cmSystemTools::FileExists(option)) {
-      Logo = option;
+      this->Logo = option;
     } else {
-      printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option);
+      this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option);
     }
   }
 
   // Watermark
-  if (const char* option = GetOption("CPACK_IFW_PACKAGE_WATERMARK")) {
+  if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) {
     if (cmSystemTools::FileExists(option)) {
-      Watermark = option;
+      this->Watermark = option;
     } else {
-      printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option);
+      this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option);
     }
   }
 
   // Banner
-  if (const char* option = GetOption("CPACK_IFW_PACKAGE_BANNER")) {
+  if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) {
     if (cmSystemTools::FileExists(option)) {
-      Banner = option;
+      this->Banner = option;
     } else {
-      printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option);
+      this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option);
     }
   }
 
   // Background
-  if (const char* option = GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) {
+  if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) {
     if (cmSystemTools::FileExists(option)) {
-      Background = option;
+      this->Background = option;
     } else {
-      printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option);
+      this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option);
     }
   }
 
   // WizardStyle
-  if (const char* option = GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) {
-    if (WizardStyle.compare("Modern") == 0 &&
-        WizardStyle.compare("Aero") == 0 && WizardStyle.compare("Mac") == 0 &&
-        WizardStyle.compare("Classic") == 0) {
-      cmCPackLogger(
-        cmCPackLog::LOG_WARNING,
-        "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \""
+  if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) {
+    // Setting the user value in any case
+    this->WizardStyle = option;
+    // Check known values
+    if (this->WizardStyle != "Modern" && this->WizardStyle != "Aero" &&
+        this->WizardStyle != "Mac" && this->WizardStyle != "Classic") {
+      cmCPackIFWLogger(
+        WARNING, "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \""
           << option << "\". Expected values are: Modern, Aero, Mac, Classic."
           << std::endl);
     }
-
-    WizardStyle = option;
   }
 
   // WizardDefaultWidth
   if (const char* option =
-        GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) {
-    WizardDefaultWidth = option;
+        this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) {
+    this->WizardDefaultWidth = option;
   }
 
   // WizardDefaultHeight
   if (const char* option =
-        GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) {
-    WizardDefaultHeight = option;
+        this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) {
+    this->WizardDefaultHeight = option;
   }
 
   // TitleColor
-  if (const char* option = GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
-    TitleColor = option;
+  if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
+    this->TitleColor = option;
   }
 
   // Start menu
   if (const char* optIFW_START_MENU_DIR =
         this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) {
-    StartMenuDir = optIFW_START_MENU_DIR;
+    this->StartMenuDir = optIFW_START_MENU_DIR;
   } else {
-    StartMenuDir = Name;
+    this->StartMenuDir = Name;
   }
 
   // Default target directory for installation
   if (const char* optIFW_TARGET_DIRECTORY =
-        GetOption("CPACK_IFW_TARGET_DIRECTORY")) {
-    TargetDir = optIFW_TARGET_DIRECTORY;
+        this->GetOption("CPACK_IFW_TARGET_DIRECTORY")) {
+    this->TargetDir = optIFW_TARGET_DIRECTORY;
   } else if (const char* optPACKAGE_INSTALL_DIRECTORY =
-               GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
-    TargetDir = "@ApplicationsDir@/";
-    TargetDir += optPACKAGE_INSTALL_DIRECTORY;
+               this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
+    this->TargetDir = "@ApplicationsDir@/";
+    this->TargetDir += optPACKAGE_INSTALL_DIRECTORY;
   } else {
-    TargetDir = "@RootDir@/usr/local";
+    this->TargetDir = "@RootDir@/usr/local";
   }
 
   // Default target directory for installation with administrator rights
-  if (const char* option = GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
-    AdminTargetDir = option;
+  if (const char* option =
+        this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
+    this->AdminTargetDir = option;
   }
 
   // Maintenance tool
   if (const char* optIFW_MAINTENANCE_TOOL =
         this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) {
-    MaintenanceToolName = optIFW_MAINTENANCE_TOOL;
+    this->MaintenanceToolName = optIFW_MAINTENANCE_TOOL;
   }
 
   // Maintenance tool ini file
   if (const char* optIFW_MAINTENANCE_TOOL_INI =
         this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) {
-    MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI;
+    this->MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI;
   }
 
   // Allow non-ASCII characters
   if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
-    if (IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
-      AllowNonAsciiCharacters = "true";
+    if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
+      this->AllowNonAsciiCharacters = "true";
     } else {
-      AllowNonAsciiCharacters = "false";
+      this->AllowNonAsciiCharacters = "false";
     }
   }
 
   // Space in path
   if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
-    if (IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
-      AllowSpaceInPath = "true";
+    if (this->IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
+      this->AllowSpaceInPath = "true";
     } else {
-      AllowSpaceInPath = "false";
+      this->AllowSpaceInPath = "false";
     }
   }
 
   // Control script
   if (const char* optIFW_CONTROL_SCRIPT =
         this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) {
-    ControlScript = optIFW_CONTROL_SCRIPT;
+    this->ControlScript = optIFW_CONTROL_SCRIPT;
   }
 
   // Resources
   if (const char* optIFW_PACKAGE_RESOURCES =
         this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) {
-    Resources.clear();
-    cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, Resources);
+    this->Resources.clear();
+    cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES,
+                                      this->Resources);
   }
 }
 
@@ -280,19 +241,20 @@ public:
     : installer(i)
     , file(false)
   {
-    path = i->Directory + "/resources";
+    this->path = i->Directory + "/resources";
   }
 
   bool ParseResource(size_t r)
   {
-    hasFiles = false;
-    hasErrors = false;
+    this->hasFiles = false;
+    this->hasErrors = false;
 
-    basePath = cmSystemTools::GetFilenamePath(installer->Resources[r].data());
+    this->basePath =
+      cmSystemTools::GetFilenamePath(this->installer->Resources[r]);
 
-    ParseFile(installer->Resources[r].data());
+    this->ParseFile(this->installer->Resources[r].data());
 
-    return hasFiles && !hasErrors;
+    return this->hasFiles && !this->hasErrors;
   }
 
   cmCPackIFWInstaller* installer;
@@ -302,22 +264,22 @@ public:
 protected:
   void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE
   {
-    file = name == "file";
+    this->file = name == "file";
     if (file) {
-      hasFiles = true;
+      this->hasFiles = true;
     }
   }
 
   void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
   {
-    if (file) {
+    if (this->file) {
       std::string content(data, data + length);
       content = cmSystemTools::TrimWhitespace(content);
-      std::string source = basePath + "/" + content;
-      std::string destination = path + "/" + content;
+      std::string source = this->basePath + "/" + content;
+      std::string destination = this->path + "/" + content;
       if (!cmSystemTools::CopyFileIfDifferent(source.data(),
                                               destination.data())) {
-        hasErrors = true;
+        this->hasErrors = true;
       }
     }
   }
@@ -328,12 +290,12 @@ protected:
 void cmCPackIFWInstaller::GenerateInstallerFile()
 {
   // Lazy directory initialization
-  if (Directory.empty() && Generator) {
-    Directory = Generator->toplevel;
+  if (this->Directory.empty() && this->Generator) {
+    this->Directory = this->Generator->toplevel;
   }
 
   // Output stream
-  cmGeneratedFileStream fout((Directory + "/config/config.xml").data());
+  cmGeneratedFileStream fout((this->Directory + "/config/config.xml").data());
   cmXMLWriter xout(fout);
 
   xout.StartDocument();
@@ -342,166 +304,165 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
 
   xout.StartElement("Installer");
 
-  xout.Element("Name", Name);
-  xout.Element("Version", Version);
-  xout.Element("Title", Title);
+  xout.Element("Name", this->Name);
+  xout.Element("Version", this->Version);
+  xout.Element("Title", this->Title);
 
-  if (!Publisher.empty()) {
-    xout.Element("Publisher", Publisher);
+  if (!this->Publisher.empty()) {
+    xout.Element("Publisher", this->Publisher);
   }
 
-  if (!ProductUrl.empty()) {
-    xout.Element("ProductUrl", ProductUrl);
+  if (!this->ProductUrl.empty()) {
+    xout.Element("ProductUrl", this->ProductUrl);
   }
 
   // ApplicationIcon
-  if (!InstallerApplicationIcon.empty()) {
+  if (!this->InstallerApplicationIcon.empty()) {
     std::string name =
-      cmSystemTools::GetFilenameName(InstallerApplicationIcon);
-    std::string path = Directory + "/config/" + name;
+      cmSystemTools::GetFilenameName(this->InstallerApplicationIcon);
+    std::string path = this->Directory + "/config/" + name;
     name = cmSystemTools::GetFilenameWithoutExtension(name);
-    cmsys::SystemTools::CopyFileIfDifferent(InstallerApplicationIcon.data(),
-                                            path.data());
+    cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon,
+                                            path);
     xout.Element("InstallerApplicationIcon", name);
   }
 
   // WindowIcon
-  if (!InstallerWindowIcon.empty()) {
-    std::string name = cmSystemTools::GetFilenameName(InstallerWindowIcon);
-    std::string path = Directory + "/config/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(InstallerWindowIcon.data(),
-                                            path.data());
+  if (!this->InstallerWindowIcon.empty()) {
+    std::string name =
+      cmSystemTools::GetFilenameName(this->InstallerWindowIcon);
+    std::string path = this->Directory + "/config/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path);
     xout.Element("InstallerWindowIcon", name);
   }
 
   // Logo
-  if (!Logo.empty()) {
-    std::string name = cmSystemTools::GetFilenameName(Logo);
-    std::string path = Directory + "/config/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(Logo.data(), path.data());
+  if (!this->Logo.empty()) {
+    std::string name = cmSystemTools::GetFilenameName(this->Logo);
+    std::string path = this->Directory + "/config/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(this->Logo, path);
     xout.Element("Logo", name);
   }
 
   // Banner
-  if (!Banner.empty()) {
-    std::string name = cmSystemTools::GetFilenameName(Banner);
-    std::string path = Directory + "/config/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(Banner.data(), path.data());
+  if (!this->Banner.empty()) {
+    std::string name = cmSystemTools::GetFilenameName(this->Banner);
+    std::string path = this->Directory + "/config/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(this->Banner, path);
     xout.Element("Banner", name);
   }
 
   // Watermark
-  if (!Watermark.empty()) {
-    std::string name = cmSystemTools::GetFilenameName(Watermark);
-    std::string path = Directory + "/config/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(Watermark.data(), path.data());
+  if (!this->Watermark.empty()) {
+    std::string name = cmSystemTools::GetFilenameName(this->Watermark);
+    std::string path = this->Directory + "/config/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(this->Watermark, path);
     xout.Element("Watermark", name);
   }
 
   // Background
-  if (!Background.empty()) {
-    std::string name = cmSystemTools::GetFilenameName(Background);
-    std::string path = Directory + "/config/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(Background.data(), path.data());
+  if (!this->Background.empty()) {
+    std::string name = cmSystemTools::GetFilenameName(this->Background);
+    std::string path = this->Directory + "/config/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(this->Background, path);
     xout.Element("Background", name);
   }
 
   // WizardStyle
-  if (!WizardStyle.empty()) {
-    xout.Element("WizardStyle", WizardStyle);
+  if (!this->WizardStyle.empty()) {
+    xout.Element("WizardStyle", this->WizardStyle);
   }
 
   // WizardDefaultWidth
-  if (!WizardDefaultWidth.empty()) {
-    xout.Element("WizardDefaultWidth", WizardDefaultWidth);
+  if (!this->WizardDefaultWidth.empty()) {
+    xout.Element("WizardDefaultWidth", this->WizardDefaultWidth);
   }
 
   // WizardDefaultHeight
-  if (!WizardDefaultHeight.empty()) {
-    xout.Element("WizardDefaultHeight", WizardDefaultHeight);
+  if (!this->WizardDefaultHeight.empty()) {
+    xout.Element("WizardDefaultHeight", this->WizardDefaultHeight);
   }
 
   // TitleColor
-  if (!TitleColor.empty()) {
-    xout.Element("TitleColor", TitleColor);
+  if (!this->TitleColor.empty()) {
+    xout.Element("TitleColor", this->TitleColor);
   }
 
   // Start menu
-  if (!IsVersionLess("2.0")) {
-    xout.Element("StartMenuDir", StartMenuDir);
+  if (!this->IsVersionLess("2.0")) {
+    xout.Element("StartMenuDir", this->StartMenuDir);
   }
 
   // Target dir
-  if (!TargetDir.empty()) {
-    xout.Element("TargetDir", TargetDir);
+  if (!this->TargetDir.empty()) {
+    xout.Element("TargetDir", this->TargetDir);
   }
 
   // Admin target dir
-  if (!AdminTargetDir.empty()) {
-    xout.Element("AdminTargetDir", AdminTargetDir);
+  if (!this->AdminTargetDir.empty()) {
+    xout.Element("AdminTargetDir", this->AdminTargetDir);
   }
 
   // Remote repositories
-  if (!RemoteRepositories.empty()) {
+  if (!this->RemoteRepositories.empty()) {
     xout.StartElement("RemoteRepositories");
-    for (RepositoriesVector::iterator rit = RemoteRepositories.begin();
-         rit != RemoteRepositories.end(); ++rit) {
+    for (RepositoriesVector::iterator rit = this->RemoteRepositories.begin();
+         rit != this->RemoteRepositories.end(); ++rit) {
       (*rit)->WriteRepositoryConfig(xout);
     }
     xout.EndElement();
   }
 
   // Maintenance tool
-  if (!IsVersionLess("2.0") && !MaintenanceToolName.empty()) {
-    xout.Element("MaintenanceToolName", MaintenanceToolName);
+  if (!this->IsVersionLess("2.0") && !this->MaintenanceToolName.empty()) {
+    xout.Element("MaintenanceToolName", this->MaintenanceToolName);
   }
 
   // Maintenance tool ini file
-  if (!IsVersionLess("2.0") && !MaintenanceToolIniFile.empty()) {
-    xout.Element("MaintenanceToolIniFile", MaintenanceToolIniFile);
+  if (!this->IsVersionLess("2.0") && !this->MaintenanceToolIniFile.empty()) {
+    xout.Element("MaintenanceToolIniFile", this->MaintenanceToolIniFile);
   }
 
   // Different allows
-  if (IsVersionLess("2.0")) {
+  if (this->IsVersionLess("2.0")) {
     // CPack IFW default policy
     xout.Comment("CPack IFW default policy for QtIFW less 2.0");
     xout.Element("AllowNonAsciiCharacters", "true");
     xout.Element("AllowSpaceInPath", "true");
   } else {
-    if (!AllowNonAsciiCharacters.empty()) {
-      xout.Element("AllowNonAsciiCharacters", AllowNonAsciiCharacters);
+    if (!this->AllowNonAsciiCharacters.empty()) {
+      xout.Element("AllowNonAsciiCharacters", this->AllowNonAsciiCharacters);
     }
-    if (!AllowSpaceInPath.empty()) {
-      xout.Element("AllowSpaceInPath", AllowSpaceInPath);
+    if (!this->AllowSpaceInPath.empty()) {
+      xout.Element("AllowSpaceInPath", this->AllowSpaceInPath);
     }
   }
 
   // Control script (copy to config dir)
-  if (!IsVersionLess("2.0") && !ControlScript.empty()) {
-    std::string name = cmSystemTools::GetFilenameName(ControlScript);
-    std::string path = Directory + "/config/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(ControlScript.data(), path.data());
+  if (!this->IsVersionLess("2.0") && !this->ControlScript.empty()) {
+    std::string name = cmSystemTools::GetFilenameName(this->ControlScript);
+    std::string path = this->Directory + "/config/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(this->ControlScript, path);
     xout.Element("ControlScript", name);
   }
 
   // Resources (copy to resources dir)
-  if (!Resources.empty()) {
+  if (!this->Resources.empty()) {
     std::vector<std::string> resources;
     cmCPackIFWResourcesParser parser(this);
-    for (size_t i = 0; i < Resources.size(); i++) {
+    for (size_t i = 0; i < this->Resources.size(); i++) {
       if (parser.ParseResource(i)) {
-        std::string name = cmSystemTools::GetFilenameName(Resources[i]);
-        std::string path = Directory + "/resources/" + name;
-        cmsys::SystemTools::CopyFileIfDifferent(Resources[i].data(),
-                                                path.data());
+        std::string name = cmSystemTools::GetFilenameName(this->Resources[i]);
+        std::string path = this->Directory + "/resources/" + name;
+        cmsys::SystemTools::CopyFileIfDifferent(this->Resources[i], path);
         resources.push_back(name);
       } else {
-        cmCPackLogger(cmCPackLog::LOG_WARNING, "Can't copy resources from \""
-                        << Resources[i] << "\". Resource will be skipped."
-                        << std::endl);
+        cmCPackIFWLogger(WARNING, "Can't copy resources from \""
+                           << this->Resources[i]
+                           << "\". Resource will be skipped." << std::endl);
       }
     }
-    Resources = resources;
+    this->Resources = resources;
   }
 
   xout.EndElement();
@@ -510,13 +471,13 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
 
 void cmCPackIFWInstaller::GeneratePackageFiles()
 {
-  if (Packages.empty() || Generator->IsOnePackage()) {
+  if (this->Packages.empty() || this->Generator->IsOnePackage()) {
     // Generate default package
     cmCPackIFWPackage package;
-    package.Generator = Generator;
+    package.Generator = this->Generator;
     package.Installer = this;
     // Check package group
-    if (const char* option = GetOption("CPACK_IFW_PACKAGE_GROUP")) {
+    if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) {
       package.ConfigureFromGroup(option);
       std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" +
         cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION";
@@ -531,16 +492,9 @@ void cmCPackIFWInstaller::GeneratePackageFiles()
   }
 
   // Generate packages meta information
-  for (PackagesMap::iterator pit = Packages.begin(); pit != Packages.end();
-       ++pit) {
+  for (PackagesMap::iterator pit = this->Packages.begin();
+       pit != this->Packages.end(); ++pit) {
     cmCPackIFWPackage* package = pit->second;
     package->GeneratePackageFile();
   }
 }
-
-void cmCPackIFWInstaller::WriteGeneratedByToStrim(cmXMLWriter& xout)
-{
-  if (Generator) {
-    Generator->WriteGeneratedByToStrim(xout);
-  }
-}
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h
index 4ec3e70..b635f42 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.h
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.h
@@ -3,21 +3,21 @@
 #ifndef cmCPackIFWInstaller_h
 #define cmCPackIFWInstaller_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmCPackIFWCommon.h"
 
 #include <map>
 #include <string>
 #include <vector>
 
-class cmCPackIFWGenerator;
 class cmCPackIFWPackage;
 class cmCPackIFWRepository;
-class cmXMLWriter;
 
 /** \class cmCPackIFWInstaller
  * \brief A binary installer to be created CPack IFW generator
  */
-class cmCPackIFWInstaller
+class cmCPackIFWInstaller : public cmCPackIFWCommon
 {
 public:
   // Types
@@ -111,28 +111,17 @@ public:
 public:
   // Internal implementation
 
-  const char* GetOption(const std::string& op) const;
-  bool IsOn(const std::string& op) const;
-
-  bool IsVersionLess(const char* version);
-  bool IsVersionGreater(const char* version);
-  bool IsVersionEqual(const char* version);
-
   void ConfigureFromOptions();
 
   void GenerateInstallerFile();
 
   void GeneratePackageFiles();
 
-  cmCPackIFWGenerator* Generator;
   PackagesMap Packages;
   RepositoriesVector RemoteRepositories;
   std::string Directory;
 
 protected:
-  void WriteGeneratedByToStrim(cmXMLWriter& xout);
-
-private:
   void printSkippedOptionWarning(const std::string& optionName,
                                  const std::string& optionValue);
 };
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx
index e23b1b9..c5311c3 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.cxx
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -2,38 +2,24 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackIFWPackage.h"
 
-#include "CPack/cmCPackComponentGroup.h"
-#include "CPack/cmCPackGenerator.h"
-#include "CPack/cmCPackLog.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackIFWCommon.h"
 #include "cmCPackIFWGenerator.h"
 #include "cmCPackIFWInstaller.h"
+#include "cmCPackLog.h" // IWYU pragma: keep
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 #include "cmTimestamp.h"
 #include "cmXMLWriter.h"
 
-#include <cmConfigure.h>
 #include <map>
 #include <sstream>
 #include <stddef.h>
-
-//----------------------------------------------------------------- Logger ---
-#ifdef cmCPackLogger
-#undef cmCPackLogger
-#endif
-#define cmCPackLogger(logType, msg)                                           \
-  do {                                                                        \
-    std::ostringstream cmCPackLog_msg;                                        \
-    cmCPackLog_msg << msg;                                                    \
-    if (Generator) {                                                          \
-      Generator->Logger->Log(logType, __FILE__, __LINE__,                     \
-                             cmCPackLog_msg.str().c_str());                   \
-    }                                                                         \
-  } while (false)
+#include <utility>
 
 //---------------------------------------------------------- CompareStruct ---
 cmCPackIFWPackage::CompareStruct::CompareStruct()
-  : Type(CompareNone)
+  : Type(cmCPackIFWPackage::CompareNone)
 {
 }
 
@@ -48,101 +34,66 @@ cmCPackIFWPackage::DependenceStruct::DependenceStruct(
   // Search compare section
   size_t pos = std::string::npos;
   if ((pos = dependence.find("<=")) != std::string::npos) {
-    Compare.Type = CompareLessOrEqual;
-    Compare.Value = dependence.substr(pos + 2);
+    this->Compare.Type = cmCPackIFWPackage::CompareLessOrEqual;
+    this->Compare.Value = dependence.substr(pos + 2);
   } else if ((pos = dependence.find(">=")) != std::string::npos) {
-    Compare.Type = CompareGreaterOrEqual;
-    Compare.Value = dependence.substr(pos + 2);
+    this->Compare.Type = cmCPackIFWPackage::CompareGreaterOrEqual;
+    this->Compare.Value = dependence.substr(pos + 2);
   } else if ((pos = dependence.find('<')) != std::string::npos) {
-    Compare.Type = CompareLess;
-    Compare.Value = dependence.substr(pos + 1);
+    this->Compare.Type = cmCPackIFWPackage::CompareLess;
+    this->Compare.Value = dependence.substr(pos + 1);
   } else if ((pos = dependence.find('=')) != std::string::npos) {
-    Compare.Type = CompareEqual;
-    Compare.Value = dependence.substr(pos + 1);
+    this->Compare.Type = cmCPackIFWPackage::CompareEqual;
+    this->Compare.Value = dependence.substr(pos + 1);
   } else if ((pos = dependence.find('>')) != std::string::npos) {
-    Compare.Type = CompareGreater;
-    Compare.Value = dependence.substr(pos + 1);
+    this->Compare.Type = cmCPackIFWPackage::CompareGreater;
+    this->Compare.Value = dependence.substr(pos + 1);
   } else if ((pos = dependence.find('-')) != std::string::npos) {
-    Compare.Type = CompareNone;
-    Compare.Value = dependence.substr(pos + 1);
+    this->Compare.Type = cmCPackIFWPackage::CompareNone;
+    this->Compare.Value = dependence.substr(pos + 1);
   }
   size_t dashPos = dependence.find('-');
   if (dashPos != std::string::npos) {
     pos = dashPos;
   }
-  Name = pos == std::string::npos ? dependence : dependence.substr(0, pos);
+  this->Name =
+    pos == std::string::npos ? dependence : dependence.substr(0, pos);
 }
 
 std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const
 {
-  if (Compare.Type == CompareNone) {
-    return Name;
+  if (this->Compare.Type == cmCPackIFWPackage::CompareNone) {
+    return this->Name;
   }
 
-  std::string result = Name;
+  std::string result = this->Name;
 
-  if (Compare.Type != CompareNone || !Compare.Value.empty()) {
+  if (this->Compare.Type != cmCPackIFWPackage::CompareNone ||
+      !this->Compare.Value.empty()) {
     result += "-";
   }
 
-  if (Compare.Type == CompareLessOrEqual) {
+  if (this->Compare.Type == cmCPackIFWPackage::CompareLessOrEqual) {
     result += "<=";
-  } else if (Compare.Type == CompareGreaterOrEqual) {
+  } else if (this->Compare.Type == cmCPackIFWPackage::CompareGreaterOrEqual) {
     result += ">=";
-  } else if (Compare.Type == CompareLess) {
+  } else if (this->Compare.Type == cmCPackIFWPackage::CompareLess) {
     result += "<";
-  } else if (Compare.Type == CompareEqual) {
+  } else if (this->Compare.Type == cmCPackIFWPackage::CompareEqual) {
     result += "=";
-  } else if (Compare.Type == CompareGreater) {
+  } else if (this->Compare.Type == cmCPackIFWPackage::CompareGreater) {
     result += ">";
   }
 
-  result += Compare.Value;
+  result += this->Compare.Value;
 
   return result;
 }
 
 //------------------------------------------------------ cmCPackIFWPackage ---
 cmCPackIFWPackage::cmCPackIFWPackage()
-  : Generator(CM_NULLPTR)
-  , Installer(CM_NULLPTR)
-{
-}
-
-const char* cmCPackIFWPackage::GetOption(const std::string& op) const
-{
-  const char* option = Generator ? Generator->GetOption(op) : CM_NULLPTR;
-  return option && *option ? option : CM_NULLPTR;
-}
-
-bool cmCPackIFWPackage::IsOn(const std::string& op) const
-{
-  return Generator ? Generator->IsOn(op) : false;
-}
-
-bool cmCPackIFWPackage::IsSetToOff(const std::string& op) const
-{
-  return Generator ? Generator->IsSetToOff(op) : false;
-}
-
-bool cmCPackIFWPackage::IsSetToEmpty(const std::string& op) const
-{
-  return Generator ? Generator->IsSetToEmpty(op) : false;
-}
-
-bool cmCPackIFWPackage::IsVersionLess(const char* version)
-{
-  return Generator ? Generator->IsVersionLess(version) : false;
-}
-
-bool cmCPackIFWPackage::IsVersionGreater(const char* version)
-{
-  return Generator ? Generator->IsVersionGreater(version) : false;
-}
-
-bool cmCPackIFWPackage::IsVersionEqual(const char* version)
+  : Installer(CM_NULLPTR)
 {
-  return Generator ? Generator->IsVersionEqual(version) : false;
 }
 
 std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component)
@@ -151,62 +102,62 @@ std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component)
     return "";
   }
   const char* option =
-    GetOption("CPACK_IFW_COMPONENT_" +
-              cmsys::SystemTools::UpperCase(component->Name) + "_NAME");
+    this->GetOption("CPACK_IFW_COMPONENT_" +
+                    cmsys::SystemTools::UpperCase(component->Name) + "_NAME");
   return option ? option : component->Name;
 }
 
 void cmCPackIFWPackage::DefaultConfiguration()
 {
-  DisplayName = "";
-  Description = "";
-  Version = "";
-  ReleaseDate = "";
-  Script = "";
-  Licenses.clear();
-  UserInterfaces.clear();
-  Translations.clear();
-  SortingPriority = "";
-  UpdateText = "";
-  Default = "";
-  Essential = "";
-  Virtual = "";
-  ForcedInstallation = "";
-  RequiresAdminRights = "";
+  this->DisplayName.clear();
+  this->Description.clear();
+  this->Version = "";
+  this->ReleaseDate = "";
+  this->Script = "";
+  this->Licenses.clear();
+  this->UserInterfaces.clear();
+  this->Translations.clear();
+  this->SortingPriority = "";
+  this->UpdateText = "";
+  this->Default = "";
+  this->Essential = "";
+  this->Virtual = "";
+  this->ForcedInstallation = "";
+  this->RequiresAdminRights = "";
 }
 
 // Defaul configuration (all in one package)
 int cmCPackIFWPackage::ConfigureFromOptions()
 {
   // Restore defaul configuration
-  DefaultConfiguration();
+  this->DefaultConfiguration();
 
   // Name
-  Name = Generator->GetRootPackageName();
+  this->Name = this->Generator->GetRootPackageName();
 
   // Display name
   if (const char* option = this->GetOption("CPACK_PACKAGE_NAME")) {
-    DisplayName = option;
+    this->DisplayName[""] = option;
   } else {
-    DisplayName = "Your package";
+    this->DisplayName[""] = "Your package";
   }
 
   // Description
   if (const char* option =
         this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
-    Description = option;
+    this->Description[""] = option;
   } else {
-    Description = "Your package description";
+    this->Description[""] = "Your package description";
   }
 
   // Version
-  if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) {
-    Version = option;
+  if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) {
+    this->Version = option;
   } else {
-    Version = "1.0.0";
+    this->Version = "1.0.0";
   }
 
-  ForcedInstallation = "true";
+  this->ForcedInstallation = "true";
 
   return 1;
 }
@@ -218,36 +169,36 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
   }
 
   // Restore defaul configuration
-  DefaultConfiguration();
+  this->DefaultConfiguration();
 
   std::string prefix = "CPACK_IFW_COMPONENT_" +
     cmsys::SystemTools::UpperCase(component->Name) + "_";
 
   // Display name
-  DisplayName = component->DisplayName;
+  this->DisplayName[""] = component->DisplayName;
 
   // Description
-  Description = component->Description;
+  this->Description[""] = component->Description;
 
   // Version
-  if (const char* optVERSION = GetOption(prefix + "VERSION")) {
-    Version = optVERSION;
+  if (const char* optVERSION = this->GetOption(prefix + "VERSION")) {
+    this->Version = optVERSION;
   } else if (const char* optPACKAGE_VERSION =
-               GetOption("CPACK_PACKAGE_VERSION")) {
-    Version = optPACKAGE_VERSION;
+               this->GetOption("CPACK_PACKAGE_VERSION")) {
+    this->Version = optPACKAGE_VERSION;
   } else {
-    Version = "1.0.0";
+    this->Version = "1.0.0";
   }
 
   // Script
-  if (const char* option = GetOption(prefix + "SCRIPT")) {
-    Script = option;
+  if (const char* option = this->GetOption(prefix + "SCRIPT")) {
+    this->Script = option;
   }
 
   // User interfaces
   if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
-    UserInterfaces.clear();
-    cmSystemTools::ExpandListArgument(option, UserInterfaces);
+    this->UserInterfaces.clear();
+    cmSystemTools::ExpandListArgument(option, this->UserInterfaces);
   }
 
   // CMake dependencies
@@ -255,49 +206,49 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
     std::vector<cmCPackComponent*>::iterator dit;
     for (dit = component->Dependencies.begin();
          dit != component->Dependencies.end(); ++dit) {
-      Dependencies.insert(Generator->ComponentPackages[*dit]);
+      this->Dependencies.insert(this->Generator->ComponentPackages[*dit]);
     }
   }
 
   // Licenses
   if (const char* option = this->GetOption(prefix + "LICENSES")) {
-    Licenses.clear();
-    cmSystemTools::ExpandListArgument(option, Licenses);
-    if (Licenses.size() % 2 != 0) {
-      cmCPackLogger(
-        cmCPackLog::LOG_WARNING, prefix
-          << "LICENSES"
-          << " should contain pairs of <display_name> and <file_path>."
-          << std::endl);
-      Licenses.clear();
+    this->Licenses.clear();
+    cmSystemTools::ExpandListArgument(option, this->Licenses);
+    if (this->Licenses.size() % 2 != 0) {
+      cmCPackIFWLogger(
+        WARNING,
+        prefix << "LICENSES"
+               << " should contain pairs of <display_name> and <file_path>."
+               << std::endl);
+      this->Licenses.clear();
     }
   }
 
   // Priority
   if (const char* option = this->GetOption(prefix + "PRIORITY")) {
-    SortingPriority = option;
-    cmCPackLogger(
-      cmCPackLog::LOG_WARNING, "The \"PRIORITY\" option is set "
+    this->SortingPriority = option;
+    cmCPackIFWLogger(
+      WARNING, "The \"PRIORITY\" option is set "
         << "for component \"" << component->Name << "\", but there option is "
         << "deprecated. Please use \"SORTING_PRIORITY\" option instead."
         << std::endl);
   }
 
   // Default
-  Default = component->IsDisabledByDefault ? "false" : "true";
+  this->Default = component->IsDisabledByDefault ? "false" : "true";
 
   // Essential
   if (this->IsOn(prefix + "ESSENTIAL")) {
-    Essential = "true";
+    this->Essential = "true";
   }
 
   // Virtual
-  Virtual = component->IsHidden ? "true" : "";
+  this->Virtual = component->IsHidden ? "true" : "";
 
   // ForcedInstallation
-  ForcedInstallation = component->IsRequired ? "true" : "false";
+  this->ForcedInstallation = component->IsRequired ? "true" : "false";
 
-  return ConfigureFromPrefix(prefix);
+  return this->ConfigureFromPrefix(prefix);
 }
 
 int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
@@ -307,61 +258,61 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
   }
 
   // Restore defaul configuration
-  DefaultConfiguration();
+  this->DefaultConfiguration();
 
   std::string prefix = "CPACK_IFW_COMPONENT_GROUP_" +
     cmsys::SystemTools::UpperCase(group->Name) + "_";
 
-  DisplayName = group->DisplayName;
-  Description = group->Description;
+  this->DisplayName[""] = group->DisplayName;
+  this->Description[""] = group->Description;
 
   // Version
-  if (const char* optVERSION = GetOption(prefix + "VERSION")) {
-    Version = optVERSION;
+  if (const char* optVERSION = this->GetOption(prefix + "VERSION")) {
+    this->Version = optVERSION;
   } else if (const char* optPACKAGE_VERSION =
-               GetOption("CPACK_PACKAGE_VERSION")) {
-    Version = optPACKAGE_VERSION;
+               this->GetOption("CPACK_PACKAGE_VERSION")) {
+    this->Version = optPACKAGE_VERSION;
   } else {
-    Version = "1.0.0";
+    this->Version = "1.0.0";
   }
 
   // Script
-  if (const char* option = GetOption(prefix + "SCRIPT")) {
-    Script = option;
+  if (const char* option = this->GetOption(prefix + "SCRIPT")) {
+    this->Script = option;
   }
 
   // User interfaces
   if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
-    UserInterfaces.clear();
-    cmSystemTools::ExpandListArgument(option, UserInterfaces);
+    this->UserInterfaces.clear();
+    cmSystemTools::ExpandListArgument(option, this->UserInterfaces);
   }
 
   // Licenses
   if (const char* option = this->GetOption(prefix + "LICENSES")) {
-    Licenses.clear();
-    cmSystemTools::ExpandListArgument(option, Licenses);
-    if (Licenses.size() % 2 != 0) {
-      cmCPackLogger(
-        cmCPackLog::LOG_WARNING, prefix
-          << "LICENSES"
-          << " should contain pairs of <display_name> and <file_path>."
-          << std::endl);
-      Licenses.clear();
+    this->Licenses.clear();
+    cmSystemTools::ExpandListArgument(option, this->Licenses);
+    if (this->Licenses.size() % 2 != 0) {
+      cmCPackIFWLogger(
+        WARNING,
+        prefix << "LICENSES"
+               << " should contain pairs of <display_name> and <file_path>."
+               << std::endl);
+      this->Licenses.clear();
     }
   }
 
   // Priority
   if (const char* option = this->GetOption(prefix + "PRIORITY")) {
-    SortingPriority = option;
-    cmCPackLogger(
-      cmCPackLog::LOG_WARNING, "The \"PRIORITY\" option is set "
+    this->SortingPriority = option;
+    cmCPackIFWLogger(
+      WARNING, "The \"PRIORITY\" option is set "
         << "for component group \"" << group->Name
         << "\", but there option is "
         << "deprecated. Please use \"SORTING_PRIORITY\" option instead."
         << std::endl);
   }
 
-  return ConfigureFromPrefix(prefix);
+  return this->ConfigureFromPrefix(prefix);
 }
 
 int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName)
@@ -372,29 +323,29 @@ int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName)
   std::string prefix =
     "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_";
 
-  if (const char* option = GetOption(prefix + "DISPLAY_NAME")) {
+  if (const char* option = this->GetOption(prefix + "DISPLAY_NAME")) {
     group.DisplayName = option;
   } else {
     group.DisplayName = group.Name;
   }
 
-  if (const char* option = GetOption(prefix + "DESCRIPTION")) {
+  if (const char* option = this->GetOption(prefix + "DESCRIPTION")) {
     group.Description = option;
   }
-  group.IsBold = IsOn(prefix + "BOLD_TITLE");
-  group.IsExpandedByDefault = IsOn(prefix + "EXPANDED");
+  group.IsBold = this->IsOn(prefix + "BOLD_TITLE");
+  group.IsExpandedByDefault = this->IsOn(prefix + "EXPANDED");
 
   // Package configuration
 
   group.Name = groupName;
 
   if (Generator) {
-    Name = Generator->GetGroupPackageName(&group);
+    this->Name = this->Generator->GetGroupPackageName(&group);
   } else {
-    Name = group.Name;
+    this->Name = group.Name;
   }
 
-  return ConfigureFromGroup(&group);
+  return this->ConfigureFromGroup(&group);
 }
 
 // Common options for components and groups
@@ -405,51 +356,51 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
 
   // Display name
   option = prefix + "DISPLAY_NAME";
-  if (IsSetToEmpty(option)) {
-    DisplayName.clear();
-  } else if (const char* value = GetOption(option)) {
-    DisplayName = value;
+  if (this->IsSetToEmpty(option)) {
+    this->DisplayName.clear();
+  } else if (const char* value = this->GetOption(option)) {
+    this->ExpandListArgument(value, this->DisplayName);
   }
 
   // Description
   option = prefix + "DESCRIPTION";
-  if (IsSetToEmpty(option)) {
-    Description.clear();
-  } else if (const char* value = GetOption(option)) {
-    Description = value;
+  if (this->IsSetToEmpty(option)) {
+    this->Description.clear();
+  } else if (const char* value = this->GetOption(option)) {
+    this->ExpandListArgument(value, this->Description);
   }
 
   // Release date
   option = prefix + "RELEASE_DATE";
-  if (IsSetToEmpty(option)) {
-    ReleaseDate.clear();
-  } else if (const char* value = GetOption(option)) {
-    ReleaseDate = value;
+  if (this->IsSetToEmpty(option)) {
+    this->ReleaseDate.clear();
+  } else if (const char* value = this->GetOption(option)) {
+    this->ReleaseDate = value;
   }
 
   // Sorting priority
   option = prefix + "SORTING_PRIORITY";
-  if (IsSetToEmpty(option)) {
-    SortingPriority.clear();
-  } else if (const char* value = GetOption(option)) {
-    SortingPriority = value;
+  if (this->IsSetToEmpty(option)) {
+    this->SortingPriority.clear();
+  } else if (const char* value = this->GetOption(option)) {
+    this->SortingPriority = value;
   }
 
   // Update text
   option = prefix + "UPDATE_TEXT";
-  if (IsSetToEmpty(option)) {
-    UpdateText.clear();
-  } else if (const char* value = GetOption(option)) {
-    UpdateText = value;
+  if (this->IsSetToEmpty(option)) {
+    this->UpdateText.clear();
+  } else if (const char* value = this->GetOption(option)) {
+    this->UpdateText = value;
   }
 
   // Translations
   option = prefix + "TRANSLATIONS";
-  if (IsSetToEmpty(option)) {
-    Translations.clear();
+  if (this->IsSetToEmpty(option)) {
+    this->Translations.clear();
   } else if (const char* value = this->GetOption(option)) {
-    Translations.clear();
-    cmSystemTools::ExpandListArgument(value, Translations);
+    this->Translations.clear();
+    cmSystemTools::ExpandListArgument(value, this->Translations);
   }
 
   // QtIFW dependencies
@@ -465,84 +416,84 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
   for (std::vector<std::string>::iterator dit = deps.begin();
        dit != deps.end(); ++dit) {
     DependenceStruct dep(*dit);
-    if (Generator->Packages.count(dep.Name)) {
-      cmCPackIFWPackage& depPkg = Generator->Packages[dep.Name];
+    if (this->Generator->Packages.count(dep.Name)) {
+      cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name];
       dep.Name = depPkg.Name;
     }
-    bool hasDep = Generator->DependentPackages.count(dep.Name) > 0;
-    DependenceStruct& depRef = Generator->DependentPackages[dep.Name];
+    bool hasDep = this->Generator->DependentPackages.count(dep.Name) > 0;
+    DependenceStruct& depRef = this->Generator->DependentPackages[dep.Name];
     if (!hasDep) {
       depRef = dep;
     }
-    AlienDependencies.insert(&depRef);
+    this->AlienDependencies.insert(&depRef);
   }
 
   // Automatic dependency on
   option = prefix + "AUTO_DEPEND_ON";
-  if (IsSetToEmpty(option)) {
-    AlienAutoDependOn.clear();
+  if (this->IsSetToEmpty(option)) {
+    this->AlienAutoDependOn.clear();
   } else if (const char* value = this->GetOption(option)) {
     std::vector<std::string> depsOn;
     cmSystemTools::ExpandListArgument(value, depsOn);
     for (std::vector<std::string>::iterator dit = depsOn.begin();
          dit != depsOn.end(); ++dit) {
       DependenceStruct dep(*dit);
-      if (Generator->Packages.count(dep.Name)) {
-        cmCPackIFWPackage& depPkg = Generator->Packages[dep.Name];
+      if (this->Generator->Packages.count(dep.Name)) {
+        cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name];
         dep.Name = depPkg.Name;
       }
-      bool hasDep = Generator->DependentPackages.count(dep.Name) > 0;
-      DependenceStruct& depRef = Generator->DependentPackages[dep.Name];
+      bool hasDep = this->Generator->DependentPackages.count(dep.Name) > 0;
+      DependenceStruct& depRef = this->Generator->DependentPackages[dep.Name];
       if (!hasDep) {
         depRef = dep;
       }
-      AlienAutoDependOn.insert(&depRef);
+      this->AlienAutoDependOn.insert(&depRef);
     }
   }
 
   // Visibility
   option = prefix + "VIRTUAL";
-  if (IsSetToEmpty(option)) {
-    Virtual.clear();
-  } else if (IsOn(option)) {
-    Virtual = "true";
+  if (this->IsSetToEmpty(option)) {
+    this->Virtual.clear();
+  } else if (this->IsOn(option)) {
+    this->Virtual = "true";
   }
 
   // Default selection
   option = prefix + "DEFAULT";
-  if (IsSetToEmpty(option)) {
-    Default.clear();
-  } else if (const char* value = GetOption(option)) {
+  if (this->IsSetToEmpty(option)) {
+    this->Default.clear();
+  } else if (const char* value = this->GetOption(option)) {
     std::string lowerValue = cmsys::SystemTools::LowerCase(value);
-    if (lowerValue.compare("true") == 0) {
-      Default = "true";
-    } else if (lowerValue.compare("false") == 0) {
-      Default = "false";
-    } else if (lowerValue.compare("script") == 0) {
-      Default = "script";
+    if (lowerValue == "true") {
+      this->Default = "true";
+    } else if (lowerValue == "false") {
+      this->Default = "false";
+    } else if (lowerValue == "script") {
+      this->Default = "script";
     } else {
-      Default = value;
+      this->Default = value;
     }
   }
 
   // Forsed installation
   option = prefix + "FORCED_INSTALLATION";
-  if (IsSetToEmpty(option)) {
-    ForcedInstallation.clear();
-  } else if (IsOn(option)) {
-    ForcedInstallation = "true";
-  } else if (IsSetToOff(option)) {
-    ForcedInstallation = "false";
+  if (this->IsSetToEmpty(option)) {
+    this->ForcedInstallation.clear();
+  } else if (this->IsOn(option)) {
+    this->ForcedInstallation = "true";
+  } else if (this->IsSetToOff(option)) {
+    this->ForcedInstallation = "false";
   }
 
   // Requires admin rights
   option = prefix + "REQUIRES_ADMIN_RIGHTS";
-  if (IsSetToEmpty(option)) {
-    RequiresAdminRights.clear();
-  } else if (IsOn(option)) {
-    RequiresAdminRights = "true";
-  } else if (IsSetToOff(option)) {
-    RequiresAdminRights = "false";
+  if (this->IsSetToEmpty(option)) {
+    this->RequiresAdminRights.clear();
+  } else if (this->IsOn(option)) {
+    this->RequiresAdminRights = "true";
+  } else if (this->IsSetToOff(option)) {
+    this->RequiresAdminRights = "false";
   }
 
   return 1;
@@ -551,16 +502,16 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
 void cmCPackIFWPackage::GeneratePackageFile()
 {
   // Lazy directory initialization
-  if (Directory.empty()) {
-    if (Installer) {
-      Directory = Installer->Directory + "/packages/" + Name;
-    } else if (Generator) {
-      Directory = Generator->toplevel + "/packages/" + Name;
+  if (this->Directory.empty()) {
+    if (this->Installer) {
+      this->Directory = this->Installer->Directory + "/packages/" + this->Name;
+    } else if (this->Generator) {
+      this->Directory = this->Generator->toplevel + "/packages/" + this->Name;
     }
   }
 
   // Output stream
-  cmGeneratedFileStream fout((Directory + "/meta/package.xml").data());
+  cmGeneratedFileStream fout((this->Directory + "/meta/package.xml").data());
   cmXMLWriter xout(fout);
 
   xout.StartDocument();
@@ -569,28 +520,49 @@ void cmCPackIFWPackage::GeneratePackageFile()
 
   xout.StartElement("Package");
 
-  xout.Element("DisplayName", DisplayName);
-  xout.Element("Description", Description);
+  // DisplayName (with translations)
+  for (std::map<std::string, std::string>::iterator it =
+         this->DisplayName.begin();
+       it != this->DisplayName.end(); ++it) {
+    xout.StartElement("DisplayName");
+    if (!it->first.empty()) {
+      xout.Attribute("xml:lang", it->first);
+    }
+    xout.Content(it->second);
+    xout.EndElement();
+  }
+
+  // Description (with translations)
+  for (std::map<std::string, std::string>::iterator it =
+         this->Description.begin();
+       it != this->Description.end(); ++it) {
+    xout.StartElement("Description");
+    if (!it->first.empty()) {
+      xout.Attribute("xml:lang", it->first);
+    }
+    xout.Content(it->second);
+    xout.EndElement();
+  }
 
   // Update text
-  if (!UpdateText.empty()) {
-    xout.Element("UpdateText", UpdateText);
+  if (!this->UpdateText.empty()) {
+    xout.Element("UpdateText", this->UpdateText);
   }
 
-  xout.Element("Name", Name);
-  xout.Element("Version", Version);
+  xout.Element("Name", this->Name);
+  xout.Element("Version", this->Version);
 
-  if (!ReleaseDate.empty()) {
-    xout.Element("ReleaseDate", ReleaseDate);
+  if (!this->ReleaseDate.empty()) {
+    xout.Element("ReleaseDate", this->ReleaseDate);
   } else {
     xout.Element("ReleaseDate", cmTimestamp().CurrentTime("%Y-%m-%d", true));
   }
 
   // Script (copy to meta dir)
-  if (!Script.empty()) {
-    std::string name = cmSystemTools::GetFilenameName(Script);
-    std::string path = Directory + "/meta/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(Script.data(), path.data());
+  if (!this->Script.empty()) {
+    std::string name = cmSystemTools::GetFilenameName(this->Script);
+    std::string path = this->Directory + "/meta/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(this->Script, path);
     xout.Element("Script", name);
   }
 
@@ -598,9 +570,8 @@ void cmCPackIFWPackage::GeneratePackageFile()
   std::vector<std::string> userInterfaces = UserInterfaces;
   for (size_t i = 0; i < userInterfaces.size(); i++) {
     std::string name = cmSystemTools::GetFilenameName(userInterfaces[i]);
-    std::string path = Directory + "/meta/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(userInterfaces[i].data(),
-                                            path.data());
+    std::string path = this->Directory + "/meta/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(userInterfaces[i], path);
     userInterfaces[i] = name;
   }
   if (!userInterfaces.empty()) {
@@ -615,9 +586,8 @@ void cmCPackIFWPackage::GeneratePackageFile()
   std::vector<std::string> translations = Translations;
   for (size_t i = 0; i < translations.size(); i++) {
     std::string name = cmSystemTools::GetFilenameName(translations[i]);
-    std::string path = Directory + "/meta/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(translations[i].data(),
-                                            path.data());
+    std::string path = this->Directory + "/meta/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(translations[i], path);
     translations[i] = name;
   }
   if (!translations.empty()) {
@@ -630,12 +600,13 @@ void cmCPackIFWPackage::GeneratePackageFile()
 
   // Dependencies
   std::set<DependenceStruct> compDepSet;
-  for (std::set<DependenceStruct*>::iterator ait = AlienDependencies.begin();
-       ait != AlienDependencies.end(); ++ait) {
+  for (std::set<DependenceStruct*>::iterator ait =
+         this->AlienDependencies.begin();
+       ait != this->AlienDependencies.end(); ++ait) {
     compDepSet.insert(*(*ait));
   }
-  for (std::set<cmCPackIFWPackage*>::iterator it = Dependencies.begin();
-       it != Dependencies.end(); ++it) {
+  for (std::set<cmCPackIFWPackage*>::iterator it = this->Dependencies.begin();
+       it != this->Dependencies.end(); ++it) {
     compDepSet.insert(DependenceStruct((*it)->Name));
   }
   // Write dependencies
@@ -653,8 +624,9 @@ void cmCPackIFWPackage::GeneratePackageFile()
 
   // Automatic dependency on
   std::set<DependenceStruct> compAutoDepSet;
-  for (std::set<DependenceStruct*>::iterator ait = AlienAutoDependOn.begin();
-       ait != AlienAutoDependOn.end(); ++ait) {
+  for (std::set<DependenceStruct*>::iterator ait =
+         this->AlienAutoDependOn.begin();
+       ait != this->AlienAutoDependOn.end(); ++ait) {
     compAutoDepSet.insert(*(*ait));
   }
   // Write automatic dependency on
@@ -671,11 +643,11 @@ void cmCPackIFWPackage::GeneratePackageFile()
   }
 
   // Licenses (copy to meta dir)
-  std::vector<std::string> licenses = Licenses;
+  std::vector<std::string> licenses = this->Licenses;
   for (size_t i = 1; i < licenses.size(); i += 2) {
     std::string name = cmSystemTools::GetFilenameName(licenses[i]);
-    std::string path = Directory + "/meta/" + name;
-    cmsys::SystemTools::CopyFileIfDifferent(licenses[i].data(), path.data());
+    std::string path = this->Directory + "/meta/" + name;
+    cmsys::SystemTools::CopyFileIfDifferent(licenses[i], path);
     licenses[i] = name;
   }
   if (!licenses.empty()) {
@@ -689,37 +661,30 @@ void cmCPackIFWPackage::GeneratePackageFile()
     xout.EndElement();
   }
 
-  if (!ForcedInstallation.empty()) {
-    xout.Element("ForcedInstallation", ForcedInstallation);
+  if (!this->ForcedInstallation.empty()) {
+    xout.Element("ForcedInstallation", this->ForcedInstallation);
   }
 
-  if (!RequiresAdminRights.empty()) {
-    xout.Element("RequiresAdminRights", RequiresAdminRights);
+  if (!this->RequiresAdminRights.empty()) {
+    xout.Element("RequiresAdminRights", this->RequiresAdminRights);
   }
 
-  if (!Virtual.empty()) {
-    xout.Element("Virtual", Virtual);
-  } else if (!Default.empty()) {
-    xout.Element("Default", Default);
+  if (!this->Virtual.empty()) {
+    xout.Element("Virtual", this->Virtual);
+  } else if (!this->Default.empty()) {
+    xout.Element("Default", this->Default);
   }
 
   // Essential
-  if (!Essential.empty()) {
-    xout.Element("Essential", Essential);
+  if (!this->Essential.empty()) {
+    xout.Element("Essential", this->Essential);
   }
 
   // Priority
-  if (!SortingPriority.empty()) {
-    xout.Element("SortingPriority", SortingPriority);
+  if (!this->SortingPriority.empty()) {
+    xout.Element("SortingPriority", this->SortingPriority);
   }
 
   xout.EndElement();
   xout.EndDocument();
 }
-
-void cmCPackIFWPackage::WriteGeneratedByToStrim(cmXMLWriter& xout)
-{
-  if (Generator) {
-    Generator->WriteGeneratedByToStrim(xout);
-  }
-}
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h
index bd1d6c5..cec59b0 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.h
+++ b/Source/CPack/IFW/cmCPackIFWPackage.h
@@ -3,22 +3,23 @@
 #ifndef cmCPackIFWPackage_h
 #define cmCPackIFWPackage_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cmCPackIFWCommon.h"
+
+#include <map>
 #include <set>
 #include <string>
 #include <vector>
 
 class cmCPackComponent;
 class cmCPackComponentGroup;
-class cmCPackIFWGenerator;
 class cmCPackIFWInstaller;
-class cmXMLWriter;
 
 /** \class cmCPackIFWPackage
  * \brief A single component to be installed by CPack IFW generator
  */
-class cmCPackIFWPackage
+class cmCPackIFWPackage : public cmCPackIFWCommon
 {
 public:
   // Types
@@ -69,10 +70,10 @@ public:
   // Configuration
 
   /// Human-readable name of the component
-  std::string DisplayName;
+  std::map<std::string, std::string> DisplayName;
 
   /// Human-readable description of the component
-  std::string Description;
+  std::map<std::string, std::string> Description;
 
   /// Version number of the component
   std::string Version;
@@ -119,15 +120,6 @@ public:
 public:
   // Internal implementation
 
-  const char* 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;
-
-  bool IsVersionLess(const char* version);
-  bool IsVersionGreater(const char* version);
-  bool IsVersionEqual(const char* version);
-
   std::string GetComponentName(cmCPackComponent* component);
 
   void DefaultConfiguration();
@@ -140,8 +132,6 @@ public:
 
   void GeneratePackageFile();
 
-  // Pointer to generator
-  cmCPackIFWGenerator* Generator;
   // Pointer to installer
   cmCPackIFWInstaller* Installer;
   // Collection of dependencies
@@ -152,9 +142,6 @@ public:
   std::set<DependenceStruct*> AlienAutoDependOn;
   // Patch to package directory
   std::string Directory;
-
-protected:
-  void WriteGeneratedByToStrim(cmXMLWriter& xout);
 };
 
 #endif // cmCPackIFWPackage_h
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx
index cc204e8..b115db0 100644
--- a/Source/CPack/IFW/cmCPackIFWRepository.cxx
+++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx
@@ -2,32 +2,16 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackIFWRepository.h"
 
-#include "CPack/cmCPackGenerator.h"
 #include "cmCPackIFWGenerator.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 #include "cmXMLWriter.h"
 
-#include <cmConfigure.h>
 #include <stddef.h>
 
-#ifdef cmCPackLogger
-#undef cmCPackLogger
-#endif
-#define cmCPackLogger(logType, msg)                                           \
-  do {                                                                        \
-    std::ostringstream cmCPackLog_msg;                                        \
-    cmCPackLog_msg << msg;                                                    \
-    if (Generator) {                                                          \
-      Generator->Logger->Log(logType, __FILE__, __LINE__,                     \
-                             cmCPackLog_msg.str().c_str());                   \
-    }                                                                         \
-  } while (false)
-
 cmCPackIFWRepository::cmCPackIFWRepository()
-  : Update(None)
-  , Generator(CM_NULLPTR)
+  : Update(cmCPackIFWRepository::None)
 {
 }
 
@@ -35,120 +19,95 @@ bool cmCPackIFWRepository::IsValid() const
 {
   bool valid = true;
 
-  switch (Update) {
-    case None:
-      valid = !Url.empty();
+  switch (this->Update) {
+    case cmCPackIFWRepository::None:
+      valid = !this->Url.empty();
       break;
-    case Add:
-      valid = !Url.empty();
+    case cmCPackIFWRepository::Add:
+      valid = !this->Url.empty();
       break;
-    case Remove:
-      valid = !Url.empty();
+    case cmCPackIFWRepository::Remove:
+      valid = !this->Url.empty();
       break;
-    case Replace:
-      valid = !OldUrl.empty() && !NewUrl.empty();
+    case cmCPackIFWRepository::Replace:
+      valid = !this->OldUrl.empty() && !this->NewUrl.empty();
       break;
   }
 
   return valid;
 }
 
-const char* cmCPackIFWRepository::GetOption(const std::string& op) const
-{
-  return Generator ? Generator->GetOption(op) : CM_NULLPTR;
-}
-
-bool cmCPackIFWRepository::IsOn(const std::string& op) const
-{
-  return Generator ? Generator->IsOn(op) : false;
-}
-
-bool cmCPackIFWRepository::IsVersionLess(const char* version)
-{
-  return Generator ? Generator->IsVersionLess(version) : false;
-}
-
-bool cmCPackIFWRepository::IsVersionGreater(const char* version)
-{
-  return Generator ? Generator->IsVersionGreater(version) : false;
-}
-
-bool cmCPackIFWRepository::IsVersionEqual(const char* version)
-{
-  return Generator ? Generator->IsVersionEqual(version) : false;
-}
-
 bool cmCPackIFWRepository::ConfigureFromOptions()
 {
   // Name;
-  if (Name.empty()) {
+  if (this->Name.empty()) {
     return false;
   }
 
   std::string prefix =
-    "CPACK_IFW_REPOSITORY_" + cmsys::SystemTools::UpperCase(Name) + "_";
+    "CPACK_IFW_REPOSITORY_" + cmsys::SystemTools::UpperCase(this->Name) + "_";
 
   // Update
-  if (IsOn(prefix + "ADD")) {
-    Update = Add;
+  if (this->IsOn(prefix + "ADD")) {
+    this->Update = cmCPackIFWRepository::Add;
   } else if (IsOn(prefix + "REMOVE")) {
-    Update = Remove;
+    this->Update = cmCPackIFWRepository::Remove;
   } else if (IsOn(prefix + "REPLACE")) {
-    Update = Replace;
+    this->Update = cmCPackIFWRepository::Replace;
   } else {
-    Update = None;
+    this->Update = cmCPackIFWRepository::None;
   }
 
   // Url
-  if (const char* url = GetOption(prefix + "URL")) {
-    Url = url;
+  if (const char* url = this->GetOption(prefix + "URL")) {
+    this->Url = url;
   } else {
-    Url = "";
+    this->Url = "";
   }
 
   // Old url
-  if (const char* oldUrl = GetOption(prefix + "OLD_URL")) {
-    OldUrl = oldUrl;
+  if (const char* oldUrl = this->GetOption(prefix + "OLD_URL")) {
+    this->OldUrl = oldUrl;
   } else {
-    OldUrl = "";
+    this->OldUrl = "";
   }
 
   // New url
-  if (const char* newUrl = GetOption(prefix + "NEW_URL")) {
-    NewUrl = newUrl;
+  if (const char* newUrl = this->GetOption(prefix + "NEW_URL")) {
+    this->NewUrl = newUrl;
   } else {
-    NewUrl = "";
+    this->NewUrl = "";
   }
 
   // Enabled
-  if (IsOn(prefix + "DISABLED")) {
-    Enabled = "0";
+  if (this->IsOn(prefix + "DISABLED")) {
+    this->Enabled = "0";
   } else {
-    Enabled = "";
+    this->Enabled = "";
   }
 
   // Username
-  if (const char* username = GetOption(prefix + "USERNAME")) {
-    Username = username;
+  if (const char* username = this->GetOption(prefix + "USERNAME")) {
+    this->Username = username;
   } else {
-    Username = "";
+    this->Username = "";
   }
 
   // Password
-  if (const char* password = GetOption(prefix + "PASSWORD")) {
-    Password = password;
+  if (const char* password = this->GetOption(prefix + "PASSWORD")) {
+    this->Password = password;
   } else {
-    Password = "";
+    this->Password = "";
   }
 
   // DisplayName
-  if (const char* displayName = GetOption(prefix + "DISPLAY_NAME")) {
-    DisplayName = displayName;
+  if (const char* displayName = this->GetOption(prefix + "DISPLAY_NAME")) {
+    this->DisplayName = displayName;
   } else {
-    DisplayName = "";
+    this->DisplayName = "";
   }
 
-  return IsValid();
+  return this->IsValid();
 }
 
 /** \class cmCPackeIFWUpdatesPatcher
@@ -171,8 +130,8 @@ public:
 protected:
   void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
   {
-    xout.StartElement(name);
-    StartFragment(atts);
+    this->xout.StartElement(name);
+    this->StartFragment(atts);
   }
 
   void StartFragment(const char** atts)
@@ -180,23 +139,23 @@ protected:
     for (size_t i = 0; atts[i]; i += 2) {
       const char* key = atts[i];
       const char* value = atts[i + 1];
-      xout.Attribute(key, value);
+      this->xout.Attribute(key, value);
     }
   }
 
   void EndElement(const std::string& name) CM_OVERRIDE
   {
-    if (name == "Updates" && !patched) {
-      repository->WriteRepositoryUpdates(xout);
-      patched = true;
+    if (name == "Updates" && !this->patched) {
+      this->repository->WriteRepositoryUpdates(this->xout);
+      this->patched = true;
     }
-    xout.EndElement();
-    if (patched) {
+    this->xout.EndElement();
+    if (this->patched) {
       return;
     }
     if (name == "Checksum") {
-      repository->WriteRepositoryUpdates(xout);
-      patched = true;
+      this->repository->WriteRepositoryUpdates(this->xout);
+      this->patched = true;
     }
   }
 
@@ -207,20 +166,21 @@ protected:
         content == "\n") {
       return;
     }
-    xout.Content(content);
+    this->xout.Content(content);
   }
 };
 
 bool cmCPackIFWRepository::PatchUpdatesXml()
 {
   // Lazy directory initialization
-  if (Directory.empty() && Generator) {
-    Directory = Generator->toplevel;
+  if (this->Directory.empty() && this->Generator) {
+    this->Directory = this->Generator->toplevel;
   }
 
   // Filenames
-  std::string updatesXml = Directory + "/repository/Updates.xml";
-  std::string updatesPatchXml = Directory + "/repository/UpdatesPatch.xml";
+  std::string updatesXml = this->Directory + "/repository/Updates.xml";
+  std::string updatesPatchXml =
+    this->Directory + "/repository/UpdatesPatch.xml";
 
   // Output stream
   cmGeneratedFileStream fout(updatesPatchXml.data());
@@ -228,7 +188,7 @@ bool cmCPackIFWRepository::PatchUpdatesXml()
 
   xout.StartDocument();
 
-  WriteGeneratedByToStrim(xout);
+  this->WriteGeneratedByToStrim(xout);
 
   // Patch
   {
@@ -248,22 +208,22 @@ void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout)
   xout.StartElement("Repository");
 
   // Url
-  xout.Element("Url", Url);
+  xout.Element("Url", this->Url);
   // Enabled
-  if (!Enabled.empty()) {
-    xout.Element("Enabled", Enabled);
+  if (!this->Enabled.empty()) {
+    xout.Element("Enabled", this->Enabled);
   }
   // Username
-  if (!Username.empty()) {
-    xout.Element("Username", Username);
+  if (!this->Username.empty()) {
+    xout.Element("Username", this->Username);
   }
   // Password
-  if (!Password.empty()) {
-    xout.Element("Password", Password);
+  if (!this->Password.empty()) {
+    xout.Element("Password", this->Password);
   }
   // DisplayName
-  if (!DisplayName.empty()) {
-    xout.Element("DisplayName", DisplayName);
+  if (!this->DisplayName.empty()) {
+    xout.Element("DisplayName", this->DisplayName);
   }
 
   xout.EndElement();
@@ -273,42 +233,43 @@ void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout)
 {
   xout.StartElement("Repository");
 
-  switch (Update) {
-    case None:
+  switch (this->Update) {
+    case cmCPackIFWRepository::None:
       break;
-    case Add:
+    case cmCPackIFWRepository::Add:
       xout.Attribute("action", "add");
       break;
-    case Remove:
+    case cmCPackIFWRepository::Remove:
       xout.Attribute("action", "remove");
       break;
-    case Replace:
+    case cmCPackIFWRepository::Replace:
       xout.Attribute("action", "replace");
       break;
   }
 
   // Url
-  if (Update == Add || Update == Remove) {
-    xout.Attribute("url", Url);
-  } else if (Update == Replace) {
-    xout.Attribute("oldUrl", OldUrl);
-    xout.Attribute("newUrl", NewUrl);
+  if (this->Update == cmCPackIFWRepository::Add ||
+      this->Update == cmCPackIFWRepository::Remove) {
+    xout.Attribute("url", this->Url);
+  } else if (Update == cmCPackIFWRepository::Replace) {
+    xout.Attribute("oldUrl", this->OldUrl);
+    xout.Attribute("newUrl", this->NewUrl);
   }
   // Enabled
-  if (!Enabled.empty()) {
-    xout.Attribute("enabled", Enabled);
+  if (!this->Enabled.empty()) {
+    xout.Attribute("enabled", this->Enabled);
   }
   // Username
-  if (!Username.empty()) {
-    xout.Attribute("username", Username);
+  if (!this->Username.empty()) {
+    xout.Attribute("username", this->Username);
   }
   // Password
-  if (!Password.empty()) {
-    xout.Attribute("password", Password);
+  if (!this->Password.empty()) {
+    xout.Attribute("password", this->Password);
   }
   // DisplayName
-  if (!DisplayName.empty()) {
-    xout.Attribute("displayname", DisplayName);
+  if (!this->DisplayName.empty()) {
+    xout.Attribute("displayname", this->DisplayName);
   }
 
   xout.EndElement();
@@ -316,19 +277,12 @@ void cmCPackIFWRepository::WriteRepositoryUpdate(cmXMLWriter& xout)
 
 void cmCPackIFWRepository::WriteRepositoryUpdates(cmXMLWriter& xout)
 {
-  if (!RepositoryUpdate.empty()) {
+  if (!this->RepositoryUpdate.empty()) {
     xout.StartElement("RepositoryUpdate");
-    for (RepositoriesVector::iterator rit = RepositoryUpdate.begin();
-         rit != RepositoryUpdate.end(); ++rit) {
+    for (RepositoriesVector::iterator rit = this->RepositoryUpdate.begin();
+         rit != this->RepositoryUpdate.end(); ++rit) {
       (*rit)->WriteRepositoryUpdate(xout);
     }
     xout.EndElement();
   }
 }
-
-void cmCPackIFWRepository::WriteGeneratedByToStrim(cmXMLWriter& xout)
-{
-  if (Generator) {
-    Generator->WriteGeneratedByToStrim(xout);
-  }
-}
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.h b/Source/CPack/IFW/cmCPackIFWRepository.h
index 36f46da..227cfae 100644
--- a/Source/CPack/IFW/cmCPackIFWRepository.h
+++ b/Source/CPack/IFW/cmCPackIFWRepository.h
@@ -3,18 +3,19 @@
 #ifndef cmCPackIFWRepository_h
 #define cmCPackIFWRepository_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmCPackIFWCommon.h"
 
 #include <string>
 #include <vector>
 
-class cmCPackIFWGenerator;
 class cmXMLWriter;
 
 /** \class cmCPackIFWRepository
  * \brief A remote repository to be created CPack IFW generator
  */
-class cmCPackIFWRepository
+class cmCPackIFWRepository : public cmCPackIFWCommon
 {
 public:
   // Types
@@ -72,13 +73,6 @@ public:
 
   bool IsValid() const;
 
-  const char* GetOption(const std::string& op) const;
-  bool IsOn(const std::string& op) const;
-
-  bool IsVersionLess(const char* version);
-  bool IsVersionGreater(const char* version);
-  bool IsVersionEqual(const char* version);
-
   bool ConfigureFromOptions();
 
   bool PatchUpdatesXml();
@@ -87,12 +81,8 @@ public:
   void WriteRepositoryUpdate(cmXMLWriter& xout);
   void WriteRepositoryUpdates(cmXMLWriter& xout);
 
-  cmCPackIFWGenerator* Generator;
   RepositoriesVector RepositoryUpdate;
   std::string Directory;
-
-protected:
-  void WriteGeneratedByToStrim(cmXMLWriter& xout);
 };
 
 #endif // cmCPackIFWRepository_h
diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx
index b159e64..b48bf12 100644
--- a/Source/CPack/OSXScriptLauncher.cxx
+++ b/Source/CPack/OSXScriptLauncher.cxx
@@ -1,8 +1,8 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
-#include <cmsys/FStream.hxx>
-#include <cmsys/Process.h>
-#include <cmsys/SystemTools.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/Process.h"
+#include "cmsys/SystemTools.hxx"
 #include <iostream>
 #include <stddef.h>
 #include <string>
@@ -20,7 +20,6 @@
 int main(int argc, char* argv[])
 {
   // if ( cmsys::SystemTools::FileExists(
-  std::string cwd = cmsys::SystemTools::GetCurrentWorkingDirectory();
   cmsys::ofstream ofs("/tmp/output.txt");
 
   CFStringRef fileName;
@@ -86,8 +85,6 @@ int main(int argc, char* argv[])
   int length;
   while (cmsysProcess_WaitForData(cp, &data, &length, 0)) {
     // Translate NULL characters in the output into valid text.
-    // Visual Studio 7 puts these characters in the output of its
-    // build process.
     for (int i = 0; i < length; ++i) {
       if (data[i] == '\0') {
         data[i] = ' ';
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 2bccf2e..274dfd0 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -2,14 +2,14 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackWIXGenerator.h"
 
-#include <CPack/cmCPackComponentGroup.h>
-#include <CPack/cmCPackLog.h>
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+#include "cmCryptoHash.h"
+#include "cmGeneratedFileStream.h"
+#include "cmInstalledFile.h"
+#include "cmSystemTools.h"
+#include "cmUuid.h"
 #include <algorithm>
-#include <cmCryptoHash.h>
-#include <cmGeneratedFileStream.h>
-#include <cmInstalledFile.h>
-#include <cmSystemTools.h>
-#include <cmUuid.h>
 
 #include "cmWIXDirectoriesSourceWriter.h"
 #include "cmWIXFeaturesSourceWriter.h"
@@ -17,10 +17,10 @@
 #include "cmWIXRichTextFormatWriter.h"
 #include "cmWIXSourceWriter.h"
 
-#include <cmsys/Directory.hxx>
-#include <cmsys/Encoding.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/SystemTools.hxx>
+#include "cmsys/Directory.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/SystemTools.hxx"
 
 #include <rpc.h> // for GUID generation
 
@@ -437,8 +437,8 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
   directoryDefinitions.AddAttribute("Name", "SourceDir");
 
   size_t installRootSize =
-    directoryDefinitions.BeginInstallationPrefixDirectory(
-      GetProgramFilesFolderId(), installRoot);
+    directoryDefinitions.BeginInstallationPrefixDirectory(GetRootFolderId(),
+                                                          installRoot);
 
   std::string fileDefinitionsFilename = this->CPackTopLevel + "/files.wxs";
 
@@ -570,16 +570,26 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
   return this->Patch->CheckForUnappliedFragments();
 }
 
-std::string cmCPackWIXGenerator::GetProgramFilesFolderId() const
+std::string cmCPackWIXGenerator::GetRootFolderId() const
 {
   if (cmSystemTools::IsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) {
     return "";
   }
+
+  std::string result = "ProgramFiles<64>Folder";
+
+  const char* rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID");
+  if (rootFolderId) {
+    result = rootFolderId;
+  }
+
   if (GetArchitecture() == "x86") {
-    return "ProgramFilesFolder";
+    cmSystemTools::ReplaceString(result, "<64>", "");
   } else {
-    return "ProgramFiles64Folder";
+    cmSystemTools::ReplaceString(result, "<64>", "64");
   }
+
+  return result;
 }
 
 bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate()
@@ -667,10 +677,10 @@ bool cmCPackWIXGenerator::AddComponentsToFeature(
                                       cpackPackageDesktopLinksList);
   }
 
-  AddDirectoryAndFileDefinitons(rootPath, "INSTALL_ROOT", directoryDefinitions,
-                                fileDefinitions, featureDefinitions,
-                                cpackPackageExecutablesList,
-                                cpackPackageDesktopLinksList, shortcuts);
+  AddDirectoryAndFileDefinitions(
+    rootPath, "INSTALL_ROOT", directoryDefinitions, fileDefinitions,
+    featureDefinitions, cpackPackageExecutablesList,
+    cpackPackageDesktopLinksList, shortcuts);
 
   featureDefinitions.EndElement("FeatureRef");
 
@@ -831,7 +841,7 @@ bool cmCPackWIXGenerator::CreateLicenseFile()
   return true;
 }
 
-void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
+void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions(
   std::string const& topdir, std::string const& directoryId,
   cmWIXDirectoriesSourceWriter& directoryDefinitions,
   cmWIXFilesSourceWriter& fileDefinitions,
@@ -896,12 +906,12 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
       directoryDefinitions.BeginElement("Directory");
       directoryDefinitions.AddAttribute("Id", subDirectoryId);
       directoryDefinitions.AddAttribute("Name", fileName);
+      this->Patch->ApplyFragment(subDirectoryId, directoryDefinitions);
 
-      AddDirectoryAndFileDefinitons(
+      AddDirectoryAndFileDefinitions(
         fullPath, subDirectoryId, directoryDefinitions, fileDefinitions,
         featureDefinitions, packageExecutables, desktopExecutables, shortcuts);
 
-      this->Patch->ApplyFragment(subDirectoryId, directoryDefinitions);
       directoryDefinitions.EndElement("Directory");
     } else {
       cmInstalledFile const* installedFile = this->GetInstalledFile(
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index fc0994c..b2633a7 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackWIXGenerator_h
 #define cmCPackWIXGenerator_h
 
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
 
 #include "cmWIXPatch.h"
 #include "cmWIXShortcut.h"
@@ -65,7 +65,7 @@ private:
 
   bool CreateWiXSourceFiles();
 
-  std::string GetProgramFilesFolderId() const;
+  std::string GetRootFolderId() const;
 
   bool GenerateMainSourceFileFromTemplate();
 
@@ -104,7 +104,7 @@ private:
 
   bool RunLightCommand(std::string const& objectFiles);
 
-  void AddDirectoryAndFileDefinitons(
+  void AddDirectoryAndFileDefinitions(
     std::string const& topdir, std::string const& directoryId,
     cmWIXDirectoriesSourceWriter& directoryDefinitions,
     cmWIXFilesSourceWriter& fileDefinitions,
diff --git a/Source/CPack/WiX/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx
index 9f9b39c..744a932 100644
--- a/Source/CPack/WiX/cmWIXAccessControlList.cxx
+++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmWIXAccessControlList.h"
 
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
 
-#include <cmSystemTools.h>
+#include "cmSystemTools.h"
 
 cmWIXAccessControlList::cmWIXAccessControlList(
   cmCPackLog* logger, cmInstalledFile const& installedFile,
diff --git a/Source/CPack/WiX/cmWIXAccessControlList.h b/Source/CPack/WiX/cmWIXAccessControlList.h
index 0a25ee5..2a23f2f 100644
--- a/Source/CPack/WiX/cmWIXAccessControlList.h
+++ b/Source/CPack/WiX/cmWIXAccessControlList.h
@@ -5,8 +5,8 @@
 
 #include "cmWIXSourceWriter.h"
 
-#include <CPack/cmCPackLog.h>
-#include <cmInstalledFile.h>
+#include "cmCPackLog.h"
+#include "cmInstalledFile.h"
 
 class cmWIXAccessControlList
 {
diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h
index 062efe3..8233331 100644
--- a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h
@@ -5,7 +5,7 @@
 
 #include "cmWIXSourceWriter.h"
 
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
 
 #include <string>
 
diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx
index 79a9fdd..0be4377 100644
--- a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx
@@ -44,6 +44,8 @@ void cmWIXFeaturesSourceWriter::EmitFeatureForComponentGroup(
   AddAttributeUnlessEmpty("Title", group.DisplayName);
   AddAttributeUnlessEmpty("Description", group.Description);
 
+  patch.ApplyFragment("CM_G_" + group.Name, *this);
+
   for (std::vector<cmCPackComponentGroup*>::const_iterator i =
          group.Subgroups.begin();
        i != group.Subgroups.end(); ++i) {
@@ -56,8 +58,6 @@ void cmWIXFeaturesSourceWriter::EmitFeatureForComponentGroup(
     EmitFeatureForComponent(**i, patch);
   }
 
-  patch.ApplyFragment("CM_G_" + group.Name, *this);
-
   EndElement("Feature");
 }
 
diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h
index 368b250..e751ca7 100644
--- a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h
@@ -6,7 +6,7 @@
 #include "cmWIXPatch.h"
 #include "cmWIXSourceWriter.h"
 
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
 
 /** \class cmWIXFeaturesSourceWriter
  * \brief Helper class to generate features.wxs
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
index a471d26..b4cd1a3 100644
--- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
@@ -4,14 +4,12 @@
 
 #include "cmWIXAccessControlList.h"
 
-#include <cmInstalledFile.h>
+#include "cmInstalledFile.h"
 
-#include <cmSystemTools.h>
-#include <cmUuid.h>
+#include "cmSystemTools.h"
+#include "cmUuid.h"
 
-#include <sys/types.h>
-// include sys/stat.h after sys/types.h
-#include <sys/stat.h>
+#include "cm_sys_stat.h"
 
 cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger,
                                                std::string const& filename,
@@ -138,6 +136,7 @@ std::string cmWIXFilesSourceWriter::EmitComponentFile(
     }
   }
 
+  patch.ApplyFragment(componentId, *this);
   BeginElement("File");
   AddAttribute("Id", fileId);
   AddAttribute("Source", filePath);
@@ -149,16 +148,15 @@ std::string cmWIXFilesSourceWriter::EmitComponentFile(
   if (!(fileMode & S_IWRITE)) {
     AddAttribute("ReadOnly", "yes");
   }
+  patch.ApplyFragment(fileId, *this);
 
   if (installedFile) {
     cmWIXAccessControlList acl(Logger, *installedFile, *this);
     acl.Apply();
   }
 
-  patch.ApplyFragment(fileId, *this);
   EndElement("File");
 
-  patch.ApplyFragment(componentId, *this);
   EndElement("Component");
   EndElement("DirectoryRef");
 
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.h b/Source/CPack/WiX/cmWIXFilesSourceWriter.h
index d7a642d..dc9c636 100644
--- a/Source/CPack/WiX/cmWIXFilesSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.h
@@ -8,7 +8,7 @@
 #include "cmWIXPatch.h"
 #include "cmWIXShortcut.h"
 
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
 
 /** \class cmWIXFilesSourceWriter
  * \brief Helper class to generate files.wxs
diff --git a/Source/CPack/WiX/cmWIXPatch.cxx b/Source/CPack/WiX/cmWIXPatch.cxx
index 7c48653..287a644 100644
--- a/Source/CPack/WiX/cmWIXPatch.cxx
+++ b/Source/CPack/WiX/cmWIXPatch.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmWIXPatch.h"
 
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
 
 cmWIXPatch::cmWIXPatch(cmCPackLog* logger)
   : Logger(logger)
@@ -29,7 +29,11 @@ void cmWIXPatch::ApplyFragment(std::string const& id,
     return;
 
   const cmWIXPatchElement& fragment = i->second;
-
+  for (cmWIXPatchElement::attributes_t::const_iterator attr_i =
+         fragment.attributes.begin();
+       attr_i != fragment.attributes.end(); ++attr_i) {
+    writer.AddAttribute(attr_i->first, attr_i->second);
+  }
   this->ApplyElementChildren(fragment, writer);
 
   Fragments.erase(i);
diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx
index 47f98d1..0dcc74a 100644
--- a/Source/CPack/WiX/cmWIXPatchParser.cxx
+++ b/Source/CPack/WiX/cmWIXPatchParser.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmWIXPatchParser.h"
 
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
 
-#include <cm_expat.h>
+#include "cm_expat.h"
 
 cmWIXPatchNode::Type cmWIXPatchText::type()
 {
@@ -72,9 +72,11 @@ void cmWIXPatchParser::StartElement(const std::string& name, const char** atts)
 
 void cmWIXPatchParser::StartFragment(const char** attributes)
 {
+  cmWIXPatchElement* new_element = CM_NULLPTR;
+  /* find the id of for fragment */
   for (size_t i = 0; attributes[i]; i += 2) {
-    std::string key = attributes[i];
-    std::string value = attributes[i + 1];
+    const std::string key = attributes[i];
+    const std::string value = attributes[i + 1];
 
     if (key == "Id") {
       if (Fragments.find(value) != Fragments.end()) {
@@ -83,10 +85,22 @@ void cmWIXPatchParser::StartFragment(const char** attributes)
         ReportValidationError(tmp.str());
       }
 
-      ElementStack.push_back(&Fragments[value]);
-    } else {
-      ReportValidationError(
-        "The only allowed 'CPackWixFragment' attribute is 'Id'");
+      new_element = &Fragments[value];
+      ElementStack.push_back(new_element);
+    }
+  }
+
+  /* add any additional attributes for the fragement */
+  if (!new_element) {
+    ReportValidationError("No 'Id' specified for 'CPackWixFragment' element");
+  } else {
+    for (size_t i = 0; attributes[i]; i += 2) {
+      const std::string key = attributes[i];
+      const std::string value = attributes[i + 1];
+
+      if (key != "Id") {
+        new_element->attributes[key] = value;
+      }
     }
   }
 }
diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h
index a2f0a3c..52c7e35 100644
--- a/Source/CPack/WiX/cmWIXPatchParser.h
+++ b/Source/CPack/WiX/cmWIXPatchParser.h
@@ -3,12 +3,12 @@
 #ifndef cmCPackWIXPatchParser_h
 #define cmCPackWIXPatchParser_h
 
-#include <CPack/cmCPackLog.h>
+#include "cmCPackLog.h"
 
-#include <cmXMLParser.h>
+#include "cmXMLParser.h"
 
-#include <list>
 #include <map>
+#include <vector>
 
 struct cmWIXPatchNode
 {
@@ -36,7 +36,7 @@ struct cmWIXPatchElement : cmWIXPatchNode
 
   ~cmWIXPatchElement();
 
-  typedef std::list<cmWIXPatchNode*> child_list_t;
+  typedef std::vector<cmWIXPatchNode*> child_list_t;
   typedef std::map<std::string, std::string> attributes_t;
 
   std::string name;
@@ -84,7 +84,7 @@ private:
 
   fragment_map_t& Fragments;
 
-  std::list<cmWIXPatchElement*> ElementStack;
+  std::vector<cmWIXPatchElement*> ElementStack;
 };
 
 #endif
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
index d819347..2c99a22 100644
--- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
+++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmWIXRichTextFormatWriter.h"
 
-#include <cmVersion.h>
+#include "cmVersion.h"
 
 cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter(
   std::string const& filename)
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
index a3c8394..30df878 100644
--- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
+++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
@@ -3,9 +3,9 @@
 #ifndef cmWIXRichTextFormatWriter_h
 #define cmWIXRichTextFormatWriter_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <string>
 
 /** \class cmWIXRichtTextFormatWriter
diff --git a/Source/CPack/WiX/cmWIXShortcut.h b/Source/CPack/WiX/cmWIXShortcut.h
index cba3b34..23ddc6a 100644
--- a/Source/CPack/WiX/cmWIXShortcut.h
+++ b/Source/CPack/WiX/cmWIXShortcut.h
@@ -3,7 +3,7 @@
 #ifndef cmWIXShortcut_h
 #define cmWIXShortcut_h
 
-#include <cmInstalledFile.h>
+#include "cmInstalledFile.h"
 
 #include <map>
 #include <set>
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx
index b434334..a86e28d 100644
--- a/Source/CPack/WiX/cmWIXSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmWIXSourceWriter.h"
 
-#include <CPack/cmCPackGenerator.h>
+#include "cmCPackGenerator.h"
 
-#include <cmUuid.h>
+#include "cmUuid.h"
 
 #include <windows.h>
 
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h
index 45aefe5..4af1ed6 100644
--- a/Source/CPack/WiX/cmWIXSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXSourceWriter.h
@@ -3,9 +3,9 @@
 #ifndef cmWIXSourceWriter_h
 #define cmWIXSourceWriter_h
 
-#include <CPack/cmCPackLog.h>
+#include "cmCPackLog.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 
 #include <string>
 #include <vector>
diff --git a/Source/CPack/cmCPack7zGenerator.h b/Source/CPack/cmCPack7zGenerator.h
index a617d9b..42a4781 100644
--- a/Source/CPack/cmCPack7zGenerator.h
+++ b/Source/CPack/cmCPack7zGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPack7zGenerator_h
 #define cmCPack7zGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackArchiveGenerator.h"
 #include "cmCPackGenerator.h"
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 9d9cd66..575c949 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -7,6 +7,7 @@
 #include "cmCPackLog.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 
 #include <map>
 #include <ostream>
@@ -24,6 +25,28 @@ cmCPackArchiveGenerator::~cmCPackArchiveGenerator()
 {
 }
 
+std::string cmCPackArchiveGenerator::GetArchiveComponentFileName(
+  const std::string& component, bool isGroupName)
+{
+  std::string componentUpper(cmSystemTools::UpperCase(component));
+  std::string packageFileName;
+
+  if (this->IsSet("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME")) {
+    packageFileName +=
+      this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME");
+  } else if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) {
+    packageFileName += GetComponentPackageFileName(
+      this->GetOption("CPACK_ARCHIVE_FILE_NAME"), component, isGroupName);
+  } else {
+    packageFileName += GetComponentPackageFileName(
+      this->GetOption("CPACK_PACKAGE_FILE_NAME"), component, isGroupName);
+  }
+
+  packageFileName += this->GetOutputExtension();
+
+  return packageFileName;
+}
+
 int cmCPackArchiveGenerator::InitializeInternal()
 {
   this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1");
@@ -37,9 +60,8 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
   // Add the files of this component to the archive
   std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
   localToplevel += "/" + component->Name;
-  std::string dir = cmSystemTools::GetCurrentWorkingDirectory();
   // Change to local toplevel
-  cmSystemTools::ChangeDirectory(localToplevel);
+  cmWorkingDirectory workdir(localToplevel);
   std::string filePrefix;
   if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
     filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME");
@@ -64,8 +86,6 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
       return 0;
     }
   }
-  // Go back to previous dir
-  cmSystemTools::ChangeDirectory(dir);
   return 1;
 }
 
@@ -103,11 +123,9 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
       cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
                       << compGIt->first << std::endl);
       // Begin the archive for this group
-      std::string packageFileName = std::string(toplevel);
-      packageFileName += "/" +
-        GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
-                                    compGIt->first, true) +
-        this->GetOutputExtension();
+      std::string packageFileName = std::string(toplevel) + "/" +
+        this->GetArchiveComponentFileName(compGIt->first, true);
+
       // open a block in order to automatically close archive
       // at the end of the block
       {
@@ -139,10 +157,9 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
         std::string packageFileName = std::string(toplevel);
 
         localToplevel += "/" + compIt->first;
-        packageFileName += "/" + GetComponentPackageFileName(
-                                   this->GetOption("CPACK_PACKAGE_FILE_NAME"),
-                                   compIt->first, false) +
-          this->GetOutputExtension();
+        packageFileName +=
+          "/" + this->GetArchiveComponentFileName(compIt->first, false);
+
         {
           DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive);
           // Add the files of this component to the archive
@@ -163,10 +180,9 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
       std::string packageFileName = std::string(toplevel);
 
       localToplevel += "/" + compIt->first;
-      packageFileName += "/" +
-        GetComponentPackageFileName(this->GetOption("CPACK_PACKAGE_FILE_NAME"),
-                                    compIt->first, false) +
-        this->GetOutputExtension();
+      packageFileName +=
+        "/" + this->GetArchiveComponentFileName(compIt->first, false);
+
       {
         DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive);
         // Add the files of this component to the archive
@@ -184,9 +200,16 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne()
   // reset the package file names
   packageFileNames.clear();
   packageFileNames.push_back(std::string(toplevel));
-  packageFileNames[0] += "/" +
-    std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) +
-    this->GetOutputExtension();
+  packageFileNames[0] += "/";
+
+  if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) {
+    packageFileNames[0] += this->GetOption("CPACK_ARCHIVE_FILE_NAME");
+  } else {
+    packageFileNames[0] += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+  }
+
+  packageFileNames[0] += this->GetOutputExtension();
+
   cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                 "Packaging all groups in one package..."
                 "(CPACK_COMPONENTS_ALL_GROUPS_IN_ONE_PACKAGE is set)"
@@ -227,8 +250,7 @@ int cmCPackArchiveGenerator::PackageFiles()
   // CASE 3 : NON COMPONENT package.
   DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive);
   std::vector<std::string>::const_iterator fileIt;
-  std::string dir = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(toplevel);
+  cmWorkingDirectory workdir(toplevel);
   for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
     // Get the relative path to the file
     std::string rp =
@@ -241,7 +263,6 @@ int cmCPackArchiveGenerator::PackageFiles()
       return 0;
     }
   }
-  cmSystemTools::ChangeDirectory(dir);
   // The destructor of cmArchiveWrite will close and finish the write
   return 1;
 }
diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h
index df02ae8..e7116c4 100644
--- a/Source/CPack/cmCPackArchiveGenerator.h
+++ b/Source/CPack/cmCPackArchiveGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackArchiveGenerator_h
 #define cmCPackArchiveGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmArchiveWrite.h"
 #include "cmCPackGenerator.h"
@@ -34,6 +34,11 @@ public:
   // component support
   bool SupportsComponentInstallation() const CM_OVERRIDE;
 
+private:
+  // get archive component filename
+  std::string GetArchiveComponentFileName(const std::string& component,
+                                          bool isGroupName);
+
 protected:
   int InitializeInternal() CM_OVERRIDE;
   /**
diff --git a/Source/CPack/cmCPackBundleGenerator.h b/Source/CPack/cmCPackBundleGenerator.h
index c9200c1..861fe4b 100644
--- a/Source/CPack/cmCPackBundleGenerator.h
+++ b/Source/CPack/cmCPackBundleGenerator.h
@@ -3,7 +3,8 @@
 #ifndef cmCPackBundleGenerator_h
 #define cmCPackBundleGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 
 #include "cmCPackDragNDropGenerator.h"
diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h
index f955daf..26d69ba 100644
--- a/Source/CPack/cmCPackComponentGroup.h
+++ b/Source/CPack/cmCPackComponentGroup.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackComponentGroup_h
 #define cmCPackComponentGroup_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <string>
 #include <vector>
@@ -78,6 +78,10 @@ public:
   /// contains the files that are part of this component.
   std::string ArchiveFile;
 
+  /// The file to pass to --component-plist when using the
+  /// productbuild generator.
+  std::string Plist;
+
   /// The components that this component depends on.
   std::vector<cmCPackComponent*> Dependencies;
 
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
index e67811d..2119f78 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
@@ -9,7 +9,7 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-#include <cmsys/SystemTools.hxx>
+#include "cmsys/SystemTools.hxx"
 
 cmCPackCygwinBinaryGenerator::cmCPackCygwinBinaryGenerator()
 {
diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
index 92475d9..2c289f6 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
@@ -9,13 +9,13 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-#include <cmsys/SystemTools.hxx>
+#include "cmsys/SystemTools.hxx"
 
 // Includes needed for implementation of RenameFile.  This is not in
 // system tools because it is not implemented robustly enough to move
 // files across directories.
 #ifdef _WIN32
-#include <sys/stat.h>
+#include "cm_sys_stat.h"
 #include <windows.h>
 #endif
 
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 5c50da8..af54fce 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -8,15 +8,15 @@
 #include "cmCPackLog.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
+#include "cm_sys_stat.h"
 
-#include <cmsys/Glob.hxx>
+#include "cmsys/Glob.hxx"
 #include <limits.h>
 #include <map>
 #include <ostream>
 #include <set>
 #include <stdio.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <utility>
 
 // NOTE:
diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h
index 7db933e..e7cde11 100644
--- a/Source/CPack/cmCPackDebGenerator.h
+++ b/Source/CPack/cmCPackDebGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackDebGenerator_h
 #define cmCPackDebGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackGenerator.h"
 
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index fd67df9..9864cf3 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -7,8 +7,8 @@
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <iomanip>
 #include <map>
 #include <stdlib.h>
@@ -390,6 +390,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
   bool remount_image =
     !cpack_package_icon.empty() || !cpack_dmg_ds_store_setup_script.empty();
 
+  std::string temp_image_format = "UDZO";
+
   // Create 1 MB dummy padding file in staging area when we need to remount
   // image, so we have enough space for storing changes ...
   if (remount_image) {
@@ -401,6 +403,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
 
       return 0;
     }
+    temp_image_format = "UDRW";
   }
 
   // Create a temporary read-write disk image ...
@@ -413,7 +416,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
   temp_image_command << " -ov";
   temp_image_command << " -srcfolder \"" << staging.str() << "\"";
   temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\"";
-  temp_image_command << " -format UDRW";
+  temp_image_command << " -format " << temp_image_format;
   temp_image_command << " \"" << temp_image << "\"";
 
   if (!this->RunCommand(temp_image_command)) {
@@ -632,29 +635,33 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
       return 0;
     }
 
-    // convert to UDCO
-    std::string temp_udco = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    temp_udco += "/temp-udco.dmg";
+    if (temp_image_format != "UDZO") {
+      temp_image_format = "UDZO";
+      // convert to UDZO to enable unflatten/flatten
+      std::string temp_udzo = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+      temp_udzo += "/temp-udzo.dmg";
 
-    std::ostringstream udco_image_command;
-    udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
-    udco_image_command << " convert \"" << temp_image << "\"";
-    udco_image_command << " -format UDCO";
-    udco_image_command << " -ov -o \"" << temp_udco << "\"";
+      std::ostringstream udco_image_command;
+      udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
+      udco_image_command << " convert \"" << temp_image << "\"";
+      udco_image_command << " -format UDZO";
+      udco_image_command << " -ov -o \"" << temp_udzo << "\"";
 
-    if (!this->RunCommand(udco_image_command, &error)) {
-      cmCPackLogger(cmCPackLog::LOG_ERROR,
-                    "Error converting to UDCO dmg for adding SLA."
-                      << std::endl
-                      << error << std::endl);
-      return 0;
+      if (!this->RunCommand(udco_image_command, &error)) {
+        cmCPackLogger(cmCPackLog::LOG_ERROR,
+                      "Error converting to UDCO dmg for adding SLA."
+                        << std::endl
+                        << error << std::endl);
+        return 0;
+      }
+      temp_image = temp_udzo;
     }
 
     // unflatten dmg
     std::ostringstream unflatten_command;
     unflatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
     unflatten_command << " unflatten ";
-    unflatten_command << "\"" << temp_udco << "\"";
+    unflatten_command << "\"" << temp_image << "\"";
 
     if (!this->RunCommand(unflatten_command, &error)) {
       cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -673,7 +680,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
     }
     embed_sla_command << " \"" << sla_r << "\"";
     embed_sla_command << " -a -o ";
-    embed_sla_command << "\"" << temp_udco << "\"";
+    embed_sla_command << "\"" << temp_image << "\"";
 
     if (!this->RunCommand(embed_sla_command, &error)) {
       cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding SLA." << std::endl
@@ -686,7 +693,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
     std::ostringstream flatten_command;
     flatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
     flatten_command << " flatten ";
-    flatten_command << "\"" << temp_udco << "\"";
+    flatten_command << "\"" << temp_image << "\"";
 
     if (!this->RunCommand(flatten_command, &error)) {
       cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -695,8 +702,6 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
                                                            << std::endl);
       return 0;
     }
-
-    temp_image = temp_udco;
   }
 
   // Create the final compressed read-only disk image ...
diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h
index 876eab7..ae2cc17 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.h
+++ b/Source/CPack/cmCPackDragNDropGenerator.h
@@ -3,7 +3,8 @@
 #ifndef cmCPackDragNDropGenerator_h
 #define cmCPackDragNDropGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <sstream>
 #include <stddef.h>
 #include <string>
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 21eda79..d8e2753 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -2,11 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackGenerator.h"
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/RegularExpression.hxx>
-#include <list>
 #include <utility>
 
 #include "cmCPackComponentGroup.h"
@@ -16,6 +15,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmStateSnapshot.h"
+#include "cmWorkingDirectory.h"
 #include "cmXMLSafe.h"
 #include "cm_auto_ptr.hxx"
 #include "cmake.h"
@@ -313,7 +313,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
     const std::string& tempDir = tempInstallDirectory;
     for (it = installDirectoriesVector.begin();
          it != installDirectoriesVector.end(); ++it) {
-      std::list<std::pair<std::string, std::string> > symlinkedFiles;
+      std::vector<std::pair<std::string, std::string> > symlinkedFiles;
       cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
       cmsys::Glob gl;
       std::string top = *it;
@@ -377,13 +377,14 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
       }
       /* rebuild symlinks in the installed tree */
       if (!symlinkedFiles.empty()) {
-        std::list<std::pair<std::string, std::string> >::iterator symlinkedIt;
+        std::vector<std::pair<std::string, std::string> >::iterator
+          symlinkedIt;
         std::string curDir = cmSystemTools::GetCurrentWorkingDirectory();
         std::string goToDir = tempDir;
         goToDir += "/" + subdir;
         cmCPackLogger(cmCPackLog::LOG_DEBUG, "Change dir to: " << goToDir
                                                                << std::endl);
-        cmSystemTools::ChangeDirectory(goToDir);
+        cmWorkingDirectory workdir(goToDir);
         for (symlinkedIt = symlinkedFiles.begin();
              symlinkedIt != symlinkedFiles.end(); ++symlinkedIt) {
           cmCPackLogger(cmCPackLog::LOG_DEBUG, "Will create a symlink: "
@@ -408,7 +409,6 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
         }
         cmCPackLogger(cmCPackLog::LOG_DEBUG, "Going back to: " << curDir
                                                                << std::endl);
-        cmSystemTools::ChangeDirectory(curDir);
       }
     }
   }
@@ -620,7 +620,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
                           << installComponent << std::endl);
         }
 
-        cmake cm;
+        cmake cm(cmake::RoleScript);
         cm.SetHomeDirectory("");
         cm.SetHomeOutputDirectory("");
         cm.GetCurrentSnapshot().SetDefaultDefinitions();
@@ -795,6 +795,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
           cmsys::Glob glA;
           glA.RecurseOn();
           glA.SetRecurseListDirs(true);
+          glA.SetRecurseThroughSymlinks(false);
           glA.FindFiles(findExpr);
           std::vector<std::string> filesAfter = glA.GetFiles();
           std::sort(filesAfter.begin(), filesAfter.end());
@@ -810,8 +811,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
           for (fit = result.begin(); fit != diff; ++fit) {
             localFileName =
               cmSystemTools::RelativePath(InstallPrefix, fit->c_str());
-            localFileName = localFileName.substr(
-              localFileName.find_first_not_of('/'), std::string::npos);
+            localFileName =
+              localFileName.substr(localFileName.find_first_not_of('/'));
             Components[installComponent].Files.push_back(localFileName);
             cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file <"
                             << localFileName << "> to component <"
@@ -1396,6 +1397,11 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
       component->ArchiveFile = archiveFile;
     }
 
+    const char* plist = this->GetOption(macroPrefix + "_PLIST");
+    if (plist && *plist) {
+      component->Plist = plist;
+    }
+
     const char* groupName = this->GetOption(macroPrefix + "_GROUP");
     if (groupName && *groupName) {
       component->Group = GetComponentGroup(projectName, groupName);
diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h
index 5354fca..45777fa 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackGenerator_h
 #define cmCPackGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <map>
 #include <sstream>
@@ -13,25 +13,10 @@
 #include "cmCPackComponentGroup.h"
 #include "cmSystemTools.h"
 
-class cmCPackGenerator;
 class cmCPackLog;
 class cmInstalledFile;
 class cmMakefile;
 
-#define cmCPackTypeMacro(klass, superclass)                                   \
-  typedef superclass Superclass;                                              \
-  const char* GetNameOfClass() CM_OVERRIDE { return #klass; }                 \
-  static cmCPackGenerator* CreateGenerator() { return new klass; }            \
-  class cmCPackTypeMacro_UseTrailingSemicolon
-
-#define cmCPackLogger(logType, msg)                                           \
-  do {                                                                        \
-    std::ostringstream cmCPackLog_msg;                                        \
-    cmCPackLog_msg << msg;                                                    \
-    this->Logger->Log(logType, __FILE__, __LINE__,                            \
-                      cmCPackLog_msg.str().c_str());                          \
-  } while (false)
-
 /** \class cmCPackGenerator
  * \brief A superclass of all CPack Generators
  *
@@ -312,4 +297,18 @@ private:
   cmMakefile* MakefileMap;
 };
 
+#define cmCPackTypeMacro(klass, superclass)                                   \
+  typedef superclass Superclass;                                              \
+  const char* GetNameOfClass() CM_OVERRIDE { return #klass; }                 \
+  static cmCPackGenerator* CreateGenerator() { return new klass; }            \
+  class cmCPackTypeMacro_UseTrailingSemicolon
+
+#define cmCPackLogger(logType, msg)                                           \
+  do {                                                                        \
+    std::ostringstream cmCPackLog_msg;                                        \
+    cmCPackLog_msg << msg;                                                    \
+    this->Logger->Log(logType, __FILE__, __LINE__,                            \
+                      cmCPackLog_msg.str().c_str());                          \
+  } while (false)
+
 #endif
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index b012f01..31f48c7 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackGeneratorFactory.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 #include <ostream>
 #include <utility>
 
diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h
index 4ee0bc1..7f633e4 100644
--- a/Source/CPack/cmCPackGeneratorFactory.h
+++ b/Source/CPack/cmCPackGeneratorFactory.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackGeneratorFactory_h
 #define cmCPackGeneratorFactory_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <string>
diff --git a/Source/CPack/cmCPackLog.cxx b/Source/CPack/cmCPackLog.cxx
index 7d5c192..5c71239 100644
--- a/Source/CPack/cmCPackLog.cxx
+++ b/Source/CPack/cmCPackLog.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackLog.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 #include <iostream>
 
 #include "cmGeneratedFileStream.h"
diff --git a/Source/CPack/cmCPackLog.h b/Source/CPack/cmCPackLog.h
index a988ccc..10deda4 100644
--- a/Source/CPack/cmCPackLog.h
+++ b/Source/CPack/cmCPackLog.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackLog_h
 #define cmCPackLog_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <ostream>
 #include <string.h>
@@ -85,12 +85,12 @@ public:
 
   //! Set the various prefixes for the logging. SetPrefix sets the generic
   // prefix that overwrittes missing ones.
-  void SetPrefix(std::string pfx) { this->Prefix = pfx; }
-  void SetOutputPrefix(std::string pfx) { this->OutputPrefix = pfx; }
-  void SetVerbosePrefix(std::string pfx) { this->VerbosePrefix = pfx; }
-  void SetDebugPrefix(std::string pfx) { this->DebugPrefix = pfx; }
-  void SetWarningPrefix(std::string pfx) { this->WarningPrefix = pfx; }
-  void SetErrorPrefix(std::string pfx) { this->ErrorPrefix = pfx; }
+  void SetPrefix(std::string const& pfx) { this->Prefix = pfx; }
+  void SetOutputPrefix(std::string const& pfx) { this->OutputPrefix = pfx; }
+  void SetVerbosePrefix(std::string const& pfx) { this->VerbosePrefix = pfx; }
+  void SetDebugPrefix(std::string const& pfx) { this->DebugPrefix = pfx; }
+  void SetWarningPrefix(std::string const& pfx) { this->WarningPrefix = pfx; }
+  void SetErrorPrefix(std::string const& pfx) { this->ErrorPrefix = pfx; }
 
 private:
   bool Verbose;
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 1940953..9697a38 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -8,9 +8,9 @@
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 
+#include "cmsys/Directory.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
-#include <cmsys/Directory.hxx>
-#include <cmsys/RegularExpression.hxx>
 #include <map>
 #include <sstream>
 #include <stdlib.h>
@@ -76,7 +76,7 @@ int cmCPackNSISGenerator::PackageFiles()
       }
 
       // Strip off the component part of the path.
-      fileN = fileN.substr(pos + 1, std::string::npos);
+      fileN = fileN.substr(pos + 1);
     }
     std::replace(fileN.begin(), fileN.end(), '/', '\\');
 
@@ -106,7 +106,7 @@ int cmCPackNSISGenerator::PackageFiles()
         componentName = fileN.substr(0, slash);
 
         // Strip off the component part of the path.
-        fileN = fileN.substr(slash + 1, std::string::npos);
+        fileN = fileN.substr(slash + 1);
       }
     }
     std::replace(fileN.begin(), fileN.end(), '/', '\\');
diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h
index b4bf2d4..77be325 100644
--- a/Source/CPack/cmCPackNSISGenerator.h
+++ b/Source/CPack/cmCPackNSISGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackNSISGenerator_h
 #define cmCPackNSISGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackGenerator.h"
 
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 0d8dc48..8ea88a8 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -3,12 +3,12 @@
 #include "cmCPackOSXX11Generator.h"
 
 #include <sstream>
-#include <sys/stat.h>
 
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
+#include "cm_sys_stat.h"
 
 cmCPackOSXX11Generator::cmCPackOSXX11Generator()
 {
diff --git a/Source/CPack/cmCPackOSXX11Generator.h b/Source/CPack/cmCPackOSXX11Generator.h
index 1918e21..0eebc6d 100644
--- a/Source/CPack/cmCPackOSXX11Generator.h
+++ b/Source/CPack/cmCPackOSXX11Generator.h
@@ -3,7 +3,8 @@
 #ifndef cmCPackOSXX11Generator_h
 #define cmCPackOSXX11Generator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 
 #include "cmCPackGenerator.h"
diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h
index 1e96a62..f873c59 100644
--- a/Source/CPack/cmCPackPKGGenerator.h
+++ b/Source/CPack/cmCPackPKGGenerator.h
@@ -3,7 +3,8 @@
 #ifndef cmCPackPKGGenerator_h
 #define cmCPackPKGGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <set>
 #include <sstream>
 #include <string>
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index 8000d6e..8db7cfb 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackPackageMakerGenerator.h"
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <assert.h>
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
 #include <map>
 #include <sstream>
 #include <stdio.h>
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.h b/Source/CPack/cmCPackPackageMakerGenerator.h
index d4c6744..6274515 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.h
+++ b/Source/CPack/cmCPackPackageMakerGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackPackageMakerGenerator_h
 #define cmCPackPackageMakerGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackGenerator.h"
 #include "cmCPackPKGGenerator.h"
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
index a5a18dc..1389eaa 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -59,12 +59,25 @@ int cmCPackProductBuildGenerator::PackageFiles()
     }
   }
 
-  // Copy or create all of the resource files we need.
   std::string resDir = packageDirFileName + "/Contents";
+
+  if (this->IsSet("CPACK_PRODUCTBUILD_RESOURCES_DIR")) {
+    std::string userResDir =
+      this->GetOption("CPACK_PRODUCTBUILD_RESOURCES_DIR");
+
+    if (!cmSystemTools::CopyADirectory(userResDir, resDir)) {
+      cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
+                      << std::endl);
+      return 0;
+    }
+  }
+
+  // Copy or create all of the resource files we need.
   if (!this->CopyCreateResourceFile("License", resDir) ||
       !this->CopyCreateResourceFile("ReadMe", resDir) ||
       !this->CopyCreateResourceFile("Welcome", resDir)) {
-    cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
+    cmCPackLogger(cmCPackLog::LOG_ERROR,
+                  "Problem copying the License, ReadMe and Welcome files"
                     << std::endl);
     return 0;
   }
@@ -223,6 +236,10 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
                                   : " --keychain \"" + keychainPath + "\"")
          << " \"" << packageFile << "\"";
 
+  if (component && !component->Plist.empty()) {
+    pkgCmd << " --component-plist \"" << component->Plist << "\"";
+  }
+
   // Run ProductBuild
   return RunProductBuild(pkgCmd.str());
 }
diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h
index b6da470..12093a0 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.h
+++ b/Source/CPack/cmCPackProductBuildGenerator.h
@@ -3,7 +3,8 @@
 #ifndef cmCPackProductBuildGenerator_h
 #define cmCPackProductBuildGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 
 #include "cmCPackGenerator.h"
diff --git a/Source/CPack/cmCPackRPMGenerator.h b/Source/CPack/cmCPackRPMGenerator.h
index 4d48bd8..52cfc13 100644
--- a/Source/CPack/cmCPackRPMGenerator.h
+++ b/Source/CPack/cmCPackRPMGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackRPMGenerator_h
 #define cmCPackRPMGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackGenerator.h"
 
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index 682394e..c541614 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -2,19 +2,16 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackSTGZGenerator.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <sstream>
 #include <stdio.h>
 #include <string>
 #include <vector>
 
-#include <sys/types.h>
-// include sys/stat.h after sys/types.h
-#include <sys/stat.h>
-
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
 #include "cmSystemTools.h"
+#include "cm_sys_stat.h"
 
 cmCPackSTGZGenerator::cmCPackSTGZGenerator()
 {
diff --git a/Source/CPack/cmCPackSTGZGenerator.h b/Source/CPack/cmCPackSTGZGenerator.h
index 4b9c1c6..8304e80 100644
--- a/Source/CPack/cmCPackSTGZGenerator.h
+++ b/Source/CPack/cmCPackSTGZGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackSTGZGenerator_h
 #define cmCPackSTGZGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackGenerator.h"
 #include "cmCPackTGZGenerator.h"
diff --git a/Source/CPack/cmCPackTGZGenerator.h b/Source/CPack/cmCPackTGZGenerator.h
index ee2e975..9426b3a 100644
--- a/Source/CPack/cmCPackTGZGenerator.h
+++ b/Source/CPack/cmCPackTGZGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackTGZGenerator_h
 #define cmCPackTGZGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackArchiveGenerator.h"
 #include "cmCPackGenerator.h"
diff --git a/Source/CPack/cmCPackTXZGenerator.h b/Source/CPack/cmCPackTXZGenerator.h
index 876ca7d..3b96e2d 100644
--- a/Source/CPack/cmCPackTXZGenerator.h
+++ b/Source/CPack/cmCPackTXZGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackTXZGenerator_h
 #define cmCPackTXZGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackArchiveGenerator.h"
 #include "cmCPackGenerator.h"
diff --git a/Source/CPack/cmCPackTarBZip2Generator.h b/Source/CPack/cmCPackTarBZip2Generator.h
index 42214fd..9b4b8f4 100644
--- a/Source/CPack/cmCPackTarBZip2Generator.h
+++ b/Source/CPack/cmCPackTarBZip2Generator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackTarBZip2Generator_h
 #define cmCPackTarBZip2Generator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackArchiveGenerator.h"
 #include "cmCPackGenerator.h"
diff --git a/Source/CPack/cmCPackTarCompressGenerator.h b/Source/CPack/cmCPackTarCompressGenerator.h
index 1476642..381d6eb 100644
--- a/Source/CPack/cmCPackTarCompressGenerator.h
+++ b/Source/CPack/cmCPackTarCompressGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackTarCompressGenerator_h
 #define cmCPackTarCompressGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackArchiveGenerator.h"
 #include "cmCPackGenerator.h"
diff --git a/Source/CPack/cmCPackZIPGenerator.h b/Source/CPack/cmCPackZIPGenerator.h
index 95b6489..00c8720 100644
--- a/Source/CPack/cmCPackZIPGenerator.h
+++ b/Source/CPack/cmCPackZIPGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackZIPGenerator_h
 #define cmCPackZIPGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCPackArchiveGenerator.h"
 #include "cmCPackGenerator.h"
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index af80cbf..a44bc3d 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -1,9 +1,9 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cmsys/CommandLineArguments.hxx>
-#include <cmsys/Encoding.hxx>
+#include "cmsys/CommandLineArguments.hxx"
+#include "cmsys/Encoding.hxx"
 #include <iostream>
 #include <map>
 #include <sstream>
@@ -13,7 +13,7 @@
 #include <vector>
 
 #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-#include <cmsys/ConsoleBuf.hxx>
+#include "cmsys/ConsoleBuf.hxx"
 #endif
 
 #include "cmCPackGenerator.h"
@@ -23,7 +23,6 @@
 #include "cmDocumentationEntry.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
-#include "cmState.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
 #include "cm_auto_ptr.hxx"
@@ -189,11 +188,10 @@ int main(int argc, char const* const* argv)
   cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
               "Read CPack config file: " << cpackConfigFile << std::endl);
 
-  cmake cminst;
+  cmake cminst(cmake::RoleScript);
   cminst.SetHomeDirectory("");
   cminst.SetHomeOutputDirectory("");
   cminst.GetCurrentSnapshot().SetDefaultDefinitions();
-  cminst.GetState()->RemoveUnscriptableCommands();
   cmGlobalGenerator cmgg(&cminst);
   CM_AUTO_PTR<cmMakefile> globalMF(
     new cmMakefile(&cmgg, cminst.GetCurrentSnapshot()));
diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx
index b42953b..94f39c2 100644
--- a/Source/CTest/cmCTestBZR.cxx
+++ b/Source/CTest/cmCTestBZR.cxx
@@ -8,8 +8,8 @@
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 
-#include <cm_expat.h>
-#include <cmsys/RegularExpression.hxx>
+#include "cm_expat.h"
+#include "cmsys/RegularExpression.hxx"
 #include <list>
 #include <map>
 #include <ostream>
@@ -151,22 +151,24 @@ std::string cmCTestBZR::LoadInfo()
   return rev;
 }
 
-void cmCTestBZR::NoteOldRevision()
+bool cmCTestBZR::NoteOldRevision()
 {
   this->OldRevision = this->LoadInfo();
   this->Log << "Revision before update: " << this->OldRevision << "\n";
   cmCTestLog(this->CTest, HANDLER_OUTPUT, "   Old revision of repository is: "
                << this->OldRevision << "\n");
   this->PriorRev.Rev = this->OldRevision;
+  return true;
 }
 
-void cmCTestBZR::NoteNewRevision()
+bool cmCTestBZR::NoteNewRevision()
 {
   this->NewRevision = this->LoadInfo();
   this->Log << "Revision after update: " << this->NewRevision << "\n";
   cmCTestLog(this->CTest, HANDLER_OUTPUT, "   New revision of repository is: "
                << this->NewRevision << "\n");
   this->Log << "URL = " << this->URL << "\n";
+  return true;
 }
 
 class cmCTestBZR::LogParser : public cmCTestVC::OutputLogger,
@@ -386,7 +388,7 @@ bool cmCTestBZR::UpdateImpl()
   return this->RunUpdateCommand(&bzr_update[0], &out, &err);
 }
 
-void cmCTestBZR::LoadRevisions()
+bool cmCTestBZR::LoadRevisions()
 {
   cmCTestLog(this->CTest, HANDLER_OUTPUT,
              "   Gathering version information (one . per revision):\n"
@@ -400,7 +402,7 @@ void cmCTestBZR::LoadRevisions()
     // DoRevision takes care of discarding the information about OldRevision
     revs = this->OldRevision + ".." + this->NewRevision;
   } else {
-    return;
+    return true;
   }
 
   // Run "bzr log" to get all global revisions of interest.
@@ -415,6 +417,7 @@ void cmCTestBZR::LoadRevisions()
     this->RunChild(bzr_log, &out, &err);
   }
   cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
+  return true;
 }
 
 class cmCTestBZR::StatusParser : public cmCTestVC::LineParser
@@ -460,7 +463,7 @@ private:
   }
 };
 
-void cmCTestBZR::LoadModifications()
+bool cmCTestBZR::LoadModifications()
 {
   // Run "bzr status" which reports local modifications.
   const char* bzr = this->CommandLineTool.c_str();
@@ -468,4 +471,5 @@ void cmCTestBZR::LoadModifications()
   StatusParser out(this, "status-out> ");
   OutputLogger err(this->Log, "status-err> ");
   this->RunChild(bzr_status, &out, &err);
+  return true;
 }
diff --git a/Source/CTest/cmCTestBZR.h b/Source/CTest/cmCTestBZR.h
index e7af90b..2e8e88f 100644
--- a/Source/CTest/cmCTestBZR.h
+++ b/Source/CTest/cmCTestBZR.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestBZR_h
 #define cmCTestBZR_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGlobalVC.h"
 
@@ -26,16 +26,16 @@ public:
 
 private:
   // Implement cmCTestVC internal API.
-  void NoteOldRevision() CM_OVERRIDE;
-  void NoteNewRevision() CM_OVERRIDE;
+  bool NoteOldRevision() CM_OVERRIDE;
+  bool NoteNewRevision() CM_OVERRIDE;
   bool UpdateImpl() CM_OVERRIDE;
 
   // URL of repository directory checked out in the working tree.
   std::string URL;
 
   std::string LoadInfo();
-  void LoadModifications() CM_OVERRIDE;
-  void LoadRevisions() CM_OVERRIDE;
+  bool LoadModifications() CM_OVERRIDE;
+  bool LoadRevisions() CM_OVERRIDE;
 
   // Parsing helper classes.
   class InfoParser;
diff --git a/Source/CTest/cmCTestBatchTestHandler.h b/Source/CTest/cmCTestBatchTestHandler.h
index 44db252..4a5dac1 100644
--- a/Source/CTest/cmCTestBatchTestHandler.h
+++ b/Source/CTest/cmCTestBatchTestHandler.h
@@ -3,10 +3,10 @@
 #ifndef cmCTestBatchTestHandler_h
 #define cmCTestBatchTestHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cmCTestMultiProcessHandler.h>
-#include <cmsys/FStream.hxx>
+#include "cmCTestMultiProcessHandler.h"
+#include "cmsys/FStream.hxx"
 #include <string>
 
 /** \class cmCTestBatchTestHandler
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 6780a0e..cc29071 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -6,9 +6,10 @@
 #include "cmCTestTestHandler.h"
 #include "cmGlobalGenerator.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 #include "cmake.h"
 
-#include <cmsys/Process.h>
+#include "cmsys/Process.h"
 #include <stdlib.h>
 
 cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
@@ -42,7 +43,7 @@ int cmCTestBuildAndTestHandler::ProcessHandler()
 int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
                                          std::ostringstream& out,
                                          std::string& cmakeOutString,
-                                         std::string& cwd, cmake* cm)
+                                         cmake* cm)
 {
   unsigned int k;
   std::vector<std::string> args;
@@ -85,8 +86,6 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
   if (cm->Run(args) != 0) {
     out << "Error: cmake execution failed\n";
     out << cmakeOutString << "\n";
-    // return to the original directory
-    cmSystemTools::ChangeDirectory(cwd);
     if (outstring) {
       *outstring = out.str();
     } else {
@@ -99,8 +98,6 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
     if (cm->Run(args) != 0) {
       out << "Error: cmake execution failed\n";
       out << cmakeOutString << "\n";
-      // return to the original directory
-      cmSystemTools::ChangeDirectory(cwd);
       if (outstring) {
         *outstring = out.str();
       } else {
@@ -170,7 +167,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
     return 1;
   }
 
-  cmake cm;
+  cmake cm(cmake::RoleProject);
   cm.SetHomeDirectory("");
   cm.SetHomeOutputDirectory("");
   std::string cmakeOutString;
@@ -199,13 +196,12 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
   double clock_start = cmSystemTools::GetTime();
 
   // make sure the binary dir is there
-  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
   out << "Internal cmake changing into directory: " << this->BinaryDir
       << std::endl;
   if (!cmSystemTools::FileIsDirectory(this->BinaryDir)) {
     cmSystemTools::MakeDirectory(this->BinaryDir.c_str());
   }
-  cmSystemTools::ChangeDirectory(this->BinaryDir);
+  cmWorkingDirectory workdir(this->BinaryDir);
 
   if (this->BuildNoCMake) {
     // Make the generator available for the Build call below.
@@ -217,7 +213,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
     cm.LoadCache(this->BinaryDir);
   } else {
     // do the cmake step, no timeout here since it is not a sub process
-    if (this->RunCMake(outstring, out, cmakeOutString, cwd, &cm)) {
+    if (this->RunCMake(outstring, out, cmakeOutString, &cm)) {
       return 1;
     }
   }
@@ -304,8 +300,6 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
     } else {
       cmCTestLog(this->CTest, ERROR_MESSAGE, out.str());
     }
-    // return to the original directory
-    cmSystemTools::ChangeDirectory(cwd);
     return 1;
   }
 
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h
index 5885738..2e85e9f 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.h
+++ b/Source/CTest/cmCTestBuildAndTestHandler.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestBuildAndTestHandler_h
 #define cmCTestBuildAndTestHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGenericHandler.h"
 
@@ -46,7 +46,7 @@ protected:
   ///! Run CMake and build a test and then run it as a single test.
   int RunCMakeAndTest(std::string* output);
   int RunCMake(std::string* outstring, std::ostringstream& out,
-               std::string& cmakeOutString, std::string& cwd, cmake* cm);
+               std::string& cmakeOutString, cmake* cm);
 
   std::string Output;
 
diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h
index 9cc6f7e..9cf6a96 100644
--- a/Source/CTest/cmCTestBuildCommand.h
+++ b/Source/CTest/cmCTestBuildCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestBuildCommand_h
 #define cmCTestBuildCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestHandlerCommand.h"
 
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 1868a1e..18ef05c 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -11,9 +11,9 @@
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Process.h>
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Process.h"
 #include <set>
 #include <stdlib.h>
 #include <string.h>
@@ -596,10 +596,10 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
           // At this point we need to make this->SourceFile relative to
           // the source root of the project, so cvs links will work
           cmSystemTools::ConvertToUnixSlashes(cm->SourceFile);
-          if (cm->SourceFile.find("/.../") != cm->SourceFile.npos) {
+          if (cm->SourceFile.find("/.../") != std::string::npos) {
             cmSystemTools::ReplaceString(cm->SourceFile, "/.../", "");
             std::string::size_type p = cm->SourceFile.find('/');
-            if (p != cm->SourceFile.npos) {
+            if (p != std::string::npos) {
               cm->SourceFile =
                 cm->SourceFile.substr(p + 1, cm->SourceFile.size() - p);
             }
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index a2f6112..ef3cddf 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -3,12 +3,12 @@
 #ifndef cmCTestBuildHandler_h
 #define cmCTestBuildHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGenericHandler.h"
 
-#include <cmProcessOutput.h>
-#include <cmsys/RegularExpression.hxx>
+#include "cmProcessOutput.h"
+#include "cmsys/RegularExpression.hxx"
 #include <deque>
 #include <iosfwd>
 #include <stddef.h>
diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx
index 98bb678..fad360b 100644
--- a/Source/CTest/cmCTestCVS.cxx
+++ b/Source/CTest/cmCTestCVS.cxx
@@ -7,8 +7,8 @@
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <utility>
 
 cmCTestCVS::cmCTestCVS(cmCTest* ct, std::ostream& log)
diff --git a/Source/CTest/cmCTestCVS.h b/Source/CTest/cmCTestCVS.h
index d921b1a..1208cfa 100644
--- a/Source/CTest/cmCTestCVS.h
+++ b/Source/CTest/cmCTestCVS.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestCVS_h
 #define cmCTestCVS_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestVC.h"
 
diff --git a/Source/CTest/cmCTestConfigureCommand.h b/Source/CTest/cmCTestConfigureCommand.h
index 22d1217..917f5ab 100644
--- a/Source/CTest/cmCTestConfigureCommand.h
+++ b/Source/CTest/cmCTestConfigureCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestConfigureCommand_h
 #define cmCTestConfigureCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestHandlerCommand.h"
 
diff --git a/Source/CTest/cmCTestConfigureHandler.h b/Source/CTest/cmCTestConfigureHandler.h
index 7fa95ed..2b45282 100644
--- a/Source/CTest/cmCTestConfigureHandler.h
+++ b/Source/CTest/cmCTestConfigureHandler.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestConfigureHandler_h
 #define cmCTestConfigureHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGenericHandler.h"
 
diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h
index bf42aa1..78c4f61 100644
--- a/Source/CTest/cmCTestCoverageCommand.h
+++ b/Source/CTest/cmCTestCoverageCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestCoverageCommand_h
 #define cmCTestCoverageCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestHandlerCommand.h"
 
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 989c096..877cd24 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -12,14 +12,15 @@
 #include "cmParseJacocoCoverage.h"
 #include "cmParsePHPCoverage.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 #include "cmXMLWriter.h"
 #include "cmake.h"
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/Process.h"
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/Process.h>
-#include <cmsys/RegularExpression.hxx>
 #include <iomanip>
 #include <iterator>
 #include <sstream>
@@ -102,6 +103,7 @@ public:
     return this->PipeState;
   }
   int GetProcessState() { return this->PipeState; }
+
 private:
   int PipeState;
   cmsysProcess* Process;
@@ -895,7 +897,7 @@ int cmCTestCoverageHandler::HandleBlanketJSCoverage(
     cmsys::ifstream in(files[fileEntry].c_str());
     cmSystemTools::GetLineFromStream(in, line);
     cmSystemTools::GetLineFromStream(in, line);
-    if (line.find("node-jscoverage") != line.npos) {
+    if (line.find("node-jscoverage") != std::string::npos) {
       blanketFiles.push_back(files[fileEntry]);
     }
   }
@@ -969,9 +971,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
 
   std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
   std::string tempDir = testingDir + "/CoverageInfo";
-  std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
   cmSystemTools::MakeDirectory(tempDir.c_str());
-  cmSystemTools::ChangeDirectory(tempDir);
+  cmWorkingDirectory workdir(tempDir);
 
   int gcovStyle = 0;
 
@@ -1222,7 +1223,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
               // Initially all entries are -1 (not used). If we get coverage
               // information, increment it to 0 first.
               if (vec[lineIdx] < 0) {
-                if (cov > 0 || prefix.find('#') != prefix.npos) {
+                if (cov > 0 || prefix.find('#') != std::string::npos) {
                   vec[lineIdx] = 0;
                 }
               }
@@ -1294,7 +1295,6 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
     }
   }
 
-  cmSystemTools::ChangeDirectory(currentDirectory);
   return file_count;
 }
 
@@ -1340,7 +1340,6 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
     return 0;
   }
   std::string testingDir = this->CTest->GetBinaryDir();
-  std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
 
   std::set<std::string> missingFiles;
 
@@ -1362,7 +1361,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
     cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "." << std::flush,
                        this->Quiet);
     std::string fileDir = cmSystemTools::GetFilenamePath(*it);
-    cmSystemTools::ChangeDirectory(fileDir);
+    cmWorkingDirectory workdir(fileDir);
     std::string command = "\"" + lcovCommand + "\" " + lcovExtraFlags + " ";
 
     cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -1526,7 +1525,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
                 // Initially all entries are -1 (not used). If we get coverage
                 // information, increment it to 0 first.
                 if (vec[lineIdx] < 0) {
-                  if (cov > 0 || prefix.find('#') != prefix.npos) {
+                  if (cov > 0 || prefix.find('#') != std::string::npos) {
                     vec[lineIdx] = 0;
                   }
                 }
@@ -1552,7 +1551,6 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
     }
   }
 
-  cmSystemTools::ChangeDirectory(currentDirectory);
   return file_count;
 }
 
@@ -1591,13 +1589,8 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
   gl.RecurseOff(); // No need of recurse if -prof_dir${BUILD_DIR} flag is
                    // used while compiling.
   gl.RecurseThroughSymlinksOff();
-  std::string prevBinaryDir;
   std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory");
-  if (cmSystemTools::ChangeDirectory(buildDir)) {
-    cmCTestLog(this->CTest, ERROR_MESSAGE, "Error changing directory to "
-                 << buildDir << std::endl);
-    return false;
-  }
+  cmWorkingDirectory workdir(buildDir);
 
   // Run profmerge to merge all *.dyn files into dpi files
   if (!cmSystemTools::RunSingleCommand("profmerge")) {
@@ -1605,11 +1598,9 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
     return false;
   }
 
-  prevBinaryDir = cmSystemTools::GetCurrentWorkingDirectory();
-
   // DPI file should appear in build directory
   std::string daGlob;
-  daGlob = prevBinaryDir;
+  daGlob = buildDir;
   daGlob += "/*.dpi";
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                      "   looking for dpi files in: " << daGlob << std::endl,
@@ -1646,11 +1637,7 @@ int cmCTestCoverageHandler::HandleTracePyCoverage(
 
   std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
   std::string tempDir = testingDir + "/CoverageInfo";
-  std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
   cmSystemTools::MakeDirectory(tempDir.c_str());
-  cmSystemTools::ChangeDirectory(tempDir);
-
-  cmSystemTools::ChangeDirectory(currentDirectory);
 
   std::vector<std::string>::iterator fileIt;
   int file_count = 0;
@@ -1737,7 +1724,6 @@ int cmCTestCoverageHandler::HandleTracePyCoverage(
     }
     ++file_count;
   }
-  cmSystemTools::ChangeDirectory(currentDirectory);
   return file_count;
 }
 
@@ -2142,7 +2128,7 @@ bool cmCTestCoverageHandler::GetNextInt(std::string const& inputLine,
   std::string::size_type start = pos;
   pos = inputLine.find(',', start);
   value = atoi(inputLine.substr(start, pos).c_str());
-  if (pos == inputLine.npos) {
+  if (pos == std::string::npos) {
     return true;
   }
   pos++;
@@ -2156,7 +2142,7 @@ bool cmCTestCoverageHandler::ParseBullsEyeCovsrcLine(
 {
   // find the first comma
   std::string::size_type pos = inputLine.find(',');
-  if (pos == inputLine.npos) {
+  if (pos == std::string::npos) {
     cmCTestLog(this->CTest, ERROR_MESSAGE,
                "Error parsing string : " << inputLine << "\n");
     return false;
@@ -2183,7 +2169,7 @@ bool cmCTestCoverageHandler::ParseBullsEyeCovsrcLine(
     return false;
   }
   // should be at the end now
-  if (pos != inputLine.npos) {
+  if (pos != std::string::npos) {
     cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing input : "
                  << inputLine << " last pos not npos =  " << pos << "\n");
   }
@@ -2237,7 +2223,8 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir)
     if (line.empty() || line[0] == '#') {
       // Ignore blank and comment lines.
       continue;
-    } else if (line[0] == ' ') {
+    }
+    if (line[0] == ' ') {
       // Label lines appear indented by one space.
       std::string label = line.substr(1);
       int id = this->GetLabelId(label);
diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h
index 339b5d7..933f606 100644
--- a/Source/CTest/cmCTestCoverageHandler.h
+++ b/Source/CTest/cmCTestCoverageHandler.h
@@ -3,11 +3,11 @@
 #ifndef cmCTestCoverageHandler_h
 #define cmCTestCoverageHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGenericHandler.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <iosfwd>
 #include <map>
 #include <set>
diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx
index ab1412d..b80ea5a 100644
--- a/Source/CTest/cmCTestCurl.cxx
+++ b/Source/CTest/cmCTestCurl.cxx
@@ -5,7 +5,7 @@
 #include "cmCTest.h"
 #include "cmSystemTools.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 #include <ostream>
 #include <stdio.h>
 
@@ -143,9 +143,17 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
   ::curl_easy_setopt(this->Curl, CURLOPT_WRITEFUNCTION,
                      curlWriteMemoryCallback);
   ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGFUNCTION, curlDebugCallback);
-  // Be sure to set Content-Type to satisfy fussy modsecurity rules
+  // Set Content-Type to satisfy fussy modsecurity rules.
   struct curl_slist* headers =
     ::curl_slist_append(CM_NULLPTR, "Content-Type: text/xml");
+  // Add any additional headers that the user specified.
+  for (std::vector<std::string>::const_iterator h = this->HttpHeaders.begin();
+       h != this->HttpHeaders.end(); ++h) {
+    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+                       "   Add HTTP Header: \"" << *h << "\"" << std::endl,
+                       this->Quiet);
+    headers = ::curl_slist_append(headers, h->c_str());
+  }
   ::curl_easy_setopt(this->Curl, CURLOPT_HTTPHEADER, headers);
   std::vector<char> responseData;
   std::vector<char> debugData;
@@ -203,7 +211,22 @@ bool cmCTestCurl::HttpRequest(std::string const& url,
   ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGDATA, (void*)&debugData);
   ::curl_easy_setopt(this->Curl, CURLOPT_FAILONERROR, 1);
 
+  // Add headers if any were specified.
+  struct curl_slist* headers = CM_NULLPTR;
+  if (!this->HttpHeaders.empty()) {
+    for (std::vector<std::string>::const_iterator h =
+           this->HttpHeaders.begin();
+         h != this->HttpHeaders.end(); ++h) {
+      cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+                         "   Add HTTP Header: \"" << *h << "\"" << std::endl,
+                         this->Quiet);
+      headers = ::curl_slist_append(headers, h->c_str());
+    }
+  }
+
+  ::curl_easy_setopt(this->Curl, CURLOPT_HTTPHEADER, headers);
   CURLcode res = ::curl_easy_perform(this->Curl);
+  ::curl_slist_free_all(headers);
 
   if (!responseData.empty()) {
     response = std::string(responseData.begin(), responseData.end());
diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h
index cdce393..427a392 100644
--- a/Source/CTest/cmCTestCurl.h
+++ b/Source/CTest/cmCTestCurl.h
@@ -3,9 +3,9 @@
 #ifndef cmCTestCurl_h
 #define cmCTestCurl_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
-#include <cm_curl.h>
+#include "cm_curl.h"
 #include <string>
 #include <vector>
 
@@ -23,6 +23,10 @@ public:
   // currently only supports CURLOPT_SSL_VERIFYPEER_OFF
   // and CURLOPT_SSL_VERIFYHOST_OFF
   void SetCurlOptions(std::vector<std::string> const& args);
+  void SetHttpHeaders(std::vector<std::string> const& v)
+  {
+    this->HttpHeaders = v;
+  }
   void SetUseHttp10On() { this->UseHttp10 = true; }
   void SetTimeOutSeconds(int s) { this->TimeOutSeconds = s; }
   void SetQuiet(bool b) { this->Quiet = b; }
@@ -35,6 +39,7 @@ protected:
 private:
   cmCTest* CTest;
   CURL* Curl;
+  std::vector<std::string> HttpHeaders;
   std::string HTTPProxyAuth;
   std::string HTTPProxy;
   curl_proxytype HTTPProxyType;
diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
index 4c1438b..503ed23 100644
--- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
+++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestEmptyBinaryDirectoryCommand_h
 #define cmCTestEmptyBinaryDirectoryCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestCommand.h"
 
@@ -42,14 +42,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "ctest_empty_binary_directory";
-  }
 };
 
 #endif
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index d30f6b3..230aedf 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestGIT.h"
 
-#include <cmsys/FStream.hxx>
-#include <cmsys/Process.h>
+#include "cmsys/FStream.hxx"
+#include "cmsys/Process.h"
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -67,19 +67,21 @@ std::string cmCTestGIT::GetWorkingRevision()
   return rev;
 }
 
-void cmCTestGIT::NoteOldRevision()
+bool cmCTestGIT::NoteOldRevision()
 {
   this->OldRevision = this->GetWorkingRevision();
   cmCTestLog(this->CTest, HANDLER_OUTPUT, "   Old revision of repository is: "
                << this->OldRevision << "\n");
   this->PriorRev.Rev = this->OldRevision;
+  return true;
 }
 
-void cmCTestGIT::NoteNewRevision()
+bool cmCTestGIT::NoteNewRevision()
 {
   this->NewRevision = this->GetWorkingRevision();
   cmCTestLog(this->CTest, HANDLER_OUTPUT, "   New revision of repository is: "
                << this->NewRevision << "\n");
+  return true;
 }
 
 std::string cmCTestGIT::FindGitDir()
@@ -189,9 +191,9 @@ bool cmCTestGIT::UpdateByFetchAndReset()
     std::string line;
     while (sha1.empty() && cmSystemTools::GetLineFromStream(fin, line)) {
       this->Log << "FETCH_HEAD> " << line << "\n";
-      if (line.find("\tnot-for-merge\t") == line.npos) {
+      if (line.find("\tnot-for-merge\t") == std::string::npos) {
         std::string::size_type pos = line.find('\t');
-        if (pos != line.npos) {
+        if (pos != std::string::npos) {
           sha1 = line.substr(0, pos);
         }
       }
@@ -607,7 +609,7 @@ private:
 char const cmCTestGIT::CommitParser::SectionSep[SectionCount] = { '\n', '\n',
                                                                   '\0' };
 
-void cmCTestGIT::LoadRevisions()
+bool cmCTestGIT::LoadRevisions()
 {
   // Use 'git rev-list ... | git diff-tree ...' to get revisions.
   std::string range = this->OldRevision + ".." + this->NewRevision;
@@ -634,9 +636,10 @@ void cmCTestGIT::LoadRevisions()
   out.Process("", 1);
 
   cmsysProcess_Delete(cp);
+  return true;
 }
 
-void cmCTestGIT::LoadModifications()
+bool cmCTestGIT::LoadModifications()
 {
   const char* git = this->CommandLineTool.c_str();
 
@@ -660,4 +663,5 @@ void cmCTestGIT::LoadModifications()
        ci != out.Changes.end(); ++ci) {
     this->DoModification(PathModified, ci->Path);
   }
+  return true;
 }
diff --git a/Source/CTest/cmCTestGIT.h b/Source/CTest/cmCTestGIT.h
index a655502..4bf8294 100644
--- a/Source/CTest/cmCTestGIT.h
+++ b/Source/CTest/cmCTestGIT.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestGIT_h
 #define cmCTestGIT_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGlobalVC.h"
 
@@ -28,8 +28,8 @@ private:
   unsigned int CurrentGitVersion;
   unsigned int GetGitVersion();
   std::string GetWorkingRevision();
-  void NoteOldRevision() CM_OVERRIDE;
-  void NoteNewRevision() CM_OVERRIDE;
+  bool NoteOldRevision() CM_OVERRIDE;
+  bool NoteNewRevision() CM_OVERRIDE;
   bool UpdateImpl() CM_OVERRIDE;
 
   std::string FindGitDir();
@@ -39,8 +39,8 @@ private:
   bool UpdateByCustom(std::string const& custom);
   bool UpdateInternal();
 
-  void LoadRevisions() CM_OVERRIDE;
-  void LoadModifications() CM_OVERRIDE;
+  bool LoadRevisions() CM_OVERRIDE;
+  bool LoadModifications() CM_OVERRIDE;
 
   // "public" needed by older Sun compilers
 public:
diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index 7638f45..19034c0 100644
--- a/Source/CTest/cmCTestGenericHandler.cxx
+++ b/Source/CTest/cmCTestGenericHandler.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestGenericHandler.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 #include <sstream>
 #include <utility>
 
diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h
index 2ebbe70..e881252 100644
--- a/Source/CTest/cmCTestGenericHandler.h
+++ b/Source/CTest/cmCTestGenericHandler.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestGenericHandler_h
 #define cmCTestGenericHandler_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <stddef.h>
diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx
index 08af179..25294b5 100644
--- a/Source/CTest/cmCTestGlobalVC.cxx
+++ b/Source/CTest/cmCTestGlobalVC.cxx
@@ -102,14 +102,15 @@ void cmCTestGlobalVC::WriteXMLGlobal(cmXMLWriter& xml)
 
 bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml)
 {
+  bool result = true;
   cmCTestLog(this->CTest, HANDLER_OUTPUT,
              "   Gathering version information (one . per revision):\n"
              "    "
                << std::flush);
-  this->LoadRevisions();
+  result = this->LoadRevisions() && result;
   cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
 
-  this->LoadModifications();
+  result = this->LoadModifications() && result;
 
   this->WriteXMLGlobal(xml);
 
@@ -119,5 +120,5 @@ bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml)
     this->WriteXMLDirectory(xml, di->first, di->second);
   }
 
-  return true;
+  return result;
 }
diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h
index 9a3757d..a5273d3 100644
--- a/Source/CTest/cmCTestGlobalVC.h
+++ b/Source/CTest/cmCTestGlobalVC.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestGlobalVC_h
 #define cmCTestGlobalVC_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestVC.h"
 
@@ -64,8 +64,8 @@ protected:
   virtual void DoRevision(Revision const& revision,
                           std::vector<Change> const& changes);
   virtual void DoModification(PathStatus status, std::string const& path);
-  virtual void LoadModifications() = 0;
-  virtual void LoadRevisions() = 0;
+  virtual bool LoadModifications() = 0;
+  virtual bool LoadRevisions() = 0;
 
   virtual void WriteXMLGlobal(cmXMLWriter& xml);
   void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx
index 8443c93..49f9a65 100644
--- a/Source/CTest/cmCTestHG.cxx
+++ b/Source/CTest/cmCTestHG.cxx
@@ -8,7 +8,7 @@
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <ostream>
 #include <vector>
 
@@ -104,19 +104,21 @@ std::string cmCTestHG::GetWorkingRevision()
   return rev;
 }
 
-void cmCTestHG::NoteOldRevision()
+bool cmCTestHG::NoteOldRevision()
 {
   this->OldRevision = this->GetWorkingRevision();
   cmCTestLog(this->CTest, HANDLER_OUTPUT, "   Old revision of repository is: "
                << this->OldRevision << "\n");
   this->PriorRev.Rev = this->OldRevision;
+  return true;
 }
 
-void cmCTestHG::NoteNewRevision()
+bool cmCTestHG::NoteNewRevision()
 {
   this->NewRevision = this->GetWorkingRevision();
   cmCTestLog(this->CTest, HANDLER_OUTPUT, "   New revision of repository is: "
                << this->NewRevision << "\n");
+  return true;
 }
 
 bool cmCTestHG::UpdateImpl()
@@ -262,7 +264,7 @@ private:
   }
 };
 
-void cmCTestHG::LoadRevisions()
+bool cmCTestHG::LoadRevisions()
 {
   // Use 'hg log' to get revisions in a xml format.
   //
@@ -293,9 +295,10 @@ void cmCTestHG::LoadRevisions()
   OutputLogger err(this->Log, "log-err> ");
   this->RunChild(hg_log, &out, &err);
   out.Process("</log>\n");
+  return true;
 }
 
-void cmCTestHG::LoadModifications()
+bool cmCTestHG::LoadModifications()
 {
   // Use 'hg status' to get modified files.
   const char* hg = this->CommandLineTool.c_str();
@@ -303,4 +306,5 @@ void cmCTestHG::LoadModifications()
   StatusParser out(this, "status-out> ");
   OutputLogger err(this->Log, "status-err> ");
   this->RunChild(hg_status, &out, &err);
+  return true;
 }
diff --git a/Source/CTest/cmCTestHG.h b/Source/CTest/cmCTestHG.h
index a81c347..ec9eaff 100644
--- a/Source/CTest/cmCTestHG.h
+++ b/Source/CTest/cmCTestHG.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestHG_h
 #define cmCTestHG_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGlobalVC.h"
 
@@ -26,12 +26,12 @@ public:
 
 private:
   std::string GetWorkingRevision();
-  void NoteOldRevision() CM_OVERRIDE;
-  void NoteNewRevision() CM_OVERRIDE;
+  bool NoteOldRevision() CM_OVERRIDE;
+  bool NoteNewRevision() CM_OVERRIDE;
   bool UpdateImpl() CM_OVERRIDE;
 
-  void LoadRevisions() CM_OVERRIDE;
-  void LoadModifications() CM_OVERRIDE;
+  bool LoadRevisions() CM_OVERRIDE;
+  bool LoadModifications() CM_OVERRIDE;
 
   // Parsing helper classes.
   class IdentifyParser;
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index a989b12..c99e450 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -6,6 +6,7 @@
 #include "cmCTestGenericHandler.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 #include "cmake.h"
 
 #include <sstream>
@@ -123,8 +124,8 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
     if (capureCMakeError) {
       this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                     "-1");
-      const char* err = this->GetError();
-      if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
+      std::string const err = this->GetName() + " " + this->GetError();
+      if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
         cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
       }
       // return success because failure is recorded in CAPTURE_CMAKE_ERROR
@@ -216,8 +217,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
       handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX]));
     }
   }
-  std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(
+  cmWorkingDirectory workdir(
     this->CTest->GetCTestConfiguration("BuildDirectory"));
   int res = handler->ProcessHandler();
   if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) {
@@ -243,7 +243,6 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
     this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                   returnString);
   }
-  cmSystemTools::ChangeDirectory(current_dir);
   return true;
 }
 
diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h
index c86841f..0ea0612 100644
--- a/Source/CTest/cmCTestHandlerCommand.h
+++ b/Source/CTest/cmCTestHandlerCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestHandlerCommand_h
 #define cmCTestHandlerCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestCommand.h"
 
@@ -25,6 +25,11 @@ public:
   cmCTestHandlerCommand();
 
   /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual std::string GetName() const = 0;
+
+  /**
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    */
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index 03e0319..5b21351 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -2,11 +2,11 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestLaunch.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cmsys/FStream.hxx>
-#include <cmsys/Process.h>
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/Process.h"
+#include "cmsys/RegularExpression.hxx"
 #include <iostream>
 #include <stdlib.h>
 #include <string.h>
@@ -306,7 +306,8 @@ void cmCTestLaunch::LoadLabels()
     if (line.empty() || line[0] == '#') {
       // Ignore blank and comment lines.
       continue;
-    } else if (line[0] == ' ') {
+    }
+    if (line[0] == ' ') {
       // Label lines appear indented by one space.
       if (inTarget || inSource) {
         this->Labels.insert(line.c_str() + 1);
@@ -622,7 +623,7 @@ int cmCTestLaunch::Main(int argc, const char* const argv[])
 
 void cmCTestLaunch::LoadConfig()
 {
-  cmake cm;
+  cmake cm(cmake::RoleScript);
   cm.SetHomeDirectory("");
   cm.SetHomeOutputDirectory("");
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h
index fbc9e2b..29986ff 100644
--- a/Source/CTest/cmCTestLaunch.h
+++ b/Source/CTest/cmCTestLaunch.h
@@ -3,9 +3,9 @@
 #ifndef cmCTestLaunch_h
 #define cmCTestLaunch_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <set>
 #include <string>
 #include <vector>
diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx
index fd7c3a9..b9cae3b 100644
--- a/Source/CTest/cmCTestMemCheckCommand.cxx
+++ b/Source/CTest/cmCTestMemCheckCommand.cxx
@@ -3,6 +3,7 @@
 #include "cmCTestMemCheckCommand.h"
 
 #include <sstream>
+#include <string>
 #include <vector>
 
 #include "cmCTest.h"
diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h
index 458ebb0..fa59559 100644
--- a/Source/CTest/cmCTestMemCheckCommand.h
+++ b/Source/CTest/cmCTestMemCheckCommand.h
@@ -3,12 +3,10 @@
 #ifndef cmCTestMemCheckCommand_h
 #define cmCTestMemCheckCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestTestCommand.h"
 
-#include <string>
-
 class cmCTestGenericHandler;
 class cmCommand;
 
@@ -33,11 +31,6 @@ public:
     return ni;
   }
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "ctest_memcheck"; }
-
 protected:
   cmCTestGenericHandler* InitializeActualHandler() CM_OVERRIDE;
 
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 620e237..c35f0bc 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -7,9 +7,9 @@
 #include "cmXMLParser.h"
 #include "cmXMLWriter.h"
 
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <iostream>
 #include <sstream>
 #include <string.h>
@@ -801,7 +801,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
   std::vector<std::string> lines;
   cmSystemTools::Split(str.c_str(), lines);
   bool unlimitedOutput = false;
-  if (str.find("CTEST_FULL_OUTPUT") != str.npos ||
+  if (str.find("CTEST_FULL_OUTPUT") != std::string::npos ||
       this->CustomMaximumFailedTestOutputSize == 0) {
     unlimitedOutput = true;
   }
@@ -953,7 +953,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
       std::string& theLine = lines[cc];
       // check for command line arguments that are not escaped
       // correctly by BC
-      if (theLine.find("TargetArgs=") != theLine.npos) {
+      if (theLine.find("TargetArgs=") != std::string::npos) {
         // skip this because BC gets it wrong and we can't parse it
       } else if (!parser.ParseChunk(theLine.c_str(), theLine.size())) {
         cmCTestLog(this->CTest, ERROR_MESSAGE,
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index ff8b593..333c2e2 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestMemCheckHandler_h
 #define cmCTestMemCheckHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestTestHandler.h"
 
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index c1724ab..2c16a0d 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -7,11 +7,12 @@
 #include "cmCTestScriptHandler.h"
 #include "cmCTestTestHandler.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/String.hxx"
+#include "cmsys/SystemInformation.hxx"
 #include <algorithm>
-#include <cmsys/FStream.hxx>
-#include <cmsys/String.hxx>
-#include <cmsys/SystemInformation.hxx>
 #include <iomanip>
 #include <list>
 #include <math.h>
@@ -138,8 +139,7 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test)
     }
   }
 
-  std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(this->Properties[test]->Directory);
+  cmWorkingDirectory workdir(this->Properties[test]->Directory);
 
   // Lock the resources we'll be using
   this->LockResources(test);
@@ -163,10 +163,11 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test)
     this->TestRunningMap[test] = false;
     this->RunningCount -= GetProcessorsUsed(test);
     testRun->EndTest(this->Completed, this->Total, false);
-    this->Failed->push_back(this->Properties[test]->Name);
+    if (!this->Properties[test]->Disabled) {
+      this->Failed->push_back(this->Properties[test]->Name);
+    }
     delete testRun;
   }
-  cmSystemTools::ChangeDirectory(current_dir);
 }
 
 void cmCTestMultiProcessHandler::LockResources(int index)
@@ -560,7 +561,7 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList()
   // In parallel test runs repeatedly move dependencies of the tests on
   // the current dependency level to the next level until no
   // further dependencies exist.
-  while (priorityStack.back().size()) {
+  while (!priorityStack.back().empty()) {
     TestSet& previousSet = priorityStack.back();
     priorityStack.push_back(TestSet());
     TestSet& currentSet = priorityStack.back();
@@ -683,9 +684,7 @@ void cmCTestMultiProcessHandler::PrintTestList()
     count++;
     cmCTestTestHandler::cmCTestTestProperties& p = *it->second;
 
-    // push working dir
-    std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
-    cmSystemTools::ChangeDirectory(p.Directory);
+    cmWorkingDirectory workdir(p.Directory);
 
     cmCTestRunTest testRun(this->TestHandler);
     testRun.SetIndex(p.Index);
@@ -721,11 +720,13 @@ void cmCTestMultiProcessHandler::PrintTestList()
       std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex()))
         << indexStr.str(),
       this->Quiet);
-    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet);
-    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, p.Name << std::endl,
+    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " " << p.Name,
                        this->Quiet);
-    // pop working dir
-    cmSystemTools::ChangeDirectory(current_dir);
+    if (p.Disabled) {
+      cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " (Disabled)",
+                         this->Quiet);
+    }
+    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet);
   }
 
   cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index fe32e15..dccc2c8 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -3,9 +3,9 @@
 #ifndef cmCTestMultiProcessHandler_h
 #define cmCTestMultiProcessHandler_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
-#include <cmCTestTestHandler.h>
+#include "cmCTestTestHandler.h"
 #include <map>
 #include <set>
 #include <stddef.h>
diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx
index 41b45a8..c802216 100644
--- a/Source/CTest/cmCTestP4.cxx
+++ b/Source/CTest/cmCTestP4.cxx
@@ -7,8 +7,8 @@
 #include "cmProcessTools.h"
 #include "cmSystemTools.h"
 
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
-#include <cmsys/RegularExpression.hxx>
 #include <ostream>
 #include <time.h>
 #include <utility>
@@ -369,24 +369,26 @@ std::string cmCTestP4::GetWorkingRevision()
   return rev;
 }
 
-void cmCTestP4::NoteOldRevision()
+bool cmCTestP4::NoteOldRevision()
 {
   this->OldRevision = this->GetWorkingRevision();
 
   cmCTestLog(this->CTest, HANDLER_OUTPUT, "   Old revision of repository is: "
                << this->OldRevision << "\n");
   this->PriorRev.Rev = this->OldRevision;
+  return true;
 }
 
-void cmCTestP4::NoteNewRevision()
+bool cmCTestP4::NoteNewRevision()
 {
   this->NewRevision = this->GetWorkingRevision();
 
   cmCTestLog(this->CTest, HANDLER_OUTPUT, "   New revision of repository is: "
                << this->NewRevision << "\n");
+  return true;
 }
 
-void cmCTestP4::LoadRevisions()
+bool cmCTestP4::LoadRevisions()
 {
   std::vector<char const*> p4_changes;
   SetP4Options(p4_changes);
@@ -399,7 +401,7 @@ void cmCTestP4::LoadRevisions()
   if (this->OldRevision == "<unknown>" || this->NewRevision == "<unknown>") {
     cmCTestLog(this->CTest, HANDLER_OUTPUT, "   At least one of the revisions "
                  << "is unknown. No repository changes will be reported.\n");
-    return;
+    return false;
   }
 
   range.append("@")
@@ -418,7 +420,7 @@ void cmCTestP4::LoadRevisions()
   this->RunChild(&p4_changes[0], &out, &err);
 
   if (ChangeLists.empty()) {
-    return;
+    return true;
   }
 
   // p4 describe -s ... at 1111111,2222222
@@ -435,9 +437,10 @@ void cmCTestP4::LoadRevisions()
     OutputLogger errDescribe(this->Log, "p4_describe-err> ");
     this->RunChild(&p4_describe[0], &outDescribe, &errDescribe);
   }
+  return true;
 }
 
-void cmCTestP4::LoadModifications()
+bool cmCTestP4::LoadModifications()
 {
   std::vector<char const*> p4_diff;
   SetP4Options(p4_diff);
@@ -453,6 +456,7 @@ void cmCTestP4::LoadModifications()
   DiffParser out(this, "p4_diff-out> ");
   OutputLogger err(this->Log, "p4_diff-err> ");
   this->RunChild(&p4_diff[0], &out, &err);
+  return true;
 }
 
 bool cmCTestP4::UpdateCustom(const std::string& custom)
diff --git a/Source/CTest/cmCTestP4.h b/Source/CTest/cmCTestP4.h
index eadc4fb..e234efb 100644
--- a/Source/CTest/cmCTestP4.h
+++ b/Source/CTest/cmCTestP4.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestP4_h
 #define cmCTestP4_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGlobalVC.h"
 
@@ -51,13 +51,13 @@ private:
   void SetP4Options(std::vector<char const*>& options);
 
   std::string GetWorkingRevision();
-  void NoteOldRevision() CM_OVERRIDE;
-  void NoteNewRevision() CM_OVERRIDE;
+  bool NoteOldRevision() CM_OVERRIDE;
+  bool NoteNewRevision() CM_OVERRIDE;
   bool UpdateImpl() CM_OVERRIDE;
   bool UpdateCustom(const std::string& custom);
 
-  void LoadRevisions() CM_OVERRIDE;
-  void LoadModifications() CM_OVERRIDE;
+  bool LoadRevisions() CM_OVERRIDE;
+  bool LoadModifications() CM_OVERRIDE;
 
   class ChangesParser;
   class DescribeParser;
diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.h b/Source/CTest/cmCTestReadCustomFilesCommand.h
index e155595..5989fa0 100644
--- a/Source/CTest/cmCTestReadCustomFilesCommand.h
+++ b/Source/CTest/cmCTestReadCustomFilesCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestReadCustomFilesCommand_h
 #define cmCTestReadCustomFilesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestCommand.h"
 
@@ -40,11 +40,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "ctest_read_custom_files"; }
 };
 
 #endif
diff --git a/Source/CTest/cmCTestRunScriptCommand.h b/Source/CTest/cmCTestRunScriptCommand.h
index 01ed62e..9bd0965 100644
--- a/Source/CTest/cmCTestRunScriptCommand.h
+++ b/Source/CTest/cmCTestRunScriptCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestRunScriptCommand_h
 #define cmCTestRunScriptCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestCommand.h"
 
@@ -41,11 +41,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "ctest_run_script"; }
 };
 
 #endif
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index ac1644f..0c4269e 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -7,13 +7,14 @@
 #include "cmCTestTestHandler.h"
 #include "cmProcess.h"
 #include "cmSystemTools.h"
-
-#include <cmConfigure.h>
-#include <cm_curl.h>
-#include <cm_zlib.h>
-#include <cmsys/Base64.h>
-#include <cmsys/Process.h>
-#include <cmsys/RegularExpression.hxx>
+#include "cmWorkingDirectory.h"
+
+#include "cmConfigure.h"
+#include "cm_curl.h"
+#include "cm_zlib.h"
+#include "cmsys/Base64.h"
+#include "cmsys/Process.h"
+#include "cmsys/RegularExpression.hxx"
 #include <iomanip>
 #include <sstream>
 #include <stdio.h>
@@ -166,6 +167,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
   std::vector<std::pair<cmsys::RegularExpression, std::string> >::iterator
     passIt;
   bool forceFail = false;
+  bool skipped = false;
   bool outputTestErrorsToConsole = false;
   if (!this->TestProperties->RequiredRegularExpressions.empty() &&
       this->FailedDependencies.empty()) {
@@ -214,7 +216,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
     if (this->TestProperties->SkipReturnCode >= 0 &&
         this->TestProperties->SkipReturnCode == retVal) {
       this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+      std::ostringstream s;
+      s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode;
+      this->TestResult.CompletionStatus = s.str();
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Skipped ");
+      skipped = true;
     } else if ((success && !this->TestProperties->WillFail) ||
                (!success && this->TestProperties->WillFail)) {
       this->TestResult.Status = cmCTestTestHandler::COMPLETED;
@@ -252,6 +258,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
         cmCTestLog(this->CTest, HANDLER_OUTPUT, "Other");
         this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT;
     }
+  } else if ("Disabled" == this->TestResult.CompletionStatus) {
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run (Disabled) ");
   } else // cmsysProcess_State_Error
   {
     cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run ");
@@ -270,14 +278,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
     *this->TestHandler->LogFile << "Test time = " << buf << std::endl;
   }
 
-  // Set the working directory to the tests directory
-  std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(this->TestProperties->Directory);
-
-  this->DartProcessing();
-
-  // restore working directory
-  cmSystemTools::ChangeDirectory(oldpath);
+  // Set the working directory to the tests directory to process Dart files.
+  {
+    cmWorkingDirectory workdir(this->TestProperties->Directory);
+    this->DartProcessing();
+  }
 
   // if this is doing MemCheck then all the output needs to be put into
   // Output since that is what is parsed by cmCTestMemCheckHandler
@@ -335,7 +340,9 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
       compress ? this->CompressedOutput : this->ProcessOutput;
     this->TestResult.CompressOutput = compress;
     this->TestResult.ReturnValue = this->TestProcess->GetExitValue();
-    this->TestResult.CompletionStatus = "Completed";
+    if (!skipped) {
+      this->TestResult.CompletionStatus = "Completed";
+    }
     this->TestResult.ExecutionTime = this->TestProcess->GetTotalTime();
     this->MemCheckPostProcess();
     this->ComputeWeightedCost();
@@ -346,7 +353,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
     this->TestHandler->TestResults.push_back(this->TestResult);
   }
   delete this->TestProcess;
-  return passed;
+  return passed || skipped;
 }
 
 bool cmCTestRunTest::StartAgain()
@@ -356,11 +363,8 @@ bool cmCTestRunTest::StartAgain()
   }
   this->RunAgain = false; // reset
   // change to tests directory
-  std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(this->TestProperties->Directory);
+  cmWorkingDirectory workdir(this->TestProperties->Directory);
   this->StartTest(this->TotalNumberOfTests);
-  // change back
-  cmSystemTools::ChangeDirectory(current_dir);
   return true;
 }
 
@@ -418,6 +422,24 @@ bool cmCTestRunTest::StartTest(size_t total)
                << this->TestProperties->Index << ": "
                << this->TestProperties->Name << std::endl);
   this->ProcessOutput.clear();
+
+  // Return immediately if test is disabled
+  if (this->TestProperties->Disabled) {
+    this->TestResult.Properties = this->TestProperties;
+    this->TestResult.ExecutionTime = 0;
+    this->TestResult.CompressOutput = false;
+    this->TestResult.ReturnValue = -1;
+    this->TestResult.CompletionStatus = "Disabled";
+    this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+    this->TestResult.TestCount = this->TestProperties->Index;
+    this->TestResult.Name = this->TestProperties->Name;
+    this->TestResult.Path = this->TestProperties->Directory;
+    this->TestProcess = new cmProcess;
+    this->TestResult.Output = "Disabled";
+    this->TestResult.FullCommandLine = "";
+    return false;
+  }
+
   this->ComputeArguments();
   std::vector<std::string>& args = this->TestProperties->Args;
   this->TestResult.Properties = this->TestProperties;
@@ -442,7 +464,7 @@ bool cmCTestRunTest::StartTest(size_t total)
     cmCTestLog(this->CTest, HANDLER_OUTPUT, msg << std::endl);
     this->TestResult.Output = msg;
     this->TestResult.FullCommandLine = "";
-    this->TestResult.CompletionStatus = "Not Run";
+    this->TestResult.CompletionStatus = "Fixture dependency failed";
     this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
     return false;
   }
@@ -462,7 +484,7 @@ bool cmCTestRunTest::StartTest(size_t total)
     cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl);
     this->TestResult.Output = msg;
     this->TestResult.FullCommandLine = "";
-    this->TestResult.CompletionStatus = "Not Run";
+    this->TestResult.CompletionStatus = "Missing Configuration";
     this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
     return false;
   }
@@ -482,7 +504,7 @@ bool cmCTestRunTest::StartTest(size_t total)
                  "Unable to find required file: " << file << std::endl);
       this->TestResult.Output = "Unable to find required file: " + file;
       this->TestResult.FullCommandLine = "";
-      this->TestResult.CompletionStatus = "Not Run";
+      this->TestResult.CompletionStatus = "Required Files Missing";
       this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
       return false;
     }
@@ -498,7 +520,7 @@ bool cmCTestRunTest::StartTest(size_t total)
                "Unable to find executable: " << args[1] << std::endl);
     this->TestResult.Output = "Unable to find executable: " + args[1];
     this->TestResult.FullCommandLine = "";
-    this->TestResult.CompletionStatus = "Not Run";
+    this->TestResult.CompletionStatus = "Unable to find executable";
     this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
     return false;
   }
@@ -574,8 +596,7 @@ void cmCTestRunTest::ComputeArguments()
 void cmCTestRunTest::DartProcessing()
 {
   if (!this->ProcessOutput.empty() &&
-      this->ProcessOutput.find("<DartMeasurement") !=
-        this->ProcessOutput.npos) {
+      this->ProcessOutput.find("<DartMeasurement") != std::string::npos) {
     if (this->TestHandler->DartStuff.find(this->ProcessOutput.c_str())) {
       this->TestResult.DartString = this->TestHandler->DartStuff.match(1);
       // keep searching and replacing until none are left
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index ee4630a..d3bb229 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestRunTest_h
 #define cmCTestRunTest_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <set>
 #include <stddef.h>
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index 410e0d4..f60f78c 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -9,7 +9,7 @@
 #include "cmXMLParser.h"
 #include "cmXMLWriter.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <map>
 #include <ostream>
 #include <stdlib.h>
@@ -97,12 +97,14 @@ std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo)
   return rev;
 }
 
-void cmCTestSVN::NoteOldRevision()
+bool cmCTestSVN::NoteOldRevision()
 {
-  this->LoadRepositories();
+  if (!this->LoadRepositories()) {
+    return false;
+  }
 
-  std::list<SVNInfo>::iterator itbeg = this->Repositories.begin();
-  std::list<SVNInfo>::iterator itend = this->Repositories.end();
+  std::vector<SVNInfo>::iterator itbeg = this->Repositories.begin();
+  std::vector<SVNInfo>::iterator itend = this->Repositories.end();
   for (; itbeg != itend; itbeg++) {
     SVNInfo& svninfo = *itbeg;
     svninfo.OldRevision = this->LoadInfo(svninfo);
@@ -116,14 +118,17 @@ void cmCTestSVN::NoteOldRevision()
   // Set the global old revision to the one of the root
   this->OldRevision = this->RootInfo->OldRevision;
   this->PriorRev.Rev = this->OldRevision;
+  return true;
 }
 
-void cmCTestSVN::NoteNewRevision()
+bool cmCTestSVN::NoteNewRevision()
 {
-  this->LoadRepositories();
+  if (!this->LoadRepositories()) {
+    return false;
+  }
 
-  std::list<SVNInfo>::iterator itbeg = this->Repositories.begin();
-  std::list<SVNInfo>::iterator itend = this->Repositories.end();
+  std::vector<SVNInfo>::iterator itbeg = this->Repositories.begin();
+  std::vector<SVNInfo>::iterator itend = this->Repositories.end();
   for (; itbeg != itend; itbeg++) {
     SVNInfo& svninfo = *itbeg;
     svninfo.NewRevision = this->LoadInfo(svninfo);
@@ -153,6 +158,7 @@ void cmCTestSVN::NoteNewRevision()
 
   // Set the global new revision to the one of the root
   this->NewRevision = this->RootInfo->NewRevision;
+  return true;
 }
 
 void cmCTestSVN::GuessBase(SVNInfo& svninfo,
@@ -370,18 +376,20 @@ private:
   }
 };
 
-void cmCTestSVN::LoadRevisions()
+bool cmCTestSVN::LoadRevisions()
 {
+  bool result = true;
   // Get revisions for all the external repositories
-  std::list<SVNInfo>::iterator itbeg = this->Repositories.begin();
-  std::list<SVNInfo>::iterator itend = this->Repositories.end();
+  std::vector<SVNInfo>::iterator itbeg = this->Repositories.begin();
+  std::vector<SVNInfo>::iterator itend = this->Repositories.end();
   for (; itbeg != itend; itbeg++) {
     SVNInfo& svninfo = *itbeg;
-    LoadRevisions(svninfo);
+    result = this->LoadRevisions(svninfo) && result;
   }
+  return result;
 }
 
-void cmCTestSVN::LoadRevisions(SVNInfo& svninfo)
+bool cmCTestSVN::LoadRevisions(SVNInfo& svninfo)
 {
   // We are interested in every revision included in the update.
   std::string revs;
@@ -400,7 +408,7 @@ void cmCTestSVN::LoadRevisions(SVNInfo& svninfo)
   svn_log.push_back(svninfo.LocalPath.c_str());
   LogParser out(this, "log-out> ", svninfo);
   OutputLogger err(this->Log, "log-err> ");
-  this->RunSVNCommand(svn_log, &out, &err);
+  return this->RunSVNCommand(svn_log, &out, &err);
 }
 
 void cmCTestSVN::DoRevisionSVN(Revision const& revision,
@@ -468,7 +476,7 @@ private:
   }
 };
 
-void cmCTestSVN::LoadModifications()
+bool cmCTestSVN::LoadModifications()
 {
   // Run "svn status" which reports local modifications.
   std::vector<const char*> svn_status;
@@ -476,6 +484,7 @@ void cmCTestSVN::LoadModifications()
   StatusParser out(this, "status-out> ");
   OutputLogger err(this->Log, "status-err> ");
   this->RunSVNCommand(svn_status, &out, &err);
+  return true;
 }
 
 void cmCTestSVN::WriteXMLGlobal(cmXMLWriter& xml)
@@ -521,10 +530,10 @@ private:
   }
 };
 
-void cmCTestSVN::LoadRepositories()
+bool cmCTestSVN::LoadRepositories()
 {
   if (!this->Repositories.empty()) {
-    return;
+    return true;
   }
 
   // Info for root repository
@@ -536,7 +545,7 @@ void cmCTestSVN::LoadRepositories()
   svn_status.push_back("status");
   ExternalParser out(this, "external-out> ");
   OutputLogger err(this->Log, "external-err> ");
-  this->RunSVNCommand(svn_status, &out, &err);
+  return this->RunSVNCommand(svn_status, &out, &err);
 }
 
 std::string cmCTestSVN::SVNInfo::BuildLocalPath(std::string const& path) const
diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h
index c0348c2..46b0778 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -3,12 +3,11 @@
 #ifndef cmCTestSVN_h
 #define cmCTestSVN_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGlobalVC.h"
 
 #include <iosfwd>
-#include <list>
 #include <string>
 #include <vector>
 
@@ -30,8 +29,8 @@ public:
 private:
   // Implement cmCTestVC internal API.
   void CleanupImpl() CM_OVERRIDE;
-  void NoteOldRevision() CM_OVERRIDE;
-  void NoteNewRevision() CM_OVERRIDE;
+  bool NoteOldRevision() CM_OVERRIDE;
+  bool NoteNewRevision() CM_OVERRIDE;
   bool UpdateImpl() CM_OVERRIDE;
 
   bool RunSVNCommand(std::vector<char const*> const& parameters,
@@ -71,16 +70,16 @@ private:
   friend struct Revision;
 
   // Info of all the repositories (root, externals and nested ones).
-  std::list<SVNInfo> Repositories;
+  std::vector<SVNInfo> Repositories;
 
   // Pointer to the infos of the root repository.
   SVNInfo* RootInfo;
 
   std::string LoadInfo(SVNInfo& svninfo);
-  void LoadRepositories();
-  void LoadModifications() CM_OVERRIDE;
-  void LoadRevisions() CM_OVERRIDE;
-  void LoadRevisions(SVNInfo& svninfo);
+  bool LoadRepositories();
+  bool LoadModifications() CM_OVERRIDE;
+  bool LoadRevisions() CM_OVERRIDE;
+  bool LoadRevisions(SVNInfo& svninfo);
 
   void GuessBase(SVNInfo& svninfo, std::vector<Change> const& changes);
 
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index b537242..1d29dfa 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestScriptHandler.h"
 
-#include <cmsys/Directory.hxx>
-#include <cmsys/Process.h>
+#include "cmsys/Directory.hxx"
+#include "cmsys/Process.h"
 #include <map>
 #include <sstream>
 #include <stdio.h>
@@ -166,12 +166,12 @@ void cmCTestScriptHandler::UpdateElapsedTime()
   }
 }
 
-void cmCTestScriptHandler::AddCTestCommand(cmCTestCommand* command)
+void cmCTestScriptHandler::AddCTestCommand(std::string const& name,
+                                           cmCTestCommand* command)
 {
-  cmCTestCommand* newCom = command;
-  newCom->CTest = this->CTest;
-  newCom->CTestScriptHandler = this;
-  this->CMake->GetState()->AddCommand(newCom);
+  command->CTest = this->CTest;
+  command->CTestScriptHandler = this;
+  this->CMake->GetState()->AddBuiltinCommand(name, command);
 }
 
 int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
@@ -275,7 +275,7 @@ void cmCTestScriptHandler::CreateCMake()
     delete this->GlobalGenerator;
     delete this->Makefile;
   }
-  this->CMake = new cmake;
+  this->CMake = new cmake(cmake::RoleScript);
   this->CMake->SetHomeDirectory("");
   this->CMake->SetHomeOutputDirectory("");
   this->CMake->GetCurrentSnapshot().SetDefaultDefinitions();
@@ -290,26 +290,21 @@ void cmCTestScriptHandler::CreateCMake()
 
   this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest);
 
-  // remove all cmake commands which are not scriptable, since they can't be
-  // used in ctest scripts
-  this->CMake->GetState()->RemoveUnscriptableCommands();
-
-  // add any ctest specific commands, probably should have common superclass
-  // for ctest commands to clean this up. If a couple more commands are
-  // created with the same format lets do that - ken
-  this->AddCTestCommand(new cmCTestBuildCommand);
-  this->AddCTestCommand(new cmCTestConfigureCommand);
-  this->AddCTestCommand(new cmCTestCoverageCommand);
-  this->AddCTestCommand(new cmCTestEmptyBinaryDirectoryCommand);
-  this->AddCTestCommand(new cmCTestMemCheckCommand);
-  this->AddCTestCommand(new cmCTestReadCustomFilesCommand);
-  this->AddCTestCommand(new cmCTestRunScriptCommand);
-  this->AddCTestCommand(new cmCTestSleepCommand);
-  this->AddCTestCommand(new cmCTestStartCommand);
-  this->AddCTestCommand(new cmCTestSubmitCommand);
-  this->AddCTestCommand(new cmCTestTestCommand);
-  this->AddCTestCommand(new cmCTestUpdateCommand);
-  this->AddCTestCommand(new cmCTestUploadCommand);
+  this->AddCTestCommand("ctest_build", new cmCTestBuildCommand);
+  this->AddCTestCommand("ctest_configure", new cmCTestConfigureCommand);
+  this->AddCTestCommand("ctest_coverage", new cmCTestCoverageCommand);
+  this->AddCTestCommand("ctest_empty_binary_directory",
+                        new cmCTestEmptyBinaryDirectoryCommand);
+  this->AddCTestCommand("ctest_memcheck", new cmCTestMemCheckCommand);
+  this->AddCTestCommand("ctest_read_custom_files",
+                        new cmCTestReadCustomFilesCommand);
+  this->AddCTestCommand("ctest_run_script", new cmCTestRunScriptCommand);
+  this->AddCTestCommand("ctest_sleep", new cmCTestSleepCommand);
+  this->AddCTestCommand("ctest_start", new cmCTestStartCommand);
+  this->AddCTestCommand("ctest_submit", new cmCTestSubmitCommand);
+  this->AddCTestCommand("ctest_test", new cmCTestTestCommand);
+  this->AddCTestCommand("ctest_update", new cmCTestUpdateCommand);
+  this->AddCTestCommand("ctest_upload", new cmCTestUploadCommand);
 }
 
 // this sets up some variables for the script to use, creates the required
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index 47644be..6678702 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestScriptHandler_h
 #define cmCTestScriptHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGenericHandler.h"
 
@@ -126,7 +126,7 @@ private:
   int RunConfigurationDashboard();
 
   // Add ctest command
-  void AddCTestCommand(cmCTestCommand* command);
+  void AddCTestCommand(std::string const& name, cmCTestCommand* command);
 
   // Try to remove the binary directory once
   static bool TryToRemoveBinaryDirectoryOnce(const std::string& directoryPath);
diff --git a/Source/CTest/cmCTestSleepCommand.h b/Source/CTest/cmCTestSleepCommand.h
index 1052f76..f0b5f1e 100644
--- a/Source/CTest/cmCTestSleepCommand.h
+++ b/Source/CTest/cmCTestSleepCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestSleepCommand_h
 #define cmCTestSleepCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestCommand.h"
 
@@ -41,11 +41,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "ctest_sleep"; }
 };
 
 #endif
diff --git a/Source/CTest/cmCTestStartCommand.h b/Source/CTest/cmCTestStartCommand.h
index cc72d0c..b4943f9 100644
--- a/Source/CTest/cmCTestStartCommand.h
+++ b/Source/CTest/cmCTestStartCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestStartCommand_h
 #define cmCTestStartCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestCommand.h"
 
@@ -54,11 +54,6 @@ public:
    */
   bool ShouldBeQuiet() { return this->Quiet; }
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "ctest_start"; }
-
 private:
   bool InitialCheckout(std::ostream& ofs, std::string const& sourceDir);
   bool CreateNewTag;
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index 5cf4ddc..409eb51 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -129,6 +129,12 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
     static_cast<cmCTestSubmitHandler*>(handler)->SelectParts(this->Parts);
   }
 
+  // Pass along any HTTPHEADER to the handler if this option was given.
+  if (!this->HttpHeaders.empty()) {
+    static_cast<cmCTestSubmitHandler*>(handler)->SetHttpHeaders(
+      this->HttpHeaders);
+  }
+
   static_cast<cmCTestSubmitHandler*>(handler)->SetOption(
     "RetryDelay", this->RetryDelay.c_str());
   static_cast<cmCTestSubmitHandler*>(handler)->SetOption(
@@ -182,6 +188,11 @@ bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg)
     }
   }
   // Arguments used by both modes.
+  if (arg == "HTTPHEADER") {
+    this->ArgumentDoing = ArgumentDoingHttpHeader;
+    return true;
+  }
+
   if (arg == "RETRY_COUNT") {
     this->ArgumentDoing = ArgumentDoingRetryCount;
     return true;
@@ -230,6 +241,11 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg)
     return true;
   }
 
+  if (this->ArgumentDoing == ArgumentDoingHttpHeader) {
+    this->HttpHeaders.push_back(arg);
+    return true;
+  }
+
   if (this->ArgumentDoing == ArgumentDoingRetryCount) {
     this->RetryCount = arg;
     return true;
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index f5b52c1..cf65cdc 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestSubmitCommand_h
 #define cmCTestSubmitCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTest.h"
 #include "cmCTestHandlerCommand.h"
@@ -70,6 +70,7 @@ protected:
     ArgumentDoingRetryCount,
     ArgumentDoingCDashUpload,
     ArgumentDoingCDashUploadType,
+    ArgumentDoingHttpHeader,
     ArgumentDoingLast2
   };
 
@@ -83,6 +84,7 @@ protected:
   bool CDashUpload;
   std::string CDashUploadFile;
   std::string CDashUploadType;
+  std::vector<std::string> HttpHeaders;
 };
 
 #endif
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 5e5119d..8d62fa1 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -2,10 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestSubmitHandler.h"
 
-#include <cm_curl.h>
-#include <cm_jsoncpp_reader.h>
-#include <cm_jsoncpp_value.h>
-#include <cmsys/Process.h>
+#include "cm_curl.h"
+#include "cm_jsoncpp_reader.h"
+#include "cm_jsoncpp_value.h"
+#include "cmsys/Process.h"
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -19,13 +19,14 @@
 #include "cmState.h"
 #include "cmSystemTools.h"
 #include "cmThirdParty.h"
+#include "cmWorkingDirectory.h"
 #include "cmXMLParser.h"
 #include "cmake.h"
 
 #if defined(CTEST_USE_XMLRPC)
 #include "cmVersion.h"
-#include <cm_xmlrpc.h>
-#include <sys/stat.h>
+#include "cm_sys_stat.h"
+#include "cm_xmlrpc.h"
 #endif
 
 #define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120
@@ -300,9 +301,19 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
   CURLcode res;
   FILE* ftpfile;
   char error_buffer[1024];
+  // Set Content-Type to satisfy fussy modsecurity rules.
   struct curl_slist* headers =
     ::curl_slist_append(CM_NULLPTR, "Content-Type: text/xml");
 
+  // Add any additional headers that the user specified.
+  for (std::vector<std::string>::const_iterator h = this->HttpHeaders.begin();
+       h != this->HttpHeaders.end(); ++h) {
+    cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+                       "   Add HTTP Header: \"" << *h << "\"" << std::endl,
+                       this->Quiet);
+    headers = ::curl_slist_append(headers, h->c_str());
+  }
+
   /* In windows, this will init the winsock stuff */
   ::curl_global_init(CURL_GLOBAL_ALL);
   std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
@@ -375,7 +386,6 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
       ::curl_easy_setopt(curl, CURLOPT_PUT, 1);
       ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
 
-      // Be sure to set Content-Type to satisfy fussy modsecurity rules
       ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
 
       std::string local_file = *file;
@@ -585,7 +595,7 @@ void cmCTestSubmitHandler::ParseResponse(
   std::string output;
   output.append(chunk.begin(), chunk.end());
 
-  if (output.find("<cdash") != output.npos) {
+  if (output.find("<cdash") != std::string::npos) {
     ResponseParser parser;
     parser.Parse(output.c_str());
 
@@ -1013,6 +1023,7 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
   cmSystemTools::ExpandListArgument(curlopt, args);
   curl.SetCurlOptions(args);
   curl.SetTimeOutSeconds(SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
+  curl.SetHttpHeaders(this->HttpHeaders);
   std::string dropMethod;
   std::string url;
   this->ConstructCDashURL(dropMethod, url);
@@ -1519,7 +1530,6 @@ int cmCTestSubmitHandler::ProcessHandler()
 #endif
   } else if (dropMethod == "scp") {
     std::string url;
-    std::string oldWorkingDirectory;
     if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) {
       url += this->CTest->GetCTestConfiguration("DropSiteUser") + "@";
     }
@@ -1528,19 +1538,16 @@ int cmCTestSubmitHandler::ProcessHandler()
 
     // change to the build directory so that we can uses a relative path
     // on windows since scp dosn't support "c:" a drive in the path
-    oldWorkingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
-    cmSystemTools::ChangeDirectory(buildDirectory);
+    cmWorkingDirectory workdir(buildDirectory);
 
     if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"),
                               "Testing/" + this->CTest->GetCurrentTag(), files,
                               prefix, url)) {
-      cmSystemTools::ChangeDirectory(oldWorkingDirectory);
       cmCTestLog(this->CTest, ERROR_MESSAGE,
                  "   Problems when submitting via SCP" << std::endl);
       ofs << "   Problems when submitting via SCP" << std::endl;
       return -1;
     }
-    cmSystemTools::ChangeDirectory(oldWorkingDirectory);
     cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
                        "   Submission successful" << std::endl, this->Quiet);
     ofs << "   Submission successful" << std::endl;
@@ -1550,22 +1557,18 @@ int cmCTestSubmitHandler::ProcessHandler()
 
     // change to the build directory so that we can uses a relative path
     // on windows since scp dosn't support "c:" a drive in the path
-    std::string oldWorkingDirectory =
-      cmSystemTools::GetCurrentWorkingDirectory();
-    cmSystemTools::ChangeDirectory(buildDirectory);
+    cmWorkingDirectory workdir(buildDirectory);
     cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                        "   Change directory: " << buildDirectory << std::endl,
                        this->Quiet);
 
     if (!this->SubmitUsingCP("Testing/" + this->CTest->GetCurrentTag(), files,
                              prefix, location)) {
-      cmSystemTools::ChangeDirectory(oldWorkingDirectory);
       cmCTestLog(this->CTest, ERROR_MESSAGE,
                  "   Problems when submitting via CP" << std::endl);
       ofs << "   Problems when submitting via cp" << std::endl;
       return -1;
     }
-    cmSystemTools::ChangeDirectory(oldWorkingDirectory);
     cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
                        "   Submission successful" << std::endl, this->Quiet);
     ofs << "   Submission successful" << std::endl;
diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h
index baaf8af..2923f4f 100644
--- a/Source/CTest/cmCTestSubmitHandler.h
+++ b/Source/CTest/cmCTestSubmitHandler.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestSubmitHandler_h
 #define cmCTestSubmitHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTest.h"
 #include "cmCTestGenericHandler.h"
@@ -43,6 +43,11 @@ public:
   // handle the cdash file upload protocol
   int HandleCDashUploadFile(std::string const& file, std::string const& type);
 
+  void SetHttpHeaders(std::vector<std::string> const& v)
+  {
+    this->HttpHeaders = v;
+  }
+
   void ConstructCDashURL(std::string& dropMethod, std::string& url);
 
 private:
@@ -95,6 +100,7 @@ private:
   bool HasWarnings;
   bool HasErrors;
   cmCTest::SetOfStrings Files;
+  std::vector<std::string> HttpHeaders;
 };
 
 #endif
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index a756188..075b140 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -20,6 +20,9 @@ cmCTestTestCommand::cmCTestTestCommand()
   this->Arguments[ctt_INCLUDE] = "INCLUDE";
   this->Arguments[ctt_EXCLUDE_LABEL] = "EXCLUDE_LABEL";
   this->Arguments[ctt_INCLUDE_LABEL] = "INCLUDE_LABEL";
+  this->Arguments[ctt_EXCLUDE_FIXTURE] = "EXCLUDE_FIXTURE";
+  this->Arguments[ctt_EXCLUDE_FIXTURE_SETUP] = "EXCLUDE_FIXTURE_SETUP";
+  this->Arguments[ctt_EXCLUDE_FIXTURE_CLEANUP] = "EXCLUDE_FIXTURE_CLEANUP";
   this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL";
   this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM";
   this->Arguments[ctt_STOP_TIME] = "STOP_TIME";
@@ -33,10 +36,11 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
   const char* ctestTimeout =
     this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT");
 
-  double timeout = this->CTest->GetTimeOut();
+  double timeout;
   if (ctestTimeout) {
     timeout = atof(ctestTimeout);
   } else {
+    timeout = this->CTest->GetTimeOut();
     if (timeout <= 0) {
       // By default use timeout of 10 minutes
       timeout = 600;
@@ -75,6 +79,18 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
     handler->SetOption("LabelRegularExpression",
                        this->Values[ctt_INCLUDE_LABEL]);
   }
+  if (this->Values[ctt_EXCLUDE_FIXTURE]) {
+    handler->SetOption("ExcludeFixtureRegularExpression",
+                       this->Values[ctt_EXCLUDE_FIXTURE]);
+  }
+  if (this->Values[ctt_EXCLUDE_FIXTURE_SETUP]) {
+    handler->SetOption("ExcludeFixtureSetupRegularExpression",
+                       this->Values[ctt_EXCLUDE_FIXTURE_SETUP]);
+  }
+  if (this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]) {
+    handler->SetOption("ExcludeFixtureCleanupRegularExpression",
+                       this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]);
+  }
   if (this->Values[ctt_PARALLEL_LEVEL]) {
     handler->SetOption("ParallelLevel", this->Values[ctt_PARALLEL_LEVEL]);
   }
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index 3250d93..be7e783 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestTestCommand_h
 #define cmCTestTestCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestHandlerCommand.h"
 
@@ -53,6 +53,9 @@ protected:
     ctt_INCLUDE,
     ctt_EXCLUDE_LABEL,
     ctt_INCLUDE_LABEL,
+    ctt_EXCLUDE_FIXTURE,
+    ctt_EXCLUDE_FIXTURE_SETUP,
+    ctt_EXCLUDE_FIXTURE_CLEANUP,
     ctt_PARALLEL_LEVEL,
     ctt_SCHEDULE_RANDOM,
     ctt_STOP_TIME,
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 6175e50..674be60 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -2,11 +2,11 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestTestHandler.h"
 
+#include "cmsys/Base64.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
-#include <cmsys/Base64.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
 #include <functional>
 #include <iomanip>
 #include <iterator>
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <time.h>
 
+#include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCTestBatchTestHandler.h"
 #include "cmCTestMultiProcessHandler.h"
@@ -27,6 +28,7 @@
 #include "cmState.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 #include "cmXMLWriter.h"
 #include "cm_auto_ptr.hxx"
 #include "cm_utf8.h"
@@ -54,11 +56,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& /*unused*/) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "subdirs"; }
-
   cmCTestTestHandler* TestHandler;
 };
 
@@ -86,22 +83,24 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
       // No subdirectory? So what...
       continue;
     }
-    cmSystemTools::ChangeDirectory(fname);
-    const char* testFilename;
-    if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
-      // does the CTestTestfile.cmake exist ?
-      testFilename = "CTestTestfile.cmake";
-    } else if (cmSystemTools::FileExists("DartTestfile.txt")) {
-      // does the DartTestfile.txt exist ?
-      testFilename = "DartTestfile.txt";
-    } else {
-      // No CTestTestfile? Who cares...
-      continue;
+    bool readit = false;
+    {
+      cmWorkingDirectory workdir(fname);
+      const char* testFilename;
+      if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
+        // does the CTestTestfile.cmake exist ?
+        testFilename = "CTestTestfile.cmake";
+      } else if (cmSystemTools::FileExists("DartTestfile.txt")) {
+        // does the DartTestfile.txt exist ?
+        testFilename = "DartTestfile.txt";
+      } else {
+        // No CTestTestfile? Who cares...
+        continue;
+      }
+      fname += "/";
+      fname += testFilename;
+      readit = this->Makefile->ReadDependentFile(fname.c_str());
     }
-    fname += "/";
-    fname += testFilename;
-    bool readit = this->Makefile->ReadDependentFile(fname.c_str());
-    cmSystemTools::ChangeDirectory(cwd);
     if (!readit) {
       std::string m = "Could not find include file: ";
       m += fname;
@@ -109,7 +108,6 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
       return false;
     }
   }
-  cmSystemTools::ChangeDirectory(cwd);
   return true;
 }
 
@@ -133,11 +131,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& /*unused*/) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_subdirectory"; }
-
   cmCTestTestHandler* TestHandler;
 };
 
@@ -149,9 +142,7 @@ bool cmCTestAddSubdirectoryCommand::InitialPass(
     return false;
   }
 
-  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(cwd);
-  std::string fname = cwd;
+  std::string fname = cmSystemTools::GetCurrentWorkingDirectory();
   fname += "/";
   fname += args[0];
 
@@ -159,23 +150,23 @@ bool cmCTestAddSubdirectoryCommand::InitialPass(
     // No subdirectory? So what...
     return true;
   }
-  cmSystemTools::ChangeDirectory(fname);
-  const char* testFilename;
-  if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
-    // does the CTestTestfile.cmake exist ?
-    testFilename = "CTestTestfile.cmake";
-  } else if (cmSystemTools::FileExists("DartTestfile.txt")) {
-    // does the DartTestfile.txt exist ?
-    testFilename = "DartTestfile.txt";
-  } else {
-    // No CTestTestfile? Who cares...
-    cmSystemTools::ChangeDirectory(cwd);
-    return true;
+  bool readit = false;
+  {
+    const char* testFilename;
+    if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
+      // does the CTestTestfile.cmake exist ?
+      testFilename = "CTestTestfile.cmake";
+    } else if (cmSystemTools::FileExists("DartTestfile.txt")) {
+      // does the DartTestfile.txt exist ?
+      testFilename = "DartTestfile.txt";
+    } else {
+      // No CTestTestfile? Who cares...
+      return true;
+    }
+    fname += "/";
+    fname += testFilename;
+    readit = this->Makefile->ReadDependentFile(fname.c_str());
   }
-  fname += "/";
-  fname += testFilename;
-  bool readit = this->Makefile->ReadDependentFile(fname.c_str());
-  cmSystemTools::ChangeDirectory(cwd);
   if (!readit) {
     std::string m = "Could not find include file: ";
     m += fname;
@@ -205,11 +196,6 @@ public:
   bool InitialPass(std::vector<std::string> const& /*args*/,
                    cmExecutionStatus& /*unused*/) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_test"; }
-
   cmCTestTestHandler* TestHandler;
 };
 
@@ -239,15 +225,10 @@ public:
   /**
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
-  */
+   */
   bool InitialPass(std::vector<std::string> const& /*args*/,
                    cmExecutionStatus& /*unused*/) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "set_tests_properties"; }
-
   cmCTestTestHandler* TestHandler;
 };
 
@@ -266,7 +247,7 @@ inline int GetNextNumber(std::string const& in, int& val,
                          std::string::size_type& pos2)
 {
   pos2 = in.find(',', pos);
-  if (pos2 != in.npos) {
+  if (pos2 != std::string::npos) {
     if (pos2 - pos == 0) {
       val = -1;
     } else {
@@ -292,7 +273,7 @@ inline int GetNextRealNumber(std::string const& in, double& val,
                              std::string::size_type& pos2)
 {
   pos2 = in.find(',', pos);
-  if (pos2 != in.npos) {
+  if (pos2 != std::string::npos) {
     if (pos2 - pos == 0) {
       val = -1;
     } else {
@@ -361,6 +342,9 @@ void cmCTestTestHandler::Initialize()
   this->ExcludeLabelRegularExpression = "";
   this->IncludeRegExp = "";
   this->ExcludeRegExp = "";
+  this->ExcludeFixtureRegExp.clear();
+  this->ExcludeFixtureSetupRegExp.clear();
+  this->ExcludeFixtureCleanupRegExp.clear();
 
   TestsToRunString = "";
   this->UseUnion = false;
@@ -438,6 +422,18 @@ int cmCTestTestHandler::ProcessHandler()
     this->UseExcludeRegExp();
     this->SetExcludeRegExp(val);
   }
+  val = this->GetOption("ExcludeFixtureRegularExpression");
+  if (val) {
+    this->ExcludeFixtureRegExp = val;
+  }
+  val = this->GetOption("ExcludeFixtureSetupRegularExpression");
+  if (val) {
+    this->ExcludeFixtureSetupRegExp = val;
+  }
+  val = this->GetOption("ExcludeFixtureCleanupRegularExpression");
+  if (val) {
+    this->ExcludeFixtureCleanupRegExp = val;
+  }
   this->SetRerunFailed(cmSystemTools::IsOn(this->GetOption("RerunFailed")));
 
   this->TestResults.clear();
@@ -487,6 +483,20 @@ int cmCTestTestHandler::ProcessHandler()
       }
     }
 
+    typedef std::set<cmCTestTestHandler::cmCTestTestResult,
+                     cmCTestTestResultLess>
+      SetOfTests;
+    SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end());
+    std::vector<cmCTestTestHandler::cmCTestTestResult> disabledTests;
+
+    for (SetOfTests::iterator ftit = resultsSet.begin();
+         ftit != resultsSet.end(); ++ftit) {
+      if (cmHasLiteralPrefix(ftit->CompletionStatus, "SKIP_RETURN_CODE=") ||
+          ftit->CompletionStatus == "Disabled") {
+        disabledTests.push_back(*ftit);
+      }
+    }
+
     float percent = float(passed.size()) * 100.0f / float(total);
     if (!failed.empty() && percent > 99) {
       percent = 99;
@@ -505,21 +515,39 @@ int cmCTestTestHandler::ProcessHandler()
                        "\nTotal Test time (real) = " << realBuf << "\n",
                        this->Quiet);
 
+    if (!disabledTests.empty()) {
+      cmGeneratedFileStream ofs;
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
+                   << "The following tests did not run:" << std::endl);
+      this->StartLogFile("TestsDisabled", ofs);
+
+      const char* disabled_reason;
+      for (std::vector<cmCTestTestHandler::cmCTestTestResult>::iterator dtit =
+             disabledTests.begin();
+           dtit != disabledTests.end(); ++dtit) {
+        ofs << dtit->TestCount << ":" << dtit->Name << std::endl;
+        if (dtit->CompletionStatus == "Disabled") {
+          disabled_reason = "Disabled";
+        } else {
+          disabled_reason = "Skipped";
+        }
+        cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t"
+                     << std::setw(3) << dtit->TestCount << " - " << dtit->Name
+                     << " (" << disabled_reason << ")" << std::endl);
+      }
+    }
+
     if (!failed.empty()) {
       cmGeneratedFileStream ofs;
       cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
                    << "The following tests FAILED:" << std::endl);
       this->StartLogFile("TestsFailed", ofs);
 
-      typedef std::set<cmCTestTestHandler::cmCTestTestResult,
-                       cmCTestTestResultLess>
-        SetOfTests;
-      SetOfTests resultsSet(this->TestResults.begin(),
-                            this->TestResults.end());
-
       for (SetOfTests::iterator ftit = resultsSet.begin();
            ftit != resultsSet.end(); ++ftit) {
-        if (ftit->Status != cmCTestTestHandler::COMPLETED) {
+        if (ftit->Status != cmCTestTestHandler::COMPLETED &&
+            !cmHasLiteralPrefix(ftit->CompletionStatus, "SKIP_RETURN_CODE=") &&
+            ftit->CompletionStatus != "Disabled") {
           ofs << ftit->TestCount << ":" << ftit->Name << std::endl;
           cmCTestLog(
             this->CTest, HANDLER_OUTPUT, "\t"
@@ -795,13 +823,35 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
                      "Updating test list for fixtures" << std::endl,
                      this->Quiet);
 
+  // Prepare regular expression evaluators
+  std::string setupRegExp(this->ExcludeFixtureRegExp);
+  std::string cleanupRegExp(this->ExcludeFixtureRegExp);
+  if (!this->ExcludeFixtureSetupRegExp.empty()) {
+    if (setupRegExp.empty()) {
+      setupRegExp = this->ExcludeFixtureSetupRegExp;
+    } else {
+      setupRegExp.append("(" + setupRegExp + ")|(" +
+                         this->ExcludeFixtureSetupRegExp + ")");
+    }
+  }
+  if (!this->ExcludeFixtureCleanupRegExp.empty()) {
+    if (cleanupRegExp.empty()) {
+      cleanupRegExp = this->ExcludeFixtureCleanupRegExp;
+    } else {
+      cleanupRegExp.append("(" + cleanupRegExp + ")|(" +
+                           this->ExcludeFixtureCleanupRegExp + ")");
+    }
+  }
+  cmsys::RegularExpression excludeSetupRegex(setupRegExp);
+  cmsys::RegularExpression excludeCleanupRegex(cleanupRegExp);
+
   // Prepare some maps to help us find setup and cleanup tests for
   // any given fixture
   typedef ListOfTests::const_iterator TestIterator;
   typedef std::multimap<std::string, TestIterator> FixtureDependencies;
   typedef FixtureDependencies::const_iterator FixtureDepsIterator;
   FixtureDependencies fixtureSetups;
-  FixtureDependencies fixtureDeps;
+  FixtureDependencies fixtureCleanups;
 
   for (ListOfTests::const_iterator it = this->TestList.begin();
        it != this->TestList.end(); ++it) {
@@ -811,13 +861,12 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
     for (std::set<std::string>::const_iterator depsIt = setups.begin();
          depsIt != setups.end(); ++depsIt) {
       fixtureSetups.insert(std::make_pair(*depsIt, it));
-      fixtureDeps.insert(std::make_pair(*depsIt, it));
     }
 
     const std::set<std::string>& cleanups = p.FixturesCleanup;
     for (std::set<std::string>::const_iterator depsIt = cleanups.begin();
          depsIt != cleanups.end(); ++depsIt) {
-      fixtureDeps.insert(std::make_pair(*depsIt, it));
+      fixtureCleanups.insert(std::make_pair(*depsIt, it));
     }
   }
 
@@ -841,6 +890,11 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
   size_t fixtureTestsAdded = 0;
   std::set<std::string> addedFixtures;
   for (size_t i = 0; i < tests.size(); ++i) {
+    // Skip disabled tests
+    if (tests[i].Disabled) {
+      continue;
+    }
+
     // There are two things to do for each test:
     //   1. For every fixture required by this test, record that fixture as
     //      being required and create dependencies on that fixture's setup
@@ -886,34 +940,72 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
       // added from a previously checked test). A fixture isn't required
       // to have setup/cleanup tests.
       if (!addedFixtures.insert(requiredFixtureName).second) {
-        // Already added this fixture
+        // Already seen this fixture, no need to check it again
         continue;
       }
-      std::pair<FixtureDepsIterator, FixtureDepsIterator> fixtureRange =
-        fixtureDeps.equal_range(requiredFixtureName);
-      for (FixtureDepsIterator it = fixtureRange.first;
-           it != fixtureRange.second; ++it) {
-        ListOfTests::const_iterator lotIt = it->second;
-        const cmCTestTestProperties& p = *lotIt;
-
-        if (!addedTests.insert(p.Name).second) {
-          // Already have p in our test list
-          continue;
+
+      // Only add setup tests if this fixture has not been excluded
+      if (setupRegExp.empty() ||
+          !excludeSetupRegex.find(requiredFixtureName)) {
+        std::pair<FixtureDepsIterator, FixtureDepsIterator> fixtureRange =
+          fixtureSetups.equal_range(requiredFixtureName);
+        for (FixtureDepsIterator it = fixtureRange.first;
+             it != fixtureRange.second; ++it) {
+          ListOfTests::const_iterator lotIt = it->second;
+          const cmCTestTestProperties& p = *lotIt;
+
+          if (!addedTests.insert(p.Name).second) {
+            // Already have p in our test list
+            continue;
+          }
+
+          // This is a test not yet in our list, so add it and
+          // update its index to reflect where it was in the original
+          // full list of all tests (needed to track individual tests
+          // across ctest runs for re-run failed, etc.)
+          tests.push_back(p);
+          tests.back().Index =
+            1 + static_cast<int>(std::distance(this->TestList.begin(), lotIt));
+          ++fixtureTestsAdded;
+
+          cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+                             "Added setup test "
+                               << p.Name << " required by fixture "
+                               << requiredFixtureName << std::endl,
+                             this->Quiet);
         }
+      }
 
-        // This is a test not yet in our list, so add it and
-        // update its index to reflect where it was in the original
-        // full list of all tests (needed to track individual tests
-        // across ctest runs for re-run failed, etc.)
-        tests.push_back(p);
-        tests.back().Index =
-          1 + static_cast<int>(std::distance(this->TestList.begin(), lotIt));
-        ++fixtureTestsAdded;
-
-        cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Added test "
-                             << p.Name << " required by fixture "
-                             << requiredFixtureName << std::endl,
-                           this->Quiet);
+      // Only add cleanup tests if this fixture has not been excluded
+      if (cleanupRegExp.empty() ||
+          !excludeCleanupRegex.find(requiredFixtureName)) {
+        std::pair<FixtureDepsIterator, FixtureDepsIterator> fixtureRange =
+          fixtureCleanups.equal_range(requiredFixtureName);
+        for (FixtureDepsIterator it = fixtureRange.first;
+             it != fixtureRange.second; ++it) {
+          ListOfTests::const_iterator lotIt = it->second;
+          const cmCTestTestProperties& p = *lotIt;
+
+          if (!addedTests.insert(p.Name).second) {
+            // Already have p in our test list
+            continue;
+          }
+
+          // This is a test not yet in our list, so add it and
+          // update its index to reflect where it was in the original
+          // full list of all tests (needed to track individual tests
+          // across ctest runs for re-run failed, etc.)
+          tests.push_back(p);
+          tests.back().Index =
+            1 + static_cast<int>(std::distance(this->TestList.begin(), lotIt));
+          ++fixtureTestsAdded;
+
+          cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+                             "Added cleanup test "
+                               << p.Name << " required by fixture "
+                               << requiredFixtureName << std::endl,
+                             this->Quiet);
+        }
       }
     }
 
@@ -1200,6 +1292,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
     cmCTestTestResult* result = &this->TestResults[cc];
     this->WriteTestResultHeader(xml, result);
     xml.StartElement("Results");
+
     if (result->Status != cmCTestTestHandler::NOT_RUN) {
       if (result->Status != cmCTestTestHandler::COMPLETED ||
           result->ReturnValue) {
@@ -1208,6 +1301,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
         xml.Attribute("name", "Exit Code");
         xml.Element("Value", this->GetTestStatus(result->Status));
         xml.EndElement(); // NamedMeasurement
+
         xml.StartElement("NamedMeasurement");
         xml.Attribute("type", "text/string");
         xml.Attribute("name", "Exit Value");
@@ -1222,8 +1316,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
       xml.EndElement(); // NamedMeasurement
       if (!result->Reason.empty()) {
         const char* reasonType = "Pass Reason";
-        if (result->Status != cmCTestTestHandler::COMPLETED &&
-            result->Status != cmCTestTestHandler::NOT_RUN) {
+        if (result->Status != cmCTestTestHandler::COMPLETED) {
           reasonType = "Fail Reason";
         }
         xml.StartElement("NamedMeasurement");
@@ -1232,12 +1325,14 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
         xml.Element("Value", result->Reason);
         xml.EndElement(); // NamedMeasurement
       }
-      xml.StartElement("NamedMeasurement");
-      xml.Attribute("type", "text/string");
-      xml.Attribute("name", "Completion Status");
-      xml.Element("Value", result->CompletionStatus);
-      xml.EndElement(); // NamedMeasurement
     }
+
+    xml.StartElement("NamedMeasurement");
+    xml.Attribute("type", "text/string");
+    xml.Attribute("name", "Completion Status");
+    xml.Element("Value", result->CompletionStatus);
+    xml.EndElement(); // NamedMeasurement
+
     xml.StartElement("NamedMeasurement");
     xml.Attribute("type", "text/string");
     xml.Attribute("name", "Command Line");
@@ -1535,7 +1630,7 @@ void cmCTestTestHandler::GetListOfTests()
   }
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                      "Constructing a list of tests" << std::endl, this->Quiet);
-  cmake cm;
+  cmake cm(cmake::RoleScript);
   cm.SetHomeDirectory("");
   cm.SetHomeOutputDirectory("");
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
@@ -1547,23 +1642,23 @@ void cmCTestTestHandler::GetListOfTests()
   // Add handler for ADD_TEST
   cmCTestAddTestCommand* newCom1 = new cmCTestAddTestCommand;
   newCom1->TestHandler = this;
-  cm.GetState()->AddCommand(newCom1);
+  cm.GetState()->AddBuiltinCommand("add_test", newCom1);
 
   // Add handler for SUBDIRS
   cmCTestSubdirCommand* newCom2 = new cmCTestSubdirCommand;
   newCom2->TestHandler = this;
-  cm.GetState()->AddCommand(newCom2);
+  cm.GetState()->AddBuiltinCommand("subdirs", newCom2);
 
   // Add handler for ADD_SUBDIRECTORY
   cmCTestAddSubdirectoryCommand* newCom3 = new cmCTestAddSubdirectoryCommand;
   newCom3->TestHandler = this;
-  cm.GetState()->AddCommand(newCom3);
+  cm.GetState()->AddBuiltinCommand("add_subdirectory", newCom3);
 
-  // Add handler for SET_SOURCE_FILES_PROPERTIES
+  // Add handler for SET_TESTS_PROPERTIES
   cmCTestSetTestsPropertiesCommand* newCom4 =
     new cmCTestSetTestsPropertiesCommand;
   newCom4->TestHandler = this;
-  cm.GetState()->AddCommand(newCom4);
+  cm.GetState()->AddBuiltinCommand("set_tests_properties", newCom4);
 
   const char* testFilename;
   if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
@@ -1600,10 +1695,10 @@ void cmCTestTestHandler::UseExcludeRegExp()
 
 const char* cmCTestTestHandler::GetTestStatus(int status)
 {
-  static const char statuses[][100] = {
-    "Not Run",   "Timeout",     "SEGFAULT", "ILLEGAL",     "INTERRUPT",
-    "NUMERICAL", "OTHER_FAULT", "Failed",   "BAD_COMMAND", "Completed"
-  };
+  static const char* statuses[] = { "Not Run",     "Timeout",   "SEGFAULT",
+                                    "ILLEGAL",     "INTERRUPT", "NUMERICAL",
+                                    "OTHER_FAULT", "Failed",    "BAD_COMMAND",
+                                    "Completed" };
 
   if (status < cmCTestTestHandler::NOT_RUN ||
       status > cmCTestTestHandler::COMPLETED) {
@@ -1694,7 +1789,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
     // bcc crashes if we attempt a normal substring comparison,
     // hence the following workaround
     std::string fileNameSubstring = fileName.substr(0, pattern.length());
-    if (fileNameSubstring.compare(pattern) != 0) {
+    if (fileNameSubstring != pattern) {
       continue;
     }
     if (logName == "") {
@@ -1728,7 +1823,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
     std::string::size_type pos;
     while (cmSystemTools::GetLineFromStream(ifs, line)) {
       pos = line.find(':', 0);
-      if (pos == line.npos) {
+      if (pos == std::string::npos) {
         continue;
       }
 
@@ -1932,7 +2027,7 @@ void cmCTestTestHandler::SetTestsToRunInformation(const char* in)
 bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t length)
 {
   if (!length || length >= output.size() ||
-      output.find("CTEST_FULL_OUTPUT") != output.npos) {
+      output.find("CTEST_FULL_OUTPUT") != std::string::npos) {
     return true;
   }
 
@@ -2000,6 +2095,9 @@ bool cmCTestTestHandler::SetTestsProperties(
           if (key == "WILL_FAIL") {
             rtit->WillFail = cmSystemTools::IsOn(val.c_str());
           }
+          if (key == "DISABLED") {
+            rtit->Disabled = cmSystemTools::IsOn(val.c_str());
+          }
           if (key == "ATTACHED_FILES") {
             cmSystemTools::ExpandListArgument(val, rtit->AttachedFiles);
           }
@@ -2077,7 +2175,7 @@ bool cmCTestTestHandler::SetTestsProperties(
           }
           if (key == "MEASUREMENT") {
             size_t pos = val.find_first_of('=');
-            if (pos != val.npos) {
+            if (pos != std::string::npos) {
               std::string mKey = val.substr(0, pos);
               const char* mVal = val.c_str() + pos + 1;
               rtit->Measurements[mKey] = mVal;
@@ -2178,6 +2276,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
 
   test.IsInBasedOnREOptions = true;
   test.WillFail = false;
+  test.Disabled = false;
   test.RunSerial = false;
   test.Timeout = 0;
   test.ExplicitTimeout = false;
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 5b07e98..0edcb14 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -3,11 +3,11 @@
 #ifndef cmCTestTestHandler_h
 #define cmCTestTestHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGenericHandler.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <iosfwd>
 #include <map>
 #include <set>
@@ -114,6 +114,7 @@ public:
     std::map<std::string, std::string> Measurements;
     bool IsInBasedOnREOptions;
     bool WillFail;
+    bool Disabled;
     float Cost;
     int PreviousRuns;
     bool RunSerial;
@@ -279,6 +280,9 @@ private:
   std::string ExcludeLabelRegExp;
   std::string IncludeRegExp;
   std::string ExcludeRegExp;
+  std::string ExcludeFixtureRegExp;
+  std::string ExcludeFixtureSetupRegExp;
+  std::string ExcludeFixtureCleanupRegExp;
   cmsys::RegularExpression IncludeLabelRegularExpression;
   cmsys::RegularExpression ExcludeLabelRegularExpression;
   cmsys::RegularExpression IncludeTestsRegularExpression;
diff --git a/Source/CTest/cmCTestUpdateCommand.h b/Source/CTest/cmCTestUpdateCommand.h
index 5761f50..3b8f0a6 100644
--- a/Source/CTest/cmCTestUpdateCommand.h
+++ b/Source/CTest/cmCTestUpdateCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestUpdateCommand_h
 #define cmCTestUpdateCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestHandlerCommand.h"
 
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index 0998d59..e08a9b7 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -16,7 +16,7 @@
 #include "cmVersion.h"
 #include "cmXMLWriter.h"
 
-#include <cm_auto_ptr.hxx>
+#include "cm_auto_ptr.hxx"
 #include <sstream>
 
 static const char* cmCTestUpdateHandlerUpdateStrings[] = {
@@ -198,7 +198,7 @@ int cmCTestUpdateHandler::ProcessHandler()
   xml.Element("UpdateType",
               cmCTestUpdateHandlerUpdateToString(this->UpdateType));
 
-  vc->WriteXML(xml);
+  bool loadedMods = vc->WriteXML(xml);
 
   int localModifications = 0;
   int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated);
@@ -246,7 +246,7 @@ int cmCTestUpdateHandler::ProcessHandler()
   xml.EndElement(); // UpdateReturnStatus
   xml.EndElement(); // Update
   xml.EndDocument();
-  return updated ? numUpdated : -1;
+  return updated && loadedMods ? numUpdated : -1;
 }
 
 int cmCTestUpdateHandler::DetectVCS(const char* dir)
diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h
index 87781e8..0cd2844 100644
--- a/Source/CTest/cmCTestUpdateHandler.h
+++ b/Source/CTest/cmCTestUpdateHandler.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestUpdateHandler_h
 #define cmCTestUpdateHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTestGenericHandler.h"
 
diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h
index 474f699..6e72179 100644
--- a/Source/CTest/cmCTestUploadCommand.h
+++ b/Source/CTest/cmCTestUploadCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestUploadCommand_h
 #define cmCTestUploadCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTest.h"
 #include "cmCTestHandlerCommand.h"
diff --git a/Source/CTest/cmCTestUploadHandler.h b/Source/CTest/cmCTestUploadHandler.h
index 77c2aec..1e8d3c8 100644
--- a/Source/CTest/cmCTestUploadHandler.h
+++ b/Source/CTest/cmCTestUploadHandler.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestUploadHandler_h
 #define cmCTestUploadHandler_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTest.h"
 #include "cmCTestGenericHandler.h"
diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx
index 444c43d..fb2742e 100644
--- a/Source/CTest/cmCTestVC.cxx
+++ b/Source/CTest/cmCTestVC.cxx
@@ -6,7 +6,7 @@
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
-#include <cmsys/Process.h>
+#include "cmsys/Process.h"
 #include <sstream>
 #include <stdio.h>
 #include <time.h>
@@ -147,23 +147,25 @@ bool cmCTestVC::Update()
   // just note the current version and finish
   if (!cmSystemTools::IsOn(
         this->CTest->GetCTestConfiguration("UpdateVersionOnly").c_str())) {
-    this->NoteOldRevision();
+    result = this->NoteOldRevision() && result;
     this->Log << "--- Begin Update ---\n";
-    result = this->UpdateImpl();
+    result = this->UpdateImpl() && result;
     this->Log << "--- End Update ---\n";
   }
-  this->NoteNewRevision();
+  result = this->NoteNewRevision() && result;
   return result;
 }
 
-void cmCTestVC::NoteOldRevision()
+bool cmCTestVC::NoteOldRevision()
 {
   // We do nothing by default.
+  return true;
 }
 
-void cmCTestVC::NoteNewRevision()
+bool cmCTestVC::NoteNewRevision()
 {
   // We do nothing by default.
+  return true;
 }
 
 bool cmCTestVC::UpdateImpl()
diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h
index 2681ba0..6400bcd 100644
--- a/Source/CTest/cmCTestVC.h
+++ b/Source/CTest/cmCTestVC.h
@@ -3,7 +3,7 @@
 #ifndef cmCTestVC_h
 #define cmCTestVC_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <string>
@@ -67,9 +67,9 @@ public:
 protected:
   // Internal API to be implemented by subclasses.
   virtual void CleanupImpl();
-  virtual void NoteOldRevision();
+  virtual bool NoteOldRevision();
   virtual bool UpdateImpl();
-  virtual void NoteNewRevision();
+  virtual bool NoteNewRevision();
   virtual bool WriteXMLUpdates(cmXMLWriter& xml);
 
 #if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x510
diff --git a/Source/CTest/cmParseBlanketJSCoverage.cxx b/Source/CTest/cmParseBlanketJSCoverage.cxx
index 6fa982e..83a7b75 100644
--- a/Source/CTest/cmParseBlanketJSCoverage.cxx
+++ b/Source/CTest/cmParseBlanketJSCoverage.cxx
@@ -6,7 +6,7 @@
 #include "cmCTestCoverageHandler.h"
 #include "cmSystemTools.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -22,7 +22,7 @@ public:
 
   virtual ~JSONParser() {}
 
-  std::string getValue(std::string line, int type)
+  std::string getValue(std::string const& line, int type)
   {
     size_t begIndex;
     size_t endIndex;
@@ -35,7 +35,7 @@ public:
         line.substr(begIndex + 3, endIndex - (begIndex + 4));
       return foundFileName;
     }
-    return line.substr(begIndex, line.npos);
+    return line.substr(begIndex);
   }
   bool ParseFile(std::string const& file)
   {
@@ -51,13 +51,13 @@ public:
       return false;
     }
     while (cmSystemTools::GetLineFromStream(in, line)) {
-      if (line.find("filename") != line.npos) {
+      if (line.find("filename") != std::string::npos) {
         if (foundFile) {
           /*
-          * Upon finding a second file name, generate a
-          * vector within the total coverage to capture the
-          * information in the local vector
-          */
+           * Upon finding a second file name, generate a
+           * vector within the total coverage to capture the
+           * information in the local vector
+           */
           FileLinesType& CoverageVector =
             this->Coverage.TotalCoverage[filename];
           CoverageVector = localCoverageVector;
@@ -66,19 +66,19 @@ public:
         foundFile = true;
         inSource = false;
         filename = getValue(line, 0);
-      } else if ((line.find("coverage") != line.npos) && foundFile &&
+      } else if ((line.find("coverage") != std::string::npos) && foundFile &&
                  inSource) {
         /*
-        *  two types of "coverage" in the JSON structure
-        *
-        *  The coverage result over the file or set of files
-        *  and the coverage for each individual line
-        *
-        *  FoundFile and foundSource ensure that
-        *  only the value of the line coverage is captured
-        */
+         *  two types of "coverage" in the JSON structure
+         *
+         *  The coverage result over the file or set of files
+         *  and the coverage for each individual line
+         *
+         *  FoundFile and foundSource ensure that
+         *  only the value of the line coverage is captured
+         */
         std::string result = getValue(line, 1);
-        result = result.substr(2, result.npos);
+        result = result.substr(2);
         if (result == "\"\"") {
           // Empty quotation marks indicate that the
           // line is not executable
@@ -87,7 +87,7 @@ public:
           // Else, it contains the number of time executed
           localCoverageVector.push_back(atoi(result.c_str()));
         }
-      } else if (line.find("source") != line.npos) {
+      } else if (line.find("source") != std::string::npos) {
         inSource = true;
       }
     }
diff --git a/Source/CTest/cmParseBlanketJSCoverage.h b/Source/CTest/cmParseBlanketJSCoverage.h
index 660590d..696121f 100644
--- a/Source/CTest/cmParseBlanketJSCoverage.h
+++ b/Source/CTest/cmParseBlanketJSCoverage.h
@@ -3,7 +3,7 @@
 #ifndef cmParseBlanketJSCoverage_h
 #define cmParseBlanketJSCoverage_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/CTest/cmParseCacheCoverage.cxx b/Source/CTest/cmParseCacheCoverage.cxx
index 23176b5..629010c 100644
--- a/Source/CTest/cmParseCacheCoverage.cxx
+++ b/Source/CTest/cmParseCacheCoverage.cxx
@@ -4,8 +4,8 @@
 #include "cmCTestCoverageHandler.h"
 #include "cmSystemTools.h"
 
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
 #include <map>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/Source/CTest/cmParseCacheCoverage.h b/Source/CTest/cmParseCacheCoverage.h
index 645d710..005d272 100644
--- a/Source/CTest/cmParseCacheCoverage.h
+++ b/Source/CTest/cmParseCacheCoverage.h
@@ -3,7 +3,7 @@
 #ifndef cmParseCacheCoverage_h
 #define cmParseCacheCoverage_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmParseMumpsCoverage.h"
 
diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx
index db17748..ba55cd7 100644
--- a/Source/CTest/cmParseCoberturaCoverage.cxx
+++ b/Source/CTest/cmParseCoberturaCoverage.cxx
@@ -5,8 +5,8 @@
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 
-#include <cmConfigure.h>
-#include <cmsys/FStream.hxx>
+#include "cmConfigure.h"
+#include "cmsys/FStream.hxx"
 #include <stdlib.h>
 #include <string.h>
 
diff --git a/Source/CTest/cmParseCoberturaCoverage.h b/Source/CTest/cmParseCoberturaCoverage.h
index 077eb80..cb6d097 100644
--- a/Source/CTest/cmParseCoberturaCoverage.h
+++ b/Source/CTest/cmParseCoberturaCoverage.h
@@ -3,7 +3,7 @@
 #ifndef cmParseCoberturaCoverage_h
 #define cmParseCoberturaCoverage_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/CTest/cmParseDelphiCoverage.cxx b/Source/CTest/cmParseDelphiCoverage.cxx
index 7fe91f4..4b781a6 100644
--- a/Source/CTest/cmParseDelphiCoverage.cxx
+++ b/Source/CTest/cmParseDelphiCoverage.cxx
@@ -4,8 +4,8 @@
 #include "cmCTestCoverageHandler.h"
 #include "cmSystemTools.h"
 
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -42,17 +42,20 @@ public:
       size_t beginPos = line.find("begin");
 
       // Check that the begin is the first non-space string on the line
-      if ((beginPos == line.find_first_not_of(' ')) && beginPos != line.npos) {
+      if ((beginPos == line.find_first_not_of(' ')) &&
+          beginPos != std::string::npos) {
         beginSet.push_back("begin");
         coverageVector.push_back(-1);
         continue;
-      } else if (line.find('{') != line.npos) {
+      }
+      if (line.find('{') != std::string::npos) {
         blockComFlag = true;
-      } else if (line.find('}') != line.npos) {
+      } else if (line.find('}') != std::string::npos) {
         blockComFlag = false;
         coverageVector.push_back(-1);
         continue;
-      } else if ((line.find("end;") != line.npos) && !beginSet.empty()) {
+      } else if ((line.find("end;") != std::string::npos) &&
+                 !beginSet.empty()) {
         beginSet.pop_back();
         coverageVector.push_back(-1);
         continue;
@@ -61,7 +64,7 @@ public:
       //  This checks for comments after lines of code, finding the
       //  comment symbol after the ending semicolon.
       comPos = line.find("//");
-      if (comPos != line.npos) {
+      if (comPos != std::string::npos) {
         semiPos = line.find(';');
         if (comPos < semiPos) {
           lineComFlag = true;
@@ -90,20 +93,20 @@ public:
     size_t pos = 0;
 
     /*
-    *  This first 'while' section goes through the found HTML
-    *  file name and attempts to capture the source file name
-    *   which is set as part of the HTML file name: the name of
-    *   the file is found in parenthesis '()'
-    *
-    *   See test HTML file name: UTCovTest(UTCovTest.pas).html.
-    *
-    *   Find the text inside each pair of parenthesis and check
-    *   to see if it ends in '.pas'.  If it can't be found,
-    *   exit the function.
-    */
+     *  This first 'while' section goes through the found HTML
+     *  file name and attempts to capture the source file name
+     *   which is set as part of the HTML file name: the name of
+     *   the file is found in parenthesis '()'
+     *
+     *   See test HTML file name: UTCovTest(UTCovTest.pas).html.
+     *
+     *   Find the text inside each pair of parenthesis and check
+     *   to see if it ends in '.pas'.  If it can't be found,
+     *   exit the function.
+     */
     while (true) {
       lastoffset = line.find('(', pos);
-      if (lastoffset == line.npos) {
+      if (lastoffset == std::string::npos) {
         cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, endnamepos
                              << "File not found  " << lastoffset << std::endl,
                            this->Coverage.Quiet);
@@ -111,7 +114,7 @@ public:
       }
       endnamepos = line.find(')', lastoffset);
       filename = line.substr(lastoffset + 1, (endnamepos - 1) - lastoffset);
-      if (filename.find(".pas") != filename.npos) {
+      if (filename.find(".pas") != std::string::npos) {
         cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                            "Coverage found for file:  " << filename
                                                         << std::endl,
@@ -121,9 +124,9 @@ public:
       pos = lastoffset + 1;
     }
     /*
-    *  Glob through the source directory for the
-    *  file found above
-    */
+     *  Glob through the source directory for the
+     *  file found above
+     */
     cmsys::Glob gl;
     gl.RecurseOn();
     gl.RecurseThroughSymlinksOff();
@@ -132,9 +135,9 @@ public:
     std::vector<std::string> const& files = gl.GetFiles();
     if (files.empty()) {
       /*
-      *  If that doesn't find any matching files
-      *  return a failure.
-      */
+       *  If that doesn't find any matching files
+       *  return a failure.
+       */
       cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                          "Unable to find file matching" << glob << std::endl,
                          this->Coverage.Quiet);
@@ -143,9 +146,9 @@ public:
     FileLinesType& coverageVector = this->Coverage.TotalCoverage[files[0]];
 
     /*
-    *  Initialize the file to have all code between 'begin' and
-    *  'end' tags marked as executable
-    */
+     *  Initialize the file to have all code between 'begin' and
+     *  'end' tags marked as executable
+     */
 
     this->initializeDelphiFile(files[0], coverageVector);
 
@@ -155,19 +158,19 @@ public:
     }
 
     /*
-    *  Now read the HTML file, looking for the lines that have an
-    *  "inline" in it. Then parse out the "class" value of that
-    *  line to determine if the line is executed or not.
-    *
-    *  Sample HTML line:
-    *
-    *  <tr class="covered"><td>47</td><td><pre style="display:inline;">
-    *     CheckEquals(1,2-1);</pre></td></tr>
-    *
-    */
+     *  Now read the HTML file, looking for the lines that have an
+     *  "inline" in it. Then parse out the "class" value of that
+     *  line to determine if the line is executed or not.
+     *
+     *  Sample HTML line:
+     *
+     *  <tr class="covered"><td>47</td><td><pre style="display:inline;">
+     *     CheckEquals(1,2-1);</pre></td></tr>
+     *
+     */
 
     while (cmSystemTools::GetLineFromStream(in, line)) {
-      if (line.find("inline") == line.npos) {
+      if (line.find("inline") == std::string::npos) {
         continue;
       }
 
diff --git a/Source/CTest/cmParseDelphiCoverage.h b/Source/CTest/cmParseDelphiCoverage.h
index 278fbeb..1b37405 100644
--- a/Source/CTest/cmParseDelphiCoverage.h
+++ b/Source/CTest/cmParseDelphiCoverage.h
@@ -3,7 +3,7 @@
 #ifndef cmParseDelphiCoverage_h
 #define cmParseDelphiCoverage_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index 214ce5a..e4ee699 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -4,8 +4,8 @@
 #include "cmCTestCoverageHandler.h"
 #include "cmSystemTools.h"
 
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
 #include <map>
 #include <stdio.h>
 #include <stdlib.h>
@@ -56,7 +56,7 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
   int lastoffset = 0;
   while (cmSystemTools::GetLineFromStream(in, line)) {
     // only look at lines that have coverage data
-    if (line.find("^ZZCOVERAGE") == line.npos) {
+    if (line.find("^ZZCOVERAGE") == std::string::npos) {
       continue;
     }
     std::string filepath;
@@ -199,7 +199,7 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line,
   // now parse the right hand side of the =
   pos = line.find('=');
   // no = found, this is an error
-  if (pos == line.npos) {
+  if (pos == std::string::npos) {
     return false;
   }
   pos++; // move past =
diff --git a/Source/CTest/cmParseGTMCoverage.h b/Source/CTest/cmParseGTMCoverage.h
index 34721ff..c4949d4 100644
--- a/Source/CTest/cmParseGTMCoverage.h
+++ b/Source/CTest/cmParseGTMCoverage.h
@@ -3,7 +3,7 @@
 #ifndef cmParseGTMCoverage_h
 #define cmParseGTMCoverage_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmParseMumpsCoverage.h"
 
diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx
index 0e36c01..d15864a 100644
--- a/Source/CTest/cmParseJacocoCoverage.cxx
+++ b/Source/CTest/cmParseJacocoCoverage.cxx
@@ -1,15 +1,15 @@
 #include "cmParseJacocoCoverage.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCTest.h"
 #include "cmCTestCoverageHandler.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
 #include <stdlib.h>
 #include <string.h>
 
diff --git a/Source/CTest/cmParseJacocoCoverage.h b/Source/CTest/cmParseJacocoCoverage.h
index 04f1949..f2aec6d 100644
--- a/Source/CTest/cmParseJacocoCoverage.h
+++ b/Source/CTest/cmParseJacocoCoverage.h
@@ -3,7 +3,7 @@
 #ifndef cmParseJacocoCoverage_h
 #define cmParseJacocoCoverage_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <string>
diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx
index ab8be76..eb29f55 100644
--- a/Source/CTest/cmParseMumpsCoverage.cxx
+++ b/Source/CTest/cmParseMumpsCoverage.cxx
@@ -4,9 +4,9 @@
 #include "cmCTestCoverageHandler.h"
 #include "cmSystemTools.h"
 
-#include <cmConfigure.h>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
+#include "cmConfigure.h"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
 #include <map>
 #include <string>
 #include <utility>
diff --git a/Source/CTest/cmParseMumpsCoverage.h b/Source/CTest/cmParseMumpsCoverage.h
index c4ed175..2c54495 100644
--- a/Source/CTest/cmParseMumpsCoverage.h
+++ b/Source/CTest/cmParseMumpsCoverage.h
@@ -3,7 +3,7 @@
 #ifndef cmParseMumpsCoverage_h
 #define cmParseMumpsCoverage_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <string>
diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx
index d8bb31b..761ebec 100644
--- a/Source/CTest/cmParsePHPCoverage.cxx
+++ b/Source/CTest/cmParsePHPCoverage.cxx
@@ -4,8 +4,8 @@
 #include "cmCTestCoverageHandler.h"
 #include "cmSystemTools.h"
 
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
 #include <stdlib.h>
 #include <string.h>
 
diff --git a/Source/CTest/cmParsePHPCoverage.h b/Source/CTest/cmParsePHPCoverage.h
index 4bcad6d..ff0e636 100644
--- a/Source/CTest/cmParsePHPCoverage.h
+++ b/Source/CTest/cmParsePHPCoverage.h
@@ -3,7 +3,7 @@
 #ifndef cmParsePHPCoverage_h
 #define cmParsePHPCoverage_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
 #include <string>
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 32ffa6b..f4ec6da 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmProcess.h"
 
-#include <cmConfigure.h>
-#include <cmProcessOutput.h>
-#include <cmSystemTools.h>
+#include "cmConfigure.h"
+#include "cmProcessOutput.h"
+#include "cmSystemTools.h"
 #include <iostream>
 
 cmProcess::cmProcess()
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index 9d201d1..86e905a 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -3,9 +3,9 @@
 #ifndef cmProcess_h
 #define cmProcess_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
-#include <cmsys/Process.h>
+#include "cmsys/Process.h"
 #include <string>
 #include <vector>
 
diff --git a/Source/Checks/cm_cxx_attribute_fallthrough.cxx b/Source/Checks/cm_cxx_attribute_fallthrough.cxx
new file mode 100644
index 0000000..df43625
--- /dev/null
+++ b/Source/Checks/cm_cxx_attribute_fallthrough.cxx
@@ -0,0 +1,11 @@
+int main(int argc, char* argv[])
+{
+  int i = 3;
+  switch (argc) {
+    case 1:
+      i = 0;
+      __attribute__((fallthrough));
+    default:
+      return i;
+  }
+}
diff --git a/Source/Checks/cm_cxx_eq_delete.cxx b/Source/Checks/cm_cxx_eq_delete.cxx
new file mode 100644
index 0000000..809e4cf
--- /dev/null
+++ b/Source/Checks/cm_cxx_eq_delete.cxx
@@ -0,0 +1,14 @@
+struct Foo
+{
+  Foo() {}
+  ~Foo() {}
+  Foo(Foo const&) = delete;
+  Foo& operator=(Foo const&) = delete;
+  int test() const { return 0; }
+};
+
+int main()
+{
+  Foo const foo;
+  return foo.test();
+}
diff --git a/Source/Checks/cm_cxx_fallthrough.cxx b/Source/Checks/cm_cxx_fallthrough.cxx
new file mode 100644
index 0000000..7b35a5f
--- /dev/null
+++ b/Source/Checks/cm_cxx_fallthrough.cxx
@@ -0,0 +1,11 @@
+int main(int argc, char* argv[])
+{
+  int i = 3;
+  switch (argc) {
+    case 1:
+      i = 0;
+      [[fallthrough]];
+    default:
+      return i;
+  }
+}
diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake
index 80c9f3b..3b08025 100644
--- a/Source/Checks/cm_cxx_features.cmake
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -3,14 +3,21 @@ function(cm_check_cxx_feature name)
   string(TOUPPER ${name} FEATURE)
   if(NOT DEFINED CMake_HAVE_CXX_${FEATURE})
     message(STATUS "Checking if compiler supports C++ ${name}")
+    if(CMAKE_CXX_STANDARD)
+      set(maybe_cxx_standard -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD})
+    else()
+      set(maybe_cxx_standard "")
+    endif()
     try_compile(CMake_HAVE_CXX_${FEATURE}
       ${CMAKE_CURRENT_BINARY_DIR}
       ${CMAKE_CURRENT_LIST_DIR}/cm_cxx_${name}.cxx
-      CMAKE_FLAGS -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}
+      CMAKE_FLAGS ${maybe_cxx_standard}
       OUTPUT_VARIABLE OUTPUT
       )
+    # Filter out MSBuild output that looks like a warning.
+    string(REGEX REPLACE " +0 Warning\\(s\\)" "" check_output "${OUTPUT}")
     # If using the feature causes warnings, treat it as broken/unavailable.
-    if(OUTPUT MATCHES "warning")
+    if(check_output MATCHES "[Ww]arning")
       set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE)
     endif()
     if(CMake_HAVE_CXX_${FEATURE})
@@ -31,15 +38,21 @@ function(cm_check_cxx_feature name)
   endif()
 endfunction()
 
-if(CMAKE_CXX_STANDARD)
-  cm_check_cxx_feature(auto_ptr)
-  cm_check_cxx_feature(make_unique)
-  if(CMake_HAVE_CXX_MAKE_UNIQUE)
-    set(CMake_HAVE_CXX_UNIQUE_PTR 1)
+cm_check_cxx_feature(auto_ptr)
+cm_check_cxx_feature(eq_delete)
+cm_check_cxx_feature(fallthrough)
+if(NOT CMake_HAVE_CXX_FALLTHROUGH)
+  cm_check_cxx_feature(gnu_fallthrough)
+  if(NOT CMake_HAVE_CXX_GNU_FALLTHROUGH)
+    cm_check_cxx_feature(attribute_fallthrough)
   endif()
-  cm_check_cxx_feature(nullptr)
-  cm_check_cxx_feature(override)
-  cm_check_cxx_feature(unique_ptr)
-  cm_check_cxx_feature(unordered_map)
-  cm_check_cxx_feature(unordered_set)
 endif()
+cm_check_cxx_feature(make_unique)
+if(CMake_HAVE_CXX_MAKE_UNIQUE)
+  set(CMake_HAVE_CXX_UNIQUE_PTR 1)
+endif()
+cm_check_cxx_feature(nullptr)
+cm_check_cxx_feature(override)
+cm_check_cxx_feature(unique_ptr)
+cm_check_cxx_feature(unordered_map)
+cm_check_cxx_feature(unordered_set)
diff --git a/Source/Checks/cm_cxx_gnu_fallthrough.cxx b/Source/Checks/cm_cxx_gnu_fallthrough.cxx
new file mode 100644
index 0000000..6021094
--- /dev/null
+++ b/Source/Checks/cm_cxx_gnu_fallthrough.cxx
@@ -0,0 +1,11 @@
+int main(int argc, char* argv[])
+{
+  int i = 3;
+  switch (argc) {
+    case 1:
+      i = 0;
+      [[gnu::fallthrough]];
+    default:
+      return i;
+  }
+}
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index ff8e010..28a0e95 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -1,6 +1,6 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCursesForm.h"
 #include "cmCursesMainForm.h"
@@ -10,7 +10,7 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-#include <cmsys/Encoding.hxx>
+#include "cmsys/Encoding.hxx"
 #include <iostream>
 #include <signal.h>
 #include <string.h>
@@ -81,7 +81,7 @@ int main(int argc, char const* const* argv)
   cmDocumentation doc;
   doc.addCMakeStandardDocSections();
   if (doc.CheckOptions(argc, argv)) {
-    cmake hcm;
+    cmake hcm(cmake::RoleInternal);
     hcm.SetHomeDirectory("");
     hcm.SetHomeOutputDirectory("");
     hcm.AddCMakePaths();
diff --git a/Source/CursesDialog/cmCursesBoolWidget.h b/Source/CursesDialog/cmCursesBoolWidget.h
index f79f7e8..90bcc22 100644
--- a/Source/CursesDialog/cmCursesBoolWidget.h
+++ b/Source/CursesDialog/cmCursesBoolWidget.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesBoolWidget_h
 #define cmCursesBoolWidget_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCursesStandardIncludes.h"
 #include "cmCursesWidget.h"
@@ -12,6 +12,8 @@ class cmCursesMainForm;
 
 class cmCursesBoolWidget : public cmCursesWidget
 {
+  CM_DISABLE_COPY(cmCursesBoolWidget)
+
 public:
   cmCursesBoolWidget(int width, int height, int left, int top);
 
@@ -25,10 +27,6 @@ public:
   // Set/Get the value (on/off).
   void SetValueAsBool(bool value);
   bool GetValueAsBool();
-
-protected:
-  cmCursesBoolWidget(const cmCursesBoolWidget& from);
-  void operator=(const cmCursesBoolWidget&);
 };
 
 #endif // cmCursesBoolWidget_h
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
index 5539fbe..d071c91 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
@@ -15,7 +15,6 @@
 #include "cmake.h"
 
 #include <assert.h>
-#include <cmConfigure.h>
 #include <vector>
 
 cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h
index 59a1fd7..3c50078 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.h
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesCacheEntryComposite_h
 #define cmCursesCacheEntryComposite_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include <string>
 
@@ -13,6 +13,8 @@ class cmake;
 
 class cmCursesCacheEntryComposite
 {
+  CM_DISABLE_COPY(cmCursesCacheEntryComposite)
+
 public:
   cmCursesCacheEntryComposite(const std::string& key, int labelwidth,
                               int entrywidth);
@@ -24,9 +26,6 @@ public:
   friend class cmCursesMainForm;
 
 protected:
-  cmCursesCacheEntryComposite(const cmCursesCacheEntryComposite& from);
-  void operator=(const cmCursesCacheEntryComposite&);
-
   cmCursesLabelWidget* Label;
   cmCursesLabelWidget* IsNewLabel;
   cmCursesWidget* Entry;
diff --git a/Source/CursesDialog/cmCursesDummyWidget.h b/Source/CursesDialog/cmCursesDummyWidget.h
index fe43de5..d9bb6ba 100644
--- a/Source/CursesDialog/cmCursesDummyWidget.h
+++ b/Source/CursesDialog/cmCursesDummyWidget.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesDummyWidget_h
 #define cmCursesDummyWidget_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCursesStandardIncludes.h"
 #include "cmCursesWidget.h"
@@ -12,6 +12,8 @@ class cmCursesMainForm;
 
 class cmCursesDummyWidget : public cmCursesWidget
 {
+  CM_DISABLE_COPY(cmCursesDummyWidget)
+
 public:
   cmCursesDummyWidget(int width, int height, int left, int top);
 
@@ -20,10 +22,6 @@ public:
   // when this widget has focus. Returns true if the input was
   // handled.
   bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
-
-protected:
-  cmCursesDummyWidget(const cmCursesDummyWidget& from);
-  void operator=(const cmCursesDummyWidget&);
 };
 
 #endif // cmCursesDummyWidget_h
diff --git a/Source/CursesDialog/cmCursesFilePathWidget.h b/Source/CursesDialog/cmCursesFilePathWidget.h
index 7df7f00..6ad535b 100644
--- a/Source/CursesDialog/cmCursesFilePathWidget.h
+++ b/Source/CursesDialog/cmCursesFilePathWidget.h
@@ -3,18 +3,16 @@
 #ifndef cmCursesFilePathWidget_h
 #define cmCursesFilePathWidget_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include "cmCursesPathWidget.h"
 
 class cmCursesFilePathWidget : public cmCursesPathWidget
 {
+  CM_DISABLE_COPY(cmCursesFilePathWidget)
+
 public:
   cmCursesFilePathWidget(int width, int height, int left, int top);
-
-protected:
-  cmCursesFilePathWidget(const cmCursesFilePathWidget& from);
-  void operator=(const cmCursesFilePathWidget&);
 };
 
 #endif // cmCursesFilePathWidget_h
diff --git a/Source/CursesDialog/cmCursesForm.cxx b/Source/CursesDialog/cmCursesForm.cxx
index 0eb16cb..06c1e9c 100644
--- a/Source/CursesDialog/cmCursesForm.cxx
+++ b/Source/CursesDialog/cmCursesForm.cxx
@@ -2,8 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCursesForm.h"
 
-#include <cmConfigure.h>
-
 cmsys::ofstream cmCursesForm::DebugFile;
 bool cmCursesForm::Debug = false;
 
diff --git a/Source/CursesDialog/cmCursesForm.h b/Source/CursesDialog/cmCursesForm.h
index 85a80c2..553105c 100644
--- a/Source/CursesDialog/cmCursesForm.h
+++ b/Source/CursesDialog/cmCursesForm.h
@@ -3,14 +3,16 @@
 #ifndef cmCursesForm_h
 #define cmCursesForm_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include "cmCursesStandardIncludes.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 
 class cmCursesForm
 {
+  CM_DISABLE_COPY(cmCursesForm)
+
 public:
   cmCursesForm();
   virtual ~cmCursesForm();
@@ -55,9 +57,6 @@ protected:
   static cmsys::ofstream DebugFile;
   static bool Debug;
 
-  cmCursesForm(const cmCursesForm& form);
-  void operator=(const cmCursesForm&);
-
   FORM* Form;
 };
 
diff --git a/Source/CursesDialog/cmCursesLabelWidget.h b/Source/CursesDialog/cmCursesLabelWidget.h
index 4d63f48..267de7c 100644
--- a/Source/CursesDialog/cmCursesLabelWidget.h
+++ b/Source/CursesDialog/cmCursesLabelWidget.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesLabelWidget_h
 #define cmCursesLabelWidget_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCursesStandardIncludes.h"
 #include "cmCursesWidget.h"
@@ -14,6 +14,8 @@ class cmCursesMainForm;
 
 class cmCursesLabelWidget : public cmCursesWidget
 {
+  CM_DISABLE_COPY(cmCursesLabelWidget)
+
 public:
   cmCursesLabelWidget(int width, int height, int left, int top,
                       const std::string& name);
@@ -24,10 +26,6 @@ public:
   // when this widget has focus. Returns true if the input was
   // handled
   bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
-
-protected:
-  cmCursesLabelWidget(const cmCursesLabelWidget& from);
-  void operator=(const cmCursesLabelWidget&);
 };
 
 #endif // cmCursesLabelWidget_h
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index d299547..7fb065d 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -159,7 +159,8 @@ void cmCursesLongMessageForm::HandleInput()
     // quit
     if (key == 'o' || key == 'e') {
       break;
-    } else if (key == KEY_DOWN || key == ctrl('n')) {
+    }
+    if (key == KEY_DOWN || key == ctrl('n')) {
       form_driver(this->Form, REQ_SCR_FLINE);
     } else if (key == KEY_UP || key == ctrl('p')) {
       form_driver(this->Form, REQ_SCR_BLINE);
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h
index e9eae7c..cd8e095 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.h
+++ b/Source/CursesDialog/cmCursesLongMessageForm.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesLongMessageForm_h
 #define cmCursesLongMessageForm_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCursesForm.h"
 #include "cmCursesStandardIncludes.h"
@@ -13,6 +13,8 @@
 
 class cmCursesLongMessageForm : public cmCursesForm
 {
+  CM_DISABLE_COPY(cmCursesLongMessageForm)
+
 public:
   cmCursesLongMessageForm(std::vector<std::string> const& messages,
                           const char* title);
@@ -38,9 +40,6 @@ public:
   void UpdateStatusBar() CM_OVERRIDE;
 
 protected:
-  cmCursesLongMessageForm(const cmCursesLongMessageForm& from);
-  void operator=(const cmCursesLongMessageForm&);
-
   std::string Messages;
   std::string Title;
 
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 939c736..026320a 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -40,7 +40,7 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> const& args,
     "Welcome to ccmake, curses based user interface for CMake.");
   this->HelpMessage.push_back("");
   this->HelpMessage.push_back(s_ConstHelpMessage);
-  this->CMakeInstance = new cmake;
+  this->CMakeInstance = new cmake(cmake::RoleProject);
   this->CMakeInstance->SetCMakeEditCommand(
     cmSystemTools::GetCMakeCursesCommand());
 
@@ -764,9 +764,8 @@ void cmCursesMainForm::HandleInput()
       // quit
       if (key == 'q') {
         break;
-      } else {
-        continue;
       }
+      continue;
     }
 
     currentField = current_field(this->Form);
@@ -826,7 +825,7 @@ void cmCursesMainForm::HandleInput()
       // (index always corresponds to the value field)
       // scroll down with arrow down, ctrl+n (emacs binding), or j (vim
       // binding)
-      else if (key == KEY_DOWN || key == ctrl('n') || key == 'j') {
+      if (key == KEY_DOWN || key == ctrl('n') || key == 'j') {
         FIELD* cur = current_field(this->Form);
         size_t findex = field_index(cur);
         if (findex == 3 * this->NumberOfVisibleEntries - 1) {
@@ -1051,7 +1050,7 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr)
         const char* curField = lbl->GetValue();
         if (curField) {
           std::string cfld = cmSystemTools::LowerCase(curField);
-          if (cfld.find(str) != cfld.npos && findex != start_index) {
+          if (cfld.find(str) != std::string::npos && findex != start_index) {
             break;
           }
         }
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index d891ea0..e35cf3e 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesMainForm_h
 #define cmCursesMainForm_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCursesForm.h"
 #include "cmCursesStandardIncludes.h"
@@ -23,6 +23,8 @@ class cmake;
  */
 class cmCursesMainForm : public cmCursesForm
 {
+  CM_DISABLE_COPY(cmCursesMainForm)
+
 public:
   cmCursesMainForm(std::vector<std::string> const& args, int initwidth);
   ~cmCursesMainForm() CM_OVERRIDE;
@@ -103,9 +105,6 @@ public:
   static void UpdateProgress(const char* msg, float prog, void*);
 
 protected:
-  cmCursesMainForm(const cmCursesMainForm& from);
-  void operator=(const cmCursesMainForm&);
-
   // Copy the cache values from the user interface to the actual
   // cache.
   void FillCacheManagerFromUI();
diff --git a/Source/CursesDialog/cmCursesOptionsWidget.h b/Source/CursesDialog/cmCursesOptionsWidget.h
index 75065a2..7f4416f 100644
--- a/Source/CursesDialog/cmCursesOptionsWidget.h
+++ b/Source/CursesDialog/cmCursesOptionsWidget.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesOptionsWidget_h
 #define cmCursesOptionsWidget_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCursesStandardIncludes.h"
 #include "cmCursesWidget.h"
@@ -15,6 +15,8 @@ class cmCursesMainForm;
 
 class cmCursesOptionsWidget : public cmCursesWidget
 {
+  CM_DISABLE_COPY(cmCursesOptionsWidget)
+
 public:
   cmCursesOptionsWidget(int width, int height, int left, int top);
 
@@ -29,8 +31,6 @@ public:
   void PreviousOption();
 
 protected:
-  cmCursesOptionsWidget(const cmCursesOptionsWidget& from);
-  void operator=(const cmCursesOptionsWidget&);
   std::vector<std::string> Options;
   std::vector<std::string>::size_type CurrentOption;
 };
diff --git a/Source/CursesDialog/cmCursesPathWidget.h b/Source/CursesDialog/cmCursesPathWidget.h
index 63ed05b..ae6c16d 100644
--- a/Source/CursesDialog/cmCursesPathWidget.h
+++ b/Source/CursesDialog/cmCursesPathWidget.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesPathWidget_h
 #define cmCursesPathWidget_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCursesStandardIncludes.h"
 #include "cmCursesStringWidget.h"
@@ -14,6 +14,8 @@ class cmCursesMainForm;
 
 class cmCursesPathWidget : public cmCursesStringWidget
 {
+  CM_DISABLE_COPY(cmCursesPathWidget)
+
 public:
   cmCursesPathWidget(int width, int height, int left, int top);
 
@@ -26,9 +28,6 @@ public:
   void OnType(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
 
 protected:
-  cmCursesPathWidget(const cmCursesPathWidget& from);
-  void operator=(const cmCursesPathWidget&);
-
   std::string LastString;
   std::string LastGlob;
   bool Cycle;
diff --git a/Source/CursesDialog/cmCursesStandardIncludes.h b/Source/CursesDialog/cmCursesStandardIncludes.h
index 7818e3e..5c59504 100644
--- a/Source/CursesDialog/cmCursesStandardIncludes.h
+++ b/Source/CursesDialog/cmCursesStandardIncludes.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesStandardIncludes_h
 #define cmCursesStandardIncludes_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #if defined(__hpux)
 #define _BOOL_DEFINED
diff --git a/Source/CursesDialog/cmCursesStringWidget.h b/Source/CursesDialog/cmCursesStringWidget.h
index b3c1089..5eb3366 100644
--- a/Source/CursesDialog/cmCursesStringWidget.h
+++ b/Source/CursesDialog/cmCursesStringWidget.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesStringWidget_h
 #define cmCursesStringWidget_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCursesStandardIncludes.h"
 #include "cmCursesWidget.h"
@@ -20,6 +20,8 @@ class cmCursesMainForm;
 
 class cmCursesStringWidget : public cmCursesWidget
 {
+  CM_DISABLE_COPY(cmCursesStringWidget)
+
 public:
   cmCursesStringWidget(int width, int height, int left, int top);
 
@@ -60,9 +62,6 @@ public:
   bool PrintKeys() CM_OVERRIDE;
 
 protected:
-  cmCursesStringWidget(const cmCursesStringWidget& from);
-  void operator=(const cmCursesStringWidget&);
-
   // true if the widget is in edit mode
   bool InEdit;
   char* OriginalString;
diff --git a/Source/CursesDialog/cmCursesWidget.cxx b/Source/CursesDialog/cmCursesWidget.cxx
index a9918f7..054f27e 100644
--- a/Source/CursesDialog/cmCursesWidget.cxx
+++ b/Source/CursesDialog/cmCursesWidget.cxx
@@ -2,8 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCursesWidget.h"
 
-#include <cmConfigure.h>
-
 cmCursesWidget::cmCursesWidget(int width, int height, int left, int top)
 {
   this->Field = new_field(height, width, top, left, 0, 0);
diff --git a/Source/CursesDialog/cmCursesWidget.h b/Source/CursesDialog/cmCursesWidget.h
index d226dd7..3470d70 100644
--- a/Source/CursesDialog/cmCursesWidget.h
+++ b/Source/CursesDialog/cmCursesWidget.h
@@ -3,7 +3,7 @@
 #ifndef cmCursesWidget_h
 #define cmCursesWidget_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include "cmCursesStandardIncludes.h"
 #include "cmStateTypes.h"
@@ -14,6 +14,8 @@ class cmCursesMainForm;
 
 class cmCursesWidget
 {
+  CM_DISABLE_COPY(cmCursesWidget)
+
 public:
   cmCursesWidget(int width, int height, int left, int top);
   virtual ~cmCursesWidget();
@@ -59,9 +61,6 @@ public:
   friend class cmCursesMainForm;
 
 protected:
-  cmCursesWidget(const cmCursesWidget& from);
-  void operator=(const cmCursesWidget&);
-
   cmStateEnums::CacheEntryType Type;
   std::string Value;
   FIELD* Field;
diff --git a/Source/CursesDialog/form/form.h b/Source/CursesDialog/form/form.h
index b65a3ca..39ed75a 100644
--- a/Source/CursesDialog/form/form.h
+++ b/Source/CursesDialog/form/form.h
@@ -33,7 +33,7 @@
 #ifndef FORM_H
 #define FORM_H
 
-#include <cmFormConfigure.h>
+#include "cmFormConfigure.h"
 
 /* figure out which curses.h to include */
 # if defined(CURSES_HAVE_NCURSES_H)
diff --git a/Source/LexerParser/.clang-tidy b/Source/LexerParser/.clang-tidy
new file mode 100644
index 0000000..52b11bf
--- /dev/null
+++ b/Source/LexerParser/.clang-tidy
@@ -0,0 +1,6 @@
+---
+# We want to disable all checks for generated code.  However, clang-tidy will
+# assume we did not configure it correctly.  Just add one check that will never
+# be found.
+Checks: '-*,llvm-twine-local'
+...
diff --git a/Source/LexerParser/.gitattributes b/Source/LexerParser/.gitattributes
new file mode 100644
index 0000000..47eedfb
--- /dev/null
+++ b/Source/LexerParser/.gitattributes
@@ -0,0 +1,17 @@
+/cmCommandArgumentLexer.cxx        generated
+/cmCommandArgumentLexer.h          generated
+/cmCommandArgumentParser.cxx       generated
+/cmCommandArgumentParserTokens.h   generated
+/cmDependsJavaLexer.cxx            generated
+/cmDependsJavaLexer.h              generated
+/cmDependsJavaParser.cxx           generated
+/cmDependsJavaParserTokens.h       generated
+/cmExprLexer.cxx                   generated
+/cmExprLexer.h                     generated
+/cmExprParser.cxx                  generated
+/cmExprParserTokens.h              generated
+/cmFortranLexer.cxx                generated
+/cmFortranLexer.h                  generated
+/cmFortranParser.cxx               generated
+/cmFortranParserTokens.h           generated
+/cmListFileLexer.c                 generated
diff --git a/Source/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx
similarity index 100%
rename from Source/cmCommandArgumentLexer.cxx
rename to Source/LexerParser/cmCommandArgumentLexer.cxx
diff --git a/Source/cmCommandArgumentLexer.h b/Source/LexerParser/cmCommandArgumentLexer.h
similarity index 100%
rename from Source/cmCommandArgumentLexer.h
rename to Source/LexerParser/cmCommandArgumentLexer.h
diff --git a/Source/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l
similarity index 100%
rename from Source/cmCommandArgumentLexer.in.l
rename to Source/LexerParser/cmCommandArgumentLexer.in.l
diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx
new file mode 100644
index 0000000..aed0826
--- /dev/null
+++ b/Source/LexerParser/cmCommandArgumentParser.cxx
@@ -0,0 +1,1723 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names.  */
+#define yyparse         cmCommandArgument_yyparse
+#define yylex           cmCommandArgument_yylex
+#define yyerror         cmCommandArgument_yyerror
+#define yydebug         cmCommandArgument_yydebug
+#define yynerrs         cmCommandArgument_yynerrs
+
+
+/* Copy the first part of user declarations.  */
+#line 1 "cmCommandArgumentParser.y" /* yacc.c:339  */
+
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+  bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
+
+Modify cmCommandArgumentParser.cxx:
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string.h>
+
+#define yyGetParser (cmCommandArgument_yyget_extra(yyscanner))
+
+/* Make sure malloc and free are available on QNX.  */
+#ifdef __QNX__
+# include <malloc.h>
+#endif
+
+/* Make sure the parser uses standard memory allocation.  The default
+   generated parser malloc/free declarations do not work on all
+   platforms.  */
+#include <stdlib.h>
+#define YYMALLOC malloc
+#define YYFREE free
+
+/*-------------------------------------------------------------------------*/
+#include "cmCommandArgumentParserHelper.h" /* Interface to parser object.  */
+#include "cmCommandArgumentLexer.h"  /* Interface to lexer object.  */
+#include "cmCommandArgumentParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
+
+/* Forward declare the lexer entry point.  */
+YY_DECL;
+
+/* Helper function to forward error callback from parser.  */
+static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
+
+/* Configure the parser to support large input.  */
+#define YYMAXDEPTH 100000
+#define YYINITDEPTH 10000
+
+/* Disable some warnings in the generated code.  */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label.  */
+# pragma warning (disable: 4065) /* Switch statement contains default but no
+                                    case. */
+# pragma warning (disable: 4244) /* loss of precision */
+# pragma warning (disable: 4702) /* unreachable code */
+#endif
+
+#line 131 "cmCommandArgumentParser.cxx" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "cmCommandArgumentParserTokens.h".  */
+#ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
+# define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmCommandArgument_yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    cal_ENVCURLY = 258,
+    cal_NCURLY = 259,
+    cal_DCURLY = 260,
+    cal_DOLLAR = 261,
+    cal_LCURLY = 262,
+    cal_RCURLY = 263,
+    cal_NAME = 264,
+    cal_BSLASH = 265,
+    cal_SYMBOL = 266,
+    cal_AT = 267,
+    cal_ERROR = 268,
+    cal_ATNAME = 269
+  };
+#endif
+/* Tokens.  */
+#define cal_ENVCURLY 258
+#define cal_NCURLY 259
+#define cal_DCURLY 260
+#define cal_DOLLAR 261
+#define cal_LCURLY 262
+#define cal_RCURLY 263
+#define cal_NAME 264
+#define cal_BSLASH 265
+#define cal_SYMBOL 266
+#define cal_AT 267
+#define cal_ERROR 268
+#define cal_ATNAME 269
+
+/* Value type.  */
+
+
+
+int cmCommandArgument_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 204 "cmCommandArgumentParser.cxx" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  25
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   40
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  15
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  10
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  24
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  33
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   269
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint8 yyrline[] =
+{
+       0,    96,    96,   102,   105,   110,   113,   118,   121,   126,
+     129,   132,   135,   138,   141,   146,   149,   152,   155,   160,
+     163,   168,   171,   176,   179
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "cal_ENVCURLY", "cal_NCURLY",
+  "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"",
+  "cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start",
+  "GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable",
+  "EnvVarName", "MultipleIds", "ID", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269
+};
+# endif
+
+#define YYPACT_NINF -3
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-3)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int8 yypact[] =
+{
+       0,    14,    26,    26,    -3,    -3,    -3,    -3,    -3,    -3,
+      -3,    10,    -3,     3,     0,    -3,    -3,    -3,    14,    -3,
+       7,    -3,    26,    13,    16,    -3,    -3,    -3,    -3,    -3,
+      -3,    -3,    -3
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       5,    21,    21,    21,    11,    12,    13,     9,    14,    10,
+      18,     0,     2,     3,     5,     7,     8,    23,    21,    24,
+       0,    19,    21,     0,     0,     1,     4,     6,    20,    15,
+      22,    16,    17
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+      -3,    -3,    -3,     8,    -3,    -3,     2,     9,    -2,    -3
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,    11,    12,    13,    14,    15,    19,    20,    21,    22
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+      23,    24,    16,     1,     2,     3,     4,     5,     6,     7,
+      25,     8,     9,    26,    10,    29,    16,     1,     2,     3,
+      30,    31,    27,    17,    32,    18,     0,    28,    10,     1,
+       2,     3,     0,     0,     0,    17,     0,     0,     0,     0,
+      10
+};
+
+static const yytype_int8 yycheck[] =
+{
+       2,     3,     0,     3,     4,     5,     6,     7,     8,     9,
+       0,    11,    12,    10,    14,     8,    14,     3,     4,     5,
+      22,     8,    14,     9,     8,    11,    -1,    18,    14,     3,
+       4,     5,    -1,    -1,    -1,     9,    -1,    -1,    -1,    -1,
+      14
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     3,     4,     5,     6,     7,     8,     9,    11,    12,
+      14,    16,    17,    18,    19,    20,    21,     9,    11,    21,
+      22,    23,    24,    23,    23,     0,    10,    18,    22,     8,
+      23,     8,     8
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    15,    16,    17,    17,    18,    18,    19,    19,    20,
+      20,    20,    20,    20,    20,    21,    21,    21,    21,    22,
+      22,    23,    23,    24,    24
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     1,     2,     0,     2,     1,     1,     1,
+       1,     1,     1,     1,     1,     3,     3,     3,     1,     1,
+       2,     0,     2,     1,     1
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, yyscanner); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (yyscanner);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , yyscanner);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
+{
+  YYUSE (yyvaluep);
+  YYUSE (yyscanner);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (yyscan_t yyscanner)
+{
+/* The lookahead symbol.  */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol.  */
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex (&yylval, yyscanner);
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 96 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = 0;
+    yyGetParser->SetResult((yyvsp[0].str));
+  }
+#line 1306 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 3:
+#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 4:
+#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
+  }
+#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 5:
+#line 110 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = 0;
+  }
+#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 6:
+#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
+  }
+#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 7:
+#line 118 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 126 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 12:
+#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 13:
+#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 14:
+#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 15:
+#line 146 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
+  }
+#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 16:
+#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
+  }
+#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 17:
+#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str));
+  }
+#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 18:
+#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str));
+  }
+#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 19:
+#line 160 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 20:
+#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[-1].str);
+  }
+#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 21:
+#line 168 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = 0;
+  }
+#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 22:
+#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
+  }
+#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 23:
+#line 176 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 24:
+#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646  */
+    {
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+    break;
+
+
+#line 1486 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (yyscanner, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (yyscanner, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, yyscanner);
+          yychar = YYEMPTY;
+        }
+    }
+
+#if 0
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+#endif
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, yyscanner);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (yyscanner, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, yyscanner);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp, yyscanner);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
+#line 184 "cmCommandArgumentParser.y" /* yacc.c:1906  */
+
+/* End of grammar */
+
+/*--------------------------------------------------------------------------*/
+void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message)
+{
+  yyGetParser->Error(message);
+}
diff --git a/Source/LexerParser/cmCommandArgumentParser.y b/Source/LexerParser/cmCommandArgumentParser.y
new file mode 100644
index 0000000..55a88df
--- /dev/null
+++ b/Source/LexerParser/cmCommandArgumentParser.y
@@ -0,0 +1,191 @@
+%{
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+  bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
+
+Modify cmCommandArgumentParser.cxx:
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string.h>
+
+#define yyGetParser (cmCommandArgument_yyget_extra(yyscanner))
+
+/* Make sure malloc and free are available on QNX.  */
+#ifdef __QNX__
+# include <malloc.h>
+#endif
+
+/* Make sure the parser uses standard memory allocation.  The default
+   generated parser malloc/free declarations do not work on all
+   platforms.  */
+#include <stdlib.h>
+#define YYMALLOC malloc
+#define YYFREE free
+
+/*-------------------------------------------------------------------------*/
+#include "cmCommandArgumentParserHelper.h" /* Interface to parser object.  */
+#include "cmCommandArgumentLexer.h"  /* Interface to lexer object.  */
+#include "cmCommandArgumentParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
+
+/* Forward declare the lexer entry point.  */
+YY_DECL;
+
+/* Helper function to forward error callback from parser.  */
+static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
+
+/* Configure the parser to support large input.  */
+#define YYMAXDEPTH 100000
+#define YYINITDEPTH 10000
+
+/* Disable some warnings in the generated code.  */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label.  */
+# pragma warning (disable: 4065) /* Switch statement contains default but no
+                                    case. */
+# pragma warning (disable: 4244) /* loss of precision */
+# pragma warning (disable: 4702) /* unreachable code */
+#endif
+%}
+
+/* Generate a reentrant parser object.  */
+%define api.pure
+
+/* Configure the parser to use a lexer object.  */
+%lex-param   {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
+
+%define parse.error verbose
+
+/*
+%union {
+  char* string;
+}
+*/
+
+/*-------------------------------------------------------------------------*/
+/* Tokens */
+%token cal_ENVCURLY
+%token cal_NCURLY
+%token cal_DCURLY
+%token cal_DOLLAR "$"
+%token cal_LCURLY "{"
+%token cal_RCURLY "}"
+%token cal_NAME
+%token cal_BSLASH "\\"
+%token cal_SYMBOL
+%token cal_AT     "@"
+%token cal_ERROR
+%token cal_ATNAME
+
+/*-------------------------------------------------------------------------*/
+/* grammar */
+%%
+
+
+Start:
+  GoalWithOptionalBackSlash {
+    $<str>$ = 0;
+    yyGetParser->SetResult($<str>1);
+  }
+
+GoalWithOptionalBackSlash:
+  Goal {
+    $<str>$ = $<str>1;
+  }
+| Goal cal_BSLASH {
+    $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
+  }
+
+Goal:
+  {
+    $<str>$ = 0;
+  }
+| String Goal {
+    $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
+  }
+
+String:
+  OuterText {
+    $<str>$ = $<str>1;
+  }
+| Variable {
+    $<str>$ = $<str>1;
+  }
+
+OuterText:
+  cal_NAME {
+    $<str>$ = $<str>1;
+  }
+| cal_AT {
+    $<str>$ = $<str>1;
+  }
+| cal_DOLLAR {
+    $<str>$ = $<str>1;
+  }
+| cal_LCURLY {
+    $<str>$ = $<str>1;
+  }
+| cal_RCURLY {
+    $<str>$ = $<str>1;
+  }
+| cal_SYMBOL {
+    $<str>$ = $<str>1;
+  }
+
+Variable:
+  cal_ENVCURLY EnvVarName cal_RCURLY {
+    $<str>$ = yyGetParser->ExpandSpecialVariable($<str>1, $<str>2);
+  }
+| cal_NCURLY MultipleIds cal_RCURLY {
+    $<str>$ = yyGetParser->ExpandSpecialVariable($<str>1, $<str>2);
+  }
+| cal_DCURLY MultipleIds cal_RCURLY {
+    $<str>$ = yyGetParser->ExpandVariable($<str>2);
+  }
+| cal_ATNAME {
+    $<str>$ = yyGetParser->ExpandVariableForAt($<str>1);
+  }
+
+EnvVarName:
+  MultipleIds {
+    $<str>$ = $<str>1;
+  }
+| cal_SYMBOL EnvVarName {
+    $<str>$ = $<str>1;
+  }
+
+MultipleIds:
+  {
+    $<str>$ = 0;
+  }
+| ID MultipleIds {
+    $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
+  }
+
+ID:
+  cal_NAME {
+    $<str>$ = $<str>1;
+  }
+| Variable {
+    $<str>$ = $<str>1;
+  }
+;
+
+%%
+/* End of grammar */
+
+/*--------------------------------------------------------------------------*/
+void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message)
+{
+  yyGetParser->Error(message);
+}
diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h
new file mode 100644
index 0000000..3172182
--- /dev/null
+++ b/Source/LexerParser/cmCommandArgumentParserTokens.h
@@ -0,0 +1,82 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
+# define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmCommandArgument_yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    cal_ENVCURLY = 258,
+    cal_NCURLY = 259,
+    cal_DCURLY = 260,
+    cal_DOLLAR = 261,
+    cal_LCURLY = 262,
+    cal_RCURLY = 263,
+    cal_NAME = 264,
+    cal_BSLASH = 265,
+    cal_SYMBOL = 266,
+    cal_AT = 267,
+    cal_ERROR = 268,
+    cal_ATNAME = 269
+  };
+#endif
+/* Tokens.  */
+#define cal_ENVCURLY 258
+#define cal_NCURLY 259
+#define cal_DCURLY 260
+#define cal_DOLLAR 261
+#define cal_LCURLY 262
+#define cal_RCURLY 263
+#define cal_NAME 264
+#define cal_BSLASH 265
+#define cal_SYMBOL 266
+#define cal_AT 267
+#define cal_ERROR 268
+#define cal_ATNAME 269
+
+/* Value type.  */
+
+
+
+int cmCommandArgument_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED  */
diff --git a/Source/cmDependsJavaLexer.cxx b/Source/LexerParser/cmDependsJavaLexer.cxx
similarity index 100%
rename from Source/cmDependsJavaLexer.cxx
rename to Source/LexerParser/cmDependsJavaLexer.cxx
diff --git a/Source/cmDependsJavaLexer.h b/Source/LexerParser/cmDependsJavaLexer.h
similarity index 100%
rename from Source/cmDependsJavaLexer.h
rename to Source/LexerParser/cmDependsJavaLexer.h
diff --git a/Source/cmDependsJavaLexer.in.l b/Source/LexerParser/cmDependsJavaLexer.in.l
similarity index 100%
rename from Source/cmDependsJavaLexer.in.l
rename to Source/LexerParser/cmDependsJavaLexer.in.l
diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx
new file mode 100644
index 0000000..bc45d45
--- /dev/null
+++ b/Source/LexerParser/cmDependsJavaParser.cxx
@@ -0,0 +1,6421 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names.  */
+#define yyparse         cmDependsJava_yyparse
+#define yylex           cmDependsJava_yylex
+#define yyerror         cmDependsJava_yyerror
+#define yydebug         cmDependsJava_yydebug
+#define yynerrs         cmDependsJava_yynerrs
+
+
+/* Copy the first part of user declarations.  */
+#line 1 "cmDependsJavaParser.y" /* yacc.c:339  */
+
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+  bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y
+
+Modify cmDependsJavaParser.cxx:
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
+#define yyGetParser (cmDependsJava_yyget_extra(yyscanner))
+
+/*-------------------------------------------------------------------------*/
+#include "cmDependsJavaParserHelper.h" /* Interface to parser object.  */
+#include "cmDependsJavaLexer.h"  /* Interface to lexer object.  */
+#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
+
+/* Forward declare the lexer entry point.  */
+YY_DECL;
+
+/* Helper function to forward error callback from parser.  */
+static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
+
+#define YYMAXDEPTH 1000000
+
+
+#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp);
+#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval)
+#define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str))
+/* Disable some warnings in the generated code.  */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label.  */
+# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
+#endif
+
+#line 120 "cmDependsJavaParser.cxx" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "cmDependsJavaParserTokens.h".  */
+#ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
+# define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmDependsJava_yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    jp_ABSTRACT = 258,
+    jp_ASSERT = 259,
+    jp_BOOLEAN_TYPE = 260,
+    jp_BREAK = 261,
+    jp_BYTE_TYPE = 262,
+    jp_CASE = 263,
+    jp_CATCH = 264,
+    jp_CHAR_TYPE = 265,
+    jp_CLASS = 266,
+    jp_CONTINUE = 267,
+    jp_DEFAULT = 268,
+    jp_DO = 269,
+    jp_DOUBLE_TYPE = 270,
+    jp_ELSE = 271,
+    jp_EXTENDS = 272,
+    jp_FINAL = 273,
+    jp_FINALLY = 274,
+    jp_FLOAT_TYPE = 275,
+    jp_FOR = 276,
+    jp_IF = 277,
+    jp_IMPLEMENTS = 278,
+    jp_IMPORT = 279,
+    jp_INSTANCEOF = 280,
+    jp_INT_TYPE = 281,
+    jp_INTERFACE = 282,
+    jp_LONG_TYPE = 283,
+    jp_NATIVE = 284,
+    jp_NEW = 285,
+    jp_PACKAGE = 286,
+    jp_PRIVATE = 287,
+    jp_PROTECTED = 288,
+    jp_PUBLIC = 289,
+    jp_RETURN = 290,
+    jp_SHORT_TYPE = 291,
+    jp_STATIC = 292,
+    jp_STRICTFP = 293,
+    jp_SUPER = 294,
+    jp_SWITCH = 295,
+    jp_SYNCHRONIZED = 296,
+    jp_THIS = 297,
+    jp_THROW = 298,
+    jp_THROWS = 299,
+    jp_TRANSIENT = 300,
+    jp_TRY = 301,
+    jp_VOID = 302,
+    jp_VOLATILE = 303,
+    jp_WHILE = 304,
+    jp_BOOLEANLITERAL = 305,
+    jp_CHARACTERLITERAL = 306,
+    jp_DECIMALINTEGERLITERAL = 307,
+    jp_FLOATINGPOINTLITERAL = 308,
+    jp_HEXINTEGERLITERAL = 309,
+    jp_NULLLITERAL = 310,
+    jp_STRINGLITERAL = 311,
+    jp_NAME = 312,
+    jp_AND = 313,
+    jp_ANDAND = 314,
+    jp_ANDEQUALS = 315,
+    jp_BRACKETEND = 316,
+    jp_BRACKETSTART = 317,
+    jp_CARROT = 318,
+    jp_CARROTEQUALS = 319,
+    jp_COLON = 320,
+    jp_COMMA = 321,
+    jp_CURLYEND = 322,
+    jp_CURLYSTART = 323,
+    jp_DIVIDE = 324,
+    jp_DIVIDEEQUALS = 325,
+    jp_DOLLAR = 326,
+    jp_DOT = 327,
+    jp_EQUALS = 328,
+    jp_EQUALSEQUALS = 329,
+    jp_EXCLAMATION = 330,
+    jp_EXCLAMATIONEQUALS = 331,
+    jp_GREATER = 332,
+    jp_GTEQUALS = 333,
+    jp_GTGT = 334,
+    jp_GTGTEQUALS = 335,
+    jp_GTGTGT = 336,
+    jp_GTGTGTEQUALS = 337,
+    jp_LESLESEQUALS = 338,
+    jp_LESSTHAN = 339,
+    jp_LTEQUALS = 340,
+    jp_LTLT = 341,
+    jp_MINUS = 342,
+    jp_MINUSEQUALS = 343,
+    jp_MINUSMINUS = 344,
+    jp_PAREEND = 345,
+    jp_PARESTART = 346,
+    jp_PERCENT = 347,
+    jp_PERCENTEQUALS = 348,
+    jp_PIPE = 349,
+    jp_PIPEEQUALS = 350,
+    jp_PIPEPIPE = 351,
+    jp_PLUS = 352,
+    jp_PLUSEQUALS = 353,
+    jp_PLUSPLUS = 354,
+    jp_QUESTION = 355,
+    jp_SEMICOL = 356,
+    jp_TILDE = 357,
+    jp_TIMES = 358,
+    jp_TIMESEQUALS = 359,
+    jp_ERROR = 360
+  };
+#endif
+/* Tokens.  */
+#define jp_ABSTRACT 258
+#define jp_ASSERT 259
+#define jp_BOOLEAN_TYPE 260
+#define jp_BREAK 261
+#define jp_BYTE_TYPE 262
+#define jp_CASE 263
+#define jp_CATCH 264
+#define jp_CHAR_TYPE 265
+#define jp_CLASS 266
+#define jp_CONTINUE 267
+#define jp_DEFAULT 268
+#define jp_DO 269
+#define jp_DOUBLE_TYPE 270
+#define jp_ELSE 271
+#define jp_EXTENDS 272
+#define jp_FINAL 273
+#define jp_FINALLY 274
+#define jp_FLOAT_TYPE 275
+#define jp_FOR 276
+#define jp_IF 277
+#define jp_IMPLEMENTS 278
+#define jp_IMPORT 279
+#define jp_INSTANCEOF 280
+#define jp_INT_TYPE 281
+#define jp_INTERFACE 282
+#define jp_LONG_TYPE 283
+#define jp_NATIVE 284
+#define jp_NEW 285
+#define jp_PACKAGE 286
+#define jp_PRIVATE 287
+#define jp_PROTECTED 288
+#define jp_PUBLIC 289
+#define jp_RETURN 290
+#define jp_SHORT_TYPE 291
+#define jp_STATIC 292
+#define jp_STRICTFP 293
+#define jp_SUPER 294
+#define jp_SWITCH 295
+#define jp_SYNCHRONIZED 296
+#define jp_THIS 297
+#define jp_THROW 298
+#define jp_THROWS 299
+#define jp_TRANSIENT 300
+#define jp_TRY 301
+#define jp_VOID 302
+#define jp_VOLATILE 303
+#define jp_WHILE 304
+#define jp_BOOLEANLITERAL 305
+#define jp_CHARACTERLITERAL 306
+#define jp_DECIMALINTEGERLITERAL 307
+#define jp_FLOATINGPOINTLITERAL 308
+#define jp_HEXINTEGERLITERAL 309
+#define jp_NULLLITERAL 310
+#define jp_STRINGLITERAL 311
+#define jp_NAME 312
+#define jp_AND 313
+#define jp_ANDAND 314
+#define jp_ANDEQUALS 315
+#define jp_BRACKETEND 316
+#define jp_BRACKETSTART 317
+#define jp_CARROT 318
+#define jp_CARROTEQUALS 319
+#define jp_COLON 320
+#define jp_COMMA 321
+#define jp_CURLYEND 322
+#define jp_CURLYSTART 323
+#define jp_DIVIDE 324
+#define jp_DIVIDEEQUALS 325
+#define jp_DOLLAR 326
+#define jp_DOT 327
+#define jp_EQUALS 328
+#define jp_EQUALSEQUALS 329
+#define jp_EXCLAMATION 330
+#define jp_EXCLAMATIONEQUALS 331
+#define jp_GREATER 332
+#define jp_GTEQUALS 333
+#define jp_GTGT 334
+#define jp_GTGTEQUALS 335
+#define jp_GTGTGT 336
+#define jp_GTGTGTEQUALS 337
+#define jp_LESLESEQUALS 338
+#define jp_LESSTHAN 339
+#define jp_LTEQUALS 340
+#define jp_LTLT 341
+#define jp_MINUS 342
+#define jp_MINUSEQUALS 343
+#define jp_MINUSMINUS 344
+#define jp_PAREEND 345
+#define jp_PARESTART 346
+#define jp_PERCENT 347
+#define jp_PERCENTEQUALS 348
+#define jp_PIPE 349
+#define jp_PIPEEQUALS 350
+#define jp_PIPEPIPE 351
+#define jp_PLUS 352
+#define jp_PLUSEQUALS 353
+#define jp_PLUSPLUS 354
+#define jp_QUESTION 355
+#define jp_SEMICOL 356
+#define jp_TILDE 357
+#define jp_TIMES 358
+#define jp_TIMESEQUALS 359
+#define jp_ERROR 360
+
+/* Value type.  */
+
+
+
+int cmDependsJava_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 375 "cmDependsJavaParser.cxx" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  23
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   2215
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  106
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  158
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  351
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  575
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   360
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   179,   179,   188,   196,   204,   212,   220,   228,   237,
+     245,   254,   262,   271,   276,   281,   286,   291,   296,   301,
+     306,   312,   320,   329,   339,   348,   357,   365,   375,   381,
+     388,   395,   401,   408,   417,   427,   437,   446,   454,   463,
+     472,   478,   487,   493,   502,   508,   517,   529,   537,   546,
+     558,   571,   579,   587,   596,   604,   613,   613,   613,   614,
+     615,   615,   615,   615,   615,   615,   616,   619,   629,   638,
+     647,   656,   666,   672,   681,   690,   699,   707,   716,   725,
+     731,   740,   748,   756,   764,   773,   781,   790,   796,   804,
+     813,   821,   830,   839,   848,   856,   865,   873,   881,   890,
+     899,   909,   916,   926,   936,   943,   950,   953,   959,   969,
+     979,   989,   995,  1005,  1015,  1025,  1034,  1044,  1055,  1065,
+    1072,  1082,  1091,  1101,  1110,  1120,  1126,  1136,  1145,  1155,
+    1165,  1172,  1181,  1190,  1199,  1208,  1216,  1225,  1234,  1244,
+    1254,  1263,  1273,  1283,  1290,  1299,  1309,  1318,  1328,  1337,
+    1344,  1354,  1363,  1373,  1382,  1391,  1401,  1411,  1420,  1430,
+    1439,  1448,  1457,  1466,  1475,  1485,  1494,  1503,  1512,  1521,
+    1531,  1540,  1549,  1558,  1567,  1576,  1585,  1594,  1603,  1612,
+    1621,  1630,  1640,  1650,  1661,  1671,  1681,  1690,  1699,  1708,
+    1717,  1726,  1735,  1745,  1755,  1765,  1775,  1782,  1789,  1796,
+    1806,  1813,  1823,  1833,  1842,  1852,  1861,  1871,  1878,  1885,
+    1892,  1900,  1907,  1917,  1924,  1934,  1944,  1951,  1961,  1970,
+    1980,  1990,  1999,  2009,  2018,  2028,  2039,  2046,  2053,  2064,
+    2074,  2084,  2094,  2103,  2113,  2120,  2130,  2139,  2149,  2156,
+    2166,  2175,  2185,  2194,  2200,  2209,  2218,  2227,  2236,  2246,
+    2256,  2263,  2273,  2280,  2290,  2299,  2309,  2318,  2327,  2336,
+    2346,  2353,  2363,  2372,  2382,  2392,  2398,  2405,  2415,  2425,
+    2435,  2446,  2456,  2467,  2477,  2488,  2498,  2508,  2517,  2526,
+    2535,  2544,  2554,  2564,  2574,  2583,  2592,  2601,  2610,  2620,
+    2630,  2640,  2649,  2658,  2667,  2677,  2686,  2695,  2702,  2711,
+    2720,  2729,  2739,  2748,  2757,  2767,  2776,  2785,  2794,  2804,
+    2813,  2822,  2831,  2840,  2849,  2859,  2868,  2877,  2887,  2896,
+    2906,  2915,  2925,  2934,  2944,  2953,  2963,  2972,  2982,  2991,
+    3001,  3010,  3020,  3030,  3040,  3049,  3059,  3068,  3077,  3086,
+    3095,  3104,  3113,  3122,  3131,  3140,  3149,  3158,  3168,  3178,
+    3188,  3197
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "jp_ABSTRACT", "jp_ASSERT",
+  "jp_BOOLEAN_TYPE", "jp_BREAK", "jp_BYTE_TYPE", "jp_CASE", "jp_CATCH",
+  "jp_CHAR_TYPE", "jp_CLASS", "jp_CONTINUE", "jp_DEFAULT", "jp_DO",
+  "jp_DOUBLE_TYPE", "jp_ELSE", "jp_EXTENDS", "jp_FINAL", "jp_FINALLY",
+  "jp_FLOAT_TYPE", "jp_FOR", "jp_IF", "jp_IMPLEMENTS", "jp_IMPORT",
+  "jp_INSTANCEOF", "jp_INT_TYPE", "jp_INTERFACE", "jp_LONG_TYPE",
+  "jp_NATIVE", "jp_NEW", "jp_PACKAGE", "jp_PRIVATE", "jp_PROTECTED",
+  "jp_PUBLIC", "jp_RETURN", "jp_SHORT_TYPE", "jp_STATIC", "jp_STRICTFP",
+  "jp_SUPER", "jp_SWITCH", "jp_SYNCHRONIZED", "jp_THIS", "jp_THROW",
+  "jp_THROWS", "jp_TRANSIENT", "jp_TRY", "jp_VOID", "jp_VOLATILE",
+  "jp_WHILE", "jp_BOOLEANLITERAL", "jp_CHARACTERLITERAL",
+  "jp_DECIMALINTEGERLITERAL", "jp_FLOATINGPOINTLITERAL",
+  "jp_HEXINTEGERLITERAL", "jp_NULLLITERAL", "jp_STRINGLITERAL", "jp_NAME",
+  "jp_AND", "jp_ANDAND", "jp_ANDEQUALS", "jp_BRACKETEND",
+  "jp_BRACKETSTART", "jp_CARROT", "jp_CARROTEQUALS", "jp_COLON",
+  "jp_COMMA", "jp_CURLYEND", "jp_CURLYSTART", "jp_DIVIDE",
+  "jp_DIVIDEEQUALS", "jp_DOLLAR", "jp_DOT", "jp_EQUALS", "jp_EQUALSEQUALS",
+  "jp_EXCLAMATION", "jp_EXCLAMATIONEQUALS", "jp_GREATER", "jp_GTEQUALS",
+  "jp_GTGT", "jp_GTGTEQUALS", "jp_GTGTGT", "jp_GTGTGTEQUALS",
+  "jp_LESLESEQUALS", "jp_LESSTHAN", "jp_LTEQUALS", "jp_LTLT", "jp_MINUS",
+  "jp_MINUSEQUALS", "jp_MINUSMINUS", "jp_PAREEND", "jp_PARESTART",
+  "jp_PERCENT", "jp_PERCENTEQUALS", "jp_PIPE", "jp_PIPEEQUALS",
+  "jp_PIPEPIPE", "jp_PLUS", "jp_PLUSEQUALS", "jp_PLUSPLUS", "jp_QUESTION",
+  "jp_SEMICOL", "jp_TILDE", "jp_TIMES", "jp_TIMESEQUALS", "jp_ERROR",
+  "$accept", "Goal", "Literal", "IntegerLiteral", "Type", "PrimitiveType",
+  "ReferenceType", "ClassOrInterfaceType", "ClassType", "InterfaceType",
+  "ArrayType", "Name", "SimpleName", "Identifier", "QualifiedName",
+  "SimpleType", "CompilationUnit", "PackageDeclarationopt",
+  "ImportDeclarations", "TypeDeclarations", "PackageDeclaration",
+  "ImportDeclaration", "SingleTypeImportDeclaration",
+  "TypeImportOnDemandDeclaration", "TypeDeclaration", "Modifiers",
+  "Modifier", "ClassHeader", "ClassDeclaration", "Modifiersopt", "Super",
+  "Interfaces", "InterfaceTypeList", "ClassBody", "ClassBodyDeclarations",
+  "ClassBodyDeclaration", "ClassMemberDeclaration", "FieldDeclaration",
+  "VariableDeclarators", "VariableDeclarator", "VariableDeclaratorId",
+  "VariableInitializer", "MethodDeclaration", "MethodHeader", "Throwsopt",
+  "MethodDeclarator", "FormalParameterListopt", "FormalParameterList",
+  "FormalParameter", "Throws", "ClassTypeList", "MethodBody",
+  "StaticInitializer", "ConstructorDeclaration", "ConstructorDeclarator",
+  "ConstructorBody", "ExplicitConstructorInvocationopt",
+  "ExplicitConstructorInvocation", "InterfaceHeader",
+  "InterfaceDeclaration", "ExtendsInterfacesopt", "ExtendsInterfaces",
+  "InterfaceBody", "InterfaceMemberDeclarations",
+  "InterfaceMemberDeclaration", "ConstantDeclaration",
+  "AbstractMethodDeclaration", "Semicols", "ArrayInitializer",
+  "VariableInitializersOptional", "VariableInitializers", "Block",
+  "BlockStatementsopt", "BlockStatements", "BlockStatement",
+  "LocalVariableDeclarationStatement", "LocalVariableDeclaration",
+  "Statement", "StatementNoShortIf",
+  "StatementWithoutTrailingSubstatement", "EmptyStatement",
+  "LabeledStatement", "LabeledStatementNoShortIf", "ExpressionStatement",
+  "StatementExpression", "IfThenStatement", "IfThenElseStatement",
+  "IfThenElseStatementNoShortIf", "SwitchStatement", "SwitchBlock",
+  "SwitchLabelsopt", "SwitchBlockStatementGroups",
+  "SwitchBlockStatementGroup", "SwitchLabels", "SwitchLabel",
+  "WhileStatement", "WhileStatementNoShortIf", "DoStatement",
+  "ForStatement", "ForUpdateopt", "ForInitopt", "ForStatementNoShortIf",
+  "Expressionopt", "ForInit", "ForUpdate", "StatementExpressionList",
+  "AssertStatement", "BreakStatement", "Identifieropt",
+  "ContinueStatement", "ReturnStatement", "ThrowStatement",
+  "SynchronizedStatement", "TryStatement", "Catchesopt", "Catches",
+  "CatchClause", "Finally", "Primary", "PrimaryNoNewArray",
+  "ClassInstanceCreationExpression", "ClassBodyOpt", "ArgumentListopt",
+  "ArgumentList", "ArrayCreationExpression", "Dimsopt", "DimExprs",
+  "DimExpr", "Dims", "FieldAccess", "MethodInvocation", "ArrayAccess",
+  "PostfixExpression", "PostIncrementExpression",
+  "PostDecrementExpression", "UnaryExpression", "PreIncrementExpression",
+  "PreDecrementExpression", "UnaryExpressionNotPlusMinus",
+  "CastExpression", "MultiplicativeExpression", "AdditiveExpression",
+  "ShiftExpression", "RelationalExpression", "EqualityExpression",
+  "AndExpression", "ExclusiveOrExpression", "InclusiveOrExpression",
+  "ConditionalAndExpression", "ConditionalOrExpression",
+  "ConditionalExpression", "AssignmentExpression", "Assignment",
+  "LeftHandSide", "AssignmentOperator", "Expression", "ConstantExpression",
+  "New", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
+     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
+     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
+     335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
+     345,   346,   347,   348,   349,   350,   351,   352,   353,   354,
+     355,   356,   357,   358,   359,   360
+};
+# endif
+
+#define YYPACT_NINF -503
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-503)))
+
+#define YYTABLE_NINF -336
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int16 yypact[] =
+{
+     159,  1039,   236,  -503,  -503,  -503,  -503,  -503,  -503,  -503,
+    -503,  -503,  -503,  -503,  -503,  -503,   186,  -503,    56,  -503,
+    -503,  -503,   178,  -503,    35,  -503,    21,  -503,   248,  1039,
+     273,  -503,  -503,  -503,  -503,  -503,  -503,  -503,    78,  -503,
+    -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,
+    -503,  -503,  2088,  -503,    32,  -503,    16,   245,  -503,    28,
+    -503,  -503,  1039,  1039,  -503,    80,   206,  -503,   129,   129,
+    1039,   221,   228,   194,  -503,  -503,   225,  -503,  -503,   234,
+     164,   206,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  1039,
+    -503,  1039,   233,  -503,  -503,   739,  -503,  -503,  -503,  -503,
+     -49,  -503,  -503,  -503,  1116,  -503,  -503,  1276,  -503,   129,
+     129,    40,  -503,  -503,  -503,   122,   212,   265,  -503,   215,
+    -503,  -503,   219,   739,  -503,   222,   224,  -503,  -503,  -503,
+    1820,   129,   129,  1627,   237,   238,  -503,  1820,   241,   239,
+     242,   283,  1820,   233,   266,  -503,  -503,  -503,  -503,  -503,
+    -503,  -503,  1820,  1820,  1820,  -503,  -503,  -503,   129,   284,
+     476,   293,  2067,  -503,   349,  -503,   296,  1366,  -503,  -503,
+     264,  -503,  -503,  -503,  -503,  -503,   268,  -503,  -503,  -503,
+    -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,
+     294,   305,    72,  -503,  2070,    88,  2084,   121,   130,   148,
+    -503,  -503,  -503,  2111,  1039,   281,   133,   281,   -25,  -503,
+     126,   133,   314,   315,   315,   921,  1039,   308,  -503,  -503,
+    -503,  -503,   277,  -503,  1820,  1820,  1820,  1820,  1820,   317,
+     284,   545,  -503,  -503,   121,  -503,  -503,  -503,  -503,  -503,
+    -503,  -503,    73,   124,   163,    59,   196,   323,   319,   290,
+     324,    18,  -503,  -503,  -503,   -30,  -503,   285,   286,   242,
+     342,  1941,  1820,   291,  -503,   129,  1820,  1820,   129,   292,
+     385,  1820,    96,  -503,  -503,  -503,   310,  -503,  -503,   329,
+     387,  1085,     3,  1820,  1627,   129,  -503,  -503,  -503,  -503,
+     175,  1820,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,
+    -503,  -503,  -503,  -503,  -503,  -503,  1820,   339,   339,   311,
+     921,   343,  -503,   129,  -503,   344,  1766,  -503,  -503,   346,
+    1039,   313,   347,  -503,  -503,   353,  -503,   307,  -503,  -503,
+    -503,     6,   545,   326,  -503,  -503,  1820,  1820,  1820,  1820,
+    1820,  1820,  1820,  1820,  1039,  1820,  1820,  1820,  1820,  1820,
+    1820,  1820,  1820,  1820,  1820,  1820,  1820,  1820,  -503,  -503,
+    -503,   330,  2067,  -503,  -503,   327,  -503,   354,   334,  -503,
+     345,   335,   340,   348,  -503,   351,   416,   232,  -503,   356,
+    -503,  -503,   376,  -503,   357,   377,  -503,  -503,   329,  -503,
+     358,   390,  -503,  1085,   339,  -503,   154,   339,   154,  1820,
+     362,  -503,  -503,  -503,  1766,  -503,  -503,  -503,  -503,   129,
+    -503,  2088,  1039,  1456,  -503,   363,    70,    93,  1874,  -503,
+    -503,  -503,    73,    73,   124,   124,   124,  -503,   163,   163,
+     163,   163,    59,    59,   196,   323,   319,   290,   324,   383,
+     360,  1820,  1820,  1995,  1699,  1820,   386,   233,  1820,  2088,
+     233,  -503,  -503,  1627,  -503,  -503,  1820,  1820,  -503,   394,
+    -503,  -503,   315,  -503,  -503,  -503,   369,  -503,  -503,   396,
+     404,   410,  -503,  -503,    26,   113,  -503,   407,  1820,  1874,
+    -503,  1820,  -503,   391,   374,  -503,   393,   395,   397,   411,
+    -503,   466,   471,  -503,  -503,  -503,  -503,   399,  -503,  -503,
+    -503,   400,   401,  -503,  -503,  -503,   402,  -503,   206,  -503,
+    1766,  1820,  1820,  -503,  -503,  -503,  -503,   403,  1995,  1941,
+    1820,  1820,  1699,  1627,  -503,    34,  -503,   233,  -503,  -503,
+    -503,  -503,   405,   412,  -503,   413,  -503,   354,   406,   418,
+     421,  -503,  -503,  1820,   429,   430,  -503,  1186,  -503,  -503,
+     419,   422,  1627,  1820,  1699,  1699,  -503,   447,  -503,  -503,
+    1555,  -503,  -503,  -503,  -503,   423,   497,  -503,  -503,  1995,
+    1699,   432,  -503,  1699,  -503
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint16 yydefact[] =
+{
+      40,     0,     0,     2,    42,    41,    20,    13,    17,    19,
+      18,    15,    16,    14,    38,    31,     0,    37,     0,    28,
+      30,    29,     0,     1,    44,    32,     0,    46,     0,     0,
+      72,    43,    47,    48,    34,    35,    33,    36,     0,    60,
+      61,    62,    58,    57,    56,    59,    66,    63,    64,    65,
+      53,    45,    73,    54,     0,    51,     0,   125,    52,     0,
+      49,    55,     0,     0,    79,     0,     0,    68,     0,     0,
+       0,     0,   126,     0,    24,    74,    23,    25,    76,    75,
+      72,     0,    70,    69,    67,   123,   127,   130,   124,     0,
+      50,     0,    59,    78,    84,     0,    80,    81,    85,    86,
+       0,    82,    83,    71,    72,   128,    77,    72,   114,    38,
+       0,    11,    12,    21,    22,    23,    28,   101,    96,    97,
+     113,   129,   134,     0,   138,     0,   136,   131,   132,   133,
+       0,   226,   226,     0,     0,     0,   350,   216,     0,     0,
+      63,   243,     0,     0,     0,     5,     6,     9,     4,    10,
+       8,     7,     0,     0,     0,   182,   242,     3,     0,    22,
+     333,    30,    73,   155,     0,   170,     0,    72,   151,   153,
+       0,   154,   159,   171,   160,   172,     0,   161,   162,   173,
+     163,   174,   164,   181,   175,   176,   177,   179,   178,   180,
+     277,   240,   245,   241,   246,   247,   248,     0,   189,   190,
+     187,   188,   186,     0,     0,     0,   101,    92,     0,    88,
+      90,   101,     0,    26,    27,    72,     0,     0,   102,    98,
+     135,   140,   139,   137,     0,     0,     0,     0,     0,    37,
+       0,   278,   245,   247,   291,   280,   281,   298,   284,   285,
+     288,   294,   302,   305,   309,   315,   318,   320,   322,   324,
+     326,   328,   330,   348,   331,     0,   227,     0,     0,     0,
+       0,   213,     0,     0,   217,     0,     0,     0,     0,     0,
+     234,     0,   278,   246,   248,   290,     0,   289,    92,   158,
+       0,     0,     0,   252,     0,     0,   148,   152,   156,   185,
+       0,     0,   283,   282,   345,   346,   338,   336,   343,   344,
+     342,   341,   339,   347,   340,   337,     0,    37,    24,     0,
+      72,     0,   100,     0,    87,     0,     0,    99,   265,     0,
+       0,     0,   106,   107,   111,   110,   119,   115,   141,   293,
+     287,    37,   278,     0,   286,   292,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   223,   225,
+     228,     0,     0,   219,   221,     0,   214,   218,     0,   229,
+     268,     0,     0,   269,   230,     0,     0,   232,   236,     0,
+     244,   279,     0,   351,     0,   253,   254,   183,   157,   270,
+     267,     0,   332,     0,   260,   262,     0,   260,     0,   252,
+       0,   104,    89,    93,   143,    91,    95,    94,   266,     0,
+     117,    72,     0,    72,   116,     0,    26,    27,   244,   300,
+     301,   299,   304,   303,   307,   308,   306,   314,   311,   313,
+     310,   312,   316,   317,   319,   321,   323,   325,   327,     0,
+       0,     0,   216,     0,     0,   252,     0,     0,   252,    72,
+       0,   233,   237,     0,   275,   271,     0,   252,   276,     0,
+     256,   263,   261,   258,   257,   259,     0,   103,   146,     0,
+     144,   109,   108,   112,     0,   243,   120,     0,     0,     0,
+     296,     0,   224,     0,     0,   222,     0,     0,     0,    30,
+     193,     0,   159,   166,   167,   168,   169,     0,   200,   196,
+     231,     0,     0,   239,   207,   255,     0,   264,   250,   142,
+     145,   252,   252,   118,   295,   297,   329,     0,   211,   213,
+       0,     0,     0,     0,   273,   198,   274,     0,   272,   251,
+     249,   147,     0,     0,   209,     0,   212,   220,     0,     0,
+       0,   184,   194,     0,     0,     0,   201,    72,   203,   238,
+       0,     0,     0,   216,     0,     0,   349,     0,   206,   197,
+     202,   204,   122,   121,   210,     0,     0,   208,   205,   211,
+       0,     0,   195,     0,   215
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -503,  -503,  -503,  -503,   -85,     2,   181,   -41,  -198,   -45,
+     -87,    -1,   431,    14,  -503,  -503,  -503,  -503,  -503,  -503,
+    -503,  -503,  -503,  -503,   448,   -81,   -47,  -503,     7,   -23,
+    -503,   462,  -503,   -64,  -503,  -503,  -503,   425,  -146,   217,
+     123,  -391,  -503,   427,  -101,   424,   230,  -503,  -360,  -503,
+    -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,   439,
+    -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -110,  -503,
+    -503,   -77,   138,   -12,  -163,  -503,  -250,   -13,  -421,  -414,
+    -503,  -503,  -503,  -503,  -252,  -503,  -503,  -503,  -503,  -503,
+    -503,  -503,  -503,  -503,     5,  -503,  -503,  -503,  -503,   -16,
+      36,  -503,  -418,  -503,  -503,  -502,  -503,  -503,   440,  -503,
+    -503,  -503,  -503,  -503,  -503,  -503,   179,  -503,  -503,  -503,
+     -54,  -503,  -341,  -503,  -503,  -149,   255,  -136,   102,   652,
+     101,   688,   145,   157,   201,   -98,   289,   338,  -384,  -503,
+     -59,   -58,   -92,   -57,   213,   226,   218,   223,   227,  -503,
+      95,   274,   350,  -503,  -503,   660,  -503,  -503
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,     2,   156,   157,   158,   229,   112,   113,    75,    78,
+     230,   231,    19,    20,    21,    22,     3,     4,    24,    30,
+       5,    31,    32,    33,    51,    52,    53,    54,   163,   164,
+      65,    66,    79,    67,    80,    96,    97,    98,   208,   209,
+     210,   405,    99,   100,   217,   206,   321,   322,   323,   218,
+     325,   119,   101,   102,   117,   327,   413,   476,    57,    58,
+      71,    72,    88,   104,   127,   128,   129,   222,   406,   469,
+     470,   165,   166,   167,   168,   169,   170,   171,   491,   172,
+     173,   174,   493,   175,   176,   177,   178,   494,   179,   499,
+     545,   525,   546,   547,   548,   180,   495,   181,   182,   535,
+     365,   496,   263,   366,   536,   367,   183,   184,   257,   185,
+     186,   187,   188,   189,   376,   377,   378,   451,   190,   191,
+     232,   530,   384,   385,   193,   415,   394,   395,   214,   194,
+     233,   196,   234,   235,   236,   237,   238,   239,   240,   241,
+     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
+     252,   253,   254,   203,   306,   386,   557,   204
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_int16 yytable[] =
+{
+      18,    82,    83,    17,   287,    61,   309,    56,   114,   364,
+     110,   363,   279,   468,    34,   108,   537,   103,   324,   107,
+     159,    74,    77,   120,   484,    86,   162,    68,    38,    77,
+     492,    17,    34,   383,   480,   357,   114,    55,   110,    34,
+      36,   313,   543,    69,   105,    35,   106,   544,    77,    62,
+      77,   472,   118,   192,   275,    63,   277,    95,   466,    29,
+      15,    76,    76,    35,    17,    17,   270,   537,   212,    76,
+      35,   358,    17,    36,    16,   114,   314,   285,    15,   192,
+     159,   123,    84,    85,   344,    15,   162,    55,    76,   502,
+      76,    17,    16,    17,   115,   515,  -260,   111,   265,    16,
+      64,   541,   212,    63,   497,   312,   160,   501,   492,   111,
+     317,   122,   -37,   192,   355,    61,   506,   511,   356,   531,
+     260,   161,   115,   205,   207,   111,   329,   330,    26,   334,
+     335,    73,   319,   566,   567,   565,   345,   346,  -192,   388,
+     492,   492,   336,   347,   348,   256,   256,   161,    64,   572,
+      59,   272,   574,   272,  -191,   319,   492,    27,   281,   492,
+    -261,   115,  -192,   308,   111,   337,   160,    39,   282,   111,
+     532,   533,   278,  -192,   159,    74,   338,   216,  -191,    60,
+     362,   161,    40,   479,   212,   268,    15,   283,   315,  -191,
+       1,   485,   320,    41,    26,   311,    42,    43,    44,   316,
+      16,    92,    46,    76,   512,    47,   307,   192,   195,    48,
+     292,   339,    49,   213,   473,    76,   319,   389,    17,  -280,
+     293,   340,   404,   272,   272,   332,   272,   272,   331,  -280,
+     192,    93,    15,   114,   195,   409,    23,  -281,   419,   420,
+     421,   375,   341,    25,   342,   460,    16,  -281,   464,   343,
+      28,  -235,   197,   428,   429,   430,   431,   114,   461,    37,
+     160,   461,    70,   111,   198,    50,   364,   364,   195,   363,
+     349,   387,   350,   -39,    64,   114,    39,   285,   197,   370,
+     422,   423,   373,   424,   425,   426,   463,   320,   465,    87,
+     198,    40,   432,   433,    89,    90,    36,    26,   161,   278,
+      91,   107,    41,   215,   390,    42,    43,    44,   199,   216,
+      45,    46,   197,   265,    47,    61,   219,   364,    48,   115,
+     220,    49,   111,   221,   198,   223,   159,   278,   261,   262,
+     266,   213,   162,   267,   199,   272,   272,   272,   272,   272,
+     272,   272,   272,   115,   272,   272,   272,   272,   272,   272,
+     272,   272,   272,   272,   272,   268,   280,   271,   284,   192,
+      68,   115,   195,   286,   111,   288,   290,   291,   199,   289,
+     500,    74,   310,   503,    50,   318,   326,   319,   328,   212,
+     514,   351,   352,   354,   353,   195,   359,   360,   320,   192,
+     192,   361,   369,   374,   375,   313,   200,   287,   381,   192,
+     380,   393,   399,   410,   401,   403,   197,   408,   414,   396,
+     398,    76,   160,   411,    17,   111,   418,   272,   198,   412,
+     443,   441,   200,   278,   444,   446,   320,   161,   442,   197,
+     447,   490,   159,   416,   417,   450,   445,   454,   362,   448,
+     504,   198,   449,   456,   529,   201,   453,   455,   481,   457,
+     549,   458,   467,   478,   498,   507,   200,   202,   489,   508,
+     159,   482,   199,   509,   192,   192,   162,   161,   192,   192,
+     510,   201,   315,   159,   513,   518,   522,   272,   272,   162,
+     272,   517,   523,   202,   519,   199,   520,  -165,   521,   524,
+     526,   527,   528,   192,   558,   550,   462,   559,   192,   462,
+     192,   192,   551,   552,   534,   201,   192,   553,   554,   387,
+     542,   555,   568,   570,   195,   192,   192,   202,   160,   192,
+     562,   111,   573,   563,   569,   427,   116,    81,    94,   124,
+     402,   125,   471,   -23,   211,   560,   489,   161,   281,   564,
+     400,   490,   504,   126,   195,   195,   160,   -23,   282,   111,
+     200,   477,   561,   571,   195,   538,   452,   542,   197,   160,
+     564,   161,   111,   397,   434,  -278,   161,   283,   489,   489,
+     198,   436,   258,   200,   161,  -278,   516,   437,   435,     0,
+     392,     0,   438,     0,   489,     0,     0,   489,   197,   197,
+       0,     0,     0,     0,     0,     0,     0,     0,   197,   201,
+     198,   198,     0,     0,     0,  -333,     0,   281,     0,  -333,
+     198,   202,     0,     0,   199,  -333,     0,   282,  -333,   195,
+     195,     0,   201,   195,   195,  -333,     0,  -333,  -333,     0,
+       0,     0,     0,  -333,   202,     0,   283,     0,  -333,     0,
+    -333,     0,     0,  -333,   199,   199,     0,     0,   195,  -333,
+       0,     0,     0,   195,   199,   195,   195,     0,     0,     0,
+       0,   195,     0,   197,   197,     0,     0,   197,   197,     0,
+     195,   195,     0,     0,   195,   198,   198,     0,     0,   198,
+     198,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   197,     0,     0,     0,     0,   197,     0,   197,
+     197,     0,   200,     0,   198,   197,     0,     0,     0,   198,
+       0,   198,   198,     0,   197,   197,     0,   198,   197,   199,
+     199,     0,     0,   199,   199,     0,   198,   198,     0,     0,
+     198,     0,   200,   200,     0,     0,     0,     0,     0,     0,
+       0,     0,   200,     0,     6,     0,     7,     0,   199,     8,
+      68,   201,     0,   199,     9,   199,   199,     0,     0,    10,
+       0,   199,     0,   202,     0,    11,    69,    12,     0,     0,
+     199,   199,     0,     0,   199,    13,     0,     0,     0,     0,
+       0,   201,   201,     0,     0,     0,   109,     0,     0,     0,
+     255,   201,     0,   202,   202,     0,    15,   264,     0,     0,
+       0,     0,   269,   202,   273,     0,   273,   200,   200,     0,
+      16,   200,   200,   276,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   200,     0,     0,     0,
+     274,   200,   274,   200,   200,     0,     0,     0,     0,   200,
+       0,     0,     0,     0,     0,     0,   201,   201,   200,   200,
+     201,   201,   200,     0,     0,     0,     0,     0,   202,   202,
+       0,     0,   202,   202,     0,     0,   273,   273,     0,   273,
+     273,     0,     0,     0,     0,   201,   333,     0,     0,     0,
+     201,     0,   201,   201,     0,     0,     0,   202,   201,     0,
+       0,     0,   202,     0,   202,   202,     0,   201,   201,     0,
+     202,   201,   274,   274,     0,   274,   274,     0,     0,   202,
+     202,     0,   368,   202,    39,     0,   371,   372,     0,     0,
+       0,   379,     0,     0,     0,     0,     0,     0,     0,    40,
+       0,   382,     0,     0,     0,     0,     0,     0,     0,     0,
+      41,   391,     0,    42,    43,    44,     0,     0,    45,    46,
+       0,     0,    47,     0,     0,     0,    48,     0,     0,    49,
+       0,     0,     0,     0,     0,     0,   407,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   273,   273,
+     273,   273,   273,   273,   273,   273,     0,   273,   273,   273,
+     273,   273,   273,   273,   273,   273,   273,   273,     0,     0,
+       0,  -105,     0,     0,     0,     0,   439,   440,     0,     0,
+       0,     0,     0,     0,   274,   274,   274,   274,   274,   274,
+     274,   274,     0,   274,   274,   274,   274,   274,   274,   274,
+     274,   274,   274,   274,     6,     0,     7,     0,     0,     8,
+       0,     0,     0,   459,     9,     0,     0,     0,     0,    10,
+       0,     0,     0,     0,   407,    11,     0,    12,     0,     0,
+     273,     0,     0,     0,     0,    13,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    14,     0,     0,     0,
+       6,     0,     7,     0,     0,     8,    15,     0,     0,     0,
+       9,   483,   264,     0,     0,    10,   274,     0,     0,     0,
+      16,    11,     0,    12,     0,   136,   505,     0,     0,    39,
+       0,    13,     0,     0,   138,     0,     0,   141,     0,     0,
+     273,   273,    14,   273,    40,   145,   146,   147,   148,   149,
+     150,   151,    15,     0,     0,    41,   318,     0,    42,    43,
+      44,     0,     0,    45,    46,     0,    16,    47,     0,     0,
+     224,    48,     0,     0,    49,     0,   274,   274,     0,   274,
+     407,     0,   225,     0,   152,     0,   226,     0,     0,     0,
+     539,   540,   227,   121,   154,     0,     0,   228,     0,    39,
+     130,     6,   131,     7,   543,     0,     8,     0,   132,   544,
+     133,     9,     0,   556,    40,     0,    10,   134,   135,     0,
+       0,     0,    11,   264,    12,    41,   136,     0,    42,    43,
+      44,   137,    13,    45,    46,   138,   139,   140,   141,   142,
+       0,    48,   143,    14,    49,   144,   145,   146,   147,   148,
+     149,   150,   151,    15,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,  -199,   107,     0,     0,    16,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   152,     0,   153,     0,    39,
+     130,     6,   131,     7,     0,   154,     8,   155,   132,     0,
+     133,     9,     0,     0,    40,     0,    10,   134,   135,     0,
+       0,     0,    11,     0,    12,    41,   136,     0,    42,    43,
+      44,   137,    13,    45,    46,   138,   139,   140,   141,   142,
+       0,    48,   143,    14,    49,   144,   145,   146,   147,   148,
+     149,   150,   151,    15,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,  -149,   107,     0,     0,    16,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   152,     0,   153,     0,    39,
+     130,     6,   131,     7,     0,   154,     8,   155,   132,     0,
+     133,     9,     0,     0,    40,     0,    10,   134,   135,     0,
+       0,     0,    11,     0,    12,    41,   136,     0,    42,    43,
+      44,   137,    13,    45,    46,   138,   139,   140,   141,   142,
+       0,    48,   143,    14,    49,   144,   145,   146,   147,   148,
+     149,   150,   151,    15,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,  -150,   107,     0,     0,    16,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   152,     0,   153,     0,    39,
+     130,     6,   131,     7,     0,   154,     8,   155,   132,     0,
+     133,     9,     0,     0,    40,     0,    10,   134,   135,     0,
+       0,     0,    11,     0,    12,    41,   136,     0,    42,    43,
+      44,   137,    13,    45,    46,   474,   139,   140,   475,   142,
+       0,    48,   143,    14,    49,   144,   145,   146,   147,   148,
+     149,   150,   151,    15,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,  -149,   107,     0,     0,    16,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   152,     0,   153,     0,     0,
+       0,     0,     0,     0,     0,   154,     0,   155,    39,   130,
+       6,   131,     7,     0,     0,     8,   -72,   132,     0,   133,
+       9,     0,     0,    40,     0,    10,   134,   135,     0,     0,
+       0,    11,     0,    12,    41,   136,     0,    42,    43,    44,
+     137,    13,    45,    46,   138,   139,   140,   141,   142,     0,
+      48,   143,    14,    49,   144,   145,   146,   147,   148,   149,
+     150,   151,    15,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   107,     0,     0,    16,     0,     0,     0,
+       0,   130,     6,   131,     7,     0,     0,     8,     0,   132,
+       0,   133,     9,     0,   152,     0,   153,    10,   134,   135,
+       0,     0,     0,    11,   154,    12,   155,   136,     0,     0,
+       0,     0,   137,    13,     0,     0,   138,   139,   259,   141,
+     142,     0,     0,   143,    14,     0,   144,   145,   146,   147,
+     148,   149,   150,   151,    15,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   107,     0,     0,    16,     0,
+       0,     0,     0,   130,     6,   131,     7,     0,     0,     8,
+       0,   132,     0,   133,     9,     0,   152,     0,   153,    10,
+     486,   487,     0,     0,     0,    11,   154,    12,   155,   136,
+       0,     0,     0,     0,   137,    13,     0,     0,   138,   139,
+     259,   141,   142,     0,     0,   143,    14,     0,   488,   145,
+     146,   147,   148,   149,   150,   151,    15,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   107,     0,     0,
+      16,     6,     0,     7,     0,     0,     8,     0,     0,     0,
+       0,     9,     0,     0,     0,     0,    10,     0,   152,     0,
+     153,     0,    11,     0,    12,     0,   136,     0,   154,     0,
+     155,     0,    13,     0,     0,   138,     0,     0,   141,     0,
+       0,     0,     0,    14,     0,     0,   145,   146,   147,   148,
+     149,   150,   151,    15,     0,     6,     0,     7,     0,     0,
+       8,     0,     0,     0,   404,     9,     0,    16,     0,     0,
+      10,   224,     0,     0,     0,     0,    11,     0,    12,     0,
+     136,     0,     0,   225,     0,   152,    13,   226,     0,   138,
+       0,     0,   141,   227,     0,   154,     0,    14,   228,     0,
+     145,   146,   147,   148,   149,   150,   151,    15,     0,     6,
+       0,     7,     0,     0,     8,     0,     0,     0,     0,     9,
+       0,    16,     0,     0,    10,   224,     0,     0,     0,     0,
+      11,     0,    12,     0,   136,     0,     0,   225,     0,   152,
+      13,   226,     0,   138,     0,     0,   141,   227,     0,   154,
+       0,    14,   228,     0,   145,   146,   147,   148,   149,   150,
+     151,    15,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    39,    16,     6,     0,     7,   224,
+       0,     8,     0,     0,     0,     0,     9,     0,     0,    40,
+       0,    10,     0,     0,     0,   226,     0,    11,     0,    12,
+      41,   136,     0,    42,    43,    44,   228,    13,    45,    46,
+     138,     0,    47,   141,     0,     0,    48,     0,    14,    49,
+       0,   145,   146,   147,   148,   149,   150,   151,    15,     0,
+       6,     0,     7,     0,     0,     8,     0,     0,     0,     0,
+       9,     0,    16,     0,     0,    10,     0,     0,     0,     0,
+       0,    11,     0,    12,     0,   136,     0,     0,     0,     0,
+     152,    13,   153,     0,   138,     0,     0,   141,     0,     0,
+     154,     0,    14,     0,     0,   145,   146,   147,   148,   149,
+     150,   151,    15,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    16,     0,     0,     0,
+      39,     0,     6,     0,     7,     0,     0,     8,     0,     0,
+       0,     0,     9,     0,   152,    40,   153,    10,     0,     0,
+       0,    39,     0,    11,   154,    12,    41,     0,     0,    42,
+      43,    44,     0,    13,    45,    46,    40,     0,    47,     0,
+       0,     0,    48,     0,    14,    49,     0,    41,     0,     0,
+      42,    43,    44,     0,    15,    45,    46,     0,     0,    47,
+    -334,     0,     0,    48,  -334,     0,    49,     0,    16,     0,
+    -334,     0,     0,  -334,  -335,     0,     0,     0,  -335,     0,
+    -334,     0,  -334,  -334,  -335,     0,     0,  -335,  -334,     0,
+       0,     0,     0,  -334,  -335,  -334,  -335,  -335,  -334,     0,
+       0,   294,  -335,     0,  -334,   295,     0,  -335,     0,  -335,
+       0,   296,  -335,     0,   297,     0,     0,     0,  -335,     0,
+       0,   298,     0,   299,   300,     0,     0,     0,     0,   301,
+       0,     0,     0,     0,   302,     0,   303,     0,     0,   304,
+       0,     0,     0,     0,     0,   305
+};
+
+static const yytype_int16 yycheck[] =
+{
+       1,    65,    66,     1,   167,    52,   204,    30,    95,   261,
+      95,   261,   158,   404,    11,    92,   518,    81,   216,    68,
+     107,    62,    63,   100,   442,    70,   107,    11,    29,    70,
+     444,    29,    11,    30,   418,    65,   123,    30,   123,    11,
+      26,    66,     8,    27,    89,    42,    91,    13,    89,    17,
+      91,   411,   101,   107,   152,    23,   154,    80,   399,    24,
+      57,    62,    63,    42,    62,    63,   143,   569,    62,    70,
+      42,   101,    70,    59,    71,   162,   101,   162,    57,   133,
+     167,   104,    68,    69,    25,    57,   167,    80,    89,   449,
+      91,    89,    71,    91,    95,   479,    90,    95,    72,    71,
+      68,   522,    62,    23,   445,   206,   107,   448,   522,   107,
+     211,   104,    72,   167,    96,   162,   457,    91,   100,   510,
+     133,   107,   123,   109,   110,   123,   224,   225,    72,   227,
+     228,   103,    62,   554,   555,   553,    77,    78,    66,   285,
+     554,   555,    69,    84,    85,   131,   132,   133,    68,   570,
+      72,   152,   573,   154,    66,    62,   570,   101,    62,   573,
+      90,   162,    90,   204,   162,    92,   167,     3,    72,   167,
+     511,   512,   158,   101,   261,   216,   103,    44,    90,   101,
+     261,   167,    18,    90,    62,    72,    57,    91,    62,   101,
+      31,   443,   215,    29,    72,    62,    32,    33,    34,    73,
+      71,    37,    38,   204,    91,    41,   204,   261,   107,    45,
+      89,    87,    48,   111,   412,   216,    62,    42,   216,    89,
+      99,    97,    68,   224,   225,   226,   227,   228,   226,    99,
+     284,    67,    57,   320,   133,   320,     0,    89,   336,   337,
+     338,     9,    79,    57,    81,   394,    71,    99,   397,    86,
+      72,    19,   107,   345,   346,   347,   348,   344,   394,    11,
+     261,   397,    17,   261,   107,   101,   518,   519,   167,   519,
+      74,   284,    76,     0,    68,   362,     3,   362,   133,   265,
+     339,   340,   268,   341,   342,   343,   396,   310,   398,    68,
+     133,    18,   349,   350,    66,   101,   282,    72,   284,   285,
+      66,    68,    29,    91,   290,    32,    33,    34,   107,    44,
+      37,    38,   167,    72,    41,   362,   101,   569,    45,   320,
+     101,    48,   320,   101,   167,   101,   413,   313,    91,    91,
+      91,   229,   413,    91,   133,   336,   337,   338,   339,   340,
+     341,   342,   343,   344,   345,   346,   347,   348,   349,   350,
+     351,   352,   353,   354,   355,    72,    72,    91,    65,   413,
+      11,   362,   261,    67,   362,   101,    72,    62,   167,   101,
+     447,   412,    91,   450,   101,    61,    68,    62,   101,    62,
+     478,    58,    63,    59,    94,   284,   101,   101,   411,   443,
+     444,    49,   101,   101,     9,    66,   107,   560,    11,   453,
+      90,    62,    91,    90,    61,    61,   261,    61,   101,   307,
+     308,   412,   413,    66,   412,   413,    90,   418,   261,    66,
+      66,    91,   133,   409,    90,    90,   449,   413,   101,   284,
+      90,   444,   519,   331,   332,    19,    91,    61,   519,    91,
+     453,   284,    91,    66,   508,   107,    90,    90,    65,    91,
+     527,    61,    90,    90,    68,    61,   167,   107,   444,    90,
+     547,   101,   261,    67,   518,   519,   547,   453,   522,   523,
+      66,   133,    62,   560,    67,   101,    65,   478,   479,   560,
+     481,    90,    16,   133,    91,   284,    91,    16,    91,    90,
+      90,    90,    90,   547,    65,    90,   394,    67,   552,   397,
+     554,   555,    90,    90,   101,   167,   560,   101,    90,   522,
+     523,    90,    65,    16,   413,   569,   570,   167,   519,   573,
+     101,   519,    90,   101,   101,   344,    95,    65,    80,   104,
+     313,   104,   409,    57,   110,   547,   522,   523,    62,   552,
+     310,   554,   555,   104,   443,   444,   547,    71,    72,   547,
+     261,   413,   547,   569,   453,   519,   377,   570,   413,   560,
+     573,   547,   560,   308,   351,    89,   552,    91,   554,   555,
+     413,   353,   132,   284,   560,    99,   481,   354,   352,    -1,
+     306,    -1,   355,    -1,   570,    -1,    -1,   573,   443,   444,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   453,   261,
+     443,   444,    -1,    -1,    -1,    60,    -1,    62,    -1,    64,
+     453,   261,    -1,    -1,   413,    70,    -1,    72,    73,   518,
+     519,    -1,   284,   522,   523,    80,    -1,    82,    83,    -1,
+      -1,    -1,    -1,    88,   284,    -1,    91,    -1,    93,    -1,
+      95,    -1,    -1,    98,   443,   444,    -1,    -1,   547,   104,
+      -1,    -1,    -1,   552,   453,   554,   555,    -1,    -1,    -1,
+      -1,   560,    -1,   518,   519,    -1,    -1,   522,   523,    -1,
+     569,   570,    -1,    -1,   573,   518,   519,    -1,    -1,   522,
+     523,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   547,    -1,    -1,    -1,    -1,   552,    -1,   554,
+     555,    -1,   413,    -1,   547,   560,    -1,    -1,    -1,   552,
+      -1,   554,   555,    -1,   569,   570,    -1,   560,   573,   518,
+     519,    -1,    -1,   522,   523,    -1,   569,   570,    -1,    -1,
+     573,    -1,   443,   444,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   453,    -1,     5,    -1,     7,    -1,   547,    10,
+      11,   413,    -1,   552,    15,   554,   555,    -1,    -1,    20,
+      -1,   560,    -1,   413,    -1,    26,    27,    28,    -1,    -1,
+     569,   570,    -1,    -1,   573,    36,    -1,    -1,    -1,    -1,
+      -1,   443,   444,    -1,    -1,    -1,    47,    -1,    -1,    -1,
+     130,   453,    -1,   443,   444,    -1,    57,   137,    -1,    -1,
+      -1,    -1,   142,   453,   152,    -1,   154,   518,   519,    -1,
+      71,   522,   523,   153,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   547,    -1,    -1,    -1,
+     152,   552,   154,   554,   555,    -1,    -1,    -1,    -1,   560,
+      -1,    -1,    -1,    -1,    -1,    -1,   518,   519,   569,   570,
+     522,   523,   573,    -1,    -1,    -1,    -1,    -1,   518,   519,
+      -1,    -1,   522,   523,    -1,    -1,   224,   225,    -1,   227,
+     228,    -1,    -1,    -1,    -1,   547,   226,    -1,    -1,    -1,
+     552,    -1,   554,   555,    -1,    -1,    -1,   547,   560,    -1,
+      -1,    -1,   552,    -1,   554,   555,    -1,   569,   570,    -1,
+     560,   573,   224,   225,    -1,   227,   228,    -1,    -1,   569,
+     570,    -1,   262,   573,     3,    -1,   266,   267,    -1,    -1,
+      -1,   271,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    18,
+      -1,   281,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      29,   291,    -1,    32,    33,    34,    -1,    -1,    37,    38,
+      -1,    -1,    41,    -1,    -1,    -1,    45,    -1,    -1,    48,
+      -1,    -1,    -1,    -1,    -1,    -1,   316,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   336,   337,
+     338,   339,   340,   341,   342,   343,    -1,   345,   346,   347,
+     348,   349,   350,   351,   352,   353,   354,   355,    -1,    -1,
+      -1,    90,    -1,    -1,    -1,    -1,   356,   357,    -1,    -1,
+      -1,    -1,    -1,    -1,   336,   337,   338,   339,   340,   341,
+     342,   343,    -1,   345,   346,   347,   348,   349,   350,   351,
+     352,   353,   354,   355,     5,    -1,     7,    -1,    -1,    10,
+      -1,    -1,    -1,   393,    15,    -1,    -1,    -1,    -1,    20,
+      -1,    -1,    -1,    -1,   404,    26,    -1,    28,    -1,    -1,
+     418,    -1,    -1,    -1,    -1,    36,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    47,    -1,    -1,    -1,
+       5,    -1,     7,    -1,    -1,    10,    57,    -1,    -1,    -1,
+      15,   441,   442,    -1,    -1,    20,   418,    -1,    -1,    -1,
+      71,    26,    -1,    28,    -1,    30,   456,    -1,    -1,     3,
+      -1,    36,    -1,    -1,    39,    -1,    -1,    42,    -1,    -1,
+     478,   479,    47,   481,    18,    50,    51,    52,    53,    54,
+      55,    56,    57,    -1,    -1,    29,    61,    -1,    32,    33,
+      34,    -1,    -1,    37,    38,    -1,    71,    41,    -1,    -1,
+      75,    45,    -1,    -1,    48,    -1,   478,   479,    -1,   481,
+     510,    -1,    87,    -1,    89,    -1,    91,    -1,    -1,    -1,
+     520,   521,    97,    67,    99,    -1,    -1,   102,    -1,     3,
+       4,     5,     6,     7,     8,    -1,    10,    -1,    12,    13,
+      14,    15,    -1,   543,    18,    -1,    20,    21,    22,    -1,
+      -1,    -1,    26,   553,    28,    29,    30,    -1,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      -1,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    67,    68,    -1,    -1,    71,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    89,    -1,    91,    -1,     3,
+       4,     5,     6,     7,    -1,    99,    10,   101,    12,    -1,
+      14,    15,    -1,    -1,    18,    -1,    20,    21,    22,    -1,
+      -1,    -1,    26,    -1,    28,    29,    30,    -1,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      -1,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    67,    68,    -1,    -1,    71,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    89,    -1,    91,    -1,     3,
+       4,     5,     6,     7,    -1,    99,    10,   101,    12,    -1,
+      14,    15,    -1,    -1,    18,    -1,    20,    21,    22,    -1,
+      -1,    -1,    26,    -1,    28,    29,    30,    -1,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      -1,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    67,    68,    -1,    -1,    71,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    89,    -1,    91,    -1,     3,
+       4,     5,     6,     7,    -1,    99,    10,   101,    12,    -1,
+      14,    15,    -1,    -1,    18,    -1,    20,    21,    22,    -1,
+      -1,    -1,    26,    -1,    28,    29,    30,    -1,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      -1,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    67,    68,    -1,    -1,    71,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    89,    -1,    91,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    99,    -1,   101,     3,     4,
+       5,     6,     7,    -1,    -1,    10,    11,    12,    -1,    14,
+      15,    -1,    -1,    18,    -1,    20,    21,    22,    -1,    -1,
+      -1,    26,    -1,    28,    29,    30,    -1,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    -1,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    68,    -1,    -1,    71,    -1,    -1,    -1,
+      -1,     4,     5,     6,     7,    -1,    -1,    10,    -1,    12,
+      -1,    14,    15,    -1,    89,    -1,    91,    20,    21,    22,
+      -1,    -1,    -1,    26,    99,    28,   101,    30,    -1,    -1,
+      -1,    -1,    35,    36,    -1,    -1,    39,    40,    41,    42,
+      43,    -1,    -1,    46,    47,    -1,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    68,    -1,    -1,    71,    -1,
+      -1,    -1,    -1,     4,     5,     6,     7,    -1,    -1,    10,
+      -1,    12,    -1,    14,    15,    -1,    89,    -1,    91,    20,
+      21,    22,    -1,    -1,    -1,    26,    99,    28,   101,    30,
+      -1,    -1,    -1,    -1,    35,    36,    -1,    -1,    39,    40,
+      41,    42,    43,    -1,    -1,    46,    47,    -1,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    68,    -1,    -1,
+      71,     5,    -1,     7,    -1,    -1,    10,    -1,    -1,    -1,
+      -1,    15,    -1,    -1,    -1,    -1,    20,    -1,    89,    -1,
+      91,    -1,    26,    -1,    28,    -1,    30,    -1,    99,    -1,
+     101,    -1,    36,    -1,    -1,    39,    -1,    -1,    42,    -1,
+      -1,    -1,    -1,    47,    -1,    -1,    50,    51,    52,    53,
+      54,    55,    56,    57,    -1,     5,    -1,     7,    -1,    -1,
+      10,    -1,    -1,    -1,    68,    15,    -1,    71,    -1,    -1,
+      20,    75,    -1,    -1,    -1,    -1,    26,    -1,    28,    -1,
+      30,    -1,    -1,    87,    -1,    89,    36,    91,    -1,    39,
+      -1,    -1,    42,    97,    -1,    99,    -1,    47,   102,    -1,
+      50,    51,    52,    53,    54,    55,    56,    57,    -1,     5,
+      -1,     7,    -1,    -1,    10,    -1,    -1,    -1,    -1,    15,
+      -1,    71,    -1,    -1,    20,    75,    -1,    -1,    -1,    -1,
+      26,    -1,    28,    -1,    30,    -1,    -1,    87,    -1,    89,
+      36,    91,    -1,    39,    -1,    -1,    42,    97,    -1,    99,
+      -1,    47,   102,    -1,    50,    51,    52,    53,    54,    55,
+      56,    57,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,     3,    71,     5,    -1,     7,    75,
+      -1,    10,    -1,    -1,    -1,    -1,    15,    -1,    -1,    18,
+      -1,    20,    -1,    -1,    -1,    91,    -1,    26,    -1,    28,
+      29,    30,    -1,    32,    33,    34,   102,    36,    37,    38,
+      39,    -1,    41,    42,    -1,    -1,    45,    -1,    47,    48,
+      -1,    50,    51,    52,    53,    54,    55,    56,    57,    -1,
+       5,    -1,     7,    -1,    -1,    10,    -1,    -1,    -1,    -1,
+      15,    -1,    71,    -1,    -1,    20,    -1,    -1,    -1,    -1,
+      -1,    26,    -1,    28,    -1,    30,    -1,    -1,    -1,    -1,
+      89,    36,    91,    -1,    39,    -1,    -1,    42,    -1,    -1,
+      99,    -1,    47,    -1,    -1,    50,    51,    52,    53,    54,
+      55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    71,    -1,    -1,    -1,
+       3,    -1,     5,    -1,     7,    -1,    -1,    10,    -1,    -1,
+      -1,    -1,    15,    -1,    89,    18,    91,    20,    -1,    -1,
+      -1,     3,    -1,    26,    99,    28,    29,    -1,    -1,    32,
+      33,    34,    -1,    36,    37,    38,    18,    -1,    41,    -1,
+      -1,    -1,    45,    -1,    47,    48,    -1,    29,    -1,    -1,
+      32,    33,    34,    -1,    57,    37,    38,    -1,    -1,    41,
+      60,    -1,    -1,    45,    64,    -1,    48,    -1,    71,    -1,
+      70,    -1,    -1,    73,    60,    -1,    -1,    -1,    64,    -1,
+      80,    -1,    82,    83,    70,    -1,    -1,    73,    88,    -1,
+      -1,    -1,    -1,    93,    80,    95,    82,    83,    98,    -1,
+      -1,    60,    88,    -1,   104,    64,    -1,    93,    -1,    95,
+      -1,    70,    98,    -1,    73,    -1,    -1,    -1,   104,    -1,
+      -1,    80,    -1,    82,    83,    -1,    -1,    -1,    -1,    88,
+      -1,    -1,    -1,    -1,    93,    -1,    95,    -1,    -1,    98,
+      -1,    -1,    -1,    -1,    -1,   104
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint16 yystos[] =
+{
+       0,    31,   107,   122,   123,   126,     5,     7,    10,    15,
+      20,    26,    28,    36,    47,    57,    71,   111,   117,   118,
+     119,   120,   121,     0,   124,    57,    72,   101,    72,    24,
+     125,   127,   128,   129,    11,    42,   119,    11,   117,     3,
+      18,    29,    32,    33,    34,    37,    38,    41,    45,    48,
+     101,   130,   131,   132,   133,   134,   135,   164,   165,    72,
+     101,   132,    17,    23,    68,   136,   137,   139,    11,    27,
+      17,   166,   167,   103,   113,   114,   117,   113,   115,   138,
+     140,   137,   139,   139,   119,   119,   115,    68,   168,    66,
+     101,    66,    37,    67,   130,   135,   141,   142,   143,   148,
+     149,   158,   159,   139,   169,   115,   115,    68,   177,    47,
+     110,   111,   112,   113,   116,   117,   118,   160,   101,   157,
+     177,    67,   134,   135,   143,   149,   165,   170,   171,   172,
+       4,     6,    12,    14,    21,    22,    30,    35,    39,    40,
+      41,    42,    43,    46,    49,    50,    51,    52,    53,    54,
+      55,    56,    89,    91,    99,   101,   108,   109,   110,   116,
+     117,   119,   131,   134,   135,   177,   178,   179,   180,   181,
+     182,   183,   185,   186,   187,   189,   190,   191,   192,   194,
+     201,   203,   204,   212,   213,   215,   216,   217,   218,   219,
+     224,   225,   226,   230,   235,   236,   237,   238,   239,   240,
+     242,   243,   258,   259,   263,   119,   151,   119,   144,   145,
+     146,   151,    62,   234,   234,    91,    44,   150,   155,   101,
+     101,   101,   173,   101,    75,    87,    91,    97,   102,   111,
+     116,   117,   226,   236,   238,   239,   240,   241,   242,   243,
+     244,   245,   246,   247,   248,   249,   250,   251,   252,   253,
+     254,   255,   256,   257,   258,   261,   119,   214,   214,    41,
+     183,    91,    91,   208,   261,    72,    91,    91,    72,   261,
+     177,    91,   117,   235,   237,   241,   261,   241,   119,   144,
+      72,    62,    72,    91,    65,   110,    67,   180,   101,   101,
+      72,    62,    89,    99,    60,    64,    70,    73,    80,    82,
+      83,    88,    93,    95,    98,   104,   260,   111,   113,   114,
+      91,    62,   150,    66,   101,    62,    73,   150,    61,    62,
+     135,   152,   153,   154,   114,   156,    68,   161,   101,   241,
+     241,   111,   117,   261,   241,   241,    69,    92,   103,    87,
+      97,    79,    81,    86,    25,    77,    78,    84,    85,    74,
+      76,    58,    63,    94,    59,    96,   100,    65,   101,   101,
+     101,    49,   131,   182,   190,   206,   209,   211,   261,   101,
+     119,   261,   261,   119,   101,     9,   220,   221,   222,   261,
+      90,    11,   261,    30,   228,   229,   261,   183,   144,    42,
+     119,   261,   257,    62,   232,   233,   234,   232,   234,    91,
+     152,    61,   145,    61,    68,   147,   174,   261,    61,   110,
+      90,    66,    66,   162,   101,   231,   234,   234,    90,   241,
+     241,   241,   246,   246,   247,   247,   247,   112,   248,   248,
+     248,   248,   249,   249,   250,   251,   252,   253,   254,   261,
+     261,    91,   101,    66,    90,    91,    90,    90,    91,    91,
+      19,   223,   222,    90,    61,    90,    66,    91,    61,   261,
+     231,   233,   234,   174,   231,   174,   228,    90,   147,   175,
+     176,   146,   154,   114,    39,    42,   163,   178,    90,    90,
+     244,    65,   101,   261,   208,   190,    21,    22,    49,   119,
+     183,   184,   185,   188,   193,   202,   207,   228,    68,   195,
+     177,   228,   154,   177,   183,   261,   228,    61,    90,    67,
+      66,    91,    91,    67,   241,   244,   256,    90,   101,    91,
+      91,    91,    65,    16,    90,   197,    90,    90,    90,   139,
+     227,   147,   228,   228,   101,   205,   210,   211,   206,   261,
+     261,   184,   183,     8,    13,   196,   198,   199,   200,   177,
+      90,    90,    90,   101,    90,    90,   261,   262,    65,    67,
+     179,   200,   101,   101,   183,   208,   184,   184,    65,   101,
+      16,   205,   184,    90,   184
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint16 yyr1[] =
+{
+       0,   106,   107,   108,   108,   108,   108,   108,   108,   109,
+     109,   110,   110,   111,   111,   111,   111,   111,   111,   111,
+     111,   112,   112,   113,   114,   115,   116,   116,   117,   117,
+     118,   119,   119,   120,   120,   120,   120,   121,   121,   122,
+     123,   123,   124,   124,   125,   125,   126,   127,   127,   128,
+     129,   130,   130,   130,   131,   131,   132,   132,   132,   132,
+     132,   132,   132,   132,   132,   132,   132,   133,   134,   134,
+     134,   134,   135,   135,   136,   137,   138,   138,   139,   140,
+     140,   141,   141,   141,   141,   142,   142,   143,   144,   144,
+     145,   145,   146,   146,   147,   147,   148,   148,   148,   149,
+     149,   150,   150,   151,   151,   152,   152,   153,   153,   154,
+     155,   156,   156,   157,   158,   159,   159,   160,   161,   162,
+     162,   163,   163,   164,   165,   166,   166,   167,   167,   168,
+     169,   169,   170,   170,   170,   170,   170,   170,   171,   172,
+     173,   173,   174,   175,   175,   175,   176,   176,   177,   178,
+     178,   179,   179,   180,   180,   180,   181,   182,   182,   183,
+     183,   183,   183,   183,   183,   184,   184,   184,   184,   184,
+     185,   185,   185,   185,   185,   185,   185,   185,   185,   185,
+     185,   185,   186,   187,   188,   189,   190,   190,   190,   190,
+     190,   190,   190,   191,   192,   193,   194,   195,   196,   196,
+     197,   197,   198,   199,   199,   200,   200,   201,   202,   203,
+     204,   205,   205,   206,   206,   207,   208,   208,   209,   209,
+     210,   211,   211,   212,   212,   213,   214,   214,   215,   216,
+     217,   218,   219,   219,   220,   220,   221,   221,   222,   223,
+     224,   224,   225,   225,   225,   225,   225,   225,   225,   226,
+     227,   227,   228,   228,   229,   229,   230,   230,   230,   230,
+     231,   231,   232,   232,   233,   234,   234,   235,   235,   235,
+     235,   236,   236,   236,   236,   237,   237,   238,   238,   238,
+     238,   238,   239,   240,   241,   241,   241,   241,   241,   242,
+     243,   244,   244,   244,   244,   245,   245,   245,   246,   246,
+     246,   246,   247,   247,   247,   248,   248,   248,   248,   249,
+     249,   249,   249,   249,   249,   250,   250,   250,   251,   251,
+     252,   252,   253,   253,   254,   254,   255,   255,   256,   256,
+     257,   257,   258,   259,   259,   259,   260,   260,   260,   260,
+     260,   260,   260,   260,   260,   260,   260,   260,   261,   262,
+     263,   263
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     2,     2,     1,     1,
+       1,     1,     2,     3,     3,     3,     3,     1,     1,     3,
+       0,     1,     0,     2,     0,     2,     3,     1,     1,     3,
+       5,     1,     1,     1,     1,     2,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     3,     2,     3,
+       3,     4,     0,     1,     2,     2,     1,     3,     3,     0,
+       2,     1,     1,     1,     1,     1,     1,     4,     1,     3,
+       1,     3,     1,     3,     1,     1,     2,     2,     3,     4,
+       4,     0,     1,     4,     3,     0,     1,     1,     3,     3,
+       2,     1,     3,     1,     2,     4,     5,     4,     4,     0,
+       2,     5,     5,     3,     3,     0,     1,     2,     3,     3,
+       0,     2,     1,     1,     1,     2,     1,     2,     1,     2,
+       1,     2,     3,     0,     1,     2,     1,     3,     3,     0,
+       1,     1,     2,     1,     1,     1,     2,     3,     2,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     3,     3,     2,     1,     1,     1,     1,
+       1,     1,     1,     5,     7,     7,     5,     4,     0,     1,
+       0,     2,     2,     1,     2,     3,     2,     5,     5,     7,
+       9,     0,     1,     0,     1,     9,     0,     1,     1,     1,
+       1,     1,     3,     3,     5,     3,     0,     1,     3,     3,
+       3,     5,     3,     4,     0,     1,     1,     2,     5,     2,
+       1,     1,     1,     1,     3,     1,     1,     1,     1,     6,
+       0,     1,     0,     1,     1,     3,     4,     4,     4,     4,
+       0,     1,     1,     2,     3,     2,     3,     3,     3,     3,
+       3,     4,     6,     6,     6,     4,     4,     1,     1,     3,
+       1,     1,     2,     2,     1,     1,     2,     2,     1,     2,
+       2,     1,     2,     2,     1,     5,     4,     5,     1,     3,
+       3,     3,     1,     3,     3,     1,     3,     3,     3,     1,
+       3,     3,     3,     3,     3,     1,     3,     3,     1,     3,
+       1,     3,     1,     3,     1,     3,     1,     3,     1,     5,
+       1,     1,     3,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     3
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, yyscanner); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (yyscanner);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , yyscanner);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
+{
+  YYUSE (yyvaluep);
+  YYUSE (yyscanner);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (yyscan_t yyscanner)
+{
+/* The lookahead symbol.  */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol.  */
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex (&yylval, yyscanner);
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 180 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2293 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 3:
+#line 189 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2304 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 4:
+#line 197 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2315 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 5:
+#line 205 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2326 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 6:
+#line 213 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2337 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 7:
+#line 221 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2348 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 229 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2359 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 238 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2370 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 246 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2381 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 255 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2392 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 12:
+#line 263 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2403 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 13:
+#line 272 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+}
+#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 14:
+#line 277 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+}
+#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 15:
+#line 282 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+}
+#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 16:
+#line 287 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+}
+#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 17:
+#line 292 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+}
+#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 18:
+#line 297 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+}
+#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 19:
+#line 302 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+}
+#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 20:
+#line 307 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+}
+#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 21:
+#line 313 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2478 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 22:
+#line 321 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2489 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 23:
+#line 330 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpStoreClass((yyvsp[0].str));
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2501 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 24:
+#line 340 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2512 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 25:
+#line 349 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2523 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 26:
+#line 358 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2534 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 27:
+#line 366 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpStoreClass((yyvsp[-1].str));
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2546 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 28:
+#line 376 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  (yyval.str) = (yyvsp[0].str);
+}
+#line 2555 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 29:
+#line 382 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  (yyval.str) = (yyvsp[0].str);
+}
+#line 2564 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 30:
+#line 389 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  (yyval.str) = (yyvsp[0].str);
+}
+#line 2573 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 31:
+#line 396 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  (yyval.str) = (yyvsp[0].str);
+}
+#line 2582 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 32:
+#line 402 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  (yyval.str) = (yyvsp[0].str);
+}
+#line 2591 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 33:
+#line 409 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->AddClassFound((yyvsp[-2].str));
+  yyGetParser->UpdateCombine((yyvsp[-2].str), (yyvsp[0].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
+  (yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine());
+}
+#line 2603 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 34:
+#line 418 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpStoreClass((yyvsp[-2].str));
+  jpCheckEmpty(3);
+  yyGetParser->SetCurrentCombine("");
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2616 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 35:
+#line 428 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpStoreClass((yyvsp[-2].str));
+  yyGetParser->SetCurrentCombine("");
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2629 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 36:
+#line 438 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2640 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 37:
+#line 447 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2651 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 38:
+#line 455 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2662 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 39:
+#line 464 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2673 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 40:
+#line 472 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2683 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 41:
+#line 479 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2694 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 42:
+#line 487 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2704 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 43:
+#line 494 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2715 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 44:
+#line 502 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2725 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 45:
+#line 509 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2736 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 46:
+#line 518 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->SetCurrentPackage((yyvsp[-1].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
+  yyGetParser->SetCurrentCombine("");
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2750 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 47:
+#line 530 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2761 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 48:
+#line 538 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2772 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 49:
+#line 547 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->AddPackagesImport((yyvsp[-1].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
+  yyGetParser->SetCurrentCombine("");
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2786 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 50:
+#line 559 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+  std::string str = (yyvsp[-3].str);
+  str += ".*";
+  yyGetParser->AddPackagesImport(str.c_str());
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
+  yyGetParser->SetCurrentCombine("");
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2801 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 51:
+#line 572 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2812 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 52:
+#line 580 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2823 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 53:
+#line 588 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2834 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 54:
+#line 597 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2845 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 55:
+#line 605 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2856 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 67:
+#line 620 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  yyGetParser->StartClass((yyvsp[0].str));
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  jpCheckEmpty(3);
+}
+#line 2867 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 68:
+#line 630 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+#line 2879 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 69:
+#line 639 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+#line 2891 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 70:
+#line 648 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+#line 2903 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 71:
+#line 657 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+#line 2915 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 72:
+#line 666 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2925 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 73:
+#line 673 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2936 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 74:
+#line 682 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2947 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 75:
+#line 691 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2958 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 76:
+#line 700 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2969 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 77:
+#line 708 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2980 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 78:
+#line 717 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 2991 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 79:
+#line 725 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3001 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 80:
+#line 732 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3012 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 81:
+#line 741 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3023 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 82:
+#line 749 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3034 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 83:
+#line 757 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3045 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 84:
+#line 765 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3056 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 85:
+#line 774 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3067 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 86:
+#line 782 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3078 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 87:
+#line 791 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+}
+#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 88:
+#line 797 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3097 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 89:
+#line 805 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3108 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 90:
+#line 814 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3119 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 91:
+#line 822 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3130 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 92:
+#line 831 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3142 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 93:
+#line 840 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3153 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 94:
+#line 849 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3164 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 95:
+#line 857 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3175 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 96:
+#line 866 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3186 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 97:
+#line 874 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3197 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 98:
+#line 882 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3208 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 99:
+#line 891 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3220 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 100:
+#line 900 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3232 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 101:
+#line 909 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3243 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 102:
+#line 917 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3255 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 103:
+#line 927 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3268 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 104:
+#line 937 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+
+}
+#line 3277 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 105:
+#line 943 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3288 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 107:
+#line 954 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+
+}
+#line 3297 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 108:
+#line 960 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3309 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 109:
+#line 970 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3321 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 110:
+#line 980 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3333 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 111:
+#line 990 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+
+}
+#line 3342 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 112:
+#line 996 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3354 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 113:
+#line 1006 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3366 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 114:
+#line 1016 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3378 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 115:
+#line 1026 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3390 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 116:
+#line 1035 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3402 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 117:
+#line 1045 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3415 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 118:
+#line 1056 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3427 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 119:
+#line 1065 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3438 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 120:
+#line 1073 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3450 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 121:
+#line 1083 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3462 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 122:
+#line 1092 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3474 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 123:
+#line 1102 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  yyGetParser->StartClass((yyvsp[0].str));
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  jpCheckEmpty(3);
+}
+#line 3485 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 124:
+#line 1111 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+#line 3497 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 125:
+#line 1120 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+#line 3507 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 126:
+#line 1127 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3519 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 127:
+#line 1137 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3531 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 128:
+#line 1146 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3543 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 129:
+#line 1156 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3555 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 130:
+#line 1165 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3566 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 131:
+#line 1173 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3577 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 132:
+#line 1182 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3589 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 133:
+#line 1191 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3601 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 134:
+#line 1200 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3613 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 135:
+#line 1209 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3624 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 136:
+#line 1217 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3636 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 137:
+#line 1226 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3647 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 138:
+#line 1235 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3659 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 139:
+#line 1245 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3671 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 140:
+#line 1255 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3683 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 141:
+#line 1264 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3695 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 142:
+#line 1274 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3707 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 143:
+#line 1283 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3718 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 144:
+#line 1291 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3730 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 145:
+#line 1300 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3742 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 146:
+#line 1310 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3754 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 147:
+#line 1319 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3766 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 148:
+#line 1329 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3777 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 149:
+#line 1337 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3788 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 150:
+#line 1345 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3800 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 151:
+#line 1355 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3812 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 152:
+#line 1364 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3824 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 153:
+#line 1374 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3836 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 154:
+#line 1383 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3848 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 155:
+#line 1392 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3860 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 156:
+#line 1402 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3872 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 157:
+#line 1412 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3884 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 158:
+#line 1421 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3896 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 159:
+#line 1431 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3908 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 160:
+#line 1440 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3920 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 161:
+#line 1449 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3932 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 162:
+#line 1458 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3944 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 163:
+#line 1467 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3956 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 164:
+#line 1476 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3968 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 165:
+#line 1486 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3980 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 166:
+#line 1495 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 3992 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 167:
+#line 1504 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4004 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 168:
+#line 1513 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4016 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 169:
+#line 1522 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4028 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 170:
+#line 1532 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4040 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 171:
+#line 1541 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4052 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 172:
+#line 1550 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4064 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 173:
+#line 1559 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4076 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 174:
+#line 1568 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4088 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 175:
+#line 1577 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4100 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 176:
+#line 1586 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4112 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 177:
+#line 1595 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4124 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 178:
+#line 1604 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4136 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 179:
+#line 1613 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4148 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 180:
+#line 1622 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4160 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 181:
+#line 1631 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4172 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 182:
+#line 1641 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4184 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 183:
+#line 1651 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4197 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 184:
+#line 1662 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4209 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 185:
+#line 1672 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4221 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 186:
+#line 1682 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4233 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 187:
+#line 1691 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4245 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 188:
+#line 1700 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4257 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 189:
+#line 1709 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4269 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 190:
+#line 1718 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4281 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 191:
+#line 1727 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4293 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 192:
+#line 1736 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4305 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 193:
+#line 1746 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4317 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 194:
+#line 1756 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(7);
+  jpCheckEmpty(7);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4329 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 195:
+#line 1766 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(7);
+  jpCheckEmpty(7);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4341 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 196:
+#line 1776 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+
+}
+#line 4350 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 197:
+#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+
+}
+#line 4359 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 198:
+#line 1789 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4370 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 199:
+#line 1797 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4382 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 200:
+#line 1806 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4393 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 201:
+#line 1814 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4405 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 202:
+#line 1824 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4417 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 203:
+#line 1834 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4429 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 204:
+#line 1843 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4441 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 205:
+#line 1853 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4453 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 206:
+#line 1862 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4465 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 207:
+#line 1872 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+
+}
+#line 4474 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 208:
+#line 1879 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+
+}
+#line 4483 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 209:
+#line 1886 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(7);
+
+}
+#line 4492 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 210:
+#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(9);
+
+}
+#line 4501 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 211:
+#line 1900 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4512 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 212:
+#line 1908 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4524 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 213:
+#line 1917 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4535 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 214:
+#line 1925 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4547 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 215:
+#line 1936 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(9);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4558 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 216:
+#line 1944 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4569 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 217:
+#line 1952 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4581 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 218:
+#line 1962 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4593 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 219:
+#line 1971 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4605 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 220:
+#line 1981 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4617 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 221:
+#line 1991 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4629 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 222:
+#line 2000 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4641 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 223:
+#line 2010 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4653 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 224:
+#line 2019 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4665 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 225:
+#line 2029 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4678 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 226:
+#line 2039 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4689 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 227:
+#line 2047 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+
+}
+#line 4698 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 228:
+#line 2054 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4711 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 229:
+#line 2065 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4723 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 230:
+#line 2075 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4735 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 231:
+#line 2085 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4747 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 232:
+#line 2095 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4759 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 233:
+#line 2104 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4771 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 234:
+#line 2113 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4782 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 235:
+#line 2121 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4794 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 236:
+#line 2131 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4806 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 237:
+#line 2140 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4818 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 238:
+#line 2150 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+
+}
+#line 4827 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 239:
+#line 2157 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4839 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 240:
+#line 2167 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4851 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 241:
+#line 2176 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4863 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 242:
+#line 2186 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4875 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 243:
+#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+
+}
+#line 4884 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 244:
+#line 2201 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4896 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 245:
+#line 2210 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4908 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 246:
+#line 2219 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4920 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 247:
+#line 2228 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4932 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 248:
+#line 2237 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4944 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 249:
+#line 2247 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(6);
+  jpCheckEmpty(6);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4956 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 250:
+#line 2256 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4967 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 251:
+#line 2264 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4979 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 252:
+#line 2273 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 4990 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 253:
+#line 2281 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5002 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 254:
+#line 2291 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5014 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 255:
+#line 2300 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5026 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 256:
+#line 2310 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5038 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 257:
+#line 2319 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5050 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 258:
+#line 2328 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5062 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 259:
+#line 2337 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5074 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 260:
+#line 2346 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(0);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5085 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 261:
+#line 2354 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5097 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 262:
+#line 2364 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5109 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 263:
+#line 2373 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5121 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 264:
+#line 2383 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5133 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 265:
+#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+
+}
+#line 5142 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 266:
+#line 2399 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+
+}
+#line 5151 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 267:
+#line 2406 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5164 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 268:
+#line 2416 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5177 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 269:
+#line 2426 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5190 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 270:
+#line 2436 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5203 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 271:
+#line 2447 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5216 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 272:
+#line 2457 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(6);
+  yyGetParser->DeallocateParserType(&((yyvsp[-5].str)));
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
+  jpCheckEmpty(6);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5230 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 273:
+#line 2468 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(6);
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
+  jpCheckEmpty(6);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5243 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 274:
+#line 2478 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(6);
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
+  jpCheckEmpty(6);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5256 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 275:
+#line 2489 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5269 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 276:
+#line 2499 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5281 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 277:
+#line 2509 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5293 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 278:
+#line 2518 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5305 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 279:
+#line 2527 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5317 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 280:
+#line 2536 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5329 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 281:
+#line 2545 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5341 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 282:
+#line 2555 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5353 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 283:
+#line 2565 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5365 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 284:
+#line 2575 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5377 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 285:
+#line 2584 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5389 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 286:
+#line 2593 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5401 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 287:
+#line 2602 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5413 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 288:
+#line 2611 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5425 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 289:
+#line 2621 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5437 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 290:
+#line 2631 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5449 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 291:
+#line 2641 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5461 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 292:
+#line 2650 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5473 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 293:
+#line 2659 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5485 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 294:
+#line 2668 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5497 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 295:
+#line 2678 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5509 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 296:
+#line 2687 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5521 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 297:
+#line 2696 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+
+}
+#line 5530 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 298:
+#line 2703 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5542 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 299:
+#line 2712 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5554 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 300:
+#line 2721 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5566 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 301:
+#line 2730 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5578 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 302:
+#line 2740 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5590 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 303:
+#line 2749 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5602 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 304:
+#line 2758 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5614 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 305:
+#line 2768 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5626 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 306:
+#line 2777 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5638 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 307:
+#line 2786 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5650 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 308:
+#line 2795 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5662 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 309:
+#line 2805 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5674 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 310:
+#line 2814 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5686 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 311:
+#line 2823 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5698 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 312:
+#line 2832 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5710 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 313:
+#line 2841 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5722 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 314:
+#line 2850 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5734 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 315:
+#line 2860 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5746 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 316:
+#line 2869 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5758 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 317:
+#line 2878 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5770 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 318:
+#line 2888 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5782 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 319:
+#line 2897 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5794 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 320:
+#line 2907 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5806 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 321:
+#line 2916 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5818 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 322:
+#line 2926 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5830 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 323:
+#line 2935 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5842 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 324:
+#line 2945 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5854 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 325:
+#line 2954 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5866 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 326:
+#line 2964 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5878 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 327:
+#line 2973 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5890 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 328:
+#line 2983 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5902 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 329:
+#line 2992 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5914 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 330:
+#line 3002 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5926 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 331:
+#line 3011 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5938 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 332:
+#line 3021 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5950 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 333:
+#line 3031 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5963 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 334:
+#line 3041 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5975 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 335:
+#line 3050 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5987 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 336:
+#line 3060 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 5999 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 337:
+#line 3069 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6011 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 338:
+#line 3078 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6023 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 339:
+#line 3087 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6035 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 340:
+#line 3096 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6047 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 341:
+#line 3105 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6059 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 342:
+#line 3114 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6071 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 343:
+#line 3123 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6083 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 344:
+#line 3132 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6095 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 345:
+#line 3141 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6107 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 346:
+#line 3150 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6119 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 347:
+#line 3159 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6131 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 348:
+#line 3169 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6143 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 349:
+#line 3179 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6155 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 350:
+#line 3189 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6167 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 351:
+#line 3198 "cmDependsJavaParser.y" /* yacc.c:1646  */
+    {
+  jpElementStart(3);
+  jpStoreClass((yyvsp[-2].str));
+  jpCheckEmpty(3);
+  (yyval.str) = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+#line 6180 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+    break;
+
+
+#line 6184 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (yyscanner, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (yyscanner, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, yyscanner);
+          yychar = YYEMPTY;
+        }
+    }
+
+#if 0
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+#endif
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, yyscanner);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (yyscanner, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, yyscanner);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp, yyscanner);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
+#line 3207 "cmDependsJavaParser.y" /* yacc.c:1906  */
+
+/* End of grammar */
+
+/*--------------------------------------------------------------------------*/
+void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message)
+{
+  yyGetParser->Error(message);
+}
diff --git a/Source/LexerParser/cmDependsJavaParser.y b/Source/LexerParser/cmDependsJavaParser.y
new file mode 100644
index 0000000..f7eb228
--- /dev/null
+++ b/Source/LexerParser/cmDependsJavaParser.y
@@ -0,0 +1,3214 @@
+%{
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+  bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y
+
+Modify cmDependsJavaParser.cxx:
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
+#define yyGetParser (cmDependsJava_yyget_extra(yyscanner))
+
+/*-------------------------------------------------------------------------*/
+#include "cmDependsJavaParserHelper.h" /* Interface to parser object.  */
+#include "cmDependsJavaLexer.h"  /* Interface to lexer object.  */
+#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
+
+/* Forward declare the lexer entry point.  */
+YY_DECL;
+
+/* Helper function to forward error callback from parser.  */
+static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
+
+#define YYMAXDEPTH 1000000
+
+
+#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp);
+#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval)
+#define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str))
+/* Disable some warnings in the generated code.  */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label.  */
+# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
+#endif
+%}
+
+/* Generate a reentrant parser object.  */
+%define api.pure
+
+/* Configure the parser to use a lexer object.  */
+%lex-param   {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
+
+%define parse.error verbose
+
+/*
+%union {
+  char* string;
+}
+*/
+
+/*-------------------------------------------------------------------------*/
+/* Tokens */
+%token jp_ABSTRACT
+%token jp_ASSERT
+%token jp_BOOLEAN_TYPE
+%token jp_BREAK
+%token jp_BYTE_TYPE
+%token jp_CASE
+%token jp_CATCH
+%token jp_CHAR_TYPE
+%token jp_CLASS
+%token jp_CONTINUE
+%token jp_DEFAULT
+%token jp_DO
+%token jp_DOUBLE_TYPE
+%token jp_ELSE
+%token jp_EXTENDS
+%token jp_FINAL
+%token jp_FINALLY
+%token jp_FLOAT_TYPE
+%token jp_FOR
+%token jp_IF
+%token jp_IMPLEMENTS
+%token jp_IMPORT
+%token jp_INSTANCEOF
+%token jp_INT_TYPE
+%token jp_INTERFACE
+%token jp_LONG_TYPE
+%token jp_NATIVE
+%token jp_NEW
+%token jp_PACKAGE
+%token jp_PRIVATE
+%token jp_PROTECTED
+%token jp_PUBLIC
+%token jp_RETURN
+%token jp_SHORT_TYPE
+%token jp_STATIC
+%token jp_STRICTFP
+%token jp_SUPER
+%token jp_SWITCH
+%token jp_SYNCHRONIZED
+%token jp_THIS
+%token jp_THROW
+%token jp_THROWS
+%token jp_TRANSIENT
+%token jp_TRY
+%token jp_VOID
+%token jp_VOLATILE
+%token jp_WHILE
+
+%token jp_BOOLEANLITERAL
+%token jp_CHARACTERLITERAL
+%token jp_DECIMALINTEGERLITERAL
+%token jp_FLOATINGPOINTLITERAL
+%token jp_HEXINTEGERLITERAL
+%token jp_NULLLITERAL
+%token jp_STRINGLITERAL
+
+%token jp_NAME
+
+%token jp_AND
+%token jp_ANDAND
+%token jp_ANDEQUALS
+%token jp_BRACKETEND
+%token jp_BRACKETSTART
+%token jp_CARROT
+%token jp_CARROTEQUALS
+%token jp_COLON
+%token jp_COMMA
+%token jp_CURLYEND
+%token jp_CURLYSTART
+%token jp_DIVIDE
+%token jp_DIVIDEEQUALS
+%token jp_DOLLAR
+%token jp_DOT
+%token jp_EQUALS
+%token jp_EQUALSEQUALS
+%token jp_EXCLAMATION
+%token jp_EXCLAMATIONEQUALS
+%token jp_GREATER
+%token jp_GTEQUALS
+%token jp_GTGT
+%token jp_GTGTEQUALS
+%token jp_GTGTGT
+%token jp_GTGTGTEQUALS
+%token jp_LESLESEQUALS
+%token jp_LESSTHAN
+%token jp_LTEQUALS
+%token jp_LTLT
+%token jp_MINUS
+%token jp_MINUSEQUALS
+%token jp_MINUSMINUS
+%token jp_PAREEND
+%token jp_PARESTART
+%token jp_PERCENT
+%token jp_PERCENTEQUALS
+%token jp_PIPE
+%token jp_PIPEEQUALS
+%token jp_PIPEPIPE
+%token jp_PLUS
+%token jp_PLUSEQUALS
+%token jp_PLUSPLUS
+%token jp_QUESTION
+%token jp_SEMICOL
+%token jp_TILDE
+%token jp_TIMES
+%token jp_TIMESEQUALS
+
+%token jp_ERROR
+
+/*-------------------------------------------------------------------------*/
+/* grammar */
+%%
+
+Goal:
+CompilationUnit
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+Literal:
+IntegerLiteral
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+jp_FLOATINGPOINTLITERAL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+jp_BOOLEANLITERAL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+jp_CHARACTERLITERAL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+jp_STRINGLITERAL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+jp_NULLLITERAL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+IntegerLiteral:
+jp_DECIMALINTEGERLITERAL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+jp_HEXINTEGERLITERAL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+Type:
+PrimitiveType
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+ReferenceType
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+PrimitiveType:
+jp_BYTE_TYPE
+{
+  jpElementStart(0);
+}
+|
+jp_SHORT_TYPE
+{
+  jpElementStart(0);
+}
+|
+jp_INT_TYPE
+{
+  jpElementStart(0);
+}
+|
+jp_LONG_TYPE
+{
+  jpElementStart(0);
+}
+|
+jp_CHAR_TYPE
+{
+  jpElementStart(0);
+}
+|
+jp_FLOAT_TYPE
+{
+  jpElementStart(0);
+}
+|
+jp_DOUBLE_TYPE
+{
+  jpElementStart(0);
+}
+|
+jp_BOOLEAN_TYPE
+{
+  jpElementStart(0);
+}
+
+ReferenceType:
+ClassOrInterfaceType
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+ArrayType
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+ClassOrInterfaceType:
+Name
+{
+  jpElementStart(1);
+  jpStoreClass($<str>1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+ClassType:
+ClassOrInterfaceType
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+InterfaceType:
+ClassOrInterfaceType
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+ArrayType:
+PrimitiveType Dims
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+Name Dims
+{
+  jpElementStart(2);
+  jpStoreClass($<str>1);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+Name:
+SimpleName
+{
+  jpElementStart(1);
+  $<str>$ = $<str>1;
+}
+|
+QualifiedName
+{
+  jpElementStart(1);
+  $<str>$ = $<str>1;
+}
+
+SimpleName:
+Identifier
+{
+  jpElementStart(1);
+  $<str>$ = $<str>1;
+}
+
+Identifier:
+jp_NAME
+{
+  jpElementStart(1);
+  $<str>$ = $<str>1;
+}
+|
+jp_DOLLAR jp_NAME
+{
+  jpElementStart(2);
+  $<str>$ = $<str>2;
+}
+
+QualifiedName:
+Name jp_DOT Identifier
+{
+  jpElementStart(3);
+  yyGetParser->AddClassFound($<str>1);
+  yyGetParser->UpdateCombine($<str>1, $<str>3);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  $<str>$ = const_cast<char*>(yyGetParser->GetCurrentCombine());
+}
+|
+Name jp_DOT jp_CLASS
+{
+  jpElementStart(3);
+  jpStoreClass($<str>1);
+  jpCheckEmpty(3);
+  yyGetParser->SetCurrentCombine("");
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+Name jp_DOT jp_THIS
+{
+  jpElementStart(3);
+  jpStoreClass($<str>1);
+  yyGetParser->SetCurrentCombine("");
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+SimpleType jp_DOT jp_CLASS
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+SimpleType:
+PrimitiveType
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+jp_VOID
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+CompilationUnit:
+PackageDeclarationopt ImportDeclarations TypeDeclarations
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+PackageDeclarationopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+PackageDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+ImportDeclarations:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+ImportDeclarations ImportDeclaration
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+TypeDeclarations:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+TypeDeclarations TypeDeclaration
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+PackageDeclaration:
+jp_PACKAGE Name jp_SEMICOL
+{
+  jpElementStart(3);
+  yyGetParser->SetCurrentPackage($<str>2);
+  yyGetParser->DeallocateParserType(&($<str>2));
+  yyGetParser->SetCurrentCombine("");
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+ImportDeclaration:
+SingleTypeImportDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+TypeImportOnDemandDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+SingleTypeImportDeclaration:
+jp_IMPORT Name jp_SEMICOL
+{
+  jpElementStart(3);
+  yyGetParser->AddPackagesImport($<str>2);
+  yyGetParser->DeallocateParserType(&($<str>2));
+  yyGetParser->SetCurrentCombine("");
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+TypeImportOnDemandDeclaration:
+jp_IMPORT Name jp_DOT jp_TIMES jp_SEMICOL
+{
+  jpElementStart(5);
+  std::string str = $<str>2;
+  str += ".*";
+  yyGetParser->AddPackagesImport(str.c_str());
+  yyGetParser->DeallocateParserType(&($<str>2));
+  yyGetParser->SetCurrentCombine("");
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+TypeDeclaration:
+ClassDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+InterfaceDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+jp_SEMICOL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+Modifiers:
+Modifier
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+Modifiers Modifier
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+Modifier:
+jp_PUBLIC | jp_PROTECTED | jp_PRIVATE |
+jp_STATIC |
+jp_ABSTRACT | jp_FINAL | jp_NATIVE | jp_SYNCHRONIZED | jp_TRANSIENT | jp_VOLATILE |
+jp_STRICTFP
+
+ClassHeader:
+Modifiersopt jp_CLASS Identifier
+{
+  yyGetParser->StartClass($<str>3);
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&($<str>3));
+  jpCheckEmpty(3);
+}
+
+
+ClassDeclaration:
+ClassHeader ClassBody
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+|
+ClassHeader Interfaces ClassBody
+{
+  jpElementStart(3);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+|
+ClassHeader Super ClassBody
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+|
+ClassHeader Super Interfaces ClassBody
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+
+Modifiersopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+Modifiers
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+Super:
+jp_EXTENDS ClassType
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+Interfaces:
+jp_IMPLEMENTS InterfaceTypeList
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+InterfaceTypeList:
+InterfaceType
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+InterfaceTypeList jp_COMMA InterfaceType
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+ClassBody:
+jp_CURLYSTART ClassBodyDeclarations jp_CURLYEND
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+ClassBodyDeclarations:
+{
+  jpElementStart(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+ClassBodyDeclarations ClassBodyDeclaration
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+ClassBodyDeclaration:
+ClassMemberDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+StaticInitializer
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+ConstructorDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+TypeDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+ClassMemberDeclaration:
+FieldDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+MethodDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+FieldDeclaration:
+Modifiersopt Type VariableDeclarators jp_SEMICOL
+{
+  jpElementStart(4);
+}
+
+VariableDeclarators:
+VariableDeclarator
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+VariableDeclarators jp_COMMA VariableDeclarator
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+VariableDeclarator:
+VariableDeclaratorId
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+VariableDeclaratorId jp_EQUALS VariableInitializer
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+VariableDeclaratorId:
+Identifier
+{
+  jpElementStart(1);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+VariableDeclaratorId jp_BRACKETSTART jp_BRACKETEND
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+VariableInitializer:
+Expression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+ArrayInitializer
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+MethodDeclaration:
+MethodHeader jp_SEMICOL
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+MethodHeader MethodBody
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+MethodHeader MethodBody jp_SEMICOL
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+
+MethodHeader:
+Modifiersopt Type MethodDeclarator Throwsopt
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Modifiersopt jp_VOID MethodDeclarator Throwsopt
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Throwsopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Throws
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+MethodDeclarator:
+Identifier jp_PARESTART FormalParameterListopt jp_PAREEND
+{
+  jpElementStart(4);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+MethodDeclarator jp_BRACKETSTART jp_BRACKETEND
+{
+  jpElementStart(3);
+
+}
+
+FormalParameterListopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+FormalParameterList
+
+FormalParameterList:
+FormalParameter
+{
+  jpElementStart(1);
+
+}
+|
+FormalParameterList jp_COMMA FormalParameter
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+FormalParameter:
+Modifiersopt Type VariableDeclaratorId
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Throws:
+jp_THROWS ClassTypeList
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ClassTypeList:
+ClassType
+{
+  jpElementStart(1);
+
+}
+|
+ClassTypeList jp_COMMA ClassType
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+MethodBody:
+Block
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+StaticInitializer:
+jp_STATIC Block
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ConstructorDeclaration:
+Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody jp_SEMICOL
+{
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ConstructorDeclarator:
+SimpleName jp_PARESTART FormalParameterListopt jp_PAREEND
+{
+  jpElementStart(4);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ConstructorBody:
+jp_CURLYSTART ExplicitConstructorInvocationopt BlockStatementsopt jp_CURLYEND
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ExplicitConstructorInvocationopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ExplicitConstructorInvocationopt ExplicitConstructorInvocation
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ExplicitConstructorInvocation:
+jp_THIS jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL
+{
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_SUPER jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL
+{
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+InterfaceHeader:
+Modifiersopt jp_INTERFACE Identifier
+{
+  yyGetParser->StartClass($<str>3);
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&($<str>3));
+  jpCheckEmpty(3);
+}
+
+InterfaceDeclaration:
+InterfaceHeader ExtendsInterfacesopt InterfaceBody
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+  yyGetParser->EndClass();
+}
+
+ExtendsInterfacesopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+}
+|
+ExtendsInterfaces
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ExtendsInterfaces:
+jp_EXTENDS InterfaceType
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ExtendsInterfaces jp_COMMA InterfaceType
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+InterfaceBody:
+jp_CURLYSTART InterfaceMemberDeclarations jp_CURLYEND
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+InterfaceMemberDeclarations:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+InterfaceMemberDeclarations InterfaceMemberDeclaration
+{
+  jpElementStart(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+InterfaceMemberDeclaration:
+ConstantDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+AbstractMethodDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ClassDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ClassDeclaration jp_SEMICOL
+{
+  jpElementStart(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+InterfaceDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+InterfaceDeclaration jp_SEMICOL
+{
+  jpElementStart(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ConstantDeclaration:
+FieldDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+AbstractMethodDeclaration:
+MethodHeader Semicols
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Semicols:
+jp_SEMICOL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Semicols jp_SEMICOL
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ArrayInitializer:
+jp_CURLYSTART VariableInitializersOptional jp_CURLYEND
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+VariableInitializersOptional:
+{
+  jpElementStart(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+VariableInitializers
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+VariableInitializers jp_COMMA
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+VariableInitializers:
+VariableInitializer
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+VariableInitializers jp_COMMA VariableInitializer
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Block:
+jp_CURLYSTART BlockStatementsopt jp_CURLYEND
+{
+  jpElementStart(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+BlockStatementsopt:
+{
+  jpElementStart(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+BlockStatements
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+BlockStatements:
+BlockStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+BlockStatements BlockStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+BlockStatement:
+LocalVariableDeclarationStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Statement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ClassDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+LocalVariableDeclarationStatement:
+LocalVariableDeclaration jp_SEMICOL
+{
+  jpElementStart(1);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+LocalVariableDeclaration:
+Modifiers Type VariableDeclarators
+{
+  jpElementStart(1);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Type VariableDeclarators
+{
+  jpElementStart(1);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Statement:
+StatementWithoutTrailingSubstatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+LabeledStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+IfThenStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+IfThenElseStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+WhileStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ForStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+StatementNoShortIf:
+StatementWithoutTrailingSubstatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+LabeledStatementNoShortIf
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+IfThenElseStatementNoShortIf
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+WhileStatementNoShortIf
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ForStatementNoShortIf
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+StatementWithoutTrailingSubstatement:
+Block
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+EmptyStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ExpressionStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+SwitchStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+DoStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+BreakStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ContinueStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ReturnStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+SynchronizedStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ThrowStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+TryStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+AssertStatement
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+EmptyStatement:
+jp_SEMICOL
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+LabeledStatement:
+Identifier jp_COLON Statement
+{
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+LabeledStatementNoShortIf:
+Identifier jp_COLON StatementNoShortIf
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ExpressionStatement:
+StatementExpression jp_SEMICOL
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+StatementExpression:
+Assignment
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+PreIncrementExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+PreDecrementExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+PostIncrementExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+PostDecrementExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+MethodInvocation
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ClassInstanceCreationExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+IfThenStatement:
+jp_IF jp_PARESTART Expression jp_PAREEND Statement
+{
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+IfThenElseStatement:
+jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE Statement
+{
+  jpElementStart(7);
+  jpCheckEmpty(7);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+IfThenElseStatementNoShortIf:
+jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE StatementNoShortIf
+{
+  jpElementStart(7);
+  jpCheckEmpty(7);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+SwitchStatement:
+jp_SWITCH jp_PARESTART Expression jp_PAREEND SwitchBlock
+{
+  jpElementStart(5);
+
+}
+
+SwitchBlock:
+jp_CURLYSTART SwitchBlockStatementGroups SwitchLabelsopt jp_CURLYEND
+{
+  jpElementStart(4);
+
+}
+
+SwitchLabelsopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+SwitchLabels
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+SwitchBlockStatementGroups:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+SwitchBlockStatementGroups SwitchBlockStatementGroup
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+SwitchBlockStatementGroup:
+SwitchLabels BlockStatements
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+SwitchLabels:
+SwitchLabel
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+SwitchLabels SwitchLabel
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+SwitchLabel:
+jp_CASE ConstantExpression jp_COLON
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_DEFAULT jp_COLON
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+WhileStatement:
+jp_WHILE jp_PARESTART Expression jp_PAREEND Statement
+{
+  jpElementStart(5);
+
+}
+
+WhileStatementNoShortIf:
+jp_WHILE jp_PARESTART Expression jp_PAREEND StatementNoShortIf
+{
+  jpElementStart(5);
+
+}
+
+DoStatement:
+jp_DO Statement jp_WHILE jp_PARESTART Expression jp_PAREEND jp_SEMICOL
+{
+  jpElementStart(7);
+
+}
+
+ForStatement:
+jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND
+Statement
+{
+  jpElementStart(9);
+
+}
+
+ForUpdateopt:
+{
+  jpElementStart(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ForUpdate
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ForInitopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ForInit
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ForStatementNoShortIf:
+jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND
+StatementNoShortIf
+{
+  jpElementStart(9);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Expressionopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Expression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ForInit:
+StatementExpressionList
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+LocalVariableDeclaration
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ForUpdate:
+StatementExpressionList
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+StatementExpressionList:
+StatementExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+StatementExpressionList jp_COMMA StatementExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+AssertStatement:
+jp_ASSERT Expression jp_SEMICOL
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_ASSERT Expression jp_COLON Expression jp_SEMICOL
+{
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+BreakStatement:
+jp_BREAK Identifieropt jp_SEMICOL
+{
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&($<str>2));
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Identifieropt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Identifier
+{
+  jpElementStart(1);
+
+}
+
+ContinueStatement:
+jp_CONTINUE Identifieropt jp_SEMICOL
+{
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&($<str>2));
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ReturnStatement:
+jp_RETURN Expressionopt jp_SEMICOL
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ThrowStatement:
+jp_THROW Expression jp_SEMICOL
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+SynchronizedStatement:
+jp_SYNCHRONIZED jp_PARESTART Expression jp_PAREEND Block
+{
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+TryStatement:
+jp_TRY Block Catches
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_TRY Block Catchesopt Finally
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Catchesopt:
+{
+  jpElementStart(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Catches
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Catches:
+CatchClause
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Catches CatchClause
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+CatchClause:
+jp_CATCH jp_PARESTART FormalParameter jp_PAREEND Block
+{
+  jpElementStart(5);
+
+}
+
+Finally:
+jp_FINALLY Block
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Primary:
+PrimaryNoNewArray
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ArrayCreationExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+PrimaryNoNewArray:
+Literal
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_THIS
+{
+  jpElementStart(1);
+
+}
+|
+jp_PARESTART Expression jp_PAREEND
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ClassInstanceCreationExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+FieldAccess
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+MethodInvocation
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ArrayAccess
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ClassInstanceCreationExpression:
+New ClassType jp_PARESTART ArgumentListopt jp_PAREEND ClassBodyOpt
+{
+  jpElementStart(6);
+  jpCheckEmpty(6);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ClassBodyOpt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ClassBody
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ArgumentListopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ArgumentList
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ArgumentList:
+Expression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ArgumentList jp_COMMA Expression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ArrayCreationExpression:
+New PrimitiveType DimExprs Dimsopt
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+New ClassOrInterfaceType DimExprs Dimsopt
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+New PrimitiveType Dims ArrayInitializer
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+New ClassOrInterfaceType Dims ArrayInitializer
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Dimsopt:
+{
+  jpElementStart(0);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Dims
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+DimExprs:
+DimExpr
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+DimExprs DimExpr
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+DimExpr:
+jp_BRACKETSTART Expression jp_BRACKETEND
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Dims:
+jp_BRACKETSTART jp_BRACKETEND
+{
+  jpElementStart(2);
+
+}
+|
+Dims jp_BRACKETSTART jp_BRACKETEND
+{
+  jpElementStart(3);
+
+}
+
+FieldAccess:
+Primary jp_DOT Identifier
+{
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&($<str>3));
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_SUPER jp_DOT Identifier
+{
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&($<str>3));
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_THIS jp_DOT Identifier
+{
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&($<str>3));
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Primary jp_DOT jp_THIS
+{
+  jpElementStart(3);
+  yyGetParser->DeallocateParserType(&($<str>3));
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+MethodInvocation:
+Name jp_PARESTART ArgumentListopt jp_PAREEND
+{
+  jpElementStart(4);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Primary jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND
+{
+  jpElementStart(6);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  yyGetParser->DeallocateParserType(&($<str>3));
+  jpCheckEmpty(6);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_SUPER jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND
+{
+  jpElementStart(6);
+  yyGetParser->DeallocateParserType(&($<str>3));
+  jpCheckEmpty(6);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_THIS jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND
+{
+  jpElementStart(6);
+  yyGetParser->DeallocateParserType(&($<str>3));
+  jpCheckEmpty(6);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ArrayAccess:
+Name jp_BRACKETSTART Expression jp_BRACKETEND
+{
+  jpElementStart(4);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+PrimaryNoNewArray jp_BRACKETSTART Expression jp_BRACKETEND
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+PostfixExpression:
+Primary
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Name
+{
+  jpElementStart(1);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ArrayType jp_DOT jp_CLASS
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+PostIncrementExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+PostDecrementExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+PostIncrementExpression:
+PostfixExpression jp_PLUSPLUS
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+PostDecrementExpression:
+PostfixExpression jp_MINUSMINUS
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+UnaryExpression:
+PreIncrementExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+PreDecrementExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_PLUS UnaryExpression
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_MINUS UnaryExpression
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+UnaryExpressionNotPlusMinus
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+PreIncrementExpression:
+jp_PLUSPLUS UnaryExpression
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+PreDecrementExpression:
+jp_MINUSMINUS UnaryExpression
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+UnaryExpressionNotPlusMinus:
+PostfixExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_TILDE UnaryExpression
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_EXCLAMATION UnaryExpression
+{
+  jpElementStart(2);
+  jpCheckEmpty(2);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+CastExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+CastExpression:
+jp_PARESTART PrimitiveType Dimsopt jp_PAREEND UnaryExpression
+{
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_PARESTART Expression jp_PAREEND UnaryExpressionNotPlusMinus
+{
+  jpElementStart(4);
+  jpCheckEmpty(4);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_PARESTART Name Dims jp_PAREEND UnaryExpressionNotPlusMinus
+{
+  jpElementStart(5);
+
+}
+
+MultiplicativeExpression:
+UnaryExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+MultiplicativeExpression jp_TIMES UnaryExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+MultiplicativeExpression jp_DIVIDE UnaryExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+MultiplicativeExpression jp_PERCENT UnaryExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+AdditiveExpression:
+MultiplicativeExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+AdditiveExpression jp_PLUS MultiplicativeExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+AdditiveExpression jp_MINUS MultiplicativeExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ShiftExpression:
+AdditiveExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ShiftExpression jp_LTLT AdditiveExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ShiftExpression jp_GTGT AdditiveExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ShiftExpression jp_GTGTGT AdditiveExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+RelationalExpression:
+ShiftExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+RelationalExpression jp_LESSTHAN ShiftExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+RelationalExpression jp_GREATER ShiftExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+RelationalExpression jp_LTEQUALS ShiftExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+RelationalExpression jp_GTEQUALS ShiftExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+RelationalExpression jp_INSTANCEOF ReferenceType
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+EqualityExpression:
+RelationalExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+EqualityExpression jp_EQUALSEQUALS RelationalExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+EqualityExpression jp_EXCLAMATIONEQUALS RelationalExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+AndExpression:
+EqualityExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+AndExpression jp_AND EqualityExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ExclusiveOrExpression:
+AndExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ExclusiveOrExpression jp_CARROT AndExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+InclusiveOrExpression:
+ExclusiveOrExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+InclusiveOrExpression jp_PIPE ExclusiveOrExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ConditionalAndExpression:
+InclusiveOrExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ConditionalAndExpression jp_ANDAND InclusiveOrExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ConditionalOrExpression:
+ConditionalAndExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ConditionalOrExpression jp_PIPEPIPE ConditionalAndExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ConditionalExpression:
+ConditionalOrExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ConditionalOrExpression jp_QUESTION Expression jp_COLON ConditionalExpression
+{
+  jpElementStart(5);
+  jpCheckEmpty(5);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+AssignmentExpression:
+ConditionalExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Assignment
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Assignment:
+LeftHandSide AssignmentOperator AssignmentExpression
+{
+  jpElementStart(3);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+LeftHandSide:
+Name
+{
+  jpElementStart(1);
+  yyGetParser->DeallocateParserType(&($<str>1));
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+FieldAccess
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+ArrayAccess
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+AssignmentOperator:
+jp_EQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_TIMESEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_DIVIDEEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_PERCENTEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_PLUSEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_MINUSEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_LESLESEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_GTGTEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_GTGTGTEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_ANDEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_CARROTEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+jp_PIPEEQUALS
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+Expression:
+AssignmentExpression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+ConstantExpression:
+Expression
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+New:
+jp_NEW
+{
+  jpElementStart(1);
+  jpCheckEmpty(1);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+|
+Name jp_DOT jp_NEW
+{
+  jpElementStart(3);
+  jpStoreClass($<str>1);
+  jpCheckEmpty(3);
+  $<str>$ = 0;
+  yyGetParser->SetCurrentCombine("");
+
+}
+
+%%
+/* End of grammar */
+
+/*--------------------------------------------------------------------------*/
+void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message)
+{
+  yyGetParser->Error(message);
+}
diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h
new file mode 100644
index 0000000..7f18f1d
--- /dev/null
+++ b/Source/LexerParser/cmDependsJavaParserTokens.h
@@ -0,0 +1,264 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
+# define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmDependsJava_yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    jp_ABSTRACT = 258,
+    jp_ASSERT = 259,
+    jp_BOOLEAN_TYPE = 260,
+    jp_BREAK = 261,
+    jp_BYTE_TYPE = 262,
+    jp_CASE = 263,
+    jp_CATCH = 264,
+    jp_CHAR_TYPE = 265,
+    jp_CLASS = 266,
+    jp_CONTINUE = 267,
+    jp_DEFAULT = 268,
+    jp_DO = 269,
+    jp_DOUBLE_TYPE = 270,
+    jp_ELSE = 271,
+    jp_EXTENDS = 272,
+    jp_FINAL = 273,
+    jp_FINALLY = 274,
+    jp_FLOAT_TYPE = 275,
+    jp_FOR = 276,
+    jp_IF = 277,
+    jp_IMPLEMENTS = 278,
+    jp_IMPORT = 279,
+    jp_INSTANCEOF = 280,
+    jp_INT_TYPE = 281,
+    jp_INTERFACE = 282,
+    jp_LONG_TYPE = 283,
+    jp_NATIVE = 284,
+    jp_NEW = 285,
+    jp_PACKAGE = 286,
+    jp_PRIVATE = 287,
+    jp_PROTECTED = 288,
+    jp_PUBLIC = 289,
+    jp_RETURN = 290,
+    jp_SHORT_TYPE = 291,
+    jp_STATIC = 292,
+    jp_STRICTFP = 293,
+    jp_SUPER = 294,
+    jp_SWITCH = 295,
+    jp_SYNCHRONIZED = 296,
+    jp_THIS = 297,
+    jp_THROW = 298,
+    jp_THROWS = 299,
+    jp_TRANSIENT = 300,
+    jp_TRY = 301,
+    jp_VOID = 302,
+    jp_VOLATILE = 303,
+    jp_WHILE = 304,
+    jp_BOOLEANLITERAL = 305,
+    jp_CHARACTERLITERAL = 306,
+    jp_DECIMALINTEGERLITERAL = 307,
+    jp_FLOATINGPOINTLITERAL = 308,
+    jp_HEXINTEGERLITERAL = 309,
+    jp_NULLLITERAL = 310,
+    jp_STRINGLITERAL = 311,
+    jp_NAME = 312,
+    jp_AND = 313,
+    jp_ANDAND = 314,
+    jp_ANDEQUALS = 315,
+    jp_BRACKETEND = 316,
+    jp_BRACKETSTART = 317,
+    jp_CARROT = 318,
+    jp_CARROTEQUALS = 319,
+    jp_COLON = 320,
+    jp_COMMA = 321,
+    jp_CURLYEND = 322,
+    jp_CURLYSTART = 323,
+    jp_DIVIDE = 324,
+    jp_DIVIDEEQUALS = 325,
+    jp_DOLLAR = 326,
+    jp_DOT = 327,
+    jp_EQUALS = 328,
+    jp_EQUALSEQUALS = 329,
+    jp_EXCLAMATION = 330,
+    jp_EXCLAMATIONEQUALS = 331,
+    jp_GREATER = 332,
+    jp_GTEQUALS = 333,
+    jp_GTGT = 334,
+    jp_GTGTEQUALS = 335,
+    jp_GTGTGT = 336,
+    jp_GTGTGTEQUALS = 337,
+    jp_LESLESEQUALS = 338,
+    jp_LESSTHAN = 339,
+    jp_LTEQUALS = 340,
+    jp_LTLT = 341,
+    jp_MINUS = 342,
+    jp_MINUSEQUALS = 343,
+    jp_MINUSMINUS = 344,
+    jp_PAREEND = 345,
+    jp_PARESTART = 346,
+    jp_PERCENT = 347,
+    jp_PERCENTEQUALS = 348,
+    jp_PIPE = 349,
+    jp_PIPEEQUALS = 350,
+    jp_PIPEPIPE = 351,
+    jp_PLUS = 352,
+    jp_PLUSEQUALS = 353,
+    jp_PLUSPLUS = 354,
+    jp_QUESTION = 355,
+    jp_SEMICOL = 356,
+    jp_TILDE = 357,
+    jp_TIMES = 358,
+    jp_TIMESEQUALS = 359,
+    jp_ERROR = 360
+  };
+#endif
+/* Tokens.  */
+#define jp_ABSTRACT 258
+#define jp_ASSERT 259
+#define jp_BOOLEAN_TYPE 260
+#define jp_BREAK 261
+#define jp_BYTE_TYPE 262
+#define jp_CASE 263
+#define jp_CATCH 264
+#define jp_CHAR_TYPE 265
+#define jp_CLASS 266
+#define jp_CONTINUE 267
+#define jp_DEFAULT 268
+#define jp_DO 269
+#define jp_DOUBLE_TYPE 270
+#define jp_ELSE 271
+#define jp_EXTENDS 272
+#define jp_FINAL 273
+#define jp_FINALLY 274
+#define jp_FLOAT_TYPE 275
+#define jp_FOR 276
+#define jp_IF 277
+#define jp_IMPLEMENTS 278
+#define jp_IMPORT 279
+#define jp_INSTANCEOF 280
+#define jp_INT_TYPE 281
+#define jp_INTERFACE 282
+#define jp_LONG_TYPE 283
+#define jp_NATIVE 284
+#define jp_NEW 285
+#define jp_PACKAGE 286
+#define jp_PRIVATE 287
+#define jp_PROTECTED 288
+#define jp_PUBLIC 289
+#define jp_RETURN 290
+#define jp_SHORT_TYPE 291
+#define jp_STATIC 292
+#define jp_STRICTFP 293
+#define jp_SUPER 294
+#define jp_SWITCH 295
+#define jp_SYNCHRONIZED 296
+#define jp_THIS 297
+#define jp_THROW 298
+#define jp_THROWS 299
+#define jp_TRANSIENT 300
+#define jp_TRY 301
+#define jp_VOID 302
+#define jp_VOLATILE 303
+#define jp_WHILE 304
+#define jp_BOOLEANLITERAL 305
+#define jp_CHARACTERLITERAL 306
+#define jp_DECIMALINTEGERLITERAL 307
+#define jp_FLOATINGPOINTLITERAL 308
+#define jp_HEXINTEGERLITERAL 309
+#define jp_NULLLITERAL 310
+#define jp_STRINGLITERAL 311
+#define jp_NAME 312
+#define jp_AND 313
+#define jp_ANDAND 314
+#define jp_ANDEQUALS 315
+#define jp_BRACKETEND 316
+#define jp_BRACKETSTART 317
+#define jp_CARROT 318
+#define jp_CARROTEQUALS 319
+#define jp_COLON 320
+#define jp_COMMA 321
+#define jp_CURLYEND 322
+#define jp_CURLYSTART 323
+#define jp_DIVIDE 324
+#define jp_DIVIDEEQUALS 325
+#define jp_DOLLAR 326
+#define jp_DOT 327
+#define jp_EQUALS 328
+#define jp_EQUALSEQUALS 329
+#define jp_EXCLAMATION 330
+#define jp_EXCLAMATIONEQUALS 331
+#define jp_GREATER 332
+#define jp_GTEQUALS 333
+#define jp_GTGT 334
+#define jp_GTGTEQUALS 335
+#define jp_GTGTGT 336
+#define jp_GTGTGTEQUALS 337
+#define jp_LESLESEQUALS 338
+#define jp_LESSTHAN 339
+#define jp_LTEQUALS 340
+#define jp_LTLT 341
+#define jp_MINUS 342
+#define jp_MINUSEQUALS 343
+#define jp_MINUSMINUS 344
+#define jp_PAREEND 345
+#define jp_PARESTART 346
+#define jp_PERCENT 347
+#define jp_PERCENTEQUALS 348
+#define jp_PIPE 349
+#define jp_PIPEEQUALS 350
+#define jp_PIPEPIPE 351
+#define jp_PLUS 352
+#define jp_PLUSEQUALS 353
+#define jp_PLUSPLUS 354
+#define jp_QUESTION 355
+#define jp_SEMICOL 356
+#define jp_TILDE 357
+#define jp_TIMES 358
+#define jp_TIMESEQUALS 359
+#define jp_ERROR 360
+
+/* Value type.  */
+
+
+
+int cmDependsJava_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED  */
diff --git a/Source/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx
similarity index 100%
rename from Source/cmExprLexer.cxx
rename to Source/LexerParser/cmExprLexer.cxx
diff --git a/Source/cmExprLexer.h b/Source/LexerParser/cmExprLexer.h
similarity index 100%
rename from Source/cmExprLexer.h
rename to Source/LexerParser/cmExprLexer.h
diff --git a/Source/cmExprLexer.in.l b/Source/LexerParser/cmExprLexer.in.l
similarity index 100%
rename from Source/cmExprLexer.in.l
rename to Source/LexerParser/cmExprLexer.in.l
diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx
new file mode 100644
index 0000000..67664a5
--- /dev/null
+++ b/Source/LexerParser/cmExprParser.cxx
@@ -0,0 +1,1698 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names.  */
+#define yyparse         cmExpr_yyparse
+#define yylex           cmExpr_yylex
+#define yyerror         cmExpr_yyerror
+#define yydebug         cmExpr_yydebug
+#define yynerrs         cmExpr_yynerrs
+
+
+/* Copy the first part of user declarations.  */
+#line 1 "cmExprParser.y" /* yacc.c:339  */
+
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+  bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
+
+Modify cmExprParser.cxx:
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stdlib.h>
+#include <string.h>
+
+/*-------------------------------------------------------------------------*/
+#define YYDEBUG 1
+#include "cmExprParserHelper.h" /* Interface to parser object.  */
+#include "cmExprLexer.h"  /* Interface to lexer object.  */
+#include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
+
+/* Forward declare the lexer entry point.  */
+YY_DECL;
+
+/* Helper function to forward error callback from parser.  */
+static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
+
+/* Disable some warnings in the generated code.  */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label.  */
+# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
+#endif
+
+#line 112 "cmExprParser.cxx" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "cmExprParserTokens.h".  */
+#ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
+# define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmExpr_yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    exp_PLUS = 258,
+    exp_MINUS = 259,
+    exp_TIMES = 260,
+    exp_DIVIDE = 261,
+    exp_MOD = 262,
+    exp_SHIFTLEFT = 263,
+    exp_SHIFTRIGHT = 264,
+    exp_OPENPARENT = 265,
+    exp_CLOSEPARENT = 266,
+    exp_OR = 267,
+    exp_AND = 268,
+    exp_XOR = 269,
+    exp_NOT = 270,
+    exp_NUMBER = 271
+  };
+#endif
+/* Tokens.  */
+#define exp_PLUS 258
+#define exp_MINUS 259
+#define exp_TIMES 260
+#define exp_DIVIDE 261
+#define exp_MOD 262
+#define exp_SHIFTLEFT 263
+#define exp_SHIFTRIGHT 264
+#define exp_OPENPARENT 265
+#define exp_CLOSEPARENT 266
+#define exp_OR 267
+#define exp_AND 268
+#define exp_XOR 269
+#define exp_NOT 270
+#define exp_NUMBER 271
+
+/* Value type.  */
+
+
+
+int cmExpr_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 189 "cmExprParser.cxx" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  17
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   30
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  17
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  10
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  23
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  39
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   271
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint8 yyrline[] =
+{
+       0,    73,    73,    78,    81,    86,    89,    94,    97,   102,
+     105,   108,   113,   116,   119,   124,   127,   130,   133,   138,
+     141,   144,   149,   152
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "exp_PLUS", "exp_MINUS", "exp_TIMES",
+  "exp_DIVIDE", "exp_MOD", "exp_SHIFTLEFT", "exp_SHIFTRIGHT",
+  "exp_OPENPARENT", "exp_CLOSEPARENT", "exp_OR", "exp_AND", "exp_XOR",
+  "exp_NOT", "exp_NUMBER", "$accept", "start", "exp", "bitwiseor",
+  "bitwisexor", "bitwiseand", "shift", "term", "unary", "factor", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271
+};
+# endif
+
+#define YYPACT_NINF -8
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-8)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int8 yypact[] =
+{
+       0,     0,     0,     0,    -8,     2,    -7,    -5,     8,     3,
+      10,     1,    -8,    -8,    -8,    -8,     6,    -8,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    -8,    -5,
+       8,     3,    10,    10,     1,     1,    -8,    -8,    -8
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       0,     0,     0,     0,    22,     0,     2,     3,     5,     7,
+       9,    12,    15,    19,    20,    21,     0,     1,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    23,     4,
+       6,     8,    10,    11,    13,    14,    16,    17,    18
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+      -8,    -8,    12,     5,    11,     9,    -2,     4,    -1,    -8
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     5,     6,     7,     8,     9,    10,    11,    12,    13
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+      14,    15,    17,     1,     2,    18,    25,    26,    27,    19,
+       3,    21,    22,    23,    24,    16,     4,    28,    18,    32,
+      33,    20,     0,    29,    36,    37,    38,    34,    35,    31,
+      30
+};
+
+static const yytype_int8 yycheck[] =
+{
+       1,     2,     0,     3,     4,    12,     5,     6,     7,    14,
+      10,     8,     9,     3,     4,     3,    16,    11,    12,    21,
+      22,    13,    -1,    18,    25,    26,    27,    23,    24,    20,
+      19
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     3,     4,    10,    16,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    25,    25,    19,     0,    12,    14,
+      13,     8,     9,     3,     4,     5,     6,     7,    11,    20,
+      21,    22,    23,    23,    24,    24,    25,    25,    25
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    17,    18,    19,    19,    20,    20,    21,    21,    22,
+      22,    22,    23,    23,    23,    24,    24,    24,    24,    25,
+      25,    25,    26,    26
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     1,     3,     1,     3,     1,     3,     1,
+       3,     3,     1,     3,     3,     1,     3,     3,     3,     1,
+       2,     2,     1,     3
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, yyscanner); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (yyscanner);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , yyscanner);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
+{
+  YYUSE (yyvaluep);
+  YYUSE (yyscanner);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (yyscan_t yyscanner)
+{
+/* The lookahead symbol.  */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol.  */
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex (&yylval, yyscanner);
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 73 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
+  }
+#line 1289 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 3:
+#line 78 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[0].Number);
+  }
+#line 1297 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 4:
+#line 81 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
+  }
+#line 1305 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 5:
+#line 86 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[0].Number);
+  }
+#line 1313 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 6:
+#line 89 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
+  }
+#line 1321 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 7:
+#line 94 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[0].Number);
+  }
+#line 1329 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 97 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
+  }
+#line 1337 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 102 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[0].Number);
+  }
+#line 1345 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 105 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
+  }
+#line 1353 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 108 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
+  }
+#line 1361 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 12:
+#line 113 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[0].Number);
+  }
+#line 1369 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 13:
+#line 116 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
+  }
+#line 1377 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 14:
+#line 119 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
+  }
+#line 1385 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 15:
+#line 124 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[0].Number);
+  }
+#line 1393 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 16:
+#line 127 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
+  }
+#line 1401 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 17:
+#line 130 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
+  }
+#line 1409 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 18:
+#line 133 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
+  }
+#line 1417 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 19:
+#line 138 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[0].Number);
+  }
+#line 1425 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 20:
+#line 141 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = + (yyvsp[0].Number);
+  }
+#line 1433 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 21:
+#line 144 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = - (yyvsp[0].Number);
+  }
+#line 1441 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 22:
+#line 149 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[0].Number);
+  }
+#line 1449 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 23:
+#line 152 "cmExprParser.y" /* yacc.c:1646  */
+    {
+    (yyval.Number) = (yyvsp[-1].Number);
+  }
+#line 1457 "cmExprParser.cxx" /* yacc.c:1646  */
+    break;
+
+
+#line 1461 "cmExprParser.cxx" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (yyscanner, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (yyscanner, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, yyscanner);
+          yychar = YYEMPTY;
+        }
+    }
+
+#if 0
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+#endif
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, yyscanner);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (yyscanner, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, yyscanner);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp, yyscanner);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
+#line 157 "cmExprParser.y" /* yacc.c:1906  */
+
+/* End of grammar */
+
+/*--------------------------------------------------------------------------*/
+void cmExpr_yyerror(yyscan_t yyscanner, const char* message)
+{
+  cmExpr_yyget_extra(yyscanner)->Error(message);
+}
diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y
new file mode 100644
index 0000000..d1c3a97
--- /dev/null
+++ b/Source/LexerParser/cmExprParser.y
@@ -0,0 +1,164 @@
+%{
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+  bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
+
+Modify cmExprParser.cxx:
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <stdlib.h>
+#include <string.h>
+
+/*-------------------------------------------------------------------------*/
+#define YYDEBUG 1
+#include "cmExprParserHelper.h" /* Interface to parser object.  */
+#include "cmExprLexer.h"  /* Interface to lexer object.  */
+#include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
+
+/* Forward declare the lexer entry point.  */
+YY_DECL;
+
+/* Helper function to forward error callback from parser.  */
+static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
+
+/* Disable some warnings in the generated code.  */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label.  */
+# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
+#endif
+%}
+
+/* Generate a reentrant parser object.  */
+%define api.pure
+
+/* Configure the parser to use a lexer object.  */
+%lex-param   {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
+
+%define parse.error verbose
+
+/*-------------------------------------------------------------------------*/
+/* Tokens */
+%token exp_PLUS
+%token exp_MINUS
+%token exp_TIMES
+%token exp_DIVIDE
+%token exp_MOD
+%token exp_SHIFTLEFT
+%token exp_SHIFTRIGHT
+%token exp_OPENPARENT
+%token exp_CLOSEPARENT
+%token exp_OR;
+%token exp_AND;
+%token exp_XOR;
+%token exp_NOT;
+%token exp_NUMBER;
+
+/*-------------------------------------------------------------------------*/
+/* grammar */
+%%
+
+
+start:
+  exp {
+    cmExpr_yyget_extra(yyscanner)->SetResult($<Number>1);
+  }
+
+exp:
+  bitwiseor {
+    $<Number>$ = $<Number>1;
+  }
+| exp exp_OR bitwiseor {
+    $<Number>$ = $<Number>1 | $<Number>3;
+  }
+
+bitwiseor:
+  bitwisexor {
+    $<Number>$ = $<Number>1;
+  }
+| bitwiseor exp_XOR bitwisexor {
+    $<Number>$ = $<Number>1 ^ $<Number>3;
+  }
+
+bitwisexor:
+  bitwiseand {
+    $<Number>$ = $<Number>1;
+  }
+| bitwisexor exp_AND bitwiseand {
+    $<Number>$ = $<Number>1 & $<Number>3;
+  }
+
+bitwiseand:
+  shift {
+    $<Number>$ = $<Number>1;
+  }
+| bitwiseand exp_SHIFTLEFT shift {
+    $<Number>$ = $<Number>1 << $<Number>3;
+  }
+| bitwiseand exp_SHIFTRIGHT shift {
+    $<Number>$ = $<Number>1 >> $<Number>3;
+  }
+
+shift:
+  term {
+    $<Number>$ = $<Number>1;
+  }
+| shift exp_PLUS term {
+    $<Number>$ = $<Number>1 + $<Number>3;
+  }
+| shift exp_MINUS term {
+    $<Number>$ = $<Number>1 - $<Number>3;
+  }
+
+term:
+  unary {
+    $<Number>$ = $<Number>1;
+  }
+| term exp_TIMES unary {
+    $<Number>$ = $<Number>1 * $<Number>3;
+  }
+| term exp_DIVIDE unary {
+    $<Number>$ = $<Number>1 / $<Number>3;
+  }
+| term exp_MOD unary {
+    $<Number>$ = $<Number>1 % $<Number>3;
+  }
+
+unary:
+  factor {
+    $<Number>$ = $<Number>1;
+  }
+| exp_PLUS unary {
+    $<Number>$ = + $<Number>2;
+  }
+| exp_MINUS unary {
+    $<Number>$ = - $<Number>2;
+  }
+
+factor:
+  exp_NUMBER {
+    $<Number>$ = $<Number>1;
+  }
+| exp_OPENPARENT exp exp_CLOSEPARENT {
+    $<Number>$ = $<Number>2;
+  }
+;
+
+%%
+/* End of grammar */
+
+/*--------------------------------------------------------------------------*/
+void cmExpr_yyerror(yyscan_t yyscanner, const char* message)
+{
+  cmExpr_yyget_extra(yyscanner)->Error(message);
+}
diff --git a/Source/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h
similarity index 100%
rename from Source/cmExprParserTokens.h
rename to Source/LexerParser/cmExprParserTokens.h
diff --git a/Source/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx
similarity index 100%
rename from Source/cmFortranLexer.cxx
rename to Source/LexerParser/cmFortranLexer.cxx
diff --git a/Source/cmFortranLexer.h b/Source/LexerParser/cmFortranLexer.h
similarity index 100%
rename from Source/cmFortranLexer.h
rename to Source/LexerParser/cmFortranLexer.h
diff --git a/Source/cmFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l
similarity index 100%
rename from Source/cmFortranLexer.in.l
rename to Source/LexerParser/cmFortranLexer.in.l
diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
new file mode 100644
index 0000000..2b3452f
--- /dev/null
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -0,0 +1,1988 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names.  */
+#define yyparse         cmFortran_yyparse
+#define yylex           cmFortran_yylex
+#define yyerror         cmFortran_yyerror
+#define yydebug         cmFortran_yydebug
+#define yynerrs         cmFortran_yynerrs
+
+
+/* Copy the first part of user declarations.  */
+#line 1 "cmFortranParser.y" /* yacc.c:339  */
+
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*-------------------------------------------------------------------------
+  Portions of this source have been derived from makedepf90 version 2.8.8,
+
+   Copyright (C) 2000--2006 Erik Edelmann <erik.edelmann at iki.fi>
+
+  The code was originally distributed under the GPL but permission
+  from the copyright holder has been obtained to distribute this
+  derived work under the CMake license.
+-------------------------------------------------------------------------*/
+
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+  bison --yacc --name-prefix=cmFortran_yy
+        --defines=cmFortranParserTokens.h
+         -ocmFortranParser.cxx
+          cmFortranParser.y
+
+Modify cmFortranParser.cxx:
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmsys/String.h"
+#include <stdlib.h>
+#include <string.h>
+
+/*-------------------------------------------------------------------------*/
+#define cmFortranParser_cxx
+#include "cmFortranParser.h" /* Interface to parser object.  */
+#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
+
+/* Forward declare the lexer entry point.  */
+YY_DECL;
+
+/* Helper function to forward error callback from parser.  */
+static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
+{
+  cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+  cmFortranParser_Error(parser, message);
+}
+
+/* Disable some warnings in the generated code.  */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label.  */
+# pragma warning (disable: 4065) /* Switch contains default but no case. */
+# pragma warning (disable: 4701) /* Local variable may not be initialized.  */
+# pragma warning (disable: 4702) /* Unreachable code.  */
+# pragma warning (disable: 4127) /* Conditional expression is constant.  */
+# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
+#endif
+
+#line 132 "cmFortranParser.cxx" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "cmFortranParserTokens.h".  */
+#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
+# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmFortran_yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    EOSTMT = 258,
+    ASSIGNMENT_OP = 259,
+    GARBAGE = 260,
+    CPP_LINE_DIRECTIVE = 261,
+    CPP_INCLUDE = 262,
+    F90PPR_INCLUDE = 263,
+    COCO_INCLUDE = 264,
+    F90PPR_DEFINE = 265,
+    CPP_DEFINE = 266,
+    F90PPR_UNDEF = 267,
+    CPP_UNDEF = 268,
+    CPP_IFDEF = 269,
+    CPP_IFNDEF = 270,
+    CPP_IF = 271,
+    CPP_ELSE = 272,
+    CPP_ELIF = 273,
+    CPP_ENDIF = 274,
+    F90PPR_IFDEF = 275,
+    F90PPR_IFNDEF = 276,
+    F90PPR_IF = 277,
+    F90PPR_ELSE = 278,
+    F90PPR_ELIF = 279,
+    F90PPR_ENDIF = 280,
+    COMMA = 281,
+    COLON = 282,
+    DCOLON = 283,
+    LPAREN = 284,
+    RPAREN = 285,
+    UNTERMINATED_STRING = 286,
+    STRING = 287,
+    WORD = 288,
+    CPP_INCLUDE_ANGLE = 289,
+    END = 290,
+    INCLUDE = 291,
+    INTERFACE = 292,
+    MODULE = 293,
+    SUBMODULE = 294,
+    USE = 295
+  };
+#endif
+/* Tokens.  */
+#define EOSTMT 258
+#define ASSIGNMENT_OP 259
+#define GARBAGE 260
+#define CPP_LINE_DIRECTIVE 261
+#define CPP_INCLUDE 262
+#define F90PPR_INCLUDE 263
+#define COCO_INCLUDE 264
+#define F90PPR_DEFINE 265
+#define CPP_DEFINE 266
+#define F90PPR_UNDEF 267
+#define CPP_UNDEF 268
+#define CPP_IFDEF 269
+#define CPP_IFNDEF 270
+#define CPP_IF 271
+#define CPP_ELSE 272
+#define CPP_ELIF 273
+#define CPP_ENDIF 274
+#define F90PPR_IFDEF 275
+#define F90PPR_IFNDEF 276
+#define F90PPR_IF 277
+#define F90PPR_ELSE 278
+#define F90PPR_ELIF 279
+#define F90PPR_ENDIF 280
+#define COMMA 281
+#define COLON 282
+#define DCOLON 283
+#define LPAREN 284
+#define RPAREN 285
+#define UNTERMINATED_STRING 286
+#define STRING 287
+#define WORD 288
+#define CPP_INCLUDE_ANGLE 289
+#define END 290
+#define INCLUDE 291
+#define INTERFACE 292
+#define MODULE 293
+#define SUBMODULE 294
+#define USE 295
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 70 "cmFortranParser.y" /* yacc.c:355  */
+
+  char* string;
+
+#line 256 "cmFortranParser.cxx" /* yacc.c:355  */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int cmFortran_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 272 "cmFortranParser.cxx" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  2
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   593
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  41
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  14
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  63
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  126
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   295
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint8 yyrline[] =
+{
+       0,    98,    98,    98,   101,   105,   110,   119,   125,   132,
+     137,   141,   146,   154,   159,   164,   169,   174,   179,   184,
+     189,   194,   198,   202,   206,   210,   211,   216,   216,   216,
+     217,   217,   218,   218,   219,   219,   220,   220,   221,   221,
+     222,   222,   223,   223,   224,   224,   225,   225,   228,   229,
+     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
+     240,   241,   242,   243
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "EOSTMT", "ASSIGNMENT_OP", "GARBAGE",
+  "CPP_LINE_DIRECTIVE", "CPP_INCLUDE", "F90PPR_INCLUDE", "COCO_INCLUDE",
+  "F90PPR_DEFINE", "CPP_DEFINE", "F90PPR_UNDEF", "CPP_UNDEF", "CPP_IFDEF",
+  "CPP_IFNDEF", "CPP_IF", "CPP_ELSE", "CPP_ELIF", "CPP_ENDIF",
+  "F90PPR_IFDEF", "F90PPR_IFNDEF", "F90PPR_IF", "F90PPR_ELSE",
+  "F90PPR_ELIF", "F90PPR_ENDIF", "COMMA", "COLON", "DCOLON", "LPAREN",
+  "RPAREN", "UNTERMINATED_STRING", "STRING", "WORD", "CPP_INCLUDE_ANGLE",
+  "END", "INCLUDE", "INTERFACE", "MODULE", "SUBMODULE", "USE", "$accept",
+  "code", "stmt", "include", "define", "undef", "ifdef", "ifndef", "if",
+  "elif", "else", "endif", "other", "misc_code", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295
+};
+# endif
+
+#define YYPACT_NINF -39
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-39)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int16 yypact[] =
+{
+     -39,    21,   -39,     1,   -39,   -20,   -39,   -39,   -39,   -39,
+     -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,
+     -39,   -39,   -39,   -39,   -39,   -39,   -24,   -18,    20,    -8,
+      -3,    39,   -39,    15,    16,    18,    19,    33,   -39,   -39,
+     -39,   -39,   -39,   -39,    59,   -39,   -39,   -39,   -39,   -39,
+      35,    36,    37,   -39,   -39,   -39,   -39,   -39,   -39,    76,
+     114,   129,   167,   182,   -39,   -39,   -39,   -39,   -39,   -39,
+     -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,
+     -39,   -39,   220,   235,   273,   288,   -21,    26,   -39,   326,
+     341,   379,   394,   432,   447,   -39,   -39,   -39,   -39,   -39,
+     -39,   -39,   -39,   -39,    38,    40,    41,   485,   -39,   -39,
+     -39,   -39,   -39,   -39,    45,   -39,   -39,   -39,    43,   500,
+     538,   -39,   -39,   -39,   553,   -39
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       2,     0,     1,     0,    25,     0,    27,    28,    29,    31,
+      30,    33,    32,    34,    36,    38,    42,    40,    44,    35,
+      37,    39,    43,    41,    45,    46,     0,     0,     0,     0,
+       0,     0,     3,     0,     0,     0,     0,     0,    46,    46,
+      46,    46,    26,    46,     0,    46,    46,     4,    46,    46,
+       0,     0,     0,    46,    46,    46,    46,    46,    46,     0,
+       0,     0,     0,     0,    15,    57,    56,    62,    58,    59,
+      60,    61,    63,    55,    48,    49,    50,    51,    52,    53,
+      54,    47,     0,     0,     0,     0,     0,     0,    46,     0,
+       0,     0,     0,     0,     0,    21,    22,    23,    24,    14,
+      10,    13,     9,     6,     0,     0,     0,     0,     5,    16,
+      17,    18,    19,    20,     0,    46,    46,    11,     0,     0,
+       0,    46,     7,    12,     0,     8
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,
+     -39,   -39,   -38,   -39
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     1,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    44,    81
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+      59,    60,    61,    62,    42,    63,   104,    82,    83,   105,
+      84,    85,    43,    45,    46,    89,    90,    91,    92,    93,
+      94,     2,     3,    47,     4,    49,    50,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    54,     0,    55,
+     107,    56,    57,    48,   106,    25,    26,    27,    28,    29,
+      30,    31,    64,    65,    66,    51,    58,    52,    86,    87,
+      88,   114,    53,   115,   116,   118,   121,   119,   120,    95,
+      65,    66,     0,   124,     0,    67,    68,    69,    70,    71,
+      72,    73,    74,     0,    75,    76,    77,    78,    79,    80,
+       0,     0,    67,    68,    69,    70,    71,    72,    73,    74,
+       0,    75,    76,    77,    78,    79,    80,    96,    65,    66,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    97,    65,    66,     0,     0,     0,     0,     0,
+      67,    68,    69,    70,    71,    72,    73,    74,     0,    75,
+      76,    77,    78,    79,    80,    67,    68,    69,    70,    71,
+      72,    73,    74,     0,    75,    76,    77,    78,    79,    80,
+      98,    65,    66,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    99,    65,    66,     0,     0,
+       0,     0,     0,    67,    68,    69,    70,    71,    72,    73,
+      74,     0,    75,    76,    77,    78,    79,    80,    67,    68,
+      69,    70,    71,    72,    73,    74,     0,    75,    76,    77,
+      78,    79,    80,   100,    65,    66,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   101,    65,
+      66,     0,     0,     0,     0,     0,    67,    68,    69,    70,
+      71,    72,    73,    74,     0,    75,    76,    77,    78,    79,
+      80,    67,    68,    69,    70,    71,    72,    73,    74,     0,
+      75,    76,    77,    78,    79,    80,   102,    65,    66,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   103,    65,    66,     0,     0,     0,     0,     0,    67,
+      68,    69,    70,    71,    72,    73,    74,     0,    75,    76,
+      77,    78,    79,    80,    67,    68,    69,    70,    71,    72,
+      73,    74,     0,    75,    76,    77,    78,    79,    80,   108,
+      65,    66,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   109,    65,    66,     0,     0,     0,
+       0,     0,    67,    68,    69,    70,    71,    72,    73,    74,
+       0,    75,    76,    77,    78,    79,    80,    67,    68,    69,
+      70,    71,    72,    73,    74,     0,    75,    76,    77,    78,
+      79,    80,   110,    65,    66,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   111,    65,    66,
+       0,     0,     0,     0,     0,    67,    68,    69,    70,    71,
+      72,    73,    74,     0,    75,    76,    77,    78,    79,    80,
+      67,    68,    69,    70,    71,    72,    73,    74,     0,    75,
+      76,    77,    78,    79,    80,   112,    65,    66,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     113,    65,    66,     0,     0,     0,     0,     0,    67,    68,
+      69,    70,    71,    72,    73,    74,     0,    75,    76,    77,
+      78,    79,    80,    67,    68,    69,    70,    71,    72,    73,
+      74,     0,    75,    76,    77,    78,    79,    80,   117,    65,
+      66,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   122,    65,    66,     0,     0,     0,     0,
+       0,    67,    68,    69,    70,    71,    72,    73,    74,     0,
+      75,    76,    77,    78,    79,    80,    67,    68,    69,    70,
+      71,    72,    73,    74,     0,    75,    76,    77,    78,    79,
+      80,   123,    65,    66,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   125,    65,    66,     0,
+       0,     0,     0,     0,    67,    68,    69,    70,    71,    72,
+      73,    74,     0,    75,    76,    77,    78,    79,    80,    67,
+      68,    69,    70,    71,    72,    73,    74,     0,    75,    76,
+      77,    78,    79,    80
+};
+
+static const yytype_int8 yycheck[] =
+{
+      38,    39,    40,    41,     3,    43,    27,    45,    46,    30,
+      48,    49,    32,    37,    32,    53,    54,    55,    56,    57,
+      58,     0,     1,     3,     3,    33,    29,     6,     7,     8,
+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    32,    -1,    33,
+      88,    33,    33,    33,    28,    34,    35,    36,    37,    38,
+      39,    40,     3,     4,     5,    26,    33,    28,    33,    33,
+      33,    33,    33,    33,    33,    30,    33,   115,   116,     3,
+       4,     5,    -1,   121,    -1,    26,    27,    28,    29,    30,
+      31,    32,    33,    -1,    35,    36,    37,    38,    39,    40,
+      -1,    -1,    26,    27,    28,    29,    30,    31,    32,    33,
+      -1,    35,    36,    37,    38,    39,    40,     3,     4,     5,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,     3,     4,     5,    -1,    -1,    -1,    -1,    -1,
+      26,    27,    28,    29,    30,    31,    32,    33,    -1,    35,
+      36,    37,    38,    39,    40,    26,    27,    28,    29,    30,
+      31,    32,    33,    -1,    35,    36,    37,    38,    39,    40,
+       3,     4,     5,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,     3,     4,     5,    -1,    -1,
+      -1,    -1,    -1,    26,    27,    28,    29,    30,    31,    32,
+      33,    -1,    35,    36,    37,    38,    39,    40,    26,    27,
+      28,    29,    30,    31,    32,    33,    -1,    35,    36,    37,
+      38,    39,    40,     3,     4,     5,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,     3,     4,
+       5,    -1,    -1,    -1,    -1,    -1,    26,    27,    28,    29,
+      30,    31,    32,    33,    -1,    35,    36,    37,    38,    39,
+      40,    26,    27,    28,    29,    30,    31,    32,    33,    -1,
+      35,    36,    37,    38,    39,    40,     3,     4,     5,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,     3,     4,     5,    -1,    -1,    -1,    -1,    -1,    26,
+      27,    28,    29,    30,    31,    32,    33,    -1,    35,    36,
+      37,    38,    39,    40,    26,    27,    28,    29,    30,    31,
+      32,    33,    -1,    35,    36,    37,    38,    39,    40,     3,
+       4,     5,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,     3,     4,     5,    -1,    -1,    -1,
+      -1,    -1,    26,    27,    28,    29,    30,    31,    32,    33,
+      -1,    35,    36,    37,    38,    39,    40,    26,    27,    28,
+      29,    30,    31,    32,    33,    -1,    35,    36,    37,    38,
+      39,    40,     3,     4,     5,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,     3,     4,     5,
+      -1,    -1,    -1,    -1,    -1,    26,    27,    28,    29,    30,
+      31,    32,    33,    -1,    35,    36,    37,    38,    39,    40,
+      26,    27,    28,    29,    30,    31,    32,    33,    -1,    35,
+      36,    37,    38,    39,    40,     3,     4,     5,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+       3,     4,     5,    -1,    -1,    -1,    -1,    -1,    26,    27,
+      28,    29,    30,    31,    32,    33,    -1,    35,    36,    37,
+      38,    39,    40,    26,    27,    28,    29,    30,    31,    32,
+      33,    -1,    35,    36,    37,    38,    39,    40,     3,     4,
+       5,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,     3,     4,     5,    -1,    -1,    -1,    -1,
+      -1,    26,    27,    28,    29,    30,    31,    32,    33,    -1,
+      35,    36,    37,    38,    39,    40,    26,    27,    28,    29,
+      30,    31,    32,    33,    -1,    35,    36,    37,    38,    39,
+      40,     3,     4,     5,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,     3,     4,     5,    -1,
+      -1,    -1,    -1,    -1,    26,    27,    28,    29,    30,    31,
+      32,    33,    -1,    35,    36,    37,    38,    39,    40,    26,
+      27,    28,    29,    30,    31,    32,    33,    -1,    35,    36,
+      37,    38,    39,    40
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    42,     0,     1,     3,     6,     7,     8,     9,    10,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    34,    35,    36,    37,    38,
+      39,    40,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,     3,    32,    53,    37,    32,     3,    33,    33,
+      29,    26,    28,    33,    32,    33,    33,    33,    33,    53,
+      53,    53,    53,    53,     3,     4,     5,    26,    27,    28,
+      29,    30,    31,    32,    33,    35,    36,    37,    38,    39,
+      40,    54,    53,    53,    53,    53,    33,    33,    33,    53,
+      53,    53,    53,    53,    53,     3,     3,     3,     3,     3,
+       3,     3,     3,     3,    27,    30,    28,    53,     3,     3,
+       3,     3,     3,     3,    33,    33,    33,     3,    30,    53,
+      53,    33,     3,     3,    53,     3
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    41,    42,    42,    43,    43,    43,    43,    43,    43,
+      43,    43,    43,    43,    43,    43,    43,    43,    43,    43,
+      43,    43,    43,    43,    43,    43,    43,    44,    44,    44,
+      45,    45,    46,    46,    47,    47,    48,    48,    49,    49,
+      50,    50,    51,    51,    52,    52,    53,    53,    54,    54,
+      54,    54,    54,    54,    54,    54,    54,    54,    54,    54,
+      54,    54,    54,    54
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     2,     2,     4,     4,     7,     9,     4,
+       4,     5,     7,     4,     4,     3,     4,     4,     4,     4,
+       4,     3,     3,     3,     3,     1,     2,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     0,     2,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, yyscanner); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (yyscanner);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , yyscanner);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
+{
+  YYUSE (yyvaluep);
+  YYUSE (yyscanner);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (yyscan_t yyscanner)
+{
+/* The lookahead symbol.  */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol.  */
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex (&yylval, yyscanner);
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 4:
+#line 101 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_SetInInterface(parser, true);
+  }
+#line 1536 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 5:
+#line 105 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1546 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 6:
+#line 110 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
+        cmsysString_strcasecmp((yyvsp[-2].string), "procedure") != 0 &&
+        cmsysString_strcasecmp((yyvsp[-2].string), "subroutine") != 0) {
+      cmFortranParser_RuleModule(parser, (yyvsp[-2].string));
+    }
+    free((yyvsp[-2].string));
+  }
+#line 1560 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 7:
+#line 119 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUse(parser, (yyvsp[-4].string));
+    free((yyvsp[-4].string));
+    free((yyvsp[-2].string));
+  }
+#line 1571 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 125 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUse(parser, (yyvsp[-6].string));
+    free((yyvsp[-6].string));
+    free((yyvsp[-4].string));
+    free((yyvsp[-2].string));
+  }
+#line 1583 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 132 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_SetInInterface(parser, true);
+    free((yyvsp[-2].string));
+  }
+#line 1593 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 137 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_SetInInterface(parser, false);
+  }
+#line 1602 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 141 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1612 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 12:
+#line 146 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
+      cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+      cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
+    }
+    free((yyvsp[-4].string));
+    free((yyvsp[-2].string));
+  }
+#line 1625 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 13:
+#line 154 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1635 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 14:
+#line 159 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1645 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 15:
+#line 164 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1655 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 16:
+#line 169 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1665 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 17:
+#line 174 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1675 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 18:
+#line 179 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1685 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 19:
+#line 184 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1695 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 20:
+#line 189 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
+    free((yyvsp[-2].string));
+  }
+#line 1705 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 21:
+#line 194 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleIf(parser);
+  }
+#line 1714 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 22:
+#line 198 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleElif(parser);
+  }
+#line 1723 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 23:
+#line 202 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleElse(parser);
+  }
+#line 1732 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 24:
+#line 206 "cmFortranParser.y" /* yacc.c:1646  */
+    {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleEndif(parser);
+  }
+#line 1741 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 48:
+#line 228 "cmFortranParser.y" /* yacc.c:1646  */
+    { free ((yyvsp[0].string)); }
+#line 1747 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+  case 55:
+#line 235 "cmFortranParser.y" /* yacc.c:1646  */
+    { free ((yyvsp[0].string)); }
+#line 1753 "cmFortranParser.cxx" /* yacc.c:1646  */
+    break;
+
+
+#line 1757 "cmFortranParser.cxx" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (yyscanner, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (yyscanner, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, yyscanner);
+          yychar = YYEMPTY;
+        }
+    }
+
+#if 0
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+#endif
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, yyscanner);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (yyscanner, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, yyscanner);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp, yyscanner);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
+#line 246 "cmFortranParser.y" /* yacc.c:1906  */
+
+/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y
new file mode 100644
index 0000000..acfb40a
--- /dev/null
+++ b/Source/LexerParser/cmFortranParser.y
@@ -0,0 +1,247 @@
+%{
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*-------------------------------------------------------------------------
+  Portions of this source have been derived from makedepf90 version 2.8.8,
+
+   Copyright (C) 2000--2006 Erik Edelmann <erik.edelmann at iki.fi>
+
+  The code was originally distributed under the GPL but permission
+  from the copyright holder has been obtained to distribute this
+  derived work under the CMake license.
+-------------------------------------------------------------------------*/
+
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run bison like this:
+
+  bison --yacc --name-prefix=cmFortran_yy
+        --defines=cmFortranParserTokens.h
+         -ocmFortranParser.cxx
+          cmFortranParser.y
+
+Modify cmFortranParser.cxx:
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
+*/
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmsys/String.h"
+#include <stdlib.h>
+#include <string.h>
+
+/*-------------------------------------------------------------------------*/
+#define cmFortranParser_cxx
+#include "cmFortranParser.h" /* Interface to parser object.  */
+#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
+
+/* Forward declare the lexer entry point.  */
+YY_DECL;
+
+/* Helper function to forward error callback from parser.  */
+static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
+{
+  cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+  cmFortranParser_Error(parser, message);
+}
+
+/* Disable some warnings in the generated code.  */
+#ifdef _MSC_VER
+# pragma warning (disable: 4102) /* Unused goto label.  */
+# pragma warning (disable: 4065) /* Switch contains default but no case. */
+# pragma warning (disable: 4701) /* Local variable may not be initialized.  */
+# pragma warning (disable: 4702) /* Unreachable code.  */
+# pragma warning (disable: 4127) /* Conditional expression is constant.  */
+# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
+#endif
+%}
+
+/* Generate a reentrant parser object.  */
+%define api.pure
+
+/* Configure the parser to use a lexer object.  */
+%lex-param   {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
+
+%define parse.error verbose
+
+%union {
+  char* string;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Tokens */
+%token EOSTMT ASSIGNMENT_OP GARBAGE
+%token CPP_LINE_DIRECTIVE
+%token CPP_INCLUDE F90PPR_INCLUDE COCO_INCLUDE
+%token F90PPR_DEFINE CPP_DEFINE F90PPR_UNDEF CPP_UNDEF
+%token CPP_IFDEF CPP_IFNDEF CPP_IF CPP_ELSE CPP_ELIF CPP_ENDIF
+%token F90PPR_IFDEF F90PPR_IFNDEF F90PPR_IF
+%token F90PPR_ELSE F90PPR_ELIF F90PPR_ENDIF
+%token COMMA COLON DCOLON LPAREN RPAREN
+%token <number> UNTERMINATED_STRING
+%token <string> STRING WORD
+%token <string> CPP_INCLUDE_ANGLE
+%token END
+%token INCLUDE
+%token INTERFACE
+%token MODULE
+%token SUBMODULE
+%token USE
+
+/*-------------------------------------------------------------------------*/
+/* grammar */
+%%
+
+code: /* empty */ | code stmt;
+
+stmt:
+  INTERFACE EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_SetInInterface(parser, true);
+  }
+| USE WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUse(parser, $2);
+    free($2);
+  }
+| MODULE WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    if (cmsysString_strcasecmp($2, "function") != 0 &&
+        cmsysString_strcasecmp($2, "procedure") != 0 &&
+        cmsysString_strcasecmp($2, "subroutine") != 0) {
+      cmFortranParser_RuleModule(parser, $2);
+    }
+    free($2);
+  }
+| SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUse(parser, $3);
+    free($3);
+    free($5);
+  }
+| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUse(parser, $3);
+    free($3);
+    free($5);
+    free($7);
+  }
+| INTERFACE WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_SetInInterface(parser, true);
+    free($2);
+  }
+| END INTERFACE other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_SetInInterface(parser, false);
+  }
+| USE DCOLON WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUse(parser, $3);
+    free($3);
+  }
+| USE COMMA WORD DCOLON WORD other EOSTMT {
+    if (cmsysString_strcasecmp($3, "non_intrinsic") == 0) {
+      cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+      cmFortranParser_RuleUse(parser, $5);
+    }
+    free($3);
+    free($5);
+  }
+| INCLUDE STRING other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleInclude(parser, $2);
+    free($2);
+  }
+| CPP_LINE_DIRECTIVE STRING other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleLineDirective(parser, $2);
+    free($2);
+  }
+| CPP_INCLUDE_ANGLE other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleInclude(parser, $1);
+    free($1);
+  }
+| include STRING other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleInclude(parser, $2);
+    free($2);
+  }
+| define WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleDefine(parser, $2);
+    free($2);
+  }
+| undef WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleUndef(parser, $2);
+    free($2);
+  }
+| ifdef WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleIfdef(parser, $2);
+    free($2);
+  }
+| ifndef WORD other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleIfndef(parser, $2);
+    free($2);
+  }
+| if other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleIf(parser);
+  }
+| elif other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleElif(parser);
+  }
+| else other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleElse(parser);
+  }
+| endif other EOSTMT {
+    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+    cmFortranParser_RuleEndif(parser);
+  }
+| EOSTMT
+| error EOSTMT /* tolerate unknown statements until their end */
+;
+
+
+
+include: CPP_INCLUDE | F90PPR_INCLUDE | COCO_INCLUDE ;
+define: CPP_DEFINE | F90PPR_DEFINE;
+undef: CPP_UNDEF | F90PPR_UNDEF ;
+ifdef: CPP_IFDEF | F90PPR_IFDEF ;
+ifndef: CPP_IFNDEF | F90PPR_IFNDEF ;
+if: CPP_IF | F90PPR_IF ;
+elif: CPP_ELIF | F90PPR_ELIF ;
+else: CPP_ELSE | F90PPR_ELSE ;
+endif: CPP_ENDIF | F90PPR_ENDIF ;
+other: /* empty */ | other misc_code ;
+
+misc_code:
+  WORD                { free ($1); }
+| END
+| INCLUDE
+| INTERFACE
+| MODULE
+| SUBMODULE
+| USE
+| STRING              { free ($1); }
+| GARBAGE
+| ASSIGNMENT_OP
+| COLON
+| DCOLON
+| LPAREN
+| RPAREN
+| COMMA
+| UNTERMINATED_STRING
+;
+
+%%
+/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h
new file mode 100644
index 0000000..8d6a5fe
--- /dev/null
+++ b/Source/LexerParser/cmFortranParserTokens.h
@@ -0,0 +1,149 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
+# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int cmFortran_yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    EOSTMT = 258,
+    ASSIGNMENT_OP = 259,
+    GARBAGE = 260,
+    CPP_LINE_DIRECTIVE = 261,
+    CPP_INCLUDE = 262,
+    F90PPR_INCLUDE = 263,
+    COCO_INCLUDE = 264,
+    F90PPR_DEFINE = 265,
+    CPP_DEFINE = 266,
+    F90PPR_UNDEF = 267,
+    CPP_UNDEF = 268,
+    CPP_IFDEF = 269,
+    CPP_IFNDEF = 270,
+    CPP_IF = 271,
+    CPP_ELSE = 272,
+    CPP_ELIF = 273,
+    CPP_ENDIF = 274,
+    F90PPR_IFDEF = 275,
+    F90PPR_IFNDEF = 276,
+    F90PPR_IF = 277,
+    F90PPR_ELSE = 278,
+    F90PPR_ELIF = 279,
+    F90PPR_ENDIF = 280,
+    COMMA = 281,
+    COLON = 282,
+    DCOLON = 283,
+    LPAREN = 284,
+    RPAREN = 285,
+    UNTERMINATED_STRING = 286,
+    STRING = 287,
+    WORD = 288,
+    CPP_INCLUDE_ANGLE = 289,
+    END = 290,
+    INCLUDE = 291,
+    INTERFACE = 292,
+    MODULE = 293,
+    SUBMODULE = 294,
+    USE = 295
+  };
+#endif
+/* Tokens.  */
+#define EOSTMT 258
+#define ASSIGNMENT_OP 259
+#define GARBAGE 260
+#define CPP_LINE_DIRECTIVE 261
+#define CPP_INCLUDE 262
+#define F90PPR_INCLUDE 263
+#define COCO_INCLUDE 264
+#define F90PPR_DEFINE 265
+#define CPP_DEFINE 266
+#define F90PPR_UNDEF 267
+#define CPP_UNDEF 268
+#define CPP_IFDEF 269
+#define CPP_IFNDEF 270
+#define CPP_IF 271
+#define CPP_ELSE 272
+#define CPP_ELIF 273
+#define CPP_ENDIF 274
+#define F90PPR_IFDEF 275
+#define F90PPR_IFNDEF 276
+#define F90PPR_IF 277
+#define F90PPR_ELSE 278
+#define F90PPR_ELIF 279
+#define F90PPR_ENDIF 280
+#define COMMA 281
+#define COLON 282
+#define DCOLON 283
+#define LPAREN 284
+#define RPAREN 285
+#define UNTERMINATED_STRING 286
+#define STRING 287
+#define WORD 288
+#define CPP_INCLUDE_ANGLE 289
+#define END 290
+#define INCLUDE 291
+#define INTERFACE 292
+#define MODULE 293
+#define SUBMODULE 294
+#define USE 295
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 70 "cmFortranParser.y" /* yacc.c:1909  */
+
+  char* string;
+
+#line 138 "cmFortranParserTokens.h" /* yacc.c:1909  */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int cmFortran_yyparse (yyscan_t yyscanner);
+
+#endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED  */
diff --git a/Source/LexerParser/cmListFileLexer.c b/Source/LexerParser/cmListFileLexer.c
new file mode 100644
index 0000000..3dd3b85
--- /dev/null
+++ b/Source/LexerParser/cmListFileLexer.c
@@ -0,0 +1,2688 @@
+#include "cmStandardLexer.h"
+#line 2 "cmListFileLexer.c"
+
+#line 4 "cmListFileLexer.c"
+
+#define FLEXINT_H 1
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 1
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* TODO: this is always defined, so inline it */
+#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
+#else
+#define yynoreturn
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE cmListFileLexer_yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE cmListFileLexer_yylex.
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    #define YY_LINENO_REWIND_TO(dst) \
+            do {\
+                const char *p;\
+                for ( p = yy_cp-1; p >= (dst); --p)\
+                    if ( *p == '\n' )\
+                        --yylineno;\
+            }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = yyg->yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	int yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via cmListFileLexer_yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void cmListFileLexer_yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void cmListFileLexer_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE cmListFileLexer_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void cmListFileLexer_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void cmListFileLexer_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void cmListFileLexer_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void cmListFileLexer_yypop_buffer_state (yyscan_t yyscanner );
+
+static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner );
+static void cmListFileLexer_yy_load_buffer_state (yyscan_t yyscanner );
+static void cmListFileLexer_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER cmListFileLexer_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *cmListFileLexer_yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *cmListFileLexer_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void cmListFileLexer_yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer cmListFileLexer_yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        cmListFileLexer_yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        cmListFileLexer_yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define cmListFileLexer_yywrap(yyscanner) (/*CONSTCOND*/1)
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yyg->yytext_ptr = yy_bp; \
+	yyleng = (int) (yy_cp - yy_bp); \
+	yyg->yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 24
+#define YY_END_OF_BUFFER 25
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[77] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    4,    4,
+       25,   13,   22,    1,   16,    3,   13,    5,    6,    7,
+       15,   23,   17,   19,   20,   21,   10,   11,    8,   12,
+        9,    4,   13,    0,   13,    0,   22,    0,    0,    7,
+       13,    0,   13,    0,    2,    0,   13,   17,    0,   18,
+       10,    8,    4,    0,   14,    0,    0,    0,    0,   14,
+        0,    0,   14,    0,    0,    0,    2,   14,    0,    0,
+        0,    0,    0,    0,    0,    0
+    } ;
+
+static yyconst YY_CHAR yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    4,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    5,    6,    7,    1,    1,    1,    8,
+        9,    1,    1,    1,    1,    1,    1,   10,   10,   10,
+       10,   10,   10,   10,   10,   10,   10,    1,    1,    1,
+       11,    1,    1,    1,   12,   12,   12,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
+       13,   14,   15,    1,   12,    1,   12,   12,   12,   12,
+
+       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
+       12,   12,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst YY_CHAR yy_meta[16] =
+    {   0,
+        1,    1,    2,    3,    4,    3,    1,    3,    5,    6,
+        1,    6,    1,    1,    7
+    } ;
+
+static yyconst flex_uint16_t yy_base[95] =
+    {   0,
+        0,    0,   13,   25,   14,   16,   17,   18,   90,   88,
+       88,   39,   20,  237,  237,   74,   78,  237,  237,   13,
+       54,    0,   71,  237,  237,   31,    0,  237,   73,  237,
+      237,    0,    0,   65,   75,    0,   33,   30,   72,    0,
+        0,   75,   70,    0,   74,    0,    0,   62,   70,  237,
+        0,   63,    0,   85,   99,   65,  111,   62,   34,    0,
+       54,  116,    0,   54,  127,   51,  237,   50,    0,   48,
+       47,   39,   33,   29,   17,  237,  136,  143,  150,  157,
+      164,  171,  178,  184,  191,  198,  201,  207,  214,  217,
+      219,  225,  228,  230
+
+    } ;
+
+static yyconst flex_int16_t yy_def[95] =
+    {   0,
+       76,    1,   77,   77,   78,   78,   79,   79,   80,   80,
+       76,   76,   76,   76,   76,   76,   12,   76,   76,   12,
+       76,   81,   82,   76,   76,   82,   83,   76,   76,   76,
+       76,   84,   12,   85,   12,   86,   76,   76,   87,   20,
+       12,   88,   12,   21,   76,   89,   12,   82,   82,   76,
+       83,   76,   84,   85,   76,   54,   85,   90,   76,   55,
+       87,   88,   55,   62,   88,   91,   76,   55,   92,   93,
+       90,   94,   91,   93,   94,    0,   76,   76,   76,   76,
+       76,   76,   76,   76,   76,   76,   76,   76,   76,   76,
+       76,   76,   76,   76
+
+    } ;
+
+static yyconst flex_uint16_t yy_nxt[253] =
+    {   0,
+       12,   13,   14,   13,   15,   16,   17,   18,   19,   12,
+       12,   20,   21,   22,   12,   24,   28,   25,   28,   28,
+       28,   37,   40,   37,   40,   62,   26,   24,   29,   25,
+       29,   31,   31,   50,   37,   48,   37,   54,   26,   33,
+       59,   63,   45,   34,   59,   35,   45,   62,   33,   33,
+       33,   33,   36,   33,   41,   55,   54,   58,   42,   63,
+       43,   72,   60,   41,   44,   41,   45,   46,   41,   55,
+       55,   56,   70,   52,   48,   49,   67,   66,   57,   63,
+       60,   64,   58,   52,   49,   39,   38,   76,   65,   55,
+       14,   56,   14,   76,   76,   76,   76,   76,   57,   55,
+
+       76,   76,   76,   34,   76,   68,   76,   76,   55,   55,
+       55,   55,   69,   55,   54,   76,   54,   76,   54,   54,
+       63,   76,   64,   76,   76,   76,   76,   76,   76,   65,
+       62,   76,   62,   76,   62,   62,   23,   23,   23,   23,
+       23,   23,   23,   27,   27,   27,   27,   27,   27,   27,
+       30,   30,   30,   30,   30,   30,   30,   32,   32,   32,
+       32,   32,   32,   32,   47,   76,   47,   47,   47,   47,
+       47,   48,   76,   48,   76,   48,   48,   48,   51,   76,
+       51,   51,   51,   51,   53,   76,   53,   53,   53,   53,
+       53,   54,   76,   76,   54,   76,   54,   54,   33,   76,
+
+       33,   33,   33,   33,   33,   61,   61,   62,   76,   76,
+       62,   76,   62,   62,   41,   76,   41,   41,   41,   41,
+       41,   71,   71,   73,   73,   55,   76,   55,   55,   55,
+       55,   55,   74,   74,   75,   75,   11,   76,   76,   76,
+       76,   76,   76,   76,   76,   76,   76,   76,   76,   76,
+       76,   76
+    } ;
+
+static yyconst flex_int16_t yy_chk[253] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    3,    5,    3,    6,    7,
+        8,   13,   20,   13,   20,   75,    3,    4,    5,    4,
+        6,    7,    8,   26,   37,   26,   37,   74,    4,   12,
+       38,   73,   38,   12,   59,   12,   59,   72,   12,   12,
+       12,   12,   12,   12,   21,   71,   70,   68,   21,   66,
+       21,   64,   61,   21,   21,   21,   21,   21,   21,   34,
+       58,   34,   56,   52,   49,   48,   45,   43,   34,   42,
+       39,   42,   35,   29,   23,   17,   16,   11,   42,   54,
+       10,   54,    9,    0,    0,    0,    0,    0,   54,   55,
+
+        0,    0,    0,   55,    0,   55,    0,    0,   55,   55,
+       55,   55,   55,   55,   57,    0,   57,    0,   57,   57,
+       62,    0,   62,    0,    0,    0,    0,    0,    0,   62,
+       65,    0,   65,    0,   65,   65,   77,   77,   77,   77,
+       77,   77,   77,   78,   78,   78,   78,   78,   78,   78,
+       79,   79,   79,   79,   79,   79,   79,   80,   80,   80,
+       80,   80,   80,   80,   81,    0,   81,   81,   81,   81,
+       81,   82,    0,   82,    0,   82,   82,   82,   83,    0,
+       83,   83,   83,   83,   84,    0,   84,   84,   84,   84,
+       84,   85,    0,    0,   85,    0,   85,   85,   86,    0,
+
+       86,   86,   86,   86,   86,   87,   87,   88,    0,    0,
+       88,    0,   88,   88,   89,    0,   89,   89,   89,   89,
+       89,   90,   90,   91,   91,   92,    0,   92,   92,   92,
+       92,   92,   93,   93,   94,   94,   76,   76,   76,   76,
+       76,   76,   76,   76,   76,   76,   76,   76,   76,   76,
+       76,   76
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[25] =
+    {   0,
+1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1,
+    0, 0, 0, 0, 0,     };
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "cmListFileLexer.in.l"
+#line 2 "cmListFileLexer.in.l"
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run flex >= 2.6 like this:
+
+  flex --nounistd -DFLEXINT_H --prefix=cmListFileLexer_yy -ocmListFileLexer.c cmListFileLexer.in.l
+
+Modify cmListFileLexer.c:
+  - remove trailing whitespace: sed -i 's/\s*$//' cmListFileLexer.c
+  - remove blank lines at end of file
+  - #include "cmStandardLexer.h" at the top
+  - add cast in cmListFileLexer_yy_scan_bytes for loop condition of _yybytes_len to size_t
+  - change type of variable yyl under yy_find_action from yy_size_t to int
+
+*/
+
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#ifdef WIN32
+#include "cmsys/Encoding.h"
+#endif
+
+/* Setup the proper cmListFileLexer_yylex declaration.  */
+#define YY_EXTRA_TYPE cmListFileLexer*
+#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner, cmListFileLexer* lexer)
+
+#include "cmListFileLexer.h"
+
+/*--------------------------------------------------------------------------*/
+struct cmListFileLexer_s
+{
+  cmListFileLexer_Token token;
+  int bracket;
+  int comment;
+  int line;
+  int column;
+  int size;
+  FILE* file;
+  size_t cr;
+  char* string_buffer;
+  char* string_position;
+  int string_left;
+  yyscan_t scanner;
+};
+
+static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
+                                    int length);
+static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
+                                  int length);
+static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
+                                size_t bufferSize);
+static void cmListFileLexerInit(cmListFileLexer* lexer);
+static void cmListFileLexerDestroy(cmListFileLexer* lexer);
+
+/* Replace the lexer input function.  */
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+  { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); }
+
+/*--------------------------------------------------------------------------*/
+
+
+
+
+#line 606 "cmListFileLexer.c"
+
+#define INITIAL 0
+#define STRING 1
+#define BRACKET 2
+#define BRACKETEND 3
+#define COMMENT 4
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+int cmListFileLexer_yylex_init (yyscan_t* scanner);
+
+int cmListFileLexer_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int cmListFileLexer_yylex_destroy (yyscan_t yyscanner );
+
+int cmListFileLexer_yyget_debug (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE cmListFileLexer_yyget_extra (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *cmListFileLexer_yyget_in (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_in  (FILE * _in_str ,yyscan_t yyscanner );
+
+FILE *cmListFileLexer_yyget_out (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_out  (FILE * _out_str ,yyscan_t yyscanner );
+
+			int cmListFileLexer_yyget_leng (yyscan_t yyscanner );
+
+char *cmListFileLexer_yyget_text (yyscan_t yyscanner );
+
+int cmListFileLexer_yyget_lineno (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+
+int cmListFileLexer_yyget_column  (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_column (int _column_no ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int cmListFileLexer_yywrap (yyscan_t yyscanner );
+#else
+extern int cmListFileLexer_yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+
+    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
+
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int cmListFileLexer_yylex (yyscan_t yyscanner);
+
+#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK /*LINTED*/break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	yy_state_type yy_current_state;
+	char *yy_cp, *yy_bp;
+	int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( !yyg->yy_init )
+		{
+		yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yyg->yy_start )
+			yyg->yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			cmListFileLexer_yyensure_buffer_stack (yyscanner);
+			YY_CURRENT_BUFFER_LVALUE =
+				cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+		}
+
+		cmListFileLexer_yy_load_buffer_state(yyscanner );
+		}
+
+	{
+#line 80 "cmListFileLexer.in.l"
+
+
+#line 866 "cmListFileLexer.c"
+
+	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yyg->yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yyg->yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yyg->yy_start;
+yy_match:
+		do
+			{
+			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+			if ( yy_accept[yy_current_state] )
+				{
+				yyg->yy_last_accepting_state = yy_current_state;
+				yyg->yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 77 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 237 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yyg->yy_hold_char;
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 82 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_Newline;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  ++lexer->line;
+  lexer->column = 1;
+  BEGIN(INITIAL);
+  return 1;
+}
+	YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 91 "cmListFileLexer.in.l"
+{
+  const char* bracket = yytext;
+  lexer->comment = yytext[0] == '#';
+  if (lexer->comment) {
+    lexer->token.type = cmListFileLexer_Token_CommentBracket;
+    bracket += 1;
+  } else {
+    lexer->token.type = cmListFileLexer_Token_ArgumentBracket;
+  }
+  cmListFileLexerSetToken(lexer, "", 0);
+  lexer->bracket = strchr(bracket+1, '[') - bracket;
+  if (yytext[yyleng-1] == '\n') {
+    ++lexer->line;
+    lexer->column = 1;
+  } else {
+    lexer->column += yyleng;
+  }
+  BEGIN(BRACKET);
+}
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 111 "cmListFileLexer.in.l"
+{
+  lexer->column += yyleng;
+  BEGIN(COMMENT);
+}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 116 "cmListFileLexer.in.l"
+{
+  lexer->column += yyleng;
+}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 120 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_ParenLeft;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 127 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_ParenRight;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 134 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_Identifier;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 141 "cmListFileLexer.in.l"
+{
+  /* Handle ]]====]=======]*/
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  if (yyleng == lexer->bracket) {
+    BEGIN(BRACKETEND);
+  }
+}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 150 "cmListFileLexer.in.l"
+{
+  lexer->column += yyleng;
+  /* Erase the partial bracket from the token.  */
+  lexer->token.length -= lexer->bracket;
+  lexer->token.text[lexer->token.length] = 0;
+  BEGIN(INITIAL);
+  return 1;
+}
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 159 "cmListFileLexer.in.l"
+{
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+}
+	YY_BREAK
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 164 "cmListFileLexer.in.l"
+{
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  ++lexer->line;
+  lexer->column = 1;
+  BEGIN(BRACKET);
+}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 171 "cmListFileLexer.in.l"
+{
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  BEGIN(BRACKET);
+}
+	YY_BREAK
+case YY_STATE_EOF(BRACKET):
+case YY_STATE_EOF(BRACKETEND):
+#line 177 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_BadBracket;
+  BEGIN(INITIAL);
+  return 1;
+}
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 183 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 190 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 197 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 204 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
+  cmListFileLexerSetToken(lexer, "", 0);
+  lexer->column += yyleng;
+  BEGIN(STRING);
+}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 211 "cmListFileLexer.in.l"
+{
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+}
+	YY_BREAK
+case 18:
+/* rule 18 can match eol */
+YY_RULE_SETUP
+#line 216 "cmListFileLexer.in.l"
+{
+  /* Continuation: text is not part of string */
+  ++lexer->line;
+  lexer->column = 1;
+}
+	YY_BREAK
+case 19:
+/* rule 19 can match eol */
+YY_RULE_SETUP
+#line 222 "cmListFileLexer.in.l"
+{
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  ++lexer->line;
+  lexer->column = 1;
+}
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 228 "cmListFileLexer.in.l"
+{
+  lexer->column += yyleng;
+  BEGIN(INITIAL);
+  return 1;
+}
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 234 "cmListFileLexer.in.l"
+{
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+}
+	YY_BREAK
+case YY_STATE_EOF(STRING):
+#line 239 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_BadString;
+  BEGIN(INITIAL);
+  return 1;
+}
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 245 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_Space;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 252 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_BadCharacter;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(COMMENT):
+#line 259 "cmListFileLexer.in.l"
+{
+  lexer->token.type = cmListFileLexer_Token_None;
+  cmListFileLexerSetToken(lexer, 0, 0);
+  return 0;
+}
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 265 "cmListFileLexer.in.l"
+ECHO;
+	YY_BREAK
+#line 1205 "cmListFileLexer.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yyg->yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * cmListFileLexer_yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state( yyscanner );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yyg->yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yyg->yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer( yyscanner ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yyg->yy_did_buffer_switch_on_eof = 0;
+
+				if ( cmListFileLexer_yywrap(yyscanner ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yyg->yy_c_buf_p =
+					yyg->yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yyg->yy_c_buf_p =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of user's declarations */
+} /* end of cmListFileLexer_yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	char *source = yyg->yytext_ptr;
+	yy_size_t number_to_move, i;
+	int ret_val;
+
+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+			int yy_c_buf_p_offset =
+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					cmListFileLexer_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = NULL;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			yyg->yy_n_chars, num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	if ( yyg->yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			cmListFileLexer_yyrestart(yyin  ,yyscanner);
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmListFileLexer_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	yyg->yy_n_chars += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+	yy_state_type yy_current_state;
+	char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_current_state = yyg->yy_start;
+
+	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+		{
+		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yyg->yy_last_accepting_state = yy_current_state;
+			yyg->yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 77 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+	int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+	char *yy_cp = yyg->yy_c_buf_p;
+
+	YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yyg->yy_last_accepting_state = yy_current_state;
+		yyg->yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 77 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+	yy_is_jam = (yy_current_state == 76);
+
+	(void)yyg;
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+
+    static void yyunput (int c, char * yy_bp , yyscan_t yyscanner)
+{
+	char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    yy_cp = yyg->yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yyg->yy_hold_char;
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		int number_to_move = yyg->yy_n_chars + 2;
+		char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+    if ( c == '\n' ){
+        --yylineno;
+    }
+
+	yyg->yytext_ptr = yy_bp;
+	yyg->yy_hold_char = *yy_cp;
+	yyg->yy_c_buf_p = yy_cp;
+}
+
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+{
+	int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	*yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			/* This was really a NUL. */
+			*yyg->yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			++yyg->yy_c_buf_p;
+
+			switch ( yy_get_next_buffer( yyscanner ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					cmListFileLexer_yyrestart(yyin ,yyscanner);
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( cmListFileLexer_yywrap(yyscanner ) )
+						return 0;
+
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput(yyscanner);
+#else
+					return input(yyscanner);
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+	if ( c == '\n' )
+
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void cmListFileLexer_yyrestart  (FILE * input_file , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! YY_CURRENT_BUFFER ){
+        cmListFileLexer_yyensure_buffer_stack (yyscanner);
+		YY_CURRENT_BUFFER_LVALUE =
+            cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+	}
+
+	cmListFileLexer_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+	cmListFileLexer_yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+    void cmListFileLexer_yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		cmListFileLexer_yypop_buffer_state();
+	 *		cmListFileLexer_yypush_buffer_state(new_buffer);
+     */
+	cmListFileLexer_yyensure_buffer_stack (yyscanner);
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	cmListFileLexer_yy_load_buffer_state(yyscanner );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (cmListFileLexer_yywrap()) processing, but the only time this flag
+	 * is looked at is after cmListFileLexer_yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void cmListFileLexer_yy_load_buffer_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE cmListFileLexer_yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+
+	b = (YY_BUFFER_STATE) cmListFileLexer_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_create_buffer()" );
+
+	b->yy_buf_size = (yy_size_t)size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) cmListFileLexer_yyalloc(b->yy_buf_size + 2 ,yyscanner );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	cmListFileLexer_yy_init_buffer(b,file ,yyscanner);
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with cmListFileLexer_yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+    void cmListFileLexer_yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		cmListFileLexer_yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+	cmListFileLexer_yyfree((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a cmListFileLexer_yyrestart() or at EOF.
+ */
+    static void cmListFileLexer_yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+
+{
+	int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	cmListFileLexer_yy_flush_buffer(b ,yyscanner);
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then cmListFileLexer_yy_init_buffer was _probably_
+     * called from cmListFileLexer_yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+    void cmListFileLexer_yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		cmListFileLexer_yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+void cmListFileLexer_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (new_buffer == NULL)
+		return;
+
+	cmListFileLexer_yyensure_buffer_stack(yyscanner);
+
+	/* This block is copied from cmListFileLexer_yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		yyg->yy_buffer_stack_top++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from cmListFileLexer_yy_switch_to_buffer. */
+	cmListFileLexer_yy_load_buffer_state(yyscanner );
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+void cmListFileLexer_yypop_buffer_state (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (!YY_CURRENT_BUFFER)
+		return;
+
+	cmListFileLexer_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if (yyg->yy_buffer_stack_top > 0)
+		--yyg->yy_buffer_stack_top;
+
+	if (YY_CURRENT_BUFFER) {
+		cmListFileLexer_yy_load_buffer_state(yyscanner );
+		yyg->yy_did_buffer_switch_on_eof = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
+{
+	int num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if (!yyg->yy_buffer_stack) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
+
+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+		yyg->yy_buffer_stack_max = num_to_alloc;
+		yyg->yy_buffer_stack_top = 0;
+		return;
+	}
+
+	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		yy_size_t grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_yyrealloc
+								(yyg->yy_buffer_stack,
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+		yyg->yy_buffer_stack_max = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return NULL;
+
+	b = (YY_BUFFER_STATE) cmListFileLexer_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = NULL;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	cmListFileLexer_yy_switch_to_buffer(b ,yyscanner );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to cmListFileLexer_yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       cmListFileLexer_yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+	return cmListFileLexer_yy_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to cmListFileLexer_yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	yy_size_t i;
+
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = (yy_size_t) _yybytes_len + 2;
+	buf = (char *) cmListFileLexer_yyalloc(n ,yyscanner );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_bytes()" );
+
+	for ( i = 0; i < (size_t)_yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = cmListFileLexer_yy_scan_buffer(buf,n ,yyscanner);
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in cmListFileLexer_yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = yyg->yy_hold_char; \
+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+		*yyg->yy_c_buf_p = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE cmListFileLexer_yyget_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int cmListFileLexer_yyget_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int cmListFileLexer_yyget_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *cmListFileLexer_yyget_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *cmListFileLexer_yyget_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int cmListFileLexer_yyget_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *cmListFileLexer_yyget_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void cmListFileLexer_yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param _line_number line number
+ * @param yyscanner The scanner object.
+ */
+void cmListFileLexer_yyset_lineno (int  _line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           YY_FATAL_ERROR( "cmListFileLexer_yyset_lineno called with no buffer" );
+
+    yylineno = _line_number;
+}
+
+/** Set the current column.
+ * @param _column_no column number
+ * @param yyscanner The scanner object.
+ */
+void cmListFileLexer_yyset_column (int  _column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           YY_FATAL_ERROR( "cmListFileLexer_yyset_column called with no buffer" );
+
+    yycolumn = _column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param _in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see cmListFileLexer_yy_switch_to_buffer
+ */
+void cmListFileLexer_yyset_in (FILE *  _in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = _in_str ;
+}
+
+void cmListFileLexer_yyset_out (FILE *  _out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = _out_str ;
+}
+
+int cmListFileLexer_yyget_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void cmListFileLexer_yyset_debug (int  _bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = _bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+/* User-visible API */
+
+/* cmListFileLexer_yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* cmListFileLexer_yylex_init_extra has the same functionality as cmListFileLexer_yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to cmListFileLexer_yyalloc in
+ * the yyextra field.
+ */
+
+int cmListFileLexer_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    cmListFileLexer_yyset_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    cmListFileLexer_yyset_extra (yy_user_defined, *ptr_yy_globals);
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from cmListFileLexer_yylex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = NULL;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = NULL;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = NULL;
+    yyout = NULL;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * cmListFileLexer_yylex_init()
+     */
+    return 0;
+}
+
+/* cmListFileLexer_yylex_destroy is for both reentrant and non-reentrant scanners. */
+int cmListFileLexer_yylex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		cmListFileLexer_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		cmListFileLexer_yypop_buffer_state(yyscanner);
+	}
+
+	/* Destroy the stack itself. */
+	cmListFileLexer_yyfree(yyg->yy_buffer_stack ,yyscanner);
+	yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        cmListFileLexer_yyfree(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * cmListFileLexer_yylex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+    /* Destroy the main struct (reentrant only). */
+    cmListFileLexer_yyfree ( yyscanner , yyscanner );
+    yyscanner = NULL;
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+
+	int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+	int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *cmListFileLexer_yyalloc (yy_size_t  size , yyscan_t yyscanner)
+{
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+	return malloc(size);
+}
+
+void *cmListFileLexer_yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return realloc(ptr, size);
+}
+
+void cmListFileLexer_yyfree (void * ptr , yyscan_t yyscanner)
+{
+	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	(void)yyg;
+	free( (char *) ptr );	/* see cmListFileLexer_yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 265 "cmListFileLexer.in.l"
+
+
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
+                                    int length)
+{
+  /* Set the token line and column number.  */
+  lexer->token.line = lexer->line;
+  lexer->token.column = lexer->column;
+
+  /* Use the same buffer if possible.  */
+  if (lexer->token.text) {
+    if (text && length < lexer->size) {
+      strcpy(lexer->token.text, text);
+      lexer->token.length = length;
+      return;
+    }
+    free(lexer->token.text);
+    lexer->token.text = 0;
+    lexer->size = 0;
+  }
+
+  /* Need to extend the buffer.  */
+  if (text) {
+    lexer->token.text = strdup(text);
+    lexer->token.length = length;
+    lexer->size = length + 1;
+  } else {
+    lexer->token.length = 0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
+                                  int length)
+{
+  char* temp;
+  int newSize;
+
+  /* If the appended text will fit in the buffer, do not reallocate.  */
+  newSize = lexer->token.length + length + 1;
+  if (lexer->token.text && newSize <= lexer->size) {
+    strcpy(lexer->token.text + lexer->token.length, text);
+    lexer->token.length += length;
+    return;
+  }
+
+  /* We need to extend the buffer.  */
+  temp = malloc(newSize);
+  if (lexer->token.text) {
+    memcpy(temp, lexer->token.text, lexer->token.length);
+    free(lexer->token.text);
+  }
+  memcpy(temp + lexer->token.length, text, length);
+  temp[lexer->token.length + length] = 0;
+  lexer->token.text = temp;
+  lexer->token.length += length;
+  lexer->size = newSize;
+}
+
+/*--------------------------------------------------------------------------*/
+static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
+                                size_t bufferSize)
+{
+  if (lexer) {
+    if (lexer->file) {
+      /* Convert CRLF -> LF explicitly.  The C FILE "t"ext mode
+         does not convert newlines on all platforms.  Move any
+         trailing CR to the start of the buffer for the next read. */
+      size_t cr = lexer->cr;
+      size_t n;
+      buffer[0] = '\r';
+      n = fread(buffer + cr, 1, bufferSize - cr, lexer->file);
+      if (n) {
+        char* o = buffer;
+        const char* i = buffer;
+        const char* e;
+        n += cr;
+        cr = (buffer[n - 1] == '\r') ? 1 : 0;
+        e = buffer + n - cr;
+        while (i != e) {
+          if (i[0] == '\r' && i[1] == '\n') {
+            ++i;
+          }
+          *o++ = *i++;
+        }
+        n = o - buffer;
+      } else {
+        n = cr;
+        cr = 0;
+      }
+      lexer->cr = cr;
+      return n;
+    } else if (lexer->string_left) {
+      int length = lexer->string_left;
+      if ((int)bufferSize < length) {
+        length = (int)bufferSize;
+      }
+      memcpy(buffer, lexer->string_position, length);
+      lexer->string_position += length;
+      lexer->string_left -= length;
+      return length;
+    }
+  }
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerInit(cmListFileLexer* lexer)
+{
+  if (lexer->file || lexer->string_buffer) {
+    cmListFileLexer_yylex_init(&lexer->scanner);
+    cmListFileLexer_yyset_extra(lexer, lexer->scanner);
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerDestroy(cmListFileLexer* lexer)
+{
+  cmListFileLexerSetToken(lexer, 0, 0);
+  if (lexer->file || lexer->string_buffer) {
+    cmListFileLexer_yylex_destroy(lexer->scanner);
+    if (lexer->file) {
+      fclose(lexer->file);
+      lexer->file = 0;
+    }
+    if (lexer->string_buffer) {
+      free(lexer->string_buffer);
+      lexer->string_buffer = 0;
+      lexer->string_left = 0;
+      lexer->string_position = 0;
+    }
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+cmListFileLexer* cmListFileLexer_New(void)
+{
+  cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer));
+  if (!lexer) {
+    return 0;
+  }
+  memset(lexer, 0, sizeof(*lexer));
+  lexer->line = 1;
+  lexer->column = 1;
+  return lexer;
+}
+
+/*--------------------------------------------------------------------------*/
+void cmListFileLexer_Delete(cmListFileLexer* lexer)
+{
+  cmListFileLexer_SetFileName(lexer, 0, 0);
+  free(lexer);
+}
+
+/*--------------------------------------------------------------------------*/
+static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f)
+{
+  unsigned char b[2];
+  if (fread(b, 1, 2, f) == 2) {
+    if (b[0] == 0xEF && b[1] == 0xBB) {
+      if (fread(b, 1, 1, f) == 1 && b[0] == 0xBF) {
+        return cmListFileLexer_BOM_UTF8;
+      }
+    } else if (b[0] == 0xFE && b[1] == 0xFF) {
+      /* UTF-16 BE */
+      return cmListFileLexer_BOM_UTF16BE;
+    } else if (b[0] == 0 && b[1] == 0) {
+      if (fread(b, 1, 2, f) == 2 && b[0] == 0xFE && b[1] == 0xFF) {
+        return cmListFileLexer_BOM_UTF32BE;
+      }
+    } else if (b[0] == 0xFF && b[1] == 0xFE) {
+      fpos_t p;
+      fgetpos(f, &p);
+      if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) {
+        return cmListFileLexer_BOM_UTF32LE;
+      }
+      if (fsetpos(f, &p) != 0) {
+        return cmListFileLexer_BOM_Broken;
+      }
+      return cmListFileLexer_BOM_UTF16LE;
+    }
+  }
+  if (fseek(f, 0, SEEK_SET) != 0) {
+    return cmListFileLexer_BOM_Broken;
+  }
+  return cmListFileLexer_BOM_None;
+}
+
+/*--------------------------------------------------------------------------*/
+int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name,
+                                cmListFileLexer_BOM* bom)
+{
+  int result = 1;
+  cmListFileLexerDestroy(lexer);
+  if (name) {
+#ifdef _WIN32
+    wchar_t* wname = cmsysEncoding_DupToWide(name);
+    lexer->file = _wfopen(wname, L"rb");
+    free(wname);
+#else
+    lexer->file = fopen(name, "rb");
+#endif
+    if (lexer->file) {
+      if (bom) {
+        *bom = cmListFileLexer_ReadBOM(lexer->file);
+      }
+    } else {
+      result = 0;
+    }
+  }
+  cmListFileLexerInit(lexer);
+  return result;
+}
+
+/*--------------------------------------------------------------------------*/
+int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text)
+{
+  int result = 1;
+  cmListFileLexerDestroy(lexer);
+  if (text) {
+    int length = (int)strlen(text);
+    lexer->string_buffer = (char*)malloc(length + 1);
+    if (lexer->string_buffer) {
+      strcpy(lexer->string_buffer, text);
+      lexer->string_position = lexer->string_buffer;
+      lexer->string_left = length;
+    } else {
+      result = 0;
+    }
+  }
+  cmListFileLexerInit(lexer);
+  return result;
+}
+
+/*--------------------------------------------------------------------------*/
+cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer)
+{
+  if (!lexer->file) {
+    return 0;
+  }
+  if (cmListFileLexer_yylex(lexer->scanner, lexer)) {
+    return &lexer->token;
+  } else {
+    cmListFileLexer_SetFileName(lexer, 0, 0);
+    return 0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer)
+{
+  if (lexer->file) {
+    return lexer->line;
+  } else {
+    return 0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer)
+{
+  if (lexer->file) {
+    return lexer->column;
+  } else {
+    return 0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
+                                            cmListFileLexer_Type type)
+{
+  (void)lexer;
+  switch (type) {
+    case cmListFileLexer_Token_None:
+      return "nothing";
+    case cmListFileLexer_Token_Space:
+      return "space";
+    case cmListFileLexer_Token_Newline:
+      return "newline";
+    case cmListFileLexer_Token_Identifier:
+      return "identifier";
+    case cmListFileLexer_Token_ParenLeft:
+      return "left paren";
+    case cmListFileLexer_Token_ParenRight:
+      return "right paren";
+    case cmListFileLexer_Token_ArgumentUnquoted:
+      return "unquoted argument";
+    case cmListFileLexer_Token_ArgumentQuoted:
+      return "quoted argument";
+    case cmListFileLexer_Token_ArgumentBracket:
+      return "bracket argument";
+    case cmListFileLexer_Token_CommentBracket:
+      return "bracket comment";
+    case cmListFileLexer_Token_BadCharacter:
+      return "bad character";
+    case cmListFileLexer_Token_BadBracket:
+      return "unterminated bracket";
+    case cmListFileLexer_Token_BadString:
+      return "unterminated string";
+  }
+  return "unknown token";
+}
diff --git a/Source/LexerParser/cmListFileLexer.in.l b/Source/LexerParser/cmListFileLexer.in.l
new file mode 100644
index 0000000..5152dbf
--- /dev/null
+++ b/Source/LexerParser/cmListFileLexer.in.l
@@ -0,0 +1,564 @@
+%{
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+/*
+
+This file must be translated to C and modified to build everywhere.
+
+Run flex >= 2.6 like this:
+
+  flex --nounistd -DFLEXINT_H --prefix=cmListFileLexer_yy -ocmListFileLexer.c cmListFileLexer.in.l
+
+Modify cmListFileLexer.c:
+  - remove trailing whitespace: sed -i 's/\s*$//' cmListFileLexer.c
+  - remove blank lines at end of file
+  - #include "cmStandardLexer.h" at the top
+  - add cast in yy_scan_bytes for loop condition of _yybytes_len to size_t
+  - change type of variable yyl under yy_find_action from yy_size_t to int
+
+*/
+
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#ifdef WIN32
+#include "cmsys/Encoding.h"
+#endif
+
+/* Setup the proper cmListFileLexer_yylex declaration.  */
+#define YY_EXTRA_TYPE cmListFileLexer*
+#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner, cmListFileLexer* lexer)
+
+#include "cmListFileLexer.h"
+
+/*--------------------------------------------------------------------------*/
+struct cmListFileLexer_s
+{
+  cmListFileLexer_Token token;
+  int bracket;
+  int comment;
+  int line;
+  int column;
+  int size;
+  FILE* file;
+  size_t cr;
+  char* string_buffer;
+  char* string_position;
+  int string_left;
+  yyscan_t scanner;
+};
+
+static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
+                                    int length);
+static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
+                                  int length);
+static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
+                                size_t bufferSize);
+static void cmListFileLexerInit(cmListFileLexer* lexer);
+static void cmListFileLexerDestroy(cmListFileLexer* lexer);
+
+/* Replace the lexer input function.  */
+#undef YY_INPUT
+#define YY_INPUT(buf, result, max_size) \
+  { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); }
+
+/*--------------------------------------------------------------------------*/
+%}
+
+%option reentrant
+%option yylineno
+%option noyywrap
+%pointer
+%x STRING
+%x BRACKET
+%x BRACKETEND
+%x COMMENT
+
+MAKEVAR \$\([A-Za-z0-9_]*\)
+UNQUOTED ([^ \t\r\n\(\)#\\\"[=]|\\.)
+LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
+
+%%
+
+<INITIAL,COMMENT>\n {
+  lexer->token.type = cmListFileLexer_Token_Newline;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  ++lexer->line;
+  lexer->column = 1;
+  BEGIN(INITIAL);
+  return 1;
+}
+
+#?\[=*\[\n? {
+  const char* bracket = yytext;
+  lexer->comment = yytext[0] == '#';
+  if (lexer->comment) {
+    lexer->token.type = cmListFileLexer_Token_CommentBracket;
+    bracket += 1;
+  } else {
+    lexer->token.type = cmListFileLexer_Token_ArgumentBracket;
+  }
+  cmListFileLexerSetToken(lexer, "", 0);
+  lexer->bracket = strchr(bracket+1, '[') - bracket;
+  if (yytext[yyleng-1] == '\n') {
+    ++lexer->line;
+    lexer->column = 1;
+  } else {
+    lexer->column += yyleng;
+  }
+  BEGIN(BRACKET);
+}
+
+# {
+  lexer->column += yyleng;
+  BEGIN(COMMENT);
+}
+
+<COMMENT>.* {
+  lexer->column += yyleng;
+}
+
+\( {
+  lexer->token.type = cmListFileLexer_Token_ParenLeft;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+
+\) {
+  lexer->token.type = cmListFileLexer_Token_ParenRight;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+
+[A-Za-z_][A-Za-z0-9_]* {
+  lexer->token.type = cmListFileLexer_Token_Identifier;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+
+<BRACKET>\]=* {
+  /* Handle ]]====]=======]*/
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  if (yyleng == lexer->bracket) {
+    BEGIN(BRACKETEND);
+  }
+}
+
+<BRACKETEND>\] {
+  lexer->column += yyleng;
+  /* Erase the partial bracket from the token.  */
+  lexer->token.length -= lexer->bracket;
+  lexer->token.text[lexer->token.length] = 0;
+  BEGIN(INITIAL);
+  return 1;
+}
+
+<BRACKET>([^]\n])+ {
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+}
+
+<BRACKET,BRACKETEND>\n {
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  ++lexer->line;
+  lexer->column = 1;
+  BEGIN(BRACKET);
+}
+
+<BRACKET,BRACKETEND>. {
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  BEGIN(BRACKET);
+}
+
+<BRACKET,BRACKETEND><<EOF>> {
+  lexer->token.type = cmListFileLexer_Token_BadBracket;
+  BEGIN(INITIAL);
+  return 1;
+}
+
+({UNQUOTED}|=|\[=*{UNQUOTED})({UNQUOTED}|[[=])* {
+  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+
+({MAKEVAR}|{UNQUOTED}|=|\[=*{LEGACY})({LEGACY}|[[=])* {
+  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+
+\[ {
+  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+
+\" {
+  lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
+  cmListFileLexerSetToken(lexer, "", 0);
+  lexer->column += yyleng;
+  BEGIN(STRING);
+}
+
+<STRING>([^\\\n\"]|\\.)+ {
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+}
+
+<STRING>\\\n {
+  /* Continuation: text is not part of string */
+  ++lexer->line;
+  lexer->column = 1;
+}
+
+<STRING>\n {
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  ++lexer->line;
+  lexer->column = 1;
+}
+
+<STRING>\" {
+  lexer->column += yyleng;
+  BEGIN(INITIAL);
+  return 1;
+}
+
+<STRING>. {
+  cmListFileLexerAppend(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+}
+
+<STRING><<EOF>> {
+  lexer->token.type = cmListFileLexer_Token_BadString;
+  BEGIN(INITIAL);
+  return 1;
+}
+
+[ \t\r]+ {
+  lexer->token.type = cmListFileLexer_Token_Space;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+
+. {
+  lexer->token.type = cmListFileLexer_Token_BadCharacter;
+  cmListFileLexerSetToken(lexer, yytext, yyleng);
+  lexer->column += yyleng;
+  return 1;
+}
+
+<<EOF>> {
+  lexer->token.type = cmListFileLexer_Token_None;
+  cmListFileLexerSetToken(lexer, 0, 0);
+  return 0;
+}
+
+%%
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
+                                    int length)
+{
+  /* Set the token line and column number.  */
+  lexer->token.line = lexer->line;
+  lexer->token.column = lexer->column;
+
+  /* Use the same buffer if possible.  */
+  if (lexer->token.text) {
+    if (text && length < lexer->size) {
+      strcpy(lexer->token.text, text);
+      lexer->token.length = length;
+      return;
+    }
+    free(lexer->token.text);
+    lexer->token.text = 0;
+    lexer->size = 0;
+  }
+
+  /* Need to extend the buffer.  */
+  if (text) {
+    lexer->token.text = strdup(text);
+    lexer->token.length = length;
+    lexer->size = length + 1;
+  } else {
+    lexer->token.length = 0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
+                                  int length)
+{
+  char* temp;
+  int newSize;
+
+  /* If the appended text will fit in the buffer, do not reallocate.  */
+  newSize = lexer->token.length + length + 1;
+  if (lexer->token.text && newSize <= lexer->size) {
+    strcpy(lexer->token.text + lexer->token.length, text);
+    lexer->token.length += length;
+    return;
+  }
+
+  /* We need to extend the buffer.  */
+  temp = malloc(newSize);
+  if (lexer->token.text) {
+    memcpy(temp, lexer->token.text, lexer->token.length);
+    free(lexer->token.text);
+  }
+  memcpy(temp + lexer->token.length, text, length);
+  temp[lexer->token.length + length] = 0;
+  lexer->token.text = temp;
+  lexer->token.length += length;
+  lexer->size = newSize;
+}
+
+/*--------------------------------------------------------------------------*/
+static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
+                                size_t bufferSize)
+{
+  if (lexer) {
+    if (lexer->file) {
+      /* Convert CRLF -> LF explicitly.  The C FILE "t"ext mode
+         does not convert newlines on all platforms.  Move any
+         trailing CR to the start of the buffer for the next read. */
+      size_t cr = lexer->cr;
+      size_t n;
+      buffer[0] = '\r';
+      n = fread(buffer + cr, 1, bufferSize - cr, lexer->file);
+      if (n) {
+        char* o = buffer;
+        const char* i = buffer;
+        const char* e;
+        n += cr;
+        cr = (buffer[n - 1] == '\r') ? 1 : 0;
+        e = buffer + n - cr;
+        while (i != e) {
+          if (i[0] == '\r' && i[1] == '\n') {
+            ++i;
+          }
+          *o++ = *i++;
+        }
+        n = o - buffer;
+      } else {
+        n = cr;
+        cr = 0;
+      }
+      lexer->cr = cr;
+      return n;
+    } else if (lexer->string_left) {
+      int length = lexer->string_left;
+      if ((int)bufferSize < length) {
+        length = (int)bufferSize;
+      }
+      memcpy(buffer, lexer->string_position, length);
+      lexer->string_position += length;
+      lexer->string_left -= length;
+      return length;
+    }
+  }
+  return 0;
+}
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerInit(cmListFileLexer* lexer)
+{
+  if (lexer->file || lexer->string_buffer) {
+    cmListFileLexer_yylex_init(&lexer->scanner);
+    cmListFileLexer_yyset_extra(lexer, lexer->scanner);
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+static void cmListFileLexerDestroy(cmListFileLexer* lexer)
+{
+  cmListFileLexerSetToken(lexer, 0, 0);
+  if (lexer->file || lexer->string_buffer) {
+    cmListFileLexer_yylex_destroy(lexer->scanner);
+    if (lexer->file) {
+      fclose(lexer->file);
+      lexer->file = 0;
+    }
+    if (lexer->string_buffer) {
+      free(lexer->string_buffer);
+      lexer->string_buffer = 0;
+      lexer->string_left = 0;
+      lexer->string_position = 0;
+    }
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+cmListFileLexer* cmListFileLexer_New(void)
+{
+  cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer));
+  if (!lexer) {
+    return 0;
+  }
+  memset(lexer, 0, sizeof(*lexer));
+  lexer->line = 1;
+  lexer->column = 1;
+  return lexer;
+}
+
+/*--------------------------------------------------------------------------*/
+void cmListFileLexer_Delete(cmListFileLexer* lexer)
+{
+  cmListFileLexer_SetFileName(lexer, 0, 0);
+  free(lexer);
+}
+
+/*--------------------------------------------------------------------------*/
+static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f)
+{
+  unsigned char b[2];
+  if (fread(b, 1, 2, f) == 2) {
+    if (b[0] == 0xEF && b[1] == 0xBB) {
+      if (fread(b, 1, 1, f) == 1 && b[0] == 0xBF) {
+        return cmListFileLexer_BOM_UTF8;
+      }
+    } else if (b[0] == 0xFE && b[1] == 0xFF) {
+      /* UTF-16 BE */
+      return cmListFileLexer_BOM_UTF16BE;
+    } else if (b[0] == 0 && b[1] == 0) {
+      if (fread(b, 1, 2, f) == 2 && b[0] == 0xFE && b[1] == 0xFF) {
+        return cmListFileLexer_BOM_UTF32BE;
+      }
+    } else if (b[0] == 0xFF && b[1] == 0xFE) {
+      fpos_t p;
+      fgetpos(f, &p);
+      if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) {
+        return cmListFileLexer_BOM_UTF32LE;
+      }
+      fsetpos(f, &p);
+      return cmListFileLexer_BOM_UTF16LE;
+    }
+  }
+  rewind(f);
+  return cmListFileLexer_BOM_None;
+}
+
+/*--------------------------------------------------------------------------*/
+int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name,
+                                cmListFileLexer_BOM* bom)
+{
+  int result = 1;
+  cmListFileLexerDestroy(lexer);
+  if (name) {
+#ifdef _WIN32
+    wchar_t* wname = cmsysEncoding_DupToWide(name);
+    lexer->file = _wfopen(wname, L"rb");
+    free(wname);
+#else
+    lexer->file = fopen(name, "rb");
+#endif
+    if (lexer->file) {
+      if (bom) {
+        *bom = cmListFileLexer_ReadBOM(lexer->file);
+      }
+    } else {
+      result = 0;
+    }
+  }
+  cmListFileLexerInit(lexer);
+  return result;
+}
+
+/*--------------------------------------------------------------------------*/
+int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text)
+{
+  int result = 1;
+  cmListFileLexerDestroy(lexer);
+  if (text) {
+    int length = (int)strlen(text);
+    lexer->string_buffer = (char*)malloc(length + 1);
+    if (lexer->string_buffer) {
+      strcpy(lexer->string_buffer, text);
+      lexer->string_position = lexer->string_buffer;
+      lexer->string_left = length;
+    } else {
+      result = 0;
+    }
+  }
+  cmListFileLexerInit(lexer);
+  return result;
+}
+
+/*--------------------------------------------------------------------------*/
+cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer)
+{
+  if (!lexer->file) {
+    return 0;
+  }
+  if (cmListFileLexer_yylex(lexer->scanner, lexer)) {
+    return &lexer->token;
+  } else {
+    cmListFileLexer_SetFileName(lexer, 0, 0);
+    return 0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer)
+{
+  if (lexer->file) {
+    return lexer->line;
+  } else {
+    return 0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer)
+{
+  if (lexer->file) {
+    return lexer->column;
+  } else {
+    return 0;
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
+                                            cmListFileLexer_Type type)
+{
+  (void)lexer;
+  switch (type) {
+    case cmListFileLexer_Token_None:
+      return "nothing";
+    case cmListFileLexer_Token_Space:
+      return "space";
+    case cmListFileLexer_Token_Newline:
+      return "newline";
+    case cmListFileLexer_Token_Identifier:
+      return "identifier";
+    case cmListFileLexer_Token_ParenLeft:
+      return "left paren";
+    case cmListFileLexer_Token_ParenRight:
+      return "right paren";
+    case cmListFileLexer_Token_ArgumentUnquoted:
+      return "unquoted argument";
+    case cmListFileLexer_Token_ArgumentQuoted:
+      return "quoted argument";
+    case cmListFileLexer_Token_ArgumentBracket:
+      return "bracket argument";
+    case cmListFileLexer_Token_CommentBracket:
+      return "bracket comment";
+    case cmListFileLexer_Token_BadCharacter:
+      return "bad character";
+    case cmListFileLexer_Token_BadBracket:
+      return "unterminated bracket";
+    case cmListFileLexer_Token_BadString:
+      return "unterminated string";
+  }
+  return "unknown token";
+}
diff --git a/Source/Modules/FindLibUV.cmake b/Source/Modules/FindLibUV.cmake
index b8cb365..ba13d75 100644
--- a/Source/Modules/FindLibUV.cmake
+++ b/Source/Modules/FindLibUV.cmake
@@ -49,7 +49,7 @@ They may be set by end users to point at libuv components.
 
 #-----------------------------------------------------------------------------
 find_library(LibUV_LIBRARY
-  NAMES uv
+  NAMES uv libuv
   )
 mark_as_advanced(LibUV_LIBRARY)
 
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 10fd718..9e9df78 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -160,6 +160,25 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
 add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE})
 target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES})
 
+# cmake-gui has not been updated for `include-what-you-use`.
+# Block the tool until this is done.
+set_target_properties(cmake-gui PROPERTIES
+  CXX_INCLUDE_WHAT_YOU_USE ""
+  )
+
+# Files generated by MOC, RCC, and UIC may produce clang-tidy warnings.
+# We generate a dummy .clang-tidy file in the binary directory that disables
+# all clang-tidy checks except one that will never match.  This one check is
+# necessary; clang-tidy reports an error when no checks are enabled.
+# Since the Qt code generators will generate source files in the binary tree,
+# clang-tidy will load the configuration from this dummy file when the sources
+# are built.
+file(WRITE "${QtDialog_BINARY_DIR}/.clang-tidy" "
+---
+Checks: '-*,llvm-twine-local'
+...
+")
+
 if(APPLE)
   file(STRINGS "${CMake_SOURCE_DIR}/Copyright.txt" copyright_line
     LIMIT_COUNT 1 REGEX "^Copyright 2000-20[0-9][0-9] Kitware")
@@ -198,7 +217,7 @@ if(UNIX AND NOT APPLE)
 
   # install a desktop file so CMake appears in the application start menu
   # with an icon
-  install(FILES CMake.desktop
+  install(FILES cmake-gui.desktop
     DESTINATION "${CMAKE_XDGDATA_DIR}/applications"
     ${COMPONENT})
   install(FILES cmakecache.xml
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index 5e03c39..7fa2ac6 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -8,6 +8,9 @@
 #include "cmDocumentationEntry.h"
 #include "cmVersion.h"
 #include "cmake.h"
+#include "cmsys/CommandLineArguments.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/SystemTools.hxx"
 #include <QApplication>
 #include <QDir>
 #include <QLocale>
@@ -15,9 +18,6 @@
 #include <QTextCodec>
 #include <QTranslator>
 #include <QtPlugin>
-#include <cmsys/CommandLineArguments.hxx>
-#include <cmsys/Encoding.hxx>
-#include <cmsys/SystemTools.hxx>
 #include <iostream>
 
 #include "cmSystemTools.h" // IWYU pragma: keep
@@ -59,7 +59,7 @@ int main(int argc, char** argv)
   doc.addCMakeStandardDocSections();
   if (argc2 > 1 && doc.CheckOptions(argc2, argv2)) {
     // Construct and print requested documentation.
-    cmake hcm;
+    cmake hcm(cmake::RoleInternal);
     hcm.SetHomeDirectory("");
     hcm.SetHomeOutputDirectory("");
     hcm.AddCMakePaths();
@@ -184,9 +184,9 @@ int main(int argc, char** argv)
 }
 
 #if defined(Q_OS_MAC)
+#include "cm_sys_stat.h"
 #include <errno.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <unistd.h>
 static bool cmOSXInstall(std::string const& dir, std::string const& tool)
 {
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 111b28a..57f8e10 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -990,10 +990,10 @@ void CMakeSetupDialog::removeSelectedCacheEntries()
 {
   QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
   QList<QPersistentModelIndex> pidxs;
-  foreach (QModelIndex i, idxs) {
+  foreach (QModelIndex const& i, idxs) {
     pidxs.append(i);
   }
-  foreach (QPersistentModelIndex pi, pidxs) {
+  foreach (QPersistentModelIndex const& pi, pidxs) {
     this->CacheValues->model()->removeRow(pi.row(), pi.parent());
   }
 }
@@ -1152,7 +1152,7 @@ void CMakeSetupDialog::showUserChanges()
   QString command;
   QString cache;
 
-  foreach (QCMakeProperty prop, changes) {
+  foreach (QCMakeProperty const& prop, changes) {
     QString type;
     switch (prop.Type) {
       case QCMakeProperty::BOOL:
@@ -1175,12 +1175,9 @@ void CMakeSetupDialog::showUserChanges()
       value = prop.Value.toString();
     }
 
-    QString line("%1:%2=");
-    line = line.arg(prop.Key);
-    line = line.arg(type);
-
-    command += QString("-D%1\"%2\" ").arg(line).arg(value);
-    cache += QString("%1%2\n").arg(line).arg(value);
+    QString const line = QString("%1:%2=").arg(prop.Key, type);
+    command += QString("-D%1\"%2\" ").arg(line, value);
+    cache += QString("%1%2\n").arg(line, value);
   }
 
   textedit->append(tr("Commandline options:"));
diff --git a/Source/QtDialog/Compilers.h b/Source/QtDialog/Compilers.h
index 276e2a5..6c8c8f5 100644
--- a/Source/QtDialog/Compilers.h
+++ b/Source/QtDialog/Compilers.h
@@ -3,7 +3,7 @@
 #ifndef COMPILERS_HPP
 #define COMPILERS_HPP
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <QWidget>
 
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx
index 2f1df4f..b193a27 100644
--- a/Source/QtDialog/FirstConfigure.cxx
+++ b/Source/QtDialog/FirstConfigure.cxx
@@ -130,7 +130,7 @@ bool StartCompilerSetup::crossCompilerSetup() const
 void StartCompilerSetup::onSelectionChanged(bool on)
 {
   if (on) {
-    selectionChanged();
+    emit selectionChanged();
   }
 }
 
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index abeff97..d473d9b 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -27,7 +27,7 @@ QCMake::QCMake(QObject* p)
   cmSystemTools::SetStdoutCallback(QCMake::stdoutCallback, this);
   cmSystemTools::SetStderrCallback(QCMake::stderrCallback, this);
 
-  this->CMakeInstance = new cmake;
+  this->CMakeInstance = new cmake(cmake::RoleProject);
   this->CMakeInstance->SetCMakeEditCommand(
     cmSystemTools::GetCMakeGUICommand());
   this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this);
@@ -219,14 +219,14 @@ void QCMake::setProperties(const QCMakePropertyList& newProps)
   }
 
   // remove some properites
-  foreach (QString s, toremove) {
+  foreach (QString const& s, toremove) {
     this->CMakeInstance->UnwatchUnusedCli(s.toLocal8Bit().data());
 
     state->RemoveCacheEntry(s.toLocal8Bit().data());
   }
 
   // add some new properites
-  foreach (QCMakeProperty s, props) {
+  foreach (QCMakeProperty const& s, props) {
     this->CMakeInstance->WatchUnusedCli(s.Key.toLocal8Bit().data());
 
     if (s.Type == QCMakeProperty::BOOL) {
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
index 12f6037..e14cdf2 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -3,7 +3,7 @@
 #ifndef QCMake_h
 #define QCMake_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmake.h"
 
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
index 9f5208a..08c2d58 100644
--- a/Source/QtDialog/QCMakeCacheView.cxx
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -47,7 +47,7 @@ protected:
     }
 
     // check all strings for a match
-    foreach (QString str, strs) {
+    foreach (QString const& str, strs) {
       if (str.contains(this->filterRegExp())) {
         return true;
       }
@@ -236,12 +236,12 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
     qSort(newP);
     qSort(newP2);
     int row_count = 0;
-    foreach (QCMakeProperty p, newP) {
+    foreach (QCMakeProperty const& p, newP) {
       this->insertRow(row_count);
       this->setPropertyData(this->index(row_count, 0), p, true);
       row_count++;
     }
-    foreach (QCMakeProperty p, newP2) {
+    foreach (QCMakeProperty const& p, newP2) {
       this->insertRow(row_count);
       this->setPropertyData(this->index(row_count, 0), p, false);
       row_count++;
@@ -254,8 +254,11 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
 
     QStandardItem* root = this->invisibleRootItem();
 
-    foreach (QString key, newPropsTree.keys()) {
-      QCMakePropertyList props2 = newPropsTree[key];
+    for (QMap<QString, QCMakePropertyList>::const_iterator iter =
+           newPropsTree.begin();
+         iter != newPropsTree.end(); ++iter) {
+      QString const& key = iter.key();
+      QCMakePropertyList const& props2 = iter.value();
 
       QList<QStandardItem*> parentItems;
       parentItems.append(
@@ -280,8 +283,11 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
       }
     }
 
-    foreach (QString key, newPropsTree2.keys()) {
-      QCMakePropertyList props2 = newPropsTree2[key];
+    for (QMap<QString, QCMakePropertyList>::const_iterator iter =
+           newPropsTree2.begin();
+         iter != newPropsTree2.end(); ++iter) {
+      QString const& key = iter.key();
+      QCMakePropertyList const& props2 = iter.value();
 
       QStandardItem* parentItem =
         new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key);
@@ -393,7 +399,7 @@ void QCMakeCacheModel::breakProperties(
 {
   QMap<QString, QCMakePropertyList> tmp;
   // return a map of properties grouped by prefixes, and sorted
-  foreach (QCMakeProperty p, props) {
+  foreach (QCMakeProperty const& p, props) {
     QString prefix = QCMakeCacheModel::prefix(p.Key);
     tmp[prefix].append(p);
   }
@@ -423,7 +429,7 @@ QCMakePropertyList QCMakeCacheModel::properties() const
     return props;
   }
 
-  QList<QModelIndex> idxs;
+  QVector<QModelIndex> idxs;
   idxs.append(this->index(0, 0));
 
   // walk the entire model for property entries
@@ -448,7 +454,7 @@ QCMakePropertyList QCMakeCacheModel::properties() const
                (idxs.last().row() + 1) >= rowCount(idxs.last().parent()) ||
 #endif
                !idxs.last().sibling(idxs.last().row() + 1, 0).isValid())) {
-        idxs.removeLast();
+        idxs.remove(idxs.size() - 1);
       }
       if (!idxs.isEmpty()) {
         idxs.last() = idxs.last().sibling(idxs.last().row() + 1, 0);
diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx
index 6a55a76..7f0cafa 100644
--- a/Source/QtDialog/QCMakeWidgets.cxx
+++ b/Source/QtDialog/QCMakeWidgets.cxx
@@ -54,11 +54,11 @@ void QCMakeFilePathEditor::chooseFile()
     title = tr("Select File for %1");
     title = title.arg(this->Variable);
   }
-  this->fileDialogExists(true);
+  emit this->fileDialogExists(true);
   path =
     QFileDialog::getOpenFileName(this, title, info.absolutePath(), QString(),
                                  CM_NULLPTR, QFileDialog::DontResolveSymlinks);
-  this->fileDialogExists(false);
+  emit this->fileDialogExists(false);
 
   if (!path.isEmpty()) {
     this->setText(QDir::fromNativeSeparators(path));
@@ -76,11 +76,11 @@ void QCMakePathEditor::chooseFile()
     title = tr("Select Path for %1");
     title = title.arg(this->Variable);
   }
-  this->fileDialogExists(true);
+  emit this->fileDialogExists(true);
   path = QFileDialog::getExistingDirectory(this, title, this->text(),
                                            QFileDialog::ShowDirsOnly |
                                              QFileDialog::DontResolveSymlinks);
-  this->fileDialogExists(false);
+  emit this->fileDialogExists(false);
   if (!path.isEmpty()) {
     this->setText(QDir::fromNativeSeparators(path));
   }
diff --git a/Source/QtDialog/QCMakeWidgets.h b/Source/QtDialog/QCMakeWidgets.h
index 0db810c..1ec666f 100644
--- a/Source/QtDialog/QCMakeWidgets.h
+++ b/Source/QtDialog/QCMakeWidgets.h
@@ -3,7 +3,7 @@
 #ifndef QCMakeWidgets_h
 #define QCMakeWidgets_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <QComboBox>
 #include <QCompleter>
diff --git a/Source/QtDialog/RegexExplorer.h b/Source/QtDialog/RegexExplorer.h
index caef975..8679892 100644
--- a/Source/QtDialog/RegexExplorer.h
+++ b/Source/QtDialog/RegexExplorer.h
@@ -3,8 +3,8 @@
 #ifndef RegexExplorer_h
 #define RegexExplorer_h
 
+#include "cmsys/RegularExpression.hxx"
 #include <QDialog>
-#include <cmsys/RegularExpression.hxx>
 #include <string>
 
 #include "ui_RegexExplorer.h"
diff --git a/Source/QtDialog/CMake.desktop b/Source/QtDialog/cmake-gui.desktop
similarity index 100%
rename from Source/QtDialog/CMake.desktop
rename to Source/QtDialog/cmake-gui.desktop
diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx
index eded883..e96226a 100644
--- a/Source/bindexplib.cxx
+++ b/Source/bindexplib.cxx
@@ -63,86 +63,93 @@
 */
 #include "bindexplib.h"
 
-#include <cmsys/Encoding.hxx>
-#include <fstream>
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
 #include <iostream>
 #include <windows.h>
 
-typedef struct cmANON_OBJECT_HEADER_BIGOBJ {
-   /* same as ANON_OBJECT_HEADER_V2 */
-    WORD    Sig1;            // Must be IMAGE_FILE_MACHINE_UNKNOWN
-    WORD    Sig2;            // Must be 0xffff
-    WORD    Version;         // >= 2 (implies the Flags field is present)
-    WORD    Machine;         // Actual machine - IMAGE_FILE_MACHINE_xxx
-    DWORD   TimeDateStamp;
-    CLSID   ClassID;         // {D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8}
-    DWORD   SizeOfData;      // Size of data that follows the header
-    DWORD   Flags;           // 0x1 -> contains metadata
-    DWORD   MetaDataSize;    // Size of CLR metadata
-    DWORD   MetaDataOffset;  // Offset of CLR metadata
+#ifndef IMAGE_FILE_MACHINE_ARMNT
+#define IMAGE_FILE_MACHINE_ARMNT 0x01c4
+#endif
 
-    /* bigobj specifics */
-    DWORD   NumberOfSections; // extended from WORD
-    DWORD   PointerToSymbolTable;
-    DWORD   NumberOfSymbols;
+typedef struct cmANON_OBJECT_HEADER_BIGOBJ
+{
+  /* same as ANON_OBJECT_HEADER_V2 */
+  WORD Sig1;    // Must be IMAGE_FILE_MACHINE_UNKNOWN
+  WORD Sig2;    // Must be 0xffff
+  WORD Version; // >= 2 (implies the Flags field is present)
+  WORD Machine; // Actual machine - IMAGE_FILE_MACHINE_xxx
+  DWORD TimeDateStamp;
+  CLSID ClassID;        // {D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8}
+  DWORD SizeOfData;     // Size of data that follows the header
+  DWORD Flags;          // 0x1 -> contains metadata
+  DWORD MetaDataSize;   // Size of CLR metadata
+  DWORD MetaDataOffset; // Offset of CLR metadata
+
+  /* bigobj specifics */
+  DWORD NumberOfSections; // extended from WORD
+  DWORD PointerToSymbolTable;
+  DWORD NumberOfSymbols;
 } cmANON_OBJECT_HEADER_BIGOBJ;
 
-typedef struct _cmIMAGE_SYMBOL_EX {
-    union {
-        BYTE     ShortName[8];
-        struct {
-            DWORD   Short;     // if 0, use LongName
-            DWORD   Long;      // offset into string table
-        } Name;
-        DWORD   LongName[2];    // PBYTE  [2]
-    } N;
-    DWORD   Value;
-    LONG    SectionNumber;
-    WORD    Type;
-    BYTE    StorageClass;
-    BYTE    NumberOfAuxSymbols;
+typedef struct _cmIMAGE_SYMBOL_EX
+{
+  union
+  {
+    BYTE ShortName[8];
+    struct
+    {
+      DWORD Short; // if 0, use LongName
+      DWORD Long;  // offset into string table
+    } Name;
+    DWORD LongName[2]; // PBYTE  [2]
+  } N;
+  DWORD Value;
+  LONG SectionNumber;
+  WORD Type;
+  BYTE StorageClass;
+  BYTE NumberOfAuxSymbols;
 } cmIMAGE_SYMBOL_EX;
-typedef cmIMAGE_SYMBOL_EX UNALIGNED *cmPIMAGE_SYMBOL_EX;
+typedef cmIMAGE_SYMBOL_EX UNALIGNED* cmPIMAGE_SYMBOL_EX;
 
-PIMAGE_SECTION_HEADER GetSectionHeaderOffset(PIMAGE_FILE_HEADER
-                                             pImageFileHeader)
+PIMAGE_SECTION_HEADER GetSectionHeaderOffset(
+  PIMAGE_FILE_HEADER pImageFileHeader)
 {
-  return (PIMAGE_SECTION_HEADER)
-    ((DWORD_PTR)pImageFileHeader +
-     IMAGE_SIZEOF_FILE_HEADER +
-     pImageFileHeader->SizeOfOptionalHeader);
+  return (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageFileHeader +
+                                 IMAGE_SIZEOF_FILE_HEADER +
+                                 pImageFileHeader->SizeOfOptionalHeader);
 }
 
-PIMAGE_SECTION_HEADER GetSectionHeaderOffset(cmANON_OBJECT_HEADER_BIGOBJ*
-                                             pImageFileHeader)
+PIMAGE_SECTION_HEADER GetSectionHeaderOffset(
+  cmANON_OBJECT_HEADER_BIGOBJ* pImageFileHeader)
 {
-  return (PIMAGE_SECTION_HEADER)
-      ((DWORD_PTR)pImageFileHeader          +
-       sizeof(cmANON_OBJECT_HEADER_BIGOBJ));
+  return (PIMAGE_SECTION_HEADER)((DWORD_PTR)pImageFileHeader +
+                                 sizeof(cmANON_OBJECT_HEADER_BIGOBJ));
 }
 
 /*
 + * Utility func, strstr with size
 + */
-const char* StrNStr(const char* start, const char* find, size_t &size) {
-   size_t len;
-   const char* hint;
+const char* StrNStr(const char* start, const char* find, size_t& size)
+{
+  size_t len;
+  const char* hint;
 
-   if (!start || !find || !size) {
-      size = 0;
-      return 0;
-   }
-   len = strlen(find);
+  if (!start || !find || !size) {
+    size = 0;
+    return 0;
+  }
+  len = strlen(find);
 
-   while ((hint = (const char*) memchr(start, find[0], size-len+1))) {
-      size -= (hint - start);
-      if (!strncmp(hint, find, len))
-         return hint;
-      start = hint + 1;
-   }
+  while ((hint = (const char*)memchr(start, find[0], size - len + 1))) {
+    size -= (hint - start);
+    if (!strncmp(hint, find, len))
+      return hint;
+    start = hint + 1;
+  }
 
-   size = 0;
-   return 0;
+  size = 0;
+  return 0;
 }
 
 template <
@@ -162,68 +169,18 @@ public:
    *----------------------------------------------------------------------
    */
 
-   DumpSymbols(ObjectHeaderType* ih,
-               std::set<std::string>& symbols,
-               std::set<std::string>& dataSymbols,
-               bool is64)
-     :Symbols(symbols), DataSymbols(dataSymbols)
-    {
-      this->ObjectImageHeader = ih;
-      this->SymbolTable = (SymbolTableType*)
-      ((DWORD_PTR)this->ObjectImageHeader
-       + this->ObjectImageHeader->PointerToSymbolTable);
-      this->SectionHeaders =
-        GetSectionHeaderOffset(this->ObjectImageHeader);
-      this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols;
-      this->Is64Bit = is64;
-   }
-
-  /*
-   *----------------------------------------------------------------------
-   * HaveExportedObjects --
-   *
-   *      Returns true if export directives (declspec(dllexport)) exist.
-   *
-   *----------------------------------------------------------------------
-   */
-
-  bool HaveExportedObjects() {
-     WORD i = 0;
-     size_t size = 0;
-     const char * rawdata = 0;
-     PIMAGE_SECTION_HEADER pDirectivesSectionHeader = 0;
-     PIMAGE_SECTION_HEADER pSectionHeaders = this->SectionHeaders;
-     for(i = 0; (i < this->ObjectImageHeader->NumberOfSections &&
-                 !pDirectivesSectionHeader); i++)
-       if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8))
-         pDirectivesSectionHeader = &pSectionHeaders[i];
-     if (!pDirectivesSectionHeader) return 0;
-
-     rawdata=(const char*)
-       this->ObjectImageHeader+pDirectivesSectionHeader->PointerToRawData;
-     if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0;
-
-     size = pDirectivesSectionHeader->SizeOfRawData;
-     const char* posImportFlag = rawdata;
-     while ((posImportFlag = StrNStr(posImportFlag, " /EXPORT:", size))) {
-       const char* lookingForDict = posImportFlag + 9;
-       if (!strncmp(lookingForDict, "_G__cpp_",8) ||
-           !strncmp(lookingForDict, "_G__set_cpp_",12)) {
-          posImportFlag = lookingForDict;
-          continue;
-       }
-
-       const char* lookingForDATA = posImportFlag + 9;
-       while (*(++lookingForDATA) && *lookingForDATA != ' ');
-       lookingForDATA -= 5;
-       // ignore DATA exports
-       if (strncmp(lookingForDATA, ",DATA", 5)) break;
-       posImportFlag = lookingForDATA + 5;
-     }
-     if(posImportFlag) {
-        return true;
-     }
-     return false;
+  DumpSymbols(ObjectHeaderType* ih, std::set<std::string>& symbols,
+              std::set<std::string>& dataSymbols, bool isI386)
+    : Symbols(symbols)
+    , DataSymbols(dataSymbols)
+  {
+    this->ObjectImageHeader = ih;
+    this->SymbolTable =
+      (SymbolTableType*)((DWORD_PTR) this->ObjectImageHeader +
+                         this->ObjectImageHeader->PointerToSymbolTable);
+    this->SectionHeaders = GetSectionHeaderOffset(this->ObjectImageHeader);
+    this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols;
+    this->IsI386 = isI386;
   }
 
   /*
@@ -233,9 +190,7 @@ public:
    *      Dump an object file's exported symbols.
    *----------------------------------------------------------------------
    */
-  void DumpObjFile() {
-    this->DumpExternalsObjects();
-  }
+  void DumpObjFile() { this->DumpExternalsObjects(); }
 
   /*
    *----------------------------------------------------------------------
@@ -244,7 +199,8 @@ public:
    *      Dumps a COFF symbol table from an OBJ.
    *----------------------------------------------------------------------
    */
-  void DumpExternalsObjects() {
+  void DumpExternalsObjects()
+  {
     unsigned i;
     PSTR stringTable;
     std::string symbol;
@@ -252,82 +208,65 @@ public:
     /*
      * The string table apparently starts right after the symbol table
      */
-    stringTable = (PSTR)&this->SymbolTable[this->SymbolCount];
+    stringTable = (PSTR) & this->SymbolTable[this->SymbolCount];
     SymbolTableType* pSymbolTable = this->SymbolTable;
-    for ( i=0; i < this->SymbolCount; i++ ) {
+    for (i = 0; i < this->SymbolCount; i++) {
       if (pSymbolTable->SectionNumber > 0 &&
-          ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) {
-         if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
-            /*
-            *    The name of the Function entry points
-            */
-            if (pSymbolTable->N.Name.Short != 0) {
-               symbol = "";
-               symbol.insert(0, (const char *)pSymbolTable->N.ShortName, 8);
-            } else {
-               symbol = stringTable + pSymbolTable->N.Name.Long;
-            }
+          (pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) {
+        if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
+          /*
+          *    The name of the Function entry points
+          */
+          if (pSymbolTable->N.Name.Short != 0) {
+            symbol = "";
+            symbol.insert(0, (const char*)pSymbolTable->N.ShortName, 8);
+          } else {
+            symbol = stringTable + pSymbolTable->N.Name.Long;
+          }
 
-            // clear out any leading spaces
-            while (isspace(symbol[0])) symbol.erase(0,1);
-            // if it starts with _ and has an @ then it is a __cdecl
-            // so remove the @ stuff for the export
-            if(symbol[0] == '_') {
-               std::string::size_type posAt = symbol.find('@');
-               if (posAt != std::string::npos) {
-                  symbol.erase(posAt);
-               }
+          // clear out any leading spaces
+          while (isspace(symbol[0]))
+            symbol.erase(0, 1);
+          // if it starts with _ and has an @ then it is a __cdecl
+          // so remove the @ stuff for the export
+          if (symbol[0] == '_') {
+            std::string::size_type posAt = symbol.find('@');
+            if (posAt != std::string::npos) {
+              symbol.erase(posAt);
             }
-            // For 64 bit builds we don't need to remove _
-            if(!this->Is64Bit)
-              {
-              if (symbol[0] == '_')
-                {
-                symbol.erase(0,1);
+          }
+          // For i386 builds we need to remove _
+          if (this->IsI386 && symbol[0] == '_') {
+            symbol.erase(0, 1);
+          }
+
+          // Check whether it is "Scalar deleting destructor" and "Vector
+          // deleting destructor"
+          // if scalarPrefix and vectorPrefix are not found then print
+          // the symbol
+          const char* scalarPrefix = "??_G";
+          const char* vectorPrefix = "??_E";
+          // The original code had a check for
+          //     symbol.find("real@") == std::string::npos)
+          // but this disallows member functions with the name "real".
+          if (symbol.compare(0, 4, scalarPrefix) &&
+              symbol.compare(0, 4, vectorPrefix)) {
+            SectChar = this->SectionHeaders[pSymbolTable->SectionNumber - 1]
+                         .Characteristics;
+            // skip symbols containing a dot
+            if (symbol.find('.') == std::string::npos) {
+              if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) {
+                // Read only (i.e. constants) must be excluded
+                this->DataSymbols.insert(symbol);
+              } else {
+                if (pSymbolTable->Type || !(SectChar & IMAGE_SCN_MEM_READ) ||
+                    (SectChar & IMAGE_SCN_MEM_EXECUTE)) {
+                  this->Symbols.insert(symbol);
                 }
               }
-            /*
-            Check whether it is "Scalar deleting destructor" and
-            "Vector deleting destructor"
-            */
-            const char *scalarPrefix = "??_G";
-            const char *vectorPrefix = "??_E";
-            // original code had a check for
-            // symbol.find("real@") == std::string::npos)
-            // but if this disallows memmber functions with the name real
-            // if scalarPrefix and vectorPrefix are not found then print
-            // the symbol
-            if (symbol.compare(0, 4, scalarPrefix) &&
-                symbol.compare(0, 4, vectorPrefix) )
-            {
-               SectChar =
-                 this->
-                 SectionHeaders[pSymbolTable->SectionNumber-1].Characteristics;
-               if (!pSymbolTable->Type  && (SectChar & IMAGE_SCN_MEM_WRITE)) {
-                  // Read only (i.e. constants) must be excluded
-                  this->DataSymbols.insert(symbol);
-               } else {
-                  if ( pSymbolTable->Type  ||
-                       !(SectChar & IMAGE_SCN_MEM_READ)) {
-                     this->Symbols.insert(symbol);
-                  } else {
-                     // printf(" strange symbol: %s \n",symbol.c_str());
-                  }
-               }
             }
-         }
-      }
-      else if (pSymbolTable->SectionNumber == IMAGE_SYM_UNDEFINED &&
-               !pSymbolTable->Type && 0) {
-         /*
-         *    The IMPORT global variable entry points
-         */
-         if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
-            symbol = stringTable + pSymbolTable->N.Name.Long;
-            while (isspace(symbol[0]))  symbol.erase(0,1);
-            if (symbol[0] == '_') symbol.erase(0,1);
-            this->DataSymbols.insert(symbol);
-         }
+          }
+        }
       }
 
       /*
@@ -338,111 +277,129 @@ public:
       pSymbolTable++;
     }
   }
+
 private:
   std::set<std::string>& Symbols;
   std::set<std::string>& DataSymbols;
   DWORD_PTR SymbolCount;
   PIMAGE_SECTION_HEADER SectionHeaders;
   ObjectHeaderType* ObjectImageHeader;
-  SymbolTableType*  SymbolTable;
-  bool Is64Bit;
+  SymbolTableType* SymbolTable;
+  bool IsI386;
 };
 
-bool
-DumpFile(const char* filename,
-         std::set<std::string>& symbols,
-         std::set<std::string>& dataSymbols)
+bool DumpFile(const char* filename, std::set<std::string>& symbols,
+              std::set<std::string>& dataSymbols)
 {
-   HANDLE hFile;
-   HANDLE hFileMapping;
-   LPVOID lpFileBase;
-   PIMAGE_DOS_HEADER dosHeader;
+  HANDLE hFile;
+  HANDLE hFileMapping;
+  LPVOID lpFileBase;
+  PIMAGE_DOS_HEADER dosHeader;
 
-   hFile = CreateFileW(cmsys::Encoding::ToWide(filename).c_str(),
-                       GENERIC_READ, FILE_SHARE_READ, NULL,
-      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+  hFile = CreateFileW(cmsys::Encoding::ToWide(filename).c_str(), GENERIC_READ,
+                      FILE_SHARE_READ, NULL, OPEN_EXISTING,
+                      FILE_ATTRIBUTE_NORMAL, 0);
 
-   if (hFile == INVALID_HANDLE_VALUE) {
-      fprintf(stderr, "Couldn't open file '%s' with CreateFile()\n", filename);
-      return false;
-   }
+  if (hFile == INVALID_HANDLE_VALUE) {
+    fprintf(stderr, "Couldn't open file '%s' with CreateFile()\n", filename);
+    return false;
+  }
 
-   hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
-   if (hFileMapping == 0) {
-      CloseHandle(hFile);
-      fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
-      return false;
-   }
+  hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+  if (hFileMapping == 0) {
+    CloseHandle(hFile);
+    fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
+    return false;
+  }
 
-   lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
-   if (lpFileBase == 0) {
-      CloseHandle(hFileMapping);
-      CloseHandle(hFile);
-      fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
-      return false;
-   }
+  lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
+  if (lpFileBase == 0) {
+    CloseHandle(hFileMapping);
+    CloseHandle(hFile);
+    fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
+    return false;
+  }
 
-   dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
-   if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
-      fprintf(stderr, "File is an executable.  I don't dump those.\n");
-      return false;
-   }
-   /* Does it look like a i386 COFF OBJ file??? */
-   else if (
-           ((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) ||
-            (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64))
-           && (dosHeader->e_sp == 0)
-           ) {
-      /*
-      * The two tests above aren't what they look like.  They're
-      * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
-      * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
-      */
-      DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL>
-        symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, symbols, dataSymbols,
-                     (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64));
+  dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
+  if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
+    fprintf(stderr, "File is an executable.  I don't dump those.\n");
+    return false;
+  }
+  /* Does it look like a COFF OBJ file??? */
+  else if (((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) ||
+            (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64) ||
+            (dosHeader->e_magic == IMAGE_FILE_MACHINE_ARMNT)) &&
+           (dosHeader->e_sp == 0)) {
+    /*
+    * The two tests above aren't what they look like.  They're
+    * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
+    * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
+    */
+    DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL> symbolDumper(
+      (PIMAGE_FILE_HEADER)lpFileBase, symbols, dataSymbols,
+      (dosHeader->e_magic == IMAGE_FILE_MACHINE_I386));
+    symbolDumper.DumpObjFile();
+  } else {
+    // check for /bigobj format
+    cmANON_OBJECT_HEADER_BIGOBJ* h = (cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase;
+    if (h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
+      DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX> symbolDumper(
+        (cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase, symbols, dataSymbols,
+        (h->Machine == IMAGE_FILE_MACHINE_I386));
       symbolDumper.DumpObjFile();
-   } else {
-      // check for /bigobj format
-      cmANON_OBJECT_HEADER_BIGOBJ* h =
-        (cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase;
-      if(h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
-         DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX>
-           symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, symbols,
-                        dataSymbols,
-                        (h->Machine == IMAGE_FILE_MACHINE_AMD64));
-         symbolDumper.DumpObjFile();
-      } else {
-         printf("unrecognized file format in '%s'\n", filename);
-         return false;
-      }
-   }
-   UnmapViewOfFile(lpFileBase);
-   CloseHandle(hFileMapping);
-   CloseHandle(hFile);
-   return true;
+    } else {
+      printf("unrecognized file format in '%s'\n", filename);
+      return false;
+    }
+  }
+  UnmapViewOfFile(lpFileBase);
+  CloseHandle(hFileMapping);
+  CloseHandle(hFile);
+  return true;
 }
 
 bool bindexplib::AddObjectFile(const char* filename)
 {
-  if(!DumpFile(filename, this->Symbols, this->DataSymbols))
-    {
+  return DumpFile(filename, this->Symbols, this->DataSymbols);
+}
+
+bool bindexplib::AddDefinitionFile(const char* filename)
+{
+  cmsys::ifstream infile(filename);
+  if (!infile) {
+    fprintf(stderr, "Couldn't open definition file '%s'\n", filename);
     return false;
+  }
+  std::string str;
+  while (std::getline(infile, str)) {
+    // skip the LIBRAY and EXPORTS lines (if any)
+    if ((str.compare(0, 7, "LIBRARY") == 0) ||
+        (str.compare(0, 7, "EXPORTS") == 0)) {
+      continue;
+    }
+    // remove leading tabs & spaces
+    str.erase(0, str.find_first_not_of(" \t"));
+    std::size_t found = str.find(" \t DATA");
+    if (found != std::string::npos) {
+      str.erase(found, std::string::npos);
+      this->DataSymbols.insert(str);
+    } else {
+      this->Symbols.insert(str);
     }
+  }
+  infile.close();
   return true;
 }
 
 void bindexplib::WriteFile(FILE* file)
 {
-  fprintf(file,"EXPORTS \n");
-  for(std::set<std::string>::const_iterator i = this->DataSymbols.begin();
-      i!= this->DataSymbols.end(); ++i)
-    {
+  fprintf(file, "EXPORTS \n");
+  for (std::set<std::string>::const_iterator i = this->DataSymbols.begin();
+       i != this->DataSymbols.end(); ++i) {
     fprintf(file, "\t%s \t DATA\n", i->c_str());
-    }
-  for(std::set<std::string>::const_iterator i = this->Symbols.begin();
-      i!= this->Symbols.end(); ++i)
-    {
+  }
+  for (std::set<std::string>::const_iterator i = this->Symbols.begin();
+       i != this->Symbols.end(); ++i) {
     fprintf(file, "\t%s\n", i->c_str());
-    }
+  }
 }
diff --git a/Source/bindexplib.h b/Source/bindexplib.h
index d6900ba..bc904e9 100644
--- a/Source/bindexplib.h
+++ b/Source/bindexplib.h
@@ -3,7 +3,7 @@
 #ifndef bindexplib_h
 #define bindexplib_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <set>
 #include <stdio.h>
@@ -13,8 +13,10 @@ class bindexplib
 {
 public:
   bindexplib() {}
+  bool AddDefinitionFile(const char* filename);
   bool AddObjectFile(const char* filename);
   void WriteFile(FILE* file);
+
 private:
   std::set<std::string> Symbols;
   std::set<std::string> DataSymbols;
diff --git a/Source/cmAddCompileOptionsCommand.h b/Source/cmAddCompileOptionsCommand.h
index 71009b4..297f901 100644
--- a/Source/cmAddCompileOptionsCommand.h
+++ b/Source/cmAddCompileOptionsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmAddCompileOptionsCommand_h
 #define cmAddCompileOptionsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -25,11 +26,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_compile_options"; }
 };
 
 #endif
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index a100617..b5e7c9e 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -369,7 +369,7 @@ bool cmAddCustomCommandCommand::CheckOutputs(
 
     // Make sure the output file name has no invalid characters.
     std::string::size_type pos = o->find_first_of("#<>");
-    if (pos != o->npos) {
+    if (pos != std::string::npos) {
       std::ostringstream msg;
       msg << "called with OUTPUT containing a \"" << (*o)[pos]
           << "\".  This character is not allowed.";
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index ea92163..c3a91b2 100644
--- a/Source/cmAddCustomCommandCommand.h
+++ b/Source/cmAddCustomCommandCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmAddCustomCommandCommand_h
 #define cmAddCustomCommandCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_custom_command"; }
-
 protected:
   bool CheckOutputs(const std::vector<std::string>& outputs);
 };
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index 0d01493..87e1147 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -24,10 +24,10 @@ bool cmAddCustomTargetCommand::InitialPass(
     return false;
   }
 
-  std::string targetName = args[0];
+  std::string const& targetName = args[0];
 
   // Check the target name.
-  if (targetName.find_first_of("/\\") != targetName.npos) {
+  if (targetName.find_first_of("/\\") != std::string::npos) {
     std::ostringstream e;
     e << "called with invalid target name \"" << targetName
       << "\".  Target names may not contain a slash.  "
@@ -144,7 +144,7 @@ bool cmAddCustomTargetCommand::InitialPass(
   }
 
   std::string::size_type pos = targetName.find_first_of("#<>");
-  if (pos != targetName.npos) {
+  if (pos != std::string::npos) {
     std::ostringstream msg;
     msg << "called with target name containing a \"" << targetName[pos]
         << "\".  This character is not allowed.";
diff --git a/Source/cmAddCustomTargetCommand.h b/Source/cmAddCustomTargetCommand.h
index b679247..7229c27 100644
--- a/Source/cmAddCustomTargetCommand.h
+++ b/Source/cmAddCustomTargetCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmAddCustomTargetCommand_h
 #define cmAddCustomTargetCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_custom_target"; }
 };
 
 #endif
diff --git a/Source/cmAddDefinitionsCommand.h b/Source/cmAddDefinitionsCommand.h
index 735f8cc..abf5a59 100644
--- a/Source/cmAddDefinitionsCommand.h
+++ b/Source/cmAddDefinitionsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmAddDefinitionsCommand_h
 #define cmAddDefinitionsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,11 +32,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_definitions"; }
 };
 
 #endif
diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx
index e49d5d5..a73b57e 100644
--- a/Source/cmAddDependenciesCommand.cxx
+++ b/Source/cmAddDependenciesCommand.cxx
@@ -19,7 +19,7 @@ bool cmAddDependenciesCommand::InitialPass(
     return false;
   }
 
-  std::string target_name = args[0];
+  std::string const& target_name = args[0];
   if (this->Makefile->IsAlias(target_name)) {
     std::ostringstream e;
     e << "Cannot add target-level dependencies to alias target \""
diff --git a/Source/cmAddDependenciesCommand.h b/Source/cmAddDependenciesCommand.h
index 8be546c..c7328d6 100644
--- a/Source/cmAddDependenciesCommand.h
+++ b/Source/cmAddDependenciesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmDependenciessCommand_h
 #define cmDependenciessCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,11 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_dependencies"; }
 };
 
 #endif
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index aae1085..1d0376f 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -24,7 +24,7 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
   }
   std::vector<std::string>::const_iterator s = args.begin();
 
-  std::string exename = *s;
+  std::string const& exename = *s;
 
   ++s;
   bool use_win32 = false;
diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h
index 62583d8..8100da1 100644
--- a/Source/cmAddExecutableCommand.h
+++ b/Source/cmAddExecutableCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmExecutablesCommand_h
 #define cmExecutablesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,11 +32,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_executable"; }
 };
 
 #endif
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index 9ae4ace..ebf1763 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -37,7 +37,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
 
   std::vector<std::string>::const_iterator s = args.begin();
 
-  std::string libName = *s;
+  std::string const& libName = *s;
 
   ++s;
 
@@ -297,10 +297,15 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
       return false;
     }
     if (type == cmStateEnums::OBJECT_LIBRARY) {
-      this->Makefile->IssueMessage(
-        cmake::FATAL_ERROR,
-        "The OBJECT library type may not be used for IMPORTED libraries.");
-      return true;
+      std::string reason;
+      if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
+            &reason)) {
+        this->Makefile->IssueMessage(
+          cmake::FATAL_ERROR,
+          "The OBJECT library type may not be used for IMPORTED libraries" +
+            reason + ".");
+        return true;
+      }
     }
     if (type == cmStateEnums::INTERFACE_LIBRARY) {
       if (!cmGeneratorExpression::IsValidTargetName(libName)) {
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index c23b299..df49fae 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmLibrarysCommand_h
 #define cmLibrarysCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,11 +32,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_library"; }
 };
 
 #endif
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index 34ec0e3..1727ca5 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -20,7 +20,7 @@ bool cmAddSubDirectoryCommand::InitialPass(
   }
 
   // store the binpath
-  std::string srcArg = args[0];
+  std::string const& srcArg = args[0];
   std::string binArg;
 
   bool excludeFromAll = false;
@@ -32,7 +32,8 @@ bool cmAddSubDirectoryCommand::InitialPass(
     if (*i == "EXCLUDE_FROM_ALL") {
       excludeFromAll = true;
       continue;
-    } else if (binArg.empty()) {
+    }
+    if (binArg.empty()) {
       binArg = *i;
     } else {
       this->SetError("called with incorrect number of arguments");
diff --git a/Source/cmAddSubDirectoryCommand.h b/Source/cmAddSubDirectoryCommand.h
index 85305e6..0e71ffd 100644
--- a/Source/cmAddSubDirectoryCommand.h
+++ b/Source/cmAddSubDirectoryCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmAddSubDirectoryCommand_h
 #define cmAddSubDirectoryCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_subdirectory"; }
 };
 
 #endif
diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h
index 07eff68..a098a03 100644
--- a/Source/cmAddTestCommand.h
+++ b/Source/cmAddTestCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmAddTestCommand_h
 #define cmAddTestCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,11 +32,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "add_test"; }
-
 private:
   bool HandleNameMode(std::vector<std::string> const& args);
 };
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index 7c683ad..4adfe23 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -3,10 +3,10 @@
 #ifndef cmAlgorithms_h
 #define cmAlgorithms_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cm_kwiml.h"
 #include <algorithm>
-#include <cm_kwiml.h>
 #include <functional>
 #include <iterator>
 #include <sstream>
@@ -101,6 +101,12 @@ FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last)
   return first;
 }
 
+template <typename Container, typename Predicate>
+void cmEraseIf(Container& cont, Predicate pred)
+{
+  cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end());
+}
+
 namespace ContainerAlgorithms {
 
 template <typename T>
@@ -354,7 +360,8 @@ std::string cmWrap(std::string const& prefix, Range const& r,
 }
 
 template <typename Range>
-std::string cmWrap(char prefix, Range const& r, char suffix, std::string sep)
+std::string cmWrap(char prefix, Range const& r, char suffix,
+                   std::string const& sep)
 {
   return cmWrap(std::string(1, prefix), r, std::string(1, suffix), sep);
 }
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 879c2ca..0f13b11 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -5,10 +5,10 @@
 #include "cmLocale.h"
 #include "cmSystemTools.h"
 #include "cm_get_date.h"
-#include <cm_libarchive.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/Encoding.hxx>
-#include <cmsys/FStream.hxx>
+#include "cm_libarchive.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
 #include <iostream>
 #include <string.h>
 #include <time.h>
diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h
index 27c62b9..4c85c0d 100644
--- a/Source/cmArchiveWrite.h
+++ b/Source/cmArchiveWrite.h
@@ -3,7 +3,7 @@
 #ifndef cmArchiveWrite_h
 #define cmArchiveWrite_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
 #include <stddef.h>
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index 7cfa4d8..847a416 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmAuxSourceDirectoryCommand.h"
 
+#include "cmsys/Directory.hxx"
 #include <algorithm>
-#include <cmsys/Directory.hxx>
 #include <stddef.h>
 
 #include "cmAlgorithms.h"
@@ -18,13 +18,13 @@ class cmExecutionStatus;
 bool cmAuxSourceDirectoryCommand::InitialPass(
   std::vector<std::string> const& args, cmExecutionStatus&)
 {
-  if (args.size() < 2 || args.size() > 2) {
+  if (args.size() != 2) {
     this->SetError("called with incorrect number of arguments");
     return false;
   }
 
   std::string sourceListValue;
-  std::string templateDirectory = args[0];
+  std::string const& templateDirectory = args[0];
   std::string tdir;
   if (!cmSystemTools::FileIsFullPath(templateDirectory.c_str())) {
     tdir = this->Makefile->GetCurrentSourceDirectory();
@@ -54,7 +54,7 @@ bool cmAuxSourceDirectoryCommand::InitialPass(
         std::string ext = file.substr(dotpos + 1);
         std::string base = file.substr(0, dotpos);
         // Process only source files
-        std::vector<std::string> srcExts =
+        std::vector<std::string> const& srcExts =
           this->Makefile->GetCMakeInstance()->GetSourceExtensions();
         if (!base.empty() &&
             std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) {
diff --git a/Source/cmAuxSourceDirectoryCommand.h b/Source/cmAuxSourceDirectoryCommand.h
index d99bf7b..e49e861 100644
--- a/Source/cmAuxSourceDirectoryCommand.h
+++ b/Source/cmAuxSourceDirectoryCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmAuxSourceDirectoryCommand_h
 #define cmAuxSourceDirectoryCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -34,11 +35,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "aux_source_directory"; }
 };
 
 #endif
diff --git a/Source/cmBase32.cxx b/Source/cmBase32.cxx
index 091d619..1dac212 100644
--- a/Source/cmBase32.cxx
+++ b/Source/cmBase32.cxx
@@ -58,7 +58,7 @@ std::string cmBase32Encoder::encodeString(const unsigned char* input,
     input += blockSize;
   }
 
-  size_t remain(end - input);
+  size_t remain = static_cast<size_t>(end - input);
   if (remain != 0) {
     // Temporary source buffer filled up with 0s
     unsigned char extended[blockSize];
diff --git a/Source/cmBase32.h b/Source/cmBase32.h
index 44bca2f..c6758d4 100644
--- a/Source/cmBase32.h
+++ b/Source/cmBase32.h
@@ -3,7 +3,7 @@
 #ifndef cmBase32_h
 #define cmBase32_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <stddef.h>
 #include <string>
diff --git a/Source/cmBreakCommand.cxx b/Source/cmBreakCommand.cxx
index 9bb6137..3772c6f 100644
--- a/Source/cmBreakCommand.cxx
+++ b/Source/cmBreakCommand.cxx
@@ -41,7 +41,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args,
     }
   }
 
-  status.SetBreakInvoked(true);
+  status.SetBreakInvoked();
 
   if (!args.empty()) {
     bool issueMessage = true;
diff --git a/Source/cmBreakCommand.h b/Source/cmBreakCommand.h
index 5113e18..fcca45c 100644
--- a/Source/cmBreakCommand.h
+++ b/Source/cmBreakCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmBreakCommand_h
 #define cmBreakCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "break"; }
 };
 
 #endif
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index 6836151..fd87600 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -32,7 +32,7 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args)
   }
 
   // The cmake variable in which to store the result.
-  const char* variable = args[0].c_str();
+  std::string const& variable = args[0];
 
   // Parse remaining arguments.
   std::string configuration;
@@ -104,7 +104,7 @@ bool cmBuildCommand::TwoArgsSignature(std::vector<std::string> const& args)
     return false;
   }
 
-  const char* define = args[0].c_str();
+  std::string const& define = args[0];
   const char* cacheValue = this->Makefile->GetDefinition(define);
 
   std::string configType;
diff --git a/Source/cmBuildCommand.h b/Source/cmBuildCommand.h
index 62f1fd3..1f357a9 100644
--- a/Source/cmBuildCommand.h
+++ b/Source/cmBuildCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmBuildCommand_h
 #define cmBuildCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -41,11 +42,6 @@ public:
    */
   virtual bool TwoArgsSignature(std::vector<std::string> const& args);
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "build_command"; }
-
 private:
   bool IgnoreErrors() const;
 };
diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx
index 1e1cd21..9d2c0c6 100644
--- a/Source/cmBuildNameCommand.cxx
+++ b/Source/cmBuildNameCommand.cxx
@@ -2,11 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmBuildNameCommand.h"
 
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
-#include <cmsys/RegularExpression.hxx>
 
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 
@@ -16,11 +15,6 @@ class cmExecutionStatus;
 bool cmBuildNameCommand::InitialPass(std::vector<std::string> const& args,
                                      cmExecutionStatus&)
 {
-  if (this->Disallowed(
-        cmPolicies::CMP0036,
-        "The build_name command should not be called; see CMP0036.")) {
-    return true;
-  }
   if (args.empty()) {
     this->SetError("called with incorrect number of arguments");
     return false;
diff --git a/Source/cmBuildNameCommand.h b/Source/cmBuildNameCommand.h
index 1e1f4b5..ff26c55 100644
--- a/Source/cmBuildNameCommand.h
+++ b/Source/cmBuildNameCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmBuildNameCommand_h
 #define cmBuildNameCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -17,8 +18,6 @@ public:
   cmCommand* Clone() CM_OVERRIDE { return new cmBuildNameCommand; }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-  std::string GetName() const CM_OVERRIDE { return "build_name"; }
-  bool IsScriptable() const CM_OVERRIDE { return true; }
 };
 
 #endif
diff --git a/Source/cmCLocaleEnvironmentScope.h b/Source/cmCLocaleEnvironmentScope.h
index 32cc8df..e956cb2 100644
--- a/Source/cmCLocaleEnvironmentScope.h
+++ b/Source/cmCLocaleEnvironmentScope.h
@@ -3,13 +3,15 @@
 #ifndef cmCLocaleEnvironmentScope_h
 #define cmCLocaleEnvironmentScope_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include <map>
 #include <string>
 
 class cmCLocaleEnvironmentScope
 {
+  CM_DISABLE_COPY(cmCLocaleEnvironmentScope)
+
 public:
   cmCLocaleEnvironmentScope();
   ~cmCLocaleEnvironmentScope();
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index e135ac6..4475c5a 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -26,7 +26,7 @@ bool cmCMakeHostSystemInformationCommand::InitialPass(
     return false;
   }
 
-  std::string variable = args[current_index + 1];
+  std::string const& variable = args[current_index + 1];
   current_index += 2;
 
   if (args.size() < (current_index + 2) || args[current_index] != "QUERY") {
@@ -41,7 +41,7 @@ bool cmCMakeHostSystemInformationCommand::InitialPass(
 
   std::string result_list;
   for (size_t i = current_index + 1; i < args.size(); ++i) {
-    std::string key = args[i];
+    std::string const& key = args[i];
     if (i != current_index + 1) {
       result_list += ";";
     }
diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h
index 22f3d54..ef6ca37 100644
--- a/Source/cmCMakeHostSystemInformationCommand.h
+++ b/Source/cmCMakeHostSystemInformationCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmCMakeHostSystemInformationCommand_h
 #define cmCMakeHostSystemInformationCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <stddef.h>
 #include <string>
 #include <vector>
@@ -39,19 +40,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-  * This determines if the command is invoked when in script mode.
-  */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-  * The name of the command as specified in CMakeList.txt.
-  */
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "cmake_host_system_information";
-  }
-
 private:
   bool GetValue(cmsys::SystemInformation& info, std::string const& key,
                 std::string& value);
diff --git a/Source/cmCMakeMinimumRequired.h b/Source/cmCMakeMinimumRequired.h
index 08a5c38..45b6b78 100644
--- a/Source/cmCMakeMinimumRequired.h
+++ b/Source/cmCMakeMinimumRequired.h
@@ -3,7 +3,8 @@
 #ifndef cmCMakeMinimumRequired_h
 #define cmCMakeMinimumRequired_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,16 +32,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "cmake_minimum_required"; }
-
 private:
   std::vector<std::string> UnknownArguments;
   bool EnforceUnknownArguments();
diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h
index 409fc59..0e88243 100644
--- a/Source/cmCMakePolicyCommand.h
+++ b/Source/cmCMakePolicyCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmCMakePolicyCommand_h
 #define cmCMakePolicyCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,16 +33,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-    * This determines if the command is invoked when in script mode.
-    */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-    * The name of the command as specified in CMakeList.txt.
-    */
-  std::string GetName() const CM_OVERRIDE { return "cmake_policy"; }
-
 private:
   bool HandleSetMode(std::vector<std::string> const& args);
   bool HandleGetMode(std::vector<std::string> const& args);
diff --git a/Source/cmCPackPropertiesGenerator.cxx b/Source/cmCPackPropertiesGenerator.cxx
index ae6b0a1..57a8b38 100644
--- a/Source/cmCPackPropertiesGenerator.cxx
+++ b/Source/cmCPackPropertiesGenerator.cxx
@@ -19,7 +19,7 @@ cmCPackPropertiesGenerator::cmCPackPropertiesGenerator(
 }
 
 void cmCPackPropertiesGenerator::GenerateScriptForConfig(
-  std::ostream& os, const std::string& config, Indent const& indent)
+  std::ostream& os, const std::string& config, Indent indent)
 {
   std::string const& expandedFileName =
     this->InstalledFile.GetNameExpression().Evaluate(this->LG, config);
diff --git a/Source/cmCPackPropertiesGenerator.h b/Source/cmCPackPropertiesGenerator.h
index 37c6039..48f4c10 100644
--- a/Source/cmCPackPropertiesGenerator.h
+++ b/Source/cmCPackPropertiesGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmCPackPropertiesGenerator_h
 #define cmCPackPropertiesGenerator_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include "cmScriptGenerator.h"
 
@@ -20,6 +20,8 @@ class cmLocalGenerator;
  */
 class cmCPackPropertiesGenerator : public cmScriptGenerator
 {
+  CM_DISABLE_COPY(cmCPackPropertiesGenerator)
+
 public:
   cmCPackPropertiesGenerator(cmLocalGenerator* lg,
                              cmInstalledFile const& installedFile,
@@ -27,7 +29,7 @@ public:
 
 protected:
   void GenerateScriptForConfig(std::ostream& os, const std::string& config,
-                               Indent const& indent) CM_OVERRIDE;
+                               Indent indent) CM_OVERRIDE;
 
   cmLocalGenerator* LG;
   cmInstalledFile const& InstalledFile;
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 559275e..e260556 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -2,15 +2,15 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTest.h"
 
-#include <cm_curl.h>
-#include <cm_zlib.h>
-#include <cmsys/Base64.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/Process.h>
-#include <cmsys/String.hxx>
-#include <cmsys/SystemInformation.hxx>
+#include "cm_curl.h"
+#include "cm_zlib.h"
+#include "cmsys/Base64.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/Process.h"
+#include "cmsys/String.hxx"
+#include "cmsys/SystemInformation.hxx"
 #include <ctype.h>
 #include <iostream>
 #include <map>
@@ -119,10 +119,10 @@ std::string cmCTest::CleanString(const std::string& str)
 {
   std::string::size_type spos = str.find_first_not_of(" \n\t\r\f\v");
   std::string::size_type epos = str.find_last_not_of(" \n\t\r\f\v");
-  if (spos == str.npos) {
+  if (spos == std::string::npos) {
     return std::string();
   }
-  if (epos != str.npos) {
+  if (epos != std::string::npos) {
     epos = epos - spos + 1;
   }
   return str.substr(spos, epos);
@@ -416,7 +416,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
     }
   }
 
-  cmake cm;
+  cmake cm(cmake::RoleScript);
   cm.SetHomeDirectory("");
   cm.SetHomeOutputDirectory("");
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
@@ -669,12 +669,11 @@ bool cmCTest::UpdateCTestConfiguration()
         continue;
       }
       std::string::size_type cpos = line.find_first_of(':');
-      if (cpos == line.npos) {
+      if (cpos == std::string::npos) {
         continue;
       }
       std::string key = line.substr(0, cpos);
-      std::string value =
-        cmCTest::CleanString(line.substr(cpos + 1, line.npos));
+      std::string value = cmCTest::CleanString(line.substr(cpos + 1));
       this->CTestConfiguration[key] = value;
     }
     fin.close();
@@ -1122,7 +1121,6 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
     if (log) {
       *log << "* Run internal CTest" << std::endl;
     }
-    std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
 
     CM_AUTO_PTR<cmSystemTools::SaveRestoreEnvironment> saveEnv;
     if (modifyEnv) {
@@ -1137,7 +1135,6 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
     if (log && output) {
       *log << *output;
     }
-    cmSystemTools::ChangeDirectory(oldpath);
     if (output) {
       cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
                  "Internal cmCTest object used to run test." << std::endl
@@ -1243,7 +1240,7 @@ std::string cmCTest::SafeBuildIdField(const std::string& value)
     //
     const char* disallowed = "\\:*?\"<>|\n\r\t\f\v";
 
-    if (safevalue.find_first_of(disallowed) != value.npos) {
+    if (safevalue.find_first_of(disallowed) != std::string::npos) {
       std::string::size_type i = 0;
       std::string::size_type n = strlen(disallowed);
       char replace[2];
@@ -1901,6 +1898,34 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
       ->SetPersistentOption("ExcludeRegularExpression", args[i].c_str());
   }
 
+  if (this->CheckArgument(arg, "-FA", "--fixture-exclude-any") &&
+      i < args.size() - 1) {
+    i++;
+    this->GetHandler("test")->SetPersistentOption(
+      "ExcludeFixtureRegularExpression", args[i].c_str());
+    this->GetHandler("memcheck")
+      ->SetPersistentOption("ExcludeFixtureRegularExpression",
+                            args[i].c_str());
+  }
+  if (this->CheckArgument(arg, "-FS", "--fixture-exclude-setup") &&
+      i < args.size() - 1) {
+    i++;
+    this->GetHandler("test")->SetPersistentOption(
+      "ExcludeFixtureSetupRegularExpression", args[i].c_str());
+    this->GetHandler("memcheck")
+      ->SetPersistentOption("ExcludeFixtureSetupRegularExpression",
+                            args[i].c_str());
+  }
+  if (this->CheckArgument(arg, "-FC", "--fixture-exclude-cleanup") &&
+      i < args.size() - 1) {
+    i++;
+    this->GetHandler("test")->SetPersistentOption(
+      "ExcludeFixtureCleanupRegularExpression", args[i].c_str());
+    this->GetHandler("memcheck")
+      ->SetPersistentOption("ExcludeFixtureCleanupRegularExpression",
+                            args[i].c_str());
+  }
+
   if (this->CheckArgument(arg, "--rerun-failed")) {
     this->GetHandler("test")->SetPersistentOption("RerunFailed", "true");
     this->GetHandler("memcheck")->SetPersistentOption("RerunFailed", "true");
@@ -2323,8 +2348,8 @@ std::string cmCTest::GetShortPathToFile(const char* cfname)
     cmSystemTools::RelativePath(buildDir.c_str(), fname.c_str());
 
   // If any contains "." it is not parent directory
-  bool inSrc = srcRelpath.find("..") == srcRelpath.npos;
-  bool inBld = bldRelpath.find("..") == bldRelpath.npos;
+  bool inSrc = srcRelpath.find("..") == std::string::npos;
+  bool inBld = bldRelpath.find("..") == std::string::npos;
   // TODO: Handle files with .. in their name
 
   std::string* res = CM_NULLPTR;
@@ -2483,7 +2508,7 @@ void cmCTest::AddSubmitFile(Part part, const char* name)
 void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr)
 {
   size_t epos = overStr.find('=');
-  if (epos == overStr.npos) {
+  if (epos == std::string::npos) {
     cmCTestLog(this, ERROR_MESSAGE,
                "CTest configuration overwrite specified in the wrong format."
                  << std::endl
@@ -2492,7 +2517,7 @@ void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr)
     return;
   }
   std::string key = overStr.substr(0, epos);
-  std::string value = overStr.substr(epos + 1, overStr.npos);
+  std::string value = overStr.substr(epos + 1);
   this->CTestConfigurationOverwrites[key] = value;
 }
 
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 4d33458..60f3295 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -3,10 +3,10 @@
 #ifndef cmCTest_h
 #define cmCTest_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cmProcessOutput.h>
-#include <cmsys/String.hxx>
+#include "cmProcessOutput.h"
+#include "cmsys/String.hxx"
 #include <map>
 #include <set>
 #include <sstream>
@@ -14,29 +14,12 @@
 #include <time.h>
 #include <vector>
 
-class cmCTest;
 class cmCTestGenericHandler;
 class cmCTestStartCommand;
 class cmGeneratedFileStream;
 class cmMakefile;
 class cmXMLWriter;
 
-#define cmCTestLog(ctSelf, logType, msg)                                      \
-  do {                                                                        \
-    std::ostringstream cmCTestLog_msg;                                        \
-    cmCTestLog_msg << msg;                                                    \
-    (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__,                       \
-                  cmCTestLog_msg.str().c_str());                              \
-  } while (false)
-
-#define cmCTestOptionalLog(ctSelf, logType, msg, suppress)                    \
-  do {                                                                        \
-    std::ostringstream cmCTestLog_msg;                                        \
-    cmCTestLog_msg << msg;                                                    \
-    (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__,                       \
-                  cmCTestLog_msg.str().c_str(), suppress);                    \
-  } while (false)
-
 /** \class cmCTest
  * \brief Represents a ctest invocation.
  *
@@ -648,4 +631,20 @@ inline std::ostream& operator<<(std::ostream& os, const cmCTestLogWrite& c)
   return os;
 }
 
+#define cmCTestLog(ctSelf, logType, msg)                                      \
+  do {                                                                        \
+    std::ostringstream cmCTestLog_msg;                                        \
+    cmCTestLog_msg << msg;                                                    \
+    (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__,                       \
+                  cmCTestLog_msg.str().c_str());                              \
+  } while (false)
+
+#define cmCTestOptionalLog(ctSelf, logType, msg, suppress)                    \
+  do {                                                                        \
+    std::ostringstream cmCTestLog_msg;                                        \
+    cmCTestLog_msg << msg;                                                    \
+    (ctSelf)->Log(cmCTest::logType, __FILE__, __LINE__,                       \
+                  cmCTestLog_msg.str().c_str(), suppress);                    \
+  } while (false)
+
 #endif
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index cb0ba63..0b025ab 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCacheManager.h"
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
 #include <algorithm>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
 #include <sstream>
 #include <stdio.h>
 #include <string.h>
@@ -205,8 +205,7 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
   return false;
 }
 
-void cmCacheManager::WritePropertyEntries(std::ostream& os,
-                                          CacheIterator const& i)
+void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i)
 {
   for (const char** p = this->PersistentProperties; *p; ++p) {
     if (const char* value = i.GetProperty(*p)) {
@@ -387,7 +386,7 @@ void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key)
 {
   // support : in key name by double quoting
   const char* q =
-    (key.find(':') != key.npos || key.find("//") == 0) ? "\"" : "";
+    (key.find(':') != std::string::npos || key.find("//") == 0) ? "\"" : "";
   fout << q << key << q;
 }
 
@@ -490,7 +489,7 @@ void cmCacheManager::AddCacheEntry(const std::string& key, const char* value,
   e.Type = type;
   // make sure we only use unix style paths
   if (type == cmStateEnums::FILEPATH || type == cmStateEnums::PATH) {
-    if (e.Value.find(';') != e.Value.npos) {
+    if (e.Value.find(';') != std::string::npos) {
       std::vector<std::string> paths;
       cmSystemTools::ExpandListArgument(e.Value, paths);
       const char* sep = "";
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index e82c9ef..c464311 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -3,7 +3,7 @@
 #ifndef cmCacheManager_h
 #define cmCacheManager_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
 #include <map>
@@ -228,7 +228,7 @@ private:
 
   static const char* PersistentProperties[];
   bool ReadPropertyEntry(std::string const& key, CacheEntry& e);
-  void WritePropertyEntries(std::ostream& os, CacheIterator const& i);
+  void WritePropertyEntries(std::ostream& os, CacheIterator i);
 
   CacheEntryMap Cache;
   // Only cmake and cmState should be able to add cache values
diff --git a/Source/cmCallVisualStudioMacro.h b/Source/cmCallVisualStudioMacro.h
index e9d34e5..ad35d30 100644
--- a/Source/cmCallVisualStudioMacro.h
+++ b/Source/cmCallVisualStudioMacro.h
@@ -3,7 +3,7 @@
 #ifndef cmCallVisualStudioMacro_h
 #define cmCallVisualStudioMacro_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <string>
 
diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx
index 181b412..d349c91 100644
--- a/Source/cmCommand.cxx
+++ b/Source/cmCommand.cxx
@@ -3,7 +3,6 @@
 #include "cmCommand.h"
 
 #include "cmMakefile.h"
-#include "cmake.h"
 
 class cmExecutionStatus;
 struct cmListFileArgument;
@@ -23,32 +22,12 @@ bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
 const char* cmCommand::GetError()
 {
   if (this->Error.empty()) {
-    this->Error = this->GetName();
-    this->Error += " unknown error.";
+    return "unknown error.";
   }
   return this->Error.c_str();
 }
 
 void cmCommand::SetError(const std::string& e)
 {
-  this->Error = this->GetName();
-  this->Error += " ";
-  this->Error += e;
-}
-
-bool cmCommand::Disallowed(cmPolicies::PolicyID pol, const char* e)
-{
-  switch (this->Makefile->GetPolicyStatus(pol)) {
-    case cmPolicies::WARN:
-      this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
-                                   cmPolicies::GetPolicyWarning(pol));
-    case cmPolicies::OLD:
-      return false;
-    case cmPolicies::REQUIRED_IF_USED:
-    case cmPolicies::REQUIRED_ALWAYS:
-    case cmPolicies::NEW:
-      this->Makefile->IssueMessage(cmake::FATAL_ERROR, e);
-      break;
-  }
-  return true;
+  this->Error = e;
 }
diff --git a/Source/cmCommand.h b/Source/cmCommand.h
index d9fd5a2..ad72fe2 100644
--- a/Source/cmCommand.h
+++ b/Source/cmCommand.h
@@ -3,13 +3,11 @@
 #ifndef cmCommand_h
 #define cmCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
-#include "cmCommandArgumentsHelper.h"
-#include "cmPolicies.h"
-
 class cmExecutionStatus;
 class cmMakefile;
 struct cmListFileArgument;
@@ -26,6 +24,8 @@ struct cmListFileArgument;
  */
 class cmCommand
 {
+  CM_DISABLE_COPY(cmCommand)
+
 public:
   /**
    * Construct the command. By default it has no makefile.
@@ -80,22 +80,6 @@ public:
   virtual cmCommand* Clone() = 0;
 
   /**
-   * This determines if the command is invoked when in script mode.
-   */
-  virtual bool IsScriptable() const { return false; }
-
-  /**
-   * This determines if the command is defined in a cmake script.
-   * It is the case for cmMacroHelperCommand and cmFunctionHelperCommand.
-   */
-  virtual bool IsUserDefined() const { return false; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  virtual std::string GetName() const = 0;
-
-  /**
    * Return the last error string.
    */
   const char* GetError();
@@ -105,12 +89,8 @@ public:
    */
   void SetError(const std::string& e);
 
-  /** Check if the command is disallowed by a policy.  */
-  bool Disallowed(cmPolicies::PolicyID pol, const char* e);
-
 protected:
   cmMakefile* Makefile;
-  cmCommandArgumentsHelper Helper;
 
 private:
   std::string Error;
diff --git a/Source/cmCommandArgumentParser.cxx b/Source/cmCommandArgumentParser.cxx
deleted file mode 100644
index e384f21..0000000
--- a/Source/cmCommandArgumentParser.cxx
+++ /dev/null
@@ -1,1811 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 1
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-/* Substitute the variable and function names.  */
-#define yyparse cmCommandArgument_yyparse
-#define yylex   cmCommandArgument_yylex
-#define yyerror cmCommandArgument_yyerror
-#define yylval  cmCommandArgument_yylval
-#define yychar  cmCommandArgument_yychar
-#define yydebug cmCommandArgument_yydebug
-#define yynerrs cmCommandArgument_yynerrs
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     cal_ENVCURLY = 258,
-     cal_NCURLY = 259,
-     cal_DCURLY = 260,
-     cal_DOLLAR = 261,
-     cal_LCURLY = 262,
-     cal_RCURLY = 263,
-     cal_NAME = 264,
-     cal_BSLASH = 265,
-     cal_SYMBOL = 266,
-     cal_AT = 267,
-     cal_ERROR = 268,
-     cal_ATNAME = 269
-   };
-#endif
-/* Tokens.  */
-#define cal_ENVCURLY 258
-#define cal_NCURLY 259
-#define cal_DCURLY 260
-#define cal_DOLLAR 261
-#define cal_LCURLY 262
-#define cal_RCURLY 263
-#define cal_NAME 264
-#define cal_BSLASH 265
-#define cal_SYMBOL 266
-#define cal_AT 267
-#define cal_ERROR 268
-#define cal_ATNAME 269
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 1 "cmCommandArgumentParser.y"
-
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
-  bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
-
-Modify cmCommandArgumentParser.cxx:
-  - remove TABs
-  - put header block at top of file
-
-*/
-
-#include "cmStandardIncludes.h"
-
-/* Configure the parser to use a lexer object.  */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmCommandArgument_yyerror(x) \
-        cmCommandArgumentError(yyscanner, x)
-#define yyGetParser (cmCommandArgument_yyget_extra(yyscanner))
-
-/* Make sure malloc and free are available on QNX.  */
-#ifdef __QNX__
-# include <malloc.h>
-#endif
-
-/* Make sure the parser uses standard memory allocation.  The default
-   generated parser malloc/free declarations do not work on all
-   platforms.  */
-#include <stdlib.h>
-#define YYMALLOC malloc
-#define YYFREE free
-
-/*-------------------------------------------------------------------------*/
-#include "cmCommandArgumentParserHelper.h" /* Interface to parser object.  */
-#include "cmCommandArgumentLexer.h"  /* Interface to lexer object.  */
-#include "cmCommandArgumentParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
-
-/* Forward declare the lexer entry point.  */
-YY_DECL;
-
-/* Internal utility functions.  */
-static void cmCommandArgumentError(yyscan_t yyscanner, const char* message);
-
-#define YYDEBUG 1
-/* Configure the parser to support large input.  */
-#define YYMAXDEPTH 100000
-#define YYINITDEPTH 10000
-
-/* Disable some warnings in the generated code.  */
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label.  */
-# pragma warning (disable: 4065) /* Switch statement contains default but no
-                                    case. */
-# pragma warning (disable: 4244) /* loss of precision */
-# pragma warning (disable: 4702) /* unreachable code */
-#endif
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 227 "cmCommandArgumentParser.cxx"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-             && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)              \
-      do                                        \
-        {                                       \
-          YYSIZE_T yyi;                         \
-          for (yyi = 0; yyi < (Count); yyi++)   \
-            (To)[yyi] = (From)[yyi];            \
-        }                                       \
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)                                        \
-    do                                                                  \
-      {                                                                 \
-        YYSIZE_T yynewbytes;                                            \
-        YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-        Stack = &yyptr->Stack;                                          \
-        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-        yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                 \
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  25
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   40
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  15
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  10
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  24
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  33
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   269
-
-#define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint8 yyprhs[] =
-{
-       0,     0,     3,     5,     7,    10,    11,    14,    16,    18,
-      20,    22,    24,    26,    28,    30,    34,    38,    42,    44,
-      46,    49,    50,    53,    55
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      16,     0,    -1,    17,    -1,    18,    -1,    18,    10,    -1,
-      -1,    19,    18,    -1,    20,    -1,    21,    -1,     9,    -1,
-      12,    -1,     6,    -1,     7,    -1,     8,    -1,    11,    -1,
-       3,    22,     8,    -1,     4,    23,     8,    -1,     5,    23,
-       8,    -1,    14,    -1,    23,    -1,    11,    22,    -1,    -1,
-      24,    23,    -1,     9,    -1,    21,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint8 yyrline[] =
-{
-       0,   116,   116,   123,   128,   134,   138,   144,   149,   155,
-     160,   165,   170,   175,   180,   186,   192,   198,   204,   210,
-     215,   221,   225,   231,   236
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "cal_ENVCURLY", "cal_NCURLY",
-  "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"",
-  "cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start",
-  "GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable",
-  "EnvVarName", "MultipleIds", "ID", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    15,    16,    17,    17,    18,    18,    19,    19,    20,
-      20,    20,    20,    20,    20,    21,    21,    21,    21,    22,
-      22,    23,    23,    24,    24
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     1,     1,     2,     0,     2,     1,     1,     1,
-       1,     1,     1,     1,     1,     3,     3,     3,     1,     1,
-       2,     0,     2,     1,     1
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       5,    21,    21,    21,    11,    12,    13,     9,    14,    10,
-      18,     0,     2,     3,     5,     7,     8,    23,    21,    24,
-       0,    19,    21,     0,     0,     1,     4,     6,    20,    15,
-      22,    16,    17
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
-{
-      -1,    11,    12,    13,    14,    15,    19,    20,    21,    22
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -3
-static const yytype_int8 yypact[] =
-{
-       0,    14,    26,    26,    -3,    -3,    -3,    -3,    -3,    -3,
-      -3,    10,    -3,     3,     0,    -3,    -3,    -3,    14,    -3,
-       7,    -3,    26,    13,    16,    -3,    -3,    -3,    -3,    -3,
-      -3,    -3,    -3
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] =
-{
-      -3,    -3,    -3,     8,    -3,    -3,     2,     9,    -2,    -3
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
-static const yytype_uint8 yytable[] =
-{
-      23,    24,    16,     1,     2,     3,     4,     5,     6,     7,
-      25,     8,     9,    26,    10,    29,    16,     1,     2,     3,
-      30,    31,    27,    17,    32,    18,     0,    28,    10,     1,
-       2,     3,     0,     0,     0,    17,     0,     0,     0,     0,
-      10
-};
-
-static const yytype_int8 yycheck[] =
-{
-       2,     3,     0,     3,     4,     5,     6,     7,     8,     9,
-       0,    11,    12,    10,    14,     8,    14,     3,     4,     5,
-      22,     8,    14,     9,     8,    11,    -1,    18,    14,     3,
-       4,     5,    -1,    -1,    -1,     9,    -1,    -1,    -1,    -1,
-      14
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,     3,     4,     5,     6,     7,     8,     9,    11,    12,
-      14,    16,    17,    18,    19,    20,    21,     9,    11,    21,
-      22,    23,    24,    23,    23,     0,    10,    18,    22,     8,
-      23,     8,     8
-};
-
-#define yyerrok         (yyerrstatus = 0)
-#define yyclearin       (yychar = YYEMPTY)
-#define YYEMPTY         (-2)
-#define YYEOF           0
-
-#define YYACCEPT        goto yyacceptlab
-#define YYABORT         goto yyabortlab
-#define YYERROR         goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL          goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY && yylen == 1)                          \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      yytoken = YYTRANSLATE (yychar);                           \
-      YYPOPSTACK (1);                                           \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;                                                  \
-    }                                                           \
-while (YYID (0))
-
-
-#define YYTERROR        1
-#define YYERRCODE       256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                                \
-    do                                                                  \
-      if (YYID (N))                                                    \
-        {                                                               \
-          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-        }                                                               \
-      else                                                              \
-        {                                                               \
-          (Current).first_line   = (Current).last_line   =              \
-            YYRHSLOC (Rhs, 0).last_line;                                \
-          (Current).first_column = (Current).last_column =              \
-            YYRHSLOC (Rhs, 0).last_column;                              \
-        }                                                               \
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                  \
-     fprintf (File, "%d.%d-%d.%d",                      \
-              (Loc).first_line, (Loc).first_column,     \
-              (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval)
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                        \
-do {                                            \
-  if (yydebug)                                  \
-    YYFPRINTF Args;                             \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
-do {                                                                      \
-  if (yydebug)                                                            \
-    {                                                                     \
-      YYFPRINTF (stderr, "%s ", Title);                                   \
-      yy_symbol_print (stderr,                                            \
-                  Type, Value); \
-      YYFPRINTF (stderr, "\n");                                           \
-    }                                                                     \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-        break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                            \
-do {                                                            \
-  if (yydebug)                                                  \
-    yy_stack_print ((Bottom), (Top));                           \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-             yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      fprintf (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                       &(yyvsp[(yyi + 1) - (yynrhs)])
-                                       );
-      fprintf (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)          \
-do {                                    \
-  if (yydebug)                          \
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-

-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-        switch (*++yyp)
-          {
-          case '\'':
-          case ',':
-            goto do_not_strip_quotes;
-
-          case '\\':
-            if (*++yyp != '\\')
-              goto do_not_strip_quotes;
-            /* Fall through.  */
-          default:
-            if (yyres)
-              yyres[yyn] = *yyp;
-            yyn++;
-            break;
-
-          case '"':
-            if (yyres)
-              yyres[yyn] = '\0';
-            return yyn;
-          }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-         constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-                    + sizeof yyexpecting - 1
-                    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-                       * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-         YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-        if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-          {
-            if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-              {
-                yycount = 1;
-                yysize = yysize0;
-                yyformat[sizeof yyunexpected - 1] = '\0';
-                break;
-              }
-            yyarg[yycount++] = yytname[yyx];
-            yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-            yysize_overflow |= (yysize1 < yysize);
-            yysize = yysize1;
-            yyfmt = yystpcpy (yyfmt, yyprefix);
-            yyprefix = yyor;
-          }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-        return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-        {
-          /* Avoid sprintf, as that infringes on the user's name space.
-             Don't have undefined behavior even if the translation
-             produced a string with the wrong number of "%s"s.  */
-          char *yyp = yyresult;
-          int yyi = 0;
-          while ((*yyp = *yyf) != '\0')
-            {
-              if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-                {
-                  yyp += yytnamerr (yyp, yyarg[yyi++]);
-                  yyf += 2;
-                }
-              else
-                {
-                  yyp++;
-                  yyf++;
-                }
-            }
-        }
-      return yysize;
-    }
-}
-#endif /* YYERROR_VERBOSE */
-

-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-        break;
-    }
-}
-

-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  /* The look-ahead symbol.  */
-int yychar;
-
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;             /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-        /* Give user a chance to reallocate the stack.  Use copies of
-           these so that the &'s don't force the real ones into
-           memory.  */
-        YYSTYPE *yyvs1 = yyvs;
-        yytype_int16 *yyss1 = yyss;
-
-
-        /* Each stack pointer address is followed by the size of the
-           data in use in that stack, in bytes.  This used to be a
-           conditional around just the two extra args, but that might
-           be undefined if yyoverflow is a macro.  */
-        yyoverflow (YY_("memory exhausted"),
-                    &yyss1, yysize * sizeof (*yyssp),
-                    &yyvs1, yysize * sizeof (*yyvsp),
-
-                    &yystacksize);
-
-        yyss = yyss1;
-        yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-        goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-        yystacksize = YYMAXDEPTH;
-
-      {
-        yytype_int16 *yyss1 = yyss;
-        union yyalloc *yyptr =
-          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-        if (! yyptr)
-          goto yyexhaustedlab;
-        YYSTACK_RELOCATE (yyss);
-        YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-        if (yyss1 != yyssa)
-          YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-        YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-        goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 2:
-#line 117 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = 0;
-  yyGetParser->SetResult((yyvsp[(1) - (1)].str));
-}
-    break;
-
-  case 3:
-#line 124 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 4:
-#line 129 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
-}
-    break;
-
-  case 5:
-#line 134 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = 0;
-}
-    break;
-
-  case 6:
-#line 139 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
-}
-    break;
-
-  case 7:
-#line 145 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 8:
-#line 150 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 9:
-#line 156 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 10:
-#line 161 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 11:
-#line 166 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 12:
-#line 171 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 13:
-#line 176 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 14:
-#line 181 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 15:
-#line 187 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str));
-  //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
-    break;
-
-  case 16:
-#line 193 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str));
-  //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
-    break;
-
-  case 17:
-#line 199 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = yyGetParser->ExpandVariable((yyvsp[(2) - (3)].str));
-  //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
-    break;
-
-  case 18:
-#line 205 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[(1) - (1)].str));
-}
-    break;
-
-  case 19:
-#line 211 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 20:
-#line 216 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (2)].str);
-}
-    break;
-
-  case 21:
-#line 221 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = 0;
-}
-    break;
-
-  case 22:
-#line 226 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
-}
-    break;
-
-  case 23:
-#line 232 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-  case 24:
-#line 237 "cmCommandArgumentParser.y"
-    {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
-    break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 1606 "cmCommandArgumentParser.cxx"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-      {
-        YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-        if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-          {
-            YYSIZE_T yyalloc = 2 * yysize;
-            if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-              yyalloc = YYSTACK_ALLOC_MAXIMUM;
-            if (yymsg != yymsgbuf)
-              YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-            if (yymsg)
-              yymsg_alloc = yyalloc;
-            else
-              {
-                yymsg = yymsgbuf;
-                yymsg_alloc = sizeof yymsgbuf;
-              }
-          }
-
-        if (0 < yysize && yysize <= yymsg_alloc)
-          {
-            (void) yysyntax_error (yymsg, yystate, yychar);
-            yyerror (yymsg);
-          }
-        else
-          {
-            yyerror (YY_("syntax error"));
-            if (yysize != 0)
-              goto yyexhaustedlab;
-          }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse look-ahead token after an
-         error, discard it.  */
-
-      if (yychar <= YYEOF)
-        {
-          /* Return failure if at end of input.  */
-          if (yychar == YYEOF)
-            YYABORT;
-        }
-      else
-        {
-          yydestruct ("Error: discarding",
-                      yytoken, &yylval);
-          yychar = YYEMPTY;
-        }
-    }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-        {
-          yyn += YYTERROR;
-          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-            {
-              yyn = yytable[yyn];
-              if (0 < yyn)
-                break;
-            }
-        }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-        YYABORT;
-
-
-      yydestruct ("Error: popping",
-                  yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-                 yytoken, &yylval);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                  yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-#line 242 "cmCommandArgumentParser.y"
-
-/* End of grammar */
-
-/*--------------------------------------------------------------------------*/
-void cmCommandArgumentError(yyscan_t yyscanner, const char* message)
-{
-  yyGetParser->Error(message);
-}
-
-
diff --git a/Source/cmCommandArgumentParser.y b/Source/cmCommandArgumentParser.y
deleted file mode 100644
index b2f4b1b..0000000
--- a/Source/cmCommandArgumentParser.y
+++ /dev/null
@@ -1,231 +0,0 @@
-%{
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
-  bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y
-
-Modify cmCommandArgumentParser.cxx:
-  - remove TABs
-  - remove use of the 'register' storage class specifier
-  - put header block at top of file
-
-*/
-
-#include "cmStandardIncludes.h"
-
-/* Configure the parser to use a lexer object.  */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmCommandArgument_yyerror(x) \
-        cmCommandArgumentError(yyscanner, x)
-#define yyGetParser (cmCommandArgument_yyget_extra(yyscanner))
-
-/* Make sure malloc and free are available on QNX.  */
-#ifdef __QNX__
-# include <malloc.h>
-#endif
-
-/* Make sure the parser uses standard memory allocation.  The default
-   generated parser malloc/free declarations do not work on all
-   platforms.  */
-#include <stdlib.h>
-#define YYMALLOC malloc
-#define YYFREE free
-
-/*-------------------------------------------------------------------------*/
-#include "cmCommandArgumentParserHelper.h" /* Interface to parser object.  */
-#include "cmCommandArgumentLexer.h"  /* Interface to lexer object.  */
-#include "cmCommandArgumentParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
-
-/* Forward declare the lexer entry point.  */
-YY_DECL;
-
-/* Internal utility functions.  */
-static void cmCommandArgumentError(yyscan_t yyscanner, const char* message);
-
-#define YYDEBUG 1
-/* Configure the parser to support large input.  */
-#define YYMAXDEPTH 100000
-#define YYINITDEPTH 10000
-
-/* Disable some warnings in the generated code.  */
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label.  */
-# pragma warning (disable: 4065) /* Switch statement contains default but no
-                                    case. */
-# pragma warning (disable: 4244) /* loss of precision */
-# pragma warning (disable: 4702) /* unreachable code */
-#endif
-%}
-
-/* Generate a reentrant parser object.  */
-%pure_parser
-
-/*
-%union {
-  char* string;
-}
-*/
-
-/*-------------------------------------------------------------------------*/
-/* Tokens */
-%token cal_ENVCURLY
-%token cal_NCURLY
-%token cal_DCURLY
-%token cal_DOLLAR "$"
-%token cal_LCURLY "{"
-%token cal_RCURLY "}"
-%token cal_NAME
-%token cal_BSLASH "\\"
-%token cal_SYMBOL
-%token cal_AT     "@"
-%token cal_ERROR
-%token cal_ATNAME
-
-/*-------------------------------------------------------------------------*/
-/* grammar */
-%%
-
-
-Start:
-GoalWithOptionalBackSlash
-{
-  $<str>$ = 0;
-  yyGetParser->SetResult($<str>1);
-}
-
-GoalWithOptionalBackSlash:
-Goal
-{
-  $<str>$ = $<str>1;
-}
-|
-Goal cal_BSLASH
-{
-  $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
-}
-
-Goal:
-{
-  $<str>$ = 0;
-}
-|
-String Goal
-{
-  $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
-}
-
-String:
-OuterText
-{
-  $<str>$ = $<str>1;
-}
-|
-Variable
-{
-  $<str>$ = $<str>1;
-}
-
-OuterText:
-cal_NAME
-{
-  $<str>$ = $<str>1;
-}
-|
-cal_AT
-{
-  $<str>$ = $<str>1;
-}
-|
-cal_DOLLAR
-{
-  $<str>$ = $<str>1;
-}
-|
-cal_LCURLY
-{
-  $<str>$ = $<str>1;
-}
-|
-cal_RCURLY
-{
-  $<str>$ = $<str>1;
-}
-|
-cal_SYMBOL
-{
-  $<str>$ = $<str>1;
-}
-
-Variable:
-cal_ENVCURLY EnvVarName cal_RCURLY
-{
-  $<str>$ = yyGetParser->ExpandSpecialVariable($<str>1,$<str>2);
-  //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
-|
-cal_NCURLY MultipleIds cal_RCURLY
-{
-  $<str>$ = yyGetParser->ExpandSpecialVariable($<str>1,$<str>2);
-  //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
-|
-cal_DCURLY MultipleIds cal_RCURLY
-{
-  $<str>$ = yyGetParser->ExpandVariable($<str>2);
-  //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
-|
-cal_ATNAME
-{
-  $<str>$ = yyGetParser->ExpandVariableForAt($<str>1);
-}
-
-EnvVarName:
-MultipleIds
-{
-  $<str>$ = $<str>1;
-}
-|
-cal_SYMBOL EnvVarName
-{
-  $<str>$ = $<str>1;
-}
-
-MultipleIds:
-{
-  $<str>$ = 0;
-}
-|
-ID MultipleIds
-{
-  $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
-}
-
-ID:
-cal_NAME
-{
-  $<str>$ = $<str>1;
-}
-|
-Variable
-{
-  $<str>$ = $<str>1;
-}
-
-
-%%
-/* End of grammar */
-
-/*--------------------------------------------------------------------------*/
-void cmCommandArgumentError(yyscan_t yyscanner, const char* message)
-{
-  yyGetParser->Error(message);
-}
-
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 2d66344..4eb4531 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -2,15 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCommandArgumentParserHelper.h"
 
-#include <cm_kwiml.h>
-
 #include "cmCommandArgumentLexer.h"
 #include "cmMakefile.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-#include <cmConfigure.h>
 #include <iostream>
 #include <sstream>
 #include <string.h>
diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h
index 95bf0ad..465ca9e 100644
--- a/Source/cmCommandArgumentParserHelper.h
+++ b/Source/cmCommandArgumentParserHelper.h
@@ -3,32 +3,22 @@
 #ifndef cmCommandArgumentParserHelper_h
 #define cmCommandArgumentParserHelper_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include <string>
 #include <vector>
 
-#define YYSTYPE cmCommandArgumentParserHelper::ParserType
-#define YYSTYPE_IS_DECLARED
-#define YY_EXTRA_TYPE cmCommandArgumentParserHelper*
-#define YY_DECL                                                               \
-  int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
-
-/** \class cmCommandArgumentParserHelper
- * \brief Helper class for parsing java source files
- *
- * Finds dependencies for java file and list of outputs
- */
-
 class cmMakefile;
 
 class cmCommandArgumentParserHelper
 {
+  CM_DISABLE_COPY(cmCommandArgumentParserHelper)
+
 public:
-  typedef struct
+  struct ParserType
   {
     char* str;
-  } ParserType;
+  };
 
   cmCommandArgumentParserHelper();
   ~cmCommandArgumentParserHelper();
@@ -100,4 +90,10 @@ private:
   bool RemoveEmpty;
 };
 
+#define YYSTYPE cmCommandArgumentParserHelper::ParserType
+#define YYSTYPE_IS_DECLARED
+#define YY_EXTRA_TYPE cmCommandArgumentParserHelper*
+#define YY_DECL                                                               \
+  int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+
 #endif
diff --git a/Source/cmCommandArgumentParserTokens.h b/Source/cmCommandArgumentParserTokens.h
deleted file mode 100644
index d162b82..0000000
--- a/Source/cmCommandArgumentParserTokens.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     cal_ENVCURLY = 258,
-     cal_NCURLY = 259,
-     cal_DCURLY = 260,
-     cal_DOLLAR = 261,
-     cal_LCURLY = 262,
-     cal_RCURLY = 263,
-     cal_NAME = 264,
-     cal_BSLASH = 265,
-     cal_SYMBOL = 266,
-     cal_AT = 267,
-     cal_ERROR = 268,
-     cal_ATNAME = 269
-   };
-#endif
-/* Tokens.  */
-#define cal_ENVCURLY 258
-#define cal_NCURLY 259
-#define cal_DCURLY 260
-#define cal_DOLLAR 261
-#define cal_LCURLY 262
-#define cal_RCURLY 263
-#define cal_NAME 264
-#define cal_BSLASH 265
-#define cal_SYMBOL 266
-#define cal_AT 267
-#define cal_ERROR 268
-#define cal_ATNAME 269
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
diff --git a/Source/cmCommandArgumentsHelper.h b/Source/cmCommandArgumentsHelper.h
index b19b0f9..44db374 100644
--- a/Source/cmCommandArgumentsHelper.h
+++ b/Source/cmCommandArgumentsHelper.h
@@ -3,7 +3,7 @@
 #ifndef cmCommandArgumentsHelper_h
 #define cmCommandArgumentsHelper_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <set>
 #include <string>
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 4c5b093..e1d8ef1 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -1,6 +1,8 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCommands.h"
+#include "cmPolicies.h"
+#include "cmState.h"
 
 #include "cmAddCustomCommandCommand.h"
 #include "cmAddCustomTargetCommand.h"
@@ -68,7 +70,6 @@
 #include "cmTargetLinkLibrariesCommand.h"
 #include "cmTryCompileCommand.h"
 #include "cmTryRunCommand.h"
-#include "cmUnexpectedCommand.h"
 #include "cmUnsetCommand.h"
 #include "cmWhileCommand.h"
 
@@ -104,138 +105,249 @@
 #include "cmWriteFileCommand.h"
 #endif
 
-std::vector<cmCommand*> GetPredefinedCommands()
+void GetScriptingCommands(cmState* state)
 {
-  std::vector<cmCommand*> commands;
+  state->AddBuiltinCommand("break", new cmBreakCommand);
+  state->AddBuiltinCommand("cmake_minimum_required",
+                           new cmCMakeMinimumRequired);
+  state->AddBuiltinCommand("cmake_policy", new cmCMakePolicyCommand);
+  state->AddBuiltinCommand("configure_file", new cmConfigureFileCommand);
+  state->AddBuiltinCommand("continue", new cmContinueCommand);
+  state->AddBuiltinCommand("exec_program", new cmExecProgramCommand);
+  state->AddBuiltinCommand("execute_process", new cmExecuteProcessCommand);
+  state->AddBuiltinCommand("file", new cmFileCommand);
+  state->AddBuiltinCommand("find_file", new cmFindFileCommand);
+  state->AddBuiltinCommand("find_library", new cmFindLibraryCommand);
+  state->AddBuiltinCommand("find_package", new cmFindPackageCommand);
+  state->AddBuiltinCommand("find_path", new cmFindPathCommand);
+  state->AddBuiltinCommand("find_program", new cmFindProgramCommand);
+  state->AddBuiltinCommand("foreach", new cmForEachCommand);
+  state->AddBuiltinCommand("function", new cmFunctionCommand);
+  state->AddBuiltinCommand("get_cmake_property",
+                           new cmGetCMakePropertyCommand);
+  state->AddBuiltinCommand("get_directory_property",
+                           new cmGetDirectoryPropertyCommand);
+  state->AddBuiltinCommand("get_filename_component",
+                           new cmGetFilenameComponentCommand);
+  state->AddBuiltinCommand("get_property", new cmGetPropertyCommand);
+  state->AddBuiltinCommand("if", new cmIfCommand);
+  state->AddBuiltinCommand("include", new cmIncludeCommand);
+  state->AddBuiltinCommand("list", new cmListCommand);
+  state->AddBuiltinCommand("macro", new cmMacroCommand);
+  state->AddBuiltinCommand("make_directory", new cmMakeDirectoryCommand);
+  state->AddBuiltinCommand("mark_as_advanced", new cmMarkAsAdvancedCommand);
+  state->AddBuiltinCommand("math", new cmMathCommand);
+  state->AddBuiltinCommand("message", new cmMessageCommand);
+  state->AddBuiltinCommand("option", new cmOptionCommand);
+  state->AddBuiltinCommand("cmake_parse_arguments",
+                           new cmParseArgumentsCommand);
+  state->AddBuiltinCommand("return", new cmReturnCommand);
+  state->AddBuiltinCommand("separate_arguments",
+                           new cmSeparateArgumentsCommand);
+  state->AddBuiltinCommand("set", new cmSetCommand);
+  state->AddBuiltinCommand("set_directory_properties",
+                           new cmSetDirectoryPropertiesCommand);
+  state->AddBuiltinCommand("set_property", new cmSetPropertyCommand);
+  state->AddBuiltinCommand("site_name", new cmSiteNameCommand);
+  state->AddBuiltinCommand("string", new cmStringCommand);
+  state->AddBuiltinCommand("unset", new cmUnsetCommand);
+  state->AddBuiltinCommand("while", new cmWhileCommand);
 
-  commands.push_back(new cmAddCustomCommandCommand);
-  commands.push_back(new cmAddCustomTargetCommand);
-  commands.push_back(new cmAddDefinitionsCommand);
-  commands.push_back(new cmAddDependenciesCommand);
-  commands.push_back(new cmAddExecutableCommand);
-  commands.push_back(new cmAddLibraryCommand);
-  commands.push_back(new cmAddSubDirectoryCommand);
-  commands.push_back(new cmAddTestCommand);
-  commands.push_back(new cmBreakCommand);
-  commands.push_back(new cmBuildCommand);
-  commands.push_back(new cmCMakeMinimumRequired);
-  commands.push_back(new cmCMakePolicyCommand);
-  commands.push_back(new cmConfigureFileCommand);
-  commands.push_back(new cmContinueCommand);
-  commands.push_back(new cmCreateTestSourceList);
-  commands.push_back(new cmDefinePropertyCommand);
-  commands.push_back(new cmEnableLanguageCommand);
-  commands.push_back(new cmEnableTestingCommand);
-  commands.push_back(new cmExecProgramCommand);
-  commands.push_back(new cmExecuteProcessCommand);
-  commands.push_back(new cmFileCommand);
-  commands.push_back(new cmFindFileCommand);
-  commands.push_back(new cmFindLibraryCommand);
-  commands.push_back(new cmFindPackageCommand);
-  commands.push_back(new cmFindPathCommand);
-  commands.push_back(new cmFindProgramCommand);
-  commands.push_back(new cmForEachCommand);
-  commands.push_back(new cmFunctionCommand);
-  commands.push_back(new cmGetCMakePropertyCommand);
-  commands.push_back(new cmGetDirectoryPropertyCommand);
-  commands.push_back(new cmGetFilenameComponentCommand);
-  commands.push_back(new cmGetPropertyCommand);
-  commands.push_back(new cmGetSourceFilePropertyCommand);
-  commands.push_back(new cmGetTargetPropertyCommand);
-  commands.push_back(new cmGetTestPropertyCommand);
-  commands.push_back(new cmIfCommand);
-  commands.push_back(new cmIncludeCommand);
-  commands.push_back(new cmIncludeDirectoryCommand);
-  commands.push_back(new cmIncludeRegularExpressionCommand);
-  commands.push_back(new cmInstallCommand);
-  commands.push_back(new cmInstallFilesCommand);
-  commands.push_back(new cmInstallTargetsCommand);
-  commands.push_back(new cmLinkDirectoriesCommand);
-  commands.push_back(new cmListCommand);
-  commands.push_back(new cmMacroCommand);
-  commands.push_back(new cmMakeDirectoryCommand);
-  commands.push_back(new cmMarkAsAdvancedCommand);
-  commands.push_back(new cmMathCommand);
-  commands.push_back(new cmMessageCommand);
-  commands.push_back(new cmOptionCommand);
-  commands.push_back(new cmParseArgumentsCommand);
-  commands.push_back(new cmProjectCommand);
-  commands.push_back(new cmReturnCommand);
-  commands.push_back(new cmSeparateArgumentsCommand);
-  commands.push_back(new cmSetCommand);
-  commands.push_back(new cmSetDirectoryPropertiesCommand);
-  commands.push_back(new cmSetPropertyCommand);
-  commands.push_back(new cmSetSourceFilesPropertiesCommand);
-  commands.push_back(new cmSetTargetPropertiesCommand);
-  commands.push_back(new cmSetTestsPropertiesCommand);
-  commands.push_back(new cmSiteNameCommand);
-  commands.push_back(new cmStringCommand);
-  commands.push_back(new cmSubdirCommand);
-  commands.push_back(new cmTargetLinkLibrariesCommand);
-  commands.push_back(new cmTryCompileCommand);
-  commands.push_back(new cmTryRunCommand);
-  commands.push_back(new cmUnsetCommand);
-  commands.push_back(new cmWhileCommand);
-
-  commands.push_back(new cmUnexpectedCommand(
+  state->AddUnexpectedCommand(
     "else", "An ELSE command was found outside of a proper "
             "IF ENDIF structure. Or its arguments did not match "
-            "the opening IF command."));
-  commands.push_back(new cmUnexpectedCommand(
+            "the opening IF command.");
+  state->AddUnexpectedCommand(
     "elseif", "An ELSEIF command was found outside of a proper "
-              "IF ENDIF structure."));
-  commands.push_back(new cmUnexpectedCommand(
+              "IF ENDIF structure.");
+  state->AddUnexpectedCommand(
     "endforeach", "An ENDFOREACH command was found outside of a proper "
                   "FOREACH ENDFOREACH structure. Or its arguments did "
-                  "not match the opening FOREACH command."));
-  commands.push_back(new cmUnexpectedCommand(
+                  "not match the opening FOREACH command.");
+  state->AddUnexpectedCommand(
     "endfunction", "An ENDFUNCTION command was found outside of a proper "
                    "FUNCTION ENDFUNCTION structure. Or its arguments did not "
-                   "match the opening FUNCTION command."));
-  commands.push_back(new cmUnexpectedCommand(
+                   "match the opening FUNCTION command.");
+  state->AddUnexpectedCommand(
     "endif", "An ENDIF command was found outside of a proper "
              "IF ENDIF structure. Or its arguments did not match "
-             "the opening IF command."));
-  commands.push_back(new cmUnexpectedCommand(
+             "the opening IF command.");
+  state->AddUnexpectedCommand(
     "endmacro", "An ENDMACRO command was found outside of a proper "
                 "MACRO ENDMACRO structure. Or its arguments did not "
-                "match the opening MACRO command."));
-  commands.push_back(new cmUnexpectedCommand(
+                "match the opening MACRO command.");
+  state->AddUnexpectedCommand(
     "endwhile", "An ENDWHILE command was found outside of a proper "
                 "WHILE ENDWHILE structure. Or its arguments did not "
-                "match the opening WHILE command."));
+                "match the opening WHILE command.");
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
-  commands.push_back(new cmAddCompileOptionsCommand);
-  commands.push_back(new cmAuxSourceDirectoryCommand);
-  commands.push_back(new cmBuildNameCommand);
-  commands.push_back(new cmCMakeHostSystemInformationCommand);
-  commands.push_back(new cmExportCommand);
-  commands.push_back(new cmExportLibraryDependenciesCommand);
-  commands.push_back(new cmFLTKWrapUICommand);
-  commands.push_back(new cmIncludeExternalMSProjectCommand);
-  commands.push_back(new cmInstallProgramsCommand);
-  commands.push_back(new cmLinkLibrariesCommand);
-  commands.push_back(new cmLoadCacheCommand);
-  commands.push_back(new cmLoadCommandCommand);
-  commands.push_back(new cmOutputRequiredFilesCommand);
-  commands.push_back(new cmQTWrapCPPCommand);
-  commands.push_back(new cmQTWrapUICommand);
-  commands.push_back(new cmRemoveCommand);
-  commands.push_back(new cmRemoveDefinitionsCommand);
-  commands.push_back(new cmSourceGroupCommand);
-  commands.push_back(new cmSubdirDependsCommand);
-  commands.push_back(new cmTargetCompileDefinitionsCommand);
-  commands.push_back(new cmTargetCompileFeaturesCommand);
-  commands.push_back(new cmTargetCompileOptionsCommand);
-  commands.push_back(new cmTargetIncludeDirectoriesCommand);
-  commands.push_back(new cmTargetSourcesCommand);
-  commands.push_back(new cmUseMangledMesaCommand);
-  commands.push_back(new cmUtilitySourceCommand);
-  commands.push_back(new cmVariableRequiresCommand);
-  commands.push_back(new cmVariableWatchCommand);
-  commands.push_back(new cmWriteFileCommand);
+  state->AddBuiltinCommand("cmake_host_system_information",
+                           new cmCMakeHostSystemInformationCommand);
+  state->AddBuiltinCommand("remove", new cmRemoveCommand);
+  state->AddBuiltinCommand("variable_watch", new cmVariableWatchCommand);
+  state->AddBuiltinCommand("write_file", new cmWriteFileCommand);
+
+  state->AddDisallowedCommand(
+    "build_name", new cmBuildNameCommand, cmPolicies::CMP0036,
+    "The build_name command should not be called; see CMP0036.");
+  state->AddDisallowedCommand(
+    "use_mangled_mesa", new cmUseMangledMesaCommand, cmPolicies::CMP0030,
+    "The use_mangled_mesa command should not be called; see CMP0030.");
+
 #endif
+}
+
+void GetProjectCommands(cmState* state)
+{
+  state->AddBuiltinCommand("add_custom_command",
+                           new cmAddCustomCommandCommand);
+  state->AddBuiltinCommand("add_custom_target", new cmAddCustomTargetCommand);
+  state->AddBuiltinCommand("add_definitions", new cmAddDefinitionsCommand);
+  state->AddBuiltinCommand("add_dependencies", new cmAddDependenciesCommand);
+  state->AddBuiltinCommand("add_executable", new cmAddExecutableCommand);
+  state->AddBuiltinCommand("add_library", new cmAddLibraryCommand);
+  state->AddBuiltinCommand("add_subdirectory", new cmAddSubDirectoryCommand);
+  state->AddBuiltinCommand("add_test", new cmAddTestCommand);
+  state->AddBuiltinCommand("build_command", new cmBuildCommand);
+  state->AddBuiltinCommand("create_test_sourcelist",
+                           new cmCreateTestSourceList);
+  state->AddBuiltinCommand("define_property", new cmDefinePropertyCommand);
+  state->AddBuiltinCommand("enable_language", new cmEnableLanguageCommand);
+  state->AddBuiltinCommand("enable_testing", new cmEnableTestingCommand);
+  state->AddBuiltinCommand("get_source_file_property",
+                           new cmGetSourceFilePropertyCommand);
+  state->AddBuiltinCommand("get_target_property",
+                           new cmGetTargetPropertyCommand);
+  state->AddBuiltinCommand("get_test_property", new cmGetTestPropertyCommand);
+  state->AddBuiltinCommand("include_directories",
+                           new cmIncludeDirectoryCommand);
+  state->AddBuiltinCommand("include_regular_expression",
+                           new cmIncludeRegularExpressionCommand);
+  state->AddBuiltinCommand("install", new cmInstallCommand);
+  state->AddBuiltinCommand("install_files", new cmInstallFilesCommand);
+  state->AddBuiltinCommand("install_targets", new cmInstallTargetsCommand);
+  state->AddBuiltinCommand("link_directories", new cmLinkDirectoriesCommand);
+  state->AddBuiltinCommand("project", new cmProjectCommand);
+  state->AddBuiltinCommand("set_source_files_properties",
+                           new cmSetSourceFilesPropertiesCommand);
+  state->AddBuiltinCommand("set_target_properties",
+                           new cmSetTargetPropertiesCommand);
+  state->AddBuiltinCommand("set_tests_properties",
+                           new cmSetTestsPropertiesCommand);
+  state->AddBuiltinCommand("subdirs", new cmSubdirCommand);
+  state->AddBuiltinCommand("target_link_libraries",
+                           new cmTargetLinkLibrariesCommand);
+  state->AddBuiltinCommand("try_compile", new cmTryCompileCommand);
+  state->AddBuiltinCommand("try_run", new cmTryRunCommand);
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  state->AddBuiltinCommand("add_compile_options",
+                           new cmAddCompileOptionsCommand);
+  state->AddBuiltinCommand("aux_source_directory",
+                           new cmAuxSourceDirectoryCommand);
+  state->AddBuiltinCommand("export", new cmExportCommand);
+  state->AddBuiltinCommand("fltk_wrap_ui", new cmFLTKWrapUICommand);
+  state->AddBuiltinCommand("include_external_msproject",
+                           new cmIncludeExternalMSProjectCommand);
+  state->AddBuiltinCommand("install_programs", new cmInstallProgramsCommand);
+  state->AddBuiltinCommand("link_libraries", new cmLinkLibrariesCommand);
+  state->AddBuiltinCommand("load_cache", new cmLoadCacheCommand);
+  state->AddBuiltinCommand("qt_wrap_cpp", new cmQTWrapCPPCommand);
+  state->AddBuiltinCommand("qt_wrap_ui", new cmQTWrapUICommand);
+  state->AddBuiltinCommand("remove_definitions",
+                           new cmRemoveDefinitionsCommand);
+  state->AddBuiltinCommand("source_group", new cmSourceGroupCommand);
+  state->AddBuiltinCommand("target_compile_definitions",
+                           new cmTargetCompileDefinitionsCommand);
+  state->AddBuiltinCommand("target_compile_features",
+                           new cmTargetCompileFeaturesCommand);
+  state->AddBuiltinCommand("target_compile_options",
+                           new cmTargetCompileOptionsCommand);
+  state->AddBuiltinCommand("target_include_directories",
+                           new cmTargetIncludeDirectoriesCommand);
+  state->AddBuiltinCommand("target_sources", new cmTargetSourcesCommand);
+
+  state->AddDisallowedCommand(
+    "export_library_dependencies", new cmExportLibraryDependenciesCommand,
+    cmPolicies::CMP0033,
+    "The export_library_dependencies command should not be called; "
+    "see CMP0033.");
+  state->AddDisallowedCommand(
+    "load_command", new cmLoadCommandCommand, cmPolicies::CMP0031,
+    "The load_command command should not be called; see CMP0031.");
+  state->AddDisallowedCommand(
+    "output_required_files", new cmOutputRequiredFilesCommand,
+    cmPolicies::CMP0032,
+    "The output_required_files command should not be called; see CMP0032.");
+  state->AddDisallowedCommand(
+    "subdir_depends", new cmSubdirDependsCommand, cmPolicies::CMP0029,
+    "The subdir_depends command should not be called; see CMP0029.");
+  state->AddDisallowedCommand(
+    "utility_source", new cmUtilitySourceCommand, cmPolicies::CMP0034,
+    "The utility_source command should not be called; see CMP0034.");
+  state->AddDisallowedCommand(
+    "variable_requires", new cmVariableRequiresCommand, cmPolicies::CMP0035,
+    "The variable_requires command should not be called; see CMP0035.");
+#endif
+}
+
+void GetProjectCommandsInScriptMode(cmState* state)
+{
+#define CM_UNEXPECTED_PROJECT_COMMAND(NAME)                                   \
+  state->AddUnexpectedCommand(NAME, "command is not scriptable")
+
+  CM_UNEXPECTED_PROJECT_COMMAND("add_compile_options");
+  CM_UNEXPECTED_PROJECT_COMMAND("add_custom_command");
+  CM_UNEXPECTED_PROJECT_COMMAND("add_custom_target");
+  CM_UNEXPECTED_PROJECT_COMMAND("add_definitions");
+  CM_UNEXPECTED_PROJECT_COMMAND("add_dependencies");
+  CM_UNEXPECTED_PROJECT_COMMAND("add_executable");
+  CM_UNEXPECTED_PROJECT_COMMAND("add_library");
+  CM_UNEXPECTED_PROJECT_COMMAND("add_subdirectory");
+  CM_UNEXPECTED_PROJECT_COMMAND("add_test");
+  CM_UNEXPECTED_PROJECT_COMMAND("aux_source_directory");
+  CM_UNEXPECTED_PROJECT_COMMAND("build_command");
+  CM_UNEXPECTED_PROJECT_COMMAND("create_test_sourcelist");
+  CM_UNEXPECTED_PROJECT_COMMAND("define_property");
+  CM_UNEXPECTED_PROJECT_COMMAND("enable_language");
+  CM_UNEXPECTED_PROJECT_COMMAND("enable_testing");
+  CM_UNEXPECTED_PROJECT_COMMAND("export");
+  CM_UNEXPECTED_PROJECT_COMMAND("fltk_wrap_ui");
+  CM_UNEXPECTED_PROJECT_COMMAND("get_source_file_property");
+  CM_UNEXPECTED_PROJECT_COMMAND("get_target_property");
+  CM_UNEXPECTED_PROJECT_COMMAND("get_test_property");
+  CM_UNEXPECTED_PROJECT_COMMAND("include_directories");
+  CM_UNEXPECTED_PROJECT_COMMAND("include_external_msproject");
+  CM_UNEXPECTED_PROJECT_COMMAND("include_regular_expression");
+  CM_UNEXPECTED_PROJECT_COMMAND("install");
+  CM_UNEXPECTED_PROJECT_COMMAND("link_directories");
+  CM_UNEXPECTED_PROJECT_COMMAND("link_libraries");
+  CM_UNEXPECTED_PROJECT_COMMAND("load_cache");
+  CM_UNEXPECTED_PROJECT_COMMAND("project");
+  CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_cpp");
+  CM_UNEXPECTED_PROJECT_COMMAND("qt_wrap_ui");
+  CM_UNEXPECTED_PROJECT_COMMAND("remove_definitions");
+  CM_UNEXPECTED_PROJECT_COMMAND("set_source_files_properties");
+  CM_UNEXPECTED_PROJECT_COMMAND("set_target_properties");
+  CM_UNEXPECTED_PROJECT_COMMAND("set_tests_properties");
+  CM_UNEXPECTED_PROJECT_COMMAND("source_group");
+  CM_UNEXPECTED_PROJECT_COMMAND("target_compile_definitions");
+  CM_UNEXPECTED_PROJECT_COMMAND("target_compile_features");
+  CM_UNEXPECTED_PROJECT_COMMAND("target_compile_options");
+  CM_UNEXPECTED_PROJECT_COMMAND("target_include_directories");
+  CM_UNEXPECTED_PROJECT_COMMAND("target_link_libraries");
+  CM_UNEXPECTED_PROJECT_COMMAND("target_sources");
+  CM_UNEXPECTED_PROJECT_COMMAND("try_compile");
+  CM_UNEXPECTED_PROJECT_COMMAND("try_run");
+
+  // deprected commands
+  CM_UNEXPECTED_PROJECT_COMMAND("export_library_dependencies");
+  CM_UNEXPECTED_PROJECT_COMMAND("load_command");
+  CM_UNEXPECTED_PROJECT_COMMAND("output_required_files");
+  CM_UNEXPECTED_PROJECT_COMMAND("subdir_depends");
+  CM_UNEXPECTED_PROJECT_COMMAND("utility_source");
+  CM_UNEXPECTED_PROJECT_COMMAND("variable_requires");
 
-  return commands;
+#undef CM_UNEXPECTED_PROJECT_COMMAND
 }
diff --git a/Source/cmCommands.h b/Source/cmCommands.h
index 649dea6..1f8fafb 100644
--- a/Source/cmCommands.h
+++ b/Source/cmCommands.h
@@ -3,16 +3,15 @@
 #ifndef cmCommands_h
 #define cmCommands_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+class cmState;
 
-#include <vector>
-
-class cmCommand;
 /**
- * Global function to return all compiled in commands.
+ * Global function to register all compiled in commands.
  * To add a new command edit cmCommands.cxx and add your command.
  * It is up to the caller to delete the commands created by this call.
  */
-std::vector<cmCommand*> GetPredefinedCommands();
+void GetScriptingCommands(cmState* state);
+void GetProjectCommands(cmState* state);
+void GetProjectCommandsInScriptMode(cmState* state);
 
 #endif
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 239582f..391d65c 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCommonTargetGenerator.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 #include <set>
 #include <sstream>
 #include <utility>
@@ -26,7 +26,6 @@ cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
   , GlobalGenerator(static_cast<cmGlobalCommonGenerator*>(
       gt->LocalGenerator->GetGlobalGenerator()))
   , ConfigName(LocalGenerator->GetConfigName())
-  , ModuleDefinitionFile(GeneratorTarget->GetModuleDefinitionFile(ConfigName))
 {
 }
 
@@ -44,33 +43,12 @@ const char* cmCommonTargetGenerator::GetFeature(const std::string& feature)
   return this->GeneratorTarget->GetFeature(feature, this->ConfigName);
 }
 
-bool cmCommonTargetGenerator::GetFeatureAsBool(const std::string& feature)
-{
-  return this->GeneratorTarget->GetFeatureAsBool(feature, this->ConfigName);
-}
-
-void cmCommonTargetGenerator::AddFeatureFlags(std::string& flags,
-                                              const std::string& lang)
-{
-  // Add language-specific flags.
-  this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName);
-
-  if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION")) {
-    this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
-  }
-}
-
 void cmCommonTargetGenerator::AddModuleDefinitionFlag(
   cmLinkLineComputer* linkLineComputer, std::string& flags)
 {
-  // A module definition file only makes sense on certain target types.
-  if (this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY &&
-      this->GeneratorTarget->GetType() != cmStateEnums::MODULE_LIBRARY &&
-      this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE) {
-    return;
-  }
-
-  if (!this->ModuleDefinitionFile) {
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
+  if (!mdi || mdi->DefFile.empty()) {
     return;
   }
 
@@ -85,8 +63,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(
   // vs6's "cl -link" pass it to the linker.
   std::string flag = defFileFlag;
   flag += this->LocalGenerator->ConvertToOutputFormat(
-    linkLineComputer->ConvertToLinkReference(
-      this->ModuleDefinitionFile->GetFullPath()),
+    linkLineComputer->ConvertToLinkReference(mdi->DefFile),
     cmOutputConverter::SHELL);
   this->LocalGenerator->AppendFlags(flags, flag);
 }
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
index d67fefb..c36145f 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -3,7 +3,8 @@
 #ifndef cmCommonTargetGenerator_h
 #define cmCommonTargetGenerator_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
+
 #include <map>
 #include <string>
 #include <vector>
@@ -27,12 +28,8 @@ public:
   std::string const& GetConfigName() const;
 
 protected:
-  // Add language feature flags.
-  void AddFeatureFlags(std::string& flags, const std::string& lang);
-
   // Feature query methods.
   const char* GetFeature(const std::string& feature);
-  bool GetFeatureAsBool(const std::string& feature);
 
   // Helper to add flag for windows .def file.
   void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer,
@@ -44,9 +41,6 @@ protected:
   cmGlobalCommonGenerator* GlobalGenerator;
   std::string ConfigName;
 
-  // The windows module definition source file (.def), if any.
-  cmSourceFile const* ModuleDefinitionFile;
-
   void AppendFortranFormatFlags(std::string& flags,
                                 cmSourceFile const& source);
 
diff --git a/Source/cmComputeComponentGraph.h b/Source/cmComputeComponentGraph.h
index 608dedc..8cd4fe7 100644
--- a/Source/cmComputeComponentGraph.h
+++ b/Source/cmComputeComponentGraph.h
@@ -3,7 +3,7 @@
 #ifndef cmComputeComponentGraph_h
 #define cmComputeComponentGraph_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmGraphAdjacencyList.h"
 
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 3e2cf18..9c516ee 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -333,7 +333,7 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
   return index;
 }
 
-void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
+void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe)
 {
   // Get this entry representation.
   int depender_index = qe.Index;
diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h
index 6a4e8e0..84ee916 100644
--- a/Source/cmComputeLinkDepends.h
+++ b/Source/cmComputeLinkDepends.h
@@ -3,7 +3,7 @@
 #ifndef cmComputeLinkDepends_h
 #define cmComputeLinkDepends_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmGraphAdjacencyList.h"
 #include "cmLinkItem.h"
@@ -93,7 +93,7 @@ private:
     const char* LibDepends;
   };
   std::queue<BFSEntry> BFSQueue;
-  void FollowLinkEntry(BFSEntry const&);
+  void FollowLinkEntry(BFSEntry qe);
 
   // Shared libraries that are included only because they are
   // dependencies of other shared libraries, not because they are part
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 80e7e7d..b2deaaa 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -500,7 +500,10 @@ bool cmComputeLinkInformation::Compute()
       cmGeneratorTarget const* tgt = *i;
       bool implib = (this->UseImportLibrary &&
                      (tgt->GetType() == cmStateEnums::SHARED_LIBRARY));
-      std::string lib = tgt->GetFullPath(this->Config, implib, true);
+      cmStateEnums::ArtifactType artifact = implib
+        ? cmStateEnums::ImportLibraryArtifact
+        : cmStateEnums::RuntimeBinaryArtifact;
+      std::string lib = tgt->GetFullPath(this->Config, artifact, true);
       this->OldLinkDirItems.push_back(lib);
     }
   }
@@ -596,8 +599,11 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
       // platform.  Add it now.
       std::string linkItem;
       linkItem = this->LoaderFlag;
+      cmStateEnums::ArtifactType artifact = this->UseImportLibrary
+        ? cmStateEnums::ImportLibraryArtifact
+        : cmStateEnums::RuntimeBinaryArtifact;
 
-      std::string exe = tgt->GetFullPath(config, this->UseImportLibrary, true);
+      std::string exe = tgt->GetFullPath(config, artifact, true);
       linkItem += exe;
       this->Items.push_back(Item(linkItem, true, tgt));
       this->Depends.push_back(exe);
@@ -617,9 +623,12 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
       bool implib =
         (this->UseImportLibrary &&
          (impexe || tgt->GetType() == cmStateEnums::SHARED_LIBRARY));
+      cmStateEnums::ArtifactType artifact = implib
+        ? cmStateEnums::ImportLibraryArtifact
+        : cmStateEnums::RuntimeBinaryArtifact;
 
       // Pass the full path to the target file.
-      std::string lib = tgt->GetFullPath(config, implib, true);
+      std::string lib = tgt->GetFullPath(config, artifact, true);
       if (!this->LinkDependsNoShared ||
           tgt->GetType() != cmStateEnums::SHARED_LIBRARY) {
         this->Depends.push_back(lib);
@@ -689,7 +698,10 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
   // linked will be able to find it.
   std::string lib;
   if (tgt) {
-    lib = tgt->GetFullPath(this->Config, this->UseImportLibrary);
+    cmStateEnums::ArtifactType artifact = this->UseImportLibrary
+      ? cmStateEnums::ImportLibraryArtifact
+      : cmStateEnums::RuntimeBinaryArtifact;
+    lib = tgt->GetFullPath(this->Config, artifact);
     this->AddLibraryRuntimeInfo(lib, tgt);
   } else {
     lib = item;
@@ -1021,8 +1033,8 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item)
   // See documentation of CMP0008.
   std::string generator = this->GlobalGenerator->GetName();
   if (this->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW &&
-      (generator.find("Visual Studio") != generator.npos ||
-       generator.find("Xcode") != generator.npos)) {
+      (generator.find("Visual Studio") != std::string::npos ||
+       generator.find("Xcode") != std::string::npos)) {
     std::string file = cmSystemTools::GetFilenameName(item);
     if (!this->ExtractAnyLibraryName.find(file.c_str())) {
       this->HandleBadFullItem(item, file);
@@ -1725,7 +1737,13 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
     }
   }
   if (use_build_rpath || use_link_rpath) {
-    std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+    std::string rootPath;
+    if (const char* sysrootLink =
+          this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
+      rootPath = sysrootLink;
+    } else {
+      rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+    }
     const char* stagePath =
       this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
     const char* installPrefix =
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 3d26ea7..00e3ad2 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -3,9 +3,9 @@
 #ifndef cmComputeLinkInformation_h
 #define cmComputeLinkInformation_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <iosfwd>
 #include <set>
 #include <string>
@@ -36,12 +36,6 @@ public:
       , Target(CM_NULLPTR)
     {
     }
-    Item(Item const& item)
-      : Value(item.Value)
-      , IsPath(item.IsPath)
-      , Target(item.Target)
-    {
-    }
     Item(std::string const& v, bool p,
          cmGeneratorTarget const* target = CM_NULLPTR)
       : Value(v)
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index cfebda2..ff19eac 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -238,7 +238,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
         // Don't emit the same library twice for this target.
         if (emitted.insert(*lib).second) {
           this->AddTargetDepend(depender_index, *lib, true);
-          this->AddInterfaceDepends(depender_index, *lib, emitted);
+          this->AddInterfaceDepends(depender_index, *lib, *it, emitted);
         }
       }
     }
@@ -273,7 +273,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(
       // Don't emit the same library twice for this target.
       if (emitted.insert(*lib).second) {
         this->AddTargetDepend(depender_index, *lib, true);
-        this->AddInterfaceDepends(depender_index, *lib, emitted);
+        this->AddInterfaceDepends(depender_index, *lib, config, emitted);
       }
     }
   }
@@ -281,7 +281,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(
 
 void cmComputeTargetDepends::AddInterfaceDepends(
   int depender_index, cmLinkItem const& dependee_name,
-  std::set<std::string>& emitted)
+  const std::string& config, std::set<std::string>& emitted)
 {
   cmGeneratorTarget const* depender = this->Targets[depender_index];
   cmGeneratorTarget const* dependee = dependee_name.Target;
@@ -294,15 +294,9 @@ void cmComputeTargetDepends::AddInterfaceDepends(
   }
 
   if (dependee) {
-    this->AddInterfaceDepends(depender_index, dependee, "", emitted);
-    std::vector<std::string> configs;
-    depender->Makefile->GetConfigurations(configs);
-    for (std::vector<std::string>::const_iterator it = configs.begin();
-         it != configs.end(); ++it) {
-      // A target should not depend on itself.
-      emitted.insert(depender->GetName());
-      this->AddInterfaceDepends(depender_index, dependee, *it, emitted);
-    }
+    // A target should not depend on itself.
+    emitted.insert(depender->GetName());
+    this->AddInterfaceDepends(depender_index, dependee, config, emitted);
   }
 }
 
diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h
index 2b6591f..e93e376 100644
--- a/Source/cmComputeTargetDepends.h
+++ b/Source/cmComputeTargetDepends.h
@@ -3,7 +3,7 @@
 #ifndef cmComputeTargetDepends_h
 #define cmComputeTargetDepends_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmGraphAdjacencyList.h"
 
@@ -50,6 +50,7 @@ private:
                        bool linking);
   bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
   void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name,
+                           const std::string& config,
                            std::set<std::string>& emitted);
   void AddInterfaceDepends(int depender_index,
                            cmGeneratorTarget const* dependee,
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index f2eb601..2bacf73 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmConditionEvaluator.h"
 
+#include "cmConfigure.h"
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
-#include <cmConfigure.h>
-#include <cmsys/RegularExpression.hxx>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -285,12 +285,12 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
   bool oldResult = this->GetBooleanValueOld(newArg, oneArg);
   if (newResult != oldResult) {
     switch (this->Policy12Status) {
-      case cmPolicies::WARN: {
+      case cmPolicies::WARN:
         errorString = "An argument named \"" + newArg.GetValue() +
           "\" appears in a conditional statement.  " +
           cmPolicies::GetPolicyWarning(cmPolicies::CMP0012);
         status = cmake::AUTHOR_WARNING;
-      }
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         return oldResult;
       case cmPolicies::REQUIRED_IF_USED:
diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h
index 5815177..50f4edc 100644
--- a/Source/cmConditionEvaluator.h
+++ b/Source/cmConditionEvaluator.h
@@ -3,7 +3,7 @@
 #ifndef cmConditionEvaluator_h
 #define cmConditionEvaluator_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <list>
 #include <string>
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 26f1df2..524fdf8 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -3,7 +3,7 @@
 #ifndef cmConfigure_h
 #define cmConfigure_h
 
-#include <cmsys/Configure.hxx> // IWYU pragma: keep
+#include "cmsys/Configure.hxx" // IWYU pragma: export
 
 #ifdef _MSC_VER
 #pragma warning(disable : 4786)
@@ -21,6 +21,10 @@
 #cmakedefine CMAKE_USE_MACH_PARSER
 #cmakedefine CMAKE_USE_LIBUV
 #cmakedefine CMake_HAVE_CXX_AUTO_PTR
+#cmakedefine CMake_HAVE_CXX_EQ_DELETE
+#cmakedefine CMake_HAVE_CXX_FALLTHROUGH
+#cmakedefine CMake_HAVE_CXX_GNU_FALLTHROUGH
+#cmakedefine CMake_HAVE_CXX_ATTRIBUTE_FALLTHROUGH
 #cmakedefine CMake_HAVE_CXX_MAKE_UNIQUE
 #cmakedefine CMake_HAVE_CXX_NULLPTR
 #cmakedefine CMake_HAVE_CXX_OVERRIDE
@@ -30,6 +34,22 @@
 #define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@"
 #define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
 
+#ifdef CMake_HAVE_CXX_EQ_DELETE
+#define CM_EQ_DELETE = delete
+#else
+#define CM_EQ_DELETE
+#endif
+
+#if defined(CMake_HAVE_CXX_FALLTHROUGH)
+#define CM_FALLTHROUGH [[fallthrough]]
+#elif defined(CMake_HAVE_CXX_GNU_FALLTHROUGH)
+#define CM_FALLTHROUGH [[gnu::fallthrough]]
+elif defined(CMake_HAVE_CXX_ATTRIBUTE_FALLTHROUGH)
+#define CM_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define CM_FALLTHROUGH
+#endif
+
 #ifdef CMake_HAVE_CXX_NULLPTR
 #define CM_NULLPTR nullptr
 #else
@@ -42,4 +62,8 @@
 #define CM_OVERRIDE
 #endif
 
+#define CM_DISABLE_COPY(Class)                                                \
+  Class(Class const&) CM_EQ_DELETE;                                           \
+  Class& operator=(Class const&) CM_EQ_DELETE;
+
 #endif
diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx
index b9c7549..18005f2 100644
--- a/Source/cmConfigureFileCommand.cxx
+++ b/Source/cmConfigureFileCommand.cxx
@@ -19,7 +19,7 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args,
     return false;
   }
 
-  const char* inFile = args[0].c_str();
+  std::string const& inFile = args[0];
   if (!cmSystemTools::FileIsFullPath(inFile)) {
     this->InputFile = this->Makefile->GetCurrentSourceDirectory();
     this->InputFile += "/";
@@ -38,7 +38,7 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args,
     return false;
   }
 
-  const char* outFile = args[1].c_str();
+  std::string const& outFile = args[1];
   if (!cmSystemTools::FileIsFullPath(outFile)) {
     this->OutputFile = this->Makefile->GetCurrentBinaryDirectory();
     this->OutputFile += "/";
diff --git a/Source/cmConfigureFileCommand.h b/Source/cmConfigureFileCommand.h
index e558b85..6cebbd2 100644
--- a/Source/cmConfigureFileCommand.h
+++ b/Source/cmConfigureFileCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmConfigureFileCommand_h
 #define cmConfigureFileCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -24,16 +25,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "configure_file"; }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
 private:
   int ConfigureFile();
 
diff --git a/Source/cmContinueCommand.cxx b/Source/cmContinueCommand.cxx
index 53d035d..2298a05 100644
--- a/Source/cmContinueCommand.cxx
+++ b/Source/cmContinueCommand.cxx
@@ -19,7 +19,7 @@ bool cmContinueCommand::InitialPass(std::vector<std::string> const& args,
     return true;
   }
 
-  status.SetContinueInvoked(true);
+  status.SetContinueInvoked();
 
   if (!args.empty()) {
     this->Makefile->IssueMessage(cmake::FATAL_ERROR,
diff --git a/Source/cmContinueCommand.h b/Source/cmContinueCommand.h
index c5b8919..92bc68e 100644
--- a/Source/cmContinueCommand.h
+++ b/Source/cmContinueCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmContinueCommand_h
 #define cmContinueCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "continue"; }
 };
 
 #endif
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index ff9ffc0..9a4abf3 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -2,12 +2,13 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCoreTryCompile.h"
 
-#include <cmConfigure.h>
-#include <cmsys/Directory.hxx>
+#include "cmConfigure.h"
+#include "cmsys/Directory.hxx"
 #include <set>
 #include <sstream>
 #include <stdio.h>
 #include <string.h>
+#include <utility>
 
 #include "cmAlgorithms.h"
 #include "cmExportTryCompileFileGenerator.h"
@@ -40,6 +41,8 @@ static std::string const kCMAKE_OSX_SYSROOT = "CMAKE_OSX_SYSROOT";
 static std::string const kCMAKE_POSITION_INDEPENDENT_CODE =
   "CMAKE_POSITION_INDEPENDENT_CODE";
 static std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT";
+static std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE";
+static std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK";
 static std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES =
   "CMAKE_TRY_COMPILE_OSX_ARCHITECTURES";
 static std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES =
@@ -216,6 +219,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
             if (tgt->IsExecutableWithExports()) {
               break;
             }
+            CM_FALLTHROUGH;
           default:
             this->Makefile->IssueMessage(
               cmake::FATAL_ERROR,
@@ -513,6 +517,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
         this->Makefile->IssueMessage(
           cmake::FATAL_ERROR,
           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0066));
+        CM_FALLTHROUGH;
       case cmPolicies::NEW: {
         // NEW behavior is to pass config-specific compiler flags.
         static std::string const cfgDefault = "DEBUG";
@@ -550,6 +555,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
         this->Makefile->IssueMessage(
           cmake::FATAL_ERROR,
           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0056));
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior is to pass linker flags.
         {
@@ -608,6 +614,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
       vars.insert(kCMAKE_OSX_SYSROOT);
       vars.insert(kCMAKE_POSITION_INDEPENDENT_CODE);
       vars.insert(kCMAKE_SYSROOT);
+      vars.insert(kCMAKE_SYSROOT_COMPILE);
+      vars.insert(kCMAKE_SYSROOT_LINK);
       vars.insert(kCMAKE_WARN_DEPRECATED);
 
       if (const char* varListStr = this->Makefile->GetDefinition(
@@ -667,7 +675,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
       fprintf(fout, " \"%s\"", si->c_str());
 
       // Add dependencies on any non-temporary sources.
-      if (si->find("CMakeTmp") == si->npos) {
+      if (si->find("CMakeTmp") == std::string::npos) {
         this->Makefile->AddCMakeDependFile(*si);
       }
     }
@@ -688,6 +696,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
         case cmPolicies::WARN:
           warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
             "CMAKE_POLICY_WARNING_CMP0067");
+          CM_FALLTHROUGH;
         case cmPolicies::OLD:
           // OLD behavior is to not honor the language standard variables.
           honorStandard = false;
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index 4b96aed..365154d 100644
--- a/Source/cmCoreTryCompile.h
+++ b/Source/cmCoreTryCompile.h
@@ -3,7 +3,7 @@
 #ifndef cmCoreTryCompile_h
 #define cmCoreTryCompile_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmCreateTestSourceList.h b/Source/cmCreateTestSourceList.h
index 5e003cf..f1f1e4b 100644
--- a/Source/cmCreateTestSourceList.h
+++ b/Source/cmCreateTestSourceList.h
@@ -3,7 +3,7 @@
 #ifndef cmCreateTestSourceList_h
 #define cmCreateTestSourceList_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <string>
 #include <vector>
@@ -31,11 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "create_test_sourcelist"; }
 };
 
 #endif
diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx
index d5807b1..7995b2c 100644
--- a/Source/cmCryptoHash.cxx
+++ b/Source/cmCryptoHash.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCryptoHash.h"
 
-#include <cm_kwiml.h>
-#include <cm_rhash.h>
-#include <cmsys/FStream.hxx>
+#include "cm_kwiml.h"
+#include "cm_rhash.h"
+#include "cmsys/FStream.hxx"
 #include <string.h>
 
 static unsigned int const cmCryptoHashAlgoToId[] = {
diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h
index 0b562da..c380d85 100644
--- a/Source/cmCryptoHash.h
+++ b/Source/cmCryptoHash.h
@@ -3,7 +3,7 @@
 #ifndef cmCryptoHash_h
 #define cmCryptoHash_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include <stddef.h>
 #include <string>
@@ -16,6 +16,8 @@
  */
 class cmCryptoHash
 {
+  CM_DISABLE_COPY(cmCryptoHash)
+
 public:
   enum Algo
   {
diff --git a/Source/cmCurl.h b/Source/cmCurl.h
index 60ab9fe..a2fa4b1 100644
--- a/Source/cmCurl.h
+++ b/Source/cmCurl.h
@@ -3,9 +3,9 @@
 #ifndef cmCurl_h
 #define cmCurl_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cm_curl.h>
+#include "cm_curl.h"
 #include <string>
 
 std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = CM_NULLPTR);
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 050de17..5e377b5 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -4,7 +4,7 @@
 
 #include "cmMakefile.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 cmCustomCommand::cmCustomCommand()
   : Backtrace()
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 73d53ff..9e82f25 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -3,7 +3,7 @@
 #ifndef cmCustomCommand_h
 #define cmCustomCommand_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmCustomCommandLines.h"
 #include "cmListFileCache.h"
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 8f4ff4b..67213ec 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -13,7 +13,7 @@
 #include "cmSystemTools.h"
 #include "cm_auto_ptr.hxx"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
                                                    const std::string& config,
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 286aaf3..0a2adb5 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -3,8 +3,8 @@
 #ifndef cmCustomCommandGenerator_h
 #define cmCustomCommandGenerator_h
 
+#include "cmConfigure.h" // IWYU pragma: keep
 #include "cmCustomCommandLines.h"
-#include <cmConfigure.h> // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmCustomCommandLines.h b/Source/cmCustomCommandLines.h
index 87ed4e8..36838f2 100644
--- a/Source/cmCustomCommandLines.h
+++ b/Source/cmCustomCommandLines.h
@@ -3,7 +3,7 @@
 #ifndef cmCustomCommandLines_h
 #define cmCustomCommandLines_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx
index 9a097f3..86a83da 100644
--- a/Source/cmDefinePropertyCommand.cxx
+++ b/Source/cmDefinePropertyCommand.cxx
@@ -20,23 +20,25 @@ bool cmDefinePropertyCommand::InitialPass(std::vector<std::string> const& args,
 
   // Get the scope in which to define the property.
   cmProperty::ScopeType scope;
-  if (args[0] == "GLOBAL") {
+  std::string const& scope_arg = args[0];
+
+  if (scope_arg == "GLOBAL") {
     scope = cmProperty::GLOBAL;
-  } else if (args[0] == "DIRECTORY") {
+  } else if (scope_arg == "DIRECTORY") {
     scope = cmProperty::DIRECTORY;
-  } else if (args[0] == "TARGET") {
+  } else if (scope_arg == "TARGET") {
     scope = cmProperty::TARGET;
-  } else if (args[0] == "SOURCE") {
+  } else if (scope_arg == "SOURCE") {
     scope = cmProperty::SOURCE_FILE;
-  } else if (args[0] == "TEST") {
+  } else if (scope_arg == "TEST") {
     scope = cmProperty::TEST;
-  } else if (args[0] == "VARIABLE") {
+  } else if (scope_arg == "VARIABLE") {
     scope = cmProperty::VARIABLE;
-  } else if (args[0] == "CACHED_VARIABLE") {
+  } else if (scope_arg == "CACHED_VARIABLE") {
     scope = cmProperty::CACHED_VARIABLE;
   } else {
     std::ostringstream e;
-    e << "given invalid scope " << args[0] << ".  "
+    e << "given invalid scope " << scope_arg << ".  "
       << "Valid scopes are "
       << "GLOBAL, DIRECTORY, TARGET, SOURCE, "
       << "TEST, VARIABLE, CACHED_VARIABLE.";
diff --git a/Source/cmDefinePropertyCommand.h b/Source/cmDefinePropertyCommand.h
index 02e5b88..bc120c5 100644
--- a/Source/cmDefinePropertyCommand.h
+++ b/Source/cmDefinePropertyCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmDefinesPropertyCommand_h
 #define cmDefinesPropertyCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -23,11 +24,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "define_property"; }
-
 private:
   std::string PropertyName;
   std::string BriefDocs;
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 47fe76a..7aa7641 100644
--- a/Source/cmDefinitions.cxx
+++ b/Source/cmDefinitions.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmDefinitions.h"
 
+#include "cmConfigure.h"
 #include <assert.h>
-#include <cmConfigure.h>
 #include <set>
 #include <utility>
 
diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h
index ad40665..ddb8918 100644
--- a/Source/cmDefinitions.h
+++ b/Source/cmDefinitions.h
@@ -3,7 +3,7 @@
 #ifndef cmDefinitions_h
 #define cmDefinitions_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
@@ -65,12 +65,6 @@ private:
       , Used(false)
     {
     }
-    Def(Def const& d)
-      : std_string(d)
-      , Exists(d.Exists)
-      , Used(d.Used)
-    {
-    }
     bool Exists;
     bool Used;
   };
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index c189419..c898d12 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -7,8 +7,9 @@
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <sstream>
 #include <string.h>
 #include <utility>
@@ -75,13 +76,7 @@ bool cmDepends::Check(const char* makeFile, const char* internalFile,
                       std::map<std::string, DependencyVector>& validDeps)
 {
   // Dependency checks must be done in proper working directory.
-  std::string oldcwd = ".";
-  if (this->CompileDirectory != ".") {
-    // Get the CWD but do not call CollapseFullPath because
-    // we only need it to cd back, and the form does not matter
-    oldcwd = cmSystemTools::GetCurrentWorkingDirectory(false);
-    cmSystemTools::ChangeDirectory(this->CompileDirectory);
-  }
+  cmWorkingDirectory workdir(this->CompileDirectory);
 
   // Check whether dependencies must be regenerated.
   bool okay = true;
@@ -93,11 +88,6 @@ bool cmDepends::Check(const char* makeFile, const char* internalFile,
     okay = false;
   }
 
-  // Restore working directory.
-  if (oldcwd != ".") {
-    cmSystemTools::ChangeDirectory(oldcwd);
-  }
-
   return okay;
 }
 
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index f677f80..b33feb9 100644
--- a/Source/cmDepends.h
+++ b/Source/cmDepends.h
@@ -3,7 +3,7 @@
 #ifndef cmDepends_h
 #define cmDepends_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <map>
@@ -24,6 +24,8 @@ class cmLocalGenerator;
  */
 class cmDepends
 {
+  CM_DISABLE_COPY(cmDepends)
+
 public:
   /** Instances need to know the build directory name and the relative
       path from the build directory to the target file.  */
@@ -116,10 +118,6 @@ protected:
   std::vector<std::string> IncludePath;
 
   void SetIncludePathFromLanguage(const std::string& lang);
-
-private:
-  cmDepends(cmDepends const&);      // Purposely not implemented.
-  void operator=(cmDepends const&); // Purposely not implemented.
 };
 
 #endif
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 9d4b9cc..2c464cc 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmDependsC.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <utility>
 
 #include "cmAlgorithms.h"
@@ -449,11 +449,11 @@ void cmDependsC::ParseTransform(std::string const& xform)
   // A transform rule is of the form SOME_MACRO(%)=value-with-%
   // We can simply separate with "(%)=".
   std::string::size_type pos = xform.find("(%)=");
-  if (pos == xform.npos || pos == 0) {
+  if (pos == std::string::npos || pos == 0) {
     return;
   }
   std::string name = xform.substr(0, pos);
-  std::string value = xform.substr(pos + 4, xform.npos);
+  std::string value = xform.substr(pos + 4);
   this->TransformRules[name] = value;
 }
 
diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h
index 3b5eb62..250d40f 100644
--- a/Source/cmDependsC.h
+++ b/Source/cmDependsC.h
@@ -3,11 +3,11 @@
 #ifndef cmDependsC_h
 #define cmDependsC_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmDepends.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <iosfwd>
 #include <map>
 #include <queue>
@@ -22,6 +22,8 @@ class cmLocalGenerator;
  */
 class cmDependsC : public cmDepends
 {
+  CM_DISABLE_COPY(cmDependsC)
+
 public:
   /** Checking instances need to know the build directory name and the
       relative path from the build directory to the target file.  */
@@ -93,10 +95,6 @@ protected:
 
   void WriteCacheFile() const;
   void ReadCacheFile();
-
-private:
-  cmDependsC(cmDependsC const&);     // Purposely not implemented.
-  void operator=(cmDependsC const&); // Purposely not implemented.
 };
 
 #endif
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 7927402..8b05fab 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmDependsFortran.h"
 
+#include "cmsys/FStream.hxx"
 #include <assert.h>
-#include <cmsys/FStream.hxx>
 #include <iostream>
 #include <map>
 #include <stdlib.h>
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index 90b82d4..ec208af 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -3,7 +3,8 @@
 #ifndef cmFortran_h
 #define cmFortran_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <iosfwd>
 #include <set>
 #include <string>
@@ -20,6 +21,8 @@ class cmLocalGenerator;
  */
 class cmDependsFortran : public cmDepends
 {
+  CM_DISABLE_COPY(cmDependsFortran)
+
 public:
   /** Checking instances need to know the build directory name and the
       relative path from the build directory to the target file.  */
@@ -76,9 +79,6 @@ protected:
   cmDependsFortranInternals* Internal;
 
 private:
-  cmDependsFortran(cmDependsFortran const&); // Purposely not implemented.
-  void operator=(cmDependsFortran const&);   // Purposely not implemented.
-
   std::string MaybeConvertToRelativePath(std::string const& base,
                                          std::string const& path);
 };
diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h
index 1b9cca5..a07bf09 100644
--- a/Source/cmDependsJava.h
+++ b/Source/cmDependsJava.h
@@ -3,7 +3,7 @@
 #ifndef cmDependsJava_h
 #define cmDependsJava_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmDepends.h"
 
@@ -17,6 +17,8 @@
  */
 class cmDependsJava : public cmDepends
 {
+  CM_DISABLE_COPY(cmDependsJava)
+
 public:
   /** Checking instances need to know the build directory name and the
       relative path from the build directory to the target file.  */
@@ -33,10 +35,6 @@ protected:
   bool CheckDependencies(
     std::istream& internalDepends, const char* internalDependsFileName,
     std::map<std::string, DependencyVector>& validDeps) CM_OVERRIDE;
-
-private:
-  cmDependsJava(cmDependsJava const&);  // Purposely not implemented.
-  void operator=(cmDependsJava const&); // Purposely not implemented.
 };
 
 #endif
diff --git a/Source/cmDependsJavaParser.cxx b/Source/cmDependsJavaParser.cxx
deleted file mode 100644
index b99d631..0000000
--- a/Source/cmDependsJavaParser.cxx
+++ /dev/null
@@ -1,6006 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875d.  */
-
-/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984,
-   1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, when this file is copied by Bison into a
-   Bison output file, you may use that output file without restriction.
-   This special exception was added by the Free Software Foundation
-   in version 1.24 of Bison.  */
-
-/* Written by Richard Stallman by simplifying the original so called
-   ``semantic'' parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* turn off some warning as this is generated code */
-#if defined(_MSC_VER)
-#  pragma warning ( disable : 4702 ) /* unreachable code */
-#endif
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 1
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-/* If NAME_PREFIX is specified substitute the variables and functions
-   names.  */
-#define yyparse cmDependsJava_yyparse
-#define yylex   cmDependsJava_yylex
-#define yyerror cmDependsJava_yyerror
-#define yylval  cmDependsJava_yylval
-#define yychar  cmDependsJava_yychar
-#define yydebug cmDependsJava_yydebug
-#define yynerrs cmDependsJava_yynerrs
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     jp_ABSTRACT = 258,
-     jp_ASSERT = 259,
-     jp_BOOLEAN_TYPE = 260,
-     jp_BREAK = 261,
-     jp_BYTE_TYPE = 262,
-     jp_CASE = 263,
-     jp_CATCH = 264,
-     jp_CHAR_TYPE = 265,
-     jp_CLASS = 266,
-     jp_CONTINUE = 267,
-     jp_DEFAULT = 268,
-     jp_DO = 269,
-     jp_DOUBLE_TYPE = 270,
-     jp_ELSE = 271,
-     jp_EXTENDS = 272,
-     jp_FINAL = 273,
-     jp_FINALLY = 274,
-     jp_FLOAT_TYPE = 275,
-     jp_FOR = 276,
-     jp_IF = 277,
-     jp_IMPLEMENTS = 278,
-     jp_IMPORT = 279,
-     jp_INSTANCEOF = 280,
-     jp_INT_TYPE = 281,
-     jp_INTERFACE = 282,
-     jp_LONG_TYPE = 283,
-     jp_NATIVE = 284,
-     jp_NEW = 285,
-     jp_PACKAGE = 286,
-     jp_PRIVATE = 287,
-     jp_PROTECTED = 288,
-     jp_PUBLIC = 289,
-     jp_RETURN = 290,
-     jp_SHORT_TYPE = 291,
-     jp_STATIC = 292,
-     jp_STRICTFP = 293,
-     jp_SUPER = 294,
-     jp_SWITCH = 295,
-     jp_SYNCHRONIZED = 296,
-     jp_THIS = 297,
-     jp_THROW = 298,
-     jp_THROWS = 299,
-     jp_TRANSIENT = 300,
-     jp_TRY = 301,
-     jp_VOID = 302,
-     jp_VOLATILE = 303,
-     jp_WHILE = 304,
-     jp_BOOLEANLITERAL = 305,
-     jp_CHARACTERLITERAL = 306,
-     jp_DECIMALINTEGERLITERAL = 307,
-     jp_FLOATINGPOINTLITERAL = 308,
-     jp_HEXINTEGERLITERAL = 309,
-     jp_NULLLITERAL = 310,
-     jp_STRINGLITERAL = 311,
-     jp_NAME = 312,
-     jp_AND = 313,
-     jp_ANDAND = 314,
-     jp_ANDEQUALS = 315,
-     jp_BRACKETEND = 316,
-     jp_BRACKETSTART = 317,
-     jp_CARROT = 318,
-     jp_CARROTEQUALS = 319,
-     jp_COLON = 320,
-     jp_COMMA = 321,
-     jp_CURLYEND = 322,
-     jp_CURLYSTART = 323,
-     jp_DIVIDE = 324,
-     jp_DIVIDEEQUALS = 325,
-     jp_DOLLAR = 326,
-     jp_DOT = 327,
-     jp_EQUALS = 328,
-     jp_EQUALSEQUALS = 329,
-     jp_EXCLAMATION = 330,
-     jp_EXCLAMATIONEQUALS = 331,
-     jp_GREATER = 332,
-     jp_GTEQUALS = 333,
-     jp_GTGT = 334,
-     jp_GTGTEQUALS = 335,
-     jp_GTGTGT = 336,
-     jp_GTGTGTEQUALS = 337,
-     jp_LESLESEQUALS = 338,
-     jp_LESSTHAN = 339,
-     jp_LTEQUALS = 340,
-     jp_LTLT = 341,
-     jp_MINUS = 342,
-     jp_MINUSEQUALS = 343,
-     jp_MINUSMINUS = 344,
-     jp_PAREEND = 345,
-     jp_PARESTART = 346,
-     jp_PERCENT = 347,
-     jp_PERCENTEQUALS = 348,
-     jp_PIPE = 349,
-     jp_PIPEEQUALS = 350,
-     jp_PIPEPIPE = 351,
-     jp_PLUS = 352,
-     jp_PLUSEQUALS = 353,
-     jp_PLUSPLUS = 354,
-     jp_QUESTION = 355,
-     jp_SEMICOL = 356,
-     jp_TILDE = 357,
-     jp_TIMES = 358,
-     jp_TIMESEQUALS = 359,
-     jp_ERROR = 360
-   };
-#endif
-#define jp_ABSTRACT 258
-#define jp_ASSERT 259
-#define jp_BOOLEAN_TYPE 260
-#define jp_BREAK 261
-#define jp_BYTE_TYPE 262
-#define jp_CASE 263
-#define jp_CATCH 264
-#define jp_CHAR_TYPE 265
-#define jp_CLASS 266
-#define jp_CONTINUE 267
-#define jp_DEFAULT 268
-#define jp_DO 269
-#define jp_DOUBLE_TYPE 270
-#define jp_ELSE 271
-#define jp_EXTENDS 272
-#define jp_FINAL 273
-#define jp_FINALLY 274
-#define jp_FLOAT_TYPE 275
-#define jp_FOR 276
-#define jp_IF 277
-#define jp_IMPLEMENTS 278
-#define jp_IMPORT 279
-#define jp_INSTANCEOF 280
-#define jp_INT_TYPE 281
-#define jp_INTERFACE 282
-#define jp_LONG_TYPE 283
-#define jp_NATIVE 284
-#define jp_NEW 285
-#define jp_PACKAGE 286
-#define jp_PRIVATE 287
-#define jp_PROTECTED 288
-#define jp_PUBLIC 289
-#define jp_RETURN 290
-#define jp_SHORT_TYPE 291
-#define jp_STATIC 292
-#define jp_STRICTFP 293
-#define jp_SUPER 294
-#define jp_SWITCH 295
-#define jp_SYNCHRONIZED 296
-#define jp_THIS 297
-#define jp_THROW 298
-#define jp_THROWS 299
-#define jp_TRANSIENT 300
-#define jp_TRY 301
-#define jp_VOID 302
-#define jp_VOLATILE 303
-#define jp_WHILE 304
-#define jp_BOOLEANLITERAL 305
-#define jp_CHARACTERLITERAL 306
-#define jp_DECIMALINTEGERLITERAL 307
-#define jp_FLOATINGPOINTLITERAL 308
-#define jp_HEXINTEGERLITERAL 309
-#define jp_NULLLITERAL 310
-#define jp_STRINGLITERAL 311
-#define jp_NAME 312
-#define jp_AND 313
-#define jp_ANDAND 314
-#define jp_ANDEQUALS 315
-#define jp_BRACKETEND 316
-#define jp_BRACKETSTART 317
-#define jp_CARROT 318
-#define jp_CARROTEQUALS 319
-#define jp_COLON 320
-#define jp_COMMA 321
-#define jp_CURLYEND 322
-#define jp_CURLYSTART 323
-#define jp_DIVIDE 324
-#define jp_DIVIDEEQUALS 325
-#define jp_DOLLAR 326
-#define jp_DOT 327
-#define jp_EQUALS 328
-#define jp_EQUALSEQUALS 329
-#define jp_EXCLAMATION 330
-#define jp_EXCLAMATIONEQUALS 331
-#define jp_GREATER 332
-#define jp_GTEQUALS 333
-#define jp_GTGT 334
-#define jp_GTGTEQUALS 335
-#define jp_GTGTGT 336
-#define jp_GTGTGTEQUALS 337
-#define jp_LESLESEQUALS 338
-#define jp_LESSTHAN 339
-#define jp_LTEQUALS 340
-#define jp_LTLT 341
-#define jp_MINUS 342
-#define jp_MINUSEQUALS 343
-#define jp_MINUSMINUS 344
-#define jp_PAREEND 345
-#define jp_PARESTART 346
-#define jp_PERCENT 347
-#define jp_PERCENTEQUALS 348
-#define jp_PIPE 349
-#define jp_PIPEEQUALS 350
-#define jp_PIPEPIPE 351
-#define jp_PLUS 352
-#define jp_PLUSEQUALS 353
-#define jp_PLUSPLUS 354
-#define jp_QUESTION 355
-#define jp_SEMICOL 356
-#define jp_TILDE 357
-#define jp_TIMES 358
-#define jp_TIMESEQUALS 359
-#define jp_ERROR 360
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 1 "cmDependsJavaParser.y"
-
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
-  bison --yacc --name-prefix=cmDependsJava_yy
-  --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx
-  cmDependsJavaParser.y
-
-Modify cmDependsJavaParser.c:
-  - remove TABs
-
-*/
-
-/* Configure the parser to use a lexer object.  */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmDependsJava_yyerror(x) \
-        cmDependsJavaError(yyscanner, x)
-#define yyGetParser (cmDependsJava_yyget_extra(yyscanner))
-
-/*-------------------------------------------------------------------------*/
-#include "cmDependsJavaParserHelper.h" /* Interface to parser object.  */
-#include "cmDependsJavaLexer.h"  /* Interface to lexer object.  */
-#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
-
-/* Forward declare the lexer entry point.  */
-YY_DECL;
-
-/* Internal utility functions.  */
-static void cmDependsJavaError(yyscan_t yyscanner, const char* message);
-
-#define YYDEBUG 1
-#define YYMAXDEPTH 1000000
-
-
-#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp);
-#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval)
-#define jpStoreClass(str) \
-yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str))
-/* Disable some warnings in the generated code.  */
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label.  */
-# pragma warning (disable: 4065) /* Switch statement contains default but
-                                    no case. */
-#endif
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 214 of yacc.c.  */
-#line 372 "cmDependsJavaParser.cxx"
-
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
-
-# ifndef YYFREE
-#  define YYFREE free
-# endif
-# ifndef YYMALLOC
-#  define YYMALLOC malloc
-# endif
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   define YYSTACK_ALLOC alloca
-#  endif
-# else
-#  if defined (alloca) || defined (_ALLOCA_H)
-#   define YYSTACK_ALLOC alloca
-#  else
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning. */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-#  if defined (__STDC__) || defined (__cplusplus)
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   define YYSIZE_T size_t
-#  endif
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-# endif
-#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
-
-
-#if (! defined (yyoverflow) \
-     && (! defined (__cplusplus) \
-   || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  short int yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (short int) + sizeof (YYSTYPE))      \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined (__GNUC__) && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)    \
-      do          \
-  {          \
-    YYSIZE_T yyi;    \
-    for (yyi = 0; yyi < (Count); yyi++)  \
-      (To)[yyi] = (From)[yyi];    \
-  }          \
-      while (0)
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)          \
-    do                  \
-      {                  \
-  YYSIZE_T yynewbytes;            \
-  YYCOPY (&yyptr->Stack, Stack, yysize);        \
-  Stack = &yyptr->Stack;            \
-  yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-  yyptr += yynewbytes / sizeof (*yyptr);        \
-      }                  \
-    while (0)
-
-#endif
-
-#if defined (__STDC__) || defined (__cplusplus)
-   typedef signed char yysigned_char;
-#else
-   typedef short int yysigned_char;
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL  23
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   2215
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  106
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  158
-/* YYNRULES -- Number of rules. */
-#define YYNRULES  351
-/* YYNRULES -- Number of states. */
-#define YYNSTATES  575
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   360
-
-#define YYTRANSLATE(YYX)             \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const unsigned char yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
-      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
-      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
-      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
-      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
-     105
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const unsigned short int yyprhs[] =
-{
-       0,     0,     3,     5,     7,     9,    11,    13,    15,    17,
-      19,    21,    23,    25,    27,    29,    31,    33,    35,    37,
-      39,    41,    43,    45,    47,    49,    51,    54,    57,    59,
-      61,    63,    65,    68,    72,    76,    80,    84,    86,    88,
-      92,    93,    95,    96,    99,   100,   103,   107,   109,   111,
-     115,   121,   123,   125,   127,   129,   132,   134,   136,   138,
-     140,   142,   144,   146,   148,   150,   152,   154,   158,   161,
-     165,   169,   174,   175,   177,   180,   183,   185,   189,   193,
-     194,   197,   199,   201,   203,   205,   207,   209,   214,   216,
-     220,   222,   226,   228,   232,   234,   236,   239,   242,   246,
-     251,   256,   257,   259,   264,   268,   269,   271,   273,   277,
-     281,   284,   286,   290,   292,   295,   300,   306,   311,   316,
-     317,   320,   326,   332,   336,   340,   341,   343,   346,   350,
-     354,   355,   358,   360,   362,   364,   367,   369,   372,   374,
-     377,   379,   382,   386,   387,   389,   392,   394,   398,   402,
-     403,   405,   407,   410,   412,   414,   416,   419,   423,   426,
-     428,   430,   432,   434,   436,   438,   440,   442,   444,   446,
-     448,   450,   452,   454,   456,   458,   460,   462,   464,   466,
-     468,   470,   472,   474,   478,   482,   485,   487,   489,   491,
-     493,   495,   497,   499,   505,   513,   521,   527,   532,   533,
-     535,   536,   539,   542,   544,   547,   551,   554,   560,   566,
-     574,   584,   585,   587,   588,   590,   600,   601,   603,   605,
-     607,   609,   611,   615,   619,   625,   629,   630,   632,   636,
-     640,   644,   650,   654,   659,   660,   662,   664,   667,   673,
-     676,   678,   680,   682,   684,   688,   690,   692,   694,   696,
-     703,   704,   706,   707,   709,   711,   715,   720,   725,   730,
-     735,   736,   738,   740,   743,   747,   750,   754,   758,   762,
-     766,   770,   775,   782,   789,   796,   801,   806,   808,   810,
-     814,   816,   818,   821,   824,   826,   828,   831,   834,   836,
-     839,   842,   844,   847,   850,   852,   858,   863,   869,   871,
-     875,   879,   883,   885,   889,   893,   895,   899,   903,   907,
-     909,   913,   917,   921,   925,   929,   931,   935,   939,   941,
-     945,   947,   951,   953,   957,   959,   963,   965,   969,   971,
-     977,   979,   981,   985,   987,   989,   991,   993,   995,   997,
-     999,  1001,  1003,  1005,  1007,  1009,  1011,  1013,  1015,  1017,
-    1019,  1021
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const short int yyrhs[] =
-{
-     107,     0,    -1,   122,    -1,   109,    -1,    53,    -1,    50,
-      -1,    51,    -1,    56,    -1,    55,    -1,    52,    -1,    54,
-      -1,   111,    -1,   112,    -1,     7,    -1,    36,    -1,    26,
-      -1,    28,    -1,    10,    -1,    20,    -1,    15,    -1,     5,
-      -1,   113,    -1,   116,    -1,   117,    -1,   113,    -1,   113,
-      -1,   111,   234,    -1,   117,   234,    -1,   118,    -1,   120,
-      -1,   119,    -1,    57,    -1,    71,    57,    -1,   117,    72,
-     119,    -1,   117,    72,    11,    -1,   117,    72,    42,    -1,
-     121,    72,    11,    -1,   111,    -1,    47,    -1,   123,   124,
-     125,    -1,    -1,   126,    -1,    -1,   124,   127,    -1,    -1,
-     125,   130,    -1,    31,   117,   101,    -1,   128,    -1,   129,
-      -1,    24,   117,   101,    -1,    24,   117,    72,   103,   101,
-      -1,   134,    -1,   165,    -1,   101,    -1,   132,    -1,   131,
-     132,    -1,    34,    -1,    33,    -1,    32,    -1,    37,    -1,
-       3,    -1,    18,    -1,    29,    -1,    41,    -1,    45,    -1,
-      48,    -1,    38,    -1,   135,    11,   119,    -1,   133,   139,
-      -1,   133,   137,   139,    -1,   133,   136,   139,    -1,   133,
-     136,   137,   139,    -1,    -1,   131,    -1,    17,   114,    -1,
-      23,   138,    -1,   115,    -1,   138,    66,   115,    -1,    68,
-     140,    67,    -1,    -1,   140,   141,    -1,   142,    -1,   158,
-      -1,   159,    -1,   130,    -1,   143,    -1,   148,    -1,   135,
-     110,   144,   101,    -1,   145,    -1,   144,    66,   145,    -1,
-     146,    -1,   146,    73,   147,    -1,   119,    -1,   146,    62,
-      61,    -1,   261,    -1,   174,    -1,   149,   101,    -1,   149,
-     157,    -1,   149,   157,   101,    -1,   135,   110,   151,   150,
-      -1,   135,    47,   151,   150,    -1,    -1,   155,    -1,   119,
-      91,   152,    90,    -1,   151,    62,    61,    -1,    -1,   153,
-      -1,   154,    -1,   153,    66,   154,    -1,   135,   110,   146,
-      -1,    44,   156,    -1,   114,    -1,   156,    66,   114,    -1,
-     177,    -1,    37,   177,    -1,   135,   160,   150,   161,    -1,
-     135,   160,   150,   161,   101,    -1,   118,    91,   152,    90,
-      -1,    68,   162,   178,    67,    -1,    -1,   162,   163,    -1,
-      42,    91,   228,    90,   101,    -1,    39,    91,   228,    90,
-     101,    -1,   135,    27,   119,    -1,   164,   166,   168,    -1,
-      -1,   167,    -1,    17,   115,    -1,   167,    66,   115,    -1,
-      68,   169,    67,    -1,    -1,   169,   170,    -1,   171,    -1,
-     172,    -1,   134,    -1,   134,   101,    -1,   165,    -1,   165,
-     101,    -1,   143,    -1,   149,   173,    -1,   101,    -1,   173,
-     101,    -1,    68,   175,    67,    -1,    -1,   176,    -1,   176,
-      66,    -1,   147,    -1,   176,    66,   147,    -1,    68,   178,
-      67,    -1,    -1,   179,    -1,   180,    -1,   179,   180,    -1,
-     181,    -1,   183,    -1,   134,    -1,   182,   101,    -1,   131,
-     110,   144,    -1,   110,   144,    -1,   185,    -1,   187,    -1,
-     191,    -1,   192,    -1,   201,    -1,   204,    -1,   185,    -1,
-     188,    -1,   193,    -1,   202,    -1,   207,    -1,   177,    -1,
-     186,    -1,   189,    -1,   194,    -1,   203,    -1,   213,    -1,
-     215,    -1,   216,    -1,   218,    -1,   217,    -1,   219,    -1,
-     212,    -1,   101,    -1,   119,    65,   183,    -1,   119,    65,
-     184,    -1,   190,   101,    -1,   258,    -1,   242,    -1,   243,
-      -1,   239,    -1,   240,    -1,   236,    -1,   226,    -1,    22,
-      91,   261,    90,   183,    -1,    22,    91,   261,    90,   184,
-      16,   183,    -1,    22,    91,   261,    90,   184,    16,   184,
-      -1,    40,    91,   261,    90,   195,    -1,    68,   197,   196,
-      67,    -1,    -1,   199,    -1,    -1,   197,   198,    -1,   199,
-     179,    -1,   200,    -1,   199,   200,    -1,     8,   262,    65,
-      -1,    13,    65,    -1,    49,    91,   261,    90,   183,    -1,
-      49,    91,   261,    90,   184,    -1,    14,   183,    49,    91,
-     261,    90,   101,    -1,    21,    91,   206,   101,   208,   101,
-     205,    90,   183,    -1,    -1,   210,    -1,    -1,   209,    -1,
-      21,    91,   206,   101,   208,   101,   205,    90,   184,    -1,
-      -1,   261,    -1,   211,    -1,   182,    -1,   211,    -1,   190,
-      -1,   211,    66,   190,    -1,     4,   261,   101,    -1,     4,
-     261,    65,   261,   101,    -1,     6,   214,   101,    -1,    -1,
-     119,    -1,    12,   214,   101,    -1,    35,   208,   101,    -1,
-      43,   261,   101,    -1,    41,    91,   261,    90,   177,    -1,
-      46,   177,   221,    -1,    46,   177,   220,   223,    -1,    -1,
-     221,    -1,   222,    -1,   221,   222,    -1,     9,    91,   154,
-      90,   177,    -1,    19,   177,    -1,   225,    -1,   230,    -1,
-     108,    -1,    42,    -1,    91,   261,    90,    -1,   226,    -1,
-     235,    -1,   236,    -1,   237,    -1,   263,   114,    91,   228,
-      90,   227,    -1,    -1,   139,    -1,    -1,   229,    -1,   261,
-      -1,   229,    66,   261,    -1,   263,   111,   232,   231,    -1,
-     263,   113,   232,   231,    -1,   263,   111,   234,   174,    -1,
-     263,   113,   234,   174,    -1,    -1,   234,    -1,   233,    -1,
-     232,   233,    -1,    62,   261,    61,    -1,    62,    61,    -1,
-     234,    62,    61,    -1,   224,    72,   119,    -1,    39,    72,
-     119,    -1,    42,    72,   119,    -1,   224,    72,    42,    -1,
-     117,    91,   228,    90,    -1,   224,    72,   119,    91,   228,
-      90,    -1,    39,    72,   119,    91,   228,    90,    -1,    42,
-      72,   119,    91,   228,    90,    -1,   117,    62,   261,    61,
-      -1,   225,    62,   261,    61,    -1,   224,    -1,   117,    -1,
-     116,    72,    11,    -1,   239,    -1,   240,    -1,   238,    99,
-      -1,   238,    89,    -1,   242,    -1,   243,    -1,    97,   241,
-      -1,    87,   241,    -1,   244,    -1,    99,   241,    -1,    89,
-     241,    -1,   238,    -1,   102,   241,    -1,    75,   241,    -1,
-     245,    -1,    91,   111,   231,    90,   241,    -1,    91,   261,
-      90,   244,    -1,    91,   117,   234,    90,   244,    -1,   241,
-      -1,   246,   103,   241,    -1,   246,    69,   241,    -1,   246,
-      92,   241,    -1,   246,    -1,   247,    97,   246,    -1,   247,
-      87,   246,    -1,   247,    -1,   248,    86,   247,    -1,   248,
-      79,   247,    -1,   248,    81,   247,    -1,   248,    -1,   249,
-      84,   248,    -1,   249,    77,   248,    -1,   249,    85,   248,
-      -1,   249,    78,   248,    -1,   249,    25,   112,    -1,   249,
-      -1,   250,    74,   249,    -1,   250,    76,   249,    -1,   250,
-      -1,   251,    58,   250,    -1,   251,    -1,   252,    63,   251,
-      -1,   252,    -1,   253,    94,   252,    -1,   253,    -1,   254,
-      59,   253,    -1,   254,    -1,   255,    96,   254,    -1,   255,
-      -1,   255,   100,   261,    65,   256,    -1,   256,    -1,   258,
-      -1,   259,   260,   257,    -1,   117,    -1,   235,    -1,   237,
-      -1,    73,    -1,   104,    -1,    70,    -1,    93,    -1,    98,
-      -1,    88,    -1,    83,    -1,    80,    -1,    82,    -1,    60,
-      -1,    64,    -1,    95,    -1,   257,    -1,   261,    -1,    30,
-      -1,   117,    72,    30,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const unsigned short int yyrline[] =
-{
-       0,   191,   191,   200,   208,   216,   224,   232,   240,   249,
-     257,   266,   274,   283,   288,   293,   298,   303,   308,   313,
-     318,   324,   332,   341,   351,   360,   369,   377,   387,   393,
-     400,   407,   413,   420,   429,   439,   449,   458,   466,   475,
-     484,   490,   499,   505,   514,   520,   529,   541,   549,   558,
-     570,   583,   591,   599,   608,   616,   625,   625,   625,   626,
-     627,   627,   627,   627,   627,   627,   628,   631,   641,   650,
-     659,   668,   678,   684,   693,   702,   711,   719,   728,   737,
-     743,   752,   760,   768,   776,   785,   793,   802,   808,   816,
-     825,   833,   842,   851,   860,   868,   877,   885,   893,   902,
-     911,   921,   928,   938,   948,   955,   962,   965,   971,   981,
-     991,  1001,  1007,  1017,  1027,  1037,  1046,  1056,  1067,  1077,
-    1084,  1094,  1103,  1113,  1122,  1132,  1138,  1148,  1157,  1167,
-    1177,  1184,  1193,  1202,  1211,  1220,  1228,  1237,  1246,  1256,
-    1266,  1275,  1285,  1295,  1302,  1311,  1321,  1330,  1340,  1349,
-    1356,  1366,  1375,  1385,  1394,  1403,  1413,  1423,  1432,  1442,
-    1451,  1460,  1469,  1478,  1487,  1497,  1506,  1515,  1524,  1533,
-    1543,  1552,  1561,  1570,  1579,  1588,  1597,  1606,  1615,  1624,
-    1633,  1642,  1652,  1662,  1673,  1683,  1693,  1702,  1711,  1720,
-    1729,  1738,  1747,  1757,  1767,  1777,  1787,  1794,  1801,  1808,
-    1818,  1825,  1835,  1845,  1854,  1864,  1873,  1883,  1890,  1897,
-    1904,  1912,  1919,  1929,  1936,  1946,  1956,  1963,  1973,  1982,
-    1992,  2002,  2011,  2021,  2030,  2040,  2051,  2058,  2065,  2076,
-    2086,  2096,  2106,  2115,  2125,  2132,  2142,  2151,  2161,  2168,
-    2178,  2187,  2197,  2206,  2212,  2221,  2230,  2239,  2248,  2258,
-    2268,  2275,  2285,  2292,  2302,  2311,  2321,  2330,  2339,  2348,
-    2358,  2365,  2375,  2384,  2394,  2404,  2410,  2417,  2427,  2437,
-    2447,  2458,  2468,  2479,  2489,  2500,  2510,  2520,  2529,  2538,
-    2547,  2556,  2566,  2576,  2586,  2595,  2604,  2613,  2622,  2632,
-    2642,  2652,  2661,  2670,  2679,  2689,  2698,  2707,  2714,  2723,
-    2732,  2741,  2751,  2760,  2769,  2779,  2788,  2797,  2806,  2816,
-    2825,  2834,  2843,  2852,  2861,  2871,  2880,  2889,  2899,  2908,
-    2918,  2927,  2937,  2946,  2956,  2965,  2975,  2984,  2994,  3003,
-    3013,  3022,  3032,  3042,  3052,  3061,  3071,  3080,  3089,  3098,
-    3107,  3116,  3125,  3134,  3143,  3152,  3161,  3170,  3180,  3190,
-    3200,  3209
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "jp_ABSTRACT", "jp_ASSERT",
-  "jp_BOOLEAN_TYPE", "jp_BREAK", "jp_BYTE_TYPE", "jp_CASE", "jp_CATCH",
-  "jp_CHAR_TYPE", "jp_CLASS", "jp_CONTINUE", "jp_DEFAULT", "jp_DO",
-  "jp_DOUBLE_TYPE", "jp_ELSE", "jp_EXTENDS", "jp_FINAL", "jp_FINALLY",
-  "jp_FLOAT_TYPE", "jp_FOR", "jp_IF", "jp_IMPLEMENTS", "jp_IMPORT",
-  "jp_INSTANCEOF", "jp_INT_TYPE", "jp_INTERFACE", "jp_LONG_TYPE",
-  "jp_NATIVE", "jp_NEW", "jp_PACKAGE", "jp_PRIVATE", "jp_PROTECTED",
-  "jp_PUBLIC", "jp_RETURN", "jp_SHORT_TYPE", "jp_STATIC", "jp_STRICTFP",
-  "jp_SUPER", "jp_SWITCH", "jp_SYNCHRONIZED", "jp_THIS", "jp_THROW",
-  "jp_THROWS", "jp_TRANSIENT", "jp_TRY", "jp_VOID", "jp_VOLATILE",
-  "jp_WHILE", "jp_BOOLEANLITERAL", "jp_CHARACTERLITERAL",
-  "jp_DECIMALINTEGERLITERAL", "jp_FLOATINGPOINTLITERAL",
-  "jp_HEXINTEGERLITERAL", "jp_NULLLITERAL", "jp_STRINGLITERAL", "jp_NAME",
-  "jp_AND", "jp_ANDAND", "jp_ANDEQUALS", "jp_BRACKETEND",
-  "jp_BRACKETSTART", "jp_CARROT", "jp_CARROTEQUALS", "jp_COLON",
-  "jp_COMMA", "jp_CURLYEND", "jp_CURLYSTART", "jp_DIVIDE",
-  "jp_DIVIDEEQUALS", "jp_DOLLAR", "jp_DOT", "jp_EQUALS", "jp_EQUALSEQUALS",
-  "jp_EXCLAMATION", "jp_EXCLAMATIONEQUALS", "jp_GREATER", "jp_GTEQUALS",
-  "jp_GTGT", "jp_GTGTEQUALS", "jp_GTGTGT", "jp_GTGTGTEQUALS",
-  "jp_LESLESEQUALS", "jp_LESSTHAN", "jp_LTEQUALS", "jp_LTLT", "jp_MINUS",
-  "jp_MINUSEQUALS", "jp_MINUSMINUS", "jp_PAREEND", "jp_PARESTART",
-  "jp_PERCENT", "jp_PERCENTEQUALS", "jp_PIPE", "jp_PIPEEQUALS",
-  "jp_PIPEPIPE", "jp_PLUS", "jp_PLUSEQUALS", "jp_PLUSPLUS", "jp_QUESTION",
-  "jp_SEMICOL", "jp_TILDE", "jp_TIMES", "jp_TIMESEQUALS", "jp_ERROR",
-  "$accept", "Goal", "Literal", "IntegerLiteral", "Type", "PrimitiveType",
-  "ReferenceType", "ClassOrInterfaceType", "ClassType", "InterfaceType",
-  "ArrayType", "Name", "SimpleName", "Identifier", "QualifiedName",
-  "SimpleType", "CompilationUnit", "PackageDeclarationopt",
-  "ImportDeclarations", "TypeDeclarations", "PackageDeclaration",
-  "ImportDeclaration", "SingleTypeImportDeclaration",
-  "TypeImportOnDemandDeclaration", "TypeDeclaration", "Modifiers",
-  "Modifier", "ClassHeader", "ClassDeclaration", "Modifiersopt", "Super",
-  "Interfaces", "InterfaceTypeList", "ClassBody", "ClassBodyDeclarations",
-  "ClassBodyDeclaration", "ClassMemberDeclaration", "FieldDeclaration",
-  "VariableDeclarators", "VariableDeclarator", "VariableDeclaratorId",
-  "VariableInitializer", "MethodDeclaration", "MethodHeader", "Throwsopt",
-  "MethodDeclarator", "FormalParameterListopt", "FormalParameterList",
-  "FormalParameter", "Throws", "ClassTypeList", "MethodBody",
-  "StaticInitializer", "ConstructorDeclaration", "ConstructorDeclarator",
-  "ConstructorBody", "ExplicitConstructorInvocationopt",
-  "ExplicitConstructorInvocation", "InterfaceHeader",
-  "InterfaceDeclaration", "ExtendsInterfacesopt", "ExtendsInterfaces",
-  "InterfaceBody", "InterfaceMemberDeclarations",
-  "InterfaceMemberDeclaration", "ConstantDeclaration",
-  "AbstractMethodDeclaration", "Semicols", "ArrayInitializer",
-  "VariableInitializersOptional", "VariableInitializers", "Block",
-  "BlockStatementsopt", "BlockStatements", "BlockStatement",
-  "LocalVariableDeclarationStatement", "LocalVariableDeclaration",
-  "Statement", "StatementNoShortIf",
-  "StatementWithoutTrailingSubstatement", "EmptyStatement",
-  "LabeledStatement", "LabeledStatementNoShortIf", "ExpressionStatement",
-  "StatementExpression", "IfThenStatement", "IfThenElseStatement",
-  "IfThenElseStatementNoShortIf", "SwitchStatement", "SwitchBlock",
-  "SwitchLabelsopt", "SwitchBlockStatementGroups",
-  "SwitchBlockStatementGroup", "SwitchLabels", "SwitchLabel",
-  "WhileStatement", "WhileStatementNoShortIf", "DoStatement",
-  "ForStatement", "ForUpdateopt", "ForInitopt", "ForStatementNoShortIf",
-  "Expressionopt", "ForInit", "ForUpdate", "StatementExpressionList",
-  "AssertStatement", "BreakStatement", "Identifieropt",
-  "ContinueStatement", "ReturnStatement", "ThrowStatement",
-  "SynchronizedStatement", "TryStatement", "Catchesopt", "Catches",
-  "CatchClause", "Finally", "Primary", "PrimaryNoNewArray",
-  "ClassInstanceCreationExpression", "ClassBodyOpt", "ArgumentListopt",
-  "ArgumentList", "ArrayCreationExpression", "Dimsopt", "DimExprs",
-  "DimExpr", "Dims", "FieldAccess", "MethodInvocation", "ArrayAccess",
-  "PostfixExpression", "PostIncrementExpression",
-  "PostDecrementExpression", "UnaryExpression", "PreIncrementExpression",
-  "PreDecrementExpression", "UnaryExpressionNotPlusMinus",
-  "CastExpression", "MultiplicativeExpression", "AdditiveExpression",
-  "ShiftExpression", "RelationalExpression", "EqualityExpression",
-  "AndExpression", "ExclusiveOrExpression", "InclusiveOrExpression",
-  "ConditionalAndExpression", "ConditionalOrExpression",
-  "ConditionalExpression", "AssignmentExpression", "Assignment",
-  "LeftHandSide", "AssignmentOperator", "Expression", "ConstantExpression",
-  "New", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const unsigned short int yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
-     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
-     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
-     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
-     335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
-     345,   346,   347,   348,   349,   350,   351,   352,   353,   354,
-     355,   356,   357,   358,   359,   360
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const unsigned short int yyr1[] =
-{
-       0,   106,   107,   108,   108,   108,   108,   108,   108,   109,
-     109,   110,   110,   111,   111,   111,   111,   111,   111,   111,
-     111,   112,   112,   113,   114,   115,   116,   116,   117,   117,
-     118,   119,   119,   120,   120,   120,   120,   121,   121,   122,
-     123,   123,   124,   124,   125,   125,   126,   127,   127,   128,
-     129,   130,   130,   130,   131,   131,   132,   132,   132,   132,
-     132,   132,   132,   132,   132,   132,   132,   133,   134,   134,
-     134,   134,   135,   135,   136,   137,   138,   138,   139,   140,
-     140,   141,   141,   141,   141,   142,   142,   143,   144,   144,
-     145,   145,   146,   146,   147,   147,   148,   148,   148,   149,
-     149,   150,   150,   151,   151,   152,   152,   153,   153,   154,
-     155,   156,   156,   157,   158,   159,   159,   160,   161,   162,
-     162,   163,   163,   164,   165,   166,   166,   167,   167,   168,
-     169,   169,   170,   170,   170,   170,   170,   170,   171,   172,
-     173,   173,   174,   175,   175,   175,   176,   176,   177,   178,
-     178,   179,   179,   180,   180,   180,   181,   182,   182,   183,
-     183,   183,   183,   183,   183,   184,   184,   184,   184,   184,
-     185,   185,   185,   185,   185,   185,   185,   185,   185,   185,
-     185,   185,   186,   187,   188,   189,   190,   190,   190,   190,
-     190,   190,   190,   191,   192,   193,   194,   195,   196,   196,
-     197,   197,   198,   199,   199,   200,   200,   201,   202,   203,
-     204,   205,   205,   206,   206,   207,   208,   208,   209,   209,
-     210,   211,   211,   212,   212,   213,   214,   214,   215,   216,
-     217,   218,   219,   219,   220,   220,   221,   221,   222,   223,
-     224,   224,   225,   225,   225,   225,   225,   225,   225,   226,
-     227,   227,   228,   228,   229,   229,   230,   230,   230,   230,
-     231,   231,   232,   232,   233,   234,   234,   235,   235,   235,
-     235,   236,   236,   236,   236,   237,   237,   238,   238,   238,
-     238,   238,   239,   240,   241,   241,   241,   241,   241,   242,
-     243,   244,   244,   244,   244,   245,   245,   245,   246,   246,
-     246,   246,   247,   247,   247,   248,   248,   248,   248,   249,
-     249,   249,   249,   249,   249,   250,   250,   250,   251,   251,
-     252,   252,   253,   253,   254,   254,   255,   255,   256,   256,
-     257,   257,   258,   259,   259,   259,   260,   260,   260,   260,
-     260,   260,   260,   260,   260,   260,   260,   260,   261,   262,
-     263,   263
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const unsigned char yyr2[] =
-{
-       0,     2,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     2,     2,     1,     1,
-       1,     1,     2,     3,     3,     3,     3,     1,     1,     3,
-       0,     1,     0,     2,     0,     2,     3,     1,     1,     3,
-       5,     1,     1,     1,     1,     2,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     3,     2,     3,
-       3,     4,     0,     1,     2,     2,     1,     3,     3,     0,
-       2,     1,     1,     1,     1,     1,     1,     4,     1,     3,
-       1,     3,     1,     3,     1,     1,     2,     2,     3,     4,
-       4,     0,     1,     4,     3,     0,     1,     1,     3,     3,
-       2,     1,     3,     1,     2,     4,     5,     4,     4,     0,
-       2,     5,     5,     3,     3,     0,     1,     2,     3,     3,
-       0,     2,     1,     1,     1,     2,     1,     2,     1,     2,
-       1,     2,     3,     0,     1,     2,     1,     3,     3,     0,
-       1,     1,     2,     1,     1,     1,     2,     3,     2,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     3,     3,     2,     1,     1,     1,     1,
-       1,     1,     1,     5,     7,     7,     5,     4,     0,     1,
-       0,     2,     2,     1,     2,     3,     2,     5,     5,     7,
-       9,     0,     1,     0,     1,     9,     0,     1,     1,     1,
-       1,     1,     3,     3,     5,     3,     0,     1,     3,     3,
-       3,     5,     3,     4,     0,     1,     1,     2,     5,     2,
-       1,     1,     1,     1,     3,     1,     1,     1,     1,     6,
-       0,     1,     0,     1,     1,     3,     4,     4,     4,     4,
-       0,     1,     1,     2,     3,     2,     3,     3,     3,     3,
-       3,     4,     6,     6,     6,     4,     4,     1,     1,     3,
-       1,     1,     2,     2,     1,     1,     2,     2,     1,     2,
-       2,     1,     2,     2,     1,     5,     4,     5,     1,     3,
-       3,     3,     1,     3,     3,     1,     3,     3,     3,     1,
-       3,     3,     3,     3,     3,     1,     3,     3,     1,     3,
-       1,     3,     1,     3,     1,     3,     1,     3,     1,     5,
-       1,     1,     3,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const unsigned short int yydefact[] =
-{
-      40,     0,     0,     2,    42,    41,    20,    13,    17,    19,
-      18,    15,    16,    14,    38,    31,     0,    37,     0,    28,
-      30,    29,     0,     1,    44,    32,     0,    46,     0,     0,
-      72,    43,    47,    48,    34,    35,    33,    36,     0,    60,
-      61,    62,    58,    57,    56,    59,    66,    63,    64,    65,
-      53,    45,    73,    54,     0,    51,     0,   125,    52,     0,
-      49,    55,     0,     0,    79,     0,     0,    68,     0,     0,
-       0,     0,   126,     0,    24,    74,    23,    25,    76,    75,
-      72,     0,    70,    69,    67,   123,   127,   130,   124,     0,
-      50,     0,    59,    78,    84,     0,    80,    81,    85,    86,
-       0,    82,    83,    71,    72,   128,    77,    72,   114,    38,
-       0,    11,    12,    21,    22,    23,    28,   101,    96,    97,
-     113,   129,   134,     0,   138,     0,   136,   131,   132,   133,
-       0,   226,   226,     0,     0,     0,   350,   216,     0,     0,
-      63,   243,     0,     0,     0,     5,     6,     9,     4,    10,
-       8,     7,     0,     0,     0,   182,   242,     3,     0,    22,
-     333,    30,    73,   155,     0,   170,     0,    72,   151,   153,
-       0,   154,   159,   171,   160,   172,     0,   161,   162,   173,
-     163,   174,   164,   181,   175,   176,   177,   179,   178,   180,
-     277,   240,   245,   241,   246,   247,   248,     0,   189,   190,
-     187,   188,   186,     0,     0,     0,   101,    92,     0,    88,
-      90,   101,     0,    26,    27,    72,     0,     0,   102,    98,
-     135,   140,   139,   137,     0,     0,     0,     0,     0,    37,
-       0,   278,   245,   247,   291,   280,   281,   298,   284,   285,
-     288,   294,   302,   305,   309,   315,   318,   320,   322,   324,
-     326,   328,   330,   348,   331,     0,   227,     0,     0,     0,
-       0,   213,     0,     0,   217,     0,     0,     0,     0,     0,
-     234,     0,   278,   246,   248,   290,     0,   289,    92,   158,
-       0,     0,     0,   252,     0,     0,   148,   152,   156,   185,
-       0,     0,   283,   282,   345,   346,   338,   336,   343,   344,
-     342,   341,   339,   347,   340,   337,     0,    37,    24,     0,
-      72,     0,   100,     0,    87,     0,     0,    99,   265,     0,
-       0,     0,   106,   107,   111,   110,   119,   115,   141,   293,
-     287,    37,   278,     0,   286,   292,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   223,   225,
-     228,     0,     0,   219,   221,     0,   214,   218,     0,   229,
-     268,     0,     0,   269,   230,     0,     0,   232,   236,     0,
-     244,   279,     0,   351,     0,   253,   254,   183,   157,   270,
-     267,     0,   332,     0,   260,   262,     0,   260,     0,   252,
-       0,   104,    89,    93,   143,    91,    95,    94,   266,     0,
-     117,    72,     0,    72,   116,     0,    26,    27,   244,   300,
-     301,   299,   304,   303,   307,   308,   306,   314,   311,   313,
-     310,   312,   316,   317,   319,   321,   323,   325,   327,     0,
-       0,     0,   216,     0,     0,   252,     0,     0,   252,    72,
-       0,   233,   237,     0,   275,   271,     0,   252,   276,     0,
-     256,   263,   261,   258,   257,   259,     0,   103,   146,     0,
-     144,   109,   108,   112,     0,   243,   120,     0,     0,     0,
-     296,     0,   224,     0,     0,   222,     0,     0,     0,    30,
-     193,     0,   159,   166,   167,   168,   169,     0,   200,   196,
-     231,     0,     0,   239,   207,   255,     0,   264,   250,   142,
-     145,   252,   252,   118,   295,   297,   329,     0,   211,   213,
-       0,     0,     0,     0,   273,   198,   274,     0,   272,   251,
-     249,   147,     0,     0,   209,     0,   212,   220,     0,     0,
-       0,   184,   194,     0,     0,     0,   201,    72,   203,   238,
-       0,     0,     0,   216,     0,     0,   349,     0,   206,   197,
-     202,   204,   122,   121,   210,     0,     0,   208,   205,   211,
-       0,     0,   195,     0,   215
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const short int yydefgoto[] =
-{
-      -1,     2,   156,   157,   158,   229,   112,   113,    75,    78,
-     230,   231,    19,    20,    21,    22,     3,     4,    24,    30,
-       5,    31,    32,    33,    51,    52,    53,    54,   163,   164,
-      65,    66,    79,    67,    80,    96,    97,    98,   208,   209,
-     210,   405,    99,   100,   217,   206,   321,   322,   323,   218,
-     325,   119,   101,   102,   117,   327,   413,   476,    57,    58,
-      71,    72,    88,   104,   127,   128,   129,   222,   406,   469,
-     470,   165,   166,   167,   168,   169,   170,   171,   491,   172,
-     173,   174,   493,   175,   176,   177,   178,   494,   179,   499,
-     545,   525,   546,   547,   548,   180,   495,   181,   182,   535,
-     365,   496,   263,   366,   536,   367,   183,   184,   257,   185,
-     186,   187,   188,   189,   376,   377,   378,   451,   190,   191,
-     232,   530,   384,   385,   193,   415,   394,   395,   214,   194,
-     233,   196,   234,   235,   236,   237,   238,   239,   240,   241,
-     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
-     252,   253,   254,   203,   306,   386,   557,   204
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -503
-static const short int yypact[] =
-{
-     159,  1039,   236,  -503,  -503,  -503,  -503,  -503,  -503,  -503,
-    -503,  -503,  -503,  -503,  -503,  -503,   186,  -503,    56,  -503,
-    -503,  -503,   178,  -503,    35,  -503,    21,  -503,   248,  1039,
-     273,  -503,  -503,  -503,  -503,  -503,  -503,  -503,    78,  -503,
-    -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,
-    -503,  -503,  2088,  -503,    32,  -503,    16,   245,  -503,    28,
-    -503,  -503,  1039,  1039,  -503,    80,   206,  -503,   129,   129,
-    1039,   221,   228,   194,  -503,  -503,   225,  -503,  -503,   234,
-     164,   206,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  1039,
-    -503,  1039,   233,  -503,  -503,   739,  -503,  -503,  -503,  -503,
-     -49,  -503,  -503,  -503,  1116,  -503,  -503,  1276,  -503,   129,
-     129,    40,  -503,  -503,  -503,   122,   212,   265,  -503,   215,
-    -503,  -503,   219,   739,  -503,   222,   224,  -503,  -503,  -503,
-    1820,   129,   129,  1627,   237,   238,  -503,  1820,   241,   239,
-     242,   283,  1820,   233,   266,  -503,  -503,  -503,  -503,  -503,
-    -503,  -503,  1820,  1820,  1820,  -503,  -503,  -503,   129,   284,
-     476,   293,  2067,  -503,   349,  -503,   296,  1366,  -503,  -503,
-     264,  -503,  -503,  -503,  -503,  -503,   268,  -503,  -503,  -503,
-    -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,
-     294,   305,    72,  -503,  2070,    88,  2084,   121,   130,   148,
-    -503,  -503,  -503,  2111,  1039,   281,   133,   281,   -25,  -503,
-     126,   133,   314,   315,   315,   921,  1039,   308,  -503,  -503,
-    -503,  -503,   277,  -503,  1820,  1820,  1820,  1820,  1820,   317,
-     284,   545,  -503,  -503,   121,  -503,  -503,  -503,  -503,  -503,
-    -503,  -503,    73,   124,   163,    59,   196,   323,   319,   290,
-     324,    18,  -503,  -503,  -503,   -30,  -503,   285,   286,   242,
-     342,  1941,  1820,   291,  -503,   129,  1820,  1820,   129,   292,
-     385,  1820,    96,  -503,  -503,  -503,   310,  -503,  -503,   329,
-     387,  1085,     3,  1820,  1627,   129,  -503,  -503,  -503,  -503,
-     175,  1820,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,
-    -503,  -503,  -503,  -503,  -503,  -503,  1820,   339,   339,   311,
-     921,   343,  -503,   129,  -503,   344,  1766,  -503,  -503,   346,
-    1039,   313,   347,  -503,  -503,   353,  -503,   307,  -503,  -503,
-    -503,     6,   545,   326,  -503,  -503,  1820,  1820,  1820,  1820,
-    1820,  1820,  1820,  1820,  1039,  1820,  1820,  1820,  1820,  1820,
-    1820,  1820,  1820,  1820,  1820,  1820,  1820,  1820,  -503,  -503,
-    -503,   330,  2067,  -503,  -503,   327,  -503,   354,   334,  -503,
-     345,   335,   340,   348,  -503,   351,   416,   232,  -503,   356,
-    -503,  -503,   376,  -503,   357,   377,  -503,  -503,   329,  -503,
-     358,   390,  -503,  1085,   339,  -503,   154,   339,   154,  1820,
-     362,  -503,  -503,  -503,  1766,  -503,  -503,  -503,  -503,   129,
-    -503,  2088,  1039,  1456,  -503,   363,    70,    93,  1874,  -503,
-    -503,  -503,    73,    73,   124,   124,   124,  -503,   163,   163,
-     163,   163,    59,    59,   196,   323,   319,   290,   324,   383,
-     360,  1820,  1820,  1995,  1699,  1820,   386,   233,  1820,  2088,
-     233,  -503,  -503,  1627,  -503,  -503,  1820,  1820,  -503,   394,
-    -503,  -503,   315,  -503,  -503,  -503,   369,  -503,  -503,   396,
-     404,   410,  -503,  -503,    26,   113,  -503,   407,  1820,  1874,
-    -503,  1820,  -503,   391,   374,  -503,   393,   395,   397,   411,
-    -503,   466,   471,  -503,  -503,  -503,  -503,   399,  -503,  -503,
-    -503,   400,   401,  -503,  -503,  -503,   402,  -503,   206,  -503,
-    1766,  1820,  1820,  -503,  -503,  -503,  -503,   403,  1995,  1941,
-    1820,  1820,  1699,  1627,  -503,    34,  -503,   233,  -503,  -503,
-    -503,  -503,   405,   412,  -503,   413,  -503,   354,   406,   418,
-     421,  -503,  -503,  1820,   429,   430,  -503,  1186,  -503,  -503,
-     419,   422,  1627,  1820,  1699,  1699,  -503,   447,  -503,  -503,
-    1555,  -503,  -503,  -503,  -503,   423,   497,  -503,  -503,  1995,
-    1699,   432,  -503,  1699,  -503
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const short int yypgoto[] =
-{
-    -503,  -503,  -503,  -503,   -85,     2,   181,   -41,  -198,   -45,
-     -87,    -1,   431,    14,  -503,  -503,  -503,  -503,  -503,  -503,
-    -503,  -503,  -503,  -503,   448,   -81,   -47,  -503,     7,   -23,
-    -503,   462,  -503,   -64,  -503,  -503,  -503,   425,  -146,   217,
-     123,  -391,  -503,   427,  -101,   424,   230,  -503,  -360,  -503,
-    -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,   439,
-    -503,  -503,  -503,  -503,  -503,  -503,  -503,  -503,  -110,  -503,
-    -503,   -77,   138,   -12,  -163,  -503,  -250,   -13,  -421,  -414,
-    -503,  -503,  -503,  -503,  -252,  -503,  -503,  -503,  -503,  -503,
-    -503,  -503,  -503,  -503,     5,  -503,  -503,  -503,  -503,   -16,
-      36,  -503,  -418,  -503,  -503,  -502,  -503,  -503,   440,  -503,
-    -503,  -503,  -503,  -503,  -503,  -503,   179,  -503,  -503,  -503,
-     -54,  -503,  -341,  -503,  -503,  -149,   255,  -136,   102,   652,
-     101,   688,   145,   157,   201,   -98,   289,   338,  -384,  -503,
-     -59,   -58,   -92,   -57,   213,   226,   218,   223,   227,  -503,
-      95,   274,   350,  -503,  -503,   660,  -503,  -503
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -336
-static const short int yytable[] =
-{
-      18,    82,    83,    17,   287,    61,   309,    56,   114,   364,
-     110,   363,   279,   468,    34,   108,   537,   103,   324,   107,
-     159,    74,    77,   120,   484,    86,   162,    68,    38,    77,
-     492,    17,    34,   383,   480,   357,   114,    55,   110,    34,
-      36,   313,   543,    69,   105,    35,   106,   544,    77,    62,
-      77,   472,   118,   192,   275,    63,   277,    95,   466,    29,
-      15,    76,    76,    35,    17,    17,   270,   537,   212,    76,
-      35,   358,    17,    36,    16,   114,   314,   285,    15,   192,
-     159,   123,    84,    85,   344,    15,   162,    55,    76,   502,
-      76,    17,    16,    17,   115,   515,  -260,   111,   265,    16,
-      64,   541,   212,    63,   497,   312,   160,   501,   492,   111,
-     317,   122,   -37,   192,   355,    61,   506,   511,   356,   531,
-     260,   161,   115,   205,   207,   111,   329,   330,    26,   334,
-     335,    73,   319,   566,   567,   565,   345,   346,  -192,   388,
-     492,   492,   336,   347,   348,   256,   256,   161,    64,   572,
-      59,   272,   574,   272,  -191,   319,   492,    27,   281,   492,
-    -261,   115,  -192,   308,   111,   337,   160,    39,   282,   111,
-     532,   533,   278,  -192,   159,    74,   338,   216,  -191,    60,
-     362,   161,    40,   479,   212,   268,    15,   283,   315,  -191,
-       1,   485,   320,    41,    26,   311,    42,    43,    44,   316,
-      16,    92,    46,    76,   512,    47,   307,   192,   195,    48,
-     292,   339,    49,   213,   473,    76,   319,   389,    17,  -280,
-     293,   340,   404,   272,   272,   332,   272,   272,   331,  -280,
-     192,    93,    15,   114,   195,   409,    23,  -281,   419,   420,
-     421,   375,   341,    25,   342,   460,    16,  -281,   464,   343,
-      28,  -235,   197,   428,   429,   430,   431,   114,   461,    37,
-     160,   461,    70,   111,   198,    50,   364,   364,   195,   363,
-     349,   387,   350,   -39,    64,   114,    39,   285,   197,   370,
-     422,   423,   373,   424,   425,   426,   463,   320,   465,    87,
-     198,    40,   432,   433,    89,    90,    36,    26,   161,   278,
-      91,   107,    41,   215,   390,    42,    43,    44,   199,   216,
-      45,    46,   197,   265,    47,    61,   219,   364,    48,   115,
-     220,    49,   111,   221,   198,   223,   159,   278,   261,   262,
-     266,   213,   162,   267,   199,   272,   272,   272,   272,   272,
-     272,   272,   272,   115,   272,   272,   272,   272,   272,   272,
-     272,   272,   272,   272,   272,   268,   280,   271,   284,   192,
-      68,   115,   195,   286,   111,   288,   290,   291,   199,   289,
-     500,    74,   310,   503,    50,   318,   326,   319,   328,   212,
-     514,   351,   352,   354,   353,   195,   359,   360,   320,   192,
-     192,   361,   369,   374,   375,   313,   200,   287,   381,   192,
-     380,   393,   399,   410,   401,   403,   197,   408,   414,   396,
-     398,    76,   160,   411,    17,   111,   418,   272,   198,   412,
-     443,   441,   200,   278,   444,   446,   320,   161,   442,   197,
-     447,   490,   159,   416,   417,   450,   445,   454,   362,   448,
-     504,   198,   449,   456,   529,   201,   453,   455,   481,   457,
-     549,   458,   467,   478,   498,   507,   200,   202,   489,   508,
-     159,   482,   199,   509,   192,   192,   162,   161,   192,   192,
-     510,   201,   315,   159,   513,   518,   522,   272,   272,   162,
-     272,   517,   523,   202,   519,   199,   520,  -165,   521,   524,
-     526,   527,   528,   192,   558,   550,   462,   559,   192,   462,
-     192,   192,   551,   552,   534,   201,   192,   553,   554,   387,
-     542,   555,   568,   570,   195,   192,   192,   202,   160,   192,
-     562,   111,   573,   563,   569,   427,   116,    81,    94,   124,
-     402,   125,   471,   -23,   211,   560,   489,   161,   281,   564,
-     400,   490,   504,   126,   195,   195,   160,   -23,   282,   111,
-     200,   477,   561,   571,   195,   538,   452,   542,   197,   160,
-     564,   161,   111,   397,   434,  -278,   161,   283,   489,   489,
-     198,   436,   258,   200,   161,  -278,   516,   437,   435,     0,
-     392,     0,   438,     0,   489,     0,     0,   489,   197,   197,
-       0,     0,     0,     0,     0,     0,     0,     0,   197,   201,
-     198,   198,     0,     0,     0,  -333,     0,   281,     0,  -333,
-     198,   202,     0,     0,   199,  -333,     0,   282,  -333,   195,
-     195,     0,   201,   195,   195,  -333,     0,  -333,  -333,     0,
-       0,     0,     0,  -333,   202,     0,   283,     0,  -333,     0,
-    -333,     0,     0,  -333,   199,   199,     0,     0,   195,  -333,
-       0,     0,     0,   195,   199,   195,   195,     0,     0,     0,
-       0,   195,     0,   197,   197,     0,     0,   197,   197,     0,
-     195,   195,     0,     0,   195,   198,   198,     0,     0,   198,
-     198,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   197,     0,     0,     0,     0,   197,     0,   197,
-     197,     0,   200,     0,   198,   197,     0,     0,     0,   198,
-       0,   198,   198,     0,   197,   197,     0,   198,   197,   199,
-     199,     0,     0,   199,   199,     0,   198,   198,     0,     0,
-     198,     0,   200,   200,     0,     0,     0,     0,     0,     0,
-       0,     0,   200,     0,     6,     0,     7,     0,   199,     8,
-      68,   201,     0,   199,     9,   199,   199,     0,     0,    10,
-       0,   199,     0,   202,     0,    11,    69,    12,     0,     0,
-     199,   199,     0,     0,   199,    13,     0,     0,     0,     0,
-       0,   201,   201,     0,     0,     0,   109,     0,     0,     0,
-     255,   201,     0,   202,   202,     0,    15,   264,     0,     0,
-       0,     0,   269,   202,   273,     0,   273,   200,   200,     0,
-      16,   200,   200,   276,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   200,     0,     0,     0,
-     274,   200,   274,   200,   200,     0,     0,     0,     0,   200,
-       0,     0,     0,     0,     0,     0,   201,   201,   200,   200,
-     201,   201,   200,     0,     0,     0,     0,     0,   202,   202,
-       0,     0,   202,   202,     0,     0,   273,   273,     0,   273,
-     273,     0,     0,     0,     0,   201,   333,     0,     0,     0,
-     201,     0,   201,   201,     0,     0,     0,   202,   201,     0,
-       0,     0,   202,     0,   202,   202,     0,   201,   201,     0,
-     202,   201,   274,   274,     0,   274,   274,     0,     0,   202,
-     202,     0,   368,   202,    39,     0,   371,   372,     0,     0,
-       0,   379,     0,     0,     0,     0,     0,     0,     0,    40,
-       0,   382,     0,     0,     0,     0,     0,     0,     0,     0,
-      41,   391,     0,    42,    43,    44,     0,     0,    45,    46,
-       0,     0,    47,     0,     0,     0,    48,     0,     0,    49,
-       0,     0,     0,     0,     0,     0,   407,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   273,   273,
-     273,   273,   273,   273,   273,   273,     0,   273,   273,   273,
-     273,   273,   273,   273,   273,   273,   273,   273,     0,     0,
-       0,  -105,     0,     0,     0,     0,   439,   440,     0,     0,
-       0,     0,     0,     0,   274,   274,   274,   274,   274,   274,
-     274,   274,     0,   274,   274,   274,   274,   274,   274,   274,
-     274,   274,   274,   274,     6,     0,     7,     0,     0,     8,
-       0,     0,     0,   459,     9,     0,     0,     0,     0,    10,
-       0,     0,     0,     0,   407,    11,     0,    12,     0,     0,
-     273,     0,     0,     0,     0,    13,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    14,     0,     0,     0,
-       6,     0,     7,     0,     0,     8,    15,     0,     0,     0,
-       9,   483,   264,     0,     0,    10,   274,     0,     0,     0,
-      16,    11,     0,    12,     0,   136,   505,     0,     0,    39,
-       0,    13,     0,     0,   138,     0,     0,   141,     0,     0,
-     273,   273,    14,   273,    40,   145,   146,   147,   148,   149,
-     150,   151,    15,     0,     0,    41,   318,     0,    42,    43,
-      44,     0,     0,    45,    46,     0,    16,    47,     0,     0,
-     224,    48,     0,     0,    49,     0,   274,   274,     0,   274,
-     407,     0,   225,     0,   152,     0,   226,     0,     0,     0,
-     539,   540,   227,   121,   154,     0,     0,   228,     0,    39,
-     130,     6,   131,     7,   543,     0,     8,     0,   132,   544,
-     133,     9,     0,   556,    40,     0,    10,   134,   135,     0,
-       0,     0,    11,   264,    12,    41,   136,     0,    42,    43,
-      44,   137,    13,    45,    46,   138,   139,   140,   141,   142,
-       0,    48,   143,    14,    49,   144,   145,   146,   147,   148,
-     149,   150,   151,    15,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,  -199,   107,     0,     0,    16,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   152,     0,   153,     0,    39,
-     130,     6,   131,     7,     0,   154,     8,   155,   132,     0,
-     133,     9,     0,     0,    40,     0,    10,   134,   135,     0,
-       0,     0,    11,     0,    12,    41,   136,     0,    42,    43,
-      44,   137,    13,    45,    46,   138,   139,   140,   141,   142,
-       0,    48,   143,    14,    49,   144,   145,   146,   147,   148,
-     149,   150,   151,    15,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,  -149,   107,     0,     0,    16,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   152,     0,   153,     0,    39,
-     130,     6,   131,     7,     0,   154,     8,   155,   132,     0,
-     133,     9,     0,     0,    40,     0,    10,   134,   135,     0,
-       0,     0,    11,     0,    12,    41,   136,     0,    42,    43,
-      44,   137,    13,    45,    46,   138,   139,   140,   141,   142,
-       0,    48,   143,    14,    49,   144,   145,   146,   147,   148,
-     149,   150,   151,    15,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,  -150,   107,     0,     0,    16,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   152,     0,   153,     0,    39,
-     130,     6,   131,     7,     0,   154,     8,   155,   132,     0,
-     133,     9,     0,     0,    40,     0,    10,   134,   135,     0,
-       0,     0,    11,     0,    12,    41,   136,     0,    42,    43,
-      44,   137,    13,    45,    46,   474,   139,   140,   475,   142,
-       0,    48,   143,    14,    49,   144,   145,   146,   147,   148,
-     149,   150,   151,    15,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,  -149,   107,     0,     0,    16,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   152,     0,   153,     0,     0,
-       0,     0,     0,     0,     0,   154,     0,   155,    39,   130,
-       6,   131,     7,     0,     0,     8,   -72,   132,     0,   133,
-       9,     0,     0,    40,     0,    10,   134,   135,     0,     0,
-       0,    11,     0,    12,    41,   136,     0,    42,    43,    44,
-     137,    13,    45,    46,   138,   139,   140,   141,   142,     0,
-      48,   143,    14,    49,   144,   145,   146,   147,   148,   149,
-     150,   151,    15,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   107,     0,     0,    16,     0,     0,     0,
-       0,   130,     6,   131,     7,     0,     0,     8,     0,   132,
-       0,   133,     9,     0,   152,     0,   153,    10,   134,   135,
-       0,     0,     0,    11,   154,    12,   155,   136,     0,     0,
-       0,     0,   137,    13,     0,     0,   138,   139,   259,   141,
-     142,     0,     0,   143,    14,     0,   144,   145,   146,   147,
-     148,   149,   150,   151,    15,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   107,     0,     0,    16,     0,
-       0,     0,     0,   130,     6,   131,     7,     0,     0,     8,
-       0,   132,     0,   133,     9,     0,   152,     0,   153,    10,
-     486,   487,     0,     0,     0,    11,   154,    12,   155,   136,
-       0,     0,     0,     0,   137,    13,     0,     0,   138,   139,
-     259,   141,   142,     0,     0,   143,    14,     0,   488,   145,
-     146,   147,   148,   149,   150,   151,    15,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   107,     0,     0,
-      16,     6,     0,     7,     0,     0,     8,     0,     0,     0,
-       0,     9,     0,     0,     0,     0,    10,     0,   152,     0,
-     153,     0,    11,     0,    12,     0,   136,     0,   154,     0,
-     155,     0,    13,     0,     0,   138,     0,     0,   141,     0,
-       0,     0,     0,    14,     0,     0,   145,   146,   147,   148,
-     149,   150,   151,    15,     0,     6,     0,     7,     0,     0,
-       8,     0,     0,     0,   404,     9,     0,    16,     0,     0,
-      10,   224,     0,     0,     0,     0,    11,     0,    12,     0,
-     136,     0,     0,   225,     0,   152,    13,   226,     0,   138,
-       0,     0,   141,   227,     0,   154,     0,    14,   228,     0,
-     145,   146,   147,   148,   149,   150,   151,    15,     0,     6,
-       0,     7,     0,     0,     8,     0,     0,     0,     0,     9,
-       0,    16,     0,     0,    10,   224,     0,     0,     0,     0,
-      11,     0,    12,     0,   136,     0,     0,   225,     0,   152,
-      13,   226,     0,   138,     0,     0,   141,   227,     0,   154,
-       0,    14,   228,     0,   145,   146,   147,   148,   149,   150,
-     151,    15,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    39,    16,     6,     0,     7,   224,
-       0,     8,     0,     0,     0,     0,     9,     0,     0,    40,
-       0,    10,     0,     0,     0,   226,     0,    11,     0,    12,
-      41,   136,     0,    42,    43,    44,   228,    13,    45,    46,
-     138,     0,    47,   141,     0,     0,    48,     0,    14,    49,
-       0,   145,   146,   147,   148,   149,   150,   151,    15,     0,
-       6,     0,     7,     0,     0,     8,     0,     0,     0,     0,
-       9,     0,    16,     0,     0,    10,     0,     0,     0,     0,
-       0,    11,     0,    12,     0,   136,     0,     0,     0,     0,
-     152,    13,   153,     0,   138,     0,     0,   141,     0,     0,
-     154,     0,    14,     0,     0,   145,   146,   147,   148,   149,
-     150,   151,    15,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    16,     0,     0,     0,
-      39,     0,     6,     0,     7,     0,     0,     8,     0,     0,
-       0,     0,     9,     0,   152,    40,   153,    10,     0,     0,
-       0,    39,     0,    11,   154,    12,    41,     0,     0,    42,
-      43,    44,     0,    13,    45,    46,    40,     0,    47,     0,
-       0,     0,    48,     0,    14,    49,     0,    41,     0,     0,
-      42,    43,    44,     0,    15,    45,    46,     0,     0,    47,
-    -334,     0,     0,    48,  -334,     0,    49,     0,    16,     0,
-    -334,     0,     0,  -334,  -335,     0,     0,     0,  -335,     0,
-    -334,     0,  -334,  -334,  -335,     0,     0,  -335,  -334,     0,
-       0,     0,     0,  -334,  -335,  -334,  -335,  -335,  -334,     0,
-       0,   294,  -335,     0,  -334,   295,     0,  -335,     0,  -335,
-       0,   296,  -335,     0,   297,     0,     0,     0,  -335,     0,
-       0,   298,     0,   299,   300,     0,     0,     0,     0,   301,
-       0,     0,     0,     0,   302,     0,   303,     0,     0,   304,
-       0,     0,     0,     0,     0,   305
-};
-
-static const short int yycheck[] =
-{
-       1,    65,    66,     1,   167,    52,   204,    30,    95,   261,
-      95,   261,   158,   404,    11,    92,   518,    81,   216,    68,
-     107,    62,    63,   100,   442,    70,   107,    11,    29,    70,
-     444,    29,    11,    30,   418,    65,   123,    30,   123,    11,
-      26,    66,     8,    27,    89,    42,    91,    13,    89,    17,
-      91,   411,   101,   107,   152,    23,   154,    80,   399,    24,
-      57,    62,    63,    42,    62,    63,   143,   569,    62,    70,
-      42,   101,    70,    59,    71,   162,   101,   162,    57,   133,
-     167,   104,    68,    69,    25,    57,   167,    80,    89,   449,
-      91,    89,    71,    91,    95,   479,    90,    95,    72,    71,
-      68,   522,    62,    23,   445,   206,   107,   448,   522,   107,
-     211,   104,    72,   167,    96,   162,   457,    91,   100,   510,
-     133,   107,   123,   109,   110,   123,   224,   225,    72,   227,
-     228,   103,    62,   554,   555,   553,    77,    78,    66,   285,
-     554,   555,    69,    84,    85,   131,   132,   133,    68,   570,
-      72,   152,   573,   154,    66,    62,   570,   101,    62,   573,
-      90,   162,    90,   204,   162,    92,   167,     3,    72,   167,
-     511,   512,   158,   101,   261,   216,   103,    44,    90,   101,
-     261,   167,    18,    90,    62,    72,    57,    91,    62,   101,
-      31,   443,   215,    29,    72,    62,    32,    33,    34,    73,
-      71,    37,    38,   204,    91,    41,   204,   261,   107,    45,
-      89,    87,    48,   111,   412,   216,    62,    42,   216,    89,
-      99,    97,    68,   224,   225,   226,   227,   228,   226,    99,
-     284,    67,    57,   320,   133,   320,     0,    89,   336,   337,
-     338,     9,    79,    57,    81,   394,    71,    99,   397,    86,
-      72,    19,   107,   345,   346,   347,   348,   344,   394,    11,
-     261,   397,    17,   261,   107,   101,   518,   519,   167,   519,
-      74,   284,    76,     0,    68,   362,     3,   362,   133,   265,
-     339,   340,   268,   341,   342,   343,   396,   310,   398,    68,
-     133,    18,   349,   350,    66,   101,   282,    72,   284,   285,
-      66,    68,    29,    91,   290,    32,    33,    34,   107,    44,
-      37,    38,   167,    72,    41,   362,   101,   569,    45,   320,
-     101,    48,   320,   101,   167,   101,   413,   313,    91,    91,
-      91,   229,   413,    91,   133,   336,   337,   338,   339,   340,
-     341,   342,   343,   344,   345,   346,   347,   348,   349,   350,
-     351,   352,   353,   354,   355,    72,    72,    91,    65,   413,
-      11,   362,   261,    67,   362,   101,    72,    62,   167,   101,
-     447,   412,    91,   450,   101,    61,    68,    62,   101,    62,
-     478,    58,    63,    59,    94,   284,   101,   101,   411,   443,
-     444,    49,   101,   101,     9,    66,   107,   560,    11,   453,
-      90,    62,    91,    90,    61,    61,   261,    61,   101,   307,
-     308,   412,   413,    66,   412,   413,    90,   418,   261,    66,
-      66,    91,   133,   409,    90,    90,   449,   413,   101,   284,
-      90,   444,   519,   331,   332,    19,    91,    61,   519,    91,
-     453,   284,    91,    66,   508,   107,    90,    90,    65,    91,
-     527,    61,    90,    90,    68,    61,   167,   107,   444,    90,
-     547,   101,   261,    67,   518,   519,   547,   453,   522,   523,
-      66,   133,    62,   560,    67,   101,    65,   478,   479,   560,
-     481,    90,    16,   133,    91,   284,    91,    16,    91,    90,
-      90,    90,    90,   547,    65,    90,   394,    67,   552,   397,
-     554,   555,    90,    90,   101,   167,   560,   101,    90,   522,
-     523,    90,    65,    16,   413,   569,   570,   167,   519,   573,
-     101,   519,    90,   101,   101,   344,    95,    65,    80,   104,
-     313,   104,   409,    57,   110,   547,   522,   523,    62,   552,
-     310,   554,   555,   104,   443,   444,   547,    71,    72,   547,
-     261,   413,   547,   569,   453,   519,   377,   570,   413,   560,
-     573,   547,   560,   308,   351,    89,   552,    91,   554,   555,
-     413,   353,   132,   284,   560,    99,   481,   354,   352,    -1,
-     306,    -1,   355,    -1,   570,    -1,    -1,   573,   443,   444,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   453,   261,
-     443,   444,    -1,    -1,    -1,    60,    -1,    62,    -1,    64,
-     453,   261,    -1,    -1,   413,    70,    -1,    72,    73,   518,
-     519,    -1,   284,   522,   523,    80,    -1,    82,    83,    -1,
-      -1,    -1,    -1,    88,   284,    -1,    91,    -1,    93,    -1,
-      95,    -1,    -1,    98,   443,   444,    -1,    -1,   547,   104,
-      -1,    -1,    -1,   552,   453,   554,   555,    -1,    -1,    -1,
-      -1,   560,    -1,   518,   519,    -1,    -1,   522,   523,    -1,
-     569,   570,    -1,    -1,   573,   518,   519,    -1,    -1,   522,
-     523,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   547,    -1,    -1,    -1,    -1,   552,    -1,   554,
-     555,    -1,   413,    -1,   547,   560,    -1,    -1,    -1,   552,
-      -1,   554,   555,    -1,   569,   570,    -1,   560,   573,   518,
-     519,    -1,    -1,   522,   523,    -1,   569,   570,    -1,    -1,
-     573,    -1,   443,   444,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   453,    -1,     5,    -1,     7,    -1,   547,    10,
-      11,   413,    -1,   552,    15,   554,   555,    -1,    -1,    20,
-      -1,   560,    -1,   413,    -1,    26,    27,    28,    -1,    -1,
-     569,   570,    -1,    -1,   573,    36,    -1,    -1,    -1,    -1,
-      -1,   443,   444,    -1,    -1,    -1,    47,    -1,    -1,    -1,
-     130,   453,    -1,   443,   444,    -1,    57,   137,    -1,    -1,
-      -1,    -1,   142,   453,   152,    -1,   154,   518,   519,    -1,
-      71,   522,   523,   153,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   547,    -1,    -1,    -1,
-     152,   552,   154,   554,   555,    -1,    -1,    -1,    -1,   560,
-      -1,    -1,    -1,    -1,    -1,    -1,   518,   519,   569,   570,
-     522,   523,   573,    -1,    -1,    -1,    -1,    -1,   518,   519,
-      -1,    -1,   522,   523,    -1,    -1,   224,   225,    -1,   227,
-     228,    -1,    -1,    -1,    -1,   547,   226,    -1,    -1,    -1,
-     552,    -1,   554,   555,    -1,    -1,    -1,   547,   560,    -1,
-      -1,    -1,   552,    -1,   554,   555,    -1,   569,   570,    -1,
-     560,   573,   224,   225,    -1,   227,   228,    -1,    -1,   569,
-     570,    -1,   262,   573,     3,    -1,   266,   267,    -1,    -1,
-      -1,   271,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    18,
-      -1,   281,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      29,   291,    -1,    32,    33,    34,    -1,    -1,    37,    38,
-      -1,    -1,    41,    -1,    -1,    -1,    45,    -1,    -1,    48,
-      -1,    -1,    -1,    -1,    -1,    -1,   316,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   336,   337,
-     338,   339,   340,   341,   342,   343,    -1,   345,   346,   347,
-     348,   349,   350,   351,   352,   353,   354,   355,    -1,    -1,
-      -1,    90,    -1,    -1,    -1,    -1,   356,   357,    -1,    -1,
-      -1,    -1,    -1,    -1,   336,   337,   338,   339,   340,   341,
-     342,   343,    -1,   345,   346,   347,   348,   349,   350,   351,
-     352,   353,   354,   355,     5,    -1,     7,    -1,    -1,    10,
-      -1,    -1,    -1,   393,    15,    -1,    -1,    -1,    -1,    20,
-      -1,    -1,    -1,    -1,   404,    26,    -1,    28,    -1,    -1,
-     418,    -1,    -1,    -1,    -1,    36,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    47,    -1,    -1,    -1,
-       5,    -1,     7,    -1,    -1,    10,    57,    -1,    -1,    -1,
-      15,   441,   442,    -1,    -1,    20,   418,    -1,    -1,    -1,
-      71,    26,    -1,    28,    -1,    30,   456,    -1,    -1,     3,
-      -1,    36,    -1,    -1,    39,    -1,    -1,    42,    -1,    -1,
-     478,   479,    47,   481,    18,    50,    51,    52,    53,    54,
-      55,    56,    57,    -1,    -1,    29,    61,    -1,    32,    33,
-      34,    -1,    -1,    37,    38,    -1,    71,    41,    -1,    -1,
-      75,    45,    -1,    -1,    48,    -1,   478,   479,    -1,   481,
-     510,    -1,    87,    -1,    89,    -1,    91,    -1,    -1,    -1,
-     520,   521,    97,    67,    99,    -1,    -1,   102,    -1,     3,
-       4,     5,     6,     7,     8,    -1,    10,    -1,    12,    13,
-      14,    15,    -1,   543,    18,    -1,    20,    21,    22,    -1,
-      -1,    -1,    26,   553,    28,    29,    30,    -1,    32,    33,
-      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
-      -1,    45,    46,    47,    48,    49,    50,    51,    52,    53,
-      54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    67,    68,    -1,    -1,    71,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    89,    -1,    91,    -1,     3,
-       4,     5,     6,     7,    -1,    99,    10,   101,    12,    -1,
-      14,    15,    -1,    -1,    18,    -1,    20,    21,    22,    -1,
-      -1,    -1,    26,    -1,    28,    29,    30,    -1,    32,    33,
-      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
-      -1,    45,    46,    47,    48,    49,    50,    51,    52,    53,
-      54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    67,    68,    -1,    -1,    71,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    89,    -1,    91,    -1,     3,
-       4,     5,     6,     7,    -1,    99,    10,   101,    12,    -1,
-      14,    15,    -1,    -1,    18,    -1,    20,    21,    22,    -1,
-      -1,    -1,    26,    -1,    28,    29,    30,    -1,    32,    33,
-      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
-      -1,    45,    46,    47,    48,    49,    50,    51,    52,    53,
-      54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    67,    68,    -1,    -1,    71,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    89,    -1,    91,    -1,     3,
-       4,     5,     6,     7,    -1,    99,    10,   101,    12,    -1,
-      14,    15,    -1,    -1,    18,    -1,    20,    21,    22,    -1,
-      -1,    -1,    26,    -1,    28,    29,    30,    -1,    32,    33,
-      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
-      -1,    45,    46,    47,    48,    49,    50,    51,    52,    53,
-      54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    67,    68,    -1,    -1,    71,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    89,    -1,    91,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    99,    -1,   101,     3,     4,
-       5,     6,     7,    -1,    -1,    10,    11,    12,    -1,    14,
-      15,    -1,    -1,    18,    -1,    20,    21,    22,    -1,    -1,
-      -1,    26,    -1,    28,    29,    30,    -1,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    -1,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    68,    -1,    -1,    71,    -1,    -1,    -1,
-      -1,     4,     5,     6,     7,    -1,    -1,    10,    -1,    12,
-      -1,    14,    15,    -1,    89,    -1,    91,    20,    21,    22,
-      -1,    -1,    -1,    26,    99,    28,   101,    30,    -1,    -1,
-      -1,    -1,    35,    36,    -1,    -1,    39,    40,    41,    42,
-      43,    -1,    -1,    46,    47,    -1,    49,    50,    51,    52,
-      53,    54,    55,    56,    57,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    68,    -1,    -1,    71,    -1,
-      -1,    -1,    -1,     4,     5,     6,     7,    -1,    -1,    10,
-      -1,    12,    -1,    14,    15,    -1,    89,    -1,    91,    20,
-      21,    22,    -1,    -1,    -1,    26,    99,    28,   101,    30,
-      -1,    -1,    -1,    -1,    35,    36,    -1,    -1,    39,    40,
-      41,    42,    43,    -1,    -1,    46,    47,    -1,    49,    50,
-      51,    52,    53,    54,    55,    56,    57,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    68,    -1,    -1,
-      71,     5,    -1,     7,    -1,    -1,    10,    -1,    -1,    -1,
-      -1,    15,    -1,    -1,    -1,    -1,    20,    -1,    89,    -1,
-      91,    -1,    26,    -1,    28,    -1,    30,    -1,    99,    -1,
-     101,    -1,    36,    -1,    -1,    39,    -1,    -1,    42,    -1,
-      -1,    -1,    -1,    47,    -1,    -1,    50,    51,    52,    53,
-      54,    55,    56,    57,    -1,     5,    -1,     7,    -1,    -1,
-      10,    -1,    -1,    -1,    68,    15,    -1,    71,    -1,    -1,
-      20,    75,    -1,    -1,    -1,    -1,    26,    -1,    28,    -1,
-      30,    -1,    -1,    87,    -1,    89,    36,    91,    -1,    39,
-      -1,    -1,    42,    97,    -1,    99,    -1,    47,   102,    -1,
-      50,    51,    52,    53,    54,    55,    56,    57,    -1,     5,
-      -1,     7,    -1,    -1,    10,    -1,    -1,    -1,    -1,    15,
-      -1,    71,    -1,    -1,    20,    75,    -1,    -1,    -1,    -1,
-      26,    -1,    28,    -1,    30,    -1,    -1,    87,    -1,    89,
-      36,    91,    -1,    39,    -1,    -1,    42,    97,    -1,    99,
-      -1,    47,   102,    -1,    50,    51,    52,    53,    54,    55,
-      56,    57,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,     3,    71,     5,    -1,     7,    75,
-      -1,    10,    -1,    -1,    -1,    -1,    15,    -1,    -1,    18,
-      -1,    20,    -1,    -1,    -1,    91,    -1,    26,    -1,    28,
-      29,    30,    -1,    32,    33,    34,   102,    36,    37,    38,
-      39,    -1,    41,    42,    -1,    -1,    45,    -1,    47,    48,
-      -1,    50,    51,    52,    53,    54,    55,    56,    57,    -1,
-       5,    -1,     7,    -1,    -1,    10,    -1,    -1,    -1,    -1,
-      15,    -1,    71,    -1,    -1,    20,    -1,    -1,    -1,    -1,
-      -1,    26,    -1,    28,    -1,    30,    -1,    -1,    -1,    -1,
-      89,    36,    91,    -1,    39,    -1,    -1,    42,    -1,    -1,
-      99,    -1,    47,    -1,    -1,    50,    51,    52,    53,    54,
-      55,    56,    57,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    71,    -1,    -1,    -1,
-       3,    -1,     5,    -1,     7,    -1,    -1,    10,    -1,    -1,
-      -1,    -1,    15,    -1,    89,    18,    91,    20,    -1,    -1,
-      -1,     3,    -1,    26,    99,    28,    29,    -1,    -1,    32,
-      33,    34,    -1,    36,    37,    38,    18,    -1,    41,    -1,
-      -1,    -1,    45,    -1,    47,    48,    -1,    29,    -1,    -1,
-      32,    33,    34,    -1,    57,    37,    38,    -1,    -1,    41,
-      60,    -1,    -1,    45,    64,    -1,    48,    -1,    71,    -1,
-      70,    -1,    -1,    73,    60,    -1,    -1,    -1,    64,    -1,
-      80,    -1,    82,    83,    70,    -1,    -1,    73,    88,    -1,
-      -1,    -1,    -1,    93,    80,    95,    82,    83,    98,    -1,
-      -1,    60,    88,    -1,   104,    64,    -1,    93,    -1,    95,
-      -1,    70,    98,    -1,    73,    -1,    -1,    -1,   104,    -1,
-      -1,    80,    -1,    82,    83,    -1,    -1,    -1,    -1,    88,
-      -1,    -1,    -1,    -1,    93,    -1,    95,    -1,    -1,    98,
-      -1,    -1,    -1,    -1,    -1,   104
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const unsigned short int yystos[] =
-{
-       0,    31,   107,   122,   123,   126,     5,     7,    10,    15,
-      20,    26,    28,    36,    47,    57,    71,   111,   117,   118,
-     119,   120,   121,     0,   124,    57,    72,   101,    72,    24,
-     125,   127,   128,   129,    11,    42,   119,    11,   117,     3,
-      18,    29,    32,    33,    34,    37,    38,    41,    45,    48,
-     101,   130,   131,   132,   133,   134,   135,   164,   165,    72,
-     101,   132,    17,    23,    68,   136,   137,   139,    11,    27,
-      17,   166,   167,   103,   113,   114,   117,   113,   115,   138,
-     140,   137,   139,   139,   119,   119,   115,    68,   168,    66,
-     101,    66,    37,    67,   130,   135,   141,   142,   143,   148,
-     149,   158,   159,   139,   169,   115,   115,    68,   177,    47,
-     110,   111,   112,   113,   116,   117,   118,   160,   101,   157,
-     177,    67,   134,   135,   143,   149,   165,   170,   171,   172,
-       4,     6,    12,    14,    21,    22,    30,    35,    39,    40,
-      41,    42,    43,    46,    49,    50,    51,    52,    53,    54,
-      55,    56,    89,    91,    99,   101,   108,   109,   110,   116,
-     117,   119,   131,   134,   135,   177,   178,   179,   180,   181,
-     182,   183,   185,   186,   187,   189,   190,   191,   192,   194,
-     201,   203,   204,   212,   213,   215,   216,   217,   218,   219,
-     224,   225,   226,   230,   235,   236,   237,   238,   239,   240,
-     242,   243,   258,   259,   263,   119,   151,   119,   144,   145,
-     146,   151,    62,   234,   234,    91,    44,   150,   155,   101,
-     101,   101,   173,   101,    75,    87,    91,    97,   102,   111,
-     116,   117,   226,   236,   238,   239,   240,   241,   242,   243,
-     244,   245,   246,   247,   248,   249,   250,   251,   252,   253,
-     254,   255,   256,   257,   258,   261,   119,   214,   214,    41,
-     183,    91,    91,   208,   261,    72,    91,    91,    72,   261,
-     177,    91,   117,   235,   237,   241,   261,   241,   119,   144,
-      72,    62,    72,    91,    65,   110,    67,   180,   101,   101,
-      72,    62,    89,    99,    60,    64,    70,    73,    80,    82,
-      83,    88,    93,    95,    98,   104,   260,   111,   113,   114,
-      91,    62,   150,    66,   101,    62,    73,   150,    61,    62,
-     135,   152,   153,   154,   114,   156,    68,   161,   101,   241,
-     241,   111,   117,   261,   241,   241,    69,    92,   103,    87,
-      97,    79,    81,    86,    25,    77,    78,    84,    85,    74,
-      76,    58,    63,    94,    59,    96,   100,    65,   101,   101,
-     101,    49,   131,   182,   190,   206,   209,   211,   261,   101,
-     119,   261,   261,   119,   101,     9,   220,   221,   222,   261,
-      90,    11,   261,    30,   228,   229,   261,   183,   144,    42,
-     119,   261,   257,    62,   232,   233,   234,   232,   234,    91,
-     152,    61,   145,    61,    68,   147,   174,   261,    61,   110,
-      90,    66,    66,   162,   101,   231,   234,   234,    90,   241,
-     241,   241,   246,   246,   247,   247,   247,   112,   248,   248,
-     248,   248,   249,   249,   250,   251,   252,   253,   254,   261,
-     261,    91,   101,    66,    90,    91,    90,    90,    91,    91,
-      19,   223,   222,    90,    61,    90,    66,    91,    61,   261,
-     231,   233,   234,   174,   231,   174,   228,    90,   147,   175,
-     176,   146,   154,   114,    39,    42,   163,   178,    90,    90,
-     244,    65,   101,   261,   208,   190,    21,    22,    49,   119,
-     183,   184,   185,   188,   193,   202,   207,   228,    68,   195,
-     177,   228,   154,   177,   183,   261,   228,    61,    90,    67,
-      66,    91,    91,    67,   241,   244,   256,    90,   101,    91,
-      91,    91,    65,    16,    90,   197,    90,    90,    90,   139,
-     227,   147,   228,   228,   101,   205,   210,   211,   206,   261,
-     261,   184,   183,     8,    13,   196,   198,   199,   200,   177,
-      90,    90,    90,   101,    90,    90,   261,   262,    65,    67,
-     179,   200,   101,   101,   183,   208,   184,   184,    65,   101,
-      16,   205,   184,    90,   184
-};
-
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
-#define yyerrok    (yyerrstatus = 0)
-#define yyclearin  (yychar = YYEMPTY)
-#define YYEMPTY    (-2)
-#define YYEOF    0
-
-#define YYACCEPT  goto yyacceptlab
-#define YYABORT    goto yyabortlab
-#define YYERROR    goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL    goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)          \
-do                \
-  if (yychar == YYEMPTY && yylen == 1)        \
-    {                \
-      yychar = (Token);            \
-      yylval = (Value);            \
-      yytoken = YYTRANSLATE (yychar);        \
-      YYPOPSTACK;            \
-      goto yybackup;            \
-    }                \
-  else                \
-    {                 \
-      yyerror ("syntax error: cannot back up");\
-      YYERROR;              \
-    }                \
-while (0)
-
-#define YYTERROR  1
-#define YYERRCODE  256
-
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions
-   are run).  */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)    \
-   ((Current).first_line   = (Rhs)[1].first_line,  \
-    (Current).first_column = (Rhs)[1].first_column,  \
-    (Current).last_line    = (Rhs)[N].last_line,  \
-    (Current).last_column  = (Rhs)[N].last_column)
-#endif
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval)
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)      \
-do {            \
-  if (yydebug)          \
-    YYFPRINTF Args;        \
-} while (0)
-
-# define YYDSYMPRINT(Args)      \
-do {            \
-  if (yydebug)          \
-    yysymprint Args;        \
-} while (0)
-
-# define YYDSYMPRINTF(Title, Token, Value, Location)    \
-do {                \
-  if (yydebug)              \
-    {                \
-      YYFPRINTF (stderr, "%s ", Title);        \
-      yysymprint (stderr,           \
-                  Token, Value);  \
-      YYFPRINTF (stderr, "\n");          \
-    }                \
-} while (0)
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_stack_print (short int *bottom, short int *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    short int *bottom;
-    short int *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (/* Nothing. */; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)        \
-do {                \
-  if (yydebug)              \
-    yy_stack_print ((Bottom), (Top));        \
-} while (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_reduce_print (int yyrule)
-#else
-static void
-yy_reduce_print (yyrule)
-    int yyrule;
-#endif
-{
-  int yyi;
-  unsigned int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
-             yyrule - 1, yylno);
-  /* Print the symbols being reduced, and their result.  */
-  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
-    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
-  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
-}
-
-# define YY_REDUCE_PRINT(Rule)    \
-do {          \
-  if (yydebug)        \
-    yy_reduce_print (Rule);    \
-} while (0)
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef  YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-

-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined (__GLIBC__) && defined (_STRING_H)
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-static YYSIZE_T
-#   if defined (__STDC__) || defined (__cplusplus)
-yystrlen (const char *yystr)
-#   else
-yystrlen (yystr)
-     const char *yystr;
-#   endif
-{
-  const char *yys = yystr;
-
-  while (*yys++ != '\0')
-    continue;
-
-  return yys - yystr - 1;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-static char *
-#   if defined (__STDC__) || defined (__cplusplus)
-yystpcpy (char *yydest, const char *yysrc)
-#   else
-yystpcpy (yydest, yysrc)
-     char *yydest;
-     const char *yysrc;
-#   endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-#endif /* !YYERROR_VERBOSE */
-
-

-
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  /* Pacify ``unused variable'' warnings.  */
-  (void) yyvaluep;
-
-  if (yytype < YYNTOKENS)
-    {
-      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
-      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
-    }
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  switch (yytype)
-    {
-      default:
-        break;
-    }
-  YYFPRINTF (yyoutput, ")");
-}
-
-#endif /* ! YYDEBUG */
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yytype, yyvaluep)
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  /* Pacify ``unused variable'' warnings.  */
-  (void) yyvaluep;
-
-  switch (yytype)
-    {
-
-      default:
-        break;
-    }
-}
-

-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM);
-# else
-int yyparse ();
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
-  void *YYPARSE_PARAM;
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  /* The lookahead symbol.  */
-int yychar;
-
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  short int yyssa[YYINITDEPTH];
-  short int *yyss = yyssa;
-  short int *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK   (yyvsp--, yyssp--)
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* When reducing, the number of symbols on the RHS of the reduced
-     rule.  */
-  int yylen;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;    /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed. so pushing a state here evens the stacks.
-     */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-  /* Give user a chance to reallocate the stack. Use copies of
-     these so that the &'s don't force the real ones into
-     memory.  */
-  YYSTYPE *yyvs1 = yyvs;
-  short int *yyss1 = yyss;
-
-
-  /* Each stack pointer address is followed by the size of the
-     data in use in that stack, in bytes.  This used to be a
-     conditional around just the two extra args, but that might
-     be undefined if yyoverflow is a macro.  */
-  yyoverflow ("parser stack overflow",
-        &yyss1, yysize * sizeof (*yyssp),
-        &yyvs1, yysize * sizeof (*yyvsp),
-
-        &yystacksize);
-
-  yyss = yyss1;
-  yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyoverflowlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-  goto yyoverflowlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-  yystacksize = YYMAXDEPTH;
-
-      {
-  short int *yyss1 = yyss;
-  union yyalloc *yyptr =
-    (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-  if (! yyptr)
-    goto yyoverflowlab;
-  YYSTACK_RELOCATE (yyss);
-  YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-  if (yyss1 != yyssa)
-    YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-      (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-  YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-/* Do appropriate processing given the current state.  */
-/* Read a lookahead token if we need one and don't already have one.  */
-/* yyresume: */
-
-  /* First try to decide what to do without reference to lookahead token.  */
-
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a lookahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-  goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Shift the lookahead token.  */
-  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
-
-  /* Discard the token being shifted unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  *++yyvsp = yylval;
-
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 2:
-#line 192 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 3:
-#line 201 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 4:
-#line 209 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 5:
-#line 217 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 6:
-#line 225 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 7:
-#line 233 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 8:
-#line 241 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 9:
-#line 250 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 10:
-#line 258 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 11:
-#line 267 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 12:
-#line 275 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 13:
-#line 284 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-}
-    break;
-
-  case 14:
-#line 289 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-}
-    break;
-
-  case 15:
-#line 294 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-}
-    break;
-
-  case 16:
-#line 299 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-}
-    break;
-
-  case 17:
-#line 304 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-}
-    break;
-
-  case 18:
-#line 309 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-}
-    break;
-
-  case 19:
-#line 314 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-}
-    break;
-
-  case 20:
-#line 319 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-}
-    break;
-
-  case 21:
-#line 325 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 22:
-#line 333 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 23:
-#line 342 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpStoreClass(yyvsp[0].str);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 24:
-#line 352 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 25:
-#line 361 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 26:
-#line 370 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 27:
-#line 378 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpStoreClass(yyvsp[-1].str);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 28:
-#line 388 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyval.str = yyvsp[0].str;
-}
-    break;
-
-  case 29:
-#line 394 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyval.str = yyvsp[0].str;
-}
-    break;
-
-  case 30:
-#line 401 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyval.str = yyvsp[0].str;
-}
-    break;
-
-  case 31:
-#line 408 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyval.str = yyvsp[0].str;
-}
-    break;
-
-  case 32:
-#line 414 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  yyval.str = yyvsp[0].str;
-}
-    break;
-
-  case 33:
-#line 421 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->AddClassFound(yyvsp[-2].str);
-  yyGetParser->UpdateCombine(yyvsp[-2].str, yyvsp[0].str);
-  yyGetParser->DeallocateParserType(&(yyvsp[-2].str));
-  yyval.str = const_cast<char*>(yyGetParser->GetCurrentCombine());
-}
-    break;
-
-  case 34:
-#line 430 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpStoreClass(yyvsp[-2].str);
-  jpCheckEmpty(3);
-  yyGetParser->SetCurrentCombine("");
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 35:
-#line 440 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpStoreClass(yyvsp[-2].str);
-  yyGetParser->SetCurrentCombine("");
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 36:
-#line 450 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 37:
-#line 459 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 38:
-#line 467 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 39:
-#line 476 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 40:
-#line 484 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 41:
-#line 491 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 42:
-#line 499 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 43:
-#line 506 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 44:
-#line 514 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 45:
-#line 521 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 46:
-#line 530 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->SetCurrentPackage(yyvsp[-1].str);
-  yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
-  yyGetParser->SetCurrentCombine("");
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 47:
-#line 542 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 48:
-#line 550 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 49:
-#line 559 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->AddPackagesImport(yyvsp[-1].str);
-  yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
-  yyGetParser->SetCurrentCombine("");
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 50:
-#line 571 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-  std::string str = yyvsp[-3].str;
-  str += ".*";
-  yyGetParser->AddPackagesImport(str.c_str());
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
-  yyGetParser->SetCurrentCombine("");
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 51:
-#line 584 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 52:
-#line 592 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 53:
-#line 600 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 54:
-#line 609 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 55:
-#line 617 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 67:
-#line 632 "cmDependsJavaParser.y"
-    {
-  yyGetParser->StartClass(yyvsp[0].str);
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  jpCheckEmpty(3);
-}
-    break;
-
-  case 68:
-#line 642 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-    break;
-
-  case 69:
-#line 651 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-    break;
-
-  case 70:
-#line 660 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-    break;
-
-  case 71:
-#line 669 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-    break;
-
-  case 72:
-#line 678 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 73:
-#line 685 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 74:
-#line 694 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 75:
-#line 703 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 76:
-#line 712 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 77:
-#line 720 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 78:
-#line 729 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 79:
-#line 737 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 80:
-#line 744 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 81:
-#line 753 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 82:
-#line 761 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 83:
-#line 769 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 84:
-#line 777 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 85:
-#line 786 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 86:
-#line 794 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 87:
-#line 803 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-}
-    break;
-
-  case 88:
-#line 809 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 89:
-#line 817 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 90:
-#line 826 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 91:
-#line 834 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 92:
-#line 843 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 93:
-#line 852 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 94:
-#line 861 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 95:
-#line 869 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 96:
-#line 878 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 97:
-#line 886 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 98:
-#line 894 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 99:
-#line 903 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 100:
-#line 912 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 101:
-#line 921 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 102:
-#line 929 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 103:
-#line 939 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 104:
-#line 949 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-
-}
-    break;
-
-  case 105:
-#line 955 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 107:
-#line 966 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-
-}
-    break;
-
-  case 108:
-#line 972 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 109:
-#line 982 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 110:
-#line 992 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 111:
-#line 1002 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-
-}
-    break;
-
-  case 112:
-#line 1008 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 113:
-#line 1018 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 114:
-#line 1028 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 115:
-#line 1038 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 116:
-#line 1047 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 117:
-#line 1057 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 118:
-#line 1068 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 119:
-#line 1077 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 120:
-#line 1085 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 121:
-#line 1095 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 122:
-#line 1104 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 123:
-#line 1114 "cmDependsJavaParser.y"
-    {
-  yyGetParser->StartClass(yyvsp[0].str);
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  jpCheckEmpty(3);
-}
-    break;
-
-  case 124:
-#line 1123 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-    break;
-
-  case 125:
-#line 1132 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-    break;
-
-  case 126:
-#line 1139 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 127:
-#line 1149 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 128:
-#line 1158 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 129:
-#line 1168 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 130:
-#line 1177 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 131:
-#line 1185 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 132:
-#line 1194 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 133:
-#line 1203 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 134:
-#line 1212 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 135:
-#line 1221 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 136:
-#line 1229 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 137:
-#line 1238 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 138:
-#line 1247 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 139:
-#line 1257 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 140:
-#line 1267 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 141:
-#line 1276 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 142:
-#line 1286 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 143:
-#line 1295 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 144:
-#line 1303 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 145:
-#line 1312 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 146:
-#line 1322 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 147:
-#line 1331 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 148:
-#line 1341 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 149:
-#line 1349 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 150:
-#line 1357 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 151:
-#line 1367 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 152:
-#line 1376 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 153:
-#line 1386 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 154:
-#line 1395 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 155:
-#line 1404 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 156:
-#line 1414 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 157:
-#line 1424 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 158:
-#line 1433 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 159:
-#line 1443 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 160:
-#line 1452 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 161:
-#line 1461 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 162:
-#line 1470 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 163:
-#line 1479 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 164:
-#line 1488 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 165:
-#line 1498 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 166:
-#line 1507 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 167:
-#line 1516 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 168:
-#line 1525 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 169:
-#line 1534 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 170:
-#line 1544 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 171:
-#line 1553 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 172:
-#line 1562 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 173:
-#line 1571 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 174:
-#line 1580 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 175:
-#line 1589 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 176:
-#line 1598 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 177:
-#line 1607 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 178:
-#line 1616 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 179:
-#line 1625 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 180:
-#line 1634 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 181:
-#line 1643 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 182:
-#line 1653 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 183:
-#line 1663 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[-2].str));
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 184:
-#line 1674 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 185:
-#line 1684 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 186:
-#line 1694 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 187:
-#line 1703 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 188:
-#line 1712 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 189:
-#line 1721 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 190:
-#line 1730 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 191:
-#line 1739 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 192:
-#line 1748 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 193:
-#line 1758 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 194:
-#line 1768 "cmDependsJavaParser.y"
-    {
-  jpElementStart(7);
-  jpCheckEmpty(7);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 195:
-#line 1778 "cmDependsJavaParser.y"
-    {
-  jpElementStart(7);
-  jpCheckEmpty(7);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 196:
-#line 1788 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-
-}
-    break;
-
-  case 197:
-#line 1795 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-
-}
-    break;
-
-  case 198:
-#line 1801 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 199:
-#line 1809 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 200:
-#line 1818 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 201:
-#line 1826 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 202:
-#line 1836 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 203:
-#line 1846 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 204:
-#line 1855 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 205:
-#line 1865 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 206:
-#line 1874 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 207:
-#line 1884 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-
-}
-    break;
-
-  case 208:
-#line 1891 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-
-}
-    break;
-
-  case 209:
-#line 1898 "cmDependsJavaParser.y"
-    {
-  jpElementStart(7);
-
-}
-    break;
-
-  case 210:
-#line 1906 "cmDependsJavaParser.y"
-    {
-  jpElementStart(9);
-
-}
-    break;
-
-  case 211:
-#line 1912 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 212:
-#line 1920 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 213:
-#line 1929 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 214:
-#line 1937 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 215:
-#line 1948 "cmDependsJavaParser.y"
-    {
-  jpElementStart(9);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 216:
-#line 1956 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 217:
-#line 1964 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 218:
-#line 1974 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 219:
-#line 1983 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 220:
-#line 1993 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 221:
-#line 2003 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 222:
-#line 2012 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 223:
-#line 2022 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 224:
-#line 2031 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 225:
-#line 2041 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 226:
-#line 2051 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 227:
-#line 2059 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-
-}
-    break;
-
-  case 228:
-#line 2066 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 229:
-#line 2077 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 230:
-#line 2087 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 231:
-#line 2097 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 232:
-#line 2107 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 233:
-#line 2116 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 234:
-#line 2125 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 235:
-#line 2133 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 236:
-#line 2143 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 237:
-#line 2152 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 238:
-#line 2162 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-
-}
-    break;
-
-  case 239:
-#line 2169 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 240:
-#line 2179 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 241:
-#line 2188 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 242:
-#line 2198 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 243:
-#line 2207 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-
-}
-    break;
-
-  case 244:
-#line 2213 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 245:
-#line 2222 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 246:
-#line 2231 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 247:
-#line 2240 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 248:
-#line 2249 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 249:
-#line 2259 "cmDependsJavaParser.y"
-    {
-  jpElementStart(6);
-  jpCheckEmpty(6);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 250:
-#line 2268 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 251:
-#line 2276 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 252:
-#line 2285 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 253:
-#line 2293 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 254:
-#line 2303 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 255:
-#line 2312 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 256:
-#line 2322 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 257:
-#line 2331 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 258:
-#line 2340 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 259:
-#line 2349 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 260:
-#line 2358 "cmDependsJavaParser.y"
-    {
-  jpElementStart(0);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 261:
-#line 2366 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 262:
-#line 2376 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 263:
-#line 2385 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 264:
-#line 2395 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 265:
-#line 2405 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-
-}
-    break;
-
-  case 266:
-#line 2411 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-
-}
-    break;
-
-  case 267:
-#line 2418 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 268:
-#line 2428 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 269:
-#line 2438 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 270:
-#line 2448 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 271:
-#line 2459 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 272:
-#line 2469 "cmDependsJavaParser.y"
-    {
-  jpElementStart(6);
-  yyGetParser->DeallocateParserType(&(yyvsp[-5].str));
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
-  jpCheckEmpty(6);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 273:
-#line 2480 "cmDependsJavaParser.y"
-    {
-  jpElementStart(6);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
-  jpCheckEmpty(6);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 274:
-#line 2490 "cmDependsJavaParser.y"
-    {
-  jpElementStart(6);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
-  jpCheckEmpty(6);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 275:
-#line 2501 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 276:
-#line 2511 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 277:
-#line 2521 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 278:
-#line 2530 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 279:
-#line 2539 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 280:
-#line 2548 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 281:
-#line 2557 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 282:
-#line 2567 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 283:
-#line 2577 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 284:
-#line 2587 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 285:
-#line 2596 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 286:
-#line 2605 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 287:
-#line 2614 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 288:
-#line 2623 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 289:
-#line 2633 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 290:
-#line 2643 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 291:
-#line 2653 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 292:
-#line 2662 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 293:
-#line 2671 "cmDependsJavaParser.y"
-    {
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 294:
-#line 2680 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 295:
-#line 2690 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 296:
-#line 2699 "cmDependsJavaParser.y"
-    {
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 297:
-#line 2708 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-
-}
-    break;
-
-  case 298:
-#line 2715 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 299:
-#line 2724 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 300:
-#line 2733 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 301:
-#line 2742 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 302:
-#line 2752 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 303:
-#line 2761 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 304:
-#line 2770 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 305:
-#line 2780 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 306:
-#line 2789 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 307:
-#line 2798 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 308:
-#line 2807 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 309:
-#line 2817 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 310:
-#line 2826 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 311:
-#line 2835 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 312:
-#line 2844 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 313:
-#line 2853 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 314:
-#line 2862 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 315:
-#line 2872 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 316:
-#line 2881 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 317:
-#line 2890 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 318:
-#line 2900 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 319:
-#line 2909 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 320:
-#line 2919 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 321:
-#line 2928 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 322:
-#line 2938 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 323:
-#line 2947 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 324:
-#line 2957 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 325:
-#line 2966 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 326:
-#line 2976 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 327:
-#line 2985 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 328:
-#line 2995 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 329:
-#line 3004 "cmDependsJavaParser.y"
-    {
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 330:
-#line 3014 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 331:
-#line 3023 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 332:
-#line 3033 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 333:
-#line 3043 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 334:
-#line 3053 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 335:
-#line 3062 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 336:
-#line 3072 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 337:
-#line 3081 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 338:
-#line 3090 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 339:
-#line 3099 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 340:
-#line 3108 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 341:
-#line 3117 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 342:
-#line 3126 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 343:
-#line 3135 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 344:
-#line 3144 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 345:
-#line 3153 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 346:
-#line 3162 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 347:
-#line 3171 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 348:
-#line 3181 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 349:
-#line 3191 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 350:
-#line 3201 "cmDependsJavaParser.y"
-    {
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-  case 351:
-#line 3210 "cmDependsJavaParser.y"
-    {
-  jpElementStart(3);
-  jpStoreClass(yyvsp[-2].str);
-  jpCheckEmpty(3);
-  yyval.str = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-    break;
-
-
-    }
-
-/* Line 1010 of yacc.c.  */
-#line 5780 "cmDependsJavaParser.cxx"
-

-  yyvsp -= yylen;
-  yyssp -= yylen;
-
-
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if YYERROR_VERBOSE
-      yyn = yypact[yystate];
-
-      if (YYPACT_NINF < yyn && yyn < YYLAST)
-  {
-    YYSIZE_T yysize = 0;
-    int yytype = YYTRANSLATE (yychar);
-    const char* yyprefix;
-    char *yymsg;
-    int yyx;
-
-    /* Start YYX at -YYN if negative to avoid negative indexes in
-       YYCHECK.  */
-    int yyxbegin = yyn < 0 ? -yyn : 0;
-
-    /* Stay within bounds of both yycheck and yytname.  */
-    int yychecklim = YYLAST - yyn;
-    int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-    int yycount = 0;
-
-    yyprefix = ", expecting ";
-    for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-      if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-        {
-    yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
-    yycount += 1;
-    if (yycount == 5)
-      {
-        yysize = 0;
-        break;
-      }
-        }
-    yysize += (sizeof ("syntax error, unexpected ")
-         + yystrlen (yytname[yytype]));
-    yymsg = (char *) YYSTACK_ALLOC (yysize);
-    if (yymsg != 0)
-      {
-        char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
-        yyp = yystpcpy (yyp, yytname[yytype]);
-
-        if (yycount < 5)
-    {
-      yyprefix = ", expecting ";
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-        if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-          {
-      yyp = yystpcpy (yyp, yyprefix);
-      yyp = yystpcpy (yyp, yytname[yyx]);
-      yyprefix = " or ";
-          }
-    }
-        yyerror (yymsg);
-        YYSTACK_FREE (yymsg);
-      }
-    else
-      yyerror ("syntax error; also virtual memory exhausted");
-  }
-      else
-#endif /* YYERROR_VERBOSE */
-  yyerror ("syntax error");
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse lookahead token after an
-   error, discard it.  */
-
-      if (yychar <= YYEOF)
-        {
-          /* If at end of input, pop the error token,
-       then the rest of the stack, then return failure.  */
-    if (yychar == YYEOF)
-       for (;;)
-         {
-     YYPOPSTACK;
-     if (yyssp == yyss)
-       YYABORT;
-     YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-     yydestruct (yystos[*yyssp], yyvsp);
-         }
-        }
-      else
-  {
-    YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
-    yydestruct (yytoken, &yylval);
-    yychar = YYEMPTY;
-
-  }
-    }
-
-  /* Else will try to reuse lookahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-#if defined(__GNUC__) || defined(__HP_aCC)
-  /* Pacify GCC when the user code never invokes YYERROR and the label
-     yyerrorlab therefore never appears in user code.  */
-  if (0)
-     goto yyerrorlab;
-#endif
-
-  yyvsp -= yylen;
-  yyssp -= yylen;
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;  /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-  {
-    yyn += YYTERROR;
-    if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-      {
-        yyn = yytable[yyn];
-        if (0 < yyn)
-    break;
-      }
-  }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-  YYABORT;
-
-      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-      yydestruct (yystos[yystate], yyvsp);
-      YYPOPSTACK;
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  YYDPRINTF ((stderr, "Shifting error token, "));
-
-  *++yyvsp = yylval;
-
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here.  |
-`----------------------------------------------*/
-yyoverflowlab:
-  yyerror ("parser stack overflow");
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-  return yyresult;
-}
-
-
-#line 3219 "cmDependsJavaParser.y"
-
-/* End of grammar */
-
-/*--------------------------------------------------------------------------*/
-void cmDependsJavaError(yyscan_t yyscanner, const char* message)
-{
-  yyGetParser->Error(message);
-}
-
-
diff --git a/Source/cmDependsJavaParser.y b/Source/cmDependsJavaParser.y
deleted file mode 100644
index 91ee7c8..0000000
--- a/Source/cmDependsJavaParser.y
+++ /dev/null
@@ -1,3212 +0,0 @@
-%{
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
-  bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y
-
-Modify cmDependsJavaParser.cxx:
-  - remove TABs
-  - remove use of the 'register' storage class specifier
-  - add __HP_aCC to the #if test for yyerrorlab warning suppression
-
-*/
-
-/* Configure the parser to use a lexer object.  */
-#define YYPARSE_PARAM yyscanner
-#define YYLEX_PARAM yyscanner
-#define YYERROR_VERBOSE 1
-#define cmDependsJava_yyerror(x) \
-        cmDependsJavaError(yyscanner, x)
-#define yyGetParser (cmDependsJava_yyget_extra(yyscanner))
-
-/*-------------------------------------------------------------------------*/
-#include "cmDependsJavaParserHelper.h" /* Interface to parser object.  */
-#include "cmDependsJavaLexer.h"  /* Interface to lexer object.  */
-#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
-
-/* Forward declare the lexer entry point.  */
-YY_DECL;
-
-/* Internal utility functions.  */
-static void cmDependsJavaError(yyscan_t yyscanner, const char* message);
-
-#define YYDEBUG 1
-#define YYMAXDEPTH 1000000
-
-
-#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp);
-#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval)
-#define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str))
-/* Disable some warnings in the generated code.  */
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label.  */
-# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
-#endif
-%}
-
-/* Generate a reentrant parser object.  */
-%pure_parser
-
-/*
-%union {
-  char* string;
-}
-*/
-
-/*-------------------------------------------------------------------------*/
-/* Tokens */
-%token jp_ABSTRACT
-%token jp_ASSERT
-%token jp_BOOLEAN_TYPE
-%token jp_BREAK
-%token jp_BYTE_TYPE
-%token jp_CASE
-%token jp_CATCH
-%token jp_CHAR_TYPE
-%token jp_CLASS
-%token jp_CONTINUE
-%token jp_DEFAULT
-%token jp_DO
-%token jp_DOUBLE_TYPE
-%token jp_ELSE
-%token jp_EXTENDS
-%token jp_FINAL
-%token jp_FINALLY
-%token jp_FLOAT_TYPE
-%token jp_FOR
-%token jp_IF
-%token jp_IMPLEMENTS
-%token jp_IMPORT
-%token jp_INSTANCEOF
-%token jp_INT_TYPE
-%token jp_INTERFACE
-%token jp_LONG_TYPE
-%token jp_NATIVE
-%token jp_NEW
-%token jp_PACKAGE
-%token jp_PRIVATE
-%token jp_PROTECTED
-%token jp_PUBLIC
-%token jp_RETURN
-%token jp_SHORT_TYPE
-%token jp_STATIC
-%token jp_STRICTFP
-%token jp_SUPER
-%token jp_SWITCH
-%token jp_SYNCHRONIZED
-%token jp_THIS
-%token jp_THROW
-%token jp_THROWS
-%token jp_TRANSIENT
-%token jp_TRY
-%token jp_VOID
-%token jp_VOLATILE
-%token jp_WHILE
-
-%token jp_BOOLEANLITERAL
-%token jp_CHARACTERLITERAL
-%token jp_DECIMALINTEGERLITERAL
-%token jp_FLOATINGPOINTLITERAL
-%token jp_HEXINTEGERLITERAL
-%token jp_NULLLITERAL
-%token jp_STRINGLITERAL
-
-%token jp_NAME
-
-%token jp_AND
-%token jp_ANDAND
-%token jp_ANDEQUALS
-%token jp_BRACKETEND
-%token jp_BRACKETSTART
-%token jp_CARROT
-%token jp_CARROTEQUALS
-%token jp_COLON
-%token jp_COMMA
-%token jp_CURLYEND
-%token jp_CURLYSTART
-%token jp_DIVIDE
-%token jp_DIVIDEEQUALS
-%token jp_DOLLAR
-%token jp_DOT
-%token jp_EQUALS
-%token jp_EQUALSEQUALS
-%token jp_EXCLAMATION
-%token jp_EXCLAMATIONEQUALS
-%token jp_GREATER
-%token jp_GTEQUALS
-%token jp_GTGT
-%token jp_GTGTEQUALS
-%token jp_GTGTGT
-%token jp_GTGTGTEQUALS
-%token jp_LESLESEQUALS
-%token jp_LESSTHAN
-%token jp_LTEQUALS
-%token jp_LTLT
-%token jp_MINUS
-%token jp_MINUSEQUALS
-%token jp_MINUSMINUS
-%token jp_PAREEND
-%token jp_PARESTART
-%token jp_PERCENT
-%token jp_PERCENTEQUALS
-%token jp_PIPE
-%token jp_PIPEEQUALS
-%token jp_PIPEPIPE
-%token jp_PLUS
-%token jp_PLUSEQUALS
-%token jp_PLUSPLUS
-%token jp_QUESTION
-%token jp_SEMICOL
-%token jp_TILDE
-%token jp_TIMES
-%token jp_TIMESEQUALS
-
-%token jp_ERROR
-
-/*-------------------------------------------------------------------------*/
-/* grammar */
-%%
-
-Goal:
-CompilationUnit
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-Literal:
-IntegerLiteral
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-jp_FLOATINGPOINTLITERAL
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-jp_BOOLEANLITERAL
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-jp_CHARACTERLITERAL
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-jp_STRINGLITERAL
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-jp_NULLLITERAL
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-IntegerLiteral:
-jp_DECIMALINTEGERLITERAL
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-jp_HEXINTEGERLITERAL	
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-Type:
-PrimitiveType
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-ReferenceType
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-PrimitiveType:
-jp_BYTE_TYPE
-{
-  jpElementStart(0);
-}
-|
-jp_SHORT_TYPE
-{
-  jpElementStart(0);
-}
-|
-jp_INT_TYPE
-{
-  jpElementStart(0);
-}
-|
-jp_LONG_TYPE
-{
-  jpElementStart(0);
-}
-|
-jp_CHAR_TYPE
-{
-  jpElementStart(0);
-}
-|
-jp_FLOAT_TYPE
-{
-  jpElementStart(0);
-}
-|
-jp_DOUBLE_TYPE
-{
-  jpElementStart(0);
-}
-|
-jp_BOOLEAN_TYPE
-{
-  jpElementStart(0);
-}
-
-ReferenceType:
-ClassOrInterfaceType
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-ArrayType
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-ClassOrInterfaceType:
-Name
-{
-  jpElementStart(1);
-  jpStoreClass($<str>1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-ClassType:
-ClassOrInterfaceType
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-InterfaceType:
-ClassOrInterfaceType
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-ArrayType:
-PrimitiveType Dims
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-Name Dims
-{
-  jpElementStart(2);
-  jpStoreClass($<str>1);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-Name:
-SimpleName
-{
-  jpElementStart(1);
-  $<str>$ = $<str>1;
-}
-|
-QualifiedName
-{
-  jpElementStart(1);
-  $<str>$ = $<str>1;
-}
-
-SimpleName:
-Identifier
-{
-  jpElementStart(1);
-  $<str>$ = $<str>1;
-}
-
-Identifier:
-jp_NAME
-{
-  jpElementStart(1);
-  $<str>$ = $<str>1;
-}
-|
-jp_DOLLAR jp_NAME
-{
-  jpElementStart(2);
-  $<str>$ = $<str>2;
-}
-
-QualifiedName:
-Name jp_DOT Identifier
-{
-  jpElementStart(3);
-  yyGetParser->AddClassFound($<str>1);
-  yyGetParser->UpdateCombine($<str>1, $<str>3);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  $<str>$ = const_cast<char*>(yyGetParser->GetCurrentCombine());
-}
-|
-Name jp_DOT jp_CLASS
-{
-  jpElementStart(3);
-  jpStoreClass($<str>1);
-  jpCheckEmpty(3);
-  yyGetParser->SetCurrentCombine("");
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-Name jp_DOT jp_THIS
-{
-  jpElementStart(3);
-  jpStoreClass($<str>1);
-  yyGetParser->SetCurrentCombine("");
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-SimpleType jp_DOT jp_CLASS
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-SimpleType:
-PrimitiveType
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-jp_VOID
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-CompilationUnit:
-PackageDeclarationopt ImportDeclarations TypeDeclarations
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-PackageDeclarationopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-PackageDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-ImportDeclarations:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-ImportDeclarations ImportDeclaration
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-TypeDeclarations:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-TypeDeclarations TypeDeclaration
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-PackageDeclaration:
-jp_PACKAGE Name jp_SEMICOL
-{
-  jpElementStart(3);
-  yyGetParser->SetCurrentPackage($<str>2);
-  yyGetParser->DeallocateParserType(&($<str>2));
-  yyGetParser->SetCurrentCombine("");
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-ImportDeclaration:
-SingleTypeImportDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-TypeImportOnDemandDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-SingleTypeImportDeclaration:
-jp_IMPORT Name jp_SEMICOL
-{
-  jpElementStart(3);
-  yyGetParser->AddPackagesImport($<str>2);
-  yyGetParser->DeallocateParserType(&($<str>2));
-  yyGetParser->SetCurrentCombine("");
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-TypeImportOnDemandDeclaration:
-jp_IMPORT Name jp_DOT jp_TIMES jp_SEMICOL
-{
-  jpElementStart(5);
-  std::string str = $<str>2;
-  str += ".*";
-  yyGetParser->AddPackagesImport(str.c_str());
-  yyGetParser->DeallocateParserType(&($<str>2));
-  yyGetParser->SetCurrentCombine("");
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-TypeDeclaration:
-ClassDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-InterfaceDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-jp_SEMICOL
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-Modifiers:
-Modifier
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-Modifiers Modifier
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-Modifier:
-jp_PUBLIC | jp_PROTECTED | jp_PRIVATE |
-jp_STATIC |
-jp_ABSTRACT | jp_FINAL | jp_NATIVE | jp_SYNCHRONIZED | jp_TRANSIENT | jp_VOLATILE |
-jp_STRICTFP
-
-ClassHeader:
-Modifiersopt jp_CLASS Identifier
-{
-  yyGetParser->StartClass($<str>3);
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&($<str>3));
-  jpCheckEmpty(3);
-}
-
-
-ClassDeclaration:
-ClassHeader ClassBody
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-|
-ClassHeader Interfaces ClassBody
-{
-  jpElementStart(3);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-|
-ClassHeader Super ClassBody
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-|
-ClassHeader Super Interfaces ClassBody
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-
-Modifiersopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-Modifiers
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-Super:
-jp_EXTENDS ClassType
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-Interfaces:
-jp_IMPLEMENTS InterfaceTypeList
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-InterfaceTypeList:
-InterfaceType
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-InterfaceTypeList jp_COMMA InterfaceType
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-ClassBody:
-jp_CURLYSTART ClassBodyDeclarations jp_CURLYEND
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-ClassBodyDeclarations:
-{
-  jpElementStart(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-ClassBodyDeclarations ClassBodyDeclaration
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-ClassBodyDeclaration:
-ClassMemberDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-StaticInitializer
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-ConstructorDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-TypeDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-ClassMemberDeclaration:
-FieldDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-MethodDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-FieldDeclaration:
-Modifiersopt Type VariableDeclarators jp_SEMICOL
-{
-  jpElementStart(4);
-}
-
-VariableDeclarators:
-VariableDeclarator
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-VariableDeclarators jp_COMMA VariableDeclarator
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-VariableDeclarator:
-VariableDeclaratorId
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-VariableDeclaratorId jp_EQUALS VariableInitializer
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-VariableDeclaratorId:
-Identifier
-{
-  jpElementStart(1);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-VariableDeclaratorId jp_BRACKETSTART jp_BRACKETEND
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-VariableInitializer:
-Expression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-ArrayInitializer
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-MethodDeclaration:
-MethodHeader jp_SEMICOL
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-MethodHeader MethodBody
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-MethodHeader MethodBody jp_SEMICOL
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-
-MethodHeader:
-Modifiersopt Type MethodDeclarator Throwsopt
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Modifiersopt jp_VOID MethodDeclarator Throwsopt
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Throwsopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Throws
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-MethodDeclarator:
-Identifier jp_PARESTART FormalParameterListopt jp_PAREEND
-{
-  jpElementStart(4);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-MethodDeclarator jp_BRACKETSTART jp_BRACKETEND
-{
-  jpElementStart(3);
-
-}
-
-FormalParameterListopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-FormalParameterList
-
-FormalParameterList:
-FormalParameter
-{
-  jpElementStart(1);
-
-}
-|
-FormalParameterList jp_COMMA FormalParameter
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-FormalParameter:
-Modifiersopt Type VariableDeclaratorId
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Throws:
-jp_THROWS ClassTypeList
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ClassTypeList:
-ClassType
-{
-  jpElementStart(1);
-
-}
-|
-ClassTypeList jp_COMMA ClassType
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-MethodBody:
-Block
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-StaticInitializer:
-jp_STATIC Block
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ConstructorDeclaration:
-Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Modifiersopt ConstructorDeclarator Throwsopt ConstructorBody jp_SEMICOL
-{
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ConstructorDeclarator:
-SimpleName jp_PARESTART FormalParameterListopt jp_PAREEND
-{
-  jpElementStart(4);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ConstructorBody:
-jp_CURLYSTART ExplicitConstructorInvocationopt BlockStatementsopt jp_CURLYEND
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ExplicitConstructorInvocationopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ExplicitConstructorInvocationopt ExplicitConstructorInvocation
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ExplicitConstructorInvocation:
-jp_THIS jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL
-{
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_SUPER jp_PARESTART ArgumentListopt jp_PAREEND jp_SEMICOL
-{
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-InterfaceHeader:
-Modifiersopt jp_INTERFACE Identifier
-{
-  yyGetParser->StartClass($<str>3);
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&($<str>3));
-  jpCheckEmpty(3);
-}
-
-InterfaceDeclaration:
-InterfaceHeader ExtendsInterfacesopt InterfaceBody
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-  yyGetParser->EndClass();
-}
-
-ExtendsInterfacesopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-}
-|
-ExtendsInterfaces
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ExtendsInterfaces:
-jp_EXTENDS InterfaceType
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ExtendsInterfaces jp_COMMA InterfaceType
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-InterfaceBody:
-jp_CURLYSTART InterfaceMemberDeclarations jp_CURLYEND
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-InterfaceMemberDeclarations:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-InterfaceMemberDeclarations InterfaceMemberDeclaration
-{
-  jpElementStart(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-InterfaceMemberDeclaration:
-ConstantDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-AbstractMethodDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ClassDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ClassDeclaration jp_SEMICOL
-{
-  jpElementStart(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-InterfaceDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-InterfaceDeclaration jp_SEMICOL
-{
-  jpElementStart(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ConstantDeclaration:
-FieldDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-AbstractMethodDeclaration:
-MethodHeader Semicols
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Semicols:
-jp_SEMICOL
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Semicols jp_SEMICOL
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ArrayInitializer:
-jp_CURLYSTART VariableInitializersOptional jp_CURLYEND
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-VariableInitializersOptional:
-{
-  jpElementStart(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-VariableInitializers
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-VariableInitializers jp_COMMA
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-VariableInitializers:
-VariableInitializer
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-VariableInitializers jp_COMMA VariableInitializer
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Block:
-jp_CURLYSTART BlockStatementsopt jp_CURLYEND
-{
-  jpElementStart(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-BlockStatementsopt:
-{
-  jpElementStart(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-BlockStatements
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-BlockStatements:
-BlockStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-BlockStatements BlockStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-BlockStatement:
-LocalVariableDeclarationStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Statement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ClassDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-LocalVariableDeclarationStatement:
-LocalVariableDeclaration jp_SEMICOL
-{
-  jpElementStart(1);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-LocalVariableDeclaration:
-Modifiers Type VariableDeclarators
-{
-  jpElementStart(1);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Type VariableDeclarators
-{
-  jpElementStart(1);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Statement:
-StatementWithoutTrailingSubstatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-LabeledStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-IfThenStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-IfThenElseStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-WhileStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ForStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-StatementNoShortIf:
-StatementWithoutTrailingSubstatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-LabeledStatementNoShortIf
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-IfThenElseStatementNoShortIf
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-WhileStatementNoShortIf
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ForStatementNoShortIf
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-StatementWithoutTrailingSubstatement:
-Block
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-EmptyStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ExpressionStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-SwitchStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-DoStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-BreakStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ContinueStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ReturnStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-SynchronizedStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ThrowStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-TryStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-AssertStatement
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-EmptyStatement:
-jp_SEMICOL
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-LabeledStatement:
-Identifier jp_COLON Statement
-{
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-LabeledStatementNoShortIf:
-Identifier jp_COLON StatementNoShortIf
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ExpressionStatement:
-StatementExpression jp_SEMICOL
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-StatementExpression:
-Assignment
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-PreIncrementExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-PreDecrementExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-PostIncrementExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-PostDecrementExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-MethodInvocation
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ClassInstanceCreationExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-IfThenStatement:
-jp_IF jp_PARESTART Expression jp_PAREEND Statement
-{
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-IfThenElseStatement:
-jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE Statement
-{
-  jpElementStart(7);
-  jpCheckEmpty(7);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-IfThenElseStatementNoShortIf:
-jp_IF jp_PARESTART Expression jp_PAREEND StatementNoShortIf jp_ELSE StatementNoShortIf
-{
-  jpElementStart(7);
-  jpCheckEmpty(7);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-SwitchStatement:
-jp_SWITCH jp_PARESTART Expression jp_PAREEND SwitchBlock
-{
-  jpElementStart(5);
-
-}
-
-SwitchBlock:
-jp_CURLYSTART SwitchBlockStatementGroups SwitchLabelsopt jp_CURLYEND
-{
-  jpElementStart(4);
-
-}
-
-SwitchLabelsopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-SwitchLabels
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-SwitchBlockStatementGroups:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-SwitchBlockStatementGroups SwitchBlockStatementGroup
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-SwitchBlockStatementGroup:
-SwitchLabels BlockStatements
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-SwitchLabels:
-SwitchLabel
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-SwitchLabels SwitchLabel
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-SwitchLabel:
-jp_CASE ConstantExpression jp_COLON
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_DEFAULT jp_COLON
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-WhileStatement:
-jp_WHILE jp_PARESTART Expression jp_PAREEND Statement
-{
-  jpElementStart(5);
-
-}
-
-WhileStatementNoShortIf:
-jp_WHILE jp_PARESTART Expression jp_PAREEND StatementNoShortIf
-{
-  jpElementStart(5);
-
-}
-
-DoStatement:
-jp_DO Statement jp_WHILE jp_PARESTART Expression jp_PAREEND jp_SEMICOL
-{
-  jpElementStart(7);
-
-}
-
-ForStatement:
-jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND
-Statement
-{
-  jpElementStart(9);
-
-}
-
-ForUpdateopt:
-{
-  jpElementStart(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ForUpdate
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ForInitopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ForInit
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ForStatementNoShortIf:
-jp_FOR jp_PARESTART ForInitopt jp_SEMICOL Expressionopt jp_SEMICOL ForUpdateopt jp_PAREEND
-StatementNoShortIf
-{
-  jpElementStart(9);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Expressionopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Expression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ForInit:
-StatementExpressionList
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-LocalVariableDeclaration
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ForUpdate:
-StatementExpressionList
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-StatementExpressionList:
-StatementExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-StatementExpressionList jp_COMMA StatementExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-AssertStatement:
-jp_ASSERT Expression jp_SEMICOL
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_ASSERT Expression jp_COLON Expression jp_SEMICOL
-{
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-BreakStatement:
-jp_BREAK Identifieropt jp_SEMICOL
-{
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&($<str>2));
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Identifieropt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Identifier
-{
-  jpElementStart(1);
-
-}
-
-ContinueStatement:
-jp_CONTINUE Identifieropt jp_SEMICOL
-{
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&($<str>2));
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ReturnStatement:
-jp_RETURN Expressionopt jp_SEMICOL
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ThrowStatement:
-jp_THROW Expression jp_SEMICOL
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-SynchronizedStatement:
-jp_SYNCHRONIZED jp_PARESTART Expression jp_PAREEND Block
-{
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-TryStatement:
-jp_TRY Block Catches
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_TRY Block Catchesopt Finally
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Catchesopt:
-{
-  jpElementStart(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Catches
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Catches:
-CatchClause
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Catches CatchClause
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-CatchClause:
-jp_CATCH jp_PARESTART FormalParameter jp_PAREEND Block
-{
-  jpElementStart(5);
-
-}
-
-Finally:
-jp_FINALLY Block
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Primary:
-PrimaryNoNewArray
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ArrayCreationExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-PrimaryNoNewArray:
-Literal
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_THIS
-{
-  jpElementStart(1);
-
-}
-|
-jp_PARESTART Expression jp_PAREEND
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ClassInstanceCreationExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-FieldAccess
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-MethodInvocation
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ArrayAccess
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ClassInstanceCreationExpression:
-New ClassType jp_PARESTART ArgumentListopt jp_PAREEND ClassBodyOpt
-{
-  jpElementStart(6);
-  jpCheckEmpty(6);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ClassBodyOpt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ClassBody
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ArgumentListopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ArgumentList
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ArgumentList:
-Expression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ArgumentList jp_COMMA Expression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ArrayCreationExpression:
-New PrimitiveType DimExprs Dimsopt
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-New ClassOrInterfaceType DimExprs Dimsopt
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-New PrimitiveType Dims ArrayInitializer
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-New ClassOrInterfaceType Dims ArrayInitializer
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Dimsopt:
-{
-  jpElementStart(0);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Dims
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-DimExprs:
-DimExpr
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-DimExprs DimExpr
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-DimExpr:
-jp_BRACKETSTART Expression jp_BRACKETEND
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Dims:
-jp_BRACKETSTART jp_BRACKETEND
-{
-  jpElementStart(2);
-
-}
-|
-Dims jp_BRACKETSTART jp_BRACKETEND
-{
-  jpElementStart(3);
-
-}
-
-FieldAccess:
-Primary jp_DOT Identifier
-{
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&($<str>3));
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_SUPER jp_DOT Identifier
-{
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&($<str>3));
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_THIS jp_DOT Identifier
-{
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&($<str>3));
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Primary jp_DOT jp_THIS
-{
-  jpElementStart(3);
-  yyGetParser->DeallocateParserType(&($<str>3));
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-MethodInvocation:
-Name jp_PARESTART ArgumentListopt jp_PAREEND
-{
-  jpElementStart(4);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Primary jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND
-{
-  jpElementStart(6);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  yyGetParser->DeallocateParserType(&($<str>3));
-  jpCheckEmpty(6);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_SUPER jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND
-{
-  jpElementStart(6);
-  yyGetParser->DeallocateParserType(&($<str>3));
-  jpCheckEmpty(6);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_THIS jp_DOT Identifier jp_PARESTART ArgumentListopt jp_PAREEND
-{
-  jpElementStart(6);
-  yyGetParser->DeallocateParserType(&($<str>3));
-  jpCheckEmpty(6);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ArrayAccess:
-Name jp_BRACKETSTART Expression jp_BRACKETEND
-{
-  jpElementStart(4);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-PrimaryNoNewArray jp_BRACKETSTART Expression jp_BRACKETEND
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-PostfixExpression:
-Primary
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Name
-{
-  jpElementStart(1);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ArrayType jp_DOT jp_CLASS
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-PostIncrementExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-PostDecrementExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-PostIncrementExpression:
-PostfixExpression jp_PLUSPLUS
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-PostDecrementExpression:
-PostfixExpression jp_MINUSMINUS
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-UnaryExpression:
-PreIncrementExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-PreDecrementExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_PLUS UnaryExpression
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_MINUS UnaryExpression
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-UnaryExpressionNotPlusMinus
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-PreIncrementExpression:
-jp_PLUSPLUS UnaryExpression
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-PreDecrementExpression:
-jp_MINUSMINUS UnaryExpression
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-UnaryExpressionNotPlusMinus:
-PostfixExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_TILDE UnaryExpression
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_EXCLAMATION UnaryExpression
-{
-  jpElementStart(2);
-  jpCheckEmpty(2);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-CastExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-CastExpression:
-jp_PARESTART PrimitiveType Dimsopt jp_PAREEND UnaryExpression
-{
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_PARESTART Expression jp_PAREEND UnaryExpressionNotPlusMinus
-{
-  jpElementStart(4);
-  jpCheckEmpty(4);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_PARESTART Name Dims jp_PAREEND UnaryExpressionNotPlusMinus
-{
-  jpElementStart(5);
-
-}
-
-MultiplicativeExpression:
-UnaryExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-MultiplicativeExpression jp_TIMES UnaryExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-MultiplicativeExpression jp_DIVIDE UnaryExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-MultiplicativeExpression jp_PERCENT UnaryExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-AdditiveExpression:
-MultiplicativeExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-AdditiveExpression jp_PLUS MultiplicativeExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-AdditiveExpression jp_MINUS MultiplicativeExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ShiftExpression:
-AdditiveExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ShiftExpression jp_LTLT AdditiveExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ShiftExpression jp_GTGT AdditiveExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ShiftExpression jp_GTGTGT AdditiveExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-RelationalExpression:
-ShiftExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-RelationalExpression jp_LESSTHAN ShiftExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-RelationalExpression jp_GREATER ShiftExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-RelationalExpression jp_LTEQUALS ShiftExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-RelationalExpression jp_GTEQUALS ShiftExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-RelationalExpression jp_INSTANCEOF ReferenceType
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-EqualityExpression:
-RelationalExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-EqualityExpression jp_EQUALSEQUALS RelationalExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-EqualityExpression jp_EXCLAMATIONEQUALS RelationalExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-AndExpression:
-EqualityExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-AndExpression jp_AND EqualityExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ExclusiveOrExpression:
-AndExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ExclusiveOrExpression jp_CARROT AndExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-InclusiveOrExpression:
-ExclusiveOrExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-InclusiveOrExpression jp_PIPE ExclusiveOrExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ConditionalAndExpression:
-InclusiveOrExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ConditionalAndExpression jp_ANDAND InclusiveOrExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ConditionalOrExpression:
-ConditionalAndExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ConditionalOrExpression jp_PIPEPIPE ConditionalAndExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ConditionalExpression:
-ConditionalOrExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ConditionalOrExpression jp_QUESTION Expression jp_COLON ConditionalExpression
-{
-  jpElementStart(5);
-  jpCheckEmpty(5);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-AssignmentExpression:
-ConditionalExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Assignment
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Assignment:
-LeftHandSide AssignmentOperator AssignmentExpression
-{
-  jpElementStart(3);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-LeftHandSide:
-Name
-{
-  jpElementStart(1);
-  yyGetParser->DeallocateParserType(&($<str>1));
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-FieldAccess
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-ArrayAccess
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-AssignmentOperator:
-jp_EQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_TIMESEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_DIVIDEEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_PERCENTEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_PLUSEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_MINUSEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_LESLESEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_GTGTEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_GTGTGTEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_ANDEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_CARROTEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-jp_PIPEEQUALS
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-Expression:
-AssignmentExpression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-ConstantExpression:
-Expression
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-New:
-jp_NEW
-{
-  jpElementStart(1);
-  jpCheckEmpty(1);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-|
-Name jp_DOT jp_NEW
-{
-  jpElementStart(3);
-  jpStoreClass($<str>1);
-  jpCheckEmpty(3);
-  $<str>$ = 0;
-  yyGetParser->SetCurrentCombine("");
-
-}
-
-%%
-/* End of grammar */
-
-/*--------------------------------------------------------------------------*/
-void cmDependsJavaError(yyscan_t yyscanner, const char* message)
-{
-  yyGetParser->Error(message);
-}
-
diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx
index f5998ef..7bc91bf 100644
--- a/Source/cmDependsJavaParserHelper.cxx
+++ b/Source/cmDependsJavaParserHelper.cxx
@@ -2,12 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmDependsJavaParserHelper.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmDependsJavaLexer.h"
 #include "cmSystemTools.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <iostream>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h
index 71b939c..0b445d9 100644
--- a/Source/cmDependsJavaParserHelper.h
+++ b/Source/cmDependsJavaParserHelper.h
@@ -3,31 +3,23 @@
 #ifndef cmDependsJavaParserHelper_h
 #define cmDependsJavaParserHelper_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
 
-class cmDependsJavaParserHelper;
-
-#define YYSTYPE cmDependsJavaParserHelper::ParserType
-#define YYSTYPE_IS_DECLARED
-#define YY_EXTRA_TYPE cmDependsJavaParserHelper*
-#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
-
 /** \class cmDependsJavaParserHelper
  * \brief Helper class for parsing java source files
  *
  * Finds dependencies for java file and list of outputs
  */
-
 class cmDependsJavaParserHelper
 {
 public:
-  typedef struct
+  struct ParserType
   {
     char* str;
-  } ParserType;
+  };
 
   cmDependsJavaParserHelper();
   ~cmDependsJavaParserHelper();
@@ -96,4 +88,9 @@ private:
   void CleanupParser();
 };
 
+#define YYSTYPE cmDependsJavaParserHelper::ParserType
+#define YYSTYPE_IS_DECLARED
+#define YY_EXTRA_TYPE cmDependsJavaParserHelper*
+#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+
 #endif
diff --git a/Source/cmDependsJavaParserTokens.h b/Source/cmDependsJavaParserTokens.h
deleted file mode 100644
index c7a414f..0000000
--- a/Source/cmDependsJavaParserTokens.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875d.  */
-
-/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984,
-   1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, when this file is copied by Bison into a
-   Bison output file, you may use that output file without restriction.
-   This special exception was added by the Free Software Foundation
-   in version 1.24 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     jp_ABSTRACT = 258,
-     jp_ASSERT = 259,
-     jp_BOOLEAN_TYPE = 260,
-     jp_BREAK = 261,
-     jp_BYTE_TYPE = 262,
-     jp_CASE = 263,
-     jp_CATCH = 264,
-     jp_CHAR_TYPE = 265,
-     jp_CLASS = 266,
-     jp_CONTINUE = 267,
-     jp_DEFAULT = 268,
-     jp_DO = 269,
-     jp_DOUBLE_TYPE = 270,
-     jp_ELSE = 271,
-     jp_EXTENDS = 272,
-     jp_FINAL = 273,
-     jp_FINALLY = 274,
-     jp_FLOAT_TYPE = 275,
-     jp_FOR = 276,
-     jp_IF = 277,
-     jp_IMPLEMENTS = 278,
-     jp_IMPORT = 279,
-     jp_INSTANCEOF = 280,
-     jp_INT_TYPE = 281,
-     jp_INTERFACE = 282,
-     jp_LONG_TYPE = 283,
-     jp_NATIVE = 284,
-     jp_NEW = 285,
-     jp_PACKAGE = 286,
-     jp_PRIVATE = 287,
-     jp_PROTECTED = 288,
-     jp_PUBLIC = 289,
-     jp_RETURN = 290,
-     jp_SHORT_TYPE = 291,
-     jp_STATIC = 292,
-     jp_STRICTFP = 293,
-     jp_SUPER = 294,
-     jp_SWITCH = 295,
-     jp_SYNCHRONIZED = 296,
-     jp_THIS = 297,
-     jp_THROW = 298,
-     jp_THROWS = 299,
-     jp_TRANSIENT = 300,
-     jp_TRY = 301,
-     jp_VOID = 302,
-     jp_VOLATILE = 303,
-     jp_WHILE = 304,
-     jp_BOOLEANLITERAL = 305,
-     jp_CHARACTERLITERAL = 306,
-     jp_DECIMALINTEGERLITERAL = 307,
-     jp_FLOATINGPOINTLITERAL = 308,
-     jp_HEXINTEGERLITERAL = 309,
-     jp_NULLLITERAL = 310,
-     jp_STRINGLITERAL = 311,
-     jp_NAME = 312,
-     jp_AND = 313,
-     jp_ANDAND = 314,
-     jp_ANDEQUALS = 315,
-     jp_BRACKETEND = 316,
-     jp_BRACKETSTART = 317,
-     jp_CARROT = 318,
-     jp_CARROTEQUALS = 319,
-     jp_COLON = 320,
-     jp_COMMA = 321,
-     jp_CURLYEND = 322,
-     jp_CURLYSTART = 323,
-     jp_DIVIDE = 324,
-     jp_DIVIDEEQUALS = 325,
-     jp_DOLLAR = 326,
-     jp_DOT = 327,
-     jp_EQUALS = 328,
-     jp_EQUALSEQUALS = 329,
-     jp_EXCLAMATION = 330,
-     jp_EXCLAMATIONEQUALS = 331,
-     jp_GREATER = 332,
-     jp_GTEQUALS = 333,
-     jp_GTGT = 334,
-     jp_GTGTEQUALS = 335,
-     jp_GTGTGT = 336,
-     jp_GTGTGTEQUALS = 337,
-     jp_LESLESEQUALS = 338,
-     jp_LESSTHAN = 339,
-     jp_LTEQUALS = 340,
-     jp_LTLT = 341,
-     jp_MINUS = 342,
-     jp_MINUSEQUALS = 343,
-     jp_MINUSMINUS = 344,
-     jp_PAREEND = 345,
-     jp_PARESTART = 346,
-     jp_PERCENT = 347,
-     jp_PERCENTEQUALS = 348,
-     jp_PIPE = 349,
-     jp_PIPEEQUALS = 350,
-     jp_PIPEPIPE = 351,
-     jp_PLUS = 352,
-     jp_PLUSEQUALS = 353,
-     jp_PLUSPLUS = 354,
-     jp_QUESTION = 355,
-     jp_SEMICOL = 356,
-     jp_TILDE = 357,
-     jp_TIMES = 358,
-     jp_TIMESEQUALS = 359,
-     jp_ERROR = 360
-   };
-#endif
-#define jp_ABSTRACT 258
-#define jp_ASSERT 259
-#define jp_BOOLEAN_TYPE 260
-#define jp_BREAK 261
-#define jp_BYTE_TYPE 262
-#define jp_CASE 263
-#define jp_CATCH 264
-#define jp_CHAR_TYPE 265
-#define jp_CLASS 266
-#define jp_CONTINUE 267
-#define jp_DEFAULT 268
-#define jp_DO 269
-#define jp_DOUBLE_TYPE 270
-#define jp_ELSE 271
-#define jp_EXTENDS 272
-#define jp_FINAL 273
-#define jp_FINALLY 274
-#define jp_FLOAT_TYPE 275
-#define jp_FOR 276
-#define jp_IF 277
-#define jp_IMPLEMENTS 278
-#define jp_IMPORT 279
-#define jp_INSTANCEOF 280
-#define jp_INT_TYPE 281
-#define jp_INTERFACE 282
-#define jp_LONG_TYPE 283
-#define jp_NATIVE 284
-#define jp_NEW 285
-#define jp_PACKAGE 286
-#define jp_PRIVATE 287
-#define jp_PROTECTED 288
-#define jp_PUBLIC 289
-#define jp_RETURN 290
-#define jp_SHORT_TYPE 291
-#define jp_STATIC 292
-#define jp_STRICTFP 293
-#define jp_SUPER 294
-#define jp_SWITCH 295
-#define jp_SYNCHRONIZED 296
-#define jp_THIS 297
-#define jp_THROW 298
-#define jp_THROWS 299
-#define jp_TRANSIENT 300
-#define jp_TRY 301
-#define jp_VOID 302
-#define jp_VOLATILE 303
-#define jp_WHILE 304
-#define jp_BOOLEANLITERAL 305
-#define jp_CHARACTERLITERAL 306
-#define jp_DECIMALINTEGERLITERAL 307
-#define jp_FLOATINGPOINTLITERAL 308
-#define jp_HEXINTEGERLITERAL 309
-#define jp_NULLLITERAL 310
-#define jp_STRINGLITERAL 311
-#define jp_NAME 312
-#define jp_AND 313
-#define jp_ANDAND 314
-#define jp_ANDEQUALS 315
-#define jp_BRACKETEND 316
-#define jp_BRACKETSTART 317
-#define jp_CARROT 318
-#define jp_CARROTEQUALS 319
-#define jp_COLON 320
-#define jp_COMMA 321
-#define jp_CURLYEND 322
-#define jp_CURLYSTART 323
-#define jp_DIVIDE 324
-#define jp_DIVIDEEQUALS 325
-#define jp_DOLLAR 326
-#define jp_DOT 327
-#define jp_EQUALS 328
-#define jp_EQUALSEQUALS 329
-#define jp_EXCLAMATION 330
-#define jp_EXCLAMATIONEQUALS 331
-#define jp_GREATER 332
-#define jp_GTEQUALS 333
-#define jp_GTGT 334
-#define jp_GTGTEQUALS 335
-#define jp_GTGTGT 336
-#define jp_GTGTGTEQUALS 337
-#define jp_LESLESEQUALS 338
-#define jp_LESSTHAN 339
-#define jp_LTEQUALS 340
-#define jp_LTLT 341
-#define jp_MINUS 342
-#define jp_MINUSEQUALS 343
-#define jp_MINUSMINUS 344
-#define jp_PAREEND 345
-#define jp_PARESTART 346
-#define jp_PERCENT 347
-#define jp_PERCENTEQUALS 348
-#define jp_PIPE 349
-#define jp_PIPEEQUALS 350
-#define jp_PIPEPIPE 351
-#define jp_PLUS 352
-#define jp_PLUSEQUALS 353
-#define jp_PLUSPLUS 354
-#define jp_QUESTION 355
-#define jp_SEMICOL 356
-#define jp_TILDE 357
-#define jp_TIMES 358
-#define jp_TIMESEQUALS 359
-#define jp_ERROR 360
-
-
-
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-
-
diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx
new file mode 100644
index 0000000..ce1965d
--- /dev/null
+++ b/Source/cmDisallowedCommand.cxx
@@ -0,0 +1,31 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmDisallowedCommand.h"
+
+#include "cmMakefile.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
+
+bool cmDisallowedCommand::InitialPass(std::vector<std::string> const& args,
+                                      cmExecutionStatus& status)
+{
+  switch (this->Makefile->GetPolicyStatus(this->Policy)) {
+    case cmPolicies::WARN:
+      this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
+                                   cmPolicies::GetPolicyWarning(this->Policy));
+      break;
+    case cmPolicies::OLD:
+      break;
+    case cmPolicies::REQUIRED_IF_USED:
+    case cmPolicies::REQUIRED_ALWAYS:
+    case cmPolicies::NEW:
+      this->Makefile->IssueMessage(cmake::FATAL_ERROR, this->Message);
+      return true;
+  }
+
+  this->Command->SetMakefile(this->GetMakefile());
+  bool const ret = this->Command->InitialPass(args, status);
+  this->SetError(this->Command->GetError());
+  return ret;
+}
diff --git a/Source/cmDisallowedCommand.h b/Source/cmDisallowedCommand.h
new file mode 100644
index 0000000..0030116
--- /dev/null
+++ b/Source/cmDisallowedCommand.h
@@ -0,0 +1,51 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmDisallowedCommand_h
+#define cmDisallowedCommand_h
+
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
+#include "cmCommand.h"
+#include "cmPolicies.h"
+
+class cmExecutionStatus;
+
+class cmDisallowedCommand : public cmCommand
+{
+public:
+  cmDisallowedCommand(cmCommand* command, cmPolicies::PolicyID policy,
+                      const char* message)
+    : Command(command)
+    , Policy(policy)
+    , Message(message)
+  {
+  }
+
+  ~cmDisallowedCommand() CM_OVERRIDE { delete this->Command; }
+
+  cmCommand* Clone() CM_OVERRIDE
+  {
+    return new cmDisallowedCommand(this->Command->Clone(), this->Policy,
+                                   this->Message);
+  }
+
+  bool InitialPass(std::vector<std::string> const& args,
+                   cmExecutionStatus& status) CM_OVERRIDE;
+
+  void FinalPass() CM_OVERRIDE { this->Command->FinalPass(); }
+
+  bool HasFinalPass() const CM_OVERRIDE
+  {
+    return this->Command->HasFinalPass();
+  }
+
+private:
+  cmCommand* Command;
+  cmPolicies::PolicyID Policy;
+  const char* Message;
+};
+
+#endif
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index cb24adf..c6286b3 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -9,9 +9,9 @@
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
 #include <algorithm>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
 #include <ctype.h>
 #include <string.h>
 #include <utility>
@@ -129,28 +129,19 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os)
     this->CurrentArgument = i->Argument;
     // If a file name was given, use it.  Otherwise, default to the
     // given stream.
-    cmsys::ofstream* fout = CM_NULLPTR;
+    cmsys::ofstream fout;
     std::ostream* s = &os;
     if (!i->Filename.empty()) {
-      fout = new cmsys::ofstream(i->Filename.c_str());
-      if (fout) {
-        s = fout;
-      } else {
-        result = false;
-      }
+      fout.open(i->Filename.c_str());
+      s = &fout;
     } else if (++count > 1) {
       os << "\n\n";
     }
 
     // Print this documentation type to the stream.
-    if (!this->PrintDocumentation(i->HelpType, *s) || !*s) {
+    if (!this->PrintDocumentation(i->HelpType, *s) || s->fail()) {
       result = false;
     }
-
-    // Close the file if we wrote one.
-    if (fout) {
-      delete fout;
-    }
   }
   return result;
 }
diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h
index 66afd2c..2866fef 100644
--- a/Source/cmDocumentation.h
+++ b/Source/cmDocumentation.h
@@ -3,7 +3,7 @@
 #ifndef _cmDocumentation_h
 #define _cmDocumentation_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmDocumentationFormatter.h"
 
diff --git a/Source/cmDocumentationEntry.h b/Source/cmDocumentationEntry.h
index 1ccb82d..ea43b88 100644
--- a/Source/cmDocumentationEntry.h
+++ b/Source/cmDocumentationEntry.h
@@ -3,7 +3,7 @@
 #ifndef cmDocumentationEntry_h
 #define cmDocumentationEntry_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h
index ffa80f1..1f04250 100644
--- a/Source/cmDocumentationFormatter.h
+++ b/Source/cmDocumentationFormatter.h
@@ -3,7 +3,7 @@
 #ifndef _cmDocumentationFormatter_h
 #define _cmDocumentationFormatter_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
 
diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h
index c1eb5c8..d9e8187 100644
--- a/Source/cmDocumentationSection.h
+++ b/Source/cmDocumentationSection.h
@@ -3,7 +3,7 @@
 #ifndef _cmDocumentationSection_h
 #define _cmDocumentationSection_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmDocumentationEntry.h"
 
diff --git a/Source/cmDynamicLoader.cxx b/Source/cmDynamicLoader.cxx
index a30b642..7fbe75c 100644
--- a/Source/cmDynamicLoader.cxx
+++ b/Source/cmDynamicLoader.cxx
@@ -2,9 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmDynamicLoader.h"
 
-#include <cmConfigure.h>
-
-#include <cmsys/DynamicLoader.hxx>
 #include <map>
 #include <string>
 #include <utility>
@@ -13,8 +10,7 @@ class cmDynamicLoaderCache
 {
 public:
   ~cmDynamicLoaderCache();
-  void CacheFile(const char* path,
-                 const cmsys::DynamicLoader::LibraryHandle& /*p*/);
+  void CacheFile(const char* path, cmsys::DynamicLoader::LibraryHandle /*p*/);
   bool GetCacheFile(const char* path,
                     cmsys::DynamicLoader::LibraryHandle& /*p*/);
   bool FlushCache(const char* path);
@@ -32,8 +28,8 @@ cmDynamicLoaderCache::~cmDynamicLoaderCache()
 {
 }
 
-void cmDynamicLoaderCache::CacheFile(
-  const char* path, const cmsys::DynamicLoader::LibraryHandle& p)
+void cmDynamicLoaderCache::CacheFile(const char* path,
+                                     cmsys::DynamicLoader::LibraryHandle p)
 {
   cmsys::DynamicLoader::LibraryHandle h;
   if (this->GetCacheFile(path, h)) {
diff --git a/Source/cmDynamicLoader.h b/Source/cmDynamicLoader.h
index d14f81e..7c46dd5 100644
--- a/Source/cmDynamicLoader.h
+++ b/Source/cmDynamicLoader.h
@@ -8,12 +8,14 @@
 #ifndef cmDynamicLoader_h
 #define cmDynamicLoader_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
-#include <cmsys/DynamicLoader.hxx>
+#include "cmsys/DynamicLoader.hxx" // IWYU pragma: export
 
 class cmDynamicLoader
 {
+  CM_DISABLE_COPY(cmDynamicLoader)
+
 public:
   // Description:
   // Load a dynamic library into the current process.
@@ -28,10 +30,6 @@ public:
 protected:
   cmDynamicLoader() {}
   ~cmDynamicLoader() {}
-
-private:
-  cmDynamicLoader(const cmDynamicLoader&); // Not implemented.
-  void operator=(const cmDynamicLoader&);  // Not implemented.
 };
 
 #endif
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index 0655da9..fc97bf3 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmELF.h"
 
-#include <cm_auto_ptr.hxx>
-#include <cm_kwiml.h>
-#include <cmsys/FStream.hxx>
+#include "cm_auto_ptr.hxx"
+#include "cm_kwiml.h"
+#include "cmsys/FStream.hxx"
 #include <map>
 #include <sstream>
 #include <stddef.h>
@@ -44,23 +44,26 @@ typedef struct Elf32_Rela Elf32_Rela;
 #ifdef _SCO_DS
 #include <link.h> // For DT_SONAME etc.
 #endif
+#ifndef DT_RUNPATH
+#define DT_RUNPATH 29
+#endif
 
 // Low-level byte swapping implementation.
 template <size_t s>
 struct cmELFByteSwapSize
 {
 };
-void cmELFByteSwap(char* /*unused*/, cmELFByteSwapSize<1> const& /*unused*/)
+void cmELFByteSwap(char* /*unused*/, cmELFByteSwapSize<1> /*unused*/)
 {
 }
-void cmELFByteSwap(char* data, cmELFByteSwapSize<2> const& /*unused*/)
+void cmELFByteSwap(char* data, cmELFByteSwapSize<2> /*unused*/)
 {
   char one_byte;
   one_byte = data[0];
   data[0] = data[1];
   data[1] = one_byte;
 }
-void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const& /*unused*/)
+void cmELFByteSwap(char* data, cmELFByteSwapSize<4> /*unused*/)
 {
   char one_byte;
   one_byte = data[0];
@@ -70,7 +73,7 @@ void cmELFByteSwap(char* data, cmELFByteSwapSize<4> const& /*unused*/)
   data[1] = data[2];
   data[2] = one_byte;
 }
-void cmELFByteSwap(char* data, cmELFByteSwapSize<8> const& /*unused*/)
+void cmELFByteSwap(char* data, cmELFByteSwapSize<8> /*unused*/)
 {
   char one_byte;
   one_byte = data[0];
@@ -154,11 +157,7 @@ public:
   // Lookup the RUNPATH in the DYNAMIC section.
   StringEntry const* GetRunPath()
   {
-#if defined(DT_RUNPATH)
     return this->GetDynamicSectionString(DT_RUNPATH);
-#else
-    return 0;
-#endif
   }
 
   // Return the recorded ELF type.
diff --git a/Source/cmELF.h b/Source/cmELF.h
index 763a240..a6e407f 100644
--- a/Source/cmELF.h
+++ b/Source/cmELF.h
@@ -3,7 +3,7 @@
 #ifndef cmELF_h
 #define cmELF_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <string>
diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h
index bafb79e..33c1c22 100644
--- a/Source/cmEnableLanguageCommand.h
+++ b/Source/cmEnableLanguageCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmEnableLanguageCommand_h
 #define cmEnableLanguageCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -33,11 +34,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "enable_language"; }
 };
 
 #endif
diff --git a/Source/cmEnableTestingCommand.h b/Source/cmEnableTestingCommand.h
index 67cd237..e249662 100644
--- a/Source/cmEnableTestingCommand.h
+++ b/Source/cmEnableTestingCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmEnableTestingCommand_h
 #define cmEnableTestingCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -38,11 +39,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const&,
                    cmExecutionStatus&) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "enable_testing"; }
 };
 
 #endif
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx
index 6a7292d..fcc3c45 100644
--- a/Source/cmExecProgramCommand.cxx
+++ b/Source/cmExecProgramCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExecProgramCommand.h"
 
-#include <cmsys/Process.h>
+#include "cmsys/Process.h"
 #include <stdio.h>
 
 #include "cmMakefile.h"
diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h
index 58e948e..6463c4d 100644
--- a/Source/cmExecProgramCommand.h
+++ b/Source/cmExecProgramCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmExecProgramCommand_h
 #define cmExecProgramCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -35,16 +36,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "exec_program"; }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
 private:
   static bool RunCommand(const char* command, std::string& output, int& retVal,
                          const char* directory = CM_NULLPTR,
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 92cdf64..8c10dbe 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExecuteProcessCommand.h"
 
-#include <cmsys/Process.h>
+#include "cmsys/Process.h"
 #include <ctype.h> /* isspace */
 #include <sstream>
 #include <stdio.h>
diff --git a/Source/cmExecuteProcessCommand.h b/Source/cmExecuteProcessCommand.h
index 9ce4338..08fde0a 100644
--- a/Source/cmExecuteProcessCommand.h
+++ b/Source/cmExecuteProcessCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmExecuteProcessCommand_h
 #define cmExecuteProcessCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,16 +32,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "execute_process"; }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
 };
 
 #endif
diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h
index fd3c416..ac5fe1d 100644
--- a/Source/cmExecutionStatus.h
+++ b/Source/cmExecutionStatus.h
@@ -11,16 +11,13 @@
 class cmExecutionStatus
 {
 public:
-  cmExecutionStatus() { this->Clear(); }
-
-  void SetReturnInvoked(bool val) { this->ReturnInvoked = val; }
-  bool GetReturnInvoked() { return this->ReturnInvoked; }
-
-  void SetBreakInvoked(bool val) { this->BreakInvoked = val; }
-  bool GetBreakInvoked() { return this->BreakInvoked; }
-
-  void SetContinueInvoked(bool val) { this->ContinueInvoked = val; }
-  bool GetContinueInvoked() { return this->ContinueInvoked; }
+  cmExecutionStatus()
+    : ReturnInvoked(false)
+    , BreakInvoked(false)
+    , ContinueInvoked(false)
+    , NestedError(false)
+  {
+  }
 
   void Clear()
   {
@@ -29,8 +26,18 @@ public:
     this->ContinueInvoked = false;
     this->NestedError = false;
   }
-  void SetNestedError(bool val) { this->NestedError = val; }
-  bool GetNestedError() { return this->NestedError; }
+
+  void SetReturnInvoked() { this->ReturnInvoked = true; }
+  bool GetReturnInvoked() const { return this->ReturnInvoked; }
+
+  void SetBreakInvoked() { this->BreakInvoked = true; }
+  bool GetBreakInvoked() const { return this->BreakInvoked; }
+
+  void SetContinueInvoked() { this->ContinueInvoked = true; }
+  bool GetContinueInvoked() const { return this->ContinueInvoked; }
+
+  void SetNestedError() { this->NestedError = true; }
+  bool GetNestedError() const { return this->NestedError; }
 
 private:
   bool ReturnInvoked;
diff --git a/Source/cmExpandedCommandArgument.h b/Source/cmExpandedCommandArgument.h
index 9770fe6..fe86528 100644
--- a/Source/cmExpandedCommandArgument.h
+++ b/Source/cmExpandedCommandArgument.h
@@ -3,7 +3,7 @@
 #ifndef cmExpandedCommandArgument_h
 #define cmExpandedCommandArgument_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h
index 2a5a42e..d028ef4 100644
--- a/Source/cmExportBuildAndroidMKGenerator.h
+++ b/Source/cmExportBuildAndroidMKGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExportBuildAndroidMKGenerator_h
 #define cmExportBuildAndroidMKGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <string>
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 0c25268..a1c424a 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportBuildFileGenerator.h"
 
+#include "cmAlgorithms.h"
 #include "cmExportSet.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
@@ -21,6 +22,8 @@
 #include <sstream>
 #include <utility>
 
+class cmSourceFile;
+
 cmExportBuildFileGenerator::cmExportBuildFileGenerator()
 {
   this->LG = CM_NULLPTR;
@@ -171,29 +174,51 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
   // Get the makefile in which to lookup target information.
   cmMakefile* mf = target->Makefile;
 
-  // Add the main target file.
-  {
-    std::string prop = "IMPORTED_LOCATION";
+  if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+    std::string prop = "IMPORTED_OBJECTS";
     prop += suffix;
-    std::string value;
-    if (target->IsAppBundleOnApple()) {
-      value = target->GetFullPath(config, false);
-    } else {
-      value = target->GetFullPath(config, false, true);
+
+    // Compute all the object files inside this target and setup
+    // IMPORTED_OBJECTS as a list of object files
+    std::vector<cmSourceFile const*> objectSources;
+    target->GetObjectSources(objectSources, config);
+    std::string const obj_dir = target->GetObjectDirectory(config);
+    std::vector<std::string> objects;
+    for (std::vector<cmSourceFile const*>::const_iterator si =
+           objectSources.begin();
+         si != objectSources.end(); ++si) {
+      const std::string& obj = target->GetObjectName(*si);
+      objects.push_back(obj_dir + obj);
     }
-    properties[prop] = value;
-  }
 
-  // Add the import library for windows DLLs.
-  if (target->IsDLLPlatform() &&
-      (target->GetType() == cmStateEnums::SHARED_LIBRARY ||
-       target->IsExecutableWithExports()) &&
-      mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
-    std::string prop = "IMPORTED_IMPLIB";
-    prop += suffix;
-    std::string value = target->GetFullPath(config, true);
-    target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
-    properties[prop] = value;
+    // Store the property.
+    properties[prop] = cmJoin(objects, ";");
+  } else {
+    // Add the main target file.
+    {
+      std::string prop = "IMPORTED_LOCATION";
+      prop += suffix;
+      std::string value;
+      if (target->IsAppBundleOnApple()) {
+        value =
+          target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
+      } else {
+        value = target->GetFullPath(config,
+                                    cmStateEnums::RuntimeBinaryArtifact, true);
+      }
+      properties[prop] = value;
+    }
+
+    // Add the import library for windows DLLs.
+    if (target->HasImportLibrary() &&
+        mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+      std::string prop = "IMPORTED_IMPLIB";
+      prop += suffix;
+      std::string value =
+        target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact);
+      target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+      properties[prop] = value;
+    }
   }
 }
 
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 0539b6a..0556983 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExportBuildFileGenerator_h
 #define cmExportBuildFileGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExportFileGenerator.h"
 
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 8102276..38cd511 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportCommand.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <map>
 #include <sstream>
 
@@ -149,11 +149,15 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
 
       if (cmTarget* target = gg->FindTarget(*currentTarget)) {
         if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
-          std::ostringstream e;
-          e << "given OBJECT library \"" << *currentTarget
-            << "\" which may not be exported.";
-          this->SetError(e.str());
-          return false;
+          std::string reason;
+          if (!this->Makefile->GetGlobalGenerator()
+                 ->HasKnownObjectFileLocation(&reason)) {
+            std::ostringstream e;
+            e << "given OBJECT library \"" << *currentTarget
+              << "\" which may not be exported" << reason << ".";
+            this->SetError(e.str());
+            return false;
+          }
         }
         if (target->GetType() == cmStateEnums::UTILITY) {
           this->SetError("given custom target \"" + *currentTarget +
@@ -279,7 +283,6 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args)
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include <windows.h>
 
-#undef GetCurrentDirectory
 void cmExportCommand::ReportRegistryError(std::string const& msg,
                                           std::string const& key, long err)
 {
diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h
index 99dac7d..c47bc42 100644
--- a/Source/cmExportCommand.h
+++ b/Source/cmExportCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmExportCommand_h
 #define cmExportCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -35,12 +36,8 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "export"; }
-
 private:
+  cmCommandArgumentsHelper Helper;
   cmCommandArgumentGroup ArgumentGroup;
   cmCAStringVector Targets;
   cmCAEnabler Append;
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 6c21eaf..972f4b9 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -17,9 +17,9 @@
 #include "cmTargetExport.h"
 #include "cmake.h"
 
+#include "cm_auto_ptr.hxx"
+#include "cmsys/FStream.hxx"
 #include <assert.h>
-#include <cm_auto_ptr.hxx>
-#include <cmsys/FStream.hxx>
 #include <sstream>
 #include <string.h>
 #include <utility>
@@ -273,6 +273,7 @@ static bool checkInterfaceDirs(const std::string& prepro,
                 << std::endl;
               target->GetLocalGenerator()->IssueMessage(cmake::AUTHOR_WARNING,
                                                         s.str());
+              CM_FALLTHROUGH;
             }
             case cmPolicies::OLD:
               shouldContinue = true;
@@ -441,6 +442,11 @@ void getCompatibleInterfaceProperties(cmGeneratorTarget* target,
                                       std::set<std::string>& ifaceProperties,
                                       const std::string& config)
 {
+  if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+    // object libraries have no link information, so nothing to compute
+    return;
+  }
+
   cmComputeLinkInformation* info = target->GetLinkInformation(config);
 
   if (!info) {
@@ -585,16 +591,17 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
   std::string::size_type pos = 0;
   std::string::size_type lastPos = pos;
 
-  while ((pos = input.find("$<TARGET_PROPERTY:", lastPos)) != input.npos) {
+  while ((pos = input.find("$<TARGET_PROPERTY:", lastPos)) !=
+         std::string::npos) {
     std::string::size_type nameStartPos =
       pos + sizeof("$<TARGET_PROPERTY:") - 1;
     std::string::size_type closePos = input.find('>', nameStartPos);
     std::string::size_type commaPos = input.find(',', nameStartPos);
     std::string::size_type nextOpenPos = input.find("$<", nameStartPos);
-    if (commaPos == input.npos     // Implied 'this' target
-        || closePos == input.npos  // Imcomplete expression.
-        || closePos < commaPos     // Implied 'this' target
-        || nextOpenPos < commaPos) // Non-literal
+    if (commaPos == std::string::npos    // Implied 'this' target
+        || closePos == std::string::npos // Imcomplete expression.
+        || closePos < commaPos           // Implied 'this' target
+        || nextOpenPos < commaPos)       // Non-literal
     {
       lastPos = nameStartPos;
       continue;
@@ -612,15 +619,15 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
   std::string errorString;
   pos = 0;
   lastPos = pos;
-  while ((pos = input.find("$<TARGET_NAME:", lastPos)) != input.npos) {
+  while ((pos = input.find("$<TARGET_NAME:", lastPos)) != std::string::npos) {
     std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1;
     std::string::size_type endPos = input.find('>', nameStartPos);
-    if (endPos == input.npos) {
+    if (endPos == std::string::npos) {
       errorString = "$<TARGET_NAME:...> expression incomplete";
       break;
     }
     std::string targetName = input.substr(nameStartPos, endPos - nameStartPos);
-    if (targetName.find("$<") != input.npos) {
+    if (targetName.find("$<") != std::string::npos) {
       errorString = "$<TARGET_NAME:...> requires its parameter to be a "
                     "literal.";
       break;
@@ -637,10 +644,10 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
   pos = 0;
   lastPos = pos;
   while (errorString.empty() &&
-         (pos = input.find("$<LINK_ONLY:", lastPos)) != input.npos) {
+         (pos = input.find("$<LINK_ONLY:", lastPos)) != std::string::npos) {
     std::string::size_type nameStartPos = pos + sizeof("$<LINK_ONLY:") - 1;
     std::string::size_type endPos = input.find('>', nameStartPos);
-    if (endPos == input.npos) {
+    if (endPos == std::string::npos) {
       errorString = "$<LINK_ONLY:...> expression incomplete";
       break;
     }
@@ -927,6 +934,9 @@ void cmExportFileGenerator::GenerateImportTargetCode(
     case cmStateEnums::UNKNOWN_LIBRARY:
       os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
       break;
+    case cmStateEnums::OBJECT_LIBRARY:
+      os << "add_library(" << targetName << " OBJECT IMPORTED)\n";
+      break;
     case cmStateEnums::INTERFACE_LIBRARY:
       os << "add_library(" << targetName << " INTERFACE IMPORTED)\n";
       break;
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index e7712d2..985c8f6 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExportFileGenerator_h
 #define cmExportFileGenerator_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmGeneratorExpression.h"
 #include "cmVersion.h"
diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h
index f2f8927..ebef783 100644
--- a/Source/cmExportInstallAndroidMKGenerator.h
+++ b/Source/cmExportInstallAndroidMKGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExportInstallAndroidMKGenerator_h
 #define cmExportInstallAndroidMKGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <set>
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 64ea3c8..664a342 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -195,8 +195,10 @@ void cmExportInstallFileGenerator::GenerateImportPrefix(std::ostream& os)
        << " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
     if (cmHasLiteralPrefix(absDestS.c_str(), "/lib/") ||
         cmHasLiteralPrefix(absDestS.c_str(), "/lib64/") ||
+        cmHasLiteralPrefix(absDestS.c_str(), "/libx32/") ||
         cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib/") ||
-        cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib64/")) {
+        cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib64/") ||
+        cmHasLiteralPrefix(absDestS.c_str(), "/usr/libx32/")) {
       // Handle "/usr move" symlinks created by some Linux distros.
       /* clang-format off */
       os <<
@@ -253,7 +255,8 @@ void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input)
   std::string::size_type pos = 0;
   std::string::size_type lastPos = pos;
 
-  while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != input.npos) {
+  while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) !=
+         std::string::npos) {
     std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1;
     input.replace(pos, endPos - pos, "${_IMPORT_PREFIX}");
     lastPos = endPos;
@@ -329,6 +332,8 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
                                     properties, importedLocations);
     this->SetImportLocationProperty(config, suffix, te->RuntimeGenerator,
                                     properties, importedLocations);
+    this->SetImportLocationProperty(config, suffix, te->ObjectsGenerator,
+                                    properties, importedLocations);
     this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator,
                                     properties, importedLocations);
     this->SetImportLocationProperty(config, suffix, te->BundleGenerator,
@@ -395,6 +400,23 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
     // Store the property.
     properties[prop] = value;
     importedLocations.insert(prop);
+  } else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+    // Construct the property name.
+    std::string prop = "IMPORTED_OBJECTS";
+    prop += suffix;
+
+    // Compute all the object files inside this target and setup
+    // IMPORTED_OBJECTS as a list of object files
+    std::vector<std::string> objects;
+    itgen->GetInstallObjectNames(config, objects);
+    for (std::vector<std::string>::iterator i = objects.begin();
+         i != objects.end(); ++i) {
+      *i = value + *i;
+    }
+
+    // Store the property.
+    properties[prop] = cmJoin(objects, ";");
+    importedLocations.insert(prop);
   } else {
     // Construct the property name.
     std::string prop = "IMPORTED_LOCATION";
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 3c9777a..8fa9b7f 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExportInstallFileGenerator_h
 #define cmExportInstallFileGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExportFileGenerator.h"
 
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index ac4f040..69150ae 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -2,14 +2,13 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExportLibraryDependenciesCommand.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <map>
 #include <utility>
 
 #include "cmGeneratedFileStream.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -23,12 +22,6 @@ class cmExecutionStatus;
 bool cmExportLibraryDependenciesCommand::InitialPass(
   std::vector<std::string> const& args, cmExecutionStatus&)
 {
-  if (this->Disallowed(
-        cmPolicies::CMP0033,
-        "The export_library_dependencies command should not be called; "
-        "see CMP0033.")) {
-    return true;
-  }
   if (args.empty()) {
     this->SetError("called with incorrect number of arguments");
     return false;
diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h
index be53349..5559af9 100644
--- a/Source/cmExportLibraryDependenciesCommand.h
+++ b/Source/cmExportLibraryDependenciesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmExportLibraryDependenciesCommand_h
 #define cmExportLibraryDependenciesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -20,10 +21,6 @@ public:
   }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "export_library_dependencies";
-  }
 
   void FinalPass() CM_OVERRIDE;
   bool HasFinalPass() const CM_OVERRIDE { return true; }
diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h
index 420f472..58ad617 100644
--- a/Source/cmExportSet.h
+++ b/Source/cmExportSet.h
@@ -3,7 +3,7 @@
 #ifndef cmExportSet_h
 #define cmExportSet_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmExportSetMap.h b/Source/cmExportSetMap.h
index 5090692..0f71c79 100644
--- a/Source/cmExportSetMap.h
+++ b/Source/cmExportSetMap.h
@@ -3,7 +3,7 @@
 #ifndef cmExportSetMap_h
 #define cmExportSetMap_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <string>
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 88a70a1..9671fac 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExportTryCompileFileGenerator_h
 #define cmExportTryCompileFileGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExportFileGenerator.h"
 
diff --git a/Source/cmExprParser.cxx b/Source/cmExprParser.cxx
deleted file mode 100644
index d11d0b6..0000000
--- a/Source/cmExprParser.cxx
+++ /dev/null
@@ -1,1696 +0,0 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
-
-/* Bison implementation for Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "3.0.4"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 1
-
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
-
-/* Substitute the variable and function names.  */
-#define yyparse         cmExpr_yyparse
-#define yylex           cmExpr_yylex
-#define yyerror         cmExpr_yyerror
-#define yydebug         cmExpr_yydebug
-#define yynerrs         cmExpr_yynerrs
-
-
-/* Copy the first part of user declarations.  */
-#line 1 "cmExprParser.y" /* yacc.c:339  */
-
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
-  bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
-
-Modify cmExprParser.cxx:
-  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
-
-*/
-
-/*-------------------------------------------------------------------------*/
-#define YYDEBUG 1
-#include "cmExprParserHelper.h" /* Interface to parser object.  */
-#include "cmExprLexer.h"  /* Interface to lexer object.  */
-#include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
-
-#include <math.h>
-
-/* Forward declare the lexer entry point.  */
-YY_DECL;
-
-/* Helper function to forward error callback from parser.  */
-static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
-
-/* Disable some warnings in the generated code.  */
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label.  */
-# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
-#endif
-
-#line 109 "cmExprParser.cxx" /* yacc.c:339  */
-
-# ifndef YY_NULLPTR
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULLPTR nullptr
-#  else
-#   define YY_NULLPTR 0
-#  endif
-# endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 1
-#endif
-
-/* In a future release of Bison, this section will be replaced
-   by #include "cmExprParserTokens.h".  */
-#ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
-# define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
-/* Debug traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int cmExpr_yydebug;
-#endif
-
-/* Token type.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-  enum yytokentype
-  {
-    exp_PLUS = 258,
-    exp_MINUS = 259,
-    exp_TIMES = 260,
-    exp_DIVIDE = 261,
-    exp_MOD = 262,
-    exp_SHIFTLEFT = 263,
-    exp_SHIFTRIGHT = 264,
-    exp_OPENPARENT = 265,
-    exp_CLOSEPARENT = 266,
-    exp_OR = 267,
-    exp_AND = 268,
-    exp_XOR = 269,
-    exp_NOT = 270,
-    exp_NUMBER = 271
-  };
-#endif
-/* Tokens.  */
-#define exp_PLUS 258
-#define exp_MINUS 259
-#define exp_TIMES 260
-#define exp_DIVIDE 261
-#define exp_MOD 262
-#define exp_SHIFTLEFT 263
-#define exp_SHIFTRIGHT 264
-#define exp_OPENPARENT 265
-#define exp_CLOSEPARENT 266
-#define exp_OR 267
-#define exp_AND 268
-#define exp_XOR 269
-#define exp_NOT 270
-#define exp_NUMBER 271
-
-/* Value type.  */
-
-
-
-int cmExpr_yyparse (yyscan_t yyscanner);
-
-#endif /* !YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED  */
-
-/* Copy the second part of user declarations.  */
-
-#line 186 "cmExprParser.cxx" /* yacc.c:358  */
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#else
-typedef signed char yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(Msgid) Msgid
-# endif
-#endif
-
-#ifndef YY_ATTRIBUTE
-# if (defined __GNUC__                                               \
-      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
-     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
-#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
-# else
-#  define YY_ATTRIBUTE(Spec) /* empty */
-# endif
-#endif
-
-#ifndef YY_ATTRIBUTE_PURE
-# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
-#endif
-
-#ifndef YY_ATTRIBUTE_UNUSED
-# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
-#endif
-
-#if !defined _Noreturn \
-     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-#  define _Noreturn __declspec (noreturn)
-# else
-#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
-#else
-# define YYUSE(E) /* empty */
-#endif
-
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
-/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
-    _Pragma ("GCC diagnostic push") \
-    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
-    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
-    _Pragma ("GCC diagnostic pop")
-#else
-# define YY_INITIAL_VALUE(Value) Value
-#endif
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
-
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's 'empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
-       && ! ((defined YYMALLOC || defined malloc) \
-             && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef EXIT_SUCCESS
-#    define EXIT_SUCCESS 0
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss_alloc;
-  YYSTYPE yyvs_alloc;
-};
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-# define YYCOPY_NEEDED 1
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
-    do                                                                  \
-      {                                                                 \
-        YYSIZE_T yynewbytes;                                            \
-        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
-        Stack = &yyptr->Stack_alloc;                                    \
-        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-        yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                 \
-    while (0)
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(Dst, Src, Count) \
-      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
-#  else
-#   define YYCOPY(Dst, Src, Count)              \
-      do                                        \
-        {                                       \
-          YYSIZE_T yyi;                         \
-          for (yyi = 0; yyi < (Count); yyi++)   \
-            (Dst)[yyi] = (Src)[yyi];            \
-        }                                       \
-      while (0)
-#  endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  17
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   30
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  17
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  10
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  23
-/* YYNSTATES -- Number of states.  */
-#define YYNSTATES  39
-
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
-   by yylex, with out-of-bounds checking.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   271
-
-#define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
-   as returned by yylex, without out-of-bounds checking.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16
-};
-
-#if YYDEBUG
-  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
-static const yytype_uint8 yyrline[] =
-{
-       0,    70,    70,    75,    78,    83,    86,    91,    94,    99,
-     102,   105,   110,   113,   116,   121,   124,   127,   130,   135,
-     138,   141,   146,   149
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || 1
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "exp_PLUS", "exp_MINUS", "exp_TIMES",
-  "exp_DIVIDE", "exp_MOD", "exp_SHIFTLEFT", "exp_SHIFTRIGHT",
-  "exp_OPENPARENT", "exp_CLOSEPARENT", "exp_OR", "exp_AND", "exp_XOR",
-  "exp_NOT", "exp_NUMBER", "$accept", "start", "exp", "bitwiseor",
-  "bitwisexor", "bitwiseand", "shift", "term", "unary", "factor", YY_NULLPTR
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[NUM] -- (External) token number corresponding to the
-   (internal) symbol number NUM (which must be that of a token).  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271
-};
-# endif
-
-#define YYPACT_NINF -8
-
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-8)))
-
-#define YYTABLE_NINF -1
-
-#define yytable_value_is_error(Yytable_value) \
-  0
-
-  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-     STATE-NUM.  */
-static const yytype_int8 yypact[] =
-{
-       0,     0,     0,     0,    -8,     2,    -7,    -5,     8,     3,
-      10,     1,    -8,    -8,    -8,    -8,     6,    -8,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    -8,    -5,
-       8,     3,    10,    10,     1,     1,    -8,    -8,    -8
-};
-
-  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
-     Performed when YYTABLE does not specify something else to do.  Zero
-     means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       0,     0,     0,     0,    22,     0,     2,     3,     5,     7,
-       9,    12,    15,    19,    20,    21,     0,     1,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    23,     4,
-       6,     8,    10,    11,    13,    14,    16,    17,    18
-};
-
-  /* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] =
-{
-      -8,    -8,    12,     5,    11,     9,    -2,     4,    -1,    -8
-};
-
-  /* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
-{
-      -1,     5,     6,     7,     8,     9,    10,    11,    12,    13
-};
-
-  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
-     positive, shift that token.  If negative, reduce the rule whose
-     number is the opposite.  If YYTABLE_NINF, syntax error.  */
-static const yytype_uint8 yytable[] =
-{
-      14,    15,    17,     1,     2,    18,    25,    26,    27,    19,
-       3,    21,    22,    23,    24,    16,     4,    28,    18,    32,
-      33,    20,     0,    29,    36,    37,    38,    34,    35,    31,
-      30
-};
-
-static const yytype_int8 yycheck[] =
-{
-       1,     2,     0,     3,     4,    12,     5,     6,     7,    14,
-      10,     8,     9,     3,     4,     3,    16,    11,    12,    21,
-      22,    13,    -1,    18,    25,    26,    27,    23,    24,    20,
-      19
-};
-
-  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-     symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,     3,     4,    10,    16,    18,    19,    20,    21,    22,
-      23,    24,    25,    26,    25,    25,    19,     0,    12,    14,
-      13,     8,     9,     3,     4,     5,     6,     7,    11,    20,
-      21,    22,    23,    23,    24,    24,    25,    25,    25
-};
-
-  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    17,    18,    19,    19,    20,    20,    21,    21,    22,
-      22,    22,    23,    23,    23,    24,    24,    24,    24,    25,
-      25,    25,    26,    26
-};
-
-  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     1,     1,     3,     1,     3,     1,     3,     1,
-       3,     3,     1,     3,     3,     1,     3,     3,     3,     1,
-       2,     2,     1,     3
-};
-
-
-#define yyerrok         (yyerrstatus = 0)
-#define yyclearin       (yychar = YYEMPTY)
-#define YYEMPTY         (-2)
-#define YYEOF           0
-
-#define YYACCEPT        goto yyacceptlab
-#define YYABORT         goto yyabortlab
-#define YYERROR         goto yyerrorlab
-
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
-      YYERROR;                                                  \
-    }                                                           \
-while (0)
-
-/* Error token number */
-#define YYTERROR        1
-#define YYERRCODE       256
-
-
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                        \
-do {                                            \
-  if (yydebug)                                  \
-    YYFPRINTF Args;                             \
-} while (0)
-
-/* This macro is provided for backward compatibility. */
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
-
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
-do {                                                                      \
-  if (yydebug)                                                            \
-    {                                                                     \
-      YYFPRINTF (stderr, "%s ", Title);                                   \
-      yy_symbol_print (stderr,                                            \
-                  Type, Value, yyscanner); \
-      YYFPRINTF (stderr, "\n");                                           \
-    }                                                                     \
-} while (0)
-
-
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT.  |
-`----------------------------------------*/
-
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
-{
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
-  YYUSE (yyscanner);
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
-  YYUSE (yytype);
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
-{
-  YYFPRINTF (yyoutput, "%s %s (",
-             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; yybottom <= yytop; yybottom++)
-    {
-      int yybot = *yybottom;
-      YYFPRINTF (stderr, " %d", yybot);
-    }
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                            \
-do {                                                            \
-  if (yydebug)                                                  \
-    yy_stack_print ((Bottom), (Top));                           \
-} while (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
-{
-  unsigned long int yylno = yyrline[yyrule];
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-             yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr,
-                       yystos[yyssp[yyi + 1 - yynrhs]],
-                       &(yyvsp[(yyi + 1) - (yynrhs)])
-                                              , yyscanner);
-      YYFPRINTF (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)          \
-do {                                    \
-  if (yydebug)                          \
-    yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
-} while (0)
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-static YYSIZE_T
-yystrlen (const char *yystr)
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-        switch (*++yyp)
-          {
-          case '\'':
-          case ',':
-            goto do_not_strip_quotes;
-
-          case '\\':
-            if (*++yyp != '\\')
-              goto do_not_strip_quotes;
-            /* Fall through.  */
-          default:
-            if (yyres)
-              yyres[yyn] = *yyp;
-            yyn++;
-            break;
-
-          case '"':
-            if (yyres)
-              yyres[yyn] = '\0';
-            return yyn;
-          }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN for the state stack whose top is
-   YYSSP.
-
-   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
-   not large enough to hold the message.  In that case, also set
-   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
-{
-  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = YY_NULLPTR;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
-  int yycount = 0;
-
-  /* There are many possibilities here to consider:
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[*yyssp];
-      yyarg[yycount++] = yytname[yytoken];
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for
-             this state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
-
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytname[yyx];
-                {
-                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                    return 2;
-                  yysize = yysize1;
-                }
-              }
-        }
-    }
-
-  switch (yycount)
-    {
-# define YYCASE_(N, S)                      \
-      case N:                               \
-        yyformat = S;                       \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
-    }
-
-  {
-    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-      return 2;
-    yysize = yysize1;
-  }
-
-  if (*yymsg_alloc < yysize)
-    {
-      *yymsg_alloc = 2 * yysize;
-      if (! (yysize <= *yymsg_alloc
-             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
-        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
-      return 1;
-    }
-
-  /* Avoid sprintf, as that infringes on the user's name space.
-     Don't have undefined behavior even if the translation
-     produced a string with the wrong number of "%s"s.  */
-  {
-    char *yyp = *yymsg;
-    int yyi = 0;
-    while ((*yyp = *yyformat) != '\0')
-      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyformat += 2;
-        }
-      else
-        {
-          yyp++;
-          yyformat++;
-        }
-  }
-  return 0;
-}
-#endif /* YYERROR_VERBOSE */
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
-{
-  YYUSE (yyvaluep);
-  YYUSE (yyscanner);
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  YYUSE (yytype);
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-}
-
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-int
-yyparse (yyscan_t yyscanner)
-{
-/* The lookahead symbol.  */
-int yychar;
-
-
-/* The semantic value of the lookahead symbol.  */
-/* Default value used for initialization, for pacifying older GCCs
-   or non-GCC compilers.  */
-YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
-YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
-
-    /* Number of syntax errors so far.  */
-    int yynerrs;
-
-    int yystate;
-    /* Number of tokens to shift before error messages enabled.  */
-    int yyerrstatus;
-
-    /* The stacks and their tools:
-       'yyss': related to states.
-       'yyvs': related to semantic values.
-
-       Refer to the stacks through separate pointers, to allow yyoverflow
-       to reallocate them elsewhere.  */
-
-    /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
-
-    /* The semantic value stack.  */
-    YYSTYPE yyvsa[YYINITDEPTH];
-    YYSTYPE *yyvs;
-    YYSTYPE *yyvsp;
-
-    YYSIZE_T yystacksize;
-
-  int yyn;
-  int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  yyssp = yyss = yyssa;
-  yyvsp = yyvs = yyvsa;
-  yystacksize = YYINITDEPTH;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY; /* Cause a token to be read.  */
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-        /* Give user a chance to reallocate the stack.  Use copies of
-           these so that the &'s don't force the real ones into
-           memory.  */
-        YYSTYPE *yyvs1 = yyvs;
-        yytype_int16 *yyss1 = yyss;
-
-        /* Each stack pointer address is followed by the size of the
-           data in use in that stack, in bytes.  This used to be a
-           conditional around just the two extra args, but that might
-           be undefined if yyoverflow is a macro.  */
-        yyoverflow (YY_("memory exhausted"),
-                    &yyss1, yysize * sizeof (*yyssp),
-                    &yyvs1, yysize * sizeof (*yyvsp),
-                    &yystacksize);
-
-        yyss = yyss1;
-        yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-        goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-        yystacksize = YYMAXDEPTH;
-
-      {
-        yytype_int16 *yyss1 = yyss;
-        union yyalloc *yyptr =
-          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-        if (! yyptr)
-          goto yyexhaustedlab;
-        YYSTACK_RELOCATE (yyss_alloc, yyss);
-        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-#  undef YYSTACK_RELOCATE
-        if (yyss1 != yyssa)
-          YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-        YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  if (yystate == YYFINAL)
-    YYACCEPT;
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     lookahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to lookahead token.  */
-  yyn = yypact[yystate];
-  if (yypact_value_is_default (yyn))
-    goto yydefault;
-
-  /* Not known => get a lookahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = yylex (&yylval, yyscanner);
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yytable_value_is_error (yyn))
-        goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the lookahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token.  */
-  yychar = YYEMPTY;
-
-  yystate = yyn;
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     '$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 2:
-#line 70 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
-  }
-#line 1286 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 3:
-#line 75 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[0].Number);
-  }
-#line 1294 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 4:
-#line 78 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
-  }
-#line 1302 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 5:
-#line 83 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[0].Number);
-  }
-#line 1310 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 6:
-#line 86 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
-  }
-#line 1318 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 7:
-#line 91 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[0].Number);
-  }
-#line 1326 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 8:
-#line 94 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
-  }
-#line 1334 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 9:
-#line 99 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[0].Number);
-  }
-#line 1342 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 10:
-#line 102 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
-  }
-#line 1350 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 11:
-#line 105 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
-  }
-#line 1358 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 12:
-#line 110 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[0].Number);
-  }
-#line 1366 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 13:
-#line 113 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
-  }
-#line 1374 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 14:
-#line 116 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
-  }
-#line 1382 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 15:
-#line 121 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[0].Number);
-  }
-#line 1390 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 16:
-#line 124 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
-  }
-#line 1398 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 17:
-#line 127 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
-  }
-#line 1406 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 18:
-#line 130 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
-  }
-#line 1414 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 19:
-#line 135 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[0].Number);
-  }
-#line 1422 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 20:
-#line 138 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = + (yyvsp[0].Number);
-  }
-#line 1430 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 21:
-#line 141 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = - (yyvsp[0].Number);
-  }
-#line 1438 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 22:
-#line 146 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[0].Number);
-  }
-#line 1446 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 23:
-#line 149 "cmExprParser.y" /* yacc.c:1646  */
-    {
-    (yyval.Number) = (yyvsp[-1].Number);
-  }
-#line 1454 "cmExprParser.cxx" /* yacc.c:1646  */
-    break;
-
-
-#line 1458 "cmExprParser.cxx" /* yacc.c:1646  */
-      default: break;
-    }
-  /* User semantic actions sometimes alter yychar, and that requires
-     that yytoken be updated with the new translation.  We take the
-     approach of translating immediately before every use of yytoken.
-     One alternative is translating here after every semantic action,
-     but that translation would be missed if the semantic action invokes
-     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
-     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
-     incorrect destructor might then be invoked immediately.  In the
-     case of YYERROR or YYBACKUP, subsequent parser actions might lead
-     to an incorrect destructor call or verbose syntax error message
-     before the lookahead is translated.  */
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-  /* Now 'shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*--------------------------------------.
-| yyerrlab -- here on detecting error.  |
-`--------------------------------------*/
-yyerrlab:
-  /* Make sure we have latest lookahead translation.  See comments at
-     user semantic actions for why this is necessary.  */
-  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (yyscanner, YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
-                                        yyssp, yytoken)
-      {
-        char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status;
-        yysyntax_error_status = YYSYNTAX_ERROR;
-        if (yysyntax_error_status == 0)
-          yymsgp = yymsg;
-        else if (yysyntax_error_status == 1)
-          {
-            if (yymsg != yymsgbuf)
-              YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
-            if (!yymsg)
-              {
-                yymsg = yymsgbuf;
-                yymsg_alloc = sizeof yymsgbuf;
-                yysyntax_error_status = 2;
-              }
-            else
-              {
-                yysyntax_error_status = YYSYNTAX_ERROR;
-                yymsgp = yymsg;
-              }
-          }
-        yyerror (yyscanner, yymsgp);
-        if (yysyntax_error_status == 2)
-          goto yyexhaustedlab;
-      }
-# undef YYSYNTAX_ERROR
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse lookahead token after an
-         error, discard it.  */
-
-      if (yychar <= YYEOF)
-        {
-          /* Return failure if at end of input.  */
-          if (yychar == YYEOF)
-            YYABORT;
-        }
-      else
-        {
-          yydestruct ("Error: discarding",
-                      yytoken, &yylval, yyscanner);
-          yychar = YYEMPTY;
-        }
-    }
-
-#if 0
-  /* Else will try to reuse lookahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule whose action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-#endif
-  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (!yypact_value_is_default (yyn))
-        {
-          yyn += YYTERROR;
-          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-            {
-              yyn = yytable[yyn];
-              if (0 < yyn)
-                break;
-            }
-        }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-        YYABORT;
-
-
-      yydestruct ("Error: popping",
-                  yystos[yystate], yyvsp, yyscanner);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#if !defined yyoverflow || YYERROR_VERBOSE
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (yyscanner, YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEMPTY)
-    {
-      /* Make sure we have latest lookahead translation.  See comments at
-         user semantic actions for why this is necessary.  */
-      yytoken = YYTRANSLATE (yychar);
-      yydestruct ("Cleanup: discarding lookahead",
-                  yytoken, &yylval, yyscanner);
-    }
-  /* Do not reclaim the symbols of the rule whose action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                  yystos[*yyssp], yyvsp, yyscanner);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  return yyresult;
-}
-#line 154 "cmExprParser.y" /* yacc.c:1906  */
-
-/* End of grammar */
-
-/*--------------------------------------------------------------------------*/
-void cmExpr_yyerror(yyscan_t yyscanner, const char* message)
-{
-  cmExpr_yyget_extra(yyscanner)->Error(message);
-}
-
diff --git a/Source/cmExprParser.y b/Source/cmExprParser.y
deleted file mode 100644
index c7c4a7b..0000000
--- a/Source/cmExprParser.y
+++ /dev/null
@@ -1,162 +0,0 @@
-%{
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
-  bison --yacc --name-prefix=cmExpr_yy --defines=cmExprParserTokens.h -ocmExprParser.cxx cmExprParser.y
-
-Modify cmExprParser.cxx:
-  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
-
-*/
-
-/*-------------------------------------------------------------------------*/
-#define YYDEBUG 1
-#include "cmExprParserHelper.h" /* Interface to parser object.  */
-#include "cmExprLexer.h"  /* Interface to lexer object.  */
-#include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
-
-#include <math.h>
-
-/* Forward declare the lexer entry point.  */
-YY_DECL;
-
-/* Helper function to forward error callback from parser.  */
-static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
-
-/* Disable some warnings in the generated code.  */
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label.  */
-# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
-#endif
-%}
-
-/* Generate a reentrant parser object.  */
-%define api.pure
-
-/* Configure the parser to use a lexer object.  */
-%lex-param   {yyscan_t yyscanner}
-%parse-param {yyscan_t yyscanner}
-
-%define parse.error verbose
-
-/*-------------------------------------------------------------------------*/
-/* Tokens */
-%token exp_PLUS
-%token exp_MINUS
-%token exp_TIMES
-%token exp_DIVIDE
-%token exp_MOD
-%token exp_SHIFTLEFT
-%token exp_SHIFTRIGHT
-%token exp_OPENPARENT
-%token exp_CLOSEPARENT
-%token exp_OR;
-%token exp_AND;
-%token exp_XOR;
-%token exp_NOT;
-%token exp_NUMBER;
-
-/*-------------------------------------------------------------------------*/
-/* grammar */
-%%
-
-
-start:
-  exp {
-    cmExpr_yyget_extra(yyscanner)->SetResult($<Number>1);
-  }
-
-exp:
-  bitwiseor {
-    $<Number>$ = $<Number>1;
-  }
-| exp exp_OR bitwiseor {
-    $<Number>$ = $<Number>1 | $<Number>3;
-  }
-
-bitwiseor:
-  bitwisexor {
-    $<Number>$ = $<Number>1;
-  }
-| bitwiseor exp_XOR bitwisexor {
-    $<Number>$ = $<Number>1 ^ $<Number>3;
-  }
-
-bitwisexor:
-  bitwiseand {
-    $<Number>$ = $<Number>1;
-  }
-| bitwisexor exp_AND bitwiseand {
-    $<Number>$ = $<Number>1 & $<Number>3;
-  }
-
-bitwiseand:
-  shift {
-    $<Number>$ = $<Number>1;
-  }
-| bitwiseand exp_SHIFTLEFT shift {
-    $<Number>$ = $<Number>1 << $<Number>3;
-  }
-| bitwiseand exp_SHIFTRIGHT shift {
-    $<Number>$ = $<Number>1 >> $<Number>3;
-  }
-
-shift:
-  term {
-    $<Number>$ = $<Number>1;
-  }
-| shift exp_PLUS term {
-    $<Number>$ = $<Number>1 + $<Number>3;
-  }
-| shift exp_MINUS term {
-    $<Number>$ = $<Number>1 - $<Number>3;
-  }
-
-term:
-  unary {
-    $<Number>$ = $<Number>1;
-  }
-| term exp_TIMES unary {
-    $<Number>$ = $<Number>1 * $<Number>3;
-  }
-| term exp_DIVIDE unary {
-    $<Number>$ = $<Number>1 / $<Number>3;
-  }
-| term exp_MOD unary {
-    $<Number>$ = $<Number>1 % $<Number>3;
-  }
-
-unary:
-  factor {
-    $<Number>$ = $<Number>1;
-  }
-| exp_PLUS unary {
-    $<Number>$ = + $<Number>2;
-  }
-| exp_MINUS unary {
-    $<Number>$ = - $<Number>2;
-  }
-
-factor:
-  exp_NUMBER {
-    $<Number>$ = $<Number>1;
-  }
-| exp_OPENPARENT exp exp_CLOSEPARENT {
-    $<Number>$ = $<Number>2;
-  }
-;
-
-%%
-/* End of grammar */
-
-/*--------------------------------------------------------------------------*/
-void cmExpr_yyerror(yyscan_t yyscanner, const char* message)
-{
-  cmExpr_yyget_extra(yyscanner)->Error(message);
-}
-
diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx
index 1b49def..c3f026a 100644
--- a/Source/cmExprParserHelper.cxx
+++ b/Source/cmExprParserHelper.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExprParserHelper.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExprLexer.h"
 
diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h
index 8f00f1d..dcdaca9 100644
--- a/Source/cmExprParserHelper.h
+++ b/Source/cmExprParserHelper.h
@@ -3,28 +3,18 @@
 #ifndef cmExprParserHelper_h
 #define cmExprParserHelper_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
 
-#define YYSTYPE cmExprParserHelper::ParserType
-#define YYSTYPE_IS_DECLARED
-#define YY_EXTRA_TYPE cmExprParserHelper*
-#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
-
-/** \class cmExprParserHelper
- * \brief Helper class for parsing java source files
- *
- * Finds dependencies for java file and list of outputs
- */
 class cmExprParserHelper
 {
 public:
-  typedef struct
+  struct ParserType
   {
     int Number;
-  } ParserType;
+  };
 
   cmExprParserHelper();
   ~cmExprParserHelper();
@@ -57,4 +47,9 @@ private:
   std::string ErrorString;
 };
 
+#define YYSTYPE cmExprParserHelper::ParserType
+#define YYSTYPE_IS_DECLARED
+#define YY_EXTRA_TYPE cmExprParserHelper*
+#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner)
+
 #endif
diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h
index c49d39b..6b89037 100644
--- a/Source/cmExternalMakefileProjectGenerator.h
+++ b/Source/cmExternalMakefileProjectGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExternalMakefileProjectGenerator_h
 #define cmExternalMakefileProjectGenerator_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 2dffcaa..5b7b827 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -353,7 +353,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
   all_files_map_t allFiles;
   std::vector<std::string> cFiles;
 
-  std::vector<std::string> srcExts =
+  std::vector<std::string> const& srcExts =
     this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
 
   for (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
@@ -387,7 +387,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
             bool isCFile = false;
             std::string lang = (*si)->GetLanguage();
             if (lang == "C" || lang == "CXX") {
-              std::string srcext = (*si)->GetExtension();
+              std::string const& srcext = (*si)->GetExtension();
               for (std::vector<std::string>::const_iterator ext =
                      srcExts.begin();
                    ext != srcExts.end(); ++ext) {
@@ -398,7 +398,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
               }
             }
 
-            std::string fullPath = (*si)->GetFullPath();
+            std::string const& fullPath = (*si)->GetFullPath();
 
             if (isCFile) {
               cFiles.push_back(fullPath);
@@ -414,7 +414,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
     }
   }
 
-  std::vector<std::string> headerExts =
+  std::vector<std::string> const& headerExts =
     this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
 
   // The following loop tries to add header files matching to implementation
diff --git a/Source/cmExtraCodeBlocksGenerator.h b/Source/cmExtraCodeBlocksGenerator.h
index 06aadc4..450a9d0 100644
--- a/Source/cmExtraCodeBlocksGenerator.h
+++ b/Source/cmExtraCodeBlocksGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExtraCodeBlocksGenerator_h
 #define cmExtraCodeBlocksGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExternalMakefileProjectGenerator.h"
 
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index fd7da18..b478f34 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -13,7 +13,7 @@
 #include "cmXMLWriter.h"
 #include "cmake.h"
 
-#include <cmsys/SystemInformation.hxx>
+#include "cmsys/SystemInformation.hxx"
 #include <map>
 #include <set>
 #include <sstream>
@@ -141,6 +141,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
         case cmStateEnums::STATIC_LIBRARY:
         case cmStateEnums::MODULE_LIBRARY:
           visualname = "lib" + visualname;
+          CM_FALLTHROUGH;
         case cmStateEnums::EXECUTABLE:
           xml->StartElement("Project");
           xml->Attribute("Name", visualname);
@@ -240,7 +241,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
         bool isCFile = false;
         std::string lang = (*si)->GetLanguage();
         if (lang == "C" || lang == "CXX") {
-          std::string srcext = (*si)->GetExtension();
+          std::string const& srcext = (*si)->GetExtension();
           for (std::vector<std::string>::const_iterator ext = srcExts.begin();
                ext != srcExts.end(); ++ext) {
             if (srcext == *ext) {
@@ -349,6 +350,87 @@ void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles(
   }
 }
 
+void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
+  std::set<std::string>& cFiles, cmXMLWriter& xml,
+  const std::string& projectPath)
+{
+  std::vector<std::string> tmp_path;
+  std::vector<std::string> components;
+  size_t numOfEndEl = 0;
+
+  for (std::set<std::string>::const_iterator it = cFiles.begin();
+       it != cFiles.end(); ++it) {
+    std::string frelapath =
+      cmSystemTools::RelativePath(projectPath.c_str(), it->c_str());
+    cmsys::SystemTools::SplitPath(frelapath, components, false);
+    components.pop_back(); // erase last member -> it is file, not folder
+    components.erase(components.begin()); // erase "root"
+
+    size_t sizeOfSkip = 0;
+
+    for (size_t i = 0; i < components.size(); ++i) {
+      // skip relative path
+      if (components[i] == ".." || components[i] == ".") {
+        sizeOfSkip++;
+        continue;
+      }
+
+      // same folder
+      if (tmp_path.size() > i - sizeOfSkip &&
+          tmp_path[i - sizeOfSkip] == components[i]) {
+        continue;
+      }
+
+      // delete "old" subfolders
+      if (tmp_path.size() > i - sizeOfSkip) {
+        numOfEndEl = tmp_path.size() - i + sizeOfSkip;
+        tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end());
+        for (; numOfEndEl--;) {
+          xml.EndElement();
+        }
+      }
+
+      // add folder
+      xml.StartElement("VirtualDirectory");
+      xml.Attribute("Name", components[i]);
+      tmp_path.push_back(components[i]);
+    }
+
+    // delete "old" subfolders
+    numOfEndEl = tmp_path.size() - components.size() + sizeOfSkip;
+    if (numOfEndEl) {
+      tmp_path.erase(tmp_path.end() - numOfEndEl, tmp_path.end());
+      for (; numOfEndEl--;) {
+        xml.EndElement();
+      }
+    }
+
+    // add file
+    xml.StartElement("File");
+    xml.Attribute("Name", frelapath);
+    xml.EndElement();
+  }
+
+  // end of folders
+  numOfEndEl = tmp_path.size();
+  for (; numOfEndEl--;) {
+    xml.EndElement();
+  }
+}
+
+void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
+  std::map<std::string, cmSourceFile*>& cFiles, cmXMLWriter& xml,
+  const std::string& projectPath)
+{
+  std::set<std::string> s;
+  for (std::map<std::string, cmSourceFile*>::const_iterator it =
+         cFiles.begin();
+       it != cFiles.end(); ++it) {
+    s.insert(it->first);
+  }
+  this->CreateFoldersAndFiles(s, xml, projectPath);
+}
+
 void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
   std::map<std::string, cmSourceFile*>& cFiles,
   std::set<std::string>& otherFiles, cmXMLWriter* _xml,
@@ -366,26 +448,12 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
 
   // insert all source files in the codelite project
   // first the C/C++ implementation files, then all others
-  for (std::map<std::string, cmSourceFile*>::const_iterator sit =
-         cFiles.begin();
-       sit != cFiles.end(); ++sit) {
-    xml.StartElement("File");
-    std::string fpath(sit->first);
-    std::string frelapath =
-      cmSystemTools::RelativePath(projectPath.c_str(), sit->first.c_str());
-    xml.Attribute("Name", frelapath);
-    xml.EndElement();
-  }
+  this->CreateFoldersAndFiles(cFiles, xml, projectPath);
   xml.EndElement(); // VirtualDirectory
+
   xml.StartElement("VirtualDirectory");
   xml.Attribute("Name", "include");
-  for (std::set<std::string>::const_iterator sit = otherFiles.begin();
-       sit != otherFiles.end(); ++sit) {
-    xml.StartElement("File");
-    xml.Attribute(
-      "Name", cmSystemTools::RelativePath(projectPath.c_str(), sit->c_str()));
-    xml.EndElement();
-  }
+  this->CreateFoldersAndFiles(otherFiles, xml, projectPath);
   xml.EndElement(); // VirtualDirectory
 
   // Get the number of CPUs. We use this information for the make -jN
@@ -533,9 +601,6 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
   // which may have an acompanying header, one for all other files
   std::string projectType;
 
-  std::vector<std::string> headerExts =
-    this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
-
   std::map<std::string, cmSourceFile*> cFiles;
   std::set<std::string> otherFiles;
 
diff --git a/Source/cmExtraCodeLiteGenerator.h b/Source/cmExtraCodeLiteGenerator.h
index 773515d..de33098 100644
--- a/Source/cmExtraCodeLiteGenerator.h
+++ b/Source/cmExtraCodeLiteGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalCodeLiteGenerator_h
 #define cmGlobalCodeLiteGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExternalMakefileProjectGenerator.h"
 
@@ -50,6 +50,10 @@ protected:
                                   const cmMakefile* mf,
                                   const std::string& projectType,
                                   const std::string& targetName);
+  void CreateFoldersAndFiles(std::set<std::string>& cFiles, cmXMLWriter& xml,
+                             const std::string& projectPath);
+  void CreateFoldersAndFiles(std::map<std::string, cmSourceFile*>& cFiles,
+                             cmXMLWriter& xml, const std::string& projectPath);
 
 public:
   cmExtraCodeLiteGenerator();
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index b4fc771..2a6ce98 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExtraEclipseCDT4Generator.h"
 
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
-#include <cmsys/RegularExpression.hxx>
 #include <map>
 #include <sstream>
 #include <stdio.h>
@@ -453,7 +453,7 @@ void cmExtraEclipseCDT4Generator::WriteGroups(
     for (std::vector<const cmSourceFile*>::const_iterator fileIt =
            sFiles.begin();
          fileIt != sFiles.end(); ++fileIt) {
-      std::string fullPath = (*fileIt)->GetFullPath();
+      std::string const& fullPath = (*fileIt)->GetFullPath();
 
       if (!cmSystemTools::FileIsDirectory(fullPath)) {
         std::string linkName4 = linkName3;
@@ -508,7 +508,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml)
           for (std::vector<cmSourceFile*>::const_iterator sfIt = files.begin();
                sfIt != files.end(); sfIt++) {
             // Add the file to the list of sources.
-            std::string source = (*sfIt)->GetFullPath();
+            std::string const& source = (*sfIt)->GetFullPath();
             cmSourceGroup* sourceGroup =
               makefile->FindSourceGroup(source.c_str(), sourceGroups);
             sourceGroup->AssignSource(*sfIt);
diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h
index fe71172..1380d18 100644
--- a/Source/cmExtraEclipseCDT4Generator.h
+++ b/Source/cmExtraEclipseCDT4Generator.h
@@ -3,7 +3,7 @@
 #ifndef cmExtraEclipseCDT4Generator_h
 #define cmExtraEclipseCDT4Generator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExternalMakefileProjectGenerator.h"
 
diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h
index badaca9..6b9c7af 100644
--- a/Source/cmExtraKateGenerator.h
+++ b/Source/cmExtraKateGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExtraKateGenerator_h
 #define cmExtraKateGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExternalMakefileProjectGenerator.h"
 
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 36ba520..1fd1418 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExtraSublimeTextGenerator.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <set>
 #include <sstream>
 #include <string.h>
diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h
index a860d34..9022d37 100644
--- a/Source/cmExtraSublimeTextGenerator.h
+++ b/Source/cmExtraSublimeTextGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmExtraSublimeTextGenerator_h
 #define cmExtraSublimeTextGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExternalMakefileProjectGenerator.h"
 
diff --git a/Source/cmFLTKWrapUICommand.h b/Source/cmFLTKWrapUICommand.h
index 835f0a7..d8045ab 100644
--- a/Source/cmFLTKWrapUICommand.h
+++ b/Source/cmFLTKWrapUICommand.h
@@ -3,7 +3,8 @@
 #ifndef cmFLTKWrapUICommand_h
 #define cmFLTKWrapUICommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -42,11 +43,6 @@ public:
   void FinalPass() CM_OVERRIDE;
   bool HasFinalPass() const CM_OVERRIDE { return true; }
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "fltk_wrap_ui"; }
-
 private:
   /**
    * List of produced files.
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 91cecb3..5777fb2 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -2,23 +2,19 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFileCommand.h"
 
+#include "cm_kwiml.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include "cmsys/String.hxx"
 #include <algorithm>
 #include <assert.h>
-#include <cm_kwiml.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/String.hxx>
-#include <list>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-
-#include <sys/types.h>
-// include sys/stat.h after sys/types.h
-#include <sys/stat.h>
+#include <vector>
 
 #include "cmAlgorithms.h"
 #include "cmCommandArgumentsHelper.h"
@@ -35,11 +31,21 @@
 #include "cmSystemTools.h"
 #include "cmTimestamp.h"
 #include "cm_auto_ptr.hxx"
+#include "cm_sys_stat.h"
 #include "cmake.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmCurl.h"
 #include "cmFileLockResult.h"
+#include "cm_curl.h"
+#endif
+
+#if defined(CMAKE_USE_ELF_PARSER)
+#include "cmELF.h"
+#endif
+
+#if defined(_WIN32)
+#include <windows.h>
 #endif
 
 class cmSystemToolsFileTime;
@@ -104,7 +110,7 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
     this->SetError("must be called with at least two arguments.");
     return false;
   }
-  std::string subCommand = args[0];
+  std::string const& subCommand = args[0];
   if (subCommand == "WRITE") {
     return this->HandleWriteCommand(args, false);
   }
@@ -166,6 +172,9 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
   if (subCommand == "RPATH_REMOVE") {
     return this->HandleRPathRemoveCommand(args);
   }
+  if (subCommand == "READ_ELF") {
+    return this->HandleReadElfCommand(args);
+  }
   if (subCommand == "RELATIVE_PATH") {
     return this->HandleRelativePathCommand(args);
   }
@@ -608,8 +617,8 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
       continue;
     }
 
-    else if ((c >= 0x20 && c < 0x7F) || c == '\t' ||
-             (c == '\n' && newline_consume)) {
+    if ((c >= 0x20 && c < 0x7F) || c == '\t' ||
+        (c == '\n' && newline_consume)) {
       // This is an ASCII character that may be part of a string.
       // Cast added to avoid compiler warning. Cast is ok because
       // c is guaranteed to fit in char by the above if...
@@ -1024,8 +1033,6 @@ protected:
     {
     }
   };
-  struct MatchRule;
-  friend struct MatchRule;
   struct MatchRule
   {
     cmsys::RegularExpression Regex;
@@ -1114,9 +1121,9 @@ protected:
 
   bool InstallSymlink(const char* fromFile, const char* toFile);
   bool InstallFile(const char* fromFile, const char* toFile,
-                   MatchProperties const& match_properties);
+                   MatchProperties match_properties);
   bool InstallDirectory(const char* source, const char* destination,
-                        MatchProperties const& match_properties);
+                        MatchProperties match_properties);
   virtual bool Install(const char* fromFile, const char* toFile);
   virtual std::string const& ToName(std::string const& fromName)
   {
@@ -1144,6 +1151,7 @@ protected:
   bool UseGivenPermissionsDir;
   bool UseSourcePermissions;
   std::string Destination;
+  std::string FilesFromDir;
   std::vector<std::string> Files;
   int Doing;
 
@@ -1153,6 +1161,7 @@ protected:
     DoingNone,
     DoingError,
     DoingDestination,
+    DoingFilesFromDir,
     DoingFiles,
     DoingPattern,
     DoingRegex,
@@ -1248,6 +1257,12 @@ bool cmFileCopier::CheckKeyword(std::string const& arg)
     } else {
       this->Doing = DoingDestination;
     }
+  } else if (arg == "FILES_FROM_DIR") {
+    if (this->CurrentMatchRule) {
+      this->NotAfterMatch(arg);
+    } else {
+      this->Doing = DoingFilesFromDir;
+    }
   } else if (arg == "PATTERN") {
     this->Doing = DoingPattern;
   } else if (arg == "REGEX") {
@@ -1311,13 +1326,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
 {
   switch (this->Doing) {
     case DoingFiles:
-      if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) {
-        this->Files.push_back(arg);
-      } else {
-        std::string file = this->Makefile->GetCurrentSourceDirectory();
-        file += "/" + arg;
-        this->Files.push_back(file);
-      }
+      this->Files.push_back(arg);
       break;
     case DoingDestination:
       if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) {
@@ -1328,6 +1337,16 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       }
       this->Doing = DoingNone;
       break;
+    case DoingFilesFromDir:
+      if (cmSystemTools::FileIsFullPath(arg.c_str())) {
+        this->FilesFromDir = arg;
+      } else {
+        this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory();
+        this->FilesFromDir += "/" + arg;
+      }
+      cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir);
+      this->Doing = DoingNone;
+      break;
     case DoingPattern: {
       // Convert the pattern to a regular expression.  Require a
       // leading slash and trailing end-of-string in the matched
@@ -1387,17 +1406,41 @@ bool cmFileCopier::Run(std::vector<std::string> const& args)
     return false;
   }
 
-  std::vector<std::string> const& files = this->Files;
-  for (std::vector<std::string>::size_type i = 0; i < files.size(); ++i) {
+  for (std::vector<std::string>::const_iterator i = this->Files.begin();
+       i != this->Files.end(); ++i) {
+    std::string file;
+    if (!i->empty() && !cmSystemTools::FileIsFullPath(*i)) {
+      if (!this->FilesFromDir.empty()) {
+        file = this->FilesFromDir;
+      } else {
+        file = this->Makefile->GetCurrentSourceDirectory();
+      }
+      file += "/";
+      file += *i;
+    } else if (!this->FilesFromDir.empty()) {
+      this->FileCommand->SetError("option FILES_FROM_DIR requires all files "
+                                  "to be specified as relative paths.");
+      return false;
+    } else {
+      file = *i;
+    }
+
     // Split the input file into its directory and name components.
     std::vector<std::string> fromPathComponents;
-    cmSystemTools::SplitPath(files[i], fromPathComponents);
+    cmSystemTools::SplitPath(file, fromPathComponents);
     std::string fromName = *(fromPathComponents.end() - 1);
     std::string fromDir = cmSystemTools::JoinPath(
       fromPathComponents.begin(), fromPathComponents.end() - 1);
 
     // Compute the full path to the destination file.
     std::string toFile = this->Destination;
+    if (!this->FilesFromDir.empty()) {
+      std::string dir = cmSystemTools::GetFilenamePath(*i);
+      if (!dir.empty()) {
+        toFile += "/";
+        toFile += dir;
+      }
+    }
     std::string const& toName = this->ToName(fromName);
     if (!toName.empty()) {
       toFile += "/";
@@ -1482,6 +1525,9 @@ bool cmFileCopier::InstallSymlink(const char* fromFile, const char* toFile)
     // 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(symlinkTarget, toFile)) {
       std::ostringstream e;
@@ -1496,7 +1542,7 @@ bool cmFileCopier::InstallSymlink(const char* fromFile, const char* toFile)
 }
 
 bool cmFileCopier::InstallFile(const char* fromFile, const char* toFile,
-                               MatchProperties const& match_properties)
+                               MatchProperties match_properties)
 {
   // Determine whether we will copy the file.
   bool copy = true;
@@ -1550,7 +1596,7 @@ bool cmFileCopier::InstallFile(const char* fromFile, const char* toFile,
 
 bool cmFileCopier::InstallDirectory(const char* source,
                                     const char* destination,
-                                    MatchProperties const& match_properties)
+                                    MatchProperties match_properties)
 {
   // Inform the user about this directory installation.
   this->ReportCopy(destination, TypeDir,
@@ -1724,6 +1770,7 @@ protected:
         if (this->Makefile->IsOn("CMAKE_INSTALL_SO_NO_EXE")) {
           break;
         }
+        CM_FALLTHROUGH;
       case cmInstallType_EXECUTABLE:
       case cmInstallType_PROGRAMS:
         this->FilePermissions |= mode_owner_execute;
@@ -1745,6 +1792,11 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args)
   }
 
   if (!this->Rename.empty()) {
+    if (!this->FilesFromDir.empty()) {
+      this->FileCommand->SetError("INSTALL option RENAME may not be "
+                                  "combined with FILES_FROM_DIR.");
+      return false;
+    }
     if (this->InstallType != cmInstallType_FILES &&
         this->InstallType != cmInstallType_PROGRAMS) {
       this->FileCommand->SetError("INSTALL option RENAME may be used "
@@ -2177,6 +2229,68 @@ bool cmFileCommand::HandleRPathCheckCommand(
   return true;
 }
 
+bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args)
+{
+  if (args.size() < 4) {
+    this->SetError("READ_ELF must be called with at least three additional "
+                   "arguments.");
+    return false;
+  }
+
+  cmCommandArgumentsHelper argHelper;
+  cmCommandArgumentGroup group;
+
+  cmCAString readArg(&argHelper, "READ_ELF");
+  cmCAString fileNameArg(&argHelper, CM_NULLPTR);
+
+  cmCAString rpathArg(&argHelper, "RPATH", &group);
+  cmCAString runpathArg(&argHelper, "RUNPATH", &group);
+  cmCAString errorArg(&argHelper, "CAPTURE_ERROR", &group);
+
+  readArg.Follows(CM_NULLPTR);
+  fileNameArg.Follows(&readArg);
+  group.Follows(&fileNameArg);
+  argHelper.Parse(&args, CM_NULLPTR);
+
+  if (!cmSystemTools::FileExists(fileNameArg.GetString(), true)) {
+    std::ostringstream e;
+    e << "READ_ELF given FILE \"" << fileNameArg.GetString()
+      << "\" that does not exist.";
+    this->SetError(e.str());
+    return false;
+  }
+
+#if defined(CMAKE_USE_ELF_PARSER)
+  cmELF elf(fileNameArg.GetCString());
+
+  if (!rpathArg.GetString().empty()) {
+    if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
+      std::string rpath(se_rpath->Value);
+      std::replace(rpath.begin(), rpath.end(), ':', ';');
+      this->Makefile->AddDefinition(rpathArg.GetString(), rpath.c_str());
+    }
+  }
+  if (!runpathArg.GetString().empty()) {
+    if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) {
+      std::string runpath(se_runpath->Value);
+      std::replace(runpath.begin(), runpath.end(), ':', ';');
+      this->Makefile->AddDefinition(runpathArg.GetString(), runpath.c_str());
+    }
+  }
+
+  return true;
+#else
+  std::string error = "ELF parser not available on this platform.";
+  if (errorArg.GetString().empty()) {
+    this->SetError(error);
+    return false;
+  } else {
+    this->Makefile->AddDefinition(errorArg.GetString(), error.c_str());
+    return true;
+  }
+#endif
+}
+
 bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args)
 {
   cmFileInstaller installer(this);
@@ -2509,7 +2623,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
   bool showProgress = false;
   std::string userpwd;
 
-  std::list<std::string> curl_headers;
+  std::vector<std::string> curl_headers;
 
   while (i != args.end()) {
     if (*i == "TIMEOUT") {
@@ -2753,7 +2867,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
   }
 
   struct curl_slist* headers = CM_NULLPTR;
-  for (std::list<std::string>::const_iterator h = curl_headers.begin();
+  for (std::vector<std::string>::const_iterator h = curl_headers.begin();
        h != curl_headers.end(); ++h) {
     headers = ::curl_slist_append(headers, h->c_str());
   }
@@ -2843,7 +2957,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
   bool showProgress = false;
   std::string userpwd;
 
-  std::list<std::string> curl_headers;
+  std::vector<std::string> curl_headers;
 
   while (i != args.end()) {
     if (*i == "TIMEOUT") {
@@ -3011,7 +3125,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
   }
 
   struct curl_slist* headers = CM_NULLPTR;
-  for (std::list<std::string>::const_iterator h = curl_headers.begin();
+  for (std::vector<std::string>::const_iterator h = curl_headers.begin();
        h != curl_headers.end(); ++h) {
     headers = ::curl_slist_append(headers, h->c_str());
   }
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 319864c..d09ef42 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmFileCommand_h
 #define cmFileCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "file"; }
-
 protected:
   bool HandleRename(std::vector<std::string> const& args);
   bool HandleRemove(std::vector<std::string> const& args, bool recurse);
@@ -53,6 +44,7 @@ protected:
   bool HandleRelativePathCommand(std::vector<std::string> const& args);
   bool HandleCMakePathCommand(std::vector<std::string> const& args,
                               bool nativePath);
+  bool HandleReadElfCommand(std::vector<std::string> const& args);
   bool HandleRPathChangeCommand(std::vector<std::string> const& args);
   bool HandleRPathCheckCommand(std::vector<std::string> const& args);
   bool HandleRPathRemoveCommand(std::vector<std::string> const& args);
diff --git a/Source/cmFileLock.h b/Source/cmFileLock.h
index ab3cb1f..ccef508 100644
--- a/Source/cmFileLock.h
+++ b/Source/cmFileLock.h
@@ -3,7 +3,7 @@
 #ifndef cmFileLock_h
 #define cmFileLock_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include <string>
 
@@ -21,6 +21,8 @@ class cmFileLockResult;
   */
 class cmFileLock
 {
+  CM_DISABLE_COPY(cmFileLock)
+
 public:
   cmFileLock();
   ~cmFileLock();
@@ -44,9 +46,6 @@ public:
   bool IsLocked(const std::string& filename) const;
 
 private:
-  cmFileLock(const cmFileLock&);
-  cmFileLock& operator=(const cmFileLock&);
-
   cmFileLockResult OpenFile();
   cmFileLockResult LockWithoutTimeout();
   cmFileLockResult LockWithTimeout(unsigned long timeoutSec);
diff --git a/Source/cmFileLockPool.h b/Source/cmFileLockPool.h
index fbe01c8..c96a8c2 100644
--- a/Source/cmFileLockPool.h
+++ b/Source/cmFileLockPool.h
@@ -3,16 +3,18 @@
 #ifndef cmFileLockPool_h
 #define cmFileLockPool_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
-#include <list>
 #include <string>
+#include <vector>
 
 class cmFileLock;
 class cmFileLockResult;
 
 class cmFileLockPool
 {
+  CM_DISABLE_COPY(cmFileLockPool)
+
 public:
   cmFileLockPool();
   ~cmFileLockPool();
@@ -52,13 +54,12 @@ public:
   cmFileLockResult Release(const std::string& filename);
 
 private:
-  cmFileLockPool(const cmFileLockPool&);
-  cmFileLockPool& operator=(const cmFileLockPool&);
-
   bool IsAlreadyLocked(const std::string& filename) const;
 
   class ScopePool
   {
+    CM_DISABLE_COPY(ScopePool)
+
   public:
     ScopePool();
     ~ScopePool();
@@ -69,17 +70,14 @@ private:
     bool IsAlreadyLocked(const std::string& filename) const;
 
   private:
-    ScopePool(const ScopePool&);
-    ScopePool& operator=(const ScopePool&);
-
-    typedef std::list<cmFileLock*> List;
+    typedef std::vector<cmFileLock*> List;
     typedef List::iterator It;
     typedef List::const_iterator CIt;
 
     List Locks;
   };
 
-  typedef std::list<ScopePool*> List;
+  typedef std::vector<ScopePool*> List;
 
   typedef List::iterator It;
   typedef List::const_iterator CIt;
diff --git a/Source/cmFileLockResult.h b/Source/cmFileLockResult.h
index 679432a..4cedc0a 100644
--- a/Source/cmFileLockResult.h
+++ b/Source/cmFileLockResult.h
@@ -3,7 +3,7 @@
 #ifndef cmFileLockResult_h
 #define cmFileLockResult_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx
index 909be78..8027535 100644
--- a/Source/cmFileMonitor.cxx
+++ b/Source/cmFileMonitor.cxx
@@ -2,12 +2,13 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFileMonitor.h"
 
-#include <cmsys/SystemTools.hxx>
+#include "cmAlgorithms.h"
+#include "cmsys/SystemTools.hxx"
 
 #include <cassert>
-#include <iostream>
-#include <set>
+#include <stddef.h>
 #include <unordered_map>
+#include <utility>
 
 namespace {
 void on_directory_change(uv_fs_event_t* handle, const char* filename,
@@ -36,12 +37,7 @@ public:
 class cmVirtualDirectoryWatcher : public cmIBaseWatcher
 {
 public:
-  ~cmVirtualDirectoryWatcher() override
-  {
-    for (auto i : this->Children) {
-      delete i.second;
-    }
-  }
+  ~cmVirtualDirectoryWatcher() override { cmDeleteAll(this->Children); }
 
   cmIBaseWatcher* Find(const std::string& ps)
   {
@@ -102,9 +98,7 @@ public:
 
   void Reset()
   {
-    for (auto c : this->Children) {
-      delete c.second;
-    }
+    cmDeleteAll(this->Children);
     this->Children.clear();
   }
 
@@ -236,7 +230,7 @@ public:
                 cmFileMonitor::Callback cb)
     : Parent(p)
     , PathSegment(ps)
-    , CbList({ cb })
+    , CbList({ std::move(cb) })
   {
     assert(p);
     assert(!ps.empty());
diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h
index 48169b8..d7ec92a 100644
--- a/Source/cmFileMonitor.h
+++ b/Source/cmFileMonitor.h
@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #pragma once
 
+#include "cmConfigure.h"
+
 #include <functional>
 #include <string>
 #include <vector>
@@ -12,6 +14,8 @@ class cmRootWatcher;
 
 class cmFileMonitor
 {
+  CM_DISABLE_COPY(cmFileMonitor)
+
 public:
   cmFileMonitor(uv_loop_t* l);
   ~cmFileMonitor();
diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx
index 3d8b695..62f52e5 100644
--- a/Source/cmFilePathChecksum.cxx
+++ b/Source/cmFilePathChecksum.cxx
@@ -45,7 +45,7 @@ void cmFilePathChecksum::setupParentDirs(const std::string& currentSrcDir,
   parentDirs[3].second = "ProjectBinary";
 }
 
-std::string cmFilePathChecksum::get(const std::string& filePath)
+std::string cmFilePathChecksum::get(const std::string& filePath) const
 {
   std::string relPath;
   std::string relSeed;
@@ -82,7 +82,7 @@ std::string cmFilePathChecksum::get(const std::string& filePath)
 }
 
 std::string cmFilePathChecksum::getPart(const std::string& filePath,
-                                        size_t length)
+                                        size_t length) const
 {
   return get(filePath).substr(0, length);
 }
diff --git a/Source/cmFilePathChecksum.h b/Source/cmFilePathChecksum.h
index df19053..9d570eb 100644
--- a/Source/cmFilePathChecksum.h
+++ b/Source/cmFilePathChecksum.h
@@ -3,7 +3,7 @@
 #ifndef cmFilePathChecksum_h
 #define cmFilePathChecksum_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <stddef.h>
 #include <string>
@@ -47,13 +47,13 @@ public:
   /* @brief Calculates the path checksum for the parent directory of a file
    *
    */
-  std::string get(const std::string& filePath);
+  std::string get(const std::string& filePath) const;
 
   /* @brief Same as get() but returns only the first length characters
    *
    */
   std::string getPart(const std::string& filePath,
-                      size_t length = partLengthDefault);
+                      size_t length = partLengthDefault) const;
 
 private:
   /// Size of the parent directory list
diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx
index 991ebb8..f591a8d 100644
--- a/Source/cmFileTimeComparison.cxx
+++ b/Source/cmFileTimeComparison.cxx
@@ -10,10 +10,10 @@
 
 // Use a platform-specific API to get file times efficiently.
 #if !defined(_WIN32) || defined(__CYGWIN__)
-#include <sys/stat.h>
+#include "cm_sys_stat.h"
 #define cmFileTimeComparison_Type struct stat
 #else
-#include <cmsys/Encoding.hxx>
+#include "cmsys/Encoding.hxx"
 #include <windows.h>
 #define cmFileTimeComparison_Type FILETIME
 #endif
diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h
index 6eb1500..b1f8ed6 100644
--- a/Source/cmFileTimeComparison.h
+++ b/Source/cmFileTimeComparison.h
@@ -3,7 +3,7 @@
 #ifndef cmFileTimeComparison_h
 #define cmFileTimeComparison_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 class cmFileTimeComparisonInternal;
 
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index dce5021..e378208 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -2,8 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFindBase.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+#include <deque>
 #include <iostream>
+#include <iterator>
 #include <map>
 #include <stddef.h>
 
@@ -158,6 +160,9 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
 void cmFindBase::ExpandPaths()
 {
   if (!this->NoDefaultPath) {
+    if (!this->NoPackageRootPath) {
+      this->FillPackageRootPath();
+    }
     if (!this->NoCMakePath) {
       this->FillCMakeVariablePath();
     }
@@ -196,6 +201,25 @@ void cmFindBase::FillCMakeEnvironmentPath()
   paths.AddSuffixes(this->SearchPathSuffixes);
 }
 
+void cmFindBase::FillPackageRootPath()
+{
+  cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
+
+  // Add package specific search prefixes
+  // NOTE: This should be using const_reverse_iterator but HP aCC and
+  //       Oracle sunCC both currently have standard library issues
+  //       with the reverse iterator APIs.
+  for (std::deque<std::string>::reverse_iterator pkg =
+         this->Makefile->FindPackageModuleStack.rbegin();
+       pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) {
+    std::string varName = *pkg + "_ROOT";
+    paths.AddCMakePrefixPath(varName);
+    paths.AddEnvPrefixPath(varName);
+  }
+
+  paths.AddSuffixes(this->SearchPathSuffixes);
+}
+
 void cmFindBase::FillCMakeVariablePath()
 {
   cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake];
diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h
index 423d453..88b5b6c 100644
--- a/Source/cmFindBase.h
+++ b/Source/cmFindBase.h
@@ -3,7 +3,7 @@
 #ifndef cmFindBase_h
 #define cmFindBase_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
@@ -50,6 +50,7 @@ protected:
 
 private:
   // Add pieces of the search.
+  void FillPackageRootPath();
   void FillCMakeVariablePath();
   void FillCMakeEnvironmentPath();
   void FillUserHintsPath();
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 110195c..fd0e317 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -10,6 +10,8 @@
 #include "cmSystemTools.h"
 
 cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL");
+cmFindCommon::PathLabel cmFindCommon::PathLabel::PackageRoot(
+  "PackageName_ROOT");
 cmFindCommon::PathLabel cmFindCommon::PathLabel::CMake("CMAKE");
 cmFindCommon::PathLabel cmFindCommon::PathLabel::CMakeEnvironment(
   "CMAKE_ENVIRONMENT");
@@ -23,6 +25,7 @@ cmFindCommon::cmFindCommon()
 {
   this->FindRootPathMode = RootPathModeBoth;
   this->NoDefaultPath = false;
+  this->NoPackageRootPath = false;
   this->NoCMakePath = false;
   this->NoCMakeEnvironmentPath = false;
   this->NoSystemEnvironmentPath = false;
@@ -57,6 +60,7 @@ void cmFindCommon::InitializeSearchPathGroups()
 
   // All search paths
   labels = &this->PathGroupLabelMap[PathGroup::All];
+  labels->push_back(PathLabel::PackageRoot);
   labels->push_back(PathLabel::CMake);
   labels->push_back(PathLabel::CMakeEnvironment);
   labels->push_back(PathLabel::Hints);
@@ -69,6 +73,8 @@ void cmFindCommon::InitializeSearchPathGroups()
 
   // Create the idividual labeld search paths
   this->LabeledPaths.insert(
+    std::make_pair(PathLabel::PackageRoot, cmSearchPath(this)));
+  this->LabeledPaths.insert(
     std::make_pair(PathLabel::CMake, cmSearchPath(this)));
   this->LabeledPaths.insert(
     std::make_pair(PathLabel::CMakeEnvironment, cmSearchPath(this)));
@@ -154,10 +160,16 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
   }
 
   const char* sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT");
+  const char* sysrootCompile =
+    this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE");
+  const char* sysrootLink =
+    this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK");
   const char* rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
   const bool noSysroot = !sysroot || !*sysroot;
+  const bool noCompileSysroot = !sysrootCompile || !*sysrootCompile;
+  const bool noLinkSysroot = !sysrootLink || !*sysrootLink;
   const bool noRootPath = !rootPath || !*rootPath;
-  if (noSysroot && noRootPath) {
+  if (noSysroot && noCompileSysroot && noLinkSysroot && noRootPath) {
     return;
   }
 
@@ -166,6 +178,12 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
   if (rootPath) {
     cmSystemTools::ExpandListArgument(rootPath, roots);
   }
+  if (sysrootCompile) {
+    roots.push_back(sysrootCompile);
+  }
+  if (sysrootLink) {
+    roots.push_back(sysrootLink);
+  }
   if (sysroot) {
     roots.push_back(sysroot);
   }
@@ -213,18 +231,6 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
   }
 }
 
-void cmFindCommon::FilterPaths(const std::vector<std::string>& inPaths,
-                               const std::set<std::string>& ignore,
-                               std::vector<std::string>& outPaths)
-{
-  for (std::vector<std::string>::const_iterator i = inPaths.begin();
-       i != inPaths.end(); ++i) {
-    if (ignore.count(*i) == 0) {
-      outPaths.push_back(*i);
-    }
-  }
-}
-
 void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore)
 {
   // null-terminated list of paths.
@@ -259,10 +265,12 @@ bool cmFindCommon::CheckCommonArgument(std::string const& arg)
 {
   if (arg == "NO_DEFAULT_PATH") {
     this->NoDefaultPath = true;
-  } else if (arg == "NO_CMAKE_ENVIRONMENT_PATH") {
-    this->NoCMakeEnvironmentPath = true;
+  } else if (arg == "NO_PACKAGE_ROOT_PATH") {
+    this->NoPackageRootPath = true;
   } else if (arg == "NO_CMAKE_PATH") {
     this->NoCMakePath = true;
+  } else if (arg == "NO_CMAKE_ENVIRONMENT_PATH") {
+    this->NoCMakeEnvironmentPath = true;
   } else if (arg == "NO_SYSTEM_ENVIRONMENT_PATH") {
     this->NoSystemEnvironmentPath = true;
   } else if (arg == "NO_CMAKE_SYSTEM_PATH") {
@@ -291,7 +299,7 @@ void cmFindCommon::AddPathSuffix(std::string const& arg)
     return;
   }
   if (suffix[0] == '/') {
-    suffix = suffix.substr(1, suffix.npos);
+    suffix = suffix.substr(1);
   }
   if (suffix.empty()) {
     return;
@@ -334,15 +342,3 @@ void cmFindCommon::ComputeFinalPaths()
   std::for_each(this->SearchPaths.begin(), this->SearchPaths.end(),
                 &AddTrailingSlash);
 }
-
-void cmFindCommon::SetMakefile(cmMakefile* makefile)
-{
-  cmCommand::SetMakefile(makefile);
-
-  // If we are building for Apple (OSX or also iphone), make sure
-  // that frameworks and bundles are searched first.
-  if (this->Makefile->IsOn("APPLE")) {
-    this->SearchFrameworkFirst = true;
-    this->SearchAppBundleFirst = true;
-  }
-}
diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h
index 4d6d569..7954267 100644
--- a/Source/cmFindCommon.h
+++ b/Source/cmFindCommon.h
@@ -3,7 +3,7 @@
 #ifndef cmFindCommon_h
 #define cmFindCommon_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <map>
 #include <set>
@@ -14,8 +14,6 @@
 #include "cmPathLabel.h"
 #include "cmSearchPath.h"
 
-class cmMakefile;
-
 /** \class cmFindCommon
  * \brief Base class for FIND_XXX implementations.
  *
@@ -57,6 +55,7 @@ protected:
       : cmPathLabel(label)
     {
     }
+    static PathLabel PackageRoot;
     static PathLabel CMake;
     static PathLabel CMakeEnvironment;
     static PathLabel Hints;
@@ -82,11 +81,6 @@ protected:
   void GetIgnoredPaths(std::vector<std::string>& ignore);
   void GetIgnoredPaths(std::set<std::string>& ignore);
 
-  /** Remove paths in the ignore set from the supplied vector.  */
-  void FilterPaths(const std::vector<std::string>& inPaths,
-                   const std::set<std::string>& ignore,
-                   std::vector<std::string>& outPaths);
-
   /** Compute final search path list (reroot + trailing slash).  */
   void ComputeFinalPaths();
 
@@ -105,9 +99,9 @@ protected:
 
   bool CheckCommonArgument(std::string const& arg);
   void AddPathSuffix(std::string const& arg);
-  void SetMakefile(cmMakefile* makefile);
 
   bool NoDefaultPath;
+  bool NoPackageRootPath;
   bool NoCMakePath;
   bool NoCMakeEnvironmentPath;
   bool NoSystemEnvironmentPath;
diff --git a/Source/cmFindFileCommand.h b/Source/cmFindFileCommand.h
index 5c94ebf..bf57fec 100644
--- a/Source/cmFindFileCommand.h
+++ b/Source/cmFindFileCommand.h
@@ -3,8 +3,7 @@
 #ifndef cmFindFileCommand_h
 #define cmFindFileCommand_h
 
-#include <cmConfigure.h>
-#include <string>
+#include "cmConfigure.h"
 
 #include "cmFindPathCommand.h"
 
@@ -26,7 +25,6 @@ public:
    * This is a virtual constructor for the command.
    */
   cmCommand* Clone() CM_OVERRIDE { return new cmFindFileCommand; }
-  std::string GetName() const CM_OVERRIDE { return "find_file"; }
 };
 
 #endif
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index c86f9c1..a6b1a21 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFindLibraryCommand.h"
 
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
-#include <cmsys/RegularExpression.hxx>
 #include <set>
 #include <stdio.h>
 #include <string.h>
@@ -43,20 +43,29 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn,
     return true;
   }
 
-  if (this->Makefile->GetState()->GetGlobalPropertyAsBool(
-        "FIND_LIBRARY_USE_LIB32_PATHS")) {
-    // add special 32 bit paths if this is a 32 bit compile.
-    if (this->Makefile->PlatformIs32Bit()) {
-      this->AddArchitecturePaths("32");
-    }
+  // add custom lib<qual> paths instead of using fixed lib32, lib64 or
+  // libx32
+  if (const char* customLib = this->Makefile->GetDefinition(
+        "CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX")) {
+    this->AddArchitecturePaths(customLib);
   }
-
-  if (this->Makefile->GetState()->GetGlobalPropertyAsBool(
-        "FIND_LIBRARY_USE_LIB64_PATHS")) {
-    // add special 64 bit paths if this is a 64 bit compile.
-    if (this->Makefile->PlatformIs64Bit()) {
-      this->AddArchitecturePaths("64");
-    }
+  // add special 32 bit paths if this is a 32 bit compile.
+  else if (this->Makefile->PlatformIs32Bit() &&
+           this->Makefile->GetState()->GetGlobalPropertyAsBool(
+             "FIND_LIBRARY_USE_LIB32_PATHS")) {
+    this->AddArchitecturePaths("32");
+  }
+  // add special 64 bit paths if this is a 64 bit compile.
+  else if (this->Makefile->PlatformIs64Bit() &&
+           this->Makefile->GetState()->GetGlobalPropertyAsBool(
+             "FIND_LIBRARY_USE_LIB64_PATHS")) {
+    this->AddArchitecturePaths("64");
+  }
+  // add special 32 bit paths if this is an x32 compile.
+  else if (this->Makefile->PlatformIsx32() &&
+           this->Makefile->GetState()->GetGlobalPropertyAsBool(
+             "FIND_LIBRARY_USE_LIBX32_PATHS")) {
+    this->AddArchitecturePaths("x32");
   }
 
   std::string library = this->FindLibrary();
@@ -294,7 +303,7 @@ bool cmFindLibraryHelper::HasValidSuffix(std::string const& name)
     // Check if a valid library suffix is somewhere in the name,
     // this may happen e.g. for versioned shared libraries: libfoo.so.2
     suffix += ".";
-    if (name.find(suffix) != name.npos) {
+    if (name.find(suffix) != std::string::npos) {
       return true;
     }
   }
diff --git a/Source/cmFindLibraryCommand.h b/Source/cmFindLibraryCommand.h
index aeff629..9d38eab 100644
--- a/Source/cmFindLibraryCommand.h
+++ b/Source/cmFindLibraryCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmFindLibraryCommand_h
 #define cmFindLibraryCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -35,16 +36,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "find_library"; }
-
 protected:
   void AddArchitecturePaths(const char* suffix);
   void AddArchitecturePath(std::string const& dir,
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 60de74f..f291f9d 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -2,14 +2,15 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFindPackageCommand.h"
 
+#include "cmSystemTools.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include "cmsys/String.h"
 #include <algorithm>
 #include <assert.h>
-#include <cmSystemTools.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/String.h>
+#include <deque>
 #include <functional>
 #include <iterator>
 #include <sstream>
@@ -92,6 +93,7 @@ cmFindPackageCommand::cmFindPackageCommand()
   this->DebugMode = false;
   this->UseLib32Paths = false;
   this->UseLib64Paths = false;
+  this->UseLibx32Paths = false;
   this->PolicyScope = true;
   this->VersionMajor = 0;
   this->VersionMinor = 0;
@@ -173,6 +175,13 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
     this->UseLib64Paths = true;
   }
 
+  // Lookup whether libx32 paths should be used.
+  if (this->Makefile->PlatformIsx32() &&
+      this->Makefile->GetState()->GetGlobalPropertyAsBool(
+        "FIND_LIBRARY_USE_LIBX32_PATHS")) {
+    this->UseLibx32Paths = true;
+  }
+
   // Check if User Package Registry should be disabled
   if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) {
     this->NoUserRegistry = true;
@@ -317,7 +326,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
     } else if (doing == DoingPathSuffixes) {
       this->AddPathSuffix(args[i]);
     } else if (doing == DoingConfigs) {
-      if (args[i].find_first_of(":/\\") != args[i].npos ||
+      if (args[i].find_first_of(":/\\") != std::string::npos ||
           cmSystemTools::GetFilenameLastExtension(args[i]) != ".cmake") {
         std::ostringstream e;
         e << "given CONFIGS option followed by invalid file name \"" << args[i]
@@ -414,13 +423,17 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
              &parsed_minor, &parsed_patch, &parsed_tweak);
     switch (this->VersionCount) {
       case 4:
-        this->VersionTweak = parsed_tweak; // no break!
+        this->VersionTweak = parsed_tweak;
+        CM_FALLTHROUGH;
       case 3:
-        this->VersionPatch = parsed_patch; // no break!
+        this->VersionPatch = parsed_patch;
+        CM_FALLTHROUGH;
       case 2:
-        this->VersionMinor = parsed_minor; // no break!
+        this->VersionMinor = parsed_minor;
+        CM_FALLTHROUGH;
       case 1:
-        this->VersionMajor = parsed_major; // no break!
+        this->VersionMajor = parsed_major;
+        CM_FALLTHROUGH;
       default:
         break;
     }
@@ -577,6 +590,9 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
     exact += "_FIND_VERSION_EXACT";
     this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
   }
+
+  // Push on to the pacakge stack
+  this->Makefile->FindPackageModuleStack.push_back(this->Name);
 }
 
 void cmFindPackageCommand::AddFindDefinition(const std::string& var,
@@ -719,104 +735,119 @@ bool cmFindPackageCommand::HandlePackageMode()
     }
   }
 
-  if (result && !found && (!this->Quiet || this->Required)) {
-    // The variable is not set.
-    std::ostringstream e;
-    std::ostringstream aw;
-    if (configFileSetFOUNDFalse) {
-      /* clang-format off */
-      e << "Found package configuration file:\n"
-        "  " << this->FileFound << "\n"
-        "but it set " << foundVar << " to FALSE so package \"" <<
-        this->Name << "\" is considered to be NOT FOUND.";
-      /* clang-format on */
-      if (!notFoundMessage.empty()) {
-        e << " Reason given by package: \n" << notFoundMessage << "\n";
-      }
-    }
-    // If there are files in ConsideredConfigs, it means that FooConfig.cmake
-    // have been found, but they didn't have appropriate versions.
-    else if (!this->ConsideredConfigs.empty()) {
-      std::vector<ConfigFileInfo>::const_iterator duplicate_end =
-        cmRemoveDuplicates(this->ConsideredConfigs);
-      e << "Could not find a configuration file for package \"" << this->Name
-        << "\" that "
-        << (this->VersionExact ? "exactly matches" : "is compatible with")
-        << " requested version \"" << this->Version << "\".\n"
-        << "The following configuration files were considered but not "
-           "accepted:\n";
-      for (std::vector<ConfigFileInfo>::const_iterator i =
-             this->ConsideredConfigs.begin();
-           i != duplicate_end; ++i) {
-        e << "  " << i->filename << ", version: " << i->version << "\n";
-      }
-    } else {
-      std::string requestedVersionString;
-      if (!this->Version.empty()) {
-        requestedVersionString = " (requested version ";
-        requestedVersionString += this->Version;
-        requestedVersionString += ")";
+  // package not found
+  if (result && !found) {
+    // warn if package required or neither quiet nor in config mode
+    if (this->Required ||
+        !(this->Quiet || (this->UseConfigFiles && !this->UseFindModules &&
+                          this->ConsideredConfigs.empty()))) {
+      // The variable is not set.
+      std::ostringstream e;
+      std::ostringstream aw;
+      if (configFileSetFOUNDFalse) {
+        /* clang-format off */
+        e << "Found package configuration file:\n"
+          "  " << this->FileFound << "\n"
+          "but it set " << foundVar << " to FALSE so package \"" <<
+          this->Name << "\" is considered to be NOT FOUND.";
+        /* clang-format on */
+        if (!notFoundMessage.empty()) {
+          e << " Reason given by package: \n" << notFoundMessage << "\n";
+        }
       }
-
-      if (this->UseConfigFiles) {
-        if (this->UseFindModules) {
-          e << "By not providing \"Find" << this->Name
-            << ".cmake\" in "
-               "CMAKE_MODULE_PATH this project has asked CMake to find a "
-               "package configuration file provided by \""
-            << this->Name << "\", "
-                             "but CMake did not find one.\n";
+      // If there are files in ConsideredConfigs, it means that FooConfig.cmake
+      // have been found, but they didn't have appropriate versions.
+      else if (!this->ConsideredConfigs.empty()) {
+        std::vector<ConfigFileInfo>::const_iterator duplicate_end =
+          cmRemoveDuplicates(this->ConsideredConfigs);
+        e << "Could not find a configuration file for package \"" << this->Name
+          << "\" that "
+          << (this->VersionExact ? "exactly matches" : "is compatible with")
+          << " requested version \"" << this->Version << "\".\n"
+          << "The following configuration files were considered but not "
+             "accepted:\n";
+        for (std::vector<ConfigFileInfo>::const_iterator i =
+               this->ConsideredConfigs.begin();
+             i != duplicate_end; ++i) {
+          e << "  " << i->filename << ", version: " << i->version << "\n";
+        }
+      } else {
+        std::string requestedVersionString;
+        if (!this->Version.empty()) {
+          requestedVersionString = " (requested version ";
+          requestedVersionString += this->Version;
+          requestedVersionString += ")";
         }
 
-        if (this->Configs.size() == 1) {
-          e << "Could not find a package configuration file named \""
-            << this->Configs[0] << "\" provided by package \"" << this->Name
-            << "\"" << requestedVersionString << ".\n";
-        } else {
-          e << "Could not find a package configuration file provided by \""
-            << this->Name << "\"" << requestedVersionString
-            << " with any of the following names:\n"
-            << cmWrap("  ", this->Configs, "", "\n") << "\n";
+        if (this->UseConfigFiles) {
+          if (this->UseFindModules) {
+            e << "By not providing \"Find" << this->Name
+              << ".cmake\" in "
+                 "CMAKE_MODULE_PATH this project has asked CMake to find a "
+                 "package configuration file provided by \""
+              << this->Name << "\", "
+                               "but CMake did not find one.\n";
+          }
+
+          if (this->Configs.size() == 1) {
+            e << "Could not find a package configuration file named \""
+              << this->Configs[0] << "\" provided by package \"" << this->Name
+              << "\"" << requestedVersionString << ".\n";
+          } else {
+            e << "Could not find a package configuration file provided by \""
+              << this->Name << "\"" << requestedVersionString
+              << " with any of the following names:\n"
+              << cmWrap("  ", this->Configs, "", "\n") << "\n";
+          }
+
+          e << "Add the installation prefix of \"" << this->Name
+            << "\" to "
+               "CMAKE_PREFIX_PATH or set \""
+            << this->Variable
+            << "\" to a "
+               "directory containing one of the above files. "
+               "If \""
+            << this->Name << "\" provides a separate development "
+                             "package or SDK, be sure it has been installed.";
+        } else // if(!this->UseFindModules && !this->UseConfigFiles)
+        {
+          e << "No \"Find" << this->Name << ".cmake\" found in "
+            << "CMAKE_MODULE_PATH.";
+
+          aw
+            << "Find" << this->Name
+            << ".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.\n"
+               "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 "
+               "Find"
+            << this->Name
+            << ".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.\n";
         }
+      }
 
-        e << "Add the installation prefix of \"" << this->Name
-          << "\" to "
-             "CMAKE_PREFIX_PATH or set \""
-          << this->Variable << "\" to a "
-                               "directory containing one of the above files. "
-                               "If \""
-          << this->Name << "\" provides a separate development "
-                           "package or SDK, be sure it has been installed.";
-      } else // if(!this->UseFindModules && !this->UseConfigFiles)
-      {
-        e << "No \"Find" << this->Name << ".cmake\" found in "
-          << "CMAKE_MODULE_PATH.";
-
-        aw << "Find" << this->Name
-           << ".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.\n"
-              "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 "
-              "Find"
-           << this->Name
-           << ".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.\n";
+      this->Makefile->IssueMessage(
+        this->Required ? cmake::FATAL_ERROR : cmake::WARNING, e.str());
+      if (this->Required) {
+        cmSystemTools::SetFatalErrorOccured();
       }
-    }
 
-    this->Makefile->IssueMessage(
-      this->Required ? cmake::FATAL_ERROR : cmake::WARNING, e.str());
-    if (this->Required) {
-      cmSystemTools::SetFatalErrorOccured();
+      if (!aw.str().empty()) {
+        this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str());
+      }
     }
-
-    if (!aw.str().empty()) {
-      this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str());
+    // output result if in config mode but not in quiet mode
+    else if (!this->Quiet) {
+      std::ostringstream aw;
+      aw << "Could NOT find " << this->Name << " (missing: " << this->Name
+         << "_DIR)";
+      this->Makefile->DisplayStatus(aw.str().c_str(), -1);
     }
   }
 
@@ -912,7 +943,7 @@ bool cmFindPackageCommand::FindConfig()
 
 bool cmFindPackageCommand::FindPrefixedConfig()
 {
-  std::vector<std::string>& prefixes = this->SearchPaths;
+  std::vector<std::string> const& prefixes = this->SearchPaths;
   for (std::vector<std::string>::const_iterator pi = prefixes.begin();
        pi != prefixes.end(); ++pi) {
     if (this->SearchPrefix(*pi)) {
@@ -924,7 +955,7 @@ bool cmFindPackageCommand::FindPrefixedConfig()
 
 bool cmFindPackageCommand::FindFrameworkConfig()
 {
-  std::vector<std::string>& prefixes = this->SearchPaths;
+  std::vector<std::string> const& prefixes = this->SearchPaths;
   for (std::vector<std::string>::const_iterator i = prefixes.begin();
        i != prefixes.end(); ++i) {
     if (this->SearchFrameworkPrefix(*i)) {
@@ -936,7 +967,7 @@ bool cmFindPackageCommand::FindFrameworkConfig()
 
 bool cmFindPackageCommand::FindAppBundleConfig()
 {
-  std::vector<std::string>& prefixes = this->SearchPaths;
+  std::vector<std::string> const& prefixes = this->SearchPaths;
   for (std::vector<std::string>::const_iterator i = prefixes.begin();
        i != prefixes.end(); ++i) {
     if (this->SearchAppBundlePrefix(*i)) {
@@ -1051,6 +1082,9 @@ void cmFindPackageCommand::AppendSuccessInformation()
 
   // Restore original state of "_FIND_" variables we set.
   this->RestoreFindDefinitions();
+
+  // Pop the package stack
+  this->Makefile->FindPackageModuleStack.pop_back();
 }
 
 void cmFindPackageCommand::ComputePrefixes()
@@ -1165,7 +1199,6 @@ void cmFindPackageCommand::FillPrefixesSystemRegistry()
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include <windows.h>
-#undef GetCurrentDirectory
 // http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx
 #if !defined(KEY_WOW64_32KEY)
 #define KEY_WOW64_32KEY 0x0200
@@ -1514,13 +1547,17 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
                &parsed_minor, &parsed_patch, &parsed_tweak);
       switch (this->VersionFoundCount) {
         case 4:
-          this->VersionFoundTweak = parsed_tweak; // no break!
+          this->VersionFoundTweak = parsed_tweak;
+          CM_FALLTHROUGH;
         case 3:
-          this->VersionFoundPatch = parsed_patch; // no break!
+          this->VersionFoundPatch = parsed_patch;
+          CM_FALLTHROUGH;
         case 2:
-          this->VersionFoundMinor = parsed_minor; // no break!
+          this->VersionFoundMinor = parsed_minor;
+          CM_FALLTHROUGH;
         case 1:
-          this->VersionFoundMajor = parsed_major; // no break!
+          this->VersionFoundMajor = parsed_major;
+          CM_FALLTHROUGH;
         default:
           break;
       }
@@ -1565,6 +1602,7 @@ class cmFileListGeneratorBase
 {
 public:
   virtual ~cmFileListGeneratorBase() {}
+
 protected:
   bool Consider(std::string const& fullPath, cmFileList& listing);
 
@@ -2002,6 +2040,9 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
   if (this->UseLib64Paths) {
     common.push_back("lib64");
   }
+  if (this->UseLibx32Paths) {
+    common.push_back("libx32");
+  }
   common.push_back("lib");
   common.push_back("share");
 
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index d454892..318b1dc 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -3,8 +3,9 @@
 #ifndef cmFindPackageCommand_h
 #define cmFindPackageCommand_h
 
-#include <cmConfigure.h>
-#include <cm_kwiml.h>
+#include "cmConfigure.h"
+
+#include "cm_kwiml.h"
 #include <map>
 #include <set>
 #include <string>
@@ -59,16 +60,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "find_package"; }
-
 private:
   class PathLabel : public cmFindCommon::PathLabel
   {
@@ -169,6 +160,7 @@ private:
   bool DebugMode;
   bool UseLib32Paths;
   bool UseLib64Paths;
+  bool UseLibx32Paths;
   bool PolicyScope;
   std::string LibraryArchitecture;
   std::vector<std::string> Names;
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 8d4bcf3..d3541ca 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFindPathCommand.h"
 
-#include <cmsys/Glob.hxx>
+#include "cmsys/Glob.hxx"
 
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
@@ -76,14 +76,14 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
   // if there is a / in the name try to find the header as a framework
   // For example bar/foo.h would look for:
   // bar.framework/Headers/foo.h
-  if (pos != fileName.npos) {
+  if (pos != std::string::npos) {
     // remove the name from the slash;
     fileName = fileName.substr(pos + 1);
     frameWorkName = file;
     frameWorkName =
       frameWorkName.substr(0, frameWorkName.size() - fileName.size() - 1);
     // if the framework has a path in it then just use the filename
-    if (frameWorkName.find('/') != frameWorkName.npos) {
+    if (frameWorkName.find('/') != std::string::npos) {
       fileName = file;
       frameWorkName = "";
     }
diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h
index edeeb3a..3761145 100644
--- a/Source/cmFindPathCommand.h
+++ b/Source/cmFindPathCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmFindPathCommand_h
 #define cmFindPathCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -35,16 +36,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "find_path"; }
-
   bool IncludeFileInPath;
 
 private:
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index ea031cf..9327c18 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -212,7 +212,8 @@ std::string cmFindProgramCommand::FindAppBundle()
   return "";
 }
 
-std::string cmFindProgramCommand::GetBundleExecutable(std::string bundlePath)
+std::string cmFindProgramCommand::GetBundleExecutable(
+  std::string const& bundlePath)
 {
   std::string executable;
   (void)bundlePath;
diff --git a/Source/cmFindProgramCommand.h b/Source/cmFindProgramCommand.h
index dc17803..b0cd420 100644
--- a/Source/cmFindProgramCommand.h
+++ b/Source/cmFindProgramCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmFindProgramCommand_h
 #define cmFindProgramCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -36,23 +37,13 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "find_program"; }
-
 private:
   std::string FindProgram();
   std::string FindNormalProgram();
   std::string FindNormalProgramDirsPerName();
   std::string FindNormalProgramNamesPerDir();
   std::string FindAppBundle();
-  std::string GetBundleExecutable(std::string bundlePath);
+  std::string GetBundleExecutable(std::string const& bundlePath);
 };
 
 #endif
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 6273f6e..8346b23 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -58,7 +58,7 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
           status.Clear();
           mf.ExecuteCommand(this->Functions[c], status);
           if (status.GetReturnInvoked()) {
-            inStatus.SetReturnInvoked(true);
+            inStatus.SetReturnInvoked();
             // restore the variable to its prior value
             mf.AddDefinition(this->Args[0], oldDef.c_str());
             return true;
diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h
index 93c4676..7c8a6d8 100644
--- a/Source/cmForEachCommand.h
+++ b/Source/cmForEachCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmForEachCommand_h
 #define cmForEachCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -47,16 +48,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "foreach"; }
-
 private:
   bool HandleInMode(std::vector<std::string> const& args);
 };
diff --git a/Source/cmFortranParser.cxx b/Source/cmFortranParser.cxx
deleted file mode 100644
index 896e589..0000000
--- a/Source/cmFortranParser.cxx
+++ /dev/null
@@ -1,1984 +0,0 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
-
-/* Bison implementation for Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "3.0.4"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 1
-
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
-
-/* Substitute the variable and function names.  */
-#define yyparse         cmFortran_yyparse
-#define yylex           cmFortran_yylex
-#define yyerror         cmFortran_yyerror
-#define yydebug         cmFortran_yydebug
-#define yynerrs         cmFortran_yynerrs
-
-
-/* Copy the first part of user declarations.  */
-#line 1 "cmFortranParser.y" /* yacc.c:339  */
-
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*-------------------------------------------------------------------------
-  Portions of this source have been derived from makedepf90 version 2.8.8,
-
-   Copyright (C) 2000--2006 Erik Edelmann <erik.edelmann at iki.fi>
-
-  The code was originally distributed under the GPL but permission
-  from the copyright holder has been obtained to distribute this
-  derived work under the CMake license.
--------------------------------------------------------------------------*/
-
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
-  bison --yacc --name-prefix=cmFortran_yy
-        --defines=cmFortranParserTokens.h
-         -ocmFortranParser.cxx
-          cmFortranParser.y
-
-Modify cmFortranParser.cxx:
-  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
-*/
-
-/*-------------------------------------------------------------------------*/
-#define cmFortranParser_cxx
-#include "cmFortranParser.h" /* Interface to parser object.  */
-#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
-
-#include <cmsys/String.h>
-
-/* Forward declare the lexer entry point.  */
-YY_DECL;
-
-/* Helper function to forward error callback from parser.  */
-static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
-{
-  cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-  cmFortranParser_Error(parser, message);
-}
-
-/* Disable some warnings in the generated code.  */
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label.  */
-# pragma warning (disable: 4065) /* Switch contains default but no case. */
-# pragma warning (disable: 4701) /* Local variable may not be initialized.  */
-# pragma warning (disable: 4702) /* Unreachable code.  */
-# pragma warning (disable: 4127) /* Conditional expression is constant.  */
-# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
-#endif
-
-#line 137 "cmFortranParser.cxx" /* yacc.c:339  */
-
-# ifndef YY_NULLPTR
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULLPTR nullptr
-#  else
-#   define YY_NULLPTR 0
-#  endif
-# endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 1
-#endif
-
-/* In a future release of Bison, this section will be replaced
-   by #include "cmFortranParserTokens.h".  */
-#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
-# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
-/* Debug traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int cmFortran_yydebug;
-#endif
-
-/* Token type.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-  enum yytokentype
-  {
-    EOSTMT = 258,
-    ASSIGNMENT_OP = 259,
-    GARBAGE = 260,
-    CPP_LINE_DIRECTIVE = 261,
-    CPP_INCLUDE = 262,
-    F90PPR_INCLUDE = 263,
-    COCO_INCLUDE = 264,
-    F90PPR_DEFINE = 265,
-    CPP_DEFINE = 266,
-    F90PPR_UNDEF = 267,
-    CPP_UNDEF = 268,
-    CPP_IFDEF = 269,
-    CPP_IFNDEF = 270,
-    CPP_IF = 271,
-    CPP_ELSE = 272,
-    CPP_ELIF = 273,
-    CPP_ENDIF = 274,
-    F90PPR_IFDEF = 275,
-    F90PPR_IFNDEF = 276,
-    F90PPR_IF = 277,
-    F90PPR_ELSE = 278,
-    F90PPR_ELIF = 279,
-    F90PPR_ENDIF = 280,
-    COMMA = 281,
-    COLON = 282,
-    DCOLON = 283,
-    LPAREN = 284,
-    RPAREN = 285,
-    UNTERMINATED_STRING = 286,
-    STRING = 287,
-    WORD = 288,
-    CPP_INCLUDE_ANGLE = 289,
-    END = 290,
-    INCLUDE = 291,
-    INTERFACE = 292,
-    MODULE = 293,
-    SUBMODULE = 294,
-    USE = 295
-  };
-#endif
-/* Tokens.  */
-#define EOSTMT 258
-#define ASSIGNMENT_OP 259
-#define GARBAGE 260
-#define CPP_LINE_DIRECTIVE 261
-#define CPP_INCLUDE 262
-#define F90PPR_INCLUDE 263
-#define COCO_INCLUDE 264
-#define F90PPR_DEFINE 265
-#define CPP_DEFINE 266
-#define F90PPR_UNDEF 267
-#define CPP_UNDEF 268
-#define CPP_IFDEF 269
-#define CPP_IFNDEF 270
-#define CPP_IF 271
-#define CPP_ELSE 272
-#define CPP_ELIF 273
-#define CPP_ENDIF 274
-#define F90PPR_IFDEF 275
-#define F90PPR_IFNDEF 276
-#define F90PPR_IF 277
-#define F90PPR_ELSE 278
-#define F90PPR_ELIF 279
-#define F90PPR_ENDIF 280
-#define COMMA 281
-#define COLON 282
-#define DCOLON 283
-#define LPAREN 284
-#define RPAREN 285
-#define UNTERMINATED_STRING 286
-#define STRING 287
-#define WORD 288
-#define CPP_INCLUDE_ANGLE 289
-#define END 290
-#define INCLUDE 291
-#define INTERFACE 292
-#define MODULE 293
-#define SUBMODULE 294
-#define USE 295
-
-/* Value type.  */
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
-union YYSTYPE
-{
-#line 75 "cmFortranParser.y" /* yacc.c:355  */
-
-  char* string;
-
-#line 261 "cmFortranParser.cxx" /* yacc.c:355  */
-};
-
-typedef union YYSTYPE YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-
-
-int cmFortran_yyparse (yyscan_t yyscanner);
-
-#endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED  */
-
-/* Copy the second part of user declarations.  */
-
-#line 277 "cmFortranParser.cxx" /* yacc.c:358  */
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#else
-typedef signed char yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(Msgid) Msgid
-# endif
-#endif
-
-#ifndef YY_ATTRIBUTE
-# if (defined __GNUC__                                               \
-      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
-     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
-#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
-# else
-#  define YY_ATTRIBUTE(Spec) /* empty */
-# endif
-#endif
-
-#ifndef YY_ATTRIBUTE_PURE
-# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
-#endif
-
-#ifndef YY_ATTRIBUTE_UNUSED
-# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
-#endif
-
-#if !defined _Noreturn \
-     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-#  define _Noreturn __declspec (noreturn)
-# else
-#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
-#else
-# define YYUSE(E) /* empty */
-#endif
-
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
-/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
-    _Pragma ("GCC diagnostic push") \
-    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
-    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
-    _Pragma ("GCC diagnostic pop")
-#else
-# define YY_INITIAL_VALUE(Value) Value
-#endif
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
-
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's 'empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
-       && ! ((defined YYMALLOC || defined malloc) \
-             && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef EXIT_SUCCESS
-#    define EXIT_SUCCESS 0
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss_alloc;
-  YYSTYPE yyvs_alloc;
-};
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-# define YYCOPY_NEEDED 1
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
-    do                                                                  \
-      {                                                                 \
-        YYSIZE_T yynewbytes;                                            \
-        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
-        Stack = &yyptr->Stack_alloc;                                    \
-        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-        yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                 \
-    while (0)
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(Dst, Src, Count) \
-      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
-#  else
-#   define YYCOPY(Dst, Src, Count)              \
-      do                                        \
-        {                                       \
-          YYSIZE_T yyi;                         \
-          for (yyi = 0; yyi < (Count); yyi++)   \
-            (Dst)[yyi] = (Src)[yyi];            \
-        }                                       \
-      while (0)
-#  endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  2
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   593
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  41
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  14
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  63
-/* YYNSTATES -- Number of states.  */
-#define YYNSTATES  126
-
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
-   by yylex, with out-of-bounds checking.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   295
-
-#define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
-   as returned by yylex, without out-of-bounds checking.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40
-};
-
-#if YYDEBUG
-  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
-static const yytype_uint8 yyrline[] =
-{
-       0,   103,   103,   103,   106,   110,   115,   124,   130,   137,
-     142,   146,   151,   159,   164,   169,   174,   179,   184,   189,
-     194,   199,   203,   207,   211,   215,   216,   221,   221,   221,
-     222,   222,   223,   223,   224,   224,   225,   225,   226,   226,
-     227,   227,   228,   228,   229,   229,   230,   230,   233,   234,
-     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
-     245,   246,   247,   248
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || 1
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "EOSTMT", "ASSIGNMENT_OP", "GARBAGE",
-  "CPP_LINE_DIRECTIVE", "CPP_INCLUDE", "F90PPR_INCLUDE", "COCO_INCLUDE",
-  "F90PPR_DEFINE", "CPP_DEFINE", "F90PPR_UNDEF", "CPP_UNDEF", "CPP_IFDEF",
-  "CPP_IFNDEF", "CPP_IF", "CPP_ELSE", "CPP_ELIF", "CPP_ENDIF",
-  "F90PPR_IFDEF", "F90PPR_IFNDEF", "F90PPR_IF", "F90PPR_ELSE",
-  "F90PPR_ELIF", "F90PPR_ENDIF", "COMMA", "COLON", "DCOLON", "LPAREN",
-  "RPAREN", "UNTERMINATED_STRING", "STRING", "WORD", "CPP_INCLUDE_ANGLE",
-  "END", "INCLUDE", "INTERFACE", "MODULE", "SUBMODULE", "USE", "$accept",
-  "code", "stmt", "include", "define", "undef", "ifdef", "ifndef", "if",
-  "elif", "else", "endif", "other", "misc_code", YY_NULLPTR
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[NUM] -- (External) token number corresponding to the
-   (internal) symbol number NUM (which must be that of a token).  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295
-};
-# endif
-
-#define YYPACT_NINF -39
-
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-39)))
-
-#define YYTABLE_NINF -1
-
-#define yytable_value_is_error(Yytable_value) \
-  0
-
-  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-     STATE-NUM.  */
-static const yytype_int16 yypact[] =
-{
-     -39,    21,   -39,     1,   -39,   -20,   -39,   -39,   -39,   -39,
-     -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,
-     -39,   -39,   -39,   -39,   -39,   -39,   -24,   -18,    20,    -8,
-      -3,    39,   -39,    15,    16,    18,    19,    33,   -39,   -39,
-     -39,   -39,   -39,   -39,    59,   -39,   -39,   -39,   -39,   -39,
-      35,    36,    37,   -39,   -39,   -39,   -39,   -39,   -39,    76,
-     114,   129,   167,   182,   -39,   -39,   -39,   -39,   -39,   -39,
-     -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,
-     -39,   -39,   220,   235,   273,   288,   -21,    26,   -39,   326,
-     341,   379,   394,   432,   447,   -39,   -39,   -39,   -39,   -39,
-     -39,   -39,   -39,   -39,    38,    40,    41,   485,   -39,   -39,
-     -39,   -39,   -39,   -39,    45,   -39,   -39,   -39,    43,   500,
-     538,   -39,   -39,   -39,   553,   -39
-};
-
-  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
-     Performed when YYTABLE does not specify something else to do.  Zero
-     means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       2,     0,     1,     0,    25,     0,    27,    28,    29,    31,
-      30,    33,    32,    34,    36,    38,    42,    40,    44,    35,
-      37,    39,    43,    41,    45,    46,     0,     0,     0,     0,
-       0,     0,     3,     0,     0,     0,     0,     0,    46,    46,
-      46,    46,    26,    46,     0,    46,    46,     4,    46,    46,
-       0,     0,     0,    46,    46,    46,    46,    46,    46,     0,
-       0,     0,     0,     0,    15,    57,    56,    62,    58,    59,
-      60,    61,    63,    55,    48,    49,    50,    51,    52,    53,
-      54,    47,     0,     0,     0,     0,     0,     0,    46,     0,
-       0,     0,     0,     0,     0,    21,    22,    23,    24,    14,
-      10,    13,     9,     6,     0,     0,     0,     0,     5,    16,
-      17,    18,    19,    20,     0,    46,    46,    11,     0,     0,
-       0,    46,     7,    12,     0,     8
-};
-
-  /* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] =
-{
-     -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,   -39,
-     -39,   -39,   -38,   -39
-};
-
-  /* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
-{
-      -1,     1,    32,    33,    34,    35,    36,    37,    38,    39,
-      40,    41,    44,    81
-};
-
-  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
-     positive, shift that token.  If negative, reduce the rule whose
-     number is the opposite.  If YYTABLE_NINF, syntax error.  */
-static const yytype_uint8 yytable[] =
-{
-      59,    60,    61,    62,    42,    63,   104,    82,    83,   105,
-      84,    85,    43,    45,    46,    89,    90,    91,    92,    93,
-      94,     2,     3,    47,     4,    49,    50,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    54,     0,    55,
-     107,    56,    57,    48,   106,    25,    26,    27,    28,    29,
-      30,    31,    64,    65,    66,    51,    58,    52,    86,    87,
-      88,   114,    53,   115,   116,   118,   121,   119,   120,    95,
-      65,    66,     0,   124,     0,    67,    68,    69,    70,    71,
-      72,    73,    74,     0,    75,    76,    77,    78,    79,    80,
-       0,     0,    67,    68,    69,    70,    71,    72,    73,    74,
-       0,    75,    76,    77,    78,    79,    80,    96,    65,    66,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    97,    65,    66,     0,     0,     0,     0,     0,
-      67,    68,    69,    70,    71,    72,    73,    74,     0,    75,
-      76,    77,    78,    79,    80,    67,    68,    69,    70,    71,
-      72,    73,    74,     0,    75,    76,    77,    78,    79,    80,
-      98,    65,    66,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    99,    65,    66,     0,     0,
-       0,     0,     0,    67,    68,    69,    70,    71,    72,    73,
-      74,     0,    75,    76,    77,    78,    79,    80,    67,    68,
-      69,    70,    71,    72,    73,    74,     0,    75,    76,    77,
-      78,    79,    80,   100,    65,    66,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   101,    65,
-      66,     0,     0,     0,     0,     0,    67,    68,    69,    70,
-      71,    72,    73,    74,     0,    75,    76,    77,    78,    79,
-      80,    67,    68,    69,    70,    71,    72,    73,    74,     0,
-      75,    76,    77,    78,    79,    80,   102,    65,    66,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   103,    65,    66,     0,     0,     0,     0,     0,    67,
-      68,    69,    70,    71,    72,    73,    74,     0,    75,    76,
-      77,    78,    79,    80,    67,    68,    69,    70,    71,    72,
-      73,    74,     0,    75,    76,    77,    78,    79,    80,   108,
-      65,    66,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   109,    65,    66,     0,     0,     0,
-       0,     0,    67,    68,    69,    70,    71,    72,    73,    74,
-       0,    75,    76,    77,    78,    79,    80,    67,    68,    69,
-      70,    71,    72,    73,    74,     0,    75,    76,    77,    78,
-      79,    80,   110,    65,    66,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   111,    65,    66,
-       0,     0,     0,     0,     0,    67,    68,    69,    70,    71,
-      72,    73,    74,     0,    75,    76,    77,    78,    79,    80,
-      67,    68,    69,    70,    71,    72,    73,    74,     0,    75,
-      76,    77,    78,    79,    80,   112,    65,    66,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     113,    65,    66,     0,     0,     0,     0,     0,    67,    68,
-      69,    70,    71,    72,    73,    74,     0,    75,    76,    77,
-      78,    79,    80,    67,    68,    69,    70,    71,    72,    73,
-      74,     0,    75,    76,    77,    78,    79,    80,   117,    65,
-      66,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   122,    65,    66,     0,     0,     0,     0,
-       0,    67,    68,    69,    70,    71,    72,    73,    74,     0,
-      75,    76,    77,    78,    79,    80,    67,    68,    69,    70,
-      71,    72,    73,    74,     0,    75,    76,    77,    78,    79,
-      80,   123,    65,    66,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   125,    65,    66,     0,
-       0,     0,     0,     0,    67,    68,    69,    70,    71,    72,
-      73,    74,     0,    75,    76,    77,    78,    79,    80,    67,
-      68,    69,    70,    71,    72,    73,    74,     0,    75,    76,
-      77,    78,    79,    80
-};
-
-static const yytype_int8 yycheck[] =
-{
-      38,    39,    40,    41,     3,    43,    27,    45,    46,    30,
-      48,    49,    32,    37,    32,    53,    54,    55,    56,    57,
-      58,     0,     1,     3,     3,    33,    29,     6,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    32,    -1,    33,
-      88,    33,    33,    33,    28,    34,    35,    36,    37,    38,
-      39,    40,     3,     4,     5,    26,    33,    28,    33,    33,
-      33,    33,    33,    33,    33,    30,    33,   115,   116,     3,
-       4,     5,    -1,   121,    -1,    26,    27,    28,    29,    30,
-      31,    32,    33,    -1,    35,    36,    37,    38,    39,    40,
-      -1,    -1,    26,    27,    28,    29,    30,    31,    32,    33,
-      -1,    35,    36,    37,    38,    39,    40,     3,     4,     5,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,     3,     4,     5,    -1,    -1,    -1,    -1,    -1,
-      26,    27,    28,    29,    30,    31,    32,    33,    -1,    35,
-      36,    37,    38,    39,    40,    26,    27,    28,    29,    30,
-      31,    32,    33,    -1,    35,    36,    37,    38,    39,    40,
-       3,     4,     5,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,     3,     4,     5,    -1,    -1,
-      -1,    -1,    -1,    26,    27,    28,    29,    30,    31,    32,
-      33,    -1,    35,    36,    37,    38,    39,    40,    26,    27,
-      28,    29,    30,    31,    32,    33,    -1,    35,    36,    37,
-      38,    39,    40,     3,     4,     5,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,     3,     4,
-       5,    -1,    -1,    -1,    -1,    -1,    26,    27,    28,    29,
-      30,    31,    32,    33,    -1,    35,    36,    37,    38,    39,
-      40,    26,    27,    28,    29,    30,    31,    32,    33,    -1,
-      35,    36,    37,    38,    39,    40,     3,     4,     5,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,     3,     4,     5,    -1,    -1,    -1,    -1,    -1,    26,
-      27,    28,    29,    30,    31,    32,    33,    -1,    35,    36,
-      37,    38,    39,    40,    26,    27,    28,    29,    30,    31,
-      32,    33,    -1,    35,    36,    37,    38,    39,    40,     3,
-       4,     5,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,     3,     4,     5,    -1,    -1,    -1,
-      -1,    -1,    26,    27,    28,    29,    30,    31,    32,    33,
-      -1,    35,    36,    37,    38,    39,    40,    26,    27,    28,
-      29,    30,    31,    32,    33,    -1,    35,    36,    37,    38,
-      39,    40,     3,     4,     5,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,     3,     4,     5,
-      -1,    -1,    -1,    -1,    -1,    26,    27,    28,    29,    30,
-      31,    32,    33,    -1,    35,    36,    37,    38,    39,    40,
-      26,    27,    28,    29,    30,    31,    32,    33,    -1,    35,
-      36,    37,    38,    39,    40,     3,     4,     5,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-       3,     4,     5,    -1,    -1,    -1,    -1,    -1,    26,    27,
-      28,    29,    30,    31,    32,    33,    -1,    35,    36,    37,
-      38,    39,    40,    26,    27,    28,    29,    30,    31,    32,
-      33,    -1,    35,    36,    37,    38,    39,    40,     3,     4,
-       5,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,     3,     4,     5,    -1,    -1,    -1,    -1,
-      -1,    26,    27,    28,    29,    30,    31,    32,    33,    -1,
-      35,    36,    37,    38,    39,    40,    26,    27,    28,    29,
-      30,    31,    32,    33,    -1,    35,    36,    37,    38,    39,
-      40,     3,     4,     5,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,     3,     4,     5,    -1,
-      -1,    -1,    -1,    -1,    26,    27,    28,    29,    30,    31,
-      32,    33,    -1,    35,    36,    37,    38,    39,    40,    26,
-      27,    28,    29,    30,    31,    32,    33,    -1,    35,    36,
-      37,    38,    39,    40
-};
-
-  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-     symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    42,     0,     1,     3,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    34,    35,    36,    37,    38,
-      39,    40,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,     3,    32,    53,    37,    32,     3,    33,    33,
-      29,    26,    28,    33,    32,    33,    33,    33,    33,    53,
-      53,    53,    53,    53,     3,     4,     5,    26,    27,    28,
-      29,    30,    31,    32,    33,    35,    36,    37,    38,    39,
-      40,    54,    53,    53,    53,    53,    33,    33,    33,    53,
-      53,    53,    53,    53,    53,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,    27,    30,    28,    53,     3,     3,
-       3,     3,     3,     3,    33,    33,    33,     3,    30,    53,
-      53,    33,     3,     3,    53,     3
-};
-
-  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    41,    42,    42,    43,    43,    43,    43,    43,    43,
-      43,    43,    43,    43,    43,    43,    43,    43,    43,    43,
-      43,    43,    43,    43,    43,    43,    43,    44,    44,    44,
-      45,    45,    46,    46,    47,    47,    48,    48,    49,    49,
-      50,    50,    51,    51,    52,    52,    53,    53,    54,    54,
-      54,    54,    54,    54,    54,    54,    54,    54,    54,    54,
-      54,    54,    54,    54
-};
-
-  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     0,     2,     2,     4,     4,     7,     9,     4,
-       4,     5,     7,     4,     4,     3,     4,     4,     4,     4,
-       4,     3,     3,     3,     3,     1,     2,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     0,     2,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1
-};
-
-
-#define yyerrok         (yyerrstatus = 0)
-#define yyclearin       (yychar = YYEMPTY)
-#define YYEMPTY         (-2)
-#define YYEOF           0
-
-#define YYACCEPT        goto yyacceptlab
-#define YYABORT         goto yyabortlab
-#define YYERROR         goto yyerrorlab
-
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
-      YYERROR;                                                  \
-    }                                                           \
-while (0)
-
-/* Error token number */
-#define YYTERROR        1
-#define YYERRCODE       256
-
-
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                        \
-do {                                            \
-  if (yydebug)                                  \
-    YYFPRINTF Args;                             \
-} while (0)
-
-/* This macro is provided for backward compatibility. */
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
-
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
-do {                                                                      \
-  if (yydebug)                                                            \
-    {                                                                     \
-      YYFPRINTF (stderr, "%s ", Title);                                   \
-      yy_symbol_print (stderr,                                            \
-                  Type, Value, yyscanner); \
-      YYFPRINTF (stderr, "\n");                                           \
-    }                                                                     \
-} while (0)
-
-
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT.  |
-`----------------------------------------*/
-
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
-{
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
-  YYUSE (yyscanner);
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
-  YYUSE (yytype);
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
-{
-  YYFPRINTF (yyoutput, "%s %s (",
-             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; yybottom <= yytop; yybottom++)
-    {
-      int yybot = *yybottom;
-      YYFPRINTF (stderr, " %d", yybot);
-    }
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                            \
-do {                                                            \
-  if (yydebug)                                                  \
-    yy_stack_print ((Bottom), (Top));                           \
-} while (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
-{
-  unsigned long int yylno = yyrline[yyrule];
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-             yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr,
-                       yystos[yyssp[yyi + 1 - yynrhs]],
-                       &(yyvsp[(yyi + 1) - (yynrhs)])
-                                              , yyscanner);
-      YYFPRINTF (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)          \
-do {                                    \
-  if (yydebug)                          \
-    yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
-} while (0)
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-static YYSIZE_T
-yystrlen (const char *yystr)
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-        switch (*++yyp)
-          {
-          case '\'':
-          case ',':
-            goto do_not_strip_quotes;
-
-          case '\\':
-            if (*++yyp != '\\')
-              goto do_not_strip_quotes;
-            /* Fall through.  */
-          default:
-            if (yyres)
-              yyres[yyn] = *yyp;
-            yyn++;
-            break;
-
-          case '"':
-            if (yyres)
-              yyres[yyn] = '\0';
-            return yyn;
-          }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN for the state stack whose top is
-   YYSSP.
-
-   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
-   not large enough to hold the message.  In that case, also set
-   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
-{
-  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = YY_NULLPTR;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
-  int yycount = 0;
-
-  /* There are many possibilities here to consider:
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[*yyssp];
-      yyarg[yycount++] = yytname[yytoken];
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for
-             this state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
-
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytname[yyx];
-                {
-                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                    return 2;
-                  yysize = yysize1;
-                }
-              }
-        }
-    }
-
-  switch (yycount)
-    {
-# define YYCASE_(N, S)                      \
-      case N:                               \
-        yyformat = S;                       \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
-    }
-
-  {
-    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-      return 2;
-    yysize = yysize1;
-  }
-
-  if (*yymsg_alloc < yysize)
-    {
-      *yymsg_alloc = 2 * yysize;
-      if (! (yysize <= *yymsg_alloc
-             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
-        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
-      return 1;
-    }
-
-  /* Avoid sprintf, as that infringes on the user's name space.
-     Don't have undefined behavior even if the translation
-     produced a string with the wrong number of "%s"s.  */
-  {
-    char *yyp = *yymsg;
-    int yyi = 0;
-    while ((*yyp = *yyformat) != '\0')
-      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyformat += 2;
-        }
-      else
-        {
-          yyp++;
-          yyformat++;
-        }
-  }
-  return 0;
-}
-#endif /* YYERROR_VERBOSE */
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
-{
-  YYUSE (yyvaluep);
-  YYUSE (yyscanner);
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  YYUSE (yytype);
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-}
-
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-int
-yyparse (yyscan_t yyscanner)
-{
-/* The lookahead symbol.  */
-int yychar;
-
-
-/* The semantic value of the lookahead symbol.  */
-/* Default value used for initialization, for pacifying older GCCs
-   or non-GCC compilers.  */
-YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
-YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
-
-    /* Number of syntax errors so far.  */
-    int yynerrs;
-
-    int yystate;
-    /* Number of tokens to shift before error messages enabled.  */
-    int yyerrstatus;
-
-    /* The stacks and their tools:
-       'yyss': related to states.
-       'yyvs': related to semantic values.
-
-       Refer to the stacks through separate pointers, to allow yyoverflow
-       to reallocate them elsewhere.  */
-
-    /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
-
-    /* The semantic value stack.  */
-    YYSTYPE yyvsa[YYINITDEPTH];
-    YYSTYPE *yyvs;
-    YYSTYPE *yyvsp;
-
-    YYSIZE_T yystacksize;
-
-  int yyn;
-  int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  yyssp = yyss = yyssa;
-  yyvsp = yyvs = yyvsa;
-  yystacksize = YYINITDEPTH;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY; /* Cause a token to be read.  */
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-        /* Give user a chance to reallocate the stack.  Use copies of
-           these so that the &'s don't force the real ones into
-           memory.  */
-        YYSTYPE *yyvs1 = yyvs;
-        yytype_int16 *yyss1 = yyss;
-
-        /* Each stack pointer address is followed by the size of the
-           data in use in that stack, in bytes.  This used to be a
-           conditional around just the two extra args, but that might
-           be undefined if yyoverflow is a macro.  */
-        yyoverflow (YY_("memory exhausted"),
-                    &yyss1, yysize * sizeof (*yyssp),
-                    &yyvs1, yysize * sizeof (*yyvsp),
-                    &yystacksize);
-
-        yyss = yyss1;
-        yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-        goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-        yystacksize = YYMAXDEPTH;
-
-      {
-        yytype_int16 *yyss1 = yyss;
-        union yyalloc *yyptr =
-          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-        if (! yyptr)
-          goto yyexhaustedlab;
-        YYSTACK_RELOCATE (yyss_alloc, yyss);
-        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-#  undef YYSTACK_RELOCATE
-        if (yyss1 != yyssa)
-          YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-        YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  if (yystate == YYFINAL)
-    YYACCEPT;
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     lookahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to lookahead token.  */
-  yyn = yypact[yystate];
-  if (yypact_value_is_default (yyn))
-    goto yydefault;
-
-  /* Not known => get a lookahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = yylex (&yylval, yyscanner);
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yytable_value_is_error (yyn))
-        goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the lookahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token.  */
-  yychar = YYEMPTY;
-
-  yystate = yyn;
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     '$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 4:
-#line 106 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_SetInInterface(parser, true);
-  }
-#line 1541 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 5:
-#line 110 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1551 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 6:
-#line 115 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
-        cmsysString_strcasecmp((yyvsp[-2].string), "procedure") != 0 &&
-        cmsysString_strcasecmp((yyvsp[-2].string), "subroutine") != 0) {
-      cmFortranParser_RuleModule(parser, (yyvsp[-2].string));
-    }
-    free((yyvsp[-2].string));
-  }
-#line 1565 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 7:
-#line 124 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUse(parser, (yyvsp[-4].string));
-    free((yyvsp[-4].string));
-    free((yyvsp[-2].string));
-  }
-#line 1576 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 8:
-#line 130 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUse(parser, (yyvsp[-6].string));
-    free((yyvsp[-6].string));
-    free((yyvsp[-4].string));
-    free((yyvsp[-2].string));
-  }
-#line 1588 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 9:
-#line 137 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_SetInInterface(parser, true);
-    free((yyvsp[-2].string));
-  }
-#line 1598 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 10:
-#line 142 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_SetInInterface(parser, false);
-  }
-#line 1607 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 11:
-#line 146 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1617 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 12:
-#line 151 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
-      cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-      cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
-    }
-    free((yyvsp[-4].string));
-    free((yyvsp[-2].string));
-  }
-#line 1630 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 13:
-#line 159 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1640 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 14:
-#line 164 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1650 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 15:
-#line 169 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1660 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 16:
-#line 174 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1670 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 17:
-#line 179 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1680 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 18:
-#line 184 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1690 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 19:
-#line 189 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1700 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 20:
-#line 194 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
-    free((yyvsp[-2].string));
-  }
-#line 1710 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 21:
-#line 199 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleIf(parser);
-  }
-#line 1719 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 22:
-#line 203 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleElif(parser);
-  }
-#line 1728 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 23:
-#line 207 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleElse(parser);
-  }
-#line 1737 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 24:
-#line 211 "cmFortranParser.y" /* yacc.c:1646  */
-    {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleEndif(parser);
-  }
-#line 1746 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 48:
-#line 233 "cmFortranParser.y" /* yacc.c:1646  */
-    { free ((yyvsp[0].string)); }
-#line 1752 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-  case 55:
-#line 240 "cmFortranParser.y" /* yacc.c:1646  */
-    { free ((yyvsp[0].string)); }
-#line 1758 "cmFortranParser.cxx" /* yacc.c:1646  */
-    break;
-
-
-#line 1762 "cmFortranParser.cxx" /* yacc.c:1646  */
-      default: break;
-    }
-  /* User semantic actions sometimes alter yychar, and that requires
-     that yytoken be updated with the new translation.  We take the
-     approach of translating immediately before every use of yytoken.
-     One alternative is translating here after every semantic action,
-     but that translation would be missed if the semantic action invokes
-     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
-     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
-     incorrect destructor might then be invoked immediately.  In the
-     case of YYERROR or YYBACKUP, subsequent parser actions might lead
-     to an incorrect destructor call or verbose syntax error message
-     before the lookahead is translated.  */
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-  /* Now 'shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*--------------------------------------.
-| yyerrlab -- here on detecting error.  |
-`--------------------------------------*/
-yyerrlab:
-  /* Make sure we have latest lookahead translation.  See comments at
-     user semantic actions for why this is necessary.  */
-  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (yyscanner, YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
-                                        yyssp, yytoken)
-      {
-        char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status;
-        yysyntax_error_status = YYSYNTAX_ERROR;
-        if (yysyntax_error_status == 0)
-          yymsgp = yymsg;
-        else if (yysyntax_error_status == 1)
-          {
-            if (yymsg != yymsgbuf)
-              YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
-            if (!yymsg)
-              {
-                yymsg = yymsgbuf;
-                yymsg_alloc = sizeof yymsgbuf;
-                yysyntax_error_status = 2;
-              }
-            else
-              {
-                yysyntax_error_status = YYSYNTAX_ERROR;
-                yymsgp = yymsg;
-              }
-          }
-        yyerror (yyscanner, yymsgp);
-        if (yysyntax_error_status == 2)
-          goto yyexhaustedlab;
-      }
-# undef YYSYNTAX_ERROR
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse lookahead token after an
-         error, discard it.  */
-
-      if (yychar <= YYEOF)
-        {
-          /* Return failure if at end of input.  */
-          if (yychar == YYEOF)
-            YYABORT;
-        }
-      else
-        {
-          yydestruct ("Error: discarding",
-                      yytoken, &yylval, yyscanner);
-          yychar = YYEMPTY;
-        }
-    }
-
-#if 0
-  /* Else will try to reuse lookahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule whose action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-#endif
-  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (!yypact_value_is_default (yyn))
-        {
-          yyn += YYTERROR;
-          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-            {
-              yyn = yytable[yyn];
-              if (0 < yyn)
-                break;
-            }
-        }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-        YYABORT;
-
-
-      yydestruct ("Error: popping",
-                  yystos[yystate], yyvsp, yyscanner);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#if !defined yyoverflow || YYERROR_VERBOSE
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (yyscanner, YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEMPTY)
-    {
-      /* Make sure we have latest lookahead translation.  See comments at
-         user semantic actions for why this is necessary.  */
-      yytoken = YYTRANSLATE (yychar);
-      yydestruct ("Cleanup: discarding lookahead",
-                  yytoken, &yylval, yyscanner);
-    }
-  /* Do not reclaim the symbols of the rule whose action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                  yystos[*yyssp], yyvsp, yyscanner);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  return yyresult;
-}
-#line 251 "cmFortranParser.y" /* yacc.c:1906  */
-
-/* End of grammar */
diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h
index 06985d2..d8b0023 100644
--- a/Source/cmFortranParser.h
+++ b/Source/cmFortranParser.h
@@ -4,9 +4,11 @@
 #define cmFortranParser_h
 
 #if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx)
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include "cmStandardIncludes.h"
+#include <set>
+#include <string>
+#include <vector>
 #endif
 
 #include <stddef.h> /* size_t */
@@ -52,8 +54,7 @@ void cmFortranParser_RuleElse(cmFortranParser* parser);
 void cmFortranParser_RuleEndif(cmFortranParser* parser);
 
 /* Define the parser stack element type.  */
-typedef union cmFortran_yystype_u cmFortran_yystype;
-union cmFortran_yystype_u
+struct cmFortran_yystype
 {
   char* string;
 };
diff --git a/Source/cmFortranParser.y b/Source/cmFortranParser.y
deleted file mode 100644
index 7eb5ef5..0000000
--- a/Source/cmFortranParser.y
+++ /dev/null
@@ -1,243 +0,0 @@
-%{
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*-------------------------------------------------------------------------
-  Portions of this source have been derived from makedepf90 version 2.8.8,
-
-   Copyright (C) 2000--2006 Erik Edelmann <erik.edelmann at iki.fi>
-
-  The code was originally distributed under the GPL but permission
-  from the copyright holder has been obtained to distribute this
-  derived work under the CMake license.
--------------------------------------------------------------------------*/
-
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run bison like this:
-
-  bison --yacc --name-prefix=cmFortran_yy
-        --defines=cmFortranParserTokens.h
-         -ocmFortranParser.cxx
-          cmFortranParser.y
-
-Modify cmFortranParser.cxx:
-  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
-*/
-
-/*-------------------------------------------------------------------------*/
-#define cmFortranParser_cxx
-#include "cmFortranParser.h" /* Interface to parser object.  */
-#include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL.  */
-
-#include <cmsys/String.h>
-
-/* Forward declare the lexer entry point.  */
-YY_DECL;
-
-/* Helper function to forward error callback from parser.  */
-static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
-{
-  cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-  cmFortranParser_Error(parser, message);
-}
-
-/* Disable some warnings in the generated code.  */
-#ifdef _MSC_VER
-# pragma warning (disable: 4102) /* Unused goto label.  */
-# pragma warning (disable: 4065) /* Switch contains default but no case. */
-# pragma warning (disable: 4701) /* Local variable may not be initialized.  */
-# pragma warning (disable: 4702) /* Unreachable code.  */
-# pragma warning (disable: 4127) /* Conditional expression is constant.  */
-# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
-#endif
-%}
-
-/* Generate a reentrant parser object.  */
-%define api.pure
-
-/* Configure the parser to use a lexer object.  */
-%lex-param   {yyscan_t yyscanner}
-%parse-param {yyscan_t yyscanner}
-
-%define parse.error verbose
-
-%union {
-  char* string;
-}
-
-/*-------------------------------------------------------------------------*/
-/* Tokens */
-%token EOSTMT ASSIGNMENT_OP GARBAGE
-%token CPP_LINE_DIRECTIVE
-%token CPP_INCLUDE F90PPR_INCLUDE COCO_INCLUDE
-%token F90PPR_DEFINE CPP_DEFINE F90PPR_UNDEF CPP_UNDEF
-%token CPP_IFDEF CPP_IFNDEF CPP_IF CPP_ELSE CPP_ELIF CPP_ENDIF
-%token F90PPR_IFDEF F90PPR_IFNDEF F90PPR_IF
-%token F90PPR_ELSE F90PPR_ELIF F90PPR_ENDIF
-%token COMMA COLON DCOLON LPAREN RPAREN
-%token <number> UNTERMINATED_STRING
-%token <string> STRING WORD
-%token <string> CPP_INCLUDE_ANGLE
-%token END
-%token INCLUDE
-%token INTERFACE
-%token MODULE
-%token SUBMODULE
-%token USE
-
-/*-------------------------------------------------------------------------*/
-/* grammar */
-%%
-
-code: /* empty */ | code stmt;
-
-stmt:
-  INTERFACE EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_SetInInterface(parser, true);
-  }
-| USE WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUse(parser, $2);
-    free($2);
-  }
-| MODULE WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    if (cmsysString_strcasecmp($2, "function") != 0 &&
-        cmsysString_strcasecmp($2, "procedure") != 0 &&
-        cmsysString_strcasecmp($2, "subroutine") != 0) {
-      cmFortranParser_RuleModule(parser, $2);
-    }
-    free($2);
-  }
-| SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUse(parser, $3);
-    free($3);
-    free($5);
-  }
-| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUse(parser, $3);
-    free($3);
-    free($5);
-    free($7);
-  }
-| INTERFACE WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_SetInInterface(parser, true);
-    free($2);
-  }
-| END INTERFACE other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_SetInInterface(parser, false);
-  }
-| USE DCOLON WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUse(parser, $3);
-    free($3);
-  }
-| USE COMMA WORD DCOLON WORD other EOSTMT {
-    if (cmsysString_strcasecmp($3, "non_intrinsic") == 0) {
-      cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-      cmFortranParser_RuleUse(parser, $5);
-    }
-    free($3);
-    free($5);
-  }
-| INCLUDE STRING other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleInclude(parser, $2);
-    free($2);
-  }
-| CPP_LINE_DIRECTIVE STRING other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleLineDirective(parser, $2);
-    free($2);
-  }
-| CPP_INCLUDE_ANGLE other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleInclude(parser, $1);
-    free($1);
-  }
-| include STRING other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleInclude(parser, $2);
-    free($2);
-  }
-| define WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleDefine(parser, $2);
-    free($2);
-  }
-| undef WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleUndef(parser, $2);
-    free($2);
-  }
-| ifdef WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleIfdef(parser, $2);
-    free($2);
-  }
-| ifndef WORD other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleIfndef(parser, $2);
-    free($2);
-  }
-| if other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleIf(parser);
-  }
-| elif other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleElif(parser);
-  }
-| else other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleElse(parser);
-  }
-| endif other EOSTMT {
-    cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
-    cmFortranParser_RuleEndif(parser);
-  }
-| EOSTMT
-| error EOSTMT /* tolerate unknown statements until their end */
-;
-
-
-
-include: CPP_INCLUDE | F90PPR_INCLUDE | COCO_INCLUDE ;
-define: CPP_DEFINE | F90PPR_DEFINE;
-undef: CPP_UNDEF | F90PPR_UNDEF ;
-ifdef: CPP_IFDEF | F90PPR_IFDEF ;
-ifndef: CPP_IFNDEF | F90PPR_IFNDEF ;
-if: CPP_IF | F90PPR_IF ;
-elif: CPP_ELIF | F90PPR_ELIF ;
-else: CPP_ELSE | F90PPR_ELSE ;
-endif: CPP_ENDIF | F90PPR_ENDIF ;
-other: /* empty */ | other misc_code ;
-
-misc_code:
-  WORD                { free ($1); }
-| END
-| INCLUDE
-| INTERFACE
-| MODULE
-| SUBMODULE
-| USE
-| STRING              { free ($1); }
-| GARBAGE
-| ASSIGNMENT_OP
-| COLON
-| DCOLON
-| LPAREN
-| RPAREN
-| COMMA
-| UNTERMINATED_STRING
-;
-
-%%
-/* End of grammar */
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx
index 1a5e6c5..4e23f36 100644
--- a/Source/cmFortranParserImpl.cxx
+++ b/Source/cmFortranParserImpl.cxx
@@ -1,11 +1,10 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFortranParser.h"
-#include "cmFortranLexer.h"
 #include "cmSystemTools.h"
 
+#include "cmConfigure.h"
 #include <assert.h>
-#include <cmConfigure.h>
 #include <set>
 #include <stack>
 #include <stdio.h>
diff --git a/Source/cmFortranParserTokens.h b/Source/cmFortranParserTokens.h
deleted file mode 100644
index 18b9e0a..0000000
--- a/Source/cmFortranParserTokens.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
-
-/* Bison interface for Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
-# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
-/* Debug traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int cmFortran_yydebug;
-#endif
-
-/* Token type.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-  enum yytokentype
-  {
-    EOSTMT = 258,
-    ASSIGNMENT_OP = 259,
-    GARBAGE = 260,
-    CPP_LINE_DIRECTIVE = 261,
-    CPP_INCLUDE = 262,
-    F90PPR_INCLUDE = 263,
-    COCO_INCLUDE = 264,
-    F90PPR_DEFINE = 265,
-    CPP_DEFINE = 266,
-    F90PPR_UNDEF = 267,
-    CPP_UNDEF = 268,
-    CPP_IFDEF = 269,
-    CPP_IFNDEF = 270,
-    CPP_IF = 271,
-    CPP_ELSE = 272,
-    CPP_ELIF = 273,
-    CPP_ENDIF = 274,
-    F90PPR_IFDEF = 275,
-    F90PPR_IFNDEF = 276,
-    F90PPR_IF = 277,
-    F90PPR_ELSE = 278,
-    F90PPR_ELIF = 279,
-    F90PPR_ENDIF = 280,
-    COMMA = 281,
-    COLON = 282,
-    DCOLON = 283,
-    LPAREN = 284,
-    RPAREN = 285,
-    UNTERMINATED_STRING = 286,
-    STRING = 287,
-    WORD = 288,
-    CPP_INCLUDE_ANGLE = 289,
-    END = 290,
-    INCLUDE = 291,
-    INTERFACE = 292,
-    MODULE = 293,
-    SUBMODULE = 294,
-    USE = 295
-  };
-#endif
-/* Tokens.  */
-#define EOSTMT 258
-#define ASSIGNMENT_OP 259
-#define GARBAGE 260
-#define CPP_LINE_DIRECTIVE 261
-#define CPP_INCLUDE 262
-#define F90PPR_INCLUDE 263
-#define COCO_INCLUDE 264
-#define F90PPR_DEFINE 265
-#define CPP_DEFINE 266
-#define F90PPR_UNDEF 267
-#define CPP_UNDEF 268
-#define CPP_IFDEF 269
-#define CPP_IFNDEF 270
-#define CPP_IF 271
-#define CPP_ELSE 272
-#define CPP_ELIF 273
-#define CPP_ENDIF 274
-#define F90PPR_IFDEF 275
-#define F90PPR_IFNDEF 276
-#define F90PPR_IF 277
-#define F90PPR_ELSE 278
-#define F90PPR_ELIF 279
-#define F90PPR_ENDIF 280
-#define COMMA 281
-#define COLON 282
-#define DCOLON 283
-#define LPAREN 284
-#define RPAREN 285
-#define UNTERMINATED_STRING 286
-#define STRING 287
-#define WORD 288
-#define CPP_INCLUDE_ANGLE 289
-#define END 290
-#define INCLUDE 291
-#define INTERFACE 292
-#define MODULE 293
-#define SUBMODULE 294
-#define USE 295
-
-/* Value type.  */
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
-union YYSTYPE
-{
-#line 75 "cmFortranParser.y" /* yacc.c:1909  */
-
-  char* string;
-
-#line 138 "cmFortranParserTokens.h" /* yacc.c:1909  */
-};
-
-typedef union YYSTYPE YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-
-
-int cmFortran_yyparse (yyscan_t yyscanner);
-
-#endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED  */
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index 31adcb7..ee52bde 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -21,11 +21,6 @@ public:
   ~cmFunctionHelperCommand() CM_OVERRIDE {}
 
   /**
-   * This determines if the command is defined in a cmake script.
-   */
-  bool IsUserDefined() const CM_OVERRIDE { return true; }
-
-  /**
    * This is a virtual constructor for the command.
    */
   cmCommand* Clone() CM_OVERRIDE
@@ -40,11 +35,6 @@ public:
   }
 
   /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    */
@@ -57,11 +47,6 @@ public:
     return false;
   }
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return this->Args[0]; }
-
   std::vector<std::string> Args;
   std::vector<cmListFileFunction> Functions;
   cmPolicies::PolicyMap Policies;
@@ -126,7 +111,7 @@ bool cmFunctionHelperCommand::InvokeInitialPass(
       // The error message should have already included the call stack
       // so we do not need to report an error here.
       functionScope.Quiet();
-      inStatus.SetNestedError(true);
+      inStatus.SetNestedError();
       return false;
     }
     if (status.GetReturnInvoked()) {
@@ -154,11 +139,7 @@ bool cmFunctionFunctionBlocker::IsFunctionBlocked(
       f->Functions = this->Functions;
       f->FilePath = this->GetStartingContext().FilePath;
       mf.RecordPolicies(f->Policies);
-
-      std::string newName = "_" + this->Args[0];
-      mf.GetState()->RenameCommand(this->Args[0], newName);
-      mf.GetState()->AddCommand(f);
-
+      mf.GetState()->AddScriptedCommand(this->Args[0], f);
       // remove the function blocker now that the function is defined
       mf.RemoveFunctionBlocker(this, lff);
       return true;
diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h
index afea6f9..f263126 100644
--- a/Source/cmFunctionCommand.h
+++ b/Source/cmFunctionCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmFunctionCommand_h
 #define cmFunctionCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -43,16 +44,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "function"; }
 };
 
 #endif
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index 4731493..6aa593c 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -8,7 +8,7 @@
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cm_codecvt.hxx"
-#include <cm_zlib.h>
+#include "cm_zlib.h"
 #endif
 
 cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h
index a027b01..56f9988 100644
--- a/Source/cmGeneratedFileStream.h
+++ b/Source/cmGeneratedFileStream.h
@@ -3,10 +3,10 @@
 #ifndef cmGeneratedFileStream_h
 #define cmGeneratedFileStream_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cm_codecvt.hxx>
-#include <cmsys/FStream.hxx>
+#include "cm_codecvt.hxx"
+#include "cmsys/FStream.hxx"
 #include <string>
 
 // This is the first base class of cmGeneratedFileStream.  It will be
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index e70bbfe..00b5ff4 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGeneratorExpression.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <utility>
 
 #include "assert.h"
@@ -126,7 +126,7 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
 std::string cmGeneratorExpression::StripEmptyListElements(
   const std::string& input)
 {
-  if (input.find(';') == input.npos) {
+  if (input.find(';') == std::string::npos) {
     return input;
   }
   std::string result;
@@ -161,7 +161,7 @@ static std::string stripAllGeneratorExpressions(const std::string& input)
   std::string::size_type pos = 0;
   std::string::size_type lastPos = pos;
   int nestingLevel = 0;
-  while ((pos = input.find("$<", lastPos)) != input.npos) {
+  while ((pos = input.find("$<", lastPos)) != std::string::npos) {
     result += input.substr(lastPos, pos - lastPos);
     pos += 2;
     nestingLevel = 1;
@@ -290,7 +290,7 @@ void cmGeneratorExpression::Split(const std::string& input,
 {
   std::string::size_type pos = 0;
   std::string::size_type lastPos = pos;
-  while ((pos = input.find("$<", lastPos)) != input.npos) {
+  while ((pos = input.find("$<", lastPos)) != std::string::npos) {
     std::string part = input.substr(lastPos, pos - lastPos);
     std::string preGenex;
     if (!part.empty()) {
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 8f82a6b..34516f5 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -3,11 +3,11 @@
 #ifndef cmGeneratorExpression_h
 #define cmGeneratorExpression_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmListFileCache.h"
 
-#include <cm_auto_ptr.hxx>
+#include "cm_auto_ptr.hxx"
 #include <map>
 #include <set>
 #include <string>
@@ -31,6 +31,8 @@ struct cmGeneratorExpressionEvaluator;
  */
 class cmGeneratorExpression
 {
+  CM_DISABLE_COPY(cmGeneratorExpression)
+
 public:
   /** Construct. */
   cmGeneratorExpression(
@@ -61,14 +63,13 @@ public:
   static std::string StripEmptyListElements(const std::string& input);
 
 private:
-  cmGeneratorExpression(const cmGeneratorExpression&);
-  void operator=(const cmGeneratorExpression&);
-
   cmListFileBacktrace Backtrace;
 };
 
 class cmCompiledGeneratorExpression
 {
+  CM_DISABLE_COPY(cmCompiledGeneratorExpression)
+
 public:
   const char* Evaluate(
     cmLocalGenerator* lg, const std::string& config, bool quiet = false,
@@ -133,9 +134,6 @@ private:
 
   friend class cmGeneratorExpression;
 
-  cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression&);
-  void operator=(const cmCompiledGeneratorExpression&);
-
   cmListFileBacktrace Backtrace;
   std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
   const std::string Input;
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 8f10259..557a192 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -3,7 +3,7 @@
 #ifndef cmGeneratorExpressionDAGChecker_h
 #define cmGeneratorExpressionDAGChecker_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmListFileCache.h"
 
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index aeb005f..1526454 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGeneratorExpressionEvaluationFile.h"
 
-#include <cmConfigure.h>
-#include <cmsys/FStream.hxx>
+#include "cmConfigure.h"
+#include "cmsys/FStream.hxx"
 #include <sstream>
 #include <utility>
 
@@ -64,8 +64,10 @@ void cmGeneratorExpressionEvaluationFile::Generate(
       return;
     }
     std::ostringstream e;
-    e << "Evaluation file to be written multiple times for different "
-         "configurations or languages with different content:\n  "
+    e << "Evaluation file to be written multiple times with different "
+         "content. "
+         "This is generally caused by the content evaluating the "
+         "configuration type, language, or location of object files:\n "
       << outputFileName;
     lg->IssueMessage(cmake::FATAL_ERROR, e.str());
     return;
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
index 26135df..9872746 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.h
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -3,7 +3,7 @@
 #ifndef cmGeneratorExpressionEvaluationFile_h
 #define cmGeneratorExpressionEvaluationFile_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <string>
@@ -11,12 +11,7 @@
 
 #include "cmGeneratorExpression.h"
 #include "cm_auto_ptr.hxx"
-
-#if defined(_MSC_VER)
-typedef unsigned short mode_t;
-#else
-#include <sys/types.h>
-#endif
+#include "cm_sys_stat.h"
 
 class cmLocalGenerator;
 
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 41bea9b..a0a826a 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -3,7 +3,7 @@
 #ifndef cmGeneratorExpressionEvaluator_h
 #define cmGeneratorExpressionEvaluator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <stddef.h>
 #include <string>
@@ -30,8 +30,7 @@ struct cmGeneratorExpressionEvaluator
                                cmGeneratorExpressionDAGChecker*) const = 0;
 
 private:
-  cmGeneratorExpressionEvaluator(const cmGeneratorExpressionEvaluator&);
-  void operator=(const cmGeneratorExpressionEvaluator&);
+  CM_DISABLE_COPY(cmGeneratorExpressionEvaluator)
 };
 
 struct TextContent : public cmGeneratorExpressionEvaluator
diff --git a/Source/cmGeneratorExpressionLexer.h b/Source/cmGeneratorExpressionLexer.h
index cac255d..e53f0b5 100644
--- a/Source/cmGeneratorExpressionLexer.h
+++ b/Source/cmGeneratorExpressionLexer.h
@@ -3,7 +3,7 @@
 #ifndef cmGeneratorExpressionLexer_h
 #define cmGeneratorExpressionLexer_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <stddef.h>
 #include <string>
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 66202df..a57d2a0 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -14,18 +14,17 @@
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
-#include "cmSourceFile.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cm_auto_ptr.hxx"
 #include "cmake.h"
 
+#include "cmConfigure.h"
+#include "cmsys/RegularExpression.hxx"
+#include "cmsys/String.h"
 #include <algorithm>
 #include <assert.h>
-#include <cmConfigure.h>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/String.h>
 #include <errno.h>
 #include <map>
 #include <set>
@@ -411,6 +410,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
           e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044);
           context->LG->GetCMakeInstance()->IssueMessage(
             cmake::AUTHOR_WARNING, e.str(), context->Backtrace);
+          CM_FALLTHROUGH;
         }
         case cmPolicies::OLD:
           return "1";
@@ -1227,15 +1227,6 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
                        cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
     CM_OVERRIDE
   {
-    if (!context->EvaluateForBuildsystem) {
-      std::ostringstream e;
-      e << "The evaluation of the TARGET_OBJECTS generator expression "
-           "is only suitable for consumption by CMake.  It is not suitable "
-           "for writing out elsewhere.";
-      reportError(context, content->GetOriginalExpression(), e.str());
-      return std::string();
-    }
-
     std::string tgtName = parameters.front();
     cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
     if (!gt) {
@@ -1252,40 +1243,60 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
       reportError(context, content->GetOriginalExpression(), e.str());
       return std::string();
     }
+    if (!context->EvaluateForBuildsystem) {
+      cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
+      std::string reason;
+      if (!gg->HasKnownObjectFileLocation(&reason)) {
+        std::ostringstream e;
+        e << "The evaluation of the TARGET_OBJECTS generator expression "
+             "is only suitable for consumption by CMake (limited"
+          << reason << ").  "
+                       "It is not suitable for writing out elsewhere.";
+        reportError(context, content->GetOriginalExpression(), e.str());
+        return std::string();
+      }
+    }
 
-    std::vector<cmSourceFile const*> objectSources;
-    gt->GetObjectSources(objectSources, context->Config);
-    std::map<cmSourceFile const*, std::string> mapping;
-
-    for (std::vector<cmSourceFile const*>::const_iterator it =
-           objectSources.begin();
-         it != objectSources.end(); ++it) {
-      mapping[*it];
-    }
-
-    gt->LocalGenerator->ComputeObjectFilenames(mapping, gt);
-
-    std::string obj_dir = gt->ObjectDirectory;
-    std::string result;
-    const char* sep = "";
-    for (std::vector<cmSourceFile const*>::const_iterator it =
-           objectSources.begin();
-         it != objectSources.end(); ++it) {
-      // Find the object file name corresponding to this source file.
-      std::map<cmSourceFile const*, std::string>::const_iterator map_it =
-        mapping.find(*it);
-      // It must exist because we populated the mapping just above.
-      assert(!map_it->second.empty());
-      result += sep;
-      std::string objFile = obj_dir + map_it->second;
-      cmSourceFile* sf =
-        context->LG->GetMakefile()->GetOrCreateSource(objFile, true);
-      sf->SetObjectLibrary(tgtName);
-      sf->SetProperty("EXTERNAL_OBJECT", "1");
-      result += objFile;
-      sep = ";";
+    std::vector<std::string> objects;
+
+    if (gt->IsImported()) {
+      const char* loc = CM_NULLPTR;
+      const char* imp = CM_NULLPTR;
+      std::string suffix;
+      if (gt->Target->GetMappedConfig(context->Config, &loc, &imp, suffix)) {
+        cmSystemTools::ExpandListArgument(loc, objects);
+      }
+      context->HadContextSensitiveCondition = true;
+    } else {
+      gt->GetTargetObjectNames(context->Config, objects);
+
+      std::string obj_dir;
+      if (context->EvaluateForBuildsystem) {
+        // Use object file directory with buildsystem placeholder.
+        obj_dir = gt->ObjectDirectory;
+        // Here we assume that the set of object files produced
+        // by an object library does not vary with configuration
+        // and do not set HadContextSensitiveCondition to true.
+      } else {
+        // Use object file directory with per-config location.
+        obj_dir = gt->GetObjectDirectory(context->Config);
+        context->HadContextSensitiveCondition = true;
+      }
+
+      for (std::vector<std::string>::iterator oi = objects.begin();
+           oi != objects.end(); ++oi) {
+        *oi = obj_dir + *oi;
+      }
     }
-    return result;
+
+    // Create the cmSourceFile instances in the referencing directory.
+    cmMakefile* mf = context->LG->GetMakefile();
+    for (std::vector<std::string>::iterator oi = objects.begin();
+         oi != objects.end(); ++oi) {
+      mf->AddTargetObject(tgtName, *oi);
+    }
+
+    return cmJoin(objects, ";");
   }
 } targetObjectsNode;
 
@@ -1449,6 +1460,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
             lg->IssueMessage(
               cmake::AUTHOR_WARNING,
               cmPolicies::GetPolicyWarning(policyForString(policy)));
+            CM_FALLTHROUGH;
           case cmPolicies::REQUIRED_IF_USED:
           case cmPolicies::REQUIRED_ALWAYS:
           case cmPolicies::OLD:
@@ -1504,6 +1516,8 @@ class ArtifactNameTag;
 class ArtifactPathTag;
 class ArtifactPdbTag;
 class ArtifactSonameTag;
+class ArtifactBundleDirTag;
+class ArtifactBundleContentDirTag;
 
 template <typename ArtifactT>
 struct TargetFilesystemArtifactResultCreator
@@ -1595,7 +1609,60 @@ struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
                     "executables with ENABLE_EXPORTS.");
       return std::string();
     }
-    return target->GetFullPath(context->Config, target->HasImportLibrary());
+    cmStateEnums::ArtifactType artifact = target->HasImportLibrary()
+      ? cmStateEnums::ImportLibraryArtifact
+      : cmStateEnums::RuntimeBinaryArtifact;
+    return target->GetFullPath(context->Config, artifact);
+  }
+};
+
+template <>
+struct TargetFilesystemArtifactResultCreator<ArtifactBundleDirTag>
+{
+  static std::string Create(cmGeneratorTarget* target,
+                            cmGeneratorExpressionContext* context,
+                            const GeneratorExpressionContent* content)
+  {
+    if (target->IsImported()) {
+      ::reportError(context, content->GetOriginalExpression(),
+                    "TARGET_BUNDLE_DIR not allowed for IMPORTED targets.");
+      return std::string();
+    }
+    if (!target->IsBundleOnApple()) {
+      ::reportError(context, content->GetOriginalExpression(),
+                    "TARGET_BUNDLE_DIR is allowed only for Bundle targets.");
+      return std::string();
+    }
+
+    std::string outpath = target->GetDirectory(context->Config) + '/';
+    return target->BuildBundleDirectory(outpath, context->Config,
+                                        cmGeneratorTarget::BundleDirLevel);
+  }
+};
+
+template <>
+struct TargetFilesystemArtifactResultCreator<ArtifactBundleContentDirTag>
+{
+  static std::string Create(cmGeneratorTarget* target,
+                            cmGeneratorExpressionContext* context,
+                            const GeneratorExpressionContent* content)
+  {
+    if (target->IsImported()) {
+      ::reportError(
+        context, content->GetOriginalExpression(),
+        "TARGET_BUNDLE_CONTENT_DIR not allowed for IMPORTED targets.");
+      return std::string();
+    }
+    if (!target->IsBundleOnApple()) {
+      ::reportError(
+        context, content->GetOriginalExpression(),
+        "TARGET_BUNDLE_CONTENT_DIR is allowed only for Bundle targets.");
+      return std::string();
+    }
+
+    std::string outpath = target->GetDirectory(context->Config) + '/';
+    return target->BuildBundleDirectory(outpath, context->Config,
+                                        cmGeneratorTarget::ContentLevel);
   }
 };
 
@@ -1606,7 +1673,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactNameTag>
                             cmGeneratorExpressionContext* context,
                             const GeneratorExpressionContent* /*unused*/)
   {
-    return target->GetFullPath(context->Config, false, true);
+    return target->GetFullPath(context->Config,
+                               cmStateEnums::RuntimeBinaryArtifact, true);
   }
 };
 
@@ -1716,6 +1784,13 @@ static const TargetFilesystemArtifactNodeGroup<ArtifactSonameTag>
 static const TargetFilesystemArtifactNodeGroup<ArtifactPdbTag>
   targetPdbNodeGroup;
 
+static const TargetFilesystemArtifact<ArtifactBundleDirTag, ArtifactPathTag>
+  targetBundleDirNode;
+
+static const TargetFilesystemArtifact<ArtifactBundleContentDirTag,
+                                      ArtifactPathTag>
+  targetBundleContentDirNode;
+
 static const struct ShellPathNode : public cmGeneratorExpressionNode
 {
   ShellPathNode() {}
@@ -1772,6 +1847,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
     nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerNodeGroup.FileDir;
     nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameNodeGroup.FileDir;
     nodeMap["TARGET_PDB_FILE_DIR"] = &targetPdbNodeGroup.FileDir;
+    nodeMap["TARGET_BUNDLE_DIR"] = &targetBundleDirNode;
+    nodeMap["TARGET_BUNDLE_CONTENT_DIR"] = &targetBundleContentDirNode;
     nodeMap["STREQUAL"] = &strEqualNode;
     nodeMap["EQUAL"] = &equalNode;
     nodeMap["LOWER_CASE"] = &lowerCaseNode;
diff --git a/Source/cmGeneratorExpressionNode.h b/Source/cmGeneratorExpressionNode.h
index ecf745e..ece1c11 100644
--- a/Source/cmGeneratorExpressionNode.h
+++ b/Source/cmGeneratorExpressionNode.h
@@ -3,7 +3,7 @@
 #ifndef cmGeneratorExpressionNode_h
 #define cmGeneratorExpressionNode_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h
index e30cb20..633381c 100644
--- a/Source/cmGeneratorExpressionParser.h
+++ b/Source/cmGeneratorExpressionParser.h
@@ -3,7 +3,7 @@
 #ifndef cmGeneratorExpressionParser_h
 #define cmGeneratorExpressionParser_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <vector>
 
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 3fe5c83..329c7a9 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGeneratorTarget.h"
 
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
-#include <cmsys/RegularExpression.hxx>
 #include <errno.h>
 #include <iterator>
 #include <queue>
@@ -75,199 +75,8 @@ public:
 };
 cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
 
-void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib,
-                     cmGeneratorTarget const* target, cmake* cm)
-{
-  if (!badObjLib.empty()) {
-    std::ostringstream e;
-    e << "OBJECT library \"" << target->GetName() << "\" contains:\n";
-    for (std::vector<cmSourceFile*>::const_iterator i = badObjLib.begin();
-         i != badObjLib.end(); ++i) {
-      e << "  " << (*i)->GetLocation().GetName() << "\n";
-    }
-    e << "but may contain only sources that compile, header files, and "
-         "other files that would not affect linking of a normal library.";
-    cm->IssueMessage(cmake::FATAL_ERROR, e.str(), target->GetBacktrace());
-  }
-}
-
-struct ObjectSourcesTag
-{
-};
-struct CustomCommandsTag
-{
-};
-struct ExtraSourcesTag
-{
-};
-struct HeaderSourcesTag
-{
-};
-struct ExternalObjectsTag
-{
-};
-struct IDLSourcesTag
-{
-};
-struct ResxTag
-{
-};
-struct ModuleDefinitionFileTag
-{
-};
-struct AppManifestTag
-{
-};
-struct ManifestsTag
-{
-};
-struct CertificatesTag
-{
-};
-struct XamlTag
-{
-};
-
-template <typename Tag, typename OtherTag>
-struct IsSameTag
-{
-  enum
-  {
-    Result = false
-  };
-};
-
-template <typename Tag>
-struct IsSameTag<Tag, Tag>
-{
-  enum
-  {
-    Result = true
-  };
-};
-
-template <bool>
-struct DoAccept
-{
-  template <typename T>
-  static void Do(T& /*unused*/, cmSourceFile* /*unused*/)
-  {
-  }
-};
-
-template <>
-struct DoAccept<true>
-{
-  static void Do(std::vector<cmSourceFile const*>& files, cmSourceFile* f)
-  {
-    files.push_back(f);
-  }
-  static void Do(cmGeneratorTarget::ResxData& data, cmSourceFile* f)
-  {
-    // Build and save the name of the corresponding .h file
-    // This relationship will be used later when building the project files.
-    // Both names would have been auto generated from Visual Studio
-    // where the user supplied the file name and Visual Studio
-    // appended the suffix.
-    std::string resx = f->GetFullPath();
-    std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
-    data.ExpectedResxHeaders.insert(hFileName);
-    data.ResxSources.push_back(f);
-  }
-  static void Do(cmGeneratorTarget::XamlData& data, cmSourceFile* f)
-  {
-    // Build and save the name of the corresponding .h and .cpp file
-    // This relationship will be used later when building the project files.
-    // Both names would have been auto generated from Visual Studio
-    // where the user supplied the file name and Visual Studio
-    // appended the suffix.
-    std::string xaml = f->GetFullPath();
-    std::string hFileName = xaml + ".h";
-    std::string cppFileName = xaml + ".cpp";
-    data.ExpectedXamlHeaders.insert(hFileName);
-    data.ExpectedXamlSources.insert(cppFileName);
-    data.XamlSources.push_back(f);
-  }
-  static void Do(std::string& data, cmSourceFile* f)
-  {
-    data = f->GetFullPath();
-  }
-};
-
-template <typename Tag, typename DataType = std::vector<cmSourceFile const*> >
-struct TagVisitor
-{
-  DataType& Data;
-  std::vector<cmSourceFile*> BadObjLibFiles;
-  cmGeneratorTarget const* Target;
-  cmGlobalGenerator* GlobalGenerator;
-  cmsys::RegularExpression Header;
-  bool IsObjLib;
-
-  TagVisitor(cmGeneratorTarget const* target, DataType& data)
-    : Data(data)
-    , Target(target)
-    , GlobalGenerator(target->GetLocalGenerator()->GetGlobalGenerator())
-    , Header(CM_HEADER_REGEX)
-    , IsObjLib(target->GetType() == cmStateEnums::OBJECT_LIBRARY)
-  {
-  }
-
-  ~TagVisitor()
-  {
-    reportBadObjLib(this->BadObjLibFiles, this->Target,
-                    this->GlobalGenerator->GetCMakeInstance());
-  }
-
-  void Accept(cmSourceFile* sf)
-  {
-    std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
-    if (sf->GetCustomCommand()) {
-      DoAccept<IsSameTag<Tag, CustomCommandsTag>::Result>::Do(this->Data, sf);
-    } else if (this->Target->GetType() == cmStateEnums::UTILITY) {
-      DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
-    } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
-      DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
-    } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
-      DoAccept<IsSameTag<Tag, ExternalObjectsTag>::Result>::Do(this->Data, sf);
-      if (this->IsObjLib) {
-        this->BadObjLibFiles.push_back(sf);
-      }
-    } else if (!sf->GetLanguage().empty()) {
-      DoAccept<IsSameTag<Tag, ObjectSourcesTag>::Result>::Do(this->Data, sf);
-    } else if (ext == "def") {
-      DoAccept<IsSameTag<Tag, ModuleDefinitionFileTag>::Result>::Do(this->Data,
-                                                                    sf);
-      if (this->IsObjLib) {
-        this->BadObjLibFiles.push_back(sf);
-      }
-    } else if (ext == "idl") {
-      DoAccept<IsSameTag<Tag, IDLSourcesTag>::Result>::Do(this->Data, sf);
-      if (this->IsObjLib) {
-        this->BadObjLibFiles.push_back(sf);
-      }
-    } else if (ext == "resx") {
-      DoAccept<IsSameTag<Tag, ResxTag>::Result>::Do(this->Data, sf);
-    } else if (ext == "appxmanifest") {
-      DoAccept<IsSameTag<Tag, AppManifestTag>::Result>::Do(this->Data, sf);
-    } else if (ext == "manifest") {
-      DoAccept<IsSameTag<Tag, ManifestsTag>::Result>::Do(this->Data, sf);
-    } else if (ext == "pfx") {
-      DoAccept<IsSameTag<Tag, CertificatesTag>::Result>::Do(this->Data, sf);
-    } else if (ext == "xaml") {
-      DoAccept<IsSameTag<Tag, XamlTag>::Result>::Do(this->Data, sf);
-    } else if (this->Header.find(sf->GetFullPath().c_str())) {
-      DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
-    } else if (this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) {
-      DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
-    } else {
-      DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
-    }
-  }
-};
-
 void CreatePropertyGeneratorExpressions(
-  cmStringRange const& entries, cmBacktraceRange const& backtraces,
+  cmStringRange entries, cmBacktraceRange backtraces,
   std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items,
   bool evaluateForBuildsystem = false)
 {
@@ -286,6 +95,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
   , FortranModuleDirectoryCreated(false)
   , SourceFileFlagsConstructed(false)
   , PolicyWarnedCMP0022(false)
+  , PolicyReportedCMP0069(false)
   , DebugIncludesDone(false)
   , DebugCompileOptionsDone(false)
   , DebugCompileFeaturesDone(false)
@@ -406,52 +216,60 @@ const char* cmGeneratorTarget::GetProperty(const std::string& prop) const
   return this->Target->GetProperty(prop);
 }
 
-const char* cmGeneratorTarget::GetOutputTargetType(bool implib) const
+const char* cmGeneratorTarget::GetOutputTargetType(
+  cmStateEnums::ArtifactType artifact) const
 {
   switch (this->GetType()) {
     case cmStateEnums::SHARED_LIBRARY:
       if (this->IsDLLPlatform()) {
-        if (implib) {
-          // A DLL import library is treated as an archive target.
-          return "ARCHIVE";
+        switch (artifact) {
+          case cmStateEnums::RuntimeBinaryArtifact:
+            // A DLL shared library is treated as a runtime target.
+            return "RUNTIME";
+          case cmStateEnums::ImportLibraryArtifact:
+            // A DLL import library is treated as an archive target.
+            return "ARCHIVE";
         }
-        // A DLL shared library is treated as a runtime target.
-        return "RUNTIME";
       } else {
         // For non-DLL platforms shared libraries are treated as
         // library targets.
         return "LIBRARY";
       }
+      break;
     case cmStateEnums::STATIC_LIBRARY:
       // Static libraries are always treated as archive targets.
       return "ARCHIVE";
     case cmStateEnums::MODULE_LIBRARY:
-      if (implib) {
-        // Module libraries are always treated as library targets.
-        return "ARCHIVE";
-      } else {
-        // Module import libraries are treated as archive targets.
-        return "LIBRARY";
+      switch (artifact) {
+        case cmStateEnums::RuntimeBinaryArtifact:
+          // Module import libraries are treated as archive targets.
+          return "LIBRARY";
+        case cmStateEnums::ImportLibraryArtifact:
+          // Module libraries are always treated as library targets.
+          return "ARCHIVE";
       }
+      break;
     case cmStateEnums::EXECUTABLE:
-      if (implib) {
-        // Executable import libraries are treated as archive targets.
-        return "ARCHIVE";
-      } else {
-        // Executables are always treated as runtime targets.
-        return "RUNTIME";
+      switch (artifact) {
+        case cmStateEnums::RuntimeBinaryArtifact:
+          // Executables are always treated as runtime targets.
+          return "RUNTIME";
+        case cmStateEnums::ImportLibraryArtifact:
+          // Executable import libraries are treated as archive targets.
+          return "ARCHIVE";
       }
+      break;
     default:
       break;
   }
   return "";
 }
 
-std::string cmGeneratorTarget::GetOutputName(const std::string& config,
-                                             bool implib) const
+std::string cmGeneratorTarget::GetOutputName(
+  const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   // Lookup/compute/cache the output name for this configuration.
-  OutputNameKey key(config, implib);
+  OutputNameKey key(config, artifact);
   cmGeneratorTarget::OutputNameMapType::iterator i =
     this->OutputNameMap.find(key);
   if (i == this->OutputNameMap.end()) {
@@ -461,7 +279,7 @@ std::string cmGeneratorTarget::GetOutputName(const std::string& config,
 
     // Compute output name.
     std::vector<std::string> props;
-    std::string type = this->GetOutputTargetType(implib);
+    std::string type = this->GetOutputTargetType(artifact);
     std::string configUpper = cmSystemTools::UpperCase(config);
     if (!type.empty() && !configUpper.empty()) {
       // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
@@ -515,7 +333,7 @@ void cmGeneratorTarget::AddSourceCommon(const std::string& src)
   CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(src);
   cge->SetEvaluateForBuildsystem(true);
   this->SourceEntries.push_back(new TargetPropertyEntry(cge));
-  this->SourceFilesMap.clear();
+  this->KindedSourcesMap.clear();
   this->LinkImplementationLanguageIsContextDependent = true;
 }
 
@@ -587,27 +405,22 @@ static void handleSystemIncludesDep(
 }
 
 /* clang-format off */
-#define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE)                                  \
+#define IMPLEMENT_VISIT(KIND)                                                 \
   {                                                                           \
-    std::vector<cmSourceFile*> sourceFiles;                                   \
-    this->GetSourceFiles(sourceFiles, config);                                \
-    TagVisitor< DATA##Tag DATATYPE > visitor(this, data);                     \
-    for (std::vector<cmSourceFile*>::const_iterator si = sourceFiles.begin(); \
-         si != sourceFiles.end(); ++si) {                                     \
-      visitor.Accept(*si);                                                    \
+    KindedSources const& kinded = this->GetKindedSources(config);             \
+    for (std::vector<SourceAndKind>::const_iterator                           \
+         si = kinded.Sources.begin(); si != kinded.Sources.end(); ++si) {     \
+      if (si->Kind == KIND) {                                                 \
+        data.push_back(si->Source);                                           \
+      }                                                                       \
     }                                                                         \
   }
 /* clang-format on */
 
-#define IMPLEMENT_VISIT(DATA) IMPLEMENT_VISIT_IMPL(DATA, EMPTY)
-
-#define EMPTY
-#define COMMA ,
-
 void cmGeneratorTarget::GetObjectSources(
   std::vector<cmSourceFile const*>& data, const std::string& config) const
 {
-  IMPLEMENT_VISIT(ObjectSources);
+  IMPLEMENT_VISIT(SourceKindObjectSource);
 
   if (!this->Objects.empty()) {
     return;
@@ -656,10 +469,73 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
   return this->LocalGenerator->GetFeature(feature, config);
 }
 
-bool cmGeneratorTarget::GetFeatureAsBool(const std::string& feature,
-                                         const std::string& config) const
+bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
+                                     std::string const& config) const
 {
-  return cmSystemTools::IsOn(this->GetFeature(feature, config));
+  const char* feature = "INTERPROCEDURAL_OPTIMIZATION";
+  const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config));
+
+  if (!result) {
+    // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies
+    return false;
+  }
+
+  if (lang != "C" && lang != "CXX" && lang != "Fortran") {
+    // We do not define IPO behavior for other languages.
+    return false;
+  }
+
+  cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069();
+
+  if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) {
+    if (this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_LEGACY_BEHAVIOR")) {
+      return true;
+    }
+    if (this->PolicyReportedCMP0069) {
+      // problem is already reported, no need to issue a message
+      return false;
+    }
+    const bool in_try_compile =
+      this->LocalGenerator->GetCMakeInstance()->GetIsInTryCompile();
+    if (cmp0069 == cmPolicies::WARN && !in_try_compile) {
+      std::ostringstream w;
+      w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0069) << "\n";
+      w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target "
+        << "'" << this->GetName() << "'.";
+      this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+        cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace());
+
+      this->PolicyReportedCMP0069 = true;
+    }
+    return false;
+  }
+
+  // Note: check consistency with messages from CheckIPOSupported
+  const char* message = CM_NULLPTR;
+  if (!this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_SUPPORTED_BY_CMAKE")) {
+    message = "CMake doesn't support IPO for current compiler";
+  } else if (!this->Makefile->IsOn("_CMAKE_" + lang +
+                                   "_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) {
+    message = "Compiler doesn't support IPO";
+  } else if (!this->GlobalGenerator->IsIPOSupported()) {
+    message = "CMake doesn't support IPO for current generator";
+  }
+
+  if (!message) {
+    // No error/warning messages
+    return true;
+  }
+
+  if (this->PolicyReportedCMP0069) {
+    // problem is already reported, no need to issue a message
+    return false;
+  }
+
+  this->PolicyReportedCMP0069 = true;
+
+  this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+    cmake::FATAL_ERROR, message, this->GetBacktrace());
+  return false;
 }
 
 const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
@@ -668,6 +544,18 @@ const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
   return this->Objects[file];
 }
 
+const char* cmGeneratorTarget::GetCustomObjectExtension() const
+{
+  static std::string extension;
+  const bool has_ptx_extension =
+    this->GetPropertyAsBool("CUDA_PTX_COMPILATION");
+  if (has_ptx_extension) {
+    extension = ".ptx";
+    return extension.c_str();
+  }
+  return CM_NULLPTR;
+}
+
 void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
 {
   this->ExplicitObjectName.insert(sf);
@@ -681,84 +569,79 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
   return it != this->ExplicitObjectName.end();
 }
 
-void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile const*>& data,
-                                      const std::string& config) const
+void cmGeneratorTarget::GetModuleDefinitionSources(
+  std::vector<cmSourceFile const*>& data, const std::string& config) const
 {
-  IMPLEMENT_VISIT(IDLSources);
+  IMPLEMENT_VISIT(SourceKindModuleDefinition);
 }
 
 void cmGeneratorTarget::GetHeaderSources(
   std::vector<cmSourceFile const*>& data, const std::string& config) const
 {
-  IMPLEMENT_VISIT(HeaderSources);
+  IMPLEMENT_VISIT(SourceKindHeader);
 }
 
 void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile const*>& data,
                                         const std::string& config) const
 {
-  IMPLEMENT_VISIT(ExtraSources);
+  IMPLEMENT_VISIT(SourceKindExtra);
 }
 
 void cmGeneratorTarget::GetCustomCommands(
   std::vector<cmSourceFile const*>& data, const std::string& config) const
 {
-  IMPLEMENT_VISIT(CustomCommands);
+  IMPLEMENT_VISIT(SourceKindCustomCommand);
 }
 
 void cmGeneratorTarget::GetExternalObjects(
   std::vector<cmSourceFile const*>& data, const std::string& config) const
 {
-  IMPLEMENT_VISIT(ExternalObjects);
+  IMPLEMENT_VISIT(SourceKindExternalObject);
 }
 
-void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& srcs,
+void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& headers,
                                                const std::string& config) const
 {
-  ResxData data;
-  IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
-  srcs = data.ExpectedResxHeaders;
+  KindedSources const& kinded = this->GetKindedSources(config);
+  headers = kinded.ExpectedResxHeaders;
 }
 
-void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& srcs,
+void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& data,
                                        const std::string& config) const
 {
-  ResxData data;
-  IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
-  srcs = data.ResxSources;
+  IMPLEMENT_VISIT(SourceKindResx);
 }
 
 void cmGeneratorTarget::GetAppManifest(std::vector<cmSourceFile const*>& data,
                                        const std::string& config) const
 {
-  IMPLEMENT_VISIT(AppManifest);
+  IMPLEMENT_VISIT(SourceKindAppManifest);
 }
 
 void cmGeneratorTarget::GetManifests(std::vector<cmSourceFile const*>& data,
                                      const std::string& config) const
 {
-  IMPLEMENT_VISIT(Manifests);
+  IMPLEMENT_VISIT(SourceKindManifest);
 }
 
 void cmGeneratorTarget::GetCertificates(std::vector<cmSourceFile const*>& data,
                                         const std::string& config) const
 {
-  IMPLEMENT_VISIT(Certificates);
+  IMPLEMENT_VISIT(SourceKindCertificate);
 }
 
 void cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers,
                                                const std::string& config) const
 {
-  XamlData data;
-  IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
-  headers = data.ExpectedXamlHeaders;
+  KindedSources const& kinded = this->GetKindedSources(config);
+  headers = kinded.ExpectedXamlHeaders;
 }
 
 void cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
                                                const std::string& config) const
 {
-  XamlData data;
-  IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
-  srcs = data.ExpectedXamlSources;
+  KindedSources const& kinded = this->GetKindedSources(config);
+  srcs = kinded.ExpectedXamlSources;
 }
 
 std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
@@ -776,21 +659,20 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
   return this->UtilityItems;
 }
 
-void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& srcs,
+void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& data,
                                        const std::string& config) const
 {
-  XamlData data;
-  IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
-  srcs = data.XamlSources;
+  IMPLEMENT_VISIT(SourceKindXaml);
 }
 
 const char* cmGeneratorTarget::GetLocation(const std::string& config) const
 {
   static std::string location;
   if (this->IsImported()) {
-    location = this->Target->ImportedGetFullPath(config, false);
+    location = this->Target->ImportedGetFullPath(
+      config, cmStateEnums::RuntimeBinaryArtifact);
   } else {
-    location = this->GetFullPath(config, false);
+    location = this->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
   }
   return location.c_str();
 }
@@ -827,7 +709,8 @@ const char* cmGeneratorTarget::GetLocationForBuild() const
 {
   static std::string location;
   if (this->IsImported()) {
-    location = this->Target->ImportedGetFullPath("", false);
+    location = this->Target->ImportedGetFullPath(
+      "", cmStateEnums::RuntimeBinaryArtifact);
     return location.c_str();
   }
 
@@ -840,14 +723,14 @@ const char* cmGeneratorTarget::GetLocationForBuild() const
   }
 
   if (this->IsAppBundleOnApple()) {
-    std::string macdir = this->BuildMacContentDirectory("", "", false);
+    std::string macdir = this->BuildBundleDirectory("", "", FullLevel);
     if (!macdir.empty()) {
       location += "/";
       location += macdir;
     }
   }
   location += "/";
-  location += this->GetFullName("", false);
+  location += this->GetFullName("", cmStateEnums::RuntimeBinaryArtifact);
   return location.c_str();
 }
 
@@ -1088,24 +971,16 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
 void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
                                        const std::string& config) const
 {
-
-  // Lookup any existing link implementation for this configuration.
-  std::string key = cmSystemTools::UpperCase(config);
-
-  if (!this->LinkImplementationLanguageIsContextDependent) {
-    files = this->SourceFilesMap.begin()->second;
-    return;
-  }
-
-  SourceFilesMapType::iterator it = this->SourceFilesMap.find(key);
-  if (it != this->SourceFilesMap.end()) {
-    files = it->second;
-  } else {
+  if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+    // Since we are still configuring not all sources may exist yet,
+    // so we need to avoid full source classification because that
+    // requires the absolute paths to all sources to be determined.
+    // Since this is only for compatibility with old policies that
+    // projects should not depend on anymore, just compute the files
+    // without memoizing them.
     std::vector<std::string> srcs;
     this->GetSourceFiles(srcs, config);
-
     std::set<cmSourceFile*> emitted;
-
     for (std::vector<std::string>::const_iterator i = srcs.begin();
          i != srcs.end(); ++i) {
       cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
@@ -1113,7 +988,195 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
         files.push_back(sf);
       }
     }
-    this->SourceFilesMap[key] = files;
+    return;
+  }
+
+  KindedSources const& kinded = this->GetKindedSources(config);
+  files.reserve(kinded.Sources.size());
+  for (std::vector<SourceAndKind>::const_iterator si = kinded.Sources.begin();
+       si != kinded.Sources.end(); ++si) {
+    files.push_back(si->Source);
+  }
+}
+
+void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
+  std::vector<cmSourceFile*>& files, const std::string& config) const
+{
+  KindedSources const& kinded = this->GetKindedSources(config);
+  files.reserve(kinded.Sources.size());
+  for (std::vector<SourceAndKind>::const_iterator si = kinded.Sources.begin();
+       si != kinded.Sources.end(); ++si) {
+    if (si->Source->GetObjectLibrary().empty()) {
+      files.push_back(si->Source);
+    }
+  }
+}
+
+cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
+  std::string const& config) const
+{
+  // If we already processed one configuration and found no dependenc
+  // on configuration then always use the one result.
+  if (!this->LinkImplementationLanguageIsContextDependent) {
+    return this->KindedSourcesMap.begin()->second;
+  }
+
+  // Lookup any existing link implementation for this configuration.
+  std::string const key = cmSystemTools::UpperCase(config);
+  KindedSourcesMapType::iterator it = this->KindedSourcesMap.find(key);
+  if (it != this->KindedSourcesMap.end()) {
+    if (!it->second.Initialized) {
+      std::ostringstream e;
+      e << "The SOURCES of \"" << this->GetName()
+        << "\" use a generator expression that depends on the "
+           "SOURCES themselves.";
+      this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+        cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
+      static KindedSources empty;
+      return empty;
+    }
+    return it->second;
+  }
+
+  // Add an entry to the map for this configuration.
+  KindedSources& files = this->KindedSourcesMap[key];
+  this->ComputeKindedSources(files, config);
+  files.Initialized = true;
+  return files;
+}
+
+void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
+                                             std::string const& config) const
+{
+  // Get the source file paths by string.
+  std::vector<std::string> srcs;
+  this->GetSourceFiles(srcs, config);
+
+  cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
+  std::vector<cmSourceFile*> badObjLib;
+
+  std::set<cmSourceFile*> emitted;
+  for (std::vector<std::string>::const_iterator i = srcs.begin();
+       i != srcs.end(); ++i) {
+    // Create each source at most once.
+    cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
+    if (!emitted.insert(sf).second) {
+      continue;
+    }
+
+    // Compute the kind (classification) of this source file.
+    SourceKind kind;
+    std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
+    if (sf->GetCustomCommand()) {
+      kind = SourceKindCustomCommand;
+    } else if (this->Target->GetType() == cmStateEnums::UTILITY) {
+      kind = SourceKindExtra;
+    } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
+      kind = SourceKindHeader;
+    } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
+      kind = SourceKindExternalObject;
+      if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+        badObjLib.push_back(sf);
+      }
+    } else if (!sf->GetLanguage().empty()) {
+      kind = SourceKindObjectSource;
+    } else if (ext == "def") {
+      kind = SourceKindModuleDefinition;
+      if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+        badObjLib.push_back(sf);
+      }
+    } else if (ext == "idl") {
+      kind = SourceKindIDL;
+      if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+        badObjLib.push_back(sf);
+      }
+    } else if (ext == "resx") {
+      kind = SourceKindResx;
+      // Build and save the name of the corresponding .h file
+      // This relationship will be used later when building the project files.
+      // Both names would have been auto generated from Visual Studio
+      // where the user supplied the file name and Visual Studio
+      // appended the suffix.
+      std::string resx = sf->GetFullPath();
+      std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
+      files.ExpectedResxHeaders.insert(hFileName);
+    } else if (ext == "appxmanifest") {
+      kind = SourceKindAppManifest;
+    } else if (ext == "manifest") {
+      kind = SourceKindManifest;
+    } else if (ext == "pfx") {
+      kind = SourceKindCertificate;
+    } else if (ext == "xaml") {
+      kind = SourceKindXaml;
+      // Build and save the name of the corresponding .h and .cpp file
+      // This relationship will be used later when building the project files.
+      // Both names would have been auto generated from Visual Studio
+      // where the user supplied the file name and Visual Studio
+      // appended the suffix.
+      std::string xaml = sf->GetFullPath();
+      std::string hFileName = xaml + ".h";
+      std::string cppFileName = xaml + ".cpp";
+      files.ExpectedXamlHeaders.insert(hFileName);
+      files.ExpectedXamlSources.insert(cppFileName);
+    } else if (header_regex.find(sf->GetFullPath().c_str())) {
+      kind = SourceKindHeader;
+    } else {
+      kind = SourceKindExtra;
+    }
+
+    // Save this classified source file in the result vector.
+    SourceAndKind entry = { sf, kind };
+    files.Sources.push_back(entry);
+  }
+
+  if (!badObjLib.empty()) {
+    std::ostringstream e;
+    e << "OBJECT library \"" << this->GetName() << "\" contains:\n";
+    for (std::vector<cmSourceFile*>::const_iterator i = badObjLib.begin();
+         i != badObjLib.end(); ++i) {
+      e << "  " << (*i)->GetLocation().GetName() << "\n";
+    }
+    e << "but may contain only sources that compile, header files, and "
+         "other files that would not affect linking of a normal library.";
+    this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+      cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
+  }
+}
+
+std::vector<cmGeneratorTarget::AllConfigSource> const&
+cmGeneratorTarget::GetAllConfigSources() const
+{
+  if (this->AllConfigSources.empty()) {
+    this->ComputeAllConfigSources();
+  }
+  return this->AllConfigSources;
+}
+
+void cmGeneratorTarget::ComputeAllConfigSources() const
+{
+  std::vector<std::string> configs;
+  this->Makefile->GetConfigurations(configs);
+
+  std::map<cmSourceFile const*, size_t> index;
+
+  for (size_t ci = 0; ci < configs.size(); ++ci) {
+    KindedSources const& sources = this->GetKindedSources(configs[ci]);
+    for (std::vector<cmGeneratorTarget::SourceAndKind>::const_iterator si =
+           sources.Sources.begin();
+         si != sources.Sources.end(); ++si) {
+      std::map<cmSourceFile const*, size_t>::iterator mi =
+        index.find(si->Source);
+      if (mi == index.end()) {
+        AllConfigSource acs;
+        acs.Source = si->Source;
+        acs.Kind = si->Kind;
+        this->AllConfigSources.push_back(acs);
+        std::map<cmSourceFile const*, size_t>::value_type entry(
+          si->Source, this->AllConfigSources.size() - 1);
+        mi = index.insert(entry).first;
+      }
+      this->AllConfigSources[mi->second].Configs.push_back(ci);
+    }
   }
 }
 
@@ -1123,7 +1186,8 @@ std::string cmGeneratorTarget::GetCompilePDBName(
   std::string prefix;
   std::string base;
   std::string suffix;
-  this->GetFullNameInternal(config, false, prefix, base, suffix);
+  this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+                            prefix, base, suffix);
 
   // Check for a per-configuration output directory target property.
   std::string configUpper = cmSystemTools::UpperCase(config);
@@ -1321,8 +1385,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir(
       return false;
     }
     const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
-    bool use_install_name =
-      this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
+    bool use_install_name = this->MacOSXUseInstallNameDir();
     if (install_name && use_install_name &&
         std::string(install_name) == "@rpath") {
       install_name_is_rpath = true;
@@ -1395,6 +1458,53 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const
   return cmp0042 == cmPolicies::NEW;
 }
 
+bool cmGeneratorTarget::MacOSXUseInstallNameDir() const
+{
+  const char* build_with_install_name =
+    this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR");
+  if (build_with_install_name) {
+    return cmSystemTools::IsOn(build_with_install_name);
+  }
+
+  cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
+  if (cmp0068 == cmPolicies::NEW) {
+    return false;
+  }
+
+  bool use_install_name = this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
+
+  if (use_install_name && cmp0068 == cmPolicies::WARN) {
+    this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
+      this->GetName());
+  }
+
+  return use_install_name;
+}
+
+bool cmGeneratorTarget::CanGenerateInstallNameDir(
+  InstallNameType name_type) const
+{
+  cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
+
+  if (cmp0068 == cmPolicies::NEW) {
+    return true;
+  }
+
+  bool skip = this->Makefile->IsOn("CMAKE_SKIP_RPATH");
+  if (name_type == INSTALL_NAME_FOR_INSTALL) {
+    skip |= this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
+  } else {
+    skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH");
+  }
+
+  if (skip && cmp0068 == cmPolicies::WARN) {
+    this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget(
+      this->GetName());
+  }
+
+  return !skip;
+}
+
 std::string cmGeneratorTarget::GetSOName(const std::string& config) const
 {
   if (this->IsImported()) {
@@ -1424,19 +1534,31 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const
   return soName;
 }
 
-std::string cmGeneratorTarget::GetAppBundleDirectory(const std::string& config,
-                                                     bool contentOnly) const
+static bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level)
 {
-  std::string fpath = this->GetFullName(config, false);
+  return level == cmGeneratorTarget::FullLevel;
+}
+
+static bool shouldAddContentLevel(
+  cmGeneratorTarget::BundleDirectoryLevel level)
+{
+  return level == cmGeneratorTarget::ContentLevel || shouldAddFullLevel(level);
+}
+
+std::string cmGeneratorTarget::GetAppBundleDirectory(
+  const std::string& config, BundleDirectoryLevel level) const
+{
+  std::string fpath =
+    this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact);
   fpath += ".";
   const char* ext = this->GetProperty("BUNDLE_EXTENSION");
   if (!ext) {
     ext = "app";
   }
   fpath += ext;
-  if (!this->Makefile->PlatformIsAppleIos()) {
+  if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
     fpath += "/Contents";
-    if (!contentOnly) {
+    if (shouldAddFullLevel(level)) {
       fpath += "/MacOS";
     }
   }
@@ -1449,11 +1571,11 @@ bool cmGeneratorTarget::IsBundleOnApple() const
     this->IsCFBundleOnApple();
 }
 
-std::string cmGeneratorTarget::GetCFBundleDirectory(const std::string& config,
-                                                    bool contentOnly) const
+std::string cmGeneratorTarget::GetCFBundleDirectory(
+  const std::string& config, BundleDirectoryLevel level) const
 {
   std::string fpath;
-  fpath += this->GetOutputName(config, false);
+  fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
   fpath += ".";
   const char* ext = this->GetProperty("BUNDLE_EXTENSION");
   if (!ext) {
@@ -1464,63 +1586,64 @@ std::string cmGeneratorTarget::GetCFBundleDirectory(const std::string& config,
     }
   }
   fpath += ext;
-  if (!this->Makefile->PlatformIsAppleIos()) {
+  if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
     fpath += "/Contents";
-    if (!contentOnly) {
+    if (shouldAddFullLevel(level)) {
       fpath += "/MacOS";
     }
   }
   return fpath;
 }
 
-std::string cmGeneratorTarget::GetFrameworkDirectory(const std::string& config,
-                                                     bool rootDir) const
+std::string cmGeneratorTarget::GetFrameworkDirectory(
+  const std::string& config, BundleDirectoryLevel level) const
 {
   std::string fpath;
-  fpath += this->GetOutputName(config, false);
+  fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
   fpath += ".";
   const char* ext = this->GetProperty("BUNDLE_EXTENSION");
   if (!ext) {
     ext = "framework";
   }
   fpath += ext;
-  if (!rootDir && !this->Makefile->PlatformIsAppleIos()) {
+  if (shouldAddFullLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
     fpath += "/Versions/";
     fpath += this->GetFrameworkVersion();
   }
   return fpath;
 }
 
-std::string cmGeneratorTarget::GetFullName(const std::string& config,
-                                           bool implib) const
+std::string cmGeneratorTarget::GetFullName(
+  const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   if (this->IsImported()) {
-    return this->GetFullNameImported(config, implib);
+    return this->GetFullNameImported(config, artifact);
   }
-  return this->GetFullNameInternal(config, implib);
+  return this->GetFullNameInternal(config, artifact);
 }
 
 std::string cmGeneratorTarget::GetInstallNameDirForBuildTree(
   const std::string& config) const
 {
-  // If building directly for installation then the build tree install_name
-  // is the same as the install tree.
-  if (this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) {
-    return this->GetInstallNameDirForInstallTree();
-  }
+  if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
 
-  // Use the build tree directory for the target.
-  if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") &&
-      !this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
-      !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) {
-    std::string dir;
-    if (this->MacOSXRpathInstallNameDirDefault()) {
-      dir = "@rpath";
-    } else {
-      dir = this->GetDirectory(config);
+    // If building directly for installation then the build tree install_name
+    // is the same as the install tree.
+    if (this->MacOSXUseInstallNameDir()) {
+      return this->GetInstallNameDirForInstallTree();
+    }
+
+    // Use the build tree directory for the target.
+    if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_BUILD)) {
+      std::string dir;
+      if (this->MacOSXRpathInstallNameDirDefault()) {
+        dir = "@rpath";
+      } else {
+        dir = this->GetDirectory(config);
+      }
+      dir += "/";
+      return dir;
     }
-    dir += "/";
-    return dir;
   }
   return "";
 }
@@ -1531,8 +1654,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
     std::string dir;
     const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
 
-    if (!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
-        !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) {
+    if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
       if (install_name_dir && *install_name_dir) {
         dir = install_name_dir;
         dir += "/";
@@ -1790,44 +1912,43 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
   }
 }
 
-void cmGeneratorTarget::GetFullNameComponents(std::string& prefix,
-                                              std::string& base,
-                                              std::string& suffix,
-                                              const std::string& config,
-                                              bool implib) const
+void cmGeneratorTarget::GetFullNameComponents(
+  std::string& prefix, std::string& base, std::string& suffix,
+  const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
-  this->GetFullNameInternal(config, implib, prefix, base, suffix);
+  this->GetFullNameInternal(config, artifact, prefix, base, suffix);
 }
 
-std::string cmGeneratorTarget::BuildMacContentDirectory(
-  const std::string& base, const std::string& config, bool contentOnly) const
+std::string cmGeneratorTarget::BuildBundleDirectory(
+  const std::string& base, const std::string& config,
+  BundleDirectoryLevel level) const
 {
   std::string fpath = base;
   if (this->IsAppBundleOnApple()) {
-    fpath += this->GetAppBundleDirectory(config, contentOnly);
+    fpath += this->GetAppBundleDirectory(config, level);
   }
   if (this->IsFrameworkOnApple()) {
-    fpath += this->GetFrameworkDirectory(config, contentOnly);
+    fpath += this->GetFrameworkDirectory(config, level);
   }
   if (this->IsCFBundleOnApple()) {
-    fpath += this->GetCFBundleDirectory(config, contentOnly);
+    fpath += this->GetCFBundleDirectory(config, level);
   }
   return fpath;
 }
 
 std::string cmGeneratorTarget::GetMacContentDirectory(
-  const std::string& config, bool implib) const
+  const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   // Start with the output directory for the target.
-  std::string fpath = this->GetDirectory(config, implib);
+  std::string fpath = this->GetDirectory(config, artifact);
   fpath += "/";
-  bool contentOnly = true;
+  BundleDirectoryLevel level = ContentLevel;
   if (this->IsFrameworkOnApple()) {
     // additional files with a framework go into the version specific
     // directory
-    contentOnly = false;
+    level = FullLevel;
   }
-  fpath = this->BuildMacContentDirectory(fpath, config, contentOnly);
+  fpath = this->BuildBundleDirectory(fpath, config, level);
   return fpath;
 }
 
@@ -1880,57 +2001,51 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
   return &i->second;
 }
 
-cmSourceFile const* cmGeneratorTarget::GetModuleDefinitionFile(
-  const std::string& config) const
+cmGeneratorTarget::ModuleDefinitionInfo const*
+cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const
 {
-  std::vector<cmSourceFile const*> data;
-  IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile,
-                       COMMA std::vector<cmSourceFile const*>)
-  if (!data.empty()) {
-    return data.front();
+  // A module definition file only makes sense on certain target types.
+  if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+      this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+      !this->IsExecutableWithExports()) {
+    return CM_NULLPTR;
   }
 
-  return CM_NULLPTR;
+  // Lookup/compute/cache the compile information for this configuration.
+  std::string config_upper;
+  if (!config.empty()) {
+    config_upper = cmSystemTools::UpperCase(config);
+  }
+  ModuleDefinitionInfoMapType::const_iterator i =
+    this->ModuleDefinitionInfoMap.find(config_upper);
+  if (i == this->ModuleDefinitionInfoMap.end()) {
+    ModuleDefinitionInfo info;
+    this->ComputeModuleDefinitionInfo(config, info);
+    ModuleDefinitionInfoMapType::value_type entry(config_upper, info);
+    i = this->ModuleDefinitionInfoMap.insert(entry).first;
+  }
+  return &i->second;
 }
 
-bool cmGeneratorTarget::IsDLLPlatform() const
+void cmGeneratorTarget::ComputeModuleDefinitionInfo(
+  std::string const& config, ModuleDefinitionInfo& info) const
 {
-  return this->DLLPlatform;
+  this->GetModuleDefinitionSources(info.Sources, config);
+  info.WindowsExportAllSymbols =
+    this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
+    this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
+  info.DefFileGenerated =
+    info.WindowsExportAllSymbols || info.Sources.size() > 1;
+  if (info.DefFileGenerated) {
+    info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
+  } else if (!info.Sources.empty()) {
+    info.DefFile = info.Sources.front()->GetFullPath();
+  }
 }
 
-void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs,
-                                           const std::string& config) const
+bool cmGeneratorTarget::IsDLLPlatform() const
 {
-  std::vector<cmSourceFile const*> objectFiles;
-  this->GetExternalObjects(objectFiles, config);
-  std::vector<cmGeneratorTarget*> objectLibraries;
-  for (std::vector<cmSourceFile const*>::const_iterator it =
-         objectFiles.begin();
-       it != objectFiles.end(); ++it) {
-    std::string objLib = (*it)->GetObjectLibrary();
-    if (cmGeneratorTarget* tgt =
-          this->LocalGenerator->FindGeneratorTargetToUse(objLib)) {
-      objectLibraries.push_back(tgt);
-    }
-  }
-
-  std::vector<cmGeneratorTarget*>::const_iterator end =
-    cmRemoveDuplicates(objectLibraries);
-
-  for (std::vector<cmGeneratorTarget*>::const_iterator ti =
-         objectLibraries.begin();
-       ti != end; ++ti) {
-    cmGeneratorTarget* ogt = *ti;
-    std::vector<cmSourceFile const*> objectSources;
-    ogt->GetObjectSources(objectSources, config);
-    for (std::vector<cmSourceFile const*>::const_iterator si =
-           objectSources.begin();
-         si != objectSources.end(); ++si) {
-      std::string obj = ogt->ObjectDirectory;
-      obj += ogt->Objects[*si];
-      objs.push_back(obj);
-    }
-  }
+  return this->DLLPlatform;
 }
 
 void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
@@ -2317,19 +2432,29 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
   }
 }
 
+//----------------------------------------------------------------------------
+std::string cmGeneratorTarget::GetFeatureSpecificLinkRuleVariable(
+  std::string const& var, std::string const& lang,
+  std::string const& config) const
+{
+  if (this->IsIPOEnabled(lang, config)) {
+    std::string varIPO = var + "_IPO";
+    if (this->Makefile->IsDefinitionSet(varIPO)) {
+      return varIPO;
+    }
+  }
+
+  return var;
+}
+
+//----------------------------------------------------------------------------
 std::string cmGeneratorTarget::GetCreateRuleVariable(
   std::string const& lang, std::string const& config) const
 {
   switch (this->GetType()) {
     case cmStateEnums::STATIC_LIBRARY: {
       std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY";
-      if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION", config)) {
-        std::string varIPO = var + "_IPO";
-        if (this->Makefile->GetDefinition(varIPO)) {
-          return varIPO;
-        }
-      }
-      return var;
+      return this->GetFeatureSpecificLinkRuleVariable(var, lang, config);
     }
     case cmStateEnums::SHARED_LIBRARY:
       return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY";
@@ -2374,6 +2499,7 @@ static void processIncludeDirectories(
           switch (tgt->GetPolicyStatusCMP0027()) {
             case cmPolicies::WARN:
               e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n";
+              CM_FALLTHROUGH;
             case cmPolicies::OLD:
               messageType = cmake::AUTHOR_WARNING;
               break;
@@ -2518,18 +2644,6 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
 
   cmDeleteAll(linkInterfaceIncludeDirectoriesEntries);
 
-  // Add standard include directories for this language.
-  std::string const standardIncludesVar =
-    "CMAKE_" + lang + "_STANDARD_INCLUDE_DIRECTORIES";
-  std::string const standardIncludes =
-    this->Makefile->GetSafeDefinition(standardIncludesVar);
-  std::vector<std::string>::size_type const before = includes.size();
-  cmSystemTools::ExpandListArgument(standardIncludes, includes);
-  for (std::vector<std::string>::iterator i = includes.begin() + before;
-       i != includes.end(); ++i) {
-    cmSystemTools::ConvertToUnixSlashes(*i);
-  }
-
   return includes;
 }
 
@@ -2730,6 +2844,7 @@ void cmGeneratorTarget::GetCompileDefinitions(
           std::ostringstream e;
           e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043);
           this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+          CM_FALLTHROUGH;
         }
         case cmPolicies::OLD: {
           cmGeneratorExpression ge;
@@ -2777,7 +2892,8 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
   }
 
   // Get the directory.
-  std::string dir = this->GetDirectory(config, false);
+  std::string dir =
+    this->GetDirectory(config, cmStateEnums::RuntimeBinaryArtifact);
 
   // Add each name.
   std::string f;
@@ -2806,13 +2922,26 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
     gg->AddToManifest(f);
   }
   if (!impName.empty()) {
-    f = this->GetDirectory(config, true);
+    f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
     f += "/";
     f += impName;
     gg->AddToManifest(f);
   }
 }
 
+bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
+{
+  std::vector<std::string> features;
+  this->GetCompileFeatures(features, config);
+  for (std::vector<std::string>::const_iterator it = features.begin();
+       it != features.end(); ++it) {
+    if (!this->Makefile->AddRequiredTargetFeature(this->Target, *it)) {
+      return false;
+    }
+  }
+  return true;
+}
+
 std::string cmGeneratorTarget::GetImportedLibName(
   std::string const& config) const
 {
@@ -2824,32 +2953,39 @@ std::string cmGeneratorTarget::GetImportedLibName(
 }
 
 std::string cmGeneratorTarget::GetFullPath(const std::string& config,
-                                           bool implib, bool realname) const
+                                           cmStateEnums::ArtifactType artifact,
+                                           bool realname) const
 {
   if (this->IsImported()) {
-    return this->Target->ImportedGetFullPath(config, implib);
+    return this->Target->ImportedGetFullPath(config, artifact);
   }
-  return this->NormalGetFullPath(config, implib, realname);
+  return this->NormalGetFullPath(config, artifact, realname);
 }
 
-std::string cmGeneratorTarget::NormalGetFullPath(const std::string& config,
-                                                 bool implib,
-                                                 bool realname) const
+std::string cmGeneratorTarget::NormalGetFullPath(
+  const std::string& config, cmStateEnums::ArtifactType artifact,
+  bool realname) const
 {
-  std::string fpath = this->GetDirectory(config, implib);
+  std::string fpath = this->GetDirectory(config, artifact);
   fpath += "/";
   if (this->IsAppBundleOnApple()) {
-    fpath = this->BuildMacContentDirectory(fpath, config, false);
+    fpath = this->BuildBundleDirectory(fpath, config, FullLevel);
     fpath += "/";
   }
 
   // Add the full name of the target.
-  if (implib) {
-    fpath += this->GetFullName(config, true);
-  } else if (realname) {
-    fpath += this->NormalGetRealName(config);
-  } else {
-    fpath += this->GetFullName(config, false);
+  switch (artifact) {
+    case cmStateEnums::RuntimeBinaryArtifact:
+      if (realname) {
+        fpath += this->NormalGetRealName(config);
+      } else {
+        fpath +=
+          this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact);
+      }
+      break;
+    case cmStateEnums::ImportLibraryArtifact:
+      fpath += this->GetFullName(config, cmStateEnums::ImportLibraryArtifact);
+      break;
   }
   return fpath;
 }
@@ -2926,7 +3062,8 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName,
   std::string prefix;
   std::string base;
   std::string suffix;
-  this->GetFullNameInternal(config, false, prefix, base, suffix);
+  this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+                            prefix, base, suffix);
 
   // The library name.
   name = prefix + base + suffix;
@@ -2951,7 +3088,8 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName,
   // The import library name.
   if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
       this->GetType() == cmStateEnums::MODULE_LIBRARY) {
-    impName = this->GetFullNameInternal(config, true);
+    impName =
+      this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
   } else {
     impName = "";
   }
@@ -2992,7 +3130,8 @@ void cmGeneratorTarget::GetExecutableNames(std::string& name,
   std::string prefix;
   std::string base;
   std::string suffix;
-  this->GetFullNameInternal(config, false, prefix, base, suffix);
+  this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+                            prefix, base, suffix);
 
   // The executable name.
   name = prefix + base + suffix;
@@ -3012,19 +3151,20 @@ void cmGeneratorTarget::GetExecutableNames(std::string& name,
 #endif
 
   // The import library name.
-  impName = this->GetFullNameInternal(config, true);
+  impName =
+    this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
 
   // The program database file name.
   pdbName = this->GetPDBName(config);
 }
 
-std::string cmGeneratorTarget::GetFullNameInternal(const std::string& config,
-                                                   bool implib) const
+std::string cmGeneratorTarget::GetFullNameInternal(
+  const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   std::string prefix;
   std::string base;
   std::string suffix;
-  this->GetFullNameInternal(config, implib, prefix, base, suffix);
+  this->GetFullNameInternal(config, artifact, prefix, base, suffix);
   return prefix + base + suffix;
 }
 
@@ -3033,22 +3173,21 @@ const char* cmGeneratorTarget::ImportedGetLocation(
 {
   static std::string location;
   assert(this->IsImported());
-  location = this->Target->ImportedGetFullPath(config, false);
+  location = this->Target->ImportedGetFullPath(
+    config, cmStateEnums::RuntimeBinaryArtifact);
   return location.c_str();
 }
 
-std::string cmGeneratorTarget::GetFullNameImported(const std::string& config,
-                                                   bool implib) const
+std::string cmGeneratorTarget::GetFullNameImported(
+  const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   return cmSystemTools::GetFilenameName(
-    this->Target->ImportedGetFullPath(config, implib));
+    this->Target->ImportedGetFullPath(config, artifact));
 }
 
-void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
-                                            bool implib,
-                                            std::string& outPrefix,
-                                            std::string& outBase,
-                                            std::string& outSuffix) const
+void cmGeneratorTarget::GetFullNameInternal(
+  const std::string& config, cmStateEnums::ArtifactType artifact,
+  std::string& outPrefix, std::string& outBase, std::string& outSuffix) const
 {
   // Use just the target name for non-main target types.
   if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
@@ -3061,9 +3200,12 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
     return;
   }
 
+  const bool isImportedLibraryArtifact =
+    (artifact == cmStateEnums::ImportLibraryArtifact);
+
   // Return an empty name for the import library if this platform
   // does not support import libraries.
-  if (implib &&
+  if (isImportedLibraryArtifact &&
       !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
     outPrefix = "";
     outBase = "";
@@ -3076,14 +3218,16 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
   if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
       this->GetType() != cmStateEnums::MODULE_LIBRARY &&
       this->GetType() != cmStateEnums::EXECUTABLE) {
-    implib = false;
+    artifact = cmStateEnums::RuntimeBinaryArtifact;
   }
 
   // Compute the full name for main target types.
-  const char* targetPrefix = (implib ? this->GetProperty("IMPORT_PREFIX")
-                                     : this->GetProperty("PREFIX"));
-  const char* targetSuffix = (implib ? this->GetProperty("IMPORT_SUFFIX")
-                                     : this->GetProperty("SUFFIX"));
+  const char* targetPrefix =
+    (isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX")
+                               : this->GetProperty("PREFIX"));
+  const char* targetSuffix =
+    (isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX")
+                               : this->GetProperty("SUFFIX"));
   const char* configPostfix = CM_NULLPTR;
   if (!config.empty()) {
     std::string configProp = cmSystemTools::UpperCase(config);
@@ -3095,8 +3239,8 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
       configPostfix = CM_NULLPTR;
     }
   }
-  const char* prefixVar = this->Target->GetPrefixVariableInternal(implib);
-  const char* suffixVar = this->Target->GetSuffixVariableInternal(implib);
+  const char* prefixVar = this->Target->GetPrefixVariableInternal(artifact);
+  const char* suffixVar = this->Target->GetSuffixVariableInternal(artifact);
 
   // Check for language-specific default prefix and suffix.
   std::string ll = this->GetLinkerLanguage(config);
@@ -3123,20 +3267,14 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
   // frameworks have directory prefix but no suffix
   std::string fw_prefix;
   if (this->IsFrameworkOnApple()) {
-    fw_prefix = this->GetOutputName(config, false);
-    fw_prefix += ".";
-    const char* ext = this->GetProperty("BUNDLE_EXTENSION");
-    if (!ext) {
-      ext = "framework";
-    }
-    fw_prefix += ext;
+    fw_prefix = this->GetFrameworkDirectory(config, ContentLevel);
     fw_prefix += "/";
     targetPrefix = fw_prefix.c_str();
     targetSuffix = CM_NULLPTR;
   }
 
   if (this->IsCFBundleOnApple()) {
-    fw_prefix = this->GetCFBundleDirectory(config, false);
+    fw_prefix = this->GetCFBundleDirectory(config, FullLevel);
     fw_prefix += "/";
     targetPrefix = fw_prefix.c_str();
     targetSuffix = CM_NULLPTR;
@@ -3146,14 +3284,15 @@ void cmGeneratorTarget::GetFullNameInternal(const std::string& config,
   outPrefix = targetPrefix ? targetPrefix : "";
 
   // Append the target name or property-specified name.
-  outBase += this->GetOutputName(config, implib);
+  outBase += this->GetOutputName(config, artifact);
 
   // Append the per-configuration postfix.
   outBase += configPostfix ? configPostfix : "";
 
   // Name shared libraries with their version number on some platforms.
   if (const char* soversion = this->GetProperty("SOVERSION")) {
-    if (this->GetType() == cmStateEnums::SHARED_LIBRARY && !implib &&
+    if (this->GetType() == cmStateEnums::SHARED_LIBRARY &&
+        !isImportedLibraryArtifact &&
         this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) {
       outBase += "-";
       outBase += soversion;
@@ -3175,7 +3314,8 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
   std::string prefix;
   std::string base;
   std::string suffix;
-  this->GetFullNameInternal(config, false, prefix, base, suffix);
+  this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
+                            prefix, base, suffix);
 
   std::vector<std::string> props;
   std::string configUpper = cmSystemTools::UpperCase(config);
@@ -3197,6 +3337,46 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
   return prefix + base + ".pdb";
 }
 
+std::string cmGeneratorTarget::GetObjectDirectory(
+  std::string const& config) const
+{
+  std::string obj_dir =
+    this->GlobalGenerator->ExpandCFGIntDir(this->ObjectDirectory, config);
+#if defined(__APPLE__)
+  // find and replace $(PROJECT_NAME) xcode placeholder
+  const std::string projectName = this->LocalGenerator->GetProjectName();
+  cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName);
+#endif
+  return obj_dir;
+}
+
+void cmGeneratorTarget::GetTargetObjectNames(
+  std::string const& config, std::vector<std::string>& objects) const
+{
+  std::vector<cmSourceFile const*> objectSources;
+  this->GetObjectSources(objectSources, config);
+  std::map<cmSourceFile const*, std::string> mapping;
+
+  for (std::vector<cmSourceFile const*>::const_iterator it =
+         objectSources.begin();
+       it != objectSources.end(); ++it) {
+    mapping[*it];
+  }
+
+  this->LocalGenerator->ComputeObjectFilenames(mapping, this);
+
+  for (std::vector<cmSourceFile const*>::const_iterator it =
+         objectSources.begin();
+       it != objectSources.end(); ++it) {
+    // Find the object file name corresponding to this source file.
+    std::map<cmSourceFile const*, std::string>::const_iterator map_it =
+      mapping.find(*it);
+    // It must exist because we populated the mapping just above.
+    assert(!map_it->second.empty());
+    objects.push_back(map_it->second);
+  }
+}
+
 bool cmGeneratorTarget::StrictTargetComparison::operator()(
   cmGeneratorTarget const* t1, cmGeneratorTarget const* t2) const
 {
@@ -3222,8 +3402,18 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
     // were not listed in one of the other lists.
     if (const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) {
       flags.MacFolder = location;
+      const bool stripResources =
+        this->GlobalGenerator->ShouldStripResourcePath(this->Makefile);
       if (strcmp(location, "Resources") == 0) {
         flags.Type = cmGeneratorTarget::SourceFileTypeResource;
+        if (stripResources) {
+          flags.MacFolder = "";
+        }
+      } else if (cmSystemTools::StringStartsWith(location, "Resources/")) {
+        flags.Type = cmGeneratorTarget::SourceFileTypeDeepResource;
+        if (stripResources) {
+          flags.MacFolder += strlen("Resources/");
+        }
       } else {
         flags.Type = cmGeneratorTarget::SourceFileTypeMacContent;
       }
@@ -3277,7 +3467,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const
       if (cmSourceFile* sf = this->Makefile->GetSource(*it)) {
         SourceFileFlags& flags = this->SourceFlagsMap[sf];
         flags.MacFolder = "";
-        if (!this->Makefile->PlatformIsAppleIos()) {
+        if (!this->GlobalGenerator->ShouldStripResourcePath(this->Makefile)) {
           flags.MacFolder = "Resources";
         }
         flags.Type = cmGeneratorTarget::SourceFileTypeResource;
@@ -3806,15 +3996,14 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
             << theTarget->GetName() << "\".\n";
           cmSystemTools::Error(e.str().c_str());
           break;
-        } else {
-          propContent = consistent.second;
-          continue;
         }
-      } else {
-        // Explicitly set on target and not set in iface. Can't disagree.
+        propContent = consistent.second;
         continue;
       }
-    } else if (impliedByUse) {
+      // Explicitly set on target and not set in iface. Can't disagree.
+      continue;
+    }
+    if (impliedByUse) {
       propContent = impliedValue<PropertyType>(propContent);
 
       if (ifaceIsSet) {
@@ -3832,43 +4021,36 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
             << "\" is in conflict.\n";
           cmSystemTools::Error(e.str().c_str());
           break;
-        } else {
-          propContent = consistent.second;
-          continue;
         }
-      } else {
-        // Implicitly set on target and not set in iface. Can't disagree.
+        propContent = consistent.second;
         continue;
       }
-    } else {
-      if (ifaceIsSet) {
-        if (propInitialized) {
-          std::pair<bool, PropertyType> consistent =
-            consistentProperty(propContent, ifacePropContent, t);
-          report += reportEntry;
-          report += compatibilityAgree(t, propContent != consistent.second);
-          if (!consistent.first) {
-            std::ostringstream e;
-            e << "The INTERFACE_" << p << " property of \""
-              << theTarget->GetName() << "\" does\nnot agree with the value "
-                                         "of "
-              << p << " already determined\nfor \"" << tgt->GetName()
-              << "\".\n";
-            cmSystemTools::Error(e.str().c_str());
-            break;
-          } else {
-            propContent = consistent.second;
-            continue;
-          }
-        } else {
-          report += reportEntry + "(Interface set)\n";
-          propContent = ifacePropContent;
-          propInitialized = true;
+      // Implicitly set on target and not set in iface. Can't disagree.
+      continue;
+    }
+    if (ifaceIsSet) {
+      if (propInitialized) {
+        std::pair<bool, PropertyType> consistent =
+          consistentProperty(propContent, ifacePropContent, t);
+        report += reportEntry;
+        report += compatibilityAgree(t, propContent != consistent.second);
+        if (!consistent.first) {
+          std::ostringstream e;
+          e << "The INTERFACE_" << p << " property of \""
+            << theTarget->GetName() << "\" does\nnot agree with the value of "
+            << p << " already determined\nfor \"" << tgt->GetName() << "\".\n";
+          cmSystemTools::Error(e.str().c_str());
+          break;
         }
-      } else {
-        // Not set. Nothing to agree on.
+        propContent = consistent.second;
         continue;
       }
+      report += reportEntry + "(Interface set)\n";
+      propContent = ifacePropContent;
+      propInitialized = true;
+    } else {
+      // Not set. Nothing to agree on.
+      continue;
     }
   }
 
@@ -3958,11 +4140,14 @@ void cmGeneratorTarget::GetTargetVersion(bool soversion, int& major,
     switch (sscanf(version, "%d.%d.%d", &parsed_major, &parsed_minor,
                    &parsed_patch)) {
       case 3:
-        patch = parsed_patch; // no break!
+        patch = parsed_patch;
+        CM_FALLTHROUGH;
       case 2:
-        minor = parsed_minor; // no break!
+        minor = parsed_minor;
+        CM_FALLTHROUGH;
       case 1:
-        major = parsed_major; // no break!
+        major = parsed_major;
+        CM_FALLTHROUGH;
       default:
         break;
     }
@@ -4277,26 +4462,31 @@ const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries(
   return iface.Exists ? &iface : CM_NULLPTR;
 }
 
-std::string cmGeneratorTarget::GetDirectory(const std::string& config,
-                                            bool implib) const
+std::string cmGeneratorTarget::GetDirectory(
+  const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   if (this->IsImported()) {
     // Return the directory from which the target is imported.
     return cmSystemTools::GetFilenamePath(
-      this->Target->ImportedGetFullPath(config, implib));
+      this->Target->ImportedGetFullPath(config, artifact));
   }
   if (OutputInfo const* info = this->GetOutputInfo(config)) {
     // Return the directory in which the target will be built.
-    return implib ? info->ImpDir : info->OutDir;
+    switch (artifact) {
+      case cmStateEnums::RuntimeBinaryArtifact:
+        return info->OutDir;
+      case cmStateEnums::ImportLibraryArtifact:
+        return info->ImpDir;
+    }
   }
   return "";
 }
 
-bool cmGeneratorTarget::UsesDefaultOutputDir(const std::string& config,
-                                             bool implib) const
+bool cmGeneratorTarget::UsesDefaultOutputDir(
+  const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   std::string dir;
-  return this->ComputeOutputDir(config, implib, dir);
+  return this->ComputeOutputDir(config, artifact, dir);
 }
 
 cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
@@ -4330,8 +4520,10 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
     i = this->OutputInfoMap.insert(entry).first;
 
     // Compute output directories.
-    this->ComputeOutputDir(config, false, info.OutDir);
-    this->ComputeOutputDir(config, true, info.ImpDir);
+    this->ComputeOutputDir(config, cmStateEnums::RuntimeBinaryArtifact,
+                           info.OutDir);
+    this->ComputeOutputDir(config, cmStateEnums::ImportLibraryArtifact,
+                           info.ImpDir);
     if (!this->ComputePDBOutputDir("PDB", config, info.PdbDir)) {
       info.PdbDir = info.OutDir;
     }
@@ -4351,14 +4543,15 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
 }
 
 bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
-                                         bool implib, std::string& out) const
+                                         cmStateEnums::ArtifactType artifact,
+                                         std::string& out) const
 {
   bool usesDefaultOutputDir = false;
   std::string conf = config;
 
   // Look for a target property defining the target output directory
   // based on the target type.
-  std::string targetTypeName = this->GetOutputTargetType(implib);
+  std::string targetTypeName = this->GetOutputTargetType(artifact);
   const char* propertyName = CM_NULLPTR;
   std::string propertyNameStr = targetTypeName;
   if (!propertyNameStr.empty()) {
@@ -4883,11 +5076,11 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles(
 
   std::vector<std::string>::const_iterator it = configs.begin();
   const std::string& firstConfig = *it;
-  this->GetSourceFiles(files, firstConfig);
+  this->GetSourceFilesWithoutObjectLibraries(files, firstConfig);
 
   for (; it != configs.end(); ++it) {
     std::vector<cmSourceFile*> configFiles;
-    this->GetSourceFiles(configFiles, *it);
+    this->GetSourceFilesWithoutObjectLibraries(configFiles, *it);
     if (configFiles != files) {
       std::string firstConfigFiles;
       const char* sep = "";
@@ -4966,11 +5159,11 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const
   // do the expansion but users link to libraries like " ${VAR} ".
   std::string lib = item;
   std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
-  if (pos != lib.npos) {
-    lib = lib.substr(pos, lib.npos);
+  if (pos != std::string::npos) {
+    lib = lib.substr(pos);
   }
   pos = lib.find_last_not_of(" \t\r\n");
-  if (pos != lib.npos) {
+  if (pos != std::string::npos) {
     lib = lib.substr(0, pos + 1);
   }
   if (lib != item) {
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index f568699..52147e3 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -3,7 +3,7 @@
 #ifndef cmGeneratorTarget_h
 #define cmGeneratorTarget_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmLinkItem.h"
 #include "cmListFileCache.h"
@@ -12,6 +12,7 @@
 
 #include <map>
 #include <set>
+#include <stddef.h>
 #include <string>
 #include <utility>
 #include <vector>
@@ -26,6 +27,8 @@ class cmTarget;
 
 class cmGeneratorTarget
 {
+  CM_DISABLE_COPY(cmGeneratorTarget)
+
 public:
   cmGeneratorTarget(cmTarget*, cmLocalGenerator* lg);
   ~cmGeneratorTarget();
@@ -69,18 +72,74 @@ public:
   bool GetPropertyAsBool(const std::string& prop) const;
   void GetSourceFiles(std::vector<cmSourceFile*>& files,
                       const std::string& config) const;
+  void GetSourceFilesWithoutObjectLibraries(std::vector<cmSourceFile*>& files,
+                                            const std::string& config) const;
+
+  /** Source file kinds (classifications).
+      Generators use this to decide how to treat a source file.  */
+  enum SourceKind
+  {
+    SourceKindAppManifest,
+    SourceKindCertificate,
+    SourceKindCustomCommand,
+    SourceKindExternalObject,
+    SourceKindExtra,
+    SourceKindHeader,
+    SourceKindIDL,
+    SourceKindManifest,
+    SourceKindModuleDefinition,
+    SourceKindObjectSource,
+    SourceKindResx,
+    SourceKindXaml
+  };
+
+  /** A source file paired with a kind (classification).  */
+  struct SourceAndKind
+  {
+    cmSourceFile* Source;
+    SourceKind Kind;
+  };
+
+  /** All sources needed for a configuration with kinds assigned.  */
+  struct KindedSources
+  {
+    std::vector<SourceAndKind> Sources;
+    std::set<std::string> ExpectedResxHeaders;
+    std::set<std::string> ExpectedXamlHeaders;
+    std::set<std::string> ExpectedXamlSources;
+    bool Initialized;
+    KindedSources()
+      : Initialized(false)
+    {
+    }
+  };
+
+  /** Get all sources needed for a configuration with kinds assigned.  */
+  KindedSources const& GetKindedSources(std::string const& config) const;
+
+  struct AllConfigSource
+  {
+    cmSourceFile const* Source;
+    cmGeneratorTarget::SourceKind Kind;
+    std::vector<size_t> Configs;
+  };
+
+  /** Get all sources needed for all configurations with kinds and
+      per-source configurations assigned.  */
+  std::vector<AllConfigSource> const& GetAllConfigSources() const;
 
   void GetObjectSources(std::vector<cmSourceFile const*>&,
                         const std::string& config) const;
   const std::string& GetObjectName(cmSourceFile const* file);
+  const char* GetCustomObjectExtension() const;
 
   bool HasExplicitObjectName(cmSourceFile const* file) const;
   void AddExplicitObjectName(cmSourceFile const* sf);
 
+  void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&,
+                                  const std::string& config) const;
   void GetResxSources(std::vector<cmSourceFile const*>&,
                       const std::string& config) const;
-  void GetIDLSources(std::vector<cmSourceFile const*>&,
-                     const std::string& config) const;
   void GetExternalObjects(std::vector<cmSourceFile const*>&,
                           const std::string& config) const;
   void GetHeaderSources(std::vector<cmSourceFile const*>&,
@@ -110,8 +169,8 @@ public:
 
   const char* GetFeature(const std::string& feature,
                          const std::string& config) const;
-  bool GetFeatureAsBool(const std::string& feature,
-                        const std::string& config) const;
+
+  bool IsIPOEnabled(std::string const& lang, std::string const& config) const;
 
   bool IsLinkInterfaceDependentBoolProperty(const std::string& p,
                                             const std::string& config) const;
@@ -152,15 +211,31 @@ public:
 
   /** Get the full path to the target according to the settings in its
       makefile and the configuration type.  */
-  std::string GetFullPath(const std::string& config = "", bool implib = false,
-                          bool realname = false) const;
-  std::string NormalGetFullPath(const std::string& config, bool implib,
+  std::string GetFullPath(
+    const std::string& config = "",
+    cmStateEnums::ArtifactType artifact = cmStateEnums::RuntimeBinaryArtifact,
+    bool realname = false) const;
+  std::string NormalGetFullPath(const std::string& config,
+                                cmStateEnums::ArtifactType artifact,
                                 bool realname) const;
   std::string NormalGetRealName(const std::string& config) const;
 
+  /** Get the names of an object library's object files underneath
+      its object file directory.  */
+  void GetTargetObjectNames(std::string const& config,
+                            std::vector<std::string>& objects) const;
+
+  /** What hierarchy level should the reported directory contain */
+  enum BundleDirectoryLevel
+  {
+    BundleDirLevel,
+    ContentLevel,
+    FullLevel
+  };
+
   /** @return the Mac App directory without the base */
   std::string GetAppBundleDirectory(const std::string& config,
-                                    bool contentOnly) const;
+                                    BundleDirectoryLevel level) const;
 
   /** Return whether this target is an executable Bundle, a framework
       or CFBundle on Apple.  */
@@ -169,11 +244,12 @@ public:
   /** Get the full name of the target according to the settings in its
       makefile.  */
   std::string GetFullName(const std::string& config = "",
-                          bool implib = false) const;
+                          cmStateEnums::ArtifactType artifact =
+                            cmStateEnums::RuntimeBinaryArtifact) const;
 
   /** @return the Mac framework directory without the base. */
   std::string GetFrameworkDirectory(const std::string& config,
-                                    bool rootDir) const;
+                                    BundleDirectoryLevel level) const;
 
   /** Return the framework version string.  Undefined if
       IsFrameworkOnApple returns false.  */
@@ -181,7 +257,7 @@ public:
 
   /** @return the Mac CFBundle directory without the base */
   std::string GetCFBundleDirectory(const std::string& config,
-                                   bool contentOnly) const;
+                                   BundleDirectoryLevel level) const;
 
   /** Return the install name directory for the target in the
     * build tree.  For example: "\@rpath/", "\@loader_path/",
@@ -214,16 +290,18 @@ public:
   void GetFullNameComponents(std::string& prefix, std::string& base,
                              std::string& suffix,
                              const std::string& config = "",
-                             bool implib = false) const;
+                             cmStateEnums::ArtifactType artifact =
+                               cmStateEnums::RuntimeBinaryArtifact) const;
 
-  /** Append to @a base the mac content directory and return it. */
-  std::string BuildMacContentDirectory(const std::string& base,
-                                       const std::string& config = "",
-                                       bool contentOnly = true) const;
+  /** Append to @a base the bundle directory hierarchy up to a certain @a level
+   * and return it. */
+  std::string BuildBundleDirectory(const std::string& base,
+                                   const std::string& config,
+                                   BundleDirectoryLevel level) const;
 
   /** @return the mac content directory for this target. */
-  std::string GetMacContentDirectory(const std::string& config = CM_NULLPTR,
-                                     bool implib = false) const;
+  std::string GetMacContentDirectory(
+    const std::string& config, cmStateEnums::ArtifactType artifact) const;
 
   /** @return folder prefix for IDEs. */
   std::string GetEffectiveFolderName() const;
@@ -233,7 +311,15 @@ public:
   cmLocalGenerator* LocalGenerator;
   cmGlobalGenerator const* GlobalGenerator;
 
-  cmSourceFile const* GetModuleDefinitionFile(const std::string& config) const;
+  struct ModuleDefinitionInfo
+  {
+    std::string DefFile;
+    bool DefFileGenerated;
+    bool WindowsExportAllSymbols;
+    std::vector<cmSourceFile const*> Sources;
+  };
+  ModuleDefinitionInfo const* GetModuleDefinitionInfo(
+    std::string const& config) const;
 
   /** Return whether or not the target is for a DLL platform.  */
   bool IsDLLPlatform() const;
@@ -282,8 +368,11 @@ public:
     std::vector<cmGeneratorTarget*>& objlibs) const;
 
   std::string GetFullNameImported(const std::string& config,
-                                  bool implib) const;
+                                  cmStateEnums::ArtifactType artifact) const;
 
+  /** Get source files common to all configurations and diagnose cases
+      with per-config sources.  Excludes sources added by a TARGET_OBJECTS
+      generator expression.  */
   bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const;
 
   bool HaveBuildTreeRPATH(const std::string& config) const;
@@ -293,12 +382,17 @@ public:
       time config name placeholder if needed for the generator.  */
   std::string ObjectDirectory;
 
-  void UseObjectLibraries(std::vector<std::string>& objs,
-                          const std::string& config) const;
+  /** Full path with trailing slash to the top-level directory
+      holding object files for the given configuration.  */
+  std::string GetObjectDirectory(std::string const& config) const;
 
   void GetAppleArchs(const std::string& config,
                      std::vector<std::string>& archVec) const;
 
+  std::string GetFeatureSpecificLinkRuleVariable(
+    std::string const& var, std::string const& lang,
+    std::string const& config) const;
+
   /** Return the rule variable used to create this type of target.  */
   std::string GetCreateRuleVariable(std::string const& lang,
                                     std::string const& config) const;
@@ -324,6 +418,8 @@ public:
   /** Add the target output files to the global generator manifest.  */
   void ComputeTargetManifest(const std::string& config) const;
 
+  bool ComputeCompileFeatures(std::string const& config) const;
+
   /**
    * Trace through the source files in this target and add al source files
    * that they depend on, used by all generators
@@ -335,7 +431,8 @@ public:
       subdirectory for that configuration.  Otherwise just the canonical
       output directory is given.  */
   std::string GetDirectory(const std::string& config = "",
-                           bool implib = false) const;
+                           cmStateEnums::ArtifactType artifact =
+                             cmStateEnums::RuntimeBinaryArtifact) const;
 
   /** Get the directory in which to place the target compiler .pdb file.
       If the configuration name is given then the generator will add its
@@ -349,7 +446,8 @@ public:
 
   /** Return whether this target uses the default value for its output
       directory.  */
-  bool UsesDefaultOutputDir(const std::string& config, bool implib) const;
+  bool UsesDefaultOutputDir(const std::string& config,
+                            cmStateEnums::ArtifactType artifact) const;
 
   // Cache target output paths for each configuration.
   struct OutputInfo
@@ -390,7 +488,8 @@ public:
   std::string GetCompilePDBPath(const std::string& config = "") const;
 
   // Get the target base name.
-  std::string GetOutputName(const std::string& config, bool implib) const;
+  std::string GetOutputName(const std::string& config,
+                            cmStateEnums::ArtifactType artifact) const;
 
   void AddSource(const std::string& src);
   void AddTracedSources(std::vector<std::string> const& srcs);
@@ -412,7 +511,9 @@ public:
     SourceFileTypePublicHeader,  // is in "PUBLIC_HEADER" target property
     SourceFileTypeResource,      // is in "RESOURCE" target property *or*
                                  // has MACOSX_PACKAGE_LOCATION=="Resources"
-    SourceFileTypeMacContent     // has MACOSX_PACKAGE_LOCATION!="Resources"
+    SourceFileTypeDeepResource,  // MACOSX_PACKAGE_LOCATION starts with
+                                 // "Resources/"
+    SourceFileTypeMacContent     // has MACOSX_PACKAGE_LOCATION!="Resources[/]"
   };
   struct SourceFileFlags
   {
@@ -421,11 +522,6 @@ public:
       , MacFolder(CM_NULLPTR)
     {
     }
-    SourceFileFlags(SourceFileFlags const& r)
-      : Type(r.Type)
-      , MacFolder(r.MacFolder)
-    {
-    }
     SourceFileType Type;
     const char* MacFolder; // location inside Mac content folders
   };
@@ -461,7 +557,7 @@ public:
   std::string GetPDBDirectory(const std::string& config) const;
 
   ///! Return the preferred linker language for this target
-  std::string GetLinkerLanguage(const std::string& config = "") const;
+  std::string GetLinkerLanguage(const std::string& config) const;
 
   /** Does this target have a GNU implib to convert to MS format?  */
   bool HasImplibGNUtoMS() const;
@@ -498,19 +594,6 @@ public:
   struct SourceFileFlags GetTargetSourceFileFlags(
     const cmSourceFile* sf) const;
 
-  struct ResxData
-  {
-    mutable std::set<std::string> ExpectedResxHeaders;
-    mutable std::vector<cmSourceFile const*> ResxSources;
-  };
-
-  struct XamlData
-  {
-    std::set<std::string> ExpectedXamlHeaders;
-    std::set<std::string> ExpectedXamlSources;
-    std::vector<cmSourceFile const*> XamlSources;
-  };
-
   void ReportPropertyOrigin(const std::string& p, const std::string& result,
                             const std::string& report,
                             const std::string& compatibilityType) const;
@@ -525,6 +608,16 @@ public:
   /** Whether this library defaults to \@rpath.  */
   bool MacOSXRpathInstallNameDirDefault() const;
 
+  enum InstallNameType
+  {
+    INSTALL_NAME_FOR_BUILD,
+    INSTALL_NAME_FOR_INSTALL
+  };
+  /** Whether to use INSTALL_NAME_DIR. */
+  bool MacOSXUseInstallNameDir() const;
+  /** Whether to generate an install_name. */
+  bool CanGenerateInstallNameDir(InstallNameType t) const;
+
   /** Test for special case of a third-party shared library that has
       no soname at all.  */
   bool IsImportedSharedLibWithoutSOName(const std::string& config) const;
@@ -574,8 +667,9 @@ private:
   mutable std::map<std::string, bool> DebugCompatiblePropertiesDone;
 
   std::string GetFullNameInternal(const std::string& config,
-                                  bool implib) const;
-  void GetFullNameInternal(const std::string& config, bool implib,
+                                  cmStateEnums::ArtifactType artifact) const;
+  void GetFullNameInternal(const std::string& config,
+                           cmStateEnums::ArtifactType artifact,
                            std::string& outPrefix, std::string& outBase,
                            std::string& outSuffix) const;
 
@@ -583,7 +677,7 @@ private:
   mutable LinkClosureMapType LinkClosureMap;
 
   // Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type.
-  const char* GetOutputTargetType(bool implib) const;
+  const char* GetOutputTargetType(cmStateEnums::ArtifactType artifact) const;
 
   void ComputeVersionedName(std::string& vName, std::string const& prefix,
                             std::string const& base, std::string const& suffix,
@@ -617,9 +711,6 @@ private:
   void CheckPropertyCompatibility(cmComputeLinkInformation* info,
                                   const std::string& config) const;
 
-  cmGeneratorTarget(cmGeneratorTarget const&);
-  void operator=(cmGeneratorTarget const&);
-
   struct LinkImplClosure : public std::vector<cmGeneratorTarget const*>
   {
     LinkImplClosure()
@@ -673,9 +764,13 @@ private:
     const std::string& config, const cmGeneratorTarget* head,
     bool usage_requirements_only) const;
 
-  typedef std::map<std::string, std::vector<cmSourceFile*> >
-    SourceFilesMapType;
-  mutable SourceFilesMapType SourceFilesMap;
+  typedef std::map<std::string, KindedSources> KindedSourcesMapType;
+  mutable KindedSourcesMapType KindedSourcesMap;
+  void ComputeKindedSources(KindedSources& files,
+                            std::string const& config) const;
+
+  mutable std::vector<AllConfigSource> AllConfigSources;
+  void ComputeAllConfigSources() const;
 
   std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
   std::vector<TargetPropertyEntry*> CompileOptionsEntries;
@@ -705,18 +800,26 @@ private:
 
   cmLinkImplementationLibraries const* GetLinkImplementationLibrariesInternal(
     const std::string& config, const cmGeneratorTarget* head) const;
-  bool ComputeOutputDir(const std::string& config, bool implib,
+  bool ComputeOutputDir(const std::string& config,
+                        cmStateEnums::ArtifactType artifact,
                         std::string& out) const;
 
   typedef std::map<std::string, OutputInfo> OutputInfoMapType;
   mutable OutputInfoMapType OutputInfoMap;
 
-  typedef std::pair<std::string, bool> OutputNameKey;
+  typedef std::map<std::string, ModuleDefinitionInfo>
+    ModuleDefinitionInfoMapType;
+  mutable ModuleDefinitionInfoMapType ModuleDefinitionInfoMap;
+  void ComputeModuleDefinitionInfo(std::string const& config,
+                                   ModuleDefinitionInfo& info) const;
+
+  typedef std::pair<std::string, cmStateEnums::ArtifactType> OutputNameKey;
   typedef std::map<OutputNameKey, std::string> OutputNameMapType;
   mutable OutputNameMapType OutputNameMap;
   mutable std::set<cmLinkItem> UtilityItems;
   cmPolicies::PolicyMap PolicyMap;
   mutable bool PolicyWarnedCMP0022;
+  mutable bool PolicyReportedCMP0069;
   mutable bool DebugIncludesDone;
   mutable bool DebugCompileOptionsDone;
   mutable bool DebugCompileFeaturesDone;
diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx
index 7962da6..5ba3326 100644
--- a/Source/cmGetCMakePropertyCommand.cxx
+++ b/Source/cmGetCMakePropertyCommand.cxx
@@ -20,7 +20,7 @@ bool cmGetCMakePropertyCommand::InitialPass(
     return false;
   }
 
-  std::string variable = args[0];
+  std::string const& variable = args[0];
   std::string output = "NOTFOUND";
 
   if (args[1] == "VARIABLES") {
diff --git a/Source/cmGetCMakePropertyCommand.h b/Source/cmGetCMakePropertyCommand.h
index 41a51a4..9dfc40f 100644
--- a/Source/cmGetCMakePropertyCommand.h
+++ b/Source/cmGetCMakePropertyCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmGetCMakePropertyCommand_h
 #define cmGetCMakePropertyCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -22,16 +23,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "get_cmake_property"; }
 };
 
 #endif
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index 920e1a0..1005b15 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -20,7 +20,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass(
   }
 
   std::vector<std::string>::const_iterator i = args.begin();
-  std::string variable = *i;
+  std::string const& variable = *i;
   ++i;
 
   // get the directory argument if there is one
@@ -78,6 +78,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass(
           this->Makefile->IssueMessage(
             cmake::AUTHOR_WARNING,
             cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
+          CM_FALLTHROUGH;
         case cmPolicies::OLD:
           this->StoreResult(variable, this->Makefile->GetDefineFlagsCMP0059());
           return true;
diff --git a/Source/cmGetDirectoryPropertyCommand.h b/Source/cmGetDirectoryPropertyCommand.h
index 1ae3125..7d97950 100644
--- a/Source/cmGetDirectoryPropertyCommand.h
+++ b/Source/cmGetDirectoryPropertyCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmGetDirectoryPropertyCommand_h
 #define cmGetDirectoryPropertyCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -23,16 +24,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "get_directory_property"; }
-
 private:
   void StoreResult(const std::string& variable, const char* prop);
 };
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx
index 5915a67..c23684c 100644
--- a/Source/cmGetFilenameComponentCommand.cxx
+++ b/Source/cmGetFilenameComponentCommand.cxx
@@ -28,7 +28,7 @@ bool cmGetFilenameComponentCommand::InitialPass(
 
   std::string result;
   std::string filename = args[1];
-  if (filename.find("[HKEY") != filename.npos) {
+  if (filename.find("[HKEY") != std::string::npos) {
     // Check the registry as the target application would view it.
     cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32;
     cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64;
@@ -37,10 +37,10 @@ bool cmGetFilenameComponentCommand::InitialPass(
       other_view = cmSystemTools::KeyWOW64_32;
     }
     cmSystemTools::ExpandRegistryValues(filename, view);
-    if (filename.find("/registry") != filename.npos) {
+    if (filename.find("/registry") != std::string::npos) {
       std::string other = args[1];
       cmSystemTools::ExpandRegistryValues(other, other_view);
-      if (other.find("/registry") == other.npos) {
+      if (other.find("/registry") == std::string::npos) {
         filename = other;
       }
     }
diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h
index c0ad903..c8a23c7 100644
--- a/Source/cmGetFilenameComponentCommand.h
+++ b/Source/cmGetFilenameComponentCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmGetFilenameComponentCommand_h
 #define cmGetFilenameComponentCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,16 +32,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "get_filename_component"; }
 };
 
 #endif
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index d2056d2..ddecdf6 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -232,6 +232,7 @@ bool cmGetPropertyCommand::HandleDirectoryMode()
       case cmPolicies::WARN:
         mf->IssueMessage(cmake::AUTHOR_WARNING,
                          cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         return this->StoreResult(mf->GetDefineFlagsCMP0059());
       case cmPolicies::NEW:
diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h
index f9a33ac..6497801 100644
--- a/Source/cmGetPropertyCommand.h
+++ b/Source/cmGetPropertyCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmGetPropertyCommand_h
 #define cmGetPropertyCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -25,16 +26,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "get_property"; }
-
 private:
   enum OutType
   {
diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx
index 509ef95..1a5f08e 100644
--- a/Source/cmGetSourceFilePropertyCommand.cxx
+++ b/Source/cmGetSourceFilePropertyCommand.cxx
@@ -15,8 +15,8 @@ bool cmGetSourceFilePropertyCommand::InitialPass(
     this->SetError("called with incorrect number of arguments");
     return false;
   }
-  const char* var = args[0].c_str();
-  const char* file = args[1].c_str();
+  std::string const& var = args[0];
+  std::string const& file = args[1];
   cmSourceFile* sf = this->Makefile->GetSource(file);
 
   // for the location we must create a source file first
diff --git a/Source/cmGetSourceFilePropertyCommand.h b/Source/cmGetSourceFilePropertyCommand.h
index 0f71851..e96bb29 100644
--- a/Source/cmGetSourceFilePropertyCommand.h
+++ b/Source/cmGetSourceFilePropertyCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmGetSourceFilePropertyCommand_h
 #define cmGetSourceFilePropertyCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -22,14 +23,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "get_source_file_property";
-  }
 };
 
 #endif
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 2379292..0910a53 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -22,8 +22,8 @@ bool cmGetTargetPropertyCommand::InitialPass(
     this->SetError("called with incorrect number of arguments");
     return false;
   }
-  std::string var = args[0];
-  const std::string& targetName = args[1];
+  std::string const& var = args[0];
+  std::string const& targetName = args[1];
   std::string prop;
   bool prop_exists = false;
 
diff --git a/Source/cmGetTargetPropertyCommand.h b/Source/cmGetTargetPropertyCommand.h
index 32fe803..5de3225 100644
--- a/Source/cmGetTargetPropertyCommand.h
+++ b/Source/cmGetTargetPropertyCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmGetTargetPropertyCommand_h
 #define cmGetTargetPropertyCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -22,11 +23,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "get_target_property"; }
 };
 
 #endif
diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx
index a8a44b7..6424515 100644
--- a/Source/cmGetTestPropertyCommand.cxx
+++ b/Source/cmGetTestPropertyCommand.cxx
@@ -16,8 +16,8 @@ bool cmGetTestPropertyCommand::InitialPass(
     return false;
   }
 
-  std::string testName = args[0];
-  std::string var = args[2];
+  std::string const& testName = args[0];
+  std::string const& var = args[2];
   cmTest* test = this->Makefile->GetTest(testName);
   if (test) {
     const char* prop = CM_NULLPTR;
diff --git a/Source/cmGetTestPropertyCommand.h b/Source/cmGetTestPropertyCommand.h
index 0491cc8..b17e7a1 100644
--- a/Source/cmGetTestPropertyCommand.h
+++ b/Source/cmGetTestPropertyCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmGetTestPropertyCommand_h
 #define cmGetTestPropertyCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -22,11 +23,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "get_test_property"; }
 };
 
 #endif
diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h
index 2c2b123..7bc7bfc 100644
--- a/Source/cmGhsMultiGpj.h
+++ b/Source/cmGhsMultiGpj.h
@@ -3,7 +3,7 @@
 #ifndef cmGhsMultiGpj_h
 #define cmGhsMultiGpj_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 class cmGeneratedFileStream;
 
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index ba623d5..7032cd5 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -232,10 +232,12 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config,
     const char* lang = language.c_str();
 
     if (notKernel) {
-      this->LocalGenerator->AddLanguageFlags(flags, lang, config);
+      this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
+                                             lang, config);
     } else {
-      this->LocalGenerator->AddLanguageFlags(
-        flags, lang + std::string("_GHS_KERNEL"), config);
+      this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
+                                             lang + std::string("_GHS_KERNEL"),
+                                             config);
     }
     this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, lang,
                                           config);
diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h
index e8e6ad9..f2ad059 100644
--- a/Source/cmGlobalCommonGenerator.h
+++ b/Source/cmGlobalCommonGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalCommonGenerator_h
 #define cmGlobalCommonGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmGlobalGenerator.h"
 
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index f118250..099f705 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1,24 +1,21 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "windows.h" // this must be first to define GetCurrentDirectory
-#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#endif
-#endif
-
 #include "cmGlobalGenerator.h"
 
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
 #include <algorithm>
 #include <assert.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
 #include <iterator>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <windows.h>
+#endif
+
 #include "cmAlgorithms.h"
 #include "cmCPackPropertiesGenerator.h"
 #include "cmComputeTargetDepends.h"
@@ -42,12 +39,17 @@
 #include "cmStateDirectory.h"
 #include "cmStateTypes.h"
 #include "cmVersion.h"
+#include "cmWorkingDirectory.h"
 #include "cmake.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmCryptoHash.h"
-#include <cm_jsoncpp_value.h>
-#include <cm_jsoncpp_writer.h>
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1800
+#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
 #endif
 
 const std::string kCMAKE_PLATFORM_INFO_INITIALIZED =
@@ -94,6 +96,7 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
   this->ConfigureDoneCMP0026AndCMP0024 = false;
   this->FirstTimeProgress = 0.0f;
 
+  cm->GetState()->SetIsGeneratorMultiConfig(false);
   cm->GetState()->SetMinGWMake(false);
   cm->GetState()->SetMSYSShell(false);
   cm->GetState()->SetNMake(false);
@@ -303,7 +306,7 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
   // if there are spaces in the make program use short path
   // but do not short path the actual program name, as
   // this can cause trouble with VSExpress
-  if (makeProgram.find(' ') != makeProgram.npos) {
+  if (makeProgram.find(' ') != std::string::npos) {
     std::string dir;
     std::string file;
     cmSystemTools::SplitProgramPath(makeProgram, dir, file);
@@ -835,6 +838,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
           /* clang-format on */
           mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
         }
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         // OLD behavior is to convert AppleClang to Clang.
         mf->AddDefinition(compilerIdVar, "Clang");
@@ -864,6 +868,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
           /* clang-format on */
           mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
         }
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         // OLD behavior is to convert QCC to GNU.
         mf->AddDefinition(compilerIdVar, "GNU");
@@ -878,6 +883,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
         mf->IssueMessage(
           cmake::FATAL_ERROR,
           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047));
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior is to keep QCC.
         break;
@@ -1194,6 +1200,11 @@ void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target)
   this->CMP0042WarnTargets.insert(target);
 }
 
+void cmGlobalGenerator::AddCMP0068WarnTarget(const std::string& target)
+{
+  this->CMP0068WarnTargets.insert(target);
+}
+
 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const
 {
   // If the property is not enabled then okay.
@@ -1235,6 +1246,8 @@ bool cmGlobalGenerator::Compute()
 
   // clear targets to issue warning CMP0042 for
   this->CMP0042WarnTargets.clear();
+  // clear targets to issue warning CMP0068 for
+  this->CMP0068WarnTargets.clear();
 
   // Check whether this generator is allowed to run.
   if (!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) {
@@ -1262,6 +1275,18 @@ bool cmGlobalGenerator::Compute()
     this->LocalGenerators[i]->AddHelperCommands();
   }
 
+  // Finalize the set of compile features for each target.
+  // FIXME: This turns into calls to cmMakefile::AddRequiredTargetFeature
+  // which actually modifies the <lang>_STANDARD target property
+  // on the original cmTarget instance.  It accumulates features
+  // across all configurations.  Some refactoring is needed to
+  // compute a per-config resulta purely during generation.
+  for (i = 0; i < this->LocalGenerators.size(); ++i) {
+    if (!this->LocalGenerators[i]->ComputeTargetCompileFeatures()) {
+      return false;
+    }
+  }
+
 #ifdef CMAKE_BUILD_WITH_CMAKE
   for (std::vector<cmGeneratorTarget const*>::iterator it =
          autogenTargets.begin();
@@ -1337,10 +1362,11 @@ void cmGlobalGenerator::Generate()
   for (std::map<std::string, cmExportBuildFileGenerator*>::iterator it =
          this->BuildExportSets.begin();
        it != this->BuildExportSets.end(); ++it) {
-    if (!it->second->GenerateImportFile() &&
-        !cmSystemTools::GetErrorOccuredFlag()) {
-      this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR,
-                                             "Could not write export file.");
+    if (!it->second->GenerateImportFile()) {
+      if (!cmSystemTools::GetErrorOccuredFlag()) {
+        this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR,
+                                               "Could not write export file.");
+      }
       return;
     }
   }
@@ -1366,6 +1392,24 @@ void cmGlobalGenerator::Generate()
     this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
   }
 
+  if (!this->CMP0068WarnTargets.empty()) {
+    std::ostringstream w;
+    /* clang-format off */
+    w <<
+      cmPolicies::GetPolicyWarning(cmPolicies::CMP0068) << "\n"
+      "For compatibility with older versions of CMake, the install_name "
+      "fields for the following targets are still affected by RPATH "
+      "settings:\n"
+      ;
+    /* clang-format on */
+    for (std::set<std::string>::iterator iter =
+           this->CMP0068WarnTargets.begin();
+         iter != this->CMP0068WarnTargets.end(); ++iter) {
+      w << " " << *iter << "\n";
+    }
+    this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+  }
+
   this->CMakeInstance->UpdateProgress("Generating done", -1);
 }
 
@@ -1441,13 +1485,13 @@ cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
 }
 
 cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
-  cmOutputConverter* outputConverter, cmStateDirectory stateDir) const
+  cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const
 {
   return new cmLinkLineComputer(outputConverter, stateDir);
 }
 
 cmLinkLineComputer* cmGlobalGenerator::CreateMSVC60LinkLineComputer(
-  cmOutputConverter* outputConverter, cmStateDirectory stateDir) const
+  cmOutputConverter* outputConverter, cmStateDirectory const& stateDir) const
 {
   return new cmMSVC60LinkLineComputer(outputConverter, stateDir);
 }
@@ -1738,8 +1782,7 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
   /**
    * Run an executable command and put the stdout in output.
    */
-  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(bindir);
+  cmWorkingDirectory workdir(bindir);
   output += "Change Dir: ";
   output += bindir;
   output += "\n";
@@ -1779,8 +1822,6 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
       output += *outputPtr;
       output += "\nGenerator: execution of make clean failed.\n";
 
-      // return to the original directory
-      cmSystemTools::ChangeDirectory(cwd);
       return 1;
     }
     output += *outputPtr;
@@ -1803,8 +1844,6 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
     output += "\nGenerator: execution of make failed. Make command was: " +
       makeCommandStr + "\n";
 
-    // return to the original directory
-    cmSystemTools::ChangeDirectory(cwd);
     return 1;
   }
   output += *outputPtr;
@@ -1817,7 +1856,6 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
     retVal = 1;
   }
 
-  cmSystemTools::ChangeDirectory(cwd);
   return retVal;
 }
 
@@ -2466,6 +2504,11 @@ std::string cmGlobalGenerator::GenerateRuleFile(
   return ruleFile;
 }
 
+bool cmGlobalGenerator::ShouldStripResourcePath(cmMakefile* mf) const
+{
+  return mf->PlatformIsAppleIos();
+}
+
 std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage(
   std::string const& l) const
 {
@@ -2690,7 +2733,7 @@ void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile,
     }
 
     // Get the filename.
-    fname = line.substr(33, line.npos);
+    fname = line.substr(33);
 
     // Look for a hash for this file's rule.
     std::map<std::string, RuleHash>::const_iterator rhi =
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 18e3730..871178b 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalGenerator_h
 #define cmGlobalGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <map>
@@ -105,10 +105,12 @@ public:
   virtual void Generate();
 
   virtual cmLinkLineComputer* CreateLinkLineComputer(
-    cmOutputConverter* outputConverter, cmStateDirectory stateDir) const;
+    cmOutputConverter* outputConverter,
+    cmStateDirectory const& stateDir) const;
 
   cmLinkLineComputer* CreateMSVC60LinkLineComputer(
-    cmOutputConverter* outputConverter, cmStateDirectory stateDir) const;
+    cmOutputConverter* outputConverter,
+    cmStateDirectory const& stateDir) const;
 
   /**
    * Set/Get and Clear the enabled languages.
@@ -331,12 +333,23 @@ public:
       i.e. "Can I build Debug and Release in the same tree?" */
   virtual bool IsMultiConfig() const { return false; }
 
+  /** Return true if we know the exact location of object files.
+      If false, store the reason in the given string.
+      This is meaningful only after EnableLanguage has been called.  */
+  virtual bool HasKnownObjectFileLocation(std::string*) const { return true; }
+
   virtual bool UseFolderProperty() const;
 
+  virtual bool IsIPOSupported() const { return false; }
+
   /** Return whether the generator should use EFFECTIVE_PLATFORM_NAME. This is
       relevant for mixed macOS and iOS builds. */
   virtual bool UseEffectivePlatformName(cmMakefile*) const { return false; }
 
+  /** Return whether the "Resources" folder prefix should be stripped from
+      MacFolder. */
+  virtual bool ShouldStripResourcePath(cmMakefile*) const;
+
   std::string GetSharedLibFlagsForLanguage(std::string const& lang) const;
 
   /** Generate an <output>.rule file path for a given command output.  */
@@ -357,6 +370,7 @@ public:
   cmExportBuildFileGenerator* GetExportedTargetsFile(
     const std::string& filename) const;
   void AddCMP0042WarnTarget(const std::string& target);
+  void AddCMP0068WarnTarget(const std::string& target);
 
   virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
 
@@ -548,12 +562,6 @@ private:
       : LastDiskTime(-1)
     {
     }
-    DirectoryContent(DirectoryContent const& dc)
-      : LastDiskTime(dc.LastDiskTime)
-      , All(dc.All)
-      , Generated(dc.Generated)
-    {
-    }
   };
   std::map<std::string, DirectoryContent> DirectoryContentMap;
 
@@ -562,6 +570,8 @@ private:
 
   // track targets to issue CMP0042 warning for.
   std::set<std::string> CMP0042WarnTargets;
+  // track targets to issue CMP0068 warning for.
+  std::set<std::string> CMP0068WarnTargets;
 
   mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*> >
     FilenameTargetDepends;
diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h
index 5e948f7..d5a6db0 100644
--- a/Source/cmGlobalGeneratorFactory.h
+++ b/Source/cmGlobalGeneratorFactory.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalGeneratorFactory_h
 #define cmGlobalGeneratorFactory_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <string>
 #include <vector>
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 286f375..42ab4d9 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGlobalGhsMultiGenerator.h"
 
-#include <cmsys/SystemTools.hxx>
+#include "cmsys/SystemTools.hxx"
 
 #include "cmAlgorithms.h"
 #include "cmDocumentationEntry.h"
diff --git a/Source/cmGlobalKdevelopGenerator.cxx b/Source/cmGlobalKdevelopGenerator.cxx
index 75209c3..e72c6e3 100644
--- a/Source/cmGlobalKdevelopGenerator.cxx
+++ b/Source/cmGlobalKdevelopGenerator.cxx
@@ -14,8 +14,8 @@
 #include "cmXMLWriter.h"
 #include "cmake.h"
 
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
 #include <map>
 #include <set>
 #include <string.h>
@@ -101,7 +101,7 @@ bool cmGlobalKdevelopGenerator::CreateFilelistFile(
   std::set<std::string> files;
   std::string tmp;
 
-  std::vector<std::string> hdrExts =
+  std::vector<std::string> const& hdrExts =
     this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
 
   for (std::vector<cmLocalGenerator*>::const_iterator it = lgs.begin();
diff --git a/Source/cmGlobalKdevelopGenerator.h b/Source/cmGlobalKdevelopGenerator.h
index 8121fa8..bdcf8a1 100644
--- a/Source/cmGlobalKdevelopGenerator.h
+++ b/Source/cmGlobalKdevelopGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalKdevelopGenerator_h
 #define cmGlobalKdevelopGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmExternalMakefileProjectGenerator.h"
 
diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index 7e0d0d4..3f22382 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGlobalMSYSMakefileGenerator.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 
 #include "cmDocumentationEntry.h"
 #include "cmLocalUnixMakefileGenerator3.h"
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 1bdef53..2eef9e4 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -2,11 +2,11 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGlobalNinjaGenerator.h"
 
+#include "cm_jsoncpp_reader.h"
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+#include "cmsys/FStream.hxx"
 #include <algorithm>
-#include <cm_jsoncpp_reader.h>
-#include <cm_jsoncpp_value.h>
-#include <cm_jsoncpp_writer.h>
-#include <cmsys/FStream.hxx>
 #include <ctype.h>
 #include <functional>
 #include <iterator>
@@ -56,7 +56,7 @@ void cmGlobalNinjaGenerator::Indent(std::ostream& os, int count)
 void cmGlobalNinjaGenerator::WriteDivider(std::ostream& os)
 {
   os << "# ======================================"
-     << "=======================================\n";
+        "=======================================\n";
 }
 
 void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
@@ -77,7 +77,8 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
 }
 
 cmLinkLineComputer* cmGlobalNinjaGenerator::CreateLinkLineComputer(
-  cmOutputConverter* outputConverter, cmStateDirectory /* stateDir */) const
+  cmOutputConverter* outputConverter,
+  cmStateDirectory const& /* stateDir */) const
 {
   return new cmNinjaLinkLineComputer(
     outputConverter,
@@ -146,13 +147,6 @@ std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path)
   return EncodeLiteral(result);
 }
 
-std::string cmGlobalNinjaGenerator::EncodeDepfileSpace(const std::string& path)
-{
-  std::string result = path;
-  cmSystemTools::ReplaceString(result, " ", "\\ ");
-  return result;
-}
-
 void cmGlobalNinjaGenerator::WriteBuild(
   std::ostream& os, const std::string& comment, const std::string& rule,
   const cmNinjaDeps& outputs, const cmNinjaDeps& implicitOuts,
@@ -216,7 +210,7 @@ void cmGlobalNinjaGenerator::WriteBuild(
        ++i) {
     build += " " + EncodeIdent(EncodePath(*i), os);
     if (this->ComputingUnknownDependencies) {
-      this->CombinedBuildOutputs.insert(EncodePath(*i));
+      this->CombinedBuildOutputs.insert(*i);
     }
   }
   if (!implicitOuts.empty()) {
@@ -246,7 +240,7 @@ void cmGlobalNinjaGenerator::WriteBuild(
   bool useResponseFile = false;
   if (cmdLineLimit < 0 ||
       (cmdLineLimit > 0 &&
-       (args.size() + buildstr.size() + assignments.size()) >
+       (args.size() + buildstr.size() + assignments.size() + 1000) >
          static_cast<size_t>(cmdLineLimit))) {
     variable_assignments.str(std::string());
     cmGlobalNinjaGenerator::WriteVariable(variable_assignments, "RSP_FILE",
@@ -318,7 +312,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
     // we need to track every dependency that comes in, since we are trying
     // to find dependencies that are side effects of build commands
     for (cmNinjaDeps::const_iterator i = deps.begin(); i != deps.end(); ++i) {
-      this->CombinedCustomCommandExplicitDependencies.insert(EncodePath(*i));
+      this->CombinedCustomCommandExplicitDependencies.insert(*i);
     }
   }
 }
@@ -898,6 +892,10 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand(
     this->GetCMakeInstance()->GetHomeOutputDirectory();
   if (!this->CompileCommandsStream) {
     std::string buildFilePath = buildFileDir + "/compile_commands.json";
+    if (this->ComputingUnknownDependencies) {
+      this->CombinedBuildOutputs.insert(
+        this->NinjaOutputPath("compile_commands.json"));
+    }
 
     // Get a stream where to generate things.
     this->CompileCommandsStream =
@@ -966,8 +964,14 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
   }
 }
 
+std::string OrderDependsTargetForTarget(cmGeneratorTarget const* target)
+{
+  return "cmake_object_order_depends_target_" + target->GetName();
+}
+
 void cmGlobalNinjaGenerator::AppendTargetOutputs(
-  cmGeneratorTarget const* target, cmNinjaDeps& outputs)
+  cmGeneratorTarget const* target, cmNinjaDeps& outputs,
+  cmNinjaTargetDepends depends)
 {
   std::string configName =
     target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
@@ -979,15 +983,27 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
   bool realname = target->IsFrameworkOnApple();
 
   switch (target->GetType()) {
-    case cmStateEnums::EXECUTABLE:
     case cmStateEnums::SHARED_LIBRARY:
     case cmStateEnums::STATIC_LIBRARY:
     case cmStateEnums::MODULE_LIBRARY: {
-      outputs.push_back(this->ConvertToNinjaPath(
-        target->GetFullPath(configName, false, realname)));
+      if (depends == DependOnTargetOrdering) {
+        outputs.push_back(OrderDependsTargetForTarget(target));
+        break;
+      }
+    }
+    // FALLTHROUGH
+    case cmStateEnums::EXECUTABLE: {
+      outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath(
+        configName, cmStateEnums::RuntimeBinaryArtifact, realname)));
       break;
     }
-    case cmStateEnums::OBJECT_LIBRARY:
+    case cmStateEnums::OBJECT_LIBRARY: {
+      if (depends == DependOnTargetOrdering) {
+        outputs.push_back(OrderDependsTargetForTarget(target));
+        break;
+      }
+    }
+    // FALLTHROUGH
     case cmStateEnums::GLOBAL_TARGET:
     case cmStateEnums::UTILITY: {
       std::string path =
@@ -1003,7 +1019,8 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
 }
 
 void cmGlobalNinjaGenerator::AppendTargetDepends(
-  cmGeneratorTarget const* target, cmNinjaDeps& outputs)
+  cmGeneratorTarget const* target, cmNinjaDeps& outputs,
+  cmNinjaTargetDepends depends)
 {
   if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
     // These depend only on other CMake-provided targets, e.g. "all".
@@ -1023,7 +1040,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
       if ((*i)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
         continue;
       }
-      this->AppendTargetOutputs(*i, outs);
+      this->AppendTargetOutputs(*i, outs, depends);
     }
     std::sort(outs.begin(), outs.end());
     outputs.insert(outputs.end(), outs.begin(), outs.end());
@@ -1823,10 +1840,14 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
 int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
                              std::vector<std::string>::const_iterator argEnd)
 {
+  std::vector<std::string> arg_full =
+    cmSystemTools::HandleResponseFile(argBeg, argEnd);
+
   std::string arg_dd;
   std::string arg_tdi;
   std::vector<std::string> arg_ddis;
-  for (std::vector<std::string>::const_iterator a = argBeg; a != argEnd; ++a) {
+  for (std::vector<std::string>::const_iterator a = arg_full.begin();
+       a != arg_full.end(); ++a) {
     std::string const& arg = *a;
     if (cmHasLiteralPrefix(arg, "--tdi=")) {
       arg_tdi = arg.substr(6);
@@ -1880,7 +1901,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
     }
   }
 
-  cmake cm;
+  cmake cm(cmake::RoleInternal);
   cm.SetHomeDirectory(dir_top_src);
   cm.SetHomeOutputDirectory(dir_top_bld);
   CM_AUTO_PTR<cmGlobalNinjaGenerator> ggd(
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index a51e919..b0008f7 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalNinjaGenerator_h
 #define cmGlobalNinjaGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <map>
@@ -75,11 +75,10 @@ public:
   static std::string EncodeIdent(const std::string& ident, std::ostream& vars);
   static std::string EncodeLiteral(const std::string& lit);
   std::string EncodePath(const std::string& path);
-  static std::string EncodeDepfileSpace(const std::string& path);
 
   cmLinkLineComputer* CreateLinkLineComputer(
     cmOutputConverter* outputConverter,
-    cmStateDirectory stateDir) const CM_OVERRIDE;
+    cmStateDirectory const& stateDir) const CM_OVERRIDE;
 
   /**
    * Write the given @a comment to the output stream @a os. It
@@ -99,6 +98,8 @@ public:
    */
   static bool SupportsPlatform() { return false; }
 
+  bool IsIPOSupported() const CM_OVERRIDE { return true; }
+
   /**
    * Write a build statement to @a os with the @a comment using
    * the @a rule the list of @a outputs files and inputs.
@@ -314,10 +315,12 @@ public:
     ASD.insert(deps.begin(), deps.end());
   }
 
-  void AppendTargetOutputs(cmGeneratorTarget const* target,
-                           cmNinjaDeps& outputs);
-  void AppendTargetDepends(cmGeneratorTarget const* target,
-                           cmNinjaDeps& outputs);
+  void AppendTargetOutputs(
+    cmGeneratorTarget const* target, cmNinjaDeps& outputs,
+    cmNinjaTargetDepends depends = DependOnTargetArtifact);
+  void AppendTargetDepends(
+    cmGeneratorTarget const* target, cmNinjaDeps& outputs,
+    cmNinjaTargetDepends depends = DependOnTargetArtifact);
   void AppendTargetDependsClosure(cmGeneratorTarget const* target,
                                   cmNinjaDeps& outputs);
   void AddDependencyToAll(cmGeneratorTarget* target);
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 67d7bc9..a656102 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalUnixMakefileGenerator3_h
 #define cmGlobalUnixMakefileGenerator3_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <map>
@@ -149,6 +149,8 @@ public:
   /** Does the make tool tolerate .DELETE_ON_ERROR? */
   virtual bool AllowDeleteOnError() const { return true; }
 
+  bool IsIPOSupported() const CM_OVERRIDE { return true; }
+
   void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE;
 
   std::string IncludeDirective;
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index e27615a..e3835ff 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -10,14 +10,25 @@
 #include "cmSourceFile.h"
 #include "cmVS10CLFlagTable.h"
 #include "cmVS10CSharpFlagTable.h"
+#include "cmVS10CudaFlagTable.h"
+#include "cmVS10CudaHostFlagTable.h"
 #include "cmVS10LibFlagTable.h"
 #include "cmVS10LinkFlagTable.h"
 #include "cmVS10MASMFlagTable.h"
+#include "cmVS10NASMFlagTable.h"
 #include "cmVS10RCFlagTable.h"
+#include "cmVersion.h"
 #include "cmVisualStudioSlnData.h"
 #include "cmVisualStudioSlnParser.h"
+#include "cmXMLWriter.h"
 #include "cmake.h"
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include <algorithm>
+
 static const char vs10generatorName[] = "Visual Studio 10 2010";
 
 // Map generator name without year to name with year.
@@ -94,6 +105,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;"
     "ProductDir",
     vc10Express, cmSystemTools::KeyWOW64_32);
+  this->CudaEnabled = false;
   this->SystemIsWindowsCE = false;
   this->SystemIsWindowsPhone = false;
   this->SystemIsWindowsStore = false;
@@ -112,9 +124,13 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
   this->DefaultCSharpFlagTable = cmVS10CSharpFlagTable;
   this->DefaultLibFlagTable = cmVS10LibFlagTable;
   this->DefaultLinkFlagTable = cmVS10LinkFlagTable;
+  this->DefaultCudaFlagTable = cmVS10CudaFlagTable;
+  this->DefaultCudaHostFlagTable = cmVS10CudaHostFlagTable;
   this->DefaultMasmFlagTable = cmVS10MASMFlagTable;
+  this->DefaultNasmFlagTable = cmVS10NASMFlagTable;
   this->DefaultRcFlagTable = cmVS10RCFlagTable;
   this->Version = VS10;
+  this->PlatformToolsetNeedsDebugEnum = false;
 }
 
 bool cmGlobalVisualStudio10Generator::MatchesGeneratorName(
@@ -153,6 +169,13 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorPlatform(
   return true;
 }
 
+static void cmCudaToolVersion(std::string& s)
+{
+  // "CUDA x.y.props" => "x.y"
+  s = s.substr(5);
+  s = s.substr(0, s.size() - 6);
+}
+
 bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
   std::string const& ts, cmMakefile* mf)
 {
@@ -168,36 +191,137 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
   if (!this->ParseGeneratorToolset(ts, mf)) {
     return false;
   }
+
+  if (!this->FindVCTargetsPath(mf)) {
+    return false;
+  }
+
+  if (cmHasLiteralPrefix(this->GetPlatformToolsetString(), "v140")) {
+    // The GenerateDebugInformation link setting for the v140 toolset
+    // in VS 2015 was originally an enum with "No" and "Debug" values,
+    // differing from the "false" and "true" values used in older toolsets.
+    // A VS 2015 update changed it back.  Parse the "link.xml" file to
+    // discover which one we need.
+    std::string const link_xml = this->VCTargetsPath + "/1033/link.xml";
+    cmsys::ifstream fin(link_xml.c_str());
+    std::string line;
+    while (fin && cmSystemTools::GetLineFromStream(fin, line)) {
+      if (line.find(" Switch=\"DEBUG\" ") != std::string::npos) {
+        this->PlatformToolsetNeedsDebugEnum =
+          line.find(" Name=\"Debug\" ") != std::string::npos;
+        break;
+      }
+    }
+  }
+
+  if (this->GeneratorToolsetCuda.empty()) {
+    // Find the highest available version of the CUDA tools.
+    std::vector<std::string> cudaTools;
+    std::string const bcDir = this->VCTargetsPath + "/BuildCustomizations";
+    cmsys::Glob gl;
+    gl.SetRelative(bcDir.c_str());
+    if (gl.FindFiles(bcDir + "/CUDA *.props")) {
+      cudaTools = gl.GetFiles();
+    }
+    if (!cudaTools.empty()) {
+      std::for_each(cudaTools.begin(), cudaTools.end(), cmCudaToolVersion);
+      std::sort(cudaTools.begin(), cudaTools.end(),
+                cmSystemTools::VersionCompareGreater);
+      this->GeneratorToolsetCuda = cudaTools.at(0);
+    }
+  }
+
   if (const char* toolset = this->GetPlatformToolset()) {
     mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset);
   }
   if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) {
     mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch);
   }
+  if (const char* cuda = this->GetPlatformToolsetCuda()) {
+    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA", cuda);
+  }
   return true;
 }
 
 bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
   std::string const& ts, cmMakefile* mf)
 {
-  if (ts.find_first_of(",=") != ts.npos) {
-    std::ostringstream e;
-    /* clang-format off */
-    e <<
-      "Generator\n"
-      "  " << this->GetName() << "\n"
-      "does not recognize the toolset\n"
-      "  " << ts << "\n"
-      "that was specified.";
-    /* clang-format on */
-    mf->IssueMessage(cmake::FATAL_ERROR, e.str());
-    return false;
+  std::vector<std::string> const fields = cmSystemTools::tokenize(ts, ",");
+  std::vector<std::string>::const_iterator fi = fields.begin();
+  if (fi == fields.end()) {
+    return true;
+  }
+
+  // The first field may be the VS platform toolset.
+  if (fi->find('=') == fi->npos) {
+    this->GeneratorToolset = *fi;
+    ++fi;
+  }
+
+  std::set<std::string> handled;
+
+  // The rest of the fields must be key=value pairs.
+  for (; fi != fields.end(); ++fi) {
+    std::string::size_type pos = fi->find('=');
+    if (pos == fi->npos) {
+      std::ostringstream e;
+      /* clang-format off */
+      e <<
+        "Generator\n"
+        "  " << this->GetName() << "\n"
+        "given toolset specification\n"
+        "  " << ts << "\n"
+        "that contains a field after the first ',' with no '='."
+        ;
+      /* clang-format on */
+      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return false;
+    }
+    std::string const key = fi->substr(0, pos);
+    std::string const value = fi->substr(pos + 1);
+    if (!handled.insert(key).second) {
+      std::ostringstream e;
+      /* clang-format off */
+      e <<
+        "Generator\n"
+        "  " << this->GetName() << "\n"
+        "given toolset specification\n"
+        "  " << ts << "\n"
+        "that contains duplicate field key '" << key << "'."
+        ;
+      /* clang-format on */
+      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return false;
+    }
+    if (!this->ProcessGeneratorToolsetField(key, value)) {
+      std::ostringstream e;
+      /* clang-format off */
+      e <<
+        "Generator\n"
+        "  " << this->GetName() << "\n"
+        "given toolset specification\n"
+        "  " << ts << "\n"
+        "that contains invalid field '" << *fi << "'."
+        ;
+      /* clang-format on */
+      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return false;
+    }
   }
 
-  this->GeneratorToolset = ts;
   return true;
 }
 
+bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
+  std::string const& key, std::string const& value)
+{
+  if (key == "cuda") {
+    this->GeneratorToolsetCuda = value;
+    return true;
+  }
+  return false;
+}
+
 bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf)
 {
   if (this->SystemName == "Windows") {
@@ -354,6 +478,16 @@ void cmGlobalVisualStudio10Generator::Generate()
 void cmGlobalVisualStudio10Generator::EnableLanguage(
   std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
 {
+  for (std::vector<std::string>::const_iterator it = lang.begin();
+       it != lang.end(); ++it) {
+    if (*it == "ASM_NASM") {
+      this->NasmEnabled = true;
+    }
+    if (*it == "CUDA") {
+      this->CudaEnabled = true;
+    }
+  }
+  this->AddPlatformDefinitions(mf);
   cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
 }
 
@@ -388,6 +522,20 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const
   return CM_NULLPTR;
 }
 
+const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const
+{
+  if (!this->GeneratorToolsetCuda.empty()) {
+    return this->GeneratorToolsetCuda.c_str();
+  }
+  return CM_NULLPTR;
+}
+
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const
+{
+  return this->GeneratorToolsetCuda;
+}
+
 bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf)
 {
   if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) {
@@ -442,6 +590,208 @@ std::string cmGlobalVisualStudio10Generator::FindDevEnvCommand()
   return this->cmGlobalVisualStudio71Generator::FindDevEnvCommand();
 }
 
+bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
+{
+  // Skip this in special cases within our own test suite.
+  if (this->GetPlatformName() == "Test Platform" ||
+      this->GetPlatformToolsetString() == "Test Toolset") {
+    return true;
+  }
+
+  std::string wd;
+  if (!this->ConfiguredFilesPath.empty()) {
+    // In a try-compile we are given the outer CMakeFiles directory.
+    wd = this->ConfiguredFilesPath;
+  } else {
+    wd = this->GetCMakeInstance()->GetHomeOutputDirectory();
+    wd += cmake::GetCMakeFilesDirectory();
+  }
+  wd += "/";
+  wd += cmVersion::GetCMakeVersion();
+
+  // We record the result persistently in a file.
+  std::string const txt = wd + "/VCTargetsPath.txt";
+
+  // If we have a recorded result, use it.
+  {
+    cmsys::ifstream fin(txt.c_str());
+    if (fin && cmSystemTools::GetLineFromStream(fin, this->VCTargetsPath) &&
+        cmSystemTools::FileIsDirectory(this->VCTargetsPath)) {
+      cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath);
+      return true;
+    }
+  }
+
+  // Prepare the work directory.
+  if (!cmSystemTools::MakeDirectory(wd)) {
+    std::string e = "Failed to make directory:\n  " + wd;
+    mf->IssueMessage(cmake::FATAL_ERROR, e.c_str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+  }
+
+  // Generate a project file for MSBuild to tell us the VCTargetsPath value.
+  std::string const vcxproj = "VCTargetsPath.vcxproj";
+  {
+    std::string const vcxprojAbs = wd + "/" + vcxproj;
+    cmsys::ofstream fout(vcxprojAbs.c_str());
+    cmXMLWriter xw(fout);
+
+    /* clang-format off */
+    xw.StartDocument();
+    xw.StartElement("Project");
+     xw.Attribute("DefaultTargets", "Build");
+     xw.Attribute("ToolsVersion", "4.0");
+     xw.Attribute("xmlns",
+                  "http://schemas.microsoft.com/developer/msbuild/2003");
+     if (this->IsNsightTegra()) {
+       xw.StartElement("PropertyGroup");
+        xw.Attribute("Label", "NsightTegraProject");
+        xw.StartElement("NsightTegraProjectRevisionNumber");
+         xw.Content("6");
+        xw.EndElement(); // NsightTegraProjectRevisionNumber
+       xw.EndElement(); // PropertyGroup
+     }
+     xw.StartElement("ItemGroup");
+      xw.Attribute("Label", "ProjectConfigurations");
+      xw.StartElement("ProjectConfiguration");
+       xw.Attribute("Include", "Debug|" + this->GetPlatformName());
+       xw.StartElement("Configuration");
+        xw.Content("Debug");
+       xw.EndElement(); // Configuration
+       xw.StartElement("Platform");
+        xw.Content(this->GetPlatformName());
+       xw.EndElement(); // Platform
+      xw.EndElement(); // ProjectConfiguration
+     xw.EndElement(); // ItemGroup
+    xw.StartElement("PropertyGroup");
+     xw.Attribute("Label", "Globals");
+     xw.StartElement("ProjectGuid");
+      xw.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
+     xw.EndElement(); // ProjectGuid
+     xw.StartElement("Keyword");
+      xw.Content("Win32Proj");
+     xw.EndElement(); // Keyword
+     xw.StartElement("Platform");
+      xw.Content(this->GetPlatformName());
+     xw.EndElement(); // Platform
+     if (this->GetSystemName() == "WindowsPhone") {
+       xw.StartElement("ApplicationType");
+        xw.Content("Windows Phone");
+       xw.EndElement(); // ApplicationType
+       xw.StartElement("ApplicationTypeRevision");
+        xw.Content(this->GetSystemVersion());
+       xw.EndElement(); // ApplicationTypeRevision
+     } else if (this->GetSystemName() == "WindowsStore") {
+       xw.StartElement("ApplicationType");
+        xw.Content("Windows Store");
+       xw.EndElement(); // ApplicationType
+       xw.StartElement("ApplicationTypeRevision");
+        xw.Content(this->GetSystemVersion());
+       xw.EndElement(); // ApplicationTypeRevision
+     }
+     if (!this->WindowsTargetPlatformVersion.empty()) {
+       xw.StartElement("WindowsTargetPlatformVersion");
+        xw.Content(this->WindowsTargetPlatformVersion);
+       xw.EndElement(); // WindowsTargetPlatformVersion
+     }
+     if (this->GetPlatformName() == "ARM") {
+       xw.StartElement("WindowsSDKDesktopARMSupport");
+        xw.Content("true");
+       xw.EndElement(); // WindowsSDKDesktopARMSupport
+     }
+    xw.EndElement(); // PropertyGroup
+    xw.StartElement("Import");
+     xw.Attribute("Project",
+                  "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
+    xw.EndElement(); // Import
+    if (!this->GeneratorToolsetHostArchitecture.empty()) {
+      xw.StartElement("PropertyGroup");
+       xw.StartElement("PreferredToolArchitecture");
+        xw.Content(this->GeneratorToolsetHostArchitecture);
+       xw.EndElement(); // PreferredToolArchitecture
+      xw.EndElement(); // PropertyGroup
+    }
+    xw.StartElement("PropertyGroup");
+     xw.Attribute("Label", "Configuration");
+     xw.StartElement("ConfigurationType");
+      if (this->IsNsightTegra()) {
+        // Tegra-Android platform does not understand "Utility".
+        xw.Content("StaticLibrary");
+      } else {
+        xw.Content("Utility");
+      }
+     xw.EndElement(); // ConfigurationType
+     xw.StartElement("CharacterSet");
+      xw.Content("MultiByte");
+     xw.EndElement(); // CharacterSet
+     if (this->IsNsightTegra()) {
+       xw.StartElement("NdkToolchainVersion");
+       xw.Content(this->GetPlatformToolsetString());
+       xw.EndElement(); // NdkToolchainVersion
+     } else {
+       xw.StartElement("PlatformToolset");
+       xw.Content(this->GetPlatformToolsetString());
+       xw.EndElement(); // PlatformToolset
+     }
+    xw.EndElement(); // PropertyGroup
+    xw.StartElement("Import");
+     xw.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
+    xw.EndElement(); // Import
+    xw.StartElement("ItemDefinitionGroup");
+     xw.StartElement("PostBuildEvent");
+      xw.StartElement("Command");
+       xw.Content("echo VCTargetsPath=$(VCTargetsPath)");
+      xw.EndElement(); // Command
+     xw.EndElement(); // PostBuildEvent
+    xw.EndElement(); // ItemDefinitionGroup
+    xw.StartElement("Import");
+     xw.Attribute("Project",
+                  "$(VCTargetsPath)\\Microsoft.Cpp.targets");
+    xw.EndElement(); // Import
+    xw.EndElement(); // Project
+    xw.EndDocument();
+    /* clang-format on */
+  }
+
+  std::vector<std::string> cmd;
+  cmd.push_back(this->GetMSBuildCommand());
+  cmd.push_back(vcxproj);
+  cmd.push_back(std::string("/p:VisualStudioVersion=") +
+                this->GetIDEVersion());
+  std::string out;
+  int ret = 0;
+  cmsys::RegularExpression regex("\n *VCTargetsPath=([^%\r\n]+)[\r\n]");
+  if (!cmSystemTools::RunSingleCommand(cmd, &out, &out, &ret, wd.c_str(),
+                                       cmSystemTools::OUTPUT_NONE) ||
+      ret != 0 || !regex.find(out)) {
+    cmSystemTools::ReplaceString(out, "\n", "\n  ");
+    std::ostringstream e;
+    /* clang-format off */
+    e <<
+      "Failed to run MSBuild command:\n"
+      "  " << cmd[0] << "\n"
+      "to get the value of VCTargetsPath:\n"
+      "  " << out << "\n"
+      ;
+    /* clang-format on */
+    if (ret != 0) {
+      e << "Exit code: " << ret << "\n";
+    }
+    mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+  }
+  this->VCTargetsPath = regex.match(1);
+  cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath);
+
+  {
+    cmsys::ofstream fout(txt.c_str());
+    fout << this->VCTargetsPath << "\n";
+  }
+  return true;
+}
+
 void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
   std::vector<std::string>& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& projectDir,
@@ -656,6 +1006,17 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const
   return (table != CM_NULLPTR) ? table : this->DefaultLinkFlagTable;
 }
 
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const
+{
+  return this->DefaultCudaFlagTable;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable()
+  const
+{
+  return this->DefaultCudaHostFlagTable;
+}
+
 cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const
 {
   cmIDEFlagTable const* table = this->ToolsetOptions.GetMasmFlagTable(
@@ -663,3 +1024,8 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const
 
   return (table != CM_NULLPTR) ? table : this->DefaultMasmFlagTable;
 }
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const
+{
+  return this->DefaultNasmFlagTable;
+}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 5bfaf38..4a5c245 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -23,7 +23,6 @@ public:
   virtual bool SetSystemName(std::string const& s, cmMakefile* mf);
   virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
   virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
-  virtual bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
 
   virtual void GenerateBuildCommand(
     std::vector<std::string>& makeCommand, const std::string& makeProgram,
@@ -43,6 +42,8 @@ public:
                               cmMakefile*, bool optional);
   virtual void WriteSLNHeader(std::ostream& fout);
 
+  bool IsCudaEnabled() const { return this->CudaEnabled; }
+
   /** Generating for Nsight Tegra VS plugin?  */
   bool IsNsightTegra() const;
   std::string GetNsightTegraVersion() const;
@@ -54,6 +55,17 @@ public:
   /** The toolset host architecture name (e.g. x64 for 64-bit host tools).  */
   const char* GetPlatformToolsetHostArchitecture() const;
 
+  /** The cuda toolset version.  */
+  const char* GetPlatformToolsetCuda() const;
+  std::string const& GetPlatformToolsetCudaString() const;
+
+  /** Return whether we need to use No/Debug instead of false/true
+      for GenerateDebugInformation.  */
+  bool GetPlatformToolsetNeedsDebugEnum() const
+  {
+    return this->PlatformToolsetNeedsDebugEnum;
+  }
+
   /** Return the CMAKE_SYSTEM_NAME.  */
   std::string const& GetSystemName() const { return this->SystemName; }
 
@@ -95,7 +107,10 @@ public:
   cmIDEFlagTable const* GetRcFlagTable() const;
   cmIDEFlagTable const* GetLibFlagTable() const;
   cmIDEFlagTable const* GetLinkFlagTable() const;
+  cmIDEFlagTable const* GetCudaFlagTable() const;
+  cmIDEFlagTable const* GetCudaHostFlagTable() const;
   cmIDEFlagTable const* GetMasmFlagTable() const;
+  cmIDEFlagTable const* GetNasmFlagTable() const;
 
 protected:
   virtual void Generate();
@@ -105,6 +120,9 @@ protected:
   virtual bool InitializeWindowsPhone(cmMakefile* mf);
   virtual bool InitializeWindowsStore(cmMakefile* mf);
 
+  virtual bool ProcessGeneratorToolsetField(std::string const& key,
+                                            std::string const& value);
+
   virtual std::string SelectWindowsCEToolset() const;
   virtual bool SelectWindowsPhoneToolset(std::string& toolset) const;
   virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
@@ -115,6 +133,7 @@ protected:
 
   std::string GeneratorToolset;
   std::string GeneratorToolsetHostArchitecture;
+  std::string GeneratorToolsetCuda;
   std::string DefaultPlatformToolset;
   std::string WindowsTargetPlatformVersion;
   std::string SystemName;
@@ -124,7 +143,10 @@ protected:
   cmIDEFlagTable const* DefaultCSharpFlagTable;
   cmIDEFlagTable const* DefaultLibFlagTable;
   cmIDEFlagTable const* DefaultLinkFlagTable;
+  cmIDEFlagTable const* DefaultCudaFlagTable;
+  cmIDEFlagTable const* DefaultCudaHostFlagTable;
   cmIDEFlagTable const* DefaultMasmFlagTable;
+  cmIDEFlagTable const* DefaultNasmFlagTable;
   cmIDEFlagTable const* DefaultRcFlagTable;
   bool SystemIsWindowsCE;
   bool SystemIsWindowsPhone;
@@ -154,6 +176,15 @@ private:
   virtual std::string FindDevEnvCommand();
   virtual std::string GetVSMakeProgram() { return this->GetMSBuildCommand(); }
 
+  bool PlatformToolsetNeedsDebugEnum;
+
+  bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
+
+  std::string VCTargetsPath;
+  bool FindVCTargetsPath(cmMakefile* mf);
+
+  bool CudaEnabled;
+
   // We do not use the reload macros for VS >= 10.
   virtual std::string GetUserMacrosDirectory() { return ""; }
 };
diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h
index ae99408..b4b327d 100644
--- a/Source/cmGlobalVisualStudio11Generator.h
+++ b/Source/cmGlobalVisualStudio11Generator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalVisualStudio11Generator_h
 #define cmGlobalVisualStudio11Generator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <set>
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index 2656dcc..de62ff0 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -109,19 +109,15 @@ bool cmGlobalVisualStudio12Generator::MatchesGeneratorName(
   return false;
 }
 
-bool cmGlobalVisualStudio12Generator::ParseGeneratorToolset(
-  std::string const& ts, cmMakefile* mf)
+bool cmGlobalVisualStudio12Generator::ProcessGeneratorToolsetField(
+  std::string const& key, std::string const& value)
 {
-  std::string::size_type ts_end = ts.size();
-  if (cmHasLiteralSuffix(ts, ",host=x64")) {
+  if (key == "host" && value == "x64") {
     this->GeneratorToolsetHostArchitecture = "x64";
-    ts_end -= 9;
-  } else if (ts == "host=x64") {
-    this->GeneratorToolsetHostArchitecture = "x64";
-    ts_end = 0;
+    return true;
   }
-  return this->cmGlobalVisualStudio11Generator::ParseGeneratorToolset(
-    ts.substr(0, ts_end), mf);
+  return this->cmGlobalVisualStudio11Generator::ProcessGeneratorToolsetField(
+    key, value);
 }
 
 bool cmGlobalVisualStudio12Generator::InitializeWindowsPhone(cmMakefile* mf)
diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h
index 79efe52..ebc95bb 100644
--- a/Source/cmGlobalVisualStudio12Generator.h
+++ b/Source/cmGlobalVisualStudio12Generator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalVisualStudio12Generator_h
 #define cmGlobalVisualStudio12Generator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <string>
@@ -31,8 +31,8 @@ public:
   // version number
   virtual const char* GetToolsVersion() { return "12.0"; }
 protected:
-  bool ParseGeneratorToolset(std::string const& ts,
-                             cmMakefile* mf) CM_OVERRIDE;
+  bool ProcessGeneratorToolsetField(std::string const& key,
+                                    std::string const& value) CM_OVERRIDE;
 
   virtual bool InitializeWindowsPhone(cmMakefile* mf);
   virtual bool InitializeWindowsStore(cmMakefile* mf);
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index 81c305c..c8cf02c 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -8,8 +8,8 @@
 #include "cmMakefile.h"
 #include "cmVS140CLFlagTable.h"
 #include "cmVS140CSharpFlagTable.h"
+#include "cmVS140LinkFlagTable.h"
 #include "cmVS14LibFlagTable.h"
-#include "cmVS14LinkFlagTable.h"
 #include "cmVS14MASMFlagTable.h"
 #include "cmVS14RCFlagTable.h"
 
@@ -93,7 +93,7 @@ cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator(
   this->DefaultClFlagTable = cmVS140CLFlagTable;
   this->DefaultCSharpFlagTable = cmVS140CSharpFlagTable;
   this->DefaultLibFlagTable = cmVS14LibFlagTable;
-  this->DefaultLinkFlagTable = cmVS14LinkFlagTable;
+  this->DefaultLinkFlagTable = cmVS140LinkFlagTable;
   this->DefaultMasmFlagTable = cmVS14MASMFlagTable;
   this->DefaultRcFlagTable = cmVS14RCFlagTable;
   this->Version = VS14;
@@ -217,29 +217,48 @@ struct NoWindowsH
 std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
-  // This logic is taken from the vcvarsqueryregistry.bat file from VS2015
-  // Try HKLM and then HKCU.
-  std::string win10Root;
-  if (!cmSystemTools::ReadRegistryValue(
-        "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
-        "Windows Kits\\Installed Roots;KitsRoot10",
-        win10Root, cmSystemTools::KeyWOW64_32) &&
-      !cmSystemTools::ReadRegistryValue(
-        "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\"
-        "Windows Kits\\Installed Roots;KitsRoot10",
-        win10Root, cmSystemTools::KeyWOW64_32)) {
+  std::vector<std::string> win10Roots;
+
+  {
+    std::string win10Root;
+    if (cmSystemTools::GetEnv("CMAKE_WINDOWS_KITS_10_DIR", win10Root)) {
+      cmSystemTools::ConvertToUnixSlashes(win10Root);
+      win10Roots.push_back(win10Root);
+    }
+  }
+
+  {
+    // This logic is taken from the vcvarsqueryregistry.bat file from VS2015
+    // Try HKLM and then HKCU.
+    std::string win10Root;
+    if (cmSystemTools::ReadRegistryValue(
+          "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+          "Windows Kits\\Installed Roots;KitsRoot10",
+          win10Root, cmSystemTools::KeyWOW64_32) ||
+        cmSystemTools::ReadRegistryValue(
+          "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\"
+          "Windows Kits\\Installed Roots;KitsRoot10",
+          win10Root, cmSystemTools::KeyWOW64_32)) {
+      cmSystemTools::ConvertToUnixSlashes(win10Root);
+      win10Roots.push_back(win10Root);
+    }
+  }
+
+  if (win10Roots.empty()) {
     return std::string();
   }
 
   std::vector<std::string> sdks;
-  std::string path = win10Root + "Include/*";
   // Grab the paths of the different SDKs that are installed
-  cmSystemTools::GlobDirs(path, sdks);
+  for (std::vector<std::string>::iterator i = win10Roots.begin();
+       i != win10Roots.end(); ++i) {
+    std::string path = *i + "/Include/*";
+    cmSystemTools::GlobDirs(path, sdks);
+  }
 
   // Skip SDKs that do not contain <um/windows.h> because that indicates that
   // only the UCRT MSIs were installed for them.
-  sdks.erase(std::remove_if(sdks.begin(), sdks.end(), NoWindowsH()),
-             sdks.end());
+  cmEraseIf(sdks, NoWindowsH());
 
   if (!sdks.empty()) {
     // Only use the filename, which will be the SDK version.
diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h
index ab22978..0ce9a56 100644
--- a/Source/cmGlobalVisualStudio14Generator.h
+++ b/Source/cmGlobalVisualStudio14Generator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalVisualStudio14Generator_h
 #define cmGlobalVisualStudio14Generator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <string>
diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx
index 2312bc0..ce1ba00 100644
--- a/Source/cmGlobalVisualStudio15Generator.cxx
+++ b/Source/cmGlobalVisualStudio15Generator.cxx
@@ -8,6 +8,7 @@
 #include "cmMakefile.h"
 #include "cmVS141CLFlagTable.h"
 #include "cmVS141CSharpFlagTable.h"
+#include "cmVS141LinkFlagTable.h"
 #include "cmVSSetupHelper.h"
 
 static const char vs15generatorName[] = "Visual Studio 15 2017";
@@ -85,6 +86,7 @@ cmGlobalVisualStudio15Generator::cmGlobalVisualStudio15Generator(
   this->DefaultPlatformToolset = "v141";
   this->DefaultClFlagTable = cmVS141CLFlagTable;
   this->DefaultCSharpFlagTable = cmVS141CSharpFlagTable;
+  this->DefaultLinkFlagTable = cmVS141LinkFlagTable;
   this->Version = VS15;
 }
 
@@ -164,7 +166,7 @@ bool cmGlobalVisualStudio15Generator::IsWin81SDKInstalled() const
         "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\"
         "Windows Kits\\Installed Roots;KitsRoot81",
         win81Root, cmSystemTools::KeyWOW64_32)) {
-    return true;
+    return cmSystemTools::FileExists(win81Root + "/um/windows.h", true);
   }
   return false;
 }
diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h
index f979b65..4be88f4 100644
--- a/Source/cmGlobalVisualStudio15Generator.h
+++ b/Source/cmGlobalVisualStudio15Generator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalVisualStudio15Generator_h
 #define cmGlobalVisualStudio15Generator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <string>
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 55a788f..aeceb8d 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -13,58 +13,6 @@ cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator(
   : cmGlobalVisualStudio7Generator(cm, platformName)
 {
   this->ProjectConfigurationSectionName = "ProjectConfiguration";
-  this->Version = VS71;
-}
-
-std::string cmGlobalVisualStudio71Generator::GetUserMacrosDirectory()
-{
-  // Macros not supported on Visual Studio 7.1 and earlier because
-  // they do not appear to work *during* a build when called by an
-  // outside agent...
-  //
-  return "";
-
-#if 0
-  //
-  // The COM result from calling a Visual Studio macro with 7.1 indicates
-  // that the call succeeds, but the macro does not appear to execute...
-  //
-  // So, I am leaving this code here to show how to do it, but have not
-  // yet figured out what the issue is in terms of why the macro does not
-  // appear to execute...
-  //
-  std::string base;
-  std::string path;
-
-  // base begins with the VisualStudioProjectsLocation reg value...
-  if (cmSystemTools::ReadRegistryValue(
-    "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\7.1;"
-    "VisualStudioProjectsLocation",
-    base))
-    {
-    cmSystemTools::ConvertToUnixSlashes(base);
-
-    // 7.1 macros folder:
-    path = base + "/VSMacros71";
-    }
-
-  // path is (correctly) still empty if we did not read the base value from
-  // the Registry value
-  return path;
-#endif
-}
-
-std::string cmGlobalVisualStudio71Generator::GetUserMacrosRegKeyBase()
-{
-  // Macros not supported on Visual Studio 7.1 and earlier because
-  // they do not appear to work *during* a build when called by an
-  // outside agent...
-  //
-  return "";
-
-#if 0
-  return "Software\\Microsoft\\VisualStudio\\7.1\\vsmacros";
-#endif
 }
 
 void cmGlobalVisualStudio71Generator::WriteSLNFile(
@@ -91,11 +39,6 @@ void cmGlobalVisualStudio71Generator::WriteSLNFile(
   std::ostringstream targetsSlnString;
   this->WriteTargetsToSolution(targetsSlnString, root, orderedProjectTargets);
 
-  // VS 7 does not support folders specified first.
-  if (this->GetVersion() <= VS71) {
-    fout << targetsSlnString.str();
-  }
-
   // Generate folder specification.
   bool useFolderProperty = this->UseFolderProperty();
   if (useFolderProperty) {
@@ -103,9 +46,7 @@ void cmGlobalVisualStudio71Generator::WriteSLNFile(
   }
 
   // Now write the actual target specification content.
-  if (this->GetVersion() > VS71) {
-    fout << targetsSlnString.str();
-  }
+  fout << targetsSlnString.str();
 
   // Write out the configurations information for the solution
   fout << "Global\n";
@@ -249,7 +190,7 @@ void cmGlobalVisualStudio71Generator::WriteExternalProject(
 // Write a dsp file into the SLN file, Note, that dependencies from
 // executables to the libraries it uses are also done here
 void cmGlobalVisualStudio71Generator::WriteProjectConfigurations(
-  std::ostream& fout, const std::string& name, cmStateEnums::TargetType,
+  std::ostream& fout, const std::string& name, cmGeneratorTarget const& target,
   std::vector<std::string> const& configs,
   const std::set<std::string>& configsPartOfDefaultBuild,
   std::string const& platformMapping)
@@ -259,13 +200,18 @@ void cmGlobalVisualStudio71Generator::WriteProjectConfigurations(
   std::string guid = this->GetGUID(name);
   for (std::vector<std::string>::const_iterator i = configs.begin();
        i != configs.end(); ++i) {
-    fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << *i << "|"
-         << platformName << std::endl;
+    const char* dstConfig = target.GetProperty("MAP_IMPORTED_CONFIG_" +
+                                               cmSystemTools::UpperCase(*i));
+    if (dstConfig == CM_NULLPTR) {
+      dstConfig = i->c_str();
+    }
+    fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << dstConfig
+         << "|" << platformName << std::endl;
     std::set<std::string>::const_iterator ci =
       configsPartOfDefaultBuild.find(*i);
     if (!(ci == configsPartOfDefaultBuild.end())) {
-      fout << "\t\t{" << guid << "}." << *i << ".Build.0 = " << *i << "|"
-           << platformName << std::endl;
+      fout << "\t\t{" << guid << "}." << *i << ".Build.0 = " << dstConfig
+           << "|" << platformName << std::endl;
     }
   }
 }
@@ -275,10 +221,3 @@ void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout)
 {
   fout << "Microsoft Visual Studio Solution File, Format Version 8.00\n";
 }
-
-void cmGlobalVisualStudio71Generator::GetDocumentation(
-  cmDocumentationEntry& entry)
-{
-  entry.Name = cmGlobalVisualStudio71Generator::GetActualName();
-  entry.Brief = "Deprecated. Generates Visual Studio .NET 2003 project files.";
-}
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index 9953047..0ce02aa 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -15,37 +15,8 @@ class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator
 public:
   cmGlobalVisualStudio71Generator(cmake* cm,
                                   const std::string& platformName = "");
-  static cmGlobalGeneratorFactory* NewFactory()
-  {
-    return new cmGlobalGeneratorSimpleFactory<
-      cmGlobalVisualStudio71Generator>();
-  }
-
-  ///! Get the name for the generator.
-  virtual std::string GetName() const
-  {
-    return cmGlobalVisualStudio71Generator::GetActualName();
-  }
-  static std::string GetActualName() { return "Visual Studio 7 .NET 2003"; }
-
-  /** Get the documentation entry for this generator.  */
-  static void GetDocumentation(cmDocumentationEntry& entry);
-
-  /**
-   * Where does this version of Visual Studio look for macros for the
-   * current user? Returns the empty string if this version of Visual
-   * Studio does not implement support for VB macros.
-   */
-  virtual std::string GetUserMacrosDirectory();
-
-  /**
-   * What is the reg key path to "vsmacros" for this version of Visual
-   * Studio?
-   */
-  virtual std::string GetUserMacrosRegKeyBase();
 
 protected:
-  virtual const char* GetIDEVersion() { return "7.1"; }
   virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root,
                             std::vector<cmLocalGenerator*>& generators);
   virtual void WriteSolutionConfigurations(
@@ -56,8 +27,8 @@ protected:
                                    const char* path,
                                    cmGeneratorTarget const* t);
   virtual void WriteProjectConfigurations(
-    std::ostream& fout, const std::string& name, cmStateEnums::TargetType type,
-    std::vector<std::string> const& configs,
+    std::ostream& fout, const std::string& name,
+    cmGeneratorTarget const& target, std::vector<std::string> const& configs,
     const std::set<std::string>& configsPartOfDefaultBuild,
     const std::string& platformMapping = "");
   virtual void WriteExternalProject(std::ostream& fout,
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 602666e..b155f5b 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -1,7 +1,5 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
-#include "windows.h" // this must be first to define GetCurrentDirectory
-
 #include "cmGlobalVisualStudio7Generator.h"
 
 #include "cmGeneratedFileStream.h"
@@ -11,9 +9,11 @@
 #include "cmState.h"
 #include "cmUuid.h"
 #include "cmake.h"
-#include <cmsys/Encoding.hxx>
+#include "cmsys/Encoding.hxx"
 
 #include <assert.h>
+#include <vector>
+#include <windows.h>
 
 static cmVS7FlagTable cmVS7ExtraFlagTable[] = {
   // Precompiled header and related options.  Note that the
@@ -47,6 +47,7 @@ cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
   this->IntelProjectVersion = 0;
   this->DevEnvCommandInitialized = false;
   this->MasmEnabled = false;
+  this->NasmEnabled = false;
 
   if (platformName.empty()) {
     this->DefaultPlatformName = "Win32";
@@ -54,7 +55,6 @@ cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
     this->DefaultPlatformName = platformName;
   }
   this->ExtraFlagTable = cmVS7ExtraFlagTable;
-  this->Version = VS7;
 }
 
 cmGlobalVisualStudio7Generator::~cmGlobalVisualStudio7Generator()
@@ -295,16 +295,16 @@ void cmGlobalVisualStudio7Generator::Generate()
     this->CallVisualStudioMacro(MacroReload);
   }
 
-  if (this->Version == VS71 && !this->CMakeInstance->GetIsInTryCompile()) {
-    const char* cmakeWarnVS71 =
-      this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_WARN_VS71");
-    if (!cmakeWarnVS71 || !cmSystemTools::IsOff(cmakeWarnVS71)) {
+  if (this->Version == VS8 && !this->CMakeInstance->GetIsInTryCompile()) {
+    const char* cmakeWarnVS8 =
+      this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_WARN_VS8");
+    if (!cmakeWarnVS8 || !cmSystemTools::IsOff(cmakeWarnVS8)) {
       this->CMakeInstance->IssueMessage(
         cmake::WARNING,
-        "The \"Visual Studio 7 .NET 2003\" generator is deprecated "
+        "The \"Visual Studio 8 2005\" generator is deprecated "
         "and will be removed in a future version of CMake."
         "\n"
-        "Add CMAKE_WARN_VS71=OFF to the cache to disable this warning.");
+        "Add CMAKE_WARN_VS8=OFF to the cache to disable this warning.");
     }
   }
 }
@@ -356,16 +356,16 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
     if (expath) {
       std::set<std::string> allConfigurations(configs.begin(), configs.end());
       const char* mapping = target->GetProperty("VS_PLATFORM_MAPPING");
-      this->WriteProjectConfigurations(
-        fout, target->GetName().c_str(), target->GetType(), configs,
-        allConfigurations, mapping ? mapping : "");
+      this->WriteProjectConfigurations(fout, target->GetName().c_str(),
+                                       *target, configs, allConfigurations,
+                                       mapping ? mapping : "");
     } else {
       const std::set<std::string>& configsPartOfDefaultBuild =
         this->IsPartOfDefaultBuild(configs, projectTargets, target);
       const char* vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
       if (vcprojName) {
-        this->WriteProjectConfigurations(fout, vcprojName, target->GetType(),
-                                         configs, configsPartOfDefaultBuild);
+        this->WriteProjectConfigurations(fout, vcprojName, *target, configs,
+                                         configsPartOfDefaultBuild);
       }
     }
   }
@@ -520,6 +520,7 @@ std::string cmGlobalVisualStudio7Generator::ConvertToSolutionPath(
 void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections(
   std::ostream& fout, cmLocalGenerator* root)
 {
+  std::string const guid = this->GetGUID(root->GetProjectName() + ".sln");
   bool extensibilityGlobalsOverridden = false;
   bool extensibilityAddInsOverridden = false;
   const std::vector<std::string> propKeys =
@@ -538,11 +539,14 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections(
       } else
         continue;
       if (!name.empty()) {
-        if (name == "ExtensibilityGlobals" && sectionType == "postSolution")
+        bool addGuid = false;
+        if (name == "ExtensibilityGlobals" && sectionType == "postSolution") {
+          addGuid = true;
           extensibilityGlobalsOverridden = true;
-        else if (name == "ExtensibilityAddIns" &&
-                 sectionType == "postSolution")
+        } else if (name == "ExtensibilityAddIns" &&
+                   sectionType == "postSolution") {
           extensibilityAddInsOverridden = true;
+        }
         fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n";
         std::vector<std::string> keyValuePairs;
         cmSystemTools::ExpandListArgument(
@@ -557,15 +561,23 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections(
             const std::string value =
               cmSystemTools::TrimWhitespace(itPair->substr(posEqual + 1));
             fout << "\t\t" << key << " = " << value << "\n";
+            if (key == "SolutionGuid") {
+              addGuid = false;
+            }
           }
         }
+        if (addGuid) {
+          fout << "\t\tSolutionGuid = {" << guid << "}\n";
+        }
         fout << "\tEndGlobalSection\n";
       }
     }
   }
-  if (!extensibilityGlobalsOverridden)
+  if (!extensibilityGlobalsOverridden) {
     fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
+         << "\t\tSolutionGuid = {" << guid << "}\n"
          << "\tEndGlobalSection\n";
+  }
   if (!extensibilityAddInsOverridden)
     fout << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
          << "\tEndGlobalSection\n";
@@ -681,10 +693,10 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
   // default build if another target depends on it
   int type = target->GetType();
   if (type == cmStateEnums::GLOBAL_TARGET) {
-    std::list<std::string> targetNames;
+    std::vector<std::string> targetNames;
     targetNames.push_back("INSTALL");
     targetNames.push_back("PACKAGE");
-    for (std::list<std::string>::const_iterator t = targetNames.begin();
+    for (std::vector<std::string>::const_iterator t = targetNames.begin();
          t != targetNames.end(); ++t) {
       // check if target <*t> is part of default build
       if (target->GetName() == *t) {
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 62194c3..32a8d60 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -95,6 +95,7 @@ public:
 
   /** Is the Microsoft Assembler enabled?  */
   bool IsMasmEnabled() const { return this->MasmEnabled; }
+  bool IsNasmEnabled() const { return this->NasmEnabled; }
 
   // Encoding for Visual Studio files
   virtual std::string Encoding();
@@ -120,8 +121,8 @@ protected:
                                    const char* path,
                                    cmGeneratorTarget const* t) = 0;
   virtual void WriteProjectConfigurations(
-    std::ostream& fout, const std::string& name, cmStateEnums::TargetType type,
-    std::vector<std::string> const& configs,
+    std::ostream& fout, const std::string& name,
+    cmGeneratorTarget const& target, std::vector<std::string> const& configs,
     const std::set<std::string>& configsPartOfDefaultBuild,
     const std::string& platformMapping = "") = 0;
   virtual void WriteSLNGlobalSections(std::ostream& fout,
@@ -163,6 +164,7 @@ protected:
   std::string GeneratorPlatform;
   std::string DefaultPlatformName;
   bool MasmEnabled;
+  bool NasmEnabled;
 
 private:
   char* IntelProjectVersion;
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 8353a3f..7a42b72 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -54,7 +54,7 @@ public:
   void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
   {
     entry.Name = std::string(vs8generatorName) + " [arch]";
-    entry.Brief = "Generates Visual Studio 2005 project files.  "
+    entry.Brief = "Deprecated.  Generates Visual Studio 2005 project files.  "
                   "Optional [arch] can be \"Win64\".";
   }
 
@@ -153,13 +153,6 @@ void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
   fout << "# Visual Studio 2005\n";
 }
 
-void cmGlobalVisualStudio8Generator::GetDocumentation(
-  cmDocumentationEntry& entry)
-{
-  entry.Name = cmGlobalVisualStudio8Generator::GetActualName();
-  entry.Brief = "Generates Visual Studio 8 2005 project files.";
-}
-
 std::string cmGlobalVisualStudio8Generator::GetGenerateStampList()
 {
   return "generate.stamp.list";
@@ -353,7 +346,7 @@ void cmGlobalVisualStudio8Generator::WriteSolutionConfigurations(
 }
 
 void cmGlobalVisualStudio8Generator::WriteProjectConfigurations(
-  std::ostream& fout, const std::string& name, cmStateEnums::TargetType type,
+  std::ostream& fout, const std::string& name, cmGeneratorTarget const& target,
   std::vector<std::string> const& configs,
   const std::set<std::string>& configsPartOfDefaultBuild,
   std::string const& platformMapping)
@@ -361,8 +354,13 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations(
   std::string guid = this->GetGUID(name);
   for (std::vector<std::string>::const_iterator i = configs.begin();
        i != configs.end(); ++i) {
+    const char* dstConfig = target.GetProperty("MAP_IMPORTED_CONFIG_" +
+                                               cmSystemTools::UpperCase(*i));
+    if (dstConfig == CM_NULLPTR) {
+      dstConfig = i->c_str();
+    }
     fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName()
-         << ".ActiveCfg = " << *i << "|"
+         << ".ActiveCfg = " << dstConfig << "|"
          << (!platformMapping.empty() ? platformMapping
                                       : this->GetPlatformName())
          << "\n";
@@ -370,14 +368,14 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations(
       configsPartOfDefaultBuild.find(*i);
     if (!(ci == configsPartOfDefaultBuild.end())) {
       fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName()
-           << ".Build.0 = " << *i << "|"
+           << ".Build.0 = " << dstConfig << "|"
            << (!platformMapping.empty() ? platformMapping
                                         : this->GetPlatformName())
            << "\n";
     }
-    if (this->NeedsDeploy(type)) {
+    if (this->NeedsDeploy(target.GetType())) {
       fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName()
-           << ".Deploy.0 = " << *i << "|"
+           << ".Deploy.0 = " << dstConfig << "|"
            << (!platformMapping.empty() ? platformMapping
                                         : this->GetPlatformName())
            << "\n";
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index 53feb47..4723b83 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -20,9 +20,6 @@ public:
   ///! Get the name for the generator.
   virtual std::string GetName() const { return this->Name; }
 
-  /** Get the documentation entry for this generator.  */
-  static void GetDocumentation(cmDocumentationEntry& entry);
-
   /** Get the name of the main stamp list file. */
   static std::string GetGenerateStampList();
 
@@ -82,8 +79,8 @@ protected:
   virtual void WriteSolutionConfigurations(
     std::ostream& fout, std::vector<std::string> const& configs);
   virtual void WriteProjectConfigurations(
-    std::ostream& fout, const std::string& name, cmStateEnums::TargetType type,
-    std::vector<std::string> const& configs,
+    std::ostream& fout, const std::string& name,
+    cmGeneratorTarget const& target, std::vector<std::string> const& configs,
     const std::set<std::string>& configsPartOfDefaultBuild,
     const std::string& platformMapping = "");
   virtual bool ComputeTargetDepends();
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index ced0c26..87a22d1 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -3,8 +3,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGlobalVisualStudioGenerator.h"
 
-#include <cmsys/Encoding.hxx>
+#include "cmsys/Encoding.hxx"
 #include <iostream>
+#include <windows.h>
 
 #include "cmAlgorithms.h"
 #include "cmCallVisualStudioMacro.h"
@@ -19,6 +20,7 @@
 cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm)
   : cmGlobalGenerator(cm)
 {
+  cm->GetState()->SetIsGeneratorMultiConfig(true);
   cm->GetState()->SetWindowsShell(true);
   cm->GetState()->SetWindowsVSIDE(true);
 }
@@ -441,8 +443,6 @@ std::string cmGlobalVisualStudioGenerator::GetStartupProjectName(
   return this->GetAllTargetName();
 }
 
-#include <windows.h>
-
 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
                                         const std::string& regKeyBase,
                                         std::string& nextAvailableSubKeyName)
@@ -730,12 +730,26 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
       return false;
     }
   }
+  // If there's only one source language, Fortran has to be used
+  // in order for the sources to compile.
+  // Note: Via linker propagation, LINKER_LANGUAGE could become CXX in
+  // this situation and mismatch from the actual language of the linker.
   gt->GetLanguages(languages, "");
   if (languages.size() == 1) {
     if (*languages.begin() == "Fortran") {
       return true;
     }
   }
+
+  // In the case of mixed object files or sources mixed with objects,
+  // decide the language based on the value of LINKER_LANGUAGE.
+  // This will not make it possible to mix source files of different
+  // languages, but object libraries will be linked together in the
+  // same fashion as other generators do.
+  if (gt->GetLinkerLanguage("") == "Fortran") {
+    return true;
+  }
+
   return false;
 }
 
@@ -814,10 +828,14 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
   cmGeneratorTarget* gt, std::vector<cmCustomCommand>& commands,
   std::string const& configName)
 {
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    gt->GetModuleDefinitionInfo(configName);
+  if (!mdi || !mdi->DefFileGenerated) {
+    return;
+  }
+
   std::vector<std::string> outputs;
-  std::string deffile = gt->ObjectDirectory;
-  deffile += "/exportall.def";
-  outputs.push_back(deffile);
+  outputs.push_back(mdi->DefFile);
   std::vector<std::string> empty;
   std::vector<cmSourceFile const*> objectSources;
   gt->GetObjectSources(objectSources, configName);
@@ -835,50 +853,58 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
   cmdl.push_back(cmakeCommand);
   cmdl.push_back("-E");
   cmdl.push_back("__create_def");
-  cmdl.push_back(deffile);
+  cmdl.push_back(mdi->DefFile);
   std::string obj_dir_expanded = obj_dir;
   cmSystemTools::ReplaceString(obj_dir_expanded, this->GetCMakeCFGIntDir(),
                                configName.c_str());
-  std::string objs_file = obj_dir_expanded;
-  cmSystemTools::MakeDirectory(objs_file.c_str());
-  objs_file += "/objects.txt";
+  cmSystemTools::MakeDirectory(obj_dir_expanded);
+  std::string const objs_file = obj_dir_expanded + "/objects.txt";
   cmdl.push_back(objs_file);
   cmGeneratedFileStream fout(objs_file.c_str());
   if (!fout) {
     cmSystemTools::Error("could not open ", objs_file.c_str());
     return;
   }
-  std::vector<std::string> objs;
-  for (std::vector<cmSourceFile const*>::const_iterator it =
-         objectSources.begin();
-       it != objectSources.end(); ++it) {
-    // Find the object file name corresponding to this source file.
-    std::map<cmSourceFile const*, std::string>::const_iterator map_it =
-      mapping.find(*it);
-    // It must exist because we populated the mapping just above.
-    assert(!map_it->second.empty());
-    std::string objFile = obj_dir + map_it->second;
-    objs.push_back(objFile);
-  }
-  std::vector<cmSourceFile const*> externalObjectSources;
-  gt->GetExternalObjects(externalObjectSources, configName);
-  for (std::vector<cmSourceFile const*>::const_iterator it =
-         externalObjectSources.begin();
-       it != externalObjectSources.end(); ++it) {
-    objs.push_back((*it)->GetFullPath());
-  }
 
-  gt->UseObjectLibraries(objs, configName);
-  for (std::vector<std::string>::iterator it = objs.begin(); it != objs.end();
-       ++it) {
-    std::string objFile = *it;
-    // replace $(ConfigurationName) in the object names
-    cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(),
-                                 configName.c_str());
-    if (cmHasLiteralSuffix(objFile, ".obj")) {
-      fout << objFile << "\n";
+  if (mdi->WindowsExportAllSymbols) {
+    std::vector<std::string> objs;
+    for (std::vector<cmSourceFile const*>::const_iterator it =
+           objectSources.begin();
+         it != objectSources.end(); ++it) {
+      // Find the object file name corresponding to this source file.
+      std::map<cmSourceFile const*, std::string>::const_iterator map_it =
+        mapping.find(*it);
+      // It must exist because we populated the mapping just above.
+      assert(!map_it->second.empty());
+      std::string objFile = obj_dir + map_it->second;
+      objs.push_back(objFile);
+    }
+    std::vector<cmSourceFile const*> externalObjectSources;
+    gt->GetExternalObjects(externalObjectSources, configName);
+    for (std::vector<cmSourceFile const*>::const_iterator it =
+           externalObjectSources.begin();
+         it != externalObjectSources.end(); ++it) {
+      objs.push_back((*it)->GetFullPath());
+    }
+
+    for (std::vector<std::string>::iterator it = objs.begin();
+         it != objs.end(); ++it) {
+      std::string objFile = *it;
+      // replace $(ConfigurationName) in the object names
+      cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(),
+                                   configName.c_str());
+      if (cmHasLiteralSuffix(objFile, ".obj")) {
+        fout << objFile << "\n";
+      }
     }
   }
+
+  for (std::vector<cmSourceFile const*>::const_iterator i =
+         mdi->Sources.begin();
+       i != mdi->Sources.end(); ++i) {
+    fout << (*i)->GetFullPath() << "\n";
+  }
+
   cmCustomCommandLines commandLines;
   commandLines.push_back(cmdl);
   cmCustomCommand command(gt->Target->GetMakefile(), outputs, empty, empty,
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index f32f0bb..c12a933 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalVisualStudioGenerator_h
 #define cmGlobalVisualStudioGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <map>
@@ -32,8 +32,6 @@ public:
   /** Known versions of Visual Studio.  */
   enum VSVersion
   {
-    VS7 = 70,
-    VS71 = 71,
     VS8 = 80,
     VS9 = 90,
     VS10 = 100,
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index 1c290f8..b2d6d5d 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmGlobalWatcomWMakeGenerator_h
 #define cmGlobalWatcomWMakeGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmGlobalGeneratorFactory.h"
 #include "cmGlobalUnixMakefileGenerator3.h"
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index dd771b1..3cd14e1 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGlobalXCodeGenerator.h"
 
+#include "cmsys/RegularExpression.hxx"
 #include <assert.h>
-#include <cmsys/RegularExpression.hxx>
 #include <iomanip>
 #include <sstream>
 #include <stdio.h>
@@ -28,6 +28,7 @@
 #include "cmTarget.h"
 #include "cmXCode21Object.h"
 #include "cmXCodeObject.h"
+#include "cmXCodeScheme.h"
 #include "cm_auto_ptr.hxx"
 #include "cmake.h"
 
@@ -132,24 +133,23 @@ public:
   bool SupportsPlatform() const CM_OVERRIDE { return false; }
 };
 
-cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(cmake* cm,
-                                               std::string const& version)
+cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(
+  cmake* cm, std::string const& version_string, unsigned int version_number)
   : cmGlobalGenerator(cm)
 {
-  this->VersionString = version;
-
-  // Compute an integer form of the version number.
-  unsigned int v[2] = { 0, 0 };
-  sscanf(this->VersionString.c_str(), "%u.%u", &v[0], &v[1]);
-  this->XcodeVersion = 10 * v[0] + v[1];
+  this->VersionString = version_string;
+  this->XcodeVersion = version_number;
 
   this->RootObject = 0;
   this->MainGroupChildren = 0;
-  this->SourcesGroupChildren = 0;
-  this->ResourcesGroupChildren = 0;
   this->CurrentMakefile = 0;
   this->CurrentLocalGenerator = 0;
   this->XcodeBuildCommandInitialized = false;
+
+  this->ObjectDirArchDefault = "$(CURRENT_ARCH)";
+  this->ObjectDirArch = this->ObjectDirArchDefault;
+
+  cm->GetState()->SetIsGeneratorMultiConfig(true);
 }
 
 cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory()
@@ -170,7 +170,7 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(
     std::string::size_type pos;
     if (cmSystemTools::RunSingleCommand("xcode-select --print-path", &out, 0,
                                         0, 0, cmSystemTools::OUTPUT_NONE) &&
-        (pos = out.find(".app/"), pos != out.npos)) {
+        (pos = out.find(".app/"), pos != std::string::npos)) {
       versionFile = out.substr(0, pos + 5) + "Contents/version.plist";
     }
   }
@@ -183,13 +183,21 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(
     parser.ParseFile(
       "/Developer/Applications/Xcode.app/Contents/version.plist");
   }
-  CM_AUTO_PTR<cmGlobalXCodeGenerator> gg(
-    new cmGlobalXCodeGenerator(cm, parser.Version));
-  if (gg->XcodeVersion == 20) {
-    cmSystemTools::Message("Xcode 2.0 not really supported by cmake, "
-                           "using Xcode 15 generator\n");
-    gg->XcodeVersion = 15;
+  std::string const& version_string = parser.Version;
+
+  // Compute an integer form of the version number.
+  unsigned int v[2] = { 0, 0 };
+  sscanf(version_string.c_str(), "%u.%u", &v[0], &v[1]);
+  unsigned int version_number = 10 * v[0] + v[1];
+
+  if (version_number < 30) {
+    cm->IssueMessage(cmake::FATAL_ERROR,
+                     "Xcode " + version_string + " not supported.");
+    return CM_NULLPTR;
   }
+
+  CM_AUTO_PTR<cmGlobalXCodeGenerator> gg(
+    new cmGlobalXCodeGenerator(cm, version_string, version_number));
   return gg.release();
 #else
   std::cerr << "CMake should be built with cmake to use Xcode, "
@@ -236,29 +244,25 @@ std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand()
 bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
                                                  cmMakefile* mf)
 {
-  if (this->XcodeVersion >= 30) {
-    if (ts.find_first_of(",=") != ts.npos) {
-      std::ostringstream e;
-      /* clang-format off */
-      e <<
-        "Generator\n"
-        "  " << this->GetName() << "\n"
-        "does not recognize the toolset\n"
-        "  " << ts << "\n"
-        "that was specified.";
-      /* clang-format on */
-      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
-      return false;
-    }
-    this->GeneratorToolset = ts;
-    if (!this->GeneratorToolset.empty()) {
-      mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
-                        this->GeneratorToolset.c_str());
-    }
-    return true;
-  } else {
-    return cmGlobalGenerator::SetGeneratorToolset(ts, mf);
+  if (ts.find_first_of(",=") != std::string::npos) {
+    std::ostringstream e;
+    /* clang-format off */
+    e <<
+      "Generator\n"
+      "  " << this->GetName() << "\n"
+      "does not recognize the toolset\n"
+      "  " << ts << "\n"
+      "that was specified.";
+    /* clang-format on */
+    mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+    return false;
+  }
+  this->GeneratorToolset = ts;
+  if (!this->GeneratorToolset.empty()) {
+    mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
+                      this->GeneratorToolset.c_str());
   }
+  return true;
 }
 
 void cmGlobalXCodeGenerator::EnableLanguage(
@@ -266,26 +270,17 @@ void cmGlobalXCodeGenerator::EnableLanguage(
 {
   mf->AddDefinition("XCODE", "1");
   mf->AddDefinition("XCODE_VERSION", this->VersionString.c_str());
-  if (this->XcodeVersion == 15) {
-  } else {
-    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);
-    }
+  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->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
   this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
-  const char* osxArch = mf->GetDefinition("CMAKE_OSX_ARCHITECTURES");
-  const char* sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT");
-  if (osxArch && sysroot) {
-    this->Architectures.clear();
-    cmSystemTools::ExpandListArgument(std::string(osxArch),
-                                      this->Architectures);
-  }
+  this->ComputeArchitectures(mf);
 }
 
 void cmGlobalXCodeGenerator::GenerateBuildCommand(
@@ -301,9 +296,7 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand(
   makeCommand.push_back("-project");
   std::string projectArg = projectName;
   projectArg += ".xcode";
-  if (this->XcodeVersion > 20) {
-    projectArg += "proj";
-  }
+  projectArg += "proj";
   makeCommand.push_back(projectArg);
 
   bool clean = false;
@@ -323,13 +316,8 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand(
   } else {
     makeCommand.push_back("ALL_BUILD");
   }
-  if (this->XcodeVersion == 15) {
-    makeCommand.push_back("-buildstyle");
-    makeCommand.push_back("Development");
-  } else {
-    makeCommand.push_back("-configuration");
-    makeCommand.push_back(!config.empty() ? config : "Debug");
-  }
+  makeCommand.push_back("-configuration");
+  makeCommand.push_back(!config.empty() ? config : "Debug");
   makeCommand.insert(makeCommand.end(), makeOptions.begin(),
                      makeOptions.end());
 }
@@ -391,9 +379,7 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget(
   std::string target = tName;
   std::replace(target.begin(), target.end(), ' ', '_');
   std::string out = "PostBuild." + target;
-  if (this->XcodeVersion > 20) {
-    out += "." + configName;
-  }
+  out += "." + configName;
   return out;
 }
 
@@ -423,14 +409,12 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
   // Add XCODE depend helper
   std::string dir = root->GetCurrentBinaryDirectory();
   cmCustomCommandLine makeHelper;
-  if (this->XcodeVersion < 50) {
-    makeHelper.push_back("make");
-    makeHelper.push_back("-C");
-    makeHelper.push_back(dir);
-    makeHelper.push_back("-f");
-    makeHelper.push_back(this->CurrentXCodeHackMakefile);
-    makeHelper.push_back(""); // placeholder, see below
-  }
+  makeHelper.push_back("make");
+  makeHelper.push_back("-C");
+  makeHelper.push_back(dir);
+  makeHelper.push_back("-f");
+  makeHelper.push_back(this->CurrentXCodeHackMakefile);
+  makeHelper.push_back(""); // placeholder, see below
 
   // Add ZERO_CHECK
   bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
@@ -475,13 +459,12 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
       // run the depend check makefile as a post build rule
       // this will make sure that when the next target is built
       // things are up-to-date
-      if (!makeHelper.empty() &&
-          (target->GetType() == cmStateEnums::EXECUTABLE ||
-           // Nope - no post-build for OBJECT_LIRBRARY
-           //          target->GetType() == cmStateEnums::OBJECT_LIBRARY ||
-           target->GetType() == cmStateEnums::STATIC_LIBRARY ||
-           target->GetType() == cmStateEnums::SHARED_LIBRARY ||
-           target->GetType() == cmStateEnums::MODULE_LIBRARY)) {
+      if (target->GetType() == cmStateEnums::OBJECT_LIBRARY ||
+          (this->XcodeVersion < 50 &&
+           (target->GetType() == cmStateEnums::EXECUTABLE ||
+            target->GetType() == cmStateEnums::STATIC_LIBRARY ||
+            target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+            target->GetType() == cmStateEnums::MODULE_LIBRARY))) {
         makeHelper[makeHelper.size() - 1] = // fill placeholder
           this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)");
         cmCustomCommandLines commandLines;
@@ -489,7 +472,8 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
         std::vector<std::string> no_byproducts;
         lg->GetMakefile()->AddCustomCommandToTarget(
           target->GetName(), no_byproducts, no_depends, commandLines,
-          cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str());
+          cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true,
+          false, "", false, cmMakefile::AcceptObjectLibraryCommands);
       }
 
       if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
@@ -605,12 +589,7 @@ void cmGlobalXCodeGenerator::addObject(cmXCodeObject* obj)
 cmXCodeObject* cmGlobalXCodeGenerator::CreateObject(
   cmXCodeObject::PBXType ptype)
 {
-  cmXCodeObject* obj;
-  if (this->XcodeVersion == 15) {
-    obj = new cmXCodeObject(ptype, cmXCodeObject::OBJECT);
-  } else {
-    obj = new cmXCode21Object(ptype, cmXCodeObject::OBJECT);
-  }
+  cmXCodeObject* obj = new cmXCode21Object(ptype, cmXCodeObject::OBJECT);
   this->addObject(obj);
   return obj;
 }
@@ -653,11 +632,6 @@ std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target,
   return key;
 }
 
-std::string GetGroupMapKey(cmGeneratorTarget* target, cmSourceFile* sf)
-{
-  return GetGroupMapKeyFromPath(target, sf->GetFullPath());
-}
-
 cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
   const std::string& fullpath, cmGeneratorTarget* target,
   const std::string& lang, cmSourceFile* sf)
@@ -725,18 +699,13 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
 
   cmXCodeObject* buildFile =
     this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), gtgt, lang, sf);
-  cmXCodeObject* fileRef = buildFile->GetObject("fileRef")->GetObject();
 
   cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
   settings->AddAttributeIfNotEmpty("COMPILER_FLAGS",
                                    this->CreateString(flags));
 
-  // Is this a resource file in this target? Add it to the resources group...
-  //
-
   cmGeneratorTarget::SourceFileFlags tsFlags =
     gtgt->GetTargetSourceFileFlags(sf);
-  bool isResource = tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource;
 
   cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
 
@@ -746,10 +715,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
   if (gtgt->IsFrameworkOnApple()) {
     if (tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) {
       attrs->AddObject(this->CreateString("Private"));
-      isResource = true;
     } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader) {
       attrs->AddObject(this->CreateString("Public"));
-      isResource = true;
     }
   }
 
@@ -769,14 +736,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
 
   settings->AddAttributeIfNotEmpty("ATTRIBUTES", attrs);
 
-  // Add the fileRef to the top level Resources group/folder if it is not
-  // already there.
-  //
-  if (isResource && this->ResourcesGroupChildren &&
-      !this->ResourcesGroupChildren->HasObject(fileRef)) {
-    this->ResourcesGroupChildren->AddObject(fileRef);
-  }
-
   buildFile->AddAttributeIfNotEmpty("settings", settings);
   return buildFile;
 }
@@ -901,9 +860,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
   fileRef->AddAttribute("name", this->CreateString(name));
   fileRef->AddAttribute("path", this->CreateString(path));
   fileRef->AddAttribute("sourceTree", this->CreateString(sourceTree));
-  if (this->XcodeVersion == 15) {
-    fileRef->AddAttribute("refType", this->CreateString("4"));
-  }
   return fileRef;
 }
 
@@ -1053,11 +1009,14 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
       // Add object library contents as external objects. (Equivalent to
       // the externalObjFiles above, except each one is not a cmSourceFile
       // within the target.)
-      std::vector<std::string> objs;
-      gtgt->UseObjectLibraries(objs, "");
-      for (std::vector<std::string>::const_iterator oi = objs.begin();
+      std::vector<cmSourceFile const*> objs;
+      gtgt->GetExternalObjects(objs, "");
+      for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin();
            oi != objs.end(); ++oi) {
-        std::string obj = *oi;
+        if ((*oi)->GetObjectLibrary().empty()) {
+          continue;
+        }
+        std::string const& obj = (*oi)->GetFullPath();
         cmXCodeObject* xsf =
           this->CreateXCodeSourceFileFromPath(obj, gtgt, "", 0);
         externalObjFiles.push_back(xsf);
@@ -1155,8 +1114,12 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
           // dstPath in frameworks is relative to Versions/<version>
           ostr << mit->first;
         } else if (mit->first != "MacOS") {
-          // dstPath in bundles is relative to Contents/MacOS
-          ostr << "../" << mit->first.c_str();
+          if (gtgt->Target->GetMakefile()->PlatformIsAppleIos()) {
+            ostr << mit->first;
+          } else {
+            // dstPath in bundles is relative to Contents/MacOS
+            ostr << "../" << mit->first;
+          }
         }
         copyFilesBuildPhase->AddAttribute("dstPath",
                                           this->CreateString(ostr.str()));
@@ -1174,6 +1137,45 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
       }
     }
 
+    // create vector of "resource content file" build phases - only for
+    // framework or bundle targets
+    if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
+      typedef std::map<std::string, std::vector<cmSourceFile*> >
+        mapOfVectorOfSourceFiles;
+      mapOfVectorOfSourceFiles bundleFiles;
+      for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
+           i != classes.end(); ++i) {
+        cmGeneratorTarget::SourceFileFlags tsFlags =
+          gtgt->GetTargetSourceFileFlags(*i);
+        if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
+          bundleFiles[tsFlags.MacFolder].push_back(*i);
+        }
+      }
+      mapOfVectorOfSourceFiles::iterator mit;
+      for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) {
+        cmXCodeObject* copyFilesBuildPhase =
+          this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
+        copyFilesBuildPhase->SetComment("Copy files");
+        copyFilesBuildPhase->AddAttribute("buildActionMask",
+                                          this->CreateString("2147483647"));
+        copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
+                                          this->CreateString("7"));
+        copyFilesBuildPhase->AddAttribute("dstPath",
+                                          this->CreateString(mit->first));
+        copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+                                          this->CreateString("0"));
+        buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+        copyFilesBuildPhase->AddAttribute("files", buildFiles);
+        std::vector<cmSourceFile*>::iterator sfIt;
+        for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) {
+          cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+            this->CurrentLocalGenerator, *sfIt, gtgt);
+          buildFiles->AddObject(xsf);
+        }
+        contentBuildPhases.push_back(copyFilesBuildPhase);
+      }
+    }
+
     // create framework build phase
     cmXCodeObject* frameworkBuildPhase = 0;
     if (!externalObjFiles.empty()) {
@@ -1398,7 +1400,7 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
   std::string retFlag;
   std::string::size_type lastOccurancePos = flags.rfind(flag);
   bool saved = false;
-  while (lastOccurancePos != flags.npos) {
+  while (lastOccurancePos != std::string::npos) {
     // increment pos, we use lastOccurancePos to reduce search space on next
     // inc
     std::string::size_type pos = lastOccurancePos;
@@ -1515,6 +1517,17 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(
   makecmd += " all";
   buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
   buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
+
+  cmXCodeObject* outputFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+  for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
+       i != commands.end(); ++i) {
+    std::vector<std::string> const& outputs = i->GetOutputs();
+    for (std::vector<std::string>::const_iterator j = outputs.begin();
+         j != outputs.end(); ++j) {
+      outputFiles->AddObject(this->CreateString(*j));
+    }
+  }
+  buildphase->AddAttribute("outputPaths", outputFiles);
 }
 
 void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
@@ -1522,9 +1535,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
   std::vector<cmCustomCommand> const& commands, const std::string& configName)
 {
   std::string makefileName = makefileBasename;
-  if (this->XcodeVersion > 20) {
-    makefileName += configName;
-  }
+  makefileName += configName;
   cmGeneratedFileStream makefileStream(makefileName.c_str());
   if (!makefileStream) {
     return;
@@ -1645,7 +1656,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
     std::string& flags = cflags[lang];
 
     // Add language-specific flags.
-    this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName);
+    this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang,
+                                                  configName);
 
     // Add shared-library flags if needed.
     this->CurrentLocalGenerator->AddCMP0018Flags(flags, gtgt, lang,
@@ -1665,16 +1677,20 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
     return;
   }
 
+  if (gtgt->IsIPOEnabled(llang, configName)) {
+    const char* ltoValue =
+      this->CurrentMakefile->IsOn("_CMAKE_LTO_THIN") ? "YES_THIN" : "YES";
+    buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue));
+  }
+
   // Add define flags
   this->CurrentLocalGenerator->AppendFlags(
     defFlags, this->CurrentMakefile->GetDefineFlags());
 
   // Add preprocessor definitions for this target and configuration.
-  BuildObjectListOrString ppDefs(this, this->XcodeVersion >= 30);
-  if (this->XcodeVersion > 15) {
-    this->AppendDefines(
-      ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
-  }
+  BuildObjectListOrString ppDefs(this, true);
+  this->AppendDefines(
+    ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
   if (const char* exportMacro = gtgt->GetExportMacro()) {
     // Add the export symbol definition for shared library objects.
     this->AppendDefines(ppDefs, exportMacro);
@@ -1774,15 +1790,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
       gtgt->GetType() == cmStateEnums::SHARED_LIBRARY ||
       gtgt->GetType() == cmStateEnums::MODULE_LIBRARY ||
       gtgt->GetType() == cmStateEnums::EXECUTABLE) {
-    if (this->XcodeVersion >= 21) {
-      if (!gtgt->UsesDefaultOutputDir(configName, false)) {
-        std::string pncdir = gtgt->GetDirectory(configName);
-        buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
-                                    this->CreateString(pncdir));
-      }
-    } else {
-      buildSettings->AddAttribute("OBJROOT", this->CreateString(pndir));
-      pndir = gtgt->GetDirectory(configName);
+    if (!gtgt->UsesDefaultOutputDir(configName,
+                                    cmStateEnums::RuntimeBinaryArtifact)) {
+      std::string pncdir = gtgt->GetDirectory(configName);
+      buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
+                                  this->CreateString(pncdir));
     }
 
     if (gtgt->IsFrameworkOnApple() || gtgt->IsCFBundleOnApple()) {
@@ -1798,16 +1810,10 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
     pnbase = gtgt->GetName();
     pnsuffix = ".a";
 
-    if (this->XcodeVersion >= 21) {
-      std::string pncdir = this->GetObjectsNormalDirectory(
-        this->CurrentProject, configName, gtgt);
-      buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
-                                  this->CreateString(pncdir));
-    } else {
-      buildSettings->AddAttribute("OBJROOT", this->CreateString(pndir));
-      pndir = this->GetObjectsNormalDirectory(this->CurrentProject, configName,
-                                              gtgt);
-    }
+    std::string pncdir =
+      this->GetObjectsNormalDirectory(this->CurrentProject, configName, gtgt);
+    buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
+                                this->CreateString(pncdir));
   }
 
   // Store the product name for all target types.
@@ -1876,7 +1882,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
           gtgt, "$(EXECUTABLE_NAME)", plist.c_str());
         buildSettings->AddAttribute("INFOPLIST_FILE",
                                     this->CreateString(plist));
-      } else if (this->XcodeVersion >= 22) {
+      } else {
         buildSettings->AddAttribute("MACH_O_TYPE",
                                     this->CreateString("mh_bundle"));
         buildSettings->AddAttribute("GCC_DYNAMIC_NO_PIC",
@@ -1888,14 +1894,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
           extraLinkOptions += " ";
           extraLinkOptions += createFlags;
         }
-      } else {
-        // Add the flags to create a module.
-        std::string createFlags = this->LookupFlags(
-          "CMAKE_SHARED_MODULE_CREATE_", llang, "_FLAGS", "-bundle");
-        if (!createFlags.empty()) {
-          extraLinkOptions += " ";
-          extraLinkOptions += createFlags;
-        }
       }
       break;
     }
@@ -1961,12 +1959,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
     default:
       break;
   }
-  if (this->XcodeVersion >= 22 && this->XcodeVersion < 40) {
+  if (this->XcodeVersion < 40) {
     buildSettings->AddAttribute("PREBINDING", this->CreateString("NO"));
   }
 
-  BuildObjectListOrString dirs(this, this->XcodeVersion >= 30);
-  BuildObjectListOrString fdirs(this, this->XcodeVersion >= 30);
+  BuildObjectListOrString dirs(this, true);
+  BuildObjectListOrString fdirs(this, true);
+  BuildObjectListOrString sysdirs(this, true);
+  BuildObjectListOrString sysfdirs(this, true);
+  const bool emitSystemIncludes = this->XcodeVersion >= 83;
+
   std::vector<std::string> includes;
   this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt, "C",
                                                      configName);
@@ -1980,11 +1982,22 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
       frameworkDir += "/../";
       frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
       if (emitted.insert(frameworkDir).second) {
-        fdirs.Add(this->XCodeEscapePath(frameworkDir));
+        std::string incpath = this->XCodeEscapePath(frameworkDir);
+        if (emitSystemIncludes &&
+            gtgt->IsSystemIncludeDirectory(frameworkDir, configName)) {
+          sysfdirs.Add(incpath);
+        } else {
+          fdirs.Add(incpath);
+        }
       }
     } else {
       std::string incpath = this->XCodeEscapePath(*i);
-      dirs.Add(incpath);
+      if (emitSystemIncludes &&
+          gtgt->IsSystemIncludeDirectory(*i, configName)) {
+        sysdirs.Add(incpath);
+      } else {
+        dirs.Add(incpath);
+      }
     }
   }
   // Add framework search paths needed for linking.
@@ -1993,7 +2006,13 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
     for (std::vector<std::string>::const_iterator fdi = fwDirs.begin();
          fdi != fwDirs.end(); ++fdi) {
       if (emitted.insert(*fdi).second) {
-        fdirs.Add(this->XCodeEscapePath(*fdi));
+        std::string incpath = this->XCodeEscapePath(*fdi);
+        if (emitSystemIncludes &&
+            gtgt->IsSystemIncludeDirectory(*fdi, configName)) {
+          sysfdirs.Add(incpath);
+        } else {
+          fdirs.Add(incpath);
+        }
       }
     }
   }
@@ -2003,8 +2022,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
   if (!dirs.IsEmpty()) {
     buildSettings->AddAttribute("HEADER_SEARCH_PATHS", dirs.CreateList());
   }
+  if (!sysfdirs.IsEmpty()) {
+    buildSettings->AddAttribute("SYSTEM_FRAMEWORK_SEARCH_PATHS",
+                                sysfdirs.CreateList());
+  }
+  if (!sysdirs.IsEmpty()) {
+    buildSettings->AddAttribute("SYSTEM_HEADER_SEARCH_PATHS",
+                                sysdirs.CreateList());
+  }
 
-  if (this->XcodeVersion >= 60) {
+  if (this->XcodeVersion >= 60 && !emitSystemIncludes) {
     // Add those per-language flags in addition to HEADER_SEARCH_PATHS to gain
     // system include directory awareness. We need to also keep on setting
     // HEADER_SEARCH_PATHS to work around a missing compile options flag for
@@ -2170,18 +2197,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
   buildSettings->AddAttribute("OTHER_REZFLAGS", this->CreateString(""));
   buildSettings->AddAttribute("SECTORDER_FLAGS", this->CreateString(""));
   buildSettings->AddAttribute("USE_HEADERMAP", this->CreateString("NO"));
-  if (this->XcodeVersion >= 30) {
-    cmXCodeObject* group = this->CreateObject(cmXCodeObject::OBJECT_LIST);
-    group->AddObject(this->CreateString("-Wmost"));
-    group->AddObject(this->CreateString("-Wno-four-char-constants"));
-    group->AddObject(this->CreateString("-Wno-unknown-pragmas"));
-    group->AddObject(this->CreateString("$(inherited)"));
-    buildSettings->AddAttribute("WARNING_CFLAGS", group);
-  } else {
-    buildSettings->AddAttribute(
-      "WARNING_CFLAGS", this->CreateString("-Wmost -Wno-four-char-constants"
-                                           " -Wno-unknown-pragmas"));
-  }
+  cmXCodeObject* group = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+  group->AddObject(this->CreateString("-Wmost"));
+  group->AddObject(this->CreateString("-Wno-four-char-constants"));
+  group->AddObject(this->CreateString("-Wno-unknown-pragmas"));
+  group->AddObject(this->CreateString("$(inherited)"));
+  buildSettings->AddAttribute("WARNING_CFLAGS", group);
 
   // Runtime version information.
   if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) {
@@ -2261,16 +2282,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
   this->CreateCustomCommands(buildPhases, 0, 0, 0, emptyContentVector, 0,
                              gtgt);
   target->AddAttribute("buildPhases", buildPhases);
-  if (this->XcodeVersion > 20) {
-    this->AddConfigurations(target, gtgt);
-  } else {
-    std::string theConfig =
-      this->CurrentMakefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
-    cmXCodeObject* buildSettings =
-      this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
-    this->CreateBuildSettings(gtgt, buildSettings, theConfig);
-    target->AddAttribute("buildSettings", buildSettings);
-  }
+  this->AddConfigurations(target, gtgt);
   cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST);
   target->AddAttribute("dependencies", dependencies);
   target->AddAttribute("name", this->CreateString(gtgt->GetName()));
@@ -2372,8 +2384,7 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(
       else if (target->IsCFBundleOnApple())
         return "wrapper.plug-in";
       else
-        return ((this->XcodeVersion >= 22) ? "compiled.mach-o.executable"
-                                           : "compiled.mach-o.dylib");
+        return "compiled.mach-o.executable";
     case cmStateEnums::SHARED_LIBRARY:
       return (target->GetPropertyAsBool("FRAMEWORK")
                 ? "wrapper.framework"
@@ -2406,9 +2417,7 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(
       else if (target->IsCFBundleOnApple())
         return "com.apple.product-type.bundle";
       else
-        return ((this->XcodeVersion >= 22)
-                  ? "com.apple.product-type.tool"
-                  : "com.apple.product-type.library.dynamic");
+        return "com.apple.product-type.tool";
     case cmStateEnums::SHARED_LIBRARY:
       return (target->GetPropertyAsBool("FRAMEWORK")
                 ? "com.apple.product-type.framework"
@@ -2434,15 +2443,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget(
   cmXCodeObject* buildRules = this->CreateObject(cmXCodeObject::OBJECT_LIST);
   target->AddAttribute("buildRules", buildRules);
   std::string defConfig;
-  if (this->XcodeVersion > 20) {
-    defConfig = this->AddConfigurations(target, gtgt);
-  } else {
-    cmXCodeObject* buildSettings =
-      this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
-    defConfig = this->CurrentMakefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
-    this->CreateBuildSettings(gtgt, buildSettings, defConfig);
-    target->AddAttribute("buildSettings", buildSettings);
-  }
+  defConfig = this->AddConfigurations(target, gtgt);
   cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST);
   target->AddAttribute("dependencies", dependencies);
   target->AddAttribute("name", this->CreateString(gtgt->GetName()));
@@ -2461,9 +2462,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget(
     fullName = gtgt->GetFullName(defConfig);
   }
   fileRef->AddAttribute("path", this->CreateString(fullName));
-  if (this->XcodeVersion == 15) {
-    fileRef->AddAttribute("refType", this->CreateString("0"));
-  }
   fileRef->AddAttribute("sourceTree",
                         this->CreateString("BUILT_PRODUCTS_DIR"));
   fileRef->SetComment(gtgt->GetName());
@@ -2564,32 +2562,25 @@ void cmGlobalXCodeGenerator::AppendBuildSettingAttribute(
   cmXCodeObject* target, const char* attribute, const char* value,
   const std::string& configName)
 {
-  if (this->XcodeVersion < 21) {
-    // There is only one configuration.  Add the setting to the buildSettings
-    // of the target.
-    this->AppendOrAddBuildSetting(target->GetObject("buildSettings"),
-                                  attribute, value);
-  } else {
-    // There are multiple configurations.  Add the setting to the
-    // buildSettings of the configuration name given.
-    cmXCodeObject* configurationList =
-      target->GetObject("buildConfigurationList")->GetObject();
-    cmXCodeObject* buildConfigs =
-      configurationList->GetObject("buildConfigurations");
-    std::vector<cmXCodeObject*> list = buildConfigs->GetObjectList();
-    // each configuration and the target itself has a buildSettings in it
-    // list.push_back(target);
-    for (std::vector<cmXCodeObject*>::iterator i = list.begin();
-         i != list.end(); ++i) {
-      if (!configName.empty()) {
-        if ((*i)->GetObject("name")->GetString() == configName) {
-          cmXCodeObject* settings = (*i)->GetObject("buildSettings");
-          this->AppendOrAddBuildSetting(settings, attribute, value);
-        }
-      } else {
+  // There are multiple configurations.  Add the setting to the
+  // buildSettings of the configuration name given.
+  cmXCodeObject* configurationList =
+    target->GetObject("buildConfigurationList")->GetObject();
+  cmXCodeObject* buildConfigs =
+    configurationList->GetObject("buildConfigurations");
+  std::vector<cmXCodeObject*> list = buildConfigs->GetObjectList();
+  // each configuration and the target itself has a buildSettings in it
+  // list.push_back(target);
+  for (std::vector<cmXCodeObject*>::iterator i = list.begin(); i != list.end();
+       ++i) {
+    if (!configName.empty()) {
+      if ((*i)->GetObject("name")->GetString() == configName) {
         cmXCodeObject* settings = (*i)->GetObject("buildSettings");
         this->AppendOrAddBuildSetting(settings, attribute, value);
       }
+    } else {
+      cmXCodeObject* settings = (*i)->GetObject("buildSettings");
+      this->AppendOrAddBuildSetting(settings, attribute, value);
     }
   }
 }
@@ -2625,13 +2616,16 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
       // Add object library contents as link flags.
       std::string linkObjs;
       const char* sep = "";
-      std::vector<std::string> objs;
-      gt->UseObjectLibraries(objs, "");
-      for (std::vector<std::string>::const_iterator oi = objs.begin();
+      std::vector<cmSourceFile const*> objs;
+      gt->GetExternalObjects(objs, configName);
+      for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin();
            oi != objs.end(); ++oi) {
+        if ((*oi)->GetObjectLibrary().empty()) {
+          continue;
+        }
         linkObjs += sep;
         sep = " ";
-        linkObjs += this->XCodeEscapePath(*oi);
+        linkObjs += this->XCodeEscapePath((*oi)->GetFullPath());
       }
       this->AppendBuildSettingAttribute(
         target, this->GetTargetLinkFlagsVar(gt), linkObjs.c_str(), configName);
@@ -2666,13 +2660,11 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
       for (std::vector<std::string>::const_iterator libDir = libDirs.begin();
            libDir != libDirs.end(); ++libDir) {
         if (libDir->size() && *libDir != "/usr/lib") {
-          if (this->XcodeVersion > 15) {
-            // Now add the same one but append
-            // $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it:
-            linkDirs += " ";
-            linkDirs += this->XCodeEscapePath(
-              *libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)");
-          }
+          // Now add the same one but append
+          // $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it:
+          linkDirs += " ";
+          linkDirs += this->XCodeEscapePath(
+            *libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)");
           linkDirs += " ";
           linkDirs += this->XCodeEscapePath(*libDir);
         }
@@ -2738,32 +2730,23 @@ bool cmGlobalXCodeGenerator::CreateGroups(
         gtgt->AddSource(plist);
       }
 
-      std::vector<cmSourceFile*> classes;
-      if (!gtgt->GetConfigCommonSourceFiles(classes)) {
-        return false;
-      }
+      std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+        gtgt->GetAllConfigSources();
+
       // Put cmSourceFile instances in proper groups:
-      for (std::vector<cmSourceFile*>::const_iterator s = classes.begin();
-           s != classes.end(); s++) {
-        cmSourceFile* sf = *s;
+      for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
+             sources.begin();
+           si != sources.end(); ++si) {
+        cmSourceFile const* sf = si->Source;
+        if (this->XcodeVersion >= 50 && !sf->GetObjectLibrary().empty()) {
+          // Object library files go on the link line instead.
+          continue;
+        }
         // Add the file to the list of sources.
         std::string const& source = sf->GetFullPath();
         cmSourceGroup* sourceGroup =
           mf->FindSourceGroup(source.c_str(), sourceGroups);
         cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
-        std::string key = GetGroupMapKey(gtgt, sf);
-        this->GroupMap[key] = pbxgroup;
-      }
-
-      // Put OBJECT_LIBRARY objects in proper groups:
-      std::vector<std::string> objs;
-      gtgt->UseObjectLibraries(objs, "");
-      for (std::vector<std::string>::const_iterator oi = objs.begin();
-           oi != objs.end(); ++oi) {
-        std::string const& source = *oi;
-        cmSourceGroup* sourceGroup =
-          mf->FindSourceGroup(source.c_str(), sourceGroups);
-        cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
         std::string key = GetGroupMapKeyFromPath(gtgt, source);
         this->GroupMap[key] = pbxgroup;
       }
@@ -2783,9 +2766,6 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreatePBXGroup(cmXCodeObject* parent,
     this->CreateObject(cmXCodeObject::OBJECT_LIST);
   group->AddAttribute("name", this->CreateString(name));
   group->AddAttribute("children", groupChildren);
-  if (this->XcodeVersion == 15) {
-    group->AddAttribute("refType", this->CreateString("4"));
-  }
   group->AddAttribute("sourceTree", this->CreateString("<group>"));
   if (parentChildren)
     parentChildren->AddObject(group);
@@ -2833,7 +2813,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
       tgroup = this->CreatePBXGroup(tgroup, tgt_folders[i]);
       this->TargetGroup[curr_tgt_folder] = tgroup;
       if (i == 0) {
-        this->SourcesGroupChildren->AddObject(tgroup);
+        this->MainGroupChildren->AddObject(tgroup);
       }
     }
   }
@@ -2879,69 +2859,27 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
 {
   this->ClearXCodeObjects();
   this->RootObject = 0;
-  this->SourcesGroupChildren = 0;
-  this->ResourcesGroupChildren = 0;
   this->MainGroupChildren = 0;
   cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
   group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
-  cmXCodeObject* developBuildStyle =
-    this->CreateObject(cmXCodeObject::PBXBuildStyle);
   cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
-  if (this->XcodeVersion == 15) {
-    developBuildStyle->AddAttribute("name", this->CreateString("Development"));
-    developBuildStyle->AddAttribute("buildSettings", group);
-    listObjs->AddObject(developBuildStyle);
-    group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
-    group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("YES"));
-    cmXCodeObject* deployBuildStyle =
+  for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
+    cmXCodeObject* buildStyle =
       this->CreateObject(cmXCodeObject::PBXBuildStyle);
-    deployBuildStyle->AddAttribute("name", this->CreateString("Deployment"));
-    deployBuildStyle->AddAttribute("buildSettings", group);
-    listObjs->AddObject(deployBuildStyle);
-  } else {
-    for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
-      cmXCodeObject* buildStyle =
-        this->CreateObject(cmXCodeObject::PBXBuildStyle);
-      const char* name = this->CurrentConfigurationTypes[i].c_str();
-      buildStyle->AddAttribute("name", this->CreateString(name));
-      buildStyle->SetComment(name);
-      cmXCodeObject* sgroup =
-        this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
-      sgroup->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
-      buildStyle->AddAttribute("buildSettings", sgroup);
-      listObjs->AddObject(buildStyle);
-    }
+    const char* name = this->CurrentConfigurationTypes[i].c_str();
+    buildStyle->AddAttribute("name", this->CreateString(name));
+    buildStyle->SetComment(name);
+    cmXCodeObject* sgroup = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
+    sgroup->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
+    buildStyle->AddAttribute("buildSettings", sgroup);
+    listObjs->AddObject(buildStyle);
   }
 
   cmXCodeObject* mainGroup = this->CreateObject(cmXCodeObject::PBXGroup);
   this->MainGroupChildren = this->CreateObject(cmXCodeObject::OBJECT_LIST);
   mainGroup->AddAttribute("children", this->MainGroupChildren);
-  if (this->XcodeVersion == 15) {
-    mainGroup->AddAttribute("refType", this->CreateString("4"));
-  }
   mainGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
 
-  cmXCodeObject* sourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup);
-  this->SourcesGroupChildren = this->CreateObject(cmXCodeObject::OBJECT_LIST);
-  sourcesGroup->AddAttribute("name", this->CreateString("Sources"));
-  sourcesGroup->AddAttribute("children", this->SourcesGroupChildren);
-  if (this->XcodeVersion == 15) {
-    sourcesGroup->AddAttribute("refType", this->CreateString("4"));
-  }
-  sourcesGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
-  this->MainGroupChildren->AddObject(sourcesGroup);
-
-  cmXCodeObject* resourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup);
-  this->ResourcesGroupChildren =
-    this->CreateObject(cmXCodeObject::OBJECT_LIST);
-  resourcesGroup->AddAttribute("name", this->CreateString("Resources"));
-  resourcesGroup->AddAttribute("children", this->ResourcesGroupChildren);
-  if (this->XcodeVersion == 15) {
-    resourcesGroup->AddAttribute("refType", this->CreateString("4"));
-  }
-  resourcesGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
-  this->MainGroupChildren->AddObject(resourcesGroup);
-
   // now create the cmake groups
   if (!this->CreateGroups(generators)) {
     return false;
@@ -2949,9 +2887,6 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
 
   cmXCodeObject* productGroup = this->CreateObject(cmXCodeObject::PBXGroup);
   productGroup->AddAttribute("name", this->CreateString("Products"));
-  if (this->XcodeVersion == 15) {
-    productGroup->AddAttribute("refType", this->CreateString("4"));
-  }
   productGroup->AddAttribute("sourceTree", this->CreateString("<group>"));
   cmXCodeObject* productGroupChildren =
     this->CreateObject(cmXCodeObject::OBJECT_LIST);
@@ -2973,24 +2908,22 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
   this->RootObject->AddAttribute("buildStyles", listObjs);
   this->RootObject->AddAttribute("hasScannedForEncodings",
                                  this->CreateString("0"));
-  if (this->XcodeVersion >= 30) {
-    group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
-    group->AddAttribute("BuildIndependentTargetsInParallel",
-                        this->CreateString("YES"));
-    std::ostringstream v;
-    v << std::setfill('0') << std::setw(4) << XcodeVersion * 10;
-    group->AddAttribute("LastUpgradeCheck", this->CreateString(v.str()));
-    this->RootObject->AddAttribute("attributes", group);
-    if (this->XcodeVersion >= 32)
-      this->RootObject->AddAttribute("compatibilityVersion",
-                                     this->CreateString("Xcode 3.2"));
-    else if (this->XcodeVersion >= 31)
-      this->RootObject->AddAttribute("compatibilityVersion",
-                                     this->CreateString("Xcode 3.1"));
-    else
-      this->RootObject->AddAttribute("compatibilityVersion",
-                                     this->CreateString("Xcode 3.0"));
-  }
+  group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
+  group->AddAttribute("BuildIndependentTargetsInParallel",
+                      this->CreateString("YES"));
+  std::ostringstream v;
+  v << std::setfill('0') << std::setw(4) << XcodeVersion * 10;
+  group->AddAttribute("LastUpgradeCheck", this->CreateString(v.str()));
+  this->RootObject->AddAttribute("attributes", group);
+  if (this->XcodeVersion >= 32)
+    this->RootObject->AddAttribute("compatibilityVersion",
+                                   this->CreateString("Xcode 3.2"));
+  else if (this->XcodeVersion >= 31)
+    this->RootObject->AddAttribute("compatibilityVersion",
+                                   this->CreateString("Xcode 3.1"));
+  else
+    this->RootObject->AddAttribute("compatibilityVersion",
+                                   this->CreateString("Xcode 3.0"));
   // Point Xcode at the top of the source tree.
   {
     std::string pdir =
@@ -3005,26 +2938,15 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
   typedef std::vector<std::pair<std::string, cmXCodeObject*> > Configs;
   Configs configs;
   const char* defaultConfigName = "Debug";
-  if (this->XcodeVersion == 15) {
-    cmXCodeObject* configDebug =
-      this->CreateObject(cmXCodeObject::XCBuildConfiguration);
-    configDebug->AddAttribute("name", this->CreateString("Debug"));
-    configs.push_back(std::make_pair("Debug", configDebug));
-    cmXCodeObject* configRelease =
-      this->CreateObject(cmXCodeObject::XCBuildConfiguration);
-    configRelease->AddAttribute("name", this->CreateString("Release"));
-    configs.push_back(std::make_pair("Release", configRelease));
-  } else {
-    for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
-      const char* name = this->CurrentConfigurationTypes[i].c_str();
-      if (0 == i) {
-        defaultConfigName = name;
-      }
-      cmXCodeObject* config =
-        this->CreateObject(cmXCodeObject::XCBuildConfiguration);
-      config->AddAttribute("name", this->CreateString(name));
-      configs.push_back(std::make_pair(name, config));
+  for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
+    const char* name = this->CurrentConfigurationTypes[i].c_str();
+    if (0 == i) {
+      defaultConfigName = name;
     }
+    cmXCodeObject* config =
+      this->CreateObject(cmXCodeObject::XCBuildConfiguration);
+    config->AddAttribute("name", this->CreateString(name));
+    configs.push_back(std::make_pair(name, config));
   }
   for (Configs::iterator c = configs.begin(); c != configs.end(); ++c) {
     buildConfigurations->AddObject(c->second);
@@ -3042,23 +2964,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
                            this->CreateString(defaultConfigName));
   cmXCodeObject* buildSettings =
     this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
-  const char* osxArch =
-    this->CurrentMakefile->GetDefinition("CMAKE_OSX_ARCHITECTURES");
   const char* sysroot =
     this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT");
   const char* deploymentTarget =
     this->CurrentMakefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
-  std::string archs;
   if (sysroot) {
-    if (osxArch) {
-      // recompute this as it may have been changed since enable language
-      this->Architectures.clear();
-      cmSystemTools::ExpandListArgument(std::string(osxArch),
-                                        this->Architectures);
-      archs = cmJoin(this->Architectures, " ");
-    }
     buildSettings->AddAttribute("SDKROOT", this->CreateString(sysroot));
   }
+  // recompute this as it may have been changed since enable language
+  this->ComputeArchitectures(this->CurrentMakefile);
+  std::string const archs = cmJoin(this->Architectures, " ");
   if (archs.empty()) {
     // Tell Xcode to use NATIVE_ARCH instead of ARCHS.
     buildSettings->AddAttribute("ONLY_ACTIVE_ARCH", this->CreateString("YES"));
@@ -3133,10 +3048,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
     cmXCodeObject* t = *i;
     this->AddDependAndLinkInformation(t);
   }
-  if (this->XcodeVersion < 50) {
-    // now create xcode depend hack makefile
-    this->CreateXCodeDependHackTarget(targets);
-  }
+  this->CreateXCodeDependHackTarget(targets);
   // now add all targets to the root object
   cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST);
   for (std::vector<cmXCodeObject*>::iterator i = targets.begin();
@@ -3168,6 +3080,38 @@ std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory(
   return dir;
 }
 
+void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf)
+{
+  this->Architectures.clear();
+  const char* osxArch = mf->GetDefinition("CMAKE_OSX_ARCHITECTURES");
+  const char* sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT");
+  if (osxArch && sysroot) {
+    cmSystemTools::ExpandListArgument(std::string(osxArch),
+                                      this->Architectures);
+  }
+
+  if (this->Architectures.empty()) {
+    // With no ARCHS we use ONLY_ACTIVE_ARCH.
+    // Look up the arch that Xcode chooses in this case.
+    if (const char* arch = mf->GetDefinition("CMAKE_XCODE_CURRENT_ARCH")) {
+      this->ObjectDirArchDefault = arch;
+    }
+  }
+
+  this->ComputeObjectDirArch(mf);
+}
+
+void cmGlobalXCodeGenerator::ComputeObjectDirArch(cmMakefile* mf)
+{
+  if (this->Architectures.size() > 1 || this->UseEffectivePlatformName(mf)) {
+    this->ObjectDirArch = "$(CURRENT_ARCH)";
+  } else if (!this->Architectures.empty()) {
+    this->ObjectDirArch = this->Architectures[0];
+  } else {
+    this->ObjectDirArch = this->ObjectDirArchDefault;
+  }
+}
+
 void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
   std::vector<cmXCodeObject*>& targets)
 {
@@ -3187,29 +3131,9 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
     "default:\n"
     "\techo \"Do not invoke directly\"\n"
     "\n";
-  makefileStream
-    << "# For each target create a dummy rule "
-    "so the target does not have to exist\n";
   /* clang-format on */
-  std::set<std::string> emitted;
-  for (std::vector<cmXCodeObject*>::iterator i = targets.begin();
-       i != targets.end(); ++i) {
-    cmXCodeObject* target = *i;
-    std::map<std::string, cmXCodeObject::StringVec> const& deplibs =
-      target->GetDependLibraries();
-    for (std::map<std::string, cmXCodeObject::StringVec>::const_iterator ci =
-           deplibs.begin();
-         ci != deplibs.end(); ++ci) {
-      for (cmXCodeObject::StringVec::const_iterator d = ci->second.begin();
-           d != ci->second.end(); ++d) {
-        if (emitted.insert(*d).second) {
-          makefileStream << this->ConvertToRelativeForMake(d->c_str())
-                         << ":\n";
-        }
-      }
-    }
-  }
-  makefileStream << "\n\n";
+
+  std::set<std::string> dummyRules;
 
   // Write rules to help Xcode relink things at the right time.
   /* clang-format off */
@@ -3228,8 +3152,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
       cmGeneratorTarget* gt = target->GetTarget();
 
       if (gt->GetType() == cmStateEnums::EXECUTABLE ||
-          // Nope - no post-build for OBJECT_LIRBRARY
-          //         gt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
+          gt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
           gt->GetType() == cmStateEnums::STATIC_LIBRARY ||
           gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
           gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
@@ -3239,6 +3162,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
       }
 
       if (gt->GetType() == cmStateEnums::EXECUTABLE ||
+          gt->GetType() == cmStateEnums::STATIC_LIBRARY ||
           gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
           gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
         std::string tfull = gt->GetFullPath(configName);
@@ -3256,6 +3180,15 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
           }
         }
 
+        std::vector<cmGeneratorTarget*> objlibs;
+        gt->GetObjectLibrariesCMP0026(objlibs);
+        for (std::vector<cmGeneratorTarget*>::const_iterator it =
+               objlibs.begin();
+             it != objlibs.end(); ++it) {
+          makefileStream << this->PostBuildMakeTarget((*it)->GetName(), *ct)
+                         << ": " << trel << "\n";
+        }
+
         // Create a rule for this target.
         makefileStream << trel << ":";
 
@@ -3266,10 +3199,28 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
           std::vector<std::string> const& deplibs = x->second;
           for (std::vector<std::string>::const_iterator d = deplibs.begin();
                d != deplibs.end(); ++d) {
-            makefileStream << "\\\n\t"
-                           << this->ConvertToRelativeForMake(d->c_str());
+            std::string file = this->ConvertToRelativeForMake(d->c_str());
+            makefileStream << "\\\n\t" << file;
+            dummyRules.insert(file);
           }
         }
+
+        for (std::vector<cmGeneratorTarget*>::const_iterator it =
+               objlibs.begin();
+             it != objlibs.end(); ++it) {
+
+          const std::string objLibName = (*it)->GetName();
+          std::string d = this->GetObjectsNormalDirectory(this->CurrentProject,
+                                                          configName, *it);
+          d += "lib";
+          d += objLibName;
+          d += ".a";
+
+          std::string dependency = this->ConvertToRelativeForMake(d.c_str());
+          makefileStream << "\\\n\t" << dependency;
+          dummyRules.insert(dependency);
+        }
+
         // Write the action to remove the target if it is out of date.
         makefileStream << "\n";
         makefileStream << "\t/bin/rm -f "
@@ -3297,6 +3248,14 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
       }
     }
   }
+
+  makefileStream << "\n\n"
+                 << "# For each target create a dummy rule"
+                 << "so the target does not have to exist\n";
+  for (std::set<std::string>::const_iterator it = dummyRules.begin();
+       it != dummyRules.end(); ++it) {
+    makefileStream << *it << ":\n";
+  }
 }
 
 void cmGlobalXCodeGenerator::OutputXCodeProject(
@@ -3319,10 +3278,7 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
   std::string xcodeDir = root->GetCurrentBinaryDirectory();
   xcodeDir += "/";
   xcodeDir += root->GetProjectName();
-  xcodeDir += ".xcode";
-  if (this->XcodeVersion > 20) {
-    xcodeDir += "proj";
-  }
+  xcodeDir += ".xcodeproj";
   cmSystemTools::MakeDirectory(xcodeDir.c_str());
   std::string xcodeProjFile = xcodeDir + "/project.pbxproj";
   cmGeneratedFileStream fout(xcodeProjFile.c_str());
@@ -3331,6 +3287,17 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
     return;
   }
   this->WriteXCodePBXProj(fout, root, generators);
+
+  // Since the lowest available Xcode version for testing was 7.0,
+  // I'm setting this as a limit then
+  if (this->XcodeVersion >= 70) {
+    if (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() ||
+        root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")) {
+      this->OutputXCodeSharedSchemes(xcodeDir);
+      this->OutputXCodeWorkspaceSettings(xcodeDir);
+    }
+  }
+
   this->ClearXCodeObjects();
 
   // Since this call may have created new cache entries, save the cache:
@@ -3339,6 +3306,54 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
     root->GetBinaryDirectory());
 }
 
+void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
+  const std::string& xcProjDir)
+{
+  for (std::vector<cmXCodeObject*>::const_iterator i =
+         this->XCodeObjects.begin();
+       i != this->XCodeObjects.end(); ++i) {
+    cmXCodeObject* obj = *i;
+    if (obj->GetType() == cmXCodeObject::OBJECT &&
+        (obj->GetIsA() == cmXCodeObject::PBXNativeTarget ||
+         obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) {
+      cmXCodeScheme schm(obj, this->CurrentConfigurationTypes,
+                         this->XcodeVersion);
+      schm.WriteXCodeSharedScheme(xcProjDir,
+                                  this->RelativeToSource(xcProjDir.c_str()));
+    }
+  }
+}
+
+void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings(
+  const std::string& xcProjDir)
+{
+  std::string xcodeSharedDataDir = xcProjDir;
+  xcodeSharedDataDir += "/project.xcworkspace/xcshareddata";
+  cmSystemTools::MakeDirectory(xcodeSharedDataDir);
+
+  std::string workspaceSettingsFile = xcodeSharedDataDir;
+  workspaceSettingsFile += "/WorkspaceSettings.xcsettings";
+
+  cmGeneratedFileStream fout(workspaceSettingsFile.c_str());
+  fout.SetCopyIfDifferent(true);
+  if (!fout) {
+    return;
+  }
+
+  cmXMLWriter xout(fout);
+  xout.StartDocument();
+  xout.Doctype("plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\""
+               "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"");
+  xout.StartElement("plist");
+  xout.Attribute("version", "1.0");
+  xout.StartElement("dict");
+  xout.Element("key", "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded");
+  xout.Element("false");
+  xout.EndElement(); // dict
+  xout.EndElement(); // plist
+  xout.EndDocument();
+}
+
 void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
                                                cmLocalGenerator*,
                                                std::vector<cmLocalGenerator*>&)
@@ -3354,20 +3369,13 @@ void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
   cmXCodeObject::Indent(1, fout);
   fout << "};\n";
   cmXCodeObject::Indent(1, fout);
-  if (this->XcodeVersion >= 21) {
-    if (this->XcodeVersion >= 32)
-      fout << "objectVersion = 46;\n";
-    else if (this->XcodeVersion >= 31)
-      fout << "objectVersion = 45;\n";
-    else if (this->XcodeVersion >= 30)
-      fout << "objectVersion = 44;\n";
-    else
-      fout << "objectVersion = 42;\n";
-    cmXCode21Object::PrintList(this->XCodeObjects, fout);
-  } else {
-    fout << "objectVersion = 39;\n";
-    cmXCodeObject::PrintList(this->XCodeObjects, fout);
-  }
+  if (this->XcodeVersion >= 32)
+    fout << "objectVersion = 46;\n";
+  else if (this->XcodeVersion >= 31)
+    fout << "objectVersion = 45;\n";
+  else
+    fout << "objectVersion = 44;\n";
+  cmXCode21Object::PrintList(this->XCodeObjects, fout);
   cmXCodeObject::Indent(1, fout);
   fout << "rootObject = " << this->RootObject->GetId()
        << " /* Project object */;\n";
@@ -3376,9 +3384,7 @@ void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
 
 const char* cmGlobalXCodeGenerator::GetCMakeCFGIntDir() const
 {
-  return this->XcodeVersion >= 21
-    ? "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"
-    : ".";
+  return "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
 }
 
 std::string cmGlobalXCodeGenerator::ExpandCFGIntDir(
@@ -3428,7 +3434,7 @@ std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p)
 
 std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p)
 {
-  if (p.find(' ') != p.npos) {
+  if (p.find(' ') != std::string::npos) {
     std::string t = "\"";
     t += p;
     t += "\"";
@@ -3441,12 +3447,10 @@ void cmGlobalXCodeGenerator::AppendDirectoryForConfig(
   const std::string& prefix, const std::string& config,
   const std::string& suffix, std::string& dir)
 {
-  if (this->XcodeVersion > 20) {
-    if (!config.empty()) {
-      dir += prefix;
-      dir += config;
-      dir += suffix;
-    }
+  if (!config.empty()) {
+    dir += prefix;
+    dir += config;
+    dir += suffix;
   }
 }
 
@@ -3518,7 +3522,7 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
 
   // Check if the flag needs quoting.
   bool quoteFlag =
-    flag.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != flag.npos;
+    flag.find_first_of("`~!@#$%^&*()+={}[]|:;\"'<>,.? ") != std::string::npos;
 
   // We escape a flag as follows:
   //   - Place each flag in single quotes ''
@@ -3571,12 +3575,19 @@ std::string cmGlobalXCodeGenerator::ComputeInfoPListLocation(
 // i.e. "Can I build Debug and Release in the same tree?"
 bool cmGlobalXCodeGenerator::IsMultiConfig() const
 {
-  // Old Xcode 1.5 is single config:
-  if (this->XcodeVersion == 15) {
+  // Newer Xcode versions are multi config:
+  return true;
+}
+
+bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation(
+  std::string* reason) const
+{
+  if (this->ObjectDirArch.find('$') != std::string::npos) {
+    if (reason != CM_NULLPTR) {
+      *reason = " under Xcode with multiple architectures";
+    }
     return false;
   }
-
-  // Newer Xcode versions are multi config:
   return true;
 }
 
@@ -3593,21 +3604,19 @@ bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const
   return cmSystemTools::IsOn(epnValue);
 }
 
+bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const
+{
+  // Xcode determines Resource location itself
+  return true;
+}
+
 void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
   std::string configName = this->GetCMakeCFGIntDir();
   std::string dir =
     this->GetObjectsNormalDirectory("$(PROJECT_NAME)", configName, gt);
-  if (this->XcodeVersion >= 21) {
-    dir += "$(CURRENT_ARCH)/";
-  } else {
-#ifdef __ppc__
-    dir += "ppc/";
-#endif
-#ifdef __i386
-    dir += "i386/";
-#endif
-  }
+  dir += this->ObjectDirArch;
+  dir += "/";
   gt->ObjectDirectory = dir;
 }
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 1aaf9c7..e69793b 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -3,7 +3,8 @@
 #ifndef cmGlobalXCodeGenerator_h
 #define cmGlobalXCodeGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <iosfwd>
 #include <map>
 #include <set>
@@ -31,7 +32,8 @@ struct cmDocumentationEntry;
 class cmGlobalXCodeGenerator : public cmGlobalGenerator
 {
 public:
-  cmGlobalXCodeGenerator(cmake* cm, std::string const& version);
+  cmGlobalXCodeGenerator(cmake* cm, std::string const& version_string,
+                         unsigned int version_number);
   static cmGlobalGeneratorFactory* NewFactory();
 
   ///! Get the name for the generator.
@@ -86,8 +88,14 @@ public:
       i.e. "Can I build Debug and Release in the same tree?" */
   bool IsMultiConfig() const CM_OVERRIDE;
 
+  bool HasKnownObjectFileLocation(std::string* reason) const CM_OVERRIDE;
+
+  bool IsIPOSupported() const CM_OVERRIDE { return true; }
+
   bool UseEffectivePlatformName(cmMakefile* mf) const CM_OVERRIDE;
 
+  bool ShouldStripResourcePath(cmMakefile*) const CM_OVERRIDE;
+
   bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) CM_OVERRIDE;
   void AppendFlag(std::string& flags, std::string const& flag);
 
@@ -165,6 +173,9 @@ private:
                           std::vector<cmLocalGenerator*>& generators);
   void OutputXCodeProject(cmLocalGenerator* root,
                           std::vector<cmLocalGenerator*>& generators);
+  // Write shared scheme files for all the native targets
+  void OutputXCodeSharedSchemes(const std::string& xcProjDir);
+  void OutputXCodeWorkspaceSettings(const std::string& xcProjDir);
   void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root,
                          std::vector<cmLocalGenerator*>& generators);
   cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath,
@@ -235,12 +246,13 @@ private:
                                         const std::string& configName,
                                         const cmGeneratorTarget* t) const;
 
+  void ComputeArchitectures(cmMakefile* mf);
+  void ComputeObjectDirArch(cmMakefile* mf);
+
   void addObject(cmXCodeObject* obj);
   std::string PostBuildMakeTarget(std::string const& tName,
                                   std::string const& configName);
   cmXCodeObject* MainGroupChildren;
-  cmXCodeObject* SourcesGroupChildren;
-  cmXCodeObject* ResourcesGroupChildren;
   cmMakefile* CurrentMakefile;
   cmLocalGenerator* CurrentLocalGenerator;
   std::vector<std::string> CurrentConfigurationTypes;
@@ -256,6 +268,8 @@ private:
   std::map<std::string, cmXCodeObject*> FileRefs;
   std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap;
   std::vector<std::string> Architectures;
+  std::string ObjectDirArchDefault;
+  std::string ObjectDirArch;
   std::string GeneratorToolset;
 };
 
diff --git a/Source/cmGraphAdjacencyList.h b/Source/cmGraphAdjacencyList.h
index e6aec47..46cf878 100644
--- a/Source/cmGraphAdjacencyList.h
+++ b/Source/cmGraphAdjacencyList.h
@@ -3,7 +3,7 @@
 #ifndef cmGraphAdjacencyList_h
 #define cmGraphAdjacencyList_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <vector>
 
@@ -15,26 +15,11 @@
 class cmGraphEdge
 {
 public:
-  cmGraphEdge()
-    : Dest(0)
-    , Strong(true)
-  {
-  }
-  cmGraphEdge(int n)
-    : Dest(n)
-    , Strong(true)
-  {
-  }
-  cmGraphEdge(int n, bool s)
+  cmGraphEdge(int n = 0, bool s = true)
     : Dest(n)
     , Strong(s)
   {
   }
-  cmGraphEdge(cmGraphEdge const& r)
-    : Dest(r.Dest)
-    , Strong(r.Strong)
-  {
-  }
   operator int() const { return this->Dest; }
 
   bool IsStrong() const { return this->Strong; }
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index 0f69aaa..7e953ce 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmGraphVizWriter.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 #include <iostream>
 #include <sstream>
 #include <utility>
@@ -61,7 +61,7 @@ cmGraphVizWriter::cmGraphVizWriter(
 void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
                                     const char* fallbackSettingsFileName)
 {
-  cmake cm;
+  cmake cm(cmake::RoleScript);
   cm.SetHomeDirectory("");
   cm.SetHomeOutputDirectory("");
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h
index 1ff07ab..824999b 100644
--- a/Source/cmGraphVizWriter.h
+++ b/Source/cmGraphVizWriter.h
@@ -3,11 +3,11 @@
 #ifndef CMGRAPHVIZWRITER_H
 #define CMGRAPHVIZWRITER_H
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmStateTypes.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <map>
 #include <set>
 #include <string>
diff --git a/Source/cmHexFileConverter.cxx b/Source/cmHexFileConverter.cxx
index d9d6598..78dceb7 100644
--- a/Source/cmHexFileConverter.cxx
+++ b/Source/cmHexFileConverter.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmHexFileConverter.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 #include <stdio.h>
 #include <string.h>
 
diff --git a/Source/cmIDEFlagTable.h b/Source/cmIDEFlagTable.h
index 64ade76..152e293 100644
--- a/Source/cmIDEFlagTable.h
+++ b/Source/cmIDEFlagTable.h
@@ -24,6 +24,9 @@ struct cmIDEFlagTable
                                     // IgnoreDefaultLibraryNames)
     UserFollowing = (1 << 5),       // expect value in following argument
     CaseInsensitive = (1 << 6),     // flag may be any case
+    SpaceAppendable = (1 << 7),     // a flag that if specified multiple times
+                                    // should have its value appended to the
+                                    // old value with spaces
 
     UserValueIgnored = UserValue | UserIgnored,
     UserValueRequired = UserValue | UserRequired
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index 8d07776..5e872d2 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmIDEOptions.h"
 
-#include <cmsys/String.h>
+#include "cmsys/String.h"
 #include <iterator>
 #include <string.h>
 
@@ -125,6 +125,8 @@ void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
     this->FlagMap[entry->IDEName] = entry->value;
   } else if (entry->special & cmIDEFlagTable::SemicolonAppendable) {
     this->FlagMap[entry->IDEName].push_back(new_value);
+  } else if (entry->special & cmIDEFlagTable::SpaceAppendable) {
+    this->FlagMap[entry->IDEName].append_with_space(new_value);
   } else {
     // Use the user-specified value.
     this->FlagMap[entry->IDEName] = new_value;
@@ -177,6 +179,12 @@ void cmIDEOptions::AppendFlag(std::string const& flag,
   std::copy(value.begin(), value.end(), std::back_inserter(fv));
 }
 
+void cmIDEOptions::AppendFlagString(std::string const& flag,
+                                    std::string const& value)
+{
+  this->FlagMap[flag].append_with_space(value);
+}
+
 void cmIDEOptions::RemoveFlag(const char* flag)
 {
   this->FlagMap.erase(flag);
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index be2fd6d..19e96bd 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -3,7 +3,7 @@
 #ifndef cmIDEOptions_h
 #define cmIDEOptions_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <map>
 #include <string>
@@ -31,6 +31,7 @@ public:
   void AppendFlag(std::string const& flag, std::string const& value);
   void AppendFlag(std::string const& flag,
                   std::vector<std::string> const& value);
+  void AppendFlagString(std::string const& flag, std::string const& value);
   void RemoveFlag(const char* flag);
   bool HasFlag(std::string const& flag) const;
   const char* GetFlag(const char* flag);
@@ -59,15 +60,22 @@ protected:
       this->derived::operator=(r);
       return *this;
     }
+    FlagValue& append_with_space(std::string const& r)
+    {
+      this->resize(1);
+      std::string& l = this->operator[](0);
+      if (!l.empty()) {
+        l += " ";
+      }
+      l += r;
+      return *this;
+    }
   };
   std::map<std::string, FlagValue> FlagMap;
 
   // Preprocessor definitions.
   std::vector<std::string> Defines;
 
-  // Unrecognized flags that get no special handling.
-  std::string FlagString;
-
   bool DoingDefine;
   bool AllowDefine;
   bool AllowSlash;
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index a8fa4f9..0972664 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -57,8 +57,19 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
         // watch for our state change
         if (scopeDepth == 0 &&
             !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(), "else")) {
+
+          if (this->ElseSeen) {
+            cmListFileBacktrace bt = mf.GetBacktrace(this->Functions[c]);
+            mf.GetCMakeInstance()->IssueMessage(
+              cmake::FATAL_ERROR,
+              "A duplicate ELSE command was found inside an IF block.", bt);
+            cmSystemTools::SetFatalErrorOccured();
+            return true;
+          }
+
           this->IsBlocking = this->HasRun;
           this->HasRun = true;
+          this->ElseSeen = true;
 
           // if trace is enabled, print a (trivially) evaluated "else"
           // statement
@@ -68,6 +79,15 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
         } else if (scopeDepth == 0 &&
                    !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),
                                            "elseif")) {
+          if (this->ElseSeen) {
+            cmListFileBacktrace bt = mf.GetBacktrace(this->Functions[c]);
+            mf.GetCMakeInstance()->IssueMessage(
+              cmake::FATAL_ERROR,
+              "An ELSEIF command was found after an ELSE command.", bt);
+            cmSystemTools::SetFatalErrorOccured();
+            return true;
+          }
+
           if (this->HasRun) {
             this->IsBlocking = true;
           } else {
@@ -117,15 +137,15 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
           status.Clear();
           mf.ExecuteCommand(this->Functions[c], status);
           if (status.GetReturnInvoked()) {
-            inStatus.SetReturnInvoked(true);
+            inStatus.SetReturnInvoked();
             return true;
           }
           if (status.GetBreakInvoked()) {
-            inStatus.SetBreakInvoked(true);
+            inStatus.SetBreakInvoked();
             return true;
           }
           if (status.GetContinueInvoked()) {
-            inStatus.SetContinueInvoked(true);
+            inStatus.SetContinueInvoked();
             return true;
           }
         }
diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h
index 56eef30..5877a7d 100644
--- a/Source/cmIfCommand.h
+++ b/Source/cmIfCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmIfCommand_h
 #define cmIfCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -21,6 +22,7 @@ public:
   cmIfFunctionBlocker()
   {
     this->HasRun = false;
+    this->ElseSeen = false;
     this->ScopeDepth = 0;
   }
   ~cmIfFunctionBlocker() CM_OVERRIDE {}
@@ -32,6 +34,7 @@ public:
   std::vector<cmListFileFunction> Functions;
   bool IsBlocking;
   bool HasRun;
+  bool ElseSeen;
   unsigned int ScopeDepth;
 };
 
@@ -61,16 +64,6 @@ public:
     return false;
   }
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "if"; }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
   // Filter the given variable definition based on policy CMP0054.
   static const char* GetDefinitionIfUnquoted(
     const cmMakefile* mf, cmExpandedCommandArgument const& argument);
diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h
index 78edd43..16dda0e 100644
--- a/Source/cmIncludeCommand.h
+++ b/Source/cmIncludeCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmIncludeCommand_h
 #define cmIncludeCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,16 +32,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "include"; }
 };
 
 #endif
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index cdb0279..b81f7cb 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -113,7 +113,7 @@ void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc)
 {
   std::string::size_type b = inc.find_first_not_of(" \r");
   std::string::size_type e = inc.find_last_not_of(" \r");
-  if ((b != inc.npos) && (e != inc.npos)) {
+  if ((b != std::string::npos) && (e != std::string::npos)) {
     inc.assign(inc, b, 1 + e - b); // copy the remaining substring
   } else {
     inc = "";
diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h
index 287b5d3..12de698 100644
--- a/Source/cmIncludeDirectoryCommand.h
+++ b/Source/cmIncludeDirectoryCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmIncludeDirectoryCommand_h
 #define cmIncludeDirectoryCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "include_directories"; }
-
 protected:
   // used internally
   void GetIncludes(const std::string& arg, std::vector<std::string>& incs);
diff --git a/Source/cmIncludeExternalMSProjectCommand.h b/Source/cmIncludeExternalMSProjectCommand.h
index 9fcf467..375646f 100644
--- a/Source/cmIncludeExternalMSProjectCommand.h
+++ b/Source/cmIncludeExternalMSProjectCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmIncludeExternalMSProjectCommand_h
 #define cmIncludeExternalMSProjectCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -35,14 +36,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "include_external_msproject";
-  }
 };
 
 #endif
diff --git a/Source/cmIncludeRegularExpressionCommand.h b/Source/cmIncludeRegularExpressionCommand.h
index c68d9f2..bac4b8f 100644
--- a/Source/cmIncludeRegularExpressionCommand.h
+++ b/Source/cmIncludeRegularExpressionCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmIncludeRegularExpressionCommand_h
 #define cmIncludeRegularExpressionCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -34,14 +35,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "include_regular_expression";
-  }
 };
 
 #endif
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 4c331c7..294fb17 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallCommand.h"
 
-#include <cmsys/Glob.hxx>
+#include "cmsys/Glob.hxx"
 #include <sstream>
 #include <stddef.h>
 
@@ -75,29 +75,31 @@ bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
     this->DefaultComponentName = "Unspecified";
   }
 
+  std::string const& mode = args[0];
+
   // Switch among the command modes.
-  if (args[0] == "SCRIPT") {
+  if (mode == "SCRIPT") {
     return this->HandleScriptMode(args);
   }
-  if (args[0] == "CODE") {
+  if (mode == "CODE") {
     return this->HandleScriptMode(args);
   }
-  if (args[0] == "TARGETS") {
+  if (mode == "TARGETS") {
     return this->HandleTargetsMode(args);
   }
-  if (args[0] == "FILES") {
+  if (mode == "FILES") {
     return this->HandleFilesMode(args);
   }
-  if (args[0] == "PROGRAMS") {
+  if (mode == "PROGRAMS") {
     return this->HandleFilesMode(args);
   }
-  if (args[0] == "DIRECTORY") {
+  if (mode == "DIRECTORY") {
     return this->HandleDirectoryMode(args);
   }
-  if (args[0] == "EXPORT") {
+  if (mode == "EXPORT") {
     return this->HandleExportMode(args);
   }
-  if (args[0] == "EXPORT_ANDROID_MK") {
+  if (mode == "EXPORT_ANDROID_MK") {
     return this->HandleExportAndroidMKMode(args);
   }
 
@@ -165,7 +167,7 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
         script.c_str(), false, component.c_str(), exclude_from_all));
     } else if (doing_code) {
       doing_code = false;
-      std::string code = args[i];
+      std::string const& code = args[i];
       this->Makefile->AddInstallGenerator(new cmInstallScriptGenerator(
         code.c_str(), true, component.c_str(), exclude_from_all));
     }
@@ -206,6 +208,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   cmCAStringVector archiveArgVector(&argHelper, "ARCHIVE", &group);
   cmCAStringVector libraryArgVector(&argHelper, "LIBRARY", &group);
   cmCAStringVector runtimeArgVector(&argHelper, "RUNTIME", &group);
+  cmCAStringVector objectArgVector(&argHelper, "OBJECTS", &group);
   cmCAStringVector frameworkArgVector(&argHelper, "FRAMEWORK", &group);
   cmCAStringVector bundleArgVector(&argHelper, "BUNDLE", &group);
   cmCAStringVector includesArgVector(&argHelper, "INCLUDES", &group);
@@ -234,6 +237,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   cmInstallCommandArguments archiveArgs(this->DefaultComponentName);
   cmInstallCommandArguments libraryArgs(this->DefaultComponentName);
   cmInstallCommandArguments runtimeArgs(this->DefaultComponentName);
+  cmInstallCommandArguments objectArgs(this->DefaultComponentName);
   cmInstallCommandArguments frameworkArgs(this->DefaultComponentName);
   cmInstallCommandArguments bundleArgs(this->DefaultComponentName);
   cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName);
@@ -246,6 +250,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   archiveArgs.Parse(&archiveArgVector.GetVector(), &unknownArgs);
   libraryArgs.Parse(&libraryArgVector.GetVector(), &unknownArgs);
   runtimeArgs.Parse(&runtimeArgVector.GetVector(), &unknownArgs);
+  objectArgs.Parse(&objectArgVector.GetVector(), &unknownArgs);
   frameworkArgs.Parse(&frameworkArgVector.GetVector(), &unknownArgs);
   bundleArgs.Parse(&bundleArgVector.GetVector(), &unknownArgs);
   privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
@@ -265,6 +270,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   archiveArgs.SetGenericArguments(&genericArgs);
   libraryArgs.SetGenericArguments(&genericArgs);
   runtimeArgs.SetGenericArguments(&genericArgs);
+  objectArgs.SetGenericArguments(&genericArgs);
   frameworkArgs.SetGenericArguments(&genericArgs);
   bundleArgs.SetGenericArguments(&genericArgs);
   privateHeaderArgs.SetGenericArguments(&genericArgs);
@@ -274,6 +280,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   success = success && archiveArgs.Finalize();
   success = success && libraryArgs.Finalize();
   success = success && runtimeArgs.Finalize();
+  success = success && objectArgs.Finalize();
   success = success && frameworkArgs.Finalize();
   success = success && bundleArgs.Finalize();
   success = success && privateHeaderArgs.Finalize();
@@ -287,8 +294,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   // Enforce argument rules too complex to specify for the
   // general-purpose parser.
   if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() ||
-      frameworkArgs.GetNamelinkOnly() || bundleArgs.GetNamelinkOnly() ||
-      privateHeaderArgs.GetNamelinkOnly() ||
+      objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() ||
+      bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() ||
       publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) {
     this->SetError(
       "TARGETS given NAMELINK_ONLY option not in LIBRARY group.  "
@@ -296,8 +303,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
     return false;
   }
   if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() ||
-      frameworkArgs.GetNamelinkSkip() || bundleArgs.GetNamelinkSkip() ||
-      privateHeaderArgs.GetNamelinkSkip() ||
+      objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() ||
+      bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() ||
       publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) {
     this->SetError(
       "TARGETS given NAMELINK_SKIP option not in LIBRARY group.  "
@@ -356,11 +363,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
         return false;
       }
       if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
-        std::ostringstream e;
-        e << "TARGETS given OBJECT library \"" << (*targetIt)
-          << "\" which may not be installed.";
-        this->SetError(e.str());
-        return false;
+        std::string reason;
+        if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
+              &reason)) {
+          std::ostringstream e;
+          e << "TARGETS given OBJECT library \"" << (*targetIt)
+            << "\" which may not be installed" << reason << ".";
+          this->SetError(e.str());
+          return false;
+        }
       }
       // Store the target in the list to be installed.
       targets.push_back(target);
@@ -379,6 +390,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   bool installsArchive = false;
   bool installsLibrary = false;
   bool installsRuntime = false;
+  bool installsObject = false;
   bool installsFramework = false;
   bool installsBundle = false;
   bool installsPrivateHeader = false;
@@ -393,6 +405,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
     cmInstallTargetGenerator* archiveGenerator = CM_NULLPTR;
     cmInstallTargetGenerator* libraryGenerator = CM_NULLPTR;
     cmInstallTargetGenerator* runtimeGenerator = CM_NULLPTR;
+    cmInstallTargetGenerator* objectGenerator = CM_NULLPTR;
     cmInstallTargetGenerator* frameworkGenerator = CM_NULLPTR;
     cmInstallTargetGenerator* bundleGenerator = CM_NULLPTR;
     cmInstallFilesGenerator* privateHeaderGenerator = CM_NULLPTR;
@@ -522,6 +535,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
           return false;
         }
       } break;
+      case cmStateEnums::OBJECT_LIBRARY: {
+        // Objects use OBJECT properties.
+        if (!objectArgs.GetDestination().empty()) {
+          objectGenerator =
+            CreateInstallTargetGenerator(target, objectArgs, false);
+        } else {
+          std::ostringstream e;
+          e << "TARGETS given no OBJECTS DESTINATION for object library "
+               "target \""
+            << target.GetName() << "\".";
+          this->SetError(e.str());
+          return false;
+        }
+      } break;
       case cmStateEnums::EXECUTABLE: {
         if (target.IsAppBundleOnApple()) {
           // Application bundles use the BUNDLE properties.
@@ -664,6 +691,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
     installsArchive = installsArchive || archiveGenerator != CM_NULLPTR;
     installsLibrary = installsLibrary || libraryGenerator != CM_NULLPTR;
     installsRuntime = installsRuntime || runtimeGenerator != CM_NULLPTR;
+    installsObject = installsObject || objectGenerator != CM_NULLPTR;
     installsFramework = installsFramework || frameworkGenerator != CM_NULLPTR;
     installsBundle = installsBundle || bundleGenerator != CM_NULLPTR;
     installsPrivateHeader =
@@ -675,6 +703,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
     this->Makefile->AddInstallGenerator(archiveGenerator);
     this->Makefile->AddInstallGenerator(libraryGenerator);
     this->Makefile->AddInstallGenerator(runtimeGenerator);
+    this->Makefile->AddInstallGenerator(objectGenerator);
     this->Makefile->AddInstallGenerator(frameworkGenerator);
     this->Makefile->AddInstallGenerator(bundleGenerator);
     this->Makefile->AddInstallGenerator(privateHeaderGenerator);
@@ -692,6 +721,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       te->HeaderGenerator = publicHeaderGenerator;
       te->LibraryGenerator = libraryGenerator;
       te->RuntimeGenerator = runtimeGenerator;
+      te->ObjectsGenerator = objectGenerator;
       this->Makefile->GetGlobalGenerator()
         ->GetExportSets()[exports.GetString()]
         ->AddTargetExport(te);
@@ -715,6 +745,10 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
     this->Makefile->GetGlobalGenerator()->AddInstallComponent(
       runtimeArgs.GetComponent().c_str());
   }
+  if (installsObject) {
+    this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+      objectArgs.GetComponent().c_str());
+  }
   if (installsFramework) {
     this->Makefile->GetGlobalGenerator()->AddInstallComponent(
       frameworkArgs.GetComponent().c_str());
@@ -1176,7 +1210,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
 
   // Check the file name.
   std::string fname = filename.GetString();
-  if (fname.find_first_of(":/\\") != fname.npos) {
+  if (fname.find_first_of(":/\\") != std::string::npos) {
     std::ostringstream e;
     e << args[0] << " given invalid export file name \"" << fname << "\".  "
       << "The FILE argument may not contain a path.  "
@@ -1194,7 +1228,7 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
     this->SetError(e.str());
     return false;
   }
-  if (fname.find_first_of(":/\\") != fname.npos) {
+  if (fname.find_first_of(":/\\") != std::string::npos) {
     std::ostringstream e;
     e << args[0] << " given export name \"" << exp.GetString() << "\".  "
       << "This name cannot be safely converted to a file name.  "
@@ -1268,7 +1302,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
 
   // Check the file name.
   std::string fname = filename.GetString();
-  if (fname.find_first_of(":/\\") != fname.npos) {
+  if (fname.find_first_of(":/\\") != std::string::npos) {
     std::ostringstream e;
     e << args[0] << " given invalid export file name \"" << fname << "\".  "
       << "The FILE argument may not contain a path.  "
@@ -1292,7 +1326,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
     fname = exp.GetString();
     fname += ".cmake";
 
-    if (fname.find_first_of(":/\\") != fname.npos) {
+    if (fname.find_first_of(":/\\") != std::string::npos) {
       std::ostringstream e;
       e << args[0] << " given export name \"" << exp.GetString() << "\".  "
         << "This name cannot be safely converted to a file name.  "
@@ -1357,7 +1391,7 @@ bool cmInstallCommand::MakeFilesFullPath(
     }
 
     // Make sure the file is not a directory.
-    if (gpos == file.npos && cmSystemTools::FileIsDirectory(file)) {
+    if (gpos == std::string::npos && cmSystemTools::FileIsDirectory(file)) {
       std::ostringstream e;
       e << modeName << " given directory \"" << (*fileIt) << "\" to install.";
       this->SetError(e.str());
@@ -1372,11 +1406,11 @@ bool cmInstallCommand::MakeFilesFullPath(
 bool cmInstallCommand::CheckCMP0006(bool& failure)
 {
   switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) {
-    case cmPolicies::WARN: {
+    case cmPolicies::WARN:
       this->Makefile->IssueMessage(
         cmake::AUTHOR_WARNING,
         cmPolicies::GetPolicyWarning(cmPolicies::CMP0006));
-    }
+      CM_FALLTHROUGH;
     case cmPolicies::OLD:
       // OLD behavior is to allow compatibility
       return true;
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index 187a6ce..f5d1f92 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmInstallCommand_h
 #define cmInstallCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "install"; }
-
 private:
   bool HandleScriptMode(std::vector<std::string> const& args);
   bool HandleTargetsMode(std::vector<std::string> const& args);
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 6b15468..b73414d 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmInstallCommandArguments.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmSystemTools.h"
 
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index c1523b2..a576e72 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -3,7 +3,7 @@
 #ifndef cmInstallCommandArguments_h
 #define cmInstallCommandArguments_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index dfb3aeb..54ad85c 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -48,7 +48,7 @@ void cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg)
 }
 
 void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
-                                                        Indent const& indent)
+                                                        Indent indent)
 {
   if (this->ActionsPerConfig) {
     this->cmInstallGenerator::GenerateScriptActions(os, indent);
@@ -58,7 +58,7 @@ void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
 }
 
 void cmInstallDirectoryGenerator::GenerateScriptForConfig(
-  std::ostream& os, const std::string& config, Indent const& indent)
+  std::ostream& os, const std::string& config, Indent indent)
 {
   std::vector<std::string> dirs;
   cmGeneratorExpression ge;
@@ -82,7 +82,7 @@ void cmInstallDirectoryGenerator::GenerateScriptForConfig(
 }
 
 void cmInstallDirectoryGenerator::AddDirectoryInstallRule(
-  std::ostream& os, const std::string& config, Indent const& indent,
+  std::ostream& os, const std::string& config, Indent indent,
   std::vector<std::string> const& dirs)
 {
   // Write code to install the directories.
diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h
index 0518092..aa2cbc6 100644
--- a/Source/cmInstallDirectoryGenerator.h
+++ b/Source/cmInstallDirectoryGenerator.h
@@ -6,7 +6,8 @@
 #include "cmInstallGenerator.h"
 #include "cmScriptGenerator.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <iosfwd>
 #include <string>
 #include <vector>
@@ -33,12 +34,11 @@ public:
   std::string GetDestination(std::string const& config) const;
 
 protected:
-  void GenerateScriptActions(std::ostream& os,
-                             Indent const& indent) CM_OVERRIDE;
+  void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
   void GenerateScriptForConfig(std::ostream& os, const std::string& config,
-                               Indent const& indent) CM_OVERRIDE;
+                               Indent indent) CM_OVERRIDE;
   void AddDirectoryInstallRule(std::ostream& os, const std::string& config,
-                               Indent const& indent,
+                               Indent indent,
                                std::vector<std::string> const& dirs);
   cmLocalGenerator* LocalGenerator;
   std::vector<std::string> Directories;
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index 39fab4f..b176e85 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -166,7 +166,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
 }
 
 void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
-                                                     Indent const& indent)
+                                                     Indent indent)
 {
   // Create the main install rules first.
   this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
@@ -189,7 +189,7 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
 }
 
 void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
-                                                     Indent const& indent)
+                                                     Indent indent)
 {
   // Remove old per-configuration export files if the main changes.
   std::string installedDir = "$ENV{DESTDIR}";
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index b0fe889..047e6b3 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmInstallExportGenerator_h
 #define cmInstallExportGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmInstallGenerator.h"
 #include "cmScriptGenerator.h"
@@ -44,10 +44,8 @@ public:
 
 protected:
   void GenerateScript(std::ostream& os) CM_OVERRIDE;
-  void GenerateScriptConfigs(std::ostream& os,
-                             Indent const& indent) CM_OVERRIDE;
-  void GenerateScriptActions(std::ostream& os,
-                             Indent const& indent) CM_OVERRIDE;
+  void GenerateScriptConfigs(std::ostream& os, Indent indent) CM_OVERRIDE;
+  void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
   void GenerateImportFile(cmExportSet const* exportSet);
   void GenerateImportFile(const char* config, cmExportSet const* exportSet);
   void ComputeTempDir();
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index 86fd46d..4a3b620 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -54,7 +54,7 @@ void cmInstallFilesCommand::FinalPass()
   }
 
   std::string testf;
-  std::string ext = this->FinalArgs[0];
+  std::string const& ext = this->FinalArgs[0];
 
   // two different options
   if (this->FinalArgs.size() > 1) {
@@ -64,7 +64,7 @@ void cmInstallFilesCommand::FinalPass()
     // for each argument, get the files
     for (; s != this->FinalArgs.end(); ++s) {
       // replace any variables
-      std::string temps = *s;
+      std::string const& temps = *s;
       if (!cmSystemTools::GetFilenamePath(temps).empty()) {
         testf = cmSystemTools::GetFilenamePath(temps) + "/" +
           cmSystemTools::GetFilenameWithoutLastExtension(temps) + ext;
@@ -78,7 +78,7 @@ void cmInstallFilesCommand::FinalPass()
   } else // reg exp list
   {
     std::vector<std::string> files;
-    std::string regex = this->FinalArgs[0];
+    std::string const& regex = this->FinalArgs[0];
     cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(), regex,
                         files);
 
diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h
index c3e2919..b3c27b8 100644
--- a/Source/cmInstallFilesCommand.h
+++ b/Source/cmInstallFilesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmInstallFilesCommand_h
 #define cmInstallFilesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -33,11 +34,6 @@ public:
                    cmExecutionStatus& status) CM_OVERRIDE;
 
   /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "install_files"; }
-
-  /**
    * This is called at the end after all the information
    * specified by the command is accumulated. Most commands do
    * not implement this method.  At this point, reading and
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index 7daea38..6323a91 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -54,7 +54,7 @@ std::string cmInstallFilesGenerator::GetDestination(
 }
 
 void cmInstallFilesGenerator::AddFilesInstallRule(
-  std::ostream& os, std::string const& config, Indent const& indent,
+  std::ostream& os, std::string const& config, Indent indent,
   std::vector<std::string> const& files)
 {
   // Write code to install the files.
@@ -67,7 +67,7 @@ void cmInstallFilesGenerator::AddFilesInstallRule(
 }
 
 void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
-                                                    Indent const& indent)
+                                                    Indent indent)
 {
   if (this->ActionsPerConfig) {
     this->cmInstallGenerator::GenerateScriptActions(os, indent);
@@ -77,7 +77,7 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
 }
 
 void cmInstallFilesGenerator::GenerateScriptForConfig(
-  std::ostream& os, const std::string& config, Indent const& indent)
+  std::ostream& os, const std::string& config, Indent indent)
 {
   std::vector<std::string> files;
   cmGeneratorExpression ge;
diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h
index ca8c6e1..62b57f9 100644
--- a/Source/cmInstallFilesGenerator.h
+++ b/Source/cmInstallFilesGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmInstallFilesGenerator_h
 #define cmInstallFilesGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmInstallGenerator.h"
 #include "cmScriptGenerator.h"
@@ -34,12 +34,11 @@ public:
   std::string GetDestination(std::string const& config) const;
 
 protected:
-  void GenerateScriptActions(std::ostream& os,
-                             Indent const& indent) CM_OVERRIDE;
+  void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
   void GenerateScriptForConfig(std::ostream& os, const std::string& config,
-                               Indent const& indent) CM_OVERRIDE;
+                               Indent indent) CM_OVERRIDE;
   void AddFilesInstallRule(std::ostream& os, std::string const& config,
-                           Indent const& indent,
+                           Indent indent,
                            std::vector<std::string> const& files);
 
   cmLocalGenerator* LocalGenerator;
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 120d1b3..13b588e 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -27,7 +27,7 @@ void cmInstallGenerator::AddInstallRule(
   std::vector<std::string> const& files, bool optional /* = false */,
   const char* permissions_file /* = 0 */,
   const char* permissions_dir /* = 0 */, const char* rename /* = 0 */,
-  const char* literal_args /* = 0 */, Indent const& indent)
+  const char* literal_args /* = 0 */, Indent indent)
 {
   // Use the FILE command to install the file.
   std::string stype;
diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index 48e1644..8f8701f 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmInstallGenerator_h
 #define cmInstallGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmInstallType.h"
 #include "cmScriptGenerator.h"
@@ -21,6 +21,8 @@ class cmMakefile;
  */
 class cmInstallGenerator : public cmScriptGenerator
 {
+  CM_DISABLE_COPY(cmInstallGenerator)
+
 public:
   enum MessageLevel
   {
@@ -41,7 +43,7 @@ public:
     std::vector<std::string> const& files, bool optional = false,
     const char* permissions_file = CM_NULLPTR,
     const char* permissions_dir = CM_NULLPTR, const char* rename = CM_NULLPTR,
-    const char* literal_args = CM_NULLPTR, Indent const& indent = Indent());
+    const char* literal_args = CM_NULLPTR, Indent indent = Indent());
 
   /** Get the install destination as it should appear in the
       installation script.  */
diff --git a/Source/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h
index ca07a2f..242fb95 100644
--- a/Source/cmInstallProgramsCommand.h
+++ b/Source/cmInstallProgramsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmInstallProgramsCommand_h
 #define cmInstallProgramsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -33,11 +34,6 @@ public:
                    cmExecutionStatus& status) CM_OVERRIDE;
 
   /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "install_programs"; }
-
-  /**
    * This is called at the end after all the information
    * specified by the command is accumulated. Most commands do
    * not implement this method.  At this point, reading and
diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h
index 0b54994..e183999 100644
--- a/Source/cmInstallScriptGenerator.h
+++ b/Source/cmInstallScriptGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmInstallScriptGenerator_h
 #define cmInstallScriptGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmInstallGenerator.h"
 
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 88fcc56..84d6f7a 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -58,27 +58,8 @@ void cmInstallTargetGenerator::GenerateScript(std::ostream& os)
 }
 
 void cmInstallTargetGenerator::GenerateScriptForConfig(
-  std::ostream& os, const std::string& config, Indent const& indent)
+  std::ostream& os, const std::string& config, Indent indent)
 {
-  // Compute the build tree directory from which to copy the target.
-  std::string fromDirConfig;
-  if (this->Target->NeedRelinkBeforeInstall(config)) {
-    fromDirConfig =
-      this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory();
-    fromDirConfig += cmake::GetCMakeFilesDirectory();
-    fromDirConfig += "/CMakeRelink.dir/";
-  } else {
-    fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary);
-    fromDirConfig += "/";
-  }
-  std::string toDir =
-    this->ConvertToAbsoluteDestination(this->GetDestination(config));
-  toDir += "/";
-
-  // Compute the list of files to install for this target.
-  std::vector<std::string> filesFrom;
-  std::vector<std::string> filesTo;
-  std::string literal_args;
   cmStateEnums::TargetType targetType = this->Target->GetType();
   cmInstallType type = cmInstallType();
   switch (targetType) {
@@ -100,7 +81,11 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
       assert(false &&
              "INTERFACE_LIBRARY targets have no installable outputs.");
       break;
+
     case cmStateEnums::OBJECT_LIBRARY:
+      this->GenerateScriptForConfigObjectLibrary(os, config, indent);
+      return;
+
     case cmStateEnums::UTILITY:
     case cmStateEnums::GLOBAL_TARGET:
     case cmStateEnums::UNKNOWN_LIBRARY:
@@ -109,6 +94,31 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
         "cmInstallTargetGenerator created with non-installable target.");
       return;
   }
+
+  // Compute the build tree directory from which to copy the target.
+  std::string fromDirConfig;
+  if (this->Target->NeedRelinkBeforeInstall(config)) {
+    fromDirConfig =
+      this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory();
+    fromDirConfig += cmake::GetCMakeFilesDirectory();
+    fromDirConfig += "/CMakeRelink.dir/";
+  } else {
+    cmStateEnums::ArtifactType artifact = this->ImportLibrary
+      ? cmStateEnums::ImportLibraryArtifact
+      : cmStateEnums::RuntimeBinaryArtifact;
+    fromDirConfig = this->Target->GetDirectory(config, artifact);
+    fromDirConfig += "/";
+  }
+
+  std::string toDir =
+    this->ConvertToAbsoluteDestination(this->GetDestination(config));
+  toDir += "/";
+
+  // Compute the list of files to install for this target.
+  std::vector<std::string> filesFrom;
+  std::vector<std::string> filesTo;
+  std::string literal_args;
+
   if (targetType == cmStateEnums::EXECUTABLE) {
     // There is a bug in cmInstallCommand if this fails.
     assert(this->NamelinkMode == NamelinkModeNone);
@@ -315,6 +325,49 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
                  &cmInstallTargetGenerator::PostReplacementTweaks);
 }
 
+static std::string computeInstallObjectDir(cmGeneratorTarget* gt,
+                                           std::string const& config)
+{
+  std::string objectDir = "objects";
+  if (!config.empty()) {
+    objectDir += "-";
+    objectDir += config;
+  }
+  objectDir += "/";
+  objectDir += gt->GetName();
+  return objectDir;
+}
+
+void cmInstallTargetGenerator::GenerateScriptForConfigObjectLibrary(
+  std::ostream& os, const std::string& config, Indent indent)
+{
+  // Compute all the object files inside this target
+  std::vector<std::string> objects;
+  this->Target->GetTargetObjectNames(config, objects);
+
+  std::string const dest = this->GetDestination(config) + "/" +
+    computeInstallObjectDir(this->Target, config);
+
+  std::string const obj_dir = this->Target->GetObjectDirectory(config);
+  std::string const literal_args = " FILES_FROM_DIR \"" + obj_dir + "\"";
+
+  const char* no_dir_permissions = CM_NULLPTR;
+  const char* no_rename = CM_NULLPTR;
+  this->AddInstallRule(os, dest, cmInstallType_FILES, objects, this->Optional,
+                       this->FilePermissions.c_str(), no_dir_permissions,
+                       no_rename, literal_args.c_str(), indent);
+}
+
+void cmInstallTargetGenerator::GetInstallObjectNames(
+  std::string const& config, std::vector<std::string>& objects) const
+{
+  this->Target->GetTargetObjectNames(config, objects);
+  for (std::vector<std::string>::iterator i = objects.begin();
+       i != objects.end(); ++i) {
+    *i = computeInstallObjectDir(this->Target, config) + "/" + *i;
+  }
+}
+
 std::string cmInstallTargetGenerator::GetDestination(
   std::string const& config) const
 {
@@ -391,7 +444,7 @@ void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
   this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
 }
 
-void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent const& indent,
+void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
                                         const std::string& config,
                                         std::string const& file,
                                         TweakMethod tweak)
@@ -407,7 +460,7 @@ void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent const& indent,
   }
 }
 
-void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent const& indent,
+void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
                                         const std::string& config,
                                         std::vector<std::string> const& files,
                                         TweakMethod tweak)
@@ -447,7 +500,7 @@ std::string cmInstallTargetGenerator::GetDestDirPath(std::string const& file)
 }
 
 void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os,
-                                                    Indent const& indent,
+                                                    Indent indent,
                                                     const std::string& config,
                                                     std::string const& file)
 {
@@ -455,7 +508,7 @@ void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os,
 }
 
 void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os,
-                                                     Indent const& indent,
+                                                     Indent indent,
                                                      const std::string& config,
                                                      std::string const& file)
 {
@@ -467,7 +520,7 @@ void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os,
 }
 
 void cmInstallTargetGenerator::AddInstallNamePatchRule(
-  std::ostream& os, Indent const& indent, const std::string& config,
+  std::ostream& os, Indent indent, const std::string& config,
   std::string const& toDestDirPath)
 {
   if (this->ImportLibrary ||
@@ -568,7 +621,7 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule(
 }
 
 void cmInstallTargetGenerator::AddRPathCheckRule(
-  std::ostream& os, Indent const& indent, const std::string& config,
+  std::ostream& os, Indent indent, const std::string& config,
   std::string const& toDestDirPath)
 {
   // Skip the chrpath if the target does not need it.
@@ -602,7 +655,7 @@ void cmInstallTargetGenerator::AddRPathCheckRule(
 }
 
 void cmInstallTargetGenerator::AddChrpathPatchRule(
-  std::ostream& os, Indent const& indent, const std::string& config,
+  std::ostream& os, Indent indent, const std::string& config,
   std::string const& toDestDirPath)
 {
   // Skip the chrpath if the target does not need it.
@@ -697,8 +750,7 @@ void cmInstallTargetGenerator::AddChrpathPatchRule(
   }
 }
 
-void cmInstallTargetGenerator::AddStripRule(std::ostream& os,
-                                            Indent const& indent,
+void cmInstallTargetGenerator::AddStripRule(std::ostream& os, Indent indent,
                                             const std::string& toDestDirPath)
 {
 
@@ -726,8 +778,7 @@ void cmInstallTargetGenerator::AddStripRule(std::ostream& os,
   os << indent << "endif()\n";
 }
 
-void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os,
-                                             Indent const& indent,
+void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, Indent indent,
                                              const std::string& toDestDirPath)
 {
   // Static libraries need ranlib on this platform.
@@ -752,7 +803,7 @@ void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os,
 }
 
 void cmInstallTargetGenerator::AddUniversalInstallRule(
-  std::ostream& os, Indent const& indent, const std::string& toDestDirPath)
+  std::ostream& os, Indent indent, const std::string& toDestDirPath)
 {
   cmMakefile const* mf = this->Target->Target->GetMakefile();
 
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index 084a033..cf2de58 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmInstallTargetGenerator_h
 #define cmInstallTargetGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmInstallGenerator.h"
 #include "cmScriptGenerator.h"
@@ -41,6 +41,9 @@ public:
 
   std::string GetInstallFilename(const std::string& config) const;
 
+  void GetInstallObjectNames(std::string const& config,
+                             std::vector<std::string>& objects) const;
+
   enum NameType
   {
     NameNormal,
@@ -64,39 +67,39 @@ public:
 protected:
   void GenerateScript(std::ostream& os) CM_OVERRIDE;
   void GenerateScriptForConfig(std::ostream& os, const std::string& config,
-                               Indent const& indent) CM_OVERRIDE;
-  typedef void (cmInstallTargetGenerator::*TweakMethod)(std::ostream&,
-                                                        Indent const&,
+                               Indent indent) CM_OVERRIDE;
+  void GenerateScriptForConfigObjectLibrary(std::ostream& os,
+                                            const std::string& config,
+                                            Indent indent);
+  typedef void (cmInstallTargetGenerator::*TweakMethod)(std::ostream&, Indent,
                                                         const std::string&,
                                                         std::string const&);
-  void AddTweak(std::ostream& os, Indent const& indent,
-                const std::string& config, std::string const& file,
-                TweakMethod tweak);
-  void AddTweak(std::ostream& os, Indent const& indent,
-                const std::string& config,
+  void AddTweak(std::ostream& os, Indent indent, const std::string& config,
+                std::string const& file, TweakMethod tweak);
+  void AddTweak(std::ostream& os, Indent indent, const std::string& config,
                 std::vector<std::string> const& files, TweakMethod tweak);
   std::string GetDestDirPath(std::string const& file);
-  void PreReplacementTweaks(std::ostream& os, Indent const& indent,
+  void PreReplacementTweaks(std::ostream& os, Indent indent,
                             const std::string& config,
                             std::string const& file);
-  void PostReplacementTweaks(std::ostream& os, Indent const& indent,
+  void PostReplacementTweaks(std::ostream& os, Indent indent,
                              const std::string& config,
                              std::string const& file);
-  void AddInstallNamePatchRule(std::ostream& os, Indent const& indent,
+  void AddInstallNamePatchRule(std::ostream& os, Indent indent,
                                const std::string& config,
                                const std::string& toDestDirPath);
-  void AddChrpathPatchRule(std::ostream& os, Indent const& indent,
+  void AddChrpathPatchRule(std::ostream& os, Indent indent,
                            const std::string& config,
                            std::string const& toDestDirPath);
-  void AddRPathCheckRule(std::ostream& os, Indent const& indent,
+  void AddRPathCheckRule(std::ostream& os, Indent indent,
                          const std::string& config,
                          std::string const& toDestDirPath);
 
-  void AddStripRule(std::ostream& os, Indent const& indent,
+  void AddStripRule(std::ostream& os, Indent indent,
                     const std::string& toDestDirPath);
-  void AddRanlibRule(std::ostream& os, Indent const& indent,
+  void AddRanlibRule(std::ostream& os, Indent indent,
                      const std::string& toDestDirPath);
-  void AddUniversalInstallRule(std::ostream& os, Indent const& indent,
+  void AddUniversalInstallRule(std::ostream& os, Indent indent,
                                const std::string& toDestDirPath);
 
   std::string TargetName;
diff --git a/Source/cmInstallTargetsCommand.h b/Source/cmInstallTargetsCommand.h
index 150397d..cc84843 100644
--- a/Source/cmInstallTargetsCommand.h
+++ b/Source/cmInstallTargetsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmInstallTargetsCommand_h
 #define cmInstallTargetsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "install_targets"; }
 };
 
 #endif
diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx
index 8dd42b6..d51fd8d 100644
--- a/Source/cmInstalledFile.cxx
+++ b/Source/cmInstalledFile.cxx
@@ -7,7 +7,7 @@
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 #include <utility>
 
 cmInstalledFile::cmInstalledFile()
diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h
index 4fe8134..fbf754f 100644
--- a/Source/cmInstalledFile.h
+++ b/Source/cmInstalledFile.h
@@ -3,6 +3,8 @@
 #ifndef cmInstalledFile_h
 #define cmInstalledFile_h
 
+#include "cmConfigure.h" // IWYU pragma: keep
+
 #include "cmGeneratorExpression.h"
 #include "cm_auto_ptr.hxx"
 
diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx
index f863292..9b0c288 100644
--- a/Source/cmLinkDirectoriesCommand.cxx
+++ b/Source/cmLinkDirectoriesCommand.cxx
@@ -49,6 +49,7 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
       case cmPolicies::REQUIRED_ALWAYS:
         e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0015);
         this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior converts
         convertToAbsolute = true;
diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h
index 387b3b9..b64e48d 100644
--- a/Source/cmLinkDirectoriesCommand.h
+++ b/Source/cmLinkDirectoriesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmLinkDirectoriesCommand_h
 #define cmLinkDirectoriesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -34,11 +35,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "link_directories"; }
-
 private:
   void AddLinkDir(std::string const& dir);
 };
diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h
index 6fd6f50..f0fded2 100644
--- a/Source/cmLinkItem.h
+++ b/Source/cmLinkItem.h
@@ -3,7 +3,7 @@
 #ifndef cmLinkItem_h
 #define cmLinkItem_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <algorithm>
 #include <map>
@@ -32,11 +32,6 @@ public:
     , Target(t)
   {
   }
-  cmLinkItem(cmLinkItem const& r)
-    : std_string(r)
-    , Target(r.Target)
-  {
-  }
   cmGeneratorTarget const* Target;
 };
 
@@ -56,12 +51,6 @@ public:
     , FromGenex(fromGenex)
   {
   }
-  cmLinkImplItem(cmLinkImplItem const& r)
-    : cmLinkItem(r)
-    , Backtrace(r.Backtrace)
-    , FromGenex(r.FromGenex)
-  {
-  }
   cmListFileBacktrace Backtrace;
   bool FromGenex;
 };
diff --git a/Source/cmLinkLibrariesCommand.h b/Source/cmLinkLibrariesCommand.h
index 66d7ec4..f1b3a68 100644
--- a/Source/cmLinkLibrariesCommand.h
+++ b/Source/cmLinkLibrariesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmLinkLibrariesCommand_h
 #define cmLinkLibrariesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "link_libraries"; }
 };
 
 #endif
diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx
index e728632..c0f702e 100644
--- a/Source/cmLinkLineComputer.cxx
+++ b/Source/cmLinkLineComputer.cxx
@@ -13,7 +13,7 @@
 #include "cmStateTypes.h"
 
 cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
-                                       cmStateDirectory stateDir)
+                                       cmStateDirectory const& stateDir)
   : StateDir(stateDir)
   , OutputConverter(outputConverter)
   , ForResponse(false)
diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h
index 57a70bc..d33e8d1 100644
--- a/Source/cmLinkLineComputer.h
+++ b/Source/cmLinkLineComputer.h
@@ -4,7 +4,7 @@
 #ifndef cmLinkLineComputer_h
 #define cmLinkLineComputer_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include <string>
 
@@ -16,9 +16,11 @@ class cmOutputConverter;
 
 class cmLinkLineComputer
 {
+  CM_DISABLE_COPY(cmLinkLineComputer)
+
 public:
   cmLinkLineComputer(cmOutputConverter* outputConverter,
-                     cmStateDirectory stateDir);
+                     cmStateDirectory const& stateDir);
   virtual ~cmLinkLineComputer();
 
   void SetUseWatcomQuote(bool useWatcomQuote);
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 6a700ff..942e9b9 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -2,13 +2,20 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 
 #include "cmLinkLineDeviceComputer.h"
+
+#include <set>
+#include <sstream>
+#include <vector>
+
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalNinjaGenerator.h"
-#include "cmOutputConverter.h"
+#include "cmStateTypes.h"
+
+class cmOutputConverter;
 
 cmLinkLineDeviceComputer::cmLinkLineDeviceComputer(
-  cmOutputConverter* outputConverter, cmStateDirectory stateDir)
+  cmOutputConverter* outputConverter, cmStateDirectory const& stateDir)
   : cmLinkLineComputer(outputConverter, stateDir)
 {
 }
@@ -31,9 +38,24 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
       continue;
     }
 
-    if (li->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
-        li->Target->GetType() == cmStateEnums::SHARED_LIBRARY ||
-        li->Target->GetType() == cmStateEnums::MODULE_LIBRARY) {
+    bool skippable = false;
+    switch (li->Target->GetType()) {
+      case cmStateEnums::SHARED_LIBRARY:
+      case cmStateEnums::MODULE_LIBRARY:
+      case cmStateEnums::INTERFACE_LIBRARY:
+        skippable = true;
+        break;
+      case cmStateEnums::STATIC_LIBRARY:
+        // If a static library is resolving its device linking, it should
+        // be removed for other device linking
+        skippable =
+          li->Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
+        break;
+      default:
+        break;
+    }
+
+    if (skippable) {
       continue;
     }
 
@@ -66,7 +88,7 @@ std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*,
 }
 
 cmNinjaLinkLineDeviceComputer::cmNinjaLinkLineDeviceComputer(
-  cmOutputConverter* outputConverter, cmStateDirectory stateDir,
+  cmOutputConverter* outputConverter, cmStateDirectory const& stateDir,
   cmGlobalNinjaGenerator const* gg)
   : cmLinkLineDeviceComputer(outputConverter, stateDir)
   , GG(gg)
diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h
index f4bb3eb..c3fac61 100644
--- a/Source/cmLinkLineDeviceComputer.h
+++ b/Source/cmLinkLineDeviceComputer.h
@@ -4,14 +4,25 @@
 #ifndef cmLinkLineDeviceComputer_h
 #define cmLinkLineDeviceComputer_h
 
+#include "cmConfigure.h"
+
+#include <string>
+
 #include "cmLinkLineComputer.h"
+
+class cmComputeLinkInformation;
+class cmGeneratorTarget;
 class cmGlobalNinjaGenerator;
+class cmOutputConverter;
+class cmStateDirectory;
 
 class cmLinkLineDeviceComputer : public cmLinkLineComputer
 {
+  CM_DISABLE_COPY(cmLinkLineDeviceComputer)
+
 public:
   cmLinkLineDeviceComputer(cmOutputConverter* outputConverter,
-                           cmStateDirectory stateDir);
+                           cmStateDirectory const& stateDir);
   ~cmLinkLineDeviceComputer() CM_OVERRIDE;
 
   std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
@@ -24,9 +35,11 @@ public:
 
 class cmNinjaLinkLineDeviceComputer : public cmLinkLineDeviceComputer
 {
+  CM_DISABLE_COPY(cmNinjaLinkLineDeviceComputer)
+
 public:
   cmNinjaLinkLineDeviceComputer(cmOutputConverter* outputConverter,
-                                cmStateDirectory stateDir,
+                                cmStateDirectory const& stateDir,
                                 cmGlobalNinjaGenerator const* gg);
 
   std::string ConvertToLinkReference(std::string const& input) const
diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h
index 4f95522..55592cb 100644
--- a/Source/cmLinkedTree.h
+++ b/Source/cmLinkedTree.h
@@ -3,7 +3,7 @@
 #ifndef cmLinkedTree_h
 #define cmLinkedTree_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <assert.h>
 #include <iterator>
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 295ea28..0542c4f 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmListCommand.h"
 
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
-#include <cmsys/RegularExpression.hxx>
 #include <iterator>
 #include <sstream>
 #include <stdio.h>
diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h
index e7413ca..7789f7d 100644
--- a/Source/cmListCommand.h
+++ b/Source/cmListCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmListCommand_h
 #define cmListCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "list"; }
-
 protected:
   bool HandleLengthCommand(std::vector<std::string> const& args);
   bool HandleGetCommand(std::vector<std::string> const& args);
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index b1cd889..0c73cd7 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -9,14 +9,14 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
+#include "cmConfigure.h"
 #include <algorithm>
 #include <assert.h>
-#include <cmConfigure.h>
 #include <sstream>
 
 struct cmListFileParser
 {
-  cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
+  cmListFileParser(cmListFile* lf, cmListFileBacktrace const& lfbt,
                    cmMessenger* messenger, const char* filename);
   ~cmListFileParser();
   void IssueFileOpenError(std::string const& text) const;
@@ -39,7 +39,8 @@ struct cmListFileParser
   } Separation;
 };
 
-cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
+cmListFileParser::cmListFileParser(cmListFile* lf,
+                                   cmListFileBacktrace const& lfbt,
                                    cmMessenger* messenger,
                                    const char* filename)
   : ListFile(lf)
@@ -80,6 +81,13 @@ bool cmListFileParser::ParseFile()
     return false;
   }
 
+  if (bom == cmListFileLexer_BOM_Broken) {
+    cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR);
+    this->IssueFileOpenError("Error while reading Byte-Order-Mark. "
+                             "File not seekable?");
+    return false;
+  }
+
   // Verify the Byte-Order-Mark, if any.
   if (bom != cmListFileLexer_BOM_None && bom != cmListFileLexer_BOM_UTF8) {
     cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR);
@@ -299,7 +307,8 @@ struct cmListFileBacktrace::Entry : public cmListFileContext
   unsigned int RefCount;
 };
 
-cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot bottom, Entry* up,
+cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom,
+                                         Entry* up,
                                          cmListFileContext const& lfc)
   : Bottom(bottom)
   , Cur(new Entry(lfc, up))
@@ -308,7 +317,8 @@ cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot bottom, Entry* up,
   this->Cur->Ref();
 }
 
-cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot bottom, Entry* cur)
+cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom,
+                                         Entry* cur)
   : Bottom(bottom)
   , Cur(cur)
 {
@@ -324,7 +334,7 @@ cmListFileBacktrace::cmListFileBacktrace()
 {
 }
 
-cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot snapshot)
+cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& snapshot)
   : Bottom(snapshot.GetCallStackBottom())
   , Cur(CM_NULLPTR)
 {
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 1a30f29..349ddef 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -3,7 +3,7 @@
 #ifndef cmListFileCache_h
 #define cmListFileCache_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
 #include <string>
@@ -45,12 +45,6 @@ struct cmListFileArgument
     , Line(0)
   {
   }
-  cmListFileArgument(const cmListFileArgument& r)
-    : Value(r.Value)
-    , Delim(r.Delim)
-    , Line(r.Line)
-  {
-  }
   cmListFileArgument(const std::string& v, Delimiter d, long line)
     : Value(v)
     , Delim(d)
@@ -113,7 +107,7 @@ public:
 
   // Construct an empty backtrace whose bottom sits in the directory
   // indicated by the given valid snapshot.
-  cmListFileBacktrace(cmStateSnapshot snapshot);
+  cmListFileBacktrace(cmStateSnapshot const& snapshot);
 
   // Backtraces may be copied and assigned as values.
   cmListFileBacktrace(cmListFileBacktrace const& r);
@@ -149,9 +143,9 @@ private:
 
   cmStateSnapshot Bottom;
   Entry* Cur;
-  cmListFileBacktrace(cmStateSnapshot bottom, Entry* up,
+  cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* up,
                       cmListFileContext const& lfc);
-  cmListFileBacktrace(cmStateSnapshot bottom, Entry* cur);
+  cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* cur);
 };
 
 struct cmListFile
diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c
deleted file mode 100644
index 56559f6..0000000
--- a/Source/cmListFileLexer.c
+++ /dev/null
@@ -1,2684 +0,0 @@
-#include "cmStandardLexer.h"
-#line 2 "cmListFileLexer.c"
-
-#line 4 "cmListFileLexer.c"
-
-#define FLEXINT_H 1
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-/* TODO: this is always defined, so inline it */
-#define yyconst const
-
-#if defined(__GNUC__) && __GNUC__ >= 3
-#define yynoreturn __attribute__((__noreturn__))
-#else
-#define yynoreturn
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* An opaque pointer. */
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-/* For convenience, these vars (plus the bison vars far below)
-   are macros in the reentrant scanner. */
-#define yyin yyg->yyin_r
-#define yyout yyg->yyout_r
-#define yyextra yyg->yyextra_r
-#define yyleng yyg->yyleng_r
-#define yytext yyg->yytext_r
-#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
-#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
-#define yy_flex_debug yyg->yy_flex_debug_r
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yyg->yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yyg->yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE cmListFileLexer_yyrestart(yyin ,yyscanner )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
-     *       access to the local variable yy_act. Since yyless() is a macro, it would break
-     *       existing scanners that call yyless() from OUTSIDE cmListFileLexer_yylex.
-     *       One obvious solution it to make yy_act a global. I tried that, and saw
-     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
-     *       normally declared as a register variable-- so it is not worth it.
-     */
-    #define  YY_LESS_LINENO(n) \
-            do { \
-                int yyl;\
-                for ( yyl = n; yyl < yyleng; ++yyl )\
-                    if ( yytext[yyl] == '\n' )\
-                        --yylineno;\
-            }while(0)
-    #define YY_LINENO_REWIND_TO(dst) \
-            do {\
-                const char *p;\
-                for ( p = yy_cp-1; p >= (dst); --p)\
-                    if ( *p == '\n' )\
-                        --yylineno;\
-            }while(0)
-
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = yyg->yy_hold_char; \
-		YY_RESTORE_YY_MORE_OFFSET \
-		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	int yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via cmListFileLexer_yyrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
-                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-
-void cmListFileLexer_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmListFileLexer_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmListFileLexer_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmListFileLexer_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmListFileLexer_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmListFileLexer_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmListFileLexer_yypop_buffer_state (yyscan_t yyscanner );
-
-static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner );
-static void cmListFileLexer_yy_load_buffer_state (yyscan_t yyscanner );
-static void cmListFileLexer_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER cmListFileLexer_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
-
-YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
-
-void *cmListFileLexer_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmListFileLexer_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmListFileLexer_yyfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer cmListFileLexer_yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        cmListFileLexer_yyensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        cmListFileLexer_yyensure_buffer_stack (yyscanner); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define cmListFileLexer_yywrap(yyscanner) (/*CONSTCOND*/1)
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-typedef int yy_state_type;
-
-#define yytext_ptr yytext_r
-
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	yyg->yytext_ptr = yy_bp; \
-	yyleng = (int) (yy_cp - yy_bp); \
-	yyg->yy_hold_char = *yy_cp; \
-	*yy_cp = '\0'; \
-	yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 24
-#define YY_END_OF_BUFFER 25
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[77] =
-    {   0,
-        0,    0,    0,    0,    0,    0,    0,    0,    4,    4,
-       25,   13,   22,    1,   16,    3,   13,    5,    6,    7,
-       15,   23,   17,   19,   20,   21,   10,   11,    8,   12,
-        9,    4,   13,    0,   13,    0,   22,    0,    0,    7,
-       13,    0,   13,    0,    2,    0,   13,   17,    0,   18,
-       10,    8,    4,    0,   14,    0,    0,    0,    0,   14,
-        0,    0,   14,    0,    0,    0,    2,   14,    0,    0,
-        0,    0,    0,    0,    0,    0
-    } ;
-
-static yyconst YY_CHAR yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    4,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    1,    5,    6,    7,    1,    1,    1,    8,
-        9,    1,    1,    1,    1,    1,    1,   10,   10,   10,
-       10,   10,   10,   10,   10,   10,   10,    1,    1,    1,
-       11,    1,    1,    1,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       13,   14,   15,    1,   12,    1,   12,   12,   12,   12,
-
-       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   12,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst YY_CHAR yy_meta[16] =
-    {   0,
-        1,    1,    2,    3,    4,    3,    1,    3,    5,    6,
-        1,    6,    1,    1,    7
-    } ;
-
-static yyconst flex_uint16_t yy_base[95] =
-    {   0,
-        0,    0,   13,   25,   14,   16,   17,   18,   90,   88,
-       88,   39,   20,  237,  237,   74,   78,  237,  237,   13,
-       54,    0,   71,  237,  237,   31,    0,  237,   73,  237,
-      237,    0,    0,   65,   75,    0,   33,   30,   72,    0,
-        0,   75,   70,    0,   74,    0,    0,   62,   70,  237,
-        0,   63,    0,   85,   99,   65,  111,   62,   34,    0,
-       54,  116,    0,   54,  127,   51,  237,   50,    0,   48,
-       47,   39,   33,   29,   17,  237,  136,  143,  150,  157,
-      164,  171,  178,  184,  191,  198,  201,  207,  214,  217,
-      219,  225,  228,  230
-
-    } ;
-
-static yyconst flex_int16_t yy_def[95] =
-    {   0,
-       76,    1,   77,   77,   78,   78,   79,   79,   80,   80,
-       76,   76,   76,   76,   76,   76,   12,   76,   76,   12,
-       76,   81,   82,   76,   76,   82,   83,   76,   76,   76,
-       76,   84,   12,   85,   12,   86,   76,   76,   87,   20,
-       12,   88,   12,   21,   76,   89,   12,   82,   82,   76,
-       83,   76,   84,   85,   76,   54,   85,   90,   76,   55,
-       87,   88,   55,   62,   88,   91,   76,   55,   92,   93,
-       90,   94,   91,   93,   94,    0,   76,   76,   76,   76,
-       76,   76,   76,   76,   76,   76,   76,   76,   76,   76,
-       76,   76,   76,   76
-
-    } ;
-
-static yyconst flex_uint16_t yy_nxt[253] =
-    {   0,
-       12,   13,   14,   13,   15,   16,   17,   18,   19,   12,
-       12,   20,   21,   22,   12,   24,   28,   25,   28,   28,
-       28,   37,   40,   37,   40,   62,   26,   24,   29,   25,
-       29,   31,   31,   50,   37,   48,   37,   54,   26,   33,
-       59,   63,   45,   34,   59,   35,   45,   62,   33,   33,
-       33,   33,   36,   33,   41,   55,   54,   58,   42,   63,
-       43,   72,   60,   41,   44,   41,   45,   46,   41,   55,
-       55,   56,   70,   52,   48,   49,   67,   66,   57,   63,
-       60,   64,   58,   52,   49,   39,   38,   76,   65,   55,
-       14,   56,   14,   76,   76,   76,   76,   76,   57,   55,
-
-       76,   76,   76,   34,   76,   68,   76,   76,   55,   55,
-       55,   55,   69,   55,   54,   76,   54,   76,   54,   54,
-       63,   76,   64,   76,   76,   76,   76,   76,   76,   65,
-       62,   76,   62,   76,   62,   62,   23,   23,   23,   23,
-       23,   23,   23,   27,   27,   27,   27,   27,   27,   27,
-       30,   30,   30,   30,   30,   30,   30,   32,   32,   32,
-       32,   32,   32,   32,   47,   76,   47,   47,   47,   47,
-       47,   48,   76,   48,   76,   48,   48,   48,   51,   76,
-       51,   51,   51,   51,   53,   76,   53,   53,   53,   53,
-       53,   54,   76,   76,   54,   76,   54,   54,   33,   76,
-
-       33,   33,   33,   33,   33,   61,   61,   62,   76,   76,
-       62,   76,   62,   62,   41,   76,   41,   41,   41,   41,
-       41,   71,   71,   73,   73,   55,   76,   55,   55,   55,
-       55,   55,   74,   74,   75,   75,   11,   76,   76,   76,
-       76,   76,   76,   76,   76,   76,   76,   76,   76,   76,
-       76,   76
-    } ;
-
-static yyconst flex_int16_t yy_chk[253] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    3,    5,    3,    6,    7,
-        8,   13,   20,   13,   20,   75,    3,    4,    5,    4,
-        6,    7,    8,   26,   37,   26,   37,   74,    4,   12,
-       38,   73,   38,   12,   59,   12,   59,   72,   12,   12,
-       12,   12,   12,   12,   21,   71,   70,   68,   21,   66,
-       21,   64,   61,   21,   21,   21,   21,   21,   21,   34,
-       58,   34,   56,   52,   49,   48,   45,   43,   34,   42,
-       39,   42,   35,   29,   23,   17,   16,   11,   42,   54,
-       10,   54,    9,    0,    0,    0,    0,    0,   54,   55,
-
-        0,    0,    0,   55,    0,   55,    0,    0,   55,   55,
-       55,   55,   55,   55,   57,    0,   57,    0,   57,   57,
-       62,    0,   62,    0,    0,    0,    0,    0,    0,   62,
-       65,    0,   65,    0,   65,   65,   77,   77,   77,   77,
-       77,   77,   77,   78,   78,   78,   78,   78,   78,   78,
-       79,   79,   79,   79,   79,   79,   79,   80,   80,   80,
-       80,   80,   80,   80,   81,    0,   81,   81,   81,   81,
-       81,   82,    0,   82,    0,   82,   82,   82,   83,    0,
-       83,   83,   83,   83,   84,    0,   84,   84,   84,   84,
-       84,   85,    0,    0,   85,    0,   85,   85,   86,    0,
-
-       86,   86,   86,   86,   86,   87,   87,   88,    0,    0,
-       88,    0,   88,   88,   89,    0,   89,   89,   89,   89,
-       89,   90,   90,   91,   91,   92,    0,   92,   92,   92,
-       92,   92,   93,   93,   94,   94,   76,   76,   76,   76,
-       76,   76,   76,   76,   76,   76,   76,   76,   76,   76,
-       76,   76
-    } ;
-
-/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[25] =
-    {   0,
-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1,
-    0, 0, 0, 0, 0,     };
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "cmListFileLexer.in.l"
-#line 2 "cmListFileLexer.in.l"
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run flex >= 2.6 like this:
-
-  flex --nounistd -DFLEXINT_H --prefix=cmListFileLexer_yy -ocmListFileLexer.c cmListFileLexer.in.l
-
-Modify cmListFileLexer.c:
-  - remove trailing whitespace: sed -i 's/\s*$//' cmListFileLexer.c
-  - remove blank lines at end of file
-  - #include "cmStandardLexer.h" at the top
-  - add cast in cmListFileLexer_yy_scan_bytes for loop condition of _yybytes_len to size_t
-  - change type of variable yyl under yy_find_action from yy_size_t to int
-
-*/
-
-/* IWYU pragma: no_forward_declare yyguts_t */
-
-#ifdef WIN32
-#include <cmsys/Encoding.h>
-#endif
-
-/* Setup the proper cmListFileLexer_yylex declaration.  */
-#define YY_EXTRA_TYPE cmListFileLexer*
-#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner, cmListFileLexer* lexer)
-
-#include "cmListFileLexer.h"
-
-/*--------------------------------------------------------------------------*/
-struct cmListFileLexer_s
-{
-  cmListFileLexer_Token token;
-  int bracket;
-  int comment;
-  int line;
-  int column;
-  int size;
-  FILE* file;
-  size_t cr;
-  char* string_buffer;
-  char* string_position;
-  int string_left;
-  yyscan_t scanner;
-};
-
-static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
-                                    int length);
-static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
-                                  int length);
-static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
-                                size_t bufferSize);
-static void cmListFileLexerInit(cmListFileLexer* lexer);
-static void cmListFileLexerDestroy(cmListFileLexer* lexer);
-
-/* Replace the lexer input function.  */
-#undef YY_INPUT
-#define YY_INPUT(buf, result, max_size) \
-  { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); }
-
-/*--------------------------------------------------------------------------*/
-
-
-
-
-#line 606 "cmListFileLexer.c"
-
-#define INITIAL 0
-#define STRING 1
-#define BRACKET 2
-#define BRACKETEND 3
-#define COMMENT 4
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-/* Holds the entire state of the reentrant scanner. */
-struct yyguts_t
-    {
-
-    /* User-defined. Not touched by flex. */
-    YY_EXTRA_TYPE yyextra_r;
-
-    /* The rest are the same as the globals declared in the non-reentrant scanner. */
-    FILE *yyin_r, *yyout_r;
-    size_t yy_buffer_stack_top; /**< index of top of stack. */
-    size_t yy_buffer_stack_max; /**< capacity of stack. */
-    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
-    char yy_hold_char;
-    int yy_n_chars;
-    int yyleng_r;
-    char *yy_c_buf_p;
-    int yy_init;
-    int yy_start;
-    int yy_did_buffer_switch_on_eof;
-    int yy_start_stack_ptr;
-    int yy_start_stack_depth;
-    int *yy_start_stack;
-    yy_state_type yy_last_accepting_state;
-    char* yy_last_accepting_cpos;
-
-    int yylineno_r;
-    int yy_flex_debug_r;
-
-    char *yytext_r;
-    int yy_more_flag;
-    int yy_more_len;
-
-    }; /* end struct yyguts_t */
-
-static int yy_init_globals (yyscan_t yyscanner );
-
-int cmListFileLexer_yylex_init (yyscan_t* scanner);
-
-int cmListFileLexer_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int cmListFileLexer_yylex_destroy (yyscan_t yyscanner );
-
-int cmListFileLexer_yyget_debug (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_debug (int debug_flag ,yyscan_t yyscanner );
-
-YY_EXTRA_TYPE cmListFileLexer_yyget_extra (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
-
-FILE *cmListFileLexer_yyget_in (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_in  (FILE * _in_str ,yyscan_t yyscanner );
-
-FILE *cmListFileLexer_yyget_out (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_out  (FILE * _out_str ,yyscan_t yyscanner );
-
-			int cmListFileLexer_yyget_leng (yyscan_t yyscanner );
-
-char *cmListFileLexer_yyget_text (yyscan_t yyscanner );
-
-int cmListFileLexer_yyget_lineno (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_lineno (int _line_number ,yyscan_t yyscanner );
-
-int cmListFileLexer_yyget_column  (yyscan_t yyscanner );
-
-void cmListFileLexer_yyset_column (int _column_no ,yyscan_t yyscanner );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int cmListFileLexer_yywrap (yyscan_t yyscanner );
-#else
-extern int cmListFileLexer_yywrap (yyscan_t yyscanner );
-#endif
-#endif
-
-#ifndef YY_NO_UNPUT
-
-    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
-
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
-#else
-static int input (yyscan_t yyscanner );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		size_t n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int cmListFileLexer_yylex (yyscan_t yyscanner);
-
-#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK /*LINTED*/break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	yy_state_type yy_current_state;
-	char *yy_cp, *yy_bp;
-	int yy_act;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( !yyg->yy_init )
-		{
-		yyg->yy_init = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! yyg->yy_start )
-			yyg->yy_start = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			cmListFileLexer_yyensure_buffer_stack (yyscanner);
-			YY_CURRENT_BUFFER_LVALUE =
-				cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-		}
-
-		cmListFileLexer_yy_load_buffer_state(yyscanner );
-		}
-
-	{
-#line 80 "cmListFileLexer.in.l"
-
-
-#line 866 "cmListFileLexer.c"
-
-	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = yyg->yy_c_buf_p;
-
-		/* Support of yytext. */
-		*yy_cp = yyg->yy_hold_char;
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = yyg->yy_start;
-yy_match:
-		do
-			{
-			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
-			if ( yy_accept[yy_current_state] )
-				{
-				yyg->yy_last_accepting_state = yy_current_state;
-				yyg->yy_last_accepting_cpos = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 77 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-			++yy_cp;
-			}
-		while ( yy_base[yy_current_state] != 237 );
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-		if ( yy_act == 0 )
-			{ /* have to back up */
-			yy_cp = yyg->yy_last_accepting_cpos;
-			yy_current_state = yyg->yy_last_accepting_state;
-			yy_act = yy_accept[yy_current_state];
-			}
-
-		YY_DO_BEFORE_ACTION;
-
-		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
-			{
-			int yyl;
-			for ( yyl = 0; yyl < yyleng; ++yyl )
-				if ( yytext[yyl] == '\n' )
-
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-			}
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = yyg->yy_hold_char;
-			yy_cp = yyg->yy_last_accepting_cpos;
-			yy_current_state = yyg->yy_last_accepting_state;
-			goto yy_find_action;
-
-case 1:
-/* rule 1 can match eol */
-YY_RULE_SETUP
-#line 82 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_Newline;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  ++lexer->line;
-  lexer->column = 1;
-  BEGIN(INITIAL);
-  return 1;
-}
-	YY_BREAK
-case 2:
-/* rule 2 can match eol */
-YY_RULE_SETUP
-#line 91 "cmListFileLexer.in.l"
-{
-  const char* bracket = yytext;
-  lexer->comment = yytext[0] == '#';
-  if (lexer->comment) {
-    lexer->token.type = cmListFileLexer_Token_CommentBracket;
-    bracket += 1;
-  } else {
-    lexer->token.type = cmListFileLexer_Token_ArgumentBracket;
-  }
-  cmListFileLexerSetToken(lexer, "", 0);
-  lexer->bracket = strchr(bracket+1, '[') - bracket;
-  if (yytext[yyleng-1] == '\n') {
-    ++lexer->line;
-    lexer->column = 1;
-  } else {
-    lexer->column += yyleng;
-  }
-  BEGIN(BRACKET);
-}
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 111 "cmListFileLexer.in.l"
-{
-  lexer->column += yyleng;
-  BEGIN(COMMENT);
-}
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 116 "cmListFileLexer.in.l"
-{
-  lexer->column += yyleng;
-}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 120 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_ParenLeft;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 127 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_ParenRight;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 134 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_Identifier;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 141 "cmListFileLexer.in.l"
-{
-  /* Handle ]]====]=======]*/
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  if (yyleng == lexer->bracket) {
-    BEGIN(BRACKETEND);
-  }
-}
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 150 "cmListFileLexer.in.l"
-{
-  lexer->column += yyleng;
-  /* Erase the partial bracket from the token.  */
-  lexer->token.length -= lexer->bracket;
-  lexer->token.text[lexer->token.length] = 0;
-  BEGIN(INITIAL);
-  return 1;
-}
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 159 "cmListFileLexer.in.l"
-{
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-}
-	YY_BREAK
-case 11:
-/* rule 11 can match eol */
-YY_RULE_SETUP
-#line 164 "cmListFileLexer.in.l"
-{
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  ++lexer->line;
-  lexer->column = 1;
-  BEGIN(BRACKET);
-}
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 171 "cmListFileLexer.in.l"
-{
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  BEGIN(BRACKET);
-}
-	YY_BREAK
-case YY_STATE_EOF(BRACKET):
-case YY_STATE_EOF(BRACKETEND):
-#line 177 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_BadBracket;
-  BEGIN(INITIAL);
-  return 1;
-}
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 183 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 190 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 197 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 204 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
-  cmListFileLexerSetToken(lexer, "", 0);
-  lexer->column += yyleng;
-  BEGIN(STRING);
-}
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 211 "cmListFileLexer.in.l"
-{
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-}
-	YY_BREAK
-case 18:
-/* rule 18 can match eol */
-YY_RULE_SETUP
-#line 216 "cmListFileLexer.in.l"
-{
-  /* Continuation: text is not part of string */
-  ++lexer->line;
-  lexer->column = 1;
-}
-	YY_BREAK
-case 19:
-/* rule 19 can match eol */
-YY_RULE_SETUP
-#line 222 "cmListFileLexer.in.l"
-{
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  ++lexer->line;
-  lexer->column = 1;
-}
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 228 "cmListFileLexer.in.l"
-{
-  lexer->column += yyleng;
-  BEGIN(INITIAL);
-  return 1;
-}
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 234 "cmListFileLexer.in.l"
-{
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-}
-	YY_BREAK
-case YY_STATE_EOF(STRING):
-#line 239 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_BadString;
-  BEGIN(INITIAL);
-  return 1;
-}
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 245 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_Space;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 252 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_BadCharacter;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-	YY_BREAK
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(COMMENT):
-#line 259 "cmListFileLexer.in.l"
-{
-  lexer->token.type = cmListFileLexer_Token_None;
-  cmListFileLexerSetToken(lexer, 0, 0);
-  return 0;
-}
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 265 "cmListFileLexer.in.l"
-ECHO;
-	YY_BREAK
-#line 1205 "cmListFileLexer.c"
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = yyg->yy_hold_char;
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * cmListFileLexer_yylex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state( yyscanner );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
-
-			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++yyg->yy_c_buf_p;
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = yyg->yy_c_buf_p;
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer( yyscanner ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				yyg->yy_did_buffer_switch_on_eof = 0;
-
-				if ( cmListFileLexer_yywrap(yyscanner ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				yyg->yy_c_buf_p =
-					yyg->yytext_ptr + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				yyg->yy_c_buf_p =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
-
-				yy_current_state = yy_get_previous_state( yyscanner );
-
-				yy_cp = yyg->yy_c_buf_p;
-				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-	} /* end of user's declarations */
-} /* end of cmListFileLexer_yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	char *source = yyg->yytext_ptr;
-	yy_size_t number_to_move, i;
-	int ret_val;
-
-	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
-
-			int yy_c_buf_p_offset =
-				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					cmListFileLexer_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = NULL;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			yyg->yy_n_chars, num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	if ( yyg->yy_n_chars == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			cmListFileLexer_yyrestart(yyin  ,yyscanner);
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmListFileLexer_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	yyg->yy_n_chars += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
-	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
-{
-	yy_state_type yy_current_state;
-	char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	yy_current_state = yyg->yy_start;
-
-	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
-		{
-		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			yyg->yy_last_accepting_state = yy_current_state;
-			yyg->yy_last_accepting_cpos = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 77 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
-{
-	int yy_is_jam;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
-	char *yy_cp = yyg->yy_c_buf_p;
-
-	YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		yyg->yy_last_accepting_state = yy_current_state;
-		yyg->yy_last_accepting_cpos = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 77 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
-	yy_is_jam = (yy_current_state == 76);
-
-	(void)yyg;
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_UNPUT
-
-    static void yyunput (int c, char * yy_bp , yyscan_t yyscanner)
-{
-	char *yy_cp;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    yy_cp = yyg->yy_c_buf_p;
-
-	/* undo effects of setting up yytext */
-	*yy_cp = yyg->yy_hold_char;
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		int number_to_move = yyg->yy_n_chars + 2;
-		char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-    if ( c == '\n' ){
-        --yylineno;
-    }
-
-	yyg->yytext_ptr = yy_bp;
-	yyg->yy_hold_char = *yy_cp;
-	yyg->yy_c_buf_p = yy_cp;
-}
-
-#endif
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (yyscan_t yyscanner)
-#else
-    static int input  (yyscan_t yyscanner)
-#endif
-
-{
-	int c;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	*yyg->yy_c_buf_p = yyg->yy_hold_char;
-
-	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
-			/* This was really a NUL. */
-			*yyg->yy_c_buf_p = '\0';
-
-		else
-			{ /* need more input */
-			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
-			++yyg->yy_c_buf_p;
-
-			switch ( yy_get_next_buffer( yyscanner ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					cmListFileLexer_yyrestart(yyin ,yyscanner);
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( cmListFileLexer_yywrap(yyscanner ) )
-						return 0;
-
-					if ( ! yyg->yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput(yyscanner);
-#else
-					return input(yyscanner);
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
-	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
-	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
-
-	if ( c == '\n' )
-
-    do{ yylineno++;
-        yycolumn=0;
-    }while(0)
-;
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * @param yyscanner The scanner object.
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void cmListFileLexer_yyrestart  (FILE * input_file , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! YY_CURRENT_BUFFER ){
-        cmListFileLexer_yyensure_buffer_stack (yyscanner);
-		YY_CURRENT_BUFFER_LVALUE =
-            cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
-	}
-
-	cmListFileLexer_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
-	cmListFileLexer_yy_load_buffer_state(yyscanner );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * @param yyscanner The scanner object.
- */
-    void cmListFileLexer_yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		cmListFileLexer_yypop_buffer_state();
-	 *		cmListFileLexer_yypush_buffer_state(new_buffer);
-     */
-	cmListFileLexer_yyensure_buffer_stack (yyscanner);
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	cmListFileLexer_yy_load_buffer_state(yyscanner );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (cmListFileLexer_yywrap()) processing, but the only time this flag
-	 * is looked at is after cmListFileLexer_yywrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-static void cmListFileLexer_yy_load_buffer_state  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	yyg->yy_hold_char = *yyg->yy_c_buf_p;
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * @param yyscanner The scanner object.
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE cmListFileLexer_yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-
-	b = (YY_BUFFER_STATE) cmListFileLexer_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_create_buffer()" );
-
-	b->yy_buf_size = (yy_size_t)size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) cmListFileLexer_yyalloc(b->yy_buf_size + 2 ,yyscanner );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	cmListFileLexer_yy_init_buffer(b,file ,yyscanner);
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with cmListFileLexer_yy_create_buffer()
- * @param yyscanner The scanner object.
- */
-    void cmListFileLexer_yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		cmListFileLexer_yyfree((void *) b->yy_ch_buf ,yyscanner );
-
-	cmListFileLexer_yyfree((void *) b ,yyscanner );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a cmListFileLexer_yyrestart() or at EOF.
- */
-    static void cmListFileLexer_yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
-
-{
-	int oerrno = errno;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	cmListFileLexer_yy_flush_buffer(b ,yyscanner);
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then cmListFileLexer_yy_init_buffer was _probably_
-     * called from cmListFileLexer_yyrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * @param yyscanner The scanner object.
- */
-    void cmListFileLexer_yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		cmListFileLexer_yy_load_buffer_state(yyscanner );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  @param yyscanner The scanner object.
- */
-void cmListFileLexer_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (new_buffer == NULL)
-		return;
-
-	cmListFileLexer_yyensure_buffer_stack(yyscanner);
-
-	/* This block is copied from cmListFileLexer_yy_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*yyg->yy_c_buf_p = yyg->yy_hold_char;
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		yyg->yy_buffer_stack_top++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from cmListFileLexer_yy_switch_to_buffer. */
-	cmListFileLexer_yy_load_buffer_state(yyscanner );
-	yyg->yy_did_buffer_switch_on_eof = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  @param yyscanner The scanner object.
- */
-void cmListFileLexer_yypop_buffer_state (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	if (!YY_CURRENT_BUFFER)
-		return;
-
-	cmListFileLexer_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if (yyg->yy_buffer_stack_top > 0)
-		--yyg->yy_buffer_stack_top;
-
-	if (YY_CURRENT_BUFFER) {
-		cmListFileLexer_yy_load_buffer_state(yyscanner );
-		yyg->yy_did_buffer_switch_on_eof = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
-{
-	int num_to_alloc;
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-	if (!yyg->yy_buffer_stack) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_yyalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
-
-		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
-		yyg->yy_buffer_stack_max = num_to_alloc;
-		yyg->yy_buffer_stack_top = 0;
-		return;
-	}
-
-	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		yy_size_t grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
-		yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_yyrealloc
-								(yyg->yy_buffer_stack,
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								, yyscanner);
-		if ( ! yyg->yy_buffer_stack )
-			YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
-		yyg->yy_buffer_stack_max = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return NULL;
-
-	b = (YY_BUFFER_STATE) cmListFileLexer_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = NULL;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	cmListFileLexer_yy_switch_to_buffer(b ,yyscanner );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to cmListFileLexer_yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       cmListFileLexer_yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
-{
-
-	return cmListFileLexer_yy_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to cmListFileLexer_yylex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	yy_size_t i;
-
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = (yy_size_t) _yybytes_len + 2;
-	buf = (char *) cmListFileLexer_yyalloc(n ,yyscanner );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_bytes()" );
-
-	for ( i = 0; i < (size_t)_yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = cmListFileLexer_yy_scan_buffer(buf,n ,yyscanner);
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in cmListFileLexer_yy_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = yyg->yy_hold_char; \
-		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
-		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
-		*yyg->yy_c_buf_p = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the user-defined data for this scanner.
- * @param yyscanner The scanner object.
- */
-YY_EXTRA_TYPE cmListFileLexer_yyget_extra  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyextra;
-}
-
-/** Get the current line number.
- * @param yyscanner The scanner object.
- */
-int cmListFileLexer_yyget_lineno  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-
-    return yylineno;
-}
-
-/** Get the current column number.
- * @param yyscanner The scanner object.
- */
-int cmListFileLexer_yyget_column  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        if (! YY_CURRENT_BUFFER)
-            return 0;
-
-    return yycolumn;
-}
-
-/** Get the input stream.
- * @param yyscanner The scanner object.
- */
-FILE *cmListFileLexer_yyget_in  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyin;
-}
-
-/** Get the output stream.
- * @param yyscanner The scanner object.
- */
-FILE *cmListFileLexer_yyget_out  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyout;
-}
-
-/** Get the length of the current token.
- * @param yyscanner The scanner object.
- */
-int cmListFileLexer_yyget_leng  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yyleng;
-}
-
-/** Get the current token.
- * @param yyscanner The scanner object.
- */
-
-char *cmListFileLexer_yyget_text  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yytext;
-}
-
-/** Set the user-defined data. This data is never touched by the scanner.
- * @param user_defined The data to be associated with this scanner.
- * @param yyscanner The scanner object.
- */
-void cmListFileLexer_yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyextra = user_defined ;
-}
-
-/** Set the current line number.
- * @param _line_number line number
- * @param yyscanner The scanner object.
- */
-void cmListFileLexer_yyset_lineno (int  _line_number , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* lineno is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "cmListFileLexer_yyset_lineno called with no buffer" );
-
-    yylineno = _line_number;
-}
-
-/** Set the current column.
- * @param _column_no column number
- * @param yyscanner The scanner object.
- */
-void cmListFileLexer_yyset_column (int  _column_no , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-        /* column is only valid if an input buffer exists. */
-        if (! YY_CURRENT_BUFFER )
-           YY_FATAL_ERROR( "cmListFileLexer_yyset_column called with no buffer" );
-
-    yycolumn = _column_no;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param _in_str A readable stream.
- * @param yyscanner The scanner object.
- * @see cmListFileLexer_yy_switch_to_buffer
- */
-void cmListFileLexer_yyset_in (FILE *  _in_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyin = _in_str ;
-}
-
-void cmListFileLexer_yyset_out (FILE *  _out_str , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yyout = _out_str ;
-}
-
-int cmListFileLexer_yyget_debug  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    return yy_flex_debug;
-}
-
-void cmListFileLexer_yyset_debug (int  _bdebug , yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    yy_flex_debug = _bdebug ;
-}
-
-/* Accessor methods for yylval and yylloc */
-
-/* User-visible API */
-
-/* cmListFileLexer_yylex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals)
-
-{
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-
-    *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), NULL );
-
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-
-    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-/* cmListFileLexer_yylex_init_extra has the same functionality as cmListFileLexer_yylex_init, but follows the
- * convention of taking the scanner as the last argument. Note however, that
- * this is a *pointer* to a scanner, as it will be allocated by this call (and
- * is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to cmListFileLexer_yyalloc in
- * the yyextra field.
- */
-
-int cmListFileLexer_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
-{
-    struct yyguts_t dummy_yyguts;
-
-    cmListFileLexer_yyset_extra (yy_user_defined, &dummy_yyguts);
-
-    if (ptr_yy_globals == NULL){
-        errno = EINVAL;
-        return 1;
-    }
-
-    *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-
-    if (*ptr_yy_globals == NULL){
-        errno = ENOMEM;
-        return 1;
-    }
-
-    /* By setting to 0xAA, we expose bugs in
-    yy_init_globals. Leave at 0x00 for releases. */
-    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
-    cmListFileLexer_yyset_extra (yy_user_defined, *ptr_yy_globals);
-
-    return yy_init_globals ( *ptr_yy_globals );
-}
-
-static int yy_init_globals (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-    /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from cmListFileLexer_yylex_destroy(), so don't allocate here.
-     */
-
-    yyg->yy_buffer_stack = NULL;
-    yyg->yy_buffer_stack_top = 0;
-    yyg->yy_buffer_stack_max = 0;
-    yyg->yy_c_buf_p = NULL;
-    yyg->yy_init = 0;
-    yyg->yy_start = 0;
-
-    yyg->yy_start_stack_ptr = 0;
-    yyg->yy_start_stack_depth = 0;
-    yyg->yy_start_stack =  NULL;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    yyin = stdin;
-    yyout = stdout;
-#else
-    yyin = NULL;
-    yyout = NULL;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * cmListFileLexer_yylex_init()
-     */
-    return 0;
-}
-
-/* cmListFileLexer_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmListFileLexer_yylex_destroy  (yyscan_t yyscanner)
-{
-    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		cmListFileLexer_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		cmListFileLexer_yypop_buffer_state(yyscanner);
-	}
-
-	/* Destroy the stack itself. */
-	cmListFileLexer_yyfree(yyg->yy_buffer_stack ,yyscanner);
-	yyg->yy_buffer_stack = NULL;
-
-    /* Destroy the start condition stack. */
-        cmListFileLexer_yyfree(yyg->yy_start_stack ,yyscanner );
-        yyg->yy_start_stack = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * cmListFileLexer_yylex() is called, initialization will occur. */
-    yy_init_globals( yyscanner);
-
-    /* Destroy the main struct (reentrant only). */
-    cmListFileLexer_yyfree ( yyscanner , yyscanner );
-    yyscanner = NULL;
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-
-	int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
-{
-	int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *cmListFileLexer_yyalloc (yy_size_t  size , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-	return malloc(size);
-}
-
-void *cmListFileLexer_yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return realloc(ptr, size);
-}
-
-void cmListFileLexer_yyfree (void * ptr , yyscan_t yyscanner)
-{
-	struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-	(void)yyg;
-	free( (char *) ptr );	/* see cmListFileLexer_yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 265 "cmListFileLexer.in.l"
-
-
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
-                                    int length)
-{
-  /* Set the token line and column number.  */
-  lexer->token.line = lexer->line;
-  lexer->token.column = lexer->column;
-
-  /* Use the same buffer if possible.  */
-  if (lexer->token.text) {
-    if (text && length < lexer->size) {
-      strcpy(lexer->token.text, text);
-      lexer->token.length = length;
-      return;
-    }
-    free(lexer->token.text);
-    lexer->token.text = 0;
-    lexer->size = 0;
-  }
-
-  /* Need to extend the buffer.  */
-  if (text) {
-    lexer->token.text = strdup(text);
-    lexer->token.length = length;
-    lexer->size = length + 1;
-  } else {
-    lexer->token.length = 0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
-                                  int length)
-{
-  char* temp;
-  int newSize;
-
-  /* If the appended text will fit in the buffer, do not reallocate.  */
-  newSize = lexer->token.length + length + 1;
-  if (lexer->token.text && newSize <= lexer->size) {
-    strcpy(lexer->token.text + lexer->token.length, text);
-    lexer->token.length += length;
-    return;
-  }
-
-  /* We need to extend the buffer.  */
-  temp = malloc(newSize);
-  if (lexer->token.text) {
-    memcpy(temp, lexer->token.text, lexer->token.length);
-    free(lexer->token.text);
-  }
-  memcpy(temp + lexer->token.length, text, length);
-  temp[lexer->token.length + length] = 0;
-  lexer->token.text = temp;
-  lexer->token.length += length;
-  lexer->size = newSize;
-}
-
-/*--------------------------------------------------------------------------*/
-static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
-                                size_t bufferSize)
-{
-  if (lexer) {
-    if (lexer->file) {
-      /* Convert CRLF -> LF explicitly.  The C FILE "t"ext mode
-         does not convert newlines on all platforms.  Move any
-         trailing CR to the start of the buffer for the next read. */
-      size_t cr = lexer->cr;
-      size_t n;
-      buffer[0] = '\r';
-      n = fread(buffer + cr, 1, bufferSize - cr, lexer->file);
-      if (n) {
-        char* o = buffer;
-        const char* i = buffer;
-        const char* e;
-        n += cr;
-        cr = (buffer[n - 1] == '\r') ? 1 : 0;
-        e = buffer + n - cr;
-        while (i != e) {
-          if (i[0] == '\r' && i[1] == '\n') {
-            ++i;
-          }
-          *o++ = *i++;
-        }
-        n = o - buffer;
-      } else {
-        n = cr;
-        cr = 0;
-      }
-      lexer->cr = cr;
-      return n;
-    } else if (lexer->string_left) {
-      int length = lexer->string_left;
-      if ((int)bufferSize < length) {
-        length = (int)bufferSize;
-      }
-      memcpy(buffer, lexer->string_position, length);
-      lexer->string_position += length;
-      lexer->string_left -= length;
-      return length;
-    }
-  }
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerInit(cmListFileLexer* lexer)
-{
-  if (lexer->file || lexer->string_buffer) {
-    cmListFileLexer_yylex_init(&lexer->scanner);
-    cmListFileLexer_yyset_extra(lexer, lexer->scanner);
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerDestroy(cmListFileLexer* lexer)
-{
-  cmListFileLexerSetToken(lexer, 0, 0);
-  if (lexer->file || lexer->string_buffer) {
-    cmListFileLexer_yylex_destroy(lexer->scanner);
-    if (lexer->file) {
-      fclose(lexer->file);
-      lexer->file = 0;
-    }
-    if (lexer->string_buffer) {
-      free(lexer->string_buffer);
-      lexer->string_buffer = 0;
-      lexer->string_left = 0;
-      lexer->string_position = 0;
-    }
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-cmListFileLexer* cmListFileLexer_New(void)
-{
-  cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer));
-  if (!lexer) {
-    return 0;
-  }
-  memset(lexer, 0, sizeof(*lexer));
-  lexer->line = 1;
-  lexer->column = 1;
-  return lexer;
-}
-
-/*--------------------------------------------------------------------------*/
-void cmListFileLexer_Delete(cmListFileLexer* lexer)
-{
-  cmListFileLexer_SetFileName(lexer, 0, 0);
-  free(lexer);
-}
-
-/*--------------------------------------------------------------------------*/
-static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f)
-{
-  unsigned char b[2];
-  if (fread(b, 1, 2, f) == 2) {
-    if (b[0] == 0xEF && b[1] == 0xBB) {
-      if (fread(b, 1, 1, f) == 1 && b[0] == 0xBF) {
-        return cmListFileLexer_BOM_UTF8;
-      }
-    } else if (b[0] == 0xFE && b[1] == 0xFF) {
-      /* UTF-16 BE */
-      return cmListFileLexer_BOM_UTF16BE;
-    } else if (b[0] == 0 && b[1] == 0) {
-      if (fread(b, 1, 2, f) == 2 && b[0] == 0xFE && b[1] == 0xFF) {
-        return cmListFileLexer_BOM_UTF32BE;
-      }
-    } else if (b[0] == 0xFF && b[1] == 0xFE) {
-      fpos_t p;
-      fgetpos(f, &p);
-      if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) {
-        return cmListFileLexer_BOM_UTF32LE;
-      }
-      fsetpos(f, &p);
-      return cmListFileLexer_BOM_UTF16LE;
-    }
-  }
-  rewind(f);
-  return cmListFileLexer_BOM_None;
-}
-
-/*--------------------------------------------------------------------------*/
-int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name,
-                                cmListFileLexer_BOM* bom)
-{
-  int result = 1;
-  cmListFileLexerDestroy(lexer);
-  if (name) {
-#ifdef _WIN32
-    wchar_t* wname = cmsysEncoding_DupToWide(name);
-    lexer->file = _wfopen(wname, L"rb");
-    free(wname);
-#else
-    lexer->file = fopen(name, "rb");
-#endif
-    if (lexer->file) {
-      if (bom) {
-        *bom = cmListFileLexer_ReadBOM(lexer->file);
-      }
-    } else {
-      result = 0;
-    }
-  }
-  cmListFileLexerInit(lexer);
-  return result;
-}
-
-/*--------------------------------------------------------------------------*/
-int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text)
-{
-  int result = 1;
-  cmListFileLexerDestroy(lexer);
-  if (text) {
-    int length = (int)strlen(text);
-    lexer->string_buffer = (char*)malloc(length + 1);
-    if (lexer->string_buffer) {
-      strcpy(lexer->string_buffer, text);
-      lexer->string_position = lexer->string_buffer;
-      lexer->string_left = length;
-    } else {
-      result = 0;
-    }
-  }
-  cmListFileLexerInit(lexer);
-  return result;
-}
-
-/*--------------------------------------------------------------------------*/
-cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer)
-{
-  if (!lexer->file) {
-    return 0;
-  }
-  if (cmListFileLexer_yylex(lexer->scanner, lexer)) {
-    return &lexer->token;
-  } else {
-    cmListFileLexer_SetFileName(lexer, 0, 0);
-    return 0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer)
-{
-  if (lexer->file) {
-    return lexer->line;
-  } else {
-    return 0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer)
-{
-  if (lexer->file) {
-    return lexer->column;
-  } else {
-    return 0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
-                                            cmListFileLexer_Type type)
-{
-  (void)lexer;
-  switch (type) {
-    case cmListFileLexer_Token_None:
-      return "nothing";
-    case cmListFileLexer_Token_Space:
-      return "space";
-    case cmListFileLexer_Token_Newline:
-      return "newline";
-    case cmListFileLexer_Token_Identifier:
-      return "identifier";
-    case cmListFileLexer_Token_ParenLeft:
-      return "left paren";
-    case cmListFileLexer_Token_ParenRight:
-      return "right paren";
-    case cmListFileLexer_Token_ArgumentUnquoted:
-      return "unquoted argument";
-    case cmListFileLexer_Token_ArgumentQuoted:
-      return "quoted argument";
-    case cmListFileLexer_Token_ArgumentBracket:
-      return "bracket argument";
-    case cmListFileLexer_Token_CommentBracket:
-      return "bracket comment";
-    case cmListFileLexer_Token_BadCharacter:
-      return "bad character";
-    case cmListFileLexer_Token_BadBracket:
-      return "unterminated bracket";
-    case cmListFileLexer_Token_BadString:
-      return "unterminated string";
-  }
-  return "unknown token";
-}
diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h
index c9fb6da..f243010 100644
--- a/Source/cmListFileLexer.h
+++ b/Source/cmListFileLexer.h
@@ -32,6 +32,7 @@ struct cmListFileLexer_Token_s
 enum cmListFileLexer_BOM_e
 {
   cmListFileLexer_BOM_None,
+  cmListFileLexer_BOM_Broken,
   cmListFileLexer_BOM_UTF8,
   cmListFileLexer_BOM_UTF16BE,
   cmListFileLexer_BOM_UTF16LE,
diff --git a/Source/cmListFileLexer.in.l b/Source/cmListFileLexer.in.l
deleted file mode 100644
index dd64923..0000000
--- a/Source/cmListFileLexer.in.l
+++ /dev/null
@@ -1,564 +0,0 @@
-%{
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/*
-
-This file must be translated to C and modified to build everywhere.
-
-Run flex >= 2.6 like this:
-
-  flex --nounistd -DFLEXINT_H --prefix=cmListFileLexer_yy -ocmListFileLexer.c cmListFileLexer.in.l
-
-Modify cmListFileLexer.c:
-  - remove trailing whitespace: sed -i 's/\s*$//' cmListFileLexer.c
-  - remove blank lines at end of file
-  - #include "cmStandardLexer.h" at the top
-  - add cast in yy_scan_bytes for loop condition of _yybytes_len to size_t
-  - change type of variable yyl under yy_find_action from yy_size_t to int
-
-*/
-
-/* IWYU pragma: no_forward_declare yyguts_t */
-
-#ifdef WIN32
-#include <cmsys/Encoding.h>
-#endif
-
-/* Setup the proper cmListFileLexer_yylex declaration.  */
-#define YY_EXTRA_TYPE cmListFileLexer*
-#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner, cmListFileLexer* lexer)
-
-#include "cmListFileLexer.h"
-
-/*--------------------------------------------------------------------------*/
-struct cmListFileLexer_s
-{
-  cmListFileLexer_Token token;
-  int bracket;
-  int comment;
-  int line;
-  int column;
-  int size;
-  FILE* file;
-  size_t cr;
-  char* string_buffer;
-  char* string_position;
-  int string_left;
-  yyscan_t scanner;
-};
-
-static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
-                                    int length);
-static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
-                                  int length);
-static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
-                                size_t bufferSize);
-static void cmListFileLexerInit(cmListFileLexer* lexer);
-static void cmListFileLexerDestroy(cmListFileLexer* lexer);
-
-/* Replace the lexer input function.  */
-#undef YY_INPUT
-#define YY_INPUT(buf, result, max_size) \
-  { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); }
-
-/*--------------------------------------------------------------------------*/
-%}
-
-%option reentrant
-%option yylineno
-%option noyywrap
-%pointer
-%x STRING
-%x BRACKET
-%x BRACKETEND
-%x COMMENT
-
-MAKEVAR \$\([A-Za-z0-9_]*\)
-UNQUOTED ([^ \t\r\n\(\)#\\\"[=]|\\.)
-LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
-
-%%
-
-<INITIAL,COMMENT>\n {
-  lexer->token.type = cmListFileLexer_Token_Newline;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  ++lexer->line;
-  lexer->column = 1;
-  BEGIN(INITIAL);
-  return 1;
-}
-
-#?\[=*\[\n? {
-  const char* bracket = yytext;
-  lexer->comment = yytext[0] == '#';
-  if (lexer->comment) {
-    lexer->token.type = cmListFileLexer_Token_CommentBracket;
-    bracket += 1;
-  } else {
-    lexer->token.type = cmListFileLexer_Token_ArgumentBracket;
-  }
-  cmListFileLexerSetToken(lexer, "", 0);
-  lexer->bracket = strchr(bracket+1, '[') - bracket;
-  if (yytext[yyleng-1] == '\n') {
-    ++lexer->line;
-    lexer->column = 1;
-  } else {
-    lexer->column += yyleng;
-  }
-  BEGIN(BRACKET);
-}
-
-# {
-  lexer->column += yyleng;
-  BEGIN(COMMENT);
-}
-
-<COMMENT>.* {
-  lexer->column += yyleng;
-}
-
-\( {
-  lexer->token.type = cmListFileLexer_Token_ParenLeft;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-
-\) {
-  lexer->token.type = cmListFileLexer_Token_ParenRight;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-
-[A-Za-z_][A-Za-z0-9_]* {
-  lexer->token.type = cmListFileLexer_Token_Identifier;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-
-<BRACKET>\]=* {
-  /* Handle ]]====]=======]*/
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  if (yyleng == lexer->bracket) {
-    BEGIN(BRACKETEND);
-  }
-}
-
-<BRACKETEND>\] {
-  lexer->column += yyleng;
-  /* Erase the partial bracket from the token.  */
-  lexer->token.length -= lexer->bracket;
-  lexer->token.text[lexer->token.length] = 0;
-  BEGIN(INITIAL);
-  return 1;
-}
-
-<BRACKET>([^]\n])+ {
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-}
-
-<BRACKET,BRACKETEND>\n {
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  ++lexer->line;
-  lexer->column = 1;
-  BEGIN(BRACKET);
-}
-
-<BRACKET,BRACKETEND>. {
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  BEGIN(BRACKET);
-}
-
-<BRACKET,BRACKETEND><<EOF>> {
-  lexer->token.type = cmListFileLexer_Token_BadBracket;
-  BEGIN(INITIAL);
-  return 1;
-}
-
-({UNQUOTED}|=|\[=*{UNQUOTED})({UNQUOTED}|[[=])* {
-  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-
-({MAKEVAR}|{UNQUOTED}|=|\[=*{LEGACY})({LEGACY}|[[=])* {
-  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-
-\[ {
-  lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-
-\" {
-  lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
-  cmListFileLexerSetToken(lexer, "", 0);
-  lexer->column += yyleng;
-  BEGIN(STRING);
-}
-
-<STRING>([^\\\n\"]|\\.)+ {
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-}
-
-<STRING>\\\n {
-  /* Continuation: text is not part of string */
-  ++lexer->line;
-  lexer->column = 1;
-}
-
-<STRING>\n {
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  ++lexer->line;
-  lexer->column = 1;
-}
-
-<STRING>\" {
-  lexer->column += yyleng;
-  BEGIN(INITIAL);
-  return 1;
-}
-
-<STRING>. {
-  cmListFileLexerAppend(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-}
-
-<STRING><<EOF>> {
-  lexer->token.type = cmListFileLexer_Token_BadString;
-  BEGIN(INITIAL);
-  return 1;
-}
-
-[ \t\r]+ {
-  lexer->token.type = cmListFileLexer_Token_Space;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-
-. {
-  lexer->token.type = cmListFileLexer_Token_BadCharacter;
-  cmListFileLexerSetToken(lexer, yytext, yyleng);
-  lexer->column += yyleng;
-  return 1;
-}
-
-<<EOF>> {
-  lexer->token.type = cmListFileLexer_Token_None;
-  cmListFileLexerSetToken(lexer, 0, 0);
-  return 0;
-}
-
-%%
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
-                                    int length)
-{
-  /* Set the token line and column number.  */
-  lexer->token.line = lexer->line;
-  lexer->token.column = lexer->column;
-
-  /* Use the same buffer if possible.  */
-  if (lexer->token.text) {
-    if (text && length < lexer->size) {
-      strcpy(lexer->token.text, text);
-      lexer->token.length = length;
-      return;
-    }
-    free(lexer->token.text);
-    lexer->token.text = 0;
-    lexer->size = 0;
-  }
-
-  /* Need to extend the buffer.  */
-  if (text) {
-    lexer->token.text = strdup(text);
-    lexer->token.length = length;
-    lexer->size = length + 1;
-  } else {
-    lexer->token.length = 0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
-                                  int length)
-{
-  char* temp;
-  int newSize;
-
-  /* If the appended text will fit in the buffer, do not reallocate.  */
-  newSize = lexer->token.length + length + 1;
-  if (lexer->token.text && newSize <= lexer->size) {
-    strcpy(lexer->token.text + lexer->token.length, text);
-    lexer->token.length += length;
-    return;
-  }
-
-  /* We need to extend the buffer.  */
-  temp = malloc(newSize);
-  if (lexer->token.text) {
-    memcpy(temp, lexer->token.text, lexer->token.length);
-    free(lexer->token.text);
-  }
-  memcpy(temp + lexer->token.length, text, length);
-  temp[lexer->token.length + length] = 0;
-  lexer->token.text = temp;
-  lexer->token.length += length;
-  lexer->size = newSize;
-}
-
-/*--------------------------------------------------------------------------*/
-static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer,
-                                size_t bufferSize)
-{
-  if (lexer) {
-    if (lexer->file) {
-      /* Convert CRLF -> LF explicitly.  The C FILE "t"ext mode
-         does not convert newlines on all platforms.  Move any
-         trailing CR to the start of the buffer for the next read. */
-      size_t cr = lexer->cr;
-      size_t n;
-      buffer[0] = '\r';
-      n = fread(buffer + cr, 1, bufferSize - cr, lexer->file);
-      if (n) {
-        char* o = buffer;
-        const char* i = buffer;
-        const char* e;
-        n += cr;
-        cr = (buffer[n - 1] == '\r') ? 1 : 0;
-        e = buffer + n - cr;
-        while (i != e) {
-          if (i[0] == '\r' && i[1] == '\n') {
-            ++i;
-          }
-          *o++ = *i++;
-        }
-        n = o - buffer;
-      } else {
-        n = cr;
-        cr = 0;
-      }
-      lexer->cr = cr;
-      return n;
-    } else if (lexer->string_left) {
-      int length = lexer->string_left;
-      if ((int)bufferSize < length) {
-        length = (int)bufferSize;
-      }
-      memcpy(buffer, lexer->string_position, length);
-      lexer->string_position += length;
-      lexer->string_left -= length;
-      return length;
-    }
-  }
-  return 0;
-}
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerInit(cmListFileLexer* lexer)
-{
-  if (lexer->file || lexer->string_buffer) {
-    cmListFileLexer_yylex_init(&lexer->scanner);
-    cmListFileLexer_yyset_extra(lexer, lexer->scanner);
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-static void cmListFileLexerDestroy(cmListFileLexer* lexer)
-{
-  cmListFileLexerSetToken(lexer, 0, 0);
-  if (lexer->file || lexer->string_buffer) {
-    cmListFileLexer_yylex_destroy(lexer->scanner);
-    if (lexer->file) {
-      fclose(lexer->file);
-      lexer->file = 0;
-    }
-    if (lexer->string_buffer) {
-      free(lexer->string_buffer);
-      lexer->string_buffer = 0;
-      lexer->string_left = 0;
-      lexer->string_position = 0;
-    }
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-cmListFileLexer* cmListFileLexer_New(void)
-{
-  cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer));
-  if (!lexer) {
-    return 0;
-  }
-  memset(lexer, 0, sizeof(*lexer));
-  lexer->line = 1;
-  lexer->column = 1;
-  return lexer;
-}
-
-/*--------------------------------------------------------------------------*/
-void cmListFileLexer_Delete(cmListFileLexer* lexer)
-{
-  cmListFileLexer_SetFileName(lexer, 0, 0);
-  free(lexer);
-}
-
-/*--------------------------------------------------------------------------*/
-static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f)
-{
-  unsigned char b[2];
-  if (fread(b, 1, 2, f) == 2) {
-    if (b[0] == 0xEF && b[1] == 0xBB) {
-      if (fread(b, 1, 1, f) == 1 && b[0] == 0xBF) {
-        return cmListFileLexer_BOM_UTF8;
-      }
-    } else if (b[0] == 0xFE && b[1] == 0xFF) {
-      /* UTF-16 BE */
-      return cmListFileLexer_BOM_UTF16BE;
-    } else if (b[0] == 0 && b[1] == 0) {
-      if (fread(b, 1, 2, f) == 2 && b[0] == 0xFE && b[1] == 0xFF) {
-        return cmListFileLexer_BOM_UTF32BE;
-      }
-    } else if (b[0] == 0xFF && b[1] == 0xFE) {
-      fpos_t p;
-      fgetpos(f, &p);
-      if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) {
-        return cmListFileLexer_BOM_UTF32LE;
-      }
-      fsetpos(f, &p);
-      return cmListFileLexer_BOM_UTF16LE;
-    }
-  }
-  rewind(f);
-  return cmListFileLexer_BOM_None;
-}
-
-/*--------------------------------------------------------------------------*/
-int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name,
-                                cmListFileLexer_BOM* bom)
-{
-  int result = 1;
-  cmListFileLexerDestroy(lexer);
-  if (name) {
-#ifdef _WIN32
-    wchar_t* wname = cmsysEncoding_DupToWide(name);
-    lexer->file = _wfopen(wname, L"rb");
-    free(wname);
-#else
-    lexer->file = fopen(name, "rb");
-#endif
-    if (lexer->file) {
-      if (bom) {
-        *bom = cmListFileLexer_ReadBOM(lexer->file);
-      }
-    } else {
-      result = 0;
-    }
-  }
-  cmListFileLexerInit(lexer);
-  return result;
-}
-
-/*--------------------------------------------------------------------------*/
-int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text)
-{
-  int result = 1;
-  cmListFileLexerDestroy(lexer);
-  if (text) {
-    int length = (int)strlen(text);
-    lexer->string_buffer = (char*)malloc(length + 1);
-    if (lexer->string_buffer) {
-      strcpy(lexer->string_buffer, text);
-      lexer->string_position = lexer->string_buffer;
-      lexer->string_left = length;
-    } else {
-      result = 0;
-    }
-  }
-  cmListFileLexerInit(lexer);
-  return result;
-}
-
-/*--------------------------------------------------------------------------*/
-cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer)
-{
-  if (!lexer->file) {
-    return 0;
-  }
-  if (cmListFileLexer_yylex(lexer->scanner, lexer)) {
-    return &lexer->token;
-  } else {
-    cmListFileLexer_SetFileName(lexer, 0, 0);
-    return 0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer)
-{
-  if (lexer->file) {
-    return lexer->line;
-  } else {
-    return 0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer)
-{
-  if (lexer->file) {
-    return lexer->column;
-  } else {
-    return 0;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
-                                            cmListFileLexer_Type type)
-{
-  (void)lexer;
-  switch (type) {
-    case cmListFileLexer_Token_None:
-      return "nothing";
-    case cmListFileLexer_Token_Space:
-      return "space";
-    case cmListFileLexer_Token_Newline:
-      return "newline";
-    case cmListFileLexer_Token_Identifier:
-      return "identifier";
-    case cmListFileLexer_Token_ParenLeft:
-      return "left paren";
-    case cmListFileLexer_Token_ParenRight:
-      return "right paren";
-    case cmListFileLexer_Token_ArgumentUnquoted:
-      return "unquoted argument";
-    case cmListFileLexer_Token_ArgumentQuoted:
-      return "quoted argument";
-    case cmListFileLexer_Token_ArgumentBracket:
-      return "bracket argument";
-    case cmListFileLexer_Token_CommentBracket:
-      return "bracket comment";
-    case cmListFileLexer_Token_BadCharacter:
-      return "bad character";
-    case cmListFileLexer_Token_BadBracket:
-      return "unterminated bracket";
-    case cmListFileLexer_Token_BadString:
-      return "unterminated string";
-  }
-  return "unknown token";
-}
diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx
index ea84877..00a30bf 100644
--- a/Source/cmLoadCacheCommand.cxx
+++ b/Source/cmLoadCacheCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmLoadCacheCommand.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
diff --git a/Source/cmLoadCacheCommand.h b/Source/cmLoadCacheCommand.h
index 539c74e..1a8a0fc 100644
--- a/Source/cmLoadCacheCommand.h
+++ b/Source/cmLoadCacheCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmLoadCacheCommand_h
 #define cmLoadCacheCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <set>
 #include <string>
 #include <vector>
@@ -32,11 +33,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "load_cache"; }
-
 protected:
   std::set<std::string> VariablesToRead;
   std::string Prefix;
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index b6743f1..92a32a1 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -2,22 +2,21 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmLoadCommandCommand.h"
 
+#include <signal.h>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
 #include "cmCPluginAPI.cxx"
 #include "cmCPluginAPI.h"
 #include "cmDynamicLoader.h"
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
 
-#include <signal.h>
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
 #ifdef __QNX__
 #include <malloc.h> /* for malloc/free on QNX */
 #endif
@@ -67,11 +66,6 @@ public:
     return this->info.FinalPass != CM_NULLPTR;
   }
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return info.Name; }
-
   static const char* LastName;
   static void TrapsForSignals(int sig)
   {
@@ -174,11 +168,6 @@ cmLoadedCommand::~cmLoadedCommand()
 bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
                                        cmExecutionStatus&)
 {
-  if (this->Disallowed(
-        cmPolicies::CMP0031,
-        "The load_command command should not be called; see CMP0031.")) {
-    return true;
-  }
   if (args.empty()) {
     return true;
   }
@@ -252,7 +241,7 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
     // create a function blocker and set it up
     cmLoadedCommand* f = new cmLoadedCommand();
     (*initFunction)(&f->info);
-    this->Makefile->GetState()->AddCommand(f);
+    this->Makefile->GetState()->AddScriptedCommand(args[0], f);
     return true;
   }
   this->SetError("Attempt to load command failed. "
diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h
index d16dfea..030786e 100644
--- a/Source/cmLoadCommandCommand.h
+++ b/Source/cmLoadCommandCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmLoadCommandCommand_h
 #define cmLoadCommandCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -17,7 +18,6 @@ public:
   cmCommand* Clone() CM_OVERRIDE { return new cmLoadCommandCommand; }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-  std::string GetName() const CM_OVERRIDE { return "load_command"; }
 };
 
 #endif
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
index d5f9d27..6524db4 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -16,14 +16,6 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
   : cmLocalGenerator(gg, mf)
   , WorkingDirectory(wd)
 {
-}
-
-cmLocalCommonGenerator::~cmLocalCommonGenerator()
-{
-}
-
-void cmLocalCommonGenerator::SetConfigName()
-{
   // Store the configuration name that will be generated.
   if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) {
     // Use the build type given by the user.
@@ -34,6 +26,10 @@ void cmLocalCommonGenerator::SetConfigName()
   }
 }
 
+cmLocalCommonGenerator::~cmLocalCommonGenerator()
+{
+}
+
 std::string cmLocalCommonGenerator::GetTargetFortranFlags(
   cmGeneratorTarget const* target, std::string const& config)
 {
diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h
index f83f371..a5afcd8 100644
--- a/Source/cmLocalCommonGenerator.h
+++ b/Source/cmLocalCommonGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmLocalCommonGenerator_h
 #define cmLocalCommonGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <string>
 
@@ -33,7 +33,6 @@ public:
 protected:
   std::string WorkingDirectory;
 
-  void SetConfigName();
   std::string ConfigName;
 
   friend class cmCommonTargetGenerator;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 7077bbb..6ce31c5 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -13,7 +13,6 @@
 #include "cmInstallScriptGenerator.h"
 #include "cmInstallTargetGenerator.h"
 #include "cmLinkLineComputer.h"
-#include "cmLinkLineDeviceComputer.h"
 #include "cmMakefile.h"
 #include "cmRulePlaceholderExpander.h"
 #include "cmSourceFile.h"
@@ -31,9 +30,9 @@
 #include "cmCryptoHash.h"
 #endif
 
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
-#include <cmsys/RegularExpression.hxx>
 #include <iterator>
 #include <sstream>
 #include <stdio.h>
@@ -89,7 +88,19 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
   std::vector<std::string> enabledLanguages =
     this->GetState()->GetEnabledLanguages();
 
-  this->CompilerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+  if (const char* sysrootCompile =
+        this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
+    this->CompilerSysroot = sysrootCompile;
+  } else {
+    this->CompilerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+  }
+
+  if (const char* sysrootLink =
+        this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
+    this->LinkerSysroot = sysrootLink;
+  } else {
+    this->LinkerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+  }
 
   for (std::vector<std::string>::iterator i = enabledLanguages.begin();
        i != enabledLanguages.end(); ++i) {
@@ -129,7 +140,7 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
     for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
          replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
       std::string actualReplace = *replaceIter;
-      if (actualReplace.find("${LANG}") != actualReplace.npos) {
+      if (actualReplace.find("${LANG}") != std::string::npos) {
         cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
       }
 
@@ -143,7 +154,8 @@ cmRulePlaceholderExpander* cmLocalGenerator::CreateRulePlaceholderExpander()
   const
 {
   return new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings,
-                                       this->CompilerSysroot);
+                                       this->CompilerSysroot,
+                                       this->LinkerSysroot);
 }
 
 cmLocalGenerator::~cmLocalGenerator()
@@ -559,6 +571,31 @@ void cmLocalGenerator::ComputeTargetManifest()
   }
 }
 
+bool cmLocalGenerator::ComputeTargetCompileFeatures()
+{
+  // Collect the set of configuration types.
+  std::vector<std::string> configNames;
+  this->Makefile->GetConfigurations(configNames);
+  if (configNames.empty()) {
+    configNames.push_back("");
+  }
+
+  // Process compile features of all targets.
+  std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
+  for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
+       t != targets.end(); ++t) {
+    cmGeneratorTarget* target = *t;
+    for (std::vector<std::string>::iterator ci = configNames.begin();
+         ci != configNames.end(); ++ci) {
+      if (!target->ComputeCompileFeatures(*ci)) {
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
 bool cmLocalGenerator::IsRootMakefile() const
 {
   return !this->StateSnapshot.GetBuildsystemDirectoryParent().IsValid();
@@ -743,14 +780,6 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags,
       this->AppendFlagEscape(flags, *i);
     }
   }
-  std::vector<std::string> features;
-  target->GetCompileFeatures(features, config);
-  for (std::vector<std::string>::const_iterator it = features.begin();
-       it != features.end(); ++it) {
-    if (!this->Makefile->AddRequiredTargetFeature(target->Target, *it)) {
-      return;
-    }
-  }
 
   for (std::map<std::string, std::string>::const_iterator it =
          target->GetMaxLanguageStandards().begin();
@@ -827,7 +856,13 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
     return;
   }
 
-  std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+  std::string rootPath;
+  if (const char* sysrootCompile =
+        this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
+    rootPath = sysrootCompile;
+  } else {
+    rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+  }
 
   std::vector<std::string> implicitDirs;
   // Load implicit include directories for this language.
@@ -881,6 +916,20 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
     }
   }
 
+  // Add standard include directories for this language.
+  // We do not filter out implicit directories here.
+  std::string const standardIncludesVar =
+    "CMAKE_" + lang + "_STANDARD_INCLUDE_DIRECTORIES";
+  std::string const standardIncludes =
+    this->Makefile->GetSafeDefinition(standardIncludesVar);
+  std::vector<std::string>::size_type const before = includes.size();
+  cmSystemTools::ExpandListArgument(standardIncludes, includes);
+  for (std::vector<std::string>::iterator i = includes.begin() + before;
+       i != includes.end(); ++i) {
+    cmSystemTools::ConvertToUnixSlashes(*i);
+    dirs.push_back(*i);
+  }
+
   for (std::vector<std::string>::const_iterator i = implicitDirs.begin();
        i != implicitDirs.end(); ++i) {
     if (std::find(includes.begin(), includes.end(), *i) != includes.end()) {
@@ -916,12 +965,16 @@ void cmLocalGenerator::GetTargetFlags(
   const char* libraryLinkVariable =
     "CMAKE_SHARED_LINKER_FLAGS"; // default to shared library
 
+  const std::string linkLanguage =
+    linkLineComputer->GetLinkerLanguage(target, buildType);
+
   switch (target->GetType()) {
     case cmStateEnums::STATIC_LIBRARY:
       this->GetStaticLibraryFlags(linkFlags, buildType, target);
       break;
     case cmStateEnums::MODULE_LIBRARY:
       libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
+      CM_FALLTHROUGH;
     case cmStateEnums::SHARED_LIBRARY: {
       linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable);
       linkFlags += " ";
@@ -977,16 +1030,13 @@ void cmLocalGenerator::GetTargetFlags(
         linkFlags += this->Makefile->GetSafeDefinition(build);
         linkFlags += " ";
       }
-
-      const std::string linkLanguage =
-        linkLineComputer->GetLinkerLanguage(target, buildType);
       if (linkLanguage.empty()) {
         cmSystemTools::Error(
           "CMake can not determine linker language for target: ",
           target->GetName().c_str());
         return;
       }
-      this->AddLanguageFlags(flags, linkLanguage, buildType);
+      this->AddLanguageFlagsForLinking(flags, target, linkLanguage, buildType);
       if (pcli) {
         this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
                                   frameworkPath, linkPath);
@@ -1041,6 +1091,8 @@ void cmLocalGenerator::GetTargetFlags(
     default:
       break;
   }
+
+  this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage);
 }
 
 void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target,
@@ -1051,11 +1103,7 @@ void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target,
   cmMakefile* mf = this->GetMakefile();
 
   // Add language-specific flags.
-  this->AddLanguageFlags(flags, lang, config);
-
-  if (target->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION", config)) {
-    this->AppendFeatureOptions(flags, lang, "IPO");
-  }
+  this->AddLanguageFlags(flags, target, lang, config);
 
   this->AddArchitectureFlags(flags, target, lang, config);
 
@@ -1215,6 +1263,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065(
           /* clang-format on */
           this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
         }
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         // OLD behavior is to always add the flags
         add_shlib_flags = true;
@@ -1224,6 +1273,7 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065(
         this->IssueMessage(
           cmake::FATAL_ERROR,
           cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065));
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior is to only add the flags if ENABLE_EXPORTS is on
         add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS");
@@ -1288,6 +1338,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
 }
 
 void cmLocalGenerator::AddLanguageFlags(std::string& flags,
+                                        cmGeneratorTarget const* target,
                                         const std::string& lang,
                                         const std::string& config)
 {
@@ -1296,6 +1347,26 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
   flagsVar += lang;
   flagsVar += "_FLAGS";
   this->AddConfigVariableFlags(flags, flagsVar, config);
+
+  if (target->IsIPOEnabled(lang, config)) {
+    this->AppendFeatureOptions(flags, lang, "IPO");
+  }
+}
+
+void cmLocalGenerator::AddLanguageFlagsForLinking(
+  std::string& flags, cmGeneratorTarget const* target, const std::string& lang,
+  const std::string& config)
+{
+  if (this->Makefile->IsOn("CMAKE_" + lang +
+                           "_LINK_WITH_STANDARD_COMPILE_OPTION")) {
+    // This toolchain requires use of the language standard flag
+    // when linking in order to use the matching standard library.
+    // FIXME: If CMake gains an abstraction for standard library
+    // selection, this will have to be reconciled with it.
+    this->AddCompilerRequirementFlag(flags, target, lang);
+  }
+
+  this->AddLanguageFlags(flags, target, lang, config);
 }
 
 cmGeneratorTarget* cmLocalGenerator::FindGeneratorTargetToUse(
@@ -1462,7 +1533,11 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
            "does not know the compile flags to use to enable it.";
       this->IssueMessage(cmake::FATAL_ERROR, e.str());
     } else {
-      this->AppendFlagEscape(flags, opt);
+      std::vector<std::string> optVec;
+      cmSystemTools::ExpandListArgument(opt, optVec);
+      for (size_t i = 0; i < optVec.size(); ++i) {
+        this->AppendFlagEscape(flags, optVec[i]);
+      }
     }
     return;
   }
@@ -1479,6 +1554,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
     langStdMap["C"].push_back("99");
     langStdMap["C"].push_back("90");
 
+    langStdMap["CUDA"].push_back("14");
     langStdMap["CUDA"].push_back("11");
     langStdMap["CUDA"].push_back("98");
   }
@@ -1515,7 +1591,11 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
 
     const char* opt =
       target->Target->GetMakefile()->GetRequiredDefinition(option_flag);
-    this->AppendFlagEscape(flags, opt);
+    std::vector<std::string> optVec;
+    cmSystemTools::ExpandListArgument(opt, optVec);
+    for (size_t i = 0; i < optVec.size(); ++i) {
+      this->AppendFlagEscape(flags, optVec[i]);
+    }
     return;
   }
 
@@ -1525,7 +1605,11 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
 
     if (const char* opt =
           target->Target->GetMakefile()->GetDefinition(option_flag)) {
-      this->AppendFlagEscape(flags, opt);
+      std::vector<std::string> optVec;
+      cmSystemTools::ExpandListArgument(opt, optVec);
+      for (size_t i = 0; i < optVec.size(); ++i) {
+        this->AppendFlagEscape(flags, optVec[i]);
+      }
       return;
     }
   }
@@ -1688,7 +1772,7 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared,
             << cmPolicies::GetPolicyWarning(cmPolicies::CMP0018);
 
           this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
-          // fall through to OLD behaviour
+          CM_FALLTHROUGH;
         }
         case cmPolicies::OLD:
           return true;
@@ -1769,6 +1853,38 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags,
   this->AppendFlags(flags, this->EscapeForShell(rawFlag));
 }
 
+void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
+                                            cmGeneratorTarget* target,
+                                            const std::string& config,
+                                            const std::string& lang)
+{
+  if (!target->IsIPOEnabled(lang, config)) {
+    return;
+  }
+
+  switch (target->GetType()) {
+    case cmStateEnums::EXECUTABLE:
+    case cmStateEnums::SHARED_LIBRARY:
+    case cmStateEnums::MODULE_LIBRARY:
+      break;
+    default:
+      return;
+  }
+
+  const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO";
+  const char* rawFlagsList = this->Makefile->GetDefinition(name);
+  if (rawFlagsList == CM_NULLPTR) {
+    return;
+  }
+
+  std::vector<std::string> flagsList;
+  cmSystemTools::ExpandListArgument(rawFlagsList, flagsList);
+  for (std::vector<std::string>::const_iterator oi = flagsList.begin();
+       oi != flagsList.end(); ++oi) {
+    this->AppendFlagEscape(flags, *oi);
+  }
+}
+
 void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
                                      const char* defines_list) const
 {
@@ -1841,7 +1957,7 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
       // -DNAME="value" instead of -D"NAME=value" for historical reasons.
       std::string::size_type eq = defineIt->find("=");
       def += defineIt->substr(0, eq);
-      if (eq != defineIt->npos) {
+      if (eq != std::string::npos) {
         def += "=";
         def += this->EscapeForShell(defineIt->c_str() + eq + 1, true);
       }
@@ -2018,7 +2134,7 @@ static bool cmLocalGeneratorShortenObjectName(std::string& objName,
   // its own md5 sum.
   std::string::size_type pos =
     objName.find('/', objName.size() - max_len + 32);
-  if (pos != objName.npos) {
+  if (pos != std::string::npos) {
     cmCryptoHash md5(cmCryptoHash::AlgoMD5);
     std::string md5name = md5.HashString(objName.substr(0, pos));
     md5name += objName.substr(pos);
@@ -2163,11 +2279,11 @@ bool cmLocalGenerator::IsNMake() const
 
 std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
   const cmSourceFile& source, std::string const& dir_max,
-  bool* hasSourceExtension)
+  bool* hasSourceExtension, char const* customOutputExtension)
 {
   // Construct the object file name using the full path to the source
   // file which is its only unique identification.
-  const char* fullPath = source.GetFullPath().c_str();
+  std::string const& fullPath = source.GetFullPath();
 
   // Try referencing the source relative to the source tree.
   std::string relFromSource =
@@ -2224,7 +2340,7 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
     }
 
     // Remove the source extension if it is to be replaced.
-    if (replaceExt) {
+    if (replaceExt || customOutputExtension) {
       keptSourceExtension = false;
       std::string::size_type dot_pos = objectName.rfind('.');
       if (dot_pos != std::string::npos) {
@@ -2233,7 +2349,11 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
     }
 
     // Store the new extension.
-    objectName += this->GlobalGenerator->GetLanguageOutputExtension(source);
+    if (customOutputExtension) {
+      objectName += customOutputExtension;
+    } else {
+      objectName += this->GlobalGenerator->GetLanguageOutputExtension(source);
+    }
   }
   if (hasSourceExtension) {
     *hasSourceExtension = keptSourceExtension;
@@ -2365,7 +2485,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const
   }
 
   // Many compilers do not support # in the value so we disable it.
-  if (define.find_first_of('#') != define.npos) {
+  if (define.find_first_of('#') != std::string::npos) {
     std::ostringstream e;
     /* clang-format off */
     e << "WARNING: Preprocessor definitions containing '#' may not be "
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 901ca35..9f78be4 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -3,9 +3,9 @@
 #ifndef cmLocalGenerator_h
 #define cmLocalGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cm_kwiml.h>
+#include "cm_kwiml.h"
 #include <iosfwd>
 #include <map>
 #include <set>
@@ -70,6 +70,8 @@ public:
    */
   void ComputeTargetManifest();
 
+  bool ComputeTargetCompileFeatures();
+
   bool IsRootMakefile() const;
 
   ///! Get the makefile for this generator
@@ -98,8 +100,12 @@ public:
                             const std::string& lang,
                             const std::string& config);
 
-  void AddLanguageFlags(std::string& flags, const std::string& lang,
-                        const std::string& config);
+  void AddLanguageFlags(std::string& flags, cmGeneratorTarget const* target,
+                        const std::string& lang, const std::string& config);
+  void AddLanguageFlagsForLinking(std::string& flags,
+                                  cmGeneratorTarget const* target,
+                                  const std::string& lang,
+                                  const std::string& config);
   void AddCMP0018Flags(std::string& flags, cmGeneratorTarget const* target,
                        std::string const& lang, const std::string& config);
   void AddVisibilityPresetFlags(std::string& flags,
@@ -115,6 +121,9 @@ public:
   virtual void AppendFlags(std::string& flags, const char* newFlags);
   virtual void AppendFlagEscape(std::string& flags,
                                 const std::string& rawFlag);
+  void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
+                            const std::string& config,
+                            const std::string& lang);
   ///! Get the include flags for the current makefile and language
   std::string GetIncludeFlags(const std::vector<std::string>& includes,
                               cmGeneratorTarget* target,
@@ -273,7 +282,8 @@ public:
   // Compute object file names.
   std::string GetObjectFileNameWithoutTarget(
     const cmSourceFile& source, std::string const& dir_max,
-    bool* hasSourceExtension = CM_NULLPTR);
+    bool* hasSourceExtension = CM_NULLPTR,
+    char const* customOutputExtension = CM_NULLPTR);
 
   /** Fill out the static linker flags for the given target.  */
   void GetStaticLibraryFlags(std::string& flags, std::string const& config,
@@ -352,6 +362,7 @@ protected:
   std::map<std::string, std::string> Compilers;
   std::map<std::string, std::string> VariableMappings;
   std::string CompilerSysroot;
+  std::string LinkerSysroot;
 
   bool EmitUniversalBinaryFlags;
 
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index c2d9d57..266710c 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -37,8 +37,9 @@ cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
 cmRulePlaceholderExpander*
 cmLocalNinjaGenerator::CreateRulePlaceholderExpander() const
 {
-  cmRulePlaceholderExpander* ret = new cmRulePlaceholderExpander(
-    this->Compilers, this->VariableMappings, this->CompilerSysroot);
+  cmRulePlaceholderExpander* ret =
+    new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings,
+                                  this->CompilerSysroot, this->LinkerSysroot);
   ret->SetTargetImpLib("$TARGET_IMPLIB");
   return ret;
 }
@@ -57,8 +58,6 @@ void cmLocalNinjaGenerator::Generate()
     this->HomeRelativeOutputPath = "";
   }
 
-  this->SetConfigName();
-
   this->WriteProcessedMakefile(this->GetBuildFileStream());
 #ifdef NINJA_GEN_VERBOSE_FILES
   this->WriteProcessedMakefile(this->GetRulesFileStream());
@@ -214,7 +213,7 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os)
     std::vector<std::string> pools;
     cmSystemTools::ExpandListArgument(jobpools, pools);
     for (size_t i = 0; i < pools.size(); ++i) {
-      const std::string pool = pools[i];
+      std::string const& pool = pools[i];
       const std::string::size_type eq = pool.find('=');
       unsigned int jobs;
       if (eq != std::string::npos &&
@@ -249,12 +248,15 @@ void cmLocalNinjaGenerator::ComputeObjectFilenames(
   std::map<cmSourceFile const*, std::string>& mapping,
   cmGeneratorTarget const* gt)
 {
+  // Determine if these object files should use a custom extension
+  char const* custom_ext = gt->GetCustomObjectExtension();
   for (std::map<cmSourceFile const*, std::string>::iterator si =
          mapping.begin();
        si != mapping.end(); ++si) {
     cmSourceFile const* sf = si->first;
-    si->second =
-      this->GetObjectFileNameWithoutTarget(*sf, gt->ObjectDirectory);
+    bool keptSourceExtension;
+    si->second = this->GetObjectFileNameWithoutTarget(
+      *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext);
   }
 }
 
@@ -278,9 +280,11 @@ void cmLocalNinjaGenerator::AppendTargetOutputs(cmGeneratorTarget* target,
 }
 
 void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target,
-                                                cmNinjaDeps& outputs)
+                                                cmNinjaDeps& outputs,
+                                                cmNinjaTargetDepends depends)
 {
-  this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs);
+  this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs,
+                                                       depends);
 }
 
 void cmLocalNinjaGenerator::AppendCustomCommandDeps(
@@ -317,7 +321,13 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
     } else if (cmdLines.size() > 1) {
       cmd << "cmd.exe /C \"";
     }
-    cmd << *li;
+    // Put current cmdLine in brackets if it contains "||" because it has
+    // higher precedence than "&&" in cmd.exe
+    if (li->find("||") != std::string::npos) {
+      cmd << "( " << *li << " )";
+    } else {
+      cmd << *li;
+    }
   }
   if (cmdLines.size() > 1) {
     cmd << "\"";
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 1080319..a45e018 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmLocalNinjaGenerator_h
 #define cmLocalNinjaGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <map>
@@ -63,7 +63,9 @@ public:
   std::string BuildCommandLine(const std::vector<std::string>& cmdLines);
 
   void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs);
-  void AppendTargetDepends(cmGeneratorTarget* target, cmNinjaDeps& outputs);
+  void AppendTargetDepends(
+    cmGeneratorTarget* target, cmNinjaDeps& outputs,
+    cmNinjaTargetDepends depends = DependOnTargetArtifact);
 
   void AddCustomCommandTarget(cmCustomCommand const* cc,
                               cmGeneratorTarget* target);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 41a4caf..9b9d22c 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmLocalUnixMakefileGenerator3.h"
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/Terminal.h"
 #include <algorithm>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Terminal.h>
 #include <functional>
 #include <sstream>
 #include <stdio.h>
@@ -79,7 +79,7 @@ static std::string cmSplitExtension(std::string const& in, std::string& base)
   std::string::size_type dot_pos = in.rfind('.');
   if (dot_pos != std::string::npos) {
     // Remove the extension first in case &base == &in.
-    ext = in.substr(dot_pos, std::string::npos);
+    ext = in.substr(dot_pos);
     base = in.substr(0, dot_pos);
   } else {
     base = in;
@@ -105,8 +105,6 @@ cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3()
 
 void cmLocalUnixMakefileGenerator3::Generate()
 {
-  this->SetConfigName();
-
   // Record whether some options are enabled to avoid checking many
   // times later.
   if (!this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile()) {
@@ -159,12 +157,15 @@ void cmLocalUnixMakefileGenerator3::ComputeObjectFilenames(
   std::map<cmSourceFile const*, std::string>& mapping,
   cmGeneratorTarget const* gt)
 {
+  // Determine if these object files should use a custom extension
+  char const* custom_ext = gt->GetCustomObjectExtension();
   for (std::map<cmSourceFile const*, std::string>::iterator si =
          mapping.begin();
        si != mapping.end(); ++si) {
     cmSourceFile const* sf = si->first;
-    si->second =
-      this->GetObjectFileNameWithoutTarget(*sf, gt->ObjectDirectory);
+    bool keptSourceExtension;
+    si->second = this->GetObjectFileNameWithoutTarget(
+      *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext);
   }
 }
 
@@ -605,7 +606,7 @@ std::string cmLocalUnixMakefileGenerator3::MaybeConvertWatcomShellCommand(
   std::string const& cmd)
 {
   if (this->IsWatcomWMake() && cmSystemTools::FileIsFullPath(cmd.c_str()) &&
-      cmd.find_first_of("( )") != cmd.npos) {
+      cmd.find_first_of("( )") != std::string::npos) {
     // On Watcom WMake use the windows short path for the command
     // name.  This is needed to avoid funny quoting problems on
     // lines with shell redirection operators.
@@ -851,7 +852,7 @@ void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
 {
   if (this->IsWatcomWMake() && !newFlags.empty()) {
     std::string newf = newFlags;
-    if (newf.find("\\\"") != newf.npos) {
+    if (newf.find("\\\"") != std::string::npos) {
       cmSystemTools::ReplaceString(newf, "\\\"", "\"");
       this->cmLocalGenerator::AppendFlags(flags, newf);
       return;
@@ -977,11 +978,11 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
       cmSystemTools::ReplaceString(cmd, "/./", "/");
       // Convert the command to a relative path only if the current
       // working directory will be the start-output directory.
-      bool had_slash = cmd.find('/') != cmd.npos;
+      bool had_slash = cmd.find('/') != std::string::npos;
       if (workingDir.empty()) {
         cmd = this->MaybeConvertToRelativePath(currentBinDir, cmd);
       }
-      bool has_slash = cmd.find('/') != cmd.npos;
+      bool has_slash = cmd.find('/') != std::string::npos;
       if (had_slash && !has_slash) {
         // This command was specified as a path to a file in the
         // current directory.  Add a leading "./" so it can run
@@ -1038,9 +1039,9 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
         // curly braces are removed.  The hack can be skipped if the
         // first curly brace is the last character.
         std::string::size_type lcurly = cmd.find('{');
-        if (lcurly != cmd.npos && lcurly < (cmd.size() - 1)) {
+        if (lcurly != std::string::npos && lcurly < (cmd.size() - 1)) {
           std::string::size_type rcurly = cmd.find('}');
-          if (rcurly == cmd.npos || rcurly > lcurly) {
+          if (rcurly == std::string::npos || rcurly > lcurly) {
             // The first curly is a left curly.  Use the hack.
             std::string hack_cmd = cmd.substr(0, lcurly);
             hack_cmd += "{{}";
@@ -1199,17 +1200,19 @@ void cmLocalUnixMakefileGenerator3::AppendEcho(
 }
 
 std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable(
-  const std::string& sin, const std::string& s2)
+  std::string const& s, std::string const& s2)
 {
-  std::string s = sin;
   std::string unmodified = s;
   unmodified += s2;
   // if there is no restriction on the length of make variables
   // and there are no "." characters in the string, then return the
   // unmodified combination.
-  if ((!this->MakefileVariableSize && unmodified.find('.') == s.npos) &&
-      (!this->MakefileVariableSize && unmodified.find('+') == s.npos) &&
-      (!this->MakefileVariableSize && unmodified.find('-') == s.npos)) {
+  if ((!this->MakefileVariableSize &&
+       unmodified.find('.') == std::string::npos) &&
+      (!this->MakefileVariableSize &&
+       unmodified.find('+') == std::string::npos) &&
+      (!this->MakefileVariableSize &&
+       unmodified.find('-') == std::string::npos)) {
     return unmodified;
   }
 
@@ -1864,10 +1867,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
     std::string binaryDir = this->GetState()->GetBinaryDirectory();
     if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
       const char* sourceDir = this->GetState()->GetSourceDirectory();
-      std::vector<std::string>::iterator itr =
-        std::remove_if(includes.begin(), includes.end(),
-                       ::NotInProjectDir(sourceDir, binaryDir));
-      includes.erase(itr, includes.end());
+      cmEraseIf(includes, ::NotInProjectDir(sourceDir, binaryDir));
     }
     for (std::vector<std::string>::iterator i = includes.begin();
          i != includes.end(); ++i) {
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index c3ecda4..f64409c 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -3,7 +3,7 @@
 #ifndef cmLocalUnixMakefileGenerator3_h
 #define cmLocalUnixMakefileGenerator3_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmDepends.h"
 #include "cmLocalCommonGenerator.h"
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index 0516bdf..85d4a73 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -8,7 +8,7 @@
 #include "cmVisualStudio10TargetGenerator.h"
 #include "cmXMLParser.h"
 
-#include <cm_expat.h>
+#include "cm_expat.h"
 
 class cmVS10XMLParser : public cmXMLParser
 {
diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h
index 1ed57ec..e57dd8f 100644
--- a/Source/cmLocalVisualStudio10Generator.h
+++ b/Source/cmLocalVisualStudio10Generator.h
@@ -3,7 +3,7 @@
 #ifndef cmLocalVisualStudio10Generator_h
 #define cmLocalVisualStudio10Generator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <string>
 
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 38dda04..dd08e5b 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -9,13 +9,14 @@
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
+#include "cm_expat.h"
 #include "cmake.h"
-#include <cm_expat.h>
 
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratedFileStream.h"
 
 #include <ctype.h> // for isspace
+#include <windows.h>
 
 static bool cmLVS7G_IsFAT(const char* dir);
 
@@ -29,7 +30,7 @@ public:
   typedef cmComputeLinkInformation::ItemVector ItemVector;
   void OutputLibraries(std::ostream& fout, ItemVector const& libs);
   void OutputObjects(std::ostream& fout, cmGeneratorTarget* t,
-                     const char* isep = 0);
+                     std::string const& config, const char* isep = 0);
 
 private:
   cmLocalVisualStudio7Generator* LocalGenerator;
@@ -669,6 +670,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
 
     // Add the target-specific flags.
     this->AddCompileOptions(flags, target, linkLanguage, configName);
+
+    // Check IPO related warning/error.
+    target->IsIPOEnabled(linkLanguage, configName);
   }
 
   if (this->FortranProject) {
@@ -745,11 +749,13 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
 
   if (this->FortranProject) {
     // Intel Fortran >= 15.0 uses TargetName property.
-    std::string targetNameFull = target->GetFullName(configName);
-    std::string targetName =
+    std::string const targetNameFull = target->GetFullName(configName);
+    std::string const targetName =
       cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
-    std::string targetExt =
-      cmSystemTools::GetFilenameLastExtension(targetNameFull);
+    std::string const targetExt =
+      target->GetType() == cmStateEnums::OBJECT_LIBRARY
+      ? ".lib"
+      : cmSystemTools::GetFilenameLastExtension(targetNameFull);
     /* clang-format off */
     fout <<
       "\t\t\tTargetName=\"" << this->EscapeForXML(targetName) << "\"\n"
@@ -787,7 +793,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
          << this->ConvertToXMLOutputPath(modDir.c_str())
          << "\\$(ConfigurationName)\"\n";
   }
-  targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
   fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
   std::vector<std::string> includes;
   this->GetIncludeDirectories(includes, target, "C", configName);
@@ -893,8 +898,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
   // end of <Tool Name=VCMIDLTool
 
   // Add manifest tool settings.
-  if (targetBuilds &&
-      this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8) {
+  if (targetBuilds) {
     const char* manifestTool = "VCManifestTool";
     if (this->FortranProject) {
       manifestTool = "VFManifestTool";
@@ -997,19 +1001,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
   linkOptions.AddTable(cmLocalVisualStudio7GeneratorLinkFlagTable);
 
   linkOptions.Parse(extraLinkOptions.c_str());
-  if (!this->ModuleDefinitionFile.empty()) {
-    std::string defFile = this->ConvertToOutputFormat(
-      this->ModuleDefinitionFile, cmOutputConverter::SHELL);
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    target->GetModuleDefinitionInfo(configName);
+  if (mdi && !mdi->DefFile.empty()) {
+    std::string defFile =
+      this->ConvertToOutputFormat(mdi->DefFile, cmOutputConverter::SHELL);
     linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
   }
 
-  if ((target->GetType() == cmStateEnums::SHARED_LIBRARY ||
-       target->IsExecutableWithExports()) &&
-      this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)/exportall.def");
-    }
-  }
   switch (target->GetType()) {
     case cmStateEnums::UNKNOWN_LIBRARY:
       break;
@@ -1040,10 +1039,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       fout << "\t\t\t<Tool\n"
            << "\t\t\t\tName=\"" << tool << "\"\n";
 
-      if (this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 ||
-          this->FortranProject) {
+      if (this->FortranProject) {
         std::ostringstream libdeps;
-        this->Internal->OutputObjects(libdeps, target);
+        this->Internal->OutputObjects(libdeps, target, configName);
         if (!libdeps.str().empty()) {
           fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str()
                << "\"\n";
@@ -1090,14 +1088,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       if (!gg->NeedLinkLibraryDependencies(target)) {
         fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n";
       }
-      linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
       // Use the NOINHERIT macro to avoid getting VS project default
       // libraries which may be set by the user to something bad.
       fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
            << this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
-      if (this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 ||
-          this->FortranProject) {
-        this->Internal->OutputObjects(fout, target, " ");
+      if (this->FortranProject) {
+        this->Internal->OutputObjects(fout, target, configName, " ");
       }
       fout << " ";
       this->Internal->OutputLibraries(fout, cli.GetItems());
@@ -1134,7 +1130,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       if (stackVal) {
         fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"\n";
       }
-      temp = target->GetDirectory(configName, true);
+      temp =
+        target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact);
       temp += "/";
       temp += targetNameImport;
       fout << "\t\t\t\tImportLibrary=\""
@@ -1176,14 +1173,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       if (!gg->NeedLinkLibraryDependencies(target)) {
         fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n";
       }
-      linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
       // Use the NOINHERIT macro to avoid getting VS project default
       // libraries which may be set by the user to something bad.
       fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
            << this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
-      if (this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 ||
-          this->FortranProject) {
-        this->Internal->OutputObjects(fout, target, " ");
+      if (this->FortranProject) {
+        this->Internal->OutputObjects(fout, target, configName, " ");
       }
       fout << " ";
       this->Internal->OutputLibraries(fout, cli.GetItems());
@@ -1233,7 +1228,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       if (stackVal) {
         fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"";
       }
-      temp = target->GetDirectory(configName, true);
+      temp =
+        target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact);
       temp += "/";
       temp += targetNameImport;
       fout << "\t\t\t\tImportLibrary=\""
@@ -1302,20 +1298,26 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries(
 }
 
 void cmLocalVisualStudio7GeneratorInternals::OutputObjects(
-  std::ostream& fout, cmGeneratorTarget* gt, const char* isep)
+  std::ostream& fout, cmGeneratorTarget* gt, std::string const& configName,
+  const char* isep)
 {
   // VS < 8 does not support per-config source locations so we
   // list object library content on the link line instead.
   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
   std::string currentBinDir = lg->GetCurrentBinaryDirectory();
-  std::vector<std::string> objs;
-  gt->UseObjectLibraries(objs, "");
+
+  std::vector<cmSourceFile const*> objs;
+  gt->GetExternalObjects(objs, configName);
+
   const char* sep = isep ? isep : "";
-  for (std::vector<std::string>::const_iterator oi = objs.begin();
-       oi != objs.end(); ++oi) {
-    std::string rel = lg->ConvertToRelativePath(currentBinDir, oi->c_str());
-    fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
-    sep = " ";
+  for (std::vector<cmSourceFile const*>::const_iterator i = objs.begin();
+       i != objs.end(); ++i) {
+    if (!(*i)->GetObjectLibrary().empty()) {
+      std::string const& objFile = (*i)->GetFullPath();
+      std::string rel = lg->ConvertToRelativePath(currentBinDir, objFile);
+      fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
+      sep = " ";
+    }
   }
 }
 
@@ -1364,25 +1366,26 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
   // We may be modifying the source groups temporarily, so make a copy.
   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
 
-  // get the classes from the source lists then add them to the groups
-  this->ModuleDefinitionFile = "";
-  std::vector<cmSourceFile*> classes;
-  if (!target->GetConfigCommonSourceFiles(classes)) {
-    return;
-  }
-  for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
-       i != classes.end(); i++) {
-    if (!(*i)->GetObjectLibrary().empty()) {
-      continue;
+  std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+    target->GetAllConfigSources();
+  std::map<cmSourceFile const*, size_t> sourcesIndex;
+
+  for (size_t si = 0; si < sources.size(); ++si) {
+    cmSourceFile const* sf = sources[si].Source;
+    sourcesIndex[sf] = si;
+    if (!sf->GetObjectLibrary().empty()) {
+      if (this->FortranProject) {
+        // Intel Fortran does not support per-config source locations
+        // so we list object library content on the link line instead.
+        // See OutputObjects.
+        continue;
+      }
     }
     // Add the file to the list of sources.
-    std::string source = (*i)->GetFullPath();
-    if (cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF") {
-      this->ModuleDefinitionFile = (*i)->GetFullPath();
-    }
+    std::string const source = sf->GetFullPath();
     cmSourceGroup* sourceGroup =
       this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
-    sourceGroup->AssignSource(*i);
+    sourceGroup->AssignSource(sf);
   }
 
   // open the project
@@ -1395,25 +1398,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
   // Loop through every source group.
   for (unsigned int i = 0; i < sourceGroups.size(); ++i) {
     cmSourceGroup sg = sourceGroups[i];
-    this->WriteGroup(&sg, target, fout, libName, configs);
-  }
-
-  if (this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8 &&
-      !this->FortranProject) {
-    // VS >= 8 support per-config source locations so we
-    // list object library content as external objects.
-    std::vector<std::string> objs;
-    target->UseObjectLibraries(objs, "");
-    if (!objs.empty()) {
-      // TODO: Separate sub-filter for each object library used?
-      fout << "\t\t<Filter Name=\"Object Libraries\">\n";
-      for (std::vector<std::string>::const_iterator oi = objs.begin();
-           oi != objs.end(); ++oi) {
-        std::string o = this->ConvertToXMLOutputPathSingle(oi->c_str());
-        fout << "\t\t\t<File RelativePath=\"" << o << "\" />\n";
-      }
-      fout << "\t\t</Filter>\n";
-    }
+    this->WriteGroup(&sg, target, fout, libName, configs, sourcesIndex);
   }
 
   fout << "\t</Files>\n";
@@ -1435,25 +1420,28 @@ struct cmLVS7GFileConfig
 class cmLocalVisualStudio7GeneratorFCInfo
 {
 public:
-  cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
-                                      cmGeneratorTarget* target,
-                                      cmSourceFile const& sf,
-                                      std::vector<std::string> const& configs);
+  cmLocalVisualStudio7GeneratorFCInfo(
+    cmLocalVisualStudio7Generator* lg, cmGeneratorTarget* target,
+    cmGeneratorTarget::AllConfigSource const& acs,
+    std::vector<std::string> const& configs);
   std::map<std::string, cmLVS7GFileConfig> FileConfigMap;
 };
 
 cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
   cmLocalVisualStudio7Generator* lg, cmGeneratorTarget* gt,
-  cmSourceFile const& sf, std::vector<std::string> const& configs)
+  cmGeneratorTarget::AllConfigSource const& acs,
+  std::vector<std::string> const& configs)
 {
+  cmSourceFile const& sf = *acs.Source;
   std::string objectName;
   if (gt->HasExplicitObjectName(&sf)) {
     objectName = gt->GetObjectName(&sf);
   }
 
   // Compute per-source, per-config information.
+  size_t ci = 0;
   for (std::vector<std::string>::const_iterator i = configs.begin();
-       i != configs.end(); ++i) {
+       i != configs.end(); ++i, ++ci) {
     std::string configUpper = cmSystemTools::UpperCase(*i);
     cmLVS7GFileConfig fc;
     bool needfc = false;
@@ -1519,7 +1507,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
     }
     // If HEADER_FILE_ONLY is set, we must suppress this generation in
     // the project file
-    fc.ExcludedFromBuild = (sf.GetPropertyAsBool("HEADER_FILE_ONLY"));
+    fc.ExcludedFromBuild = sf.GetPropertyAsBool("HEADER_FILE_ONLY") ||
+      std::find(acs.Configs.begin(), acs.Configs.end(), ci) ==
+        acs.Configs.end();
     if (fc.ExcludedFromBuild) {
       needfc = true;
     }
@@ -1574,7 +1564,8 @@ std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory(
 
 bool cmLocalVisualStudio7Generator::WriteGroup(
   const cmSourceGroup* sg, cmGeneratorTarget* target, std::ostream& fout,
-  const std::string& libName, std::vector<std::string> const& configs)
+  const std::string& libName, std::vector<std::string> const& configs,
+  std::map<cmSourceFile const*, size_t> const& sourcesIndex)
 {
   cmGlobalVisualStudio7Generator* gg =
     static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
@@ -1585,7 +1576,8 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
   bool hasChildrenWithSources = false;
   std::ostringstream tmpOut;
   for (unsigned int i = 0; i < children.size(); ++i) {
-    if (this->WriteGroup(&children[i], target, tmpOut, libName, configs)) {
+    if (this->WriteGroup(&children[i], target, tmpOut, libName, configs,
+                         sourcesIndex)) {
       hasChildrenWithSources = true;
     }
   }
@@ -1601,15 +1593,26 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
     this->WriteVCProjBeginGroup(fout, name.c_str(), "");
   }
 
+  std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+    target->GetAllConfigSources();
+
   // Loop through each source in the source group.
   for (std::vector<const cmSourceFile*>::const_iterator sf =
          sourceFiles.begin();
        sf != sourceFiles.end(); ++sf) {
     std::string source = (*sf)->GetFullPath();
-    FCInfo fcinfo(this, target, *(*sf), configs);
 
     if (source != libName || target->GetType() == cmStateEnums::UTILITY ||
         target->GetType() == cmStateEnums::GLOBAL_TARGET) {
+      // Look up the source kind and configs.
+      std::map<cmSourceFile const*, size_t>::const_iterator map_it =
+        sourcesIndex.find(*sf);
+      // The map entry must exist because we populated it earlier.
+      assert(map_it != sourcesIndex.end());
+      cmGeneratorTarget::AllConfigSource const& acs = sources[map_it->second];
+
+      FCInfo fcinfo(this, target, acs, configs);
+
       fout << "\t\t\t<File\n";
       std::string d = this->ConvertToXMLOutputPathSingle(source.c_str());
       // Tell MS-Dev what the source is.  If the compiler knows how to
@@ -1649,6 +1652,9 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
             lang == "ASM_MASM") {
           aCompilerTool = "MASM";
         }
+        if (acs.Kind == cmGeneratorTarget::SourceKindExternalObject) {
+          aCompilerTool = "VCCustomBuildTool";
+        }
         for (std::map<std::string, cmLVS7GFileConfig>::const_iterator fci =
                fcinfo.FileConfigMap.begin();
              fci != fcinfo.FileConfigMap.end(); ++fci) {
@@ -1675,7 +1681,6 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
             fileOptions.Parse(fc.CompileFlags.c_str());
             fileOptions.AddDefines(fc.CompileDefs.c_str());
             fileOptions.AddDefines(fc.CompileDefsConfig.c_str());
-            fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n");
             fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
             fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n",
                                                       ppLang);
@@ -1829,17 +1834,15 @@ void cmLocalVisualStudio7Generator::OutputTargetRules(
   tool = this->FortranProject ? "VFPreLinkEventTool" : "VCPreLinkEventTool";
   event.Start(tool);
   bool addedPrelink = false;
-  if ((target->GetType() == cmStateEnums::SHARED_LIBRARY ||
-       target->IsExecutableWithExports()) &&
-      this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      addedPrelink = true;
-      std::vector<cmCustomCommand> commands = target->GetPreLinkCommands();
-      cmGlobalVisualStudioGenerator* gg =
-        static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
-      gg->AddSymbolExportCommand(target, commands, configName);
-      event.Write(commands);
-    }
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    target->GetModuleDefinitionInfo(configName);
+  if (mdi && mdi->DefFileGenerated) {
+    addedPrelink = true;
+    std::vector<cmCustomCommand> commands = target->GetPreLinkCommands();
+    cmGlobalVisualStudioGenerator* gg =
+      static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
+    gg->AddSymbolExportCommand(target, commands, configName);
+    event.Write(commands);
   }
   if (!addedPrelink) {
     event.Write(target->GetPreLinkCommands());
@@ -1956,11 +1959,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStart(
        << "<VisualStudioProject\n"
        << "\tProjectType=\"Visual C++\"\n";
   /* clang-format on */
-  if (gg->GetVersion() == cmGlobalVisualStudioGenerator::VS71) {
-    fout << "\tVersion=\"7.10\"\n";
-  } else {
-    fout << "\tVersion=\"" << (gg->GetVersion() / 10) << ".00\"\n";
-  }
+  fout << "\tVersion=\"" << (gg->GetVersion() / 10) << ".00\"\n";
   const char* projLabel = target->GetProperty("PROJECT_LABEL");
   if (!projLabel) {
     projLabel = libName.c_str();
@@ -1970,9 +1969,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStart(
     keyword = "Win32Proj";
   }
   fout << "\tName=\"" << projLabel << "\"\n";
-  if (gg->GetVersion() >= cmGlobalVisualStudioGenerator::VS8) {
-    fout << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\"\n";
-  }
+  fout << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\"\n";
   this->WriteProjectSCC(fout, target);
   if (const char* targetFrameworkVersion =
         target->GetProperty("VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
@@ -2130,7 +2127,6 @@ std::string cmLocalVisualStudio7Generator::GetTargetDirectory(
   return dir;
 }
 
-#include <windows.h>
 static bool cmLVS7G_IsFAT(const char* dir)
 {
   if (dir[0] && dir[1] == ':') {
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index d69cce1..89a3ee3 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -3,7 +3,7 @@
 #ifndef cmLocalVisualStudio7Generator_h
 #define cmLocalVisualStudio7Generator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <string>
@@ -119,7 +119,8 @@ private:
 
   bool WriteGroup(const cmSourceGroup* sg, cmGeneratorTarget* target,
                   std::ostream& fout, const std::string& libName,
-                  std::vector<std::string> const& configs);
+                  std::vector<std::string> const& configs,
+                  std::map<cmSourceFile const*, size_t> const& sourcesIndex);
 
   friend class cmLocalVisualStudio7GeneratorFCInfo;
   friend class cmLocalVisualStudio7GeneratorInternals;
@@ -128,7 +129,6 @@ private:
 
   friend class EventWriter;
 
-  std::string ModuleDefinitionFile;
   bool FortranProject;
   bool WindowsCEProject;
   cmLocalVisualStudio7GeneratorInternals* Internal;
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index e20fe50..41025af 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -32,6 +32,7 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
   std::map<cmSourceFile const*, std::string>& mapping,
   cmGeneratorTarget const* gt)
 {
+  char const* custom_ext = gt->GetCustomObjectExtension();
   std::string dir_max = this->ComputeLongestObjectDirectory(gt);
 
   // Count the number of object files with each name.  Note that
@@ -44,7 +45,12 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
     cmSourceFile const* sf = si->first;
     std::string objectNameLower = cmSystemTools::LowerCase(
       cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
-    objectNameLower += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+    if (custom_ext) {
+      objectNameLower += custom_ext;
+    } else {
+      objectNameLower +=
+        this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+    }
     counts[objectNameLower] += 1;
   }
 
@@ -57,10 +63,16 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
     cmSourceFile const* sf = si->first;
     std::string objectName =
       cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
-    objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+    if (custom_ext) {
+      objectName += custom_ext;
+    } else {
+      objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+    }
     if (counts[cmSystemTools::LowerCase(objectName)] > 1) {
       const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
-      objectName = this->GetObjectFileNameWithoutTarget(*sf, dir_max);
+      bool keptSourceExtension;
+      objectName = this->GetObjectFileNameWithoutTarget(
+        *sf, dir_max, &keptSourceExtension, custom_ext);
     }
     si->second = objectName;
   }
@@ -80,8 +92,10 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target,
       !(isFortran && target->GetType() == cmStateEnums::SHARED_LIBRARY)) {
     return pcc;
   }
-  std::string outDir = target->GetDirectory(config, false);
-  std::string impDir = target->GetDirectory(config, true);
+  std::string outDir =
+    target->GetDirectory(config, cmStateEnums::RuntimeBinaryArtifact);
+  std::string impDir =
+    target->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
   if (impDir == outDir) {
     return pcc;
   }
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index 39188f9..85fb8a5 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmLocalVisualStudioGenerator_h
 #define cmLocalVisualStudioGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <map>
 #include <memory>
diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h
index b4a8c6c..4ca02a9 100644
--- a/Source/cmLocalXCodeGenerator.h
+++ b/Source/cmLocalXCodeGenerator.h
@@ -3,7 +3,8 @@
 #ifndef cmLocalXCodeGenerator_h
 #define cmLocalXCodeGenerator_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
+
 #include <map>
 #include <string>
 
diff --git a/Source/cmLocale.h b/Source/cmLocale.h
index cca7cf5..9f90a3a 100644
--- a/Source/cmLocale.h
+++ b/Source/cmLocale.h
@@ -3,14 +3,14 @@
 #ifndef cmLocale_h
 #define cmLocale_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <locale.h>
 #include <string>
 
 class cmLocaleRAII
 {
-  std::string OldLocale;
+  CM_DISABLE_COPY(cmLocaleRAII)
 
 public:
   cmLocaleRAII()
@@ -19,6 +19,9 @@ public:
     setlocale(LC_CTYPE, "");
   }
   ~cmLocaleRAII() { setlocale(LC_CTYPE, this->OldLocale.c_str()); }
+
+private:
+  std::string OldLocale;
 };
 
 #endif
diff --git a/Source/cmMSVC60LinkLineComputer.cxx b/Source/cmMSVC60LinkLineComputer.cxx
index d761e7b..5298d1a 100644
--- a/Source/cmMSVC60LinkLineComputer.cxx
+++ b/Source/cmMSVC60LinkLineComputer.cxx
@@ -3,8 +3,6 @@
 
 #include "cmMSVC60LinkLineComputer.h"
 
-#include "cmStateDirectory.h"
-
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include "cmSystemTools.h"
 #endif
@@ -12,7 +10,7 @@
 class cmOutputConverter;
 
 cmMSVC60LinkLineComputer::cmMSVC60LinkLineComputer(
-  cmOutputConverter* outputConverter, cmStateDirectory stateDir)
+  cmOutputConverter* outputConverter, cmStateDirectory const& stateDir)
   : cmLinkLineComputer(outputConverter, stateDir)
 {
 }
@@ -24,7 +22,7 @@ std::string cmMSVC60LinkLineComputer::ConvertToLinkReference(
   // Work-ardound command line parsing limitations in MSVC 6.0
   // Search for the last space.
   std::string::size_type pos = lib.rfind(' ');
-  if (pos != lib.npos) {
+  if (pos != std::string::npos) {
     // Find the slash after the last space, if any.
     pos = lib.find('/', pos);
 
diff --git a/Source/cmMSVC60LinkLineComputer.h b/Source/cmMSVC60LinkLineComputer.h
index 9a28dca..f2892d5 100644
--- a/Source/cmMSVC60LinkLineComputer.h
+++ b/Source/cmMSVC60LinkLineComputer.h
@@ -4,7 +4,7 @@
 #ifndef cmMSVC60LinkLineComputer_h
 #define cmMSVC60LinkLineComputer_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <string>
 
@@ -15,9 +15,11 @@ class cmStateDirectory;
 
 class cmMSVC60LinkLineComputer : public cmLinkLineComputer
 {
+  CM_DISABLE_COPY(cmMSVC60LinkLineComputer)
+
 public:
   cmMSVC60LinkLineComputer(cmOutputConverter* outputConverter,
-                           cmStateDirectory stateDir);
+                           cmStateDirectory const& stateDir);
 
   std::string ConvertToLinkReference(std::string const& input) const
     CM_OVERRIDE;
diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx
index 586e6c6..a4350f7 100644
--- a/Source/cmMachO.cxx
+++ b/Source/cmMachO.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMachO.h"
 
+#include "cmsys/FStream.hxx"
 #include <algorithm>
-#include <cmsys/FStream.hxx>
 #include <stddef.h>
 #include <string>
 #include <vector>
diff --git a/Source/cmMachO.h b/Source/cmMachO.h
index 901f17a..42745cf 100644
--- a/Source/cmMachO.h
+++ b/Source/cmMachO.h
@@ -3,7 +3,7 @@
 #ifndef cmMachO_h
 #define cmMachO_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <string>
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index 583f801..a6a9ea3 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -22,11 +22,6 @@ public:
   ~cmMacroHelperCommand() CM_OVERRIDE {}
 
   /**
-   * This determines if the command is defined in a cmake script.
-   */
-  bool IsUserDefined() const CM_OVERRIDE { return true; }
-
-  /**
    * This is a virtual constructor for the command.
    */
   cmCommand* Clone() CM_OVERRIDE
@@ -41,11 +36,6 @@ public:
   }
 
   /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
    * This is called when the command is first encountered in
    * the CMakeLists.txt file.
    */
@@ -58,11 +48,6 @@ public:
     return false;
   }
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return this->Args[0]; }
-
   std::vector<std::string> Args;
   std::vector<cmListFileFunction> Functions;
   cmPolicies::PolicyMap Policies;
@@ -156,15 +141,15 @@ bool cmMacroHelperCommand::InvokeInitialPass(
       // The error message should have already included the call stack
       // so we do not need to report an error here.
       macroScope.Quiet();
-      inStatus.SetNestedError(true);
+      inStatus.SetNestedError();
       return false;
     }
     if (status.GetReturnInvoked()) {
-      inStatus.SetReturnInvoked(true);
+      inStatus.SetReturnInvoked();
       return true;
     }
     if (status.GetBreakInvoked()) {
-      inStatus.SetBreakInvoked(true);
+      inStatus.SetBreakInvoked();
       return true;
     }
   }
@@ -189,10 +174,7 @@ bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
       f->Functions = this->Functions;
       f->FilePath = this->GetStartingContext().FilePath;
       mf.RecordPolicies(f->Policies);
-      std::string newName = "_" + this->Args[0];
-      mf.GetState()->RenameCommand(this->Args[0], newName);
-      mf.GetState()->AddCommand(f);
-
+      mf.GetState()->AddScriptedCommand(this->Args[0], f);
       // remove the function blocker now that the macro is defined
       mf.RemoveFunctionBlocker(this, lff);
       return true;
diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h
index acb4233..0d35fe0 100644
--- a/Source/cmMacroCommand.h
+++ b/Source/cmMacroCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmMacroCommand_h
 #define cmMacroCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -43,16 +44,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "macro"; }
 };
 
 #endif
diff --git a/Source/cmMakeDirectoryCommand.h b/Source/cmMakeDirectoryCommand.h
index d9cce6f..af72eab 100644
--- a/Source/cmMakeDirectoryCommand.h
+++ b/Source/cmMakeDirectoryCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmMakeDirectoryCommand_h
 #define cmMakeDirectoryCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -34,16 +35,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "make_directory"; }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
 };
 
 #endif
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 1e995fb..608b18a 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2,10 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMakefile.h"
 
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
 #include <ctype.h>
 #include <sstream>
 #include <stdlib.h>
@@ -36,7 +36,9 @@
 #include "cmTest.h"
 #include "cmTestGenerator.h" // IWYU pragma: keep
 #include "cmVersion.h"
+#include "cmWorkingDirectory.h"
 #include "cm_auto_ptr.hxx"
+#include "cm_sys_stat.h"
 #include "cmake.h"
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
@@ -92,6 +94,10 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
   this->AddSourceGroup("CMake Rules", "\\.rule$");
   this->AddSourceGroup("Resources", "\\.plist$");
   this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$");
+
+  this->ObjectLibrariesSourceGroupIndex = this->SourceGroups.size();
+  this->SourceGroups.push_back(
+    cmSourceGroup("Object Libraries", "^MATCH_NO_SOURCES$"));
 #endif
 }
 
@@ -112,7 +118,7 @@ void cmMakefile::IssueMessage(cmake::MessageType t,
 {
   if (!this->ExecutionStatusStack.empty()) {
     if ((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) {
-      this->ExecutionStatusStack.back()->SetNestedError(true);
+      this->ExecutionStatusStack.back()->SetNestedError();
     }
   }
   this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace());
@@ -266,11 +272,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
     pcmd->SetMakefile(this);
 
     // Decide whether to invoke the command.
-    if (!cmSystemTools::GetFatalErrorOccured() &&
-        (this->GetCMakeInstance()->GetWorkingMode() != cmake::SCRIPT_MODE ||
-         pcmd->IsScriptable()))
-
-    {
+    if (!cmSystemTools::GetFatalErrorOccured()) {
       // if trace is enabled, print out invoke information
       if (this->GetCMakeInstance()->GetTrace()) {
         this->PrintCommandTrace(lff);
@@ -281,7 +283,8 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
       if (!invokeSucceeded || hadNestedError) {
         if (!hadNestedError) {
           // The command invocation requested that we report an error.
-          this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError());
+          std::string const error = name + " " + pcmd->GetError();
+          this->IssueMessage(cmake::FATAL_ERROR, error);
         }
         result = false;
         if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) {
@@ -291,15 +294,6 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
         // use the command
         this->FinalPassCommands.push_back(pcmd.release());
       }
-    } else if (this->GetCMakeInstance()->GetWorkingMode() ==
-                 cmake::SCRIPT_MODE &&
-               !pcmd->IsScriptable()) {
-      std::string error = "Command ";
-      error += pcmd->GetName();
-      error += "() is not scriptable";
-      this->IssueMessage(cmake::FATAL_ERROR, error);
-      result = false;
-      cmSystemTools::SetFatalErrorOccured();
     }
   } else {
     if (!cmSystemTools::GetFatalErrorOccured()) {
@@ -322,6 +316,7 @@ public:
                bool noPolicyScope);
   ~IncludeScope();
   void Quiet() { this->ReportError = false; }
+
 private:
   cmMakefile* Makefile;
   bool NoPolicyScope;
@@ -365,6 +360,7 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf,
         // We should never make this policy required, but we handle it
         // here just in case.
         this->CheckCMP0011 = true;
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior is to push a (strong) scope.
         this->Makefile->PushPolicy();
@@ -486,6 +482,7 @@ public:
   }
 
   void Quiet() { this->ReportError = false; }
+
 private:
   cmMakefile* Makefile;
   bool ReportError;
@@ -631,7 +628,7 @@ struct file_not_persistent
 {
   bool operator()(const std::string& path) const
   {
-    return !(path.find("CMakeTmp") == path.npos &&
+    return !(path.find("CMakeTmp") == std::string::npos &&
              cmSystemTools::FileExists(path.c_str()));
   }
 };
@@ -653,21 +650,12 @@ void cmMakefile::FinalPass()
   // we don't want cmake to re-run if a configured file is created and deleted
   // during processing as that would make it a transient file that can't
   // influence the build process
-
-  // remove_if will move all items that don't have a valid file name to the
-  // back of the vector
-  std::vector<std::string>::iterator new_output_files_end = std::remove_if(
-    this->OutputFiles.begin(), this->OutputFiles.end(), file_not_persistent());
-  // we just have to erase all items at the back
-  this->OutputFiles.erase(new_output_files_end, this->OutputFiles.end());
+  cmEraseIf(this->OutputFiles, file_not_persistent());
 
   // if a configured file is used as input for another configured file,
   // and then deleted it will show up in the input list files so we
   // need to scan those too
-  std::vector<std::string>::iterator new_list_files_end = std::remove_if(
-    this->ListFiles.begin(), this->ListFiles.end(), file_not_persistent());
-
-  this->ListFiles.erase(new_list_files_end, this->ListFiles.end());
+  cmEraseIf(this->ListFiles, file_not_persistent());
 }
 
 // Generate the output file
@@ -692,7 +680,8 @@ void cmMakefile::AddCustomCommandToTarget(
   const std::vector<std::string>& depends,
   const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
   const char* comment, const char* workingDir, bool escapeOldStyle,
-  bool uses_terminal, const std::string& depfile, bool command_expand_lists)
+  bool uses_terminal, const std::string& depfile, bool command_expand_lists,
+  ObjectLibraryCommands objLibraryCommands)
 {
   // Find the target to which to add the custom command.
   cmTargets::iterator ti = this->Targets.find(target);
@@ -732,7 +721,8 @@ void cmMakefile::AddCustomCommandToTarget(
     return;
   }
 
-  if (ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) {
+  if (objLibraryCommands == RejectObjectLibraryCommands &&
+      ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) {
     std::ostringstream e;
     e << "Target \"" << target
       << "\" is an OBJECT library "
@@ -1172,6 +1162,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
       case cmPolicies::WARN:
         this->IssueMessage(cmake::AUTHOR_WARNING,
                            cmPolicies::GetPolicyWarning(cmPolicies::CMP0005));
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         // OLD behavior is to not escape the value.  We should not
         // convert the definition to use the property.
@@ -1360,6 +1351,7 @@ public:
   }
 
   void Quiet() { this->ReportError = false; }
+
 private:
   cmMakefile* Makefile;
   cmGlobalGenerator* GG;
@@ -1521,6 +1513,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
       case cmPolicies::REQUIRED_IF_USED:
       case cmPolicies::REQUIRED_ALWAYS:
         e << "\n" << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0014);
+        CM_FALLTHROUGH;
       case cmPolicies::NEW:
         // NEW behavior prints the error.
         this->IssueMessage(cmake::FATAL_ERROR, e.str());
@@ -1906,7 +1899,7 @@ cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput(
         out = *o;
         std::string::size_type pos = out.rfind(name);
         // If the output matches exactly
-        if (pos != out.npos && pos == out.size() - name.size() &&
+        if (pos != std::string::npos && pos == out.size() - name.size() &&
             (pos == 0 || out[pos - 1] == '/')) {
           return *i;
         }
@@ -2155,6 +2148,12 @@ bool cmMakefile::IsSet(const std::string& name) const
 
 bool cmMakefile::PlatformIs32Bit() const
 {
+  if (const char* plat_abi =
+        this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) {
+    if (strcmp(plat_abi, "ELF X32") == 0) {
+      return false;
+    }
+  }
   if (const char* sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) {
     return atoi(sizeof_dptr) == 4;
   }
@@ -2169,6 +2168,17 @@ bool cmMakefile::PlatformIs64Bit() const
   return false;
 }
 
+bool cmMakefile::PlatformIsx32() const
+{
+  if (const char* plat_abi =
+        this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) {
+    if (strcmp(plat_abi, "ELF X32") == 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
 bool cmMakefile::PlatformIsAppleIos() const
 {
   std::string sdkRoot;
@@ -2333,6 +2343,7 @@ const char* cmMakefile::ExpandVariablesInString(
         newErrorstr, newResult, escapeQuotes, noEscapes, atOnly, filename,
         line, removeEmpty, replaceAt);
       this->SuppressWatches = false;
+      CM_FALLTHROUGH;
     }
     case cmPolicies::OLD:
       mtype =
@@ -2402,7 +2413,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
   bool removeEmpty, bool replaceAt) const
 {
   // Fast path strings without any special characters.
-  if (source.find_first_of("$@\\") == source.npos) {
+  if (source.find_first_of("$@\\") == std::string::npos) {
     return cmake::LOG;
   }
 
@@ -2489,6 +2500,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
       switch (this->GetPolicyStatus(cmPolicies::CMP0010)) {
         case cmPolicies::WARN:
           error << "\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0010);
+          CM_FALLTHROUGH;
         case cmPolicies::OLD:
           // OLD behavior is to just warn and continue.
           mtype = cmake::AUTHOR_WARNING;
@@ -2642,6 +2654,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
           }
           break;
         }
+        CM_FALLTHROUGH;
       case '\\':
         if (!noEscapes) {
           const char* next = in + 1;
@@ -3111,6 +3124,18 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName,
   return this->CreateSource(sourceName, generated);
 }
 
+void cmMakefile::AddTargetObject(std::string const& tgtName,
+                                 std::string const& objFile)
+{
+  cmSourceFile* sf = this->GetOrCreateSource(objFile, true);
+  sf->SetObjectLibrary(tgtName);
+  sf->SetProperty("EXTERNAL_OBJECT", "1");
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  this->SourceGroups[this->ObjectLibrariesSourceGroupIndex].AddGroupFile(
+    sf->GetFullPath());
+#endif
+}
+
 void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
                                 bool optional)
 {
@@ -3124,7 +3149,7 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
   langs.reserve(lang.size());
   for (std::vector<std::string>::const_iterator i = lang.begin();
        i != lang.end(); ++i) {
-    if (i->compare("RC") == 0) {
+    if (*i == "RC") {
       langsRC.push_back(*i);
     } else {
       langs.push_back(*i);
@@ -3153,13 +3178,12 @@ int cmMakefile::TryCompile(const std::string& srcdir,
 
   // change to the tests directory and run cmake
   // use the cmake object instead of calling cmake
-  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
-  cmSystemTools::ChangeDirectory(bindir);
+  cmWorkingDirectory workdir(bindir);
 
   // 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 cm(cmake::RoleProject);
   cm.SetIsInTryCompile(true);
   cmGlobalGenerator* gg =
     cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName());
@@ -3168,8 +3192,6 @@ int cmMakefile::TryCompile(const std::string& srcdir,
                          this->GetGlobalGenerator()->GetName() +
                          "' could not be created.");
     cmSystemTools::SetFatalErrorOccured();
-    // return to the original directory
-    cmSystemTools::ChangeDirectory(cwd);
     this->IsSourceFileTryCompile = false;
     return 1;
   }
@@ -3233,8 +3255,6 @@ int cmMakefile::TryCompile(const std::string& srcdir,
     this->IssueMessage(cmake::FATAL_ERROR,
                        "Failed to configure test project build system.");
     cmSystemTools::SetFatalErrorOccured();
-    // return to the original directory
-    cmSystemTools::ChangeDirectory(cwd);
     this->IsSourceFileTryCompile = false;
     return 1;
   }
@@ -3243,8 +3263,6 @@ int cmMakefile::TryCompile(const std::string& srcdir,
     this->IssueMessage(cmake::FATAL_ERROR,
                        "Failed to generate test project build system.");
     cmSystemTools::SetFatalErrorOccured();
-    // return to the original directory
-    cmSystemTools::ChangeDirectory(cwd);
     this->IsSourceFileTryCompile = false;
     return 1;
   }
@@ -3253,7 +3271,6 @@ int cmMakefile::TryCompile(const std::string& srcdir,
   int ret = this->GetGlobalGenerator()->TryCompile(
     srcdir, bindir, projectName, targetName, fast, output, this);
 
-  cmSystemTools::ChangeDirectory(cwd);
   this->IsSourceFileTryCompile = false;
   return ret;
 }
@@ -3375,7 +3392,7 @@ std::string cmMakefile::GetModulesFile(const char* filename) const
           /* clang-format on */
 
           this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
-          // break;  // fall through to OLD behaviour
+          CM_FALLTHROUGH;
         }
         case cmPolicies::OLD:
           result = moduleInCMakeModulePath;
@@ -3452,7 +3469,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output,
 
 int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
                               bool copyonly, bool atOnly, bool escapeQuotes,
-                              const cmNewLineStyle& newLine)
+                              cmNewLineStyle newLine)
 {
   int res = 1;
   if (!this->CanIWriteThisFile(outfile)) {
@@ -3768,6 +3785,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg,
       case cmPolicies::WARN:
         this->IssueMessage(cmake::AUTHOR_WARNING,
                            cmPolicies::GetPolicyWarning(cmPolicies::CMP0002));
+        CM_FALLTHROUGH;
       case cmPolicies::OLD:
         return true;
       case cmPolicies::REQUIRED_IF_USED:
@@ -3853,12 +3871,14 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath,
         << "compatibility.";
       /* clang-format on */
       this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+      CM_FALLTHROUGH;
     case cmPolicies::OLD:
       // OLD behavior does not warn.
       return true;
     case cmPolicies::REQUIRED_IF_USED:
     case cmPolicies::REQUIRED_ALWAYS:
       e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0013) << "\n";
+      CM_FALLTHROUGH;
     case cmPolicies::NEW:
       // NEW behavior prints the error.
       /* clang-format off */
@@ -3981,6 +4001,13 @@ 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::CMP0036) {
+    this->IssueMessage(cmake::DEPRECATION_WARNING,
+                       cmPolicies::GetPolicyDeprecatedWarning(id));
+  }
+
   this->StateSnapshot.SetPolicy(id, status);
   return true;
 }
@@ -4163,6 +4190,23 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
 const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang,
                                                  std::string* error) const
 {
+  if (!this->GlobalGenerator->GetLanguageEnabled(lang)) {
+    std::ostringstream e;
+    if (error) {
+      e << "cannot";
+    } else {
+      e << "Cannot";
+    }
+    e << " use features from non-enabled language " << lang;
+    if (error) {
+      *error = e.str();
+    } else {
+      this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+                                             this->Backtrace);
+    }
+    return CM_NULLPTR;
+  }
+
   const char* featuresKnown =
     this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES");
 
@@ -4174,9 +4218,9 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang,
       e << "No";
     }
     e << " known features for " << lang << " compiler\n\""
-      << this->GetDefinition("CMAKE_" + lang + "_COMPILER_ID")
+      << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID")
       << "\"\nversion "
-      << this->GetDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << ".";
+      << this->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << ".";
     if (error) {
       *error = e.str();
     } else {
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 9d9e90a..e65ba46 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -3,12 +3,14 @@
 #ifndef cmMakefile_h
 #define cmMakefile_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
+#include <deque>
 #include <map>
 #include <set>
 #include <stack>
+#include <stddef.h>
 #include <string>
 #include <vector>
 
@@ -53,6 +55,8 @@ class cmVariableWatch;
  */
 class cmMakefile
 {
+  CM_DISABLE_COPY(cmMakefile)
+
 public:
   /* Mark a variable as used */
   void MarkVariableAsUsed(const std::string& var);
@@ -119,6 +123,13 @@ public:
    */
   void FinalPass();
 
+  /** How to handle custom commands for object libraries */
+  enum ObjectLibraryCommands
+  {
+    RejectObjectLibraryCommands,
+    AcceptObjectLibraryCommands
+  };
+
   /** Add a custom command to the build.  */
   void AddCustomCommandToTarget(
     const std::string& target, const std::vector<std::string>& byproducts,
@@ -126,7 +137,8 @@ public:
     const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
     const char* comment, const char* workingDir, bool escapeOldStyle = true,
     bool uses_terminal = false, const std::string& depfile = "",
-    bool command_expand_lists = false);
+    bool command_expand_lists = false,
+    ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands);
   cmSourceFile* AddCustomCommandToOutput(
     const std::vector<std::string>& outputs,
     const std::vector<std::string>& byproducts,
@@ -398,6 +410,8 @@ public:
   cmSourceFile* GetOrCreateSource(const std::string& sourceName,
                                   bool generated = false);
 
+  void AddTargetObject(std::string const& tgtName, std::string const& objFile);
+
   /**
    * Given a variable name, return its value (as a string).
    * If the variable is not found in this makefile instance, the
@@ -428,6 +442,8 @@ public:
 
   /** Return whether the target platform is 64-bit.  */
   bool PlatformIs64Bit() const;
+  /** Return whether the target platform is x32.  */
+  bool PlatformIsx32() const;
 
   /** Return whether the target platform is Apple iOS.  */
   bool PlatformIsAppleIos() const;
@@ -532,7 +548,7 @@ public:
    */
   int ConfigureFile(const char* infile, const char* outfile, bool copyonly,
                     bool atOnly, bool escapeQuotes,
-                    const cmNewLineStyle& = cmNewLineStyle());
+                    cmNewLineStyle = cmNewLineStyle());
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   /**
@@ -696,6 +712,7 @@ public:
   /** Helper class to push and pop scopes automatically.  */
   class ScopePushPop
   {
+    CM_DISABLE_COPY(ScopePushPop)
   public:
     ScopePushPop(cmMakefile* m)
       : Makefile(m)
@@ -770,6 +787,10 @@ public:
   void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen);
   void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen);
 
+  // Maintain a stack of pacakge names to determine the depth of find modules
+  // we are currently being called with
+  std::deque<std::string> FindPackageModuleStack;
+
 protected:
   // add link libraries and directories to the target
   void AddGlobalLinkInformation(cmTarget& target);
@@ -807,6 +828,7 @@ protected:
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   std::vector<cmSourceGroup> SourceGroups;
+  size_t ObjectLibrariesSourceGroupIndex;
 #endif
 
   std::vector<cmCommand*> FinalPassCommands;
@@ -815,9 +837,6 @@ protected:
                          cmExecutionStatus& status);
 
 private:
-  cmMakefile(const cmMakefile& mf);
-  cmMakefile& operator=(const cmMakefile& mf);
-
   cmStateSnapshot StateSnapshot;
   cmListFileBacktrace Backtrace;
 
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index b76ddeb..359b9fd 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMakefileExecutableTargetGenerator.h"
 
+#include <algorithm>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -20,6 +21,7 @@
 #include "cmState.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cm_auto_ptr.hxx"
 #include "cmake.h"
@@ -120,7 +122,11 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
     std::string buildEcho = "Linking ";
     buildEcho += linkLanguage;
     buildEcho += " device code ";
-    buildEcho += targetOutputReal;
+    buildEcho += this->LocalGenerator->ConvertToOutputFormat(
+      this->LocalGenerator->MaybeConvertToRelativePath(
+        this->LocalGenerator->GetCurrentBinaryDirectory(),
+        this->DeviceLinkObject),
+      cmOutputConverter::SHELL);
     this->LocalGenerator->AppendEcho(
       commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
   }
@@ -144,7 +150,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
                                       linkLanguage, *this->GeneratorTarget));
 
   // Add language feature flags.
-  this->AddFeatureFlags(flags, linkLanguage);
+  this->LocalGenerator->AddLanguageFlagsForLinking(
+    flags, this->GeneratorTarget, linkLanguage, this->ConfigName);
 
   this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget,
                                              linkLanguage, this->ConfigName);
@@ -331,7 +338,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   } else {
     cmSystemTools::MakeDirectory(outpath.c_str());
     if (!targetNameImport.empty()) {
-      outpathImp = this->GeneratorTarget->GetDirectory(this->ConfigName, true);
+      outpathImp = this->GeneratorTarget->GetDirectory(
+        this->ConfigName, cmStateEnums::ImportLibraryArtifact);
       cmSystemTools::MakeDirectory(outpathImp.c_str());
       outpathImp += "/";
     }
@@ -426,7 +434,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   }
 
   // Add language feature flags.
-  this->AddFeatureFlags(flags, linkLanguage);
+  this->LocalGenerator->AddLanguageFlagsForLinking(
+    flags, this->GeneratorTarget, linkLanguage, this->ConfigName);
 
   this->LocalGenerator->AddArchitectureFlags(flags, this->GeneratorTarget,
                                              linkLanguage, this->ConfigName);
@@ -448,6 +457,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags);
   }
 
+  this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget,
+                                             this->ConfigName, linkLanguage);
+
   // Construct a list of files associated with this executable that
   // may need to be cleaned.
   std::vector<std::string> exeCleanFiles;
@@ -555,10 +567,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     }
 
     // maybe create .def file from list of objects
-    if (this->GeneratorTarget->IsExecutableWithExports() &&
-        this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      this->GenDefFile(real_link_commands, linkFlags);
-    }
+    this->GenDefFile(real_link_commands);
 
     std::string manifests = this->GetManifests();
 
diff --git a/Source/cmMakefileExecutableTargetGenerator.h b/Source/cmMakefileExecutableTargetGenerator.h
index 642182b..01aa627 100644
--- a/Source/cmMakefileExecutableTargetGenerator.h
+++ b/Source/cmMakefileExecutableTargetGenerator.h
@@ -3,7 +3,9 @@
 #ifndef cmMakefileExecutableTargetGenerator_h
 #define cmMakefileExecutableTargetGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
+#include <string>
 
 #include "cmMakefileTargetGenerator.h"
 
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index ff8b604..3d1594b 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -2,8 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmMakefileLibraryTargetGenerator.h"
 
-#include <cmConfigure.h> // IWYU pragma: keep
-
+#include <algorithm>
 #include <sstream>
 #include <vector>
 
@@ -128,16 +127,29 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
 
 void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
 {
+  const std::string cuda_lang("CUDA");
+  cmGeneratorTarget::LinkClosure const* closure =
+    this->GeneratorTarget->GetLinkClosure(this->ConfigName);
+
+  const bool hasCUDA =
+    (std::find(closure->Languages.begin(), closure->Languages.end(),
+               cuda_lang) != closure->Languages.end());
+
+  const bool resolveDeviceSymbols =
+    this->GeneratorTarget->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
+  if (hasCUDA && resolveDeviceSymbols) {
+    std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
+    std::string extraFlags;
+    this->LocalGenerator->AppendFlags(
+      extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
+    this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, false);
+  }
+
   std::string linkLanguage =
     this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
-  std::string linkRuleVar = "CMAKE_";
-  linkRuleVar += linkLanguage;
-  linkRuleVar += "_CREATE_STATIC_LIBRARY";
 
-  if (this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION") &&
-      this->Makefile->GetDefinition(linkRuleVar + "_IPO")) {
-    linkRuleVar += "_IPO";
-  }
+  std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable(
+    linkLanguage, this->ConfigName);
 
   std::string extraFlags;
   this->LocalGenerator->GetStaticLibraryFlags(
@@ -298,8 +310,12 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
     cmLocalUnixMakefileGenerator3::EchoProgress progress;
     this->MakeEchoProgress(progress);
     // Add the link message.
-    std::string buildEcho = "Linking " + linkLanguage + " device code";
-    buildEcho += targetOutputReal;
+    std::string buildEcho = "Linking " + linkLanguage + " device code ";
+    buildEcho += this->LocalGenerator->ConvertToOutputFormat(
+      this->LocalGenerator->MaybeConvertToRelativePath(
+        this->LocalGenerator->GetCurrentBinaryDirectory(),
+        this->DeviceLinkObject),
+      cmOutputConverter::SHELL);
     this->LocalGenerator->AppendEcho(
       commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
   }
@@ -379,9 +395,10 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
     vars.LinkFlags = linkFlags.c_str();
     vars.TargetCompilePDB = targetOutPathCompilePDB.c_str();
 
-    // Add language feature flags.
+    // Add language-specific flags.
     std::string langFlags;
-    this->AddFeatureFlags(langFlags, linkLanguage);
+    this->LocalGenerator->AddLanguageFlagsForLinking(
+      langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName);
 
     vars.LanguageCompileFlags = langFlags.c_str();
 
@@ -477,6 +494,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
   // Create set of linking flags.
   std::string linkFlags;
   this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
+  this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget,
+                                             this->ConfigName, linkLanguage);
 
   // Add OSX version flags, if any.
   if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
@@ -520,7 +539,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     cmSystemTools::MakeDirectory(outpath.c_str());
     outpath += "/";
     if (!targetNameImport.empty()) {
-      outpathImp = this->GeneratorTarget->GetDirectory(this->ConfigName, true);
+      outpathImp = this->GeneratorTarget->GetDirectory(
+        this->ConfigName, cmStateEnums::ImportLibraryArtifact);
       cmSystemTools::MakeDirectory(outpathImp.c_str());
       outpathImp += "/";
     }
@@ -677,18 +697,30 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     std::string arCreateVar = "CMAKE_";
     arCreateVar += linkLanguage;
     arCreateVar += "_ARCHIVE_CREATE";
+
+    arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+      arCreateVar, linkLanguage, this->ConfigName);
+
     if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) {
       cmSystemTools::ExpandListArgument(rule, archiveCreateCommands);
     }
     std::string arAppendVar = "CMAKE_";
     arAppendVar += linkLanguage;
     arAppendVar += "_ARCHIVE_APPEND";
+
+    arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+      arAppendVar, linkLanguage, this->ConfigName);
+
     if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) {
       cmSystemTools::ExpandListArgument(rule, archiveAppendCommands);
     }
     std::string arFinishVar = "CMAKE_";
     arFinishVar += linkLanguage;
     arFinishVar += "_ARCHIVE_FINISH";
+
+    arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+      arFinishVar, linkLanguage, this->ConfigName);
+
     if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) {
       cmSystemTools::ExpandListArgument(rule, archiveFinishCommands);
     }
@@ -751,10 +783,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     }
 
     // maybe create .def file from list of objects
-    if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY &&
-        this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      this->GenDefFile(real_link_commands, linkFlags);
-    }
+    this->GenDefFile(real_link_commands);
 
     std::string manifests = this->GetManifests();
 
@@ -827,9 +856,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       }
     }
 
-    // Add language feature flags.
+    // Add language-specific flags.
     std::string langFlags;
-    this->AddFeatureFlags(langFlags, linkLanguage);
+    this->LocalGenerator->AddLanguageFlagsForLinking(
+      langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName);
 
     this->LocalGenerator->AddArchitectureFlags(
       langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName);
@@ -853,6 +883,16 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       std::vector<std::string> object_strings;
       this->WriteObjectsStrings(object_strings, archiveCommandLimit);
 
+      // Add the cuda device object to the list of archive files. This will
+      // only occur on archives which have CUDA_RESOLVE_DEVICE_SYMBOLS enabled
+      if (!this->DeviceLinkObject.empty()) {
+        object_strings.push_back(this->LocalGenerator->ConvertToOutputFormat(
+          this->LocalGenerator->MaybeConvertToRelativePath(
+            this->LocalGenerator->GetCurrentBinaryDirectory(),
+            this->DeviceLinkObject),
+          cmOutputConverter::SHELL));
+      }
+
       // Create the archive with the first set of objects.
       std::vector<std::string>::iterator osi = object_strings.begin();
       {
diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h
index 93ce902..da1d8b6 100644
--- a/Source/cmMakefileLibraryTargetGenerator.h
+++ b/Source/cmMakefileLibraryTargetGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmMakefileLibraryTargetGenerator_h
 #define cmMakefileLibraryTargetGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmMakefileTargetGenerator.h"
 
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 54b3f36..a4511b6 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -30,10 +30,6 @@
 #include "cm_auto_ptr.hxx"
 #include "cmake.h"
 
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
 cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
   : cmCommonTargetGenerator(target)
   , OSXBundleGenerator(CM_NULLPTR)
@@ -509,8 +505,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
         this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
         this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
         this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
-      targetFullPathReal =
-        this->GeneratorTarget->GetFullPath(this->ConfigName, false, true);
+      targetFullPathReal = this->GeneratorTarget->GetFullPath(
+        this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true);
       targetFullPathPDB =
         this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
       targetFullPathPDB += "/";
@@ -593,6 +589,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
       if (this->GeneratorTarget->GetPropertyAsBool(
             "CUDA_SEPARABLE_COMPILATION")) {
         cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+      } else if (this->GeneratorTarget->GetPropertyAsBool(
+                   "CUDA_PTX_COMPILATION")) {
+        cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
       } else {
         cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
       }
@@ -1256,7 +1255,7 @@ class cmMakefileTargetGeneratorObjectStrings
 public:
   cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
                                          cmOutputConverter* outputConverter,
-                                         cmStateDirectory stateDir,
+                                         cmStateDirectory const& stateDir,
                                          std::string::size_type limit)
     : Strings(strings)
     , OutputConverter(outputConverter)
@@ -1288,6 +1287,7 @@ public:
     this->CurrentString += this->NextObject;
   }
   void Done() { this->Strings.push_back(this->CurrentString); }
+
 private:
   std::string MaybeConvertToRelativePath(std::string const& obj)
   {
@@ -1414,8 +1414,14 @@ void cmMakefileTargetGenerator::AppendLinkDepends(
   this->AppendTargetDepends(depends);
 
   // Add a dependency on the link definitions file, if any.
-  if (this->ModuleDefinitionFile) {
-    depends.push_back(this->ModuleDefinitionFile->GetFullPath());
+  if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+        this->GeneratorTarget->GetModuleDefinitionInfo(
+          this->GetConfigName())) {
+    for (std::vector<cmSourceFile const*>::const_iterator i =
+           mdi->Sources.begin();
+         i != mdi->Sources.end(); ++i) {
+      depends.push_back((*i)->GetFullPath());
+    }
   }
 
   // Add a dependency on user-specified manifest files, if any.
@@ -1486,15 +1492,6 @@ void cmMakefileTargetGenerator::CreateLinkScript(
   makefile_depends.push_back(linkScriptName);
 }
 
-static size_t calculateCommandLineLengthLimit()
-{
-#if defined(_SC_ARG_MAX)
-  return ((size_t)sysconf(_SC_ARG_MAX)) - 1000;
-#else
-  return 0;
-#endif
-}
-
 bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
   std::string const& l) const
 {
@@ -1508,7 +1505,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
   }
 
   // Check for a system limit.
-  if (size_t const limit = calculateCommandLineLengthLimit()) {
+  if (size_t const limit = cmSystemTools::CalculateCommandLineLengthLimit()) {
     // Compute the total length of our list of object files with room
     // for argument separation and quoting.  This does not convert paths
     // relative to CMAKE_CURRENT_BINARY_DIR like the final list will be, so the
@@ -1577,7 +1574,7 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
 }
 
 cmLinkLineComputer* cmMakefileTargetGenerator::CreateLinkLineComputer(
-  cmOutputConverter* outputConverter, cmStateDirectory stateDir)
+  cmOutputConverter* outputConverter, cmStateDirectory const& stateDir)
 {
   if (this->Makefile->IsOn("MSVC60")) {
     return this->GlobalGenerator->CreateMSVC60LinkLineComputer(outputConverter,
@@ -1600,7 +1597,8 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
                                             frameworkPath, linkPath);
   linkLibs = frameworkPath + linkPath + linkLibs;
 
-  if (useResponseFile && linkLibs.find_first_not_of(' ') != linkLibs.npos) {
+  if (useResponseFile &&
+      linkLibs.find_first_not_of(' ') != std::string::npos) {
     // Lookup the response file reference flag.
     std::string responseFlagVar = "CMAKE_";
     responseFlagVar +=
@@ -1718,31 +1716,32 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
 }
 
 void cmMakefileTargetGenerator::GenDefFile(
-  std::vector<std::string>& real_link_commands, std::string& linkFlags)
+  std::vector<std::string>& real_link_commands)
 {
-  if (this->GeneratorTarget->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    std::string name_of_def_file =
-      this->GeneratorTarget->GetSupportDirectory();
-    name_of_def_file += std::string("/") + this->GeneratorTarget->GetName();
-    name_of_def_file += ".def";
-    std::string cmd = cmSystemTools::GetCMakeCommand();
-    cmd = this->LocalGenerator->ConvertToOutputFormat(
-      cmd, cmOutputConverter::SHELL);
-    cmd += " -E __create_def ";
-    cmd += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file),
-      cmOutputConverter::SHELL);
-    cmd += " ";
-    std::string objlist_file = name_of_def_file;
-    objlist_file += ".objs";
-    cmd += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
-      cmOutputConverter::SHELL);
-    real_link_commands.insert(real_link_commands.begin(), cmd);
-    // create a list of obj files for the -E __create_def to read
-    cmGeneratedFileStream fout(objlist_file.c_str());
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    this->GeneratorTarget->GetModuleDefinitionInfo(this->GetConfigName());
+  if (!mdi || !mdi->DefFileGenerated) {
+    return;
+  }
+  std::string cmd = cmSystemTools::GetCMakeCommand();
+  cmd =
+    this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL);
+  cmd += " -E __create_def ";
+  cmd += this->LocalGenerator->ConvertToOutputFormat(
+    this->LocalGenerator->MaybeConvertToRelativePath(
+      this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile),
+    cmOutputConverter::SHELL);
+  cmd += " ";
+  std::string objlist_file = mdi->DefFile + ".objs";
+  cmd += this->LocalGenerator->ConvertToOutputFormat(
+    this->LocalGenerator->MaybeConvertToRelativePath(
+      this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
+    cmOutputConverter::SHELL);
+  real_link_commands.insert(real_link_commands.begin(), cmd);
+  // create a list of obj files for the -E __create_def to read
+  cmGeneratedFileStream fout(objlist_file.c_str());
+
+  if (mdi->WindowsExportAllSymbols) {
     for (std::vector<std::string>::const_iterator i = this->Objects.begin();
          i != this->Objects.end(); ++i) {
       if (cmHasLiteralSuffix(*i, ".obj")) {
@@ -1754,13 +1753,11 @@ void cmMakefileTargetGenerator::GenDefFile(
          i != this->ExternalObjects.end(); ++i) {
       fout << *i << "\n";
     }
-    // now add the def file link flag
-    linkFlags += " ";
-    linkFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
-    linkFlags += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(), name_of_def_file),
-      cmOutputConverter::SHELL);
-    linkFlags += " ";
+  }
+
+  for (std::vector<cmSourceFile const*>::const_iterator i =
+         mdi->Sources.begin();
+       i != mdi->Sources.end(); ++i) {
+    fout << (*i)->GetFullPath() << "\n";
   }
 }
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index 347f9f2..92c9f60 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmMakefileTargetGenerator_h
 #define cmMakefileTargetGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <map>
@@ -143,7 +143,7 @@ protected:
                         std::vector<std::string>& makefile_depends);
 
   cmLinkLineComputer* CreateLinkLineComputer(
-    cmOutputConverter* outputConverter, cmStateDirectory stateDir);
+    cmOutputConverter* outputConverter, cmStateDirectory const& stateDir);
 
   /** Create a response file with the given set of options.  Returns
       the relative path from the target build working directory to the
@@ -166,8 +166,7 @@ protected:
                          bool useWatcomQuote);
 
   /** Add commands for generate def files */
-  void GenDefFile(std::vector<std::string>& real_link_commands,
-                  std::string& linkFlags);
+  void GenDefFile(std::vector<std::string>& real_link_commands);
 
   void AddIncludeFlags(std::string& flags,
                        const std::string& lang) CM_OVERRIDE;
diff --git a/Source/cmMakefileUtilityTargetGenerator.h b/Source/cmMakefileUtilityTargetGenerator.h
index 332c04e..8df5dd4 100644
--- a/Source/cmMakefileUtilityTargetGenerator.h
+++ b/Source/cmMakefileUtilityTargetGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmMakefileUtilityTargetGenerator_h
 #define cmMakefileUtilityTargetGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmMakefileTargetGenerator.h"
 
diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx
index b2f0d22..14fd96f 100644
--- a/Source/cmMarkAsAdvancedCommand.cxx
+++ b/Source/cmMarkAsAdvancedCommand.cxx
@@ -30,7 +30,7 @@ bool cmMarkAsAdvancedCommand::InitialPass(std::vector<std::string> const& args,
     i = 1;
   }
   for (; i < args.size(); ++i) {
-    std::string variable = args[i];
+    std::string const& variable = args[i];
     cmState* state = this->Makefile->GetState();
     if (!state->GetCacheEntryValue(variable)) {
       this->Makefile->GetCMakeInstance()->AddCacheEntry(
diff --git a/Source/cmMarkAsAdvancedCommand.h b/Source/cmMarkAsAdvancedCommand.h
index 26caa66..a7791a9 100644
--- a/Source/cmMarkAsAdvancedCommand.h
+++ b/Source/cmMarkAsAdvancedCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmMarkAsAdvancedCommand_h
 #define cmMarkAsAdvancedCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,19 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "mark_as_advanced"; }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   * mark_as_advanced() will have no effect in script mode, but this will
-   * make many of the modules usable in cmake/ctest scripts, (among them
-   * FindUnixMake.cmake used by the CTEST_BUILD command.
-  */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
 };
 
 #endif
diff --git a/Source/cmMathCommand.h b/Source/cmMathCommand.h
index 9b49b21..67dbdda 100644
--- a/Source/cmMathCommand.h
+++ b/Source/cmMathCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmMathCommand_h
 #define cmMathCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -27,16 +28,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "math"; }
-
 protected:
   bool HandleExprCommand(std::vector<std::string> const& args);
 };
diff --git a/Source/cmMessageCommand.h b/Source/cmMessageCommand.h
index a565635..96939e5 100644
--- a/Source/cmMessageCommand.h
+++ b/Source/cmMessageCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmMessageCommand_h
 #define cmMessageCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -29,16 +30,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "message"; }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
 };
 
 #endif
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index fe1c261..3ae5bc5 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -8,7 +8,7 @@
 #include "cmSystemTools.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
-#include <cmsys/SystemInformation.hxx>
+#include "cmsys/SystemInformation.hxx"
 #endif
 
 #include <sstream>
diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h
index 89f8efe..4aafbd4 100644
--- a/Source/cmMessenger.h
+++ b/Source/cmMessenger.h
@@ -3,7 +3,7 @@
 #ifndef cmMessenger_h
 #define cmMessenger_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmListFileCache.h"
 #include "cmake.h"
diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx
index 55451ff..5500eba 100644
--- a/Source/cmNewLineStyle.cxx
+++ b/Source/cmNewLineStyle.cxx
@@ -23,7 +23,7 @@ bool cmNewLineStyle::ReadFromArguments(const std::vector<std::string>& args,
     if (args[i] == "NEWLINE_STYLE") {
       size_t const styleIndex = i + 1;
       if (args.size() > styleIndex) {
-        const std::string eol = args[styleIndex];
+        std::string const& eol = args[styleIndex];
         if (eol == "LF" || eol == "UNIX") {
           NewLineStyle = LF;
           return true;
diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h
index b46414c..397cd2c 100644
--- a/Source/cmNewLineStyle.h
+++ b/Source/cmNewLineStyle.h
@@ -3,7 +3,7 @@
 #ifndef cmNewLineStyle_h
 #define cmNewLineStyle_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmNinjaLinkLineComputer.cxx b/Source/cmNinjaLinkLineComputer.cxx
index 2546b55..7fbeeea 100644
--- a/Source/cmNinjaLinkLineComputer.cxx
+++ b/Source/cmNinjaLinkLineComputer.cxx
@@ -4,12 +4,11 @@
 #include "cmNinjaLinkLineComputer.h"
 
 #include "cmGlobalNinjaGenerator.h"
-#include "cmStateDirectory.h"
 
 class cmOutputConverter;
 
 cmNinjaLinkLineComputer::cmNinjaLinkLineComputer(
-  cmOutputConverter* outputConverter, cmStateDirectory stateDir,
+  cmOutputConverter* outputConverter, cmStateDirectory const& stateDir,
   cmGlobalNinjaGenerator const* gg)
   : cmLinkLineComputer(outputConverter, stateDir)
   , GG(gg)
diff --git a/Source/cmNinjaLinkLineComputer.h b/Source/cmNinjaLinkLineComputer.h
index ff0771b..13f05a8 100644
--- a/Source/cmNinjaLinkLineComputer.h
+++ b/Source/cmNinjaLinkLineComputer.h
@@ -4,7 +4,7 @@
 #ifndef cmNinjaLinkLineComputer_h
 #define cmNinjaLinkLineComputer_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <string>
 
@@ -16,9 +16,11 @@ class cmStateDirectory;
 
 class cmNinjaLinkLineComputer : public cmLinkLineComputer
 {
+  CM_DISABLE_COPY(cmNinjaLinkLineComputer)
+
 public:
   cmNinjaLinkLineComputer(cmOutputConverter* outputConverter,
-                          cmStateDirectory stateDir,
+                          cmStateDirectory const& stateDir,
                           cmGlobalNinjaGenerator const* gg);
 
   std::string ConvertToLinkReference(std::string const& input) const
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index b1374c2..14a4ef8 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -5,11 +5,9 @@
 #include <algorithm>
 #include <assert.h>
 #include <iterator>
-#include <limits>
 #include <map>
 #include <set>
 #include <sstream>
-#include <stddef.h>
 
 #include "cmAlgorithms.h"
 #include "cmCustomCommand.h"
@@ -35,10 +33,6 @@
 #include "cm_auto_ptr.hxx"
 #include "cmake.h"
 
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
 cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
   cmGeneratorTarget* target)
   : cmNinjaTargetGenerator(target)
@@ -260,12 +254,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
       rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
                                                    *i, vars);
     }
-    {
-      // If there is no ranlib the command will be ":".  Skip it.
-      std::vector<std::string>::iterator newEnd = std::remove_if(
-        linkCmds.begin(), linkCmds.end(), cmNinjaRemoveNoOpCommands());
-      linkCmds.erase(newEnd, linkCmds.end());
-    }
+
+    // If there is no ranlib the command will be ":".  Skip it.
+    cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands());
 
     std::string linkCmd =
       this->GetLocalGenerator()->BuildCommandLine(linkCmds);
@@ -388,12 +379,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
       rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
                                                    *i, vars);
     }
-    {
-      // If there is no ranlib the command will be ":".  Skip it.
-      std::vector<std::string>::iterator newEnd = std::remove_if(
-        linkCmds.begin(), linkCmds.end(), cmNinjaRemoveNoOpCommands());
-      linkCmds.erase(newEnd, linkCmds.end());
-    }
+
+    // If there is no ranlib the command will be ":".  Skip it.
+    cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands());
 
     linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
     linkCmds.push_back("$POST_BUILD");
@@ -459,6 +447,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd()
   // an executable or a dynamic library.
   std::string linkCmd;
   switch (this->GetGeneratorTarget()->GetType()) {
+    case cmStateEnums::STATIC_LIBRARY:
     case cmStateEnums::SHARED_LIBRARY:
     case cmStateEnums::MODULE_LIBRARY: {
       const std::string cudaLinkCmd(
@@ -497,10 +486,9 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
         cmGeneratorTarget& gt = *this->GetGeneratorTarget();
         const std::string cfgName = this->GetConfigName();
         std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName));
-        std::string targetOutputReal =
-          this->ConvertToNinjaPath(gt.GetFullPath(cfgName,
-                                                  /*implib=*/false,
-                                                  /*realname=*/true));
+        std::string targetOutputReal = this->ConvertToNinjaPath(
+          gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
+                         /*realname=*/true));
         cmakeCommand += targetOutputReal;
         cmakeCommand += " || true";
         linkCmds.push_back(cmakeCommand);
@@ -522,6 +510,10 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
         std::string linkCmdVar = "CMAKE_";
         linkCmdVar += this->TargetLinkLanguage;
         linkCmdVar += "_ARCHIVE_CREATE";
+
+        linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+          linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
+
         const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
         cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
       }
@@ -529,6 +521,10 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
         std::string linkCmdVar = "CMAKE_";
         linkCmdVar += this->TargetLinkLanguage;
         linkCmdVar += "_ARCHIVE_FINISH";
+
+        linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
+          linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
+
         const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
         cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
       }
@@ -544,36 +540,6 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
   return std::vector<std::string>();
 }
 
-static int calculateCommandLineLengthLimit(int linkRuleLength)
-{
-  static int const limits[] = {
-#ifdef _WIN32
-    8000,
-#endif
-#if defined(__linux)
-    // #define MAX_ARG_STRLEN (PAGE_SIZE * 32) in Linux's binfmts.h
-    ((int)sysconf(_SC_PAGESIZE) * 32) - 1000,
-#endif
-    std::numeric_limits<int>::max()
-  };
-
-  size_t const arrSz = cmArraySize(limits);
-  int sz = *std::min_element(limits, limits + arrSz);
-#if defined(_SC_ARG_MAX)
-  // for instance ARG_MAX is 2096152 on Ubuntu or 262144 on Mac
-  int const szArgMax = static_cast<int>(sysconf(_SC_ARG_MAX));
-  // a return value of -1 signifies an unrestricted value
-  if (szArgMax != -1) {
-    sz = std::min(sz, szArgMax - 1000);
-  }
-#endif
-  if (sz == std::numeric_limits<int>::max()) {
-    return 0;
-  }
-
-  return sz - linkRuleLength;
-}
-
 void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
 {
   cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();
@@ -594,11 +560,15 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
     case cmStateEnums::EXECUTABLE:
       shouldHaveDeviceLinking = true;
       break;
+    case cmStateEnums::STATIC_LIBRARY:
+      shouldHaveDeviceLinking =
+        genTarget.GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
+      break;
     default:
       break;
   }
 
-  if (!shouldHaveDeviceLinking || !hasCUDA) {
+  if (!(shouldHaveDeviceLinking && hasCUDA)) {
     return;
   }
 
@@ -614,9 +584,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
   std::string const targetOutputReal = ConvertToNinjaPath(
     genTarget.ObjectDirectory + "cmake_device_link" + objExt);
 
-  std::string const targetOutputImplib =
-    ConvertToNinjaPath(genTarget.GetFullPath(cfgName,
-                                             /*implib=*/true));
+  std::string const targetOutputImplib = ConvertToNinjaPath(
+    genTarget.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
 
   this->DeviceLinkObject = targetOutputReal;
 
@@ -686,7 +655,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
     localGen.AddArchitectureFlags(t, &genTarget, cudaLinkLanguage, cfgName);
     vars["ARCH_FLAGS"] = t;
     t = "";
-    localGen.AddLanguageFlags(t, cudaLinkLanguage, cfgName);
+    localGen.AddLanguageFlagsForLinking(t, &genTarget, cudaLinkLanguage,
+                                        cfgName);
     vars["LANGUAGE_COMPILE_FLAGS"] = t;
   }
   if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
@@ -759,8 +729,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
 
   // Device linking currently doesn't support response files so
   // do not check if the user has explicitly forced a response file.
-  int const commandLineLengthLimit = calculateCommandLineLengthLimit(
-    globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule()));
+  int const commandLineLengthLimit =
+    static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
+    globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule());
 
   const std::string rspfile =
     std::string(cmake::GetCMakeFilesDirectoryPostSlash()) +
@@ -786,13 +757,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   cmGeneratorTarget& gt = *this->GetGeneratorTarget();
   const std::string cfgName = this->GetConfigName();
   std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName));
-  std::string targetOutputReal =
-    ConvertToNinjaPath(gt.GetFullPath(cfgName,
-                                      /*implib=*/false,
-                                      /*realname=*/true));
-  std::string targetOutputImplib =
-    ConvertToNinjaPath(gt.GetFullPath(cfgName,
-                                      /*implib=*/true));
+  std::string targetOutputReal = ConvertToNinjaPath(
+    gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
+                   /*realname=*/true));
+  std::string targetOutputImplib = ConvertToNinjaPath(
+    gt.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
 
   if (gt.IsAppBundleOnApple()) {
     // Create the app bundle
@@ -869,19 +838,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"],
     vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget);
 
-  if (this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
-      (gt.GetType() == cmStateEnums::SHARED_LIBRARY ||
-       gt.IsExecutableWithExports())) {
-    if (gt.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      std::string name_of_def_file = gt.GetSupportDirectory();
-      name_of_def_file += "/" + gt.GetName();
-      name_of_def_file += ".def ";
-      vars["LINK_FLAGS"] += " /DEF:";
-      vars["LINK_FLAGS"] += this->GetLocalGenerator()->ConvertToOutputFormat(
-        name_of_def_file, cmOutputConverter::SHELL);
-    }
-  }
-
   // Add OS X version flags, if any.
   if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
       this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
@@ -919,7 +875,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     vars["ARCH_FLAGS"] = t;
     t = "";
     t += lwyuFlags;
-    localGen.AddLanguageFlags(t, TargetLinkLanguage, cfgName);
+    localGen.AddLanguageFlagsForLinking(t, &genTarget, TargetLinkLanguage,
+                                        cfgName);
     vars["LANGUAGE_COMPILE_FLAGS"] = t;
   }
   if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
@@ -998,35 +955,39 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   }
 
   // maybe create .def file from list of objects
-  if ((gt.GetType() == cmStateEnums::SHARED_LIBRARY ||
-       gt.IsExecutableWithExports()) &&
-      this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (gt.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      std::string cmakeCommand =
-        this->GetLocalGenerator()->ConvertToOutputFormat(
-          cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
-      std::string name_of_def_file = gt.GetSupportDirectory();
-      name_of_def_file += "/" + gt.GetName();
-      name_of_def_file += ".def";
-      std::string cmd = cmakeCommand;
-      cmd += " -E __create_def ";
-      cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
-        name_of_def_file, cmOutputConverter::SHELL);
-      cmd += " ";
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    gt.GetModuleDefinitionInfo(this->GetConfigName());
+  if (mdi && mdi->DefFileGenerated) {
+    std::string cmakeCommand =
+      this->GetLocalGenerator()->ConvertToOutputFormat(
+        cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
+    std::string cmd = cmakeCommand;
+    cmd += " -E __create_def ";
+    cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
+      mdi->DefFile, cmOutputConverter::SHELL);
+    cmd += " ";
+    std::string obj_list_file = mdi->DefFile + ".objs";
+    cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
+      obj_list_file, cmOutputConverter::SHELL);
+    preLinkCmdLines.push_back(cmd);
+
+    // create a list of obj files for the -E __create_def to read
+    cmGeneratedFileStream fout(obj_list_file.c_str());
+
+    if (mdi->WindowsExportAllSymbols) {
       cmNinjaDeps objs = this->GetObjects();
-      std::string obj_list_file = name_of_def_file;
-      obj_list_file += ".objs";
-      cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
-        obj_list_file, cmOutputConverter::SHELL);
-      preLinkCmdLines.push_back(cmd);
-      // create a list of obj files for the -E __create_def to read
-      cmGeneratedFileStream fout(obj_list_file.c_str());
       for (cmNinjaDeps::iterator i = objs.begin(); i != objs.end(); ++i) {
         if (cmHasLiteralSuffix(*i, ".obj")) {
           fout << *i << "\n";
         }
       }
     }
+
+    for (std::vector<cmSourceFile const*>::const_iterator i =
+           mdi->Sources.begin();
+         i != mdi->Sources.end(); ++i) {
+      fout << (*i)->GetFullPath() << "\n";
+    }
   }
   // If we have any PRE_LINK commands, we need to go back to CMAKE_BINARY_DIR
   // for
@@ -1055,8 +1016,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     !(this->TargetLinkLanguage == "RC" || this->TargetLinkLanguage == "CUDA");
   int commandLineLengthLimit = -1;
   if (!lang_supports_response || !this->ForceResponseFile()) {
-    commandLineLengthLimit = calculateCommandLineLengthLimit(
-      globalGen.GetRuleCmdLength(this->LanguageLinkerRule()));
+    commandLineLengthLimit =
+      static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
+      globalGen.GetRuleCmdLength(this->LanguageLinkerRule());
   }
 
   const std::string rspfile =
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
index e5595ea..677b1c6 100644
--- a/Source/cmNinjaNormalTargetGenerator.h
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmNinjaNormalTargetGenerator_h
 #define cmNinjaNormalTargetGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmNinjaTargetGenerator.h"
 
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index d57b8f7..d38dbcb 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -2,10 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmNinjaTargetGenerator.h"
 
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
 #include <algorithm>
 #include <assert.h>
-#include <cm_jsoncpp_value.h>
-#include <cm_jsoncpp_writer.h>
 #include <iterator>
 #include <map>
 #include <sstream>
@@ -117,7 +117,7 @@ bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const
 
 std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget()
 {
-  return "cmake_order_depends_target_" + this->GetTargetName();
+  return "cmake_object_order_depends_target_" + this->GetTargetName();
 }
 
 // TODO: Most of the code is picked up from
@@ -212,9 +212,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
   std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
 
   // Add a dependency on the link definitions file, if any.
-  if (this->ModuleDefinitionFile) {
-    result.push_back(
-      this->ConvertToNinjaPath(this->ModuleDefinitionFile->GetFullPath()));
+  if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+        this->GeneratorTarget->GetModuleDefinitionInfo(
+          this->GetConfigName())) {
+    for (std::vector<cmSourceFile const*>::const_iterator i =
+           mdi->Sources.begin();
+         i != mdi->Sources.end(); ++i) {
+      result.push_back(this->ConvertToNinjaPath((*i)->GetFullPath()));
+    }
   }
 
   // Add a dependency on user-specified manifest files, if any.
@@ -552,13 +557,26 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     // Write the rule for ninja dyndep file generation.
     std::vector<std::string> ddCmds;
 
+#ifdef _WIN32
+    // Windows command line length is limited -> use response file for dyndep
+    // rules
+    std::string ddRspFile = "$out.rsp";
+    std::string ddRspContent = "$in";
+    std::string ddInput = "@" + ddRspFile;
+#else
+    std::string ddRspFile;
+    std::string ddRspContent;
+    std::string ddInput = "$in";
+#endif
+
     // Run CMake dependency scanner on preprocessed output.
     std::string const cmake = this->GetLocalGenerator()->ConvertToOutputFormat(
       cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
     ddCmds.push_back(cmake + " -E cmake_ninja_dyndep"
                              " --tdi=" +
                      tdi + " --dd=$out"
-                           " $in");
+                           " " +
+                     ddInput);
 
     std::string const ddCmdLine =
       this->GetLocalGenerator()->BuildCommandLine(ddCmds);
@@ -570,9 +588,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     this->GetGlobalGenerator()->AddRule(
       this->LanguageDyndepRule(lang), ddCmdLine, ddDesc.str(), ddComment.str(),
       /*depfile*/ "",
-      /*deps*/ "",
-      /*rspfile*/ "",
-      /*rspcontent*/ "",
+      /*deps*/ "", ddRspFile, ddRspContent,
       /*restat*/ "",
       /*generator*/ false);
   }
@@ -584,6 +600,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     if (this->GeneratorTarget->GetPropertyAsBool(
           "CUDA_SEPARABLE_COMPILATION")) {
       cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+    } else if (this->GeneratorTarget->GetPropertyAsBool(
+                 "CUDA_PTX_COMPILATION")) {
+      cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
     } else {
       cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
     }
@@ -710,8 +729,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
   }
 
   cmNinjaDeps orderOnlyDeps;
-  this->GetLocalGenerator()->AppendTargetDepends(this->GeneratorTarget,
-                                                 orderOnlyDeps);
+  this->GetLocalGenerator()->AppendTargetDepends(
+    this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering);
 
   // Add order-only dependencies on other files associated with the target.
   orderOnlyDeps.insert(orderOnlyDeps.end(), this->ExtraFiles.begin(),
@@ -732,7 +751,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
                    std::back_inserter(orderOnlyDeps), MapToNinjaPath());
   }
 
-  if (!orderOnlyDeps.empty()) {
+  std::sort(orderOnlyDeps.begin(), orderOnlyDeps.end());
+  orderOnlyDeps.erase(std::unique(orderOnlyDeps.begin(), orderOnlyDeps.end()),
+                      orderOnlyDeps.end());
+
+  {
     cmNinjaDeps orderOnlyTarget;
     orderOnlyTarget.push_back(this->OrderDependsTargetForTarget());
     this->GetGlobalGenerator()->WritePhonyBuild(
@@ -745,7 +768,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
   for (std::vector<cmSourceFile const*>::const_iterator si =
          objectSources.begin();
        si != objectSources.end(); ++si) {
-    this->WriteObjectBuildStatement(*si, !orderOnlyDeps.empty());
+    this->WriteObjectBuildStatement(*si);
   }
 
   if (!this->DDIFiles.empty()) {
@@ -762,6 +785,17 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
 
     ddOutputs.push_back(this->GetDyndepFilePath("Fortran"));
 
+    // Make sure dyndep files for all our dependencies have already
+    // been generated so that the 'FortranModules.json' files they
+    // produced as side-effects are available for us to read.
+    // Ideally we should depend on the 'FortranModules.json' files
+    // from our dependencies directly, but we don't know which of
+    // our dependencies produces them.  Fixing this will require
+    // refactoring the Ninja generator to generate targets in
+    // dependency order so that we can collect the needed information.
+    this->GetLocalGenerator()->AppendTargetDepends(
+      this->GeneratorTarget, ddOrderOnlyDeps, DependOnTargetArtifact);
+
     this->GetGlobalGenerator()->WriteBuild(
       this->GetBuildFileStream(), ddComment, ddRule, ddOutputs, ddImplicitOuts,
       ddExplicitDeps, ddImplicitDeps, ddOrderOnlyDeps, ddVars);
@@ -771,7 +805,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
 }
 
 void cmNinjaTargetGenerator::WriteObjectBuildStatement(
-  cmSourceFile const* source, bool writeOrderDependsTargetForTarget)
+  cmSourceFile const* source)
 {
   std::string const language = source->GetLanguage();
   std::string const sourceFileName =
@@ -788,8 +822,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
   vars["DEFINES"] = this->ComputeDefines(source, language);
   vars["INCLUDES"] = this->GetIncludes(language);
   if (!this->NeedDepTypeMSVC(language)) {
-    vars["DEP_FILE"] =
-      cmGlobalNinjaGenerator::EncodeDepfileSpace(objectFileName + ".d");
+    vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+      objectFileName + ".d", cmOutputConverter::SHELL);
   }
 
   this->ExportObjectCompileCommand(
@@ -822,9 +856,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
   }
 
   cmNinjaDeps orderOnlyDeps;
-  if (writeOrderDependsTargetForTarget) {
-    orderOnlyDeps.push_back(this->OrderDependsTargetForTarget());
-  }
+  orderOnlyDeps.push_back(this->OrderDependsTargetForTarget());
 
   // If the source file is GENERATED and does not have a custom command
   // (either attached to this source file or another one), assume that one of
@@ -888,8 +920,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
     vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"];
 
     // Explicit preprocessing always uses a depfile.
-    ppVars["DEP_FILE"] =
-      cmGlobalNinjaGenerator::EncodeDepfileSpace(ppFileName + ".d");
+    ppVars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+      ppFileName + ".d", cmOutputConverter::SHELL);
     // The actual compilation does not need a depfile because it
     // depends on the already-preprocessed source.
     vars.erase("DEP_FILE");
@@ -1032,13 +1064,28 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
   compileObjectVars.Includes = includes.c_str();
 
   // Rule for compiling object file.
-  std::string compileCmdVar = "CMAKE_";
-  compileCmdVar += language;
-  compileCmdVar += "_COMPILE_OBJECT";
-  std::string compileCmd =
-    this->GetMakefile()->GetRequiredDefinition(compileCmdVar);
   std::vector<std::string> compileCmds;
-  cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+  if (language == "CUDA") {
+    std::string cmdVar;
+    if (this->GeneratorTarget->GetPropertyAsBool(
+          "CUDA_SEPARABLE_COMPILATION")) {
+      cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+    } else if (this->GeneratorTarget->GetPropertyAsBool(
+                 "CUDA_PTX_COMPILATION")) {
+      cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+    } else {
+      cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
+    }
+    std::string compileCmd =
+      this->GetMakefile()->GetRequiredDefinition(cmdVar);
+    cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+  } else {
+    const std::string cmdVar =
+      std::string("CMAKE_") + language + "_COMPILE_OBJECT";
+    std::string compileCmd =
+      this->GetMakefile()->GetRequiredDefinition(cmdVar);
+    cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+  }
 
   CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
     this->GetLocalGenerator()->CreateRulePlaceholderExpander());
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index 7aba66b..5eb7a9a 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmNinjaTargetGenerator_h
 #define cmNinjaTargetGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmCommonTargetGenerator.h"
 #include "cmGlobalNinjaGenerator.h"
@@ -119,8 +119,7 @@ protected:
   void WriteLanguageRules(const std::string& language);
   void WriteCompileRule(const std::string& language);
   void WriteObjectBuildStatements();
-  void WriteObjectBuildStatement(cmSourceFile const* source,
-                                 bool writeOrderDependsTargetForTarget);
+  void WriteObjectBuildStatement(cmSourceFile const* source);
   void WriteTargetDependInfo(std::string const& lang);
 
   void ExportObjectCompileCommand(
diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h
index 3fd536a..ec435d9 100644
--- a/Source/cmNinjaTypes.h
+++ b/Source/cmNinjaTypes.h
@@ -3,12 +3,18 @@
 #ifndef cmNinjaTypes_h
 #define cmNinjaTypes_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <string>
 #include <vector>
 
+enum cmNinjaTargetDepends
+{
+  DependOnTargetArtifact,
+  DependOnTargetOrdering
+};
+
 typedef std::vector<std::string> cmNinjaDeps;
 typedef std::map<std::string, std::string> cmNinjaVars;
 
diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h
index 897f432..9256e36 100644
--- a/Source/cmNinjaUtilityTargetGenerator.h
+++ b/Source/cmNinjaUtilityTargetGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmNinjaUtilityTargetGenerator_h
 #define cmNinjaUtilityTargetGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmNinjaTargetGenerator.h"
 
diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx
index 8139be4..beddc6e 100644
--- a/Source/cmOSXBundleGenerator.cxx
+++ b/Source/cmOSXBundleGenerator.cxx
@@ -2,11 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmOSXBundleGenerator.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmGeneratorTarget.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
+#include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
@@ -42,22 +43,22 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
   // Compute bundle directory names.
   std::string out = outpath;
   out += "/";
-  out += this->GT->GetAppBundleDirectory(this->ConfigName, false);
+  out += this->GT->GetAppBundleDirectory(this->ConfigName,
+                                         cmGeneratorTarget::FullLevel);
   cmSystemTools::MakeDirectory(out.c_str());
   this->Makefile->AddCMakeOutputFile(out);
 
-  std::string newoutpath = out;
-
   // Configure the Info.plist file.  Note that it needs the executable name
   // to be set.
   std::string plist = outpath;
   plist += "/";
-  plist += this->GT->GetAppBundleDirectory(this->ConfigName, true);
+  plist += this->GT->GetAppBundleDirectory(this->ConfigName,
+                                           cmGeneratorTarget::ContentLevel);
   plist += "/Info.plist";
   this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName,
                                                plist.c_str());
   this->Makefile->AddCMakeOutputFile(plist);
-  outpath = newoutpath;
+  outpath = out;
 }
 
 void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
@@ -70,12 +71,14 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
   assert(this->MacContentFolders);
 
   // Compute the location of the top-level foo.framework directory.
-  std::string contentdir =
-    outpath + "/" + this->GT->GetFrameworkDirectory(this->ConfigName, true);
+  std::string contentdir = outpath + "/" +
+    this->GT->GetFrameworkDirectory(this->ConfigName,
+                                    cmGeneratorTarget::ContentLevel);
   contentdir += "/";
 
-  std::string newoutpath =
-    outpath + "/" + this->GT->GetFrameworkDirectory(this->ConfigName, false);
+  std::string newoutpath = outpath + "/" +
+    this->GT->GetFrameworkDirectory(this->ConfigName,
+                                    cmGeneratorTarget::FullLevel);
 
   std::string frameworkVersion = this->GT->GetFrameworkVersion();
 
@@ -170,14 +173,16 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
   // Compute bundle directory names.
   std::string out = root;
   out += "/";
-  out += this->GT->GetCFBundleDirectory(this->ConfigName, false);
+  out += this->GT->GetCFBundleDirectory(this->ConfigName,
+                                        cmGeneratorTarget::FullLevel);
   cmSystemTools::MakeDirectory(out.c_str());
   this->Makefile->AddCMakeOutputFile(out);
 
   // Configure the Info.plist file.  Note that it needs the executable name
   // to be set.
-  std::string plist =
-    root + "/" + this->GT->GetCFBundleDirectory(this->ConfigName, true);
+  std::string plist = root + "/" +
+    this->GT->GetCFBundleDirectory(this->ConfigName,
+                                   cmGeneratorTarget::ContentLevel);
   plist += "/Info.plist";
   std::string name = cmSystemTools::GetFilenameName(targetName);
   this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist.c_str());
@@ -207,8 +212,8 @@ std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
 {
   // Construct the full path to the content subdirectory.
 
-  std::string macdir = this->GT->GetMacContentDirectory(this->ConfigName,
-                                                        /*implib*/ false);
+  std::string macdir = this->GT->GetMacContentDirectory(
+    this->ConfigName, cmStateEnums::RuntimeBinaryArtifact);
   macdir += "/";
   macdir += pkgloc;
   cmSystemTools::MakeDirectory(macdir.c_str());
diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h
index 0a5a6c5..be7e932 100644
--- a/Source/cmOSXBundleGenerator.h
+++ b/Source/cmOSXBundleGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmOSXBundleGenerator_h
 #define cmOSXBundleGenerator_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <set>
 #include <string>
diff --git a/Source/cmOptionCommand.h b/Source/cmOptionCommand.h
index 09567ff..634e3a8 100644
--- a/Source/cmOptionCommand.h
+++ b/Source/cmOptionCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmOptionCommand_h
 #define cmOptionCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "option"; }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
 };
 
 #endif
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index d48eb53..333e313 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -424,7 +424,7 @@ struct cmOrderDirectoriesCompare
   // The conflict pair is unique based on just the directory
   // (first).  The second element is only used for displaying
   // information about why the entry is present.
-  bool operator()(ConflictPair const& l, ConflictPair const& r)
+  bool operator()(ConflictPair l, ConflictPair r)
   {
     return l.first == r.first;
   }
diff --git a/Source/cmOrderDirectories.h b/Source/cmOrderDirectories.h
index d9e0126..3a0637a 100644
--- a/Source/cmOrderDirectories.h
+++ b/Source/cmOrderDirectories.h
@@ -3,9 +3,9 @@
 #ifndef cmOrderDirectories_h
 #define cmOrderDirectories_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <map>
 #include <set>
 #include <string>
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index d6864a6..14c986d 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -14,7 +14,7 @@
 #include "cmStateDirectory.h"
 #include "cmSystemTools.h"
 
-cmOutputConverter::cmOutputConverter(cmStateSnapshot snapshot)
+cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot)
   : StateSnapshot(snapshot)
   , LinkScriptShell(false)
 {
@@ -81,7 +81,7 @@ static bool cmOutputConverterNotAbove(const char* a, const char* b)
 
 bool cmOutputConverter::ContainedInDirectory(std::string const& local_path,
                                              std::string const& remote_path,
-                                             cmStateDirectory directory)
+                                             cmStateDirectory const& directory)
 {
   const std::string relativePathTopBinary =
     directory.GetRelativePathTopBinary();
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index a3da4cd..ae15055 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -3,7 +3,7 @@
 #ifndef cmOutputConverter_h
 #define cmOutputConverter_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
@@ -15,7 +15,7 @@ class cmStateDirectory;
 class cmOutputConverter
 {
 public:
-  cmOutputConverter(cmStateSnapshot snapshot);
+  cmOutputConverter(cmStateSnapshot const& snapshot);
 
   enum OutputFormat
   {
@@ -94,7 +94,7 @@ public:
 
   static bool ContainedInDirectory(std::string const& local_path,
                                    std::string const& remote_path,
-                                   cmStateDirectory directory);
+                                   cmStateDirectory const& directory);
 
   /**
    * Convert the given remote path to a relative path with respect to
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index 7a17f2c..2339d68 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -2,15 +2,14 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmOutputRequiredFilesCommand.h"
 
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <map>
 #include <utility>
 
 #include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -189,9 +188,8 @@ protected:
           if (qstart == std::string::npos) {
             cmSystemTools::Error("unknown include directive ", line.c_str());
             continue;
-          } else {
-            qend = line.find('>', qstart + 1);
           }
+          qend = line.find('>', qstart + 1);
         } else {
           qend = line.find('\"', qstart + 1);
         }
@@ -495,11 +493,6 @@ protected:
 bool cmOutputRequiredFilesCommand::InitialPass(
   std::vector<std::string> const& args, cmExecutionStatus&)
 {
-  if (this->Disallowed(cmPolicies::CMP0032, "The output_required_files "
-                                            "command should not be called; "
-                                            "see CMP0032.")) {
-    return true;
-  }
   if (args.size() != 2) {
     this->SetError("called with incorrect number of arguments");
     return false;
diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h
index c4ce680..d20bfbd 100644
--- a/Source/cmOutputRequiredFilesCommand.h
+++ b/Source/cmOutputRequiredFilesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmOutputRequiredFilesCommand_h
 #define cmOutputRequiredFilesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <set>
 #include <stdio.h>
 #include <string>
@@ -20,7 +21,6 @@ public:
   cmCommand* Clone() CM_OVERRIDE { return new cmOutputRequiredFilesCommand; }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-  std::string GetName() const CM_OVERRIDE { return "output_required_files"; }
 
   void ListDependencies(cmDependInformation const* info, FILE* fout,
                         std::set<cmDependInformation const*>* visited);
diff --git a/Source/cmParseArgumentsCommand.h b/Source/cmParseArgumentsCommand.h
index 079eadb..359fb85 100644
--- a/Source/cmParseArgumentsCommand.h
+++ b/Source/cmParseArgumentsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmParseArgumentsCommand_h
 #define cmParseArgumentsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -28,16 +29,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "cmake_parse_arguments"; }
 };
 
 #endif
diff --git a/Source/cmPathLabel.h b/Source/cmPathLabel.h
index cd9743c..97551fb 100644
--- a/Source/cmPathLabel.h
+++ b/Source/cmPathLabel.h
@@ -3,7 +3,7 @@
 #ifndef cmPathLabel_h
 #define cmPathLabel_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 6339e11..da3edd4 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -8,8 +8,8 @@
 #include "cmVersion.h"
 #include "cmake.h"
 
+#include "cmConfigure.h"
 #include <assert.h>
-#include <cmConfigure.h>
 #include <ctype.h>
 #include <sstream>
 #include <stdio.h>
@@ -275,6 +275,22 @@ std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id)
   return msg.str();
 }
 
+std::string cmPolicies::GetPolicyDeprecatedWarning(cmPolicies::PolicyID id)
+{
+  std::ostringstream msg;
+  /* clang-format off */
+  msg <<
+    "The OLD behavior for policy " << idToString(id) << " "
+    "will be removed from a future version of CMake.\n"
+    "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."
+    ;
+  /* clang-format on */
+  return msg.str();
+}
+
 ///! return an error string for when a required policy is unspecified
 std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id)
 {
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 62e67c7..69cbc18 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -3,7 +3,7 @@
 #ifndef cmPolicies_h
 #define cmPolicies_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <bitset>
 #include <string>
@@ -200,7 +200,13 @@ class cmMakefile;
          7, 0, cmPolicies::WARN)                                              \
   SELECT(POLICY, CMP0067,                                                     \
          "Honor language standard in try_compile() source-file signature.",   \
-         3, 8, 0, cmPolicies::WARN)
+         3, 8, 0, cmPolicies::WARN)                                           \
+  SELECT(POLICY, CMP0068,                                                     \
+         "RPATH settings on macOS do not affect install_name.", 3, 9, 0,      \
+         cmPolicies::WARN)                                                    \
+  SELECT(POLICY, CMP0069,                                                     \
+         "INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.", 3, 9, 0,   \
+         cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
@@ -221,7 +227,9 @@ class cmMakefile;
   F(CMP0052)                                                                  \
   F(CMP0060)                                                                  \
   F(CMP0063)                                                                  \
-  F(CMP0065)
+  F(CMP0065)                                                                  \
+  F(CMP0068)                                                                  \
+  F(CMP0069)
 
 /** \class cmPolicies
  * \brief Handles changes in CMake behavior and policies
@@ -271,6 +279,7 @@ public:
 
   ///! return a warning string for a given policy
   static std::string GetPolicyWarning(cmPolicies::PolicyID id);
+  static std::string GetPolicyDeprecatedWarning(cmPolicies::PolicyID id);
 
   ///! return an error string for when a required policy is unspecified
   static std::string GetRequiredPolicyError(cmPolicies::PolicyID id);
diff --git a/Source/cmProcessOutput.h b/Source/cmProcessOutput.h
index d2e631f..b5ec4a8 100644
--- a/Source/cmProcessOutput.h
+++ b/Source/cmProcessOutput.h
@@ -3,7 +3,7 @@
 #ifndef cmProcessOutput_h
 #define cmProcessOutput_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <stddef.h>
 #include <string>
diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx
index b756650..de7b061 100644
--- a/Source/cmProcessTools.cxx
+++ b/Source/cmProcessTools.cxx
@@ -3,7 +3,7 @@
 #include "cmProcessTools.h"
 #include "cmProcessOutput.h"
 
-#include <cmsys/Process.h>
+#include "cmsys/Process.h"
 #include <ostream>
 
 void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out,
diff --git a/Source/cmProcessTools.h b/Source/cmProcessTools.h
index df131b9..e7d9a10 100644
--- a/Source/cmProcessTools.h
+++ b/Source/cmProcessTools.h
@@ -3,8 +3,8 @@
 #ifndef cmProcessTools_h
 #define cmProcessTools_h
 
+#include "cmConfigure.h"
 #include "cmProcessOutput.h"
-#include <cmConfigure.h>
 
 #include <iosfwd>
 #include <string.h>
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 4e0fa57..d72c790 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmProjectCommand.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <sstream>
 #include <stdio.h>
 
@@ -22,11 +22,14 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
     this->SetError("PROJECT called with incorrect number of arguments");
     return false;
   }
-  this->Makefile->SetProjectName(args[0]);
 
-  std::string bindir = args[0];
+  std::string const& projectName = args[0];
+
+  this->Makefile->SetProjectName(projectName);
+
+  std::string bindir = projectName;
   bindir += "_BINARY_DIR";
-  std::string srcdir = args[0];
+  std::string srcdir = projectName;
   srcdir += "_SOURCE_DIR";
 
   this->Makefile->AddCacheDefinition(
@@ -44,7 +47,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
   this->Makefile->AddDefinition(srcdir,
                                 this->Makefile->GetCurrentSourceDirectory());
 
-  this->Makefile->AddDefinition("PROJECT_NAME", args[0].c_str());
+  this->Makefile->AddDefinition("PROJECT_NAME", projectName.c_str());
 
   // Set the CMAKE_PROJECT_NAME variable to be the highest-level
   // project name in the tree. If there are two project commands
@@ -54,18 +57,21 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
   // will work.
   if (!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME") ||
       (this->Makefile->IsRootMakefile())) {
-    this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", args[0].c_str());
-    this->Makefile->AddCacheDefinition("CMAKE_PROJECT_NAME", args[0].c_str(),
-                                       "Value Computed by CMake",
-                                       cmStateEnums::STATIC);
+    this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", projectName.c_str());
+    this->Makefile->AddCacheDefinition(
+      "CMAKE_PROJECT_NAME", projectName.c_str(), "Value Computed by CMake",
+      cmStateEnums::STATIC);
   }
 
   bool haveVersion = false;
   bool haveLanguages = false;
+  bool haveDescription = false;
   std::string version;
+  std::string description;
   std::vector<std::string> languages;
   enum Doing
   {
+    DoingDescription,
     DoingLanguages,
     DoingVersion
   };
@@ -89,9 +95,21 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
       }
       haveVersion = true;
       doing = DoingVersion;
+    } else if (args[i] == "DESCRIPTION") {
+      if (haveDescription) {
+        this->Makefile->IssueMessage(
+          cmake::FATAL_ERROR, "DESCRITPION may be specified at most once.");
+        cmSystemTools::SetFatalErrorOccured();
+        return true;
+      }
+      haveDescription = true;
+      doing = DoingDescription;
     } else if (doing == DoingVersion) {
       doing = DoingLanguages;
       version = args[i];
+    } else if (doing == DoingDescription) {
+      doing = DoingLanguages;
+      description = args[i];
     } else // doing == DoingLanguages
     {
       languages.push_back(args[i]);
@@ -148,19 +166,19 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
     }
 
     std::string vv;
-    vv = args[0] + "_VERSION";
+    vv = projectName + "_VERSION";
     this->Makefile->AddDefinition("PROJECT_VERSION", vs.c_str());
     this->Makefile->AddDefinition(vv, vs.c_str());
-    vv = args[0] + "_VERSION_MAJOR";
+    vv = projectName + "_VERSION_MAJOR";
     this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR", vb[0]);
     this->Makefile->AddDefinition(vv, vb[0]);
-    vv = args[0] + "_VERSION_MINOR";
+    vv = projectName + "_VERSION_MINOR";
     this->Makefile->AddDefinition("PROJECT_VERSION_MINOR", vb[1]);
     this->Makefile->AddDefinition(vv, vb[1]);
-    vv = args[0] + "_VERSION_PATCH";
+    vv = projectName + "_VERSION_PATCH";
     this->Makefile->AddDefinition("PROJECT_VERSION_PATCH", vb[2]);
     this->Makefile->AddDefinition(vv, vb[2]);
-    vv = args[0] + "_VERSION_TWEAK";
+    vv = projectName + "_VERSION_TWEAK";
     this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", vb[3]);
     this->Makefile->AddDefinition(vv, vb[3]);
   } else if (cmp0048 != cmPolicies::OLD) {
@@ -171,11 +189,11 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
     vv.push_back("PROJECT_VERSION_MINOR");
     vv.push_back("PROJECT_VERSION_PATCH");
     vv.push_back("PROJECT_VERSION_TWEAK");
-    vv.push_back(args[0] + "_VERSION");
-    vv.push_back(args[0] + "_VERSION_MAJOR");
-    vv.push_back(args[0] + "_VERSION_MINOR");
-    vv.push_back(args[0] + "_VERSION_PATCH");
-    vv.push_back(args[0] + "_VERSION_TWEAK");
+    vv.push_back(projectName + "_VERSION");
+    vv.push_back(projectName + "_VERSION_MAJOR");
+    vv.push_back(projectName + "_VERSION_MINOR");
+    vv.push_back(projectName + "_VERSION_PATCH");
+    vv.push_back(projectName + "_VERSION_TWEAK");
     std::string vw;
     for (std::vector<std::string>::iterator i = vv.begin(); i != vv.end();
          ++i) {
@@ -197,13 +215,29 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
     }
   }
 
+  if (haveDescription) {
+    this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str());
+    // Set the CMAKE_PROJECT_DESCRIPTION variable to be the highest-level
+    // project name in the tree. If there are two project commands
+    // in the same CMakeLists.txt file, and it is the top level
+    // CMakeLists.txt file, then go with the last one.
+    if (!this->Makefile->GetDefinition("CMAKE_PROJECT_DESCRIPTION") ||
+        (this->Makefile->IsRootMakefile())) {
+      this->Makefile->AddDefinition("CMAKE_PROJECT_DESCRIPTION",
+                                    description.c_str());
+      this->Makefile->AddCacheDefinition(
+        "CMAKE_PROJECT_DESCRIPTION", description.c_str(),
+        "Value Computed by CMake", cmStateEnums::STATIC);
+    }
+  }
+
   if (languages.empty()) {
     // if no language is specified do c and c++
     languages.push_back("C");
     languages.push_back("CXX");
   }
   this->Makefile->EnableLanguage(languages, false);
-  std::string extraInclude = "CMAKE_PROJECT_" + args[0] + "_INCLUDE";
+  std::string extraInclude = "CMAKE_PROJECT_" + projectName + "_INCLUDE";
   const char* include = this->Makefile->GetDefinition(extraInclude);
   if (include) {
     bool readit = this->Makefile->ReadDependentFile(include);
diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h
index cd92176..3c579ac 100644
--- a/Source/cmProjectCommand.h
+++ b/Source/cmProjectCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmProjectCommand_h
 #define cmProjectCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -33,11 +34,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "project"; }
 };
 
 #endif
diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx
index 90122a4..222afb4 100644
--- a/Source/cmProperty.cxx
+++ b/Source/cmProperty.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmProperty.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 void cmProperty::Set(const char* value)
 {
diff --git a/Source/cmProperty.h b/Source/cmProperty.h
index 3f2dcfe..d11c5ef 100644
--- a/Source/cmProperty.h
+++ b/Source/cmProperty.h
@@ -3,7 +3,7 @@
 #ifndef cmProperty_h
 #define cmProperty_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h
index eb8d064..9adff49 100644
--- a/Source/cmPropertyDefinition.h
+++ b/Source/cmPropertyDefinition.h
@@ -3,7 +3,7 @@
 #ifndef cmPropertyDefinition_h
 #define cmPropertyDefinition_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmProperty.h"
 
diff --git a/Source/cmPropertyDefinitionMap.h b/Source/cmPropertyDefinitionMap.h
index e747503..97ba553 100644
--- a/Source/cmPropertyDefinitionMap.h
+++ b/Source/cmPropertyDefinitionMap.h
@@ -3,7 +3,7 @@
 #ifndef cmPropertyDefinitionMap_h
 #define cmPropertyDefinitionMap_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmProperty.h"
 #include "cmPropertyDefinition.h"
diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx
index fa92ae2..1e089d1 100644
--- a/Source/cmPropertyMap.cxx
+++ b/Source/cmPropertyMap.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmPropertyMap.h"
 
+#include "cmConfigure.h"
 #include <algorithm>
 #include <assert.h>
-#include <cmConfigure.h>
 #include <utility>
 
 cmProperty* cmPropertyMap::GetOrCreateProperty(const std::string& name)
diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h
index e1db7df..5a05150 100644
--- a/Source/cmPropertyMap.h
+++ b/Source/cmPropertyMap.h
@@ -3,7 +3,7 @@
 #ifndef cmPropertyMap_h
 #define cmPropertyMap_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmProperty.h"
 
diff --git a/Source/cmQTWrapCPPCommand.h b/Source/cmQTWrapCPPCommand.h
index 8eb5ff9..ad1ccf3 100644
--- a/Source/cmQTWrapCPPCommand.h
+++ b/Source/cmQTWrapCPPCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmQTWrapCPPCommand_h
 #define cmQTWrapCPPCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,11 +32,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "qt_wrap_cpp"; }
 };
 
 #endif
diff --git a/Source/cmQTWrapUICommand.h b/Source/cmQTWrapUICommand.h
index 876ddd5..ac7ab01 100644
--- a/Source/cmQTWrapUICommand.h
+++ b/Source/cmQTWrapUICommand.h
@@ -3,7 +3,8 @@
 #ifndef cmQTWrapUICommand_h
 #define cmQTWrapUICommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,11 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "qt_wrap_ui"; }
 };
 
 #endif
diff --git a/Source/cmQtAutoGeneratorCommon.cxx b/Source/cmQtAutoGeneratorCommon.cxx
new file mode 100644
index 0000000..3e1b58c
--- /dev/null
+++ b/Source/cmQtAutoGeneratorCommon.cxx
@@ -0,0 +1,216 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmQtAutoGeneratorCommon.h"
+#include "cmAlgorithms.h"
+#include "cmSystemTools.h"
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include <sstream>
+#include <stddef.h>
+
+// - Static functions
+
+static std::string utilStripCR(std::string const& line)
+{
+  // Strip CR characters rcc may have printed (possibly more than one!).
+  std::string::size_type cr = line.find('\r');
+  if (cr != std::string::npos) {
+    return line.substr(0, cr);
+  }
+  return line;
+}
+
+/// @brief Reads the resource files list from from a .qrc file - Qt4 version
+/// @return True if the .qrc file was successfully parsed
+static bool RccListInputsQt4(const std::string& fileName,
+                             std::vector<std::string>& files,
+                             std::string* errorMessage)
+{
+  bool allGood = true;
+  // Read qrc file content into string
+  std::string qrcContents;
+  {
+    cmsys::ifstream ifs(fileName.c_str());
+    if (ifs) {
+      std::ostringstream osst;
+      osst << ifs.rdbuf();
+      qrcContents = osst.str();
+    } else {
+      if (errorMessage != CM_NULLPTR) {
+        std::ostringstream ost;
+        ost << "AutoRcc: Error: Rcc file not readable:\n"
+            << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n";
+        *errorMessage = ost.str();
+      }
+      allGood = false;
+    }
+  }
+  if (allGood) {
+    // qrc file directory
+    std::string qrcDir(cmsys::SystemTools::GetFilenamePath(fileName));
+    if (!qrcDir.empty()) {
+      qrcDir += '/';
+    }
+
+    cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
+    cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
+
+    size_t offset = 0;
+    while (fileMatchRegex.find(qrcContents.c_str() + offset)) {
+      std::string qrcEntry = fileMatchRegex.match(1);
+      offset += qrcEntry.size();
+      {
+        fileReplaceRegex.find(qrcEntry);
+        std::string tag = fileReplaceRegex.match(1);
+        qrcEntry = qrcEntry.substr(tag.size());
+      }
+      if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) {
+        qrcEntry = qrcDir + qrcEntry;
+      }
+      files.push_back(qrcEntry);
+    }
+  }
+  return allGood;
+}
+
+/// @brief Reads the resource files list from from a .qrc file - Qt5 version
+/// @return True if the .qrc file was successfully parsed
+static bool RccListInputsQt5(const std::string& rccCommand,
+                             const std::string& fileName,
+                             std::vector<std::string>& files,
+                             std::string* errorMessage)
+{
+  if (rccCommand.empty()) {
+    cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n");
+    return false;
+  }
+
+  // Read rcc features
+  bool hasDashDashList = false;
+  {
+    std::vector<std::string> command;
+    command.push_back(rccCommand);
+    command.push_back("--help");
+    std::string rccStdOut;
+    std::string rccStdErr;
+    int retVal = 0;
+    bool result =
+      cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
+                                      CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
+    if (result && retVal == 0 &&
+        rccStdOut.find("--list") != std::string::npos) {
+      hasDashDashList = true;
+    }
+  }
+
+  // Run rcc list command
+  bool result = false;
+  int retVal = 0;
+  std::string rccStdOut;
+  std::string rccStdErr;
+  {
+    std::vector<std::string> command;
+    command.push_back(rccCommand);
+    command.push_back(hasDashDashList ? "--list" : "-list");
+    command.push_back(fileName);
+    result =
+      cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
+                                      CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
+  }
+  if (!result || retVal) {
+    if (errorMessage != CM_NULLPTR) {
+      std::ostringstream ost;
+      ost << "AutoRcc: Error: Rcc list process for " << fileName
+          << " failed:\n"
+          << rccStdOut << "\n"
+          << rccStdErr << "\n";
+      *errorMessage = ost.str();
+    }
+    return false;
+  }
+
+  // Parse rcc std output
+  {
+    std::istringstream ostr(rccStdOut);
+    std::string oline;
+    while (std::getline(ostr, oline)) {
+      oline = utilStripCR(oline);
+      if (!oline.empty()) {
+        files.push_back(oline);
+      }
+    }
+  }
+  // Parse rcc error output
+  {
+    std::istringstream estr(rccStdErr);
+    std::string eline;
+    while (std::getline(estr, eline)) {
+      eline = utilStripCR(eline);
+      if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
+        static std::string searchString = "Cannot find file '";
+
+        std::string::size_type pos = eline.find(searchString);
+        if (pos == std::string::npos) {
+          if (errorMessage != CM_NULLPTR) {
+            std::ostringstream ost;
+            ost << "AutoRcc: Error: Rcc lists unparsable output:\n"
+                << cmQtAutoGeneratorCommon::Quoted(eline) << "\n";
+            *errorMessage = ost.str();
+          }
+          return false;
+        }
+        pos += searchString.length();
+        std::string::size_type sz = eline.size() - pos - 1;
+        files.push_back(eline.substr(pos, sz));
+      }
+    }
+  }
+
+  return true;
+}
+
+// - Class definitions
+
+const char* cmQtAutoGeneratorCommon::listSep = "@LSEP@";
+
+std::string cmQtAutoGeneratorCommon::Quoted(const std::string& text)
+{
+  static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a",
+                                 "\b", "\\b",  "\f", "\\f",  "\n", "\\n",
+                                 "\r", "\\r",  "\t", "\\t",  "\v", "\\v" };
+
+  std::string res = text;
+  for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep);
+       it += 2) {
+    cmSystemTools::ReplaceString(res, *it, *(it + 1));
+  }
+  res = '"' + res;
+  res += '"';
+  return res;
+}
+
+bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion,
+                                            const std::string& rccCommand,
+                                            const std::string& fileName,
+                                            std::vector<std::string>& files,
+                                            std::string* errorMessage)
+{
+  bool allGood = false;
+  if (cmsys::SystemTools::FileExists(fileName.c_str())) {
+    if (qtMajorVersion == "4") {
+      allGood = RccListInputsQt4(fileName, files, errorMessage);
+    } else {
+      allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage);
+    }
+  } else {
+    if (errorMessage != CM_NULLPTR) {
+      std::ostringstream ost;
+      ost << "AutoRcc: Error: Rcc file does not exist:\n"
+          << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n";
+      *errorMessage = ost.str();
+    }
+  }
+  return allGood;
+}
diff --git a/Source/cmQtAutoGeneratorCommon.h b/Source/cmQtAutoGeneratorCommon.h
new file mode 100644
index 0000000..a131baf
--- /dev/null
+++ b/Source/cmQtAutoGeneratorCommon.h
@@ -0,0 +1,39 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmQtAutoGeneratorCommon_h
+#define cmQtAutoGeneratorCommon_h
+
+#include "cmConfigure.h"
+
+#include <string>
+#include <vector>
+
+class cmQtAutoGeneratorCommon
+{
+  // - Types and statics
+public:
+  static const char* listSep;
+
+  enum GeneratorType
+  {
+    MOC,
+    UIC,
+    RCC
+  };
+
+public:
+  /// @brief Returns a the string escaped and enclosed in quotes
+  ///
+  static std::string Quoted(const std::string& text);
+
+  /// @brief Reads the resource files list from from a .qrc file
+  /// @arg fileName Must be the absolute path of the .qrc file
+  /// @return True if the rcc file was successfully parsed
+  static bool RccListInputs(const std::string& qtMajorVersion,
+                            const std::string& rccCommand,
+                            const std::string& fileName,
+                            std::vector<std::string>& files,
+                            std::string* errorMessage = CM_NULLPTR);
+};
+
+#endif
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index 825eba0..cecf165 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -1,6 +1,7 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQtAutoGeneratorInitializer.h"
+#include "cmQtAutoGeneratorCommon.h"
 
 #include "cmAlgorithms.h"
 #include "cmCustomCommandLines.h"
@@ -11,27 +12,23 @@
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
 #include "cmSourceFile.h"
-#include "cmSourceFileLocation.h"
+#include "cmSourceGroup.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
+#include "cm_sys_stat.h"
 #include "cmake.h"
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include "cmGlobalVisualStudioGenerator.h"
 #endif
 
+#include "cmConfigure.h"
+#include "cmsys/FStream.hxx"
 #include <algorithm>
-#include <assert.h>
-#include <cmConfigure.h>
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
 #include <map>
 #include <set>
-#include <sstream>
-#include <string.h>
 #include <string>
-#include <sys/stat.h>
 #include <utility>
 #include <vector>
 
@@ -45,14 +42,16 @@ static void utilCopyTargetProperty(cmTarget* destinationTarget,
   }
 }
 
-static std::string utilStripCR(std::string const& line)
+inline static bool PropertyEnabled(cmSourceFile* sourceFile, const char* key)
 {
-  // Strip CR characters rcc may have printed (possibly more than one!).
-  std::string::size_type cr = line.find('\r');
-  if (cr != line.npos) {
-    return line.substr(0, cr);
-  }
-  return line;
+  return cmSystemTools::IsOn(sourceFile->GetPropertyForUser(key));
+}
+
+static std::string GetSafeProperty(cmGeneratorTarget const* target,
+                                   const char* key)
+{
+  const char* tmp = target->GetProperty(key);
+  return std::string((tmp != CM_NULLPTR) ? tmp : "");
 }
 
 static std::string GetAutogenTargetName(cmGeneratorTarget const* target)
@@ -69,17 +68,19 @@ static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target)
   targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
   targetDir += "/";
   targetDir += GetAutogenTargetName(target);
-  targetDir += ".dir/";
+  targetDir += ".dir";
   return targetDir;
 }
 
 static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target)
 {
-  cmMakefile* makefile = target->Target->GetMakefile();
-  std::string targetDir = makefile->GetCurrentBinaryDirectory();
-  targetDir += "/";
-  targetDir += GetAutogenTargetName(target);
-  targetDir += "/";
+  std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR");
+  if (targetDir.empty()) {
+    cmMakefile* makefile = target->Target->GetMakefile();
+    targetDir = makefile->GetCurrentBinaryDirectory();
+    targetDir += "/";
+    targetDir += GetAutogenTargetName(target);
+  }
   return targetDir;
 }
 
@@ -98,21 +99,200 @@ static std::string GetQtMajorVersion(cmGeneratorTarget const* target)
   return qtMajorVersion;
 }
 
-static void SetupSourceFiles(cmGeneratorTarget const* target,
+static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
+                                     const std::string& qtMajorVersion)
+{
+  cmMakefile* makefile = target->Target->GetMakefile();
+  std::string qtMinorVersion;
+  if (qtMajorVersion == "5") {
+    qtMinorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
+  }
+  if (qtMinorVersion.empty()) {
+    qtMinorVersion = makefile->GetSafeDefinition("QT_VERSION_MINOR");
+  }
+
+  const char* targetQtVersion =
+    target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
+  if (targetQtVersion != CM_NULLPTR) {
+    qtMinorVersion = targetQtVersion;
+  }
+  return qtMinorVersion;
+}
+
+static bool QtVersionGreaterOrEqual(const std::string& major,
+                                    const std::string& minor,
+                                    unsigned long requestMajor,
+                                    unsigned long requestMinor)
+{
+  unsigned long majorUL(0);
+  unsigned long minorUL(0);
+  if (cmSystemTools::StringToULong(major.c_str(), &majorUL) &&
+      cmSystemTools::StringToULong(minor.c_str(), &minorUL)) {
+    return (majorUL > requestMajor) ||
+      (majorUL == requestMajor && minorUL >= requestMinor);
+  }
+  return false;
+}
+
+static void GetCompileDefinitionsAndDirectories(
+  cmGeneratorTarget const* target, const std::string& config,
+  std::string& incs, std::string& defs)
+{
+  cmLocalGenerator* localGen = target->GetLocalGenerator();
+  {
+    std::vector<std::string> includeDirs;
+    // Get the include dirs for this target, without stripping the implicit
+    // include dirs off, see
+    // https://gitlab.kitware.com/cmake/cmake/issues/13667
+    localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false);
+    incs = cmJoin(includeDirs, ";");
+  }
+  {
+    std::set<std::string> defines;
+    localGen->AddCompileDefinitions(defines, target, config, "CXX");
+    defs += cmJoin(defines, ";");
+  }
+}
+
+static bool IsMultiConfig(cmGlobalGenerator* globalGen)
+{
+  // FIXME: Xcode does not support per-config sources, yet.
+  //        (EXCLUDED_SOURCE_FILE_NAMES)
+  //        Treat it as a single configuration generator meanwhile.
+  if (globalGen->GetName().find("Xcode") != std::string::npos) {
+    return false;
+  }
+  // FIXME: Visual Studio does not fully support per-config sources yet.
+  if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
+    return false;
+  }
+  return globalGen->IsMultiConfig();
+}
+
+static std::vector<std::string> GetConfigurations(
+  cmMakefile* makefile, std::string* config = CM_NULLPTR)
+{
+  std::vector<std::string> configs;
+  {
+    std::string cfg = makefile->GetConfigurations(configs);
+    if (config != CM_NULLPTR) {
+      *config = cfg;
+    }
+  }
+  // Add empty configuration on demand
+  if (configs.empty()) {
+    configs.push_back("");
+  }
+  return configs;
+}
+
+static std::vector<std::string> GetConfigurationSuffixes(cmMakefile* makefile)
+{
+  std::vector<std::string> suffixes;
+  if (IsMultiConfig(makefile->GetGlobalGenerator())) {
+    makefile->GetConfigurations(suffixes);
+    for (std::vector<std::string>::iterator it = suffixes.begin();
+         it != suffixes.end(); ++it) {
+      it->insert(0, "_");
+    }
+  }
+  if (suffixes.empty()) {
+    suffixes.push_back("");
+  }
+  return suffixes;
+}
+
+static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
+                                 const std::string& value)
+{
+  makefile->AddDefinition(key,
+                          cmOutputConverter::EscapeForCMake(value).c_str());
+}
+
+static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
+                                 const std::vector<std::string>& values)
+{
+  makefile->AddDefinition(
+    key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
+}
+
+static bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName,
+                             cmQtAutoGeneratorCommon::GeneratorType genType)
+{
+  cmSourceGroup* sourceGroup = CM_NULLPTR;
+  // Acquire source group
+  {
+    const char* groupName = CM_NULLPTR;
+    // Use generator specific group name
+    switch (genType) {
+      case cmQtAutoGeneratorCommon::MOC:
+        groupName =
+          makefile->GetState()->GetGlobalProperty("AUTOMOC_SOURCE_GROUP");
+        break;
+      case cmQtAutoGeneratorCommon::RCC:
+        groupName =
+          makefile->GetState()->GetGlobalProperty("AUTORCC_SOURCE_GROUP");
+        break;
+      default:
+        break;
+    }
+    // Use default group name on demand
+    if ((groupName == CM_NULLPTR) || (*groupName == 0)) {
+      groupName =
+        makefile->GetState()->GetGlobalProperty("AUTOGEN_SOURCE_GROUP");
+    }
+    // Generate a source group on demand
+    if ((groupName != CM_NULLPTR) && (*groupName != 0)) {
+      {
+        const char* delimiter =
+          makefile->GetDefinition("SOURCE_GROUP_DELIMITER");
+        if (delimiter == CM_NULLPTR) {
+          delimiter = "\\";
+        }
+        std::vector<std::string> folders =
+          cmSystemTools::tokenize(groupName, delimiter);
+        sourceGroup = makefile->GetSourceGroup(folders);
+        if (sourceGroup == CM_NULLPTR) {
+          makefile->AddSourceGroup(folders);
+          sourceGroup = makefile->GetSourceGroup(folders);
+        }
+      }
+      if (sourceGroup == CM_NULLPTR) {
+        cmSystemTools::Error(
+          "Autogen: Could not create or find source group: ",
+          cmQtAutoGeneratorCommon::Quoted(groupName).c_str());
+        return false;
+      }
+    }
+  }
+  if (sourceGroup != CM_NULLPTR) {
+    sourceGroup->AddGroupFile(fileName);
+  }
+  return true;
+}
+
+static void AddGeneratedSource(cmMakefile* makefile,
+                               const std::string& filename,
+                               cmQtAutoGeneratorCommon::GeneratorType genType)
+{
+  cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
+  gFile->SetProperty("GENERATED", "1");
+  gFile->SetProperty("SKIP_AUTOGEN", "On");
+
+  AddToSourceGroup(makefile, filename, genType);
+}
+
+static void AcquireScanFiles(cmGeneratorTarget const* target,
                              std::vector<std::string>& mocUicSources,
                              std::vector<std::string>& mocUicHeaders,
-                             std::vector<std::string>& skipMocList,
-                             std::vector<std::string>& skipUicList)
+                             std::vector<std::string>& mocSkipList,
+                             std::vector<std::string>& uicSkipList)
 {
-  cmMakefile* makefile = target->Target->GetMakefile();
+  const bool mocTarget = target->GetPropertyAsBool("AUTOMOC");
+  const bool uicTarget = target->GetPropertyAsBool("AUTOUIC");
 
   std::vector<cmSourceFile*> srcFiles;
   target->GetConfigCommonSourceFiles(srcFiles);
-
-  const bool targetMoc = target->GetPropertyAsBool("AUTOMOC");
-  const bool targetUic = target->GetPropertyAsBool("AUTOUIC");
-
-  cmFilePathChecksum fpathCheckSum(makefile);
   for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
        fileIt != srcFiles.end(); ++fileIt) {
     cmSourceFile* sf = *fileIt;
@@ -123,30 +303,31 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
         !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
       continue;
     }
-    if (cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
+    if (PropertyEnabled(sf, "GENERATED") &&
+        !target->GetPropertyAsBool("__UNDOCUMENTED_AUTOGEN_GENERATED_FILES")) {
+      // FIXME: Add a policy whose NEW behavior allows generated files.
+      // The implementation already works.  We disable it here to avoid
+      // changing behavior for existing projects that do not expect it.
       continue;
     }
     const std::string absFile =
       cmsys::SystemTools::GetRealPath(sf->GetFullPath());
     // Skip flags
-    const bool skipAll =
-      cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN"));
-    const bool skipMoc =
-      skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC"));
-    const bool skipUic =
-      skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC"));
+    const bool skipAll = PropertyEnabled(sf, "SKIP_AUTOGEN");
+    const bool mocSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOMOC");
+    const bool uicSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOUIC");
     // Add file name to skip lists.
     // Do this even when the file is not added to the sources/headers lists
     // because the file name may be extracted from an other file when
     // processing
-    if (skipMoc) {
-      skipMocList.push_back(absFile);
+    if (mocSkip) {
+      mocSkipList.push_back(absFile);
     }
-    if (skipUic) {
-      skipUicList.push_back(absFile);
+    if (uicSkip) {
+      uicSkipList.push_back(absFile);
     }
 
-    if ((targetMoc && !skipMoc) || (targetUic && !skipUic)) {
+    if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) {
       // Add file name to sources or headers list
       switch (fileType) {
         case cmSystemTools::CXX_FILE_FORMAT:
@@ -162,100 +343,87 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
   }
 }
 
-static void GetCompileDefinitionsAndDirectories(
-  cmGeneratorTarget const* target, const std::string& config,
-  std::string& incs, std::string& defs)
-{
-  std::vector<std::string> includeDirs;
-  cmLocalGenerator* localGen = target->GetLocalGenerator();
-  // Get the include dirs for this target, without stripping the implicit
-  // include dirs off, see https://gitlab.kitware.com/cmake/cmake/issues/13667
-  localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false);
-
-  incs = cmJoin(includeDirs, ";");
-
-  std::set<std::string> defines;
-  localGen->AddCompileDefinitions(defines, target, config, "CXX");
-
-  defs += cmJoin(defines, ";");
-}
-
 static void MocSetupAutoTarget(
   cmGeneratorTarget const* target, const std::string& autogenTargetName,
-  std::vector<std::string> const& skipMoc,
-  std::map<std::string, std::string>& configIncludes,
-  std::map<std::string, std::string>& configDefines)
+  std::string const& qtMajorVersion, std::string const& config,
+  std::vector<std::string> const& configs,
+  std::vector<std::string> const& mocSkipList,
+  std::map<std::string, std::string>& configMocIncludes,
+  std::map<std::string, std::string>& configMocDefines)
 {
   cmLocalGenerator* lg = target->GetLocalGenerator();
   cmMakefile* makefile = target->Target->GetMakefile();
 
-  const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS");
-  std::string _moc_options = (tmp != CM_NULLPTR ? tmp : "");
-  makefile->AddDefinition(
-    "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str());
-  makefile->AddDefinition(
-    "_skip_moc",
-    cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str());
-  bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE");
-  makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE");
-
-  std::string _moc_incs;
-  std::string _moc_compile_defs;
-  std::vector<std::string> configs;
-  const std::string& config = makefile->GetConfigurations(configs);
-  GetCompileDefinitionsAndDirectories(target, config, _moc_incs,
-                                      _moc_compile_defs);
-
-  makefile->AddDefinition(
-    "_moc_incs", cmOutputConverter::EscapeForCMake(_moc_incs).c_str());
-  makefile->AddDefinition(
-    "_moc_compile_defs",
-    cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str());
-
-  for (std::vector<std::string>::const_iterator li = configs.begin();
-       li != configs.end(); ++li) {
-    std::string config_moc_incs;
-    std::string config_moc_compile_defs;
-    GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs,
-                                        config_moc_compile_defs);
-    if (config_moc_incs != _moc_incs) {
-      configIncludes[*li] = cmOutputConverter::EscapeForCMake(config_moc_incs);
-      if (_moc_incs.empty()) {
-        _moc_incs = config_moc_incs;
+  AddDefinitionEscaped(makefile, "_moc_options",
+                       GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS"));
+  AddDefinitionEscaped(makefile, "_moc_skip", mocSkipList);
+  AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
+                       makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
+                                                                    : "FALSE");
+  AddDefinitionEscaped(makefile, "_moc_depend_filters",
+                       GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
+
+  if (QtVersionGreaterOrEqual(
+        qtMajorVersion, GetQtMinorVersion(target, qtMajorVersion), 5, 8)) {
+    AddDefinitionEscaped(
+      makefile, "_moc_predefs_cmd",
+      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
+  }
+  // Moc includes and compile definitions
+  {
+    // Default settings
+    std::string incs;
+    std::string compileDefs;
+    GetCompileDefinitionsAndDirectories(target, config, incs, compileDefs);
+    AddDefinitionEscaped(makefile, "_moc_incs", incs);
+    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
+
+    // Configuration specific settings
+    for (std::vector<std::string>::const_iterator li = configs.begin();
+         li != configs.end(); ++li) {
+      std::string configIncs;
+      std::string configCompileDefs;
+      GetCompileDefinitionsAndDirectories(target, *li, configIncs,
+                                          configCompileDefs);
+      if (configIncs != incs) {
+        configMocIncludes[*li] = cmOutputConverter::EscapeForCMake(configIncs);
       }
-    }
-    if (config_moc_compile_defs != _moc_compile_defs) {
-      configDefines[*li] =
-        cmOutputConverter::EscapeForCMake(config_moc_compile_defs);
-      if (_moc_compile_defs.empty()) {
-        _moc_compile_defs = config_moc_compile_defs;
+      if (configCompileDefs != compileDefs) {
+        configMocDefines[*li] =
+          cmOutputConverter::EscapeForCMake(configCompileDefs);
       }
     }
   }
 
-  const char* qtVersion = makefile->GetDefinition("_target_qt_version");
-  if (strcmp(qtVersion, "5") == 0) {
-    cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc");
-    if (!qt5Moc) {
-      cmSystemTools::Error("Qt5::moc target not found ",
-                           autogenTargetName.c_str());
-      return;
+  // Moc executable
+  {
+    std::string err;
+    const char* mocExec = CM_NULLPTR;
+    if (qtMajorVersion == "5") {
+      cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc");
+      if (qt5Moc != CM_NULLPTR) {
+        mocExec = qt5Moc->ImportedGetLocation("");
+      } else {
+        err = "Qt5::moc target not found " + autogenTargetName;
+      }
+    } else if (qtMajorVersion == "4") {
+      cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc");
+      if (qt4Moc != CM_NULLPTR) {
+        mocExec = qt4Moc->ImportedGetLocation("");
+      } else {
+        err = "Qt4::moc target not found " + autogenTargetName;
+      }
+    } else {
+      err = "The CMAKE_AUTOMOC feature supports only Qt 4 and Qt 5 ";
+      err += autogenTargetName;
     }
-    makefile->AddDefinition("_qt_moc_executable",
-                            qt5Moc->ImportedGetLocation(""));
-  } else if (strcmp(qtVersion, "4") == 0) {
-    cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc");
-    if (!qt4Moc) {
-      cmSystemTools::Error("Qt4::moc target not found ",
-                           autogenTargetName.c_str());
-      return;
+    // Add definition or error
+    if (err.empty()) {
+      AddDefinitionEscaped(makefile, "_qt_moc_executable",
+                           mocExec ? mocExec : "");
+    } else {
+      cmSystemTools::Error(err.c_str());
     }
-    makefile->AddDefinition("_qt_moc_executable",
-                            qt4Moc->ImportedGetLocation(""));
-  } else {
-    cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and "
-                         "Qt 5 ",
-                         autogenTargetName.c_str());
   }
 }
 
@@ -268,126 +436,137 @@ static void UicGetOpts(cmGeneratorTarget const* target,
 }
 
 static void UicSetupAutoTarget(
-  cmGeneratorTarget const* target, std::vector<std::string> const& skipUic,
+  cmGeneratorTarget const* target, std::string const& qtMajorVersion,
+  std::string const& config, std::vector<std::string> const& configs,
+  std::vector<std::string> const& uicSkipList,
   std::map<std::string, std::string>& configUicOptions)
 {
   cmLocalGenerator* lg = target->GetLocalGenerator();
   cmMakefile* makefile = target->Target->GetMakefile();
 
-  std::set<std::string> skipped;
-  skipped.insert(skipUic.begin(), skipUic.end());
+  AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList);
 
-  makefile->AddDefinition(
-    "_skip_uic",
-    cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str());
-
-  std::vector<cmSourceFile*> uiFilesWithOptions =
-    makefile->GetQtUiFilesWithOptions();
-
-  const char* qtVersion = makefile->GetDefinition("_target_qt_version");
-
-  std::string _uic_opts;
-  std::vector<std::string> configs;
-  const std::string& config = makefile->GetConfigurations(configs);
-  UicGetOpts(target, config, _uic_opts);
-
-  if (!_uic_opts.empty()) {
-    _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts);
-    makefile->AddDefinition("_uic_target_options", _uic_opts.c_str());
-  }
-  for (std::vector<std::string>::const_iterator li = configs.begin();
-       li != configs.end(); ++li) {
-    std::string config_uic_opts;
-    UicGetOpts(target, *li, config_uic_opts);
-    if (config_uic_opts != _uic_opts) {
-      configUicOptions[*li] =
-        cmOutputConverter::EscapeForCMake(config_uic_opts);
-      if (_uic_opts.empty()) {
-        _uic_opts = config_uic_opts;
+  // Uic search paths
+  {
+    std::vector<std::string> uicSearchPaths;
+    cmSystemTools::ExpandListArgument(
+      GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS"), uicSearchPaths);
+    const std::string srcDir = makefile->GetCurrentSourceDirectory();
+    for (std::vector<std::string>::iterator it = uicSearchPaths.begin();
+         it != uicSearchPaths.end(); ++it) {
+      *it = cmSystemTools::CollapseFullPath(*it, srcDir);
+    }
+    AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
+  }
+  // Uic target options
+  {
+    // Default settings
+    std::string uicOpts;
+    UicGetOpts(target, config, uicOpts);
+    AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
+
+    // Configuration specific settings
+    for (std::vector<std::string>::const_iterator li = configs.begin();
+         li != configs.end(); ++li) {
+      std::string configUicOpts;
+      UicGetOpts(target, *li, configUicOpts);
+      if (configUicOpts != uicOpts) {
+        configUicOptions[*li] =
+          cmOutputConverter::EscapeForCMake(configUicOpts);
       }
     }
   }
-
-  std::string uiFileFiles;
-  std::string uiFileOptions;
-  const char* sep = "";
-
-  for (std::vector<cmSourceFile*>::const_iterator fileIt =
-         uiFilesWithOptions.begin();
-       fileIt != uiFilesWithOptions.end(); ++fileIt) {
-    cmSourceFile* sf = *fileIt;
-    std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath());
-
-    if (!skipped.insert(absFile).second) {
-      continue;
+  // Uic files options
+  {
+    std::vector<std::string> uiFileFiles;
+    std::vector<std::string> uiFileOptions;
+    {
+      std::set<std::string> skipped;
+      skipped.insert(uicSkipList.begin(), uicSkipList.end());
+
+      const std::vector<cmSourceFile*> uiFilesWithOptions =
+        makefile->GetQtUiFilesWithOptions();
+      for (std::vector<cmSourceFile*>::const_iterator fileIt =
+             uiFilesWithOptions.begin();
+           fileIt != uiFilesWithOptions.end(); ++fileIt) {
+        cmSourceFile* sf = *fileIt;
+        const std::string absFile =
+          cmsys::SystemTools::GetRealPath(sf->GetFullPath());
+        if (skipped.insert(absFile).second) {
+          // The file wasn't skipped
+          uiFileFiles.push_back(absFile);
+          {
+            std::string opts = sf->GetProperty("AUTOUIC_OPTIONS");
+            cmSystemTools::ReplaceString(opts, ";",
+                                         cmQtAutoGeneratorCommon::listSep);
+            uiFileOptions.push_back(opts);
+          }
+        }
+      }
     }
-    uiFileFiles += sep;
-    uiFileFiles += absFile;
-    uiFileOptions += sep;
-    std::string opts = sf->GetProperty("AUTOUIC_OPTIONS");
-    cmSystemTools::ReplaceString(opts, ";", "@list_sep@");
-    uiFileOptions += opts;
-    sep = ";";
+    AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
+    AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
   }
 
-  makefile->AddDefinition(
-    "_qt_uic_options_files",
-    cmOutputConverter::EscapeForCMake(uiFileFiles).c_str());
-  makefile->AddDefinition(
-    "_qt_uic_options_options",
-    cmOutputConverter::EscapeForCMake(uiFileOptions).c_str());
-
-  std::string targetName = target->GetName();
-  if (strcmp(qtVersion, "5") == 0) {
-    cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic");
-    if (!qt5Uic) {
-      // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
+  // Uic executable
+  {
+    std::string err;
+    const char* uicExec = CM_NULLPTR;
+    if (qtMajorVersion == "5") {
+      cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic");
+      if (qt5Uic != CM_NULLPTR) {
+        uicExec = qt5Uic->ImportedGetLocation("");
+      } else {
+        // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
+      }
+    } else if (qtMajorVersion == "4") {
+      cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic");
+      if (qt4Uic != CM_NULLPTR) {
+        uicExec = qt4Uic->ImportedGetLocation("");
+      } else {
+        err = "Qt4::uic target not found " + target->GetName();
+      }
     } else {
-      makefile->AddDefinition("_qt_uic_executable",
-                              qt5Uic->ImportedGetLocation(""));
+      err = "The CMAKE_AUTOUIC feature supports only Qt 4 and Qt 5 ";
+      err += target->GetName();
     }
-  } else if (strcmp(qtVersion, "4") == 0) {
-    cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic");
-    if (!qt4Uic) {
-      cmSystemTools::Error("Qt4::uic target not found ", targetName.c_str());
-      return;
+    // Add definition or error
+    if (err.empty()) {
+      AddDefinitionEscaped(makefile, "_qt_uic_executable",
+                           uicExec ? uicExec : "");
+    } else {
+      cmSystemTools::Error(err.c_str());
     }
-    makefile->AddDefinition("_qt_uic_executable",
-                            qt4Uic->ImportedGetLocation(""));
-  } else {
-    cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and "
-                         "Qt 5 ",
-                         targetName.c_str());
   }
 }
 
 static std::string RccGetExecutable(cmGeneratorTarget const* target,
                                     const std::string& qtMajorVersion)
 {
+  std::string rccExec;
   cmLocalGenerator* lg = target->GetLocalGenerator();
-
-  std::string const& targetName = target->GetName();
   if (qtMajorVersion == "5") {
     cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc");
-    if (!qt5Rcc) {
-      cmSystemTools::Error("Qt5::rcc target not found ", targetName.c_str());
-      return std::string();
+    if (qt5Rcc != CM_NULLPTR) {
+      rccExec = qt5Rcc->ImportedGetLocation("");
+    } else {
+      cmSystemTools::Error("Qt5::rcc target not found ",
+                           target->GetName().c_str());
     }
-    return qt5Rcc->ImportedGetLocation("");
-  }
-  if (qtMajorVersion == "4") {
+  } else if (qtMajorVersion == "4") {
     cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc");
-    if (!qt4Rcc) {
-      cmSystemTools::Error("Qt4::rcc target not found ", targetName.c_str());
-      return std::string();
+    if (qt4Rcc != CM_NULLPTR) {
+      rccExec = qt4Rcc->ImportedGetLocation("");
+    } else {
+      cmSystemTools::Error("Qt4::rcc target not found ",
+                           target->GetName().c_str());
     }
-    return qt4Rcc->ImportedGetLocation("");
+  } else {
+    cmSystemTools::Error(
+      "The CMAKE_AUTORCC feature supports only Qt 4 and Qt 5 ",
+      target->GetName().c_str());
   }
-
-  cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and "
-                       "Qt 5 ",
-                       targetName.c_str());
-  return std::string();
+  return rccExec;
 }
 
 static void RccMergeOptions(std::vector<std::string>& opts,
@@ -397,255 +576,104 @@ static void RccMergeOptions(std::vector<std::string>& opts,
   static const char* valueOptions[] = { "name", "root", "compress",
                                         "threshold" };
   std::vector<std::string> extraOpts;
-  for (std::vector<std::string>::const_iterator it = fileOpts.begin();
-       it != fileOpts.end(); ++it) {
+  for (std::vector<std::string>::const_iterator fit = fileOpts.begin();
+       fit != fileOpts.end(); ++fit) {
     std::vector<std::string>::iterator existingIt =
-      std::find(opts.begin(), opts.end(), *it);
+      std::find(opts.begin(), opts.end(), *fit);
     if (existingIt != opts.end()) {
-      const char* o = it->c_str();
-      if (*o == '-') {
-        ++o;
-      }
-      if (isQt5 && *o == '-') {
-        ++o;
+      const char* optName = fit->c_str();
+      if (*optName == '-') {
+        ++optName;
+        if (isQt5 && *optName == '-') {
+          ++optName;
+        }
       }
-      if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
-                       cmStrCmp(*it)) != cmArrayEnd(valueOptions)) {
-        assert(existingIt + 1 != opts.end());
-        *(existingIt + 1) = *(it + 1);
-        ++it;
+      // Test if this is a value option and change the existing value
+      if ((optName != fit->c_str()) &&
+          std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
+                       cmStrCmp(optName)) != cmArrayEnd(valueOptions)) {
+        const std::vector<std::string>::iterator existValueIt(existingIt + 1);
+        const std::vector<std::string>::const_iterator fileValueIt(fit + 1);
+        if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) {
+          *existValueIt = *fileValueIt;
+          ++fit;
+        }
       }
     } else {
-      extraOpts.push_back(*it);
+      extraOpts.push_back(*fit);
     }
   }
   opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
 }
 
-/// @brief Reads the resource files list from from a .qrc file - Qt5 version
-/// @return True if the .qrc file was successfully parsed
-static bool RccListInputsQt5(cmSourceFile* sf, cmGeneratorTarget const* target,
-                             std::vector<std::string>& depends)
-{
-  const std::string rccCommand = RccGetExecutable(target, "5");
-  if (rccCommand.empty()) {
-    cmSystemTools::Error("AUTOGEN: error: rcc executable not available\n");
-    return false;
-  }
-
-  bool hasDashDashList = false;
-  // Read rcc features
-  {
-    std::vector<std::string> command;
-    command.push_back(rccCommand);
-    command.push_back("--help");
-    std::string rccStdOut;
-    std::string rccStdErr;
-    int retVal = 0;
-    bool result =
-      cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
-                                      CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
-    if (result && retVal == 0 &&
-        rccStdOut.find("--list") != std::string::npos) {
-      hasDashDashList = true;
-    }
-  }
-  // Run rcc list command
-  std::vector<std::string> command;
-  command.push_back(rccCommand);
-  command.push_back(hasDashDashList ? "--list" : "-list");
-
-  std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath());
-  command.push_back(absFile);
-
-  std::string rccStdOut;
-  std::string rccStdErr;
-  int retVal = 0;
-  bool result =
-    cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
-                                    CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
-  if (!result || retVal) {
-    std::ostringstream err;
-    err << "AUTOGEN: error: Rcc list process for " << sf->GetFullPath()
-        << " failed:\n"
-        << rccStdOut << "\n"
-        << rccStdErr << std::endl;
-    cmSystemTools::Error(err.str().c_str());
-    return false;
-  }
-
-  // Parse rcc list output
-  {
-    std::istringstream ostr(rccStdOut);
-    std::string oline;
-    while (std::getline(ostr, oline)) {
-      oline = utilStripCR(oline);
-      if (!oline.empty()) {
-        depends.push_back(oline);
-      }
-    }
-  }
-
-  {
-    std::istringstream estr(rccStdErr);
-    std::string eline;
-    while (std::getline(estr, eline)) {
-      eline = utilStripCR(eline);
-      if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
-        static std::string searchString = "Cannot find file '";
-
-        std::string::size_type pos = eline.find(searchString);
-        if (pos == std::string::npos) {
-          std::ostringstream err;
-          err << "AUTOGEN: error: Rcc lists unparsable output " << eline
-              << std::endl;
-          cmSystemTools::Error(err.str().c_str());
-          return false;
-        }
-        pos += searchString.length();
-        std::string::size_type sz = eline.size() - pos - 1;
-        depends.push_back(eline.substr(pos, sz));
-      }
-    }
-  }
-
-  return true;
-}
-
-/// @brief Reads the resource files list from from a .qrc file - Qt4 version
-/// @return True if the .qrc file was successfully parsed
-static bool RccListInputsQt4(cmSourceFile* sf,
-                             std::vector<std::string>& depends)
-{
-  // Read file into string
-  std::string qrcContents;
-  {
-    std::ostringstream stream;
-    stream << cmsys::ifstream(sf->GetFullPath().c_str()).rdbuf();
-    qrcContents = stream.str();
-  }
-
-  cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
-
-  size_t offset = 0;
-  while (fileMatchRegex.find(qrcContents.c_str() + offset)) {
-    std::string qrcEntry = fileMatchRegex.match(1);
-
-    offset += qrcEntry.size();
-
-    cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
-    fileReplaceRegex.find(qrcEntry);
-    std::string tag = fileReplaceRegex.match(1);
-
-    qrcEntry = qrcEntry.substr(tag.size());
-
-    if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) {
-      qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry;
-    }
-
-    depends.push_back(qrcEntry);
-  }
-  return true;
-}
-
-/// @brief Reads the resource files list from from a .qrc file
-/// @return True if the rcc file was successfully parsed
-static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf,
-                          cmGeneratorTarget const* target,
-                          std::vector<std::string>& depends)
-{
-  if (qtMajorVersion == "5") {
-    return RccListInputsQt5(sf, target, depends);
-  }
-  return RccListInputsQt4(sf, depends);
-}
-
 static void RccSetupAutoTarget(cmGeneratorTarget const* target,
                                const std::string& qtMajorVersion)
 {
-  std::string _rcc_files;
-  const char* sepRccFiles = "";
   cmMakefile* makefile = target->Target->GetMakefile();
-
-  std::vector<cmSourceFile*> srcFiles;
-  target->GetConfigCommonSourceFiles(srcFiles);
-
-  std::string qrcInputs;
-  const char* qrcInputsSep = "";
-
-  std::string rccFileFiles;
-  std::string rccFileOptions;
-  const char* optionSep = "";
-
   const bool qtMajorVersion5 = (qtMajorVersion == "5");
-
-  std::vector<std::string> rccOptions;
+  const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
+  std::vector<std::string> _rcc_files;
+  std::vector<std::string> _rcc_inputs;
+  std::vector<std::string> rccFileFiles;
+  std::vector<std::string> rccFileOptions;
+  std::vector<std::string> rccOptionsTarget;
   if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) {
-    cmSystemTools::ExpandListArgument(opts, rccOptions);
+    cmSystemTools::ExpandListArgument(opts, rccOptionsTarget);
   }
 
+  std::vector<cmSourceFile*> srcFiles;
+  target->GetConfigCommonSourceFiles(srcFiles);
   for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
        fileIt != srcFiles.end(); ++fileIt) {
     cmSourceFile* sf = *fileIt;
-    std::string ext = sf->GetExtension();
-    if (ext == "qrc") {
-      std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath());
-      const bool skip =
-        cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) ||
-        cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"));
-
-      if (!skip) {
-        _rcc_files += sepRccFiles;
-        _rcc_files += absFile;
-        sepRccFiles = ";";
-
+    if ((sf->GetExtension() == "qrc") &&
+        !PropertyEnabled(sf, "SKIP_AUTOGEN") &&
+        !PropertyEnabled(sf, "SKIP_AUTORCC")) {
+      const std::string absFile =
+        cmsys::SystemTools::GetRealPath(sf->GetFullPath());
+      // qrc file
+      _rcc_files.push_back(absFile);
+      // qrc file entries
+      {
+        std::string entriesList = "{";
+        // Read input file list only for non generated .qrc files.
+        if (!PropertyEnabled(sf, "GENERATED")) {
+          std::string error;
+          std::vector<std::string> files;
+          if (cmQtAutoGeneratorCommon::RccListInputs(
+                qtMajorVersion, rccCommand, absFile, files, &error)) {
+            entriesList += cmJoin(files, cmQtAutoGeneratorCommon::listSep);
+          } else {
+            cmSystemTools::Error(error.c_str());
+          }
+        }
+        entriesList += "}";
+        _rcc_inputs.push_back(entriesList);
+      }
+      // rcc options for this qrc file
+      {
+        // Merged target and file options
+        std::vector<std::string> rccOptions(rccOptionsTarget);
         if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) {
           std::vector<std::string> optsVec;
           cmSystemTools::ExpandListArgument(prop, optsVec);
           RccMergeOptions(rccOptions, optsVec, qtMajorVersion5);
         }
-
+        // Only store non empty options lists
         if (!rccOptions.empty()) {
-          rccFileFiles += optionSep;
-          rccFileFiles += absFile;
-          rccFileOptions += optionSep;
-        }
-        const char* listSep = "";
-        for (std::vector<std::string>::const_iterator it = rccOptions.begin();
-             it != rccOptions.end(); ++it) {
-          rccFileOptions += listSep;
-          rccFileOptions += *it;
-          listSep = "@list_sep@";
+          rccFileFiles.push_back(absFile);
+          rccFileOptions.push_back(
+            cmJoin(rccOptions, cmQtAutoGeneratorCommon::listSep));
         }
-        optionSep = ";";
-
-        std::string entriesList;
-        if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
-          std::vector<std::string> depends;
-          if (RccListInputs(qtMajorVersion, sf, target, depends)) {
-            entriesList = cmJoin(depends, "@list_sep@");
-          } else {
-            return;
-          }
-        }
-        qrcInputs += qrcInputsSep;
-        qrcInputs += entriesList;
-        qrcInputsSep = ";";
       }
     }
   }
-  makefile->AddDefinition(
-    "_rcc_inputs", cmOutputConverter::EscapeForCMake(qrcInputs).c_str());
-  makefile->AddDefinition(
-    "_rcc_files", cmOutputConverter::EscapeForCMake(_rcc_files).c_str());
-  makefile->AddDefinition(
-    "_rcc_options_files",
-    cmOutputConverter::EscapeForCMake(rccFileFiles).c_str());
-  makefile->AddDefinition(
-    "_rcc_options_options",
-    cmOutputConverter::EscapeForCMake(rccFileOptions).c_str());
-  makefile->AddDefinition("_qt_rcc_executable",
-                          RccGetExecutable(target, qtMajorVersion).c_str());
+
+  AddDefinitionEscaped(makefile, "_qt_rcc_executable", rccCommand);
+  AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files);
+  AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs);
+  AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles);
+  AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions);
 }
 
 void cmQtAutoGeneratorInitializer::InitializeAutogenSources(
@@ -653,11 +681,24 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenSources(
 {
   if (target->GetPropertyAsBool("AUTOMOC")) {
     cmMakefile* makefile = target->Target->GetMakefile();
-    const std::string mocCppFile =
-      GetAutogenTargetBuildDir(target) + "moc_compilation.cpp";
-    cmSourceFile* gf = makefile->GetOrCreateSource(mocCppFile, true);
-    gf->SetProperty("SKIP_AUTOGEN", "On");
-    target->AddSource(mocCppFile);
+    const std::vector<std::string> suffixes =
+      GetConfigurationSuffixes(makefile);
+    // Get build directory
+    const std::string autogenBuildDir = GetAutogenTargetBuildDir(target);
+    // Register all compilation files as generated
+    for (std::vector<std::string>::const_iterator it = suffixes.begin();
+         it != suffixes.end(); ++it) {
+      std::string mcFile = autogenBuildDir + "/mocs_compilation";
+      mcFile += *it;
+      mcFile += ".cpp";
+      AddGeneratedSource(makefile, mcFile, cmQtAutoGeneratorCommon::MOC);
+    }
+    // Mocs compilation file
+    if (IsMultiConfig(target->GetGlobalGenerator())) {
+      target->AddSource(autogenBuildDir + "/mocs_compilation_$<CONFIG>.cpp");
+    } else {
+      target->AddSource(autogenBuildDir + "/mocs_compilation.cpp");
+    }
   }
 }
 
@@ -667,45 +708,33 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
   cmMakefile* makefile = target->Target->GetMakefile();
 
   // Create a custom target for running generators at buildtime
+  const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
+  const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
+  const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
+  const bool multiConfig = IsMultiConfig(target->GetGlobalGenerator());
   const std::string autogenTargetName = GetAutogenTargetName(target);
   const std::string autogenBuildDir = GetAutogenTargetBuildDir(target);
   const std::string workingDirectory =
     cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
   const std::string qtMajorVersion = GetQtMajorVersion(target);
-  std::vector<std::string> autogenOutputFiles;
-
-  // Remove old settings on cleanup
-  {
-    std::string fname = GetAutogenTargetFilesDir(target);
-    fname += "/AutogenOldSettings.cmake";
-    makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fname.c_str(),
-                             false);
-  }
+  const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
+  const std::vector<std::string> suffixes = GetConfigurationSuffixes(makefile);
+  std::vector<std::string> autogenDepends;
+  std::vector<std::string> autogenProvides;
 
-  // Create autogen target build directory and add it to the clean files
-  cmSystemTools::MakeDirectory(autogenBuildDir);
+  // Remove build directories on cleanup
   makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
                            autogenBuildDir.c_str(), false);
 
-  if (target->GetPropertyAsBool("AUTOMOC") ||
-      target->GetPropertyAsBool("AUTOUIC")) {
-    // Create autogen target includes directory and
-    // add it to the origin target INCLUDE_DIRECTORIES
-    const std::string incsDir = autogenBuildDir + "include";
-    cmSystemTools::MakeDirectory(incsDir);
-    target->AddIncludeDirectory(incsDir, true);
-  }
-
-  if (target->GetPropertyAsBool("AUTOMOC")) {
-    // Register moc compilation file as generated
-    autogenOutputFiles.push_back(autogenBuildDir + "moc_compilation.cpp");
-  }
-
-  // Initialize autogen target dependencies
-  std::vector<std::string> depends;
-  if (const char* autogenDepends =
-        target->GetProperty("AUTOGEN_TARGET_DEPENDS")) {
-    cmSystemTools::ExpandListArgument(autogenDepends, depends);
+  // Remove old settings on cleanup
+  {
+    std::string base = GetAutogenTargetFilesDir(target);
+    for (std::vector<std::string>::const_iterator it = suffixes.begin();
+         it != suffixes.end(); ++it) {
+      std::string fname = base + "/AutogenOldSettings" + *it + ".cmake";
+      makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fname.c_str(),
+                               false);
+    }
   }
 
   // Compose command lines
@@ -724,13 +753,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
   std::string autogenComment;
   {
     std::vector<std::string> toolNames;
-    if (target->GetPropertyAsBool("AUTOMOC")) {
+    if (mocEnabled) {
       toolNames.push_back("MOC");
     }
-    if (target->GetPropertyAsBool("AUTOUIC")) {
+    if (uicEnabled) {
       toolNames.push_back("UIC");
     }
-    if (target->GetPropertyAsBool("AUTORCC")) {
+    if (rccEnabled) {
       toolNames.push_back("RCC");
     }
 
@@ -746,76 +775,140 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
     autogenComment = "Automatic " + tools + " for target " + target->GetName();
   }
 
+  // Add moc compilation to generated files list
+  if (mocEnabled) {
+    for (std::vector<std::string>::const_iterator it = suffixes.begin();
+         it != suffixes.end(); ++it) {
+      std::string mcFile = autogenBuildDir + "/mocs_compilation";
+      mcFile += *it;
+      mcFile += ".cpp";
+      autogenProvides.push_back(mcFile);
+    }
+  }
+
+  // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
+  if (mocEnabled || uicEnabled) {
+    if (multiConfig) {
+      target->AddIncludeDirectory(autogenBuildDir + "/include_$<CONFIG>",
+                                  true);
+
+    } else {
+      target->AddIncludeDirectory(autogenBuildDir + "/include", true);
+    }
+  }
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
   bool usePRE_BUILD = false;
   cmGlobalGenerator* gg = lg->GetGlobalGenerator();
   if (gg->GetName().find("Visual Studio") != std::string::npos) {
-    cmGlobalVisualStudioGenerator* vsgg =
-      static_cast<cmGlobalVisualStudioGenerator*>(gg);
-    // Under VS >= 7 use a PRE_BUILD event instead of a separate target to
+    // Under VS use a PRE_BUILD event instead of a separate target to
     // reduce the number of targets loaded into the IDE.
     // This also works around a VS 11 bug that may skip updating the target:
     //  https://connect.microsoft.com/VisualStudio/feedback/details/769495
-    usePRE_BUILD = vsgg->GetVersion() >= cmGlobalVisualStudioGenerator::VS7;
-    if (usePRE_BUILD) {
-      // If the autogen target depends on an other target
-      // don't use PRE_BUILD
-      for (std::vector<std::string>::iterator it = depends.begin();
-           it != depends.end(); ++it) {
-        if (!makefile->FindTargetToUse(it->c_str())) {
-          usePRE_BUILD = false;
-          break;
-        }
-      }
-    }
+    usePRE_BUILD = true;
   }
 #endif
 
-  if (target->GetPropertyAsBool("AUTORCC")) {
+  // Initialize autogen target dependencies
+  if (const char* deps = target->GetProperty("AUTOGEN_TARGET_DEPENDS")) {
+    cmSystemTools::ExpandListArgument(deps, autogenDepends);
+  }
+  // Add link library targets to the autogen dependencies
+  {
+    const cmTarget::LinkLibraryVectorType& libVec =
+      target->Target->GetOriginalLinkLibraries();
+    for (cmTarget::LinkLibraryVectorType::const_iterator it = libVec.begin();
+         it != libVec.end(); ++it) {
+      const std::string& libName = it->first;
+      if (makefile->FindTargetToUse(libName) != CM_NULLPTR) {
+        autogenDepends.push_back(libName);
+      }
+    }
+  }
+  {
     cmFilePathChecksum fpathCheckSum(makefile);
+    // Iterate over all source files
     std::vector<cmSourceFile*> srcFiles;
     target->GetConfigCommonSourceFiles(srcFiles);
     for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
          fileIt != srcFiles.end(); ++fileIt) {
       cmSourceFile* sf = *fileIt;
-      if (sf->GetExtension() == "qrc" &&
-          !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) &&
-          !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) {
-        {
+      if (!PropertyEnabled(sf, "SKIP_AUTOGEN")) {
+        std::string const& ext = sf->GetExtension();
+        // Add generated file that will be scanned by moc or uic to
+        // the dependencies
+        if (mocEnabled || uicEnabled) {
+          const cmSystemTools::FileFormat fileType =
+            cmSystemTools::GetFileFormat(ext.c_str());
+          if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
+              (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
+            if (PropertyEnabled(sf, "GENERATED")) {
+              if ((mocEnabled && !PropertyEnabled(sf, "SKIP_AUTOMOC")) ||
+                  (uicEnabled && !PropertyEnabled(sf, "SKIP_AUTOUIC"))) {
+                autogenDepends.push_back(
+                  cmsys::SystemTools::GetRealPath(sf->GetFullPath()));
+#if defined(_WIN32) && !defined(__CYGWIN__)
+                // Cannot use PRE_BUILD with generated files
+                usePRE_BUILD = false;
+#endif
+              }
+            }
+          }
+        }
+        // Process rcc enabled files
+        if (rccEnabled && (ext == "qrc") &&
+            !PropertyEnabled(sf, "SKIP_AUTORCC")) {
           const std::string absFile =
             cmsys::SystemTools::GetRealPath(sf->GetFullPath());
 
-          // Run cmake again when .qrc file changes
-          makefile->AddCMakeDependFile(absFile);
-
-          std::string rccOutputFile = autogenBuildDir;
-          rccOutputFile += fpathCheckSum.getPart(absFile);
-          rccOutputFile += "/qrc_";
-          rccOutputFile +=
-            cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
-          rccOutputFile += ".cpp";
-
-          // Add rcc output file to origin target sources
-          cmSourceFile* gf = makefile->GetOrCreateSource(rccOutputFile, true);
-          gf->SetProperty("SKIP_AUTOGEN", "On");
-          target->AddSource(rccOutputFile);
-          // Register rcc output file as generated
-          autogenOutputFiles.push_back(rccOutputFile);
-        }
-        if (lg->GetGlobalGenerator()->GetName() == "Ninja"
-#if defined(_WIN32) && !defined(__CYGWIN__)
-            || usePRE_BUILD
-#endif
-            ) {
-          if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
-            RccListInputs(qtMajorVersion, sf, target, depends);
+          // Compose rcc output file name
+          {
+            std::string rccOutBase = autogenBuildDir + "/";
+            rccOutBase += fpathCheckSum.getPart(absFile);
+            rccOutBase += "/qrc_";
+            rccOutBase +=
+              cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
+
+            // Register rcc ouput file as generated
+            for (std::vector<std::string>::const_iterator it =
+                   suffixes.begin();
+                 it != suffixes.end(); ++it) {
+              std::string rccOutCfg = rccOutBase;
+              rccOutCfg += *it;
+              rccOutCfg += ".cpp";
+              AddGeneratedSource(makefile, rccOutCfg,
+                                 cmQtAutoGeneratorCommon::RCC);
+              autogenProvides.push_back(rccOutCfg);
+            }
+            // Add rcc output file to origin target sources
+            if (multiConfig) {
+              target->AddSource(rccOutBase + "_$<CONFIG>.cpp");
+            } else {
+              target->AddSource(rccOutBase + ".cpp");
+            }
+          }
+
+          if (PropertyEnabled(sf, "GENERATED")) {
+            // Add generated qrc file to the dependencies
+            autogenDepends.push_back(absFile);
+          } else {
+            // Run cmake again when .qrc file changes
+            makefile->AddCMakeDependFile(absFile);
+
+            // Add the qrc input files to the dependencies
+            std::string error;
+            if (!cmQtAutoGeneratorCommon::RccListInputs(
+                  qtMajorVersion, rccCommand, absFile, autogenDepends,
+                  &error)) {
+              cmSystemTools::Error(error.c_str());
+            }
+          }
 #if defined(_WIN32) && !defined(__CYGWIN__)
-            // Cannot use PRE_BUILD because the resource files themselves
-            // may not be sources within the target so VS may not know the
-            // target needs to re-build at all.
-            usePRE_BUILD = false;
+          // Cannot use PRE_BUILD because the resource files themselves
+          // may not be sources within the target so VS may not know the
+          // target needs to re-build at all.
+          usePRE_BUILD = false;
 #endif
-          }
         }
       }
     }
@@ -823,12 +916,21 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
   if (usePRE_BUILD) {
+    // If the autogen target depends on an other target don't use PRE_BUILD
+    for (std::vector<std::string>::iterator it = autogenDepends.begin();
+         it != autogenDepends.end(); ++it) {
+      if (makefile->FindTargetToUse(*it) != CM_NULLPTR) {
+        usePRE_BUILD = false;
+        break;
+      }
+    }
+  }
+  if (usePRE_BUILD) {
     // Add the pre-build command directly to bypass the OBJECT_LIBRARY
     // rejection in cmMakefile::AddCustomCommandToTarget because we know
     // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
     std::vector<std::string> no_output;
-    std::vector<std::string> no_byproducts;
-    cmCustomCommand cc(makefile, no_output, no_byproducts, depends,
+    cmCustomCommand cc(makefile, no_output, autogenProvides, autogenDepends,
                        commandLines, autogenComment.c_str(),
                        workingDirectory.c_str());
     cc.SetEscapeOldStyle(false);
@@ -839,7 +941,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
   {
     cmTarget* autogenTarget = makefile->AddUtilityCommand(
       autogenTargetName, true, workingDirectory.c_str(),
-      /*byproducts=*/autogenOutputFiles, depends, commandLines, false,
+      /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
       autogenComment.c_str());
 
     cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg);
@@ -872,61 +974,72 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
   cmMakefile::ScopePushPop varScope(makefile);
   static_cast<void>(varScope);
 
-  // create a custom target for running generators at buildtime:
-  const std::string autogenTargetName = GetAutogenTargetName(target);
-  const std::string qtMajorVersion = GetQtMajorVersion(target);
+  // Get configurations
+  std::string config;
+  const std::vector<std::string> configs(GetConfigurations(makefile, &config));
 
-  makefile->AddDefinition(
-    "_moc_target_name",
-    cmOutputConverter::EscapeForCMake(autogenTargetName).c_str());
-  makefile->AddDefinition(
-    "_origin_target_name",
-    cmOutputConverter::EscapeForCMake(target->GetName()).c_str());
-  makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str());
-
-  std::vector<std::string> mocUicSources;
-  std::vector<std::string> mocUicHeaders;
-  std::vector<std::string> skipMoc;
-  std::vector<std::string> skipUic;
+  // Configurations settings buffers
+  std::map<std::string, std::string> configSuffix;
   std::map<std::string, std::string> configMocIncludes;
   std::map<std::string, std::string> configMocDefines;
   std::map<std::string, std::string> configUicOptions;
 
-  if (target->GetPropertyAsBool("AUTOMOC") ||
-      target->GetPropertyAsBool("AUTOUIC") ||
-      target->GetPropertyAsBool("AUTORCC")) {
-    SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic);
+  // Configuration suffix
+  if (IsMultiConfig(target->GetGlobalGenerator())) {
+    for (std::vector<std::string>::const_iterator it = configs.begin();
+         it != configs.end(); ++it) {
+      configSuffix[*it] = "_" + *it;
+    }
   }
-  makefile->AddDefinition(
-    "_moc_uic_sources",
-    cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str());
-  makefile->AddDefinition(
-    "_moc_uic_headers",
-    cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str());
 
-  if (target->GetPropertyAsBool("AUTOMOC")) {
-    MocSetupAutoTarget(target, autogenTargetName, skipMoc, configMocIncludes,
-                       configMocDefines);
-  }
-  if (target->GetPropertyAsBool("AUTOUIC")) {
-    UicSetupAutoTarget(target, skipUic, configUicOptions);
-  }
-  if (target->GetPropertyAsBool("AUTORCC")) {
-    RccSetupAutoTarget(target, qtMajorVersion);
-  }
+  // Basic setup
+  {
+    const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
+    const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
+    const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
+    const std::string autogenTargetName = GetAutogenTargetName(target);
+    const std::string qtMajorVersion = GetQtMajorVersion(target);
+
+    std::vector<std::string> sources;
+    std::vector<std::string> headers;
+
+    if (mocEnabled || uicEnabled || rccEnabled) {
+      std::vector<std::string> mocSkipList;
+      std::vector<std::string> uicSkipList;
+      AcquireScanFiles(target, sources, headers, mocSkipList, uicSkipList);
+      if (mocEnabled) {
+        MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, config,
+                           configs, mocSkipList, configMocIncludes,
+                           configMocDefines);
+      }
+      if (uicEnabled) {
+        UicSetupAutoTarget(target, qtMajorVersion, config, configs,
+                           uicSkipList, configUicOptions);
+      }
+      if (rccEnabled) {
+        RccSetupAutoTarget(target, qtMajorVersion);
+      }
+    }
 
-  // Generate config file
-  std::string inputFile = cmSystemTools::GetCMakeRoot();
-  inputFile += "/Modules/AutogenInfo.cmake.in";
-  std::string outputFile = GetAutogenTargetFilesDir(target);
-  outputFile += "/AutogenInfo.cmake";
+    AddDefinitionEscaped(makefile, "_autogen_build_dir",
+                         GetAutogenTargetBuildDir(target));
+    AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion);
+    AddDefinitionEscaped(makefile, "_sources", sources);
+    AddDefinitionEscaped(makefile, "_headers", headers);
+  }
 
-  makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true,
-                          false);
+  // Generate info file
+  std::string infoFile = GetAutogenTargetFilesDir(target);
+  infoFile += "/AutogenInfo.cmake";
+  {
+    std::string inf = cmSystemTools::GetCMakeRoot();
+    inf += "/Modules/AutogenInfo.cmake.in";
+    makefile->ConfigureFile(inf.c_str(), infoFile.c_str(), false, true, false);
+  }
 
-  // Append custom definitions to config file
-  if (!configMocDefines.empty() || !configMocIncludes.empty() ||
-      !configUicOptions.empty()) {
+  // Append custom definitions to info file on demand
+  if (!configSuffix.empty() || !configMocDefines.empty() ||
+      !configMocIncludes.empty() || !configUicOptions.empty()) {
 
     // Ensure we have write permission in case .in was read-only.
     mode_t perm = 0;
@@ -935,45 +1048,49 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
 #else
     mode_t mode_write = S_IWUSR;
 #endif
-    cmSystemTools::GetPermissions(outputFile, perm);
+    cmSystemTools::GetPermissions(infoFile, perm);
     if (!(perm & mode_write)) {
-      cmSystemTools::SetPermissions(outputFile, perm | mode_write);
+      cmSystemTools::SetPermissions(infoFile, perm | mode_write);
     }
 
-    cmsys::ofstream infoFile(outputFile.c_str(), std::ios::app);
-    if (!infoFile) {
-      std::string error = "Internal CMake error when trying to open file: ";
-      error += outputFile;
-      error += " for writing.";
-      cmSystemTools::Error(error.c_str());
-      return;
-    }
-    if (!configMocDefines.empty()) {
+    // Open and write file
+    cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
+    if (ofs) {
+      ofs << "# Configuration specific options\n";
+      for (std::map<std::string, std::string>::iterator
+             it = configSuffix.begin(),
+             end = configSuffix.end();
+           it != end; ++it) {
+        ofs << "set(AM_CONFIG_SUFFIX_" << it->first << " " << it->second
+            << ")\n";
+      }
       for (std::map<std::string, std::string>::iterator
              it = configMocDefines.begin(),
              end = configMocDefines.end();
            it != end; ++it) {
-        infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " "
-                 << it->second << ")\n";
+        ofs << "set(AM_MOC_DEFINITIONS_" << it->first << " " << it->second
+            << ")\n";
       }
-    }
-    if (!configMocIncludes.empty()) {
       for (std::map<std::string, std::string>::iterator
              it = configMocIncludes.begin(),
              end = configMocIncludes.end();
            it != end; ++it) {
-        infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second
-                 << ")\n";
+        ofs << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second
+            << ")\n";
       }
-    }
-    if (!configUicOptions.empty()) {
       for (std::map<std::string, std::string>::iterator
              it = configUicOptions.begin(),
              end = configUicOptions.end();
            it != end; ++it) {
-        infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " "
-                 << it->second << ")\n";
+        ofs << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " << it->second
+            << ")\n";
       }
+    } else {
+      // File open error
+      std::string error = "Internal CMake error when trying to open file: ";
+      error += cmQtAutoGeneratorCommon::Quoted(infoFile);
+      error += " for writing.";
+      cmSystemTools::Error(error.c_str());
     }
   }
 }
diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h
index 26f2c8e..ca806f5 100644
--- a/Source/cmQtAutoGeneratorInitializer.h
+++ b/Source/cmQtAutoGeneratorInitializer.h
@@ -3,7 +3,7 @@
 #ifndef cmQtAutoGeneratorInitializer_h
 #define cmQtAutoGeneratorInitializer_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 class cmGeneratorTarget;
 class cmLocalGenerator;
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 1d6972b..042d111 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -1,19 +1,22 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQtAutoGenerators.h"
+#include "cmQtAutoGeneratorCommon.h"
 
+#include "cmConfigure.h"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Terminal.h"
 #include <algorithm>
 #include <assert.h>
-#include <cmConfigure.h>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Terminal.h>
-#include <iostream>
+#include <list>
 #include <sstream>
 #include <stdlib.h>
 #include <string.h>
 #include <utility>
 
 #include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmFilePathChecksum.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
@@ -29,70 +32,104 @@
 
 // -- Static variables
 
-static const char* MocOldSettingsKey = "AM_MOC_OLD_SETTINGS";
-static const char* UicOldSettingsKey = "AM_UIC_OLD_SETTINGS";
-static const char* RccOldSettingsKey = "AM_RCC_OLD_SETTINGS";
+static const char* SettingsKeyMoc = "AM_MOC_SETTINGS_HASH";
+static const char* SettingsKeyUic = "AM_UIC_SETTINGS_HASH";
+static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH";
 
 // -- Static functions
 
-static std::string GetConfigDefinition(cmMakefile* makefile,
-                                       const std::string& key,
-                                       const std::string& config)
+inline static std::string Quoted(const std::string& text)
 {
-  std::string keyConf = key;
-  if (!config.empty()) {
-    keyConf += "_";
-    keyConf += config;
-  }
-  const char* valueConf = makefile->GetDefinition(keyConf);
-  if (valueConf != CM_NULLPTR) {
-    return valueConf;
+  return cmQtAutoGeneratorCommon::Quoted(text);
+}
+
+static std::string QuotedCommand(const std::vector<std::string>& command)
+{
+  std::string res;
+  for (std::vector<std::string>::const_iterator cit = command.begin();
+       cit != command.end(); ++cit) {
+    if (!res.empty()) {
+      res.push_back(' ');
+    }
+    const std::string cesc = Quoted(*cit);
+    if (cit->empty() || (cesc.size() > (cit->size() + 2)) ||
+        (cesc.find(' ') != std::string::npos)) {
+      res += cesc;
+    } else {
+      res += *cit;
+    }
   }
-  return makefile->GetSafeDefinition(key);
+  return res;
 }
 
-static std::string OldSettingsFile(const std::string& targetDirectory)
+static void InfoGet(cmMakefile* makefile, const char* key, std::string& value)
 {
-  std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
-  cmSystemTools::ConvertToUnixSlashes(filename);
-  filename += "/AutogenOldSettings.cmake";
-  return filename;
+  value = makefile->GetSafeDefinition(key);
 }
 
-static std::string FindMatchingHeader(
-  const std::string& absPath, const std::string& mocSubDir,
-  const std::string& basename,
-  const std::vector<std::string>& headerExtensions)
+static void InfoGet(cmMakefile* makefile, const char* key, bool& value)
 {
-  std::string header;
-  for (std::vector<std::string>::const_iterator ext = headerExtensions.begin();
-       ext != headerExtensions.end(); ++ext) {
-    std::string sourceFilePath = absPath + basename + "." + (*ext);
-    if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) {
-      header = sourceFilePath;
-      break;
-    }
-    // Try subdirectory instead
-    if (!mocSubDir.empty()) {
-      sourceFilePath = mocSubDir + basename + "." + (*ext);
-      if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) {
-        header = sourceFilePath;
-        break;
-      }
+  value = makefile->IsOn(key);
+}
+
+static void InfoGet(cmMakefile* makefile, const char* key,
+                    std::vector<std::string>& list)
+{
+  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
+}
+
+static void InfoGetConfig(cmMakefile* makefile, const char* key,
+                          const std::string& config, std::string& value)
+{
+  const char* valueConf = CM_NULLPTR;
+  {
+    std::string keyConf = key;
+    if (!config.empty()) {
+      keyConf += "_";
+      keyConf += config;
     }
+    valueConf = makefile->GetDefinition(keyConf);
+  }
+  if (valueConf == CM_NULLPTR) {
+    valueConf = makefile->GetSafeDefinition(key);
   }
+  value = valueConf;
+}
 
-  return header;
+static void InfoGetConfig(cmMakefile* makefile, const char* key,
+                          const std::string& config,
+                          std::vector<std::string>& list)
+{
+  std::string value;
+  InfoGetConfig(makefile, key, config, value);
+  cmSystemTools::ExpandListArgument(value, list);
 }
 
-static std::string ExtractSubDir(const std::string& absPath,
-                                 const std::string& currentMoc)
+inline static bool SettingsMatch(cmMakefile* makefile, const char* key,
+                                 const std::string& value)
 {
-  std::string subDir;
-  if (currentMoc.find_first_of('/') != std::string::npos) {
-    subDir = absPath + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/';
+  return (value == makefile->GetSafeDefinition(key));
+}
+
+static void SettingAppend(std::string& str, const char* key,
+                          const std::string& value)
+{
+  if (!value.empty()) {
+    str += "set(";
+    str += key;
+    str += " ";
+    str += cmOutputConverter::EscapeForCMake(value);
+    str += ")\n";
   }
-  return subDir;
+}
+
+static std::string SubDirPrefix(const std::string& fileName)
+{
+  std::string res(cmsys::SystemTools::GetFilenamePath(fileName));
+  if (!res.empty()) {
+    res += '/';
+  }
+  return res;
 }
 
 static bool FileNameIsUnique(const std::string& filePath,
@@ -112,13 +149,19 @@ static bool FileNameIsUnique(const std::string& filePath,
   return true;
 }
 
-static std::string ReadAll(const std::string& filename)
+static bool ReadAll(std::string& content, const std::string& filename)
 {
-  cmsys::ifstream file(filename.c_str());
-  std::ostringstream stream;
-  stream << file.rdbuf();
-  file.close();
-  return stream.str();
+  bool success = false;
+  {
+    cmsys::ifstream ifs(filename.c_str());
+    if (ifs) {
+      std::ostringstream osst;
+      osst << ifs.rdbuf();
+      content = osst.str();
+      success = true;
+    }
+  }
+  return success;
 }
 
 /**
@@ -140,13 +183,19 @@ static bool ListContains(const std::vector<std::string>& list,
   return (std::find(list.begin(), list.end(), entry) != list.end());
 }
 
-static std::string JoinOptions(const std::map<std::string, std::string>& opts)
+static std::string JoinOptionsList(const std::vector<std::string>& opts)
+{
+  return cmOutputConverter::EscapeForCMake(cmJoin(opts, ";"));
+}
+
+static std::string JoinOptionsMap(
+  const std::map<std::string, std::string>& opts)
 {
   std::string result;
   for (std::map<std::string, std::string>::const_iterator it = opts.begin();
        it != opts.end(); ++it) {
     if (it != opts.begin()) {
-      result += "%%%";
+      result += cmQtAutoGeneratorCommon::listSep;
     }
     result += it->first;
     result += "===";
@@ -211,12 +260,13 @@ static void UicMergeOptions(std::vector<std::string>& opts,
 cmQtAutoGenerators::cmQtAutoGenerators()
   : Verbose(cmsys::SystemTools::HasEnv("VERBOSE"))
   , ColorOutput(true)
-  , RunMocFailed(false)
-  , RunUicFailed(false)
-  , RunRccFailed(false)
-  , GenerateMocAll(false)
-  , GenerateUicAll(false)
-  , GenerateRccAll(false)
+  , MocSettingsChanged(false)
+  , MocPredefsChanged(false)
+  , MocRunFailed(false)
+  , UicSettingsChanged(false)
+  , UicRunFailed(false)
+  , RccSettingsChanged(false)
+  , RccRunFailed(false)
 {
 
   std::string colorEnv;
@@ -229,20 +279,24 @@ cmQtAutoGenerators::cmQtAutoGenerators()
     }
   }
 
+  // Moc macro filters
+  this->MocMacroFilters[0].first = "Q_OBJECT";
+  this->MocMacroFilters[0].second.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
+  this->MocMacroFilters[1].first = "Q_GADGET";
+  this->MocMacroFilters[1].second.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]");
+
   // Precompile regular expressions
-  this->RegExpQObject.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
-  this->RegExpQGadget.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]");
-  this->RegExpMocInclude.compile(
+  this->MocRegExpInclude.compile(
     "[\n][ \t]*#[ \t]*include[ \t]+"
     "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
-  this->RegExpUicInclude.compile("[\n][ \t]*#[ \t]*include[ \t]+"
+  this->UicRegExpInclude.compile("[\n][ \t]*#[ \t]*include[ \t]+"
                                  "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
 }
 
 bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
                              const std::string& config)
 {
-  cmake cm;
+  cmake cm(cmake::RoleScript);
   cm.SetHomeOutputDirectory(targetDirectory);
   cm.SetHomeDirectory(targetDirectory);
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
@@ -255,23 +309,46 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
   CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, snapshot));
   gg.SetCurrentMakefile(mf.get());
 
-  if (!this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) {
-    return false;
-  }
-  // Read old settings
-  this->OldSettingsReadFile(mf.get(), targetDirectory);
-  // Init and run
-  this->Init();
-  if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") {
-    if (!this->RunAutogen(mf.get())) {
-      return false;
+  bool success = false;
+  if (this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) {
+    // Read old settings
+    this->SettingsFileRead(mf.get());
+    // Init and run
+    this->Init(mf.get());
+    if (this->RunAutogen()) {
+      // Write current settings
+      if (this->SettingsFileWrite()) {
+        success = true;
+      }
     }
   }
-  // Write latest settings
-  if (!this->OldSettingsWriteFile(targetDirectory)) {
-    return false;
+  return success;
+}
+
+bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key,
+                                             const std::string& regExp)
+{
+  bool success = false;
+  if (!key.empty()) {
+    if (!regExp.empty()) {
+      MocDependFilter filter;
+      filter.key = key;
+      if (filter.regExp.compile(regExp)) {
+        this->MocDependFilters.push_back(filter);
+        success = true;
+      } else {
+        this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling "
+                       "regular expression failed.\nKey:  " +
+                       Quoted(key) + "\nExp.: " + Quoted(regExp));
+      }
+    } else {
+      this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular "
+                     "expression is empty");
+    }
+  } else {
+    this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Key is empty");
   }
-  return true;
+  return success;
 }
 
 bool cmQtAutoGenerators::ReadAutogenInfoFile(
@@ -283,395 +360,420 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
   filename += "/AutogenInfo.cmake";
 
   if (!makefile->ReadListFile(filename.c_str())) {
-    std::ostringstream err;
-    err << "AutoGen: error processing file: " << filename << std::endl;
-    this->LogError(err.str());
+    this->LogError("AutoGen: Error processing file: " + filename);
     return false;
   }
 
-  // - Target names
-  this->OriginTargetName =
-    makefile->GetSafeDefinition("AM_ORIGIN_TARGET_NAME");
-  this->AutogenTargetName = makefile->GetSafeDefinition("AM_TARGET_NAME");
-
-  // - Directories
-  this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR");
-  this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR");
-  this->CurrentSourceDir =
-    makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR");
-  this->CurrentBinaryDir =
-    makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR");
+  // - Old settings file
+  {
+    this->SettingsFile = cmSystemTools::CollapseFullPath(targetDirectory);
+    cmSystemTools::ConvertToUnixSlashes(this->SettingsFile);
+    this->SettingsFile += "/AutogenOldSettings";
+    this->SettingsFile += this->ConfigSuffix;
+    this->SettingsFile += ".cmake";
+  }
+
+  // -- Meta
+  InfoGetConfig(makefile, "AM_CONFIG_SUFFIX", config, this->ConfigSuffix);
+
+  // - Files and directories
+  InfoGet(makefile, "AM_CMAKE_SOURCE_DIR", this->ProjectSourceDir);
+  InfoGet(makefile, "AM_CMAKE_BINARY_DIR", this->ProjectBinaryDir);
+  InfoGet(makefile, "AM_CMAKE_CURRENT_SOURCE_DIR", this->CurrentSourceDir);
+  InfoGet(makefile, "AM_CMAKE_CURRENT_BINARY_DIR", this->CurrentBinaryDir);
+  InfoGet(makefile, "AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
+          this->IncludeProjectDirsBefore);
+  InfoGet(makefile, "AM_BUILD_DIR", this->AutogenBuildDir);
+  if (this->AutogenBuildDir.empty()) {
+    this->LogError("AutoGen: Error: Missing autogen build directory ");
+    return false;
+  }
+  InfoGet(makefile, "AM_SOURCES", this->Sources);
+  InfoGet(makefile, "AM_HEADERS", this->Headers);
 
   // - Qt environment
-  this->QtMajorVersion = makefile->GetSafeDefinition("AM_QT_VERSION_MAJOR");
-  if (this->QtMajorVersion == "") {
-    this->QtMajorVersion =
-      makefile->GetSafeDefinition("AM_Qt5Core_VERSION_MAJOR");
+  InfoGet(makefile, "AM_QT_VERSION_MAJOR", this->QtMajorVersion);
+  if (this->QtMajorVersion.empty()) {
+    InfoGet(makefile, "AM_Qt5Core_VERSION_MAJOR", this->QtMajorVersion);
+  }
+  InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable);
+  InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable);
+  InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable);
+
+  InfoGet(makefile, "AM_MOC_PREDEFS_CMD", this->MocPredefsCmd);
+  // Check Qt version
+  if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
+    this->LogError("AutoGen: Error: Unsupported Qt version: " +
+                   Quoted(this->QtMajorVersion));
+    return false;
   }
-  this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE");
-  this->UicExecutable = makefile->GetSafeDefinition("AM_QT_UIC_EXECUTABLE");
-  this->RccExecutable = makefile->GetSafeDefinition("AM_QT_RCC_EXECUTABLE");
-
-  // - File Lists
-  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SOURCES"),
-                                    this->Sources);
-  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_HEADERS"),
-                                    this->Headers);
 
   // - Moc
-  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"),
-                                    this->SkipMoc);
-  this->MocCompileDefinitionsStr =
-    GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config);
-  this->MocIncludesStr =
-    GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config);
-  this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS");
-
-  // - Uic
-  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"),
-                                    this->SkipUic);
-  cmSystemTools::ExpandListArgument(
-    GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config),
-    this->UicTargetOptions);
-  {
-    std::vector<std::string> uicFilesVec;
-    std::vector<std::string> uicOptionsVec;
-    cmSystemTools::ExpandListArgument(
-      makefile->GetSafeDefinition("AM_UIC_OPTIONS_FILES"), uicFilesVec);
-    cmSystemTools::ExpandListArgument(
-      makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS"), uicOptionsVec);
-    if (uicFilesVec.size() != uicOptionsVec.size()) {
-      std::ostringstream err;
-      err << "AutoGen: Error: Uic files/options lists size missmatch in: "
-          << filename << std::endl;
-      this->LogError(err.str());
-      return false;
+  if (this->MocEnabled()) {
+    InfoGet(makefile, "AM_MOC_SKIP", this->MocSkipList);
+    InfoGetConfig(makefile, "AM_MOC_DEFINITIONS", config,
+                  this->MocDefinitions);
+#ifdef _WIN32
+    {
+      const std::string win32("WIN32");
+      if (!ListContains(this->MocDefinitions, win32)) {
+        this->MocDefinitions.push_back(win32);
+      }
     }
-    for (std::vector<std::string>::iterator fileIt = uicFilesVec.begin(),
-                                            optionIt = uicOptionsVec.begin();
-         fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) {
-      cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";");
-      this->UicOptions[*fileIt] = *optionIt;
+#endif
+    InfoGetConfig(makefile, "AM_MOC_INCLUDES", config, this->MocIncludePaths);
+    InfoGet(makefile, "AM_MOC_OPTIONS", this->MocOptions);
+    InfoGet(makefile, "AM_MOC_RELAXED_MODE", this->MocRelaxedMode);
+    {
+      std::vector<std::string> mocDependFilters;
+      InfoGet(makefile, "AM_MOC_DEPEND_FILTERS", mocDependFilters);
+      // Insert Q_PLUGIN_METADATA dependency filter
+      if (this->QtMajorVersion != "4") {
+        this->MocDependFilterPush("Q_PLUGIN_METADATA",
+                                  "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
+                                  "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
+      }
+      // Insert user defined dependency filters
+      if ((mocDependFilters.size() % 2) == 0) {
+        for (std::vector<std::string>::const_iterator dit =
+               mocDependFilters.begin();
+             dit != mocDependFilters.end(); dit += 2) {
+          if (!this->MocDependFilterPush(*dit, *(dit + 1))) {
+            return false;
+          }
+        }
+      } else {
+        this->LogError(
+          "AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not "
+          "a multiple of 2 in:\n" +
+          Quoted(filename));
+        return false;
+      }
     }
   }
 
-  // - Rcc
-  cmSystemTools::ExpandListArgument(
-    makefile->GetSafeDefinition("AM_RCC_SOURCES"), this->RccSources);
-  {
-    std::vector<std::string> rccFilesVec;
-    std::vector<std::string> rccOptionsVec;
-    cmSystemTools::ExpandListArgument(
-      makefile->GetSafeDefinition("AM_RCC_OPTIONS_FILES"), rccFilesVec);
-    cmSystemTools::ExpandListArgument(
-      makefile->GetSafeDefinition("AM_RCC_OPTIONS_OPTIONS"), rccOptionsVec);
-    if (rccFilesVec.size() != rccOptionsVec.size()) {
-      std::ostringstream err;
-      err << "AutoGen: Error: RCC files/options lists size missmatch in: "
-          << filename << std::endl;
-      this->LogError(err.str());
-      return false;
-    }
-    for (std::vector<std::string>::iterator fileIt = rccFilesVec.begin(),
-                                            optionIt = rccOptionsVec.begin();
-         fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) {
-      cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";");
-      this->RccOptions[*fileIt] = *optionIt;
+  // - Uic
+  if (this->UicEnabled()) {
+    InfoGet(makefile, "AM_UIC_SKIP", this->UicSkipList);
+    InfoGet(makefile, "AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
+    InfoGetConfig(makefile, "AM_UIC_TARGET_OPTIONS", config,
+                  this->UicTargetOptions);
+    {
+      std::vector<std::string> uicFilesVec;
+      std::vector<std::string> uicOptionsVec;
+      InfoGet(makefile, "AM_UIC_OPTIONS_FILES", uicFilesVec);
+      InfoGet(makefile, "AM_UIC_OPTIONS_OPTIONS", uicOptionsVec);
+      // Compare list sizes
+      if (uicFilesVec.size() == uicOptionsVec.size()) {
+        for (std::vector<std::string>::iterator
+               fileIt = uicFilesVec.begin(),
+               optionIt = uicOptionsVec.begin();
+             fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) {
+          cmSystemTools::ReplaceString(*optionIt,
+                                       cmQtAutoGeneratorCommon::listSep, ";");
+          this->UicOptions[*fileIt] = *optionIt;
+        }
+      } else {
+        this->LogError(
+          "AutoGen: Error: Uic files/options lists size missmatch in:\n" +
+          Quoted(filename));
+        return false;
+      }
     }
   }
-  {
-    std::vector<std::string> rccInputLists;
-    cmSystemTools::ExpandListArgument(
-      makefile->GetSafeDefinition("AM_RCC_INPUTS"), rccInputLists);
-
-    // qrc files in the end of the list may have been empty
-    if (rccInputLists.size() < this->RccSources.size()) {
-      rccInputLists.resize(this->RccSources.size());
-    }
-    if (this->RccSources.size() != rccInputLists.size()) {
-      std::ostringstream err;
-      err << "AutoGen: Error: RCC sources/inputs lists size missmatch in: "
-          << filename << std::endl;
-      this->LogError(err.str());
-      return false;
+
+  // - Rcc
+  if (this->RccEnabled()) {
+    InfoGet(makefile, "AM_RCC_SOURCES", this->RccSources);
+    // File options
+    {
+      std::vector<std::string> rccFilesVec;
+      std::vector<std::string> rccOptionsVec;
+      InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec);
+      InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec);
+      if (rccFilesVec.size() == rccOptionsVec.size()) {
+        for (std::vector<std::string>::iterator
+               fileIt = rccFilesVec.begin(),
+               optionIt = rccOptionsVec.begin();
+             fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) {
+          // Replace item separator
+          cmSystemTools::ReplaceString(*optionIt,
+                                       cmQtAutoGeneratorCommon::listSep, ";");
+          this->RccOptions[*fileIt] = *optionIt;
+        }
+      } else {
+        this->LogError(
+          "AutoGen: Error: RCC files/options lists size missmatch in:\n" +
+          Quoted(filename));
+        return false;
+      }
     }
-    for (std::vector<std::string>::iterator fileIt = this->RccSources.begin(),
-                                            inputIt = rccInputLists.begin();
-         fileIt != this->RccSources.end(); ++fileIt, ++inputIt) {
-      cmSystemTools::ReplaceString(*inputIt, "@list_sep@", ";");
-      std::vector<std::string> rccInputFiles;
-      cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
-      this->RccInputs[*fileIt] = rccInputFiles;
+    // File lists
+    {
+      std::vector<std::string> rccInputLists;
+      InfoGet(makefile, "AM_RCC_INPUTS", rccInputLists);
+      if (this->RccSources.size() == rccInputLists.size()) {
+        for (std::vector<std::string>::iterator
+               fileIt = this->RccSources.begin(),
+               inputIt = rccInputLists.begin();
+             fileIt != this->RccSources.end(); ++fileIt, ++inputIt) {
+          // Remove braces
+          *inputIt = inputIt->substr(1, inputIt->size() - 2);
+          // Replace item separator
+          cmSystemTools::ReplaceString(*inputIt,
+                                       cmQtAutoGeneratorCommon::listSep, ";");
+          std::vector<std::string> rccInputFiles;
+          cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
+          this->RccInputs[*fileIt] = rccInputFiles;
+        }
+      } else {
+        this->LogError(
+          "AutoGen: Error: RCC sources/inputs lists size missmatch in:\n" +
+          Quoted(filename));
+        return false;
+      }
     }
   }
 
-  // - Flags
-  this->IncludeProjectDirsBefore =
-    makefile->IsOn("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
-  this->MocRelaxedMode = makefile->IsOn("AM_MOC_RELAXED_MODE");
-
   return true;
 }
 
-std::string cmQtAutoGenerators::MocSettingsStringCompose()
-{
-  std::string res;
-  res += this->MocCompileDefinitionsStr;
-  res += " ~~~ ";
-  res += this->MocIncludesStr;
-  res += " ~~~ ";
-  res += this->MocOptionsStr;
-  res += " ~~~ ";
-  res += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE";
-  res += " ~~~ ";
-  return res;
-}
-
-std::string cmQtAutoGenerators::UicSettingsStringCompose()
-{
-  std::string res;
-  res += cmJoin(this->UicTargetOptions, "@osep@");
-  res += " ~~~ ";
-  res += JoinOptions(this->UicOptions);
-  res += " ~~~ ";
-  return res;
-}
-
-std::string cmQtAutoGenerators::RccSettingsStringCompose()
+void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
 {
-  std::string res;
-  res += JoinOptions(this->RccOptions);
-  res += " ~~~ ";
-  return res;
-}
-
-void cmQtAutoGenerators::OldSettingsReadFile(
-  cmMakefile* makefile, const std::string& targetDirectory)
-{
-  if (!this->MocExecutable.empty() || !this->UicExecutable.empty() ||
-      !this->RccExecutable.empty()) {
-    // Compose current settings strings
-    this->MocSettingsString = this->MocSettingsStringCompose();
-    this->UicSettingsString = this->UicSettingsStringCompose();
-    this->RccSettingsString = this->RccSettingsStringCompose();
+  // Compose current settings strings
+  {
+    cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
+    const std::string sep(" ~~~ ");
+    if (this->MocEnabled()) {
+      std::string str;
+      str += this->MocExecutable;
+      str += sep;
+      str += JoinOptionsList(this->MocDefinitions);
+      str += sep;
+      str += JoinOptionsList(this->MocIncludePaths);
+      str += sep;
+      str += JoinOptionsList(this->MocOptions);
+      str += sep;
+      str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE";
+      str += sep;
+      str += JoinOptionsList(this->MocPredefsCmd);
+      str += sep;
+      this->SettingsStringMoc = crypt.HashString(str);
+    }
+    if (this->UicEnabled()) {
+      std::string str;
+      str += this->UicExecutable;
+      str += sep;
+      str += JoinOptionsList(this->UicTargetOptions);
+      str += sep;
+      str += JoinOptionsMap(this->UicOptions);
+      str += sep;
+      this->SettingsStringUic = crypt.HashString(str);
+    }
+    if (this->RccEnabled()) {
+      std::string str;
+      str += this->RccExecutable;
+      str += sep;
+      str += JoinOptionsMap(this->RccOptions);
+      str += sep;
+      this->SettingsStringRcc = crypt.HashString(str);
+    }
+  }
 
-    // Read old settings
-    const std::string filename = OldSettingsFile(targetDirectory);
-    if (makefile->ReadListFile(filename.c_str())) {
-      if (!this->MocExecutable.empty()) {
-        const std::string sol = makefile->GetSafeDefinition(MocOldSettingsKey);
-        if (sol != this->MocSettingsString) {
-          this->GenerateMocAll = true;
-        }
-      }
-      if (!this->UicExecutable.empty()) {
-        const std::string sol = makefile->GetSafeDefinition(UicOldSettingsKey);
-        if (sol != this->UicSettingsString) {
-          this->GenerateUicAll = true;
-        }
-      }
-      if (!this->RccExecutable.empty()) {
-        const std::string sol = makefile->GetSafeDefinition(RccOldSettingsKey);
-        if (sol != this->RccSettingsString) {
-          this->GenerateRccAll = true;
-        }
-      }
-      // In case any setting changed remove the old settings file.
-      // This triggers a full rebuild on the next run if the current
-      // build is aborted before writing the current settings in the end.
-      if (this->GenerateMocAll || this->GenerateUicAll ||
-          this->GenerateRccAll) {
-        cmSystemTools::RemoveFile(filename);
-      }
-    } else {
-      // If the file could not be read re-generate everythiung.
-      this->GenerateMocAll = true;
-      this->GenerateUicAll = true;
-      this->GenerateRccAll = true;
+  // Read old settings
+  if (makefile->ReadListFile(this->SettingsFile.c_str())) {
+    if (!SettingsMatch(makefile, SettingsKeyMoc, this->SettingsStringMoc)) {
+      this->MocSettingsChanged = true;
+    }
+    if (!SettingsMatch(makefile, SettingsKeyUic, this->SettingsStringUic)) {
+      this->UicSettingsChanged = true;
+    }
+    if (!SettingsMatch(makefile, SettingsKeyRcc, this->SettingsStringRcc)) {
+      this->RccSettingsChanged = true;
+    }
+    // In case any setting changed remove the old settings file.
+    // This triggers a full rebuild on the next run if the current
+    // build is aborted before writing the current settings in the end.
+    if (this->AnySettingsChanged()) {
+      cmSystemTools::RemoveFile(this->SettingsFile);
     }
+  } else {
+    // If the file could not be read re-generate everythiung.
+    this->MocSettingsChanged = true;
+    this->UicSettingsChanged = true;
+    this->RccSettingsChanged = true;
   }
 }
 
-bool cmQtAutoGenerators::OldSettingsWriteFile(
-  const std::string& targetDirectory)
+bool cmQtAutoGenerators::SettingsFileWrite()
 {
   bool success = true;
   // Only write if any setting changed
-  if (this->GenerateMocAll || this->GenerateUicAll || this->GenerateRccAll) {
-    const std::string filename = OldSettingsFile(targetDirectory);
-    cmsys::ofstream outfile;
-    outfile.open(filename.c_str(), std::ios::trunc);
-    if (outfile) {
-      if (!this->MocExecutable.empty()) {
-        outfile << "set(" << MocOldSettingsKey << " "
-                << cmOutputConverter::EscapeForCMake(this->MocSettingsString)
-                << ")\n";
-      }
-      if (!this->UicExecutable.empty()) {
-        outfile << "set(" << UicOldSettingsKey << " "
-                << cmOutputConverter::EscapeForCMake(this->UicSettingsString)
-                << ")\n";
-      }
-      if (!this->RccExecutable.empty()) {
-        outfile << "set(" << RccOldSettingsKey << " "
-                << cmOutputConverter::EscapeForCMake(this->RccSettingsString)
-                << ")\n";
-      }
-      success = outfile.good();
-      outfile.close();
-    } else {
+  if (this->AnySettingsChanged()) {
+    if (this->Verbose) {
+      this->LogInfo("AutoGen: Writing settings file " +
+                    Quoted(this->SettingsFile));
+    }
+    // Compose settings file content
+    std::string settings;
+    SettingAppend(settings, SettingsKeyMoc, this->SettingsStringMoc);
+    SettingAppend(settings, SettingsKeyUic, this->SettingsStringUic);
+    SettingAppend(settings, SettingsKeyRcc, this->SettingsStringRcc);
+    // Write settings file
+    if (!this->FileWrite("AutoGen", this->SettingsFile, settings)) {
+      this->LogError("AutoGen: Error: Could not write old settings file " +
+                     Quoted(this->SettingsFile));
+      // Remove old settings file to trigger a full rebuild on the next run
+      cmSystemTools::RemoveFile(this->SettingsFile);
       success = false;
-      // Remove old settings file to trigger full rebuild on next run
-      cmSystemTools::RemoveFile(filename);
-      {
-        std::ostringstream err;
-        err << "AutoGen: Error: Writing old settings file failed: " << filename
-            << std::endl;
-        this->LogError(err.str());
-      }
     }
   }
   return success;
 }
 
-void cmQtAutoGenerators::Init()
+void cmQtAutoGenerators::Init(cmMakefile* makefile)
 {
-  this->AutogenBuildSubDir = this->AutogenTargetName;
-  this->AutogenBuildSubDir += "/";
+  // Mocs compilation file
+  this->MocCompFileRel = "mocs_compilation";
+  this->MocCompFileRel += this->ConfigSuffix;
+  this->MocCompFileRel += ".cpp";
+  this->MocCompFileAbs = cmSystemTools::CollapseCombinedPath(
+    this->AutogenBuildDir, this->MocCompFileRel);
 
-  this->OutMocCppFilenameRel = this->AutogenBuildSubDir;
-  this->OutMocCppFilenameRel += "moc_compilation.cpp";
+  // Mocs include directory
+  this->AutogenIncludeDir = "include";
+  this->AutogenIncludeDir += this->ConfigSuffix;
+  this->AutogenIncludeDir += "/";
 
-  this->OutMocCppFilenameAbs =
-    this->CurrentBinaryDir + this->OutMocCppFilenameRel;
+  // Moc predefs file
+  if (!this->MocPredefsCmd.empty()) {
+    this->MocPredefsFileRel = "moc_predefs.h";
+    this->MocPredefsFileAbs = cmSystemTools::CollapseCombinedPath(
+      this->AutogenBuildDir, this->MocPredefsFileRel);
+  }
 
   // Init file path checksum generator
-  fpathCheckSum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir,
+  FPathChecksum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir,
                                 this->ProjectSourceDir,
                                 this->ProjectBinaryDir);
 
-  std::vector<std::string> cdefList;
-  cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList);
-  for (std::vector<std::string>::const_iterator it = cdefList.begin();
-       it != cdefList.end(); ++it) {
-    this->MocDefinitions.push_back("-D" + (*it));
-  }
-
-  cmSystemTools::ExpandListArgument(this->MocOptionsStr, this->MocOptions);
-
-  std::vector<std::string> incPaths;
-  cmSystemTools::ExpandListArgument(this->MocIncludesStr, incPaths);
-
-  std::set<std::string> frameworkPaths;
-  for (std::vector<std::string>::const_iterator it = incPaths.begin();
-       it != incPaths.end(); ++it) {
-    const std::string& path = *it;
-    this->MocIncludes.push_back("-I" + path);
-    if (cmHasLiteralSuffix(path, ".framework/Headers")) {
-      // Go up twice to get to the framework root
-      std::vector<std::string> pathComponents;
-      cmsys::SystemTools::SplitPath(path, pathComponents);
-      std::string frameworkPath = cmsys::SystemTools::JoinPath(
-        pathComponents.begin(), pathComponents.end() - 2);
-      frameworkPaths.insert(frameworkPath);
-    }
-  }
-
-  for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
-       it != frameworkPaths.end(); ++it) {
-    this->MocIncludes.push_back("-F");
-    this->MocIncludes.push_back(*it);
-  }
+  // Acquire header extensions
+  this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
 
+  // Sort include directories on demand
   if (this->IncludeProjectDirsBefore) {
-    const std::string binDir = "-I" + this->ProjectBinaryDir;
-    const std::string srcDir = "-I" + this->ProjectSourceDir;
-
-    std::list<std::string> sortedMocIncludes;
-    std::list<std::string>::iterator it = this->MocIncludes.begin();
-    while (it != this->MocIncludes.end()) {
-      if (cmsys::SystemTools::StringStartsWith(*it, binDir.c_str())) {
-        sortedMocIncludes.push_back(*it);
-        it = this->MocIncludes.erase(it);
-      } else {
-        ++it;
+    // Move strings to temporary list
+    std::list<std::string> includes;
+    includes.insert(includes.end(), this->MocIncludePaths.begin(),
+                    this->MocIncludePaths.end());
+    this->MocIncludePaths.clear();
+    this->MocIncludePaths.reserve(includes.size());
+    // Append project directories only
+    {
+      const char* movePaths[2] = { this->ProjectBinaryDir.c_str(),
+                                   this->ProjectSourceDir.c_str() };
+      for (const char* const* mpit = cmArrayBegin(movePaths);
+           mpit != cmArrayEnd(movePaths); ++mpit) {
+        std::list<std::string>::iterator it = includes.begin();
+        while (it != includes.end()) {
+          const std::string& path = *it;
+          if (cmsys::SystemTools::StringStartsWith(path, *mpit)) {
+            this->MocIncludePaths.push_back(path);
+            it = includes.erase(it);
+          } else {
+            ++it;
+          }
+        }
       }
     }
-    it = this->MocIncludes.begin();
-    while (it != this->MocIncludes.end()) {
-      if (cmsys::SystemTools::StringStartsWith(*it, srcDir.c_str())) {
-        sortedMocIncludes.push_back(*it);
-        it = this->MocIncludes.erase(it);
-      } else {
-        ++it;
+    // Append remaining directories
+    this->MocIncludePaths.insert(this->MocIncludePaths.end(), includes.begin(),
+                                 includes.end());
+  }
+  // Compose moc includes list
+  {
+    std::set<std::string> frameworkPaths;
+    for (std::vector<std::string>::const_iterator it =
+           this->MocIncludePaths.begin();
+         it != this->MocIncludePaths.end(); ++it) {
+      const std::string& path = *it;
+      this->MocIncludes.push_back("-I" + path);
+      // Extract framework path
+      if (cmHasLiteralSuffix(path, ".framework/Headers")) {
+        // Go up twice to get to the framework root
+        std::vector<std::string> pathComponents;
+        cmsys::SystemTools::SplitPath(path, pathComponents);
+        std::string frameworkPath = cmsys::SystemTools::JoinPath(
+          pathComponents.begin(), pathComponents.end() - 2);
+        frameworkPaths.insert(frameworkPath);
       }
     }
-    sortedMocIncludes.insert(sortedMocIncludes.end(),
-                             this->MocIncludes.begin(),
-                             this->MocIncludes.end());
-    this->MocIncludes = sortedMocIncludes;
+    // Append framework includes
+    for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
+         it != frameworkPaths.end(); ++it) {
+      this->MocIncludes.push_back("-F");
+      this->MocIncludes.push_back(*it);
+    }
   }
 }
 
-bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
+bool cmQtAutoGenerators::RunAutogen()
 {
   // the program goes through all .cpp files to see which moc files are
   // included. It is not really interesting how the moc file is named, but
   // what file the moc is created from. Once a moc is included the same moc
-  // may not be included in the moc_compilation.cpp file anymore. OTOH if
-  // there's a header containing Q_OBJECT where no corresponding moc file
-  // is included anywhere a moc_<filename>.cpp file is created and included in
-  // the moc_compilation.cpp file.
+  // may not be included in the mocs_compilation_$<CONFIG>.cpp file anymore.
+  // OTOH if there's a header containing Q_OBJECT where no corresponding
+  // moc file is included anywhere a moc_<filename>.cpp file is created and
+  // included in the mocs_compilation_$<CONFIG>.cpp file.
 
   // key = moc source filepath, value = moc output filepath
-  std::map<std::string, std::string> includedMocs;
-  std::map<std::string, std::string> notIncludedMocs;
-  std::map<std::string, std::vector<std::string> > includedUis;
+  std::map<std::string, std::string> mocsIncluded;
+  std::map<std::string, std::string> mocsNotIncluded;
+  std::map<std::string, std::set<std::string> > mocDepends;
+  std::map<std::string, std::vector<std::string> > uisIncluded;
   // collects all headers which may need to be mocced
-  std::set<std::string> headerFilesMoc;
-  std::set<std::string> headerFilesUic;
+  std::set<std::string> mocHeaderFiles;
+  std::set<std::string> uicHeaderFiles;
 
   // Parse sources
-  {
-    const std::vector<std::string>& headerExtensions =
-      makefile->GetCMakeInstance()->GetHeaderExtensions();
-
-    for (std::vector<std::string>::const_iterator it = this->Sources.begin();
-         it != this->Sources.end(); ++it) {
-      const std::string& absFilename = *it;
-      // Parse source file for MOC/UIC
-      if (!this->ParseSourceFile(absFilename, headerExtensions, includedMocs,
-                                 includedUis, this->MocRelaxedMode)) {
-        return false;
-      }
-      // Find additional headers
-      this->SearchHeadersForSourceFile(absFilename, headerExtensions,
-                                       headerFilesMoc, headerFilesUic);
+  for (std::vector<std::string>::const_iterator it = this->Sources.begin();
+       it != this->Sources.end(); ++it) {
+    const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it);
+    // Parse source file for MOC/UIC
+    if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends,
+                               uisIncluded, this->MocRelaxedMode)) {
+      return false;
     }
+    // Find additional headers
+    this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles,
+                                     uicHeaderFiles);
   }
 
   // Parse headers
   for (std::vector<std::string>::const_iterator it = this->Headers.begin();
        it != this->Headers.end(); ++it) {
-    const std::string& headerName = *it;
-    if (!this->MocSkipTest(headerName)) {
-      headerFilesMoc.insert(headerName);
+    const std::string& headerName = cmsys::SystemTools::GetRealPath(*it);
+    if (!this->MocSkip(headerName)) {
+      mocHeaderFiles.insert(headerName);
     }
-    if (!this->UicSkipTest(headerName)) {
-      headerFilesUic.insert(headerName);
+    if (!this->UicSkip(headerName)) {
+      uicHeaderFiles.insert(headerName);
     }
   }
-  this->ParseHeaders(headerFilesMoc, headerFilesUic, includedMocs,
-                     notIncludedMocs, includedUis);
+  if (!this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded,
+                          mocsNotIncluded, mocDepends, uisIncluded)) {
+    return false;
+  };
 
   // Generate files
-  if (!this->MocGenerateAll(includedMocs, notIncludedMocs)) {
+  if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded, mocDepends)) {
     return false;
   }
-  if (!this->UicGenerateAll(includedUis)) {
+  if (!this->UicGenerateAll(uisIncluded)) {
     return false;
   }
-  if (!this->QrcGenerateAll()) {
+  if (!this->RccGenerateAll()) {
     return false;
   }
 
@@ -682,35 +784,73 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
  * @brief Tests if the C++ content requires moc processing
  * @return True if moc is required
  */
-bool cmQtAutoGenerators::MocRequired(const std::string& text,
-                                     std::string& macroName)
+bool cmQtAutoGenerators::MocRequired(const std::string& contentText,
+                                     std::string* macroName)
 {
-  // Run a simple check before an expensive regular expression check
-  if (strstr(text.c_str(), "Q_OBJECT") != CM_NULLPTR) {
-    if (this->RegExpQObject.find(text)) {
-      macroName = "Q_OBJECT";
-      return true;
+  for (unsigned int ii = 0; ii != cmArraySize(this->MocMacroFilters); ++ii) {
+    MocMacroFilter& filter = this->MocMacroFilters[ii];
+    // Run a simple find string operation before the expensive
+    // regular expression check
+    if (contentText.find(filter.first) != std::string::npos) {
+      if (filter.second.find(contentText)) {
+        // Return macro name on demand
+        if (macroName != CM_NULLPTR) {
+          *macroName = filter.first;
+        }
+        return true;
+      }
     }
   }
-  if (strstr(text.c_str(), "Q_GADGET") != CM_NULLPTR) {
-    if (this->RegExpQGadget.find(text)) {
-      macroName = "Q_GADGET";
-      return true;
+  return false;
+}
+
+void cmQtAutoGenerators::MocFindDepends(
+  const std::string& absFilename, const std::string& contentText,
+  std::map<std::string, std::set<std::string> >& mocDepends)
+{
+  for (std::vector<MocDependFilter>::iterator fit =
+         this->MocDependFilters.begin();
+       fit != this->MocDependFilters.end(); ++fit) {
+    MocDependFilter& filter = *fit;
+    // Run a simple find string operation before the expensive
+    // regular expression check
+    if (contentText.find(filter.key) != std::string::npos) {
+      // Run regular expression check loop
+      const std::string sourcePath = SubDirPrefix(absFilename);
+      const char* contentChars = contentText.c_str();
+      while (filter.regExp.find(contentChars)) {
+        // Evaluate match
+        const std::string match = filter.regExp.match(1);
+        if (!match.empty()) {
+          // Find the dependency file
+          std::string incFile;
+          if (this->MocFindIncludedFile(incFile, sourcePath, match)) {
+            mocDepends[absFilename].insert(incFile);
+            if (this->Verbose) {
+              this->LogInfo("AutoMoc: Found dependency:\n  " +
+                            Quoted(absFilename) + "\n  " + Quoted(incFile));
+            }
+          } else {
+            this->LogWarning("AutoMoc: Warning: " + Quoted(absFilename) +
+                             "\n" + "Could not find dependency file " +
+                             Quoted(match));
+          }
+        }
+        contentChars += filter.regExp.end();
+      }
     }
   }
-  return false;
 }
 
 /**
  * @brief Tests if the file should be ignored for moc scanning
  * @return True if the file should be ignored
  */
-bool cmQtAutoGenerators::MocSkipTest(const std::string& absFilename)
+bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) const
 {
-  // Test if moc scanning is enabled
-  if (!this->MocExecutable.empty()) {
+  if (this->MocEnabled()) {
     // Test if the file name is on the skip list
-    if (!ListContains(this->SkipMoc, absFilename)) {
+    if (!ListContains(this->MocSkipList, absFilename)) {
       return false;
     }
   }
@@ -720,12 +860,11 @@ bool cmQtAutoGenerators::MocSkipTest(const std::string& absFilename)
 /**
  * @brief Tests if the file name is in the skip list
  */
-bool cmQtAutoGenerators::UicSkipTest(const std::string& absFilename)
+bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const
 {
-  // Test if uic scanning is enabled
-  if (!this->UicExecutable.empty()) {
+  if (this->UicEnabled()) {
     // Test if the file name is on the skip list
-    if (!ListContains(this->SkipUic, absFilename)) {
+    if (!ListContains(this->UicSkipList, absFilename)) {
       return false;
     }
   }
@@ -737,53 +876,50 @@ bool cmQtAutoGenerators::UicSkipTest(const std::string& absFilename)
  */
 bool cmQtAutoGenerators::ParseSourceFile(
   const std::string& absFilename,
-  const std::vector<std::string>& headerExtensions,
-  std::map<std::string, std::string>& includedMocs,
-  std::map<std::string, std::vector<std::string> >& includedUis, bool relaxed)
+  std::map<std::string, std::string>& mocsIncluded,
+  std::map<std::string, std::set<std::string> >& mocDepends,
+  std::map<std::string, std::vector<std::string> >& uisIncluded, bool relaxed)
 {
-  bool success = true;
-  const std::string contentsString = ReadAll(absFilename);
-  if (contentsString.empty()) {
-    std::ostringstream err;
-    err << "AutoGen: Warning: " << absFilename << "\n"
-        << "The file is empty\n";
-    this->LogWarning(err.str());
-  } else {
-    // Parse source contents for MOC
-    if (success && !this->MocSkipTest(absFilename)) {
-      success = this->ParseContentForMoc(
-        absFilename, contentsString, headerExtensions, includedMocs, relaxed);
-    }
-    // Parse source contents for UIC
-    if (success && !this->UicSkipTest(absFilename)) {
-      this->ParseContentForUic(absFilename, contentsString, includedUis);
+  std::string contentText;
+  bool success = ReadAll(contentText, absFilename);
+  if (success) {
+    if (!contentText.empty()) {
+      // Parse source contents for MOC
+      if (success && !this->MocSkip(absFilename)) {
+        success = this->MocParseSourceContent(
+          absFilename, contentText, mocsIncluded, mocDepends, relaxed);
+      }
+      // Parse source contents for UIC
+      if (success && !this->UicSkip(absFilename)) {
+        this->UicParseContent(absFilename, contentText, uisIncluded);
+      }
+    } else {
+      std::ostringstream ost;
+      ost << "AutoGen: Warning: The file is empty:\n"
+          << Quoted(absFilename) << "\n";
+      this->LogWarning(ost.str());
     }
+  } else {
+    std::ostringstream ost;
+    ost << "AutoGen: Error: Could not read file:\n" << Quoted(absFilename);
+    this->LogError(ost.str());
   }
   return success;
 }
 
-void cmQtAutoGenerators::ParseContentForUic(
-  const std::string& absFilename, const std::string& contentsString,
-  std::map<std::string, std::vector<std::string> >& includedUis)
+void cmQtAutoGenerators::UicParseContent(
+  const std::string& absFilename, const std::string& contentText,
+  std::map<std::string, std::vector<std::string> >& uisIncluded)
 {
-  // Process
   if (this->Verbose) {
-    std::ostringstream err;
-    err << "AutoUic: Checking " << absFilename << "\n";
-    this->LogInfo(err.str());
+    this->LogInfo("AutoUic: Checking " + absFilename);
   }
 
-  const std::string realName = cmsys::SystemTools::GetRealPath(absFilename);
-  const char* contentChars = contentsString.c_str();
+  const char* contentChars = contentText.c_str();
   if (strstr(contentChars, "ui_") != CM_NULLPTR) {
-    while (this->RegExpUicInclude.find(contentChars)) {
-      const std::string currentUi = this->RegExpUicInclude.match(1);
-      const std::string basename =
-        cmsys::SystemTools::GetFilenameWithoutLastExtension(currentUi);
-      // basename should be the part of the ui filename used for
-      // finding the correct header, so we need to remove the ui_ part
-      includedUis[realName].push_back(basename.substr(3));
-      contentChars += this->RegExpUicInclude.end();
+    while (this->UicRegExpInclude.find(contentChars)) {
+      uisIncluded[absFilename].push_back(this->UicRegExpInclude.match(1));
+      contentChars += this->UicRegExpInclude.end();
     }
   }
 }
@@ -791,79 +927,69 @@ void cmQtAutoGenerators::ParseContentForUic(
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::ParseContentForMoc(
-  const std::string& absFilename, const std::string& contentsString,
-  const std::vector<std::string>& headerExtensions,
-  std::map<std::string, std::string>& includedMocs, bool relaxed)
+bool cmQtAutoGenerators::MocParseSourceContent(
+  const std::string& absFilename, const std::string& contentText,
+  std::map<std::string, std::string>& mocsIncluded,
+  std::map<std::string, std::set<std::string> >& mocDepends, bool relaxed)
 {
-  // Process
   if (this->Verbose) {
-    std::ostringstream err;
-    err << "AutoMoc: Checking " << absFilename << "\n";
-    this->LogInfo(err.str());
+    this->LogInfo("AutoMoc: Checking " + absFilename);
   }
 
-  const std::string scannedFileAbsPath =
-    cmsys::SystemTools::GetFilenamePath(
-      cmsys::SystemTools::GetRealPath(absFilename)) +
-    '/';
+  const std::string scannedFileAbsPath = SubDirPrefix(absFilename);
   const std::string scannedFileBasename =
     cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
 
   std::string macroName;
-  const bool requiresMoc = this->MocRequired(contentsString, macroName);
+  const bool requiresMoc = this->MocRequired(contentText, &macroName);
   bool ownDotMocIncluded = false;
-  bool ownMocUnderscoreIncluded = false;
-  std::string ownMocUnderscoreFile;
-  std::string ownMocHeaderFile;
+  std::string ownMocUnderscoreInclude;
+  std::string ownMocUnderscoreHeader;
 
   // first a simple string check for "moc" is *much* faster than the regexp,
   // and if the string search already fails, we don't have to try the
   // expensive regexp
-  const char* contentChars = contentsString.c_str();
+  const char* contentChars = contentText.c_str();
   if (strstr(contentChars, "moc") != CM_NULLPTR) {
     // Iterate over all included moc files
-    while (this->RegExpMocInclude.find(contentChars)) {
-      const std::string currentMoc = this->RegExpMocInclude.match(1);
-      // Basename of the current moc include
-      std::string basename =
-        cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc);
+    while (this->MocRegExpInclude.find(contentChars)) {
+      const std::string incString = this->MocRegExpInclude.match(1);
+      // Basename of the moc include
+      const std::string incSubDir(SubDirPrefix(incString));
+      const std::string incBasename =
+        cmsys::SystemTools::GetFilenameWithoutLastExtension(incString);
 
       // If the moc include is of the moc_foo.cpp style we expect
       // the Q_OBJECT class declaration in a header file.
       // If the moc include is of the foo.moc style we need to look for
       // a Q_OBJECT macro in the current source file, if it contains the
       // macro we generate the moc file from the source file.
-      if (cmHasLiteralPrefix(basename, "moc_")) {
+      if (cmHasLiteralPrefix(incBasename, "moc_")) {
         // Include: moc_FOO.cxx
-        // basename should be the part of the moc filename used for
-        // finding the correct header, so we need to remove the moc_ part
-        basename = basename.substr(4);
-        const std::string mocSubDir =
-          ExtractSubDir(scannedFileAbsPath, currentMoc);
-        const std::string headerToMoc = FindMatchingHeader(
-          scannedFileAbsPath, mocSubDir, basename, headerExtensions);
-
+        // Remove the moc_ part
+        const std::string incRealBasename = incBasename.substr(4);
+        const std::string headerToMoc =
+          this->MocFindHeader(scannedFileAbsPath, incSubDir + incRealBasename);
         if (!headerToMoc.empty()) {
-          includedMocs[headerToMoc] = currentMoc;
-          if (relaxed && (basename == scannedFileBasename)) {
-            ownMocUnderscoreIncluded = true;
-            ownMocUnderscoreFile = currentMoc;
-            ownMocHeaderFile = headerToMoc;
+          if (!this->MocSkip(headerToMoc)) {
+            // Register moc job
+            mocsIncluded[headerToMoc] = incString;
+            this->MocFindDepends(headerToMoc, contentText, mocDepends);
+            // Store meta information for relaxed mode
+            if (relaxed && (incRealBasename == scannedFileBasename)) {
+              ownMocUnderscoreInclude = incString;
+              ownMocUnderscoreHeader = headerToMoc;
+            }
           }
         } else {
-          std::ostringstream err;
-          err << "AutoMoc: Error: " << absFilename << "\n"
-              << "The file includes the moc file \"" << currentMoc
-              << "\", but could not find header \"" << basename << '{'
-              << JoinExts(headerExtensions) << "}\" ";
-          if (mocSubDir.empty()) {
-            err << "in " << scannedFileAbsPath << "\n";
-          } else {
-            err << "neither in " << scannedFileAbsPath << " nor in "
-                << mocSubDir << "\n";
-          }
-          this->LogError(err.str());
+          std::ostringstream ost;
+          ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
+              << "The file includes the moc file " << Quoted(incString)
+              << ", but could not find header "
+              << Quoted(incRealBasename + "{" +
+                        JoinExts(this->HeaderExtensions) + "}");
+          ;
+          this->LogError(ost.str());
           return false;
         }
       } else {
@@ -871,108 +997,125 @@ bool cmQtAutoGenerators::ParseContentForMoc(
         std::string fileToMoc;
         if (relaxed) {
           // Mode: Relaxed
-          if (!requiresMoc || basename != scannedFileBasename) {
-            const std::string mocSubDir =
-              ExtractSubDir(scannedFileAbsPath, currentMoc);
-            const std::string headerToMoc = FindMatchingHeader(
-              scannedFileAbsPath, mocSubDir, basename, headerExtensions);
+          if (requiresMoc && (incBasename == scannedFileBasename)) {
+            // Include self
+            fileToMoc = absFilename;
+            ownDotMocIncluded = true;
+          } else {
+            // In relaxed mode try to find a header instead but issue a warning
+            const std::string headerToMoc =
+              this->MocFindHeader(scannedFileAbsPath, incSubDir + incBasename);
             if (!headerToMoc.empty()) {
-              // This is for KDE4 compatibility:
-              fileToMoc = headerToMoc;
-              if (!requiresMoc && basename == scannedFileBasename) {
-                std::ostringstream err;
-                err << "AutoMoc: Warning: " << absFilename << "\n"
-                    << "The file includes the moc file \"" << currentMoc
-                    << "\", but does not contain a " << macroName
-                    << " macro. Running moc on "
-                    << "\"" << headerToMoc << "\" ! Include \"moc_" << basename
-                    << ".cpp\" for a compatibility with "
-                       "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
-                this->LogWarning(err.str());
-              } else {
-                std::ostringstream err;
-                err << "AutoMoc: Warning: " << absFilename << "\n"
-                    << "The file includes the moc file \"" << currentMoc
-                    << "\" instead of \"moc_" << basename
-                    << ".cpp\". Running moc on "
-                    << "\"" << headerToMoc << "\" ! Include \"moc_" << basename
-                    << ".cpp\" for compatibility with "
-                       "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
-                this->LogWarning(err.str());
+              if (!this->MocSkip(headerToMoc)) {
+                // This is for KDE4 compatibility:
+                fileToMoc = headerToMoc;
+                if (!requiresMoc && (incBasename == scannedFileBasename)) {
+                  std::ostringstream ost;
+                  ost
+                    << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
+                    << "The file includes the moc file " << Quoted(incString)
+                    << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n"
+                    << "Running moc on " << Quoted(headerToMoc) << "!\n"
+                    << "Include " << Quoted("moc_" + incBasename + ".cpp")
+                    << " for a compatibility with strict mode (see "
+                       "CMAKE_AUTOMOC_RELAXED_MODE).\n";
+                  this->LogWarning(ost.str());
+                } else {
+                  std::ostringstream ost;
+                  ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
+                      << "The file includes the moc file " << Quoted(incString)
+                      << " instead of "
+                      << Quoted("moc_" + incBasename + ".cpp") << ".\n"
+                      << "Running moc on " << Quoted(headerToMoc) << "!\n"
+                      << "Include " << Quoted("moc_" + incBasename + ".cpp")
+                      << " for compatibility with strict mode (see "
+                         "CMAKE_AUTOMOC_RELAXED_MODE).\n";
+                  this->LogWarning(ost.str());
+                }
               }
             } else {
-              std::ostringstream err;
-              err << "AutoMoc: Error: " << absFilename << "\n"
-                  << "The file includes the moc file \"" << currentMoc
-                  << "\", which seems to be the moc file from a different "
+              std::ostringstream ost;
+              ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
+                  << "The file includes the moc file " << Quoted(incString)
+                  << ", which seems to be the moc file from a different "
                      "source file. CMake also could not find a matching "
-                     "header.\n";
-              this->LogError(err.str());
+                     "header.";
+              this->LogError(ost.str());
               return false;
             }
-          } else {
-            // Include self
-            fileToMoc = absFilename;
-            ownDotMocIncluded = true;
           }
         } else {
           // Mode: Strict
-          if (basename == scannedFileBasename) {
+          if (incBasename == scannedFileBasename) {
             // Include self
             fileToMoc = absFilename;
             ownDotMocIncluded = true;
+            // Accept but issue a warning if moc isn't required
+            if (!requiresMoc) {
+              std::ostringstream ost;
+              ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
+                  << "The file includes the moc file " << Quoted(incString)
+                  << ", but does not contain a Q_OBJECT or Q_GADGET "
+                     "macro.";
+              this->LogWarning(ost.str());
+            }
           } else {
             // Don't allow FOO.moc include other than self in strict mode
-            std::ostringstream err;
-            err << "AutoMoc: Error: " << absFilename << "\n"
-                << "The file includes the moc file \"" << currentMoc
-                << "\", which seems to be the moc file from a different "
-                   "source file. This is not supported. Include \""
-                << scannedFileBasename
-                << ".moc\" to run moc on this source file.\n";
-            this->LogError(err.str());
+            std::ostringstream ost;
+            ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
+                << "The file includes the moc file " << Quoted(incString)
+                << ", which seems to be the moc file from a different "
+                   "source file. This is not supported. Include "
+                << Quoted(scannedFileBasename + ".moc")
+                << " to run moc on this source file.";
+            this->LogError(ost.str());
             return false;
           }
         }
         if (!fileToMoc.empty()) {
-          includedMocs[fileToMoc] = currentMoc;
+          mocsIncluded[fileToMoc] = incString;
+          this->MocFindDepends(fileToMoc, contentText, mocDepends);
         }
       }
       // Forward content pointer
-      contentChars += this->RegExpMocInclude.end();
+      contentChars += this->MocRegExpInclude.end();
     }
   }
 
-  // In this case, check whether the scanned file itself contains a Q_OBJECT.
-  // If this is the case, the moc_foo.cpp should probably be generated from
-  // foo.cpp instead of foo.h, because otherwise it won't build.
-  // But warn, since this is not how it is supposed to be used.
   if (requiresMoc && !ownDotMocIncluded) {
-    if (relaxed && ownMocUnderscoreIncluded) {
+    // In this case, check whether the scanned file itself contains a Q_OBJECT.
+    // If this is the case, the moc_foo.cpp should probably be generated from
+    // foo.cpp instead of foo.h, because otherwise it won't build.
+    // But warn, since this is not how it is supposed to be used.
+    if (relaxed && !ownMocUnderscoreInclude.empty()) {
       // This is for KDE4 compatibility:
-      std::ostringstream err;
-      err << "AutoMoc: Warning: " << absFilename << "\n"
+      std::ostringstream ost;
+      ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
           << "The file contains a " << macroName
           << " macro, but does not include "
-          << "\"" << scannedFileBasename << ".moc\", but instead includes "
-          << "\"" << ownMocUnderscoreFile << "\". Running moc on "
-          << "\"" << absFilename << "\" ! Better include \""
-          << scannedFileBasename
-          << ".moc\" for compatibility with "
-             "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
-      this->LogWarning(err.str());
+          << Quoted(scannedFileBasename + ".moc") << ", but instead includes "
+          << Quoted(ownMocUnderscoreInclude) << ".\n"
+          << "Running moc on " << Quoted(absFilename) << "!\n"
+          << "Better include " << Quoted(scannedFileBasename + ".moc")
+          << " for compatibility with strict mode (see "
+             "CMAKE_AUTOMOC_RELAXED_MODE).";
+      this->LogWarning(ost.str());
 
       // Use scanned source file instead of scanned header file as moc source
-      includedMocs[absFilename] = ownMocUnderscoreFile;
-      includedMocs.erase(ownMocHeaderFile);
+      mocsIncluded[absFilename] = ownMocUnderscoreInclude;
+      this->MocFindDepends(absFilename, contentText, mocDepends);
+      // Remove
+      mocsIncluded.erase(ownMocUnderscoreHeader);
     } else {
       // Otherwise always error out since it will not compile:
-      std::ostringstream err;
-      err << "AutoMoc: Error: " << absFilename << "\n"
+      std::ostringstream ost;
+      ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
           << "The file contains a " << macroName
           << " macro, but does not include "
-          << "\"" << scannedFileBasename << ".moc\" !\n";
-      this->LogError(err.str());
+          << Quoted(scannedFileBasename + ".moc") << "!\n"
+          << "Consider adding the include or enabling SKIP_AUTOMOC for this "
+             "file.";
+      this->LogError(ost.str());
       return false;
     }
   }
@@ -980,337 +1123,410 @@ bool cmQtAutoGenerators::ParseContentForMoc(
   return true;
 }
 
+void cmQtAutoGenerators::MocParseHeaderContent(
+  const std::string& absFilename, const std::string& contentText,
+  std::map<std::string, std::string>& mocsNotIncluded,
+  std::map<std::string, std::set<std::string> >& mocDepends)
+{
+  // Log
+  if (this->Verbose) {
+    this->LogInfo("AutoMoc: Checking " + absFilename);
+  }
+  if (this->MocRequired(contentText)) {
+    // Register moc job
+    mocsNotIncluded[absFilename] =
+      this->ChecksumedPath(absFilename, "moc_", this->ConfigSuffix + ".cpp");
+    this->MocFindDepends(absFilename, contentText, mocDepends);
+  }
+}
+
 void cmQtAutoGenerators::SearchHeadersForSourceFile(
-  const std::string& absFilename,
-  const std::vector<std::string>& headerExtensions,
-  std::set<std::string>& absHeadersMoc, std::set<std::string>& absHeadersUic)
+  const std::string& absFilename, std::set<std::string>& mocHeaderFiles,
+  std::set<std::string>& uicHeaderFiles) const
 {
-  // search for header files and private header files we may need to moc:
-  std::string basepath = cmsys::SystemTools::GetFilenamePath(
-    cmsys::SystemTools::GetRealPath(absFilename));
-  basepath += '/';
-  basepath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
-
-  // Search for regular header
-  for (std::vector<std::string>::const_iterator ext = headerExtensions.begin();
-       ext != headerExtensions.end(); ++ext) {
-    const std::string headerName = basepath + "." + (*ext);
-    if (cmsys::SystemTools::FileExists(headerName.c_str())) {
-      // Moc headers
-      if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(headerName)) {
-        absHeadersMoc.insert(headerName);
-      }
-      // Uic headers
-      if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(headerName)) {
-        absHeadersUic.insert(headerName);
-      }
-      break;
-    }
+  std::string basepaths[2];
+  {
+    std::string bpath = SubDirPrefix(absFilename);
+    bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
+    // search for default header files and private header files
+    basepaths[0] = bpath;
+    basepaths[1] = bpath + "_p";
   }
-  // Search for private header
-  for (std::vector<std::string>::const_iterator ext = headerExtensions.begin();
-       ext != headerExtensions.end(); ++ext) {
-    const std::string headerName = basepath + "_p." + (*ext);
-    if (cmsys::SystemTools::FileExists(headerName.c_str())) {
+
+  for (const std::string* bpit = cmArrayBegin(basepaths);
+       bpit != cmArrayEnd(basepaths); ++bpit) {
+    std::string headerName;
+    if (this->FindHeader(headerName, *bpit)) {
       // Moc headers
-      if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(headerName)) {
-        absHeadersMoc.insert(headerName);
+      if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) {
+        mocHeaderFiles.insert(headerName);
       }
       // Uic headers
-      if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(headerName)) {
-        absHeadersUic.insert(headerName);
+      if (!this->UicSkip(absFilename) && !this->UicSkip(headerName)) {
+        uicHeaderFiles.insert(headerName);
       }
-      break;
     }
   }
 }
 
-void cmQtAutoGenerators::ParseHeaders(
-  const std::set<std::string>& absHeadersMoc,
-  const std::set<std::string>& absHeadersUic,
-  const std::map<std::string, std::string>& includedMocs,
-  std::map<std::string, std::string>& notIncludedMocs,
-  std::map<std::string, std::vector<std::string> >& includedUis)
+bool cmQtAutoGenerators::ParseHeaders(
+  const std::set<std::string>& mocHeaderFiles,
+  const std::set<std::string>& uicHeaderFiles,
+  const std::map<std::string, std::string>& mocsIncluded,
+  std::map<std::string, std::string>& mocsNotIncluded,
+  std::map<std::string, std::set<std::string> >& mocDepends,
+  std::map<std::string, std::vector<std::string> >& uisIncluded)
 {
+  bool success = true;
   // Merged header files list to read files only once
   std::set<std::string> headerFiles;
-  headerFiles.insert(absHeadersMoc.begin(), absHeadersMoc.end());
-  headerFiles.insert(absHeadersUic.begin(), absHeadersUic.end());
+  headerFiles.insert(mocHeaderFiles.begin(), mocHeaderFiles.end());
+  headerFiles.insert(uicHeaderFiles.begin(), uicHeaderFiles.end());
 
   for (std::set<std::string>::const_iterator hIt = headerFiles.begin();
        hIt != headerFiles.end(); ++hIt) {
     const std::string& headerName = *hIt;
-    const std::string contents = ReadAll(headerName);
-
-    // Parse header content for MOC
-    if ((absHeadersMoc.find(headerName) != absHeadersMoc.end()) &&
-        (includedMocs.find(headerName) == includedMocs.end())) {
-      // Process
-      if (this->Verbose) {
-        std::ostringstream err;
-        err << "AutoMoc: Checking " << headerName << "\n";
-        this->LogInfo(err.str());
+    std::string contentText;
+    if (ReadAll(contentText, headerName)) {
+      // Parse header content for MOC
+      if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) &&
+          (mocsIncluded.find(headerName) == mocsIncluded.end())) {
+        this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded,
+                                    mocDepends);
       }
-      std::string macroName;
-      if (this->MocRequired(contents, macroName)) {
-        notIncludedMocs[headerName] = fpathCheckSum.getPart(headerName) +
-          "/moc_" +
-          cmsys::SystemTools::GetFilenameWithoutLastExtension(headerName) +
-          ".cpp";
+      // Parse header content for UIC
+      if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) {
+        this->UicParseContent(headerName, contentText, uisIncluded);
       }
-    }
-
-    // Parse header content for UIC
-    if (absHeadersUic.find(headerName) != absHeadersUic.end()) {
-      this->ParseContentForUic(headerName, contents, includedUis);
+    } else {
+      std::ostringstream ost;
+      ost << "AutoGen: Error: Could not read header file:\n"
+          << Quoted(headerName);
+      this->LogError(ost.str());
+      success = false;
+      break;
     }
   }
+  return success;
 }
 
 bool cmQtAutoGenerators::MocGenerateAll(
-  const std::map<std::string, std::string>& includedMocs,
-  const std::map<std::string, std::string>& notIncludedMocs)
+  const std::map<std::string, std::string>& mocsIncluded,
+  const std::map<std::string, std::string>& mocsNotIncluded,
+  const std::map<std::string, std::set<std::string> >& mocDepends)
 {
-  if (this->MocExecutable.empty()) {
+  if (!this->MocEnabled()) {
     return true;
   }
 
-  // look for name collisions
+  // Look for name collisions
   {
     std::multimap<std::string, std::string> collisions;
     // Test merged map of included and notIncluded
-    std::map<std::string, std::string> mergedMocs(includedMocs);
-    mergedMocs.insert(notIncludedMocs.begin(), notIncludedMocs.end());
+    std::map<std::string, std::string> mergedMocs(mocsIncluded);
+    mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end());
     if (this->NameCollisionTest(mergedMocs, collisions)) {
-      std::ostringstream err;
-      err << "AutoMoc: Error: "
+      std::ostringstream ost;
+      ost << "AutoMoc: Error: "
              "The same moc file will be generated "
-             "from different sources."
-          << std::endl
-          << "To avoid this error either" << std::endl
-          << "- rename the source files or" << std::endl
-          << "- do not include the (moc_NAME.cpp|NAME.moc) file" << std::endl;
-      this->LogErrorNameCollision(err.str(), collisions);
+             "from different sources.\n"
+             "To avoid this error either\n"
+             "- rename the source files or\n"
+             "- do not include the (moc_NAME.cpp|NAME.moc) file";
+      this->LogErrorNameCollision(ost.str(), collisions);
       return false;
     }
   }
 
-  // generate moc files that are included by source files.
-  {
-    const std::string subDirPrefix = "include/";
-    for (std::map<std::string, std::string>::const_iterator it =
-           includedMocs.begin();
-         it != includedMocs.end(); ++it) {
-      if (!this->MocGenerateFile(it->first, it->second, subDirPrefix)) {
-        if (this->RunMocFailed) {
+  // Generate moc_predefs
+  if (!this->MocPredefsCmd.empty()) {
+    if (this->MocSettingsChanged ||
+        FileAbsentOrOlder(this->MocPredefsFileAbs, this->SettingsFile)) {
+      this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel);
+
+      std::string output;
+      {
+        // Compose command
+        std::vector<std::string> cmd = this->MocPredefsCmd;
+        // Add includes
+        cmd.insert(cmd.end(), this->MocIncludes.begin(),
+                   this->MocIncludes.end());
+        // Add definitions
+        for (std::vector<std::string>::const_iterator it =
+               this->MocDefinitions.begin();
+             it != this->MocDefinitions.end(); ++it) {
+          cmd.push_back("-D" + (*it));
+        }
+        // Add options
+        cmd.insert(cmd.end(), this->MocOptions.begin(),
+                   this->MocOptions.end());
+        // Execute command
+        if (!this->RunCommand(cmd, output, false)) {
+          {
+            std::ostringstream ost;
+            ost << "AutoMoc: Error: moc predefs generation command failed\n";
+            ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n";
+            ost << "AutoMoc: Command output:\n" << output << "\n";
+            this->LogError(ost.str());
+          }
+          return false;
+        }
+      }
+      // (Re)write predefs file only on demand
+      if (this->FileDiffers(this->MocPredefsFileAbs, output)) {
+        if (this->FileWrite("AutoMoc", this->MocPredefsFileAbs, output)) {
+          this->MocPredefsChanged = true;
+        } else {
           return false;
         }
       }
     }
   }
 
-  // generate moc files that are _not_ included by source files.
-  bool automocCppChanged = false;
-  {
-    const std::string subDirPrefix;
-    for (std::map<std::string, std::string>::const_iterator it =
-           notIncludedMocs.begin();
-         it != notIncludedMocs.end(); ++it) {
-      if (this->MocGenerateFile(it->first, it->second, subDirPrefix)) {
-        automocCppChanged = true;
-      } else {
-        if (this->RunMocFailed) {
-          return false;
-        }
+  // Generate moc files that are included by source files.
+  for (std::map<std::string, std::string>::const_iterator it =
+         mocsIncluded.begin();
+       it != mocsIncluded.end(); ++it) {
+    if (!this->MocGenerateFile(it->first, it->second, mocDepends, true)) {
+      if (this->MocRunFailed) {
+        return false;
+      }
+    }
+  }
+
+  // Generate moc files that are _not_ included by source files.
+  bool mocCompFileGenerated = false;
+  for (std::map<std::string, std::string>::const_iterator it =
+         mocsNotIncluded.begin();
+       it != mocsNotIncluded.end(); ++it) {
+    if (this->MocGenerateFile(it->first, it->second, mocDepends, false)) {
+      mocCompFileGenerated = true;
+    } else {
+      if (this->MocRunFailed) {
+        return false;
       }
     }
   }
 
-  // Compose moc_compilation.cpp content
+  // Compose mocs compilation file content
   std::string automocSource;
   {
-    std::ostringstream outStream;
-    outStream << "/* This file is autogenerated, do not edit*/\n";
-    if (notIncludedMocs.empty()) {
+    std::ostringstream ost;
+    ost << "/* This file is autogenerated, do not edit*/\n";
+    if (mocsNotIncluded.empty()) {
       // Dummy content
-      outStream << "enum some_compilers { need_more_than_nothing };\n";
+      ost << "enum some_compilers { need_more_than_nothing };\n";
     } else {
       // Valid content
       for (std::map<std::string, std::string>::const_iterator it =
-             notIncludedMocs.begin();
-           it != notIncludedMocs.end(); ++it) {
-        outStream << "#include \"" << it->second << "\"\n";
+             mocsNotIncluded.begin();
+           it != mocsNotIncluded.end(); ++it) {
+        ost << "#include \"" << it->second << "\"\n";
       }
     }
-    outStream.flush();
-    automocSource = outStream.str();
-  }
-
-  // Check if we even need to update moc_compilation.cpp
-  if (!automocCppChanged) {
-    // compare contents of the moc_compilation.cpp file
-    const std::string oldContents = ReadAll(this->OutMocCppFilenameAbs);
-    if (oldContents == automocSource) {
-      // nothing changed: don't touch the moc_compilation.cpp file
-      if (this->Verbose) {
-        std::ostringstream err;
-        err << "AutoMoc: " << this->OutMocCppFilenameRel << " still up to date"
-            << std::endl;
-        this->LogInfo(err.str());
-      }
-      return true;
-    }
+    automocSource = ost.str();
   }
 
-  // Actually write moc_compilation.cpp
-  {
-    std::string msg = "Generating MOC compilation ";
-    msg += this->OutMocCppFilenameRel;
-    this->LogBold(msg);
-  }
-  // Make sure the parent directory exists
-  bool success = this->MakeParentDirectory(this->OutMocCppFilenameAbs);
-  if (success) {
-    cmsys::ofstream outfile;
-    outfile.open(this->OutMocCppFilenameAbs.c_str(), std::ios::trunc);
-    if (!outfile) {
-      success = false;
-      std::ostringstream err;
-      err << "AutoMoc: error opening " << this->OutMocCppFilenameAbs << "\n";
-      this->LogError(err.str());
-    } else {
-      outfile << automocSource;
-      // Check for write errors
-      if (!outfile.good()) {
-        success = false;
-        std::ostringstream err;
-        err << "AutoMoc: error writing " << this->OutMocCppFilenameAbs << "\n";
-        this->LogError(err.str());
-      }
+  if (this->FileDiffers(this->MocCompFileAbs, automocSource)) {
+    // Actually write mocs compilation file
+    this->LogBold("Generating MOC compilation " + this->MocCompFileRel);
+    if (!this->FileWrite("AutoMoc", this->MocCompFileAbs, automocSource)) {
+      return false;
     }
+  } else if (mocCompFileGenerated) {
+    // Only touch mocs compilation file
+    if (this->Verbose) {
+      this->LogInfo("Touching MOC compilation " + this->MocCompFileRel);
+    }
+    cmSystemTools::Touch(this->MocCompFileAbs, false);
   }
-  return success;
+
+  return true;
 }
 
 /**
  * @return True if a moc file was created. False may indicate an error.
  */
-bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile,
-                                         const std::string& mocFileName,
-                                         const std::string& subDirPrefix)
+bool cmQtAutoGenerators::MocGenerateFile(
+  const std::string& sourceFile, const std::string& mocFileName,
+  const std::map<std::string, std::set<std::string> >& mocDepends,
+  bool included)
 {
+  bool mocGenerated = false;
+  bool generateMoc = this->MocSettingsChanged || this->MocPredefsChanged;
+
   const std::string mocFileRel =
-    this->AutogenBuildSubDir + subDirPrefix + mocFileName;
-  const std::string mocFileAbs = this->CurrentBinaryDir + mocFileRel;
+    included ? (this->AutogenIncludeDir + mocFileName) : mocFileName;
+  const std::string mocFileAbs =
+    cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, mocFileRel);
 
-  bool generateMoc = this->GenerateMocAll;
-  // Test if the source file is newer that the build file
   if (!generateMoc) {
+    // Test if the source file is newer that the build file
     generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile);
+    if (!generateMoc) {
+      // Test if a dependency file changed
+      std::map<std::string, std::set<std::string> >::const_iterator dit =
+        mocDepends.find(sourceFile);
+      if (dit != mocDepends.end()) {
+        for (std::set<std::string>::const_iterator fit = dit->second.begin();
+             fit != dit->second.end(); ++fit) {
+          if (FileAbsentOrOlder(mocFileAbs, *fit)) {
+            generateMoc = true;
+            break;
+          }
+        }
+      }
+    }
   }
   if (generateMoc) {
     // Log
     this->LogBold("Generating MOC source " + mocFileRel);
 
     // Make sure the parent directory exists
-    if (!this->MakeParentDirectory(mocFileAbs)) {
-      this->RunMocFailed = true;
-      return false;
-    }
-
-    std::vector<std::string> command;
-    command.push_back(this->MocExecutable);
-    command.insert(command.end(), this->MocIncludes.begin(),
-                   this->MocIncludes.end());
-    command.insert(command.end(), this->MocDefinitions.begin(),
-                   this->MocDefinitions.end());
-    command.insert(command.end(), this->MocOptions.begin(),
-                   this->MocOptions.end());
-#ifdef _WIN32
-    command.push_back("-DWIN32");
-#endif
-    command.push_back("-o");
-    command.push_back(mocFileAbs);
-    command.push_back(sourceFile);
-
-    if (this->Verbose) {
-      this->LogCommand(command);
+    if (this->MakeParentDirectory("AutoMoc", mocFileAbs)) {
+      // Compose moc command
+      std::vector<std::string> cmd;
+      cmd.push_back(this->MocExecutable);
+      // Add includes
+      cmd.insert(cmd.end(), this->MocIncludes.begin(),
+                 this->MocIncludes.end());
+      // Add definitions
+      for (std::vector<std::string>::const_iterator it =
+             this->MocDefinitions.begin();
+           it != this->MocDefinitions.end(); ++it) {
+        cmd.push_back("-D" + (*it));
+      }
+      // Add options
+      cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end());
+      // Add predefs include
+      if (!this->MocPredefsFileAbs.empty()) {
+        cmd.push_back("--include");
+        cmd.push_back(this->MocPredefsFileAbs);
+      }
+      cmd.push_back("-o");
+      cmd.push_back(mocFileAbs);
+      cmd.push_back(sourceFile);
+
+      // Execute moc command
+      std::string output;
+      if (this->RunCommand(cmd, output)) {
+        // Success
+        mocGenerated = true;
+      } else {
+        // Command failed
+        {
+          std::ostringstream ost;
+          ost << "AutoMoc: Error: moc process failed for\n";
+          ost << Quoted(mocFileRel) << "\n";
+          ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n";
+          ost << "AutoMoc: Command output:\n" << output << "\n";
+          this->LogError(ost.str());
+        }
+        cmSystemTools::RemoveFile(mocFileAbs);
+        this->MocRunFailed = true;
+      }
+    } else {
+      // Parent directory creation failed
+      this->MocRunFailed = true;
     }
+  }
+  return mocGenerated;
+}
 
-    std::string output;
-    int retVal = 0;
-    bool result =
-      cmSystemTools::RunSingleCommand(command, &output, &output, &retVal);
-    if (!result || retVal) {
-      {
-        std::ostringstream err;
-        err << "AutoMoc: Error: moc process for " << mocFileRel << " failed:\n"
-            << output << std::endl;
-        this->LogError(err.str());
+bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
+                                             const std::string& sourceFile,
+                                             const std::string& includeString)
+{
+  bool success = false;
+  // Search in vicinity of the source
+  {
+    std::string testPath = SubDirPrefix(sourceFile);
+    testPath += includeString;
+    if (cmsys::SystemTools::FileExists(testPath.c_str())) {
+      absFile = cmsys::SystemTools::GetRealPath(testPath);
+      success = true;
+    }
+  }
+  // Search in include directories
+  if (!success) {
+    for (std::vector<std::string>::const_iterator iit =
+           this->UicSearchPaths.begin();
+         iit != this->UicSearchPaths.end(); ++iit) {
+      const std::string fullPath = ((*iit) + '/' + includeString);
+      if (cmsys::SystemTools::FileExists(fullPath.c_str())) {
+        absFile = cmsys::SystemTools::GetRealPath(fullPath);
+        success = true;
+        break;
       }
-      cmSystemTools::RemoveFile(mocFileAbs);
-      this->RunMocFailed = true;
-      return false;
     }
-    return true;
   }
-  return false;
+  return success;
 }
 
 bool cmQtAutoGenerators::UicGenerateAll(
-  const std::map<std::string, std::vector<std::string> >& includedUis)
+  const std::map<std::string, std::vector<std::string> >& uisIncluded)
 {
-  if (this->UicExecutable.empty()) {
+  if (!this->UicEnabled()) {
     return true;
   }
 
   // single map with input / output names
-  std::map<std::string, std::map<std::string, std::string> > uiGenMap;
-  std::map<std::string, std::string> testMap;
-  for (std::map<std::string, std::vector<std::string> >::const_iterator it =
-         includedUis.begin();
-       it != includedUis.end(); ++it) {
-    // source file path
-    std::string sourcePath = cmsys::SystemTools::GetFilenamePath(it->first);
-    sourcePath += '/';
-    // insert new map for source file an use new reference
-    uiGenMap[it->first] = std::map<std::string, std::string>();
-    std::map<std::string, std::string>& sourceMap = uiGenMap[it->first];
-    for (std::vector<std::string>::const_iterator sit = it->second.begin();
-         sit != it->second.end(); ++sit) {
-      const std::string& uiFileName = *sit;
-      const std::string uiInputFile = sourcePath + uiFileName + ".ui";
-      const std::string uiOutputFile = "ui_" + uiFileName + ".h";
-      sourceMap[uiInputFile] = uiOutputFile;
-      testMap[uiInputFile] = uiOutputFile;
-    }
-  }
-
-  // look for name collisions
+  std::map<std::string, std::map<std::string, std::string> > sourceGenMap;
   {
-    std::multimap<std::string, std::string> collisions;
-    if (this->NameCollisionTest(testMap, collisions)) {
-      std::ostringstream err;
-      err << "AutoUic: Error: The same ui_NAME.h file will be generated "
-             "from different sources."
-          << std::endl
-          << "To avoid this error rename the source files." << std::endl;
-      this->LogErrorNameCollision(err.str(), collisions);
-      return false;
+    // Collision lookup map
+    std::map<std::string, std::string> testMap;
+    // Compile maps
+    for (std::map<std::string, std::vector<std::string> >::const_iterator sit =
+           uisIncluded.begin();
+         sit != uisIncluded.end(); ++sit) {
+      const std::string& source(sit->first);
+      const std::vector<std::string>& sourceIncs(sit->second);
+      // insert new source/destination map
+      std::map<std::string, std::string>& uiGenMap = sourceGenMap[source];
+      for (std::vector<std::string>::const_iterator uit = sourceIncs.begin();
+           uit != sourceIncs.end(); ++uit) {
+        // Remove ui_ from the begin filename by substr()
+        const std::string uiBasePath = SubDirPrefix(*uit);
+        const std::string uiBaseName =
+          cmsys::SystemTools::GetFilenameWithoutLastExtension(*uit).substr(3);
+        const std::string searchFileName = uiBasePath + uiBaseName + ".ui";
+        std::string uiInputFile;
+        if (UicFindIncludedFile(uiInputFile, source, searchFileName)) {
+          std::string uiOutputFile = uiBasePath + "ui_" + uiBaseName + ".h";
+          cmSystemTools::ReplaceString(uiOutputFile, "..", "__");
+          uiGenMap[uiInputFile] = uiOutputFile;
+          testMap[uiInputFile] = uiOutputFile;
+        } else {
+          this->LogError("AutoUic: Error: " + Quoted(sit->first) +
+                         "\nCould not find " + Quoted(searchFileName));
+          return false;
+        }
+      }
+    }
+    // look for name collisions
+    {
+      std::multimap<std::string, std::string> collisions;
+      if (this->NameCollisionTest(testMap, collisions)) {
+        std::ostringstream ost;
+        ost << "AutoUic: Error: The same ui_NAME.h file will be generated "
+               "from different sources.\n"
+               "To avoid this error rename the source files.\n";
+        this->LogErrorNameCollision(ost.str(), collisions);
+        return false;
+      }
     }
   }
-  testMap.clear();
 
   // generate ui files
   for (std::map<std::string,
                 std::map<std::string, std::string> >::const_iterator it =
-         uiGenMap.begin();
-       it != uiGenMap.end(); ++it) {
+         sourceGenMap.begin();
+       it != sourceGenMap.end(); ++it) {
     for (std::map<std::string, std::string>::const_iterator sit =
            it->second.begin();
          sit != it->second.end(); ++sit) {
       if (!this->UicGenerateFile(it->first, sit->first, sit->second)) {
-        if (this->RunUicFailed) {
+        if (this->UicRunFailed) {
           return false;
         }
       }
@@ -1327,13 +1543,15 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName,
                                          const std::string& uiInputFile,
                                          const std::string& uiOutputFile)
 {
-  const std::string uicFileRel =
-    this->AutogenBuildSubDir + "include/" + uiOutputFile;
-  const std::string uicFileAbs = this->CurrentBinaryDir + uicFileRel;
+  bool uicGenerated = false;
+  bool generateUic = this->UicSettingsChanged;
+
+  const std::string uicFileRel = this->AutogenIncludeDir + uiOutputFile;
+  const std::string uicFileAbs =
+    cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, uicFileRel);
 
-  bool generateUic = this->GenerateUicAll;
-  // Test if the source file is newer that the build file
   if (!generateUic) {
+    // Test if the source file is newer that the build file
     generateUic = FileAbsentOrOlder(uicFileAbs, uiInputFile);
   }
   if (generateUic) {
@@ -1341,67 +1559,70 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName,
     this->LogBold("Generating UIC header " + uicFileRel);
 
     // Make sure the parent directory exists
-    if (!this->MakeParentDirectory(uicFileAbs)) {
-      this->RunUicFailed = true;
-      return false;
-    }
-
-    std::vector<std::string> command;
-    command.push_back(this->UicExecutable);
-
-    std::vector<std::string> opts = this->UicTargetOptions;
-    std::map<std::string, std::string>::const_iterator optionIt =
-      this->UicOptions.find(uiInputFile);
-    if (optionIt != this->UicOptions.end()) {
-      std::vector<std::string> fileOpts;
-      cmSystemTools::ExpandListArgument(optionIt->second, fileOpts);
-      UicMergeOptions(opts, fileOpts, this->QtMajorVersion == "5");
-    }
-    command.insert(command.end(), opts.begin(), opts.end());
-
-    command.push_back("-o");
-    command.push_back(uicFileAbs);
-    command.push_back(uiInputFile);
-
-    if (this->Verbose) {
-      this->LogCommand(command);
-    }
-    std::string output;
-    int retVal = 0;
-    bool result =
-      cmSystemTools::RunSingleCommand(command, &output, &output, &retVal);
-    if (!result || retVal) {
+    if (this->MakeParentDirectory("AutoUic", uicFileAbs)) {
+      // Compose uic command
+      std::vector<std::string> cmd;
+      cmd.push_back(this->UicExecutable);
       {
-        std::ostringstream err;
-        err << "AutoUic: Error: uic process for " << uicFileRel
-            << " needed by\n \"" << realName << "\"\nfailed:\n"
-            << output << std::endl;
-        this->LogError(err.str());
+        std::vector<std::string> allOpts = this->UicTargetOptions;
+        std::map<std::string, std::string>::const_iterator optionIt =
+          this->UicOptions.find(uiInputFile);
+        if (optionIt != this->UicOptions.end()) {
+          std::vector<std::string> fileOpts;
+          cmSystemTools::ExpandListArgument(optionIt->second, fileOpts);
+          UicMergeOptions(allOpts, fileOpts, (this->QtMajorVersion == "5"));
+        }
+        cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
       }
-      cmSystemTools::RemoveFile(uicFileAbs);
-      this->RunUicFailed = true;
-      return false;
+      cmd.push_back("-o");
+      cmd.push_back(uicFileAbs);
+      cmd.push_back(uiInputFile);
+
+      std::string output;
+      if (this->RunCommand(cmd, output)) {
+        // Success
+        uicGenerated = true;
+      } else {
+        // Command failed
+        {
+          std::ostringstream ost;
+          ost << "AutoUic: Error: uic process failed for\n";
+          ost << Quoted(uicFileRel) << " needed by\n";
+          ost << Quoted(realName) << "\n";
+          ost << "AutoUic: Command:\n" << QuotedCommand(cmd) << "\n";
+          ost << "AutoUic: Command output:\n" << output << "\n";
+          this->LogError(ost.str());
+        }
+        cmSystemTools::RemoveFile(uicFileAbs);
+        this->UicRunFailed = true;
+      }
+    } else {
+      // Parent directory creation failed
+      this->UicRunFailed = true;
     }
-    return true;
   }
-  return false;
+  return uicGenerated;
 }
 
-bool cmQtAutoGenerators::QrcGenerateAll()
+bool cmQtAutoGenerators::RccGenerateAll()
 {
-  if (this->RccExecutable.empty()) {
+  if (!this->RccEnabled()) {
     return true;
   }
 
   // generate single map with input / output names
   std::map<std::string, std::string> qrcGenMap;
-  for (std::vector<std::string>::const_iterator si = this->RccSources.begin();
-       si != this->RccSources.end(); ++si) {
-    const std::string ext = cmsys::SystemTools::GetFilenameLastExtension(*si);
-    if (ext == ".qrc") {
-      qrcGenMap[*si] = this->AutogenBuildSubDir + fpathCheckSum.getPart(*si) +
-        "/qrc_" + cmsys::SystemTools::GetFilenameWithoutLastExtension(*si) +
-        ".cpp";
+  {
+    const std::string qrcPrefix = "qrc_";
+    const std::string qrcSuffix = this->ConfigSuffix + ".cpp";
+    for (std::vector<std::string>::const_iterator si =
+           this->RccSources.begin();
+         si != this->RccSources.end(); ++si) {
+      const std::string ext =
+        cmsys::SystemTools::GetFilenameLastExtension(*si);
+      if (ext == ".qrc") {
+        qrcGenMap[*si] = this->ChecksumedPath(*si, qrcPrefix, qrcSuffix);
+      }
     }
   }
 
@@ -1409,12 +1630,11 @@ bool cmQtAutoGenerators::QrcGenerateAll()
   {
     std::multimap<std::string, std::string> collisions;
     if (this->NameCollisionTest(qrcGenMap, collisions)) {
-      std::ostringstream err;
-      err << "AutoRcc: Error: The same qrc_NAME.cpp file"
-             " will be generated from different sources."
-          << std::endl
-          << "To avoid this error rename the source .qrc files." << std::endl;
-      this->LogErrorNameCollision(err.str(), collisions);
+      std::ostringstream ost;
+      ost << "AutoRcc: Error: The same qrc_NAME.cpp file"
+             " will be generated from different sources.\n"
+             "To avoid this error rename the source .qrc files.\n";
+      this->LogErrorNameCollision(ost.str(), collisions);
       return false;
     }
   }
@@ -1424,8 +1644,8 @@ bool cmQtAutoGenerators::QrcGenerateAll()
          qrcGenMap.begin();
        si != qrcGenMap.end(); ++si) {
     bool unique = FileNameIsUnique(si->first, qrcGenMap);
-    if (!this->QrcGenerateFile(si->first, si->second, unique)) {
-      if (this->RunRccFailed) {
+    if (!this->RccGenerateFile(si->first, si->second, unique)) {
+      if (this->RccRunFailed) {
         return false;
       }
     }
@@ -1436,145 +1656,168 @@ bool cmQtAutoGenerators::QrcGenerateAll()
 /**
  * @return True if a rcc file was created. False may indicate an error.
  */
-bool cmQtAutoGenerators::QrcGenerateFile(const std::string& qrcInputFile,
-                                         const std::string& qrcOutputFile,
+bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
+                                         const std::string& rccOutputFile,
                                          bool unique_n)
 {
-  std::string symbolName =
-    cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile);
-  if (!unique_n) {
-    symbolName += "_";
-    symbolName += fpathCheckSum.getPart(qrcInputFile);
-  }
-  // Replace '-' with '_'. The former is valid for
-  // file names but not for symbol names.
-  std::replace(symbolName.begin(), symbolName.end(), '-', '_');
-
-  const std::string qrcBuildFile = this->CurrentBinaryDir + qrcOutputFile;
-
-  bool generateQrc = this->GenerateRccAll;
-  // Test if the resources list file is newer than build file
-  if (!generateQrc) {
-    generateQrc = FileAbsentOrOlder(qrcBuildFile, qrcInputFile);
-  }
-  // Test if any resource file is newer than the build file
-  if (!generateQrc) {
-    const std::vector<std::string>& files = this->RccInputs[qrcInputFile];
-    for (std::vector<std::string>::const_iterator it = files.begin();
-         it != files.end(); ++it) {
-      if (FileAbsentOrOlder(qrcBuildFile, *it)) {
-        generateQrc = true;
-        break;
+  bool rccGenerated = false;
+  bool generateRcc = this->RccSettingsChanged;
+
+  const std::string rccBuildFile =
+    cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, rccOutputFile);
+
+  if (!generateRcc) {
+    // Test if the resources list file is newer than build file
+    generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile);
+    if (!generateRcc) {
+      // Acquire input file list
+      std::vector<std::string> readFiles;
+      const std::vector<std::string>* files = &this->RccInputs[rccInputFile];
+      if (files->empty()) {
+        // Read input file list from qrc file
+        std::string error;
+        if (cmQtAutoGeneratorCommon::RccListInputs(
+              this->QtMajorVersion, this->RccExecutable, rccInputFile,
+              readFiles, &error)) {
+          files = &readFiles;
+        } else {
+          files = CM_NULLPTR;
+          this->LogError(error);
+          this->RccRunFailed = true;
+        }
+      }
+      // Test if any input file is newer than the build file
+      if (files != CM_NULLPTR) {
+        for (std::vector<std::string>::const_iterator it = files->begin();
+             it != files->end(); ++it) {
+          if (FileAbsentOrOlder(rccBuildFile, *it)) {
+            generateRcc = true;
+            break;
+          }
+        }
       }
     }
   }
-  if (generateQrc) {
-    {
-      std::string msg = "Generating RCC source ";
-      msg += qrcOutputFile;
-      this->LogBold(msg);
-    }
+  if (generateRcc) {
+    // Log
+    this->LogBold("Generating RCC source " + rccOutputFile);
 
     // Make sure the parent directory exists
-    if (!this->MakeParentDirectory(qrcOutputFile)) {
-      this->RunRccFailed = true;
-      return false;
-    }
-
-    std::vector<std::string> command;
-    command.push_back(this->RccExecutable);
-    {
-      std::map<std::string, std::string>::const_iterator optionIt =
-        this->RccOptions.find(qrcInputFile);
-      if (optionIt != this->RccOptions.end()) {
-        cmSystemTools::ExpandListArgument(optionIt->second, command);
+    if (this->MakeParentDirectory("AutoRcc", rccBuildFile)) {
+      // Compose symbol name
+      std::string symbolName =
+        cmsys::SystemTools::GetFilenameWithoutLastExtension(rccInputFile);
+      if (!unique_n) {
+        symbolName += "_";
+        symbolName += FPathChecksum.getPart(rccInputFile);
       }
-    }
-    command.push_back("-name");
-    command.push_back(symbolName);
-    command.push_back("-o");
-    command.push_back(qrcBuildFile);
-    command.push_back(qrcInputFile);
+      // Replace '-' with '_'. The former is valid for
+      // file names but not for symbol names.
+      std::replace(symbolName.begin(), symbolName.end(), '-', '_');
 
-    if (this->Verbose) {
-      this->LogCommand(command);
-    }
-    std::string output;
-    int retVal = 0;
-    bool result =
-      cmSystemTools::RunSingleCommand(command, &output, &output, &retVal);
-    if (!result || retVal) {
+      // Compose rcc command
+      std::vector<std::string> cmd;
+      cmd.push_back(this->RccExecutable);
       {
-        std::ostringstream err;
-        err << "AutoRcc: Error: rcc process for " << qrcOutputFile
-            << " failed:\n"
-            << output << std::endl;
-        this->LogError(err.str());
+        std::map<std::string, std::string>::const_iterator optionIt =
+          this->RccOptions.find(rccInputFile);
+        if (optionIt != this->RccOptions.end()) {
+          cmSystemTools::ExpandListArgument(optionIt->second, cmd);
+        }
       }
-      cmSystemTools::RemoveFile(qrcBuildFile);
-      this->RunRccFailed = true;
-      return false;
+      cmd.push_back("-name");
+      cmd.push_back(symbolName);
+      cmd.push_back("-o");
+      cmd.push_back(rccBuildFile);
+      cmd.push_back(rccInputFile);
+
+      std::string output;
+      if (this->RunCommand(cmd, output)) {
+        // Success
+        rccGenerated = true;
+      } else {
+        // Command failed
+        {
+          std::ostringstream ost;
+          ost << "AutoRcc: Error: rcc process failed for\n";
+          ost << Quoted(rccOutputFile) << "\n";
+          ost << "AutoRcc: Command:\n" << QuotedCommand(cmd) << "\n";
+          ost << "AutoRcc: Command output:\n" << output << "\n";
+          this->LogError(ost.str());
+        }
+        cmSystemTools::RemoveFile(rccBuildFile);
+        this->RccRunFailed = true;
+      }
+    } else {
+      // Parent directory creation failed
+      this->RccRunFailed = true;
     }
-    return true;
   }
-  return false;
+  return rccGenerated;
 }
 
 void cmQtAutoGenerators::LogErrorNameCollision(
   const std::string& message,
-  const std::multimap<std::string, std::string>& collisions)
+  const std::multimap<std::string, std::string>& collisions) const
 {
   typedef std::multimap<std::string, std::string>::const_iterator Iter;
 
-  std::ostringstream err;
+  std::ostringstream ost;
   // Add message
-  err << message;
+  if (!message.empty()) {
+    ost << message;
+    if (message[message.size() - 1] != '\n') {
+      ost << '\n';
+    }
+  }
   // Append collision list
   for (Iter it = collisions.begin(); it != collisions.end(); ++it) {
-    err << it->first << " : " << it->second << std::endl;
+    ost << it->first << " : " << it->second << '\n';
   }
-  this->LogError(err.str());
+  this->LogError(ost.str());
 }
 
-void cmQtAutoGenerators::LogBold(const std::string& message)
+void cmQtAutoGenerators::LogBold(const std::string& message) const
 {
   cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
                                      cmsysTerminal_Color_ForegroundBold,
                                    message.c_str(), true, this->ColorOutput);
 }
 
-void cmQtAutoGenerators::LogInfo(const std::string& message)
+void cmQtAutoGenerators::LogInfo(const std::string& message) const
 {
-  std::cout << message.c_str();
-}
-
-void cmQtAutoGenerators::LogWarning(const std::string& message)
-{
-  std::ostringstream ostr;
-  ostr << message << "\n";
-  std::cout << message.c_str();
+  std::string msg(message);
+  if (!msg.empty()) {
+    if (msg[msg.size() - 1] != '\n') {
+      msg.push_back('\n');
+    }
+    cmSystemTools::Stdout(msg.c_str(), msg.size());
+  }
 }
 
-void cmQtAutoGenerators::LogError(const std::string& message)
+void cmQtAutoGenerators::LogWarning(const std::string& message) const
 {
-  std::ostringstream ostr;
-  ostr << message << "\n\n";
-  std::cerr << ostr.str();
+  std::string msg(message);
+  if (!msg.empty()) {
+    if (msg[msg.size() - 1] != '\n') {
+      msg.push_back('\n');
+    }
+    // Append empty line
+    msg.push_back('\n');
+    cmSystemTools::Stdout(msg.c_str(), msg.size());
+  }
 }
 
-void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command)
+void cmQtAutoGenerators::LogError(const std::string& message) const
 {
-  std::ostringstream sbuf;
-  for (std::vector<std::string>::const_iterator cmdIt = command.begin();
-       cmdIt != command.end(); ++cmdIt) {
-    if (cmdIt != command.begin()) {
-      sbuf << " ";
+  std::string msg(message);
+  if (!msg.empty()) {
+    if (msg[msg.size() - 1] != '\n') {
+      msg.push_back('\n');
     }
-    sbuf << *cmdIt;
-  }
-  if (!sbuf.str().empty()) {
-    sbuf << std::endl;
-    this->LogInfo(sbuf.str());
+    // Append empty line
+    msg.push_back('\n');
+    cmSystemTools::Stderr(msg.c_str(), msg.size());
   }
 }
 
@@ -1584,7 +1827,7 @@ void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command)
  */
 bool cmQtAutoGenerators::NameCollisionTest(
   const std::map<std::string, std::string>& genFiles,
-  std::multimap<std::string, std::string>& collisions)
+  std::multimap<std::string, std::string>& collisions) const
 {
   typedef std::map<std::string, std::string>::const_iterator Iter;
   typedef std::map<std::string, std::string>::value_type VType;
@@ -1609,19 +1852,174 @@ bool cmQtAutoGenerators::NameCollisionTest(
 }
 
 /**
+ * @brief Generates a file path based on the checksum of the source file path
+ * @return The path
+ */
+std::string cmQtAutoGenerators::ChecksumedPath(
+  const std::string& sourceFile, const std::string& basePrefix,
+  const std::string& baseSuffix) const
+{
+  std::string res = FPathChecksum.getPart(sourceFile);
+  res += "/";
+  res += basePrefix;
+  res += cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFile);
+  res += baseSuffix;
+  return res;
+}
+
+/**
  * @brief Generates the parent directory of the given file on demand
  * @return True on success
  */
-bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename)
+bool cmQtAutoGenerators::MakeParentDirectory(const char* logPrefix,
+                                             const std::string& filename) const
 {
   bool success = true;
   const std::string dirName = cmSystemTools::GetFilenamePath(filename);
   if (!dirName.empty()) {
     success = cmsys::SystemTools::MakeDirectory(dirName);
     if (!success) {
-      std::ostringstream err;
-      err << "AutoGen: Directory creation failed: " << dirName << std::endl;
-      this->LogError(err.str());
+      std::string error = logPrefix;
+      error += ": Error: Parent directory creation failed for ";
+      error += Quoted(filename);
+      this->LogError(error);
+    }
+  }
+  return success;
+}
+
+bool cmQtAutoGenerators::FileDiffers(const std::string& filename,
+                                     const std::string& content)
+{
+  bool differs = true;
+  {
+    std::string oldContents;
+    if (ReadAll(oldContents, filename)) {
+      differs = (oldContents != content);
+    }
+  }
+  return differs;
+}
+
+bool cmQtAutoGenerators::FileWrite(const char* logPrefix,
+                                   const std::string& filename,
+                                   const std::string& content)
+{
+  std::string error;
+  // Make sure the parent directory exists
+  if (this->MakeParentDirectory(logPrefix, filename)) {
+    cmsys::ofstream outfile;
+    outfile.open(filename.c_str(), std::ios::trunc);
+    if (outfile) {
+      outfile << content;
+      // Check for write errors
+      if (!outfile.good()) {
+        error = logPrefix;
+        error += ": Error writing ";
+        error += Quoted(filename);
+      }
+    } else {
+      error = logPrefix;
+      error = ": Error opening ";
+      error += Quoted(filename);
+    }
+  }
+  if (!error.empty()) {
+    this->LogError(error);
+    return false;
+  }
+  return true;
+}
+
+/**
+ * @brief Runs a command and returns true on success
+ * @return True on success
+ */
+bool cmQtAutoGenerators::RunCommand(const std::vector<std::string>& command,
+                                    std::string& output, bool verbose) const
+{
+  // Log command
+  if (this->Verbose) {
+    this->LogInfo(QuotedCommand(command));
+  }
+  // Execute command
+  int retVal = 0;
+  bool res = cmSystemTools::RunSingleCommand(
+    command, &output, &output, &retVal, CM_NULLPTR,
+    verbose ? cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE);
+  return (res && (retVal == 0));
+}
+
+/**
+ * @brief Tries to find the header file to the given file base path by
+ * appending different header extensions
+ * @return True on success
+ */
+bool cmQtAutoGenerators::FindHeader(std::string& header,
+                                    const std::string& testBasePath) const
+{
+  for (std::vector<std::string>::const_iterator ext =
+         this->HeaderExtensions.begin();
+       ext != this->HeaderExtensions.end(); ++ext) {
+    std::string testFilePath(testBasePath);
+    testFilePath += '.';
+    testFilePath += (*ext);
+    if (cmsys::SystemTools::FileExists(testFilePath.c_str())) {
+      header = testFilePath;
+      return true;
+    }
+  }
+  return false;
+}
+
+std::string cmQtAutoGenerators::MocFindHeader(
+  const std::string& sourcePath, const std::string& includeBase) const
+{
+  std::string header;
+  // Search in vicinity of the source
+  if (!this->FindHeader(header, sourcePath + includeBase)) {
+    // Search in include directories
+    for (std::vector<std::string>::const_iterator iit =
+           this->MocIncludePaths.begin();
+         iit != this->MocIncludePaths.end(); ++iit) {
+      const std::string fullPath = ((*iit) + '/' + includeBase);
+      if (FindHeader(header, fullPath)) {
+        break;
+      }
+    }
+  }
+  // Sanitize
+  if (!header.empty()) {
+    header = cmsys::SystemTools::GetRealPath(header);
+  }
+  return header;
+}
+
+bool cmQtAutoGenerators::MocFindIncludedFile(
+  std::string& absFile, const std::string& sourcePath,
+  const std::string& includeString) const
+{
+  bool success = false;
+  // Search in vicinity of the source
+  {
+    std::string testPath = sourcePath;
+    testPath += includeString;
+    if (cmsys::SystemTools::FileExists(testPath.c_str())) {
+      absFile = cmsys::SystemTools::GetRealPath(testPath);
+      success = true;
+    }
+  }
+  // Search in include directories
+  if (!success) {
+    for (std::vector<std::string>::const_iterator iit =
+           this->MocIncludePaths.begin();
+         iit != this->MocIncludePaths.end(); ++iit) {
+      const std::string fullPath = ((*iit) + '/' + includeString);
+      if (cmsys::SystemTools::FileExists(fullPath.c_str())) {
+        absFile = cmsys::SystemTools::GetRealPath(fullPath);
+        success = true;
+        break;
+      }
     }
   }
   return success;
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 7891eb9..b525364 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -3,14 +3,15 @@
 #ifndef cmQtAutoGenerators_h
 #define cmQtAutoGenerators_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
-#include <cmFilePathChecksum.h>
-#include <cmsys/RegularExpression.hxx>
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmFilePathChecksum.h"
+#include "cmsys/RegularExpression.hxx"
 
-#include <list>
 #include <map>
 #include <set>
 #include <string>
+#include <utility>
 #include <vector>
 
 class cmMakefile;
@@ -22,147 +23,199 @@ public:
   bool Run(const std::string& targetDirectory, const std::string& config);
 
 private:
-  // - Configuration
+  // -- Types
+
+  /// @brief Used to extract additional dependencies from content text
+  struct MocDependFilter
+  {
+    std::string key;
+    cmsys::RegularExpression regExp;
+  };
+  typedef std::pair<std::string, cmsys::RegularExpression> MocMacroFilter;
+
+  // -- Configuration
+  bool MocDependFilterPush(const std::string& key, const std::string& regExp);
   bool ReadAutogenInfoFile(cmMakefile* makefile,
                            const std::string& targetDirectory,
                            const std::string& config);
 
-  std::string MocSettingsStringCompose();
-  std::string UicSettingsStringCompose();
-  std::string RccSettingsStringCompose();
-  void OldSettingsReadFile(cmMakefile* makefile,
-                           const std::string& targetDirectory);
-  bool OldSettingsWriteFile(const std::string& targetDirectory);
+  bool MocEnabled() const { return !this->MocExecutable.empty(); }
+  bool UicEnabled() const { return !this->UicExecutable.empty(); }
+  bool RccEnabled() const { return !this->RccExecutable.empty(); }
+
+  // -- Settings file
+  void SettingsFileRead(cmMakefile* makefile);
+  bool SettingsFileWrite();
+
+  bool AnySettingsChanged() const
+  {
+    return (this->MocSettingsChanged || this->RccSettingsChanged ||
+            this->UicSettingsChanged);
+  }
+
+  // -- Init and run
+  void Init(cmMakefile* makefile);
+  bool RunAutogen();
 
-  // - Init and run
-  void Init();
-  bool RunAutogen(cmMakefile* makefile);
+  // -- Content analysis
+  bool MocRequired(const std::string& contentText,
+                   std::string* macroName = CM_NULLPTR);
+  void MocFindDepends(
+    const std::string& absFilename, const std::string& contentText,
+    std::map<std::string, std::set<std::string> >& mocDepends);
 
-  // - Content analysis
-  bool MocRequired(const std::string& text, std::string& macroName);
-  bool MocSkipTest(const std::string& absFilename);
-  bool UicSkipTest(const std::string& absFilename);
+  bool MocSkip(const std::string& absFilename) const;
+  bool UicSkip(const std::string& absFilename) const;
 
   bool ParseSourceFile(
     const std::string& absFilename,
-    const std::vector<std::string>& headerExtensions,
-    std::map<std::string, std::string>& includedMocs,
+    std::map<std::string, std::string>& mocsIncluded,
+    std::map<std::string, std::set<std::string> >& mocDepends,
     std::map<std::string, std::vector<std::string> >& includedUis,
     bool relaxed);
 
-  void SearchHeadersForSourceFile(
-    const std::string& absFilename,
-    const std::vector<std::string>& headerExtensions,
-    std::set<std::string>& absHeadersMoc,
-    std::set<std::string>& absHeadersUic);
-
-  void ParseHeaders(
-    const std::set<std::string>& absHeadersMoc,
-    const std::set<std::string>& absHeadersUic,
-    const std::map<std::string, std::string>& includedMocs,
-    std::map<std::string, std::string>& notIncludedMocs,
+  void SearchHeadersForSourceFile(const std::string& absFilename,
+                                  std::set<std::string>& mocHeaderFiles,
+                                  std::set<std::string>& uicHeaderFiles) const;
+
+  bool ParseHeaders(
+    const std::set<std::string>& mocHeaderFiles,
+    const std::set<std::string>& uicHeaderFiles,
+    const std::map<std::string, std::string>& mocsIncluded,
+    std::map<std::string, std::string>& mocsNotIncluded,
+    std::map<std::string, std::set<std::string> >& mocDepends,
     std::map<std::string, std::vector<std::string> >& includedUis);
 
-  void ParseContentForUic(
-    const std::string& fileName, const std::string& contentsString,
+  void UicParseContent(
+    const std::string& fileName, const std::string& contentText,
     std::map<std::string, std::vector<std::string> >& includedUis);
 
-  bool ParseContentForMoc(const std::string& absFilename,
-                          const std::string& contentsString,
-                          const std::vector<std::string>& headerExtensions,
-                          std::map<std::string, std::string>& includedMocs,
-                          bool relaxed);
+  bool MocParseSourceContent(
+    const std::string& absFilename, const std::string& contentText,
+    std::map<std::string, std::string>& mocsIncluded,
+    std::map<std::string, std::set<std::string> >& mocDepends, bool relaxed);
 
-  // - Moc file generation
-  bool MocGenerateAll(
-    const std::map<std::string, std::string>& includedMocs,
-    const std::map<std::string, std::string>& notIncludedMocs);
-  bool MocGenerateFile(const std::string& sourceFile,
-                       const std::string& mocFileName,
-                       const std::string& subDirPrefix);
+  void MocParseHeaderContent(
+    const std::string& absFilename, const std::string& contentText,
+    std::map<std::string, std::string>& mocsNotIncluded,
+    std::map<std::string, std::set<std::string> >& mocDepends);
 
-  // - Uic file generation
+  // -- Moc file generation
+  bool MocGenerateAll(
+    const std::map<std::string, std::string>& mocsIncluded,
+    const std::map<std::string, std::string>& mocsNotIncluded,
+    const std::map<std::string, std::set<std::string> >& mocDepends);
+  bool MocGenerateFile(
+    const std::string& sourceFile, const std::string& mocFileName,
+    const std::map<std::string, std::set<std::string> >& mocDepends,
+    bool included);
+
+  // -- Uic file generation
+  bool UicFindIncludedFile(std::string& absFile, const std::string& sourceFile,
+                           const std::string& includeString);
   bool UicGenerateAll(
     const std::map<std::string, std::vector<std::string> >& includedUis);
   bool UicGenerateFile(const std::string& realName,
                        const std::string& uiInputFile,
                        const std::string& uiOutputFile);
 
-  // - Qrc file generation
-  bool QrcGenerateAll();
-  bool QrcGenerateFile(const std::string& qrcInputFile,
+  // -- Rcc file generation
+  bool RccGenerateAll();
+  bool RccGenerateFile(const std::string& qrcInputFile,
                        const std::string& qrcOutputFile, bool unique_n);
 
-  // - Logging
+  // -- Logging
   void LogErrorNameCollision(
     const std::string& message,
-    const std::multimap<std::string, std::string>& collisions);
-  void LogBold(const std::string& message);
-  void LogInfo(const std::string& message);
-  void LogWarning(const std::string& message);
-  void LogError(const std::string& message);
-  void LogCommand(const std::vector<std::string>& command);
-
-  // - Utility
-  bool NameCollisionTest(const std::map<std::string, std::string>& genFiles,
-                         std::multimap<std::string, std::string>& collisions);
-  bool MakeParentDirectory(const std::string& filename);
-
-  // - Target names
-  std::string OriginTargetName;
-  std::string AutogenTargetName;
-  // - Directories
+    const std::multimap<std::string, std::string>& collisions) const;
+  void LogBold(const std::string& message) const;
+  void LogInfo(const std::string& message) const;
+  void LogWarning(const std::string& message) const;
+  void LogError(const std::string& message) const;
+  void LogCommand(const std::vector<std::string>& command) const;
+
+  // -- Utility
+  bool NameCollisionTest(
+    const std::map<std::string, std::string>& genFiles,
+    std::multimap<std::string, std::string>& collisions) const;
+  std::string ChecksumedPath(const std::string& sourceFile,
+                             const std::string& basePrefix,
+                             const std::string& baseSuffix) const;
+  bool MakeParentDirectory(const char* logPrefix,
+                           const std::string& filename) const;
+  bool FileDiffers(const std::string& filename, const std::string& content);
+  bool FileWrite(const char* logPrefix, const std::string& filename,
+                 const std::string& content);
+
+  bool RunCommand(const std::vector<std::string>& command, std::string& output,
+                  bool verbose = true) const;
+
+  bool FindHeader(std::string& header, const std::string& testBasePath) const;
+
+  std::string MocFindHeader(const std::string& sourcePath,
+                            const std::string& includeBase) const;
+  bool MocFindIncludedFile(std::string& absFile, const std::string& sourceFile,
+                           const std::string& includeString) const;
+
+  // -- Meta
+  std::string ConfigSuffix;
+  // -- Directories
   std::string ProjectSourceDir;
   std::string ProjectBinaryDir;
   std::string CurrentSourceDir;
   std::string CurrentBinaryDir;
-  std::string AutogenBuildSubDir;
-  // - Qt environment
+  std::string AutogenBuildDir;
+  std::string AutogenIncludeDir;
+  // -- Qt environment
   std::string QtMajorVersion;
   std::string MocExecutable;
   std::string UicExecutable;
   std::string RccExecutable;
-  // - File lists
+  // -- File lists
   std::vector<std::string> Sources;
   std::vector<std::string> Headers;
-  // - Moc
-  std::vector<std::string> SkipMoc;
-  std::string MocCompileDefinitionsStr;
-  std::string MocIncludesStr;
-  std::string MocOptionsStr;
-  std::string OutMocCppFilenameRel;
-  std::string OutMocCppFilenameAbs;
-  std::list<std::string> MocIncludes;
-  std::list<std::string> MocDefinitions;
+  std::vector<std::string> HeaderExtensions;
+  cmFilePathChecksum FPathChecksum;
+  // -- Settings
+  bool IncludeProjectDirsBefore;
+  bool Verbose;
+  bool ColorOutput;
+  std::string SettingsFile;
+  std::string SettingsStringMoc;
+  std::string SettingsStringUic;
+  std::string SettingsStringRcc;
+  // -- Moc
+  bool MocSettingsChanged;
+  bool MocPredefsChanged;
+  bool MocRelaxedMode;
+  bool MocRunFailed;
+  std::string MocCompFileRel;
+  std::string MocCompFileAbs;
+  std::string MocPredefsFileRel;
+  std::string MocPredefsFileAbs;
+  std::vector<std::string> MocSkipList;
+  std::vector<std::string> MocIncludePaths;
+  std::vector<std::string> MocIncludes;
+  std::vector<std::string> MocDefinitions;
   std::vector<std::string> MocOptions;
-  std::string MocSettingsString;
-  // - Uic
-  std::vector<std::string> SkipUic;
+  std::vector<std::string> MocPredefsCmd;
+  std::vector<MocDependFilter> MocDependFilters;
+  MocMacroFilter MocMacroFilters[2];
+  cmsys::RegularExpression MocRegExpInclude;
+  // -- Uic
+  bool UicSettingsChanged;
+  bool UicRunFailed;
+  std::vector<std::string> UicSkipList;
   std::vector<std::string> UicTargetOptions;
   std::map<std::string, std::string> UicOptions;
-  std::string UicSettingsString;
-  // - Rcc
+  std::vector<std::string> UicSearchPaths;
+  cmsys::RegularExpression UicRegExpInclude;
+  // -- Rcc
+  bool RccSettingsChanged;
+  bool RccRunFailed;
   std::vector<std::string> RccSources;
   std::map<std::string, std::string> RccOptions;
   std::map<std::string, std::vector<std::string> > RccInputs;
-  std::string RccSettingsString;
-  // - Utility
-  cmFilePathChecksum fpathCheckSum;
-  cmsys::RegularExpression RegExpQObject;
-  cmsys::RegularExpression RegExpQGadget;
-  cmsys::RegularExpression RegExpMocInclude;
-  cmsys::RegularExpression RegExpUicInclude;
-  // - Flags
-  bool IncludeProjectDirsBefore;
-  bool Verbose;
-  bool ColorOutput;
-  bool RunMocFailed;
-  bool RunUicFailed;
-  bool RunRccFailed;
-  bool GenerateMocAll;
-  bool GenerateUicAll;
-  bool GenerateRccAll;
-  bool MocRelaxedMode;
 };
 
 #endif
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index 355b8c4..5364f76 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -6,8 +6,8 @@
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 
+#include "cmsys/FStream.hxx"
 #include <algorithm>
-#include <cmsys/FStream.hxx>
 #include <ctype.h>
 #include <iterator>
 #include <stddef.h>
@@ -80,7 +80,7 @@ void cmRST::ProcessModule(std::istream& is)
     if (!rst.empty() && rst != "#") {
       // Bracket mode: check for end bracket
       std::string::size_type pos = line.find(rst);
-      if (pos == line.npos) {
+      if (pos == std::string::npos) {
         this->ProcessLine(line);
       } else {
         if (line[0] != '#') {
@@ -96,14 +96,14 @@ void cmRST::ProcessModule(std::istream& is)
         if (line == "#") {
           this->ProcessLine("");
           continue;
-        } else if (line.substr(0, 2) == "# ") {
-          this->ProcessLine(line.substr(2, line.npos));
+        }
+        if (line.substr(0, 2) == "# ") {
+          this->ProcessLine(line.substr(2));
           continue;
-        } else {
-          rst = "";
-          this->Reset();
-          this->OutputLinePending = true;
         }
+        rst = "";
+        this->Reset();
+        this->OutputLinePending = true;
       }
       if (line == "#.rst:") {
         rst = "#";
@@ -156,8 +156,8 @@ void cmRST::ProcessLine(std::string const& line)
                        isspace(line[2]))) {
     this->Reset();
     this->Markup =
-      (line.find_first_not_of(" \t", 2) == line.npos ? MarkupEmpty
-                                                     : MarkupNormal);
+      (line.find_first_not_of(" \t", 2) == std::string::npos ? MarkupEmpty
+                                                             : MarkupNormal);
     if (this->CMakeDirective.find(line)) {
       // Output cmake domain directives and their content normally.
       this->NormalLine(line);
@@ -252,7 +252,7 @@ void cmRST::OutputLine(std::string const& line_in, bool inlineMarkup)
       // no explicit "(...)" then add "()" to the text.
       if (this->CMakeRole.match(2) == "command" &&
           this->CMakeRole.match(5).empty() &&
-          text.find_first_of("()") == text.npos) {
+          text.find_first_of("()") == std::string::npos) {
         text += "()";
       }
       this->OS << "``" << text << "``";
diff --git a/Source/cmRST.h b/Source/cmRST.h
index 2fedf4b..d1a8e27 100644
--- a/Source/cmRST.h
+++ b/Source/cmRST.h
@@ -3,9 +3,9 @@
 #ifndef _cmRST_h
 #define _cmRST_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <iosfwd>
 #include <map>
 #include <set>
diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx
index 5a52927..1db8441 100644
--- a/Source/cmRemoveCommand.cxx
+++ b/Source/cmRemoveCommand.cxx
@@ -15,7 +15,7 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args,
     return true;
   }
 
-  const char* variable = args[0].c_str(); // VAR is always first
+  std::string const& variable = args[0]; // VAR is always first
   // get the old value
   const char* cacheValue = this->Makefile->GetDefinition(variable);
 
diff --git a/Source/cmRemoveCommand.h b/Source/cmRemoveCommand.h
index c935f28..f2e89f6 100644
--- a/Source/cmRemoveCommand.h
+++ b/Source/cmRemoveCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmRemoveCommand_h
 #define cmRemoveCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "remove"; }
 };
 
 #endif
diff --git a/Source/cmRemoveDefinitionsCommand.h b/Source/cmRemoveDefinitionsCommand.h
index 2bcc12d..9a9a5d5 100644
--- a/Source/cmRemoveDefinitionsCommand.h
+++ b/Source/cmRemoveDefinitionsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmRemoveDefinitionsCommand_h
 #define cmRemoveDefinitionsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "remove_definitions"; }
 };
 
 #endif
diff --git a/Source/cmReturnCommand.cxx b/Source/cmReturnCommand.cxx
index f8b3129..ceea8b4 100644
--- a/Source/cmReturnCommand.cxx
+++ b/Source/cmReturnCommand.cxx
@@ -8,6 +8,6 @@
 bool cmReturnCommand::InitialPass(std::vector<std::string> const&,
                                   cmExecutionStatus& status)
 {
-  status.SetReturnInvoked(true);
+  status.SetReturnInvoked();
   return true;
 }
diff --git a/Source/cmReturnCommand.h b/Source/cmReturnCommand.h
index 9496d67..87900e7 100644
--- a/Source/cmReturnCommand.h
+++ b/Source/cmReturnCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmReturnCommand_h
 #define cmReturnCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "return"; }
 };
 
 #endif
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index f190a5c..a71861a 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -12,10 +12,11 @@
 cmRulePlaceholderExpander::cmRulePlaceholderExpander(
   std::map<std::string, std::string> const& compilers,
   std::map<std::string, std::string> const& variableMappings,
-  std::string const& compilerSysroot)
+  std::string const& compilerSysroot, std::string const& linkerSysroot)
   : Compilers(compilers)
   , VariableMappings(variableMappings)
   , CompilerSysroot(compilerSysroot)
+  , LinkerSysroot(linkerSysroot)
 {
 }
 
@@ -154,7 +155,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
         // Strip the last extension off the target name.
         std::string targetBase = replaceValues.Target;
         std::string::size_type pos = targetBase.rfind('.');
-        if (pos != targetBase.npos) {
+        if (pos != std::string::npos) {
           return targetBase.substr(0, pos);
         }
         return targetBase;
@@ -249,10 +250,19 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
       ret += compilerOptionExternalToolchain;
       ret += outputConverter->EscapeForShell(compilerExternalToolchain, true);
     }
-    if (!this->CompilerSysroot.empty() && !compilerOptionSysroot.empty()) {
+    std::string sysroot;
+    // Some platforms may use separate sysroots for compiling and linking.
+    // If we detect link flags, then we pass the link sysroot instead.
+    // FIXME: Use a more robust way to detect link line expansion.
+    if (replaceValues.LinkFlags) {
+      sysroot = this->LinkerSysroot;
+    } else {
+      sysroot = this->CompilerSysroot;
+    }
+    if (!sysroot.empty() && !compilerOptionSysroot.empty()) {
       ret += " ";
       ret += compilerOptionSysroot;
-      ret += outputConverter->EscapeForShell(this->CompilerSysroot, true);
+      ret += outputConverter->EscapeForShell(sysroot, true);
     }
     return ret;
   }
@@ -260,7 +270,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
   std::map<std::string, std::string>::iterator mapIt =
     this->VariableMappings.find(variable);
   if (mapIt != this->VariableMappings.end()) {
-    if (variable.find("_FLAG") == variable.npos) {
+    if (variable.find("_FLAG") == std::string::npos) {
       return outputConverter->ConvertToOutputForExisting(mapIt->second);
     }
     return mapIt->second;
@@ -274,15 +284,15 @@ void cmRulePlaceholderExpander::ExpandRuleVariables(
 {
   std::string::size_type start = s.find('<');
   // no variables to expand
-  if (start == s.npos) {
+  if (start == std::string::npos) {
     return;
   }
   std::string::size_type pos = 0;
   std::string expandedInput;
-  while (start != s.npos && start < s.size() - 2) {
+  while (start != std::string::npos && start < s.size() - 2) {
     std::string::size_type end = s.find('>', start);
     // if we find a < with no > we are done
-    if (end == s.npos) {
+    if (end == std::string::npos) {
       return;
     }
     char c = s[start + 1];
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index 8329166..7b19210 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -4,7 +4,7 @@
 #ifndef cmRulePlaceholderExpander_h
 #define cmRulePlaceholderExpander_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <string>
@@ -17,7 +17,7 @@ public:
   cmRulePlaceholderExpander(
     std::map<std::string, std::string> const& compilers,
     std::map<std::string, std::string> const& variableMappings,
-    std::string const& compilerSysroot);
+    std::string const& compilerSysroot, std::string const& linkerSysroot);
 
   void SetTargetImpLib(std::string const& targetImpLib)
   {
@@ -76,6 +76,7 @@ private:
   std::map<std::string, std::string> Compilers;
   std::map<std::string, std::string> VariableMappings;
   std::string CompilerSysroot;
+  std::string LinkerSysroot;
 };
 
 #endif
diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx
index 4c5ab64..753a1ba 100644
--- a/Source/cmScriptGenerator.cxx
+++ b/Source/cmScriptGenerator.cxx
@@ -4,8 +4,6 @@
 
 #include "cmSystemTools.h"
 
-#include <cmConfigure.h>
-
 cmScriptGenerator::cmScriptGenerator(
   const std::string& config_var,
   std::vector<std::string> const& configurations)
@@ -90,8 +88,7 @@ void cmScriptGenerator::GenerateScript(std::ostream& os)
   this->GenerateScriptConfigs(os, indent);
 }
 
-void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os,
-                                              Indent const& indent)
+void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent)
 {
   if (this->ActionsPerConfig) {
     this->GenerateScriptActionsPerConfig(os, indent);
@@ -100,8 +97,7 @@ void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os,
   }
 }
 
-void cmScriptGenerator::GenerateScriptActions(std::ostream& os,
-                                              Indent const& indent)
+void cmScriptGenerator::GenerateScriptActions(std::ostream& os, Indent indent)
 {
   if (this->ActionsPerConfig) {
     // This is reached for single-configuration build generators in a
@@ -112,7 +108,7 @@ void cmScriptGenerator::GenerateScriptActions(std::ostream& os,
 
 void cmScriptGenerator::GenerateScriptForConfig(std::ostream& /*unused*/,
                                                 const std::string& /*unused*/,
-                                                Indent const& /*unused*/)
+                                                Indent /*unused*/)
 {
   // No actions for this generator.
 }
@@ -138,7 +134,7 @@ bool cmScriptGenerator::GeneratesForConfig(const std::string& config)
 }
 
 void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os,
-                                                  Indent const& indent)
+                                                  Indent indent)
 {
   if (this->Configurations.empty()) {
     // This rule is for all configurations.
@@ -153,7 +149,7 @@ void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os,
 }
 
 void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os,
-                                                       Indent const& indent)
+                                                       Indent indent)
 {
   if (this->ConfigurationTypes->empty()) {
     // In a single-configuration generator there is only one action
diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h
index a8f6fae..d0879c6 100644
--- a/Source/cmScriptGenerator.h
+++ b/Source/cmScriptGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmScriptGenerator_h
 #define cmScriptGenerator_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include <ostream>
 #include <string>
@@ -35,7 +35,7 @@ private:
   int Level;
 };
 inline std::ostream& operator<<(std::ostream& os,
-                                cmScriptGeneratorIndent const& indent)
+                                cmScriptGeneratorIndent indent)
 {
   indent.Write(os);
   return os;
@@ -47,6 +47,8 @@ inline std::ostream& operator<<(std::ostream& os,
  */
 class cmScriptGenerator
 {
+  CM_DISABLE_COPY(cmScriptGenerator)
+
 public:
   cmScriptGenerator(const std::string& config_var,
                     std::vector<std::string> const& configurations);
@@ -58,12 +60,12 @@ public:
 protected:
   typedef cmScriptGeneratorIndent Indent;
   virtual void GenerateScript(std::ostream& os);
-  virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
-  virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
+  virtual void GenerateScriptConfigs(std::ostream& os, Indent indent);
+  virtual void GenerateScriptActions(std::ostream& os, Indent indent);
   virtual void GenerateScriptForConfig(std::ostream& os,
                                        const std::string& config,
-                                       Indent const& indent);
-  virtual void GenerateScriptNoConfig(std::ostream&, Indent const&) {}
+                                       Indent indent);
+  virtual void GenerateScriptNoConfig(std::ostream&, Indent) {}
   virtual bool NeedsScriptNoConfig() const { return false; }
 
   // Test if this generator does something for a given configuration.
@@ -87,8 +89,8 @@ protected:
   bool ActionsPerConfig;
 
 private:
-  void GenerateScriptActionsOnce(std::ostream& os, Indent const& indent);
-  void GenerateScriptActionsPerConfig(std::ostream& os, Indent const& indent);
+  void GenerateScriptActionsOnce(std::ostream& os, Indent indent);
+  void GenerateScriptActionsPerConfig(std::ostream& os, Indent indent);
 };
 
 #endif
diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h
index 9ffa871..932022a 100644
--- a/Source/cmSearchPath.h
+++ b/Source/cmSearchPath.h
@@ -3,7 +3,7 @@
 #ifndef cmSearchPath_h
 #define cmSearchPath_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <set>
 #include <string>
diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx
index b27d227..7b222a0 100644
--- a/Source/cmSeparateArgumentsCommand.cxx
+++ b/Source/cmSeparateArgumentsCommand.cxx
@@ -40,6 +40,13 @@ bool cmSeparateArgumentsCommand::InitialPass(
     if (doing == DoingVariable) {
       var = args[i];
       doing = DoingMode;
+    } else if (doing == DoingMode && args[i] == "NATIVE_COMMAND") {
+#ifdef _WIN32
+      mode = ModeWindows;
+#else
+      mode = ModeUnix;
+#endif
+      doing = DoingCommand;
     } else if (doing == DoingMode && args[i] == "UNIX_COMMAND") {
       mode = ModeUnix;
       doing = DoingCommand;
diff --git a/Source/cmSeparateArgumentsCommand.h b/Source/cmSeparateArgumentsCommand.h
index 1cbf56e..6bf8549 100644
--- a/Source/cmSeparateArgumentsCommand.h
+++ b/Source/cmSeparateArgumentsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSeparateArgumentsCommand_h
 #define cmSeparateArgumentsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "separate_arguments"; }
 };
 
 #endif
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index 5a71dc0..7fc6ed7 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -6,18 +6,15 @@
 #include "cmServerDictionary.h"
 #include "cmServerProtocol.h"
 #include "cmSystemTools.h"
-#include "cmVersionMacros.h"
-#include "cmake.h"
-
-#if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cm_jsoncpp_reader.h"
-#include "cm_jsoncpp_value.h"
-#endif
+#include "cm_jsoncpp_writer.h"
+#include "cmake.h"
+#include "cmsys/FStream.hxx"
 
 #include <algorithm>
-#include <fstream>
-#include <iostream>
-#include <memory>
+#include <cassert>
+#include <cstdint>
+#include <utility>
 
 class cmServer::DebugInfo
 {
@@ -150,7 +147,7 @@ void cmServer::reportProgress(const char* msg, float progress, void* data)
 {
   const cmServerRequest* request = static_cast<const cmServerRequest*>(data);
   assert(request);
-  if (progress < 0.0 || progress > 1.0) {
+  if (progress < 0.0f || progress > 1.0f) {
     request->ReportMessage(msg, "");
   } else {
     request->ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg);
@@ -270,10 +267,8 @@ void cmServer::WriteJsonObject(const Json::Value& jsonValue,
     }
 
     if (!debug->OutputFile.empty()) {
-      std::ofstream myfile;
-      myfile.open(debug->OutputFile);
+      cmsys::ofstream myfile(debug->OutputFile.c_str());
       myfile << result;
-      myfile.close();
     }
   }
 
diff --git a/Source/cmServer.h b/Source/cmServer.h
index 7f29e32..b814050 100644
--- a/Source/cmServer.h
+++ b/Source/cmServer.h
@@ -2,13 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #pragma once
 
-#include "cmListFileCache.h"
-#include "cmState.h"
+#include "cmConfigure.h"
 
-#if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cm_jsoncpp_value.h"
 #include "cm_uv.h"
-#endif
 
 #include <string>
 #include <vector>
@@ -21,6 +18,8 @@ class cmServerResponse;
 
 class cmServer
 {
+  CM_DISABLE_COPY(cmServer)
+
 public:
   class DebugInfo;
 
diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx
index 008052b..36312ed 100644
--- a/Source/cmServerConnection.cxx
+++ b/Source/cmServerConnection.cxx
@@ -2,10 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmServerConnection.h"
 
-#include "cmServerDictionary.h"
-
 #include "cmFileMonitor.h"
 #include "cmServer.h"
+#include "cmServerDictionary.h"
 
 #include <assert.h>
 #include <string.h>
diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h
index 3efe28d..b96bf3c 100644
--- a/Source/cmServerConnection.h
+++ b/Source/cmServerConnection.h
@@ -2,19 +2,19 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #pragma once
 
-#include <string>
-#include <vector>
+#include "cmConfigure.h"
 
-#if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cm_uv.h"
-#endif
 
-class cmServer;
+#include <string>
+
 class cmFileMonitor;
-class LoopGuard;
+class cmServer;
 
 class cmServerConnection
 {
+  CM_DISABLE_COPY(cmServerConnection)
+
 public:
   cmServerConnection();
   virtual ~cmServerConnection();
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index a5c1a23..defba77 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -4,27 +4,32 @@
 
 #include "cmExternalMakefileProjectGenerator.h"
 #include "cmFileMonitor.h"
+#include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
 #include "cmLinkLineComputer.h"
-#include "cmListFileCache.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmServer.h"
 #include "cmServerDictionary.h"
 #include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
 #include "cmSystemTools.h"
+#include "cm_uv.h"
 #include "cmake.h"
 
-#include "cmServerDictionary.h"
-
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cm_jsoncpp_reader.h"
-#include "cm_jsoncpp_value.h"
-#endif
-
 #include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <functional>
+#include <limits>
+#include <map>
+#include <set>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
 // Get rid of some windows macros:
@@ -50,9 +55,8 @@ std::vector<std::string> getConfigurations(const cmake* cm)
 bool hasString(const Json::Value& v, const std::string& s)
 {
   return !v.isNull() &&
-    std::find_if(v.begin(), v.end(), [s](const Json::Value& i) {
-      return i.asString() == s;
-    }) != v.end();
+    std::any_of(v.begin(), v.end(),
+                [s](const Json::Value& i) { return i.asString() == s; });
 }
 
 template <class T>
@@ -211,7 +215,7 @@ bool cmServerProtocol::Activate(cmServer* server,
 {
   assert(server);
   this->m_Server = server;
-  this->m_CMakeInstance = std::make_unique<cmake>();
+  this->m_CMakeInstance = std::make_unique<cmake>(cmake::RoleProject);
   const bool result = this->DoActivate(request, errorMessage);
   if (!result) {
     this->m_CMakeInstance = CM_NULLPTR;
@@ -493,16 +497,14 @@ cmServerResponse cmServerProtocol1_0::ProcessCache(
   if (keys.empty()) {
     keys = allKeys;
   } else {
-    for (auto i : keys) {
-      if (std::find_if(allKeys.begin(), allKeys.end(),
-                       [i](const std::string& j) { return i == j; }) ==
-          allKeys.end()) {
+    for (const auto& i : keys) {
+      if (std::find(allKeys.begin(), allKeys.end(), i) == allKeys.end()) {
         return request.ReportError("Key \"" + i + "\" not found in cache.");
       }
     }
   }
   std::sort(keys.begin(), keys.end());
-  for (auto key : keys) {
+  for (const auto& key : keys) {
     Json::Value entry = Json::objectValue;
     entry[kKEY_KEY] = key;
     entry[kTYPE_KEY] =
@@ -511,7 +513,7 @@ cmServerResponse cmServerProtocol1_0::ProcessCache(
 
     Json::Value props = Json::objectValue;
     bool haveProperties = false;
-    for (auto prop : state->GetCacheEntryPropertyList(key)) {
+    for (const auto& prop : state->GetCacheEntryPropertyList(key)) {
       haveProperties = true;
       props[prop] = state->GetCacheEntryProperty(key, prop);
     }
@@ -598,7 +600,7 @@ bool LanguageData::operator==(const LanguageData& other) const
 void LanguageData::SetDefines(const std::set<std::string>& defines)
 {
   std::vector<std::string> result;
-  for (auto i : defines) {
+  for (const auto& i : defines) {
     result.push_back(i);
   }
   std::sort(result.begin(), result.end());
@@ -615,11 +617,11 @@ struct hash<LanguageData>
     using std::hash;
     size_t result =
       hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags);
-    for (auto i : in.IncludePathList) {
+    for (const auto& i : in.IncludePathList) {
       result = result ^ (hash<std::string>()(i.first) ^
                          (i.second ? std::numeric_limits<size_t>::max() : 0));
     }
-    for (auto i : in.Defines) {
+    for (const auto& i : in.Defines) {
       result = result ^ hash<std::string>()(i);
     }
     result =
@@ -643,7 +645,7 @@ static Json::Value DumpSourceFileGroup(const LanguageData& data,
     }
     if (!data.IncludePathList.empty()) {
       Json::Value includes = Json::arrayValue;
-      for (auto i : data.IncludePathList) {
+      for (const auto& i : data.IncludePathList) {
         Json::Value tmp = Json::objectValue;
         tmp[kPATH_KEY] = i.first;
         if (i.second) {
@@ -661,7 +663,7 @@ static Json::Value DumpSourceFileGroup(const LanguageData& data,
   result[kIS_GENERATED_KEY] = data.IsGenerated;
 
   Json::Value sourcesValue = Json::arrayValue;
-  for (auto i : files) {
+  for (const auto& i : files) {
     const std::string relPath =
       cmSystemTools::RelativePath(baseDir.c_str(), i.c_str());
     sourcesValue.append(relPath.size() < i.size() ? relPath : i);
@@ -763,9 +765,11 @@ static Json::Value DumpTarget(cmGeneratorTarget* target,
 
   if (target->HaveWellDefinedOutputFiles()) {
     Json::Value artifacts = Json::arrayValue;
-    artifacts.append(target->GetFullPath(config, false));
+    artifacts.append(
+      target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact));
     if (target->IsDLLPlatform()) {
-      artifacts.append(target->GetFullPath(config, true));
+      artifacts.append(
+        target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
       const cmGeneratorTarget::OutputInfo* output =
         target->GetOutputInfo(config);
       if (output && !output->PdbDir.empty()) {
@@ -817,7 +821,7 @@ static Json::Value DumpTarget(cmGeneratorTarget* target,
   std::set<std::string> languages;
   target->GetLanguages(languages, config);
   std::map<std::string, LanguageData> languageDataMap;
-  for (auto lang : languages) {
+  for (const auto& lang : languages) {
     LanguageData& ld = languageDataMap[lang];
     ld.Language = lang;
     lg->GetTargetCompileFlags(target, config, lang, ld.Flags);
@@ -1093,7 +1097,7 @@ cmServerResponse cmServerProtocol1_0::ProcessSetGlobalSettings(
     kWARN_UNINITIALIZED_KEY, kWARN_UNUSED_KEY, kWARN_UNUSED_CLI_KEY,
     kCHECK_SYSTEM_VARS_KEY
   };
-  for (auto i : boolValues) {
+  for (const auto& i : boolValues) {
     if (!request.Data[i].isNull() && !request.Data[i].isBool()) {
       return request.ReportError("\"" + i +
                                  "\" must be unset or a bool value.");
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
index 027f145..83b3d58 100644
--- a/Source/cmServerProtocol.h
+++ b/Source/cmServerProtocol.h
@@ -2,20 +2,17 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #pragma once
 
-#include "cmListFileCache.h"
-#include "cmake.h"
+#include "cmConfigure.h"
 
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cm_jsoncpp_writer.h"
-#endif
+#include "cm_jsoncpp_value.h"
+#include "cmake.h"
 
 #include <memory>
 #include <string>
+#include <utility>
 
-class cmake;
 class cmFileMonitor;
 class cmServer;
-
 class cmServerRequest;
 
 class cmServerResponse
@@ -72,8 +69,11 @@ private:
 
 class cmServerProtocol
 {
+  CM_DISABLE_COPY(cmServerProtocol)
+
 public:
-  virtual ~cmServerProtocol() {}
+  cmServerProtocol() = default;
+  virtual ~cmServerProtocol() = default;
 
   virtual std::pair<int, int> ProtocolVersion() const = 0;
   virtual bool IsExperimental() const = 0;
diff --git a/Source/cmSetCommand.h b/Source/cmSetCommand.h
index 190092a..c0858b1 100644
--- a/Source/cmSetCommand.h
+++ b/Source/cmSetCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSetCommand_h
 #define cmSetCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "set"; }
 };
 
 #endif
diff --git a/Source/cmSetDirectoryPropertiesCommand.h b/Source/cmSetDirectoryPropertiesCommand.h
index 854ad43..8832b33 100644
--- a/Source/cmSetDirectoryPropertiesCommand.h
+++ b/Source/cmSetDirectoryPropertiesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSetDirectoryPropertiesCommand_h
 #define cmSetDirectoryPropertiesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -28,19 +29,6 @@ public:
                    cmExecutionStatus& status) CM_OVERRIDE;
 
   /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "set_directory_properties";
-  }
-
-  /**
    * Static entry point for use by other commands
    */
   static bool RunCommand(cmMakefile* mf,
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index 60c198a..b57f62a 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -138,7 +138,7 @@ bool cmSetPropertyCommand::HandleGlobalMode()
 
   // Set or append the property.
   cmake* cm = this->Makefile->GetCMakeInstance();
-  const char* name = this->PropertyName.c_str();
+  std::string const& name = this->PropertyName;
   const char* value = this->PropertyValue.c_str();
   if (this->Remove) {
     value = CM_NULLPTR;
@@ -188,7 +188,7 @@ bool cmSetPropertyCommand::HandleDirectoryMode()
   }
 
   // Set or append the property.
-  const char* name = this->PropertyName.c_str();
+  std::string const& name = this->PropertyName;
   const char* value = this->PropertyValue.c_str();
   if (this->Remove) {
     value = CM_NULLPTR;
@@ -229,7 +229,7 @@ bool cmSetPropertyCommand::HandleTargetMode()
 bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
 {
   // Set or append the property.
-  const char* name = this->PropertyName.c_str();
+  std::string const& name = this->PropertyName;
   const char* value = this->PropertyValue.c_str();
   if (this->Remove) {
     value = CM_NULLPTR;
@@ -268,7 +268,7 @@ bool cmSetPropertyCommand::HandleSourceMode()
 bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
 {
   // Set or append the property.
-  const char* name = this->PropertyName.c_str();
+  std::string const& name = this->PropertyName;
   const char* value = this->PropertyValue.c_str();
   if (this->Remove) {
     value = CM_NULLPTR;
@@ -316,7 +316,7 @@ bool cmSetPropertyCommand::HandleTestMode()
 bool cmSetPropertyCommand::HandleTest(cmTest* test)
 {
   // Set or append the property.
-  const char* name = this->PropertyName.c_str();
+  std::string const& name = this->PropertyName;
   const char* value = this->PropertyValue.c_str();
   if (this->Remove) {
     value = CM_NULLPTR;
@@ -383,7 +383,7 @@ bool cmSetPropertyCommand::HandleCacheMode()
 bool cmSetPropertyCommand::HandleCacheEntry(std::string const& cacheKey)
 {
   // Set or append the property.
-  const char* name = this->PropertyName.c_str();
+  std::string const& name = this->PropertyName;
   const char* value = this->PropertyValue.c_str();
   cmState* state = this->Makefile->GetState();
   if (this->Remove) {
diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h
index fd7c922..0815824 100644
--- a/Source/cmSetPropertyCommand.h
+++ b/Source/cmSetPropertyCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSetsPropertiesCommand_h
 #define cmSetsPropertiesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <set>
 #include <string>
 #include <vector>
@@ -30,16 +31,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "set_property"; }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
 private:
   std::set<std::string> Names;
   std::string PropertyName;
diff --git a/Source/cmSetSourceFilesPropertiesCommand.h b/Source/cmSetSourceFilesPropertiesCommand.h
index 8fa12c7..2e22dc9 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.h
+++ b/Source/cmSetSourceFilesPropertiesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSetSourceFilesPropertiesCommand_h
 #define cmSetSourceFilesPropertiesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -27,14 +28,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "set_source_files_properties";
-  }
-
   static bool RunCommand(cmMakefile* mf,
                          std::vector<std::string>::const_iterator filebeg,
                          std::vector<std::string>::const_iterator fileend,
diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx
index da26972..6425913 100644
--- a/Source/cmSetTargetPropertiesCommand.cxx
+++ b/Source/cmSetTargetPropertiesCommand.cxx
@@ -32,9 +32,8 @@ bool cmSetTargetPropertiesCommand::InitialPass(
       }
       propertyPairs.insert(propertyPairs.end(), j, args.end());
       break;
-    } else {
-      numFiles++;
     }
+    numFiles++;
   }
   if (propertyPairs.empty()) {
     this->SetError("called with illegal arguments, maybe missing "
diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h
index c3c0d06..4256181 100644
--- a/Source/cmSetTargetPropertiesCommand.h
+++ b/Source/cmSetTargetPropertiesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSetTargetsPropertiesCommand_h
 #define cmSetTargetsPropertiesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -25,11 +26,6 @@ public:
                    cmExecutionStatus& status) CM_OVERRIDE;
 
   /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "set_target_properties"; }
-
-  /**
    *  Used by this command and cmSetPropertiesCommand
    */
   static bool SetOneTarget(const std::string& tname,
diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx
index 4fd379f..e27c675 100644
--- a/Source/cmSetTestsPropertiesCommand.cxx
+++ b/Source/cmSetTestsPropertiesCommand.cxx
@@ -32,9 +32,8 @@ bool cmSetTestsPropertiesCommand::InitialPass(
       }
       propertyPairs.insert(propertyPairs.end(), j, args.end());
       break;
-    } else {
-      numFiles++;
     }
+    numFiles++;
   }
   if (propertyPairs.empty()) {
     this->SetError("called with illegal arguments, maybe "
diff --git a/Source/cmSetTestsPropertiesCommand.h b/Source/cmSetTestsPropertiesCommand.h
index 45aed79..90f004c 100644
--- a/Source/cmSetTestsPropertiesCommand.h
+++ b/Source/cmSetTestsPropertiesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSetTestsPropertiesCommand_h
 #define cmSetTestsPropertiesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -24,11 +25,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "set_tests_properties"; }
-
   static bool SetOneTest(const std::string& tname,
                          std::vector<std::string>& propertyPairs,
                          cmMakefile* mf, std::string& errors);
diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx
index 4322a6d..7eace26 100644
--- a/Source/cmSiteNameCommand.cxx
+++ b/Source/cmSiteNameCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmSiteNameCommand.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
diff --git a/Source/cmSiteNameCommand.h b/Source/cmSiteNameCommand.h
index 01023b9..6c65480 100644
--- a/Source/cmSiteNameCommand.h
+++ b/Source/cmSiteNameCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSiteNameCommand_h
 #define cmSiteNameCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "site_name"; }
 };
 
 #endif
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index bbcc300..0be659c 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -3,7 +3,7 @@
 #ifndef cmSourceFile_h
 #define cmSourceFile_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmPropertyMap.h"
 #include "cmSourceFileLocation.h"
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index 4e0880e..86711d7 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmSourceFileLocation.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "cmAlgorithms.h"
 #include "cmGlobalGenerator.h"
diff --git a/Source/cmSourceFileLocation.h b/Source/cmSourceFileLocation.h
index aa2e6c7..6dbc2da 100644
--- a/Source/cmSourceFileLocation.h
+++ b/Source/cmSourceFileLocation.h
@@ -3,7 +3,7 @@
 #ifndef cmSourceFileLocation_h
 #define cmSourceFileLocation_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
index 545da81..97affed 100644
--- a/Source/cmSourceGroup.h
+++ b/Source/cmSourceGroup.h
@@ -3,9 +3,9 @@
 #ifndef cmSourceGroup_h
 #define cmSourceGroup_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <set>
 #include <string>
 #include <vector>
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index 5555199..a966300 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -2,7 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmSourceGroupCommand.h"
 
+#include <set>
 #include <sstream>
+#include <stddef.h>
 
 #include "cmMakefile.h"
 #include "cmSourceGroup.h"
@@ -12,7 +14,7 @@ namespace {
 const size_t RootIndex = 1;
 const size_t FilesWithoutPrefixKeywordIndex = 2;
 const size_t FilesWithPrefixKeywordIndex = 4;
-const size_t PrefixKeywordIdex = 2;
+const size_t PrefixKeywordIndex = 2;
 
 std::vector<std::string> tokenizePath(const std::string& path)
 {
@@ -34,21 +36,31 @@ std::string getFullFilePath(const std::string& currentPath,
 }
 
 std::set<std::string> getSourceGroupFilesPaths(
-  const std::string& currentPath, const std::string& root,
-  const std::vector<std::string>& files)
+  const std::string& root, const std::vector<std::string>& files)
 {
   std::set<std::string> ret;
   const std::string::size_type rootLength = root.length();
 
   for (size_t i = 0; i < files.size(); ++i) {
-    const std::string fullPath = getFullFilePath(currentPath, files[i]);
-
-    ret.insert(fullPath.substr(rootLength + 1)); // +1 to also omnit last '/'
+    ret.insert(files[i].substr(rootLength + 1)); // +1 to also omnit last '/'
   }
 
   return ret;
 }
 
+bool rootIsPrefix(const std::string& root,
+                  const std::vector<std::string>& files, std::string& error)
+{
+  for (size_t i = 0; i < files.size(); ++i) {
+    if (!cmSystemTools::StringStartsWith(files[i], root.c_str())) {
+      error = "ROOT: " + root + " is not a prefix of file: " + files[i];
+      return false;
+    }
+  }
+
+  return true;
+}
+
 cmSourceGroup* addSourceGroup(const std::vector<std::string>& tokenizedPath,
                               cmMakefile& makefile)
 {
@@ -66,7 +78,31 @@ cmSourceGroup* addSourceGroup(const std::vector<std::string>& tokenizedPath,
   return sg;
 }
 
-bool addFilesToItsSourceGroups(const std::set<std::string>& sgFilesPaths,
+std::string prepareFilePathForTree(const std::string& path,
+                                   const std::string& currentSourceDir)
+{
+  if (!cmSystemTools::FileIsFullPath(path)) {
+    return cmSystemTools::CollapseFullPath(currentSourceDir + "/" + path);
+  }
+  return cmSystemTools::CollapseFullPath(path);
+}
+
+std::vector<std::string> prepareFilesPathsForTree(
+  std::vector<std::string>::const_iterator begin,
+  std::vector<std::string>::const_iterator end,
+  const std::string& currentSourceDir)
+{
+  std::vector<std::string> prepared;
+
+  for (; begin != end; ++begin) {
+    prepared.push_back(prepareFilePathForTree(*begin, currentSourceDir));
+  }
+
+  return prepared;
+}
+
+bool addFilesToItsSourceGroups(const std::string& root,
+                               const std::set<std::string>& sgFilesPaths,
                                const std::string& prefix, cmMakefile& makefile,
                                std::string& errorMsg)
 {
@@ -91,8 +127,7 @@ bool addFilesToItsSourceGroups(const std::set<std::string>& sgFilesPaths,
         errorMsg = "Could not create source group for file: " + *it;
         return false;
       }
-      const std::string fullPath =
-        getFullFilePath(makefile.GetCurrentSourceDirectory(), *it);
+      const std::string fullPath = getFullFilePath(root, *it);
       sg->AddGroupFile(fullPath);
     }
   }
@@ -201,13 +236,13 @@ bool cmSourceGroupCommand::checkTreeArgumentsPreconditions(
   }
 
   if (args[FilesWithoutPrefixKeywordIndex] != "FILES" &&
-      args[PrefixKeywordIdex] != "PREFIX") {
+      args[PrefixKeywordIndex] != "PREFIX") {
     errorMsg = "Unknown argument \"" + args[2] +
       "\". Perhaps the FILES keyword is missing.\n";
     return false;
   }
 
-  if (args[PrefixKeywordIdex] == "PREFIX" &&
+  if (args[PrefixKeywordIndex] == "PREFIX" &&
       (args.size() < 5 || args[FilesWithPrefixKeywordIndex] != "FILES")) {
     errorMsg = "Missing FILES arguments.";
     return false;
@@ -226,22 +261,24 @@ bool cmSourceGroupCommand::processTree(const std::vector<std::string>& args,
   const std::string root = cmSystemTools::CollapseFullPath(args[RootIndex]);
   std::string prefix;
   size_t filesBegin = FilesWithoutPrefixKeywordIndex + 1;
-  if (args[PrefixKeywordIdex] == "PREFIX") {
-    prefix = args[PrefixKeywordIdex + 1];
+  if (args[PrefixKeywordIndex] == "PREFIX") {
+    prefix = args[PrefixKeywordIndex + 1];
     filesBegin = FilesWithPrefixKeywordIndex + 1;
   }
 
-  const std::vector<std::string> filesVector(args.begin() + filesBegin,
-                                             args.end());
+  const std::vector<std::string> filesVector =
+    prepareFilesPathsForTree(args.begin() + filesBegin, args.end(),
+                             this->Makefile->GetCurrentSourceDirectory());
 
-  std::set<std::string> sourceGroupPaths = getSourceGroupFilesPaths(
-    this->Makefile->GetCurrentSourceDirectory(), root, filesVector);
+  if (!rootIsPrefix(root, filesVector, errorMsg)) {
+    return false;
+  }
 
-  addFilesToItsSourceGroups(sourceGroupPaths, prefix, *(this->Makefile),
-                            errorMsg);
+  std::set<std::string> sourceGroupPaths =
+    getSourceGroupFilesPaths(root, filesVector);
 
-  if (!errorMsg.empty()) {
-    this->SetError(errorMsg);
+  if (!addFilesToItsSourceGroups(root, sourceGroupPaths, prefix,
+                                 *(this->Makefile), errorMsg)) {
     return false;
   }
 
diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h
index 5549096..7d56b0d 100644
--- a/Source/cmSourceGroupCommand.h
+++ b/Source/cmSourceGroupCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSourceGroupCommand_h
 #define cmSourceGroupCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "source_group"; }
-
 private:
   bool processTree(const std::vector<std::string>& args,
                    std::string& errorMsg);
diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h
deleted file mode 100644
index a2047af..0000000
--- a/Source/cmStandardIncludes.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-/**
- * Include header files as a function of the build process, compiler,
- * and operating system.
- */
-#ifndef cmStandardIncludes_h
-#define cmStandardIncludes_h
-
-#include <cmConfigure.h>
-
-// Provide fixed-size integer types.
-#include <cm_kwiml.h>
-
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-
-// we must have stl with the standard include style
-#include <algorithm>
-#include <functional>
-#include <iterator>
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-// include the "c" string header
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(_MSC_VER)
-typedef unsigned short mode_t;
-#else
-#include <sys/types.h>
-#endif
-
-// use this class to shrink the size of symbols in .o files
-// std::string is really basic_string<....lots of stuff....>
-// when combined with a map or set, the symbols can be > 2000 chars!
-#include <cmsys/String.hxx>
-// typedef cmsys::String std::string;
-
-/* Poison this operator to avoid common mistakes.  */
-extern void operator<<(std::ostream&, const std::ostringstream&);
-
-#include "cmCustomCommandLines.h"
-#include "cmDocumentationEntry.h"
-#include "cmTargetLinkLibraryType.h"
-
-#endif
diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h
index b9adee5..c9f42e4 100644
--- a/Source/cmStandardLexer.h
+++ b/Source/cmStandardLexer.h
@@ -3,7 +3,7 @@
 #ifndef cmStandardLexer_h
 #define cmStandardLexer_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 /* Disable some warnings.  */
 #if defined(_MSC_VER)
@@ -50,7 +50,7 @@
 #define YY_NO_UNPUT 1
 #define ECHO
 
-#include <cm_kwiml.h>
+#include "cm_kwiml.h"
 typedef KWIML_INT_int8_t flex_int8_t;
 typedef KWIML_INT_uint8_t flex_uint8_t;
 typedef KWIML_INT_int16_t flex_int16_t;
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 18d5ea1..92e47f7 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmState.h"
 
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
-#include <cmsys/RegularExpression.hxx>
 #include <string.h>
 #include <utility>
 
@@ -12,14 +12,17 @@
 #include "cmCacheManager.h"
 #include "cmCommand.h"
 #include "cmDefinitions.h"
+#include "cmDisallowedCommand.h"
 #include "cmListFileCache.h"
 #include "cmStatePrivate.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
+#include "cmUnexpectedCommand.h"
 #include "cmake.h"
 
 cmState::cmState()
   : IsInTryCompile(false)
+  , IsGeneratorMultiConfig(false)
   , WindowsShell(false)
   , WindowsVSIDE(false)
   , WatcomWMake(false)
@@ -33,7 +36,8 @@ cmState::cmState()
 cmState::~cmState()
 {
   delete this->CacheManager;
-  cmDeleteAll(this->Commands);
+  cmDeleteAll(this->BuiltinCommands);
+  cmDeleteAll(this->ScriptedCommands);
 }
 
 const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType)
@@ -364,99 +368,102 @@ void cmState::SetIsInTryCompile(bool b)
   this->IsInTryCompile = b;
 }
 
-void cmState::RenameCommand(std::string const& oldName,
-                            std::string const& newName)
+bool cmState::GetIsGeneratorMultiConfig() const
 {
-  // if the command already exists, free the old one
-  std::string sOldName = cmSystemTools::LowerCase(oldName);
-  std::string sNewName = cmSystemTools::LowerCase(newName);
-  std::map<std::string, cmCommand*>::iterator pos =
-    this->Commands.find(sOldName);
-  if (pos == this->Commands.end()) {
-    return;
-  }
-  cmCommand* cmd = pos->second;
+  return this->IsGeneratorMultiConfig;
+}
 
-  pos = this->Commands.find(sNewName);
-  if (pos != this->Commands.end()) {
-    delete pos->second;
-    this->Commands.erase(pos);
-  }
-  this->Commands.insert(std::make_pair(sNewName, cmd));
-  pos = this->Commands.find(sOldName);
-  this->Commands.erase(pos);
+void cmState::SetIsGeneratorMultiConfig(bool b)
+{
+  this->IsGeneratorMultiConfig = b;
 }
 
-void cmState::AddCommand(cmCommand* command)
+void cmState::AddBuiltinCommand(std::string const& name, cmCommand* command)
 {
-  std::string name = cmSystemTools::LowerCase(command->GetName());
-  // if the command already exists, free the old one
-  std::map<std::string, cmCommand*>::iterator pos = this->Commands.find(name);
-  if (pos != this->Commands.end()) {
-    delete pos->second;
-    this->Commands.erase(pos);
-  }
-  this->Commands.insert(std::make_pair(name, command));
+  assert(name == cmSystemTools::LowerCase(name));
+  assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end());
+  this->BuiltinCommands.insert(std::make_pair(name, command));
+}
+
+void cmState::AddDisallowedCommand(std::string const& name, cmCommand* command,
+                                   cmPolicies::PolicyID policy,
+                                   const char* message)
+{
+  this->AddBuiltinCommand(name,
+                          new cmDisallowedCommand(command, policy, message));
+}
+
+void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
+{
+  this->AddBuiltinCommand(name, new cmUnexpectedCommand(name, error));
 }
 
-void cmState::RemoveUnscriptableCommands()
+void cmState::AddScriptedCommand(std::string const& name, cmCommand* command)
 {
-  std::vector<std::string> unscriptableCommands;
-  for (std::map<std::string, cmCommand*>::iterator pos =
-         this->Commands.begin();
-       pos != this->Commands.end();) {
-    if (!pos->second->IsScriptable()) {
+  std::string sName = cmSystemTools::LowerCase(name);
+
+  // if the command already exists, give a new name to the old command.
+  if (cmCommand* oldCmd = this->GetCommand(sName)) {
+    std::string const newName = "_" + sName;
+    std::map<std::string, cmCommand*>::iterator pos =
+      this->ScriptedCommands.find(newName);
+    if (pos != this->ScriptedCommands.end()) {
       delete pos->second;
-      this->Commands.erase(pos++);
-    } else {
-      ++pos;
+      this->ScriptedCommands.erase(pos);
     }
+    this->ScriptedCommands.insert(std::make_pair(newName, oldCmd->Clone()));
+  }
+
+  // if the command already exists, free the old one
+  std::map<std::string, cmCommand*>::iterator pos =
+    this->ScriptedCommands.find(sName);
+  if (pos != this->ScriptedCommands.end()) {
+    delete pos->second;
+    this->ScriptedCommands.erase(pos);
   }
+  this->ScriptedCommands.insert(std::make_pair(sName, command));
 }
 
 cmCommand* cmState::GetCommand(std::string const& name) const
 {
-  cmCommand* command = CM_NULLPTR;
   std::string sName = cmSystemTools::LowerCase(name);
-  std::map<std::string, cmCommand*>::const_iterator pos =
-    this->Commands.find(sName);
-  if (pos != this->Commands.end()) {
-    command = (*pos).second;
+  std::map<std::string, cmCommand*>::const_iterator pos;
+  pos = this->ScriptedCommands.find(sName);
+  if (pos != this->ScriptedCommands.end()) {
+    return pos->second;
   }
-  return command;
+  pos = this->BuiltinCommands.find(sName);
+  if (pos != this->BuiltinCommands.end()) {
+    return pos->second;
+  }
+  return CM_NULLPTR;
 }
 
 std::vector<std::string> cmState::GetCommandNames() const
 {
   std::vector<std::string> commandNames;
-  commandNames.reserve(this->Commands.size());
-  std::map<std::string, cmCommand*>::const_iterator cmds =
-    this->Commands.begin();
-  for (; cmds != this->Commands.end(); ++cmds) {
+  commandNames.reserve(this->BuiltinCommands.size() +
+                       this->ScriptedCommands.size());
+  for (std::map<std::string, cmCommand*>::const_iterator cmds =
+         this->BuiltinCommands.begin();
+       cmds != this->BuiltinCommands.end(); ++cmds) {
+    commandNames.push_back(cmds->first);
+  }
+  for (std::map<std::string, cmCommand*>::const_iterator cmds =
+         this->ScriptedCommands.begin();
+       cmds != this->ScriptedCommands.end(); ++cmds) {
     commandNames.push_back(cmds->first);
   }
+  std::sort(commandNames.begin(), commandNames.end());
+  commandNames.erase(std::unique(commandNames.begin(), commandNames.end()),
+                     commandNames.end());
   return commandNames;
 }
 
 void cmState::RemoveUserDefinedCommands()
 {
-  std::vector<cmCommand*> renamedCommands;
-  for (std::map<std::string, cmCommand*>::iterator j = this->Commands.begin();
-       j != this->Commands.end();) {
-    if (j->second->IsUserDefined()) {
-      delete j->second;
-      this->Commands.erase(j++);
-    } else if (j->first != j->second->GetName()) {
-      renamedCommands.push_back(j->second);
-      this->Commands.erase(j++);
-    } else {
-      ++j;
-    }
-  }
-  for (std::vector<cmCommand*>::const_iterator it = renamedCommands.begin();
-       it != renamedCommands.end(); ++it) {
-    this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it;
-  }
+  cmDeleteAll(this->ScriptedCommands);
+  this->ScriptedCommands.clear();
 }
 
 void cmState::SetGlobalProperty(const std::string& prop, const char* value)
@@ -481,6 +488,9 @@ const char* cmState::GetGlobalProperty(const std::string& prop)
   } else if (prop == "IN_TRY_COMPILE") {
     this->SetGlobalProperty("IN_TRY_COMPILE",
                             this->IsInTryCompile ? "1" : "0");
+  } else if (prop == "GENERATOR_IS_MULTI_CONFIG") {
+    this->SetGlobalProperty("GENERATOR_IS_MULTI_CONFIG",
+                            this->IsGeneratorMultiConfig ? "1" : "0");
   } else if (prop == "ENABLED_LANGUAGES") {
     std::string langs;
     langs = cmJoin(this->EnabledLanguages, ";");
@@ -623,7 +633,7 @@ cmStateSnapshot cmState::CreateBaseSnapshot()
 }
 
 cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot(
-  cmStateSnapshot originSnapshot)
+  cmStateSnapshot const& originSnapshot)
 {
   assert(originSnapshot.IsValid());
   cmStateDetail::PositionType pos =
@@ -657,7 +667,7 @@ cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot(
 }
 
 cmStateSnapshot cmState::CreateFunctionCallSnapshot(
-  cmStateSnapshot originSnapshot, std::string const& fileName)
+  cmStateSnapshot const& originSnapshot, std::string const& fileName)
 {
   cmStateDetail::PositionType pos =
     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
@@ -676,7 +686,7 @@ cmStateSnapshot cmState::CreateFunctionCallSnapshot(
 }
 
 cmStateSnapshot cmState::CreateMacroCallSnapshot(
-  cmStateSnapshot originSnapshot, std::string const& fileName)
+  cmStateSnapshot const& originSnapshot, std::string const& fileName)
 {
   cmStateDetail::PositionType pos =
     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
@@ -691,7 +701,7 @@ cmStateSnapshot cmState::CreateMacroCallSnapshot(
 }
 
 cmStateSnapshot cmState::CreateIncludeFileSnapshot(
-  cmStateSnapshot originSnapshot, const std::string& fileName)
+  cmStateSnapshot const& originSnapshot, std::string const& fileName)
 {
   cmStateDetail::PositionType pos =
     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
@@ -706,7 +716,7 @@ cmStateSnapshot cmState::CreateIncludeFileSnapshot(
 }
 
 cmStateSnapshot cmState::CreateVariableScopeSnapshot(
-  cmStateSnapshot originSnapshot)
+  cmStateSnapshot const& originSnapshot)
 {
   cmStateDetail::PositionType pos =
     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
@@ -724,7 +734,7 @@ cmStateSnapshot cmState::CreateVariableScopeSnapshot(
 }
 
 cmStateSnapshot cmState::CreateInlineListFileSnapshot(
-  cmStateSnapshot originSnapshot, const std::string& fileName)
+  cmStateSnapshot const& originSnapshot, std::string const& fileName)
 {
   cmStateDetail::PositionType pos =
     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
@@ -738,7 +748,7 @@ cmStateSnapshot cmState::CreateInlineListFileSnapshot(
 }
 
 cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
-  cmStateSnapshot originSnapshot)
+  cmStateSnapshot const& originSnapshot)
 {
   cmStateDetail::PositionType pos =
     this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
@@ -749,7 +759,7 @@ cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
   return cmStateSnapshot(this, pos);
 }
 
-cmStateSnapshot cmState::Pop(cmStateSnapshot originSnapshot)
+cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
 {
   cmStateDetail::PositionType pos = originSnapshot.Position;
   cmStateDetail::PositionType prevPos = pos;
diff --git a/Source/cmState.h b/Source/cmState.h
index 41ffcdc..e03ad89 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -3,7 +3,7 @@
 #ifndef cmState_h
 #define cmState_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <set>
@@ -12,6 +12,7 @@
 
 #include "cmDefinitions.h"
 #include "cmLinkedTree.h"
+#include "cmPolicies.h"
 #include "cmProperty.h"
 #include "cmPropertyDefinitionMap.h"
 #include "cmPropertyMap.h"
@@ -35,18 +36,20 @@ public:
 
   cmStateSnapshot CreateBaseSnapshot();
   cmStateSnapshot CreateBuildsystemDirectorySnapshot(
-    cmStateSnapshot originSnapshot);
-  cmStateSnapshot CreateFunctionCallSnapshot(cmStateSnapshot originSnapshot,
-                                             std::string const& fileName);
-  cmStateSnapshot CreateMacroCallSnapshot(cmStateSnapshot originSnapshot,
-                                          std::string const& fileName);
-  cmStateSnapshot CreateIncludeFileSnapshot(cmStateSnapshot originSnapshot,
-                                            std::string const& fileName);
-  cmStateSnapshot CreateVariableScopeSnapshot(cmStateSnapshot originSnapshot);
-  cmStateSnapshot CreateInlineListFileSnapshot(cmStateSnapshot originSnapshot,
-                                               std::string const& fileName);
-  cmStateSnapshot CreatePolicyScopeSnapshot(cmStateSnapshot originSnapshot);
-  cmStateSnapshot Pop(cmStateSnapshot originSnapshot);
+    cmStateSnapshot const& originSnapshot);
+  cmStateSnapshot CreateFunctionCallSnapshot(
+    cmStateSnapshot const& originSnapshot, std::string const& fileName);
+  cmStateSnapshot CreateMacroCallSnapshot(
+    cmStateSnapshot const& originSnapshot, std::string const& fileName);
+  cmStateSnapshot CreateIncludeFileSnapshot(
+    cmStateSnapshot const& originSnapshot, std::string const& fileName);
+  cmStateSnapshot CreateVariableScopeSnapshot(
+    cmStateSnapshot const& originSnapshot);
+  cmStateSnapshot CreateInlineListFileSnapshot(
+    cmStateSnapshot const& originSnapshot, std::string const& fileName);
+  cmStateSnapshot CreatePolicyScopeSnapshot(
+    cmStateSnapshot const& originSnapshot);
+  cmStateSnapshot Pop(cmStateSnapshot const& originSnapshot);
 
   static cmStateEnums::CacheEntryType StringToCacheEntryType(const char*);
   static const char* CacheEntryTypeToString(cmStateEnums::CacheEntryType);
@@ -116,10 +119,15 @@ public:
   bool GetIsInTryCompile() const;
   void SetIsInTryCompile(bool b);
 
+  bool GetIsGeneratorMultiConfig() const;
+  void SetIsGeneratorMultiConfig(bool b);
+
   cmCommand* GetCommand(std::string const& name) const;
-  void AddCommand(cmCommand* command);
-  void RemoveUnscriptableCommands();
-  void RenameCommand(std::string const& oldName, std::string const& newName);
+  void AddBuiltinCommand(std::string const& name, cmCommand* command);
+  void AddDisallowedCommand(std::string const& name, cmCommand* command,
+                            cmPolicies::PolicyID policy, const char* message);
+  void AddUnexpectedCommand(std::string const& name, const char* error);
+  void AddScriptedCommand(std::string const& name, cmCommand* command);
   void RemoveUserDefinedCommands();
   std::vector<std::string> GetCommandNames() const;
 
@@ -158,7 +166,8 @@ private:
 
   std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions;
   std::vector<std::string> EnabledLanguages;
-  std::map<std::string, cmCommand*> Commands;
+  std::map<std::string, cmCommand*> BuiltinCommands;
+  std::map<std::string, cmCommand*> ScriptedCommands;
   cmPropertyMap GlobalProperties;
   cmCacheManager* CacheManager;
 
@@ -174,6 +183,7 @@ private:
   std::string SourceDirectory;
   std::string BinaryDirectory;
   bool IsInTryCompile;
+  bool IsGeneratorMultiConfig;
   bool WindowsShell;
   bool WindowsVSIDE;
   bool WatcomWMake;
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index 8accc8e..79bb369 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -4,7 +4,7 @@
 #ifndef cmStateDirectory_h
 #define cmStateDirectory_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h
index 20700f2..f36ee37 100644
--- a/Source/cmStatePrivate.h
+++ b/Source/cmStatePrivate.h
@@ -4,7 +4,7 @@
 #ifndef cmStatePrivate_h
 #define cmStatePrivate_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
@@ -57,11 +57,6 @@ struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap
     , Weak(w)
   {
   }
-  PolicyStackEntry(PolicyStackEntry const& r)
-    : derived(r)
-    , Weak(r.Weak)
-  {
-  }
   bool Weak;
 };
 
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index c6288a5..77413c7 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -18,6 +18,10 @@
 #include "cmVersion.h"
 #include "cmake.h"
 
+#if !defined(_WIN32)
+#include <sys/utsname.h>
+#endif
+
 #if defined(__CYGWIN__)
 #include "cmSystemTools.h"
 #endif
@@ -121,7 +125,7 @@ cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const
   return cmStateSnapshot(this->State, pos);
 }
 
-void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap entry, bool weak)
+void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak)
 {
   cmStateDetail::PositionType pos = this->Position;
   pos->Policies = this->State->PolicyStack.Push(
@@ -298,9 +302,15 @@ void cmStateSnapshot::SetDefaultDefinitions()
 #if defined(_WIN32)
   this->SetDefinition("WIN32", "1");
   this->SetDefinition("CMAKE_HOST_WIN32", "1");
+  this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Windows");
 #else
   this->SetDefinition("UNIX", "1");
   this->SetDefinition("CMAKE_HOST_UNIX", "1");
+
+  struct utsname uts_name;
+  if (uname(&uts_name) >= 0) {
+    this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname);
+  }
 #endif
 #if defined(__CYGWIN__)
   std::string legacy;
diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h
index 72d0349..6293803 100644
--- a/Source/cmStateSnapshot.h
+++ b/Source/cmStateSnapshot.h
@@ -4,7 +4,7 @@
 #ifndef cmStateSnapshot_h
 #define cmStateSnapshot_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
@@ -45,7 +45,7 @@ public:
   void SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
   cmPolicies::PolicyStatus GetPolicy(cmPolicies::PolicyID id) const;
   bool HasDefinedPolicyCMP0011();
-  void PushPolicy(cmPolicies::PolicyMap entry, bool weak);
+  void PushPolicy(cmPolicies::PolicyMap const& entry, bool weak);
   bool PopPolicy();
   bool CanPopPolicyScope();
 
diff --git a/Source/cmStateTypes.h b/Source/cmStateTypes.h
index 2c974c1..7d6158e 100644
--- a/Source/cmStateTypes.h
+++ b/Source/cmStateTypes.h
@@ -4,7 +4,7 @@
 #ifndef cmStateTypes_h
 #define cmStateTypes_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmLinkedTree.h"
 
@@ -27,6 +27,9 @@ enum SnapshotType
   VariableScopeType
 };
 
+// There are multiple overlapping ranges represented here. Be aware that adding
+// a value to this enumeration may cause failures in numerous places which
+// assume details about the ordering.
 enum TargetType
 {
   EXECUTABLE,
@@ -50,6 +53,12 @@ enum CacheEntryType
   STATIC,
   UNINITIALIZED
 };
+
+enum ArtifactType
+{
+  RuntimeBinaryArtifact,
+  ImportLibraryArtifact
+};
 }
 
 #endif
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index eb94080..7a097ba 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmStringCommand.h"
 
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/RegularExpression.hxx"
 #include <ctype.h>
 #include <sstream>
 #include <stdio.h>
@@ -128,7 +128,7 @@ bool cmStringCommand::HandleToUpperLowerCommand(
     return false;
   }
 
-  std::string outvar = args[2];
+  std::string const& outvar = args[2];
   std::string output;
 
   if (toUpper) {
@@ -149,7 +149,7 @@ bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args)
     return false;
   }
   std::string::size_type cc;
-  std::string outvar = args[args.size() - 1];
+  std::string const& outvar = args[args.size() - 1];
   std::string output;
   for (cc = 1; cc < args.size() - 1; cc++) {
     int ch = atoi(args[cc].c_str());
@@ -212,7 +212,7 @@ bool cmStringCommand::HandleRegexCommand(std::vector<std::string> const& args)
     this->SetError("sub-command REGEX requires a mode to be specified.");
     return false;
   }
-  std::string mode = args[1];
+  std::string const& mode = args[1];
   if (mode == "MATCH") {
     if (args.size() < 5) {
       this->SetError("sub-command REGEX, mode MATCH needs "
@@ -247,8 +247,8 @@ bool cmStringCommand::RegexMatch(std::vector<std::string> const& args)
 {
   //"STRING(REGEX MATCH <regular_expression> <output variable>
   // <input> [<input>...])\n";
-  std::string regex = args[2];
-  std::string outvar = args[3];
+  std::string const& regex = args[2];
+  std::string const& outvar = args[3];
 
   this->Makefile->ClearMatches();
   // Compile the regular expression.
@@ -288,8 +288,8 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
 {
   //"STRING(REGEX MATCHALL <regular_expression> <output variable> <input>
   // [<input>...])\n";
-  std::string regex = args[2];
-  std::string outvar = args[3];
+  std::string const& regex = args[2];
+  std::string const& outvar = args[3];
 
   this->Makefile->ClearMatches();
   // Compile the regular expression.
@@ -334,9 +334,9 @@ bool cmStringCommand::RegexReplace(std::vector<std::string> const& args)
 {
   //"STRING(REGEX REPLACE <regular_expression> <replace_expression>
   // <output variable> <input> [<input>...])\n"
-  std::string regex = args[2];
-  std::string replace = args[3];
-  std::string outvar = args[4];
+  std::string const& regex = args[2];
+  std::string const& replace = args[3];
+  std::string const& outvar = args[4];
 
   // Pull apart the replace expression to find the escaped [0-9] values.
   std::vector<RegexReplacement> replacement;
@@ -502,7 +502,7 @@ bool cmStringCommand::HandleCompareCommand(
     this->SetError("sub-command COMPARE requires a mode to be specified.");
     return false;
   }
-  std::string mode = args[1];
+  std::string const& mode = args[1];
   if ((mode == "EQUAL") || (mode == "NOTEQUAL") || (mode == "LESS") ||
       (mode == "LESS_EQUAL") || (mode == "GREATER") ||
       (mode == "GREATER_EQUAL")) {
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index c63bc3f..88015ad 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmStringCommand_h
 #define cmStringCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "string"; }
-
 protected:
   bool HandleConfigureCommand(std::vector<std::string> const& args);
   bool HandleAsciiCommand(std::vector<std::string> const& args);
diff --git a/Source/cmSubdirCommand.h b/Source/cmSubdirCommand.h
index ce1f876..a2af0fd 100644
--- a/Source/cmSubdirCommand.h
+++ b/Source/cmSubdirCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSubdirCommand_h
 #define cmSubdirCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "subdirs"; }
 };
 
 #endif
diff --git a/Source/cmSubdirDependsCommand.cxx b/Source/cmSubdirDependsCommand.cxx
index 9259836..0bb2c0a 100644
--- a/Source/cmSubdirDependsCommand.cxx
+++ b/Source/cmSubdirDependsCommand.cxx
@@ -2,15 +2,10 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmSubdirDependsCommand.h"
 
-#include "cmPolicies.h"
-
 class cmExecutionStatus;
 
 bool cmSubdirDependsCommand::InitialPass(std::vector<std::string> const&,
                                          cmExecutionStatus&)
 {
-  this->Disallowed(
-    cmPolicies::CMP0029,
-    "The subdir_depends command should not be called; see CMP0029.");
   return true;
 }
diff --git a/Source/cmSubdirDependsCommand.h b/Source/cmSubdirDependsCommand.h
index 80ff24f..d8ea928 100644
--- a/Source/cmSubdirDependsCommand.h
+++ b/Source/cmSubdirDependsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmSubdirDependsCommand_h
 #define cmSubdirDependsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -17,7 +18,6 @@ public:
   cmCommand* Clone() CM_OVERRIDE { return new cmSubdirDependsCommand; }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-  std::string GetName() const CM_OVERRIDE { return "subdir_depends"; }
 };
 
 #endif
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 9efc13b..f7192e0 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -4,11 +4,12 @@
 
 #include "cmAlgorithms.h"
 #include "cmProcessOutput.h"
+#include "cm_sys_stat.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmArchiveWrite.h"
 #include "cmLocale.h"
-#include <cm_libarchive.h>
+#include "cm_libarchive.h"
 #ifndef __LA_INT64_T
 #define __LA_INT64_T la_int64_t
 #endif
@@ -26,15 +27,14 @@
 #include "cmMachO.h"
 #endif
 
+#include "cmsys/Directory.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include "cmsys/System.h"
+#include "cmsys/Terminal.h"
 #include <algorithm>
 #include <assert.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/Encoding.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/System.h>
-#include <cmsys/SystemTools.hxx>
-#include <cmsys/Terminal.h>
 #include <ctype.h>
 #include <errno.h>
 #include <iostream>
@@ -43,8 +43,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <time.h>
+#include <utility>
 
 #if defined(_WIN32)
 #include <windows.h>
@@ -134,6 +134,7 @@ public:
   operator bool() const { return this->handle_ != INVALID_HANDLE_VALUE; }
   bool operator!() const { return this->handle_ == INVALID_HANDLE_VALUE; }
   operator HANDLE() const { return this->handle_; }
+
 private:
   HANDLE handle_;
 };
@@ -196,7 +197,6 @@ void cmSystemTools::ExpandRegistryValues(std::string& source,
   while (regEntry.find(source)) {
     // the arguments are the second match
     std::string key = regEntry.match(1);
-    std::string val;
     std::string reg = "[";
     reg += key + "]";
     cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
@@ -348,12 +348,12 @@ bool cmSystemTools::IsInternallyOn(const char* val)
   if (!val) {
     return false;
   }
-  std::basic_string<char> v = val;
+  std::string v = val;
   if (v.size() > 4) {
     return false;
   }
 
-  for (std::basic_string<char>::iterator c = v.begin(); c != v.end(); c++) {
+  for (std::string::iterator c = v.begin(); c != v.end(); c++) {
     *c = static_cast<char>(toupper(*c));
   }
   return v == "I_ON";
@@ -368,7 +368,7 @@ bool cmSystemTools::IsOn(const char* val)
   if (len > 4) {
     return false;
   }
-  std::basic_string<char> v(val, len);
+  std::string v(val, len);
 
   static std::set<std::string> onValues;
   if (onValues.empty()) {
@@ -378,7 +378,7 @@ bool cmSystemTools::IsOn(const char* val)
     onValues.insert("TRUE");
     onValues.insert("Y");
   }
-  for (std::basic_string<char>::iterator c = v.begin(); c != v.end(); c++) {
+  for (std::string::iterator c = v.begin(); c != v.end(); c++) {
     *c = static_cast<char>(toupper(*c));
   }
   return (onValues.count(v) > 0);
@@ -413,8 +413,8 @@ bool cmSystemTools::IsOff(const char* val)
     offValues.insert("IGNORE");
   }
   // Try and avoid toupper().
-  std::basic_string<char> v(val, len);
-  for (std::basic_string<char>::iterator c = v.begin(); c != v.end(); c++) {
+  std::string v(val, len);
+  for (std::string::iterator c = v.begin(); c != v.end(); c++) {
     *c = static_cast<char>(toupper(*c));
   }
   return (offValues.count(v) > 0);
@@ -505,6 +505,39 @@ void cmSystemTools::ParseUnixCommandLine(const char* command,
   argv.Store(args);
 }
 
+std::vector<std::string> cmSystemTools::HandleResponseFile(
+  std::vector<std::string>::const_iterator argBeg,
+  std::vector<std::string>::const_iterator argEnd)
+{
+  std::vector<std::string> arg_full;
+  for (std::vector<std::string>::const_iterator a = argBeg; a != argEnd; ++a) {
+    std::string const& arg = *a;
+    if (cmHasLiteralPrefix(arg, "@")) {
+      cmsys::ifstream responseFile(arg.substr(1).c_str(), std::ios::in);
+      if (!responseFile) {
+        std::string error = "failed to open for reading (";
+        error += cmSystemTools::GetLastSystemError();
+        error += "):\n  ";
+        error += arg.substr(1);
+        cmSystemTools::Error(error.c_str());
+      } else {
+        std::string line;
+        cmSystemTools::GetLineFromStream(responseFile, line);
+        std::vector<std::string> args2;
+#ifdef _WIN32
+        cmSystemTools::ParseWindowsCommandLine(line.c_str(), args2);
+#else
+        cmSystemTools::ParseUnixCommandLine(line.c_str(), args2);
+#endif
+        arg_full.insert(arg_full.end(), args2.begin(), args2.end());
+      }
+    } else {
+      arg_full.push_back(arg);
+    }
+  }
+  return arg_full;
+}
+
 std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
 {
   std::vector<std::string> args;
@@ -570,6 +603,46 @@ std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
   return args;
 }
 
+size_t cmSystemTools::CalculateCommandLineLengthLimit()
+{
+  size_t sz =
+#ifdef _WIN32
+    // There's a maximum of 65536 bytes and thus 32768 WCHARs on Windows
+    // However, cmd.exe itself can only handle 8191 WCHARs and Ninja for
+    // example uses it to spawn processes.
+    size_t(8191);
+#elif defined(__linux)
+    // MAX_ARG_STRLEN is the maximum length of a string permissible for
+    // the execve() syscall on Linux. It's defined as (PAGE_SIZE * 32)
+    // in Linux's binfmts.h
+    static_cast<size_t>(sysconf(_SC_PAGESIZE) * 32);
+#else
+    size_t(0);
+#endif
+
+#if defined(_SC_ARG_MAX)
+  // ARG_MAX is the maximum size of the command and environment
+  // that can be passed to the exec functions on UNIX.
+  // The value in limits.h does not need to be present and may
+  // depend upon runtime memory constraints, hence sysconf()
+  // should be used to query it.
+  long szArgMax = sysconf(_SC_ARG_MAX);
+  // A return value of -1 signifies an undetermined limit, but
+  // it does not imply an infinite limit, and thus is ignored.
+  if (szArgMax != -1) {
+    // We estimate the size of the environment block to be 1000.
+    // This isn't accurate at all, but leaves some headroom.
+    szArgMax = szArgMax < 1000 ? 0 : szArgMax - 1000;
+#if defined(_WIN32) || defined(__linux)
+    sz = std::min(sz, static_cast<size_t>(szArgMax));
+#else
+    sz = static_cast<size_t>(szArgMax);
+#endif
+  }
+#endif
+  return sz;
+}
+
 bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
                                      std::string* captureStdOut,
                                      std::string* captureStdErr, int* retVal,
@@ -617,8 +690,6 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
     while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) >
            0) {
       // Translate NULL characters in the output into valid text.
-      // Visual Studio 7 puts these characters in the output of its
-      // build process.
       for (int i = 0; i < length; ++i) {
         if (data[i] == '\0') {
           data[i] = ' ';
@@ -1669,7 +1740,8 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
     for (; outiter != out.end(); ++outiter) {
       if ((*outiter == '\r') && ((outiter + 1) == out.end())) {
         break;
-      } else if (*outiter == '\n' || *outiter == '\0') {
+      }
+      if (*outiter == '\n' || *outiter == '\0') {
         std::vector<char>::size_type length = outiter - out.begin();
         if (length > 1 && *(outiter - 1) == '\r') {
           --length;
@@ -1686,7 +1758,8 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
     for (; erriter != err.end(); ++erriter) {
       if ((*erriter == '\r') && ((erriter + 1) == err.end())) {
         break;
-      } else if (*erriter == '\n' || *erriter == '\0') {
+      }
+      if (*erriter == '\n' || *erriter == '\0') {
         std::vector<char>::size_type length = erriter - err.begin();
         if (length > 1 && *(erriter - 1) == '\r') {
           --length;
@@ -1978,6 +2051,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
     // ???
   }
 #endif
+  exe_dir = cmSystemTools::GetActualCaseForPath(exe_dir);
   cmSystemToolsCMakeCommand = exe_dir;
   cmSystemToolsCMakeCommand += "/cmake";
   cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension();
@@ -2015,8 +2089,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
   // Install tree has
   // - "<prefix><CMAKE_BIN_DIR>/cmake"
   // - "<prefix><CMAKE_DATA_DIR>"
-  const std::string actual_case = cmSystemTools::GetActualCaseForPath(exe_dir);
-  if (cmHasSuffix(actual_case, CMAKE_BIN_DIR)) {
+  if (cmHasSuffix(exe_dir, CMAKE_BIN_DIR)) {
     std::string const prefix =
       exe_dir.substr(0, exe_dir.size() - strlen(CMAKE_BIN_DIR));
     cmSystemToolsCMakeRoot = prefix + CMAKE_DATA_DIR;
@@ -2299,8 +2372,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
       // not being changed.
       rp[rp_count].Value = se[i]->Value.substr(0, prefix_len);
       rp[rp_count].Value += newRPath;
-      rp[rp_count].Value +=
-        se[i]->Value.substr(pos + oldRPath.length(), oldRPath.npos);
+      rp[rp_count].Value += se[i]->Value.substr(pos + oldRPath.length());
 
       if (!rp[rp_count].Value.empty()) {
         remove_rpath = false;
@@ -2585,29 +2657,28 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
         it = dentries.erase(it);
         entriesErased++;
         continue;
-      } else {
-        if (cmELF::TagMipsRldMapRel != 0 &&
-            it->first == cmELF::TagMipsRldMapRel) {
-          // 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
-          // contain the location of the linker map, however on MIPS the
-          // .dynamic section is always read-only so this is not possible. MIPS
-          // objects instead contain a DT_MIPS_RLD_MAP tag which contains the
-          // address where the dyanmic linker will write to (an indirect
-          // version of DT_DEBUG). Since this doesn't work when using PIE, a
-          // relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this
-          // version contains a relative offset, moving it changes the
-          // calculated address. This may cause the dyanmic linker to write
-          // into memory it should not be changing.
-          //
-          // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If
-          // we move it up by n bytes, we add n bytes to the value of this tag.
-          it->second += entriesErased * sizeof_dentry;
-        }
-
-        it++;
       }
+      if (cmELF::TagMipsRldMapRel != 0 &&
+          it->first == cmELF::TagMipsRldMapRel) {
+        // 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
+        // contain the location of the linker map, however on MIPS the
+        // .dynamic section is always read-only so this is not possible. MIPS
+        // objects instead contain a DT_MIPS_RLD_MAP tag which contains the
+        // address where the dyanmic linker will write to (an indirect
+        // version of DT_DEBUG). Since this doesn't work when using PIE, a
+        // relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this
+        // version contains a relative offset, moving it changes the
+        // calculated address. This may cause the dyanmic linker to write
+        // into memory it should not be changing.
+        //
+        // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If
+        // we move it up by n bytes, we add n bytes to the value of this tag.
+        it->second += entriesErased * sizeof_dentry;
+      }
+
+      it++;
     }
 
     // Encode new entries list
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 10e8280..9de7967 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -3,21 +3,15 @@
 #ifndef cmSystemTools_h
 #define cmSystemTools_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
-#include <cmProcessOutput.h>
-#include <cmsys/Process.h>
-#include <cmsys/SystemTools.hxx>
+#include "cmProcessOutput.h"
+#include "cmsys/Process.h"
+#include "cmsys/SystemTools.hxx" // IWYU pragma: export
 #include <stddef.h>
 #include <string>
 #include <vector>
 
-#if defined(_MSC_VER)
-typedef unsigned short mode_t;
-#else
-#include <sys/types.h>
-#endif
-
 class cmSystemToolsFileTime;
 
 /** \class cmSystemTools
@@ -259,6 +253,15 @@ public:
   static void ParseUnixCommandLine(const char* command,
                                    std::vector<std::string>& args);
 
+  /**
+   * Handle response file in an argument list and return a new argument list
+   * **/
+  static std::vector<std::string> HandleResponseFile(
+    std::vector<std::string>::const_iterator argBeg,
+    std::vector<std::string>::const_iterator argEnd);
+
+  static size_t CalculateCommandLineLengthLimit();
+
   static void EnableMessages() { s_DisableMessages = false; }
   static void DisableMessages() { s_DisableMessages = true; }
   static void DisableRunCommandOutput() { s_DisableRunCommandOutput = true; }
@@ -383,9 +386,10 @@ public:
       original environment. */
   class SaveRestoreEnvironment
   {
+    CM_DISABLE_COPY(SaveRestoreEnvironment)
   public:
     SaveRestoreEnvironment();
-    virtual ~SaveRestoreEnvironment();
+    ~SaveRestoreEnvironment();
 
   private:
     std::vector<std::string> Env;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index fe3472d..c95a3ca 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -2,9 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmTarget.h"
 
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
-#include <cmsys/RegularExpression.hxx>
 #include <map>
 #include <set>
 #include <sstream>
@@ -35,7 +35,7 @@ const char* cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>(
 {
   static std::string loc;
   if (tgt->IsImported()) {
-    loc = tgt->ImportedGetFullPath("", false);
+    loc = tgt->ImportedGetFullPath("", cmStateEnums::RuntimeBinaryArtifact);
     return loc.c_str();
   }
 
@@ -54,7 +54,8 @@ const char* cmTargetPropertyComputer::ComputeLocation<cmTarget>(
 {
   static std::string loc;
   if (tgt->IsImported()) {
-    loc = tgt->ImportedGetFullPath(config, false);
+    loc =
+      tgt->ImportedGetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
     return loc.c_str();
   }
 
@@ -63,7 +64,7 @@ const char* cmTargetPropertyComputer::ComputeLocation<cmTarget>(
     gg->CreateGenerationObjects();
   }
   cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName());
-  loc = gt->GetFullPath(config, false);
+  loc = gt->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
   return loc.c_str();
 }
 
@@ -230,6 +231,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
     this->SetPropertyDefault("INSTALL_NAME_DIR", CM_NULLPTR);
     this->SetPropertyDefault("INSTALL_RPATH", "");
     this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF");
+    this->SetPropertyDefault("INTERPROCEDURAL_OPTIMIZATION", CM_NULLPTR);
     this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
     this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF");
     this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", CM_NULLPTR);
@@ -245,14 +247,17 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
     this->SetPropertyDefault("AUTOMOC", CM_NULLPTR);
     this->SetPropertyDefault("AUTOUIC", CM_NULLPTR);
     this->SetPropertyDefault("AUTORCC", CM_NULLPTR);
+    this->SetPropertyDefault("AUTOMOC_DEPEND_FILTERS", CM_NULLPTR);
     this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", CM_NULLPTR);
     this->SetPropertyDefault("AUTOUIC_OPTIONS", CM_NULLPTR);
+    this->SetPropertyDefault("AUTOUIC_SEARCH_PATHS", CM_NULLPTR);
     this->SetPropertyDefault("AUTORCC_OPTIONS", CM_NULLPTR);
     this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", CM_NULLPTR);
     this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", CM_NULLPTR);
     this->SetPropertyDefault("WIN32_EXECUTABLE", CM_NULLPTR);
     this->SetPropertyDefault("MACOSX_BUNDLE", CM_NULLPTR);
     this->SetPropertyDefault("MACOSX_RPATH", CM_NULLPTR);
+    this->SetPropertyDefault("BUILD_WITH_INSTALL_NAME_DIR", CM_NULLPTR);
     this->SetPropertyDefault("C_CLANG_TIDY", CM_NULLPTR);
     this->SetPropertyDefault("C_COMPILER_LAUNCHER", CM_NULLPTR);
     this->SetPropertyDefault("C_CPPLINT", CM_NULLPTR);
@@ -287,13 +292,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
   if (this->GetType() != cmStateEnums::UTILITY) {
     const char* configProps[] = {
       /* clang-format needs this comment to break after the opening brace */
-      "ARCHIVE_OUTPUT_DIRECTORY_",
-      "LIBRARY_OUTPUT_DIRECTORY_",
-      "RUNTIME_OUTPUT_DIRECTORY_",
-      "PDB_OUTPUT_DIRECTORY_",
-      "COMPILE_PDB_OUTPUT_DIRECTORY_",
-      "MAP_IMPORTED_CONFIG_",
-      CM_NULLPTR
+      "ARCHIVE_OUTPUT_DIRECTORY_",     "LIBRARY_OUTPUT_DIRECTORY_",
+      "RUNTIME_OUTPUT_DIRECTORY_",     "PDB_OUTPUT_DIRECTORY_",
+      "COMPILE_PDB_OUTPUT_DIRECTORY_", "MAP_IMPORTED_CONFIG_",
+      "INTERPROCEDURAL_OPTIMIZATION_", CM_NULLPTR
     };
     for (std::vector<std::string>::iterator ci = configNames.begin();
          ci != configNames.end(); ++ci) {
@@ -939,6 +941,14 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
   } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
              !this->CheckImportedLibName(prop, value ? value : "")) {
     /* error was reported by check method */
+  } else if (prop == "CUDA_PTX_COMPILATION" &&
+             this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+    std::ostringstream e;
+    e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT "
+         "targets (\""
+      << this->Name << "\")\n";
+    this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+    return;
   } else {
     this->Properties.SetProperty(prop, value);
   }
@@ -1293,68 +1303,96 @@ bool cmTarget::GetPropertyAsBool(const std::string& prop) const
   return cmSystemTools::IsOn(this->GetProperty(prop));
 }
 
-const char* cmTarget::GetSuffixVariableInternal(bool implib) const
+const char* cmTarget::GetSuffixVariableInternal(
+  cmStateEnums::ArtifactType artifact) const
 {
   switch (this->GetType()) {
     case cmStateEnums::STATIC_LIBRARY:
       return "CMAKE_STATIC_LIBRARY_SUFFIX";
     case cmStateEnums::SHARED_LIBRARY:
-      return (implib ? "CMAKE_IMPORT_LIBRARY_SUFFIX"
-                     : "CMAKE_SHARED_LIBRARY_SUFFIX");
+      switch (artifact) {
+        case cmStateEnums::RuntimeBinaryArtifact:
+          return "CMAKE_SHARED_LIBRARY_SUFFIX";
+        case cmStateEnums::ImportLibraryArtifact:
+          return "CMAKE_IMPORT_LIBRARY_SUFFIX";
+      }
+      break;
     case cmStateEnums::MODULE_LIBRARY:
-      return (implib ? "CMAKE_IMPORT_LIBRARY_SUFFIX"
-                     : "CMAKE_SHARED_MODULE_SUFFIX");
+      switch (artifact) {
+        case cmStateEnums::RuntimeBinaryArtifact:
+          return "CMAKE_SHARED_MODULE_SUFFIX";
+        case cmStateEnums::ImportLibraryArtifact:
+          return "CMAKE_IMPORT_LIBRARY_SUFFIX";
+      }
+      break;
     case cmStateEnums::EXECUTABLE:
-      return (implib
-                ? "CMAKE_IMPORT_LIBRARY_SUFFIX"
-                // Android GUI application packages store the native
-                // binary as a shared library.
-                : (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
-                     ? "CMAKE_SHARED_LIBRARY_SUFFIX"
-                     : "CMAKE_EXECUTABLE_SUFFIX"));
+      switch (artifact) {
+        case cmStateEnums::RuntimeBinaryArtifact:
+          // Android GUI application packages store the native
+          // binary as a shared library.
+          return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+                    ? "CMAKE_SHARED_LIBRARY_SUFFIX"
+                    : "CMAKE_EXECUTABLE_SUFFIX");
+        case cmStateEnums::ImportLibraryArtifact:
+          return "CMAKE_IMPORT_LIBRARY_SUFFIX";
+      }
+      break;
     default:
       break;
   }
   return "";
 }
 
-const char* cmTarget::GetPrefixVariableInternal(bool implib) const
+const char* cmTarget::GetPrefixVariableInternal(
+  cmStateEnums::ArtifactType artifact) const
 {
   switch (this->GetType()) {
     case cmStateEnums::STATIC_LIBRARY:
       return "CMAKE_STATIC_LIBRARY_PREFIX";
     case cmStateEnums::SHARED_LIBRARY:
-      return (implib ? "CMAKE_IMPORT_LIBRARY_PREFIX"
-                     : "CMAKE_SHARED_LIBRARY_PREFIX");
+      switch (artifact) {
+        case cmStateEnums::RuntimeBinaryArtifact:
+          return "CMAKE_SHARED_LIBRARY_PREFIX";
+        case cmStateEnums::ImportLibraryArtifact:
+          return "CMAKE_IMPORT_LIBRARY_PREFIX";
+      }
+      break;
     case cmStateEnums::MODULE_LIBRARY:
-      return (implib ? "CMAKE_IMPORT_LIBRARY_PREFIX"
-                     : "CMAKE_SHARED_MODULE_PREFIX");
+      switch (artifact) {
+        case cmStateEnums::RuntimeBinaryArtifact:
+          return "CMAKE_SHARED_MODULE_PREFIX";
+        case cmStateEnums::ImportLibraryArtifact:
+          return "CMAKE_IMPORT_LIBRARY_PREFIX";
+      }
+      break;
     case cmStateEnums::EXECUTABLE:
-      return (implib
-                ? "CMAKE_IMPORT_LIBRARY_PREFIX"
-                // Android GUI application packages store the native
-                // binary as a shared library.
-                : (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
-                     ? "CMAKE_SHARED_LIBRARY_PREFIX"
-                     : ""));
+      switch (artifact) {
+        case cmStateEnums::RuntimeBinaryArtifact:
+          // Android GUI application packages store the native
+          // binary as a shared library.
+          return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+                    ? "CMAKE_SHARED_LIBRARY_PREFIX"
+                    : "");
+        case cmStateEnums::ImportLibraryArtifact:
+          return "CMAKE_IMPORT_LIBRARY_PREFIX";
+      }
+      break;
     default:
       break;
   }
   return "";
 }
 
-std::string cmTarget::ImportedGetFullPath(const std::string& config,
-                                          bool pimplib) const
+std::string cmTarget::ImportedGetFullPath(
+  const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   assert(this->IsImported());
 
   // Lookup/compute/cache the import information for this
   // configuration.
-  std::string config_upper;
-  if (!config.empty()) {
-    config_upper = cmSystemTools::UpperCase(config);
-  } else {
-    config_upper = "NOCONFIG";
+  std::string desired_config = config;
+  if (config.empty()) {
+    desired_config = "NOCONFIG";
   }
 
   std::string result;
@@ -1364,33 +1402,38 @@ std::string cmTarget::ImportedGetFullPath(const std::string& config,
   std::string suffix;
 
   if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
-      this->GetMappedConfig(config_upper, &loc, &imp, suffix)) {
-    if (!pimplib) {
-      if (loc) {
-        result = loc;
-      } else {
-        std::string impProp = "IMPORTED_LOCATION";
-        impProp += suffix;
-        if (const char* config_location = this->GetProperty(impProp)) {
-          result = config_location;
-        } else if (const char* location =
-                     this->GetProperty("IMPORTED_LOCATION")) {
-          result = location;
+      this->GetMappedConfig(desired_config, &loc, &imp, suffix)) {
+    switch (artifact) {
+      case cmStateEnums::RuntimeBinaryArtifact:
+        if (loc) {
+          result = loc;
+        } else {
+          std::string impProp = "IMPORTED_LOCATION";
+          impProp += suffix;
+          if (const char* config_location = this->GetProperty(impProp)) {
+            result = config_location;
+          } else if (const char* location =
+                       this->GetProperty("IMPORTED_LOCATION")) {
+            result = location;
+          }
         }
-      }
-    } else {
-      if (imp) {
-        result = imp;
-      } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
-                 this->IsExecutableWithExports()) {
-        std::string impProp = "IMPORTED_IMPLIB";
-        impProp += suffix;
-        if (const char* config_implib = this->GetProperty(impProp)) {
-          result = config_implib;
-        } else if (const char* implib = this->GetProperty("IMPORTED_IMPLIB")) {
-          result = implib;
+        break;
+
+      case cmStateEnums::ImportLibraryArtifact:
+        if (imp) {
+          result = imp;
+        } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+                   this->IsExecutableWithExports()) {
+          std::string impProp = "IMPORTED_IMPLIB";
+          impProp += suffix;
+          if (const char* config_implib = this->GetProperty(impProp)) {
+            result = config_implib;
+          } else if (const char* implib =
+                       this->GetProperty("IMPORTED_IMPLIB")) {
+            result = implib;
+          }
         }
-      }
+        break;
     }
   }
 
@@ -1433,7 +1476,7 @@ bool cmTarget::CheckImportedLibName(std::string const& prop,
       return false;
     }
     std::string::size_type bad = value.find_first_of(":/\\;");
-    if (bad != value.npos) {
+    if (bad != std::string::npos) {
       this->Makefile->IssueMessage(
         cmake::FATAL_ERROR, prop + " property value\n  " + value +
           "\nmay not contain '" + value.substr(bad, 1) + "'.");
@@ -1447,18 +1490,28 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
                                const char** loc, const char** imp,
                                std::string& suffix) const
 {
-  std::string const locPropBase =
-    this->GetType() == cmStateEnums::INTERFACE_LIBRARY ? "IMPORTED_LIBNAME"
-                                                       : "IMPORTED_LOCATION";
+  std::string config_upper;
+  if (!desired_config.empty()) {
+    config_upper = cmSystemTools::UpperCase(desired_config);
+  }
+
+  std::string locPropBase;
+  if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+    locPropBase = "IMPORTED_LIBNAME";
+  } else if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+    locPropBase = "IMPORTED_OBJECTS";
+  } else {
+    locPropBase = "IMPORTED_LOCATION";
+  }
 
   // Track the configuration-specific property suffix.
   suffix = "_";
-  suffix += desired_config;
+  suffix += config_upper;
 
   std::vector<std::string> mappedConfigs;
   {
     std::string mapProp = "MAP_IMPORTED_CONFIG_";
-    mapProp += desired_config;
+    mapProp += config_upper;
     if (const char* mapValue = this->GetProperty(mapProp)) {
       cmSystemTools::ExpandListArgument(mapValue, mappedConfigs, true);
     }
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 1d40d20..1f00c01 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -3,7 +3,7 @@
 #ifndef cmTarget_h
 #define cmTarget_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
 #include <map>
@@ -267,11 +267,13 @@ public:
   };
 
   std::string ImportedGetFullPath(const std::string& config,
-                                  bool implib) const;
+                                  cmStateEnums::ArtifactType artifact) const;
 
 private:
-  const char* GetSuffixVariableInternal(bool implib) const;
-  const char* GetPrefixVariableInternal(bool implib) const;
+  const char* GetSuffixVariableInternal(
+    cmStateEnums::ArtifactType artifact) const;
+  const char* GetPrefixVariableInternal(
+    cmStateEnums::ArtifactType artifact) const;
 
   // Use a makefile variable to set a default for the given property.
   // If the variable is not defined use the given default instead.
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
index caaf23b..11abf57 100644
--- a/Source/cmTargetCompileDefinitionsCommand.h
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmTargetCompileDefinitionsCommand_h
 #define cmTargetCompileDefinitionsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,14 +32,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "target_compile_definitions";
-  }
-
 private:
   void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
   void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h
index 01f2938..9908680 100644
--- a/Source/cmTargetCompileFeaturesCommand.h
+++ b/Source/cmTargetCompileFeaturesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmTargetCompileFeaturesCommand_h
 #define cmTargetCompileFeaturesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -20,8 +21,6 @@ class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  std::string GetName() const CM_OVERRIDE { return "target_compile_features"; }
-
 private:
   void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
   void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
index 179013b..b5408f7 100644
--- a/Source/cmTargetCompileOptionsCommand.h
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmTargetCompileOptionsCommand_h
 #define cmTargetCompileOptionsCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -28,11 +29,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "target_compile_options"; }
-
 private:
   void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
   void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h
index a953efb..daa902e 100644
--- a/Source/cmTargetDepend.h
+++ b/Source/cmTargetDepend.h
@@ -3,7 +3,7 @@
 #ifndef cmTargetDepend_h
 #define cmTargetDepend_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <set>
 
@@ -30,7 +30,7 @@ public:
   operator cmGeneratorTarget const*() const { return this->Target; }
   cmGeneratorTarget const* operator->() const { return this->Target; }
   cmGeneratorTarget const& operator*() const { return *this->Target; }
-  friend bool operator<(cmTargetDepend const& l, cmTargetDepend const& r)
+  friend bool operator<(cmTargetDepend l, cmTargetDepend r)
   {
     return l.Target < r.Target;
   }
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index b08ede2..9304eab 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -3,7 +3,7 @@
 #ifndef cmTargetExport_h
 #define cmTargetExport_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
@@ -26,6 +26,7 @@ public:
   cmInstallTargetGenerator* ArchiveGenerator;
   cmInstallTargetGenerator* RuntimeGenerator;
   cmInstallTargetGenerator* LibraryGenerator;
+  cmInstallTargetGenerator* ObjectsGenerator;
   cmInstallTargetGenerator* FrameworkGenerator;
   cmInstallTargetGenerator* BundleGenerator;
   cmInstallFilesGenerator* HeaderGenerator;
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
index bc6cf0d..374a867 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.h
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmTargetIncludeDirectoriesCommand_h
 #define cmTargetIncludeDirectoriesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,14 +32,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE
-  {
-    return "target_include_directories";
-  }
-
 private:
   void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
   void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index 762b48f..3fd20ac 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmTargetLinkLibrariesCommand_h
 #define cmTargetLinkLibrariesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -35,11 +36,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "target_link_libraries"; }
-
 private:
   void LinkLibraryTypeSpecifierWarning(int left, int right);
   static const char* LinkLibraryTypeNames[3];
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 9a5c1da..45fe430 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -78,7 +78,7 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
   std::vector<std::string> const& args, unsigned int& argIndex, bool prepend,
   bool system)
 {
-  const std::string scope = args[argIndex];
+  std::string const& scope = args[argIndex];
 
   if (scope != "PUBLIC" && scope != "PRIVATE" && scope != "INTERFACE") {
     this->SetError("called with invalid arguments");
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index 8b49653..46a2f6b 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -3,7 +3,7 @@
 #ifndef cmTargetPropCommandBase_h
 #define cmTargetPropCommandBase_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
index 45d31be..94688e3 100644
--- a/Source/cmTargetPropertyComputer.h
+++ b/Source/cmTargetPropertyComputer.h
@@ -3,7 +3,7 @@
 #ifndef cmTargetPropertyComputer_h
 #define cmTargetPropertyComputer_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h
index b1afac2..09ba729 100644
--- a/Source/cmTargetSourcesCommand.h
+++ b/Source/cmTargetSourcesCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmTargetSourcesCommand_h
 #define cmTargetSourcesCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -28,11 +29,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "target_sources"; }
-
 private:
   void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
   void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
diff --git a/Source/cmTest.h b/Source/cmTest.h
index 274a924..d4839d1 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -3,7 +3,7 @@
 #ifndef cmTest_h
 #define cmTest_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmListFileCache.h"
 #include "cmPropertyMap.h"
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 4164f3a..be4b378 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -35,15 +35,13 @@ void cmTestGenerator::Compute(cmLocalGenerator* lg)
   this->LG = lg;
 }
 
-void cmTestGenerator::GenerateScriptConfigs(std::ostream& os,
-                                            Indent const& indent)
+void cmTestGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent)
 {
   // Create the tests.
   this->cmScriptGenerator::GenerateScriptConfigs(os, indent);
 }
 
-void cmTestGenerator::GenerateScriptActions(std::ostream& os,
-                                            Indent const& indent)
+void cmTestGenerator::GenerateScriptActions(std::ostream& os, Indent indent)
 {
   if (this->ActionsPerConfig) {
     // This is the per-config generation in a single-configuration
@@ -59,7 +57,7 @@ void cmTestGenerator::GenerateScriptActions(std::ostream& os,
 
 void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
                                               const std::string& config,
-                                              Indent const& indent)
+                                              Indent indent)
 {
   this->TestGenerated = true;
 
@@ -125,8 +123,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
   }
 }
 
-void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os,
-                                             Indent const& indent)
+void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent)
 {
   os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n";
 }
@@ -139,8 +136,7 @@ bool cmTestGenerator::NeedsScriptNoConfig() const
           !this->ConfigurationTypes->empty()); // config-dependent command
 }
 
-void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
-                                       Indent const& indent)
+void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent)
 {
   this->TestGenerated = true;
 
diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h
index b350806..b227305 100644
--- a/Source/cmTestGenerator.h
+++ b/Source/cmTestGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmTestGenerator_h
 #define cmTestGenerator_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include "cmScriptGenerator.h"
 
@@ -20,6 +20,8 @@ class cmTest;
  */
 class cmTestGenerator : public cmScriptGenerator
 {
+  CM_DISABLE_COPY(cmTestGenerator)
+
 public:
   cmTestGenerator(cmTest* test,
                   std::vector<std::string> const& configurations =
@@ -29,16 +31,13 @@ public:
   void Compute(cmLocalGenerator* lg);
 
 protected:
-  void GenerateScriptConfigs(std::ostream& os,
-                             Indent const& indent) CM_OVERRIDE;
-  void GenerateScriptActions(std::ostream& os,
-                             Indent const& indent) CM_OVERRIDE;
+  void GenerateScriptConfigs(std::ostream& os, Indent indent) CM_OVERRIDE;
+  void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
   void GenerateScriptForConfig(std::ostream& os, const std::string& config,
-                               Indent const& indent) CM_OVERRIDE;
-  void GenerateScriptNoConfig(std::ostream& os,
-                              Indent const& indent) CM_OVERRIDE;
+                               Indent indent) CM_OVERRIDE;
+  void GenerateScriptNoConfig(std::ostream& os, Indent indent) CM_OVERRIDE;
   bool NeedsScriptNoConfig() const CM_OVERRIDE;
-  void GenerateOldStyle(std::ostream& os, Indent const& indent);
+  void GenerateOldStyle(std::ostream& os, Indent indent);
 
   cmLocalGenerator* LG;
   cmTest* Test;
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 3d42e26..4b97188 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmTimestamp.h"
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 #include <cstring>
 #include <sstream>
 #include <stdlib.h>
diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h
index fdee564..8dd499a 100644
--- a/Source/cmTimestamp.h
+++ b/Source/cmTimestamp.h
@@ -3,7 +3,7 @@
 #ifndef cmTimestamp_h
 #define cmTimestamp_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <time.h>
diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h
index 52a0345..4836548 100644
--- a/Source/cmTryCompileCommand.h
+++ b/Source/cmTryCompileCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmTryCompileCommand_h
 #define cmTryCompileCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -31,11 +32,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "try_compile"; }
 };
 
 #endif
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index c4fc94e..07e20e6 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -2,7 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmTryRunCommand.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <stdio.h>
 #include <string.h>
 
diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h
index 8b44ac5..c27b026 100644
--- a/Source/cmTryRunCommand.h
+++ b/Source/cmTryRunCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmTryRunCommand_h
 #define cmTryRunCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -32,11 +33,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "try_run"; }
-
 private:
   void RunExecutable(const std::string& runArgs,
                      std::string* runOutputContents);
diff --git a/Source/cmUnexpectedCommand.h b/Source/cmUnexpectedCommand.h
index 897dfb6..995d8a5 100644
--- a/Source/cmUnexpectedCommand.h
+++ b/Source/cmUnexpectedCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmUnexpectedCommand_h
 #define cmUnexpectedCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -28,10 +29,6 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  std::string GetName() const CM_OVERRIDE { return this->Name; }
-
 private:
   std::string Name;
   const char* Error;
diff --git a/Source/cmUnsetCommand.h b/Source/cmUnsetCommand.h
index 5b07202..2a1f3f0 100644
--- a/Source/cmUnsetCommand.h
+++ b/Source/cmUnsetCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmUnsetCommand_h
 #define cmUnsetCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -30,16 +31,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "unset"; }
 };
 
 #endif
diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx
index 3e72d75..07095b1 100644
--- a/Source/cmUseMangledMesaCommand.cxx
+++ b/Source/cmUseMangledMesaCommand.cxx
@@ -2,10 +2,9 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmUseMangledMesaCommand.h"
 
-#include <cmsys/FStream.hxx>
-#include <cmsys/RegularExpression.hxx>
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
 
-#include "cmPolicies.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -13,11 +12,6 @@ class cmExecutionStatus;
 bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args,
                                           cmExecutionStatus&)
 {
-  if (this->Disallowed(
-        cmPolicies::CMP0030,
-        "The use_mangled_mesa command should not be called; see CMP0030.")) {
-    return true;
-  }
   // expected two arguments:
   // arguement one: the full path to gl_mangle.h
   // arguement two : directory for output of edited headers
diff --git a/Source/cmUseMangledMesaCommand.h b/Source/cmUseMangledMesaCommand.h
index 9a49f94..5118829 100644
--- a/Source/cmUseMangledMesaCommand.h
+++ b/Source/cmUseMangledMesaCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmUseMangledMesaCommand_h
 #define cmUseMangledMesaCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -17,8 +18,7 @@ public:
   cmCommand* Clone() CM_OVERRIDE { return new cmUseMangledMesaCommand; }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-  std::string GetName() const CM_OVERRIDE { return "use_mangled_mesa"; }
-  bool IsScriptable() const CM_OVERRIDE { return true; }
+
 protected:
   void CopyAndFullPathMesaHeader(const char* source, const char* outdir);
 };
diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx
index 3b78abe..eabd7ef 100644
--- a/Source/cmUtilitySourceCommand.cxx
+++ b/Source/cmUtilitySourceCommand.cxx
@@ -5,7 +5,6 @@
 #include <string.h>
 
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
@@ -16,11 +15,6 @@ class cmExecutionStatus;
 bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
                                          cmExecutionStatus&)
 {
-  if (this->Disallowed(
-        cmPolicies::CMP0034,
-        "The utility_source command should not be called; see CMP0034.")) {
-    return true;
-  }
   if (args.size() < 3) {
     this->SetError("called with incorrect number of arguments");
     return false;
@@ -29,7 +23,7 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
   std::vector<std::string>::const_iterator arg = args.begin();
 
   // The first argument is the cache entry name.
-  std::string cacheEntry = *arg++;
+  std::string const& cacheEntry = *arg++;
   const char* cacheValue = this->Makefile->GetDefinition(cacheEntry);
   // If it exists already and appears up to date then we are done.  If
   // the string contains "(IntDir)" but that is not the
@@ -63,11 +57,11 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
 
   // The second argument is the utility's executable name, which will be
   // needed later.
-  std::string utilityName = *arg++;
+  std::string const& utilityName = *arg++;
 
   // The third argument specifies the relative directory of the source
   // of the utility.
-  std::string relativeSource = *arg++;
+  std::string const& relativeSource = *arg++;
   std::string utilitySource = this->Makefile->GetCurrentSourceDirectory();
   utilitySource = utilitySource + "/" + relativeSource;
 
diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h
index 849b966..a95b48d 100644
--- a/Source/cmUtilitySourceCommand.h
+++ b/Source/cmUtilitySourceCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmUtilitySourceCommand_h
 #define cmUtilitySourceCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -17,7 +18,6 @@ public:
   cmCommand* Clone() CM_OVERRIDE { return new cmUtilitySourceCommand; }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-  std::string GetName() const CM_OVERRIDE { return "utility_source"; }
 };
 
 #endif
diff --git a/Source/cmUtils.hxx b/Source/cmUtils.hxx
index 3f65872..c5c767c 100644
--- a/Source/cmUtils.hxx
+++ b/Source/cmUtils.hxx
@@ -3,7 +3,7 @@
 #ifndef cmUtils_hxx
 #define cmUtils_hxx
 
-#include <cmsys/SystemTools.hxx>
+#include "cmsys/SystemTools.hxx"
 
 // Use the make system's VERBOSE environment variable to enable
 // verbose output. This can be skipped by also setting CMAKE_NO_VERBOSE
diff --git a/Source/cmUuid.h b/Source/cmUuid.h
index 1bc2229..158ce6e 100644
--- a/Source/cmUuid.h
+++ b/Source/cmUuid.h
@@ -3,7 +3,7 @@
 #ifndef cmUuid_h
 #define cmUuid_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/cmVS10CudaFlagTable.h b/Source/cmVS10CudaFlagTable.h
new file mode 100644
index 0000000..da19d64
--- /dev/null
+++ b/Source/cmVS10CudaFlagTable.h
@@ -0,0 +1,51 @@
+static cmVS7FlagTable cmVS10CudaFlagTable[] = {
+  // Collect options meant for the host compiler.
+  { "AdditionalCompilerOptions", "Xcompiler=", "Host compiler options", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SpaceAppendable },
+  { "AdditionalCompilerOptions", "Xcompiler", "Host compiler options", "",
+    cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SpaceAppendable },
+
+  // Select the CUDA runtime library.
+  { "CudaRuntime", "cudart=none", "No CUDA runtime library", "None", 0 },
+  { "CudaRuntime", "cudart=shared", "Shared/dynamic CUDA runtime library",
+    "Shared", 0 },
+  { "CudaRuntime", "cudart=static", "Static CUDA runtime library", "Static",
+    0 },
+  { "CudaRuntime", "cudart", "CUDA runtime library", "",
+    cmVS7FlagTable::UserFollowing },
+
+  // Capture arch/code arguments into temporaries for post-processing.
+  { "cmake-temp-gencode", "gencode=", "", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "cmake-temp-gencode", "gencode", "", "",
+    cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable },
+  { "cmake-temp-gencode", "-generate-code=", "", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "cmake-temp-gencode", "-generate-code", "", "",
+    cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable },
+
+  { "cmake-temp-code", "code=", "", "", cmVS7FlagTable::UserValue },
+  { "cmake-temp-code", "code", "", "", cmVS7FlagTable::UserFollowing },
+  { "cmake-temp-code", "-gpu-code=", "", "", cmVS7FlagTable::UserValue },
+  { "cmake-temp-code", "-gpu-code", "", "", cmVS7FlagTable::UserFollowing },
+
+  { "cmake-temp-arch", "arch=", "", "", cmVS7FlagTable::UserValue },
+  { "cmake-temp-arch", "arch", "", "", cmVS7FlagTable::UserFollowing },
+  { "cmake-temp-arch", "-gpu-architecture=", "", "",
+    cmVS7FlagTable::UserValue },
+  { "cmake-temp-arch", "-gpu-architecture", "", "",
+    cmVS7FlagTable::UserFollowing },
+
+  // Other flags.
+
+  { "FastMath", "use_fast_math", "", "true", 0 },
+  { "FastMath", "-use_fast_math", "", "true", 0 },
+
+  { "GPUDebugInfo", "G", "", "true", 0 },
+  { "GPUDebugInfo", "-device-debug", "", "true", 0 },
+
+  { "HostDebugInfo", "g", "", "true", 0 },
+  { "HostDebugInfo", "-debug", "", "true", 0 },
+
+  { 0, 0, 0, 0, 0 }
+};
diff --git a/Source/cmVS10CudaHostFlagTable.h b/Source/cmVS10CudaHostFlagTable.h
new file mode 100644
index 0000000..5b61066
--- /dev/null
+++ b/Source/cmVS10CudaHostFlagTable.h
@@ -0,0 +1,35 @@
+static cmVS7FlagTable cmVS10CudaHostFlagTable[] = {
+  //{"Optimization", "", "<inherit from host>", "InheritFromHost", 0},
+  { "Optimization", "Od", "Disabled", "Od", 0 },
+  { "Optimization", "O1", "Minimize Size", "O1", 0 },
+  { "Optimization", "O2", "Maximize Speed", "O2", 0 },
+  { "Optimization", "Ox", "Full Optimization", "O3", 0 },
+
+  //{"Runtime", "", "<inherit from host>", "InheritFromHost", 0},
+  { "Runtime", "MT", "Multi-Threaded", "MT", 0 },
+  { "Runtime", "MTd", "Multi-Threaded Debug", "MTd", 0 },
+  { "Runtime", "MD", "Multi-Threaded DLL", "MD", 0 },
+  { "Runtime", "MDd", "Multi-threaded Debug DLL", "MDd", 0 },
+  { "Runtime", "ML", "Single-Threaded", "ML", 0 },
+  { "Runtime", "MLd", "Single-Threaded Debug", "MLd", 0 },
+
+  //{"RuntimeChecks", "", "<inherit from host>", "InheritFromHost", 0},
+  //{"RuntimeChecks", "", "Default", "Default", 0},
+  { "RuntimeChecks", "RTCs", "Stack Frames", "RTCs", 0 },
+  { "RuntimeChecks", "RTCu", "Uninitialized Variables", "RTCu", 0 },
+  { "RuntimeChecks", "RTC1", "Both", "RTC1", 0 },
+
+  //{"TypeInfo", "", "<inherit from host>", "InheritFromHost", 0},
+  { "TypeInfo", "GR", "Yes", "true", 0 },
+  { "TypeInfo", "GR-", "No", "false", 0 },
+
+  //{"Warning", "", "<inherit from host>", "InheritFromHost", 0},
+  { "Warning", "W0", "Off: Turn Off All Warnings", "W0", 0 },
+  { "Warning", "W1", "Level 1", "W1", 0 },
+  { "Warning", "W2", "Level 2", "W2", 0 },
+  { "Warning", "W3", "Level 3", "W3", 0 },
+  { "Warning", "W4", "Level 4", "W4", 0 },
+  { "Warning", "Wall", "Enable All Warnings", "Wall", 0 },
+
+  { 0, 0, 0, 0, 0 }
+};
diff --git a/Source/cmVS10MASMFlagTable.h b/Source/cmVS10MASMFlagTable.h
index 82e5270..0a45245 100644
--- a/Source/cmVS10MASMFlagTable.h
+++ b/Source/cmVS10MASMFlagTable.h
@@ -2,74 +2,72 @@ static cmVS7FlagTable cmVS10MASMFlagTable[] = {
 
   // Enum Properties
   { "PreserveIdentifierCase", "", "Default", "0", 0 },
-  { "PreserveIdentifierCase", "/Cp", "Preserves Identifier Case (/Cp)", "1",
+  { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1",
     0 },
-  { "PreserveIdentifierCase", "/Cu",
+  { "PreserveIdentifierCase", "Cu",
     "Maps all identifiers to upper case. (/Cu)", "2", 0 },
-  { "PreserveIdentifierCase", "/Cx",
+  { "PreserveIdentifierCase", "Cx",
     "Preserves case in public and extern symbols. (/Cx)", "3", 0 },
 
-  { "WarningLevel", "/W0", "Warning Level 0 (/W0)", "0", 0 },
-  { "WarningLevel", "/W1", "Warning Level 1 (/W1)", "1", 0 },
-  { "WarningLevel", "/W2", "Warning Level 2 (/W2)", "2", 0 },
-  { "WarningLevel", "/W3", "Warning Level 3 (/W3)", "3", 0 },
+  { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 },
+  { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 },
+  { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 },
+  { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 },
 
   { "PackAlignmentBoundary", "", "Default", "0", 0 },
-  { "PackAlignmentBoundary", "/Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
-  { "PackAlignmentBoundary", "/Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
-  { "PackAlignmentBoundary", "/Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
-  { "PackAlignmentBoundary", "/Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
-  { "PackAlignmentBoundary", "/Zp16", "Sixteen Byte Boundary (/Zp16)", "5",
-    0 },
+  { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
+  { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
+  { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
+  { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
+  { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 },
 
   { "CallingConvention", "", "Default", "0", 0 },
-  { "CallingConvention", "/Gd", "Use C-style Calling Convention (/Gd)", "1",
-    0 },
-  { "CallingConvention", "/Gz", "Use stdcall Calling Convention (/Gz)", "2",
+  { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1",
     0 },
-  { "CallingConvention", "/Gc", "Use Pascal Calling Convention (/Gc)", "3",
+  { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2",
     0 },
+  { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 },
 
-  { "ErrorReporting", "/errorReport:prompt",
+  { "ErrorReporting", "errorReport:prompt",
     "Prompt to send report immediately (/errorReport:prompt)", "0", 0 },
-  { "ErrorReporting", "/errorReport:queue",
+  { "ErrorReporting", "errorReport:queue",
     "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 },
-  { "ErrorReporting", "/errorReport:send",
+  { "ErrorReporting", "errorReport:send",
     "Automatically send report (/errorReport:send)", "2", 0 },
-  { "ErrorReporting", "/errorReport:none",
+  { "ErrorReporting", "errorReport:none",
     "Do not send report (/errorReport:none)", "3", 0 },
 
   // Bool Properties
-  { "NoLogo", "/nologo", "", "true", 0 },
-  { "GeneratePreprocessedSourceListing", "/EP", "", "true", 0 },
-  { "ListAllAvailableInformation", "/Sa", "", "true", 0 },
-  { "UseSafeExceptionHandlers", "/safeseh", "", "true", 0 },
-  { "AddFirstPassListing", "/Sf", "", "true", 0 },
-  { "EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0 },
-  { "DisableSymbolTable", "/Sn", "", "true", 0 },
-  { "EnableFalseConditionalsInListing", "/Sx", "", "true", 0 },
-  { "TreatWarningsAsErrors", "/WX", "", "true", 0 },
-  { "MakeAllSymbolsPublic", "/Zf", "", "true", 0 },
-  { "GenerateDebugInformation", "/Zi", "", "true", 0 },
-  { "EnableMASM51Compatibility", "/Zm", "", "true", 0 },
-  { "PerformSyntaxCheckOnly", "/Zs", "", "true", 0 },
+  { "NoLogo", "nologo", "", "true", 0 },
+  { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 },
+  { "ListAllAvailableInformation", "Sa", "", "true", 0 },
+  { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 },
+  { "AddFirstPassListing", "Sf", "", "true", 0 },
+  { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 },
+  { "DisableSymbolTable", "Sn", "", "true", 0 },
+  { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 },
+  { "TreatWarningsAsErrors", "WX", "", "true", 0 },
+  { "MakeAllSymbolsPublic", "Zf", "", "true", 0 },
+  { "GenerateDebugInformation", "Zi", "", "true", 0 },
+  { "EnableMASM51Compatibility", "Zm", "", "true", 0 },
+  { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 },
 
   // Bool Properties With Argument
 
   // String List Properties
-  { "PreprocessorDefinitions", "/D", "Preprocessor Definitions", "",
+  { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "IncludePaths", "/I", "Include Paths", "",
+  { "IncludePaths", "I", "Include Paths", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "BrowseFile", "/FR", "Generate Browse Information File", "",
+  { "BrowseFile", "FR", "Generate Browse Information File", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
   // Skip [AdditionalDependencies] - no command line Switch.
 
   // String Properties
   // Skip [Inputs] - no command line Switch.
-  { "ObjectFileName", "/Fo", "Object File Name", "",
+  { "ObjectFileName", "Fo", "Object File Name", "",
     cmVS7FlagTable::UserValue },
-  { "AssembledCodeListingFile", "/Fl", "Assembled Code Listing File", "",
+  { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "",
     cmVS7FlagTable::UserValue },
   // Skip [CommandLineTemplate] - no command line Switch.
   // Skip [ExecutionDescription] - no command line Switch.
diff --git a/Source/cmVS10NASMFlagTable.h b/Source/cmVS10NASMFlagTable.h
new file mode 100644
index 0000000..b91af92
--- /dev/null
+++ b/Source/cmVS10NASMFlagTable.h
@@ -0,0 +1,50 @@
+static cmVS7FlagTable cmVS10NASMFlagTable[] = {
+
+  // Enum Properties
+  { "Outputswitch", "fwin32", "", "0", 0 },
+  { "Outputswitch", "fwin", "", "0", 0 },
+  { "Outputswitch", "fwin64", "", "1", 0 },
+  { "Outputswitch", "felf", "", "2", 0 },
+  { "Outputswitch", "felf32", "", "2", 0 },
+  { "Outputswitch", "felf64", "", "3", 0 },
+
+  { "ErrorReportingFormat", "Xgnu", "", "-Xgnu	GNU format: Default format",
+    0 },
+  { "ErrorReportingFormat", "Xvc", "",
+    "-Xvc	Style used by Microsoft Visual C++", 0 },
+
+  // Bool Properties
+  { "TreatWarningsAsErrors", "Werror", "", "true", 0 },
+  { "GenerateDebugInformation", "g", "", "true", 0 },
+  { "floatunderflow", "w+float-underflow", "", "true", 0 },
+  { "macrodefaults", "w-macro-defaults", "", "true", 0 },
+  { "user", "w-user", "%warning directives (default on)", "true", 0 },
+  { "floatoverflow", "w-float-overflow", "", "true", 0 },
+  { "floatdenorm", "w+float-denorm", "", "true", 0 },
+  { "numberoverflow", "w-number-overflow", "", "true", 0 },
+  { "macroselfref", "w+macro-selfref", "", "true", 0 },
+  { "floattoolong", "w-float-toolong", "", "true", 0 },
+  { "orphanlabels", "w-orphan-labels", "", "true", 0 },
+  { "tasmmode", "t", "", "true", 0 },
+
+  // Bool Properties With Argument
+
+  // String List Properties
+  { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "UndefinePreprocessorDefinitions", "U",
+    "Undefine Preprocessor Definitions", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "IncludePaths", "I", "Include Paths", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "AssembledCodeListingFile", "l",
+    "Generates an assembled code listing file.", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+
+  // String Properties
+  // Skip [Inputs] - no command line Switch.
+  // Skip [CommandLineTemplate] - no command line Switch.
+  // Skip [ExecutionDescription] - no command line Switch.
+  // Skip [AdditionalOptions] - no command line Switch.
+  { 0, 0, 0, 0, 0 }
+};
diff --git a/Source/cmVS10RCFlagTable.h b/Source/cmVS10RCFlagTable.h
index 32f35e5..6e2b834 100644
--- a/Source/cmVS10RCFlagTable.h
+++ b/Source/cmVS10RCFlagTable.h
@@ -1,6 +1,7 @@
 static cmVS7FlagTable cmVS10RCFlagTable[] = {
   // Bool Properties
   { "NullTerminateStrings", "n", "", "true", 0 },
+  { "SuppressStartupBanner", "nologo", "", "true", 0 },
 
   { 0, 0, 0, 0, 0 }
 };
diff --git a/Source/cmVS11MASMFlagTable.h b/Source/cmVS11MASMFlagTable.h
index 1aca169..fdf8239 100644
--- a/Source/cmVS11MASMFlagTable.h
+++ b/Source/cmVS11MASMFlagTable.h
@@ -2,74 +2,72 @@ static cmVS7FlagTable cmVS11MASMFlagTable[] = {
 
   // Enum Properties
   { "PreserveIdentifierCase", "", "Default", "0", 0 },
-  { "PreserveIdentifierCase", "/Cp", "Preserves Identifier Case (/Cp)", "1",
+  { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1",
     0 },
-  { "PreserveIdentifierCase", "/Cu",
+  { "PreserveIdentifierCase", "Cu",
     "Maps all identifiers to upper case. (/Cu)", "2", 0 },
-  { "PreserveIdentifierCase", "/Cx",
+  { "PreserveIdentifierCase", "Cx",
     "Preserves case in public and extern symbols. (/Cx)", "3", 0 },
 
-  { "WarningLevel", "/W0", "Warning Level 0 (/W0)", "0", 0 },
-  { "WarningLevel", "/W1", "Warning Level 1 (/W1)", "1", 0 },
-  { "WarningLevel", "/W2", "Warning Level 2 (/W2)", "2", 0 },
-  { "WarningLevel", "/W3", "Warning Level 3 (/W3)", "3", 0 },
+  { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 },
+  { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 },
+  { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 },
+  { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 },
 
   { "PackAlignmentBoundary", "", "Default", "0", 0 },
-  { "PackAlignmentBoundary", "/Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
-  { "PackAlignmentBoundary", "/Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
-  { "PackAlignmentBoundary", "/Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
-  { "PackAlignmentBoundary", "/Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
-  { "PackAlignmentBoundary", "/Zp16", "Sixteen Byte Boundary (/Zp16)", "5",
-    0 },
+  { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
+  { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
+  { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
+  { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
+  { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 },
 
   { "CallingConvention", "", "Default", "0", 0 },
-  { "CallingConvention", "/Gd", "Use C-style Calling Convention (/Gd)", "1",
-    0 },
-  { "CallingConvention", "/Gz", "Use stdcall Calling Convention (/Gz)", "2",
+  { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1",
     0 },
-  { "CallingConvention", "/Gc", "Use Pascal Calling Convention (/Gc)", "3",
+  { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2",
     0 },
+  { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 },
 
-  { "ErrorReporting", "/errorReport:prompt",
+  { "ErrorReporting", "errorReport:prompt",
     "Prompt to send report immediately (/errorReport:prompt)", "0", 0 },
-  { "ErrorReporting", "/errorReport:queue",
+  { "ErrorReporting", "errorReport:queue",
     "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 },
-  { "ErrorReporting", "/errorReport:send",
+  { "ErrorReporting", "errorReport:send",
     "Automatically send report (/errorReport:send)", "2", 0 },
-  { "ErrorReporting", "/errorReport:none",
+  { "ErrorReporting", "errorReport:none",
     "Do not send report (/errorReport:none)", "3", 0 },
 
   // Bool Properties
-  { "NoLogo", "/nologo", "", "true", 0 },
-  { "GeneratePreprocessedSourceListing", "/EP", "", "true", 0 },
-  { "ListAllAvailableInformation", "/Sa", "", "true", 0 },
-  { "UseSafeExceptionHandlers", "/safeseh", "", "true", 0 },
-  { "AddFirstPassListing", "/Sf", "", "true", 0 },
-  { "EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0 },
-  { "DisableSymbolTable", "/Sn", "", "true", 0 },
-  { "EnableFalseConditionalsInListing", "/Sx", "", "true", 0 },
-  { "TreatWarningsAsErrors", "/WX", "", "true", 0 },
-  { "MakeAllSymbolsPublic", "/Zf", "", "true", 0 },
-  { "GenerateDebugInformation", "/Zi", "", "true", 0 },
-  { "EnableMASM51Compatibility", "/Zm", "", "true", 0 },
-  { "PerformSyntaxCheckOnly", "/Zs", "", "true", 0 },
+  { "NoLogo", "nologo", "", "true", 0 },
+  { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 },
+  { "ListAllAvailableInformation", "Sa", "", "true", 0 },
+  { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 },
+  { "AddFirstPassListing", "Sf", "", "true", 0 },
+  { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 },
+  { "DisableSymbolTable", "Sn", "", "true", 0 },
+  { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 },
+  { "TreatWarningsAsErrors", "WX", "", "true", 0 },
+  { "MakeAllSymbolsPublic", "Zf", "", "true", 0 },
+  { "GenerateDebugInformation", "Zi", "", "true", 0 },
+  { "EnableMASM51Compatibility", "Zm", "", "true", 0 },
+  { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 },
 
   // Bool Properties With Argument
 
   // String List Properties
-  { "PreprocessorDefinitions", "/D", "Preprocessor Definitions", "",
+  { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "IncludePaths", "/I", "Include Paths", "",
+  { "IncludePaths", "I", "Include Paths", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "BrowseFile", "/FR", "Generate Browse Information File", "",
+  { "BrowseFile", "FR", "Generate Browse Information File", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
   // Skip [AdditionalDependencies] - no command line Switch.
 
   // String Properties
   // Skip [Inputs] - no command line Switch.
-  { "ObjectFileName", "/Fo", "Object File Name", "",
+  { "ObjectFileName", "Fo", "Object File Name", "",
     cmVS7FlagTable::UserValue },
-  { "AssembledCodeListingFile", "/Fl", "Assembled Code Listing File", "",
+  { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "",
     cmVS7FlagTable::UserValue },
   // Skip [CommandLineTemplate] - no command line Switch.
   // Skip [ExecutionDescription] - no command line Switch.
diff --git a/Source/cmVS11RCFlagTable.h b/Source/cmVS11RCFlagTable.h
index 666e434..4997fe1 100644
--- a/Source/cmVS11RCFlagTable.h
+++ b/Source/cmVS11RCFlagTable.h
@@ -1,6 +1,7 @@
 static cmVS7FlagTable cmVS11RCFlagTable[] = {
   // Bool Properties
   { "NullTerminateStrings", "n", "", "true", 0 },
+  { "SuppressStartupBanner", "nologo", "", "true", 0 },
 
   { 0, 0, 0, 0, 0 }
 };
diff --git a/Source/cmVS12MASMFlagTable.h b/Source/cmVS12MASMFlagTable.h
index a7e4a80..acc0d48 100644
--- a/Source/cmVS12MASMFlagTable.h
+++ b/Source/cmVS12MASMFlagTable.h
@@ -2,74 +2,72 @@ static cmVS7FlagTable cmVS12MASMFlagTable[] = {
 
   // Enum Properties
   { "PreserveIdentifierCase", "", "Default", "0", 0 },
-  { "PreserveIdentifierCase", "/Cp", "Preserves Identifier Case (/Cp)", "1",
+  { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1",
     0 },
-  { "PreserveIdentifierCase", "/Cu",
+  { "PreserveIdentifierCase", "Cu",
     "Maps all identifiers to upper case. (/Cu)", "2", 0 },
-  { "PreserveIdentifierCase", "/Cx",
+  { "PreserveIdentifierCase", "Cx",
     "Preserves case in public and extern symbols. (/Cx)", "3", 0 },
 
-  { "WarningLevel", "/W0", "Warning Level 0 (/W0)", "0", 0 },
-  { "WarningLevel", "/W1", "Warning Level 1 (/W1)", "1", 0 },
-  { "WarningLevel", "/W2", "Warning Level 2 (/W2)", "2", 0 },
-  { "WarningLevel", "/W3", "Warning Level 3 (/W3)", "3", 0 },
+  { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 },
+  { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 },
+  { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 },
+  { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 },
 
   { "PackAlignmentBoundary", "", "Default", "0", 0 },
-  { "PackAlignmentBoundary", "/Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
-  { "PackAlignmentBoundary", "/Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
-  { "PackAlignmentBoundary", "/Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
-  { "PackAlignmentBoundary", "/Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
-  { "PackAlignmentBoundary", "/Zp16", "Sixteen Byte Boundary (/Zp16)", "5",
-    0 },
+  { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
+  { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
+  { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
+  { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
+  { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 },
 
   { "CallingConvention", "", "Default", "0", 0 },
-  { "CallingConvention", "/Gd", "Use C-style Calling Convention (/Gd)", "1",
-    0 },
-  { "CallingConvention", "/Gz", "Use stdcall Calling Convention (/Gz)", "2",
+  { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1",
     0 },
-  { "CallingConvention", "/Gc", "Use Pascal Calling Convention (/Gc)", "3",
+  { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2",
     0 },
+  { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 },
 
-  { "ErrorReporting", "/errorReport:prompt",
+  { "ErrorReporting", "errorReport:prompt",
     "Prompt to send report immediately (/errorReport:prompt)", "0", 0 },
-  { "ErrorReporting", "/errorReport:queue",
+  { "ErrorReporting", "errorReport:queue",
     "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 },
-  { "ErrorReporting", "/errorReport:send",
+  { "ErrorReporting", "errorReport:send",
     "Automatically send report (/errorReport:send)", "2", 0 },
-  { "ErrorReporting", "/errorReport:none",
+  { "ErrorReporting", "errorReport:none",
     "Do not send report (/errorReport:none)", "3", 0 },
 
   // Bool Properties
-  { "NoLogo", "/nologo", "", "true", 0 },
-  { "GeneratePreprocessedSourceListing", "/EP", "", "true", 0 },
-  { "ListAllAvailableInformation", "/Sa", "", "true", 0 },
-  { "UseSafeExceptionHandlers", "/safeseh", "", "true", 0 },
-  { "AddFirstPassListing", "/Sf", "", "true", 0 },
-  { "EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0 },
-  { "DisableSymbolTable", "/Sn", "", "true", 0 },
-  { "EnableFalseConditionalsInListing", "/Sx", "", "true", 0 },
-  { "TreatWarningsAsErrors", "/WX", "", "true", 0 },
-  { "MakeAllSymbolsPublic", "/Zf", "", "true", 0 },
-  { "GenerateDebugInformation", "/Zi", "", "true", 0 },
-  { "EnableMASM51Compatibility", "/Zm", "", "true", 0 },
-  { "PerformSyntaxCheckOnly", "/Zs", "", "true", 0 },
+  { "NoLogo", "nologo", "", "true", 0 },
+  { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 },
+  { "ListAllAvailableInformation", "Sa", "", "true", 0 },
+  { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 },
+  { "AddFirstPassListing", "Sf", "", "true", 0 },
+  { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 },
+  { "DisableSymbolTable", "Sn", "", "true", 0 },
+  { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 },
+  { "TreatWarningsAsErrors", "WX", "", "true", 0 },
+  { "MakeAllSymbolsPublic", "Zf", "", "true", 0 },
+  { "GenerateDebugInformation", "Zi", "", "true", 0 },
+  { "EnableMASM51Compatibility", "Zm", "", "true", 0 },
+  { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 },
 
   // Bool Properties With Argument
 
   // String List Properties
-  { "PreprocessorDefinitions", "/D", "Preprocessor Definitions", "",
+  { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "IncludePaths", "/I", "Include Paths", "",
+  { "IncludePaths", "I", "Include Paths", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "BrowseFile", "/FR", "Generate Browse Information File", "",
+  { "BrowseFile", "FR", "Generate Browse Information File", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
   // Skip [AdditionalDependencies] - no command line Switch.
 
   // String Properties
   // Skip [Inputs] - no command line Switch.
-  { "ObjectFileName", "/Fo", "Object File Name", "",
+  { "ObjectFileName", "Fo", "Object File Name", "",
     cmVS7FlagTable::UserValue },
-  { "AssembledCodeListingFile", "/Fl", "Assembled Code Listing File", "",
+  { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "",
     cmVS7FlagTable::UserValue },
   // Skip [CommandLineTemplate] - no command line Switch.
   // Skip [ExecutionDescription] - no command line Switch.
diff --git a/Source/cmVS12RCFlagTable.h b/Source/cmVS12RCFlagTable.h
index d047f82..a650f85 100644
--- a/Source/cmVS12RCFlagTable.h
+++ b/Source/cmVS12RCFlagTable.h
@@ -1,6 +1,7 @@
 static cmVS7FlagTable cmVS12RCFlagTable[] = {
   // Bool Properties
   { "NullTerminateStrings", "n", "", "true", 0 },
+  { "SuppressStartupBanner", "nologo", "", "true", 0 },
 
   { 0, 0, 0, 0, 0 }
 };
diff --git a/Source/cmVS140LinkFlagTable.h b/Source/cmVS140LinkFlagTable.h
new file mode 100644
index 0000000..b9a4dc3
--- /dev/null
+++ b/Source/cmVS140LinkFlagTable.h
@@ -0,0 +1,282 @@
+static cmVS7FlagTable cmVS140LinkFlagTable[] = {
+
+  // Enum Properties
+  { "ShowProgress", "", "Not Set", "NotSet", 0 },
+  { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose",
+    0 },
+  { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib",
+    0 },
+  { "ShowProgress", "VERBOSE:ICF",
+    "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 },
+  { "ShowProgress", "VERBOSE:REF",
+    "About data removed during optimized linking", "LinkVerboseREF", 0 },
+  { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH",
+    "LinkVerboseSAFESEH", 0 },
+  { "ShowProgress", "VERBOSE:CLR",
+    "About linker activity related to managed code", "LinkVerboseCLR", 0 },
+
+  { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 },
+  { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only",
+    "MultiplyDefinedSymbolOnly", 0 },
+  { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only",
+    "UndefinedSymbolOnly", 0 },
+
+  { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 },
+  { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only",
+    "X86Image", 0 },
+  { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only",
+    "X64Image", 0 },
+  { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only",
+    "ItaniumImage", 0 },
+
+  { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 },
+  { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable",
+    "HighestAvailable", 0 },
+  { "UACExecutionLevel", "level='requireAdministrator'",
+    "requireAdministrator", "RequireAdministrator", 0 },
+
+  { "GenerateDebugInformation", "DEBUG:FASTLINK",
+    "Optimize for faster linking", "DebugFastLink",
+    cmVS7FlagTable::CaseInsensitive },
+  { "GenerateDebugInformation", "DEBUG:FULL", "Optimize for debugging", "true",
+    cmVS7FlagTable::CaseInsensitive },
+  { "GenerateDebugInformation", "DEBUG:NONE",
+    "Produces no debugging information", "false",
+    cmVS7FlagTable::CaseInsensitive },
+  { "GenerateDebugInformation", "DEBUG", "Optimize for debugging", "true",
+    cmVS7FlagTable::CaseInsensitive },
+
+  { "SubSystem", "", "Not Set", "NotSet", 0 },
+  { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
+  { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
+  { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
+  { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
+    "EFI Application", 0 },
+  { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
+    "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
+  { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
+  { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
+    0 },
+  { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
+
+  { "Driver", "", "Not Set", "NotSet", 0 },
+  { "Driver", "Driver", "Driver", "Driver", 0 },
+  { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 },
+  { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 },
+
+  { "LinkTimeCodeGeneration", "", "Default", "Default", 0 },
+  { "LinkTimeCodeGeneration", "LTCG:incremental",
+    "Use Fast Link Time Code Generation", "UseFastLinkTimeCodeGeneration", 0 },
+  { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation",
+    "UseLinkTimeCodeGeneration", 0 },
+  { "LinkTimeCodeGeneration", "LTCG:PGInstrument",
+    "Profile Guided Optimization - Instrument", "PGInstrument", 0 },
+  { "LinkTimeCodeGeneration", "LTCG:PGOptimize",
+    "Profile Guided Optimization - Optimization", "PGOptimization", 0 },
+  { "LinkTimeCodeGeneration", "LTCG:PGUpdate",
+    "Profile Guided Optimization - Update", "PGUpdate", 0 },
+
+  { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 },
+  { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 },
+
+  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
+  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
+  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
+  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
+
+  { "TargetMachine", "", "Not Set", "NotSet", 0 },
+  { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
+  { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
+  { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
+  { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
+  { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
+  { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
+    0 },
+  { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
+    "MachineMIPSFPU16", 0 },
+  { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
+  { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
+  { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
+  { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
+
+  { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute",
+    "MTAThreadingAttribute", 0 },
+  { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute",
+    "STAThreadingAttribute", 0 },
+  { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE",
+    "Default threading attribute", "DefaultThreadingAttribute", 0 },
+
+  { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage",
+    0 },
+  { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image",
+    "ForcePureILImage", 0 },
+  { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image",
+    "ForceSafeILImage", 0 },
+  { "CLRImageType", "", "Default image type", "Default", 0 },
+
+  { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
+  { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
+  { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
+  { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
+
+  { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
+    "PromptImmediately", 0 },
+  { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
+    "QueueForNextLogin", 0 },
+  { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
+    "SendErrorReport", 0 },
+  { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report",
+    "NoErrorReport", 0 },
+
+  { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 },
+  { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled",
+    0 },
+  { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only",
+    "SystemDlls", 0 },
+
+  // Bool Properties
+  { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 },
+  { "LinkIncremental", "INCREMENTAL", "", "true", 0 },
+  { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
+  { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 },
+  { "LinkStatus", "LTCG:STATUS", "", "true", 0 },
+  { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 },
+  { "PreventDllBinding", "ALLOWBIND", "", "true", 0 },
+  { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 },
+  { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 },
+  { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
+  { "GenerateManifest", "MANIFEST:NO", "", "false", 0 },
+  { "GenerateManifest", "MANIFEST", "", "true", 0 },
+  { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 },
+  { "UACUIAccess", "uiAccess='false'", "", "false", 0 },
+  { "UACUIAccess", "uiAccess='true'", "", "true", 0 },
+  { "ManifestEmbed", "manifest:embed", "", "true", 0 },
+  { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 },
+  { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 },
+  { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 },
+  { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 },
+  { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 },
+  { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 },
+  { "TerminalServerAware", "TSAWARE", "", "true", 0 },
+  { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 },
+  { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 },
+  { "OptimizeReferences", "OPT:NOREF", "", "false", 0 },
+  { "OptimizeReferences", "OPT:REF", "", "true", 0 },
+  { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 },
+  { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 },
+  { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 },
+  { "AppContainer", "APPCONTAINER", "", "true", 0 },
+  { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 },
+  { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 },
+  { "NoEntryPoint", "NOENTRY", "", "true", 0 },
+  { "SetChecksum", "RELEASE", "", "true", 0 },
+  { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 },
+  { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 },
+  { "FixedBaseAddress", "FIXED:NO", "", "false", 0 },
+  { "FixedBaseAddress", "FIXED", "", "true", 0 },
+  { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 },
+  { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 },
+  { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 },
+  { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 },
+  { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 },
+  { "Profile", "PROFILE", "", "true", 0 },
+  { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 },
+  { "LinkDelaySign", "DELAYSIGN", "", "true", 0 },
+  { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 },
+  { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 },
+  { "DetectOneDefinitionRule", "ODR", "", "true", 0 },
+  { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 },
+  { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 },
+  { "LinkDLL", "DLL", "", "true", 0 },
+
+  // Bool Properties With Argument
+  { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 },
+  { "EnableUAC", "MANIFESTUAC:", "", "true",
+    cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
+  { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "",
+    cmVS7FlagTable::UserValueRequired },
+  { "GenerateMapFile", "MAP", "", "true",
+    cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
+  { "MapFileName", "MAP:", "Generate Map File", "",
+    cmVS7FlagTable::UserValueRequired },
+
+  // String List Properties
+  { "AdditionalLibraryDirectories", "LIBPATH:",
+    "Additional Library Directories", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "Natvis", "NATVIS:", "Natvis files", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  // Skip [AdditionalDependencies] - no command line Switch.
+  { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
+    "Ignore Specific Default Libraries", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
+    "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
+    "Embed Managed Resource File", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
+    "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
+    "Additional Manifest Dependencies", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "ManifestInput", "manifestinput:", "Manifest Input", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+
+  // String Properties
+  { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
+  { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue },
+  { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "",
+    cmVS7FlagTable::UserValue },
+  { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [TrackerLogDirectory] - no command line Switch.
+  { "ModuleDefinitionFile", "DEF:", "Module Definition File", "",
+    cmVS7FlagTable::UserValue },
+  { "ManifestFile", "ManifestFile:", "Manifest File", "",
+    cmVS7FlagTable::UserValue },
+  { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "",
+    cmVS7FlagTable::UserValue },
+  { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [MapFileName] - no command line Switch.
+  // Skip [MinimumRequiredVersion] - no command line Switch.
+  { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [HeapCommitSize] - no command line Switch.
+  { "StackReserveSize", "STACK:", "Stack Reserve Size", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [StackCommitSize] - no command line Switch.
+  { "FunctionOrder", "ORDER:@", "Function Order", "",
+    cmVS7FlagTable::UserValue },
+  { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "",
+    cmVS7FlagTable::UserValue },
+  { "MidlCommandFile", "MIDL:@", "MIDL Commands", "",
+    cmVS7FlagTable::UserValue },
+  { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "",
+    cmVS7FlagTable::UserValue },
+  { "TypeLibraryFile", "TLBOUT:", "Type Library", "",
+    cmVS7FlagTable::UserValue },
+  { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "",
+    cmVS7FlagTable::UserValue },
+  { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File",
+    "", cmVS7FlagTable::UserValue },
+  { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:",
+    "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue },
+  { "EntryPointSymbol", "ENTRY:", "Entry Point", "",
+    cmVS7FlagTable::UserValue },
+  { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue },
+  { "ImportLibrary", "IMPLIB:", "Import Library", "",
+    cmVS7FlagTable::UserValue },
+  { "MergeSections", "MERGE:", "Merge Sections", "",
+    cmVS7FlagTable::UserValue },
+  { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue },
+  { "KeyContainer", "KEYCONTAINER:", "Key Container", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [AdditionalOptions] - no command line Switch.
+  { 0, 0, 0, 0, 0 }
+};
diff --git a/Source/cmVS141LinkFlagTable.h b/Source/cmVS141LinkFlagTable.h
new file mode 100644
index 0000000..8f0f1f4
--- /dev/null
+++ b/Source/cmVS141LinkFlagTable.h
@@ -0,0 +1,283 @@
+static cmVS7FlagTable cmVS141LinkFlagTable[] = {
+
+  // Enum Properties
+  { "ShowProgress", "", "Not Set", "NotSet", 0 },
+  { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose",
+    0 },
+  { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib",
+    0 },
+  { "ShowProgress", "VERBOSE:ICF",
+    "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 },
+  { "ShowProgress", "VERBOSE:REF",
+    "About data removed during optimized linking", "LinkVerboseREF", 0 },
+  { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH",
+    "LinkVerboseSAFESEH", 0 },
+  { "ShowProgress", "VERBOSE:CLR",
+    "About linker activity related to managed code", "LinkVerboseCLR", 0 },
+
+  { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 },
+  { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only",
+    "MultiplyDefinedSymbolOnly", 0 },
+  { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only",
+    "UndefinedSymbolOnly", 0 },
+
+  { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 },
+  { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only",
+    "X86Image", 0 },
+  { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only",
+    "X64Image", 0 },
+  { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only",
+    "ItaniumImage", 0 },
+
+  { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 },
+  { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable",
+    "HighestAvailable", 0 },
+  { "UACExecutionLevel", "level='requireAdministrator'",
+    "requireAdministrator", "RequireAdministrator", 0 },
+
+  { "GenerateDebugInformation", "DEBUG:FASTLINK",
+    "Generate Debug Information optimized for faster links", "DebugFastLink",
+    cmVS7FlagTable::CaseInsensitive },
+  { "GenerateDebugInformation", "DEBUG:FULL",
+    "Generate Debug Information optimized for sharing and publishing",
+    "DebugFull", cmVS7FlagTable::CaseInsensitive },
+  { "GenerateDebugInformation", "DEBUG:NONE",
+    "Produces no debugging information", "false",
+    cmVS7FlagTable::CaseInsensitive },
+  { "GenerateDebugInformation", "DEBUG", "Generate Debug Information", "true",
+    cmVS7FlagTable::CaseInsensitive },
+
+  { "SubSystem", "", "Not Set", "NotSet", 0 },
+  { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
+  { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
+  { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
+  { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
+    "EFI Application", 0 },
+  { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
+    "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
+  { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
+  { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
+    0 },
+  { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
+
+  { "Driver", "", "Not Set", "NotSet", 0 },
+  { "Driver", "Driver", "Driver", "Driver", 0 },
+  { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 },
+  { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 },
+
+  { "LinkTimeCodeGeneration", "", "Default", "Default", 0 },
+  { "LinkTimeCodeGeneration", "LTCG:incremental",
+    "Use Fast Link Time Code Generation", "UseFastLinkTimeCodeGeneration", 0 },
+  { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation",
+    "UseLinkTimeCodeGeneration", 0 },
+  { "LinkTimeCodeGeneration", "LTCG:PGInstrument",
+    "Profile Guided Optimization - Instrument", "PGInstrument", 0 },
+  { "LinkTimeCodeGeneration", "LTCG:PGOptimize",
+    "Profile Guided Optimization - Optimization", "PGOptimization", 0 },
+  { "LinkTimeCodeGeneration", "LTCG:PGUpdate",
+    "Profile Guided Optimization - Update", "PGUpdate", 0 },
+
+  { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 },
+  { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 },
+
+  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
+  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
+  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
+  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
+
+  { "TargetMachine", "", "Not Set", "NotSet", 0 },
+  { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
+  { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
+  { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
+  { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
+  { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
+  { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
+    0 },
+  { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
+    "MachineMIPSFPU16", 0 },
+  { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
+  { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
+  { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
+  { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
+
+  { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute",
+    "MTAThreadingAttribute", 0 },
+  { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute",
+    "STAThreadingAttribute", 0 },
+  { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE",
+    "Default threading attribute", "DefaultThreadingAttribute", 0 },
+
+  { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage",
+    0 },
+  { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image",
+    "ForcePureILImage", 0 },
+  { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image",
+    "ForceSafeILImage", 0 },
+  { "CLRImageType", "", "Default image type", "Default", 0 },
+
+  { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
+  { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
+  { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
+  { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
+
+  { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
+    "PromptImmediately", 0 },
+  { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
+    "QueueForNextLogin", 0 },
+  { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
+    "SendErrorReport", 0 },
+  { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report",
+    "NoErrorReport", 0 },
+
+  { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 },
+  { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled",
+    0 },
+  { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only",
+    "SystemDlls", 0 },
+
+  // Bool Properties
+  { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 },
+  { "LinkIncremental", "INCREMENTAL", "", "true", 0 },
+  { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
+  { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 },
+  { "LinkStatus", "LTCG:STATUS", "", "true", 0 },
+  { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 },
+  { "PreventDllBinding", "ALLOWBIND", "", "true", 0 },
+  { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 },
+  { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 },
+  { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
+  { "GenerateManifest", "MANIFEST:NO", "", "false", 0 },
+  { "GenerateManifest", "MANIFEST", "", "true", 0 },
+  { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 },
+  { "UACUIAccess", "uiAccess='false'", "", "false", 0 },
+  { "UACUIAccess", "uiAccess='true'", "", "true", 0 },
+  { "ManifestEmbed", "manifest:embed", "", "true", 0 },
+  { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 },
+  { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 },
+  { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 },
+  { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 },
+  { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 },
+  { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 },
+  { "TerminalServerAware", "TSAWARE", "", "true", 0 },
+  { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 },
+  { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 },
+  { "OptimizeReferences", "OPT:NOREF", "", "false", 0 },
+  { "OptimizeReferences", "OPT:REF", "", "true", 0 },
+  { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 },
+  { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 },
+  { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 },
+  { "AppContainer", "APPCONTAINER", "", "true", 0 },
+  { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 },
+  { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 },
+  { "NoEntryPoint", "NOENTRY", "", "true", 0 },
+  { "SetChecksum", "RELEASE", "", "true", 0 },
+  { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 },
+  { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 },
+  { "FixedBaseAddress", "FIXED:NO", "", "false", 0 },
+  { "FixedBaseAddress", "FIXED", "", "true", 0 },
+  { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 },
+  { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 },
+  { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 },
+  { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 },
+  { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 },
+  { "Profile", "PROFILE", "", "true", 0 },
+  { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 },
+  { "LinkDelaySign", "DELAYSIGN", "", "true", 0 },
+  { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 },
+  { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 },
+  { "DetectOneDefinitionRule", "ODR", "", "true", 0 },
+  { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 },
+  { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 },
+  { "LinkDLL", "DLL", "", "true", 0 },
+
+  // Bool Properties With Argument
+  { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 },
+  { "EnableUAC", "MANIFESTUAC:", "", "true",
+    cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
+  { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "",
+    cmVS7FlagTable::UserValueRequired },
+  { "GenerateMapFile", "MAP", "", "true",
+    cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
+  { "MapFileName", "MAP:", "Generate Map File", "",
+    cmVS7FlagTable::UserValueRequired },
+
+  // String List Properties
+  { "AdditionalLibraryDirectories", "LIBPATH:",
+    "Additional Library Directories", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "Natvis", "NATVIS:", "Natvis files", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  // Skip [AdditionalDependencies] - no command line Switch.
+  { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
+    "Ignore Specific Default Libraries", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
+    "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
+    "Embed Managed Resource File", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
+    "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
+    "Additional Manifest Dependencies", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "ManifestInput", "manifestinput:", "Manifest Input", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+
+  // String Properties
+  { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
+  { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue },
+  { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "",
+    cmVS7FlagTable::UserValue },
+  { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [TrackerLogDirectory] - no command line Switch.
+  { "ModuleDefinitionFile", "DEF:", "Module Definition File", "",
+    cmVS7FlagTable::UserValue },
+  { "ManifestFile", "ManifestFile:", "Manifest File", "",
+    cmVS7FlagTable::UserValue },
+  { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "",
+    cmVS7FlagTable::UserValue },
+  { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [MapFileName] - no command line Switch.
+  // Skip [MinimumRequiredVersion] - no command line Switch.
+  { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [HeapCommitSize] - no command line Switch.
+  { "StackReserveSize", "STACK:", "Stack Reserve Size", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [StackCommitSize] - no command line Switch.
+  { "FunctionOrder", "ORDER:@", "Function Order", "",
+    cmVS7FlagTable::UserValue },
+  { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "",
+    cmVS7FlagTable::UserValue },
+  { "MidlCommandFile", "MIDL:@", "MIDL Commands", "",
+    cmVS7FlagTable::UserValue },
+  { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "",
+    cmVS7FlagTable::UserValue },
+  { "TypeLibraryFile", "TLBOUT:", "Type Library", "",
+    cmVS7FlagTable::UserValue },
+  { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "",
+    cmVS7FlagTable::UserValue },
+  { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File",
+    "", cmVS7FlagTable::UserValue },
+  { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:",
+    "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue },
+  { "EntryPointSymbol", "ENTRY:", "Entry Point", "",
+    cmVS7FlagTable::UserValue },
+  { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue },
+  { "ImportLibrary", "IMPLIB:", "Import Library", "",
+    cmVS7FlagTable::UserValue },
+  { "MergeSections", "MERGE:", "Merge Sections", "",
+    cmVS7FlagTable::UserValue },
+  { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue },
+  { "KeyContainer", "KEYCONTAINER:", "Key Container", "",
+    cmVS7FlagTable::UserValue },
+  // Skip [AdditionalOptions] - no command line Switch.
+  { 0, 0, 0, 0, 0 }
+};
diff --git a/Source/cmVS14LinkFlagTable.h b/Source/cmVS14LinkFlagTable.h
deleted file mode 100644
index 596f880..0000000
--- a/Source/cmVS14LinkFlagTable.h
+++ /dev/null
@@ -1,280 +0,0 @@
-static cmVS7FlagTable cmVS14LinkFlagTable[] = {
-
-  // Enum Properties
-  { "ShowProgress", "", "Not Set", "NotSet", 0 },
-  { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose",
-    0 },
-  { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib",
-    0 },
-  { "ShowProgress", "VERBOSE:ICF",
-    "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 },
-  { "ShowProgress", "VERBOSE:REF",
-    "About data removed during optimized linking", "LinkVerboseREF", 0 },
-  { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH",
-    "LinkVerboseSAFESEH", 0 },
-  { "ShowProgress", "VERBOSE:CLR",
-    "About linker activity related to managed code", "LinkVerboseCLR", 0 },
-
-  { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 },
-  { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only",
-    "MultiplyDefinedSymbolOnly", 0 },
-  { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only",
-    "UndefinedSymbolOnly", 0 },
-
-  { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 },
-  { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only",
-    "X86Image", 0 },
-  { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only",
-    "X64Image", 0 },
-  { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only",
-    "ItaniumImage", 0 },
-
-  { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 },
-  { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable",
-    "HighestAvailable", 0 },
-  { "UACExecutionLevel", "level='requireAdministrator'",
-    "requireAdministrator", "RequireAdministrator", 0 },
-
-  { "GenerateDebugInformation", "DEBUG:FASTLINK",
-    "Optimize for faster linking", "DebugFastLink",
-    cmVS7FlagTable::CaseInsensitive },
-  { "GenerateDebugInformation", "DEBUG", "Optimize for debugging", "Debug",
-    cmVS7FlagTable::CaseInsensitive },
-
-  { "SubSystem", "", "Not Set", "NotSet", 0 },
-  { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
-  { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
-  { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
-  { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
-    "EFI Application", 0 },
-  { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
-    "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
-  { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
-  { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
-    0 },
-  { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
-  { "Driver", "", "Not Set", "NotSet", 0 },
-  { "Driver", "Driver", "Driver", "Driver", 0 },
-  { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 },
-  { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 },
-
-  { "LinkTimeCodeGeneration", "", "Default", "Default", 0 },
-  { "LinkTimeCodeGeneration", "LTCG:incremental",
-    "Use Fast Link Time Code Generation", "UseFastLinkTimeCodeGeneration", 0 },
-  { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation",
-    "UseLinkTimeCodeGeneration", 0 },
-  { "LinkTimeCodeGeneration", "LTCG:PGInstrument",
-    "Profile Guided Optimization - Instrument", "PGInstrument", 0 },
-  { "LinkTimeCodeGeneration", "LTCG:PGOptimize",
-    "Profile Guided Optimization - Optimization", "PGOptimization", 0 },
-  { "LinkTimeCodeGeneration", "LTCG:PGUpdate",
-    "Profile Guided Optimization - Update", "PGUpdate", 0 },
-
-  { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 },
-  { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 },
-
-  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
-  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
-  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
-  { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
-  { "TargetMachine", "", "Not Set", "NotSet", 0 },
-  { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
-  { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
-  { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
-  { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
-  { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
-  { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
-    0 },
-  { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
-    "MachineMIPSFPU16", 0 },
-  { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
-  { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
-  { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
-  { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
-  { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute",
-    "MTAThreadingAttribute", 0 },
-  { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute",
-    "STAThreadingAttribute", 0 },
-  { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE",
-    "Default threading attribute", "DefaultThreadingAttribute", 0 },
-
-  { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage",
-    0 },
-  { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image",
-    "ForcePureILImage", 0 },
-  { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image",
-    "ForceSafeILImage", 0 },
-  { "CLRImageType", "", "Default image type", "Default", 0 },
-
-  { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
-  { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
-  { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
-  { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
-  { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
-    "PromptImmediately", 0 },
-  { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
-    "QueueForNextLogin", 0 },
-  { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
-    "SendErrorReport", 0 },
-  { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report",
-    "NoErrorReport", 0 },
-
-  { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 },
-  { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled",
-    0 },
-  { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only",
-    "SystemDlls", 0 },
-
-  { "LinkControlFlowGuard", "guard:cf", "Enable Security Check with Guard",
-    "Guard", 0 },
-
-  // Bool Properties
-  { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 },
-  { "LinkIncremental", "INCREMENTAL", "", "true", 0 },
-  { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
-  { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 },
-  { "LinkStatus", "LTCG:STATUS", "", "true", 0 },
-  { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 },
-  { "PreventDllBinding", "ALLOWBIND", "", "true", 0 },
-  { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 },
-  { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 },
-  { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
-  { "GenerateManifest", "MANIFEST:NO", "", "false", 0 },
-  { "GenerateManifest", "MANIFEST", "", "true", 0 },
-  { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 },
-  { "UACUIAccess", "uiAccess='false'", "", "false", 0 },
-  { "UACUIAccess", "uiAccess='true'", "", "true", 0 },
-  { "ManifestEmbed", "manifest:embed", "", "true", 0 },
-  { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 },
-  { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 },
-  { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 },
-  { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 },
-  { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 },
-  { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 },
-  { "TerminalServerAware", "TSAWARE", "", "true", 0 },
-  { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 },
-  { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 },
-  { "OptimizeReferences", "OPT:NOREF", "", "false", 0 },
-  { "OptimizeReferences", "OPT:REF", "", "true", 0 },
-  { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 },
-  { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 },
-  { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 },
-  { "AppContainer", "APPCONTAINER", "", "true", 0 },
-  { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 },
-  { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 },
-  { "NoEntryPoint", "NOENTRY", "", "true", 0 },
-  { "SetChecksum", "RELEASE", "", "true", 0 },
-  { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 },
-  { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 },
-  { "FixedBaseAddress", "FIXED:NO", "", "false", 0 },
-  { "FixedBaseAddress", "FIXED", "", "true", 0 },
-  { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 },
-  { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 },
-  { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 },
-  { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 },
-  { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 },
-  { "Profile", "PROFILE", "", "true", 0 },
-  { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 },
-  { "LinkDelaySign", "DELAYSIGN", "", "true", 0 },
-  { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 },
-  { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 },
-  { "DetectOneDefinitionRule", "ODR", "", "true", 0 },
-  { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 },
-  { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 },
-  { "LinkDLL", "DLL", "", "true", 0 },
-
-  // Bool Properties With Argument
-  { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 },
-  { "EnableUAC", "MANIFESTUAC:", "", "true",
-    cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
-  { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "",
-    cmVS7FlagTable::UserValueRequired },
-  { "GenerateMapFile", "MAP", "", "true",
-    cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
-  { "MapFileName", "MAP:", "Generate Map File", "",
-    cmVS7FlagTable::UserValueRequired },
-
-  // String List Properties
-  { "AdditionalLibraryDirectories", "LIBPATH:",
-    "Additional Library Directories", "",
-    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "Natvis", "NATVIS:", "Natvis files", "",
-    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  // Skip [AdditionalDependencies] - no command line Switch.
-  { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
-    "Ignore Specific Default Libraries", "",
-    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
-    "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
-    "Embed Managed Resource File", "",
-    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
-    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "",
-    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
-    "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
-    "Additional Manifest Dependencies", "",
-    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "ManifestInput", "manifestinput:", "Manifest Input", "",
-    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
-  // String Properties
-  { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
-  { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue },
-  { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "",
-    cmVS7FlagTable::UserValue },
-  { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "",
-    cmVS7FlagTable::UserValue },
-  // Skip [TrackerLogDirectory] - no command line Switch.
-  { "ModuleDefinitionFile", "DEF:", "Module Definition File", "",
-    cmVS7FlagTable::UserValue },
-  { "ManifestFile", "ManifestFile:", "Manifest File", "",
-    cmVS7FlagTable::UserValue },
-  { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "",
-    cmVS7FlagTable::UserValue },
-  { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "",
-    cmVS7FlagTable::UserValue },
-  // Skip [MapFileName] - no command line Switch.
-  // Skip [MinimumRequiredVersion] - no command line Switch.
-  { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
-    cmVS7FlagTable::UserValue },
-  // Skip [HeapCommitSize] - no command line Switch.
-  { "StackReserveSize", "STACK:", "Stack Reserve Size", "",
-    cmVS7FlagTable::UserValue },
-  // Skip [StackCommitSize] - no command line Switch.
-  { "FunctionOrder", "ORDER:@", "Function Order", "",
-    cmVS7FlagTable::UserValue },
-  { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "",
-    cmVS7FlagTable::UserValue },
-  { "MidlCommandFile", "MIDL:@", "MIDL Commands", "",
-    cmVS7FlagTable::UserValue },
-  { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "",
-    cmVS7FlagTable::UserValue },
-  { "TypeLibraryFile", "TLBOUT:", "Type Library", "",
-    cmVS7FlagTable::UserValue },
-  { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "",
-    cmVS7FlagTable::UserValue },
-  { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File",
-    "", cmVS7FlagTable::UserValue },
-  { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:",
-    "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue },
-  { "EntryPointSymbol", "ENTRY:", "Entry Point", "",
-    cmVS7FlagTable::UserValue },
-  { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue },
-  { "ImportLibrary", "IMPLIB:", "Import Library", "",
-    cmVS7FlagTable::UserValue },
-  { "MergeSections", "MERGE:", "Merge Sections", "",
-    cmVS7FlagTable::UserValue },
-  { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue },
-  { "KeyContainer", "KEYCONTAINER:", "Key Container", "",
-    cmVS7FlagTable::UserValue },
-  // Skip [AdditionalOptions] - no command line Switch.
-  { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS14MASMFlagTable.h b/Source/cmVS14MASMFlagTable.h
index c4e5e1e..82ec9f1 100644
--- a/Source/cmVS14MASMFlagTable.h
+++ b/Source/cmVS14MASMFlagTable.h
@@ -2,74 +2,72 @@ static cmVS7FlagTable cmVS14MASMFlagTable[] = {
 
   // Enum Properties
   { "PreserveIdentifierCase", "", "Default", "0", 0 },
-  { "PreserveIdentifierCase", "/Cp", "Preserves Identifier Case (/Cp)", "1",
+  { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1",
     0 },
-  { "PreserveIdentifierCase", "/Cu",
+  { "PreserveIdentifierCase", "Cu",
     "Maps all identifiers to upper case. (/Cu)", "2", 0 },
-  { "PreserveIdentifierCase", "/Cx",
+  { "PreserveIdentifierCase", "Cx",
     "Preserves case in public and extern symbols. (/Cx)", "3", 0 },
 
-  { "WarningLevel", "/W0", "Warning Level 0 (/W0)", "0", 0 },
-  { "WarningLevel", "/W1", "Warning Level 1 (/W1)", "1", 0 },
-  { "WarningLevel", "/W2", "Warning Level 2 (/W2)", "2", 0 },
-  { "WarningLevel", "/W3", "Warning Level 3 (/W3)", "3", 0 },
+  { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 },
+  { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 },
+  { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 },
+  { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 },
 
   { "PackAlignmentBoundary", "", "Default", "0", 0 },
-  { "PackAlignmentBoundary", "/Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
-  { "PackAlignmentBoundary", "/Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
-  { "PackAlignmentBoundary", "/Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
-  { "PackAlignmentBoundary", "/Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
-  { "PackAlignmentBoundary", "/Zp16", "Sixteen Byte Boundary (/Zp16)", "5",
-    0 },
+  { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
+  { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
+  { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
+  { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
+  { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 },
 
   { "CallingConvention", "", "Default", "0", 0 },
-  { "CallingConvention", "/Gd", "Use C-style Calling Convention (/Gd)", "1",
-    0 },
-  { "CallingConvention", "/Gz", "Use stdcall Calling Convention (/Gz)", "2",
+  { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1",
     0 },
-  { "CallingConvention", "/Gc", "Use Pascal Calling Convention (/Gc)", "3",
+  { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2",
     0 },
+  { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 },
 
-  { "ErrorReporting", "/errorReport:prompt",
+  { "ErrorReporting", "errorReport:prompt",
     "Prompt to send report immediately (/errorReport:prompt)", "0", 0 },
-  { "ErrorReporting", "/errorReport:queue",
+  { "ErrorReporting", "errorReport:queue",
     "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 },
-  { "ErrorReporting", "/errorReport:send",
+  { "ErrorReporting", "errorReport:send",
     "Automatically send report (/errorReport:send)", "2", 0 },
-  { "ErrorReporting", "/errorReport:none",
+  { "ErrorReporting", "errorReport:none",
     "Do not send report (/errorReport:none)", "3", 0 },
 
   // Bool Properties
-  { "NoLogo", "/nologo", "", "true", 0 },
-  { "GeneratePreprocessedSourceListing", "/EP", "", "true", 0 },
-  { "ListAllAvailableInformation", "/Sa", "", "true", 0 },
-  { "UseSafeExceptionHandlers", "/safeseh", "", "true", 0 },
-  { "AddFirstPassListing", "/Sf", "", "true", 0 },
-  { "EnableAssemblyGeneratedCodeListing", "/Sg", "", "true", 0 },
-  { "DisableSymbolTable", "/Sn", "", "true", 0 },
-  { "EnableFalseConditionalsInListing", "/Sx", "", "true", 0 },
-  { "TreatWarningsAsErrors", "/WX", "", "true", 0 },
-  { "MakeAllSymbolsPublic", "/Zf", "", "true", 0 },
-  { "GenerateDebugInformation", "/Zi", "", "true", 0 },
-  { "EnableMASM51Compatibility", "/Zm", "", "true", 0 },
-  { "PerformSyntaxCheckOnly", "/Zs", "", "true", 0 },
+  { "NoLogo", "nologo", "", "true", 0 },
+  { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 },
+  { "ListAllAvailableInformation", "Sa", "", "true", 0 },
+  { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 },
+  { "AddFirstPassListing", "Sf", "", "true", 0 },
+  { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 },
+  { "DisableSymbolTable", "Sn", "", "true", 0 },
+  { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 },
+  { "TreatWarningsAsErrors", "WX", "", "true", 0 },
+  { "MakeAllSymbolsPublic", "Zf", "", "true", 0 },
+  { "GenerateDebugInformation", "Zi", "", "true", 0 },
+  { "EnableMASM51Compatibility", "Zm", "", "true", 0 },
+  { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 },
 
   // Bool Properties With Argument
 
   // String List Properties
-  { "PreprocessorDefinitions", "/D", "Preprocessor Definitions", "",
+  { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "IncludePaths", "/I", "Include Paths", "",
+  { "IncludePaths", "I", "Include Paths", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-  { "BrowseFile", "/FR", "Generate Browse Information File", "",
+  { "BrowseFile", "FR", "Generate Browse Information File", "",
     cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
   // Skip [AdditionalDependencies] - no command line Switch.
 
   // String Properties
   // Skip [Inputs] - no command line Switch.
-  { "ObjectFileName", "/Fo", "Object File Name", "",
+  { "ObjectFileName", "Fo", "Object File Name", "",
     cmVS7FlagTable::UserValue },
-  { "AssembledCodeListingFile", "/Fl", "Assembled Code Listing File", "",
+  { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "",
     cmVS7FlagTable::UserValue },
   // Skip [CommandLineTemplate] - no command line Switch.
   // Skip [ExecutionDescription] - no command line Switch.
diff --git a/Source/cmVS14RCFlagTable.h b/Source/cmVS14RCFlagTable.h
index 11e00d5..5dc8d5a 100644
--- a/Source/cmVS14RCFlagTable.h
+++ b/Source/cmVS14RCFlagTable.h
@@ -1,6 +1,7 @@
 static cmVS7FlagTable cmVS14RCFlagTable[] = {
   // Bool Properties
   { "NullTerminateStrings", "n", "", "true", 0 },
+  { "SuppressStartupBanner", "nologo", "", "true", 0 },
 
   { 0, 0, 0, 0, 0 }
 };
diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx
index c2ff664..7168f26 100644
--- a/Source/cmVSSetupHelper.cxx
+++ b/Source/cmVSSetupHelper.cxx
@@ -1,6 +1,7 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmVSSetupHelper.h"
+#include "cmSystemTools.h"
 
 #ifndef VSSetupConstants
 #define VSSetupConstants
@@ -240,6 +241,22 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
       setupHelper == NULL)
     return false;
 
+  std::string envVSCommonToolsDir;
+
+  // FIXME: When we support VS versions beyond 2017, the version
+  // to choose will be passed in by the caller.  We need to map that
+  // to a per-version name of this environment variable.
+  if (cmSystemTools::GetEnv("VS150COMNTOOLS", envVSCommonToolsDir)) {
+    cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir);
+  }
+  // FIXME: If the environment variable value changes between runs
+  // of CMake within a given build tree the results are not defined.
+  // Instead we should save a CMAKE_GENERATOR_INSTANCE value in the cache
+  // (similar to CMAKE_GENERATOR_TOOLSET) to hold it persistently.
+  // Unfortunately doing so will require refactoring elsewhere in
+  // order to make sure the value is available in time to create
+  // the generator.
+
   std::vector<VSInstanceInfo> vecVSInstances;
   SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL;
   if (FAILED(
@@ -263,6 +280,17 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
     instance = instance2 = NULL;
 
     if (isInstalled) {
+      if (!envVSCommonToolsDir.empty()) {
+        std::string currentVSLocation(instanceInfo.VSInstallLocation.begin(),
+                                      instanceInfo.VSInstallLocation.end());
+        cmSystemTools::ConvertToUnixSlashes(currentVSLocation);
+        currentVSLocation += "/Common7/Tools";
+        if (cmSystemTools::ComparePath(currentVSLocation,
+                                       envVSCommonToolsDir)) {
+          chosenInstanceInfo = instanceInfo;
+          return true;
+        }
+      }
       vecVSInstances.push_back(instanceInfo);
     }
   }
diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx
index 1eb1f20..06ca53c 100644
--- a/Source/cmVariableRequiresCommand.cxx
+++ b/Source/cmVariableRequiresCommand.cxx
@@ -3,7 +3,6 @@
 #include "cmVariableRequiresCommand.h"
 
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
 
@@ -13,21 +12,16 @@ class cmExecutionStatus;
 bool cmVariableRequiresCommand::InitialPass(
   std::vector<std::string> const& args, cmExecutionStatus&)
 {
-  if (this->Disallowed(
-        cmPolicies::CMP0035,
-        "The variable_requires command should not be called; see CMP0035.")) {
-    return true;
-  }
   if (args.size() < 3) {
     this->SetError("called with incorrect number of arguments");
     return false;
   }
 
-  std::string testVariable = args[0];
+  std::string const& testVariable = args[0];
   if (!this->Makefile->IsOn(testVariable)) {
     return true;
   }
-  std::string resultVariable = args[1];
+  std::string const& resultVariable = args[1];
   bool requirementsMet = true;
   std::string notSet;
   bool hasAdvanced = false;
diff --git a/Source/cmVariableRequiresCommand.h b/Source/cmVariableRequiresCommand.h
index baf717c..9808d5f 100644
--- a/Source/cmVariableRequiresCommand.h
+++ b/Source/cmVariableRequiresCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmVariableRequiresCommand_h
 #define cmVariableRequiresCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -17,7 +18,6 @@ public:
   cmCommand* Clone() CM_OVERRIDE { return new cmVariableRequiresCommand; }
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-  std::string GetName() const CM_OVERRIDE { return "variable_requires"; }
 };
 
 #endif
diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index c94ce17..419e1a4 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -4,8 +4,8 @@
 
 #include "cmAlgorithms.h"
 
+#include "cm_auto_ptr.hxx"
 #include <algorithm>
-#include <cm_auto_ptr.hxx>
 #include <utility>
 
 static const char* const cmVariableWatchAccessStrings[] = {
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index 0b8b433..a575afe 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -3,7 +3,7 @@
 #ifndef cmVariableWatch_h
 #define cmVariableWatch_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
 #include <string>
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 90b0b28..281850e 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -106,7 +106,7 @@ bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args,
     this->SetError("must be called with at least one argument.");
     return false;
   }
-  std::string variable = args[0];
+  std::string const& variable = args[0];
   std::string command;
   if (args.size() > 1) {
     command = args[1];
diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h
index 919bac4..9f04391 100644
--- a/Source/cmVariableWatchCommand.h
+++ b/Source/cmVariableWatchCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmVariableWatchCommand_h
 #define cmVariableWatchCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <set>
 #include <string>
 #include <vector>
@@ -37,20 +38,10 @@ public:
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
 
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
   /** This command does not really have a final pass but it needs to
       stay alive since it owns variable watch callback information. */
   bool HasFinalPass() const CM_OVERRIDE { return true; }
 
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "variable_watch"; }
-
 protected:
   std::set<std::string> WatchedVariables;
 };
diff --git a/Source/cmVersion.h b/Source/cmVersion.h
index e77ec99..bfd994d 100644
--- a/Source/cmVersion.h
+++ b/Source/cmVersion.h
@@ -3,7 +3,7 @@
 #ifndef cmVersion_h
 #define cmVersion_h
 
-#include <cm_kwiml.h>
+#include "cm_kwiml.h"
 
 /** \class cmVersion
  * \brief Helper class for providing CMake and CTest version information.
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 902fe03..88fa19c 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmVisualStudio10TargetGenerator.h"
 
+#include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
 #include "cmCustomCommandGenerator.h"
 #include "cmGeneratedFileStream.h"
@@ -10,12 +11,11 @@
 #include "cmLocalVisualStudio7Generator.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
+#include "cmSystemTools.h"
 #include "cmVisualStudioGeneratorOptions.h"
 #include "windows.h"
 
-#include <cm_auto_ptr.hxx>
-
-static std::string const kWINDOWS_7_1_SDK = "Windows7.1SDK";
+#include "cm_auto_ptr.hxx"
 
 static std::string cmVS10EscapeXML(std::string arg)
 {
@@ -111,6 +111,14 @@ cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
        i != this->LinkOptions.end(); ++i) {
     delete i->second;
   }
+  for (OptionsMap::iterator i = this->CudaOptions.begin();
+       i != this->CudaOptions.end(); ++i) {
+    delete i->second;
+  }
+  for (OptionsMap::iterator i = this->CudaLinkOptions.begin();
+       i != this->CudaLinkOptions.end(); ++i) {
+    delete i->second;
+  }
   if (!this->BuildFileStream) {
     return;
   }
@@ -205,9 +213,18 @@ void cmVisualStudio10TargetGenerator::Generate()
     if (!this->ComputeRcOptions()) {
       return;
     }
+    if (!this->ComputeCudaOptions()) {
+      return;
+    }
+    if (!this->ComputeCudaLinkOptions()) {
+      return;
+    }
     if (!this->ComputeMasmOptions()) {
       return;
     }
+    if (!this->ComputeNasmOptions()) {
+      return;
+    }
     if (!this->ComputeLinkOptions()) {
       return;
     }
@@ -279,8 +296,8 @@ void cmVisualStudio10TargetGenerator::Generate()
     this->WriteProjectConfigurations();
   }
   this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
-  this->WriteString("<ProjectGUID>", 2);
-  (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGUID>\n";
+  this->WriteString("<ProjectGuid>", 2);
+  (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGuid>\n";
 
   if (this->MSTools &&
       this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
@@ -450,11 +467,34 @@ void cmVisualStudio10TargetGenerator::Generate()
     this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1);
   }
   this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
+  if (this->GlobalGenerator->IsCudaEnabled()) {
+    this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
+                      "BuildCustomizations\\CUDA ",
+                      2);
+    (*this->BuildFileStream)
+      << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString())
+      << ".props\" />\n";
+  }
   if (this->GlobalGenerator->IsMasmEnabled()) {
     this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
                       "BuildCustomizations\\masm.props\" />\n",
                       2);
   }
+  if (this->GlobalGenerator->IsNasmEnabled()) {
+    // Always search in the standard modules location.
+    std::string propsTemplate =
+      GetCMakeFilePath("Templates/MSBuild/nasm.props.in");
+
+    std::string propsLocal;
+    propsLocal += this->DefaultArtifactDir;
+    propsLocal += "\\nasm.props";
+    this->ConvertToWindowsSlash(propsLocal);
+    this->Makefile->ConfigureFile(propsTemplate.c_str(), propsLocal.c_str(),
+                                  false, true, true);
+    std::string import = std::string("<Import Project=\"") +
+      cmVS10EscapeXML(propsLocal) + "\" />\n";
+    this->WriteString(import.c_str(), 2);
+  }
   this->WriteString("</ImportGroup>\n", 1);
   this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1);
   {
@@ -505,11 +545,26 @@ void cmVisualStudio10TargetGenerator::Generate()
   this->WriteTargetSpecificReferences();
   this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
   this->WriteTargetsFileReferences();
+  if (this->GlobalGenerator->IsCudaEnabled()) {
+    this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
+                      "BuildCustomizations\\CUDA ",
+                      2);
+    (*this->BuildFileStream)
+      << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString())
+      << ".targets\" />\n";
+  }
   if (this->GlobalGenerator->IsMasmEnabled()) {
     this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
                       "BuildCustomizations\\masm.targets\" />\n",
                       2);
   }
+  if (this->GlobalGenerator->IsNasmEnabled()) {
+    std::string nasmTargets =
+      GetCMakeFilePath("Templates/MSBuild/nasm.targets");
+    std::string import = "<Import Project=\"";
+    import += cmVS10EscapeXML(nasmTargets) + "\" />\n";
+    this->WriteString(import.c_str(), 2);
+  }
   this->WriteString("</ImportGroup>\n", 1);
   if (csproj == this->ProjectType) {
     for (std::vector<std::string>::const_iterator i =
@@ -926,19 +981,21 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
   const char* mfcFlag =
     this->GeneratorTarget->Target->GetMakefile()->GetDefinition(
       "CMAKE_MFC_FLAG");
-  std::string mfcFlagValue = mfcFlag ? mfcFlag : "0";
+  if (mfcFlag) {
+    std::string const mfcFlagValue = mfcFlag;
 
-  std::string useOfMfcValue = "false";
-  if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
-    if (mfcFlagValue == "1") {
-      useOfMfcValue = "Static";
-    } else if (mfcFlagValue == "2") {
-      useOfMfcValue = "Dynamic";
+    std::string useOfMfcValue = "false";
+    if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
+      if (mfcFlagValue == "1") {
+        useOfMfcValue = "Static";
+      } else if (mfcFlagValue == "2") {
+        useOfMfcValue = "Dynamic";
+      }
     }
+    std::string mfcLine = "<UseOfMfc>";
+    mfcLine += useOfMfcValue + "</UseOfMfc>\n";
+    this->WriteString(mfcLine.c_str(), 2);
   }
-  std::string mfcLine = "<UseOfMfc>";
-  mfcLine += useOfMfcValue + "</UseOfMfc>\n";
-  this->WriteString(mfcLine.c_str(), 2);
 
   if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY &&
        this->ClOptions[config]->UsingUnicode()) ||
@@ -1002,8 +1059,8 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
 
   std::string postfixName = cmSystemTools::UpperCase(config);
   postfixName += "_POSTFIX";
-  std::string assemblyName =
-    this->GeneratorTarget->GetOutputName(config, false);
+  std::string assemblyName = this->GeneratorTarget->GetOutputName(
+    config, cmStateEnums::RuntimeBinaryArtifact);
   if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) {
     assemblyName += postfix;
   }
@@ -1192,16 +1249,15 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
 
   // collect up group information
   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
-  std::vector<cmSourceFile*> classes;
-  if (!this->GeneratorTarget->GetConfigCommonSourceFiles(classes)) {
-    return;
-  }
+
+  std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+    this->GeneratorTarget->GetAllConfigSources();
 
   std::set<cmSourceGroup*> groupsUsed;
-  for (std::vector<cmSourceFile*>::const_iterator s = classes.begin();
-       s != classes.end(); s++) {
-    cmSourceFile* sf = *s;
-    std::string const& source = sf->GetFullPath();
+  for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
+         sources.begin();
+       si != sources.end(); ++si) {
+    std::string const& source = si->Source->GetFullPath();
     cmSourceGroup* sourceGroup =
       this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
     groupsUsed.insert(sourceGroup);
@@ -1288,23 +1344,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
     this->WriteString("</ItemGroup>\n", 1);
   }
 
-  // Add object library contents as external objects.
-  std::vector<std::string> objs;
-  this->GeneratorTarget->UseObjectLibraries(objs, "");
-  if (!objs.empty()) {
-    this->WriteString("<ItemGroup>\n", 1);
-    for (std::vector<std::string>::const_iterator oi = objs.begin();
-         oi != objs.end(); ++oi) {
-      std::string obj = *oi;
-      this->WriteString("<Object Include=\"", 2);
-      this->ConvertToWindowsSlash(obj);
-      (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\">\n";
-      this->WriteString("<Filter>Object Libraries</Filter>\n", 3);
-      this->WriteString("</Object>\n", 2);
-    }
-    this->WriteString("</ItemGroup>\n", 1);
-  }
-
   this->WriteString("<ItemGroup>\n", 1);
   for (std::set<cmSourceGroup*>::iterator g = groupsUsed.begin();
        g != groupsUsed.end(); ++g) {
@@ -1322,15 +1361,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
       this->WriteString("</Filter>\n", 2);
     }
   }
-  if (!objs.empty()) {
-    this->WriteString("<Filter Include=\"Object Libraries\">\n", 2);
-    std::string guidName = "SG_Filter_Object Libraries";
-    this->WriteString("<UniqueIdentifier>", 3);
-    std::string guid = this->GlobalGenerator->GetGUID(guidName.c_str());
-    (*this->BuildFileStream) << "{" << guid << "}"
-                             << "</UniqueIdentifier>\n";
-    this->WriteString("</Filter>\n", 2);
-  }
 
   if (!resxObjs.empty() || !this->AddedFiles.empty()) {
     this->WriteString("<Filter Include=\"Resource Files\">\n", 2);
@@ -1668,8 +1698,10 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
   //
   // and fail if this exceeds the maximum allowed path length.  Our path
   // conversion uses full paths when possible to allow deeper trees.
-  bool forceRelative = false;
-  std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false);
+  // However, CUDA 8.0 msbuild rules fail on absolute paths so for CUDA
+  // we must use relative paths.
+  bool forceRelative = sf->GetLanguage() == "CUDA";
+  std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
   if (this->LocalGenerator->GetVersion() ==
         cmGlobalVisualStudioGenerator::VS10 &&
       cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
@@ -1702,15 +1734,6 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
   this->Tools[tool].push_back(toolSource);
 }
 
-void cmVisualStudio10TargetGenerator::WriteSources(
-  std::string const& tool, std::vector<cmSourceFile const*> const& sources)
-{
-  for (std::vector<cmSourceFile const*>::const_iterator si = sources.begin();
-       si != sources.end(); ++si) {
-    this->WriteSource(tool, *si);
-  }
-}
-
 void cmVisualStudio10TargetGenerator::WriteAllSources()
 {
   if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
@@ -1718,105 +1741,121 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
   }
   this->WriteString("<ItemGroup>\n", 1);
 
-  std::vector<cmSourceFile const*> headerSources;
-  this->GeneratorTarget->GetHeaderSources(headerSources, "");
-  for (std::vector<cmSourceFile const*>::const_iterator si =
-         headerSources.begin();
-       si != headerSources.end(); ++si) {
-    this->WriteHeaderSource(*si);
+  std::vector<size_t> all_configs;
+  for (size_t ci = 0; ci < this->Configurations.size(); ++ci) {
+    all_configs.push_back(ci);
   }
-  std::vector<cmSourceFile const*> idlSources;
-  this->GeneratorTarget->GetIDLSources(idlSources, "");
-  this->WriteSources("Midl", idlSources);
 
-  std::vector<cmSourceFile const*> objectSources;
-  this->GeneratorTarget->GetObjectSources(objectSources, "");
-  for (std::vector<cmSourceFile const*>::const_iterator si =
-         objectSources.begin();
-       si != objectSources.end(); ++si) {
-    const std::string& lang = (*si)->GetLanguage();
+  std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
+    this->GeneratorTarget->GetAllConfigSources();
+
+  for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
+         sources.begin();
+       si != sources.end(); ++si) {
     std::string tool;
-    if (lang == "C" || lang == "CXX") {
-      tool = "ClCompile";
-    } else if (lang == "ASM_MASM" && this->GlobalGenerator->IsMasmEnabled()) {
-      tool = "MASM";
-    } else if (lang == "RC") {
-      tool = "ResourceCompile";
-    } else if (lang == "CSharp") {
-      tool = "Compile";
+    switch (si->Kind) {
+      case cmGeneratorTarget::SourceKindAppManifest:
+        tool = "AppxManifest";
+        break;
+      case cmGeneratorTarget::SourceKindCertificate:
+        tool = "None";
+        break;
+      case cmGeneratorTarget::SourceKindCustomCommand:
+        // Handled elsewhere.
+        break;
+      case cmGeneratorTarget::SourceKindExternalObject:
+        tool = "Object";
+        if (this->LocalGenerator->GetVersion() <
+            cmGlobalVisualStudioGenerator::VS11) {
+          // For VS == 10 we cannot use LinkObjects to avoid linking custom
+          // command outputs.  If an object file is generated in this target,
+          // then vs10 will use it in the build, and we have to list it as
+          // None instead of Object.
+          std::vector<cmSourceFile*> const* d =
+            this->GeneratorTarget->GetSourceDepends(si->Source);
+          if (d && !d->empty()) {
+            tool = "None";
+          }
+        }
+        break;
+      case cmGeneratorTarget::SourceKindExtra:
+        this->WriteExtraSource(si->Source);
+        break;
+      case cmGeneratorTarget::SourceKindHeader:
+        this->WriteHeaderSource(si->Source);
+        break;
+      case cmGeneratorTarget::SourceKindIDL:
+        tool = "Midl";
+        break;
+      case cmGeneratorTarget::SourceKindManifest:
+        // Handled elsewhere.
+        break;
+      case cmGeneratorTarget::SourceKindModuleDefinition:
+        tool = "None";
+        break;
+      case cmGeneratorTarget::SourceKindObjectSource: {
+        const std::string& lang = si->Source->GetLanguage();
+        if (lang == "C" || lang == "CXX") {
+          tool = "ClCompile";
+        } else if (lang == "ASM_MASM" &&
+                   this->GlobalGenerator->IsMasmEnabled()) {
+          tool = "MASM";
+        } else if (lang == "ASM_NASM" &&
+                   this->GlobalGenerator->IsNasmEnabled()) {
+          tool = "NASM";
+        } else if (lang == "RC") {
+          tool = "ResourceCompile";
+        } else if (lang == "CSharp") {
+          tool = "Compile";
+        } else if (lang == "CUDA" && this->GlobalGenerator->IsCudaEnabled()) {
+          tool = "CudaCompile";
+        } else {
+          tool = "None";
+        }
+      } break;
+      case cmGeneratorTarget::SourceKindResx:
+        // Handled elsewhere.
+        break;
+      case cmGeneratorTarget::SourceKindXaml:
+        // Handled elsewhere.
+        break;
     }
 
     if (!tool.empty()) {
-      this->WriteSource(tool, *si, " ");
-      if (this->OutputSourceSpecificFlags(*si)) {
+      // Compute set of configurations to exclude, if any.
+      std::vector<size_t> const& include_configs = si->Configs;
+      std::vector<size_t> exclude_configs;
+      std::set_difference(all_configs.begin(), all_configs.end(),
+                          include_configs.begin(), include_configs.end(),
+                          std::back_inserter(exclude_configs));
+
+      if (si->Kind == cmGeneratorTarget::SourceKindObjectSource) {
+        // FIXME: refactor generation to avoid tracking XML syntax state.
+        this->WriteSource(tool, si->Source, " ");
+        bool have_nested = this->OutputSourceSpecificFlags(si->Source);
+        if (!exclude_configs.empty()) {
+          if (!have_nested) {
+            (*this->BuildFileStream) << ">\n";
+          }
+          this->WriteExcludeFromBuild(exclude_configs);
+          have_nested = true;
+        }
+        if (have_nested) {
+          this->WriteString("</", 2);
+          (*this->BuildFileStream) << tool << ">\n";
+        } else {
+          (*this->BuildFileStream) << " />\n";
+        }
+      } else if (!exclude_configs.empty()) {
+        this->WriteSource(tool, si->Source, ">\n");
+        this->WriteExcludeFromBuild(exclude_configs);
         this->WriteString("</", 2);
         (*this->BuildFileStream) << tool << ">\n";
       } else {
-        (*this->BuildFileStream) << " />\n";
+        this->WriteSource(tool, si->Source);
       }
-    } else {
-      this->WriteSource("None", *si);
-    }
-  }
-
-  std::vector<cmSourceFile const*> manifestSources;
-  this->GeneratorTarget->GetAppManifest(manifestSources, "");
-  this->WriteSources("AppxManifest", manifestSources);
-
-  std::vector<cmSourceFile const*> certificateSources;
-  this->GeneratorTarget->GetCertificates(certificateSources, "");
-  this->WriteSources("None", certificateSources);
-
-  std::vector<cmSourceFile const*> externalObjects;
-  this->GeneratorTarget->GetExternalObjects(externalObjects, "");
-  for (std::vector<cmSourceFile const*>::iterator si = externalObjects.begin();
-       si != externalObjects.end();) {
-    if (!(*si)->GetObjectLibrary().empty()) {
-      si = externalObjects.erase(si);
-    } else {
-      ++si;
     }
   }
-  if (this->LocalGenerator->GetVersion() >
-      cmGlobalVisualStudioGenerator::VS10) {
-    // For VS >= 11 we use LinkObjects to avoid linking custom command
-    // outputs.  Use Object for all external objects, generated or not.
-    this->WriteSources("Object", externalObjects);
-  } else {
-    // If an object file is generated in this target, then vs10 will use
-    // it in the build, and we have to list it as None instead of Object.
-    for (std::vector<cmSourceFile const*>::const_iterator si =
-           externalObjects.begin();
-         si != externalObjects.end(); ++si) {
-      std::vector<cmSourceFile*> const* d =
-        this->GeneratorTarget->GetSourceDepends(*si);
-      this->WriteSource((d && !d->empty()) ? "None" : "Object", *si);
-    }
-  }
-
-  std::vector<cmSourceFile const*> extraSources;
-  this->GeneratorTarget->GetExtraSources(extraSources, "");
-  for (std::vector<cmSourceFile const*>::const_iterator si =
-         extraSources.begin();
-       si != extraSources.end(); ++si) {
-    this->WriteExtraSource(*si);
-  }
-
-  // Add object library contents as external objects.
-  std::vector<std::string> objs;
-  this->GeneratorTarget->UseObjectLibraries(objs, "");
-  for (std::vector<std::string>::const_iterator oi = objs.begin();
-       oi != objs.end(); ++oi) {
-    std::string obj = *oi;
-    this->WriteString("<Object Include=\"", 2);
-    this->ConvertToWindowsSlash(obj);
-    (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\" />\n";
-  }
-
-  if (cmSourceFile const* defsrc =
-        this->GeneratorTarget->GetModuleDefinitionFile("")) {
-    this->WriteSource("None", defsrc);
-  }
 
   if (this->IsMissingFiles) {
     this->WriteMissingFiles();
@@ -1850,7 +1889,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
   std::string lang =
     this->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str());
   std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf);
-  const std::string& linkLanguage = this->GeneratorTarget->GetLinkerLanguage();
+  const std::string& linkLanguage =
+    this->GeneratorTarget->GetLinkerLanguage("");
   bool needForceLang = false;
   // source file does not match its extension language
   if (lang != sourceLang) {
@@ -1904,9 +1944,24 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
       hasFlags = true;
       cmGlobalVisualStudio10Generator* gg =
         static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+      cmIDEFlagTable const* flagtable = CM_NULLPTR;
+      const std::string& srclang = source->GetLanguage();
+      if (srclang == "C" || srclang == "CXX") {
+        flagtable = gg->GetClFlagTable();
+      } else if (srclang == "ASM_MASM" &&
+                 this->GlobalGenerator->IsMasmEnabled()) {
+        flagtable = gg->GetMasmFlagTable();
+      } else if (lang == "ASM_NASM" &&
+                 this->GlobalGenerator->IsNasmEnabled()) {
+        flagtable = gg->GetNasmFlagTable();
+      } else if (srclang == "RC") {
+        flagtable = gg->GetRcFlagTable();
+      } else if (srclang == "CSharp") {
+        flagtable = gg->GetCSharpFlagTable();
+      }
       cmVisualStudioGeneratorOptions clOptions(
         this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
-        gg->GetClFlagTable(), 0, this);
+        flagtable, 0, this);
       if (compileAs) {
         clOptions.AddFlag("CompileAs", compileAs);
       }
@@ -1932,7 +1987,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
       }
       clOptions.AddDefines(configDefines.c_str());
       clOptions.SetConfiguration((*config).c_str());
-      clOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
+      clOptions.PrependInheritedString("AdditionalOptions");
       clOptions.OutputFlagMap(*this->BuildFileStream, "      ");
       clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
                                               "\n", lang);
@@ -1995,6 +2050,19 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
   return hasFlags;
 }
 
+void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
+  std::vector<size_t> const& exclude_configs)
+{
+  for (std::vector<size_t>::const_iterator ci = exclude_configs.begin();
+       ci != exclude_configs.end(); ++ci) {
+    this->WriteString("", 3);
+    (*this->BuildFileStream)
+      << "<ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='"
+      << cmVS10EscapeXML(this->Configurations[*ci]) << "|"
+      << cmVS10EscapeXML(this->Platform) << "'\">true</ExcludedFromBuild>\n";
+  }
+}
+
 void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
 {
   cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
@@ -2005,15 +2073,15 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
     return;
   }
 
-  this->WriteString("<PropertyGroup>\n", 2);
+  this->WriteString("<PropertyGroup>\n", 1);
   this->WriteString("<_ProjectFileVersion>10.0.20506.1"
                     "</_ProjectFileVersion>\n",
-                    3);
+                    2);
   for (std::vector<std::string>::const_iterator config =
          this->Configurations.begin();
        config != this->Configurations.end(); ++config) {
     if (ttype >= cmStateEnums::UTILITY) {
-      this->WritePlatformConfigTag("IntDir", config->c_str(), 3);
+      this->WritePlatformConfigTag("IntDir", config->c_str(), 2);
       *this->BuildFileStream
         << "$(Platform)\\$(Configuration)\\$(ProjectName)\\"
         << "</IntDir>\n";
@@ -2036,24 +2104,24 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
       this->ConvertToWindowsSlash(intermediateDir);
       this->ConvertToWindowsSlash(outDir);
 
-      this->WritePlatformConfigTag("OutDir", config->c_str(), 3);
+      this->WritePlatformConfigTag("OutDir", config->c_str(), 2);
       *this->BuildFileStream << cmVS10EscapeXML(outDir) << "</OutDir>\n";
 
-      this->WritePlatformConfigTag("IntDir", config->c_str(), 3);
+      this->WritePlatformConfigTag("IntDir", config->c_str(), 2);
       *this->BuildFileStream << cmVS10EscapeXML(intermediateDir)
                              << "</IntDir>\n";
 
       if (const char* workingDir = this->GeneratorTarget->GetProperty(
             "VS_DEBUGGER_WORKING_DIRECTORY")) {
         this->WritePlatformConfigTag("LocalDebuggerWorkingDirectory",
-                                     config->c_str(), 3);
+                                     config->c_str(), 2);
         *this->BuildFileStream << cmVS10EscapeXML(workingDir)
                                << "</LocalDebuggerWorkingDirectory>\n";
       }
 
       std::string name =
         cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
-      this->WritePlatformConfigTag("TargetName", config->c_str(), 3);
+      this->WritePlatformConfigTag("TargetName", config->c_str(), 2);
       *this->BuildFileStream << cmVS10EscapeXML(name) << "</TargetName>\n";
 
       std::string ext =
@@ -2063,13 +2131,13 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
         // A single "." appears to be treated as an empty extension.
         ext = ".";
       }
-      this->WritePlatformConfigTag("TargetExt", config->c_str(), 3);
+      this->WritePlatformConfigTag("TargetExt", config->c_str(), 2);
       *this->BuildFileStream << cmVS10EscapeXML(ext) << "</TargetExt>\n";
 
       this->OutputLinkIncremental(*config);
     }
   }
-  this->WriteString("</PropertyGroup>\n", 2);
+  this->WriteString("</PropertyGroup>\n", 1);
 }
 
 void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
@@ -2090,13 +2158,13 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
   Options& linkOptions = *(this->LinkOptions[configName]);
 
   const char* incremental = linkOptions.GetFlag("LinkIncremental");
-  this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 3);
+  this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 2);
   *this->BuildFileStream << (incremental ? incremental : "true")
                          << "</LinkIncremental>\n";
   linkOptions.RemoveFlag("LinkIncremental");
 
   const char* manifest = linkOptions.GetFlag("GenerateManifest");
-  this->WritePlatformConfigTag("GenerateManifest", configName.c_str(), 3);
+  this->WritePlatformConfigTag("GenerateManifest", configName.c_str(), 2);
   *this->BuildFileStream << (manifest ? manifest : "true")
                          << "</GenerateManifest>\n";
   linkOptions.RemoveFlag("GenerateManifest");
@@ -2107,7 +2175,7 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
   for (const char** f = flags; *f; ++f) {
     const char* flag = *f;
     if (const char* value = linkOptions.GetFlag(flag)) {
-      this->WritePlatformConfigTag(flag, configName.c_str(), 3);
+      this->WritePlatformConfigTag(flag, configName.c_str(), 2);
       *this->BuildFileStream << value << "</" << flag << ">\n";
       linkOptions.RemoveFlag(flag);
     }
@@ -2158,10 +2226,27 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
       this->Name.c_str());
     return false;
   }
-  if (linkLanguage == "C" || linkLanguage == "CXX" ||
-      linkLanguage == "Fortran" || linkLanguage == "CSharp") {
+
+  // Choose a language whose flags to use for ClCompile.
+  static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" };
+  std::string langForClCompile;
+  if (std::find(cmArrayBegin(clLangs), cmArrayEnd(clLangs), linkLanguage) !=
+      cmArrayEnd(clLangs)) {
+    langForClCompile = linkLanguage;
+  } else {
+    std::set<std::string> languages;
+    this->GeneratorTarget->GetLanguages(languages, configName);
+    for (const char* const* l = cmArrayBegin(clLangs);
+         l != cmArrayEnd(clLangs); ++l) {
+      if (languages.find(*l) != languages.end()) {
+        langForClCompile = *l;
+        break;
+      }
+    }
+  }
+  if (!langForClCompile.empty()) {
     std::string baseFlagVar = "CMAKE_";
-    baseFlagVar += linkLanguage;
+    baseFlagVar += langForClCompile;
     baseFlagVar += "_FLAGS";
     flags =
       this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
@@ -2172,6 +2257,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
     flags +=
       this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
         flagVar.c_str());
+    this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
+                                            langForClCompile, configName);
   }
   // set the correct language
   if (linkLanguage == "C") {
@@ -2180,8 +2267,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
   if (linkLanguage == "CXX") {
     clOptions.AddFlag("CompileAs", "CompileAsCpp");
   }
-  this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
-                                          linkLanguage, configName.c_str());
+
+  // Check IPO related warning/error.
+  this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
 
   // Get preprocessor definitions for this directory.
   std::string defineFlags =
@@ -2265,7 +2353,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
     return;
   }
   this->WriteString("<ClCompile>\n", 2);
-  clOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
+  clOptions.PrependInheritedString("AdditionalOptions");
   clOptions.AppendFlag("AdditionalIncludeDirectories", includes);
   clOptions.AppendFlag("AdditionalIncludeDirectories",
                        "%(AdditionalIncludeDirectories)");
@@ -2369,12 +2457,191 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions(
   rcOptions.AppendFlag("AdditionalIncludeDirectories", includes);
   rcOptions.AppendFlag("AdditionalIncludeDirectories",
                        "%(AdditionalIncludeDirectories)");
+  rcOptions.PrependInheritedString("AdditionalOptions");
   rcOptions.OutputFlagMap(*this->BuildFileStream, "      ");
-  rcOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
 
   this->WriteString("</ResourceCompile>\n", 2);
 }
 
+bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
+{
+  if (!this->GlobalGenerator->IsCudaEnabled()) {
+    return true;
+  }
+  for (std::vector<std::string>::const_iterator i =
+         this->Configurations.begin();
+       i != this->Configurations.end(); ++i) {
+    if (!this->ComputeCudaOptions(*i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
+  std::string const& configName)
+{
+  cmGlobalVisualStudio10Generator* gg =
+    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  CM_AUTO_PTR<Options> pOptions(new Options(
+    this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable()));
+  Options& cudaOptions = *pOptions;
+
+  // Get compile flags for CUDA in this directory.
+  std::string CONFIG = cmSystemTools::UpperCase(configName);
+  std::string configFlagsVar = std::string("CMAKE_CUDA_FLAGS_") + CONFIG;
+  std::string flags =
+    std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) +
+    std::string(" ") +
+    std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
+  this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA",
+                                          configName);
+
+  // Get preprocessor definitions for this directory.
+  std::string defineFlags =
+    this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+
+  cudaOptions.Parse(flags.c_str());
+  cudaOptions.Parse(defineFlags.c_str());
+  cudaOptions.ParseFinish();
+
+  if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
+    cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true");
+  } else if (this->GeneratorTarget->GetPropertyAsBool(
+               "CUDA_PTX_COMPILATION")) {
+    cudaOptions.AddFlag("NvccCompilation", "ptx");
+    // We drop the %(Extension) component as CMake expects all PTX files
+    // to not have the source file extension at all
+    cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).ptx");
+  }
+
+  // Convert the host compiler options to the toolset's abstractions
+  // using a secondary flag table.
+  cudaOptions.ClearTables();
+  cudaOptions.AddTable(gg->GetCudaHostFlagTable());
+  cudaOptions.Reparse("AdditionalCompilerOptions");
+
+  // `CUDA 8.0.targets` places AdditionalCompilerOptions before nvcc!
+  // Pass them through -Xcompiler in AdditionalOptions instead.
+  if (const char* acoPtr = cudaOptions.GetFlag("AdditionalCompilerOptions")) {
+    std::string aco = acoPtr;
+    cudaOptions.RemoveFlag("AdditionalCompilerOptions");
+    if (!aco.empty()) {
+      aco = this->LocalGenerator->EscapeForShell(aco, false);
+      cudaOptions.AppendFlagString("AdditionalOptions", "-Xcompiler=" + aco);
+    }
+  }
+
+  cudaOptions.FixCudaCodeGeneration();
+
+  std::vector<std::string> targetDefines;
+  this->GeneratorTarget->GetCompileDefinitions(targetDefines,
+                                               configName.c_str(), "CUDA");
+  cudaOptions.AddDefines(targetDefines);
+
+  // Add a definition for the configuration name.
+  std::string configDefine = "CMAKE_INTDIR=\"";
+  configDefine += configName;
+  configDefine += "\"";
+  cudaOptions.AddDefine(configDefine);
+  if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) {
+    cudaOptions.AddDefine(exportMacro);
+  }
+
+  this->CudaOptions[configName] = pOptions.release();
+  return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteCudaOptions(
+  std::string const& configName, std::vector<std::string> const& includes)
+{
+  if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
+    return;
+  }
+  this->WriteString("<CudaCompile>\n", 2);
+
+  Options& cudaOptions = *(this->CudaOptions[configName]);
+  cudaOptions.AppendFlag("Include", includes);
+  cudaOptions.AppendFlag("Include", "%(Include)");
+  cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
+                                            "\n", "CUDA");
+  cudaOptions.PrependInheritedString("AdditionalOptions");
+  cudaOptions.OutputFlagMap(*this->BuildFileStream, "      ");
+
+  this->WriteString("</CudaCompile>\n", 2);
+}
+
+bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
+{
+  if (!this->GlobalGenerator->IsCudaEnabled()) {
+    return true;
+  }
+  for (std::vector<std::string>::const_iterator i =
+         this->Configurations.begin();
+       i != this->Configurations.end(); ++i) {
+    if (!this->ComputeCudaLinkOptions(*i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
+  std::string const& configName)
+{
+  cmGlobalVisualStudio10Generator* gg =
+    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  CM_AUTO_PTR<Options> pOptions(new Options(
+    this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable()));
+  Options& cudaLinkOptions = *pOptions;
+
+  // Determine if we need to do a device link
+  bool doDeviceLinking = false;
+  switch (this->GeneratorTarget->GetType()) {
+    case cmStateEnums::SHARED_LIBRARY:
+    case cmStateEnums::MODULE_LIBRARY:
+    case cmStateEnums::EXECUTABLE:
+      doDeviceLinking = true;
+      break;
+    case cmStateEnums::STATIC_LIBRARY:
+      doDeviceLinking = this->GeneratorTarget->GetPropertyAsBool(
+        "CUDA_RESOLVE_DEVICE_SYMBOLS");
+      break;
+    default:
+      break;
+  }
+
+  cudaLinkOptions.AddFlag("PerformDeviceLink",
+                          doDeviceLinking ? "true" : "false");
+
+  // Suppress deprecation warnings for default GPU targets during device link.
+  if (cmSystemTools::VersionCompareGreaterEq(
+        this->GlobalGenerator->GetPlatformToolsetCudaString(), "8.0")) {
+    cudaLinkOptions.AppendFlagString("AdditionalOptions",
+                                     "-Wno-deprecated-gpu-targets");
+  }
+
+  this->CudaLinkOptions[configName] = pOptions.release();
+  return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions(
+  std::string const& configName)
+{
+  if (this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
+    return;
+  }
+
+  if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
+    return;
+  }
+
+  this->WriteString("<CudaLink>\n", 2);
+  Options& cudaLinkOptions = *(this->CudaLinkOptions[configName]);
+  cudaLinkOptions.OutputFlagMap(*this->BuildFileStream, "      ");
+  this->WriteString("</CudaLink>\n", 2);
+}
+
 bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
 {
   if (!this->GlobalGenerator->IsMasmEnabled()) {
@@ -2427,12 +2694,77 @@ void cmVisualStudio10TargetGenerator::WriteMasmOptions(
   Options& masmOptions = *(this->MasmOptions[configName]);
   masmOptions.AppendFlag("IncludePaths", includes);
   masmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
+  masmOptions.PrependInheritedString("AdditionalOptions");
   masmOptions.OutputFlagMap(*this->BuildFileStream, "      ");
-  masmOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
 
   this->WriteString("</MASM>\n", 2);
 }
 
+bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
+{
+  if (!this->GlobalGenerator->IsNasmEnabled()) {
+    return true;
+  }
+  for (std::vector<std::string>::const_iterator i =
+         this->Configurations.begin();
+       i != this->Configurations.end(); ++i) {
+    if (!this->ComputeNasmOptions(*i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
+  std::string const& configName)
+{
+  cmGlobalVisualStudio10Generator* gg =
+    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  CM_AUTO_PTR<Options> pOptions(new Options(
+    this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable()));
+  Options& nasmOptions = *pOptions;
+
+  std::string CONFIG = cmSystemTools::UpperCase(configName);
+  std::string configFlagsVar = std::string("CMAKE_ASM_NASM_FLAGS_") + CONFIG;
+  std::string flags =
+    std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS")) +
+    std::string(" -f") + std::string(this->Makefile->GetSafeDefinition(
+                           "CMAKE_ASM_NASM_OBJECT_FORMAT")) +
+    std::string(" ") +
+    std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
+  nasmOptions.Parse(flags.c_str());
+  this->NasmOptions[configName] = pOptions.release();
+  return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteNasmOptions(
+  std::string const& configName, std::vector<std::string> includes)
+{
+  if (!this->GlobalGenerator->IsNasmEnabled()) {
+    return;
+  }
+  this->WriteString("<NASM>\n", 2);
+
+  Options& nasmOptions = *(this->NasmOptions[configName]);
+  for (size_t i = 0; i < includes.size(); i++) {
+    includes[i] += "\\";
+  }
+
+  nasmOptions.AppendFlag("IncludePaths", includes);
+  nasmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
+  nasmOptions.OutputFlagMap(*this->BuildFileStream, "      ");
+  nasmOptions.PrependInheritedString("AdditionalOptions");
+  nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
+                                            "\n", "ASM_NASM");
+
+  // Preprocessor definitions and includes are shared with clOptions.
+  Options& clOptions = *(this->ClOptions[configName]);
+  clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
+                                          "\n", "ASM_NASM");
+
+  this->WriteString("</NASM>\n", 2);
+}
+
 void cmVisualStudio10TargetGenerator::WriteLibOptions(
   std::string const& config)
 {
@@ -2451,7 +2783,7 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
       this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker,
       gg->GetLibFlagTable(), 0, this);
     libOptions.Parse(libflags.c_str());
-    libOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
+    libOptions.PrependInheritedString("AdditionalOptions");
     libOptions.OutputFlagMap(*this->BuildFileStream, "      ");
     this->WriteString("</Lib>\n", 2);
   }
@@ -2648,8 +2980,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
     this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), 0, this));
   Options& linkOptions = *pOptions;
 
-  const std::string& linkLanguage =
-    this->GeneratorTarget->GetLinkerLanguage(config.c_str());
+  cmGeneratorTarget::LinkClosure const* linkClosure =
+    this->GeneratorTarget->GetLinkClosure(config);
+
+  const std::string& linkLanguage = linkClosure->LinkerLanguage;
   if (linkLanguage.empty()) {
     cmSystemTools::Error(
       "CMake can not determine linker language for target: ",
@@ -2690,25 +3024,6 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
     flags += " ";
     flags += flagsConfig;
   }
-  std::string standardLibsVar = "CMAKE_";
-  standardLibsVar += linkLanguage;
-  standardLibsVar += "_STANDARD_LIBRARIES";
-  std::string libs =
-    this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
-  // Remove trailing spaces from libs
-  std::string::size_type pos = libs.size() - 1;
-  if (!libs.empty()) {
-    while (libs[pos] == ' ') {
-      pos--;
-    }
-  }
-  if (pos != libs.size() - 1) {
-    libs = libs.substr(0, pos + 1);
-  }
-  // Replace spaces in libs with ;
-  std::replace(libs.begin(), libs.end(), ' ', ';');
-  std::vector<std::string> libVec;
-  cmSystemTools::ExpandListArgument(libs, libVec);
 
   cmComputeLinkInformation* pcli =
     this->GeneratorTarget->GetLinkInformation(config.c_str());
@@ -2718,10 +3033,30 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
       this->Name.c_str());
     return false;
   }
-  // add the libraries for the target to libs string
   cmComputeLinkInformation& cli = *pcli;
+
+  std::vector<std::string> libVec;
   std::vector<std::string> vsTargetVec;
   this->AddLibraries(cli, libVec, vsTargetVec);
+  if (std::find(linkClosure->Languages.begin(), linkClosure->Languages.end(),
+                "CUDA") != linkClosure->Languages.end()) {
+    switch (this->CudaOptions[config]->GetCudaRuntime()) {
+      case cmVisualStudioGeneratorOptions::CudaRuntimeStatic:
+        libVec.push_back("cudart_static.lib");
+        break;
+      case cmVisualStudioGeneratorOptions::CudaRuntimeShared:
+        libVec.push_back("cudart.lib");
+        break;
+      case cmVisualStudioGeneratorOptions::CudaRuntimeNone:
+        break;
+    }
+  }
+  std::string standardLibsVar = "CMAKE_";
+  standardLibsVar += linkLanguage;
+  standardLibsVar += "_STANDARD_LIBRARIES";
+  std::string const libs =
+    this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
+  cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec);
   linkOptions.AddFlag("AdditionalDependencies", libVec);
 
   // Populate TargetsFileAndConfigsVec
@@ -2793,18 +3128,13 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
       linkOptions.AddFlag("StackReserveSize", stackVal);
     }
 
-    if (this->LocalGenerator->GetVersion() >=
-        cmGlobalVisualStudioGenerator::VS14) {
-      linkOptions.AddFlag("GenerateDebugInformation", "No");
-    } else {
-      linkOptions.AddFlag("GenerateDebugInformation", "false");
-    }
+    linkOptions.AddFlag("GenerateDebugInformation", "false");
 
     std::string pdb = this->GeneratorTarget->GetPDBDirectory(config.c_str());
     pdb += "/";
     pdb += targetNamePDB;
-    std::string imLib =
-      this->GeneratorTarget->GetDirectory(config.c_str(), true);
+    std::string imLib = this->GeneratorTarget->GetDirectory(
+      config.c_str(), cmStateEnums::ImportLibraryArtifact);
     imLib += "/";
     imLib += targetNameImport;
 
@@ -2836,46 +3166,23 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
   linkOptions.Parse(flags.c_str());
 
   if (this->MSTools) {
-    if (cmSourceFile const* defsrc =
-          this->GeneratorTarget->GetModuleDefinitionFile("")) {
-      linkOptions.AddFlag("ModuleDefinitionFile",
-                          defsrc->GetFullPath().c_str());
+    cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+      this->GeneratorTarget->GetModuleDefinitionInfo(config);
+    if (mdi && !mdi->DefFile.empty()) {
+      linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile.c_str());
     }
     linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
                            "%(IgnoreSpecificDefaultLibraries)");
   }
 
-  if ((this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
-       this->GeneratorTarget->IsExecutableWithExports()) &&
-      this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (this->GeneratorTarget->GetPropertyAsBool(
-          "WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)exportall.def");
-    }
-  }
-
-  // Hack to fix flag version selection in a common use case.
-  // FIXME: Select flag table based on toolset instead of VS version.
-  if (this->LocalGenerator->GetVersion() >=
-      cmGlobalVisualStudioGenerator::VS14) {
-    cmGlobalVisualStudio10Generator* gg =
-      static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
-    const char* toolset = gg->GetPlatformToolset();
-    if (toolset &&
-        (toolset == kWINDOWS_7_1_SDK || /* clang-format please break here */
-         cmHasLiteralPrefix(toolset, "v80") ||
-         cmHasLiteralPrefix(toolset, "v90") ||
-         cmHasLiteralPrefix(toolset, "v100") ||
-         cmHasLiteralPrefix(toolset, "v110") ||
-         cmHasLiteralPrefix(toolset, "v120"))) {
-      if (const char* debug =
-            linkOptions.GetFlag("GenerateDebugInformation")) {
-        // Convert value from enumeration back to boolean for older toolsets.
-        if (strcmp(debug, "No") == 0) {
-          linkOptions.AddFlag("GenerateDebugInformation", "false");
-        } else if (strcmp(debug, "Debug") == 0) {
-          linkOptions.AddFlag("GenerateDebugInformation", "true");
-        }
+  // VS 2015 without all updates has a v140 toolset whose
+  // GenerateDebugInformation expects No/Debug instead of false/true.
+  if (gg->GetPlatformToolsetNeedsDebugEnum()) {
+    if (const char* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
+      if (strcmp(debug, "false") == 0) {
+        linkOptions.AddFlag("GenerateDebugInformation", "No");
+      } else if (strcmp(debug, "true") == 0) {
+        linkOptions.AddFlag("GenerateDebugInformation", "Debug");
       }
     }
   }
@@ -2940,7 +3247,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(
   Options& linkOptions = *(this->LinkOptions[config]);
   this->WriteString("<Link>\n", 2);
 
-  linkOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
+  linkOptions.PrependInheritedString("AdditionalOptions");
   linkOptions.OutputFlagMap(*this->BuildFileStream, "      ");
 
   this->WriteString("</Link>\n", 2);
@@ -3063,7 +3370,9 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
       this->WriteClOptions(*i, includes);
       //    output rc compile flags <ResourceCompile></ResourceCompile>
       this->WriteRCOptions(*i, includes);
+      this->WriteCudaOptions(*i, includes);
       this->WriteMasmOptions(*i, includes);
+      this->WriteNasmOptions(*i, includes);
     }
     //    output midl flags       <Midl></Midl>
     this->WriteMidlOptions(*i, includes);
@@ -3073,6 +3382,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
     }
     //    output link flags       <Link></Link>
     this->WriteLinkOptions(*i);
+    this->WriteCudaLinkOptions(*i);
     //    output lib flags       <Lib></Lib>
     this->WriteLibOptions(*i);
     //    output manifest flags  <Manifest></Manifest>
@@ -3090,18 +3400,15 @@ void cmVisualStudio10TargetGenerator::WriteEvents(
   std::string const& configName)
 {
   bool addedPrelink = false;
-  if ((this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
-       this->GeneratorTarget->IsExecutableWithExports()) &&
-      this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) {
-    if (this->GeneratorTarget->GetPropertyAsBool(
-          "WINDOWS_EXPORT_ALL_SYMBOLS")) {
-      addedPrelink = true;
-      std::vector<cmCustomCommand> commands =
-        this->GeneratorTarget->GetPreLinkCommands();
-      this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
-                                                    commands, configName);
-      this->WriteEvent("PreLinkEvent", commands, configName);
-    }
+  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
+    this->GeneratorTarget->GetModuleDefinitionInfo(configName);
+  if (mdi && mdi->DefFileGenerated) {
+    addedPrelink = true;
+    std::vector<cmCustomCommand> commands =
+      this->GeneratorTarget->GetPreLinkCommands();
+    this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
+                                                  commands, configName);
+    this->WriteEvent("PreLinkEvent", commands, configName);
   }
   if (!addedPrelink) {
     this->WriteEvent("PreLinkEvent",
@@ -3174,10 +3481,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
           ->TargetIsFortranOnly(dt)) {
       continue;
     }
-    if (csproj == this->ProjectType &&
-        !this->GlobalGenerator->TargetIsCSharpOnly(dt)) {
-      continue;
-    }
     this->WriteString("<ProjectReference Include=\"", 2);
     cmLocalGenerator* lg = dt->GetLocalGenerator();
     std::string name = dt->GetName();
@@ -3194,13 +3497,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
     this->ConvertToWindowsSlash(path);
     (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n";
     this->WriteString("<Project>", 3);
-    if (csproj == this->ProjectType) {
-      (*this->BuildFileStream) << "{";
-    }
-    (*this->BuildFileStream) << this->GlobalGenerator->GetGUID(name.c_str());
-    if (csproj == this->ProjectType) {
-      (*this->BuildFileStream) << "}";
-    }
+    (*this->BuildFileStream)
+      << "{" << this->GlobalGenerator->GetGUID(name.c_str()) << "}";
     (*this->BuildFileStream) << "</Project>\n";
     this->WriteString("<Name>", 3);
     (*this->BuildFileStream) << name << "</Name>\n";
@@ -3990,3 +4288,14 @@ bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const
   CloseHandle(h);
   return true;
 }
+
+std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
+  const char* relativeFilePath) const
+{
+  // Always search in the standard modules location.
+  std::string path = cmSystemTools::GetCMakeRoot() + "/";
+  path += relativeFilePath;
+  this->ConvertToWindowsSlash(path);
+
+  return path;
+}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 45464c0..6106615 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -3,7 +3,7 @@
 #ifndef cmVisualStudioTargetGenerator_h
 #define cmVisualStudioTargetGenerator_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <map>
@@ -51,7 +51,7 @@ private:
   };
 
   std::string ConvertPath(std::string const& path, bool forceRelative);
-  void ConvertToWindowsSlash(std::string& s);
+  static void ConvertToWindowsSlash(std::string& s);
   void WriteString(const char* line, int indentLevel);
   void WriteProjectConfigurations();
   void WriteProjectConfigurationValues();
@@ -62,8 +62,7 @@ private:
   void WriteNsightTegraConfigurationValues(std::string const& config);
   void WriteSource(std::string const& tool, cmSourceFile const* sf,
                    const char* end = 0);
-  void WriteSources(std::string const& tool,
-                    std::vector<cmSourceFile const*> const&);
+  void WriteExcludeFromBuild(std::vector<size_t> const& exclude_configs);
   void WriteAllSources();
   void WriteDotNetReferences();
   void WriteDotNetReference(std::string const& ref, std::string const& hint);
@@ -98,10 +97,24 @@ private:
   bool ComputeRcOptions(std::string const& config);
   void WriteRCOptions(std::string const& config,
                       std::vector<std::string> const& includes);
+  bool ComputeCudaOptions();
+  bool ComputeCudaOptions(std::string const& config);
+  void WriteCudaOptions(std::string const& config,
+                        std::vector<std::string> const& includes);
+
+  bool ComputeCudaLinkOptions();
+  bool ComputeCudaLinkOptions(std::string const& config);
+  void WriteCudaLinkOptions(std::string const& config);
+
   bool ComputeMasmOptions();
   bool ComputeMasmOptions(std::string const& config);
   void WriteMasmOptions(std::string const& config,
                         std::vector<std::string> const& includes);
+  bool ComputeNasmOptions();
+  bool ComputeNasmOptions(std::string const& config);
+  void WriteNasmOptions(std::string const& config,
+                        std::vector<std::string> includes);
+
   bool ComputeLinkOptions();
   bool ComputeLinkOptions(std::string const& config);
   bool ComputeLibOptions();
@@ -145,7 +158,10 @@ private:
   typedef std::map<std::string, Options*> OptionsMap;
   OptionsMap ClOptions;
   OptionsMap RcOptions;
+  OptionsMap CudaOptions;
+  OptionsMap CudaLinkOptions;
   OptionsMap MasmOptions;
+  OptionsMap NasmOptions;
   OptionsMap LinkOptions;
   std::string PathToProjectFile;
   std::string ProjectFileExtension;
@@ -177,6 +193,7 @@ private:
 
   typedef std::map<std::string, ToolSources> ToolSourceMap;
   ToolSourceMap Tools;
+  std::string GetCMakeFilePath(const char* name) const;
 };
 
 #endif
diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx
index afca216..9a1d950 100644
--- a/Source/cmVisualStudio10ToolsetOptions.cxx
+++ b/Source/cmVisualStudio10ToolsetOptions.cxx
@@ -26,10 +26,11 @@
 #include "cmVS12RCFlagTable.h"
 #include "cmVS140CLFlagTable.h"
 #include "cmVS140CSharpFlagTable.h"
+#include "cmVS140LinkFlagTable.h"
 #include "cmVS141CLFlagTable.h"
 #include "cmVS141CSharpFlagTable.h"
+#include "cmVS141LinkFlagTable.h"
 #include "cmVS14LibFlagTable.h"
-#include "cmVS14LinkFlagTable.h"
 #include "cmVS14MASMFlagTable.h"
 #include "cmVS14RCFlagTable.h"
 
@@ -114,8 +115,10 @@ cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetLinkFlagTable(
 {
   std::string const useToolset = this->GetToolsetName(name, toolset);
 
-  if ((useToolset == "v140") || (useToolset == "v141")) {
-    return cmVS14LinkFlagTable;
+  if (useToolset == "v141") {
+    return cmVS141LinkFlagTable;
+  } else if (useToolset == "v140") {
+    return cmVS140LinkFlagTable;
   } else if (useToolset == "v120") {
     return cmVS12LinkFlagTable;
   } else if (useToolset == "v110") {
diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h
index 2459f5e..4233337 100644
--- a/Source/cmVisualStudio10ToolsetOptions.h
+++ b/Source/cmVisualStudio10ToolsetOptions.h
@@ -3,7 +3,7 @@
 #ifndef cmVisualStudio10ToolsetOptions_h
 #define cmVisualStudio10ToolsetOptions_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <string>
 
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index da6f9a7..1f808c8 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -44,6 +44,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
   this->FortranRuntimeDebug = false;
   this->FortranRuntimeDLL = false;
   this->FortranRuntimeMT = false;
+
+  this->UnknownFlagField = "AdditionalOptions";
 }
 
 cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
@@ -68,6 +70,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
   this->FortranRuntimeDebug = false;
   this->FortranRuntimeDLL = false;
   this->FortranRuntimeMT = false;
+
+  this->UnknownFlagField = "AdditionalOptions";
 }
 
 void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table)
@@ -82,6 +86,13 @@ void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table)
   }
 }
 
+void cmVisualStudioGeneratorOptions::ClearTables()
+{
+  for (int i = 0; i < FlagTableCount; ++i) {
+    this->FlagTable[i] = CM_NULLPTR;
+  }
+}
+
 void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
 {
   // Exception handling is on by default because the platform file has
@@ -90,10 +101,6 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
   // the flag to disable exception handling.  When the user does
   // remove the flag we need to override the IDE default of on.
   switch (this->Version) {
-    case cmGlobalVisualStudioGenerator::VS7:
-    case cmGlobalVisualStudioGenerator::VS71:
-      this->FlagMap["ExceptionHandling"] = "FALSE";
-      break;
     case cmGlobalVisualStudioGenerator::VS10:
     case cmGlobalVisualStudioGenerator::VS11:
     case cmGlobalVisualStudioGenerator::VS12:
@@ -177,6 +184,78 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const
   return false;
 }
 
+cmVisualStudioGeneratorOptions::CudaRuntime
+cmVisualStudioGeneratorOptions::GetCudaRuntime() const
+{
+  std::map<std::string, FlagValue>::const_iterator i =
+    this->FlagMap.find("CudaRuntime");
+  if (i != this->FlagMap.end() && i->second.size() == 1) {
+    std::string const& cudaRuntime = i->second[0];
+    if (cudaRuntime == "Static") {
+      return CudaRuntimeStatic;
+    }
+    if (cudaRuntime == "Shared") {
+      return CudaRuntimeShared;
+    }
+    if (cudaRuntime == "None") {
+      return CudaRuntimeNone;
+    }
+  }
+  // nvcc default is static
+  return CudaRuntimeStatic;
+}
+
+void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
+{
+  // Extract temporary values stored by our flag table.
+  FlagValue arch = this->TakeFlag("cmake-temp-arch");
+  FlagValue code = this->TakeFlag("cmake-temp-code");
+  FlagValue gencode = this->TakeFlag("cmake-temp-gencode");
+
+  // No -code allowed without -arch.
+  if (arch.empty()) {
+    code.clear();
+  }
+
+  if (arch.empty() && gencode.empty()) {
+    return;
+  }
+
+  // Create a CodeGeneration field with [arch],[code] syntax in each entry.
+  // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`.
+  FlagValue& result = this->FlagMap["CodeGeneration"];
+
+  // First entries for the -arch=<arch> [-code=<code>,...] pair.
+  if (!arch.empty()) {
+    std::string arch_name = arch[0];
+    std::vector<std::string> codes;
+    if (!code.empty()) {
+      codes = cmSystemTools::tokenize(code[0], ",");
+    }
+    if (codes.empty()) {
+      codes.push_back(arch_name);
+      // nvcc -arch=<arch> has a special case that allows a real
+      // architecture to be specified instead of a virtual arch.
+      // It translates to -arch=<virtual> -code=<real>.
+      cmSystemTools::ReplaceString(arch_name, "sm_", "compute_");
+    }
+    for (std::vector<std::string>::iterator ci = codes.begin();
+         ci != codes.end(); ++ci) {
+      std::string entry = arch_name + "," + *ci;
+      result.push_back(entry);
+    }
+  }
+
+  // Now add entries for the -gencode=<arch>,<code> pairs.
+  for (std::vector<std::string>::iterator ei = gencode.begin();
+       ei != gencode.end(); ++ei) {
+    std::string entry = *ei;
+    cmSystemTools::ReplaceString(entry, "arch=", "");
+    cmSystemTools::ReplaceString(entry, "code=", "");
+    result.push_back(entry);
+  }
+}
+
 void cmVisualStudioGeneratorOptions::Parse(const char* flags)
 {
   // Parse the input string as a windows command line since the string
@@ -210,6 +289,44 @@ void cmVisualStudioGeneratorOptions::ParseFinish()
     rl += this->FortranRuntimeDLL ? "DLL" : "";
     this->FlagMap["RuntimeLibrary"] = rl;
   }
+
+  if (this->CurrentTool == CudaCompiler) {
+    std::map<std::string, FlagValue>::iterator i =
+      this->FlagMap.find("CudaRuntime");
+    if (i != this->FlagMap.end() && i->second.size() == 1) {
+      std::string& cudaRuntime = i->second[0];
+      if (cudaRuntime == "static") {
+        cudaRuntime = "Static";
+      } else if (cudaRuntime == "shared") {
+        cudaRuntime = "Shared";
+      } else if (cudaRuntime == "none") {
+        cudaRuntime = "None";
+      }
+    }
+  }
+}
+
+void cmVisualStudioGeneratorOptions::PrependInheritedString(
+  std::string const& key)
+{
+  std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key);
+  if (i == this->FlagMap.end() || i->second.size() != 1) {
+    return;
+  }
+  std::string& value = i->second[0];
+  value = "%(" + key + ") " + value;
+}
+
+void cmVisualStudioGeneratorOptions::Reparse(std::string const& key)
+{
+  std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key);
+  if (i == this->FlagMap.end() || i->second.size() != 1) {
+    return;
+  }
+  std::string const original = i->second[0];
+  i->second[0] = "";
+  this->UnknownFlagField = key;
+  this->Parse(original.c_str());
 }
 
 void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
@@ -235,10 +352,22 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
   }
 
   // This option is not known.  Store it in the output flags.
-  this->FlagString += " ";
-  this->FlagString += cmOutputConverter::EscapeWindowsShellArgument(
+  std::string const opts = cmOutputConverter::EscapeWindowsShellArgument(
     flag, cmOutputConverter::Shell_Flag_AllowMakeVariables |
       cmOutputConverter::Shell_Flag_VSIDE);
+  this->AppendFlagString(this->UnknownFlagField, opts);
+}
+
+cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag(
+  std::string const& key)
+{
+  FlagValue value;
+  std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key);
+  if (i != this->FlagMap.end()) {
+    value = i->second;
+    this->FlagMap.erase(i);
+  }
+  return value;
 }
 
 void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
@@ -253,19 +382,22 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
   if (this->Defines.empty()) {
     return;
   }
+  const char* tag = "PreprocessorDefinitions";
+  if (lang == "CUDA") {
+    tag = "Defines";
+  }
   if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
     // if there are configuration specific flags, then
     // use the configuration specific tag for PreprocessorDefinitions
     if (!this->Configuration.empty()) {
       fout << prefix;
       this->TargetGenerator->WritePlatformConfigTag(
-        "PreprocessorDefinitions", this->Configuration.c_str(), 0, 0, 0,
-        &fout);
+        tag, this->Configuration.c_str(), 0, 0, 0, &fout);
     } else {
-      fout << prefix << "<PreprocessorDefinitions>";
+      fout << prefix << "<" << tag << ">";
     }
   } else {
-    fout << prefix << "PreprocessorDefinitions=\"";
+    fout << prefix << tag << "=\"";
   }
   const char* sep = "";
   std::vector<std::string>::const_iterator de =
@@ -294,7 +426,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
     sep = ";";
   }
   if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
-    fout << ";%(PreprocessorDefinitions)</PreprocessorDefinitions>" << suffix;
+    fout << ";%(" << tag << ")</" << tag << ">" << suffix;
   } else {
     fout << "\"" << suffix;
   }
@@ -335,26 +467,3 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
     }
   }
 }
-
-void cmVisualStudioGeneratorOptions::OutputAdditionalOptions(
-  std::ostream& fout, const char* prefix, const char* suffix)
-{
-  if (!this->FlagString.empty()) {
-    if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
-      fout << prefix;
-      if (!this->Configuration.empty()) {
-        this->TargetGenerator->WritePlatformConfigTag(
-          "AdditionalOptions", this->Configuration.c_str(), 0, 0, 0, &fout);
-      } else {
-        fout << "<AdditionalOptions>";
-      }
-      fout << "%(AdditionalOptions) "
-           << cmVisualStudio10GeneratorOptionsEscapeForXML(this->FlagString)
-           << "</AdditionalOptions>\n";
-    } else {
-      fout << prefix << "AdditionalOptions=\"";
-      fout << cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString);
-      fout << "\"" << suffix;
-    }
-  }
-}
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index ab6b8cc..44d2719 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -3,7 +3,7 @@
 #ifndef cmVisualStudioGeneratorOptions_h
 #define cmVisualStudioGeneratorOptions_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <iosfwd>
 #include <string>
@@ -26,7 +26,9 @@ public:
   {
     Compiler,
     ResourceCompiler,
+    CudaCompiler,
     MasmCompiler,
+    NasmCompiler,
     Linker,
     FortranCompiler,
     CSharpCompiler
@@ -42,10 +44,19 @@ public:
   // Add a table of flags.
   void AddTable(cmVS7FlagTable const* table);
 
+  // Clear the flag tables.
+  void ClearTables();
+
   // Store options from command line flags.
   void Parse(const char* flags);
   void ParseFinish();
 
+  void PrependInheritedString(std::string const& key);
+
+  // Parse the content of the given flag table entry again to extract
+  // known flags and leave the rest in the original entry.
+  void Reparse(std::string const& key);
+
   // Fix the ExceptionHandling option to default to off.
   void FixExceptionHandlingDefault();
 
@@ -56,6 +67,16 @@ public:
   bool UsingUnicode() const;
   bool UsingSBCS() const;
 
+  enum CudaRuntime
+  {
+    CudaRuntimeStatic,
+    CudaRuntimeShared,
+    CudaRuntimeNone
+  };
+  CudaRuntime GetCudaRuntime() const;
+
+  void FixCudaCodeGeneration();
+
   bool IsDebug() const;
   bool IsWinRt() const;
   bool IsManaged() const;
@@ -64,8 +85,6 @@ public:
                                      const char* suffix,
                                      const std::string& lang);
   void OutputFlagMap(std::ostream& fout, const char* indent);
-  void OutputAdditionalOptions(std::ostream& fout, const char* prefix,
-                               const char* suffix);
   void SetConfiguration(const char* config);
 
 private:
@@ -80,7 +99,11 @@ private:
   bool FortranRuntimeDLL;
   bool FortranRuntimeMT;
 
+  std::string UnknownFlagField;
+
   virtual void StoreUnknownFlag(const char* flag);
+
+  FlagValue TakeFlag(std::string const& key);
 };
 
 #endif
diff --git a/Source/cmVisualStudioSlnData.h b/Source/cmVisualStudioSlnData.h
index b2f8db9..e12047f 100644
--- a/Source/cmVisualStudioSlnData.h
+++ b/Source/cmVisualStudioSlnData.h
@@ -3,7 +3,7 @@
 #ifndef cmVisualStudioSlnData_h
 #define cmVisualStudioSlnData_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <map>
 #include <string>
diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx
index 939120a..1a32aba 100644
--- a/Source/cmVisualStudioSlnParser.cxx
+++ b/Source/cmVisualStudioSlnParser.cxx
@@ -4,7 +4,7 @@
 
 #include "cmSystemTools.h"
 #include "cmVisualStudioSlnData.h"
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 
 #include <cassert>
 #include <stack>
diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h
index a3391a6..d517324 100644
--- a/Source/cmVisualStudioSlnParser.h
+++ b/Source/cmVisualStudioSlnParser.h
@@ -3,7 +3,7 @@
 #ifndef cmVisualStudioSlnParser_h
 #define cmVisualStudioSlnParser_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <bitset>
 #include <iosfwd>
diff --git a/Source/cmVisualStudioWCEPlatformParser.h b/Source/cmVisualStudioWCEPlatformParser.h
index 8ed6083..75c3d1a 100644
--- a/Source/cmVisualStudioWCEPlatformParser.h
+++ b/Source/cmVisualStudioWCEPlatformParser.h
@@ -3,7 +3,7 @@
 #ifndef cmVisualStudioWCEPlatformParser_h
 #define cmVisualStudioWCEPlatformParser_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <map>
 #include <stddef.h>
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index 38ea637..24d7bf1 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -82,7 +82,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
           cmExecutionStatus status;
           mf.ExecuteCommand(this->Functions[c], status);
           if (status.GetReturnInvoked()) {
-            inStatus.SetReturnInvoked(true);
+            inStatus.SetReturnInvoked();
             return true;
           }
           if (status.GetBreakInvoked()) {
diff --git a/Source/cmWhileCommand.h b/Source/cmWhileCommand.h
index abd36b3..a95e4c3 100644
--- a/Source/cmWhileCommand.h
+++ b/Source/cmWhileCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmWhileCommand_h
 #define cmWhileCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -56,16 +57,6 @@ public:
   {
     return false;
   }
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "while"; }
 };
 
 #endif
diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx
new file mode 100644
index 0000000..99c9ba8
--- /dev/null
+++ b/Source/cmWorkingDirectory.cxx
@@ -0,0 +1,24 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmWorkingDirectory.h"
+
+#include "cmSystemTools.h"
+
+cmWorkingDirectory::cmWorkingDirectory(std::string const& newdir)
+{
+  this->OldDir = cmSystemTools::GetCurrentWorkingDirectory();
+  cmSystemTools::ChangeDirectory(newdir);
+}
+
+cmWorkingDirectory::~cmWorkingDirectory()
+{
+  this->Pop();
+}
+
+void cmWorkingDirectory::Pop()
+{
+  if (!this->OldDir.empty()) {
+    cmSystemTools::ChangeDirectory(this->OldDir);
+    this->OldDir.clear();
+  }
+}
diff --git a/Source/cmWorkingDirectory.h b/Source/cmWorkingDirectory.h
new file mode 100644
index 0000000..aff9267
--- /dev/null
+++ b/Source/cmWorkingDirectory.h
@@ -0,0 +1,25 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmWorkingDirectory_h
+#define cmWorkingDirectory_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+/** \class cmWorkingDirectory
+ * \brief An RAII class to manipulate the working directory.
+ */
+class cmWorkingDirectory
+{
+public:
+  cmWorkingDirectory(std::string const& newdir);
+  ~cmWorkingDirectory();
+
+  void Pop();
+
+private:
+  std::string OldDir;
+};
+
+#endif
diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx
index 96c8e27..fc5fd21 100644
--- a/Source/cmWriteFileCommand.cxx
+++ b/Source/cmWriteFileCommand.cxx
@@ -2,14 +2,11 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmWriteFileCommand.h"
 
-#include <cmsys/FStream.hxx>
-
-#include <sys/types.h>
-// include sys/stat.h after sys/types.h
-#include <sys/stat.h>
+#include "cmsys/FStream.hxx"
 
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
+#include "cm_sys_stat.h"
 
 class cmExecutionStatus;
 
@@ -24,7 +21,7 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args,
   std::string message;
   std::vector<std::string>::const_iterator i = args.begin();
 
-  std::string fileName = *i;
+  std::string const& fileName = *i;
   bool overwrite = true;
   i++;
 
diff --git a/Source/cmWriteFileCommand.h b/Source/cmWriteFileCommand.h
index 73e6e22..19922cd 100644
--- a/Source/cmWriteFileCommand.h
+++ b/Source/cmWriteFileCommand.h
@@ -3,7 +3,8 @@
 #ifndef cmWriteFileCommand_h
 #define cmWriteFileCommand_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
+
 #include <string>
 #include <vector>
 
@@ -29,16 +30,6 @@ public:
    */
   bool InitialPass(std::vector<std::string> const& args,
                    cmExecutionStatus& status) CM_OVERRIDE;
-
-  /**
-   * This determines if the command is invoked when in script mode.
-   */
-  bool IsScriptable() const CM_OVERRIDE { return true; }
-
-  /**
-   * The name of the command as specified in CMakeList.txt.
-   */
-  std::string GetName() const CM_OVERRIDE { return "write_file"; }
 };
 
 #endif
diff --git a/Source/cmXCode21Object.h b/Source/cmXCode21Object.h
index 083d229..bcd8d93 100644
--- a/Source/cmXCode21Object.h
+++ b/Source/cmXCode21Object.h
@@ -3,7 +3,7 @@
 #ifndef cmXCode21Object_h
 #define cmXCode21Object_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
 #include <vector>
diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx
index 3689ac4..0def8c3 100644
--- a/Source/cmXCodeObject.cxx
+++ b/Source/cmXCodeObject.cxx
@@ -224,11 +224,11 @@ void cmXCodeObject::PrintString(std::ostream& os, std::string String)
 {
   // The string needs to be quoted if it contains any characters
   // considered special by the Xcode project file parser.
-  bool needQuote = (String.empty() || String.find("//") != String.npos ||
+  bool needQuote = (String.empty() || String.find("//") != std::string::npos ||
                     String.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                              "abcdefghijklmnopqrstuvwxyz"
                                              "0123456789"
-                                             "$_./") != String.npos);
+                                             "$_./") != std::string::npos);
   const char* quote = needQuote ? "\"" : "";
 
   // Print the string, quoted and escaped as necessary.
diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h
index 3bfecdf..b92e6e3 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -3,7 +3,7 @@
 #ifndef cmXCodeObject_h
 #define cmXCodeObject_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <algorithm>
 #include <iosfwd>
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
new file mode 100644
index 0000000..5c22531
--- /dev/null
+++ b/Source/cmXCodeScheme.cxx
@@ -0,0 +1,227 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmXCodeScheme.h"
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmXMLSafe.h"
+
+cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj,
+                             const std::vector<std::string>& configList,
+                             unsigned int xcVersion)
+  : Target(xcObj)
+  , TargetName(xcObj->GetTarget()->GetName())
+  , BuildableName(xcObj->GetTarget()->GetFullName())
+  , TargetId(xcObj->GetId())
+  , ConfigList(configList)
+  , XcodeVersion(xcVersion)
+{
+}
+
+void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir,
+                                           const std::string& container)
+{
+  // Create shared scheme sub-directory tree
+  //
+  std::string xcodeSchemeDir = xcProjDir;
+  xcodeSchemeDir += "/xcshareddata/xcschemes";
+  cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str());
+
+  std::string xcodeSchemeFile = xcodeSchemeDir;
+  xcodeSchemeFile += "/";
+  xcodeSchemeFile += this->TargetName;
+  xcodeSchemeFile += ".xcscheme";
+
+  cmGeneratedFileStream fout(xcodeSchemeFile.c_str());
+  fout.SetCopyIfDifferent(true);
+  if (!fout) {
+    return;
+  }
+
+  WriteXCodeXCScheme(fout, container);
+}
+
+void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout,
+                                       const std::string& container)
+{
+  cmXMLWriter xout(fout);
+  xout.SetIndentationElement(std::string(3, ' '));
+  xout.StartDocument();
+
+  xout.StartElement("Scheme");
+  xout.BreakAttributes();
+  xout.Attribute("LastUpgradeVersion", WriteVersionString());
+  xout.Attribute("version", "1.3");
+
+  WriteBuildAction(xout, container);
+  WriteTestAction(xout, FindConfiguration("Debug"));
+  WriteLaunchAction(xout, FindConfiguration("Debug"), container);
+  WriteProfileAction(xout, FindConfiguration("Release"));
+  WriteAnalyzeAction(xout, FindConfiguration("Debug"));
+  WriteArchiveAction(xout, FindConfiguration("Release"));
+
+  xout.EndElement();
+}
+
+void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout,
+                                     const std::string& container)
+{
+  xout.StartElement("BuildAction");
+  xout.BreakAttributes();
+  xout.Attribute("parallelizeBuildables", "YES");
+  xout.Attribute("buildImplicitDependencies", "YES");
+
+  xout.StartElement("BuildActionEntries");
+  xout.StartElement("BuildActionEntry");
+  xout.BreakAttributes();
+  xout.Attribute("buildForTesting", "YES");
+  xout.Attribute("buildForRunning", "YES");
+  xout.Attribute("buildForProfiling", "YES");
+  xout.Attribute("buildForArchiving", "YES");
+  xout.Attribute("buildForAnalyzing", "YES");
+
+  xout.StartElement("BuildableReference");
+  xout.BreakAttributes();
+  xout.Attribute("BuildableIdentifier", "primary");
+  xout.Attribute("BlueprintIdentifier", this->TargetId);
+  xout.Attribute("BuildableName", this->BuildableName);
+  xout.Attribute("BlueprintName", this->TargetName);
+  xout.Attribute("ReferencedContainer", "container:" + container);
+  xout.EndElement();
+
+  xout.EndElement(); // BuildActionEntry
+  xout.EndElement(); // BuildActionEntries
+  xout.EndElement(); // BuildAction
+}
+
+void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout,
+                                    std::string configuration)
+{
+  xout.StartElement("TestAction");
+  xout.BreakAttributes();
+  xout.Attribute("buildConfiguration", configuration);
+  xout.Attribute("selectedDebuggerIdentifier",
+                 "Xcode.DebuggerFoundation.Debugger.LLDB");
+  xout.Attribute("selectedLauncherIdentifier",
+                 "Xcode.DebuggerFoundation.Launcher.LLDB");
+  xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES");
+
+  xout.StartElement("Testables");
+  xout.EndElement();
+
+  xout.StartElement("AdditionalOptions");
+  xout.EndElement();
+
+  xout.EndElement(); // TestAction
+}
+
+void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
+                                      std::string configuration,
+                                      const std::string& container)
+{
+  xout.StartElement("LaunchAction");
+  xout.BreakAttributes();
+  xout.Attribute("buildConfiguration", configuration);
+  xout.Attribute("selectedDebuggerIdentifier",
+                 "Xcode.DebuggerFoundation.Debugger.LLDB");
+  xout.Attribute("selectedLauncherIdentifier",
+                 "Xcode.DebuggerFoundation.Launcher.LLDB");
+  xout.Attribute("launchStyle", "0");
+  xout.Attribute("useCustomWorkingDirectory", "NO");
+  xout.Attribute("ignoresPersistentStateOnLaunch", "NO");
+  xout.Attribute("debugDocumentVersioning", "YES");
+  xout.Attribute("debugServiceExtension", "internal");
+  xout.Attribute("allowLocationSimulation", "YES");
+
+  if (IsExecutable(this->Target)) {
+    xout.StartElement("BuildableProductRunnable");
+    xout.BreakAttributes();
+    xout.Attribute("runnableDebuggingMode", "0");
+
+  } else {
+    xout.StartElement("MacroExpansion");
+  }
+
+  xout.StartElement("BuildableReference");
+  xout.BreakAttributes();
+  xout.Attribute("BuildableIdentifier", "primary");
+  xout.Attribute("BlueprintIdentifier", this->TargetId);
+  xout.Attribute("BuildableName", this->BuildableName);
+  xout.Attribute("BlueprintName", this->TargetName);
+  xout.Attribute("ReferencedContainer", "container:" + container);
+  xout.EndElement();
+
+  xout.EndElement(); // MacroExpansion
+
+  xout.StartElement("AdditionalOptions");
+  xout.EndElement();
+
+  xout.EndElement(); // LaunchAction
+}
+
+void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout,
+                                       std::string configuration)
+{
+  xout.StartElement("ProfileAction");
+  xout.BreakAttributes();
+  xout.Attribute("buildConfiguration", configuration);
+  xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES");
+  xout.Attribute("savedToolIdentifier", "");
+  xout.Attribute("useCustomWorkingDirectory", "NO");
+  xout.Attribute("debugDocumentVersioning", "YES");
+  xout.EndElement();
+}
+
+void cmXCodeScheme::WriteAnalyzeAction(cmXMLWriter& xout,
+                                       std::string configuration)
+{
+  xout.StartElement("AnalyzeAction");
+  xout.BreakAttributes();
+  xout.Attribute("buildConfiguration", configuration);
+  xout.EndElement();
+}
+
+void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout,
+                                       std::string configuration)
+{
+  xout.StartElement("ArchiveAction");
+  xout.BreakAttributes();
+  xout.Attribute("buildConfiguration", configuration);
+  xout.Attribute("revealArchiveInOrganizer", "YES");
+  xout.EndElement();
+}
+
+std::string cmXCodeScheme::WriteVersionString()
+{
+  std::ostringstream v;
+  v << std::setfill('0') << std::setw(4) << this->XcodeVersion * 10;
+  return v.str();
+}
+
+std::string cmXCodeScheme::FindConfiguration(const std::string& name)
+{
+  // Try to find the desired configuration by name,
+  // and if it's not found return first from the list
+  //
+  if (std::find(this->ConfigList.begin(), this->ConfigList.end(), name) ==
+        this->ConfigList.end() &&
+      this->ConfigList.size() > 0)
+    return this->ConfigList[0];
+
+  return name;
+}
+
+bool cmXCodeScheme::IsExecutable(const cmXCodeObject* target)
+{
+  cmGeneratorTarget* gt = target->GetTarget();
+  if (!gt) {
+    cmSystemTools::Error("Error no target on xobject\n");
+    return false;
+  }
+
+  return gt->GetType() == cmStateEnums::EXECUTABLE;
+}
diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h
new file mode 100644
index 0000000..379afed
--- /dev/null
+++ b/Source/cmXCodeScheme.h
@@ -0,0 +1,50 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmXCodeScheme_h
+#define cmXCodeScheme_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmGlobalXCodeGenerator.h"
+#include "cmSystemTools.h"
+#include "cmXCodeObject.h"
+#include "cmXMLWriter.h"
+
+/** \class cmXCodeScheme
+ * \brief Write shared schemes for native targets in Xcode project.
+ */
+class cmXCodeScheme
+{
+public:
+  cmXCodeScheme(cmXCodeObject* xcObj,
+                const std::vector<std::string>& configList,
+                unsigned int xcVersion);
+
+  void WriteXCodeSharedScheme(const std::string& xcProjDir,
+                              const std::string& container);
+
+private:
+  const cmXCodeObject* const Target;
+  const std::string& TargetName;
+  const std::string BuildableName;
+  const std::string& TargetId;
+  const std::vector<std::string>& ConfigList;
+  const unsigned int XcodeVersion;
+
+  void WriteXCodeXCScheme(std::ostream& fout, const std::string& container);
+
+  void WriteBuildAction(cmXMLWriter& xout, const std::string& container);
+  void WriteTestAction(cmXMLWriter& xout, std::string configuration);
+  void WriteLaunchAction(cmXMLWriter& xout, std::string configuration,
+                         const std::string& container);
+  void WriteProfileAction(cmXMLWriter& xout, std::string configuration);
+  void WriteAnalyzeAction(cmXMLWriter& xout, std::string configuration);
+  void WriteArchiveAction(cmXMLWriter& xout, std::string configuration);
+
+  std::string WriteVersionString();
+  std::string FindConfiguration(const std::string& name);
+
+  static bool IsExecutable(const cmXCodeObject* target);
+};
+
+#endif
diff --git a/Source/cmXMLParser.cxx b/Source/cmXMLParser.cxx
index 231e95e..18afbf3 100644
--- a/Source/cmXMLParser.cxx
+++ b/Source/cmXMLParser.cxx
@@ -2,8 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmXMLParser.h"
 
-#include <cm_expat.h>
-#include <cmsys/FStream.hxx>
+#include "cm_expat.h"
+#include "cmsys/FStream.hxx"
 #include <ctype.h>
 #include <iostream>
 #include <sstream>
diff --git a/Source/cmXMLParser.h b/Source/cmXMLParser.h
index 60da51e..98ba049 100644
--- a/Source/cmXMLParser.h
+++ b/Source/cmXMLParser.h
@@ -3,7 +3,7 @@
 #ifndef cmXMLParser_h
 #define cmXMLParser_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 
diff --git a/Source/cmXMLSafe.h b/Source/cmXMLSafe.h
index c41554d..9aaf2d1 100644
--- a/Source/cmXMLSafe.h
+++ b/Source/cmXMLSafe.h
@@ -3,7 +3,7 @@
 #ifndef cmXMLSafe_h
 #define cmXMLSafe_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
 #include <string>
diff --git a/Source/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx
index 2f50fe9..3cbc70d 100644
--- a/Source/cmXMLWriter.cxx
+++ b/Source/cmXMLWriter.cxx
@@ -2,11 +2,12 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmXMLWriter.h"
 
+#include "cmsys/FStream.hxx"
 #include <cassert>
-#include <cmsys/FStream.hxx>
 
 cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
   : Output(output)
+  , IndentationElement(1, '\t')
   , Level(level)
   , ElementOpen(false)
   , BreakAttrib(false)
@@ -100,10 +101,18 @@ void cmXMLWriter::FragmentFile(const char* fname)
   this->Output << fin.rdbuf();
 }
 
+void cmXMLWriter::SetIndentationElement(std::string const& element)
+{
+  this->IndentationElement = element;
+}
+
 void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent)
 {
   if (condition) {
-    this->Output << '\n' << std::string(indent + this->Level, '\t');
+    this->Output << '\n';
+    for (std::size_t i = 0; i < indent + this->Level; ++i) {
+      this->Output << this->IndentationElement;
+    }
   }
 }
 
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
index 904f73b..ed76a88 100644
--- a/Source/cmXMLWriter.h
+++ b/Source/cmXMLWriter.h
@@ -3,7 +3,7 @@
 #ifndef cmXMLWiter_h
 #define cmXMLWiter_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h"
 
 #include "cmXMLSafe.h"
 
@@ -14,6 +14,8 @@
 
 class cmXMLWriter
 {
+  CM_DISABLE_COPY(cmXMLWriter)
+
 public:
   cmXMLWriter(std::ostream& output, std::size_t level = 0);
   ~cmXMLWriter();
@@ -60,10 +62,9 @@ public:
 
   void FragmentFile(const char* fname);
 
-private:
-  cmXMLWriter(const cmXMLWriter&);
-  cmXMLWriter& operator=(const cmXMLWriter&);
+  void SetIndentationElement(std::string const& element);
 
+private:
   void ConditionalLineBreak(bool condition, std::size_t indent);
 
   void PreAttribute();
@@ -107,6 +108,7 @@ private:
 private:
   std::ostream& Output;
   std::stack<std::string, std::vector<std::string> > Elements;
+  std::string IndentationElement;
   std::size_t Level;
   bool ElementOpen;
   bool BreakAttrib;
diff --git a/Source/cm_auto_ptr.hxx b/Source/cm_auto_ptr.hxx
index 5382018..773602a 100644
--- a/Source/cm_auto_ptr.hxx
+++ b/Source/cm_auto_ptr.hxx
@@ -3,7 +3,7 @@
 #ifndef CM_AUTO_PTR_HXX
 #define CM_AUTO_PTR_HXX
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #ifdef CMake_HAVE_CXX_AUTO_PTR
 
@@ -100,10 +100,10 @@ public:
   /** Assign from an auto_ptr holding a compatible object.  This
       transfers ownership to the left-hand-side of the assignment.  */
   template <class Y>
-  auto_ptr& operator=(auto_ptr<Y> cm_AUTO_PTR_CONST& a) throw()
+  auto_ptr& operator=(auto_ptr<Y> cm_AUTO_PTR_CONST& a) throw() // NOLINT
   {
     this->reset(cm_AUTO_PTR_CAST(a).release());
-    return *this;
+    return *this; // NOLINT
   }
 
   /**
@@ -127,10 +127,10 @@ public:
 
   /** Assign from another auto_ptr holding an object of the same type.
       This transfers ownership to the newly constructed auto_ptr.  */
-  auto_ptr& operator=(auto_ptr cm_AUTO_PTR_CONST& a) throw()
+  auto_ptr& operator=(auto_ptr cm_AUTO_PTR_CONST& a) throw() // NOLINT
   {
     this->reset(cm_AUTO_PTR_CAST(a).release());
-    return *this;
+    return *this; // NOLINT
   }
 
   /** Destruct and delete the object held.  */
@@ -192,7 +192,7 @@ public:
   auto_ptr& operator=(detail::auto_ptr_ref<X> r) throw()
   {
     this->reset(r.p_);
-    return *this;
+    return *this; // NOLINT
   }
 
   /** Convert to an auto_ptr_ref.  This is used when a function
diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx
index 869dd32..cf55741 100644
--- a/Source/cm_codecvt.cxx
+++ b/Source/cm_codecvt.cxx
@@ -1,18 +1,23 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cm_codecvt.hxx"
-#include <limits>
 
 #if defined(_WIN32)
+#include <assert.h>
+#include <string.h>
 #include <windows.h>
 #undef max
-#include <cmsys/Encoding.hxx>
+#include "cmsys/Encoding.hxx"
+#endif
+
+#if defined(_WIN32)
+/* Number of leading ones before a zero in the byte (see cm_utf8.c).  */
+extern "C" unsigned char const cm_utf8_ones[256];
 #endif
 
 codecvt::codecvt(Encoding e)
-  : m_lastState(0)
 #if defined(_WIN32)
-  , m_codepage(0)
+  : m_codepage(0)
 #endif
 {
   switch (e) {
@@ -45,76 +50,68 @@ std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from,
                                           const char*& from_next, char* to,
                                           char* to_end, char*& to_next) const
 {
+  from_next = from;
+  to_next = to;
   if (m_noconv) {
-    return noconv;
+    return std::codecvt_base::noconv;
   }
-  std::codecvt_base::result res = error;
 #if defined(_WIN32)
-  from_next = from;
-  to_next = to;
-  bool convert = true;
-  size_t count = from_end - from;
-  const char* data = from;
-  unsigned int& stateId = reinterpret_cast<unsigned int&>(state);
-  if (count == 0) {
-    return codecvt::ok;
-  } else if (count == 1) {
-    if (stateId == 0) {
-      // decode first byte for UTF-8
-      if ((*from & 0xF8) == 0xF0 || // 1111 0xxx; 4 bytes for codepoint
-          (*from & 0xF0) == 0xE0 || // 1110 xxxx; 3 bytes for codepoint
-          (*from & 0xE0) == 0xC0)   // 110x xxxx; 2 bytes for codepoint
-      {
-        stateId = findStateId();
-        codecvt::State& s = m_states.at(stateId - 1);
-        s.bytes[0] = *from;
-        convert = false;
-        if ((*from & 0xF8) == 0xF0) {
-          s.totalBytes = 4;
-        } else if ((*from & 0xF0) == 0xE0) {
-          s.totalBytes = 3;
-        } else if ((*from & 0xE0) == 0xC0) {
-          s.totalBytes = 2;
-        }
-        s.bytesLeft = s.totalBytes - 1;
-      };
-      // else 1 byte for codepoint
-    } else {
-      codecvt::State& s = m_states.at(stateId - 1);
-      s.bytes[s.totalBytes - s.bytesLeft] = *from;
-      s.bytesLeft--;
-      data = s.bytes;
-      count = s.totalBytes - s.bytesLeft;
-      if ((*from & 0xC0) == 0x80) { // 10xx xxxx
-        convert = s.bytesLeft == 0;
-      } else {
-        // invalid multi-byte
-        convert = true;
-      }
-      if (convert) {
-        s.used = false;
-        if (stateId == m_lastState) {
-          m_lastState--;
-        }
-        stateId = 0;
-      }
+  // Use a const view of the state because we should not modify it until we
+  // have fully processed and consume a byte (with sufficient space in the
+  // output buffer).  We call helpers to re-cast and modify the state
+  State const& lstate = reinterpret_cast<State&>(state);
+
+  while (from_next != from_end) {
+    // Count leading ones in the bits of the next byte.
+    unsigned char const ones =
+      cm_utf8_ones[static_cast<unsigned char>(*from_next)];
+
+    if (ones != 1 && lstate.buffered != 0) {
+      // We have a buffered partial codepoint that we never completed.
+      return std::codecvt_base::error;
+    } else if (ones == 1 && lstate.buffered == 0) {
+      // This is a continuation of a codepoint that never started.
+      return std::codecvt_base::error;
+    }
+
+    // Compute the number of bytes in the current codepoint.
+    int need = 0;
+    switch (ones) {
+      case 0: // 0xxx xxxx: new codepoint of size 1
+        need = 1;
+        break;
+      case 1: // 10xx xxxx: continues a codepoint
+        assert(lstate.size != 0);
+        need = lstate.size;
+        break;
+      case 2: // 110x xxxx: new codepoint of size 2
+        need = 2;
+        break;
+      case 3: // 1110 xxxx: new codepoint of size 3
+        need = 3;
+        break;
+      case 4: // 1111 0xxx: new codepoint of size 4
+        need = 4;
+        break;
+      default: // invalid byte
+        return std::codecvt_base::error;
     }
-    if (convert) {
-      std::wstring wide = cmsys::Encoding::ToWide(std::string(data, count));
-      int r = WideCharToMultiByte(m_codepage, 0, wide.c_str(),
-                                  static_cast<int>(wide.size()), to,
-                                  to_end - to, NULL, NULL);
-      if (r > 0) {
-        from_next = from_end;
-        to_next = to + r;
-        res = ok;
+    assert(need > 0);
+
+    if (lstate.buffered + 1 == need) {
+      // This byte completes a codepoint.
+      std::codecvt_base::result decode_result =
+        this->Decode(state, need, from_next, to_next, to_end);
+      if (decode_result != std::codecvt_base::ok) {
+        return decode_result;
       }
     } else {
-      res = partial;
-      from_next = from_end;
-      to_next = to;
+      // This byte does not complete a codepoint.
+      this->BufferPartial(state, need, from_next);
     }
   }
+
+  return std::codecvt_base::ok;
 #else
   static_cast<void>(state);
   static_cast<void>(from);
@@ -123,46 +120,118 @@ std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from,
   static_cast<void>(to);
   static_cast<void>(to_end);
   static_cast<void>(to_next);
-  res = codecvt::noconv;
+  return std::codecvt_base::noconv;
 #endif
-  return res;
 };
 
 std::codecvt_base::result codecvt::do_unshift(mbstate_t& state, char* to,
                                               char* to_end,
                                               char*& to_next) const
 {
-  std::codecvt_base::result res = error;
   to_next = to;
+  if (m_noconv) {
+    return std::codecvt_base::noconv;
+  }
 #if defined(_WIN32)
-  unsigned int& stateId = reinterpret_cast<unsigned int&>(state);
-  if (stateId > 0) {
-    codecvt::State& s = m_states.at(stateId - 1);
-    s.used = false;
-    if (stateId == m_lastState) {
-      m_lastState--;
-    }
-    stateId = 0;
-    std::wstring wide = cmsys::Encoding::ToWide(
-      std::string(s.bytes, s.totalBytes - s.bytesLeft));
-    int r = WideCharToMultiByte(m_codepage, 0, wide.c_str(),
-                                static_cast<int>(wide.size()), to, to_end - to,
-                                NULL, NULL);
-    if (r > 0) {
-      to_next = to + r;
-      res = ok;
-    }
-  } else {
-    res = ok;
+  State& lstate = reinterpret_cast<State&>(state);
+  if (lstate.buffered != 0) {
+    return this->DecodePartial(state, to_next, to_end);
   }
+  return std::codecvt_base::ok;
 #else
   static_cast<void>(state);
   static_cast<void>(to_end);
-  res = ok;
+  return std::codecvt_base::ok;
 #endif
-  return res;
 };
 
+#if defined(_WIN32)
+std::codecvt_base::result codecvt::Decode(mbstate_t& state, int size,
+                                          const char*& from_next,
+                                          char*& to_next, char* to_end) const
+{
+  State& lstate = reinterpret_cast<State&>(state);
+
+  // Collect all the bytes for this codepoint.
+  char buf[4];
+  memcpy(buf, lstate.partial, lstate.buffered);
+  buf[lstate.buffered] = *from_next;
+
+  // Convert the encoding.
+  wchar_t wbuf[2];
+  int wlen =
+    MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buf, size, wbuf, 2);
+  if (wlen <= 0) {
+    return std::codecvt_base::error;
+  }
+
+  int tlen = WideCharToMultiByte(m_codepage, 0, wbuf, wlen, to_next,
+                                 to_end - to_next, NULL, NULL);
+  if (tlen <= 0) {
+    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+      return std::codecvt_base::partial;
+    }
+    return std::codecvt_base::error;
+  }
+
+  // Move past the now-consumed byte in the input buffer.
+  ++from_next;
+
+  // Move past the converted codepoint in the output buffer.
+  to_next += tlen;
+
+  // Re-initialize the state for the next codepoint to start.
+  lstate = State();
+
+  return std::codecvt_base::ok;
+}
+
+std::codecvt_base::result codecvt::DecodePartial(mbstate_t& state,
+                                                 char*& to_next,
+                                                 char* to_end) const
+{
+  State& lstate = reinterpret_cast<State&>(state);
+
+  // Try converting the partial codepoint.
+  wchar_t wbuf[2];
+  int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, lstate.partial,
+                                 lstate.buffered, wbuf, 2);
+  if (wlen <= 0) {
+    return std::codecvt_base::error;
+  }
+
+  int tlen = WideCharToMultiByte(m_codepage, 0, wbuf, wlen, to_next,
+                                 to_end - to_next, NULL, NULL);
+  if (tlen <= 0) {
+    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+      return std::codecvt_base::partial;
+    }
+    return std::codecvt_base::error;
+  }
+
+  // Move past the converted codepoint in the output buffer.
+  to_next += tlen;
+
+  // Re-initialize the state for the next codepoint to start.
+  lstate = State();
+
+  return std::codecvt_base::ok;
+}
+
+void codecvt::BufferPartial(mbstate_t& state, int size,
+                            const char*& from_next) const
+{
+  State& lstate = reinterpret_cast<State&>(state);
+
+  // Save the byte in our buffer for later.
+  lstate.partial[lstate.buffered++] = *from_next;
+  lstate.size = size;
+
+  // Move past the now-consumed byte in the input buffer.
+  ++from_next;
+}
+#endif
+
 int codecvt::do_max_length() const throw()
 {
   return 4;
@@ -172,44 +241,3 @@ int codecvt::do_encoding() const throw()
 {
   return 0;
 };
-
-unsigned int codecvt::findStateId() const
-{
-  unsigned int stateId = 0;
-  bool add = false;
-  const unsigned int maxSize = std::numeric_limits<unsigned int>::max();
-  if (m_lastState >= maxSize) {
-    m_lastState = 0;
-  }
-  if (m_states.size() <= m_lastState) {
-    add = true;
-  } else {
-    unsigned int i = m_lastState;
-    while (i < maxSize) {
-      codecvt::State& s = m_states.at(i);
-      i++;
-      if (!s.used) {
-        m_lastState = i;
-        stateId = m_lastState;
-        s.used = true;
-        s.totalBytes = 0;
-        s.bytesLeft = 0;
-        break;
-      }
-      if (i >= m_states.size()) {
-        i = 0;
-      }
-      if (i == m_lastState) {
-        add = true;
-        break;
-      }
-    }
-  };
-  if (add) {
-    codecvt::State s = { true, 0, 0, { 0, 0, 0, 0 } };
-    m_states.push_back(s);
-    m_lastState = (unsigned int)m_states.size();
-    stateId = m_lastState;
-  }
-  return stateId;
-};
diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx
index fcd9954..30c6d54 100644
--- a/Source/cm_codecvt.hxx
+++ b/Source/cm_codecvt.hxx
@@ -3,10 +3,9 @@
 #ifndef cm_codecvt_hxx
 #define cm_codecvt_hxx
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <locale>
-#include <vector>
 #include <wchar.h>
 
 class codecvt : public std::codecvt<char, char, mbstate_t>
@@ -35,21 +34,30 @@ protected:
   int do_encoding() const throw() CM_OVERRIDE;
 
 private:
-  typedef struct
+  // The mbstate_t argument to do_out and do_unshift is responsible
+  // for storing state between calls.  We cannot control the type
+  // since we want to imbue on standard streams.  However, we do
+  // know that it is a trivial type.  Define our own type to overlay
+  // on it safely with no alignment requirements.
+  struct State
   {
-    bool used;
-    unsigned char totalBytes;
-    unsigned char bytesLeft;
-    char bytes[4];
-  } State;
+    // Buffer bytes we have consumed from a partial codepoint.
+    char partial[3];
 
-  unsigned int findStateId() const;
+    // Number of bytes we have buffered from a partial codepoint.
+    unsigned char buffered : 4;
+
+    // Size of the current codepoint in bytes.
+    unsigned char size : 4;
+  };
 
   bool m_noconv;
-  mutable std::vector<State> m_states;
-  mutable unsigned int m_lastState;
 #if defined(_WIN32)
   unsigned int m_codepage;
+  result Decode(mbstate_t& state, int need, const char*& from_next,
+                char*& to_next, char* to_end) const;
+  result DecodePartial(mbstate_t& state, char*& to_next, char* to_end) const;
+  void BufferPartial(mbstate_t& state, int need, const char*& from_next) const;
 #endif
 
 #endif
diff --git a/Source/cm_sys_stat.h b/Source/cm_sys_stat.h
new file mode 100644
index 0000000..26e4baa
--- /dev/null
+++ b/Source/cm_sys_stat.h
@@ -0,0 +1,14 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cm_sys_stat_h
+#define cm_sys_stat_h
+
+#if defined(_MSC_VER)
+typedef unsigned short mode_t;
+#endif
+
+#include <sys/types.h>
+// include sys/stat.h after sys/types.h
+#include <sys/stat.h>
+
+#endif
diff --git a/Source/cm_unordered_map.hxx b/Source/cm_unordered_map.hxx
index dc8ca35..bf38903 100644
--- a/Source/cm_unordered_map.hxx
+++ b/Source/cm_unordered_map.hxx
@@ -3,7 +3,7 @@
 #ifndef CM_UNORDERED_MAP_HXX
 #define CM_UNORDERED_MAP_HXX
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #if defined(CMake_HAVE_CXX_UNORDERED_MAP)
 
@@ -12,7 +12,7 @@
 
 #elif defined(CMAKE_BUILD_WITH_CMAKE)
 
-#include <cmsys/hash_map.hxx>
+#include "cmsys/hash_map.hxx"
 #define CM_UNORDERED_MAP cmsys::hash_map
 
 #else
diff --git a/Source/cm_unordered_set.hxx b/Source/cm_unordered_set.hxx
index ce58dbf..dd1a9a1 100644
--- a/Source/cm_unordered_set.hxx
+++ b/Source/cm_unordered_set.hxx
@@ -3,7 +3,7 @@
 #ifndef CM_UNORDERED_SET_HXX
 #define CM_UNORDERED_SET_HXX
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #if defined(CMake_HAVE_CXX_UNORDERED_SET)
 
@@ -12,7 +12,7 @@
 
 #elif defined(CMAKE_BUILD_WITH_CMAKE)
 
-#include <cmsys/hash_set.hxx>
+#include "cmsys/hash_set.hxx"
 #define CM_UNORDERED_SET cmsys::hash_set
 
 #else
diff --git a/Source/cm_utf8.c b/Source/cm_utf8.c
index 6c49b52..52af4a6 100644
--- a/Source/cm_utf8.c
+++ b/Source/cm_utf8.c
@@ -15,7 +15,7 @@
 */
 
 /* Number of leading ones before a zero in the byte.  */
-static unsigned char const cm_utf8_ones[256] = {
+unsigned char const cm_utf8_ones[256] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 6141f50..6894393 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -23,10 +23,12 @@
 #include "cmTargetLinkLibraryType.h"
 #include "cmUtils.hxx"
 #include "cmVersionConfig.h"
+#include "cmWorkingDirectory.h"
 #include "cm_auto_ptr.hxx"
+#include "cm_sys_stat.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
-#include <cm_jsoncpp_writer.h>
+#include "cm_jsoncpp_writer.h"
 
 #include "cmGraphVizWriter.h"
 #include "cmVariableWatch.h"
@@ -61,7 +63,6 @@
 #include "cmGlobalVisualStudio12Generator.h"
 #include "cmGlobalVisualStudio14Generator.h"
 #include "cmGlobalVisualStudio15Generator.h"
-#include "cmGlobalVisualStudio71Generator.h"
 #include "cmGlobalVisualStudio8Generator.h"
 #include "cmGlobalVisualStudio9Generator.h"
 #include "cmVSSetupHelper.h"
@@ -105,14 +106,10 @@
 #include <sys/time.h>
 #endif
 
-#include <sys/types.h>
-// include sys/stat.h after sys/types.h
-#include <sys/stat.h> // struct stat
-
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
 #include <algorithm>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/RegularExpression.hxx>
 #include <iostream>
 #include <sstream>
 #include <stdio.h>
@@ -120,8 +117,6 @@
 #include <string.h>
 #include <utility>
 
-class cmCommand;
-
 namespace {
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -141,7 +136,7 @@ void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
   cm->MarkCliAsUsed(variable);
 }
 
-cmake::cmake()
+cmake::cmake(Role role)
 {
   this->Trace = false;
   this->TraceExpand = false;
@@ -179,7 +174,12 @@ cmake::cmake()
 
   this->AddDefaultGenerators();
   this->AddDefaultExtraGenerators();
-  this->AddDefaultCommands();
+  if (role == RoleScript || role == RoleProject) {
+    this->AddScriptingCommands();
+  }
+  if (role == RoleProject) {
+    this->AddProjectCommands();
+  }
 
   // Make sure we can capture the build tool output.
   cmSystemTools::EnableVSConsoleOutput();
@@ -301,7 +301,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
 {
   bool findPackageMode = false;
   for (unsigned int i = 1; i < args.size(); ++i) {
-    std::string arg = args[i];
+    std::string const& arg = args[i];
     if (arg.find("-D", 0) == 0) {
       std::string entry = arg.substr(2);
       if (entry.empty()) {
@@ -447,6 +447,8 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
         cmSystemTools::Error("No cmake script provided.");
         return false;
       }
+      // Register fake project commands that hint misuse in script mode.
+      GetProjectCommandsInScriptMode(this->State);
       this->ReadListFile(args, path.c_str());
     } else if (arg.find("--find-package", 0) == 0) {
       findPackageMode = true;
@@ -615,7 +617,7 @@ void cmake::SetArgs(const std::vector<std::string>& args,
   bool haveToolset = false;
   bool havePlatform = false;
   for (unsigned int i = 1; i < args.size(); ++i) {
-    std::string arg = args[i];
+    std::string const& arg = args[i];
     if (arg.find("-H", 0) == 0) {
       directoriesSet = true;
       std::string path = arg.substr(2);
@@ -1464,8 +1466,7 @@ void cmake::CreateDefaultGlobalGenerator()
     { "11.0", "Visual Studio 11 2012" }, //
     { "10.0", "Visual Studio 10 2010" }, //
     { "9.0", "Visual Studio 9 2008" },   //
-    { "8.0", "Visual Studio 8 2005" },   //
-    { "7.1", "Visual Studio 7 .NET 2003" }
+    { "8.0", "Visual Studio 8 2005" }
   };
   static const char* const vsEntries[] = {
     "\\Setup\\VC;ProductDir", //
@@ -1654,13 +1655,14 @@ const char* cmake::GetCacheDefinition(const std::string& name) const
   return this->State->GetInitializedCacheValue(name);
 }
 
-void cmake::AddDefaultCommands()
+void cmake::AddScriptingCommands()
 {
-  std::vector<cmCommand*> const commands = GetPredefinedCommands();
-  for (std::vector<cmCommand*>::const_iterator i = commands.begin();
-       i != commands.end(); ++i) {
-    this->State->AddCommand(*i);
-  }
+  GetScriptingCommands(this->State);
+}
+
+void cmake::AddProjectCommands()
+{
+  GetProjectCommands(this->State);
 }
 
 void cmake::AddDefaultGenerators()
@@ -1674,7 +1676,6 @@ void cmake::AddDefaultGenerators()
   this->Generators.push_back(cmGlobalVisualStudio10Generator::NewFactory());
   this->Generators.push_back(cmGlobalVisualStudio9Generator::NewFactory());
   this->Generators.push_back(cmGlobalVisualStudio8Generator::NewFactory());
-  this->Generators.push_back(cmGlobalVisualStudio71Generator::NewFactory());
   this->Generators.push_back(cmGlobalBorlandMakefileGenerator::NewFactory());
   this->Generators.push_back(cmGlobalNMakeMakefileGenerator::NewFactory());
   this->Generators.push_back(cmGlobalJOMMakefileGenerator::NewFactory());
@@ -1893,7 +1894,7 @@ int cmake::CheckBuildSystem()
 
   // Read the rerun check file and use it to decide whether to do the
   // global generate.
-  cmake cm;
+  cmake cm(RoleScript); // Actually, all we need is the `set` command.
   cm.SetHomeDirectory("");
   cm.SetHomeOutputDirectory("");
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
@@ -2145,7 +2146,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
   // process the arguments
   bool writeToStdout = true;
   for (unsigned int i = 1; i < args.size(); ++i) {
-    std::string arg = args[i];
+    std::string const& arg = args[i];
     if (arg.find("-G", 0) == 0) {
       std::string value = arg.substr(2);
       if (value.empty()) {
@@ -2199,24 +2200,23 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
     resultFile += "/__cmake_systeminformation/results.txt";
   }
 
-  // now run cmake on the CMakeLists file
-  cmSystemTools::ChangeDirectory(destPath);
-  std::vector<std::string> args2;
-  args2.push_back(args[0]);
-  args2.push_back(destPath);
-  std::string resultArg = "-DRESULT_FILE=";
-  resultArg += resultFile;
-  args2.push_back(resultArg);
-  int res = this->Run(args2, false);
+  {
+    // now run cmake on the CMakeLists file
+    cmWorkingDirectory workdir(destPath);
+    std::vector<std::string> args2;
+    args2.push_back(args[0]);
+    args2.push_back(destPath);
+    std::string resultArg = "-DRESULT_FILE=";
+    resultArg += resultFile;
+    args2.push_back(resultArg);
+    int res = this->Run(args2, false);
 
-  if (res != 0) {
-    std::cerr << "Error: --system-information failed on internal CMake!\n";
-    return res;
+    if (res != 0) {
+      std::cerr << "Error: --system-information failed on internal CMake!\n";
+      return res;
+    }
   }
 
-  // change back to the original directory
-  cmSystemTools::ChangeDirectory(cwd);
-
   // echo results to stdout if needed
   if (writeToStdout) {
     FILE* fin = cmsys::SystemTools::Fopen(resultFile, "r");
@@ -2425,6 +2425,9 @@ int cmake::Build(const std::string& dir, const std::string& target,
     std::string homeOutputOrig = this->GetHomeOutputDirectory();
     this->SetDirectoriesFromFile(cachePath.c_str());
 
+    this->AddScriptingCommands();
+    this->AddProjectCommands();
+
     int ret = this->Configure();
     if (ret) {
       cmSystemTools::Message("CMake Configure step failed.  "
diff --git a/Source/cmake.h b/Source/cmake.h
index 5347745..4ddacf7 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -3,7 +3,7 @@
 #ifndef cmake_h
 #define cmake_h
 
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include <map>
 #include <set>
@@ -16,7 +16,7 @@
 #include "cmStateTypes.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
-#include <cm_jsoncpp_value.h>
+#include "cm_jsoncpp_value.h"
 #endif
 
 class cmExternalMakefileProjectGeneratorFactory;
@@ -55,7 +55,16 @@ struct cmDocumentationEntry;
 
 class cmake
 {
+  CM_DISABLE_COPY(cmake)
+
 public:
+  enum Role
+  {
+    RoleInternal, // no commands
+    RoleScript,   // script commands
+    RoleProject   // all commands
+  };
+
   enum MessageType
   {
     AUTHOR_WARNING,
@@ -110,7 +119,7 @@ public:
   typedef std::map<std::string, cmInstalledFile> InstalledFilesMap;
 
   /// Default constructor
-  cmake();
+  cmake(Role role);
   /// Destructor
   ~cmake();
 
@@ -409,7 +418,7 @@ public:
   void WatchUnusedCli(const std::string& var);
 
   cmState* GetState() const { return this->State; }
-  void SetCurrentSnapshot(cmStateSnapshot snapshot)
+  void SetCurrentSnapshot(cmStateSnapshot const& snapshot)
   {
     this->CurrentSnapshot = snapshot;
   }
@@ -425,7 +434,8 @@ protected:
   typedef std::vector<cmExternalMakefileProjectGeneratorFactory*>
     RegisteredExtraGeneratorsVector;
   RegisteredExtraGeneratorsVector ExtraGenerators;
-  void AddDefaultCommands();
+  void AddScriptingCommands();
+  void AddProjectCommands();
   void AddDefaultGenerators();
   void AddDefaultExtraGenerators();
 
@@ -459,8 +469,6 @@ protected:
   cmVariableWatch* VariableWatch;
 
 private:
-  cmake(const cmake&);          // Not implemented.
-  void operator=(const cmake&); // Not implemented.
   ProgressCallbackType ProgressCallback;
   void* ProgressCallbackClientData;
   bool InTryCompile;
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index b8e227f..c5a6836 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -1,11 +1,6 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
-// include these first, otherwise there will be problems on Windows
-// with GetCurrentDirectory() being redefined
-#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmDocumentation.h"
-#include "cmDynamicLoader.h"
-#endif
+#include "cmConfigure.h"
 
 #include "cmAlgorithms.h"
 #include "cmDocumentationEntry.h"
@@ -17,10 +12,14 @@
 #include "cmake.h"
 #include "cmcmd.h"
 
-#include <cmConfigure.h>
-#include <cmsys/Encoding.hxx>
+#ifdef CMAKE_BUILD_WITH_CMAKE
+#include "cmDocumentation.h"
+#include "cmDynamicLoader.h"
+#endif
+
+#include "cmsys/Encoding.hxx"
 #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-#include <cmsys/ConsoleBuf.hxx>
+#include "cmsys/ConsoleBuf.hxx"
 #endif
 #include <iostream>
 #include <string.h>
@@ -28,7 +27,11 @@
 #include <vector>
 
 #ifdef CMAKE_USE_LIBUV
-#include <cm_uv.h>
+#ifdef _WIN32
+#include <fcntl.h>  /* _O_TEXT */
+#include <stdlib.h> /* _set_fmode, _fmode */
+#endif
+#include "cm_uv.h"
 #endif
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
@@ -169,6 +172,18 @@ int main(int ac, char const* const* av)
   ac = args.argc();
   av = args.argv();
 
+#if defined(CMAKE_USE_LIBUV) && defined(_WIN32)
+  // Perform libuv one-time initialization now, and then un-do its
+  // global _fmode setting so that using libuv does not change the
+  // default file text/binary mode.  See libuv issue 840.
+  uv_loop_close(uv_default_loop());
+#ifdef _MSC_VER
+  _set_fmode(_O_TEXT);
+#else
+  _fmode = _O_TEXT;
+#endif
+#endif
+
   cmSystemTools::EnableMSVCDebugHook();
   cmSystemTools::FindCMakeResources(av[0]);
   if (ac > 1) {
@@ -202,7 +217,7 @@ int do_cmake(int ac, char const* const* av)
   doc.addCMakeStandardDocSections();
   if (doc.CheckOptions(ac, av)) {
     // Construct and print requested documentation.
-    cmake hcm;
+    cmake hcm(cmake::RoleInternal);
     hcm.SetHomeDirectory("");
     hcm.SetHomeOutputDirectory("");
     hcm.AddCMakePaths();
@@ -284,13 +299,15 @@ int do_cmake(int ac, char const* const* av)
     }
   }
   if (sysinfo) {
-    cmake cm;
+    cmake cm(cmake::RoleProject);
     cm.SetHomeDirectory("");
     cm.SetHomeOutputDirectory("");
     int ret = cm.GetSystemInformation(args);
     return ret;
   }
-  cmake cm;
+  cmake::Role const role =
+    workingMode == cmake::NORMAL_MODE ? cmake::RoleProject : cmake::RoleScript;
+  cmake cm(role);
   cm.SetHomeDirectory("");
   cm.SetHomeOutputDirectory("");
   cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void*)&cm);
@@ -408,7 +425,7 @@ static int do_build(int ac, char const* const* av)
     return 1;
   }
 
-  cmake cm;
+  cmake cm(cmake::RoleInternal);
   cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void*)&cm);
   cm.SetProgressCallback(cmakemainProgressCallback, (void*)&cm);
   return cm.Build(dir, target, config, nativeOptions, clean);
diff --git a/Source/cmakexbuild.cxx b/Source/cmakexbuild.cxx
index e166bee..72da456 100644
--- a/Source/cmakexbuild.cxx
+++ b/Source/cmakexbuild.cxx
@@ -1,9 +1,9 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
-#include <cmsys/Process.h>
+#include "cmsys/Process.h"
 #include <iostream>
 #include <string>
 #include <vector>
@@ -29,7 +29,8 @@ int RunXCode(std::vector<const char*>& argv, bool& hitbug)
   std::string line;
   int pipe = cmSystemTools::WaitForLine(cp, line, 100.0, out, err);
   while (pipe != cmsysProcess_Pipe_None) {
-    if (line.find("/bin/sh: bad interpreter: Text file busy") != line.npos) {
+    if (line.find("/bin/sh: bad interpreter: Text file busy") !=
+        std::string::npos) {
       hitbug = true;
       std::cerr << "Hit xcodebuild bug : " << line << "\n";
     }
@@ -37,7 +38,7 @@ int RunXCode(std::vector<const char*>& argv, bool& hitbug)
     // because it may contain bogus errors
     // also remove all output with setenv in it to tone down
     // the verbosity of xcodebuild
-    if (!hitbug && (line.find("setenv") == line.npos)) {
+    if (!hitbug && (line.find("setenv") == std::string::npos)) {
       if (pipe == cmsysProcess_Pipe_STDERR) {
         std::cerr << line << "\n";
       } else if (pipe == cmsysProcess_Pipe_STDOUT) {
diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index b86ad6e..0c5bbe2 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -18,8 +18,8 @@
 // /showIncludes is equivalent to -MD, not -MMD, that is, system headers are
 // included.
 
-#include <cmSystemTools.h>
-#include <cmsys/Encoding.hxx>
+#include "cmSystemTools.h"
+#include "cmsys/Encoding.hxx"
 
 #include <algorithm>
 #include <sstream>
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 823b38f..d5b0861 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -32,12 +32,12 @@
 #include "cmVisualStudioWCEPlatformParser.h"
 #endif
 
+#include "cmConfigure.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Process.h"
+#include "cmsys/Terminal.h"
 #include <algorithm>
-#include <cmConfigure.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Process.h>
-#include <cmsys/Terminal.h>
 #include <iostream>
 #include <sstream>
 #include <stdio.h>
@@ -258,11 +258,18 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
                   << "\n";
         return 1;
       }
-      std::string objfile;
+      std::string file;
       bindexplib deffile;
-      while (cmSystemTools::GetLineFromStream(fin, objfile)) {
-        if (!deffile.AddObjectFile(objfile.c_str())) {
-          return 1;
+      while (cmSystemTools::GetLineFromStream(fin, file)) {
+        std::string const& ext = cmSystemTools::GetFilenameLastExtension(file);
+        if (cmSystemTools::LowerCase(ext) == ".def") {
+          if (!deffile.AddDefinitionFile(file.c_str())) {
+            return 1;
+          }
+        } else {
+          if (!deffile.AddObjectFile(file.c_str())) {
+            return 1;
+          }
         }
       }
       deffile.WriteFile(fout);
@@ -344,8 +351,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
         }
 
         // Warn if iwyu reported anything.
-        if (stdErr.find("should remove these lines:") != stdErr.npos ||
-            stdErr.find("should add these lines:") != stdErr.npos) {
+        if (stdErr.find("should remove these lines:") != std::string::npos ||
+            stdErr.find("should add these lines:") != std::string::npos) {
           std::cerr << "Warning: include-what-you-use reported diagnostics:\n"
                     << stdErr << "\n";
         }
@@ -405,7 +412,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
 
         // Output the stdout from ldd -r -u to stderr
         // Warn if lwyu reported anything.
-        if (stdOut.find("Unused direct dependencies:") != stdOut.npos) {
+        if (stdOut.find("Unused direct dependencies:") != std::string::npos) {
           std::cerr << "Warning: " << stdOut;
         }
       }
@@ -473,7 +480,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
           std::cerr << "cmake -E env: unknown option '" << a << "'"
                     << std::endl;
           return 1;
-        } else if (a.find('=') != a.npos) {
+        } else if (a.find('=') != std::string::npos) {
           // Set environment variable.
           cmSystemTools::PutEnv(a);
         } else {
@@ -576,7 +583,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
         std::cerr << "-E capabilities accepts no additional arguments\n";
         return 1;
       }
-      cmake cm;
+      cmake cm(cmake::RoleInternal);
 #if defined(HAVE_SERVER_MODE) && HAVE_SERVER_MODE
       std::cout << cm.ReportCapabilities(true);
 #else
@@ -656,7 +663,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
 
     // Command to change directory and run a program.
     if (args[1] == "chdir" && args.size() >= 4) {
-      std::string directory = args[2];
+      std::string const& directory = args[2];
       if (!cmSystemTools::FileExists(directory.c_str())) {
         cmSystemTools::Error("Directory does not exist for chdir command: ",
                              args[2].c_str());
@@ -753,7 +760,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
       const bool verbose = isCMakeVerbose();
 
       // Create a cmake object instance to process dependencies.
-      cmake cm;
+      cmake cm(cmake::RoleScript); // All we need is the `set` command.
       std::string gen;
       std::string homeDir;
       std::string startDir;
@@ -876,8 +883,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
     if (args[1] == "tar" && args.size() > 3) {
       const char* knownFormats[] = { "7zip", "gnutar", "pax", "paxr", "zip" };
 
-      std::string flags = args[2];
-      std::string outFile = args[3];
+      std::string const& flags = args[2];
+      std::string const& outFile = args[3];
       std::vector<std::string> files;
       std::string mtime;
       std::string format;
@@ -917,15 +924,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
         cmSystemTools::TarCompressNone;
       bool verbose = false;
       int nCompress = 0;
-      if (flags.find_first_of('j') != flags.npos) {
+      if (flags.find_first_of('j') != std::string::npos) {
         compress = cmSystemTools::TarCompressBZip2;
         ++nCompress;
       }
-      if (flags.find_first_of('J') != flags.npos) {
+      if (flags.find_first_of('J') != std::string::npos) {
         compress = cmSystemTools::TarCompressXZ;
         ++nCompress;
       }
-      if (flags.find_first_of('z') != flags.npos) {
+      if (flags.find_first_of('z') != std::string::npos) {
         compress = cmSystemTools::TarCompressGZip;
         ++nCompress;
       }
@@ -939,22 +946,22 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
                              "at most one flag of z, j, or J may be used");
         return 1;
       }
-      if (flags.find_first_of('v') != flags.npos) {
+      if (flags.find_first_of('v') != std::string::npos) {
         verbose = true;
       }
 
-      if (flags.find_first_of('t') != flags.npos) {
+      if (flags.find_first_of('t') != std::string::npos) {
         if (!cmSystemTools::ListTar(outFile.c_str(), verbose)) {
           cmSystemTools::Error("Problem listing tar: ", outFile.c_str());
           return 1;
         }
-      } else if (flags.find_first_of('c') != flags.npos) {
+      } else if (flags.find_first_of('c') != std::string::npos) {
         if (!cmSystemTools::CreateTar(outFile.c_str(), files, compress,
                                       verbose, mtime, format)) {
           cmSystemTools::Error("Problem creating tar: ", outFile.c_str());
           return 1;
         }
-      } else if (flags.find_first_of('x') != flags.npos) {
+      } else if (flags.find_first_of('x') != std::string::npos) {
         if (!cmSystemTools::ExtractTar(outFile.c_str(), verbose)) {
           cmSystemTools::Error("Problem extracting tar: ", outFile.c_str());
           return 1;
@@ -1070,9 +1077,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
 int cmcmd::SymlinkLibrary(std::vector<std::string>& args)
 {
   int result = 0;
-  std::string realName = args[2];
-  std::string soName = args[3];
-  std::string name = args[4];
+  std::string const& realName = args[2];
+  std::string const& soName = args[3];
+  std::string const& name = args[4];
   if (soName != realName) {
     if (!cmcmd::SymlinkInternal(realName, soName)) {
       cmSystemTools::ReportLastSystemError("cmake_symlink_library");
@@ -1091,8 +1098,8 @@ int cmcmd::SymlinkLibrary(std::vector<std::string>& args)
 int cmcmd::SymlinkExecutable(std::vector<std::string>& args)
 {
   int result = 0;
-  std::string realName = args[2];
-  std::string name = args[3];
+  std::string const& realName = args[2];
+  std::string const& name = args[3];
   if (name != realName) {
     if (!cmcmd::SymlinkInternal(realName, name)) {
       cmSystemTools::ReportLastSystemError("cmake_symlink_executable");
@@ -1265,7 +1272,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
   int result = 0;
   while (result == 0 && cmSystemTools::GetLineFromStream(fin, command)) {
     // Skip empty command lines.
-    if (command.find_first_not_of(" \t") == command.npos) {
+    if (command.find_first_not_of(" \t") == std::string::npos) {
       continue;
     }
 
@@ -1413,7 +1420,7 @@ static bool RunCommand(const char* comment, std::vector<std::string>& command,
   // it is the dumb rc command banner, but if the command
   // returned an error code then print the output anyway as
   // the banner may be mixed with some other important information.
-  if (output.find("Resource Compiler Version") == output.npos || !res ||
+  if (output.find("Resource Compiler Version") == std::string::npos || !res ||
       retCode) {
     std::cout << output;
   }
@@ -1443,7 +1450,8 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
     if (*arg == "--") {
       ++arg;
       break;
-    } else if (*arg == "--manifests") {
+    }
+    if (*arg == "--manifests") {
       for (++arg; arg != argEnd && !cmHasLiteralPrefix(*arg, "-"); ++arg) {
         this->UserManifests.push_back(*arg);
       }
diff --git a/Source/cmcmd.h b/Source/cmcmd.h
index 139d2a8..929f1ae 100644
--- a/Source/cmcmd.h
+++ b/Source/cmcmd.h
@@ -3,7 +3,7 @@
 #ifndef cmcmd_h
 #define cmcmd_h
 
-#include <cmConfigure.h> // IWYU pragma: keep
+#include "cmConfigure.h" // IWYU pragma: keep
 
 #include <string>
 #include <vector>
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 1cf75c8..84e815d 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -1,17 +1,16 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
-#include <cmConfigure.h>
+#include "cmConfigure.h"
 
 #include "CTest/cmCTestLaunch.h"
 #include "CTest/cmCTestScriptHandler.h"
 #include "cmCTest.h"
 #include "cmDocumentation.h"
 #include "cmSystemTools.h"
-#include "cmake.h"
 
-#include <cmsys/Encoding.hxx>
+#include "cmsys/Encoding.hxx"
 #if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-#include <cmsys/ConsoleBuf.hxx>
+#include "cmsys/ConsoleBuf.hxx"
 #endif
 #include <iostream>
 #include <string.h>
@@ -52,6 +51,18 @@ static const char* cmDocumentationOptions[][2] = {
                                            "expression." },
   { "-LE <regex>, --label-exclude <regex>", "Exclude tests with labels "
                                             "matching regular expression." },
+  { "-FA <regex>, --fixture-exclude-any <regex>", "Do not automatically "
+                                                  "add any tests for "
+                                                  "fixtures matching "
+                                                  "regular expression." },
+  { "-FS <regex>, --fixture-exclude-setup <regex>", "Do not automatically "
+                                                    "add setup tests for "
+                                                    "fixtures matching "
+                                                    "regular expression." },
+  { "-FC <regex>, --fixture-exclude-cleanup <regex>", "Do not automatically "
+                                                      "add cleanup tests for "
+                                                      "fixtures matching "
+                                                      "regular expression." },
   { "-D <dashboard>, --dashboard <dashboard>", "Execute dashboard test" },
   { "-D <var>:<type>=<value>", "Define a variable for script mode" },
   { "-M <model>, --test-model <model>", "Sets the model for a dashboard" },
@@ -158,11 +169,6 @@ int main(int argc, char const* const* argv)
     cmDocumentation doc;
     doc.addCTestStandardDocSections();
     if (doc.CheckOptions(argc, argv)) {
-      cmake hcm;
-      hcm.SetHomeDirectory("");
-      hcm.SetHomeOutputDirectory("");
-      hcm.AddCMakePaths();
-
       // Construct and print requested documentation.
       cmCTestScriptHandler* ch =
         static_cast<cmCTestScriptHandler*>(inst.GetHandler("script"));
diff --git a/Source/kwsys/.gitattributes b/Source/kwsys/.gitattributes
index a121ad1..7065eb5 100644
--- a/Source/kwsys/.gitattributes
+++ b/Source/kwsys/.gitattributes
@@ -1,12 +1,13 @@
 .git*            export-ignore
 
-*.c              whitespace=tab-in-indent,no-lf-at-eof
-*.h              whitespace=tab-in-indent,no-lf-at-eof
-*.h.in           whitespace=tab-in-indent,no-lf-at-eof
-*.cxx            whitespace=tab-in-indent,no-lf-at-eof
-*.hxx            whitespace=tab-in-indent,no-lf-at-eof
-*.hxx.in         whitespace=tab-in-indent,no-lf-at-eof
-*.txt            whitespace=tab-in-indent,no-lf-at-eof
-*.cmake          whitespace=tab-in-indent,no-lf-at-eof
+*.c              kwsys-c-style
+*.c.in           kwsys-c-style
+*.cxx            kwsys-c-style
+*.h              kwsys-c-style
+*.h.in           kwsys-c-style
+*.hxx            kwsys-c-style
+*.hxx.in         kwsys-c-style
 
+*.cmake          whitespace=tab-in-indent
 *.rst            whitespace=tab-in-indent conflict-marker-size=79
+*.txt            whitespace=tab-in-indent
diff --git a/Source/kwsys/Base64.c b/Source/kwsys/Base64.c
index 37c3b8c..99f008e 100644
--- a/Source/kwsys/Base64.c
+++ b/Source/kwsys/Base64.c
@@ -9,13 +9,11 @@
 #include "Base64.h.in"
 #endif
 
-/*--------------------------------------------------------------------------*/
 static const unsigned char kwsysBase64EncodeTable[65] =
   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   "abcdefghijklmnopqrstuvwxyz"
   "0123456789+/";
 
-/*--------------------------------------------------------------------------*/
 static const unsigned char kwsysBase64DecodeTable[256] = {
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -40,19 +38,16 @@ static const unsigned char kwsysBase64DecodeTable[256] = {
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 };
 
-/*--------------------------------------------------------------------------*/
 static unsigned char kwsysBase64EncodeChar(int c)
 {
   return kwsysBase64EncodeTable[(unsigned char)c];
 }
 
-/*--------------------------------------------------------------------------*/
 static unsigned char kwsysBase64DecodeChar(unsigned char c)
 {
   return kwsysBase64DecodeTable[c];
 }
 
-/*--------------------------------------------------------------------------*/
 /* Encode 3 bytes into a 4 byte string. */
 void kwsysBase64_Encode3(const unsigned char* src, unsigned char* dest)
 {
@@ -64,7 +59,6 @@ void kwsysBase64_Encode3(const unsigned char* src, unsigned char* dest)
   dest[3] = kwsysBase64EncodeChar(src[2] & 0x3F);
 }
 
-/*--------------------------------------------------------------------------*/
 /* Encode 2 bytes into a 4 byte string. */
 void kwsysBase64_Encode2(const unsigned char* src, unsigned char* dest)
 {
@@ -75,7 +69,6 @@ void kwsysBase64_Encode2(const unsigned char* src, unsigned char* dest)
   dest[3] = '=';
 }
 
-/*--------------------------------------------------------------------------*/
 /* Encode 1 bytes into a 4 byte string. */
 void kwsysBase64_Encode1(const unsigned char* src, unsigned char* dest)
 {
@@ -85,7 +78,6 @@ void kwsysBase64_Encode1(const unsigned char* src, unsigned char* dest)
   dest[3] = '=';
 }
 
-/*--------------------------------------------------------------------------*/
 /* Encode 'length' bytes from the input buffer and store the
    encoded stream into the output buffer. Return the length of the encoded
    buffer (output). Note that the output buffer must be allocated by the caller
@@ -135,7 +127,6 @@ size_t kwsysBase64_Encode(const unsigned char* input, size_t length,
   return (size_t)(optr - output);
 }
 
-/*--------------------------------------------------------------------------*/
 /* Decode 4 bytes into a 3 byte string. */
 int kwsysBase64_Decode3(const unsigned char* src, unsigned char* dest)
 {
@@ -169,7 +160,6 @@ int kwsysBase64_Decode3(const unsigned char* src, unsigned char* dest)
   return 3;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Decode bytes from the input buffer and store the decoded stream
    into the output buffer until 'length' bytes have been decoded.  Return the
    real length of the decoded stream (which should be equal to 'length'). Note
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index d4fe8a7..e915b1a 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -69,6 +69,7 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR)
 FOREACH(p
     CMP0025 # CMake 3.0, Compiler id for Apple Clang is now AppleClang.
+    CMP0048 # CMake 3.0, Let the project command manage version variables.
     CMP0056 # CMake 3.2, Honor link flags in try_compile() source-file signature.
     CMP0063 # CMake 3.3, Honor visibility properties for all target types.
     )
@@ -796,6 +797,10 @@ ENDFOREACH()
 IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
   ADD_LIBRARY(${KWSYS_NAMESPACE} ${KWSYS_LIBRARY_TYPE}
     ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS})
+  SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY C_CLANG_TIDY "")
+  SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY CXX_CLANG_TIDY "")
+  SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY C_INCLUDE_WHAT_YOU_USE "")
+  SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
   SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY LABELS ${KWSYS_LABELS_LIB})
   IF(KWSYS_USE_DynamicLoader)
     IF(UNIX)
@@ -940,13 +945,17 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
     ENDIF()
     IF(KWSYS_USE_ConsoleBuf)
       ADD_EXECUTABLE(testConsoleBufChild testConsoleBufChild.cxx)
+      SET_PROPERTY(TARGET testConsoleBufChild PROPERTY C_CLANG_TIDY "")
+      SET_PROPERTY(TARGET testConsoleBufChild PROPERTY CXX_CLANG_TIDY "")
+      SET_PROPERTY(TARGET testConsoleBufChild PROPERTY C_INCLUDE_WHAT_YOU_USE "")
+      SET_PROPERTY(TARGET testConsoleBufChild PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
       SET_PROPERTY(TARGET testConsoleBufChild PROPERTY LABELS ${KWSYS_LABELS_EXE})
       TARGET_LINK_LIBRARIES(testConsoleBufChild ${KWSYS_NAMESPACE})
       SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
         testConsoleBuf
         )
       IF("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND
-         NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0")
+         CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "19.0.23506")
         set_property(SOURCE testConsoleBuf.cxx testConsoleBufChild.cxx PROPERTY COMPILE_FLAGS /utf-8)
       ENDIF()
       SET_PROPERTY(SOURCE testConsoleBuf.cxx APPEND PROPERTY COMPILE_DEFINITIONS
@@ -967,6 +976,10 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
       ${KWSYS_CXX_TESTS}
       )
     ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_CXX_TEST_SRCS})
+    SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_CLANG_TIDY "")
+    SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_CLANG_TIDY "")
+    SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_INCLUDE_WHAT_YOU_USE "")
+    SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
     SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY LABELS ${KWSYS_LABELS_EXE})
     TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_NAMESPACE})
 
@@ -1032,8 +1045,12 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
     # Some Apple compilers produce bad optimizations in this source.
     IF(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$")
       SET_SOURCE_FILES_PROPERTIES(testProcess.c PROPERTIES COMPILE_FLAGS -O0)
-    ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL")
+    ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL" AND
+           NOT (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND
+                NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1"))
       # Tell IBM XL not to warn about our test infinite loop
+      # v13.1.1 and newer on Linux ppc64le is clang based and does not accept
+      # the -qsuppress option
       SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS -qsuppress=1500-010)
     ENDIF()
 
diff --git a/Source/kwsys/CONTRIBUTING.rst b/Source/kwsys/CONTRIBUTING.rst
index d71832a..70a313e 100644
--- a/Source/kwsys/CONTRIBUTING.rst
+++ b/Source/kwsys/CONTRIBUTING.rst
@@ -27,10 +27,12 @@ copies of KWSys within dependent projects can be updated to get the changes.
 Code Style
 ==========
 
-We use `clang-format`_ to define our style for C++ code in the KWSys source
-tree.  See the `.clang-format`_ configuration file for our style settings.
-Use ``clang-format`` version 3.8 or higher to format source files.
-See also the `clang-format.bash`_ script.
+We use `clang-format`_ version **3.8** to define our style for C++ code in
+the KWSys source tree.  See the `.clang-format`_ configuration file for
+our style settings.  Use the `clang-format.bash`_ script to format source
+code.  It automatically runs ``clang-format`` on the set of source files
+for which we enforce style.  The script also has options to format only
+a subset of files, such as those that are locally modified.
 
 .. _`clang-format`: http://clang.llvm.org/docs/ClangFormat.html
 .. _`.clang-format`: .clang-format
diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx
index 226263c..5613bd7 100644
--- a/Source/kwsys/CommandLineArguments.cxx
+++ b/Source/kwsys/CommandLineArguments.cxx
@@ -41,8 +41,6 @@
 
 namespace KWSYS_NAMESPACE {
 
-//----------------------------------------------------------------------------
-//============================================================================
 struct CommandLineArgumentsCallbackStructure
 {
   const char* Argument;
@@ -91,10 +89,7 @@ public:
 
   VectorOfStrings UnusedArguments;
 };
-//============================================================================
-//----------------------------------------------------------------------------
 
-//----------------------------------------------------------------------------
 CommandLineArguments::CommandLineArguments()
 {
   this->Internals = new CommandLineArguments::Internal;
@@ -103,13 +98,11 @@ CommandLineArguments::CommandLineArguments()
   this->StoreUnusedArgumentsFlag = false;
 }
 
-//----------------------------------------------------------------------------
 CommandLineArguments::~CommandLineArguments()
 {
   delete this->Internals;
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::Initialize(int argc, const char* const argv[])
 {
   int cc;
@@ -121,26 +114,22 @@ void CommandLineArguments::Initialize(int argc, const char* const argv[])
   }
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::Initialize(int argc, char* argv[])
 {
   this->Initialize(argc, static_cast<const char* const*>(argv));
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::Initialize()
 {
   this->Internals->Argv.clear();
   this->Internals->LastArgument = 0;
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::ProcessArgument(const char* arg)
 {
   this->Internals->Argv.push_back(arg);
 }
 
-//----------------------------------------------------------------------------
 bool CommandLineArguments::GetMatchedArguments(
   std::vector<std::string>* matches, const std::string& arg)
 {
@@ -164,7 +153,6 @@ bool CommandLineArguments::GetMatchedArguments(
   return !matches->empty();
 }
 
-//----------------------------------------------------------------------------
 int CommandLineArguments::Parse()
 {
   std::vector<std::string>::size_type cc;
@@ -286,7 +274,6 @@ int CommandLineArguments::Parse()
   return 1;
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv)
 {
   CommandLineArguments::Internal::VectorOfStrings::size_type size =
@@ -310,7 +297,6 @@ void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv)
   *argv = args;
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::GetUnusedArguments(int* argc, char*** argv)
 {
   CommandLineArguments::Internal::VectorOfStrings::size_type size =
@@ -334,7 +320,6 @@ void CommandLineArguments::GetUnusedArguments(int* argc, char*** argv)
   *argv = args;
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::DeleteRemainingArguments(int argc, char*** argv)
 {
   int cc;
@@ -344,7 +329,6 @@ void CommandLineArguments::DeleteRemainingArguments(int argc, char*** argv)
   delete[] * argv;
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::AddCallback(const char* argument,
                                        ArgumentTypeEnum type,
                                        CallbackType callback, void* call_data,
@@ -363,7 +347,6 @@ void CommandLineArguments::AddCallback(const char* argument,
   this->GenerateHelp();
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::AddArgument(const char* argument,
                                        ArgumentTypeEnum type,
                                        VariableTypeEnum vtype, void* variable,
@@ -382,7 +365,6 @@ void CommandLineArguments::AddArgument(const char* argument,
   this->GenerateHelp();
 }
 
-//----------------------------------------------------------------------------
 #define CommandLineArgumentsAddArgumentMacro(type, ctype)                     \
   void CommandLineArguments::AddArgument(const char* argument,                \
                                          ArgumentTypeEnum type,               \
@@ -392,22 +374,24 @@ void CommandLineArguments::AddArgument(const char* argument,
                       variable, help);                                        \
   }
 
+/* clang-format off */
 CommandLineArgumentsAddArgumentMacro(BOOL, bool)
-  CommandLineArgumentsAddArgumentMacro(INT, int)
-    CommandLineArgumentsAddArgumentMacro(DOUBLE, double)
-      CommandLineArgumentsAddArgumentMacro(STRING, char*)
-        CommandLineArgumentsAddArgumentMacro(STL_STRING, std::string)
-
-          CommandLineArgumentsAddArgumentMacro(VECTOR_BOOL, std::vector<bool>)
-            CommandLineArgumentsAddArgumentMacro(VECTOR_INT, std::vector<int>)
-              CommandLineArgumentsAddArgumentMacro(VECTOR_DOUBLE,
-                                                   std::vector<double>)
-                CommandLineArgumentsAddArgumentMacro(VECTOR_STRING,
-                                                     std::vector<char*>)
-                  CommandLineArgumentsAddArgumentMacro(
-                    VECTOR_STL_STRING, std::vector<std::string>)
-
-//----------------------------------------------------------------------------
+CommandLineArgumentsAddArgumentMacro(INT, int)
+CommandLineArgumentsAddArgumentMacro(DOUBLE, double)
+CommandLineArgumentsAddArgumentMacro(STRING, char*)
+CommandLineArgumentsAddArgumentMacro(STL_STRING, std::string)
+
+CommandLineArgumentsAddArgumentMacro(VECTOR_BOOL, std::vector<bool>)
+CommandLineArgumentsAddArgumentMacro(VECTOR_INT, std::vector<int>)
+CommandLineArgumentsAddArgumentMacro(VECTOR_DOUBLE, std::vector<double>)
+CommandLineArgumentsAddArgumentMacro(VECTOR_STRING, std::vector<char*>)
+CommandLineArgumentsAddArgumentMacro(VECTOR_STL_STRING,
+                                     std::vector<std::string>)
+#ifdef HELP_CLANG_FORMAT
+;
+#endif
+/* clang-format on */
+
 #define CommandLineArgumentsAddBooleanArgumentMacro(type, ctype)              \
   void CommandLineArguments::AddBooleanArgument(                              \
     const char* argument, ctype* variable, const char* help)                  \
@@ -416,29 +400,28 @@ CommandLineArgumentsAddArgumentMacro(BOOL, bool)
                       CommandLineArguments::type##_TYPE, variable, help);     \
   }
 
-                    CommandLineArgumentsAddBooleanArgumentMacro(BOOL, bool)
-                      CommandLineArgumentsAddBooleanArgumentMacro(INT, int)
-                        CommandLineArgumentsAddBooleanArgumentMacro(DOUBLE,
-                                                                    double)
-                          CommandLineArgumentsAddBooleanArgumentMacro(STRING,
-                                                                      char*)
-                            CommandLineArgumentsAddBooleanArgumentMacro(
-                              STL_STRING, std::string)
+/* clang-format off */
+CommandLineArgumentsAddBooleanArgumentMacro(BOOL, bool)
+CommandLineArgumentsAddBooleanArgumentMacro(INT, int)
+CommandLineArgumentsAddBooleanArgumentMacro(DOUBLE, double)
+CommandLineArgumentsAddBooleanArgumentMacro(STRING, char*)
+CommandLineArgumentsAddBooleanArgumentMacro(STL_STRING, std::string)
+#ifdef HELP_CLANG_FORMAT
+;
+#endif
+/* clang-format on */
 
-  //----------------------------------------------------------------------------
-  void CommandLineArguments::SetClientData(void* client_data)
+void CommandLineArguments::SetClientData(void* client_data)
 {
   this->Internals->ClientData = client_data;
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::SetUnknownArgumentCallback(
   CommandLineArguments::ErrorCallbackType callback)
 {
   this->Internals->UnknownArgumentCallback = callback;
 }
 
-//----------------------------------------------------------------------------
 const char* CommandLineArguments::GetHelp(const char* arg)
 {
   CommandLineArguments::Internal::CallbacksMap::iterator it =
@@ -461,7 +444,6 @@ const char* CommandLineArguments::GetHelp(const char* arg)
   return cs->Help;
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::SetLineLength(unsigned int ll)
 {
   if (ll < 9 || ll > 1000) {
@@ -471,19 +453,16 @@ void CommandLineArguments::SetLineLength(unsigned int ll)
   this->GenerateHelp();
 }
 
-//----------------------------------------------------------------------------
 const char* CommandLineArguments::GetArgv0()
 {
   return this->Internals->Argv0.c_str();
 }
 
-//----------------------------------------------------------------------------
 unsigned int CommandLineArguments::GetLastArgument()
 {
   return static_cast<unsigned int>(this->Internals->LastArgument + 1);
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::GenerateHelp()
 {
   std::ostringstream str;
@@ -633,7 +612,6 @@ void CommandLineArguments::GenerateHelp()
   this->Help = str.str();
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(bool* variable,
                                             const std::string& value)
 {
@@ -646,7 +624,6 @@ void CommandLineArguments::PopulateVariable(bool* variable,
   }
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(int* variable,
                                             const std::string& value)
 {
@@ -658,7 +635,6 @@ void CommandLineArguments::PopulateVariable(int* variable,
   //  }
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(double* variable,
                                             const std::string& value)
 {
@@ -670,7 +646,6 @@ void CommandLineArguments::PopulateVariable(double* variable,
   //  }
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(char** variable,
                                             const std::string& value)
 {
@@ -682,14 +657,12 @@ void CommandLineArguments::PopulateVariable(char** variable,
   strcpy(*variable, value.c_str());
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(std::string* variable,
                                             const std::string& value)
 {
   *variable = value;
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(std::vector<bool>* variable,
                                             const std::string& value)
 {
@@ -702,7 +675,6 @@ void CommandLineArguments::PopulateVariable(std::vector<bool>* variable,
   variable->push_back(val);
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(std::vector<int>* variable,
                                             const std::string& value)
 {
@@ -714,7 +686,6 @@ void CommandLineArguments::PopulateVariable(std::vector<int>* variable,
   //  }
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(std::vector<double>* variable,
                                             const std::string& value)
 {
@@ -726,7 +697,6 @@ void CommandLineArguments::PopulateVariable(std::vector<double>* variable,
   //  }
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(std::vector<char*>* variable,
                                             const std::string& value)
 {
@@ -735,14 +705,12 @@ void CommandLineArguments::PopulateVariable(std::vector<char*>* variable,
   variable->push_back(var);
 }
 
-//----------------------------------------------------------------------------
 void CommandLineArguments::PopulateVariable(std::vector<std::string>* variable,
                                             const std::string& value)
 {
   variable->push_back(value);
 }
 
-//----------------------------------------------------------------------------
 bool CommandLineArguments::PopulateVariable(
   CommandLineArgumentsCallbackStructure* cs, const char* value)
 {
diff --git a/Source/kwsys/ConsoleBuf.hxx.in b/Source/kwsys/ConsoleBuf.hxx.in
index cb58865..46d65a8 100644
--- a/Source/kwsys/ConsoleBuf.hxx.in
+++ b/Source/kwsys/ConsoleBuf.hxx.in
@@ -25,8 +25,7 @@ namespace @KWSYS_NAMESPACE@ {
 #if defined(_WIN32)
 
 template <class CharT, class Traits = std::char_traits<CharT> >
-class @KWSYS_NAMESPACE at _EXPORT BasicConsoleBuf
-  : public std::basic_streambuf<CharT, Traits>
+class BasicConsoleBuf : public std::basic_streambuf<CharT, Traits>
 {
 public:
   typedef typename Traits::int_type int_type;
@@ -339,7 +338,7 @@ private:
   }
   bool decodeInputBuffer(const std::string buffer, std::wstring& wbuffer)
   {
-    int length = int(buffer.length());
+    size_t length = buffer.length();
     if (length == 0) {
       wbuffer = std::wstring();
       return true;
@@ -354,11 +353,12 @@ private:
       data += BOMsize;
       length -= BOMsize;
     }
-    const int wlength =
-      MultiByteToWideChar(actualCodepage, 0, data, length, NULL, 0);
+    const size_t wlength = static_cast<size_t>(MultiByteToWideChar(
+      actualCodepage, 0, data, static_cast<int>(length), NULL, 0));
     wchar_t* wbuf = new wchar_t[wlength];
     const bool success =
-      MultiByteToWideChar(actualCodepage, 0, data, length, wbuf, wlength) > 0
+      MultiByteToWideChar(actualCodepage, 0, data, static_cast<int>(length),
+                          wbuf, static_cast<int>(wlength)) > 0
       ? true
       : false;
     wbuffer = std::wstring(wbuf, wlength);
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 3c31b49..5141d45 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -20,7 +20,6 @@
 
 namespace KWSYS_NAMESPACE {
 
-//----------------------------------------------------------------------------
 class DirectoryInternals
 {
 public:
@@ -31,25 +30,21 @@ public:
   std::string Path;
 };
 
-//----------------------------------------------------------------------------
 Directory::Directory()
 {
   this->Internal = new DirectoryInternals;
 }
 
-//----------------------------------------------------------------------------
 Directory::~Directory()
 {
   delete this->Internal;
 }
 
-//----------------------------------------------------------------------------
 unsigned long Directory::GetNumberOfFiles() const
 {
   return static_cast<unsigned long>(this->Internal->Files.size());
 }
 
-//----------------------------------------------------------------------------
 const char* Directory::GetFile(unsigned long dindex) const
 {
   if (dindex >= this->Internal->Files.size()) {
@@ -58,13 +53,11 @@ const char* Directory::GetFile(unsigned long dindex) const
   return this->Internal->Files[dindex].c_str();
 }
 
-//----------------------------------------------------------------------------
 const char* Directory::GetPath() const
 {
   return this->Internal->Path.c_str();
 }
 
-//----------------------------------------------------------------------------
 void Directory::Clear()
 {
   this->Internal->Path.resize(0);
@@ -116,7 +109,7 @@ bool Directory::Load(const std::string& name)
     // Make sure the slashes in the wildcard suffix are consistent with the
     // rest of the path
     buf = new char[n + 2 + 1];
-    if (name.find('\\') != name.npos) {
+    if (name.find('\\') != std::string::npos) {
       sprintf(buf, "%s\\*", name.c_str());
     } else {
       sprintf(buf, "%s/*", name.c_str());
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx
index e494db6..1b4596a 100644
--- a/Source/kwsys/DynamicLoader.cxx
+++ b/Source/kwsys/DynamicLoader.cxx
@@ -26,20 +26,17 @@
 // the static methods of DynamicLoader.
 
 #if !KWSYS_SUPPORTS_SHARED_LIBS
-//----------------------------------------------------------------------------
 // Implementation for environments without dynamic libs
 #include <string.h> // for strerror()
 
 namespace KWSYS_NAMESPACE {
 
-//----------------------------------------------------------------------------
 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   const std::string& libname)
 {
   return 0;
 }
 
-//----------------------------------------------------------------------------
 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
 {
   if (!lib) {
@@ -49,14 +46,12 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
   return 1;
 }
 
-//----------------------------------------------------------------------------
 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   DynamicLoader::LibraryHandle lib, const std::string& sym)
 {
   return 0;
 }
 
-//----------------------------------------------------------------------------
 const char* DynamicLoader::LastError()
 {
   return "General error";
@@ -65,21 +60,18 @@ const char* DynamicLoader::LastError()
 } // namespace KWSYS_NAMESPACE
 
 #elif defined(__hpux)
-//----------------------------------------------------------------------------
 // Implementation for HPUX  machines
 #include <dl.h>
 #include <errno.h>
 
 namespace KWSYS_NAMESPACE {
 
-//----------------------------------------------------------------------------
 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   const std::string& libname)
 {
   return shl_load(libname.c_str(), BIND_DEFERRED | DYNAMIC_PATH, 0L);
 }
 
-//----------------------------------------------------------------------------
 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
 {
   if (!lib) {
@@ -88,7 +80,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
   return !shl_unload(lib);
 }
 
-//----------------------------------------------------------------------------
 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   DynamicLoader::LibraryHandle lib, const std::string& sym)
 {
@@ -132,14 +123,12 @@ const char* DynamicLoader::LastError()
 } // namespace KWSYS_NAMESPACE
 
 #elif defined(__APPLE__) && (MAC_OS_X_VERSION_MAX_ALLOWED < 1030)
-//----------------------------------------------------------------------------
 // Implementation for Mac OS X 10.2.x and earlier
 #include <mach-o/dyld.h>
 #include <string.h> // for strlen
 
 namespace KWSYS_NAMESPACE {
 
-//----------------------------------------------------------------------------
 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   const std::string& libname)
 {
@@ -158,7 +147,6 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   return handle;
 }
 
-//----------------------------------------------------------------------------
 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
 {
   // NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
@@ -170,7 +158,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
   return success;
 }
 
-//----------------------------------------------------------------------------
 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   DynamicLoader::LibraryHandle lib, const std::string& sym)
 {
@@ -191,7 +178,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
 }
 
-//----------------------------------------------------------------------------
 const char* DynamicLoader::LastError()
 {
   return 0;
@@ -200,13 +186,11 @@ const char* DynamicLoader::LastError()
 } // namespace KWSYS_NAMESPACE
 
 #elif defined(_WIN32) && !defined(__CYGWIN__)
-//----------------------------------------------------------------------------
 // Implementation for Windows win32 code but not cygwin
 #include <windows.h>
 
 namespace KWSYS_NAMESPACE {
 
-//----------------------------------------------------------------------------
 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   const std::string& libname)
 {
@@ -220,13 +204,11 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   return lh;
 }
 
-//----------------------------------------------------------------------------
 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
 {
   return (int)FreeLibrary(lib);
 }
 
-//----------------------------------------------------------------------------
 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   DynamicLoader::LibraryHandle lib, const std::string& sym)
 {
@@ -274,7 +256,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
 #endif
 }
 
-//----------------------------------------------------------------------------
 const char* DynamicLoader::LastError()
 {
   LPVOID lpMsgBuf = NULL;
@@ -299,7 +280,6 @@ const char* DynamicLoader::LastError()
 } // namespace KWSYS_NAMESPACE
 
 #elif defined(__BEOS__)
-//----------------------------------------------------------------------------
 // Implementation for BeOS / Haiku
 #include <string.h> // for strerror()
 
@@ -310,7 +290,6 @@ namespace KWSYS_NAMESPACE {
 
 static image_id last_dynamic_err = B_OK;
 
-//----------------------------------------------------------------------------
 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   const std::string& libname)
 {
@@ -325,7 +304,6 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   return rc + 1;
 }
 
-//----------------------------------------------------------------------------
 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
 {
   if (!lib) {
@@ -343,7 +321,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
   return 1;
 }
 
-//----------------------------------------------------------------------------
 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   DynamicLoader::LibraryHandle lib, const std::string& sym)
 {
@@ -372,7 +349,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   return result.psym;
 }
 
-//----------------------------------------------------------------------------
 const char* DynamicLoader::LastError()
 {
   const char* retval = strerror(last_dynamic_err);
@@ -383,7 +359,6 @@ const char* DynamicLoader::LastError()
 } // namespace KWSYS_NAMESPACE
 
 #elif defined(__MINT__)
-//----------------------------------------------------------------------------
 // Implementation for FreeMiNT on Atari
 #define _GNU_SOURCE /* for program_invocation_name */
 #include <dld.h>
@@ -393,7 +368,6 @@ const char* DynamicLoader::LastError()
 
 namespace KWSYS_NAMESPACE {
 
-//----------------------------------------------------------------------------
 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   const std::string& libname)
 {
@@ -404,7 +378,6 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   return (void*)name;
 }
 
-//----------------------------------------------------------------------------
 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
 {
   dld_unlink_by_file((char*)lib, 0);
@@ -412,7 +385,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
   return 0;
 }
 
-//----------------------------------------------------------------------------
 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   DynamicLoader::LibraryHandle lib, const std::string& sym)
 {
@@ -426,7 +398,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   return result.psym;
 }
 
-//----------------------------------------------------------------------------
 const char* DynamicLoader::LastError()
 {
   return dld_strerror(dld_errno);
@@ -435,21 +406,18 @@ const char* DynamicLoader::LastError()
 } // namespace KWSYS_NAMESPACE
 
 #else
-//----------------------------------------------------------------------------
 // Default implementation for *NIX systems (including Mac OS X 10.3 and
 // later) which use dlopen
 #include <dlfcn.h>
 
 namespace KWSYS_NAMESPACE {
 
-//----------------------------------------------------------------------------
 DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
   const std::string& libname)
 {
   return dlopen(libname.c_str(), RTLD_LAZY);
 }
 
-//----------------------------------------------------------------------------
 int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
 {
   if (lib) {
@@ -460,7 +428,6 @@ int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
   return 0;
 }
 
-//----------------------------------------------------------------------------
 DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   DynamicLoader::LibraryHandle lib, const std::string& sym)
 {
@@ -474,7 +441,6 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
   return result.psym;
 }
 
-//----------------------------------------------------------------------------
 const char* DynamicLoader::LastError()
 {
   return dlerror();
diff --git a/Source/kwsys/Encoding.hxx.in b/Source/kwsys/Encoding.hxx.in
index 6639efd..09691fd 100644
--- a/Source/kwsys/Encoding.hxx.in
+++ b/Source/kwsys/Encoding.hxx.in
@@ -13,7 +13,7 @@ class @KWSYS_NAMESPACE at _EXPORT Encoding
 {
 public:
   // Container class for argc/argv.
-  class CommandLineArguments
+  class @KWSYS_NAMESPACE at _EXPORT CommandLineArguments
   {
   public:
     // On Windows, get the program command line arguments
@@ -59,6 +59,17 @@ public:
   static std::string ToNarrow(const std::wstring& str);
   static std::string ToNarrow(const wchar_t* str);
 
+#if defined(_WIN32)
+  /**
+   * Convert the path to an extended length path to avoid MAX_PATH length
+   * limitations on Windows. If the input is a local path the result will be
+   * prefixed with \\?\; if the input is instead a network path, the result
+   * will be prefixed with \\?\UNC\. All output will also be converted to
+   * absolute paths with Windows-style backslashes.
+   **/
+  static std::wstring ToWindowsExtendedPath(std::string const&);
+#endif
+
 #endif // @KWSYS_NAMESPACE at _STL_HAS_WSTRING
 
 }; // class Encoding
diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx
index e904c1a..b1e54c9 100644
--- a/Source/kwsys/EncodingCXX.cxx
+++ b/Source/kwsys/EncodingCXX.cxx
@@ -29,6 +29,7 @@
 #if defined(_WIN32)
 #include <windows.h>
 
+#include <ctype.h>
 #include <shellapi.h>
 #endif
 
@@ -146,11 +147,11 @@ std::wstring Encoding::ToWide(const std::string& str)
       wstr += ToWide(str.c_str() + pos);
     }
     nullPos = str.find('\0', pos);
-    if (nullPos != str.npos) {
+    if (nullPos != std::string::npos) {
       pos = nullPos + 1;
       wstr += wchar_t('\0');
     }
-  } while (nullPos != str.npos);
+  } while (nullPos != std::string::npos);
 #endif
   return wstr;
 }
@@ -180,11 +181,11 @@ std::string Encoding::ToNarrow(const std::wstring& str)
       nstr += ToNarrow(str.c_str() + pos);
     }
     nullPos = str.find(wchar_t('\0'), pos);
-    if (nullPos != str.npos) {
+    if (nullPos != std::string::npos) {
       pos = nullPos + 1;
       nstr += '\0';
     }
-  } while (nullPos != str.npos);
+  } while (nullPos != std::string::npos);
 #endif
   return nstr;
 }
@@ -214,6 +215,63 @@ std::string Encoding::ToNarrow(const wchar_t* wcstr)
   }
   return str;
 }
+
+#if defined(_WIN32)
+// Convert local paths to UNC style paths
+std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
+{
+  std::wstring wsource = Encoding::ToWide(source);
+
+  // Resolve any relative paths
+  DWORD wfull_len;
+
+  /* The +3 is a workaround for a bug in some versions of GetFullPathNameW that
+   * won't return a large enough buffer size if the input is too small */
+  wfull_len = GetFullPathNameW(wsource.c_str(), 0, NULL, NULL) + 3;
+  std::vector<wchar_t> wfull(wfull_len);
+  GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], NULL);
+
+  /* This should get the correct size without any extra padding from the
+   * previous size workaround. */
+  wfull_len = static_cast<DWORD>(wcslen(&wfull[0]));
+
+  if (wfull_len >= 2 && isalpha(wfull[0]) &&
+      wfull[1] == L':') { /* C:\Foo\bar\FooBar.txt */
+    return L"\\\\?\\" + std::wstring(&wfull[0]);
+  } else if (wfull_len >= 2 && wfull[0] == L'\\' &&
+             wfull[1] == L'\\') { /* Starts with \\ */
+    if (wfull_len >= 4 && wfull[2] == L'?' &&
+        wfull[3] == L'\\') { /* Starts with \\?\ */
+      if (wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' &&
+          wfull[6] == L'C' &&
+          wfull[7] == L'\\') { /* \\?\UNC\Foo\bar\FooBar.txt */
+        return std::wstring(&wfull[0]);
+      } else if (wfull_len >= 6 && isalpha(wfull[4]) &&
+                 wfull[5] == L':') { /* \\?\C:\Foo\bar\FooBar.txt */
+        return std::wstring(&wfull[0]);
+      } else if (wfull_len >= 5) { /* \\?\Foo\bar\FooBar.txt */
+        return L"\\\\?\\UNC\\" + std::wstring(&wfull[4]);
+      }
+    } else if (wfull_len >= 4 && wfull[2] == L'.' &&
+               wfull[3] == L'\\') { /* Starts with \\.\ a device name */
+      if (wfull_len >= 6 && isalpha(wfull[4]) &&
+          wfull[5] == L':') { /* \\.\C:\Foo\bar\FooBar.txt */
+        return L"\\\\?\\" + std::wstring(&wfull[4]);
+      } else if (wfull_len >=
+                 5) { /* \\.\Foo\bar\ Device name is left unchanged */
+        return std::wstring(&wfull[0]);
+      }
+    } else if (wfull_len >= 3) { /* \\Foo\bar\FooBar.txt */
+      return L"\\\\?\\UNC\\" + std::wstring(&wfull[2]);
+    }
+  }
+
+  // If this case has been reached, then the path is invalid.  Leave it
+  // unchanged
+  return Encoding::ToWide(source);
+}
+#endif
+
 #endif // KWSYS_STL_HAS_WSTRING
 
 } // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
index 736214f..a4c65fe 100644
--- a/Source/kwsys/FStream.hxx.in
+++ b/Source/kwsys/FStream.hxx.in
@@ -33,7 +33,7 @@ public:
   typedef std::basic_filebuf<CharType, Traits> my_base_type;
   basic_filebuf* open(char const* s, std::ios_base::openmode mode)
   {
-    const std::wstring wstr = Encoding::ToWide(s);
+    const std::wstring wstr = Encoding::ToWindowsExtendedPath(s);
     return static_cast<basic_filebuf*>(my_base_type::open(wstr.c_str(), mode));
   }
 #endif
@@ -93,7 +93,7 @@ public:
 #if defined(_MSC_VER)
     const bool success = buf_->open(file_name, mode) != 0;
 #else
-    const std::wstring wstr = Encoding::ToWide(file_name);
+    const std::wstring wstr = Encoding::ToWindowsExtendedPath(file_name);
     bool success = false;
     std::wstring cmode = getcmode(mode);
     file_ = _wfopen(wstr.c_str(), cmode.c_str());
@@ -170,8 +170,6 @@ template <typename CharType, typename Traits = std::char_traits<CharType> >
 class basic_ifstream : public std::basic_istream<CharType, Traits>,
                        public basic_efilebuf<CharType, Traits>
 {
-  using basic_efilebuf<CharType, Traits>::is_open;
-
 public:
   typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
     internal_buffer_type;
@@ -201,6 +199,8 @@ public:
 
   void close() { this->_set_state(this->_close(), this, this); }
 
+  using basic_efilebuf<CharType, Traits>::is_open;
+
   internal_buffer_type* rdbuf() const { return this->buf_; }
 
   ~basic_ifstream() @KWSYS_NAMESPACE at _FStream_NOEXCEPT { close(); }
@@ -269,7 +269,7 @@ enum BOM
 // If a BOM exists, the stream is advanced to after the BOM.
 // This function requires a seekable stream (but not a relative
 // seekable stream).
-BOM ReadBOM(std::istream& in);
+ at KWSYS_NAMESPACE@_EXPORT BOM ReadBOM(std::istream& in);
 }
 }
 
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index fa8760d..d2f0b85 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -37,7 +37,6 @@ namespace KWSYS_NAMESPACE {
 #define KWSYS_GLOB_SUPPORT_NETWORK_PATHS
 #endif
 
-//----------------------------------------------------------------------------
 class GlobInternals
 {
 public:
@@ -45,7 +44,6 @@ public:
   std::vector<kwsys::RegularExpression> Expressions;
 };
 
-//----------------------------------------------------------------------------
 Glob::Glob()
 {
   this->Internals = new GlobInternals;
@@ -62,19 +60,16 @@ Glob::Glob()
   this->RecurseListDirs = false;
 }
 
-//----------------------------------------------------------------------------
 Glob::~Glob()
 {
   delete this->Internals;
 }
 
-//----------------------------------------------------------------------------
 std::vector<std::string>& Glob::GetFiles()
 {
   return this->Internals->Files;
 }
 
-//----------------------------------------------------------------------------
 std::string Glob::PatternToRegex(const std::string& pattern,
                                  bool require_whole_string, bool preserve_case)
 {
@@ -183,7 +178,6 @@ std::string Glob::PatternToRegex(const std::string& pattern,
   return regex;
 }
 
-//----------------------------------------------------------------------------
 bool Glob::RecurseDirectory(std::string::size_type start,
                             const std::string& dir, GlobMessages* messages)
 {
@@ -277,7 +271,6 @@ bool Glob::RecurseDirectory(std::string::size_type start,
   return true;
 }
 
-//----------------------------------------------------------------------------
 void Glob::ProcessDirectory(std::string::size_type start,
                             const std::string& dir, GlobMessages* messages)
 {
@@ -337,7 +330,6 @@ void Glob::ProcessDirectory(std::string::size_type start,
   }
 }
 
-//----------------------------------------------------------------------------
 bool Glob::FindFiles(const std::string& inexpr, GlobMessages* messages)
 {
   std::string cexpr;
@@ -420,14 +412,12 @@ bool Glob::FindFiles(const std::string& inexpr, GlobMessages* messages)
   return true;
 }
 
-//----------------------------------------------------------------------------
 void Glob::AddExpression(const std::string& expr)
 {
   this->Internals->Expressions.push_back(
     kwsys::RegularExpression(this->PatternToRegex(expr)));
 }
 
-//----------------------------------------------------------------------------
 void Glob::SetRelative(const char* dir)
 {
   if (!dir) {
@@ -437,7 +427,6 @@ void Glob::SetRelative(const char* dir)
   this->Relative = dir;
 }
 
-//----------------------------------------------------------------------------
 const char* Glob::GetRelative()
 {
   if (this->Relative.empty()) {
@@ -446,7 +435,6 @@ const char* Glob::GetRelative()
   return this->Relative.c_str();
 }
 
-//----------------------------------------------------------------------------
 void Glob::AddFile(std::vector<std::string>& files, const std::string& file)
 {
   if (!this->Relative.empty()) {
diff --git a/Source/kwsys/MD5.c b/Source/kwsys/MD5.c
index 1310c64..3188fb6 100644
--- a/Source/kwsys/MD5.c
+++ b/Source/kwsys/MD5.c
@@ -13,8 +13,6 @@
 #include <stdlib.h> /* malloc, free */
 #include <string.h> /* memcpy, strlen */
 
-/*--------------------------------------------------------------------------*/
-
 /* This MD5 implementation has been taken from a third party.  Slight
    modifications to the arrangement of the code have been made to put
    it in a single source file instead of a separate header and
@@ -425,14 +423,12 @@ static void md5_finish(md5_state_t* pms, md5_byte_t digest[16])
 #pragma clang diagnostic pop
 #endif
 
-/*--------------------------------------------------------------------------*/
 /* Wrap up the MD5 state in our opaque structure.  */
 struct kwsysMD5_s
 {
   md5_state_t md5_state;
 };
 
-/*--------------------------------------------------------------------------*/
 kwsysMD5* kwsysMD5_New(void)
 {
   /* Allocate a process control structure.  */
@@ -443,7 +439,6 @@ kwsysMD5* kwsysMD5_New(void)
   return md5;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysMD5_Delete(kwsysMD5* md5)
 {
   /* Make sure we have an instance.  */
@@ -455,13 +450,11 @@ void kwsysMD5_Delete(kwsysMD5* md5)
   free(md5);
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysMD5_Initialize(kwsysMD5* md5)
 {
   md5_init(&md5->md5_state);
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysMD5_Append(kwsysMD5* md5, unsigned char const* data, int length)
 {
   size_t dlen;
@@ -473,13 +466,11 @@ void kwsysMD5_Append(kwsysMD5* md5, unsigned char const* data, int length)
   md5_append(&md5->md5_state, (md5_byte_t const*)data, dlen);
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysMD5_Finalize(kwsysMD5* md5, unsigned char digest[16])
 {
   md5_finish(&md5->md5_state, (md5_byte_t*)digest);
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysMD5_FinalizeHex(kwsysMD5* md5, char buffer[32])
 {
   unsigned char digest[16];
@@ -487,7 +478,6 @@ void kwsysMD5_FinalizeHex(kwsysMD5* md5, char buffer[32])
   kwsysMD5_DigestToHex(digest, buffer);
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysMD5_DigestToHex(unsigned char const digest[16], char buffer[32])
 {
   /* Map from 4-bit index to hexadecimal representation.  */
diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in
index b8349a6..237001c 100644
--- a/Source/kwsys/Process.h.in
+++ b/Source/kwsys/Process.h.in
@@ -42,7 +42,6 @@
 #define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired)
 #define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed)
 #define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned)
-#define kwsysProcess_GetState kwsys_ns(Process_GetState)
 #define kwsysProcess_State_e kwsys_ns(Process_State_e)
 #define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None)
 #define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault)
@@ -50,12 +49,21 @@
 #define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt)
 #define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical)
 #define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other)
-#define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
 #define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e)
+#define kwsysProcess_GetState kwsys_ns(Process_GetState)
+#define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
 #define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode)
 #define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue)
 #define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString)
 #define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString)
+#define kwsysProcess_GetStateByIndex kwsys_ns(Process_GetStateByIndex)
+#define kwsysProcess_GetExitExceptionByIndex                                  \
+  kwsys_ns(Process_GetExitExceptionByIndex)
+#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
+#define kwsysProcess_GetExitValueByIndex kwsys_ns(Process_GetExitValueByIndex)
+#define kwsysProcess_GetExceptionStringByIndex                                \
+  kwsys_ns(Process_GetExceptionStringByIndex)
+#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
 #define kwsysProcess_Execute kwsys_ns(Process_Execute)
 #define kwsysProcess_Disown kwsys_ns(Process_Disown)
 #define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData)
@@ -298,6 +306,67 @@ kwsysEXPORT const char* kwsysProcess_GetErrorString(kwsysProcess* cp);
 kwsysEXPORT const char* kwsysProcess_GetExceptionString(kwsysProcess* cp);
 
 /**
+* Get the current state of the Process instance.  Possible states are:
+*
+*  kwsysProcess_StateByIndex_Starting  = Execute has not yet been called.
+*  kwsysProcess_StateByIndex_Exception = Child process exited abnormally.
+*  kwsysProcess_StateByIndex_Exited    = Child process exited normally.
+*  kwsysProcess_StateByIndex_Error     = Error getting the child return code.
+*/
+kwsysEXPORT int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx);
+enum kwsysProcess_StateByIndex_e
+{
+  kwsysProcess_StateByIndex_Starting = kwsysProcess_State_Starting,
+  kwsysProcess_StateByIndex_Exception = kwsysProcess_State_Exception,
+  kwsysProcess_StateByIndex_Exited = kwsysProcess_State_Exited,
+  kwsysProcess_StateByIndex_Error = kwsysProcess_State_Error
+};
+
+/**
+* When GetState returns "Exception", this method returns a
+* platform-independent description of the exceptional behavior that
+* caused the child to terminate abnormally.  Possible exceptions are:
+*
+*  kwsysProcess_Exception_None      = No exceptional behavior occurred.
+*  kwsysProcess_Exception_Fault     = Child crashed with a memory fault.
+*  kwsysProcess_Exception_Illegal   = Child crashed with an illegal
+*                                     instruction.
+*  kwsysProcess_Exception_Interrupt = Child was interrupted by user
+*                                     (Cntl-C/Break).
+*  kwsysProcess_Exception_Numerical = Child crashed with a numerical
+*                                     exception.
+*  kwsysProcess_Exception_Other     = Child terminated for another reason.
+*/
+kwsysEXPORT int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp,
+                                                     int idx);
+
+/**
+* When GetState returns "Exited" or "Exception", this method returns
+* the platform-specific raw exit code of the process.  UNIX platforms
+* should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access
+* this value.  Windows users should compare the value to the various
+* EXCEPTION_* values.
+*
+* If GetState returns "Exited", use GetExitValue to get the
+* platform-independent child return value.
+*/
+kwsysEXPORT int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx);
+
+/**
+* When GetState returns "Exited", this method returns the child's
+* platform-independent exit code (such as the value returned by the
+* child's main).
+*/
+kwsysEXPORT int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx);
+
+/**
+* When GetState returns "Exception", this method returns a string
+* describing the problem.  Otherwise, it returns NULL.
+*/
+kwsysEXPORT const char* kwsysProcess_GetExceptionStringByIndex(
+  kwsysProcess* cp, int idx);
+
+/**
  * Start executing the child process.
  */
 kwsysEXPORT void kwsysProcess_Execute(kwsysProcess* cp);
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index ed09095..9ebcfce 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -140,7 +140,6 @@ typedef struct kwsysProcessCreateInformation_s
   int ErrorPipe[2];
 } kwsysProcessCreateInformation;
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessVolatileFree(volatile void* p);
 static int kwsysProcessInitialize(kwsysProcess* cp);
 static void kwsysProcessCleanup(kwsysProcess* cp, int error);
@@ -166,7 +165,8 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
                                             kwsysProcessTime in2);
 static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
                                                  kwsysProcessTime in2);
-static void kwsysProcessSetExitException(kwsysProcess* cp, int sig);
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
+                                                int idx);
 static void kwsysProcessChildErrorExit(int errorPipe);
 static void kwsysProcessRestoreDefaultSignalHandlers(void);
 static pid_t kwsysProcessFork(kwsysProcess* cp,
@@ -184,7 +184,26 @@ static void kwsysProcessesSignalHandler(int signum, siginfo_t* info,
 static void kwsysProcessesSignalHandler(int signum);
 #endif
 
-/*--------------------------------------------------------------------------*/
+/* A structure containing results data for each process.  */
+typedef struct kwsysProcessResults_s kwsysProcessResults;
+struct kwsysProcessResults_s
+{
+  /* The status of the child process. */
+  int State;
+
+  /* The exceptional behavior that terminated the process, if any.  */
+  int ExitException;
+
+  /* The process exit code.  */
+  int ExitCode;
+
+  /* The process return code, if any.  */
+  int ExitValue;
+
+  /* Description for the ExitException.  */
+  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+};
+
 /* Structure containing data used to implement the child's execution.  */
 struct kwsysProcess_s
 {
@@ -255,28 +274,18 @@ struct kwsysProcess_s
   /* The number of children still executing.  */
   int CommandsLeft;
 
-  /* The current status of the child process.  Must be atomic because
+  /* The status of the process structure.  Must be atomic because
      the signal handler checks this to avoid a race.  */
   volatile sig_atomic_t State;
 
-  /* The exceptional behavior that terminated the child process, if
-   * any.  */
-  int ExitException;
-
-  /* The exit code of the child process.  */
-  int ExitCode;
-
-  /* The exit value of the child process, if any.  */
-  int ExitValue;
-
   /* Whether the process was killed.  */
   volatile sig_atomic_t Killed;
 
   /* Buffer for error message in case of failure.  */
   char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1];
 
-  /* Description for the ExitException.  */
-  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+  /* process results.  */
+  kwsysProcessResults* ProcessResults;
 
   /* The exit codes of each child process in the pipeline.  */
   int* CommandExitCodes;
@@ -301,7 +310,6 @@ struct kwsysProcess_s
   char* RealWorkingDirectory;
 };
 
-/*--------------------------------------------------------------------------*/
 kwsysProcess* kwsysProcess_New(void)
 {
   /* Allocate a process control structure.  */
@@ -328,7 +336,6 @@ kwsysProcess* kwsysProcess_New(void)
   return cp;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_Delete(kwsysProcess* cp)
 {
   /* Make sure we have an instance.  */
@@ -354,10 +361,10 @@ void kwsysProcess_Delete(kwsysProcess* cp)
   if (cp->CommandExitCodes) {
     free(cp->CommandExitCodes);
   }
+  free(cp->ProcessResults);
   free(cp);
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
 {
   int i;
@@ -382,7 +389,6 @@ int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
 {
   int newNumberOfCommands;
@@ -462,7 +468,6 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
 {
   if (!cp) {
@@ -476,7 +481,6 @@ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
   cp->TimeoutTime.tv_sec = -1;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
 {
   if (!cp) {
@@ -502,7 +506,6 @@ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file)
 {
   char** pfile;
@@ -543,7 +546,6 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared)
 {
   if (!cp) {
@@ -572,7 +574,6 @@ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, int p[2])
 {
   int* pPipeNative = 0;
@@ -612,7 +613,6 @@ void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, int p[2])
   }
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
 {
   if (!cp) {
@@ -633,7 +633,6 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
 {
   if (!cp) {
@@ -658,31 +657,32 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetState(kwsysProcess* cp)
 {
   return cp ? cp->State : kwsysProcess_State_Error;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetExitException(kwsysProcess* cp)
 {
-  return cp ? cp->ExitException : kwsysProcess_Exception_Other;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException
+    : kwsysProcess_Exception_Other;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetExitCode(kwsysProcess* cp)
 {
-  return cp ? cp->ExitCode : 0;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode
+    : 0;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetExitValue(kwsysProcess* cp)
 {
-  return cp ? cp->ExitValue : -1;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue
+    : -1;
 }
 
-/*--------------------------------------------------------------------------*/
 const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
 {
   if (!cp) {
@@ -693,18 +693,58 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
   return "Success";
 }
 
-/*--------------------------------------------------------------------------*/
 const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
 {
-  if (!cp) {
+  if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) {
     return "GetExceptionString called with NULL process management structure";
   } else if (cp->State == kwsysProcess_State_Exception) {
-    return cp->ExitExceptionString;
+    return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString;
+  }
+  return "No exception";
+}
+
+/* the index should be in array bound. */
+#define KWSYSPE_IDX_CHK(RET)                                                  \
+  if (!cp || idx >= cp->NumberOfCommands || idx < 0) {                        \
+    return RET;                                                               \
+  }
+
+int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(kwsysProcess_State_Error)
+  return cp->ProcessResults[idx].State;
+}
+
+int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other)
+  return cp->ProcessResults[idx].ExitException;
+}
+
+int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(-1)
+  return cp->ProcessResults[idx].ExitValue;
+}
+
+int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(-1)
+  return cp->CommandExitCodes[idx];
+}
+
+const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management "
+                  "structure or index out of bound")
+  if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) {
+    return cp->ProcessResults[idx].ExitExceptionString;
   }
   return "No exception";
 }
 
-/*--------------------------------------------------------------------------*/
+#undef KWSYSPE_IDX_CHK
+
 void kwsysProcess_Execute(kwsysProcess* cp)
 {
   int i;
@@ -990,7 +1030,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
   cp->Detached = cp->OptionDetach;
 }
 
-/*--------------------------------------------------------------------------*/
 kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp)
 {
   /* Make sure a detached child process is running.  */
@@ -1009,7 +1048,6 @@ kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp)
   cp->State = kwsysProcess_State_Disowned;
 }
 
-/*--------------------------------------------------------------------------*/
 typedef struct kwsysProcessWaitData_s
 {
   int Expired;
@@ -1021,7 +1059,6 @@ typedef struct kwsysProcessWaitData_s
 static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
                                    kwsysProcessWaitData* wd);
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
                              double* userTimeout)
 {
@@ -1083,7 +1120,6 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
                                    kwsysProcessWaitData* wd)
 {
@@ -1285,10 +1321,8 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
 #endif
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
 {
-  int status = 0;
   int prPipe = 0;
 
   /* Make sure we are executing a process.  */
@@ -1319,10 +1353,6 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
     cp->State = kwsysProcess_State_Error;
     return 1;
   }
-
-  /* Use the status of the last process in the pipeline.  */
-  status = cp->CommandExitCodes[cp->NumberOfCommands - 1];
-
   /* Determine the outcome.  */
   if (cp->Killed) {
     /* We killed the child.  */
@@ -1330,29 +1360,36 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
   } else if (cp->TimeoutExpired) {
     /* The timeout expired.  */
     cp->State = kwsysProcess_State_Expired;
-  } else if (WIFEXITED(status)) {
-    /* The child exited normally.  */
-    cp->State = kwsysProcess_State_Exited;
-    cp->ExitException = kwsysProcess_Exception_None;
-    cp->ExitCode = status;
-    cp->ExitValue = (int)WEXITSTATUS(status);
-  } else if (WIFSIGNALED(status)) {
-    /* The child received an unhandled signal.  */
-    cp->State = kwsysProcess_State_Exception;
-    cp->ExitCode = status;
-    kwsysProcessSetExitException(cp, (int)WTERMSIG(status));
   } else {
-    /* Error getting the child return code.  */
-    strcpy(cp->ErrorMessage, "Error getting child return code.");
-    cp->State = kwsysProcess_State_Error;
+    /* The children exited.  Report the outcome of the child processes.  */
+    for (prPipe = 0; prPipe < cp->NumberOfCommands; ++prPipe) {
+      cp->ProcessResults[prPipe].ExitCode = cp->CommandExitCodes[prPipe];
+      if (WIFEXITED(cp->ProcessResults[prPipe].ExitCode)) {
+        /* The child exited normally.  */
+        cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Exited;
+        cp->ProcessResults[prPipe].ExitException = kwsysProcess_Exception_None;
+        cp->ProcessResults[prPipe].ExitValue =
+          (int)WEXITSTATUS(cp->ProcessResults[prPipe].ExitCode);
+      } else if (WIFSIGNALED(cp->ProcessResults[prPipe].ExitCode)) {
+        /* The child received an unhandled signal.  */
+        cp->ProcessResults[prPipe].State = kwsysProcess_State_Exception;
+        kwsysProcessSetExitExceptionByIndex(
+          cp, (int)WTERMSIG(cp->ProcessResults[prPipe].ExitCode), prPipe);
+      } else {
+        /* Error getting the child return code.  */
+        strcpy(cp->ProcessResults[prPipe].ExitExceptionString,
+               "Error getting child return code.");
+        cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Error;
+      }
+    }
+    /* support legacy state status value */
+    cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State;
   }
-
   /* Normal cleanup.  */
   kwsysProcessCleanup(cp, 0);
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_Interrupt(kwsysProcess* cp)
 {
   int i;
@@ -1384,7 +1421,6 @@ void kwsysProcess_Interrupt(kwsysProcess* cp)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_Kill(kwsysProcess* cp)
 {
   int i;
@@ -1431,7 +1467,6 @@ void kwsysProcess_Kill(kwsysProcess* cp)
   cp->CommandsLeft = 0;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Call the free() function with a pointer to volatile without causing
    compiler warnings.  */
 static void kwsysProcessVolatileFree(volatile void* p)
@@ -1448,7 +1483,6 @@ static void kwsysProcessVolatileFree(volatile void* p)
 #endif
 }
 
-/*--------------------------------------------------------------------------*/
 /* Initialize a process control structure for kwsysProcess_Execute.  */
 static int kwsysProcessInitialize(kwsysProcess* cp)
 {
@@ -1474,11 +1508,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
 #endif
   cp->State = kwsysProcess_State_Starting;
   cp->Killed = 0;
-  cp->ExitException = kwsysProcess_Exception_None;
-  cp->ExitCode = 1;
-  cp->ExitValue = 1;
   cp->ErrorMessage[0] = 0;
-  strcpy(cp->ExitExceptionString, "No exception");
 
   oldForkPIDs = cp->ForkPIDs;
   cp->ForkPIDs = (volatile pid_t*)malloc(sizeof(volatile pid_t) *
@@ -1504,6 +1534,23 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
   memset(cp->CommandExitCodes, 0,
          sizeof(int) * (size_t)(cp->NumberOfCommands));
 
+  /* Allocate process result information for each process.  */
+  free(cp->ProcessResults);
+  cp->ProcessResults = (kwsysProcessResults*)malloc(
+    sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands));
+  if (!cp->ProcessResults) {
+    return 0;
+  }
+  memset(cp->ProcessResults, 0,
+         sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands));
+  for (i = 0; i < cp->NumberOfCommands; i++) {
+    cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None;
+    cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Starting;
+    cp->ProcessResults[i].ExitCode = 1;
+    cp->ProcessResults[i].ExitValue = 1;
+    strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception");
+  }
+
   /* Allocate memory to save the real working directory.  */
   if (cp->WorkingDirectory) {
 #if defined(MAXPATHLEN)
@@ -1523,7 +1570,6 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Free all resources used by the given kwsysProcess instance that were
    allocated by kwsysProcess_Execute.  */
 static void kwsysProcessCleanup(kwsysProcess* cp, int error)
@@ -1590,7 +1636,6 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 /* Close the given file descriptor if it is open.  Reset its value to -1.  */
 static void kwsysProcessCleanupDescriptor(int* pfd)
 {
@@ -1603,7 +1648,6 @@ static void kwsysProcessCleanupDescriptor(int* pfd)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessClosePipes(kwsysProcess* cp)
 {
   int i;
@@ -1636,7 +1680,6 @@ static void kwsysProcessClosePipes(kwsysProcess* cp)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcessSetNonBlocking(int fd)
 {
   int flags = fcntl(fd, F_GETFL);
@@ -1646,12 +1689,10 @@ static int kwsysProcessSetNonBlocking(int fd)
   return flags >= 0;
 }
 
-/*--------------------------------------------------------------------------*/
 #if defined(__VMS)
 int decc$set_child_standard_streams(int fd1, int fd2, int fd3);
 #endif
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
                               kwsysProcessCreateInformation* si)
 {
@@ -1831,7 +1872,6 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessDestroy(kwsysProcess* cp)
 {
   /* A child process has terminated.  Reap it if it is one handled by
@@ -1880,7 +1920,6 @@ static void kwsysProcessDestroy(kwsysProcess* cp)
   sigprocmask(SIG_SETMASK, &old_mask, 0);
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcessSetupOutputPipeFile(int* p, const char* name)
 {
   int fout;
@@ -1906,7 +1945,6 @@ static int kwsysProcessSetupOutputPipeFile(int* p, const char* name)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcessSetupOutputPipeNative(int* p, int des[2])
 {
   /* Close the existing descriptor.  */
@@ -1925,7 +1963,6 @@ static int kwsysProcessSetupOutputPipeNative(int* p, int des[2])
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Get the time at which either the process or user timeout will
    expire.  Returns 1 if the user timeout is first, and 0 otherwise.  */
 static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
@@ -1957,7 +1994,6 @@ static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
   return 0;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Get the length of time before the given timeout time arrives.
    Returns 1 if the time has already arrived, and 0 otherwise.  */
 static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
@@ -1992,7 +2028,6 @@ static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static kwsysProcessTime kwsysProcessTimeGetCurrent(void)
 {
   kwsysProcessTime current;
@@ -2003,13 +2038,11 @@ static kwsysProcessTime kwsysProcessTimeGetCurrent(void)
   return current;
 }
 
-/*--------------------------------------------------------------------------*/
 static double kwsysProcessTimeToDouble(kwsysProcessTime t)
 {
   return (double)t.tv_sec + (double)(t.tv_usec) * 0.000001;
 }
 
-/*--------------------------------------------------------------------------*/
 static kwsysProcessTime kwsysProcessTimeFromDouble(double d)
 {
   kwsysProcessTime t;
@@ -2018,14 +2051,12 @@ static kwsysProcessTime kwsysProcessTimeFromDouble(double d)
   return t;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2)
 {
   return ((in1.tv_sec < in2.tv_sec) ||
           ((in1.tv_sec == in2.tv_sec) && (in1.tv_usec < in2.tv_usec)));
 }
 
-/*--------------------------------------------------------------------------*/
 static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
                                             kwsysProcessTime in2)
 {
@@ -2039,7 +2070,6 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
   return out;
 }
 
-/*--------------------------------------------------------------------------*/
 static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
                                                  kwsysProcessTime in2)
 {
@@ -2053,11 +2083,11 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
   return out;
 }
 
-/*--------------------------------------------------------------------------*/
 #define KWSYSPE_CASE(type, str)                                               \
-  cp->ExitException = kwsysProcess_Exception_##type;                          \
-  strcpy(cp->ExitExceptionString, str)
-static void kwsysProcessSetExitException(kwsysProcess* cp, int sig)
+  cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_##type;      \
+  strcpy(cp->ProcessResults[idx].ExitExceptionString, str)
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
+                                                int idx)
 {
   switch (sig) {
 #ifdef SIGSEGV
@@ -2243,14 +2273,13 @@ static void kwsysProcessSetExitException(kwsysProcess* cp, int sig)
 #endif
 #endif
     default:
-      cp->ExitException = kwsysProcess_Exception_Other;
-      sprintf(cp->ExitExceptionString, "Signal %d", sig);
+      cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
+      sprintf(cp->ProcessResults[idx].ExitExceptionString, "Signal %d", sig);
       break;
   }
 }
 #undef KWSYSPE_CASE
 
-/*--------------------------------------------------------------------------*/
 /* When the child process encounters an error before its program is
    invoked, this is called to report the error to the parent and
    exit.  */
@@ -2269,7 +2298,6 @@ static void kwsysProcessChildErrorExit(int errorPipe)
   _exit(1);
 }
 
-/*--------------------------------------------------------------------------*/
 /* Restores all signal handlers to their default values.  */
 static void kwsysProcessRestoreDefaultSignalHandlers(void)
 {
@@ -2377,13 +2405,11 @@ static void kwsysProcessRestoreDefaultSignalHandlers(void)
 #endif
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessExit(void)
 {
   _exit(0);
 }
 
-/*--------------------------------------------------------------------------*/
 #if !defined(__VMS)
 static pid_t kwsysProcessFork(kwsysProcess* cp,
                               kwsysProcessCreateInformation* si)
@@ -2433,7 +2459,6 @@ static pid_t kwsysProcessFork(kwsysProcess* cp,
 }
 #endif
 
-/*--------------------------------------------------------------------------*/
 /* We try to obtain process information by invoking the ps command.
    Here we define the command to call on each platform and the
    corresponding parsing format string.  The parsing format should
@@ -2457,7 +2482,6 @@ static pid_t kwsysProcessFork(kwsysProcess* cp,
 #define KWSYSPE_PS_FORMAT "%d %d %*[^\n]\n"
 #endif
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessKill(pid_t process_id)
 {
 #if defined(__linux__) || defined(__CYGWIN__)
@@ -2561,7 +2585,6 @@ static void kwsysProcessKill(pid_t process_id)
 #endif
 }
 
-/*--------------------------------------------------------------------------*/
 #if defined(__VMS)
 int decc$feature_get_index(const char* name);
 int decc$feature_set_value(int index, int mode, int value);
@@ -2574,7 +2597,6 @@ static int kwsysProcessSetVMSFeature(const char* name, int value)
 }
 #endif
 
-/*--------------------------------------------------------------------------*/
 /* Global set of executing processes for use by the signal handler.
    This global instance will be zero-initialized by the compiler.  */
 typedef struct kwsysProcessInstances_s
@@ -2590,7 +2612,6 @@ static struct sigaction kwsysProcessesOldSigChldAction;
 static struct sigaction kwsysProcessesOldSigIntAction;
 static struct sigaction kwsysProcessesOldSigTermAction;
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses)
 {
   /* Block signals while we update the set of pipes to check.
@@ -2611,7 +2632,6 @@ static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses)
   sigprocmask(SIG_SETMASK, &oldset, 0);
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcessesAdd(kwsysProcess* cp)
 {
   /* Create a pipe through which the signal handler can notify the
@@ -2721,7 +2741,6 @@ static int kwsysProcessesAdd(kwsysProcess* cp)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessesRemove(kwsysProcess* cp)
 {
   /* Attempt to remove the given signal pipe from the signal handler set.  */
@@ -2772,7 +2791,6 @@ static void kwsysProcessesRemove(kwsysProcess* cp)
   kwsysProcessCleanupDescriptor(&cp->SignalPipe);
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessesSignalHandler(int signum
 #if KWSYSPE_USE_SIGINFO
                                         ,
@@ -2884,7 +2902,6 @@ static void kwsysProcessesSignalHandler(int signum
   errno = old_errno;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_ResetStartTime(kwsysProcess* cp)
 {
   if (!cp) {
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index d10c733..5183e3d 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -86,7 +86,6 @@ typedef struct kwsysProcessCreateInformation_s
   HANDLE hStdError;
 } kwsysProcessCreateInformation;
 
-/*--------------------------------------------------------------------------*/
 typedef struct kwsysProcessPipeData_s kwsysProcessPipeData;
 static DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd);
 static void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp,
@@ -119,6 +118,8 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
 static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
                                                  kwsysProcessTime in2);
 static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code,
+                                                int idx);
 static void kwsysProcessKillTree(int pid);
 static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
 static int kwsysProcessesInitialize(void);
@@ -129,7 +130,6 @@ static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessId,
 static void kwsysProcessesRemove(HANDLE hProcess);
 static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType);
 
-/*--------------------------------------------------------------------------*/
 /* A structure containing synchronization data for each thread.  */
 typedef struct kwsysProcessPipeSync_s kwsysProcessPipeSync;
 struct kwsysProcessPipeSync_s
@@ -147,7 +147,6 @@ struct kwsysProcessPipeSync_s
   HANDLE Reset;
 };
 
-/*--------------------------------------------------------------------------*/
 /* A structure containing data for each pipe's threads.  */
 struct kwsysProcessPipeData_s
 {
@@ -183,7 +182,26 @@ struct kwsysProcessPipeData_s
   HANDLE Write;
 };
 
-/*--------------------------------------------------------------------------*/
+/* A structure containing results data for each process.  */
+typedef struct kwsysProcessResults_s kwsysProcessResults;
+struct kwsysProcessResults_s
+{
+  /* The status of the process.  */
+  int State;
+
+  /* The exceptional behavior that terminated the process, if any.  */
+  int ExitException;
+
+  /* The process exit code.  */
+  DWORD ExitCode;
+
+  /* The process return code, if any.  */
+  int ExitValue;
+
+  /* Description for the ExitException.  */
+  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+};
+
 /* Structure containing data used to implement the child's execution.  */
 struct kwsysProcess_s
 {
@@ -249,15 +267,6 @@ struct kwsysProcess_s
 
   /* ------------- Data managed per call to Execute ------------- */
 
-  /* The exceptional behavior that terminated the process, if any.  */
-  int ExitException;
-
-  /* The process exit code.  */
-  DWORD ExitCode;
-
-  /* The process return code, if any.  */
-  int ExitValue;
-
   /* Index of last pipe to report data, if any.  */
   int CurrentIndex;
 
@@ -289,8 +298,8 @@ struct kwsysProcess_s
   /* Buffer for error messages.  */
   char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1];
 
-  /* Description for the ExitException.  */
-  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1];
+  /* process results.  */
+  kwsysProcessResults* ProcessResults;
 
   /* Windows process information data.  */
   PROCESS_INFORMATION* ProcessInformation;
@@ -308,7 +317,6 @@ struct kwsysProcess_s
   HANDLE PipeChildStd[3];
 };
 
-/*--------------------------------------------------------------------------*/
 kwsysProcess* kwsysProcess_New(void)
 {
   int i;
@@ -447,7 +455,6 @@ kwsysProcess* kwsysProcess_New(void)
   return cp;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_Delete(kwsysProcess* cp)
 {
   int i;
@@ -519,10 +526,10 @@ void kwsysProcess_Delete(kwsysProcess* cp)
   if (cp->CommandExitCodes) {
     free(cp->CommandExitCodes);
   }
+  free(cp->ProcessResults);
   free(cp);
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
 {
   int i;
@@ -543,7 +550,6 @@ int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
 {
   int newNumberOfCommands;
@@ -639,7 +645,6 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
 {
   if (!cp) {
@@ -653,7 +658,6 @@ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
   cp->TimeoutTime.QuadPart = -1;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
 {
   if (!cp) {
@@ -685,7 +689,6 @@ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
 {
   char** pfile;
@@ -727,7 +730,6 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
 {
   if (!cp) {
@@ -756,7 +758,6 @@ void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, HANDLE p[2])
 {
   HANDLE* pPipeNative = 0;
@@ -796,7 +797,6 @@ void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, HANDLE p[2])
   }
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
 {
   if (!cp) {
@@ -819,7 +819,6 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
 {
   if (!cp) {
@@ -847,31 +846,32 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetState(kwsysProcess* cp)
 {
   return cp ? cp->State : kwsysProcess_State_Error;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetExitException(kwsysProcess* cp)
 {
-  return cp ? cp->ExitException : kwsysProcess_Exception_Other;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException
+    : kwsysProcess_Exception_Other;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetExitValue(kwsysProcess* cp)
 {
-  return cp ? cp->ExitValue : -1;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue
+    : -1;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_GetExitCode(kwsysProcess* cp)
 {
-  return cp ? cp->ExitCode : 0;
+  return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0))
+    ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode
+    : 0;
 }
 
-/*--------------------------------------------------------------------------*/
 const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
 {
   if (!cp) {
@@ -882,18 +882,59 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
   return "Success";
 }
 
-/*--------------------------------------------------------------------------*/
 const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
 {
-  if (!cp) {
+  if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) {
     return "GetExceptionString called with NULL process management structure";
   } else if (cp->State == kwsysProcess_State_Exception) {
-    return cp->ExitExceptionString;
+    return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString;
   }
   return "No exception";
 }
 
-/*--------------------------------------------------------------------------*/
+/* the index should be in array bound. */
+#define KWSYSPE_IDX_CHK(RET)                                                  \
+  if (!cp || idx >= cp->NumberOfCommands || idx < 0) {                        \
+    KWSYSPE_DEBUG((stderr, "array index out of bound\n"));                    \
+    return RET;                                                               \
+  }
+
+int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(kwsysProcess_State_Error)
+  return cp->ProcessResults[idx].State;
+}
+
+int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other)
+  return cp->ProcessResults[idx].ExitException;
+}
+
+int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(-1)
+  return cp->ProcessResults[idx].ExitValue;
+}
+
+int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK(-1)
+  return cp->CommandExitCodes[idx];
+}
+
+const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx)
+{
+  KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management "
+                  "structure or index out of bound")
+  if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) {
+    return cp->ProcessResults[idx].ExitExceptionString;
+  }
+  return "No exception";
+}
+
+#undef KWSYSPE_IDX_CHK
+
 void kwsysProcess_Execute(kwsysProcess* cp)
 {
   int i;
@@ -1135,7 +1176,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
   cp->Detached = cp->OptionDetach;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_Disown(kwsysProcess* cp)
 {
   int i;
@@ -1162,8 +1202,6 @@ void kwsysProcess_Disown(kwsysProcess* cp)
   cp->State = kwsysProcess_State_Disowned;
 }
 
-/*--------------------------------------------------------------------------*/
-
 int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
                              double* userTimeout)
 {
@@ -1289,7 +1327,6 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
   }
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
 {
   int i;
@@ -1338,25 +1375,29 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
     /* The timeout expired.  */
     cp->State = kwsysProcess_State_Expired;
   } else {
-    /* The children exited.  Report the outcome of the last process.  */
-    cp->ExitCode = cp->CommandExitCodes[cp->NumberOfCommands - 1];
-    if ((cp->ExitCode & 0xF0000000) == 0xC0000000) {
-      /* Child terminated due to exceptional behavior.  */
-      cp->State = kwsysProcess_State_Exception;
-      cp->ExitValue = 1;
-      kwsysProcessSetExitException(cp, cp->ExitCode);
-    } else {
-      /* Child exited without exception.  */
-      cp->State = kwsysProcess_State_Exited;
-      cp->ExitException = kwsysProcess_Exception_None;
-      cp->ExitValue = cp->ExitCode;
+    /* The children exited.  Report the outcome of the child processes.  */
+    for (i = 0; i < cp->NumberOfCommands; ++i) {
+      cp->ProcessResults[i].ExitCode = cp->CommandExitCodes[i];
+      if ((cp->ProcessResults[i].ExitCode & 0xF0000000) == 0xC0000000) {
+        /* Child terminated due to exceptional behavior.  */
+        cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Exception;
+        cp->ProcessResults[i].ExitValue = 1;
+        kwsysProcessSetExitExceptionByIndex(cp, cp->ProcessResults[i].ExitCode,
+                                            i);
+      } else {
+        /* Child exited without exception.  */
+        cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Exited;
+        cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None;
+        cp->ProcessResults[i].ExitValue = cp->ProcessResults[i].ExitCode;
+      }
     }
+    /* support legacy state status value */
+    cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State;
   }
 
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_Interrupt(kwsysProcess* cp)
 {
   int i;
@@ -1394,7 +1435,6 @@ void kwsysProcess_Interrupt(kwsysProcess* cp)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_Kill(kwsysProcess* cp)
 {
   int i;
@@ -1429,8 +1469,6 @@ void kwsysProcess_Kill(kwsysProcess* cp)
      for them to exit.  */
 }
 
-/*--------------------------------------------------------------------------*/
-
 /*
   Function executed for each pipe's thread.  Argument is a pointer to
   the kwsysProcessPipeData instance for this thread.
@@ -1451,8 +1489,6 @@ DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd)
   return 0;
 }
 
-/*--------------------------------------------------------------------------*/
-
 /*
   Function called in each pipe's thread to handle data for one
   execution of a subprocess.
@@ -1494,8 +1530,6 @@ void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td)
   ReleaseSemaphore(td->Reader.Go, 1, 0);
 }
 
-/*--------------------------------------------------------------------------*/
-
 /*
   Function executed for each pipe's thread.  Argument is a pointer to
   the kwsysProcessPipeData instance for this thread.
@@ -1516,8 +1550,6 @@ DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd)
   return 0;
 }
 
-/*--------------------------------------------------------------------------*/
-
 /*
   Function called in each pipe's thread to handle reading thread
   wakeup for one execution of a subprocess.
@@ -1540,23 +1572,34 @@ void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, kwsysProcessPipeData* td)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 /* Initialize a process control structure for kwsysProcess_Execute.  */
 int kwsysProcessInitialize(kwsysProcess* cp)
 {
+  int i;
   /* Reset internal status flags.  */
   cp->TimeoutExpired = 0;
   cp->Terminated = 0;
   cp->Killed = 0;
-  cp->ExitException = kwsysProcess_Exception_None;
-  cp->ExitCode = 1;
-  cp->ExitValue = 1;
 
-  /* Reset error data.  */
-  cp->ErrorMessage[0] = 0;
-  strcpy(cp->ExitExceptionString, "No exception");
+  free(cp->ProcessResults);
+  /* Allocate process result information for each process.  */
+  cp->ProcessResults = (kwsysProcessResults*)malloc(
+    sizeof(kwsysProcessResults) * (cp->NumberOfCommands));
+  if (!cp->ProcessResults) {
+    return 0;
+  }
+  ZeroMemory(cp->ProcessResults,
+             sizeof(kwsysProcessResults) * cp->NumberOfCommands);
+  for (i = 0; i < cp->NumberOfCommands; i++) {
+    cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None;
+    cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Starting;
+    cp->ProcessResults[i].ExitCode = 1;
+    cp->ProcessResults[i].ExitValue = 1;
+    strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception");
+  }
 
   /* Allocate process information for each process.  */
+  free(cp->ProcessInformation);
   cp->ProcessInformation = (PROCESS_INFORMATION*)malloc(
     sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands);
   if (!cp->ProcessInformation) {
@@ -1596,7 +1639,6 @@ int kwsysProcessInitialize(kwsysProcess* cp)
     }
   }
   {
-    int i;
     for (i = 0; i < 3; ++i) {
       cp->PipeChildStd[i] = INVALID_HANDLE_VALUE;
     }
@@ -1605,7 +1647,6 @@ int kwsysProcessInitialize(kwsysProcess* cp)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 static DWORD kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn)
 {
   DWORD flags;
@@ -1641,7 +1682,6 @@ static DWORD kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 DWORD kwsysProcessCreate(kwsysProcess* cp, int index,
                          kwsysProcessCreateInformation* si)
 {
@@ -1706,7 +1746,6 @@ DWORD kwsysProcessCreate(kwsysProcess* cp, int index,
   return error;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcessDestroy(kwsysProcess* cp, int event)
 {
   int i;
@@ -1756,7 +1795,6 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 DWORD kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
 {
   HANDLE fout;
@@ -1784,7 +1822,6 @@ DWORD kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
   return ERROR_SUCCESS;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle)
 {
   /* Close the existing handle.  */
@@ -1793,7 +1830,6 @@ void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle)
   *handle = GetStdHandle(nStdHandle);
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle)
 {
   /* Close the existing handle.  */
@@ -1802,8 +1838,6 @@ void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle)
   *handle = native;
 }
 
-/*--------------------------------------------------------------------------*/
-
 /* Close the given handle if it is open.  Reset its value to 0.  */
 void kwsysProcessCleanupHandle(PHANDLE h)
 {
@@ -1816,8 +1850,6 @@ void kwsysProcessCleanupHandle(PHANDLE h)
   }
 }
 
-/*--------------------------------------------------------------------------*/
-
 /* Close all handles created by kwsysProcess_Execute.  */
 void kwsysProcessCleanup(kwsysProcess* cp, DWORD error)
 {
@@ -1902,7 +1934,6 @@ void kwsysProcessCleanup(kwsysProcess* cp, DWORD error)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcessCleanErrorMessage(kwsysProcess* cp)
 {
   /* Remove trailing period and newline, if any.  */
@@ -1920,7 +1951,6 @@ void kwsysProcessCleanErrorMessage(kwsysProcess* cp)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 /* Get the time at which either the process or user timeout will
    expire.  Returns 1 if the user timeout is first, and 0 otherwise.  */
 int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
@@ -1952,7 +1982,6 @@ int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
   return 0;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Get the length of time before the given timeout time arrives.
    Returns 1 if the time has already arrived, and 0 otherwise.  */
 int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
@@ -1982,7 +2011,6 @@ int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
   }
 }
 
-/*--------------------------------------------------------------------------*/
 kwsysProcessTime kwsysProcessTimeGetCurrent()
 {
   kwsysProcessTime current;
@@ -1993,19 +2021,16 @@ kwsysProcessTime kwsysProcessTimeGetCurrent()
   return current;
 }
 
-/*--------------------------------------------------------------------------*/
 DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t)
 {
   return (DWORD)(t.QuadPart * 0.0001);
 }
 
-/*--------------------------------------------------------------------------*/
 double kwsysProcessTimeToDouble(kwsysProcessTime t)
 {
   return t.QuadPart * 0.0000001;
 }
 
-/*--------------------------------------------------------------------------*/
 kwsysProcessTime kwsysProcessTimeFromDouble(double d)
 {
   kwsysProcessTime t;
@@ -2013,13 +2038,11 @@ kwsysProcessTime kwsysProcessTimeFromDouble(double d)
   return t;
 }
 
-/*--------------------------------------------------------------------------*/
 int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2)
 {
   return in1.QuadPart < in2.QuadPart;
 }
 
-/*--------------------------------------------------------------------------*/
 kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
                                      kwsysProcessTime in2)
 {
@@ -2028,7 +2051,6 @@ kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
   return out;
 }
 
-/*--------------------------------------------------------------------------*/
 kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
                                           kwsysProcessTime in2)
 {
@@ -2037,11 +2059,11 @@ kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
   return out;
 }
 
-/*--------------------------------------------------------------------------*/
 #define KWSYSPE_CASE(type, str)                                               \
-  cp->ExitException = kwsysProcess_Exception_##type;                          \
-  strcpy(cp->ExitExceptionString, str)
-static void kwsysProcessSetExitException(kwsysProcess* cp, int code)
+  cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_##type;      \
+  strcpy(cp->ProcessResults[idx].ExitExceptionString, str)
+static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code,
+                                                int idx)
 {
   switch (code) {
     case STATUS_CONTROL_C_EXIT:
@@ -2120,9 +2142,9 @@ static void kwsysProcessSetExitException(kwsysProcess* cp, int code)
 
     case STATUS_NO_MEMORY:
     default:
-      cp->ExitException = kwsysProcess_Exception_Other;
-      _snprintf(cp->ExitExceptionString, KWSYSPE_PIPE_BUFFER_SIZE,
-                "Exit code 0x%x\n", code);
+      cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
+      _snprintf(cp->ProcessResults[idx].ExitExceptionString,
+                KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code);
       break;
   }
 }
@@ -2136,7 +2158,6 @@ static int kwsysProcess_List_NextProcess(kwsysProcess_List* self);
 static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self);
 static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self);
 
-/*--------------------------------------------------------------------------*/
 /* Windows NT 4 API definitions.  */
 #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
 typedef LONG NTSTATUS;
@@ -2168,7 +2189,6 @@ struct _SYSTEM_PROCESS_INFORMATION
   ULONG InheritedFromProcessId;
 };
 
-/*--------------------------------------------------------------------------*/
 /* Toolhelp32 API definitions.  */
 #define TH32CS_SNAPPROCESS 0x00000002
 #if defined(_WIN64)
@@ -2192,7 +2212,6 @@ struct tagPROCESSENTRY32
   char szExeFile[MAX_PATH];
 };
 
-/*--------------------------------------------------------------------------*/
 /* Windows API function types.  */
 typedef HANDLE(WINAPI* CreateToolhelp32SnapshotType)(DWORD, DWORD);
 typedef BOOL(WINAPI* Process32FirstType)(HANDLE, LPPROCESSENTRY32);
@@ -2200,7 +2219,6 @@ typedef BOOL(WINAPI* Process32NextType)(HANDLE, LPPROCESSENTRY32);
 typedef NTSTATUS(WINAPI* ZwQuerySystemInformationType)(ULONG, PVOID, ULONG,
                                                        PULONG);
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__New_NT4(kwsysProcess_List* self);
 static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self);
 static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self);
@@ -2233,7 +2251,6 @@ struct kwsysProcess_List_s
   PROCESSENTRY32 CurrentEntry;
 };
 
-/*--------------------------------------------------------------------------*/
 static kwsysProcess_List* kwsysProcess_List_New(void)
 {
   OSVERSIONINFO osv;
@@ -2279,7 +2296,6 @@ static kwsysProcess_List* kwsysProcess_List_New(void)
   return self;
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcess_List_Delete(kwsysProcess_List* self)
 {
   if (self) {
@@ -2292,7 +2308,6 @@ static void kwsysProcess_List_Delete(kwsysProcess_List* self)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List_Update(kwsysProcess_List* self)
 {
   return self ? (self->NT4 ? kwsysProcess_List__Update_NT4(self)
@@ -2300,7 +2315,6 @@ static int kwsysProcess_List_Update(kwsysProcess_List* self)
               : 0;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self)
 {
   return self ? (self->NT4 ? kwsysProcess_List__GetProcessId_NT4(self)
@@ -2308,7 +2322,6 @@ static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self)
               : -1;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self)
 {
   return self ? (self->NT4 ? kwsysProcess_List__GetParentId_NT4(self)
@@ -2316,7 +2329,6 @@ static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self)
               : -1;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List_NextProcess(kwsysProcess_List* self)
 {
   return (self ? (self->NT4 ? kwsysProcess_List__Next_NT4(self)
@@ -2324,7 +2336,6 @@ static int kwsysProcess_List_NextProcess(kwsysProcess_List* self)
                : 0);
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__New_NT4(kwsysProcess_List* self)
 {
   /* Get a handle to the NT runtime module that should already be
@@ -2348,7 +2359,6 @@ static int kwsysProcess_List__New_NT4(kwsysProcess_List* self)
   return self->Buffer ? 1 : 0;
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self)
 {
   /* Free the process information buffer.  */
@@ -2357,7 +2367,6 @@ static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self)
 {
   self->CurrentInfo = 0;
@@ -2387,7 +2396,6 @@ static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self)
 {
   if (self->CurrentInfo) {
@@ -2401,19 +2409,16 @@ static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self)
   return 0;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List* self)
 {
   return self->CurrentInfo ? self->CurrentInfo->ProcessId : -1;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List* self)
 {
   return self->CurrentInfo ? self->CurrentInfo->InheritedFromProcessId : -1;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self)
 {
   /* Get a handle to the Windows runtime module that should already be
@@ -2436,7 +2441,6 @@ static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self)
     : 0;
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self)
 {
   if (self->Snapshot) {
@@ -2444,7 +2448,6 @@ static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self)
 {
   if (self->Snapshot) {
@@ -2464,7 +2467,6 @@ static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self)
 {
   if (self->Snapshot) {
@@ -2477,19 +2479,16 @@ static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self)
   return 0;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List* self)
 {
   return self->Snapshot ? self->CurrentEntry.th32ProcessID : -1;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List* self)
 {
   return self->Snapshot ? self->CurrentEntry.th32ParentProcessID : -1;
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessKill(DWORD pid)
 {
   HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, pid);
@@ -2500,7 +2499,6 @@ static void kwsysProcessKill(DWORD pid)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessKillTree(int pid)
 {
   kwsysProcess_List* plist = kwsysProcess_List_New();
@@ -2516,7 +2514,6 @@ static void kwsysProcessKillTree(int pid)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 static void kwsysProcessDisablePipeThreads(kwsysProcess* cp)
 {
   int i;
@@ -2568,7 +2565,6 @@ static void kwsysProcessDisablePipeThreads(kwsysProcess* cp)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 /* Global set of executing processes for use by the Ctrl handler.
    This global instance will be zero-initialized by the compiler.
 
@@ -2598,7 +2594,6 @@ typedef struct kwsysProcessInstances_s
 } kwsysProcessInstances;
 static kwsysProcessInstances kwsysProcesses;
 
-/*--------------------------------------------------------------------------*/
 /* Initialize critial section and set up console Ctrl handler.  You MUST call
    this before using any other kwsysProcesses* functions below.  */
 static int kwsysProcessesInitialize(void)
@@ -2617,7 +2612,6 @@ static int kwsysProcessesInitialize(void)
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 /* The Ctrl handler waits on the global list of processes.  To prevent an
    orphaned process, do not create a new process if the Ctrl handler is
    already running.  Do so by using this function to check if it is ok to
@@ -2636,7 +2630,6 @@ static int kwsysTryEnterCreateProcessSection(void)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 /* Matching function on successful kwsysTryEnterCreateProcessSection return.
    Make sure you called kwsysProcessesAdd if applicable before calling this.*/
 static void kwsysLeaveCreateProcessSection(void)
@@ -2644,7 +2637,6 @@ static void kwsysLeaveCreateProcessSection(void)
   LeaveCriticalSection(&kwsysProcesses.Lock);
 }
 
-/*--------------------------------------------------------------------------*/
 /* Add new process to global process list.  The Ctrl handler will wait for
    the process to exit before it returns.  Do not close the process handle
    until after calling kwsysProcessesRemove.  The newProcessGroup parameter
@@ -2702,7 +2694,6 @@ static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessid,
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Removes process to global process list.  */
 static void kwsysProcessesRemove(HANDLE hProcess)
 {
@@ -2738,7 +2729,6 @@ static void kwsysProcessesRemove(HANDLE hProcess)
   LeaveCriticalSection(&kwsysProcesses.Lock);
 }
 
-/*--------------------------------------------------------------------------*/
 static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType)
 {
   size_t i;
@@ -2774,7 +2764,6 @@ static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType)
   return FALSE;
 }
 
-/*--------------------------------------------------------------------------*/
 void kwsysProcess_ResetStartTime(kwsysProcess* cp)
 {
   if (!cp) {
diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in
index c9ae135..f638267 100644
--- a/Source/kwsys/SharedForward.h.in
+++ b/Source/kwsys/SharedForward.h.in
@@ -72,8 +72,6 @@
 #pragma warn - 8019
 #endif
 
-/*--------------------------------------------------------------------------*/
-
 /* Full path to the directory in which this executable is built.  Do
    not include a trailing slash.  */
 #if !defined(@KWSYS_NAMESPACE at _SHARED_FORWARD_DIR_BUILD)
@@ -159,7 +157,6 @@
 #undef KWSYS_SHARED_FORWARD_OPTION_LDD
 #endif
 
-/*--------------------------------------------------------------------------*/
 /* Include needed system headers.  */
 
 #include <errno.h>
@@ -180,7 +177,6 @@
 #include <unistd.h>
 #endif
 
-/*--------------------------------------------------------------------------*/
 /* Configuration for this platform.  */
 
 /* The path separator for this platform.  */
@@ -292,7 +288,6 @@ static const char kwsys_shared_forward_path_slash[2] = {
 #endif
 
 #ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
-/*--------------------------------------------------------------------------*/
 typedef struct kwsys_sf_arg_info_s
 {
   const char* arg;
@@ -300,7 +295,6 @@ typedef struct kwsys_sf_arg_info_s
   int quote;
 } kwsys_sf_arg_info;
 
-/*--------------------------------------------------------------------------*/
 static kwsys_sf_arg_info kwsys_sf_get_arg_info(const char* in)
 {
   /* Initialize information.  */
@@ -354,7 +348,6 @@ static kwsys_sf_arg_info kwsys_sf_get_arg_info(const char* in)
   return info;
 }
 
-/*--------------------------------------------------------------------------*/
 static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out)
 {
   /* String iterator.  */
@@ -413,7 +406,6 @@ static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out)
 }
 #endif
 
-/*--------------------------------------------------------------------------*/
 /* Function to convert a logical or relative path to a physical full path.  */
 static int kwsys_shared_forward_realpath(const char* in_path, char* out_path)
 {
@@ -428,7 +420,6 @@ static int kwsys_shared_forward_realpath(const char* in_path, char* out_path)
 #endif
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsys_shared_forward_samepath(const char* file1, const char* file2)
 {
 #if defined(_WIN32)
@@ -458,7 +449,6 @@ static int kwsys_shared_forward_samepath(const char* file1, const char* file2)
 #endif
 }
 
-/*--------------------------------------------------------------------------*/
 /* Function to report a system error message.  */
 static void kwsys_shared_forward_strerror(char* message)
 {
@@ -481,7 +471,6 @@ static void kwsys_shared_forward_strerror(char* message)
 #endif
 }
 
-/*--------------------------------------------------------------------------*/
 /* Functions to execute a child process.  */
 static void kwsys_shared_forward_execvp(const char* cmd,
                                         char const* const* argv)
@@ -521,7 +510,6 @@ static void kwsys_shared_forward_execvp(const char* cmd,
 #endif
 }
 
-/*--------------------------------------------------------------------------*/
 /* Function to get the directory containing the given file or directory.  */
 static void kwsys_shared_forward_dirname(const char* begin, char* result)
 {
@@ -557,7 +545,6 @@ static void kwsys_shared_forward_dirname(const char* begin, char* result)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 /* Function to check if a file exists and is executable.  */
 static int kwsys_shared_forward_is_executable(const char* f)
 {
@@ -578,7 +565,6 @@ static int kwsys_shared_forward_is_executable(const char* f)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 /* Function to locate the executable currently running.  */
 static int kwsys_shared_forward_self_path(const char* argv0, char* result)
 {
@@ -644,7 +630,6 @@ static int kwsys_shared_forward_self_path(const char* argv0, char* result)
   return 0;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Function to convert a specified path to a full path.  If it is not
    already full, it is taken relative to the self path.  */
 static int kwsys_shared_forward_fullpath(const char* self_path,
@@ -681,7 +666,6 @@ static int kwsys_shared_forward_fullpath(const char* self_path,
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Function to compute the library search path and executable name
    based on the self path.  */
 static int kwsys_shared_forward_get_settings(const char* self_path,
@@ -773,7 +757,6 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 /* Function to print why execution of a command line failed.  */
 static void kwsys_shared_forward_print_failure(char const* const* argv)
 {
@@ -791,7 +774,6 @@ static void kwsys_shared_forward_print_failure(char const* const* argv)
 static char kwsys_shared_forward_ldpath[65535] =
   KWSYS_SHARED_FORWARD_LDPATH "=";
 
-/*--------------------------------------------------------------------------*/
 /* Main driver function to be called from main.  */
 static int @KWSYS_NAMESPACE at _shared_forward_to_real(int argc, char** argv_in)
 {
diff --git a/Source/kwsys/System.c b/Source/kwsys/System.c
index 43c60c5..b9af8e9 100644
--- a/Source/kwsys/System.c
+++ b/Source/kwsys/System.c
@@ -22,7 +22,6 @@ typedef ptrdiff_t kwsysSystem_ptrdiff_t;
 typedef int kwsysSystem_ptrdiff_t;
 #endif
 
-/*--------------------------------------------------------------------------*/
 static int kwsysSystem__AppendByte(char* local, char** begin, char** end,
                                    int* size, char c)
 {
@@ -47,7 +46,6 @@ static int kwsysSystem__AppendByte(char* local, char** begin, char** end,
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 static int kwsysSystem__AppendArgument(char** local, char*** begin,
                                        char*** end, int* size, char* arg_local,
                                        char** arg_begin, char** arg_end,
@@ -91,7 +89,6 @@ static int kwsysSystem__AppendArgument(char** local, char*** begin,
   return 1;
 }
 
-/*--------------------------------------------------------------------------*/
 #define KWSYSPE_LOCAL_BYTE_COUNT 1024
 #define KWSYSPE_LOCAL_ARGS_COUNT 32
 static char** kwsysSystem__ParseUnixCommand(const char* command, int flags)
@@ -227,7 +224,6 @@ static char** kwsysSystem__ParseUnixCommand(const char* command, int flags)
   return newCommand;
 }
 
-/*--------------------------------------------------------------------------*/
 char** kwsysSystem_Parse_CommandForUnix(const char* command, int flags)
 {
   /* Validate the flags.  */
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index e01dcd7..86fdccd 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -35,8 +35,13 @@
 #include "SystemInformation.hxx.in"
 #endif
 
+#include <algorithm>
+#include <bitset>
+#include <cassert>
 #include <fstream>
 #include <iostream>
+#include <limits>
+#include <set>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -394,7 +399,6 @@ public:
     bool SupportsMP;
     bool HasMMXPlus;
     bool HasSSEMMX;
-    bool SupportsHyperthreading;
     unsigned int LogicalProcessorsPerPhysical;
     int APIC_ID;
     CPUPowerManagement PowerManagement;
@@ -463,10 +467,9 @@ protected:
   unsigned int NumberOfLogicalCPU;
   unsigned int NumberOfPhysicalCPU;
 
-  int CPUCount(); // For windows
-  unsigned char LogicalCPUPerPhysicalCPU();
+  void CPUCountWindows();    // For windows
   unsigned char GetAPICId(); // For windows
-  bool IsHyperThreadingSupported();
+  bool IsSMTSupported();
   static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows
 
   // For Linux and Cygwin, /proc/cpuinfo formats are slightly different
@@ -536,6 +539,7 @@ protected:
   std::string OSRelease;
   std::string OSVersion;
   std::string OSPlatform;
+  bool OSIs64Bit;
 };
 
 SystemInformation::SystemInformation()
@@ -834,7 +838,6 @@ void SystemInformation::RunMemoryCheck()
   this->Implementation->RunMemoryCheck();
 }
 
-// --------------------------------------------------------------
 // SystemInformationImplementation starts here
 
 #define STORE_TLBCACHE_INFO(x, y) x = (x < (y)) ? (y) : x
@@ -842,30 +845,6 @@ void SystemInformation::RunMemoryCheck()
 #define CLASSICAL_CPU_FREQ_LOOP 10000000
 #define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31
 
-#define MMX_FEATURE 0x00000001
-#define MMX_PLUS_FEATURE 0x00000002
-#define SSE_FEATURE 0x00000004
-#define SSE2_FEATURE 0x00000008
-#define AMD_3DNOW_FEATURE 0x00000010
-#define AMD_3DNOW_PLUS_FEATURE 0x00000020
-#define IA64_FEATURE 0x00000040
-#define MP_CAPABLE 0x00000080
-#define HYPERTHREAD_FEATURE 0x00000100
-#define SERIALNUMBER_FEATURE 0x00000200
-#define APIC_FEATURE 0x00000400
-#define SSE_FP_FEATURE 0x00000800
-#define SSE_MMX_FEATURE 0x00001000
-#define CMOV_FEATURE 0x00002000
-#define MTRR_FEATURE 0x00004000
-#define L1CACHE_FEATURE 0x00008000
-#define L2CACHE_FEATURE 0x00010000
-#define L3CACHE_FEATURE 0x00020000
-#define ACPI_FEATURE 0x00040000
-#define THERMALMONITOR_FEATURE 0x00080000
-#define TEMPSENSEDIODE_FEATURE 0x00100000
-#define FREQUENCYID_FEATURE 0x00200000
-#define VOLTAGEID_FREQUENCY 0x00400000
-
 // Status Flag
 #define HT_NOT_CAPABLE 0
 #define HT_ENABLED 1
@@ -939,7 +918,8 @@ int LoadLines(const char* fileName, std::vector<std::string>& lines)
 
 // ****************************************************************************
 template <typename T>
-int NameValue(std::vector<std::string>& lines, std::string name, T& value)
+int NameValue(std::vector<std::string> const& lines, std::string const& name,
+              T& value)
 {
   size_t nLines = lines.size();
   for (size_t i = 0; i < nLines; ++i) {
@@ -1310,7 +1290,6 @@ private:
   int ReportPath;
 };
 
-// --------------------------------------------------------------------------
 std::ostream& operator<<(std::ostream& os, const SymbolProperties& sp)
 {
 #if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
@@ -1329,7 +1308,6 @@ std::ostream& operator<<(std::ostream& os, const SymbolProperties& sp)
   return os;
 }
 
-// --------------------------------------------------------------------------
 SymbolProperties::SymbolProperties()
 {
   // not using an initializer list
@@ -1348,20 +1326,18 @@ SymbolProperties::SymbolProperties()
   this->GetLineNumber();
 }
 
-// --------------------------------------------------------------------------
 std::string SymbolProperties::GetFileName(const std::string& path) const
 {
   std::string file(path);
   if (!this->ReportPath) {
     size_t at = file.rfind("/");
     if (at != std::string::npos) {
-      file = file.substr(at + 1, std::string::npos);
+      file = file.substr(at + 1);
     }
   }
   return file;
 }
 
-// --------------------------------------------------------------------------
 std::string SymbolProperties::GetBinary() const
 {
 // only linux has proc fs
@@ -1382,7 +1358,6 @@ std::string SymbolProperties::GetBinary() const
   return this->GetFileName(this->Binary);
 }
 
-// --------------------------------------------------------------------------
 std::string SymbolProperties::Demangle(const char* symbol) const
 {
   std::string result = safes(symbol);
@@ -1402,7 +1377,6 @@ std::string SymbolProperties::Demangle(const char* symbol) const
   return result;
 }
 
-// --------------------------------------------------------------------------
 void SymbolProperties::Initialize(void* address)
 {
   this->Address = address;
@@ -1421,7 +1395,6 @@ void SymbolProperties::Initialize(void* address)
 }
 #endif // don't define this class if we're not using it
 
-// --------------------------------------------------------------------------
 #if defined(_WIN32) || defined(__CYGWIN__)
 #define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
 #endif
@@ -1496,6 +1469,7 @@ SystemInformationImplementation::SystemInformationImplementation()
   this->OSRelease = "";
   this->OSVersion = "";
   this->OSPlatform = "";
+  this->OSIs64Bit = (sizeof(void*) == 8);
 }
 
 SystemInformationImplementation::~SystemInformationImplementation()
@@ -1542,7 +1516,7 @@ void SystemInformationImplementation::RunCPUCheck()
     RetrieveProcessorSerialNumber();
   }
 
-  this->CPUCount();
+  this->CPUCountWindows();
 
 #elif defined(__APPLE__)
   this->ParseSysCtl();
@@ -1870,11 +1844,11 @@ int SystemInformationImplementation::GetProcessorCacheSize()
 int SystemInformationImplementation::GetProcessorCacheXSize(long int dwCacheID)
 {
   switch (dwCacheID) {
-    case L1CACHE_FEATURE:
+    case SystemInformation::CPU_FEATURE_L1CACHE:
       return this->Features.L1CacheSize;
-    case L2CACHE_FEATURE:
+    case SystemInformation::CPU_FEATURE_L2CACHE:
       return this->Features.L2CacheSize;
-    case L3CACHE_FEATURE:
+    case SystemInformation::CPU_FEATURE_L3CACHE:
       return this->Features.L3CacheSize;
   }
   return -1;
@@ -1885,104 +1859,121 @@ bool SystemInformationImplementation::DoesCPUSupportFeature(long int dwFeature)
   bool bHasFeature = false;
 
   // Check for MMX instructions.
-  if (((dwFeature & MMX_FEATURE) != 0) && this->Features.HasMMX)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_MMX) != 0) &&
+      this->Features.HasMMX)
     bHasFeature = true;
 
   // Check for MMX+ instructions.
-  if (((dwFeature & MMX_PLUS_FEATURE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_MMX_PLUS) != 0) &&
       this->Features.ExtendedFeatures.HasMMXPlus)
     bHasFeature = true;
 
   // Check for SSE FP instructions.
-  if (((dwFeature & SSE_FEATURE) != 0) && this->Features.HasSSE)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_SSE) != 0) &&
+      this->Features.HasSSE)
     bHasFeature = true;
 
   // Check for SSE FP instructions.
-  if (((dwFeature & SSE_FP_FEATURE) != 0) && this->Features.HasSSEFP)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_SSE_FP) != 0) &&
+      this->Features.HasSSEFP)
     bHasFeature = true;
 
   // Check for SSE MMX instructions.
-  if (((dwFeature & SSE_MMX_FEATURE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_SSE_MMX) != 0) &&
       this->Features.ExtendedFeatures.HasSSEMMX)
     bHasFeature = true;
 
   // Check for SSE2 instructions.
-  if (((dwFeature & SSE2_FEATURE) != 0) && this->Features.HasSSE2)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_SSE2) != 0) &&
+      this->Features.HasSSE2)
     bHasFeature = true;
 
   // Check for 3DNow! instructions.
-  if (((dwFeature & AMD_3DNOW_FEATURE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_AMD_3DNOW) != 0) &&
       this->Features.ExtendedFeatures.Has3DNow)
     bHasFeature = true;
 
   // Check for 3DNow+ instructions.
-  if (((dwFeature & AMD_3DNOW_PLUS_FEATURE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS) != 0) &&
       this->Features.ExtendedFeatures.Has3DNowPlus)
     bHasFeature = true;
 
   // Check for IA64 instructions.
-  if (((dwFeature & IA64_FEATURE) != 0) && this->Features.HasIA64)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_IA64) != 0) &&
+      this->Features.HasIA64)
     bHasFeature = true;
 
   // Check for MP capable.
-  if (((dwFeature & MP_CAPABLE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_MP_CAPABLE) != 0) &&
       this->Features.ExtendedFeatures.SupportsMP)
     bHasFeature = true;
 
   // Check for a serial number for the processor.
-  if (((dwFeature & SERIALNUMBER_FEATURE) != 0) && this->Features.HasSerial)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_SERIALNUMBER) != 0) &&
+      this->Features.HasSerial)
     bHasFeature = true;
 
   // Check for a local APIC in the processor.
-  if (((dwFeature & APIC_FEATURE) != 0) && this->Features.HasAPIC)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_APIC) != 0) &&
+      this->Features.HasAPIC)
     bHasFeature = true;
 
   // Check for CMOV instructions.
-  if (((dwFeature & CMOV_FEATURE) != 0) && this->Features.HasCMOV)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_CMOV) != 0) &&
+      this->Features.HasCMOV)
     bHasFeature = true;
 
   // Check for MTRR instructions.
-  if (((dwFeature & MTRR_FEATURE) != 0) && this->Features.HasMTRR)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_MTRR) != 0) &&
+      this->Features.HasMTRR)
     bHasFeature = true;
 
   // Check for L1 cache size.
-  if (((dwFeature & L1CACHE_FEATURE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_L1CACHE) != 0) &&
       (this->Features.L1CacheSize != -1))
     bHasFeature = true;
 
   // Check for L2 cache size.
-  if (((dwFeature & L2CACHE_FEATURE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_L2CACHE) != 0) &&
       (this->Features.L2CacheSize != -1))
     bHasFeature = true;
 
   // Check for L3 cache size.
-  if (((dwFeature & L3CACHE_FEATURE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_L3CACHE) != 0) &&
       (this->Features.L3CacheSize != -1))
     bHasFeature = true;
 
   // Check for ACPI capability.
-  if (((dwFeature & ACPI_FEATURE) != 0) && this->Features.HasACPI)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_ACPI) != 0) &&
+      this->Features.HasACPI)
     bHasFeature = true;
 
   // Check for thermal monitor support.
-  if (((dwFeature & THERMALMONITOR_FEATURE) != 0) && this->Features.HasThermal)
+  if (((dwFeature & SystemInformation::CPU_FEATURE_THERMALMONITOR) != 0) &&
+      this->Features.HasThermal)
     bHasFeature = true;
 
   // Check for temperature sensing diode support.
-  if (((dwFeature & TEMPSENSEDIODE_FEATURE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_TEMPSENSEDIODE) != 0) &&
       this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode)
     bHasFeature = true;
 
   // Check for frequency ID support.
-  if (((dwFeature & FREQUENCYID_FEATURE) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_FREQUENCYID) != 0) &&
       this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID)
     bHasFeature = true;
 
   // Check for voltage ID support.
-  if (((dwFeature & VOLTAGEID_FREQUENCY) != 0) &&
+  if (((dwFeature & SystemInformation::CPU_FEATURE_VOLTAGEID_FREQUENCY) !=
+       0) &&
       this->Features.ExtendedFeatures.PowerManagement.HasVoltageID)
     bHasFeature = true;
 
+  // Check for FPU support.
+  if (((dwFeature & SystemInformation::CPU_FEATURE_FPU) != 0) &&
+      this->Features.HasFPU)
+    bHasFeature = true;
+
   return bHasFeature;
 }
 
@@ -2090,16 +2081,10 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
 
   // Retrieve Intel specific extended features.
   if (this->ChipManufacturer == Intel) {
-    this->Features.ExtendedFeatures.SupportsHyperthreading =
-      ((cpuinfo[3] & 0x10000000) !=
-       0); // Intel specific: Hyperthreading --> Bit 28
-    this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
-      (this->Features.ExtendedFeatures.SupportsHyperthreading)
-      ? ((cpuinfo[1] & 0x00FF0000) >> 16)
-      : 1;
-
-    if ((this->Features.ExtendedFeatures.SupportsHyperthreading) &&
-        (this->Features.HasAPIC)) {
+    bool SupportsSMT =
+      ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: SMT --> Bit 28
+
+    if ((SupportsSMT) && (this->Features.HasAPIC)) {
       // Retrieve APIC information if there is one present.
       this->Features.ExtendedFeatures.APIC_ID =
         ((cpuinfo[1] & 0xFF000000) >> 24);
@@ -3357,11 +3342,11 @@ std::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(
   std::string buffer, const char* word, size_t init)
 {
   size_t pos = buffer.find(word, init);
-  if (pos != buffer.npos) {
+  if (pos != std::string::npos) {
     this->CurrentPositionInFile = pos;
     pos = buffer.find(":", pos);
     size_t pos2 = buffer.find("\n", pos);
-    if (pos != buffer.npos && pos2 != buffer.npos) {
+    if (pos != std::string::npos && pos2 != std::string::npos) {
       // It may happen that the beginning matches, but this is still not the
       // requested key.
       // An example is looking for "cpu" when "cpu family" comes first. So we
@@ -3376,7 +3361,7 @@ std::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(
       return buffer.substr(pos + 2, pos2 - pos - 2);
     }
   }
-  this->CurrentPositionInFile = buffer.npos;
+  this->CurrentPositionInFile = std::string::npos;
   return "";
 }
 
@@ -3401,38 +3386,33 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
   fclose(fd);
   buffer.resize(fileSize - 2);
   // Number of logical CPUs (combination of multiple processors, multi-core
-  // and hyperthreading)
+  // and SMT)
   size_t pos = buffer.find("processor\t");
-  while (pos != buffer.npos) {
+  while (pos != std::string::npos) {
     this->NumberOfLogicalCPU++;
     pos = buffer.find("processor\t", pos + 1);
   }
 
 #ifdef __linux
-  // Find the largest physical id.
-  int maxId = -1;
+  // Count sockets.
+  std::set<int> PhysicalIDs;
   std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id");
-  while (this->CurrentPositionInFile != buffer.npos) {
+  while (this->CurrentPositionInFile != std::string::npos) {
     int id = atoi(idc.c_str());
-    if (id > maxId) {
-      maxId = id;
-    }
+    PhysicalIDs.insert(id);
     idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id",
                                             this->CurrentPositionInFile + 1);
   }
+  uint64_t NumberOfSockets = PhysicalIDs.size();
+  NumberOfSockets = std::max(NumberOfSockets, (uint64_t)1);
   // Physical ids returned by Linux don't distinguish cores.
   // We want to record the total number of cores in this->NumberOfPhysicalCPU
   // (checking only the first proc)
-  std::string cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores");
-  int numberOfCoresPerCPU = atoi(cores.c_str());
-  if (maxId > 0) {
-    this->NumberOfPhysicalCPU =
-      static_cast<unsigned int>(numberOfCoresPerCPU * (maxId + 1));
-  } else {
-    // Linux Sparc: get cpu count
-    this->NumberOfPhysicalCPU =
-      atoi(this->ExtractValueFromCpuInfoFile(buffer, "ncpus active").c_str());
-  }
+  std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores");
+  unsigned int NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str());
+  NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u);
+  this->NumberOfPhysicalCPU =
+    NumberOfCoresPerSocket * (unsigned int)NumberOfSockets;
 
 #else // __CYGWIN__
   // does not have "physical id" entries, neither "cpu cores"
@@ -3447,7 +3427,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
   if (this->NumberOfPhysicalCPU <= 0) {
     this->NumberOfPhysicalCPU = 1;
   }
-  // LogicalProcessorsPerPhysical>1 => hyperthreading.
+  // LogicalProcessorsPerPhysical>1 => SMT.
   this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
     this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU;
 
@@ -3527,7 +3507,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
       this->ExtractValueFromCpuInfoFile(buffer, cachename[index]);
     if (!cacheSize.empty()) {
       pos = cacheSize.find(" KB");
-      if (pos != cacheSize.npos) {
+      if (pos != std::string::npos) {
         cacheSize = cacheSize.substr(0, pos);
       }
       this->Features.L1CacheSize += atoi(cacheSize.c_str());
@@ -4322,68 +4302,10 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS)
   (void)uiMS;
 }
 
-/** Return the number of logical CPU per physical CPUs Works only for windows
- */
-unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void)
-{
-#ifdef __APPLE__
-  size_t len = 4;
-  int cores_per_package = 0;
-  int err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package,
-                         &len, NULL, 0);
-  if (err != 0) {
-    return 1; // That name was not found, default to 1
-  }
-  return static_cast<unsigned char>(cores_per_package);
-#else
-  int Regs[4] = { 0, 0, 0, 0 };
-#if USE_CPUID
-  if (!this->IsHyperThreadingSupported()) {
-    return static_cast<unsigned char>(1); // HT not supported
-  }
-  call_cpuid(1, Regs);
-#endif
-  return static_cast<unsigned char>((Regs[1] & NUM_LOGICAL_BITS) >> 16);
-#endif
-}
-
 /** Works only for windows */
-bool SystemInformationImplementation::IsHyperThreadingSupported()
+bool SystemInformationImplementation::IsSMTSupported()
 {
-  if (this->Features.ExtendedFeatures.SupportsHyperthreading) {
-    return true;
-  }
-
-#if USE_CPUID
-  int Regs[4] = { 0, 0, 0, 0 }, VendorId[4] = { 0, 0, 0, 0 };
-  // Get vendor id string
-  if (!call_cpuid(0, VendorId)) {
-    return false;
-  }
-  // eax contains family processor type
-  // edx has info about the availability of hyper-Threading
-  if (!call_cpuid(1, Regs)) {
-    return false;
-  }
-
-  if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) {
-    if (VendorId[1] == 0x756e6547) // 'uneG'
-    {
-      if (VendorId[3] == 0x49656e69) // 'Ieni'
-      {
-        if (VendorId[2] == 0x6c65746e) // 'letn'
-        {
-          // Genuine Intel with hyper-Threading technology
-          this->Features.ExtendedFeatures.SupportsHyperthreading =
-            ((Regs[3] & HT_BIT) != 0);
-          return this->Features.ExtendedFeatures.SupportsHyperthreading;
-        }
-      }
-    }
-  }
-#endif
-
-  return 0; // Not genuine Intel processor
+  return this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical > 1;
 }
 
 /** Return the APIC Id. Works only for windows. */
@@ -4392,7 +4314,7 @@ unsigned char SystemInformationImplementation::GetAPICId()
   int Regs[4] = { 0, 0, 0, 0 };
 
 #if USE_CPUID
-  if (!this->IsHyperThreadingSupported()) {
+  if (!this->IsSMTSupported()) {
     return static_cast<unsigned char>(-1); // HT not supported
   }                                        // Logical processor = 1
   call_cpuid(1, Regs);
@@ -4402,102 +4324,63 @@ unsigned char SystemInformationImplementation::GetAPICId()
 }
 
 /** Count the number of CPUs. Works only on windows. */
-int SystemInformationImplementation::CPUCount()
+void SystemInformationImplementation::CPUCountWindows()
 {
 #if defined(_WIN32)
-  unsigned char StatusFlag = 0;
-  SYSTEM_INFO info;
-
   this->NumberOfPhysicalCPU = 0;
   this->NumberOfLogicalCPU = 0;
-  info.dwNumberOfProcessors = 0;
-  GetSystemInfo(&info);
-
-  // Number of physical processors in a non-Intel system
-  // or in a 32-bit Intel system with Hyper-Threading technology disabled
-  this->NumberOfPhysicalCPU = (unsigned char)info.dwNumberOfProcessors;
-
-  if (this->IsHyperThreadingSupported()) {
-    unsigned char HT_Enabled = 0;
-    this->NumberOfLogicalCPU = this->LogicalCPUPerPhysicalCPU();
-    if (this->NumberOfLogicalCPU >=
-        1) // >1 Doesn't mean HT is enabled in the BIOS
-    {
-      HANDLE hCurrentProcessHandle;
-#ifndef _WIN64
-#define DWORD_PTR DWORD
-#endif
-      DWORD_PTR dwProcessAffinity;
-      DWORD_PTR dwSystemAffinity;
-      DWORD dwAffinityMask;
-
-      // Calculate the appropriate  shifts and mask based on the
-      // number of logical processors.
-      unsigned int i = 1;
-      unsigned char PHY_ID_MASK = 0xFF;
-      // unsigned char PHY_ID_SHIFT = 0;
-
-      while (i < this->NumberOfLogicalCPU) {
-        i *= 2;
-        PHY_ID_MASK <<= 1;
-        // PHY_ID_SHIFT++;
-      }
-
-      hCurrentProcessHandle = GetCurrentProcess();
-      GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity,
-                             &dwSystemAffinity);
 
-      // Check if available process affinity mask is equal to the
-      // available system affinity mask
-      if (dwProcessAffinity != dwSystemAffinity) {
-        StatusFlag = HT_CANNOT_DETECT;
-        this->NumberOfPhysicalCPU = (unsigned char)-1;
-        return StatusFlag;
-      }
-
-      dwAffinityMask = 1;
-      while (dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity) {
-        // Check if this CPU is available
-        if (dwAffinityMask & dwProcessAffinity) {
-          if (SetProcessAffinityMask(hCurrentProcessHandle, dwAffinityMask)) {
-            unsigned char APIC_ID, LOG_ID;
-            Sleep(0); // Give OS time to switch CPU
-
-            APIC_ID = GetAPICId();
-            LOG_ID = APIC_ID & ~PHY_ID_MASK;
+  typedef BOOL(WINAPI * GetLogicalProcessorInformationType)(
+    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
+  static GetLogicalProcessorInformationType pGetLogicalProcessorInformation =
+    (GetLogicalProcessorInformationType)GetProcAddress(
+      GetModuleHandleW(L"kernel32"), "GetLogicalProcessorInformation");
+
+  if (!pGetLogicalProcessorInformation) {
+    // Fallback to approximate implementation on ancient Windows versions.
+    SYSTEM_INFO info;
+    ZeroMemory(&info, sizeof(info));
+    GetSystemInfo(&info);
+    this->NumberOfPhysicalCPU =
+      static_cast<unsigned int>(info.dwNumberOfProcessors);
+    this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
+    return;
+  }
 
-            if (LOG_ID != 0) {
-              HT_Enabled = 1;
-            }
-          }
-        }
-        dwAffinityMask = dwAffinityMask << 1;
-      }
-      // Reset the processor affinity
-      SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity);
+  std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> ProcInfo;
+  {
+    DWORD Length = 0;
+    DWORD rc = pGetLogicalProcessorInformation(NULL, &Length);
+    assert(FALSE == rc);
+    (void)rc; // Silence unused variable warning in Borland C++ 5.81
+    assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+    ProcInfo.resize(Length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
+    rc = pGetLogicalProcessorInformation(&ProcInfo[0], &Length);
+    assert(rc != FALSE);
+    (void)rc; // Silence unused variable warning in Borland C++ 5.81
+  }
+
+  typedef std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>::iterator
+    pinfoIt_t;
+  for (pinfoIt_t it = ProcInfo.begin(); it != ProcInfo.end(); ++it) {
+    SYSTEM_LOGICAL_PROCESSOR_INFORMATION PInfo = *it;
+    if (PInfo.Relationship != RelationProcessorCore) {
+      continue;
+    }
 
-      if (this->NumberOfLogicalCPU ==
-          1) // Normal P4 : HT is disabled in hardware
-      {
-        StatusFlag = HT_DISABLED;
-      } else {
-        if (HT_Enabled) {
-          // Total physical processors in a Hyper-Threading enabled system.
-          this->NumberOfPhysicalCPU /= (this->NumberOfLogicalCPU);
-          StatusFlag = HT_ENABLED;
-        } else {
-          StatusFlag = HT_SUPPORTED_NOT_ENABLED;
-        }
-      }
+    std::bitset<std::numeric_limits<ULONG_PTR>::digits> ProcMask(
+      (unsigned long long)PInfo.ProcessorMask);
+    unsigned int count = (unsigned int)ProcMask.count();
+    if (count == 0) { // I think this should never happen, but just to be safe.
+      continue;
     }
-  } else {
-    // Processors do not have Hyper-Threading technology
-    StatusFlag = HT_NOT_CAPABLE;
-    this->NumberOfLogicalCPU = 1;
+    this->NumberOfPhysicalCPU++;
+    this->NumberOfLogicalCPU += (unsigned int)count;
+    this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = count;
   }
-  return StatusFlag;
+  this->NumberOfPhysicalCPU = std::max(1u, this->NumberOfPhysicalCPU);
+  this->NumberOfLogicalCPU = std::max(1u, this->NumberOfLogicalCPU);
 #else
-  return 0;
 #endif
 }
 
@@ -4559,8 +4442,14 @@ bool SystemInformationImplementation::ParseSysCtl()
   sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0);
   len = sizeof(this->NumberOfLogicalCPU);
   sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0);
+
+  int cores_per_package = 0;
+  len = sizeof(cores_per_package);
+  err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len,
+                     NULL, 0);
+  // That name was not found, default to 1
   this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
-    this->LogicalCPUPerPhysicalCPU();
+    err != 0 ? 1 : static_cast<unsigned char>(cores_per_package);
 
   len = sizeof(value);
   sysctlbyname("hw.cpufrequency", &value, &len, NULL, 0);
@@ -4697,10 +4586,10 @@ std::string SystemInformationImplementation::ExtractValueFromSysCtl(
   const char* word)
 {
   size_t pos = this->SysCtlBuffer.find(word);
-  if (pos != this->SysCtlBuffer.npos) {
+  if (pos != std::string::npos) {
     pos = this->SysCtlBuffer.find(": ", pos);
     size_t pos2 = this->SysCtlBuffer.find("\n", pos);
-    if (pos != this->SysCtlBuffer.npos && pos2 != this->SysCtlBuffer.npos) {
+    if (pos != std::string::npos && pos2 != std::string::npos) {
       return this->SysCtlBuffer.substr(pos + 2, pos2 - pos - 2);
     }
   }
@@ -4772,14 +4661,14 @@ std::string SystemInformationImplementation::ParseValueFromKStat(
   args.push_back("-p");
 
   std::string command = arguments;
-  size_t start = command.npos;
+  size_t start = std::string::npos;
   size_t pos = command.find(' ', 0);
-  while (pos != command.npos) {
+  while (pos != std::string::npos) {
     bool inQuotes = false;
     // Check if we are between quotes
     size_t b0 = command.find('"', 0);
     size_t b1 = command.find('"', b0 + 1);
-    while (b0 != command.npos && b1 != command.npos && b1 > b0) {
+    while (b0 != std::string::npos && b1 != std::string::npos && b1 > b0) {
       if (pos > b0 && pos < b1) {
         inQuotes = true;
         break;
@@ -4793,7 +4682,7 @@ std::string SystemInformationImplementation::ParseValueFromKStat(
 
       // Remove the quotes if any
       size_t quotes = arg.find('"');
-      while (quotes != arg.npos) {
+      while (quotes != std::string::npos) {
         arg.erase(quotes, 1);
         quotes = arg.find('"');
       }
@@ -4976,11 +4865,11 @@ bool SystemInformationImplementation::QueryQNXMemory()
   args.clear();
 
   size_t pos = buffer.find("System RAM:");
-  if (pos == buffer.npos)
+  if (pos == std::string::npos)
     return false;
   pos = buffer.find(":", pos);
   size_t pos2 = buffer.find("M (", pos);
-  if (pos2 == buffer.npos)
+  if (pos2 == std::string::npos)
     return false;
 
   pos++;
@@ -5034,11 +4923,11 @@ bool SystemInformationImplementation::QueryQNXProcessor()
   args.clear();
 
   size_t pos = buffer.find("Processor1:");
-  if (pos == buffer.npos)
+  if (pos == std::string::npos)
     return false;
 
   size_t pos2 = buffer.find("MHz", pos);
-  if (pos2 == buffer.npos)
+  if (pos2 == std::string::npos)
     return false;
 
   size_t pos3 = pos2;
@@ -5048,9 +4937,9 @@ bool SystemInformationImplementation::QueryQNXProcessor()
   this->CPUSpeedInMHz = atoi(buffer.substr(pos3 + 1, pos2 - pos3 - 1).c_str());
 
   pos2 = buffer.find(" Stepping", pos);
-  if (pos2 != buffer.npos) {
+  if (pos2 != std::string::npos) {
     pos2 = buffer.find(" ", pos2 + 1);
-    if (pos2 != buffer.npos && pos2 < pos3) {
+    if (pos2 != std::string::npos && pos2 < pos3) {
       this->ChipID.Revision =
         atoi(buffer.substr(pos2 + 1, pos3 - pos2).c_str());
     }
@@ -5060,7 +4949,7 @@ bool SystemInformationImplementation::QueryQNXProcessor()
   do {
     pos = buffer.find("\nProcessor", pos + 1);
     ++this->NumberOfPhysicalCPU;
-  } while (pos != buffer.npos);
+  } while (pos != std::string::npos);
   this->NumberOfLogicalCPU = 1;
 
   return true;
@@ -5436,10 +5325,20 @@ bool SystemInformationImplementation::QueryOSInformation()
   this->Hostname = name;
 
   const char* arch = getenv("PROCESSOR_ARCHITECTURE");
+  const char* wow64 = getenv("PROCESSOR_ARCHITEW6432");
   if (arch) {
     this->OSPlatform = arch;
   }
 
+  if (wow64) {
+    // the PROCESSOR_ARCHITEW6432 is only defined when running 32bit programs
+    // on 64bit OS
+    this->OSIs64Bit = true;
+  } else if (arch) {
+    // all values other than x86 map to 64bit architectures
+    this->OSIs64Bit = (strncmp(arch, "x86", 3) != 0);
+  }
+
 #else
 
   struct utsname unameInfo;
@@ -5450,6 +5349,12 @@ bool SystemInformationImplementation::QueryOSInformation()
     this->OSRelease = unameInfo.release;
     this->OSVersion = unameInfo.version;
     this->OSPlatform = unameInfo.machine;
+
+    // This is still insufficient to capture 64bit architecture such
+    // powerpc and possible mips and sparc
+    if (this->OSPlatform.find_first_of("64") != std::string::npos) {
+      this->OSIs64Bit = true;
+    }
   }
 
 #ifdef __APPLE__
@@ -5503,6 +5408,6 @@ void SystemInformationImplementation::TrimNewline(std::string& output)
 /** Return true if the machine is 64 bits */
 bool SystemInformationImplementation::Is64Bits()
 {
-  return (sizeof(void*) == 8);
+  return this->OSIs64Bit;
 }
 }
diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in
index 0fc1067..516c505 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -26,6 +26,33 @@ class @KWSYS_NAMESPACE at _EXPORT SystemInformation
   SystemInformationImplementation* Implementation;
 
 public:
+  // possible parameter values for DoesCPUSupportFeature()
+  static const long int CPU_FEATURE_MMX = 1 << 0;
+  static const long int CPU_FEATURE_MMX_PLUS = 1 << 1;
+  static const long int CPU_FEATURE_SSE = 1 << 2;
+  static const long int CPU_FEATURE_SSE2 = 1 << 3;
+  static const long int CPU_FEATURE_AMD_3DNOW = 1 << 4;
+  static const long int CPU_FEATURE_AMD_3DNOW_PLUS = 1 << 5;
+  static const long int CPU_FEATURE_IA64 = 1 << 6;
+  static const long int CPU_FEATURE_MP_CAPABLE = 1 << 7;
+  static const long int CPU_FEATURE_HYPERTHREAD = 1 << 8;
+  static const long int CPU_FEATURE_SERIALNUMBER = 1 << 9;
+  static const long int CPU_FEATURE_APIC = 1 << 10;
+  static const long int CPU_FEATURE_SSE_FP = 1 << 11;
+  static const long int CPU_FEATURE_SSE_MMX = 1 << 12;
+  static const long int CPU_FEATURE_CMOV = 1 << 13;
+  static const long int CPU_FEATURE_MTRR = 1 << 14;
+  static const long int CPU_FEATURE_L1CACHE = 1 << 15;
+  static const long int CPU_FEATURE_L2CACHE = 1 << 16;
+  static const long int CPU_FEATURE_L3CACHE = 1 << 17;
+  static const long int CPU_FEATURE_ACPI = 1 << 18;
+  static const long int CPU_FEATURE_THERMALMONITOR = 1 << 19;
+  static const long int CPU_FEATURE_TEMPSENSEDIODE = 1 << 20;
+  static const long int CPU_FEATURE_FREQUENCYID = 1 << 21;
+  static const long int CPU_FEATURE_VOLTAGEID_FREQUENCY = 1 << 22;
+  static const long int CPU_FEATURE_FPU = 1 << 23;
+
+public:
   SystemInformation();
   ~SystemInformation();
 
@@ -65,9 +92,10 @@ public:
   // on this system.
   std::string GetOSDescription();
 
+  // returns if the operating system is 64bit or not.
   bool Is64Bits();
 
-  unsigned int GetNumberOfLogicalCPU(); // per physical cpu
+  unsigned int GetNumberOfLogicalCPU();
   unsigned int GetNumberOfPhysicalCPU();
 
   bool DoesCPUSupportCPUID();
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 97dd4ae..1c4fe33 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -22,6 +22,7 @@
 #include KWSYS_HEADER(FStream.hxx)
 #include KWSYS_HEADER(Encoding.hxx)
 
+#include <algorithm>
 #include <fstream>
 #include <iostream>
 #include <set>
@@ -54,7 +55,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <time.h>
 
 #if defined(_WIN32) && !defined(_MSC_VER) && defined(__GNUC__)
@@ -217,12 +217,12 @@ static time_t windows_filetime_to_posix_time(const FILETIME& ft)
 inline int Mkdir(const std::string& dir)
 {
   return _wmkdir(
-    KWSYS_NAMESPACE::SystemTools::ConvertToWindowsExtendedPath(dir).c_str());
+    KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str());
 }
 inline int Rmdir(const std::string& dir)
 {
   return _wrmdir(
-    KWSYS_NAMESPACE::SystemTools::ConvertToWindowsExtendedPath(dir).c_str());
+    KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str());
 }
 inline const char* Getcwd(char* buf, unsigned int len)
 {
@@ -548,15 +548,13 @@ bool SystemTools::HasEnv(const std::string& key)
   return SystemTools::HasEnv(key.c_str());
 }
 
-//----------------------------------------------------------------------------
-
 #if KWSYS_CXX_HAS_UNSETENV
 /* unsetenv("A") removes A from the environment.
    On older platforms it returns void instead of int.  */
 static int kwsysUnPutEnv(const std::string& env)
 {
   size_t pos = env.find('=');
-  if (pos != env.npos) {
+  if (pos != std::string::npos) {
     std::string name = env.substr(0, pos);
     unsetenv(name.c_str());
   } else {
@@ -572,7 +570,7 @@ static int kwsysUnPutEnv(const std::string& env)
 {
   int err = 0;
   size_t pos = env.find('=');
-  size_t const len = pos == env.npos ? env.size() : pos;
+  size_t const len = pos == std::string::npos ? env.size() : pos;
   size_t const sz = len + 1;
   char local_buf[256];
   char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
@@ -606,7 +604,7 @@ static int kwsysUnPutEnv(std::string const& env)
 {
   std::wstring wEnv = Encoding::ToWide(env);
   size_t const pos = wEnv.find('=');
-  size_t const len = pos == wEnv.npos ? wEnv.size() : pos;
+  size_t const len = pos == std::string::npos ? wEnv.size() : pos;
   wEnv.resize(len + 1, L'=');
   wchar_t* newEnv = _wcsdup(wEnv.c_str());
   if (!newEnv) {
@@ -622,7 +620,7 @@ static int kwsysUnPutEnv(std::string const& env)
 static int kwsysUnPutEnv(const std::string& env)
 {
   size_t pos = env.find('=');
-  size_t const len = pos == env.npos ? env.size() : pos;
+  size_t const len = pos == std::string::npos ? env.size() : pos;
   int in = 0;
   int out = 0;
   while (environ[in]) {
@@ -640,8 +638,6 @@ static int kwsysUnPutEnv(const std::string& env)
 }
 #endif
 
-//----------------------------------------------------------------------------
-
 #if KWSYS_CXX_HAS_SETENV
 
 /* setenv("A", "B", 1) will set A=B in the environment and makes its
@@ -649,7 +645,7 @@ static int kwsysUnPutEnv(const std::string& env)
 bool SystemTools::PutEnv(const std::string& env)
 {
   size_t pos = env.find('=');
-  if (pos != env.npos) {
+  if (pos != std::string::npos) {
     std::string name = env.substr(0, pos);
     return setenv(name.c_str(), env.c_str() + pos + 1, 1) == 0;
   } else {
@@ -732,8 +728,6 @@ bool SystemTools::UnPutEnv(const std::string& env)
 
 #endif
 
-//----------------------------------------------------------------------------
-
 const char* SystemTools::GetExecutableExtension()
 {
 #if defined(_WIN32) || defined(__CYGWIN__) || defined(__VMS)
@@ -746,7 +740,7 @@ const char* SystemTools::GetExecutableExtension()
 FILE* SystemTools::Fopen(const std::string& file, const char* mode)
 {
 #ifdef _WIN32
-  return _wfopen(SystemTools::ConvertToWindowsExtendedPath(file).c_str(),
+  return _wfopen(Encoding::ToWindowsExtendedPath(file).c_str(),
                  Encoding::ToWide(mode).c_str());
 #else
   return fopen(file.c_str(), mode);
@@ -1145,7 +1139,6 @@ bool SystemTools::SameFile(const std::string& file1, const std::string& file2)
 #endif
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::PathExists(const std::string& path)
 {
   if (path.empty()) {
@@ -1160,8 +1153,7 @@ bool SystemTools::PathExists(const std::string& path)
   struct stat st;
   return lstat(path.c_str(), &st) == 0;
 #elif defined(_WIN32)
-  return (GetFileAttributesW(
-            SystemTools::ConvertToWindowsExtendedPath(path).c_str()) !=
+  return (GetFileAttributesW(Encoding::ToWindowsExtendedPath(path).c_str()) !=
           INVALID_FILE_ATTRIBUTES);
 #else
   struct stat st;
@@ -1169,7 +1161,6 @@ bool SystemTools::PathExists(const std::string& path)
 #endif
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::FileExists(const char* filename)
 {
   if (!filename) {
@@ -1178,7 +1169,6 @@ bool SystemTools::FileExists(const char* filename)
   return SystemTools::FileExists(std::string(filename));
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::FileExists(const std::string& filename)
 {
   if (filename.empty()) {
@@ -1192,9 +1182,9 @@ bool SystemTools::FileExists(const std::string& filename)
   }
   return access(filename.c_str(), R_OK) == 0;
 #elif defined(_WIN32)
-  return (GetFileAttributesW(
-            SystemTools::ConvertToWindowsExtendedPath(filename).c_str()) !=
-          INVALID_FILE_ATTRIBUTES);
+  return (
+    GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()) !=
+    INVALID_FILE_ATTRIBUTES);
 #else
 // SCO OpenServer 5.0.7/3.2's command has 711 permission.
 #if defined(_SCO_DS)
@@ -1205,7 +1195,6 @@ bool SystemTools::FileExists(const std::string& filename)
 #endif
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::FileExists(const char* filename, bool isFile)
 {
   if (!filename) {
@@ -1214,7 +1203,6 @@ bool SystemTools::FileExists(const char* filename, bool isFile)
   return SystemTools::FileExists(std::string(filename), isFile);
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::FileExists(const std::string& filename, bool isFile)
 {
   if (SystemTools::FileExists(filename)) {
@@ -1225,7 +1213,6 @@ bool SystemTools::FileExists(const std::string& filename, bool isFile)
   return false;
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::TestFileAccess(const char* filename,
                                  TestFilePermissions permissions)
 {
@@ -1235,7 +1222,6 @@ bool SystemTools::TestFileAccess(const char* filename,
   return SystemTools::TestFileAccess(std::string(filename), permissions);
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::TestFileAccess(const std::string& filename,
                                  TestFilePermissions permissions)
 {
@@ -1250,14 +1236,43 @@ bool SystemTools::TestFileAccess(const std::string& filename,
     permissions &= ~TEST_FILE_EXECUTE;
     permissions |= TEST_FILE_READ;
   }
-  return _waccess(SystemTools::ConvertToWindowsExtendedPath(filename).c_str(),
+  return _waccess(Encoding::ToWindowsExtendedPath(filename).c_str(),
                   permissions) == 0;
 #else
   return access(filename.c_str(), permissions) == 0;
 #endif
 }
 
-//----------------------------------------------------------------------------
+int SystemTools::Stat(const char* path, SystemTools::Stat_t* buf)
+{
+  if (!path) {
+    errno = EFAULT;
+    return -1;
+  }
+  return SystemTools::Stat(std::string(path), buf);
+}
+
+int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf)
+{
+  if (path.empty()) {
+    errno = ENOENT;
+    return -1;
+  }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // Ideally we should use Encoding::ToWindowsExtendedPath to support
+  // long paths, but _wstat64 rejects paths with '?' in them, thinking
+  // they are wildcards.
+  std::wstring const& wpath = Encoding::ToWide(path);
+#if defined(__BORLANDC__)
+  return _wstati64(wpath.c_str(), buf);
+#else
+  return _wstat64(wpath.c_str(), buf);
+#endif
+#else
+  return stat(path.c_str(), buf);
+#endif
+}
+
 #ifdef __CYGWIN__
 bool SystemTools::PathCygwinToWin32(const char* path, char* win32_path)
 {
@@ -1293,10 +1308,9 @@ bool SystemTools::Touch(const std::string& filename, bool create)
     }
   }
 #if defined(_WIN32) && !defined(__CYGWIN__)
-  HANDLE h =
-    CreateFileW(SystemTools::ConvertToWindowsExtendedPath(filename).c_str(),
-                FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING,
-                FILE_FLAG_BACKUP_SEMANTICS, 0);
+  HANDLE h = CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(),
+                         FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0,
+                         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
   if (!h) {
     return false;
   }
@@ -1394,14 +1408,12 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
   // Windows version.  Get the modification time from extended file attributes.
   WIN32_FILE_ATTRIBUTE_DATA f1d;
   WIN32_FILE_ATTRIBUTE_DATA f2d;
-  if (!GetFileAttributesExW(
-        SystemTools::ConvertToWindowsExtendedPath(f1).c_str(),
-        GetFileExInfoStandard, &f1d)) {
+  if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f1).c_str(),
+                            GetFileExInfoStandard, &f1d)) {
     return false;
   }
-  if (!GetFileAttributesExW(
-        SystemTools::ConvertToWindowsExtendedPath(f2).c_str(),
-        GetFileExInfoStandard, &f2d)) {
+  if (!GetFileAttributesExW(Encoding::ToWindowsExtendedPath(f2).c_str(),
+                            GetFileExInfoStandard, &f2d)) {
     return false;
   }
 
@@ -1710,7 +1722,7 @@ std::string SystemTools::CropString(const std::string& s, size_t max_len)
   size_t middle = max_len / 2;
 
   n += s.substr(0, middle);
-  n += s.substr(s.size() - (max_len - middle), std::string::npos);
+  n += s.substr(s.size() - (max_len - middle));
 
   if (max_len > 2) {
     n[middle] = '.';
@@ -1725,7 +1737,6 @@ std::string SystemTools::CropString(const std::string& s, size_t max_len)
   return n;
 }
 
-//----------------------------------------------------------------------------
 std::vector<kwsys::String> SystemTools::SplitString(const std::string& p,
                                                     char sep, bool isPath)
 {
@@ -1750,7 +1761,6 @@ std::vector<kwsys::String> SystemTools::SplitString(const std::string& p,
   return paths;
 }
 
-//----------------------------------------------------------------------------
 int SystemTools::EstimateFormatLength(const char* format, va_list ap)
 {
   if (!format) {
@@ -1841,7 +1851,7 @@ static void ConvertVMSToUnix(std::string& path)
 {
   std::string::size_type rootEnd = path.find(":[");
   std::string::size_type pathEnd = path.find("]");
-  if (rootEnd != path.npos) {
+  if (rootEnd != std::string::npos) {
     std::string root = path.substr(0, rootEnd);
     std::string pathPart = path.substr(rootEnd + 2, pathEnd - rootEnd - 2);
     const char* pathCString = pathPart.c_str();
@@ -1929,59 +1939,10 @@ void SystemTools::ConvertToUnixSlashes(std::string& path)
 }
 
 #ifdef _WIN32
-// Convert local paths to UNC style paths
 std::wstring SystemTools::ConvertToWindowsExtendedPath(
   const std::string& source)
 {
-  std::wstring wsource = Encoding::ToWide(source);
-
-  // Resolve any relative paths
-  DWORD wfull_len;
-
-  /* The +3 is a workaround for a bug in some versions of GetFullPathNameW that
-   * won't return a large enough buffer size if the input is too small */
-  wfull_len = GetFullPathNameW(wsource.c_str(), 0, NULL, NULL) + 3;
-  std::vector<wchar_t> wfull(wfull_len);
-  GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], NULL);
-
-  /* This should get the correct size without any extra padding from the
-   * previous size workaround. */
-  wfull_len = static_cast<DWORD>(wcslen(&wfull[0]));
-
-  if (wfull_len >= 2 && isalpha(wfull[0]) &&
-      wfull[1] == L':') { /* C:\Foo\bar\FooBar.txt */
-    return L"\\\\?\\" + std::wstring(&wfull[0]);
-  } else if (wfull_len >= 2 && wfull[0] == L'\\' &&
-             wfull[1] == L'\\') { /* Starts with \\ */
-    if (wfull_len >= 4 && wfull[2] == L'?' &&
-        wfull[3] == L'\\') { /* Starts with \\?\ */
-      if (wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' &&
-          wfull[6] == L'C' &&
-          wfull[7] == L'\\') { /* \\?\UNC\Foo\bar\FooBar.txt */
-        return std::wstring(&wfull[0]);
-      } else if (wfull_len >= 6 && isalpha(wfull[4]) &&
-                 wfull[5] == L':') { /* \\?\C:\Foo\bar\FooBar.txt */
-        return std::wstring(&wfull[0]);
-      } else if (wfull_len >= 5) { /* \\?\Foo\bar\FooBar.txt */
-        return L"\\\\?\\UNC\\" + std::wstring(&wfull[4]);
-      }
-    } else if (wfull_len >= 4 && wfull[2] == L'.' &&
-               wfull[3] == L'\\') { /* Starts with \\.\ a device name */
-      if (wfull_len >= 6 && isalpha(wfull[4]) &&
-          wfull[5] == L':') { /* \\.\C:\Foo\bar\FooBar.txt */
-        return L"\\\\?\\" + std::wstring(&wfull[4]);
-      } else if (wfull_len >=
-                 5) { /* \\.\Foo\bar\ Device name is left unchanged */
-        return std::wstring(&wfull[0]);
-      }
-    } else if (wfull_len >= 3) { /* \\Foo\bar\FooBar.txt */
-      return L"\\\\?\\UNC\\" + std::wstring(&wfull[2]);
-    }
-  }
-
-  // If this case has been reached, then the path is invalid.  Leave it
-  // unchanged
-  return Encoding::ToWide(source);
+  return Encoding::ToWindowsExtendedPath(source);
 }
 #endif
 
@@ -2098,15 +2059,14 @@ bool SystemTools::FilesDiffer(const std::string& source,
 
 #if defined(_WIN32)
   WIN32_FILE_ATTRIBUTE_DATA statSource;
-  if (GetFileAttributesExW(
-        SystemTools::ConvertToWindowsExtendedPath(source).c_str(),
-        GetFileExInfoStandard, &statSource) == 0) {
+  if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(source).c_str(),
+                           GetFileExInfoStandard, &statSource) == 0) {
     return true;
   }
 
   WIN32_FILE_ATTRIBUTE_DATA statDestination;
   if (GetFileAttributesExW(
-        SystemTools::ConvertToWindowsExtendedPath(destination).c_str(),
+        Encoding::ToWindowsExtendedPath(destination).c_str(),
         GetFileExInfoStandard, &statDestination) == 0) {
     return true;
   }
@@ -2188,7 +2148,6 @@ bool SystemTools::FilesDiffer(const std::string& source,
   return false;
 }
 
-//----------------------------------------------------------------------------
 /**
  * Copy a file named by "source" to the file named by "destination".
  */
@@ -2230,8 +2189,7 @@ bool SystemTools::CopyFileAlways(const std::string& source,
 // Open files
 #if defined(_WIN32)
     kwsys::ifstream fin(
-      Encoding::ToNarrow(SystemTools::ConvertToWindowsExtendedPath(source))
-        .c_str(),
+      Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(),
       std::ios::in | std::ios::binary);
 #else
     kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
@@ -2248,8 +2206,7 @@ bool SystemTools::CopyFileAlways(const std::string& source,
 
 #if defined(_WIN32)
     kwsys::ofstream fout(
-      Encoding::ToNarrow(
-        SystemTools::ConvertToWindowsExtendedPath(real_destination))
+      Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(real_destination))
         .c_str(),
       std::ios::out | std::ios::trunc | std::ios::binary);
 #else
@@ -2294,7 +2251,6 @@ bool SystemTools::CopyFileAlways(const std::string& source,
   return true;
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::CopyAFile(const std::string& source,
                             const std::string& destination, bool always)
 {
@@ -2314,8 +2270,7 @@ bool SystemTools::CopyADirectory(const std::string& source,
 {
   Directory dir;
 #ifdef _WIN32
-  dir.Load(
-    Encoding::ToNarrow(SystemTools::ConvertToWindowsExtendedPath(source)));
+  dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)));
 #else
   dir.Load(source);
 #endif
@@ -2353,9 +2308,8 @@ unsigned long SystemTools::FileLength(const std::string& filename)
   unsigned long length = 0;
 #ifdef _WIN32
   WIN32_FILE_ATTRIBUTE_DATA fs;
-  if (GetFileAttributesExW(
-        SystemTools::ConvertToWindowsExtendedPath(filename).c_str(),
-        GetFileExInfoStandard, &fs) != 0) {
+  if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(),
+                           GetFileExInfoStandard, &fs) != 0) {
     /* To support the full 64-bit file size, use fs.nFileSizeHigh
      * and fs.nFileSizeLow to construct the 64 bit size
 
@@ -2389,9 +2343,8 @@ long int SystemTools::ModifiedTime(const std::string& filename)
   long int mt = 0;
 #ifdef _WIN32
   WIN32_FILE_ATTRIBUTE_DATA fs;
-  if (GetFileAttributesExW(
-        SystemTools::ConvertToWindowsExtendedPath(filename).c_str(),
-        GetFileExInfoStandard, &fs) != 0) {
+  if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(),
+                           GetFileExInfoStandard, &fs) != 0) {
     mt = windows_filetime_to_posix_time(fs.ftLastWriteTime);
   }
 #else
@@ -2409,9 +2362,8 @@ long int SystemTools::CreationTime(const std::string& filename)
   long int ct = 0;
 #ifdef _WIN32
   WIN32_FILE_ATTRIBUTE_DATA fs;
-  if (GetFileAttributesExW(
-        SystemTools::ConvertToWindowsExtendedPath(filename).c_str(),
-        GetFileExInfoStandard, &fs) != 0) {
+  if (GetFileAttributesExW(Encoding::ToWindowsExtendedPath(filename).c_str(),
+                           GetFileExInfoStandard, &fs) != 0) {
     ct = windows_filetime_to_posix_time(fs.ftCreationTime);
   }
 #else
@@ -2625,7 +2577,7 @@ static bool DeleteJunction(const std::wstring& source)
 bool SystemTools::RemoveFile(const std::string& source)
 {
 #ifdef _WIN32
-  std::wstring const& ws = SystemTools::ConvertToWindowsExtendedPath(source);
+  std::wstring const& ws = Encoding::ToWindowsExtendedPath(source);
   if (DeleteFileW(ws.c_str())) {
     return true;
   }
@@ -2675,8 +2627,7 @@ bool SystemTools::RemoveADirectory(const std::string& source)
 
   Directory dir;
 #ifdef _WIN32
-  dir.Load(
-    Encoding::ToNarrow(SystemTools::ConvertToWindowsExtendedPath(source)));
+  dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)));
 #else
   dir.Load(source);
 #endif
@@ -3033,8 +2984,8 @@ bool SystemTools::FileIsDirectory(const std::string& inName)
 
 // Now check the file node type.
 #if defined(_WIN32)
-  DWORD attr = GetFileAttributesW(
-    SystemTools::ConvertToWindowsExtendedPath(name).c_str());
+  DWORD attr =
+    GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str());
   if (attr != INVALID_FILE_ATTRIBUTES) {
     return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
 #else
@@ -3050,8 +3001,8 @@ bool SystemTools::FileIsDirectory(const std::string& inName)
 bool SystemTools::FileIsSymlink(const std::string& name)
 {
 #if defined(_WIN32)
-  DWORD attr = GetFileAttributesW(
-    SystemTools::ConvertToWindowsExtendedPath(name).c_str());
+  DWORD attr =
+    GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str());
   if (attr != INVALID_FILE_ATTRIBUTES) {
     return (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
   } else {
@@ -3067,6 +3018,28 @@ bool SystemTools::FileIsSymlink(const std::string& name)
 #endif
 }
 
+bool SystemTools::FileIsFIFO(const std::string& name)
+{
+#if defined(_WIN32)
+  HANDLE hFile =
+    CreateFileW(Encoding::ToWide(name).c_str(), GENERIC_READ, FILE_SHARE_READ,
+                NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+  if (hFile == INVALID_HANDLE_VALUE) {
+    return false;
+  }
+  const DWORD type = GetFileType(hFile);
+  CloseHandle(hFile);
+  return type == FILE_TYPE_PIPE;
+#else
+  struct stat fs;
+  if (lstat(name.c_str(), &fs) == 0) {
+    return S_ISFIFO(fs.st_mode);
+  } else {
+    return false;
+  }
+#endif
+}
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
 bool SystemTools::CreateSymlink(const std::string&, const std::string&)
 {
@@ -3309,7 +3282,7 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path,
   SystemTools::SplitPath(in_path, path_components);
 
   // If the input path is relative, start with a base path.
-  if (path_components[0].length() == 0) {
+  if (path_components[0].empty()) {
     std::vector<std::string> base_components;
     if (in_base) {
       // Use the given base path.
@@ -3558,7 +3531,6 @@ static std::string GetCasePathName(std::string const& pathIn)
 }
 #endif
 
-//----------------------------------------------------------------------------
 std::string SystemTools::GetActualCaseForPath(const std::string& p)
 {
 #ifndef _WIN32
@@ -3579,7 +3551,6 @@ std::string SystemTools::GetActualCaseForPath(const std::string& p)
 #endif
 }
 
-//----------------------------------------------------------------------------
 const char* SystemTools::SplitPathRootComponent(const std::string& p,
                                                 std::string* root)
 {
@@ -3646,7 +3617,6 @@ const char* SystemTools::SplitPathRootComponent(const std::string& p,
   return c;
 }
 
-//----------------------------------------------------------------------------
 void SystemTools::SplitPath(const std::string& p,
                             std::vector<std::string>& components,
                             bool expand_home_dir)
@@ -3703,13 +3673,11 @@ void SystemTools::SplitPath(const std::string& p,
   }
 }
 
-//----------------------------------------------------------------------------
 std::string SystemTools::JoinPath(const std::vector<std::string>& components)
 {
   return SystemTools::JoinPath(components.begin(), components.end());
 }
 
-//----------------------------------------------------------------------------
 std::string SystemTools::JoinPath(
   std::vector<std::string>::const_iterator first,
   std::vector<std::string>::const_iterator last)
@@ -3741,7 +3709,16 @@ std::string SystemTools::JoinPath(
   return result;
 }
 
-//----------------------------------------------------------------------------
+void SystemTools::RemoveEmptyPathElements(std::vector<std::string>& path)
+{
+  if (path.empty()) {
+    return;
+  }
+
+  path.erase(std::remove(path.begin() + 1, path.end(), std::string("")),
+             path.end());
+}
+
 bool SystemTools::ComparePath(const std::string& c1, const std::string& c2)
 {
 #if defined(_WIN32) || defined(__APPLE__)
@@ -3757,7 +3734,6 @@ bool SystemTools::ComparePath(const std::string& c1, const std::string& c2)
 #endif
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::Split(const std::string& str,
                         std::vector<std::string>& lines, char separator)
 {
@@ -3778,7 +3754,6 @@ bool SystemTools::Split(const std::string& str,
   return true;
 }
 
-//----------------------------------------------------------------------------
 bool SystemTools::Split(const std::string& str,
                         std::vector<std::string>& lines)
 {
@@ -4345,8 +4320,8 @@ bool SystemTools::GetPermissions(const char* file, mode_t& mode)
 bool SystemTools::GetPermissions(const std::string& file, mode_t& mode)
 {
 #if defined(_WIN32)
-  DWORD attr = GetFileAttributesW(
-    SystemTools::ConvertToWindowsExtendedPath(file).c_str());
+  DWORD attr =
+    GetFileAttributesW(Encoding::ToWindowsExtendedPath(file).c_str());
   if (attr == INVALID_FILE_ATTRIBUTES) {
     return false;
   }
@@ -4362,7 +4337,7 @@ bool SystemTools::GetPermissions(const std::string& file, mode_t& mode)
     mode |= S_IFREG;
   }
   size_t dotPos = file.rfind('.');
-  const char* ext = dotPos == file.npos ? 0 : (file.c_str() + dotPos);
+  const char* ext = dotPos == std::string::npos ? 0 : (file.c_str() + dotPos);
   if (ext && (Strucmp(ext, ".exe") == 0 || Strucmp(ext, ".com") == 0 ||
               Strucmp(ext, ".cmd") == 0 || Strucmp(ext, ".bat") == 0)) {
     mode |= (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6));
@@ -4398,8 +4373,7 @@ bool SystemTools::SetPermissions(const std::string& file, mode_t mode,
     mode &= ~currentMask;
   }
 #ifdef _WIN32
-  if (_wchmod(SystemTools::ConvertToWindowsExtendedPath(file).c_str(), mode) <
-      0)
+  if (_wchmod(Encoding::ToWindowsExtendedPath(file).c_str(), mode) < 0)
 #else
   if (chmod(file.c_str(), mode) < 0)
 #endif
@@ -4716,7 +4690,6 @@ std::string SystemTools::GetOperatingSystemNameAndVersion()
   return res;
 }
 
-// ----------------------------------------------------------------------
 bool SystemTools::ParseURLProtocol(const std::string& URL,
                                    std::string& protocol,
                                    std::string& dataglom)
@@ -4735,7 +4708,6 @@ bool SystemTools::ParseURLProtocol(const std::string& URL,
   return true;
 }
 
-// ----------------------------------------------------------------------
 bool SystemTools::ParseURL(const std::string& URL, std::string& protocol,
                            std::string& username, std::string& password,
                            std::string& hostname, std::string& dataport,
@@ -4766,7 +4738,6 @@ bool SystemTools::ParseURL(const std::string& URL, std::string& protocol,
   return true;
 }
 
-// ----------------------------------------------------------------------
 // These must NOT be initialized.  Default initialization to zero is
 // necessary.
 static unsigned int SystemToolsManagerCount;
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index f3d06fe..5e091c2 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -13,6 +13,9 @@
 #include <@KWSYS_NAMESPACE@/String.hxx>
 
 #include <sys/types.h>
+// include sys/stat.h after sys/types.h
+#include <sys/stat.h>
+
 #if !defined(_WIN32) || defined(__CYGWIN__)
 #include <unistd.h> // For access permissions for use with access()
 #endif
@@ -262,13 +265,7 @@ public:
   static void ConvertToUnixSlashes(std::string& path);
 
 #ifdef _WIN32
-  /**
-   * Convert the path to an extended length path to avoid MAX_PATH length
-   * limitations on Windows. If the input is a local path the result will be
-   * prefixed with \\?\; if the input is instead a network path, the result
-   * will be prefixed with \\?\UNC\. All output will also be converted to
-   * absolute paths with Windows-style backslashes.
-   **/
+  /** Calls Encoding::ToWindowsExtendedPath.  */
   static std::wstring ConvertToWindowsExtendedPath(const std::string&);
 #endif
 
@@ -324,6 +321,27 @@ public:
                              TestFilePermissions permissions);
   static bool TestFileAccess(const std::string& filename,
                              TestFilePermissions permissions);
+/**
+ * Cross platform wrapper for stat struct
+ */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(__BORLANDC__)
+  typedef struct stati64 Stat_t;
+#else
+  typedef struct _stat64 Stat_t;
+#endif
+#else
+  typedef struct stat Stat_t;
+#endif
+
+  /**
+   * Cross platform wrapper for stat system call
+   *
+   * On Windows this may not work for paths longer than 250 characters
+   * due to limitations of the underlying '_wstat64' call.
+   */
+  static int Stat(const char* path, Stat_t* buf);
+  static int Stat(const std::string& path, Stat_t* buf);
 
 /**
  * Converts Cygwin path to Win32 path. Uses dictionary container for
@@ -456,6 +474,10 @@ public:
   static std::string JoinPath(std::vector<std::string>::const_iterator first,
                               std::vector<std::string>::const_iterator last);
 
+  /** Removes empty components from path.
+   */
+  static void RemoveEmptyPathElements(std::vector<std::string>& path);
+
   /**
    * Compare a path or components of a path.
    */
@@ -654,6 +676,11 @@ public:
   static bool FileIsSymlink(const std::string& name);
 
   /**
+   * Return true if the file is a FIFO
+   */
+  static bool FileIsFIFO(const std::string& name);
+
+  /**
    * Return true if the file has a given signature (first set of bytes)
    */
   static bool FileHasSignature(const char* filename, const char* signature,
diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c
index c0b7f45..eaa5c7d 100644
--- a/Source/kwsys/Terminal.c
+++ b/Source/kwsys/Terminal.c
@@ -9,7 +9,6 @@
 #include "Terminal.h.in"
 #endif
 
-/*--------------------------------------------------------------------------*/
 /* Configure support for this platform.  */
 #if defined(_WIN32) || defined(__CYGWIN__)
 #define KWSYS_TERMINAL_SUPPORT_CONSOLE
@@ -18,7 +17,6 @@
 #define KWSYS_TERMINAL_ISATTY_WORKS
 #endif
 
-/*--------------------------------------------------------------------------*/
 /* Include needed system APIs.  */
 
 #include <stdarg.h> /* va_list */
@@ -36,7 +34,6 @@
 #include <sys/stat.h> /* fstat */
 #endif
 
-/*--------------------------------------------------------------------------*/
 static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
                                       int default_tty);
 static void kwsysTerminalSetVT100Color(FILE* stream, int color);
@@ -47,7 +44,6 @@ static void kwsysTerminalSetConsoleColor(HANDLE hOut,
                                          FILE* stream, int color);
 #endif
 
-/*--------------------------------------------------------------------------*/
 void kwsysTerminal_cfprintf(int color, FILE* stream, const char* format, ...)
 {
   /* Setup the stream with the given color if possible.  */
@@ -89,7 +85,6 @@ void kwsysTerminal_cfprintf(int color, FILE* stream, const char* format, ...)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 /* Detect cases when a stream is definitely not interactive.  */
 #if !defined(KWSYS_TERMINAL_ISATTY_WORKS)
 static int kwsysTerminalStreamIsNotInteractive(FILE* stream)
@@ -106,7 +101,6 @@ static int kwsysTerminalStreamIsNotInteractive(FILE* stream)
 }
 #endif
 
-/*--------------------------------------------------------------------------*/
 /* List of terminal names known to support VT100 color escape sequences.  */
 static const char* kwsysTerminalVT100Names[] = { "Eterm",
                                                  "ansi",
@@ -162,7 +156,6 @@ static const char* kwsysTerminalVT100Names[] = { "Eterm",
                                                  "xterm-termite",
                                                  0 };
 
-/*--------------------------------------------------------------------------*/
 /* Detect whether a stream is displayed in a VT100-compatible terminal.  */
 static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
                                       int default_tty)
@@ -214,7 +207,6 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
 #endif
 }
 
-/*--------------------------------------------------------------------------*/
 /* VT100 escape sequence strings.  */
 #define KWSYS_TERMINAL_VT100_NORMAL "\33[0m"
 #define KWSYS_TERMINAL_VT100_BOLD "\33[1m"
@@ -238,7 +230,6 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
 #define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN "\33[46m"
 #define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE "\33[47m"
 
-/*--------------------------------------------------------------------------*/
 /* Write VT100 escape sequences to the stream for the given color.  */
 static void kwsysTerminalSetVT100Color(FILE* stream, int color)
 {
@@ -307,7 +298,6 @@ static void kwsysTerminalSetVT100Color(FILE* stream, int color)
   }
 }
 
-/*--------------------------------------------------------------------------*/
 #if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
 
 #define KWSYS_TERMINAL_MASK_FOREGROUND                                        \
diff --git a/Source/kwsys/kwsysPlatformTestsC.c b/Source/kwsys/kwsysPlatformTestsC.c
index d12fac0..64a361b 100644
--- a/Source/kwsys/kwsysPlatformTestsC.c
+++ b/Source/kwsys/kwsysPlatformTestsC.c
@@ -27,7 +27,6 @@
   main(int argc, char* argv[])
 #endif
 
-/*--------------------------------------------------------------------------*/
 #ifdef TEST_KWSYS_C_HAS_PTRDIFF_T
 #include <stddef.h>
 int f(ptrdiff_t n)
@@ -43,7 +42,6 @@ int KWSYS_PLATFORM_TEST_C_MAIN()
 }
 #endif
 
-/*--------------------------------------------------------------------------*/
 #ifdef TEST_KWSYS_C_HAS_SSIZE_T
 #include <unistd.h>
 int f(ssize_t n)
@@ -57,7 +55,6 @@ int KWSYS_PLATFORM_TEST_C_MAIN()
 }
 #endif
 
-/*--------------------------------------------------------------------------*/
 #ifdef TEST_KWSYS_C_TYPE_MACROS
 char* info_macros =
 #if defined(__SIZEOF_SHORT__)
diff --git a/Source/kwsys/testConsoleBuf.cxx b/Source/kwsys/testConsoleBuf.cxx
index 3b8cdab..816a433 100644
--- a/Source/kwsys/testConsoleBuf.cxx
+++ b/Source/kwsys/testConsoleBuf.cxx
@@ -74,7 +74,6 @@ std::basic_streambuf<wchar_t>* errstream(const wchar_t* unused)
   return std::wcerr.rdbuf();
 }
 
-//----------------------------------------------------------------------------
 template <typename T>
 static void dumpBuffers(const T* expected, const T* received, size_t size)
 {
@@ -107,7 +106,6 @@ static void dumpBuffers(const T* expected, const T* received, size_t size)
   std::cerr << std::endl;
 }
 
-//----------------------------------------------------------------------------
 static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr)
 {
   BOOL bInheritHandles = FALSE;
@@ -158,7 +156,6 @@ static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr)
   return success;
 }
 
-//----------------------------------------------------------------------------
 static void finishProcess(bool success)
 {
   if (success) {
@@ -172,7 +169,6 @@ static void finishProcess(bool success)
   CloseHandle(processInfo.hThread);
 }
 
-//----------------------------------------------------------------------------
 static bool createPipe(PHANDLE readPipe, PHANDLE writePipe)
 {
   SECURITY_ATTRIBUTES securityAttributes;
@@ -183,7 +179,6 @@ static bool createPipe(PHANDLE readPipe, PHANDLE writePipe)
                                                                       : true;
 }
 
-//----------------------------------------------------------------------------
 static void finishPipe(HANDLE readPipe, HANDLE writePipe)
 {
   if (readPipe != INVALID_HANDLE_VALUE) {
@@ -194,7 +189,6 @@ static void finishPipe(HANDLE readPipe, HANDLE writePipe)
   }
 }
 
-//----------------------------------------------------------------------------
 static HANDLE createFile(LPCWSTR fileName)
 {
   SECURITY_ATTRIBUTES securityAttributes;
@@ -218,7 +212,6 @@ static HANDLE createFile(LPCWSTR fileName)
   return file;
 }
 
-//----------------------------------------------------------------------------
 static void finishFile(HANDLE file)
 {
   if (file != INVALID_HANDLE_VALUE) {
@@ -226,8 +219,6 @@ static void finishFile(HANDLE file)
   }
 }
 
-//----------------------------------------------------------------------------
-
 #ifndef MAPVK_VK_TO_VSC
 #define MAPVK_VK_TO_VSC (0)
 #endif
@@ -269,7 +260,6 @@ static void writeInputKeyEvent(INPUT_RECORD inputBuffer[], WCHAR chr)
   inputBuffer[1].Event.KeyEvent.dwControlKeyState = 0;
 }
 
-//----------------------------------------------------------------------------
 static int testPipe()
 {
   int didFail = 1;
@@ -339,9 +329,8 @@ static int testPipe()
             throw std::runtime_error("ReadFile#3 failed!");
           }
           buffer2[bytesRead] = 0;
-          didFail =
-            encodedTestString.compare(0, encodedTestString.npos, buffer2,
-                                      encodedTestString.size()) == 0
+          didFail = encodedTestString.compare(0, std::string::npos, buffer2,
+                                              encodedTestString.size()) == 0
             ? 0
             : 1;
         }
@@ -377,7 +366,6 @@ static int testPipe()
   return didFail;
 }
 
-//----------------------------------------------------------------------------
 static int testFile()
 {
   int didFail = 1;
@@ -446,9 +434,8 @@ static int testFile()
             throw std::runtime_error("ReadFile#2 failed!");
           }
           buffer2[bytesRead] = 0;
-          didFail =
-            encodedTestString.compare(0, encodedTestString.npos, buffer2,
-                                      encodedTestString.size()) == 0
+          didFail = encodedTestString.compare(0, std::string::npos, buffer2,
+                                              encodedTestString.size()) == 0
             ? 0
             : 1;
         }
@@ -487,7 +474,6 @@ static int testFile()
 #define _WIN32_WINNT_VISTA 0x0600
 #endif
 
-//----------------------------------------------------------------------------
 static int testConsole()
 {
   int didFail = 1;
@@ -748,7 +734,6 @@ static int testConsole()
 
 #endif
 
-//----------------------------------------------------------------------------
 int testConsoleBuf(int, char* [])
 {
   int ret = 0;
diff --git a/Source/kwsys/testConsoleBufChild.cxx b/Source/kwsys/testConsoleBufChild.cxx
index 83bf545..6a743ed 100644
--- a/Source/kwsys/testConsoleBufChild.cxx
+++ b/Source/kwsys/testConsoleBufChild.cxx
@@ -16,7 +16,6 @@
 
 #include "testConsoleBuf.hxx"
 
-//----------------------------------------------------------------------------
 int main(int argc, const char* argv[])
 {
 #if defined(_WIN32)
diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx
index 03f2ec9..2c5ef46 100644
--- a/Source/kwsys/testEncoding.cxx
+++ b/Source/kwsys/testEncoding.cxx
@@ -22,7 +22,6 @@
 #include "Encoding.hxx.in"
 #endif
 
-//----------------------------------------------------------------------------
 static const unsigned char helloWorldStrings[][32] = {
   // English
   { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 0 },
@@ -50,7 +49,6 @@ static const unsigned char helloWorldStrings[][32] = {
   { 0 }
 };
 
-//----------------------------------------------------------------------------
 static int testHelloWorldEncoding()
 {
   int ret = 0;
@@ -180,7 +178,88 @@ static int testCommandLineArguments()
   return status;
 }
 
-//----------------------------------------------------------------------------
+static int testToWindowsExtendedPath()
+{
+#ifdef _WIN32
+  int ret = 0;
+  if (kwsys::Encoding::ToWindowsExtendedPath(
+        "L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
+      L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
+              << std::endl;
+    ++ret;
+  }
+
+  if (kwsys::Encoding::ToWindowsExtendedPath(
+        "L:/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
+      L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"L:/Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
+    ++ret;
+  }
+
+  if (kwsys::Encoding::ToWindowsExtendedPath(
+        "\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
+      L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
+              << std::endl;
+    ++ret;
+  }
+
+  if (kwsys::Encoding::ToWindowsExtendedPath(
+        "//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
+      L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo\""
+              << std::endl;
+    ++ret;
+  }
+
+  if (kwsys::Encoding::ToWindowsExtendedPath("//") != L"//") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"//\"" << std::endl;
+    ++ret;
+  }
+
+  if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\") != L"\\\\.\\") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"\\\\.\\\"" << std::endl;
+    ++ret;
+  }
+
+  if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X") != L"\\\\.\\X") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"\\\\.\\X\"" << std::endl;
+    ++ret;
+  }
+
+  if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:") != L"\\\\?\\X:") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"\\\\.\\X:\"" << std::endl;
+    ++ret;
+  }
+
+  if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:\\") !=
+      L"\\\\?\\X:\\") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"\\\\.\\X:\\\"" << std::endl;
+    ++ret;
+  }
+
+  if (kwsys::Encoding::ToWindowsExtendedPath("NUL") != L"\\\\.\\NUL") {
+    std::cout << "Problem with ToWindowsExtendedPath "
+              << "\"NUL\"" << std::endl;
+    ++ret;
+  }
+
+  return ret;
+#else
+  return 0;
+#endif
+}
+
 int testEncoding(int, char* [])
 {
   const char* loc = setlocale(LC_ALL, "");
@@ -196,6 +275,7 @@ int testEncoding(int, char* [])
   ret |= testRobustEncoding();
   ret |= testCommandLineArguments();
   ret |= testWithNulls();
+  ret |= testToWindowsExtendedPath();
 
   return ret;
 }
diff --git a/Source/kwsys/testFStream.cxx b/Source/kwsys/testFStream.cxx
index 670f5e7..a92a781 100644
--- a/Source/kwsys/testFStream.cxx
+++ b/Source/kwsys/testFStream.cxx
@@ -20,7 +20,6 @@
 
 #include <iostream>
 
-//----------------------------------------------------------------------------
 static int testNoFile()
 {
   kwsys::ifstream in_file("NoSuchFile.txt");
@@ -69,7 +68,6 @@ static unsigned char file_data[num_test_files][max_test_file_size] = {
     0x72, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x64 },
 };
 
-//----------------------------------------------------------------------------
 static int testBOM()
 {
   // test various encodings in binary mode
@@ -104,7 +102,6 @@ static int testBOM()
   return 0;
 }
 
-//----------------------------------------------------------------------------
 int testFStream(int, char* [])
 {
   int ret = 0;
diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx
index 86a1e1e..3a9217f 100644
--- a/Source/kwsys/testSystemInformation.cxx
+++ b/Source/kwsys/testSystemInformation.cxx
@@ -52,6 +52,7 @@ int testSystemInformation(int, char* [])
   printMethod(info, GetOSRelease);
   printMethod(info, GetOSVersion);
   printMethod(info, GetOSPlatform);
+  printMethod(info, Is64Bits);
   printMethod(info, GetVendorString);
   printMethod(info, GetVendorID);
   printMethod(info, GetTypeID);
@@ -63,7 +64,6 @@ int testSystemInformation(int, char* [])
   printMethod2(info, GetProcessorCacheSize, "KB");
   printMethod(info, GetLogicalProcessorsPerPhysical);
   printMethod2(info, GetProcessorClockFrequency, "MHz");
-  printMethod(info, Is64Bits);
   printMethod(info, GetNumberOfLogicalCPU);
   printMethod(info, GetNumberOfPhysicalCPU);
   printMethod(info, DoesCPUSupportCPUID);
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 8e1ea25..e6fbf6c 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -35,7 +35,6 @@
 typedef unsigned short mode_t;
 #endif
 
-//----------------------------------------------------------------------------
 static const char* toUnixPaths[][2] = {
   { "/usr/local/bin/passwd", "/usr/local/bin/passwd" },
   { "/usr/lo cal/bin/pa sswd", "/usr/lo cal/bin/pa sswd" },
@@ -55,7 +54,8 @@ static const char* toUnixPaths[][2] = {
   { 0, 0 }
 };
 
-static bool CheckConvertToUnixSlashes(std::string input, std::string output)
+static bool CheckConvertToUnixSlashes(std::string const& input,
+                                      std::string const& output)
 {
   std::string result = input;
   kwsys::SystemTools::ConvertToUnixSlashes(result);
@@ -67,14 +67,14 @@ static bool CheckConvertToUnixSlashes(std::string input, std::string output)
   return true;
 }
 
-//----------------------------------------------------------------------------
 static const char* checkEscapeChars[][4] = { { "1 foo 2 bar 2", "12", "\\",
                                                "\\1 foo \\2 bar \\2" },
                                              { " {} ", "{}", "#", " #{#} " },
                                              { 0, 0, 0, 0 } };
 
-static bool CheckEscapeChars(std::string input, const char* chars_to_escape,
-                             char escape_char, std::string output)
+static bool CheckEscapeChars(std::string const& input,
+                             const char* chars_to_escape, char escape_char,
+                             std::string const& output)
 {
   std::string result = kwsys::SystemTools::EscapeChars(
     input.c_str(), chars_to_escape, escape_char);
@@ -86,7 +86,6 @@ static bool CheckEscapeChars(std::string input, const char* chars_to_escape,
   return true;
 }
 
-//----------------------------------------------------------------------------
 static bool CheckFileOperations()
 {
   bool res = true;
@@ -135,6 +134,19 @@ static bool CheckFileOperations()
     res = false;
   }
 
+  kwsys::SystemTools::Stat_t buf;
+  if (kwsys::SystemTools::Stat(testTxtFile.c_str(), &buf) != 0) {
+    std::cerr << "Problem with Stat - unable to stat text file: "
+              << testTxtFile << std::endl;
+    res = false;
+  }
+
+  if (kwsys::SystemTools::Stat(testBinFile, &buf) != 0) {
+    std::cerr << "Problem with Stat - unable to stat bin file: " << testBinFile
+              << std::endl;
+    res = false;
+  }
+
   if (!kwsys::SystemTools::MakeDirectory(testNewDir)) {
     std::cerr << "Problem with MakeDirectory for: " << testNewDir << std::endl;
     res = false;
@@ -456,7 +468,6 @@ static bool CheckFileOperations()
   return res;
 }
 
-//----------------------------------------------------------------------------
 static bool CheckStringOperations()
 {
   bool res = true;
@@ -572,85 +583,6 @@ static bool CheckStringOperations()
     res = false;
   }
 
-#ifdef _WIN32
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath(
-        "L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
-      L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
-              << std::endl;
-    res = false;
-  }
-
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath(
-        "L:/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
-      L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"L:/Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
-    res = false;
-  }
-
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath(
-        "\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
-      L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
-              << std::endl;
-    res = false;
-  }
-
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath(
-        "//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
-      L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo\""
-              << std::endl;
-    res = false;
-  }
-
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath("//") != L"//") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"//\"" << std::endl;
-    res = false;
-  }
-
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\") !=
-      L"\\\\.\\") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"\\\\.\\\"" << std::endl;
-    res = false;
-  }
-
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X") !=
-      L"\\\\.\\X") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"\\\\.\\X\"" << std::endl;
-    res = false;
-  }
-
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X:") !=
-      L"\\\\?\\X:") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"\\\\.\\X:\"" << std::endl;
-    res = false;
-  }
-
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X:\\") !=
-      L"\\\\?\\X:\\") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"\\\\.\\X:\\\"" << std::endl;
-    res = false;
-  }
-
-  if (kwsys::SystemTools::ConvertToWindowsExtendedPath("NUL") !=
-      L"\\\\.\\NUL") {
-    std::cerr << "Problem with ConvertToWindowsExtendedPath "
-              << "\"NUL\"" << std::endl;
-    res = false;
-  }
-
-#endif
-
   if (kwsys::SystemTools::ConvertToWindowsOutputPath(
         "L://Local Mojo/Hex Power Pack/Iffy Voodoo") !=
       "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") {
@@ -679,8 +611,6 @@ static bool CheckStringOperations()
   return res;
 }
 
-//----------------------------------------------------------------------------
-
 static bool CheckPutEnv(const std::string& env, const char* name,
                         const char* value)
 {
@@ -908,7 +838,6 @@ static bool CheckGetLineFromStream()
   return ret;
 }
 
-//----------------------------------------------------------------------------
 int testSystemTools(int, char* [])
 {
   bool res = true;
diff --git a/Templates/MSBuild/nasm.props.in b/Templates/MSBuild/nasm.props.in
new file mode 100644
index 0000000..3443108
--- /dev/null
+++ b/Templates/MSBuild/nasm.props.in
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(NASMBeforeTargets)' == '' and '$(NASMAfterTargets)' == '' and '$(ConfigurationType)' != 'Makefile'">
+    <NASMBeforeTargets>Midl</NASMBeforeTargets>
+    <NASMAfterTargets>CustomBuild</NASMAfterTargets>
+  </PropertyGroup>
+  <ItemDefinitionGroup>
+    <NASM>
+      <OutputFormat>$(IntDir)%(FileName).obj</OutputFormat>
+      <Outputswitch>0</Outputswitch>
+      <CompilerNasm>@CMAKE_ASM_NASM_COMPILER@</CompilerNasm>
+      <PackAlignmentBoundary>0</PackAlignmentBoundary>
+      <CommandLineTemplate>"%(CompilerNasm)" [AllOptions] [AdditionalOptions] "%(FullPath)"</CommandLineTemplate>
+      <ExecutionDescription>Assembling %(Filename)%(Extension)</ExecutionDescription>
+    </NASM>
+  </ItemDefinitionGroup>
+</Project>
diff --git a/Templates/MSBuild/nasm.targets b/Templates/MSBuild/nasm.targets
new file mode 100644
index 0000000..eeeb613
--- /dev/null
+++ b/Templates/MSBuild/nasm.targets
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <PropertyPageSchema Include="$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml"/>
+    <AvailableItemName Include="NASM">
+      <Targets>_NASM</Targets>
+    </AvailableItemName>
+  </ItemGroup>
+  <PropertyGroup>
+    <ComputeLinkInputsTargets>
+      $(ComputeLinkInputsTargets);
+      ComputeNASMOutput;
+    </ComputeLinkInputsTargets>
+    <ComputeLibInputsTargets>
+      $(ComputeLibInputsTargets);
+      ComputeNASMOutput;
+    </ComputeLibInputsTargets>
+  </PropertyGroup>
+  <UsingTask TaskName="NASM" TaskFactory="XamlTaskFactory" AssemblyName="Microsoft.Build.Tasks.v4.0">
+    <Task>$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml</Task>
+  </UsingTask>
+  <Target Name="_NASM" BeforeTargets="$(NASMBeforeTargets)" AfterTargets="$(NASMAfterTargets)" Condition="'@(NASM)' != ''" Outputs="%(NASM.OutputFormat)" Inputs="%(NASM.Identity);%(NASM.AdditionalDependencies);$(MSBuildProjectFile)" DependsOnTargets="_SelectedFiles">
+    <ItemGroup Condition="'@(SelectedFiles)' != ''">
+      <NASM Remove="@(NASM)" Condition="'%(Identity)' != '@(SelectedFiles)'"/>
+    </ItemGroup>
+    <ItemGroup>
+      <NASM_tlog Include="%(NASM.OutputFormat)" Condition="'%(NASM.OutputFormat)' != '' and '%(NASM.ExcludedFromBuild)' != 'true'">
+        <Source>@(NASM, '|')</Source>
+      </NASM_tlog>
+    </ItemGroup>
+    <Message Importance="High" Text="%(NASM.ExecutionDescription)"/>
+    <WriteLinesToFile Condition="'@(NASM_tlog)' != '' and '%(NASM_tlog.ExcludedFromBuild)' != 'true'" File="$(IntDir)$(ProjectName).write.1.tlog" Lines="^%(NASM_tlog.Source);@(NASM_tlog->'%(Fullpath)')"/>
+    <NASM Condition="'@(NASM)' != '' and '%(NASM.ExcludedFromBuild)' != 'true'" Inputs="%(NASM.Inputs)" OutputFormat="%(NASM.OutputFormat)" Outputswitch="%(NASM.Outputswitch)" AssembledCodeListingFile="%(NASM.AssembledCodeListingFile)" GenerateDebugInformation="%(NASM.GenerateDebugInformation)" ErrorReporting="%(NASM.ErrorReporting)" IncludePaths="%(NASM.IncludePaths)" PreprocessorDefinitions="%(NASM.PreprocessorDefinitions)" UndefinePreprocessorDefinitions="%(NASM.UndefinePreprocessorDe [...]
+  </Target>
+  <Target Name="ComputeNASMOutput" Condition="'@(NASM)' != ''">
+    <ItemGroup>
+      <Link Include="@(NASM->Metadata('OutputFormat')->Distinct()->ClearMetadata())" Condition="'%(NASM.ExcludedFromBuild)' != 'true'"/>
+      <Lib Include="@(NASM->Metadata('OutputFormat')->Distinct()->ClearMetadata())" Condition="'%(NASM.ExcludedFromBuild)' != 'true'"/>
+    </ItemGroup>
+  </Target>
+</Project>
diff --git a/Templates/MSBuild/nasm.xml b/Templates/MSBuild/nasm.xml
new file mode 100644
index 0000000..92f8548
--- /dev/null
+++ b/Templates/MSBuild/nasm.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ProjectSchemaDefinitions xmlns="http://schemas.microsoft.com/build/2009/properties" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib">
+  <Rule Name="NASM" PageTemplate="tool" DisplayName="Netwide Assembler" Order="200">
+    <Rule.DataSource>
+      <DataSource Persistence="ProjectFile" ItemType="NASM"/>
+    </Rule.DataSource>
+    <Rule.Categories>
+      <Category Name="General">
+        <Category.DisplayName>
+          <sys:String>General</sys:String>
+        </Category.DisplayName>
+      </Category>
+      <Category Name="Preprocessor">
+        <Category.DisplayName>
+          <sys:String>Preprocessing Options</sys:String>
+        </Category.DisplayName>
+      </Category>
+      <Category Name="Assembler Options">
+        <Category.DisplayName>
+          <sys:String>Assembler Options</sys:String>
+        </Category.DisplayName>
+      </Category>
+      <Category Name="Advanced">
+        <Category.DisplayName>
+          <sys:String>Advanced </sys:String>
+        </Category.DisplayName>
+      </Category>
+      <Category Name="Command Line" Subtype="CommandLine">
+        <Category.DisplayName>
+          <sys:String>Command Line</sys:String>
+        </Category.DisplayName>
+      </Category>
+    </Rule.Categories>
+    <StringProperty Name="Inputs" Category="Command Line" IsRequired="true">
+      <StringProperty.DataSource>
+        <DataSource Persistence="ProjectFile" ItemType="NASM" SourceType="Item"/>
+      </StringProperty.DataSource>
+    </StringProperty>
+    <StringProperty Name="OutputFormat" Category="Assembler Options" HelpUrl="http://www.nasm.us/doc/" DisplayName="Output File Name" Description="Specify Output Filename.-o [value]" Switch="-o [value]"/>
+    <BoolProperty Name="tasmmode" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="SciTech TASM compatible mode" Description="assemble in SciTech TASM compatible mode" Switch="-t"/>
+    <EnumProperty Name="Outputswitch" Category="Assembler Options" HelpUrl="http://www.nasm.us/doc/" DisplayName="Output Switch" Description="Select the type of output format required. Linking Should be disabled for ELF and Binary ,else error will popup">
+      <EnumValue Name="0" DisplayName="Object File win32" Switch="-fwin32"/>
+      <EnumValue Name="1" DisplayName="Object File win64" Switch="-fwin64"/>
+      <EnumValue Name="2" DisplayName="ELF32 (i386) object files (e.g. Linux)" Switch="-felf32"/>
+      <EnumValue Name="3" DisplayName="ELF64 (x86_64) object files (e.g. Linux)" Switch="-felf64"/>
+    </EnumProperty>
+    <StringListProperty Name="AssembledCodeListingFile" Category="Assembler Options" DisplayName="Assembled Code Listing File" Description="Generates an assembled code listing file.     (-l [file])" HelpUrl="http://www.nasm.us/doc/" Switch="-l "[value]""/>
+    <BoolProperty Name="GenerateDebugInformation" Category="Assembler Options" DisplayName="Generate Debug Information" Description="Generates Debug Information.     (-g)" HelpUrl="http://www.nasm.us/doc/" Switch="-g"/>
+    <StringListProperty Name="ErrorReporting" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Redirect Error Messages to File" Description="Drops the error Message on specified device" Switch="-Z "[value]""/>
+    <StringListProperty Name="IncludePaths" Category="General" DisplayName="Include Paths" Description="Sets path for include file.     (-I[path])" HelpUrl="http://www.nasm.us/doc/" Switch="-I"[value]""/>
+    <StringListProperty Name="PreprocessorDefinitions" Category="Preprocessor" HelpUrl="http://www.nasm.us/doc/" DisplayName="Preprocessor Definitions" Description="Defines a text macro with the given name.     (-D[symbol])" Switch="-D[value]"/>
+    <StringListProperty Name="UndefinePreprocessorDefinitions" Category="Preprocessor" HelpUrl="http://www.nasm.us/doc/" DisplayName="Undefine Preprocessor Definitions" Description="Undefines a text macro with the given name.     (-U[symbol])" Switch="-U[value]"/>
+    <EnumProperty Name="ErrorReportingFormat" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Error Reporting Format" Description="Select the error reporting format ie. GNU or VC">
+      <EnumValue Name="0" DisplayName="-Xgnu GNU format: Default format" Switch="-Xgnu"/>
+      <EnumValue Name="1" DisplayName="-Xvc Style used by Microsoft Visual C++" Switch="-Xvc"/>
+    </EnumProperty>
+    <BoolProperty Name="TreatWarningsAsErrors" Category="Assembler Options" DisplayName="Treat Warnings As Errors" Description="Returns an error code if warnings are generated.     (-Werror)" HelpUrl="http://www.nasm.us/doc/" Switch="-Werror"/>
+    <BoolProperty Name="floatunderflow" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="float-underflow" Description="floating point underflow (default off)" Switch="-w+float-underflow"/>
+    <BoolProperty Name="macrodefaults" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Disable macro-defaults" Description="macros with more default than optional parameters (default on)" Switch="-w-macro-defaults"/>
+    <BoolProperty Name="user" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Disable user" Description="%warning directives (default on)" Switch="-w-user"/>
+    <BoolProperty Name="floatoverflow" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Disable float-overflow" Description="floating point overflow (default on)" Switch="-w-float-overflow"/>
+    <BoolProperty Name="floatdenorm" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="float-denorm" Description="floating point denormal (default off)" Switch="-w+float-denorm"/>
+    <BoolProperty Name="numberoverflow" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Disable number-overflow" Description="numeric constant does not fit (default on)" Switch="-w-number-overflow"/>
+    <BoolProperty Name="macroselfref" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="macro-selfref" Description="cyclic macro references (default off)" Switch="-w+macro-selfref"/>
+    <BoolProperty Name="floattoolong" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Disable float-toolong" Description=" too many digits in floating-point number (default on)" Switch="-w-float-toolong"/>
+    <BoolProperty Name="orphanlabels" Category="Advanced" HelpUrl="http://www.nasm.us/doc/" DisplayName="Disable orphan-labels" Description="labels alone on lines without trailing `:' (default on)" Switch="-w-orphan-labels"/>
+    <StringProperty Name="CommandLineTemplate" DisplayName="Command Line" Visible="False" IncludeInCommandLine="False"/>
+    <DynamicEnumProperty Name="NASMBeforeTargets" Category="General" EnumProvider="Targets" IncludeInCommandLine="False">
+      <DynamicEnumProperty.DisplayName>
+        <sys:String>Execute Before</sys:String>
+      </DynamicEnumProperty.DisplayName>
+      <DynamicEnumProperty.Description>
+        <sys:String>Specifies the targets for the build customization to run before.</sys:String>
+      </DynamicEnumProperty.Description>
+      <DynamicEnumProperty.ProviderSettings>
+        <NameValuePair Name="Exclude" Value="^NASMBeforeTargets|^Compute"/>
+      </DynamicEnumProperty.ProviderSettings>
+      <DynamicEnumProperty.DataSource>
+        <DataSource Persistence="ProjectFile" ItemType="" HasConfigurationCondition="true"/>
+      </DynamicEnumProperty.DataSource>
+    </DynamicEnumProperty>
+    <DynamicEnumProperty Name="NASMAfterTargets" Category="General" EnumProvider="Targets" IncludeInCommandLine="False">
+      <DynamicEnumProperty.DisplayName>
+        <sys:String>Execute After</sys:String>
+      </DynamicEnumProperty.DisplayName>
+      <DynamicEnumProperty.Description>
+        <sys:String>Specifies the targets for the build customization to run after.</sys:String>
+      </DynamicEnumProperty.Description>
+      <DynamicEnumProperty.ProviderSettings>
+        <NameValuePair Name="Exclude" Value="^NASMAfterTargets|^Compute"/>
+      </DynamicEnumProperty.ProviderSettings>
+      <DynamicEnumProperty.DataSource>
+        <DataSource Persistence="ProjectFile" ItemType="" HasConfigurationCondition="true"/>
+      </DynamicEnumProperty.DataSource>
+    </DynamicEnumProperty>
+    <StringProperty Name="ExecutionDescription" DisplayName="Execution Description" IncludeInCommandLine="False" Visible="False"/>
+    <StringListProperty Name="AdditionalDependencies" DisplayName="Additional Dependencies" IncludeInCommandLine="False" Visible="False"/>
+    <StringProperty Subtype="AdditionalOptions" Name="AdditionalOptions" Category="Command Line">
+      <StringProperty.DisplayName>
+        <sys:String>Additional Options</sys:String>
+      </StringProperty.DisplayName>
+      <StringProperty.Description>
+        <sys:String>Additional Options</sys:String>
+      </StringProperty.Description>
+    </StringProperty>
+  </Rule>
+  <ItemType Name="NASM" DisplayName="Netwide Assembler"/>
+  <FileExtension Name="*.asm" ContentType="NASM"/>
+  <ContentType Name="NASM" DisplayName="Netwide Assembler" ItemType="NASM"/>
+</ProjectSchemaDefinitions>
diff --git a/Templates/TestDriver.cxx.in b/Templates/TestDriver.cxx.in
index ecf6fa1..bf61be4 100644
--- a/Templates/TestDriver.cxx.in
+++ b/Templates/TestDriver.cxx.in
@@ -32,15 +32,15 @@ static functionMapEntry cmakeGeneratedFunctionMapEntries[] = {
   { NULL, NULL } /* NOLINT */
 };
 
-static const int NumTests =
-  (sizeof(cmakeGeneratedFunctionMapEntries) / sizeof(functionMapEntry)) - 1;
+static const int NumTests = CM_CAST(int,
+  sizeof(cmakeGeneratedFunctionMapEntries) / sizeof(functionMapEntry)) - 1;
 
 /* Allocate and create a lowercased copy of string
    (note that it has to be free'd manually) */
 static char* lowercase(const char* string)
 {
   char *new_string, *p;
-  size_t stringSize = 0;
+  size_t stringSize;
 
   stringSize = CM_CAST(size_t, strlen(string) + 1);
   new_string = CM_CAST(char*, malloc(sizeof(char) * stringSize));
diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt
index 9b48b14..11978db 100644
--- a/Tests/BuildDepends/CMakeLists.txt
+++ b/Tests/BuildDepends/CMakeLists.txt
@@ -42,7 +42,7 @@ list(APPEND _cmake_options "-DTEST_LINK_DEPENDS=${TEST_LINK_DEPENDS}")
 
 list(APPEND _cmake_options "-DCMAKE_FORCE_DEPFILES=1")
 
-if(NOT CMAKE_GENERATOR MATCHES "Visual Studio ([^789]|[789][0-9])")
+if(NOT CMAKE_GENERATOR MATCHES "Visual Studio ([^89]|[89][0-9])")
   set(TEST_MULTI3 1)
   list(APPEND _cmake_options "-DTEST_MULTI3=1")
 endif()
diff --git a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
index 555a08f..5096a58 100644
--- a/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_features/CMakeLists.txt
@@ -1,45 +1,65 @@
 cmake_minimum_required(VERSION 3.0)
+cmake_policy(SET CMP0057 NEW)
 project(target_compile_features)
 
-if (NOT CMAKE_CXX_COMPILE_FEATURES AND NOT CMAKE_C_COMPILE_FEATURES)
-  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_dummy.cpp"
-    "int main(int,char**) { return 0; }\n"
-  )
-  add_executable(target_compile_features "${CMAKE_CURRENT_BINARY_DIR}/test_dummy.cpp")
-  return()
-endif()
-
 set(CMAKE_VERBOSE_MAKEFILE ON)
 
-if (CMAKE_C_COMPILE_FEATURES)
-  add_executable(target_compile_features main.c)
-  target_compile_features(target_compile_features
+if (c_restrict IN_LIST CMAKE_C_COMPILE_FEATURES)
+  add_executable(c_target_compile_features_specific main.c)
+  target_compile_features(c_target_compile_features_specific
     PRIVATE c_restrict
   )
 
-  add_library(lib_restrict lib_restrict.c)
-  target_compile_features(lib_restrict
+  add_library(c_lib_restrict_specific lib_restrict.c)
+  target_compile_features(c_lib_restrict_specific
     PUBLIC c_restrict
   )
 
-  add_executable(restrict_user restrict_user.c)
-  target_link_libraries(restrict_user lib_restrict)
+  add_executable(c_restrict_user_specific restrict_user.c)
+  target_link_libraries(c_restrict_user_specific c_lib_restrict_specific)
 endif()
 
-if (CMAKE_CXX_COMPILE_FEATURES AND ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_auto_type;")
-  if (CMAKE_C_COMPILE_FEATURES)
-    set(target_suffix _cxx)
-  endif()
-  add_executable(target_compile_features${target_suffix} main.cpp)
-  target_compile_features(target_compile_features${target_suffix}
+if (c_std_99 IN_LIST CMAKE_C_COMPILE_FEATURES)
+  add_executable(c_target_compile_features_meta main.c)
+  target_compile_features(c_target_compile_features_meta
+    PRIVATE c_std_99
+  )
+
+  add_library(c_lib_restrict_meta lib_restrict.c)
+  target_compile_features(c_lib_restrict_meta
+    PUBLIC c_std_99
+  )
+
+  add_executable(c_restrict_user_meta restrict_user.c)
+  target_link_libraries(c_restrict_user_meta c_lib_restrict_meta)
+endif()
+
+if (cxx_auto_type IN_LIST CMAKE_CXX_COMPILE_FEATURES)
+  add_executable(cxx_target_compile_features_specific main.cpp)
+  target_compile_features(cxx_target_compile_features_specific
     PRIVATE cxx_auto_type
   )
 
-  add_library(lib_auto_type lib_auto_type.cpp)
-  target_compile_features(lib_auto_type
+  add_library(cxx_lib_auto_type_specific lib_auto_type.cpp)
+  target_compile_features(cxx_lib_auto_type_specific
     PUBLIC cxx_auto_type
   )
 
-  add_executable(lib_user lib_user.cpp)
-  target_link_libraries(lib_user lib_auto_type)
+  add_executable(cxx_lib_user_specific lib_user.cpp)
+  target_link_libraries(cxx_lib_user_specific cxx_lib_auto_type_specific)
+endif()
+
+if (cxx_std_11 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
+  add_executable(cxx_target_compile_features_meta main.cpp)
+  target_compile_features(cxx_target_compile_features_meta
+    PRIVATE cxx_std_11
+  )
+
+  add_library(cxx_lib_auto_type_meta lib_auto_type.cpp)
+  target_compile_features(cxx_lib_auto_type_meta
+    PUBLIC cxx_std_11
+  )
+
+  add_executable(cxx_lib_user_meta lib_user.cpp)
+  target_link_libraries(cxx_lib_user_meta cxx_lib_auto_type_meta)
 endif()
diff --git a/Tests/CMakeCommands/target_compile_features/dummy.cpp b/Tests/CMakeCommands/target_compile_features/dummy.cpp
deleted file mode 100644
index e9ad257..0000000
--- a/Tests/CMakeCommands/target_compile_features/dummy.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-
-int main(int, char**)
-{
-  return 0;
-}
diff --git a/Tests/CMakeCommands/target_link_libraries/empty.cpp b/Tests/CMakeCommands/target_link_libraries/empty.cpp
index ab32cf6..a6ecef8 100644
--- a/Tests/CMakeCommands/target_link_libraries/empty.cpp
+++ b/Tests/CMakeCommands/target_link_libraries/empty.cpp
@@ -1 +1,3 @@
-// No content
+// Solaris needs non-empty content so ensure
+// we have at least one symbol
+int Solaris_requires_a_symbol_here = 0;
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt
index d680205..d1a1df5 100644
--- a/Tests/CMakeLib/CMakeLists.txt
+++ b/Tests/CMakeLib/CMakeLists.txt
@@ -34,16 +34,6 @@ target_link_libraries(CMakeLibTests CMakeLib)
 add_executable(testEncoding testEncoding.cxx)
 target_link_libraries(testEncoding cmsys)
 
-# Xcode 2.x forgets to create the output directory before linking
-# the individual architectures.
-if(CMAKE_OSX_ARCHITECTURES AND XCODE
-    AND NOT "${XCODE_VERSION}" MATCHES "^[^12]")
-  add_custom_command(
-    TARGET CMakeLibTests
-    PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}"
-    )
-endif()
-
 foreach(test ${CMakeLib_TESTS})
   add_test(CMakeLib.${test} CMakeLibTests ${test} ${${test}_ARGS})
 endforeach()
diff --git a/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt b/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt
index c53befc..7c84ee1 100644
--- a/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt
+++ b/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt
@@ -24,18 +24,3 @@ target_link_libraries(memcheck_fail CMakeLib)
 # output file. Need to be in their own subdirectory as they have the
 # same filenames.
 add_subdirectory(NoLog)
-
-# Xcode 2.x forgets to create the output directory before linking
-# the individual architectures.
-if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]")
-  foreach(t
-      memcheck_fail
-      pseudo_BC
-      pseudo_purify
-      pseudo_valgrind
-      )
-    add_custom_command(TARGET ${t}
-      PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}"
-      )
-  endforeach()
-endif()
diff --git a/Tests/CMakeLib/PseudoMemcheck/NoLog/CMakeLists.txt b/Tests/CMakeLib/PseudoMemcheck/NoLog/CMakeLists.txt
index 3a45bfe..e47b9db 100644
--- a/Tests/CMakeLib/PseudoMemcheck/NoLog/CMakeLists.txt
+++ b/Tests/CMakeLib/PseudoMemcheck/NoLog/CMakeLists.txt
@@ -11,12 +11,4 @@ configure_file(
 foreach(_pseudo IN ITEMS valgrind purify BC)
   add_executable(pseudonl_${_pseudo} "${CMAKE_CURRENT_BINARY_DIR}/ret0.c")
   set_target_properties(pseudonl_${_pseudo} PROPERTIES OUTPUT_NAME ${_pseudo})
-
-  # Xcode 2.x forgets to create the output directory before linking
-  # the individual architectures.
-  if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]")
-    add_custom_command(TARGET pseudonl_${_pseudo}
-                       PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}"
-    )
-  endif()
 endforeach()
diff --git a/Tests/CMakeLib/PseudoMemcheck/memtester.cxx.in b/Tests/CMakeLib/PseudoMemcheck/memtester.cxx.in
index e2cdec8..b4c6fae 100644
--- a/Tests/CMakeLib/PseudoMemcheck/memtester.cxx.in
+++ b/Tests/CMakeLib/PseudoMemcheck/memtester.cxx.in
@@ -1,5 +1,5 @@
 #include <cmSystemTools.h>
-#include <cmsys/Encoding.hxx>
+#include "cmsys/Encoding.hxx"
 #include <string>
 
 #define RETVAL @_retval@
diff --git a/Tests/CMakeLib/run_compile_commands.cxx b/Tests/CMakeLib/run_compile_commands.cxx
index 5d4ca70..46431bc 100644
--- a/Tests/CMakeLib/run_compile_commands.cxx
+++ b/Tests/CMakeLib/run_compile_commands.cxx
@@ -1,6 +1,6 @@
 #include <cmConfigure.h>
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <iostream>
 #include <map>
 #include <stdlib.h>
diff --git a/Tests/CMakeLib/testEncoding.cxx b/Tests/CMakeLib/testEncoding.cxx
index 88743b0..5e40638 100644
--- a/Tests/CMakeLib/testEncoding.cxx
+++ b/Tests/CMakeLib/testEncoding.cxx
@@ -1,8 +1,10 @@
-#include <fstream>
+#include "cmsys/FStream.hxx"
 #include <iostream>
 #include <string>
 
-#include <cmsys/ConsoleBuf.hxx>
+#ifdef _WIN32
+#include "cmsys/ConsoleBuf.hxx"
+#endif
 
 #ifdef _WIN32
 void setEncoding(cmsys::ConsoleBuf::Manager& buf, UINT codepage)
@@ -37,7 +39,7 @@ int main(int argc, char* argv[])
     setEncoding(consoleOut, CP_OEMCP);
   } // else AUTO
 #endif
-  std::ifstream file(argv[2]);
+  cmsys::ifstream file(argv[2]);
   if (!file.is_open()) {
     std::cout << "Failed to open file: " << argv[2] << std::endl;
     return 2;
diff --git a/Tests/CMakeLib/testRST.cxx b/Tests/CMakeLib/testRST.cxx
index e1b0903..8891276 100644
--- a/Tests/CMakeLib/testRST.cxx
+++ b/Tests/CMakeLib/testRST.cxx
@@ -3,7 +3,7 @@
 #include "cmRST.h"
 #include "cmSystemTools.h"
 
-#include <cmsys/FStream.hxx>
+#include "cmsys/FStream.hxx"
 #include <iostream>
 #include <string>
 
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 4945b31..d16df1c 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1,6 +1,9 @@
 # a macro for tests that have a simple format where the name matches the
 # directory and project
-macro(ADD_TEST_MACRO NAME COMMAND)
+macro(ADD_TEST_MACRO NAME)
+  if(${ARGC} GREATER 1)
+    set(_test_command --test-command ${ARGN})
+  endif()
   string(REPLACE "." "/" dir "${NAME}")
   string(REGEX REPLACE "[^.]*\\." "" proj "${NAME}")
   add_test(NAME "${NAME}" COMMAND "${CMAKE_CTEST_COMMAND}"
@@ -13,7 +16,8 @@ macro(ADD_TEST_MACRO NAME COMMAND)
     ${${NAME}_CTEST_OPTIONS}
     --build-options ${build_options}
     ${${NAME}_BUILD_OPTIONS}
-    --test-command ${COMMAND} ${ARGN})
+    ${_test_command})
+  unset(_test_command)
   list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/${dir}")
 endmacro()
 
@@ -46,7 +50,7 @@ if(BUILD_TESTING)
   set(CMake_TEST_DEVENV "")
   if(CMAKE_VS_DEVENV_COMMAND)
     set(CMake_TEST_DEVENV "${CMAKE_VS_DEVENV_COMMAND}")
-  elseif(CMAKE_GENERATOR MATCHES "Visual Studio [7-9] " AND
+  elseif(CMAKE_GENERATOR MATCHES "Visual Studio [89] " AND
       NOT CMAKE_MAKE_PROGRAM MATCHES "[mM][sS][bB][uU][iI][lL][dD]\\.[eE][xX][eE]")
     set(CMake_TEST_DEVENV "${CMAKE_MAKE_PROGRAM}")
   endif()
@@ -271,7 +275,7 @@ if(BUILD_TESTING)
   ADD_TEST_MACRO(SystemInformation SystemInformation)
   ADD_TEST_MACRO(MathTest MathTest)
   ADD_TEST_MACRO(CompileFeatures CompileFeatures)
-  ADD_TEST_MACRO(CMakeCommands.target_compile_features target_compile_features)
+  ADD_TEST_MACRO(CMakeCommands.target_compile_features)
 
   if(CMake_TEST_RESOURCES)
     ADD_TEST_MACRO(VSResource VSResource)
@@ -325,8 +329,9 @@ if(BUILD_TESTING)
     endif()
   endif()
 
-  if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^789]|[789][0-9])")
+  if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
     ADD_TEST_MACRO(CSharpOnly CSharpOnly)
+    ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
   endif()
 
   ADD_TEST_MACRO(COnly COnly)
@@ -477,6 +482,17 @@ if(BUILD_TESTING)
 
   ADD_TEST_MACRO(Module.CheckTypeSize CheckTypeSize)
 
+  set(Module.CheckIPOSupported-C_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_C=${CMake_TEST_IPO_WORKS_C})
+  ADD_TEST_MACRO(Module.CheckIPOSupported-C CheckIPOSupported-C)
+
+  set(Module.CheckIPOSupported-CXX_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_CXX=${CMake_TEST_IPO_WORKS_CXX})
+  ADD_TEST_MACRO(Module.CheckIPOSupported-CXX CheckIPOSupported-CXX)
+
+  if(CMAKE_Fortran_COMPILER)
+    set(Module.CheckIPOSupported-Fortran_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_Fortran=${CMake_TEST_IPO_WORKS_Fortran})
+    ADD_TEST_MACRO(Module.CheckIPOSupported-Fortran CheckIPOSupported-Fortran)
+  endif()
+
   add_test(Module.ExternalData ${CMAKE_CTEST_COMMAND}
     --build-and-test
     "${CMake_SOURCE_DIR}/Tests/Module/ExternalData"
@@ -615,8 +631,8 @@ if(BUILD_TESTING)
   endif()
 
   # test for correct sub-project generation
-  # not implemented in VS 7.0, Xcode, or Ninja
-  if(NOT CMAKE_GENERATOR MATCHES "Visual Studio 7$|Xcode|Ninja")
+  # not implemented in Xcode or Ninja
+  if(NOT CMAKE_GENERATOR MATCHES "Xcode|Ninja")
     # run cmake and configure all of SubProject
     # but only build the independent executable car
     add_test(SubProject ${CMAKE_CTEST_COMMAND}
@@ -1158,6 +1174,9 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
       )
     list(APPEND TEST_BUILD_DIRS
       "${CMake_BINARY_DIR}/Tests/CMakeTestAllGenerators")
+    # This test runs a lot of processes.  Do not make them compete
+    # for resources with other tests.
+    set_property(TEST CMakeTestAllGenerators PROPERTY RUN_SERIAL 1)
   endif()
 
   if(NOT DEFINED CTEST_RUN_CMakeTestMultipleConfigures)
@@ -1371,12 +1390,17 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     add_subdirectory(FindBZip2)
   endif()
 
+  if(CMake_TEST_FindDoxygen)
+    add_subdirectory(FindDoxygen)
+  endif()
+
   if(CMake_TEST_FindGSL)
     add_subdirectory(FindGSL)
   endif()
 
   if(CMake_TEST_FindGTest)
     add_subdirectory(FindGTest)
+    add_subdirectory(GoogleTest)
   endif()
 
   if(CMake_TEST_FindICU)
@@ -1407,14 +1431,26 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     add_subdirectory(FindOpenGL)
   endif()
 
+  if(CMake_TEST_FindOpenMP)
+    add_subdirectory(FindOpenMP)
+  endif()
+
   if(CMake_TEST_FindOpenSSL)
     add_subdirectory(FindOpenSSL)
   endif()
 
+  if(CMake_TEST_FindMPI)
+    add_subdirectory(FindMPI)
+  endif()
+
   if(CMake_TEST_FindPNG)
     add_subdirectory(FindPNG)
   endif()
 
+  if(CMake_TEST_FindProtobuf)
+    add_subdirectory(FindProtobuf)
+  endif()
+
   if(CMake_TEST_FindTIFF)
     add_subdirectory(FindTIFF)
   endif()
@@ -1697,6 +1733,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
 
   if(CMake_TEST_XCODE_VERSION AND NOT CMake_TEST_XCODE_VERSION VERSION_LESS 5
      AND OSX_VERSION MATCHES "^([0-9]+\\.[0-9]+)")
+    set(XCTest_CTEST_OPTIONS --build-config $<CONFIGURATION>)
     set(XCTest_BUILD_OPTIONS -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_MATCH_1} -DCMAKE_OSX_SYSROOT=macosx)
     ADD_TEST_MACRO(XCTest ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> -V)
   endif()
@@ -1924,7 +1961,6 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
   endif()
 
   if(MSVC AND NOT MSVC_VERSION LESS 1310
-     AND NOT CMAKE_GENERATOR MATCHES "Visual Studio 7( |$)"
      AND (NOT CMAKE_GENERATOR MATCHES "Visual Studio [89]( |$)"
           OR CMAKE_SIZEOF_VOID_P EQUAL 4)
       )
@@ -1936,7 +1972,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
       ADD_TEST_MACRO(SBCS SBCS)
     endif()
 
-    if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio [789]( |$)"
+    if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio [89]( |$)"
         AND NOT CMAKE_GENERATOR_TOOLSET)
       ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx)
     endif()
@@ -2043,7 +2079,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     set(reg_wp81 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\WindowsPhone\\v8.1;InstallationFolder]")
     select_wince_sdk(reg_wince wince_sdk)
     set(reg_tegra "[HKEY_LOCAL_MACHINE\\SOFTWARE\\NVIDIA Corporation\\Nsight Tegra;sdkRoot]")
-    foreach(reg vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra)
+    set(reg_nasm "[HKEY_CURRENT_USER\\SOFTWARE\\nasm]")
+    foreach(reg vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra nasm)
       get_filename_component(r "${reg_${reg}}" ABSOLUTE)
       if(IS_DIRECTORY "${r}")
         set(${reg} 1)
@@ -2134,6 +2171,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     endif()
   endif()
 
+  if(CMAKE_GENERATOR MATCHES "Visual Studio ([^89]|[89][0-9])" AND nasm)
+    ADD_TEST_MACRO(VSNASM VSNASM)
+  endif()
+
   if (CMake_TEST_GreenHillsMULTI)
     macro(add_test_GhsMulti name primaryTarget bspName)
       add_test(NAME GhsMulti.${name} COMMAND ${CMAKE_CTEST_COMMAND}
@@ -3074,6 +3115,9 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     endif ()
   endif ()
 
+  if(CMake_TEST_EXTERNAL_CMAKE)
+    set(CMAKE_SKIP_BOOTSTRAP_TEST 1)
+  endif()
   if("${CMAKE_GENERATOR}" MATCHES Xcode)
     set(CMAKE_SKIP_BOOTSTRAP_TEST 1)
   endif()
diff --git a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
index 8f842d6..443d366 100644
--- a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
+++ b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
@@ -1,10 +1,6 @@
-cmake_minimum_required (VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4) # new enough for CMP0017
 project(AllFindModules)
 
-if (POLICY CMP0017)
-  cmake_policy(SET CMP0017 NEW)
-endif ()
-
 # Avoid ctest truncation of output
 message(STATUS "CTEST_FULL_OUTPUT")
 
@@ -56,7 +52,10 @@ if (NOT QT4_FOUND)
 endif ()
 
 macro(check_version_string MODULE_NAME VERSION_VAR)
-    if (${MODULE_NAME}_FOUND)
+    string(FIND " ${CMake_TEST_CMakeOnly.AllFindModules_NO_VERSION} " " ${MODULE_NAME} " _exclude_pos)
+    if (NOT _exclude_pos EQUAL -1)
+        message(STATUS "excluding check of ${VERSION_VAR}='${${VERSION_VAR}}' due to local configuration")
+    elseif (${MODULE_NAME}_FOUND)
         if (DEFINED ${VERSION_VAR})
             message(STATUS "${VERSION_VAR}='${${VERSION_VAR}}'")
             if (NOT ${VERSION_VAR} MATCHES "^[0-9]")
diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt
index c692cbd..c84fa74 100644
--- a/Tests/CMakeOnly/CMakeLists.txt
+++ b/Tests/CMakeOnly/CMakeLists.txt
@@ -9,7 +9,14 @@ macro(add_CMakeOnly_test test)
 endmacro()
 
 add_CMakeOnly_test(LinkInterfaceLoop)
-set_property(TEST CMakeOnly.LinkInterfaceLoop PROPERTY TIMEOUT 90)
+# If a bug is introduced in CMake that causes an infinite loop while
+# analyzing LinkInterfaceLoop then don't let the test run too long.
+# Use an option to customize it so that the timeout can be extended
+# on busy machines.
+if(NOT DEFINED CMake_TEST_CMakeOnly.LinkInterfaceLoop_TIMEOUT)
+  set(CMake_TEST_CMakeOnly.LinkInterfaceLoop_TIMEOUT 90)
+endif()
+set_property(TEST CMakeOnly.LinkInterfaceLoop PROPERTY TIMEOUT ${CMake_TEST_CMakeOnly.LinkInterfaceLoop_TIMEOUT})
 
 add_CMakeOnly_test(CheckSymbolExists)
 
@@ -26,11 +33,15 @@ add_CMakeOnly_test(CompilerIdCXX)
 if(CMAKE_Fortran_COMPILER)
   add_CMakeOnly_test(CompilerIdFortran)
 endif()
-if(CMAKE_GENERATOR MATCHES "Visual Studio ([^789]|[789][0-9])")
+if(CMAKE_GENERATOR MATCHES "Visual Studio ([^89]|[89][0-9])")
   add_CMakeOnly_test(CompilerIdCSharp)
 endif()
 
-add_CMakeOnly_test(AllFindModules)
+add_test(CMakeOnly.AllFindModules ${CMAKE_CMAKE_COMMAND}
+  -DTEST=AllFindModules
+  -DCMAKE_ARGS=-DCMake_TEST_CMakeOnly.AllFindModules_NO_VERSION=${CMake_TEST_CMakeOnly.AllFindModules_NO_VERSION}
+  -P ${CMAKE_CURRENT_BINARY_DIR}/Test.cmake
+  )
 
 add_CMakeOnly_test(SelectLibraryConfigurations)
 
diff --git a/Tests/CMakeOnly/find_library/CMakeLists.txt b/Tests/CMakeOnly/find_library/CMakeLists.txt
index 9958650..fe3815e 100644
--- a/Tests/CMakeOnly/find_library/CMakeLists.txt
+++ b/Tests/CMakeOnly/find_library/CMakeLists.txt
@@ -24,7 +24,7 @@ endmacro()
 macro(test_find_library_subst expected)
   get_filename_component(dir ${expected} PATH)
   get_filename_component(name ${expected} NAME)
-  string(REGEX REPLACE "lib/?64" "lib" dir "${dir}")
+  string(REGEX REPLACE "lib/?[36Xx][24Y3][Z2]*" "lib" dir "${dir}")
   test_find_library(", searched as ${dir}" "${expected}"
     NAMES ${name}
     PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}
@@ -33,9 +33,11 @@ endmacro()
 
 set(CMAKE_FIND_LIBRARY_PREFIXES "lib")
 set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
+set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS TRUE)
 set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS TRUE)
 set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)
 
+set(CMAKE_INTERNAL_PLATFORM_ABI "ELF")
 set(CMAKE_SIZEOF_VOID_P 4)
 foreach(lib
     lib/32/libtest5.a
@@ -67,6 +69,20 @@ foreach(lib64
   test_find_library_subst(${lib64})
 endforeach()
 
+set(CMAKE_INTERNAL_PLATFORM_ABI "ELF X32")
+set(CMAKE_SIZEOF_VOID_P 4)
+foreach(libx32
+    lib/x32/libtest2.a
+    lib/A/libx32/libtest3.a
+    lib/libtest3.a
+    libx32/A/lib/libtest2.a
+    libx32/A/libx32/libtest1.a
+    libx32/A/libtest1.a
+    libx32/libtest1.a
+    )
+  test_find_library_subst(${libx32})
+endforeach()
+
 test_find_library("" A/libtestA.a
   NAMES testA testB
   PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B
@@ -79,3 +95,16 @@ test_find_library("" A/libtestA.a
   NAMES testB testA NAMES_PER_DIR
   PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B
   )
+
+set(CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX "XYZ")
+foreach(libXYZ
+    lib/XYZ/libtest1.a
+    lib/A/libXYZ/libtest2.a
+    lib/libtest3.a
+    libXYZ/A/lib/libtest4.a
+    libXYZ/A/libXYZ/libtest5.a
+    libXYZ/A/libtest6.a
+    libXYZ/libtest7.a
+    )
+  test_find_library_subst(${libXYZ})
+endforeach()
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/lib/A/libXYZ/libtest2.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/lib/A/libXYZ/libtest2.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON.cmake b/Tests/CMakeOnly/find_library/lib/A/libx32/libtest3.a
similarity index 100%
rename from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON.cmake
rename to Tests/CMakeOnly/find_library/lib/A/libx32/libtest3.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/lib/XYZ/libtest1.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/lib/XYZ/libtest1.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/lib/x32/libtest2.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/lib/x32/libtest2.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/libXYZ/A/lib/libtest4.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/libXYZ/A/lib/libtest4.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/libXYZ/A/libXYZ/libtest5.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/libXYZ/A/libXYZ/libtest5.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/libXYZ/A/libtest6.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/libXYZ/A/libtest6.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/libXYZ/libtest7.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/libXYZ/libtest7.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/libx32/A/lib/libtest2.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/libx32/A/lib/libtest2.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/libx32/A/libtest1.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/libx32/A/libtest1.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/libx32/A/libx32/libtest1.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/libx32/A/libx32/libtest1.a
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/CMakeOnly/find_library/libx32/libtest1.a
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/CMakeOnly/find_library/libx32/libtest1.a
diff --git a/Tests/CMakeTestAllGenerators/RunCMake.cmake b/Tests/CMakeTestAllGenerators/RunCMake.cmake
index 6d27d3b..bfbb3a5 100644
--- a/Tests/CMakeTestAllGenerators/RunCMake.cmake
+++ b/Tests/CMakeTestAllGenerators/RunCMake.cmake
@@ -9,42 +9,23 @@ endif()
 # Analyze 'cmake --help' output for list of available generators:
 #
 execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${dir})
-execute_process(COMMAND ${CMAKE_COMMAND} --help
+execute_process(COMMAND ${CMAKE_COMMAND} -E capabilities
   RESULT_VARIABLE result
   OUTPUT_VARIABLE stdout
   ERROR_VARIABLE stderr
   WORKING_DIRECTORY ${dir})
 
-string(REPLACE ";" "\\;" stdout "${stdout}")
-string(REPLACE "\n" "E;" stdout "${stdout}")
-
-set(collecting 0)
 set(generators)
-foreach(eline ${stdout})
-  string(REGEX REPLACE "^(.*)E$" "\\1" line "${eline}")
-  if(collecting AND NOT line STREQUAL "")
-    if(line MATCHES "=")
-      string(REGEX REPLACE "^  (.+)= (.*)$" "\\1" gen "${line}")
-      if(gen MATCHES "[A-Za-z]")
-        string(REGEX REPLACE "^(.*[^ ]) +$" "\\1" gen "${gen}")
-        if(gen)
-          set(generators ${generators} ${gen})
-        endif()
-      endif()
-    else()
-      if(line MATCHES "^  [A-Za-z0-9]")
-        string(REGEX REPLACE "^  (.+)$" "\\1" gen "${line}")
-        string(REGEX REPLACE "^(.*[^ ]) +$" "\\1" gen "${gen}")
-        if(gen)
-          set(generators ${generators} ${gen})
-        endif()
-      endif()
+string(REGEX MATCHALL [["name":"[^"]+","platformSupport"]] generators_json "${stdout}")
+foreach(gen_json IN LISTS generators_json)
+  if("${gen_json}" MATCHES [["name":"([^"]+)"]])
+    set(gen "${CMAKE_MATCH_1}")
+    if(NOT gen MATCHES " (Win64|IA64|ARM)$")
+      list(APPEND generators "${gen}")
     endif()
   endif()
-  if(line STREQUAL "The following generators are available on this platform:")
-    set(collecting 1)
-  endif()
 endforeach()
+list(REMOVE_DUPLICATES generators)
 
 # Also call with one non-existent generator:
 #
@@ -60,28 +41,6 @@ message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
 
 message(STATUS "CMake generators='${generators}'")
 
-# If we'll be testing any of the MinGW Makefiles generators, adjust the
-# ENV{PATH} to make sure libgmp-10.dll can be loaded as needed. But only if
-# the testing machine has a default MinGW install... (If you have a
-# non-default install, append to the PATH before running the test...)
-#
-if(generators MATCHES "MinGW Makefiles")
-  if(EXISTS "C:/MinGW/bin/libgmp-10.dll")
-    string(TOLOWER "$ENV{PATH}" path)
-    if(NOT path MATCHES "/mingw/bin")
-      if(UNIX)
-        set(sep ":")
-        set(mingw_bin "/mingw/bin")
-      else()
-        set(sep ";")
-        set(mingw_bin "C:/MinGW/bin")
-      endif()
-      set(ENV{PATH} "$ENV{PATH}${sep}${mingw_bin}")
-      message(STATUS "info: appending '${sep}${mingw_bin}' to the PATH")
-    endif()
-  endif()
-endif()
-
 # First setup a source tree to run CMake on.
 #
 execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory
diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt
index d5524c3..1619081 100644
--- a/Tests/CMakeTests/CMakeLists.txt
+++ b/Tests/CMakeTests/CMakeLists.txt
@@ -19,7 +19,6 @@ AddCMakeTest(GetFilenameComponentRealpath "")
 AddCMakeTest(Version "")
 AddCMakeTest(Message "")
 AddCMakeTest(File "")
-AddCMakeTest(SeparateArguments "")
 AddCMakeTest(ImplicitLinkInfo "")
 AddCMakeTest(ModuleNotices "")
 AddCMakeTest(GetProperty "")
@@ -53,10 +52,7 @@ set(EndStuff_PreArgs
   )
 AddCMakeTest(EndStuff "${EndStuff_PreArgs}")
 
-set(GetPrerequisites_PreArgs
-  "-DCTEST_CONFIGURATION_TYPE:STRING=\\\${CTEST_CONFIGURATION_TYPE}"
-  )
-AddCMakeTest(GetPrerequisites "${GetPrerequisites_PreArgs}")
+AddCMakeTest(GetPrerequisites "-DConfiguration:STRING=$<CONFIGURATION>")
 
 if(GIT_EXECUTABLE)
   set(PolicyCheck_PreArgs
diff --git a/Tests/CMakeTests/CompilerIdVendorTest.cmake.in b/Tests/CMakeTests/CompilerIdVendorTest.cmake.in
index 68f6462..9cf5321 100644
--- a/Tests/CMakeTests/CompilerIdVendorTest.cmake.in
+++ b/Tests/CMakeTests/CompilerIdVendorTest.cmake.in
@@ -8,7 +8,6 @@ file(MAKE_DIRECTORY ${MY_BINARY_DIR})
 
 set(CMAKE_MyLang_COMPILER ${CMAKE_COMMAND})
 set(CMAKE_MyLang_COMPILER_ID_ARG1)
-set(CMAKE_MyLang_COMPILER_ID_FLAGS_LIST)
 set(CMAKE_MyLang_COMPILER_ID_DIR ${MY_BINARY_DIR})
 
 file(WRITE "${MY_BINARY_DIR}/BogusVendor.cmake" "message(\"This is a BogusVendor compiler\")")
@@ -22,7 +21,8 @@ set(CMAKE_MyLang_COMPILER_ID_VENDOR_FLAGS_MyVendor -P MyVendor.cmake)
 set(CMAKE_MyLang_COMPILER_ID_VENDOR_REGEX_MyVendor MyVendor)
 
 set(CMAKE_BINARY_DIR ${MY_BINARY_DIR})
-cmake_determine_compiler_id_vendor(MyLang)
+set(userflags)
+cmake_determine_compiler_id_vendor(MyLang "${userflags}")
 
 if("${CMAKE_MyLang_COMPILER_ID}" STREQUAL "MyVendor")
   message(STATUS "Found MyVendor compiler id!")
diff --git a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in
index 4a47c06..64b45ed 100644
--- a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in
+++ b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in
@@ -1,4 +1,7 @@
-set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
+if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/")
+  set(slash /)
+endif()
+set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
 set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads")
 
 file(DOWNLOAD
diff --git a/Tests/CMakeTests/FileDownloadTest.cmake.in b/Tests/CMakeTests/FileDownloadTest.cmake.in
index 83ade2b..f6d9ad9 100644
--- a/Tests/CMakeTests/FileDownloadTest.cmake.in
+++ b/Tests/CMakeTests/FileDownloadTest.cmake.in
@@ -1,4 +1,7 @@
-set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
+if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/")
+  set(slash /)
+endif()
+set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
 set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads")
 
 message(STATUS "FileDownload:1")
diff --git a/Tests/CMakeTests/FileUploadTest.cmake.in b/Tests/CMakeTests/FileUploadTest.cmake.in
index 8577aef..9e22909 100644
--- a/Tests/CMakeTests/FileUploadTest.cmake.in
+++ b/Tests/CMakeTests/FileUploadTest.cmake.in
@@ -10,7 +10,10 @@ endif()
 file(MAKE_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/uploads")
 
 set(filename "@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
-set(urlbase "file://@CMAKE_CURRENT_BINARY_DIR@/uploads")
+if(NOT "@CMAKE_CURRENT_BINARY_DIR@" MATCHES "^/")
+  set(slash /)
+endif()
+set(urlbase "file://${slash}@CMAKE_CURRENT_BINARY_DIR@/uploads")
 
 message(STATUS "FileUpload:1")
 file(UPLOAD
diff --git a/Tests/CMakeTests/GetPrerequisitesTest.cmake.in b/Tests/CMakeTests/GetPrerequisitesTest.cmake.in
index 89ca735..7325b87 100644
--- a/Tests/CMakeTests/GetPrerequisitesTest.cmake.in
+++ b/Tests/CMakeTests/GetPrerequisitesTest.cmake.in
@@ -2,18 +2,15 @@
 #
 include(GetPrerequisites)
 
-set(CMAKE_BUILD_TYPE "@CMAKE_BUILD_TYPE@")
-set(CMAKE_CONFIGURATION_TYPES "@CMAKE_CONFIGURATION_TYPES@")
 set(CMAKE_EXECUTABLE_SUFFIX "@CMAKE_EXECUTABLE_SUFFIX@")
 
 
 message(STATUS "=============================================================================")
 message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
 message(STATUS "")
-message(STATUS "CMAKE_BUILD_TYPE='${CMAKE_BUILD_TYPE}'")
-message(STATUS "CMAKE_CONFIGURATION_TYPES='${CMAKE_CONFIGURATION_TYPES}'")
+message(STATUS "Configuration '${Configuration}'")
+message(STATUS "CMAKE_COMMAND='${CMAKE_COMMAND}'")
 message(STATUS "CMAKE_EXECUTABLE_SUFFIX='${CMAKE_EXECUTABLE_SUFFIX}'")
-message(STATUS "CTEST_CONFIGURATION_TYPE='${CTEST_CONFIGURATION_TYPE}'")
 message(STATUS "")
 
 
diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
index 58e2bf9..d7d881e 100644
--- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
+++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
@@ -7,19 +7,19 @@ include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
 
 # gcc dummy.c -v
 set(linux64_gcc_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr [...]
-set(linux64_gcc_libs "c")
+set(linux64_gcc_libs "gcc;gcc_s;c;gcc;gcc_s")
 set(linux64_gcc_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu")
 list(APPEND platforms linux64_gcc)
 
 # g++ dummy.cxx -v
 set(linux64_g++_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr [...]
-set(linux64_g++_libs "stdc++;m;c")
+set(linux64_g++_libs "stdc++;m;gcc_s;gcc;c;gcc_s;gcc")
 set(linux64_g++_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu")
 list(APPEND platforms linux64_g++)
 
 # f95 dummy.f -v
 set(linux64_f95_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr [...]
-set(linux64_f95_libs "gfortranbegin;gfortran;m;c")
+set(linux64_f95_libs "gfortranbegin;gfortran;m;gcc_s;gcc;c;gcc_s;gcc")
 set(linux64_f95_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu")
 list(APPEND platforms linux64_f95)
 
@@ -43,43 +43,43 @@ list(APPEND platforms linux64_sunf90)
 
 # icc dummy.c -v
 set(linux64_icc_text "ld    /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /tmp/iccBP8OfN.o -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/ [...]
-set(linux64_icc_libs "imf;svml;m;ipgo;decimal;irc;irc;c;irc_s;dl;c")
+set(linux64_icc_libs "imf;svml;m;ipgo;decimal;irc;gcc_s;gcc;irc;c;gcc_s;gcc;irc_s;dl;c")
 set(linux64_icc_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib")
 list(APPEND platforms linux64_icc)
 
 # icxx dummy.cxx -v
 set(linux64_icxx_text "ld    /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /tmp/icpc270GoT.o -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gc [...]
-set(linux64_icxx_libs "imf;svml;m;ipgo;decimal;stdc++;irc;irc;c;irc_s;dl;c")
+set(linux64_icxx_libs "imf;svml;m;ipgo;decimal;stdc++;irc;gcc_s;gcc;irc;c;gcc_s;gcc;irc_s;dl;c")
 set(linux64_icxx_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib")
 list(APPEND platforms linux64_icxx)
 
 # ifort dummy.f -v
 set(linux64_ifort_text "ld    --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../ [...]
-set(linux64_ifort_libs "ifport;ifcore;imf;svml;m;ipgo;irc;pthread;c;irc_s;dl;c")
+set(linux64_ifort_libs "ifport;ifcore;imf;svml;m;ipgo;irc;pthread;c;gcc_s;gcc;irc_s;dl;c")
 set(linux64_ifort_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib")
 list(APPEND platforms linux64_ifort)
 
 # pgcc dummy.c -v
 set(linux64_pgcc_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgcc7OscXa5ur7Zk.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lnspgc -lpgc -lm -lgcc -lc -lgcc /usr/lib64/gcc/x [...]
-set(linux64_pgcc_libs "nspgc;pgc;m;c")
+set(linux64_pgcc_libs "nspgc;pgc;m;gcc;c;gcc")
 set(linux64_pgcc_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2")
 list(APPEND platforms linux64_pgcc)
 
 # pgCC dummy.cxx -v
 set(linux64_pgCC_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgCCFhjcDt1fs1Ki.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lstd -lC -lnspgc -lpgc -lm -lgcc -lc -lgcc /usr/l [...]
-set(linux64_pgCC_libs "std;C;nspgc;pgc;m;c")
+set(linux64_pgCC_libs "std;C;nspgc;pgc;m;gcc;c;gcc")
 set(linux64_pgCC_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2")
 list(APPEND platforms linux64_pgCC)
 
 # pgf90 dummy.f -v
 set(linux64_pgf90_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o /opt/compiler/pgi/linux86-64/8.0-3/lib/f90main.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgf90QOIc_eB9xY5h.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib [...]
-set(linux64_pgf90_libs "pgf90;pgf90_rpm1;pgf902;pgf90rtl;pgftnrtl;nspgc;pgc;rt;pthread;m;c")
+set(linux64_pgf90_libs "pgf90;pgf90_rpm1;pgf902;pgf90rtl;pgftnrtl;nspgc;pgc;rt;pthread;m;gcc;c;gcc")
 set(linux64_pgf90_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2")
 list(APPEND platforms linux64_pgf90)
 
 # nagfor dummy.f -Wl,-v
 set(linux64_nagfor_text " /usr/libexec/gcc/x86_64-redhat-linux/4.4.5/collect2 --no-add-needed --eh-frame-hdr --build-id -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5 -L/usr/lib/gcc/x86_64-redhat [...]
-set(linux64_nagfor_libs "/usr/local/NAG/lib/f90_init.o;/usr/local/NAG/lib/quickfit.o;/usr/local/NAG/lib/libf53.a;m;c")
+set(linux64_nagfor_libs "/usr/local/NAG/lib/f90_init.o;/usr/local/NAG/lib/quickfit.o;/usr/local/NAG/lib/libf53.a;m;gcc;gcc_s;c;gcc;gcc_s")
 set(linux64_nagfor_dirs "/usr/lib/gcc/x86_64-redhat-linux/4.4.5;/usr/lib64;/lib64;/usr/lib")
 set(linux64_nagfor_obj_regex "^/usr/local/NAG/lib")
 list(APPEND platforms linux64_nagfor)
@@ -87,7 +87,7 @@ list(APPEND platforms linux64_nagfor)
 # absoft dummy.f -X -v
 set(linux64_absoft_text "collect2 version 4.4.5 (x86-64 Linux/ELF)
 /usr/bin/ld --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.4.5/crtbegin.o -L/opt/absoft11.1/lib64 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.5 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.5 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux [...]
-set(linux64_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;pthread;c")
+set(linux64_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;pthread;gcc;gcc_s;c;gcc;gcc_s")
 set(linux64_absoft_dirs "/opt/absoft11.1/lib64;/usr/lib/gcc/x86_64-linux-gnu/4.4.5;/usr/lib;/lib")
 list(APPEND platforms linux64_absoft)
 
@@ -108,13 +108,13 @@ list(APPEND platforms linux64_test2)
 # -specs=redhat-hardened-ld
 set(linux64_test3_text "COLLECT_GCC_OPTIONS='-specs=/usr/lib/rpm/redhat/redhat-hardened-ld' '-v' '-O2' '-g' '-pipe' '-Wall' '-Werror=format-security' '-fexceptions' '-fstack-protector-strong' '--param' 'ssp-buffer-size=4' '-grecord-gcc-switches' '-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1' '-m64' '-mtune=generic' '-I' '/usr/lib64/gfortran/modules' '-o' 'a.out' '-rdynamic' '-shared-libgcc' '-march=x86-64' '-pie'
  /usr/libexec/gcc/x86_64-redhat-linux/5.1.1/collect2 -plugin /usr/libexec/gcc/x86_64-redhat-linux/5.1.1/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/5.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/ccNzxFD8.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lquadmath -plugin-opt=-pass-through=-lm -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_ [...]
-set(linux64_test3_libs "gfortran;m;quadmath;m;c")
+set(linux64_test3_libs "gfortran;m;gcc_s;gcc;quadmath;m;gcc_s;gcc;c;gcc_s;gcc")
 set(linux64_test3_dirs "/usr/lib/gcc/x86_64-redhat-linux/5.1.1;/usr/lib64;/lib64;/usr/lib")
 list(APPEND platforms linux64_test3)
 
 # clang -fsanitize=memory
 set(linux64_clang_sanitize_memory_text [[ "/usr/bin/ld" --hash-style=both --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu -L/ [...]
-set(linux64_clang_sanitize_memory_libs "pthread;rt;m;dl;c")
+set(linux64_clang_sanitize_memory_libs "pthread;rt;m;dl;gcc;gcc_s;c;gcc;gcc_s")
 set(linux64_clang_sanitize_memory_dirs "/usr/lib/gcc/x86_64-linux-gnu/5.4.0;/usr/lib/x86_64-linux-gnu;/lib/x86_64-linux-gnu;/lib64;/usr/lib;/usr/lib/llvm-3.8/lib;/lib")
 list(APPEND platforms linux64_clang_sanitize_memory)
 
@@ -137,14 +137,14 @@ Library search paths:
 Framework search paths:
 	/Library/Frameworks/
 	/System/Library/Frameworks/")
-set(mac_i686_gcc_Wlv_libs "")
+set(mac_i686_gcc_Wlv_libs "gcc")
 set(mac_i686_gcc_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib")
 set(mac_i686_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
 list(APPEND platforms mac_i686_gcc_Wlv)
 
 # gcc -arch i686 dummy.c -v
 set(mac_i686_gcc_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccnhXAGL.o -lSystem -lgcc -lSystem")
-set(mac_i686_gcc_libs "")
+set(mac_i686_gcc_libs "gcc")
 set(mac_i686_gcc_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib")
 list(APPEND platforms mac_i686_gcc)
 
@@ -164,14 +164,14 @@ Library search paths:
 Framework search paths:
 	/Library/Frameworks/
 	/System/Library/Frameworks/")
-set(mac_i686_g++_Wlv_libs "stdc++")
+set(mac_i686_g++_Wlv_libs "stdc++;gcc")
 set(mac_i686_g++_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib")
 set(mac_i686_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
 list(APPEND platforms mac_i686_g++_Wlv)
 
 # g++ -arch i686 dummy.cxx -v
 set(mac_i686_g++_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem")
-set(mac_i686_g++_libs "stdc++")
+set(mac_i686_g++_libs "stdc++;gcc")
 set(mac_i686_g++_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib")
 list(APPEND platforms mac_i686_g++)
 
@@ -188,14 +188,14 @@ Library search paths:
 Framework search paths:
 	/Library/Frameworks/
 	/System/Library/Frameworks/")
-set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran")
+set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran;gcc_s.10.5;gcc")
 set(mac_i686_gfortran_Wlv_dirs "/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/local/lib;/usr/lib")
 set(mac_i686_gfortran_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
 list(APPEND platforms mac_i686_gfortran_Wlv)
 
 # gfortran dummy.f -v
 set(mac_i686_gfortran_text " /usr/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/lib/gcc -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//ccgqbX5P.o -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem")
-set(mac_i686_gfortran_libs "gfortranbegin;gfortran")
+set(mac_i686_gfortran_libs "gfortranbegin;gfortran;gcc_s.10.5;gcc")
 set(mac_i686_gfortran_dirs "/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/lib/gcc;/usr/lib")
 list(APPEND platforms mac_i686_gfortran)
 
@@ -215,14 +215,14 @@ Library search paths:
 Framework search paths:
 	/Library/Frameworks/
 	/System/Library/Frameworks/")
-set(mac_ppc_gcc_Wlv_libs "")
+set(mac_ppc_gcc_Wlv_libs "gcc")
 set(mac_ppc_gcc_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib")
 set(mac_ppc_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
 list(APPEND platforms mac_ppc_gcc_Wlv)
 
 # gcc -arch ppc dummy.c -v
 set(mac_ppc_gcc_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccdcolsP.o -lgcc -lSystemStubs -lSystem")
-set(mac_ppc_gcc_libs "")
+set(mac_ppc_gcc_libs "gcc")
 set(mac_ppc_gcc_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib")
 list(APPEND platforms mac_ppc_gcc)
 
@@ -242,14 +242,14 @@ Library search paths:
 Framework search paths:
 	/Library/Frameworks/
 	/System/Library/Frameworks/")
-set(mac_ppc_g++_Wlv_libs "stdc++")
+set(mac_ppc_g++_Wlv_libs "stdc++;gcc")
 set(mac_ppc_g++_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib")
 set(mac_ppc_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks")
 list(APPEND platforms mac_ppc_g++_Wlv)
 
 # g++ -arch ppc dummy.cxx -v
 set(mac_ppc_g++_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccbjB6Lj.o -lstdc++ -lgcc -lSystemSt [...]
-set(mac_ppc_g++_libs "stdc++")
+set(mac_ppc_g++_libs "stdc++;gcc")
 set(mac_ppc_g++_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib")
 list(APPEND platforms mac_ppc_g++)
 
@@ -257,7 +257,7 @@ list(APPEND platforms mac_ppc_g++)
 set(mac_absoft_text "collect2 version 4.2.1 (Apple Inc. build 5664) (i686 Darwin)
 /usr/libexec/gcc/i686-apple-darwin10/4.2.1/ld -dynamic -arch i386 -macosx_version_min 10.6.6 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/Applications/Absoft11.1/lib -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/folders/04/04+Djjm8GZWBmuEdp2Gsw++++TM/-Tmp-//bTAoJc/dummy. [...]
 ")
-set(mac_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv")
+set(mac_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;gcc")
 set(mac_absoft_dirs "/Applications/Absoft11.1/lib;/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib")
 list(APPEND platforms mac_absoft)
 
@@ -485,13 +485,13 @@ list(APPEND platforms irix64_f90_64)
 
 # gcc dummy.c -v
 set(cygwin_gcc_text " /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic --dll-search-prefix=cyg /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. /home/user/AppData/Local/Temp/cczg1Arh.o -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc")
-set(cygwin_gcc_libs "cygwin;user32;kernel32;advapi32;shell32")
+set(cygwin_gcc_libs "gcc;cygwin;user32;kernel32;advapi32;shell32;gcc")
 set(cygwin_gcc_dirs "/usr/lib/gcc/i686-pc-cygwin/3.4.4;/usr/lib")
 list(APPEND platforms cygwin_gcc)
 
 # g++ dummy.cxx -v
 set(cygwin_g++_text " /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic --dll-search-prefix=cyg /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. /home/user/AppData/Local/Temp/ccsvcDO6.o -lstdc++ -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc")
-set(cygwin_g++_libs "stdc++;cygwin;user32;kernel32;advapi32;shell32")
+set(cygwin_g++_libs "stdc++;gcc;cygwin;user32;kernel32;advapi32;shell32;gcc")
 set(cygwin_g++_dirs "/usr/lib/gcc/i686-pc-cygwin/3.4.4;/usr/lib")
 list(APPEND platforms cygwin_g++)
 
@@ -499,7 +499,7 @@ list(APPEND platforms cygwin_g++)
 set(cygwin_gfortran_text "Configured with: ... LD=/opt/gcc-tools/bin/ld.exe
  /usr/lib/gcc/i686-pc-cygwin/4.3.2/collect2.exe -Bdynamic --dll-search-prefix=cyg -u ___register_frame_info -u ___deregister_frame_info /usr/lib/gcc/i686-pc-cygwin/4.3.2/../../../crt0.o /usr/lib/gcc/i686-pc-cygwin/4.3.2/crtbegin.o -L/usr/lib/gcc/i686-pc-cygwin/4.3.2 -L/usr/lib/gcc/i686-pc-cygwin/4.3.2 -L/usr/lib/gcc/i686-pc-cygwin/4.3.2/../../.. /home/user/AppData/Local/Temp/ccqRWKWg.o -lgfortranbegin -lgfortran -lgcc_s -lgcc_s -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgc [...]
 ")
-set(cygwin_gfortran_libs "gfortranbegin;gfortran;cygwin;user32;kernel32;advapi32;shell32")
+set(cygwin_gfortran_libs "gfortranbegin;gfortran;gcc_s;gcc_s;gcc;cygwin;user32;kernel32;advapi32;shell32;gcc_s;gcc_s;gcc")
 set(cygwin_gfortran_dirs "/usr/lib/gcc/i686-pc-cygwin/4.3.2;/usr/lib")
 list(APPEND platforms cygwin_gfortran)
 
@@ -508,19 +508,19 @@ list(APPEND platforms cygwin_gfortran)
 
 # gcc dummy.c -v
 set(msys_gcc_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/cckQmvRt.o -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt C [...]
-set(msys_gcc_libs "mingw32;moldname;mingwex;msvcrt;user32;kernel32;advapi32;shell32;mingw32;moldname;mingwex;msvcrt")
+set(msys_gcc_libs "mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex")
 set(msys_gcc_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib")
 list(APPEND platforms msys_gcc)
 
 # g++ dummy.cxx -v
 set(msys_g++_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/cci5hYPk.o -lstdc++ -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex - [...]
-set(msys_g++_libs "stdc++;mingw32;moldname;mingwex;msvcrt;user32;kernel32;advapi32;shell32;mingw32;moldname;mingwex;msvcrt")
+set(msys_g++_libs "stdc++;mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex")
 set(msys_g++_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib")
 list(APPEND platforms msys_g++)
 
 # g77 dummy.f -v
 set(msys_g77_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/ccabRxQ1.o -lfrtbegin -lg2c -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lm [...]
-set(msys_g77_libs "frtbegin;g2c;mingw32;moldname;mingwex;msvcrt;user32;kernel32;advapi32;shell32;mingw32;moldname;mingwex;msvcrt")
+set(msys_g77_libs "frtbegin;g2c;mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex")
 set(msys_g77_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib")
 list(APPEND platforms msys_g77)
 
@@ -532,11 +532,56 @@ set(nvcc_msvc_libs "cudadevrt.lib;cudart_static.lib")
 set(nvcc_msvc_dirs "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/lib/x64")
 list(APPEND platforms nvcc_msvc)
 
+
+#-----------------------------------------------------------------------------
+# PGI on Windows
+
+# Due to the different behavior of separate_arguments on non-Windows platforms,
+# the following tests can only be performed on Windows
+if(CMAKE_HOST_WIN32)
+
+# pgf95 dummy.f90 -v
+set(windows_pgf95_text [[Writing to file C:\temp\pgf9510ipeUbTwN2V4pn.lnk
+X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib\pgimainmx.obj C:\Program Files\PGICE/win64/17.4/lib\f90main.obj -incremental:no -debug -merge:__nv_module_id=.data -merge:.nvFatBinSegment=.data "-libpath:X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64" -libpath:X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib C:\temp\pgf959hxeUbfMYOLj [...]
+
+"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64\link.exe" /NOLOGO @C:\temp\pgf9510ipeUbTwN2V4pn.lnk]])
+set(windows_pgf95_startfile "pgimain[mx][xpt]+[.]obj")
+set(windows_pgf95_libs "libpgmp;pg;libpgf90rtl;libpgf90;libpgf90_rpm1;libpgf902;libpgf90rtl;libpgftnrtl;libpgc14;libnspgc;legacy_stdio_definitions;oldnames")
+set(windows_pgf95_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib")
+list(APPEND platforms windows_pgf95)
+
+# pgf77 dummy.f77 -v
+set(windows_pgf77_text [[Writing to file C:\temp\pgf776eC42buYRoCNJk.lnk
+X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib\pgimainmx.obj C:\Program Files\PGICE/win64/17.4/lib\pgfmain.obj -incremental:no -debug -merge:__nv_module_id=.data -merge:.nvFatBinSegment=.data "-libpath:X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64" -libpath:X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib C:\temp\pgf775d842b0tH8Ak [...]
+
+"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64\link.exe" /NOLOGO @C:\temp\pgf776eC42buYRoCNJk.lnk]])
+set(windows_pgf77_startfile "pgimain[mx][xpt]+[.]obj")
+set(windows_pgf77_libs "libpgmp;libpgftnrtl;libpgc14;libnspgc;legacy_stdio_definitions;oldnames")
+set(windows_pgf77_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib")
+list(APPEND platforms windows_pgf77)
+
+# pgcc dummy.c -v
+set(windows_pgcc_text [[Writing to file C:\temp\pgcc6esqW26_ZNKyL.lnk
+X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib\pgimainmx.obj -incremental:no -debug -merge:__nv_module_id=.data -merge:.nvFatBinSegment=.data "-libpath:X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64" "-libpath:X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64" -libpath:X:\NOT-PROGRAM-FILES\PGICE/win64/17.4/lib C:\temp\pgcc5dcqWgQXeXPWd.obj -out:dummy.exe -pdb:./dummy.pdb /DYNAMICBASE: [...]
+
+"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64\link.exe" /NOLOGO @C:\temp\pgcc6esqW26_ZNKyL.lnk]])
+set(windows_pgcc_startfile "pgimain[mx][xpt]+[.]obj")
+set(windows_pgcc_libs "libpgmp;libpgc14;libnspgc;legacy_stdio_definitions;oldnames")
+set(windows_pgcc_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib")
+list(APPEND platforms windows_pgcc)
+
+endif()
+
 #-----------------------------------------------------------------------------
 # Test parsing for all above examples.
 set(CMAKE_LINKER "not-a-linker[]().*+^$?")
 
 foreach(p IN LISTS platforms)
+  if(DEFINED ${p}_startfile)
+    set(CMAKE_LINK_STARTFILE "${${p}_startfile}")
+  else()
+    unset(CMAKE_LINK_STARTFILE)
+  endif()
   cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}")
 
   foreach(v libs dirs fwks)
diff --git a/Tests/CMakeTests/SeparateArgumentsTest.cmake.in b/Tests/CMakeTests/SeparateArgumentsTest.cmake.in
deleted file mode 100644
index 48964b8..0000000
--- a/Tests/CMakeTests/SeparateArgumentsTest.cmake.in
+++ /dev/null
@@ -1,25 +0,0 @@
-set(old_out "a b  c")
-separate_arguments(old_out)
-set(old_exp "a;b;;c")
-
-set(unix_cmd "a \"b c\" 'd e' \";\" \\ \\'\\\" '\\'' \"\\\"\"")
-set(unix_exp "a;b c;d e;\;; '\";';\"")
-separate_arguments(unix_out UNIX_COMMAND "${unix_cmd}")
-
-set(windows_cmd "a \"b c\" 'd e' \";\" \\ \"c:\\windows\\path\\\\\" \\\"")
-set(windows_exp "a;b c;'d;e';\;;\\;c:\\windows\\path\\;\"")
-separate_arguments(windows_out WINDOWS_COMMAND "${windows_cmd}")
-
-foreach(mode old unix windows)
-  if(NOT "${${mode}_out}" STREQUAL "${${mode}_exp}")
-    message(FATAL_ERROR "separate_arguments ${mode}-style failed.  "
-      "Expected\n  [${${mode}_exp}]\nbut got\n  [${${mode}_out}]\n")
-  endif()
-endforeach()
-
-set(nothing)
-separate_arguments(nothing)
-if(DEFINED nothing)
-  message(FATAL_ERROR "separate_arguments null-case failed: "
-    "nothing=[${nothing}]")
-endif()
diff --git a/Tests/CMakeTests/ToolchainTest.cmake.in b/Tests/CMakeTests/ToolchainTest.cmake.in
index 96e7196..ea44f42 100644
--- a/Tests/CMakeTests/ToolchainTest.cmake.in
+++ b/Tests/CMakeTests/ToolchainTest.cmake.in
@@ -48,7 +48,6 @@ set(CMAKE_SYSTEM_NAME)
 set(CMAKE_SYSTEM_VERSION)
 set(CMAKE_SYSTEM_PROCESSOR)
 set(CMAKE_HOST_SYSTEM)
-set(CMAKE_HOST_SYSTEM_NAME)
 set(CMAKE_HOST_SYSTEM_VERSION)
 set(CMAKE_HOST_SYSTEM_PROCESSOR)
 
diff --git a/Tests/CPackComponents/CMakeLists.txt b/Tests/CPackComponents/CMakeLists.txt
index 3c8ae35..5b03c9e 100644
--- a/Tests/CPackComponents/CMakeLists.txt
+++ b/Tests/CPackComponents/CMakeLists.txt
@@ -79,7 +79,7 @@ set(CPACK_NSIS_MENU_LINKS
   )
 
 # Suggested default root for end users of the installer:
-set(CPACK_NSIS_INSTALL_ROOT "C:\\Program Files\\CMake Tests Install Root")
+set(CPACK_NSIS_INSTALL_ROOT "C:/Program Files/CMake Tests Install Root")
 
 # Include CPack to introduce the appropriate targets
 include(CPack)
diff --git a/Tests/CSharpLinkToCxx/CMakeLists.txt b/Tests/CSharpLinkToCxx/CMakeLists.txt
new file mode 100644
index 0000000..c4269e0
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/CMakeLists.txt
@@ -0,0 +1,17 @@
+# test if CSharp application correctly links
+# to managed C++ binary
+cmake_minimum_required(VERSION 3.9)
+project (CSharpLinkToCxx CXX CSharp)
+
+# we have to change the default flags for the
+# managed C++ project to build
+string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
+
+add_library(CLIApp SHARED cli.hpp cli.cpp)
+
+target_compile_options(CLIApp PRIVATE "/clr")
+
+add_executable(CSharpLinkToCxx csharp.cs)
+
+target_link_libraries(CSharpLinkToCxx CLIApp)
diff --git a/Tests/CSharpLinkToCxx/cli.cpp b/Tests/CSharpLinkToCxx/cli.cpp
new file mode 100644
index 0000000..97ac724
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/cli.cpp
@@ -0,0 +1,10 @@
+#include "cli.hpp"
+
+using namespace System;
+
+namespace CLIApp {
+void MyCli::testMyCli()
+{
+  Console::WriteLine("#message from CLIApp");
+}
+}
diff --git a/Tests/CSharpLinkToCxx/cli.hpp b/Tests/CSharpLinkToCxx/cli.hpp
new file mode 100644
index 0000000..a8c116d
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/cli.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+namespace CLIApp {
+public
+ref class MyCli
+{
+public:
+  void testMyCli();
+};
+}
diff --git a/Tests/CSharpLinkToCxx/csharp.cs b/Tests/CSharpLinkToCxx/csharp.cs
new file mode 100644
index 0000000..35c5cc3
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/csharp.cs
@@ -0,0 +1,16 @@
+using System;
+using CLIApp;
+
+namespace CSharpLinkToCxx
+{
+  internal class CSharpLinkToCxx
+  {
+    public static void Main(string[] args)
+    {
+      Console.WriteLine("#message from CSharpLinkToCxx");
+
+      var app = new MyCli();
+      app.testMyCli();
+    }
+  }
+}
diff --git a/Tests/CheckFortran.cmake b/Tests/CheckFortran.cmake
index 93990ad..b1652ba 100644
--- a/Tests/CheckFortran.cmake
+++ b/Tests/CheckFortran.cmake
@@ -18,6 +18,8 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
   execute_process(
     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckFortran
     COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
+                               -A "${CMAKE_GENERATOR_PLATFORM}"
+                               -T "${CMAKE_GENERATOR_TOOLSET}"
     OUTPUT_VARIABLE output
     ERROR_VARIABLE output
     RESULT_VARIABLE result
diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt
index 2a307d0..4a5558d 100644
--- a/Tests/CompileFeatures/CMakeLists.txt
+++ b/Tests/CompileFeatures/CMakeLists.txt
@@ -1,10 +1,11 @@
 
 cmake_minimum_required(VERSION 3.1)
+cmake_policy(SET CMP0057 NEW)
 
 project(CompileFeatures)
 
 macro(run_test feature lang)
-  if (";${CMAKE_${lang}_COMPILE_FEATURES};" MATCHES ${feature})
+  if (${feature} IN_LIST CMAKE_${lang}_COMPILE_FEATURES)
     add_library(test_${feature} OBJECT ${feature})
     set_property(TARGET test_${feature}
       PROPERTY COMPILE_FEATURES "${feature}"
@@ -15,12 +16,13 @@ macro(run_test feature lang)
 endmacro()
 
 get_property(c_features GLOBAL PROPERTY CMAKE_C_KNOWN_FEATURES)
-list(REMOVE_ITEM c_features c_std_90 c_std_99 c_std_11)
+list(FILTER c_features EXCLUDE REGEX "^c_std_[0-9][0-9]")
 foreach(feature ${c_features})
   run_test(${feature} C)
 endforeach()
+
 get_property(cxx_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
-list(REMOVE_ITEM cxx_features cxx_std_98 cxx_std_11 cxx_std_14 cxx_std_17)
+list(FILTER cxx_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]")
 foreach(feature ${cxx_features})
   run_test(${feature} CXX)
 endforeach()
@@ -171,12 +173,20 @@ if (CMAKE_C_COMPILER_ID STREQUAL "Intel")
   endif()
 endif()
 
+if (CMAKE_C_COMPILE_FEATURES)
+  set(C_expected_features ${CMAKE_C_COMPILE_FEATURES})
+  list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]")
+endif()
+if (CMAKE_CXX_COMPILE_FEATURES)
+  set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES})
+  list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]")
+endif ()
 set(C_ext c)
 set(C_standard_flag 11)
 set(CXX_ext cpp)
 set(CXX_standard_flag 14)
 foreach(lang CXX C)
-  if (CMAKE_${lang}_COMPILE_FEATURES)
+  if (${lang}_expected_features)
     foreach(feature ${${lang}_non_features})
       message("Testing feature : ${feature}")
       try_compile(${feature}_works
@@ -198,7 +208,7 @@ foreach(lang CXX C)
   endif()
 endforeach()
 
-if (CMAKE_C_COMPILE_FEATURES)
+if (C_expected_features)
   if (CMAKE_C_STANDARD_DEFAULT)
     string(FIND "${CMAKE_C_FLAGS}" "-std=" std_flag_idx)
     if (std_flag_idx EQUAL -1)
@@ -239,6 +249,16 @@ if (CMAKE_C_COMPILE_FEATURES)
         EXPECT_C_STATIC_ASSERT=0
         )
     endif()
+  elseif (CMAKE_C_COMPILER_ID STREQUAL "SunPro")
+    if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.13)
+      list(APPEND expected_defs
+        EXPECT_C_STATIC_ASSERT=1
+        )
+    else()
+      list(APPEND expected_defs
+        EXPECT_C_STATIC_ASSERT=0
+        )
+    endif()
   endif()
 
   list(APPEND expected_defs
@@ -270,7 +290,8 @@ if (CMAKE_CXX_COMPILE_FEATURES)
 endif ()
 
 # always add a target "CompileFeatures"
-if (NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_auto_type;")
+if ((NOT CXX_expected_features) OR
+    (NOT cxx_auto_type IN_LIST CXX_expected_features))
   file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp"
     "int main(int,char**) { return 0; }\n"
   )
diff --git a/Tests/CompileFeatures/default_dialect.c b/Tests/CompileFeatures/default_dialect.c
index 0e67095..4debd94 100644
--- a/Tests/CompileFeatures/default_dialect.c
+++ b/Tests/CompileFeatures/default_dialect.c
@@ -11,7 +11,8 @@
 #if !DEFAULT_C90
 #error Buildsystem error
 #endif
-#if defined(__STDC_VERSION__)
+#if defined(__STDC_VERSION__) &&                                              \
+  !(defined(__SUNPRO_C) && __STDC_VERSION__ == 199409L)
 #error Unexpected __STDC_VERSION__ definition
 #endif
 #endif
diff --git a/Tests/Cuda/Complex/CMakeLists.txt b/Tests/Cuda/Complex/CMakeLists.txt
index bff7d07..450ef48 100644
--- a/Tests/Cuda/Complex/CMakeLists.txt
+++ b/Tests/Cuda/Complex/CMakeLists.txt
@@ -32,9 +32,17 @@ add_library(CudaComplexSharedLib SHARED dynamic.cu)
 target_link_libraries(CudaComplexSharedLib PUBLIC CudaComplexCppBase)
 
 add_library(CudaComplexMixedLib SHARED mixed.cpp mixed.cu)
+set_target_properties(CudaComplexMixedLib
+                       PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
 target_link_libraries(CudaComplexMixedLib
                       PUBLIC CudaComplexSharedLib
                       PRIVATE CudaComplexSeperableLib)
 
 add_executable(CudaComplex main.cpp)
 target_link_libraries(CudaComplex PUBLIC CudaComplexMixedLib)
+
+if(APPLE)
+  # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that
+  # the static cuda runtime can find it at runtime.
+  target_link_libraries(CudaComplex PRIVATE -Wl,-rpath,/usr/local/cuda/lib)
+endif()
diff --git a/Tests/Cuda/Complex/dynamic.cu b/Tests/Cuda/Complex/dynamic.cu
index 82255c5..a76973d 100644
--- a/Tests/Cuda/Complex/dynamic.cu
+++ b/Tests/Cuda/Complex/dynamic.cu
@@ -20,11 +20,50 @@ static __global__ void DetermineIfValidCudaDevice()
 {
 }
 
+EXPORT int choose_cuda_device()
+{
+  int nDevices = 0;
+  cudaError_t err = cudaGetDeviceCount(&nDevices);
+  if (err != cudaSuccess) {
+    std::cerr << "Failed to retrieve the number of CUDA enabled devices"
+              << std::endl;
+    return 1;
+  }
+  for (int i = 0; i < nDevices; ++i) {
+    cudaDeviceProp prop;
+    cudaError_t err = cudaGetDeviceProperties(&prop, i);
+    if (err != cudaSuccess) {
+      std::cerr << "Could not retrieve properties from CUDA device " << i
+                << std::endl;
+      return 1;
+    }
+    if (prop.major >= 3) {
+      err = cudaSetDevice(i);
+      if (err != cudaSuccess) {
+        std::cout << "Could not select CUDA device " << i << std::endl;
+      } else {
+        return 0;
+      }
+    }
+  }
+
+  std::cout << "Could not find a CUDA enabled card supporting compute >=3.0"
+            << std::endl;
+
+  return 1;
+}
+
 EXPORT void cuda_dynamic_lib_func()
 {
   DetermineIfValidCudaDevice<<<1, 1>>>();
   cudaError_t err = cudaGetLastError();
-  if (err == cudaSuccess) {
-    std::cerr << cudaGetErrorString(err) << std::endl;
+  if (err != cudaSuccess) {
+    std::cerr << "DetermineIfValidCudaDevice [SYNC] failed: "
+              << cudaGetErrorString(err) << std::endl;
+  }
+  err = cudaDeviceSynchronize();
+  if (err != cudaSuccess) {
+    std::cerr << "DetermineIfValidCudaDevice [ASYNC] failed: "
+              << cudaGetErrorString(cudaGetLastError()) << std::endl;
   }
 }
diff --git a/Tests/Cuda/Complex/file3.cu b/Tests/Cuda/Complex/file3.cu
index 7c37d66..d055b42 100644
--- a/Tests/Cuda/Complex/file3.cu
+++ b/Tests/Cuda/Complex/file3.cu
@@ -7,20 +7,42 @@
 result_type __device__ file1_func(int x);
 result_type_dynamic __device__ file2_func(int x);
 
-static __global__ void file3_kernel(result_type& r, int x)
+static __global__ void file3_kernel(result_type* r, int x)
 {
-  r = file1_func(x);
+  *r = file1_func(x);
   result_type_dynamic rd = file2_func(x);
 }
 
 int file3_launch_kernel(int x)
 {
-  result_type r;
+  result_type* r;
+  cudaError_t err = cudaMallocManaged(&r, sizeof(result_type));
+  if (err != cudaSuccess) {
+    std::cerr << "file3_launch_kernel: cudaMallocManaged failed: "
+              << cudaGetErrorString(err) << std::endl;
+    return x;
+  }
+
   file3_kernel<<<1, 1>>>(r, x);
-  cudaError_t err = cudaGetLastError();
-  if (err == cudaSuccess) {
-    std::cerr << cudaGetErrorString(err) << std::endl;
+  err = cudaGetLastError();
+  if (err != cudaSuccess) {
+    std::cerr << "file3_kernel [SYNC] failed: " << cudaGetErrorString(err)
+              << std::endl;
+    return x;
+  }
+  err = cudaDeviceSynchronize();
+  if (err != cudaSuccess) {
+    std::cerr << "file3_kernel [ASYNC] failed: "
+              << cudaGetErrorString(cudaGetLastError()) << std::endl;
+    return x;
+  }
+  int result = r->sum;
+  err = cudaFree(r);
+  if (err != cudaSuccess) {
+    std::cerr << "file3_launch_kernel: cudaFree failed: "
+              << cudaGetErrorString(err) << std::endl;
     return x;
   }
-  return r.sum;
+
+  return result;
 }
diff --git a/Tests/Cuda/Complex/main.cpp b/Tests/Cuda/Complex/main.cpp
index 5a3f820..2498235 100644
--- a/Tests/Cuda/Complex/main.cpp
+++ b/Tests/Cuda/Complex/main.cpp
@@ -9,12 +9,18 @@
 #define IMPORT
 #endif
 
+IMPORT int choose_cuda_device();
 IMPORT int call_cuda_seperable_code(int x);
 IMPORT int mixed_launch_kernel(int x);
 
 int main(int argc, char** argv)
 {
-  call_cuda_seperable_code(42);
-  mixed_launch_kernel(42);
-  return 0;
+  int ret = choose_cuda_device();
+  if (ret) {
+    return 0;
+  }
+
+  int r1 = call_cuda_seperable_code(42);
+  int r2 = mixed_launch_kernel(42);
+  return (r1 == 42 || r2 == 42) ? 1 : 0;
 }
diff --git a/Tests/Cuda/Complex/mixed.cu b/Tests/Cuda/Complex/mixed.cu
index 4bba07c..a81ccb7 100644
--- a/Tests/Cuda/Complex/mixed.cu
+++ b/Tests/Cuda/Complex/mixed.cu
@@ -17,9 +17,9 @@ result_type_dynamic __device__ file2_func(int x);
 
 IMPORT void __host__ cuda_dynamic_lib_func();
 
-static __global__ void mixed_kernel(result_type& r, int x)
+static __global__ void mixed_kernel(result_type* r, int x)
 {
-  r = file1_func(x);
+  *r = file1_func(x);
   result_type_dynamic rd = file2_func(x);
 }
 
@@ -27,7 +27,35 @@ EXPORT int mixed_launch_kernel(int x)
 {
   cuda_dynamic_lib_func();
 
-  result_type r;
+  result_type* r;
+  cudaError_t err = cudaMallocManaged(&r, sizeof(result_type));
+  if (err != cudaSuccess) {
+    std::cerr << "mixed_launch_kernel: cudaMallocManaged failed: "
+              << cudaGetErrorString(err) << std::endl;
+    return x;
+  }
+
   mixed_kernel<<<1, 1>>>(r, x);
-  return r.sum;
+  err = cudaGetLastError();
+  if (err != cudaSuccess) {
+    std::cerr << "mixed_kernel [SYNC] failed: " << cudaGetErrorString(err)
+              << std::endl;
+    return x;
+  }
+  err = cudaDeviceSynchronize();
+  if (err != cudaSuccess) {
+    std::cerr << "mixed_kernel [ASYNC] failed: "
+              << cudaGetErrorString(cudaGetLastError()) << std::endl;
+    return x;
+  }
+
+  int result = r->sum;
+  err = cudaFree(r);
+  if (err != cudaSuccess) {
+    std::cerr << "mixed_launch_kernel: cudaFree failed: "
+              << cudaGetErrorString(err) << std::endl;
+    return x;
+  }
+
+  return result;
 }
diff --git a/Tests/Cuda/ObjectLibrary/CMakeLists.txt b/Tests/Cuda/ObjectLibrary/CMakeLists.txt
index cbe1e67..1d93be7 100644
--- a/Tests/Cuda/ObjectLibrary/CMakeLists.txt
+++ b/Tests/Cuda/ObjectLibrary/CMakeLists.txt
@@ -10,3 +10,8 @@ add_library(CudaMixedObjectLib OBJECT static.cu static.cpp)
 add_executable(CudaObjectLibrary
                main.cpp
                $<TARGET_OBJECTS:CudaMixedObjectLib>)
+if(APPLE)
+  # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that
+  # the static cuda runtime can find it at runtime.
+  target_link_libraries(CudaObjectLibrary PRIVATE -Wl,-rpath,/usr/local/cuda/lib)
+endif()
diff --git a/Tests/Cuda/ObjectLibrary/main.cpp b/Tests/Cuda/ObjectLibrary/main.cpp
index 1a70a99..4d2f890 100644
--- a/Tests/Cuda/ObjectLibrary/main.cpp
+++ b/Tests/Cuda/ObjectLibrary/main.cpp
@@ -4,14 +4,16 @@
 int static_func(int);
 int file1_sq_func(int);
 
-void test_functions()
+int test_functions()
 {
-  file1_sq_func(static_func(42));
+  return file1_sq_func(static_func(42));
 }
 
 int main(int argc, char** argv)
 {
-  test_functions();
+  if (test_functions() == 1) {
+    return 1;
+  }
   std::cout
     << "this executable doesn't use cuda code, just call methods defined"
     << std::endl;
diff --git a/Tests/Cuda/ObjectLibrary/static.cu b/Tests/Cuda/ObjectLibrary/static.cu
index cdf682b..aa35729 100644
--- a/Tests/Cuda/ObjectLibrary/static.cu
+++ b/Tests/Cuda/ObjectLibrary/static.cu
@@ -9,8 +9,8 @@ int __host__ file1_sq_func(int x)
   int nDevices = 0;
   err = cudaGetDeviceCount(&nDevices);
   if (err != cudaSuccess) {
-    std::cout << "nDevices: " << nDevices << std::endl;
-    std::cout << "err: " << err << std::endl;
+    std::cerr << "nDevices: " << nDevices << std::endl;
+    std::cerr << "err: " << err << std::endl;
     return 1;
   }
   std::cout << "this library uses cuda code" << std::endl;
diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt
index 85a2051..5f456fc 100644
--- a/Tests/CudaOnly/CMakeLists.txt
+++ b/Tests/CudaOnly/CMakeLists.txt
@@ -1,4 +1,6 @@
 
 ADD_TEST_MACRO(CudaOnly.EnableStandard CudaOnlyEnableStandard)
+ADD_TEST_MACRO(CudaOnly.ExportPTX CudaOnlyExportPTX)
 ADD_TEST_MACRO(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation)
 ADD_TEST_MACRO(CudaOnly.WithDefs CudaOnlyWithDefs)
+ADD_TEST_MACRO(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
diff --git a/Tests/CudaOnly/ExportPTX/CMakeLists.txt b/Tests/CudaOnly/ExportPTX/CMakeLists.txt
new file mode 100644
index 0000000..10249c6
--- /dev/null
+++ b/Tests/CudaOnly/ExportPTX/CMakeLists.txt
@@ -0,0 +1,82 @@
+cmake_minimum_required(VERSION 3.8)
+project (CudaOnlyExportPTX CUDA)
+
+#Goal for this example:
+# How to generate PTX files instead of OBJECT files
+# How to reference PTX files for custom commands
+# How to install PTX files
+
+add_library(CudaPTX OBJECT kernelA.cu kernelB.cu)
+set_property(TARGET CudaPTX PROPERTY CUDA_PTX_COMPILATION ON)
+
+#Test ObjectFiles with file(GENERATE)
+file(GENERATE
+     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gen_$<LOWER_CASE:$<CONFIG>/>path_to_objs.h
+     CONTENT [[
+
+#include <vector>
+#include <string>
+
+#ifndef path_to_objs
+#define path_to_objs
+
+static std::string ptx_paths = "$<TARGET_OBJECTS:CudaPTX>";
+
+#endif
+
+]]
+)
+#We are going to need a wrapper around bin2c for multiple reasons
+# 1. bin2c only converts a single file at a time
+# 2. bin2c has only standard out support, so we have to manually
+# redirect to a cmake buffer
+# 3. We want to pack everything into a single output file, so we
+# need to also pass the --name option
+set(output_file ${CMAKE_CURRENT_BINARY_DIR}/embedded_objs.h)
+
+get_filename_component(cuda_compiler_bin "${CMAKE_CUDA_COMPILER}" DIRECTORY)
+find_program(bin_to_c
+  NAMES bin2c
+  PATHS ${cuda_compiler_bin}
+  )
+if(NOT bin_to_c)
+  message(FATAL_ERROR
+    "bin2c not found:\n"
+    "  CMAKE_CUDA_COMPILER='${CMAKE_CUDA_COMPILER}'\n"
+    "  cuda_compiler_bin='${cuda_compiler_bin}'\n"
+    )
+endif()
+
+add_custom_command(
+  OUTPUT "${output_file}"
+  COMMAND ${CMAKE_COMMAND}
+    "-DBIN_TO_C_COMMAND=${bin_to_c}"
+    "-DOBJECTS=$<TARGET_OBJECTS:CudaPTX>"
+    "-DOUTPUT=${output_file}"
+    -P ${CMAKE_CURRENT_SOURCE_DIR}/bin2c_wrapper.cmake
+  VERBATIM
+  DEPENDS $<TARGET_OBJECTS:CudaPTX>
+  COMMENT "Converting Object files to a C header"
+  )
+
+add_executable(CudaOnlyExportPTX main.cu ${output_file})
+add_dependencies(CudaOnlyExportPTX CudaPTX)
+target_include_directories(CudaOnlyExportPTX PRIVATE
+                           ${CMAKE_CURRENT_BINARY_DIR} )
+target_compile_definitions(CudaOnlyExportPTX PRIVATE
+                           "CONFIG_TYPE=gen_$<LOWER_CASE:$<CONFIG>>")
+
+if(APPLE)
+  # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that
+  # the static cuda runtime can find it at runtime.
+  target_link_libraries(CudaOnlyExportPTX PRIVATE -Wl,-rpath,/usr/local/cuda/lib)
+endif()
+
+#Verify that we can install object targets properly
+install(TARGETS CudaPTX CudaOnlyExportPTX
+   EXPORT cudaPTX
+   RUNTIME DESTINATION bin
+   LIBRARY DESTINATION lib
+   OBJECTS DESTINATION objs
+   )
+install(EXPORT cudaPTX DESTINATION lib/cudaPTX)
diff --git a/Tests/CudaOnly/ExportPTX/bin2c_wrapper.cmake b/Tests/CudaOnly/ExportPTX/bin2c_wrapper.cmake
new file mode 100644
index 0000000..0baf934
--- /dev/null
+++ b/Tests/CudaOnly/ExportPTX/bin2c_wrapper.cmake
@@ -0,0 +1,19 @@
+
+set(file_contents)
+foreach(obj ${OBJECTS})
+  get_filename_component(obj_ext ${obj} EXT)
+  get_filename_component(obj_name ${obj} NAME_WE)
+  get_filename_component(obj_dir ${obj} DIRECTORY)
+
+  if(obj_ext MATCHES ".ptx")
+    set(args --name ${obj_name} ${obj})
+    execute_process(COMMAND "${BIN_TO_C_COMMAND}" ${args}
+                    WORKING_DIRECTORY ${obj_dir}
+                    RESULT_VARIABLE result
+                    OUTPUT_VARIABLE output
+                    ERROR_VARIABLE error_var
+                    )
+    set(file_contents "${file_contents} \n${output}")
+  endif()
+endforeach()
+file(WRITE "${OUTPUT}" "${file_contents}")
diff --git a/Tests/CudaOnly/ExportPTX/kernelA.cu b/Tests/CudaOnly/ExportPTX/kernelA.cu
new file mode 100644
index 0000000..fbe0d26
--- /dev/null
+++ b/Tests/CudaOnly/ExportPTX/kernelA.cu
@@ -0,0 +1,7 @@
+
+__global__ void kernelA(float* r, float* x, float* y, float* z, int size)
+{
+  for (int i = threadIdx.x; i < size; i += blockDim.x) {
+    r[i] = x[i] * y[i] + z[i];
+  }
+}
diff --git a/Tests/CudaOnly/ExportPTX/kernelB.cu b/Tests/CudaOnly/ExportPTX/kernelB.cu
new file mode 100644
index 0000000..11872e4
--- /dev/null
+++ b/Tests/CudaOnly/ExportPTX/kernelB.cu
@@ -0,0 +1,8 @@
+
+
+__global__ void kernelB(float* r, float* x, float* y, float* z, int size)
+{
+  for (int i = threadIdx.x; i < size; i += blockDim.x) {
+    r[i] = x[i] * y[i] + z[i];
+  }
+}
diff --git a/Tests/CudaOnly/ExportPTX/main.cu b/Tests/CudaOnly/ExportPTX/main.cu
new file mode 100644
index 0000000..132377c
--- /dev/null
+++ b/Tests/CudaOnly/ExportPTX/main.cu
@@ -0,0 +1,28 @@
+
+#include <iostream>
+
+/*
+  Define GENERATED_HEADER macro to allow c++ files to include headers
+  generated based on different configuration types.
+*/
+
+/* clang-format off */
+#define GENERATED_HEADER(x) GENERATED_HEADER0(CONFIG_TYPE/x)
+/* clang-format on */
+#define GENERATED_HEADER0(x) GENERATED_HEADER1(x)
+#define GENERATED_HEADER1(x) <x>
+
+#include GENERATED_HEADER(path_to_objs.h)
+
+#include "embedded_objs.h"
+
+int main(int argc, char** argv)
+{
+  (void)argc;
+  (void)argv;
+
+  unsigned char* ka = kernelA;
+  unsigned char* kb = kernelB;
+
+  return (ka != NULL && kb != NULL) ? 0 : 1;
+}
diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt b/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt
new file mode 100644
index 0000000..b96bb98
--- /dev/null
+++ b/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt
@@ -0,0 +1,52 @@
+cmake_minimum_required(VERSION 3.7)
+project (CudaOnlyResolveDeviceSymbols CUDA)
+
+# Find nm and dumpbin
+if(CMAKE_NM)
+  set(dump_command ${CMAKE_NM})
+  set(dump_args -g)
+else()
+  include(GetPrerequisites)
+  message(STATUS "calling list_prerequisites to find dumpbin")
+  list_prerequisites("${CMAKE_COMMAND}" 0 0 0)
+  if(gp_dumpbin)
+    set(dump_command ${gp_dumpbin})
+    set(dump_args /ARCHIVEMEMBERS)
+  endif()
+endif()
+
+#Goal for this example:
+#Build a static library that defines multiple methods and kernels that
+#use each other.
+#Use a custom command to build an executable that uses this static library
+#We do these together to verify that we can get a static library to do
+#device symbol linking, and not have it done when the executable is made
+string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30")
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CUDA_STANDARD 11)
+
+add_library(CUDAResolveDeviceLib STATIC file1.cu file2.cu)
+set_target_properties(CUDAResolveDeviceLib
+                      PROPERTIES
+                      CUDA_SEPARABLE_COMPILATION ON
+                      CUDA_RESOLVE_DEVICE_SYMBOLS ON
+                      POSITION_INDEPENDENT_CODE ON)
+
+if(dump_command)
+add_custom_command(TARGET CUDAResolveDeviceLib POST_BUILD
+  COMMAND ${CMAKE_COMMAND}
+  -DDUMP_COMMAND=${dump_command}
+  -DDUMP_ARGS=${dump_args}
+  -DTEST_LIBRARY_PATH=$<TARGET_FILE:CUDAResolveDeviceLib>
+  -P ${CMAKE_CURRENT_SOURCE_DIR}/verify.cmake
+  )
+endif()
+
+add_executable(CudaOnlyResolveDeviceSymbols main.cu)
+target_link_libraries(CudaOnlyResolveDeviceSymbols PRIVATE CUDAResolveDeviceLib)
+
+if(APPLE)
+  # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that
+  # the static cuda runtime can find it at runtime.
+  target_link_libraries(CudaOnlyResolveDeviceSymbols PRIVATE -Wl,-rpath,/usr/local/cuda/lib)
+endif()
diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file1.cu b/Tests/CudaOnly/ResolveDeviceSymbols/file1.cu
new file mode 100644
index 0000000..1ce63bf
--- /dev/null
+++ b/Tests/CudaOnly/ResolveDeviceSymbols/file1.cu
@@ -0,0 +1,10 @@
+
+#include "file1.h"
+
+result_type __device__ file1_func(int x)
+{
+  result_type r;
+  r.input = x;
+  r.sum = x * x;
+  return r;
+}
diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file1.h b/Tests/CudaOnly/ResolveDeviceSymbols/file1.h
new file mode 100644
index 0000000..ff1945c
--- /dev/null
+++ b/Tests/CudaOnly/ResolveDeviceSymbols/file1.h
@@ -0,0 +1,7 @@
+
+#pragma once
+struct result_type
+{
+  int input;
+  int sum;
+};
diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu b/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu
new file mode 100644
index 0000000..278fd6c
--- /dev/null
+++ b/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu
@@ -0,0 +1,25 @@
+
+#include "file2.h"
+
+result_type __device__ file1_func(int x);
+
+result_type_dynamic __device__ file2_func(int x)
+{
+  const result_type r = file1_func(x);
+  const result_type_dynamic rd{ r.input, r.sum, true };
+  return rd;
+}
+
+static __global__ void file2_kernel(result_type_dynamic& r, int x)
+{
+  // call static_func which is a method that is defined in the
+  // static library that is always out of date
+  r = file2_func(x);
+}
+
+int file2_launch_kernel(int x)
+{
+  result_type_dynamic r;
+  file2_kernel<<<1, 1>>>(r, x);
+  return r.sum;
+}
diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file2.h b/Tests/CudaOnly/ResolveDeviceSymbols/file2.h
new file mode 100644
index 0000000..d2dbaa4
--- /dev/null
+++ b/Tests/CudaOnly/ResolveDeviceSymbols/file2.h
@@ -0,0 +1,10 @@
+
+#pragma once
+#include "file1.h"
+
+struct result_type_dynamic
+{
+  int input;
+  int sum;
+  bool from_static;
+};
diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/main.cu b/Tests/CudaOnly/ResolveDeviceSymbols/main.cu
new file mode 100644
index 0000000..b4b5b9e
--- /dev/null
+++ b/Tests/CudaOnly/ResolveDeviceSymbols/main.cu
@@ -0,0 +1,85 @@
+
+#include <iostream>
+
+#include "file1.h"
+#include "file2.h"
+
+int file2_launch_kernel(int x);
+
+result_type_dynamic __device__ file2_func(int x);
+static __global__ void main_kernel(result_type_dynamic& r, int x)
+{
+  // call function that was not device linked to us, this will cause
+  // a runtime failure of "invalid device function"
+  r = file2_func(x);
+}
+
+int main_launch_kernel(int x)
+{
+  result_type_dynamic r;
+  main_kernel<<<1, 1>>>(r, x);
+  return r.sum;
+}
+
+int choose_cuda_device()
+{
+  int nDevices = 0;
+  cudaError_t err = cudaGetDeviceCount(&nDevices);
+  if (err != cudaSuccess) {
+    std::cerr << "Failed to retrieve the number of CUDA enabled devices"
+              << std::endl;
+    return 1;
+  }
+  for (int i = 0; i < nDevices; ++i) {
+    cudaDeviceProp prop;
+    cudaError_t err = cudaGetDeviceProperties(&prop, i);
+    if (err != cudaSuccess) {
+      std::cerr << "Could not retrieve properties from CUDA device " << i
+                << std::endl;
+      return 1;
+    }
+    std::cout << "prop.major: " << prop.major << std::endl;
+    if (prop.major >= 3) {
+      err = cudaSetDevice(i);
+      if (err != cudaSuccess) {
+        std::cout << "Could not select CUDA device " << i << std::endl;
+      } else {
+        return 0;
+      }
+    }
+  }
+
+  std::cout << "Could not find a CUDA enabled card supporting compute >=3.0"
+            << std::endl;
+
+  return 1;
+}
+
+int main(int argc, char** argv)
+{
+  int ret = choose_cuda_device();
+  if (ret) {
+    return 0;
+  }
+
+  cudaError_t err;
+  file2_launch_kernel(42);
+  err = cudaGetLastError();
+  if (err != cudaSuccess) {
+    std::cerr << "file2_launch_kernel: kernel launch failed: "
+              << cudaGetErrorString(err) << std::endl;
+    return 1;
+  }
+
+  main_launch_kernel(1);
+  err = cudaGetLastError();
+  if (err == cudaSuccess) {
+    // This kernel launch should fail as the file2_func was device linked
+    // into the static library and is not usable by the executable
+    std::cerr << "main_launch_kernel: kernel launch should have failed"
+              << std::endl;
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/verify.cmake b/Tests/CudaOnly/ResolveDeviceSymbols/verify.cmake
new file mode 100644
index 0000000..94d388b
--- /dev/null
+++ b/Tests/CudaOnly/ResolveDeviceSymbols/verify.cmake
@@ -0,0 +1,14 @@
+execute_process(COMMAND ${DUMP_COMMAND} ${DUMP_ARGS} ${TEST_LIBRARY_PATH}
+  RESULT_VARIABLE RESULT
+  OUTPUT_VARIABLE OUTPUT
+  ERROR_VARIABLE ERROR
+)
+
+if(NOT "${RESULT}" STREQUAL "0")
+  message(FATAL_ERROR "${DUMP_COMMAND} failed [${RESULT}] [${OUTPUT}] [${ERROR}]")
+endif()
+
+if(NOT "${OUTPUT}" MATCHES "(cmake_device_link|device-link)")
+  message(FATAL_ERROR
+    "No cuda device objects found, device linking did not occur")
+endif()
diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
index d134b96..3d4a170 100644
--- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
+++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
@@ -12,22 +12,44 @@ project (CudaOnlySeparateCompilation CUDA)
 string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30")
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CUDA_STANDARD 11)
-add_library(CUDASerarateLibA STATIC file1.cu file2.cu file3.cu)
+
+add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu)
+
+if(CMAKE_CUDA_SIMULATE_ID STREQUAL "MSVC")
+  # Test adding a flag that is not in our CUDA flag table for VS.
+  if(NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 8)
+    string(APPEND CMAKE_CUDA_FLAGS " --ftemplate-depth 50")
+  endif()
+  # Test adding a flag that nvcc should pass to the host compiler.
+  target_compile_options(CUDASeparateLibA PRIVATE -Xcompiler=-bigobj)
+endif()
 
 #Having file4/file5 in a shared library causes serious problems
 #with the nvcc linker and it will generate bad entries that will
 #cause a segv when trying to run the executable
 #
-add_library(CUDASerarateLibB STATIC file4.cu file5.cu)
-target_link_libraries(CUDASerarateLibB PRIVATE CUDASerarateLibA)
+add_library(CUDASeparateLibB STATIC file4.cu file5.cu)
+target_link_libraries(CUDASeparateLibB PRIVATE CUDASeparateLibA)
 
 add_executable(CudaOnlySeparateCompilation main.cu)
-target_link_libraries(CudaOnlySeparateCompilation PRIVATE CUDASerarateLibB)
+target_link_libraries(CudaOnlySeparateCompilation
+                      PRIVATE CUDASeparateLibB)
+
+set_target_properties(CUDASeparateLibA
+                      CUDASeparateLibB
+                      PROPERTIES CUDA_SEPARABLE_COMPILATION ON
+                      POSITION_INDEPENDENT_CODE ON)
 
-set_target_properties( CUDASerarateLibA
-                       CUDASerarateLibB
-                       PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
+if (CMAKE_GENERATOR MATCHES "^Visual Studio")
+  #Visual Studio CUDA integration will not perform device linking
+  #on a target that itself does not have GenerateRelocatableDeviceCode
+  #enabled.
+  set_target_properties(CudaOnlySeparateCompilation
+                        PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
+endif()
 
-set_target_properties( CUDASerarateLibA
-                       CUDASerarateLibB
-                       PROPERTIES POSITION_INDEPENDENT_CODE ON)
+if (APPLE)
+  # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that
+  # the static cuda runtime can find it at runtime.
+  target_link_libraries(CudaOnlySeparateCompilation PRIVATE -Wl,-rpath,/usr/local/cuda/lib)
+endif()
diff --git a/Tests/CudaOnly/SeparateCompilation/main.cu b/Tests/CudaOnly/SeparateCompilation/main.cu
index 03e0921..40dbe5d 100644
--- a/Tests/CudaOnly/SeparateCompilation/main.cu
+++ b/Tests/CudaOnly/SeparateCompilation/main.cu
@@ -7,9 +7,62 @@
 int file4_launch_kernel(int x);
 int file5_launch_kernel(int x);
 
+int choose_cuda_device()
+{
+  int nDevices = 0;
+  cudaError_t err = cudaGetDeviceCount(&nDevices);
+  if (err != cudaSuccess) {
+    std::cerr << "Failed to retrieve the number of CUDA enabled devices"
+              << std::endl;
+    return 1;
+  }
+  for (int i = 0; i < nDevices; ++i) {
+    cudaDeviceProp prop;
+    cudaError_t err = cudaGetDeviceProperties(&prop, i);
+    if (err != cudaSuccess) {
+      std::cerr << "Could not retrieve properties from CUDA device " << i
+                << std::endl;
+      return 1;
+    }
+    if (prop.major >= 3) {
+      err = cudaSetDevice(i);
+      if (err != cudaSuccess) {
+        std::cout << "Could not select CUDA device " << i << std::endl;
+      } else {
+        return 0;
+      }
+    }
+  }
+
+  std::cout << "Could not find a CUDA enabled card supporting compute >=3.0"
+            << std::endl;
+
+  return 1;
+}
+
 int main(int argc, char** argv)
 {
+  int ret = choose_cuda_device();
+  if (ret) {
+    return 0;
+  }
+
+  cudaError_t err;
   file4_launch_kernel(42);
+  err = cudaGetLastError();
+  if (err != cudaSuccess) {
+    std::cerr << "file4_launch_kernel: kernel launch failed: "
+              << cudaGetErrorString(err) << std::endl;
+    return 1;
+  }
+
   file5_launch_kernel(42);
+  err = cudaGetLastError();
+  if (err != cudaSuccess) {
+    std::cerr << "file5_launch_kernel: kernel launch failed: "
+              << cudaGetErrorString(err) << std::endl;
+    return 1;
+  }
+
   return 0;
 }
diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt
index 2646d29..e25f141 100644
--- a/Tests/CudaOnly/WithDefs/CMakeLists.txt
+++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt
@@ -16,11 +16,19 @@ set(release_compile_defs DEFREL)
 #build a executable that needs to be passed a complex define through add_defintions
 #this verifies we can pass things such as '_','(' to nvcc
 add_definitions("-DPACKED_DEFINE=__attribute__((packed))")
-set_source_files_properties(main.notcu PROPERTIES LANGUAGE CUDA)
-add_executable(CudaOnlyWithDefs main.notcu)
+
+if(CMAKE_GENERATOR MATCHES "Visual Studio")
+  # CUDA MSBuild rules do not pass '-x cu' to nvcc
+  set(main main_for_vs.cu)
+else()
+  set(main main.notcu)
+  set_source_files_properties(main.notcu PROPERTIES LANGUAGE CUDA)
+endif()
+add_executable(CudaOnlyWithDefs ${main})
 
 target_compile_options(CudaOnlyWithDefs
   PRIVATE
+    -Xcompiler=-DHOST_DEFINE
     $<$<CONFIG:DEBUG>:$<BUILD_INTERFACE:${debug_compile_flags}>>
   )
 
diff --git a/Tests/CudaOnly/WithDefs/main.notcu b/Tests/CudaOnly/WithDefs/main.notcu
index 80ed3a5..d2eff3f 100644
--- a/Tests/CudaOnly/WithDefs/main.notcu
+++ b/Tests/CudaOnly/WithDefs/main.notcu
@@ -2,6 +2,10 @@
 #include <cuda_runtime.h>
 #include <iostream>
 
+#ifndef HOST_DEFINE
+#error "HOST_DEFINE not defined!"
+#endif
+
 #ifndef PACKED_DEFINE
 #error "PACKED_DEFINE not defined!"
 #endif
diff --git a/Tests/CudaOnly/WithDefs/main_for_vs.cu b/Tests/CudaOnly/WithDefs/main_for_vs.cu
new file mode 100644
index 0000000..56078e7
--- /dev/null
+++ b/Tests/CudaOnly/WithDefs/main_for_vs.cu
@@ -0,0 +1 @@
+#include "main.notcu"
diff --git a/Tests/CustomCommandByproducts/ninja-check.cmake b/Tests/CustomCommandByproducts/ninja-check.cmake
index 2fc3cc2..a7beb3d 100644
--- a/Tests/CustomCommandByproducts/ninja-check.cmake
+++ b/Tests/CustomCommandByproducts/ninja-check.cmake
@@ -4,7 +4,7 @@ if("${build_ninja}" MATCHES [====[
 # Tell Ninja that they may appear as side effects of build rules
 # otherwise ordered by order-only dependencies.
 
-((build [^:]*: phony [^\n]*
+((build [^:]*: phony[^\n]*
 )*)# ========]====])
   set(phony "${CMAKE_MATCH_1}")
   if(NOT phony)
diff --git a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt
index f917cd7..4975feb 100644
--- a/Tests/CustomCommandWorkingDirectory/CMakeLists.txt
+++ b/Tests/CustomCommandWorkingDirectory/CMakeLists.txt
@@ -19,6 +19,7 @@ add_executable(working "${TestWorkingDir_BINARY_DIR}/working.c"
 add_custom_target(
   Custom ALL
   COMMAND "${CMAKE_COMMAND}" -E copy_if_different ./customTarget.c "${TestWorkingDir_BINARY_DIR}/customTarget.c"
+  BYPRODUCTS "${TestWorkingDir_BINARY_DIR}/customTarget.c"
   WORKING_DIRECTORY  "${TestWorkingDir_SOURCE_DIR}"
 )
 
@@ -36,6 +37,7 @@ add_executable(working2 working2.c ${TestWorkingDir_BINARY_DIR}/customTarget2.c)
 add_custom_target(
   Custom2 ALL
   COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${TestWorkingDir_SOURCE_DIR}/customTarget.c ../customTarget2.c
+  BYPRODUCTS "${TestWorkingDir_BINARY_DIR}/customTarget2.c"
   WORKING_DIRECTORY work/ # Relative to build tree, trailing slash
 )
 
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index f504c7b..eeae3f0 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -79,6 +79,15 @@ set_property(TARGET testLib7 PROPERTY OUTPUT_NAME_DEBUG testLib7D-$<CONFIG>)
 set_property(TARGET testLib7 PROPERTY OUTPUT_NAME_RELEASE testLib7R-$<CONFIG>)
 set_property(TARGET testLib7 PROPERTY OUTPUT_NAME testLib7-$<CONFIG>)
 
+# Test exporting OBJECT targets
+add_library(testLib8 OBJECT testLib8A.c testLib8B.c sub/testLib8C.c)
+
+if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
+  set(maybe_testLib8 testLib8)
+else()
+  set(maybe_testLib8 "")
+endif()
+
 # Test using the target_link_libraries command to set the
 # LINK_INTERFACE_LIBRARIES* properties.  We construct two libraries
 # providing the same two symbols.  In each library one of the symbols
@@ -474,7 +483,7 @@ install(
   TARGETS
   testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3 testExe4
   testExe2lib testLib4lib testLib4libdbg testLib4libopt
-  testLib6 testLib7
+  testLib6 testLib7 ${maybe_testLib8}
   testLibCycleA testLibCycleB
   testLibNoSONAME
   cmp0022NEW cmp0022OLD
@@ -483,6 +492,7 @@ install(
   RUNTIME DESTINATION $<1:bin>
   LIBRARY DESTINATION $<1:lib> NAMELINK_SKIP
   ARCHIVE DESTINATION $<1:lib>
+  OBJECTS DESTINATION $<1:lib>
   FRAMEWORK DESTINATION Frameworks
   BUNDLE DESTINATION Applications
   )
@@ -535,6 +545,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3
   FILE ExportBuildTree.cmake
   )
 export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 testExe2lib
+  ${maybe_testLib8}
   testLib4lib testLib4libdbg testLib4libopt
   testLibCycleA testLibCycleB
   testLibNoSONAME
diff --git a/Tests/ExportImport/Export/sub/testLib8C.c b/Tests/ExportImport/Export/sub/testLib8C.c
new file mode 100644
index 0000000..a5568c7
--- /dev/null
+++ b/Tests/ExportImport/Export/sub/testLib8C.c
@@ -0,0 +1,4 @@
+int testLib8C(void)
+{
+  return 0;
+}
diff --git a/Tests/ExportImport/Export/testLib8A.c b/Tests/ExportImport/Export/testLib8A.c
new file mode 100644
index 0000000..c64655a
--- /dev/null
+++ b/Tests/ExportImport/Export/testLib8A.c
@@ -0,0 +1,4 @@
+int testLib8A(void)
+{
+  return 0;
+}
diff --git a/Tests/ExportImport/Export/testLib8B.c b/Tests/ExportImport/Export/testLib8B.c
new file mode 100644
index 0000000..1be6c9c
--- /dev/null
+++ b/Tests/ExportImport/Export/testLib8B.c
@@ -0,0 +1,4 @@
+int testLib8B(void)
+{
+  return 0;
+}
diff --git a/Tests/ExportImport/Export/testLibNoSONAME.c b/Tests/ExportImport/Export/testLibNoSONAME.c
index 30acc83..4d98562 100644
--- a/Tests/ExportImport/Export/testLibNoSONAME.c
+++ b/Tests/ExportImport/Export/testLibNoSONAME.c
@@ -4,7 +4,7 @@
 #define testLibNoSONAME_EXPORT
 #endif
 
-testLibNoSONAME_EXPORT int testLibNoSONAME(void)
+testLibNoSONAME_EXPORT int testLibNoSoName(void)
 {
   return 0;
 }
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 5ce9628..01960ea 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -228,6 +228,16 @@ target_link_libraries(imp_lib1 exp_testLib2)
 add_library(imp_lib1b STATIC imp_lib1.c)
 target_link_libraries(imp_lib1b bld_testLib2)
 
+if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
+  # Create a executable that is using objects imported from the install tree
+  add_executable(imp_testLib8 imp_testLib8.c $<TARGET_OBJECTS:exp_testLib8>)
+
+  if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT XCODE_VERSION VERSION_LESS 5)
+    # Create a executable that is using objects imported from the build tree
+    add_executable(imp_testLib8b imp_testLib8.c $<TARGET_OBJECTS:bld_testLib8>)
+  endif()
+endif()
+
 #-----------------------------------------------------------------------------
 # Test that handling imported targets, including transitive dependencies,
 # works in CheckFunctionExists (...and hopefully all other try_compile() checks
diff --git a/Tests/ExportImport/Import/A/imp_testExe1.c b/Tests/ExportImport/Import/A/imp_testExe1.c
index 83a9bb5..3488439 100644
--- a/Tests/ExportImport/Import/A/imp_testExe1.c
+++ b/Tests/ExportImport/Import/A/imp_testExe1.c
@@ -1,15 +1,15 @@
-extern int generated_by_testExe1();
-extern int generated_by_testExe3();
-extern int generated_by_testExe4();
-extern int testLib2();
-extern int testLib3();
-extern int testLib4();
-extern int testLib4lib();
-extern int testLib5();
-extern int testLib6();
-extern int testLib7();
-extern int testLibCycleA1();
-extern int testLibPerConfigDest();
+extern int generated_by_testExe1(void);
+extern int generated_by_testExe3(void);
+extern int generated_by_testExe4(void);
+extern int testLib2(void);
+extern int testLib3(void);
+extern int testLib4(void);
+extern int testLib4lib(void);
+extern int testLib5(void);
+extern int testLib6(void);
+extern int testLib7(void);
+extern int testLibCycleA1(void);
+extern int testLibPerConfigDest(void);
 
 /* Switch a symbol between debug and optimized builds to make sure the
    proper library is found from the testLib4 link interface.  */
diff --git a/Tests/ExportImport/Import/A/imp_testLib8.c b/Tests/ExportImport/Import/A/imp_testLib8.c
new file mode 100644
index 0000000..2749b17
--- /dev/null
+++ b/Tests/ExportImport/Import/A/imp_testLib8.c
@@ -0,0 +1,8 @@
+
+int testLib8A(void);
+int testLib8B(void);
+
+int main()
+{
+  return (testLib8A() + testLib8B());
+}
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index 72c20eb..6b73563 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -90,6 +90,16 @@ ExternalProject_Add(${proj}
 )
 set_property(TARGET ${proj} PROPERTY FOLDER "")
 
+set(proj NoExtractLogDownload)
+ExternalProject_Add(${proj}
+  URL ${CMAKE_CURRENT_SOURCE_DIR}/gitrepo.tgz
+  DOWNLOAD_NO_EXTRACT 1
+  LOG_DOWNLOAD 1
+  BUILD_COMMAND ""
+  CONFIGURE_COMMAND ""
+  INSTALL_COMMAND ""
+)
+
 
 # CVS-based tests:
 #
diff --git a/Tests/FindDoxygen/CMakeLists.txt b/Tests/FindDoxygen/CMakeLists.txt
new file mode 100644
index 0000000..daceaa3
--- /dev/null
+++ b/Tests/FindDoxygen/CMakeLists.txt
@@ -0,0 +1,20 @@
+add_test(NAME FindDoxygen.SimpleTest COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindDoxygen/SimpleTest"
+  "${CMake_BINARY_DIR}/Tests/FindDoxygen/SimpleTest"
+  --build-target allDocTargets
+  ${build_generator_args}
+  --build-options ${build_options}
+)
+
+if(CMake_TEST_FindDoxygen_Dot)
+  add_test(NAME FindDoxygen.DotComponentTest COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindDoxygen/DotComponentTestTest"
+    "${CMake_BINARY_DIR}/Tests/FindDoxygen/DotComponentTestTest"
+    ${build_generator_args}
+    --build-options ${build_options}
+  )
+endif()
diff --git a/Tests/FindDoxygen/DotComponentTestTest/CMakeLists.txt b/Tests/FindDoxygen/DotComponentTestTest/CMakeLists.txt
new file mode 100644
index 0000000..586f0ff
--- /dev/null
+++ b/Tests/FindDoxygen/DotComponentTestTest/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.8)
+project(TestFindDoxygenDot VERSION 1.0 LANGUAGES NONE)
+
+# Testing a new signature w/ components
+find_package(Doxygen REQUIRED COMPONENTS dot)
+
+# No backwards compatibility expected when component form is used
+if(TARGET Doxygen::doxygen)
+    if(DOXYGEN)
+        message(FATAL_ERROR "DOXYGEN unexpectedly defined with component form")
+    endif()
+else()
+    message(FATAL_ERROR "Import target Doxygen::doxygen not defined")
+endif()
+
+if(NOT TARGET Doxygen::dot)
+    message(FATAL_ERROR "Import target Doxygen::dot not defined")
+endif()
diff --git a/Tests/FindDoxygen/SimpleTest/CMakeLists.txt b/Tests/FindDoxygen/SimpleTest/CMakeLists.txt
new file mode 100644
index 0000000..332cecc
--- /dev/null
+++ b/Tests/FindDoxygen/SimpleTest/CMakeLists.txt
@@ -0,0 +1,59 @@
+cmake_minimum_required(VERSION 3.8)
+project(TestFindDoxygen VERSION 1.0 LANGUAGES NONE)
+
+# Testing backward compatible signature
+find_package(Doxygen REQUIRED)
+
+if(TARGET Doxygen::doxygen)
+    # Check backward compatibility
+    if(NOT DOXYGEN_EXECUTABLE)
+        message(FATAL_ERROR "Backward compatibility broken: DOXYGEN_EXECUTABLE not set")
+    endif()
+    if(NOT DOXYGEN)
+        message(FATAL_ERROR "Backward compatibility broken: DOXYGEN not set")
+    endif()
+    # Check presence of expected generated files
+    foreach(file CMakeDoxyfile.in CMakeDoxygenDefaults.cmake)
+        if(NOT EXISTS "${PROJECT_BINARY_DIR}/${file}")
+            message(FATAL_ERROR "Missing generated file: ${file}")
+        endif()
+    endforeach()
+else()
+    message(FATAL_ERROR "Import target Doxygen::doxygen not defined")
+endif()
+
+doxygen_add_docs(docsNoArgs)
+if(NOT EXISTS "${PROJECT_BINARY_DIR}/Doxyfile.docsNoArgs")
+    message(FATAL_ERROR "Missing generated file: Doxyfile.docsNoArgs")
+endif()
+if(NOT TARGET docsNoArgs)
+    message(FATAL_ERROR "Target docsNoArgs not created")
+endif()
+
+configure_file(spaces_in_name.cpp.in "spaces in name.cpp" COPYONLY)
+doxygen_add_docs(docsWithArgs
+    "${CMAKE_CURRENT_BINARY_DIR}/spaces in name.cpp"
+    main.cpp
+)
+if(NOT EXISTS "${PROJECT_BINARY_DIR}/Doxyfile.docsWithArgs")
+    message(FATAL_ERROR "Missing generated file: Doxyfile.docsWithArgs")
+endif()
+if(NOT TARGET docsWithArgs)
+    message(FATAL_ERROR "Target docsWithArgs not created")
+endif()
+# Note that CMake inserts at least one entry into SOURCES when a COMMAND or
+# DEPENDS option is given to add_custom_target(), so rather than looking for an
+# exact match, we only verify that the files we expect to be there are present
+get_target_property(srcList docsWithArgs SOURCES)
+set(expectedList
+    "${CMAKE_CURRENT_BINARY_DIR}/spaces in name.cpp"
+    "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp"
+)
+foreach(f IN LISTS expectedList)
+    if(NOT f IN_LIST srcList)
+        message(FATAL_ERROR "SOURCES missing file: ${f}")
+    endif()
+endforeach()
+
+add_custom_target(allDocTargets)
+add_dependencies(allDocTargets docsNoArgs docsWithArgs)
diff --git a/Tests/FindDoxygen/SimpleTest/main.cpp b/Tests/FindDoxygen/SimpleTest/main.cpp
new file mode 100644
index 0000000..925f0af
--- /dev/null
+++ b/Tests/FindDoxygen/SimpleTest/main.cpp
@@ -0,0 +1,4 @@
+/**
+ * \file
+ * \brief One C++ file w/ sample Doxygen comment just to produce any docs...
+ */
diff --git a/Tests/FindDoxygen/SimpleTest/spaces_in_name.cpp.in b/Tests/FindDoxygen/SimpleTest/spaces_in_name.cpp.in
new file mode 100644
index 0000000..c1b9ffd
--- /dev/null
+++ b/Tests/FindDoxygen/SimpleTest/spaces_in_name.cpp.in
@@ -0,0 +1,4 @@
+/**
+ * \file
+ * \brief This file name contains spaces
+ */
diff --git a/Tests/FindGTest/Test/CMakeLists.txt b/Tests/FindGTest/Test/CMakeLists.txt
index 99368ac..b65b9d2 100644
--- a/Tests/FindGTest/Test/CMakeLists.txt
+++ b/Tests/FindGTest/Test/CMakeLists.txt
@@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.1)
 project(TestFindGTest CXX)
 include(CTest)
 
-# CMake does not actually provide FindGTest publicly.
-set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Modules)
-
 find_package(GTest REQUIRED)
 
 add_executable(test_gtest_tgt main.cxx)
diff --git a/Tests/FindMPI/CMakeLists.txt b/Tests/FindMPI/CMakeLists.txt
new file mode 100644
index 0000000..121d978
--- /dev/null
+++ b/Tests/FindMPI/CMakeLists.txt
@@ -0,0 +1,21 @@
+foreach(c C CXX Fortran)
+  if(CMake_TEST_FindMPI_${c})
+    set(CMake_TEST_FindMPI_FLAG_${c} 1)
+  else()
+    set(CMake_TEST_FindMPI_FLAG_${c} 0)
+  endif()
+endforeach()
+
+add_test(NAME FindMPI.Test COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindMPI/Test"
+  "${CMake_BINARY_DIR}/Tests/FindMPI/Test"
+  ${build_generator_args}
+  --build-project TestFindMPI
+  --build-options ${build_options}
+  -DMPI_TEST_C=${CMake_TEST_FindMPI_FLAG_C}
+  -DMPI_TEST_CXX=${CMake_TEST_FindMPI_FLAG_CXX}
+  -DMPI_TEST_Fortran=${CMake_TEST_FindMPI_FLAG_Fortran}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
diff --git a/Tests/FindMPI/Test/CMakeLists.txt b/Tests/FindMPI/Test/CMakeLists.txt
new file mode 100644
index 0000000..3910c25
--- /dev/null
+++ b/Tests/FindMPI/Test/CMakeLists.txt
@@ -0,0 +1,41 @@
+cmake_minimum_required(VERSION 3.8)
+project(TestFindMPI NONE)
+include(CTest)
+
+macro(source_code_mapper_helper LANG_NAME)
+  if("${LANG_NAME}" STREQUAL "C")
+    set(MPITEST_SOURCE_FILE "main.c")
+  elseif("${LANG_NAME}" STREQUAL "CXX")
+    configure_file("main.c" "main.cxx" COPYONLY)
+    set(MPITEST_SOURCE_FILE "main.cxx")
+  elseif("${LANG_NAME}" STREQUAL "Fortran")
+    set(MPITEST_SOURCE_FILE "main.f90")
+  endif()
+endmacro()
+
+foreach(c C CXX Fortran)
+  if("${MPI_TEST_${c}}")
+    message("Testing ${c}")
+    enable_language(${c})
+  endif()
+endforeach()
+
+find_package(MPI REQUIRED)
+
+foreach(c C CXX Fortran)
+  if(NOT "${MPI_TEST_${c}}")
+    continue()
+  endif()
+  source_code_mapper_helper(${c})
+  add_executable(test_tgt_${c} ${MPITEST_SOURCE_FILE})
+  target_link_libraries(test_tgt_${c} MPI::MPI_${c})
+  add_test(NAME test_tgt_${c} COMMAND test_tgt_${c})
+
+  add_executable(test_var_${c} ${MPITEST_SOURCE_FILE})
+  target_include_directories(test_var_${c} PRIVATE "${MPI_${c}_INCLUDE_PATH}")
+  target_link_libraries(test_var_${c} PRIVATE "${MPI_${c}_LINK_FLAGS}" "${MPI_${c}_LIBRARIES}")
+  set(copied_MPI_${c}_OPTIONS "${MPI_${c}_COMPILE_FLAGS}")
+  separate_arguments(copied_MPI_${c}_OPTIONS)
+  target_compile_options(test_var_${c} PRIVATE "${copied_MPI_${c}_OPTIONS}")
+  add_test(NAME test_var_${c} COMMAND test_var_${c})
+endforeach()
diff --git a/Tests/FindMPI/Test/main.c b/Tests/FindMPI/Test/main.c
new file mode 100644
index 0000000..7b7f175
--- /dev/null
+++ b/Tests/FindMPI/Test/main.c
@@ -0,0 +1,7 @@
+#include <mpi.h>
+
+int main(int argc, char** argv)
+{
+  MPI_Init(&argc, &argv);
+  MPI_Finalize();
+}
diff --git a/Tests/FindMPI/Test/main.f90 b/Tests/FindMPI/Test/main.f90
new file mode 100644
index 0000000..6fb6fd3
--- /dev/null
+++ b/Tests/FindMPI/Test/main.f90
@@ -0,0 +1,7 @@
+program mpi_test
+  include 'mpif.h'
+  integer ierror
+
+  call MPI_INIT(ierror)
+  call MPI_FINALIZE(ierror)
+end program mpi_test
diff --git a/Tests/FindModulesExecuteAll/CMakeLists.txt b/Tests/FindModulesExecuteAll/CMakeLists.txt
index 21b9d38..4893bb3 100644
--- a/Tests/FindModulesExecuteAll/CMakeLists.txt
+++ b/Tests/FindModulesExecuteAll/CMakeLists.txt
@@ -6,8 +6,8 @@
 #
 # I guess more things could be added, like checking whether variables are
 # defined after running the modules (e.g. FOO_FOUND etc.).
+cmake_minimum_required(VERSION 2.8.4) # new enough for CMP0017
 project(FindModulesExecuteAll)
-cmake_minimum_required(VERSION 2.7)
 
 file(GLOB all_modules "${CMAKE_CURRENT_SOURCE_DIR}/../../Modules/Find*cmake")
 
diff --git a/Tests/FindOpenMP/CMakeLists.txt b/Tests/FindOpenMP/CMakeLists.txt
new file mode 100644
index 0000000..e64885d
--- /dev/null
+++ b/Tests/FindOpenMP/CMakeLists.txt
@@ -0,0 +1,21 @@
+foreach(c C CXX Fortran)
+  if(CMake_TEST_FindOpenMP_${c})
+    set(CMake_TEST_FindOpenMP_FLAG_${c} 1)
+  else()
+    set(CMake_TEST_FindOpenMP_FLAG_${c} 0)
+  endif()
+endforeach()
+
+add_test(NAME FindOpenMP.Test COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindOpenMP/Test"
+  "${CMake_BINARY_DIR}/Tests/FindOpenMP/Test"
+  ${build_generator_args}
+  --build-project TestFindOpenMP
+  --build-options ${build_options}
+  -DOpenMP_TEST_C=${CMake_TEST_FindOpenMP_FLAG_C}
+  -DOpenMP_TEST_CXX=${CMake_TEST_FindOpenMP_FLAG_CXX}
+  -DOpenMP_TEST_Fortran=${CMake_TEST_FindOpenMP_FLAG_Fortran}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
diff --git a/Tests/FindOpenMP/Test/CMakeLists.txt b/Tests/FindOpenMP/Test/CMakeLists.txt
new file mode 100644
index 0000000..2692947
--- /dev/null
+++ b/Tests/FindOpenMP/Test/CMakeLists.txt
@@ -0,0 +1,69 @@
+cmake_minimum_required(VERSION 3.8)
+project(TestFindOpenMP NONE)
+include(CTest)
+
+macro(source_code_mapper_helper LANG_NAME SRC_FILE_NAME)
+  if("${LANG_NAME}" STREQUAL "C")
+    set(OpenMPTEST_SOURCE_FILE "${SRC_FILE_NAME}.c")
+  elseif("${LANG_NAME}" STREQUAL "CXX")
+    configure_file("${SRC_FILE_NAME}.c" "${SRC_FILE_NAME}.cxx" COPYONLY)
+    set(OpenMPTEST_SOURCE_FILE "${SRC_FILE_NAME}.cxx")
+  elseif("${LANG_NAME}" STREQUAL "Fortran")
+    set(OpenMPTEST_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/${SRC_FILE_NAME}.f90")
+    if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+      set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n      implicit none")
+    else()
+      set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n      include 'omp_lib.h'")
+    endif()
+    configure_file("${SRC_FILE_NAME}.f90.in" "${OpenMPTEST_SOURCE_FILE}" @ONLY)
+  endif()
+endmacro()
+
+foreach(c C CXX Fortran)
+  if("${OpenMP_TEST_${c}}")
+    message("Testing ${c}")
+    enable_language(${c})
+  endif()
+endforeach()
+
+find_package(OpenMP REQUIRED)
+
+foreach(c C CXX Fortran)
+  if(NOT "${OpenMP_TEST_${c}}")
+    continue()
+  endif()
+  source_code_mapper_helper(${c} main)
+  add_executable(test_tgt_${c} ${OpenMPTEST_SOURCE_FILE})
+  target_link_libraries(test_tgt_${c} PRIVATE OpenMP::OpenMP_${c})
+  set_property(TARGET test_tgt_${c} PROPERTY LINKER_LANGUAGE ${c})
+  add_test(NAME test_tgt_${c} COMMAND test_tgt_${c})
+
+  add_executable(test_var_${c} ${OpenMPTEST_SOURCE_FILE})
+  separate_arguments(_OpenMP_${c}_OPTIONS NATIVE_COMMAND "${OpenMP_${c}_FLAGS}")
+  target_compile_options(test_var_${c} PRIVATE "${_OpenMP_${c}_OPTIONS}")
+  target_link_libraries(test_var_${c} PRIVATE "${OpenMP_${c}_FLAGS}")
+  set_property(TARGET test_var_${c} PROPERTY LINKER_LANGUAGE ${c})
+  add_test(NAME test_var_${c} COMMAND test_var_${c})
+
+  source_code_mapper_helper(${c} scalprod)
+  add_library(scalprod_${c} STATIC ${OpenMPTEST_SOURCE_FILE})
+  target_link_libraries(scalprod_${c} PRIVATE OpenMP::OpenMP_${c})
+  set_property(TARGET scalprod_${c} PROPERTY LINKER_LANGUAGE ${c})
+endforeach()
+
+foreach(c C CXX Fortran)
+  if(NOT "${OpenMP_TEST_${c}}")
+    continue()
+  endif()
+  foreach(d C CXX Fortran)
+    if(NOT "${OpenMP_TEST_${d}}")
+      continue()
+    endif()
+    source_code_mapper_helper(${c} scaltest)
+    add_executable(scaltest_${c}_${d} ${OpenMPTEST_SOURCE_FILE})
+    target_link_libraries(scaltest_${c}_${d} PRIVATE scalprod_${d})
+    set_property(TARGET scaltest_${c}_${d} PROPERTY LINKER_LANGUAGE ${c})
+    add_test(NAME test_omp_${c}_${d} COMMAND scaltest_${c}_${d})
+    set_property(TEST test_omp_${c}_${d} PROPERTY PASS_REGULAR_EXPRESSION "^[ \t]*70\\.?0*")
+  endforeach()
+endforeach()
diff --git a/Tests/FindOpenMP/Test/main.c b/Tests/FindOpenMP/Test/main.c
new file mode 100644
index 0000000..4f0e874
--- /dev/null
+++ b/Tests/FindOpenMP/Test/main.c
@@ -0,0 +1,7 @@
+#include <omp.h>
+int main()
+{
+#ifndef _OPENMP
+  breaks_on_purpose
+#endif
+}
diff --git a/Tests/FindOpenMP/Test/main.f90.in b/Tests/FindOpenMP/Test/main.f90.in
new file mode 100644
index 0000000..9da22a1
--- /dev/null
+++ b/Tests/FindOpenMP/Test/main.f90.in
@@ -0,0 +1,5 @@
+      program test
+      @OpenMP_Fortran_INCLUDE_LINE@
+  !$  integer :: n
+      n = omp_get_num_threads()
+      end program test
diff --git a/Tests/FindOpenMP/Test/scalprod.c b/Tests/FindOpenMP/Test/scalprod.c
new file mode 100644
index 0000000..24c4587
--- /dev/null
+++ b/Tests/FindOpenMP/Test/scalprod.c
@@ -0,0 +1,16 @@
+#include <omp.h>
+
+#ifdef __cplusplus
+extern "C"
+#endif
+  void
+  scalprod(int n, double* x, double* y, double* res)
+{
+  int i;
+  double res_v = 0.;
+#pragma omp parallel for reduction(+ : res_v)
+  for (i = 0; i < n; ++i) {
+    res_v += x[i] * y[i];
+  }
+  *res = res_v;
+}
diff --git a/Tests/FindOpenMP/Test/scalprod.f90.in b/Tests/FindOpenMP/Test/scalprod.f90.in
new file mode 100644
index 0000000..efc7ea0
--- /dev/null
+++ b/Tests/FindOpenMP/Test/scalprod.f90.in
@@ -0,0 +1,19 @@
+subroutine scalprod(n, x_p, y_p, res) bind(c)
+    use iso_c_binding
+    implicit none
+    integer(c_int), intent(in), value :: n
+    type(c_ptr), intent(in), value :: x_p, y_p
+    real(c_double), pointer :: x(:), y(:)
+    integer :: i
+
+    real(c_double) :: res
+    real(c_double) :: scalpt = 0
+    call c_f_pointer(x_p, x, shape=[n])
+    call c_f_pointer(y_p, y, shape=[n])
+    res = 0
+!$omp parallel do private(scalpt), reduction(+:res)
+    do i=1,n
+        scalpt = y(i) * x(i)
+        res = res + scalpt
+    end do
+end subroutine scalprod
diff --git a/Tests/FindOpenMP/Test/scaltest.c b/Tests/FindOpenMP/Test/scaltest.c
new file mode 100644
index 0000000..2ee57f8
--- /dev/null
+++ b/Tests/FindOpenMP/Test/scaltest.c
@@ -0,0 +1,20 @@
+#ifdef __cplusplus
+#include <iostream>
+extern "C"
+#else
+#include <stdio.h>
+#endif
+int scalprod(int n, double* x, double* y, double* res);
+
+int main()
+{
+  double a[5] = { 1., 2., 3., 4., 5. };
+  double b[5] = { 2., 3., 4., 5., 6. };
+  double rk;
+  scalprod(5, a, b, &rk);
+#ifdef __cplusplus
+  std::cout << rk << std::endl;
+#else
+  printf("%f\n", rk);
+#endif
+}
diff --git a/Tests/FindOpenMP/Test/scaltest.f90.in b/Tests/FindOpenMP/Test/scaltest.f90.in
new file mode 100644
index 0000000..64c20d2
--- /dev/null
+++ b/Tests/FindOpenMP/Test/scaltest.f90.in
@@ -0,0 +1,21 @@
+program scaltest
+    use iso_c_binding
+    implicit none
+    interface
+        subroutine scalprod(n, x_p, y_p, res) bind(c)
+            use iso_c_binding
+            integer(c_int), value :: n
+            type(c_ptr), value :: x_p, y_p
+            real(c_double) :: res
+        end subroutine scalprod
+    end interface
+    type(c_ptr) :: x_pt, y_pt
+    real(c_double), dimension(5), target :: a = (/ 1, 2, 3, 4, 5 /)
+    real(c_double), dimension(5), target :: b = (/ 2, 3, 4, 5, 6 /)
+    integer(c_int) :: n = size(a)
+    real(c_double) :: res
+    x_pt = c_loc(a)
+    y_pt = c_loc(b)
+    call scalprod(n, x_pt, y_pt, res)
+    print *, res
+end program scaltest
diff --git a/Tests/FindProtobuf/CMakeLists.txt b/Tests/FindProtobuf/CMakeLists.txt
new file mode 100644
index 0000000..1cdb2ae
--- /dev/null
+++ b/Tests/FindProtobuf/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindProtobuf.Test COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindProtobuf/Test"
+  "${CMake_BINARY_DIR}/Tests/FindProtobuf/Test"
+  ${build_generator_args}
+  --build-project TestFindProtobuf
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
diff --git a/Tests/FindProtobuf/Test/CMakeLists.txt b/Tests/FindProtobuf/Test/CMakeLists.txt
new file mode 100644
index 0000000..8b6e38a
--- /dev/null
+++ b/Tests/FindProtobuf/Test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.4)
+project(TestFindProtobuf CXX)
+include(CTest)
+
+find_package(Protobuf REQUIRED)
+
+add_executable(test_tgt main.cxx)
+target_link_libraries(test_tgt protobuf::libprotobuf)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.cxx)
+target_include_directories(test_var PRIVATE ${Protobuf_INCLUDE_DIRS})
+target_link_libraries(test_var PRIVATE ${Protobuf_LIBRARIES})
+add_test(NAME test_var COMMAND test_var)
+
+add_executable(test_tgt_lite main.cxx)
+target_link_libraries(test_tgt_lite protobuf::libprotobuf-lite)
+add_test(NAME test_tgt_lite COMMAND test_tgt_lite)
+
+add_executable(test_var_lite main.cxx)
+target_include_directories(test_var_lite PRIVATE ${Protobuf_INCLUDE_DIRS})
+target_link_libraries(test_var_lite PRIVATE ${Protobuf_LITE_LIBRARIES})
+add_test(NAME test_var_lite COMMAND test_var_lite)
+
+add_executable(test_tgt_protoc main-protoc.cxx)
+target_link_libraries(test_tgt_protoc protobuf::libprotoc)
+add_test(NAME test_tgt_protoc COMMAND test_tgt_protoc)
+
+add_executable(test_var_protoc main-protoc.cxx)
+target_include_directories(test_var_protoc PRIVATE ${Protobuf_INCLUDE_DIRS})
+target_link_libraries(test_var_protoc PRIVATE ${Protobuf_PROTOC_LIBRARIES})
+add_test(NAME test_var_protoc COMMAND test_var_protoc)
diff --git a/Tests/FindProtobuf/Test/main-protoc.cxx b/Tests/FindProtobuf/Test/main-protoc.cxx
new file mode 100644
index 0000000..64e5ada
--- /dev/null
+++ b/Tests/FindProtobuf/Test/main-protoc.cxx
@@ -0,0 +1,8 @@
+#include <google/protobuf/compiler/command_line_interface.h>
+
+int main()
+{
+  google::protobuf::compiler::CommandLineInterface();
+
+  return 0;
+}
diff --git a/Tests/FindProtobuf/Test/main.cxx b/Tests/FindProtobuf/Test/main.cxx
new file mode 100644
index 0000000..87d5c12
--- /dev/null
+++ b/Tests/FindProtobuf/Test/main.cxx
@@ -0,0 +1,8 @@
+#include <google/protobuf/stubs/common.h>
+
+int main()
+{
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  return 0;
+}
diff --git a/Tests/FindTIFF/Test/CMakeLists.txt b/Tests/FindTIFF/Test/CMakeLists.txt
index 6985e3f..85453ed 100644
--- a/Tests/FindTIFF/Test/CMakeLists.txt
+++ b/Tests/FindTIFF/Test/CMakeLists.txt
@@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.1)
 project(TestFindTIFF C)
 include(CTest)
 
-# CMake does not actually provide FindTIFF publicly.
-set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Modules)
-
 find_package(TIFF REQUIRED)
 
 add_executable(test_tiff_tgt main.c)
diff --git a/Tests/FindXalanC/Test/CMakeLists.txt b/Tests/FindXalanC/Test/CMakeLists.txt
index b445e0e..a8c2a0a 100644
--- a/Tests/FindXalanC/Test/CMakeLists.txt
+++ b/Tests/FindXalanC/Test/CMakeLists.txt
@@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.1)
 project(TestFindXalanC CXX)
 include(CTest)
 
-# CMake does not actually provide FindXalanC publicly.
-set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Modules)
-
 find_package(XalanC REQUIRED)
 
 add_executable(test_xalanc_tgt main.cxx)
diff --git a/Tests/FindXercesC/Test/CMakeLists.txt b/Tests/FindXercesC/Test/CMakeLists.txt
index 8e7767c..267c6a9 100644
--- a/Tests/FindXercesC/Test/CMakeLists.txt
+++ b/Tests/FindXercesC/Test/CMakeLists.txt
@@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.1)
 project(TestFindXercesC CXX)
 include(CTest)
 
-# CMake does not actually provide FindXercesC publicly.
-set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Modules)
-
 find_package(XercesC REQUIRED)
 
 add_executable(test_xercesc_tgt main.cxx)
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index adc87cd..8ac3419 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -292,3 +292,19 @@ set(CMP0044_TYPE NEW)
 add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-NEW)
 set(CMP0044_TYPE OLD)
 add_subdirectory(CMP0044 ${CMAKE_BINARY_DIR}/CMP0044-OLD)
+
+if(NOT CMAKE_GENERATOR STREQUAL Xcode OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
+  add_library(objlib OBJECT objlib1.c objlib2.c)
+  file(GENERATE
+    OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/objlib_files_$<CONFIGURATION>"
+    CONTENT "$<JOIN:$<TARGET_OBJECTS:objlib>,\n>\n"
+  )
+
+  add_custom_target(check_object_files ALL
+    COMMAND ${CMAKE_COMMAND}
+      "-DOBJLIB_LISTFILE=${CMAKE_CURRENT_BINARY_DIR}/objlib_files_$<CONFIGURATION>"
+      -DEXPECTED_NUM_OBJECTFILES=2
+      -P "${CMAKE_CURRENT_SOURCE_DIR}/check_object_files.cmake"
+    DEPENDS objlib
+  )
+endif()
diff --git a/Tests/GeneratorExpression/check_object_files.cmake b/Tests/GeneratorExpression/check_object_files.cmake
new file mode 100644
index 0000000..cfccd29
--- /dev/null
+++ b/Tests/GeneratorExpression/check_object_files.cmake
@@ -0,0 +1,26 @@
+
+if (NOT EXISTS ${OBJLIB_LISTFILE})
+  message(SEND_ERROR "Object listing file \"${OBJLIB_LISTFILE}\" not found!")
+endif()
+
+file(STRINGS ${OBJLIB_LISTFILE} objlib_files ENCODING UTF-8)
+
+list(LENGTH objlib_files num_objectfiles)
+if (NOT EXPECTED_NUM_OBJECTFILES EQUAL num_objectfiles)
+  message(SEND_ERROR "Unexpected number of entries in object list file (${num_objectfiles} instead of ${EXPECTED_NUM_OBJECTFILES})")
+endif()
+
+foreach(objlib_file ${objlib_files})
+  set(file_exists False)
+  if (EXISTS ${objlib_file})
+    set(file_exists True)
+  endif()
+
+  if (NOT file_exists)
+    if(attempts)
+      list(REMOVE_DUPLICATES attempts)
+      set(tried "  Tried ${attempts}")
+    endif()
+    message(SEND_ERROR "File \"${objlib_file}\" does not exist!${tried}")
+  endif()
+endforeach()
diff --git a/Tests/GeneratorExpression/objlib1.c b/Tests/GeneratorExpression/objlib1.c
new file mode 100644
index 0000000..98a95a4
--- /dev/null
+++ b/Tests/GeneratorExpression/objlib1.c
@@ -0,0 +1,4 @@
+
+void objlib1()
+{
+}
diff --git a/Tests/GeneratorExpression/objlib2.c b/Tests/GeneratorExpression/objlib2.c
new file mode 100644
index 0000000..b2c1050
--- /dev/null
+++ b/Tests/GeneratorExpression/objlib2.c
@@ -0,0 +1,4 @@
+
+void objlib2()
+{
+}
diff --git a/Tests/GoogleTest/CMakeLists.txt b/Tests/GoogleTest/CMakeLists.txt
new file mode 100644
index 0000000..21f8b8b
--- /dev/null
+++ b/Tests/GoogleTest/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME GoogleTest.Test COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/GoogleTest/Test"
+  "${CMake_BINARY_DIR}/Tests/GoogleTest/Test"
+  ${build_generator_args}
+  --build-project TestGoogleTest
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
diff --git a/Tests/GoogleTest/Test/CMakeLists.txt b/Tests/GoogleTest/Test/CMakeLists.txt
new file mode 100644
index 0000000..f798d31
--- /dev/null
+++ b/Tests/GoogleTest/Test/CMakeLists.txt
@@ -0,0 +1,95 @@
+cmake_minimum_required(VERSION 3.8)
+project(TestGoogleTest)
+include(CTest)
+
+include(GoogleTest)
+
+find_package(GTest REQUIRED)
+
+add_executable(test_gtest1 main1.cxx)
+target_link_libraries(test_gtest1 GTest::GTest)
+
+# Simple test of defaults
+gtest_add_tests(TARGET test_gtest1
+  TEST_LIST testList
+)
+set(expectedTests
+  GoogleTest.LinksAndRuns
+  GoogleTest.ConditionalFail
+)
+if(NOT testList STREQUAL "${expectedTests}")
+  message(FATAL_ERROR "Expected test list: ${expectedTests}
+Actual test list: ${testList}")
+endif()
+
+
+# Same target, different arguments, so use test prefix and suffix to
+# differentiate from the above test cases
+gtest_add_tests(TARGET test_gtest1
+  TEST_LIST testList
+  TEST_PREFIX "set2."
+  TEST_SUFFIX ".foo"
+  EXTRA_ARGS  --forceFail
+)
+
+set(expectedTests
+  set2.GoogleTest.LinksAndRuns.foo
+  set2.GoogleTest.ConditionalFail.foo
+)
+if(NOT testList STREQUAL "${expectedTests}")
+  message(FATAL_ERROR "Expected test list: ${expectedTests}
+Actual test list: ${testList}")
+endif()
+
+set_tests_properties(set2.GoogleTest.ConditionalFail.foo PROPERTIES WILL_FAIL YES)
+
+
+# Search specific sources to get the test list
+add_executable(test_gtest2 main2.cxx)
+target_link_libraries(test_gtest2 GTest::Main)
+gtest_add_tests(TARGET test_gtest2
+  TEST_LIST testList
+  SOURCES main2.h
+)
+set(expectedTests
+  GoogleTest.SomethingElse
+  GoogleTest.OffTest1
+  GoogleTest.OffTest2
+  GoogleTest.OffTest3
+)
+if(NOT testList STREQUAL "${expectedTests}")
+  message(FATAL_ERROR "Expected test list: ${expectedTests}
+Actual test list: ${testList}")
+endif()
+set(disabledTests
+  GoogleTest.OffTest1
+  GoogleTest.OffTest2
+  GoogleTest.OffTest3
+)
+foreach(T ${disabledTests})
+  get_test_property(${T} DISABLED testDisabled)
+  if(NOT testDisabled)
+    message(FATAL_ERROR "Test ${T} should be disabled but is not")
+  endif()
+endforeach()
+
+# Non-keyword form, auto-find sources
+add_executable(test_gtest3 main3.cxx)
+target_link_libraries(test_gtest3 GTest::Main)
+gtest_add_tests(test_gtest3 "" AUTO)
+if(NOT TEST GoogleTest.Foo)
+  message(FATAL_ERROR "Test case GoogleTest.Foo not defined")
+endif()
+if(NOT TEST GoogleTest.Bar)
+  message(FATAL_ERROR "Test case GoogleTest.Bar not defined")
+endif()
+
+
+# Non-keyword form, explicitly specified sources. Allows a non-target to be
+# given for the executable.
+add_executable(test_gtest4 main4.cxx)
+target_link_libraries(test_gtest4 GTest::Main)
+gtest_add_tests($<TARGET_FILE:test_gtest4> "" main4.h)
+if(NOT TEST GoogleTest.NoKeywords)
+  message(FATAL_ERROR "Test case GoogleTest.NoKeywords not defined")
+endif()
diff --git a/Tests/GoogleTest/Test/main1.cxx b/Tests/GoogleTest/Test/main1.cxx
new file mode 100644
index 0000000..03d604b
--- /dev/null
+++ b/Tests/GoogleTest/Test/main1.cxx
@@ -0,0 +1,30 @@
+#include <gtest/gtest.h>
+
+#include <string>
+
+namespace {
+bool shouldFail = false;
+}
+
+TEST(GoogleTest, LinksAndRuns)
+{
+  ASSERT_TRUE(true);
+}
+
+TEST(GoogleTest, ConditionalFail)
+{
+  ASSERT_FALSE(shouldFail);
+}
+
+int main(int argc, char* argv[])
+{
+  ::testing::InitGoogleTest(&argc, argv);
+
+  if (argc > 1) {
+    if (argv[1] != std::string("--forceFail")) {
+      throw "Unexpected argument";
+    }
+    shouldFail = true;
+  }
+  return RUN_ALL_TESTS();
+}
diff --git a/Tests/GoogleTest/Test/main2.cxx b/Tests/GoogleTest/Test/main2.cxx
new file mode 100644
index 0000000..05ffb4a
--- /dev/null
+++ b/Tests/GoogleTest/Test/main2.cxx
@@ -0,0 +1 @@
+#include "main2.h"
diff --git a/Tests/GoogleTest/Test/main2.h b/Tests/GoogleTest/Test/main2.h
new file mode 100644
index 0000000..7881c4f
--- /dev/null
+++ b/Tests/GoogleTest/Test/main2.h
@@ -0,0 +1,21 @@
+#include <gtest/gtest.h>
+
+TEST(GoogleTest, SomethingElse)
+{
+  ASSERT_TRUE(true);
+}
+
+TEST(GoogleTest, DISABLED_OffTest1)
+{
+  ASSERT_TRUE(true);
+}
+
+TEST(DISABLED_GoogleTest, OffTest2)
+{
+  ASSERT_TRUE(true);
+}
+
+TEST(DISABLED_GoogleTest, DISABLED_OffTest3)
+{
+  ASSERT_TRUE(true);
+}
diff --git a/Tests/GoogleTest/Test/main3.cxx b/Tests/GoogleTest/Test/main3.cxx
new file mode 100644
index 0000000..98ce13c
--- /dev/null
+++ b/Tests/GoogleTest/Test/main3.cxx
@@ -0,0 +1,11 @@
+#include <gtest/gtest.h>
+
+TEST(GoogleTest, Foo)
+{
+  ASSERT_TRUE(true);
+}
+
+TEST(GoogleTest, Bar)
+{
+  ASSERT_TRUE(true);
+}
diff --git a/Tests/GoogleTest/Test/main4.cxx b/Tests/GoogleTest/Test/main4.cxx
new file mode 100644
index 0000000..8023bc1
--- /dev/null
+++ b/Tests/GoogleTest/Test/main4.cxx
@@ -0,0 +1 @@
+#include "main4.h"
diff --git a/Tests/GoogleTest/Test/main4.h b/Tests/GoogleTest/Test/main4.h
new file mode 100644
index 0000000..19da12a
--- /dev/null
+++ b/Tests/GoogleTest/Test/main4.h
@@ -0,0 +1,6 @@
+#include <gtest/gtest.h>
+
+TEST(GoogleTest, NoKeywords)
+{
+  ASSERT_TRUE(true);
+}
diff --git a/Tests/JavaExportImport/BuildExport/CMakeLists.txt b/Tests/JavaExportImport/BuildExport/CMakeLists.txt
index 953f9d0..fa7e501 100644
--- a/Tests/JavaExportImport/BuildExport/CMakeLists.txt
+++ b/Tests/JavaExportImport/BuildExport/CMakeLists.txt
@@ -7,4 +7,7 @@ find_package(Java COMPONENTS Development)
 include(UseJava)
 
 add_jar(${PROJECT_NAME} Foo.java)
-export_jars(TARGETS ${PROJECT_NAME} FILE JavaBuildExportTestConfig.cmake)
+export_jars(
+  TARGETS ${PROJECT_NAME}
+  NAMESPACE foo::
+  FILE JavaBuildExportTestConfig.cmake)
diff --git a/Tests/JavaExportImport/Import/CMakeLists.txt b/Tests/JavaExportImport/Import/CMakeLists.txt
index 79a1447..13ec05d 100644
--- a/Tests/JavaExportImport/Import/CMakeLists.txt
+++ b/Tests/JavaExportImport/Import/CMakeLists.txt
@@ -11,4 +11,4 @@ find_package(JavaInstallExportTest REQUIRED)
 
 add_jar(${PROJECT_NAME}
   SOURCES Import.java
-  INCLUDE_JARS foo bar)
+  INCLUDE_JARS foo::foo bar::bar)
diff --git a/Tests/JavaExportImport/InstallExport/CMakeLists.txt b/Tests/JavaExportImport/InstallExport/CMakeLists.txt
index 0a9afd9..2923beb 100644
--- a/Tests/JavaExportImport/InstallExport/CMakeLists.txt
+++ b/Tests/JavaExportImport/InstallExport/CMakeLists.txt
@@ -10,5 +10,6 @@ add_jar(${PROJECT_NAME} Bar.java)
 install_jar(${PROJECT_NAME} DESTINATION share/java)
 install_jar_exports(
   TARGETS ${PROJECT_NAME}
+  NAMESPACE bar::
   FILE JavaInstallExportTestConfig.cmake
   DESTINATION share/cmake)
diff --git a/Tests/Module/CheckIPOSupported-C/CMakeLists.txt b/Tests/Module/CheckIPOSupported-C/CMakeLists.txt
new file mode 100644
index 0000000..607dcd3
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-C/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.8)
+project(CheckIPOSupported-C LANGUAGES C)
+
+cmake_policy(SET CMP0069 NEW)
+
+include(CheckIPOSupported)
+check_ipo_supported(RESULT ipo_supported)
+if(ipo_supported)
+  set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
+elseif(CMake_TEST_IPO_WORKS_C)
+  message(FATAL_ERROR "IPO expected to work")
+endif()
+
+add_library(foo foo.c)
+add_executable(CheckIPOSupported-C main.c)
+target_link_libraries(CheckIPOSupported-C PUBLIC foo)
+
+enable_testing()
+add_test(NAME CheckIPOSupported-C COMMAND CheckIPOSupported-C)
diff --git a/Tests/Module/CheckIPOSupported-C/foo.c b/Tests/Module/CheckIPOSupported-C/foo.c
new file mode 100644
index 0000000..1e56597
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-C/foo.c
@@ -0,0 +1,4 @@
+int foo()
+{
+  return 0x42;
+}
diff --git a/Tests/Module/CheckIPOSupported-C/main.c b/Tests/Module/CheckIPOSupported-C/main.c
new file mode 100644
index 0000000..99204ab
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-C/main.c
@@ -0,0 +1,9 @@
+int foo();
+
+int main()
+{
+  if (foo() == 0) {
+    return 1;
+  }
+  return 0;
+}
diff --git a/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt b/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt
new file mode 100644
index 0000000..2dede93
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-CXX/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.8)
+project(CheckIPOSupported-CXX LANGUAGES CXX)
+
+cmake_policy(SET CMP0069 NEW)
+
+include(CheckIPOSupported)
+check_ipo_supported(RESULT ipo_supported)
+if(ipo_supported)
+  set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
+elseif(CMake_TEST_IPO_WORKS_CXX)
+  message(FATAL_ERROR "IPO expected to work")
+endif()
+
+add_library(foo foo.cpp)
+add_executable(CheckIPOSupported-CXX main.cpp)
+target_link_libraries(CheckIPOSupported-CXX PUBLIC foo)
+
+enable_testing()
+add_test(NAME CheckIPOSupported-CXX COMMAND CheckIPOSupported-CXX)
diff --git a/Tests/Module/CheckIPOSupported-CXX/foo.cpp b/Tests/Module/CheckIPOSupported-CXX/foo.cpp
new file mode 100644
index 0000000..1e56597
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-CXX/foo.cpp
@@ -0,0 +1,4 @@
+int foo()
+{
+  return 0x42;
+}
diff --git a/Tests/Module/CheckIPOSupported-CXX/main.cpp b/Tests/Module/CheckIPOSupported-CXX/main.cpp
new file mode 100644
index 0000000..99204ab
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-CXX/main.cpp
@@ -0,0 +1,9 @@
+int foo();
+
+int main()
+{
+  if (foo() == 0) {
+    return 1;
+  }
+  return 0;
+}
diff --git a/Tests/Module/CheckIPOSupported-Fortran/CMakeLists.txt b/Tests/Module/CheckIPOSupported-Fortran/CMakeLists.txt
new file mode 100644
index 0000000..dee5c25
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-Fortran/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.8)
+project(CheckIPOSupported-Fortran LANGUAGES Fortran)
+
+cmake_policy(SET CMP0069 NEW)
+
+include(CheckIPOSupported)
+check_ipo_supported(RESULT ipo_supported)
+if(ipo_supported)
+  set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
+elseif(CMake_TEST_IPO_WORKS_Fortran)
+  message(FATAL_ERROR "IPO expected to work")
+endif()
+
+add_library(foo foo.f)
+add_executable(CheckIPOSupported-Fortran main.f)
+target_link_libraries(CheckIPOSupported-Fortran PUBLIC foo)
+
+enable_testing()
+add_test(NAME CheckIPOSupported-Fortran COMMAND CheckIPOSupported-Fortran)
diff --git a/Tests/Module/CheckIPOSupported-Fortran/foo.f b/Tests/Module/CheckIPOSupported-Fortran/foo.f
new file mode 100644
index 0000000..945d2d5
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-Fortran/foo.f
@@ -0,0 +1,2 @@
+	SUBROUTINE FOO
+	END
diff --git a/Tests/Module/CheckIPOSupported-Fortran/main.f b/Tests/Module/CheckIPOSupported-Fortran/main.f
new file mode 100644
index 0000000..9d1de9f
--- /dev/null
+++ b/Tests/Module/CheckIPOSupported-Fortran/main.f
@@ -0,0 +1,3 @@
+	PROGRAM BOO
+	CALL FOO()
+	END
diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
index 2657aeb..52d4613 100644
--- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
+++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt
@@ -48,7 +48,14 @@ macro(set_defines target true_defs false_defs)
   )
 endmacro()
 
+# Only run the compiler detection header test for compilers with
+# detailed features tables, not just meta-features
+
 if (CMAKE_C_COMPILE_FEATURES)
+  set(C_expected_features ${CMAKE_C_COMPILE_FEATURES})
+  list(FILTER C_expected_features EXCLUDE REGEX "^c_std_[0-9][0-9]")
+endif()
+if (C_expected_features)
   string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" COMPILER_VERSION_MAJOR "${CMAKE_C_COMPILER_VERSION}")
   string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" COMPILER_VERSION_MINOR "${CMAKE_C_COMPILER_VERSION}")
   string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" COMPILER_VERSION_PATCH "${CMAKE_C_COMPILER_VERSION}")
@@ -85,7 +92,11 @@ if (CMAKE_C_COMPILE_FEATURES)
   endif()
 endif()
 
-if (NOT CMAKE_CXX_COMPILE_FEATURES)
+if (CMAKE_CXX_COMPILE_FEATURES)
+  set(CXX_expected_features ${CMAKE_CXX_COMPILE_FEATURES})
+  list(FILTER CXX_expected_features EXCLUDE REGEX "^cxx_std_[0-9][0-9]")
+endif()
+if (NOT CXX_expected_features)
   file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp"
     "int main(int,char**) { return 0; }\n"
   )
diff --git a/Tests/Module/WriteCompilerDetectionHeader/main.cpp b/Tests/Module/WriteCompilerDetectionHeader/main.cpp
index 192094c..9979cba 100644
--- a/Tests/Module/WriteCompilerDetectionHeader/main.cpp
+++ b/Tests/Module/WriteCompilerDetectionHeader/main.cpp
@@ -8,6 +8,9 @@
 #error Expect no C features defined
 #endif
 
+TEST_STATIC_ASSERT(true);
+TEST_STATIC_ASSERT_MSG(true, "msg");
+
 int main()
 {
   return 0;
diff --git a/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp b/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp
index 1635091..d1f178f 100644
--- a/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp
+++ b/Tests/Module/WriteCompilerDetectionHeader/multi_files.cpp
@@ -8,6 +8,9 @@
 #error Expect no C features defined
 #endif
 
+MULTI_STATIC_ASSERT(true);
+MULTI_STATIC_ASSERT_MSG(true, "msg");
+
 int main()
 {
   return 0;
diff --git a/Tests/ModuleDefinition/CMakeLists.txt b/Tests/ModuleDefinition/CMakeLists.txt
index bfbb343..e49ebea 100644
--- a/Tests/ModuleDefinition/CMakeLists.txt
+++ b/Tests/ModuleDefinition/CMakeLists.txt
@@ -4,6 +4,8 @@ project(ModuleDefinition C)
 # Test .def file source recognition for DLLs.
 add_library(example_dll SHARED example_dll.c example_dll.def)
 
+add_library(split_dll SHARED split_dll.c split_dll_1.def split_dll_2.def)
+
 # Test generated .def file.
 add_custom_command(OUTPUT example_dll_gen.def
   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/example_dll_gen.def.in
@@ -24,7 +26,12 @@ endif()
 # Test .def file source recognition for EXEs.
 add_executable(example_exe example_exe.c example_exe.def)
 set_property(TARGET example_exe PROPERTY ENABLE_EXPORTS 1)
-target_link_libraries(example_exe example_dll example_dll_gen ${example_dll_2})
+target_link_libraries(example_exe
+  example_dll
+  example_dll_gen
+  ${example_dll_2}
+  split_dll
+  )
 
 # Test linking to the executable.
 add_library(example_mod_1 MODULE example_mod_1.c)
diff --git a/Tests/ModuleDefinition/example_exe.c b/Tests/ModuleDefinition/example_exe.c
index dff566f..8e86fc4 100644
--- a/Tests/ModuleDefinition/example_exe.c
+++ b/Tests/ModuleDefinition/example_exe.c
@@ -3,15 +3,19 @@ extern int __declspec(dllimport) example_dll_gen_function(void);
 #ifdef EXAMPLE_DLL_2
 extern int __declspec(dllimport) example_dll_2_function(void);
 #endif
+extern int __declspec(dllimport) split_dll_1(void);
+extern int __declspec(dllimport) split_dll_2(void);
+
 int example_exe_function(void)
 {
   return 0;
 }
+
 int main(void)
 {
   return example_dll_function() + example_dll_gen_function() +
 #ifdef EXAMPLE_DLL_2
     example_dll_2_function() +
 #endif
-    example_exe_function();
+    split_dll_1() + split_dll_2() + example_exe_function();
 }
diff --git a/Tests/ModuleDefinition/split_dll.c b/Tests/ModuleDefinition/split_dll.c
new file mode 100644
index 0000000..1546a2d
--- /dev/null
+++ b/Tests/ModuleDefinition/split_dll.c
@@ -0,0 +1,9 @@
+int split_dll_1(void)
+{
+  return 0;
+}
+
+int split_dll_2(void)
+{
+  return 0;
+}
diff --git a/Tests/ModuleDefinition/split_dll_1.def b/Tests/ModuleDefinition/split_dll_1.def
new file mode 100644
index 0000000..ced9f10
--- /dev/null
+++ b/Tests/ModuleDefinition/split_dll_1.def
@@ -0,0 +1,2 @@
+EXPORTS
+split_dll_1
diff --git a/Tests/ModuleDefinition/split_dll_2.def b/Tests/ModuleDefinition/split_dll_2.def
new file mode 100644
index 0000000..b072c50
--- /dev/null
+++ b/Tests/ModuleDefinition/split_dll_2.def
@@ -0,0 +1,2 @@
+EXPORTS
+split_dll_2
diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt
index e3476df..4bffd12 100644
--- a/Tests/ObjectLibrary/CMakeLists.txt
+++ b/Tests/ObjectLibrary/CMakeLists.txt
@@ -16,11 +16,7 @@ add_custom_command(TARGET UseCshared POST_BUILD COMMAND ${CMAKE_COMMAND} -P ${CM
 
 add_executable(UseCinternal main.c c.c $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>)
 
-if("${CMAKE_GENERATOR}" MATCHES "^Visual Studio (7|7 .NET 2003)$")
-  # VS 7 generators do not add objects as sources so we need a
-  # dummy object to convince the IDE to build the targets below.
-  set(dummy dummy.obj) # In MinGW: gcc -c dummy.c -o dummy.obj
-elseif("${CMAKE_GENERATOR}" MATCHES "Xcode")
+if("${CMAKE_GENERATOR}" MATCHES "Xcode")
   # Xcode does not seem to support targets without sources.
   set(dummy dummy.c)
 endif()
diff --git a/Tests/Plugin/CMakeLists.txt b/Tests/Plugin/CMakeLists.txt
index f52b479..9e2b4ab 100644
--- a/Tests/Plugin/CMakeLists.txt
+++ b/Tests/Plugin/CMakeLists.txt
@@ -2,6 +2,9 @@ cmake_minimum_required (VERSION 2.6)
 cmake_policy(SET CMP0054 NEW)
 project(Plugin)
 
+# We need proper C++98 support from the compiler
+set(CMAKE_CXX_STANDARD 98)
+
 # Test per-target output directory properties.
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${Plugin_BINARY_DIR}/bin)
 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${Plugin_BINARY_DIR}/lib/plugin)
@@ -25,9 +28,6 @@ include_directories(
   ${Plugin_SOURCE_DIR}/include
   )
 
-# We need proper C++98 support from the compiler
-set(CMAKE_CXX_STANDARD 98)
-
 # Those versions of the HP compiler that need a flag to get proper C++98
 # template support also need a flag to use the newer C++ library.
 if (CMAKE_CXX_COMPILER_ID STREQUAL HP AND
diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt
index 807a427..8c2cdc9 100644
--- a/Tests/Preprocess/CMakeLists.txt
+++ b/Tests/Preprocess/CMakeLists.txt
@@ -25,9 +25,6 @@ endif()
 if("${CMAKE_GENERATOR}" MATCHES "Watcom WMake")
   set(PP_WATCOM 1)
 endif()
-if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 7$")
-  set(PP_VS70 1)
-endif()
 if("${CMAKE_GENERATOR}" MATCHES "Visual Studio")
   set(PP_VS 1)
 endif()
@@ -46,14 +43,11 @@ endif()
 # must not have it escaped inside the configured header.
 set(STRING_EXTRA "")
 
-if(NOT BORLAND AND NOT PP_VS70)
-  # Borland, VS70 IDE: ;
+if(NOT BORLAND)
+  # Borland: ;
   # The Borland compiler will simply not accept a non-escaped semicolon
   # on the command line.  If it is escaped \; then the escape character
   # shows up in the preprocessing output too.
-  #
-  # The VS 7.0 IDE separates definitions on semicolons and commas with
-  # no regard for quotes.  Fortunately VS 7.1 and above are okay.
   set(SEMICOLON "\;")
 endif()
 
diff --git a/Tests/QtAutoUicInterface/CMakeLists.txt b/Tests/QtAutoUicInterface/CMakeLists.txt
index 70175fb..3ea1294 100644
--- a/Tests/QtAutoUicInterface/CMakeLists.txt
+++ b/Tests/QtAutoUicInterface/CMakeLists.txt
@@ -53,6 +53,12 @@ set_property(TARGET KI18n APPEND PROPERTY
 
 # END upstream
 
+if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
+set(INC_DIR "include_${CMAKE_BUILD_TYPE}" )
+else()
+set(INC_DIR "include" )
+endif()
+
 add_library(LibWidget libwidget.cpp)
 target_link_libraries(LibWidget KI18n ${QT_GUI_TARGET})
 set_property(TARGET LibWidget PROPERTY NO_KUIT_SEMANTIC ON)
@@ -64,6 +70,6 @@ target_link_libraries(MyWidget KI18n ${QT_GUI_TARGET})
 add_executable(QtAutoUicInterface main.cpp)
 target_compile_definitions(QtAutoUicInterface
   PRIVATE
-    UI_LIBWIDGET_H="${CMAKE_CURRENT_BINARY_DIR}/LibWidget_autogen/include/ui_libwidget.h"
-    UI_MYWIDGET_H="${CMAKE_CURRENT_BINARY_DIR}/MyWidget_autogen/include/ui_mywidget.h"
+    UI_LIBWIDGET_H="${CMAKE_CURRENT_BINARY_DIR}/LibWidget_autogen/${INC_DIR}/ui_libwidget.h"
+    UI_MYWIDGET_H="${CMAKE_CURRENT_BINARY_DIR}/MyWidget_autogen/${INC_DIR}/ui_mywidget.h"
 )
diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt
index 4b90ad8..073c5fd 100644
--- a/Tests/QtAutogen/CMakeLists.txt
+++ b/Tests/QtAutogen/CMakeLists.txt
@@ -46,26 +46,26 @@ endif()
 
 get_property(QT_COMPILE_FEATURES TARGET ${QT_QTCORE_TARGET} PROPERTY INTERFACE_COMPILE_FEATURES)
 
-# -- Test: AUTORCC
+# -- Test
 # RCC only
 add_executable(rccOnly rccOnly.cpp rccOnlyRes.qrc)
 set_property(TARGET rccOnly PROPERTY AUTORCC ON)
 target_link_libraries(rccOnly ${QT_QTCORE_TARGET})
 
-# -- Test: AUTORCC
+# -- Test
 # RCC empty
 add_executable(rccEmpty rccEmpty.cpp rccEmptyRes.qrc)
 set_property(TARGET rccEmpty PROPERTY AUTORCC ON)
 target_link_libraries(rccEmpty ${QT_QTCORE_TARGET})
 
-# -- Test: AUTOUIC
+# -- Test
 # UIC only
 qtx_wrap_cpp(uicOnlyMoc uicOnlySource/uiconly.h)
 add_executable(uicOnly uicOnlySource/uiconly.cpp ${uicOnlyMoc})
 set_property(TARGET uicOnly PROPERTY AUTOUIC ON)
 target_link_libraries(uicOnly ${QT_LIBRARIES})
 
-# -- Test: AUTOMOC, AUTORCC
+# -- Test
 # Add not_generated_file.qrc to the source list to get the file-level
 # dependency, but don't generate a c++ file from it.  Disable the AUTORCC
 # feature for this target.  This tests that qrc files in the sources don't
@@ -80,66 +80,134 @@ set_target_properties(no_link_language PROPERTIES AUTOMOC TRUE)
 target_compile_features(no_link_language PRIVATE ${QT_COMPILE_FEATURES})
 target_compile_features(empty PRIVATE ${QT_COMPILE_FEATURES})
 
-# -- Test: AUTORCC
+# -- Test
 # When a file listed in a .qrc file changes the target must be rebuilt
+set(timeformat "%Y%j%H%M%S")
+set(RCC_DEPENDS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/rccDepends")
+set(RCC_DEPENDS_BIN "${CMAKE_CURRENT_BINARY_DIR}/rccDepends")
+configure_file(${RCC_DEPENDS_SRC}/res1a.qrc.in ${RCC_DEPENDS_BIN}/res1.qrc COPYONLY)
+configure_file(${RCC_DEPENDS_SRC}/res2a.qrc.in ${RCC_DEPENDS_BIN}/res2.qrc.in COPYONLY)
 try_compile(RCC_DEPENDS
-  "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends"
-  "${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends"
-  autorcc_depends
-  CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+  "${RCC_DEPENDS_BIN}"
+  "${RCC_DEPENDS_SRC}"
+  rccDepends
+  CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+              "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
               "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}"
   OUTPUT_VARIABLE output
 )
 if (NOT RCC_DEPENDS)
-  message(SEND_ERROR "Initial build of autorcc_depends failed. Output: ${output}")
+  message(SEND_ERROR "Initial build of rccDepends failed. Output: ${output}")
 endif()
-
-file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends/info_file.txt" qrc_files)
-
-list(GET qrc_files 0 qrc_file1)
-
-set(timeformat "%Y%j%H%M%S")
-
-file(TIMESTAMP "${qrc_file1}" file1_before "${timeformat}")
-
+# Get name and timestamp of the output binary
+file(STRINGS "${RCC_DEPENDS_BIN}/target.txt" targetList)
+list(GET targetList 0 rccDependsBin)
+file(TIMESTAMP "${rccDependsBin}" timeBegin "${timeformat}")
+# Sleep, touch regular qrc input file, rebuild and compare timestamp
 execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change.
-execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends/res1/input.txt")
-
-execute_process(COMMAND "${CMAKE_COMMAND}" --build .
-  WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends"
-)
-
-file(TIMESTAMP "${qrc_file1}" file1_step1 "${timeformat}")
-
-if (NOT file1_step1 GREATER file1_before)
-  message(SEND_ERROR "file1 (${qrc_file1}) should have changed in the first step!")
+execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res1/input.txt")
+execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result)
+if (result)
+  message(SEND_ERROR "Second build of rccDepends failed.")
+endif()
+file(TIMESTAMP "${rccDependsBin}" timeStep1 "${timeformat}")
+if (NOT timeStep1 GREATER timeBegin)
+  message(SEND_ERROR "File (${rccDependsBin}) should have changed in the first step!")
+endif()
+# Sleep, update regular qrc file, rebuild and compare timestamp
+execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change.
+configure_file(${RCC_DEPENDS_SRC}/res1b.qrc.in ${RCC_DEPENDS_BIN}/res1.qrc COPYONLY)
+execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result)
+if (result)
+  message(SEND_ERROR "Third build of rccDepends failed.")
+endif()
+file(TIMESTAMP "${rccDependsBin}" timeStep2 "${timeformat}")
+if (NOT timeStep2 GREATER timeStep1)
+  message(SEND_ERROR "File (${rccDependsBin}) should have changed in the second step!")
+endif()
+# Sleep, touch regular qrc newly added input file, rebuild and compare timestamp
+execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change.
+execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res1/inputAdded.txt")
+execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result)
+if (result)
+  message(SEND_ERROR "Fourth build of rccDepends failed.")
+endif()
+file(TIMESTAMP "${rccDependsBin}" timeStep3 "${timeformat}")
+if (NOT timeStep3 GREATER timeStep2)
+  message(SEND_ERROR "File (${rccDependsBin}) should have changed in the third step!")
+endif()
+# Sleep, touch generated qrc input file, rebuild and compare timestamp
+execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change.
+execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res2/input.txt")
+execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result)
+if (result)
+  message(SEND_ERROR "Fifth build of rccDepends failed.")
+endif()
+file(TIMESTAMP "${rccDependsBin}" timeStep4 "${timeformat}")
+if (NOT timeStep4 GREATER timeStep3)
+  message(SEND_ERROR "File (${rccDependsBin}) should have changed in the fourth step!")
+endif()
+# Sleep, update generated qrc file, rebuild and compare timestamp
+execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change.
+configure_file(${RCC_DEPENDS_SRC}/res2b.qrc.in ${RCC_DEPENDS_BIN}/res2.qrc.in COPYONLY)
+execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result)
+if (result)
+  message(SEND_ERROR "Sixth build of rccDepends failed.")
 endif()
+file(TIMESTAMP "${rccDependsBin}" timeStep5 "${timeformat}")
+if (NOT timeStep5 GREATER timeStep4)
+  message(SEND_ERROR "File (${rccDependsBin}) should have changed in the fitfh step!")
+endif()
+# Sleep, touch generated qrc newly added input file, rebuild and compare timestamp
+execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change.
+execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res2/inputAdded.txt")
+execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result)
+if (result)
+  message(SEND_ERROR "Seventh build of rccDepends failed.")
+endif()
+file(TIMESTAMP "${rccDependsBin}" timeStep6 "${timeformat}")
+if (NOT timeStep6 GREATER timeStep5)
+  message(SEND_ERROR "File (${rccDependsBin}) should have changed in the sixth step!")
+endif()
+
 
-# -- Test: AUTOMOC
+# -- Test
 # Ensure a repeated build succeeds when a header containing a QObject changes
+set(timeformat "%Y%j%H%M%S")
+configure_file(mocRerun/test1a.h.in mocRerun/test1.h COPYONLY)
 try_compile(MOC_RERUN
-  "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun"
-  "${CMAKE_CURRENT_SOURCE_DIR}/automoc_rerun"
-  automoc_rerun
-  CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+  "${CMAKE_CURRENT_BINARY_DIR}/mocRerun"
+  "${CMAKE_CURRENT_SOURCE_DIR}/mocRerun"
+  mocRerun
+  CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+              "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
               "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}"
   OUTPUT_VARIABLE output
 )
 if (NOT MOC_RERUN)
-  message(SEND_ERROR "Initial build of automoc_rerun failed. Output: ${output}")
+  message(SEND_ERROR "Initial build of mocRerun failed. Output: ${output}")
 endif()
-
-configure_file(automoc_rerun/test1.h.in2 automoc_rerun/test1.h COPYONLY)
-
+# Get name and timestamp of the output binary
+file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/mocRerun/target1.txt" target1List)
+list(GET target1List 0 binFile)
+file(TIMESTAMP "${binFile}" timeBegin "${timeformat}")
+# Change file content and rebuild
+execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
+configure_file(mocRerun/test1b.h.in mocRerun/test1.h COPYONLY)
 execute_process(COMMAND "${CMAKE_COMMAND}" --build .
-  WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun"
-  RESULT_VARIABLE automoc_rerun_result
+  WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocRerun"
+  RESULT_VARIABLE mocRerun_result
   )
-if (automoc_rerun_result)
-  message(SEND_ERROR "Second build of automoc_rerun failed.")
+if (mocRerun_result)
+  message(SEND_ERROR "Second build of mocRerun failed.")
+endif()
+# Compare timestamps
+file(TIMESTAMP "${binFile}" timeStep1 "${timeformat}")
+if (NOT timeStep1 GREATER timeBegin)
+  message(SEND_ERROR "File (${binFile}) should have changed in the first step!")
 endif()
 
-# -- Test: AUTOMOC, SKIP_AUTOMOC
+# -- Test
 # Test for SKIP_AUTOMOC and SKIP_AUTOGEN on an AUTOMOC enabled target
 qtx_wrap_cpp(skipMocWrapMoc
   skipSource/qItemA.hpp
@@ -161,7 +229,7 @@ set_property(TARGET skipMocB PROPERTY AUTOMOC ON)
 set_property(TARGET skipMocB PROPERTY AUTOUIC ON)
 target_link_libraries(skipMocB ${QT_LIBRARIES})
 
-# -- Test: AUTOUIC, SKIP_AUTOUIC
+# -- Test
 # Test for SKIP_AUTOUIC and SKIP_AUTOGEN on an AUTOUIC enabled target
 set(skipUicSources
   skipUic.cpp
@@ -181,7 +249,7 @@ set_property(TARGET skipUicB PROPERTY AUTOUIC ON)
 set_property(TARGET skipUicB PROPERTY AUTOMOC ON)
 target_link_libraries(skipUicB ${QT_LIBRARIES})
 
-# -- Test: AUTORCC, SKIP_AUTORCC
+# -- Test
 # Test for SKIP_AUTORCC and SKIP_AUTOGEN on an AUTORCC enabled target
 set(skipRccSources
   skipRcc.cpp
@@ -202,10 +270,96 @@ set_property(TARGET skipRccB PROPERTY AUTOUIC ON)
 set_property(TARGET skipRccB PROPERTY AUTOMOC ON)
 target_link_libraries(skipRccB ${QT_LIBRARIES})
 
-# -- Test: AUTOMOC AUTORCC
+# -- Test
 # Source files with the same basename in different subdirectories
 add_subdirectory(sameName)
 
-# -- Test: AUTOMOC AUTORCC AUTOUIC
+# -- Test
+# Tests AUTOMOC with generated sources
+add_subdirectory(mocDepends)
+
+# -- Test
+# Tests various include moc patterns
+add_subdirectory(mocIncludeStrict)
+
+# -- Test
+# Tests various include moc patterns
+add_subdirectory(mocIncludeRelaxed)
+
+# -- Test
+# Tests Q_PLUGIN_METADATA json file change detection
+if (NOT QT_TEST_VERSION STREQUAL 4)
+  try_compile(MOC_PLUGIN
+    "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin"
+    "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin"
+    mocPlugin
+    CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+                "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}"
+    OUTPUT_VARIABLE output
+  )
+  if (NOT MOC_PLUGIN)
+    message(SEND_ERROR "Initial build of mocPlugin failed. Output: ${output}")
+  endif()
+
+  set(timeformat "%Y%j%H%M%S")
+  set(mocPlugSrcDir "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin")
+  set(mocPlugBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin")
+  find_library(plAFile "PlugA" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH)
+  find_library(plBFile "PlugB" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH)
+  find_library(plCFile "PlugC" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH)
+  find_library(plDFile "PlugD" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH)
+
+  file(TIMESTAMP "${plAFile}" plABefore "${timeformat}")
+  file(TIMESTAMP "${plBFile}" plBBefore "${timeformat}")
+  file(TIMESTAMP "${plCFile}" plCBefore "${timeformat}")
+  file(TIMESTAMP "${plDFile}" plDBefore "${timeformat}")
+
+  # Ensure that the timestamp will change and change the json files
+  execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
+  configure_file("${mocPlugSrcDir}/jsonIn/StyleD.json" "${mocPlugBinDir}/jsonFiles/StyleC.json")
+  configure_file("${mocPlugSrcDir}/jsonIn/StyleC.json" "${mocPlugBinDir}/jsonFiles/sub/StyleD.json")
+  execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPlugBinDir}")
+
+  file(TIMESTAMP "${plAFile}" plAAfter "${timeformat}")
+  file(TIMESTAMP "${plBFile}" plBAfter "${timeformat}")
+  file(TIMESTAMP "${plCFile}" plCAfter "${timeformat}")
+  file(TIMESTAMP "${plDFile}" plDAfter "${timeformat}")
+
+  if (plAAfter GREATER plABefore)
+    message(SEND_ERROR "file (${plAFile}) should not have changed!")
+  endif()
+  if (plBAfter GREATER plBBefore)
+    message(SEND_ERROR "file (${plBFile}) should not have changed!")
+  endif()
+  if (NOT plCAfter GREATER plCBefore)
+    message(SEND_ERROR "file (${plCFile}) should have changed!")
+  endif()
+  if (NOT plDAfter GREATER plDBefore)
+    message(SEND_ERROR "file (${plDFile}) should have changed!")
+  endif()
+
+  # Test custom macro
+  file(TIMESTAMP "${plCFile}" plCBefore "${timeformat}")
+  file(TIMESTAMP "${plDFile}" plDBefore "${timeformat}")
+  execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
+  configure_file("${mocPlugSrcDir}/jsonIn/StyleD.json" "${mocPlugBinDir}/jsonFiles/StyleC_Custom.json")
+  configure_file("${mocPlugSrcDir}/jsonIn/StyleC.json" "${mocPlugBinDir}/jsonFiles/sub/StyleD_Custom.json")
+  execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPlugBinDir}")
+  file(TIMESTAMP "${plCFile}" plCAfter "${timeformat}")
+  file(TIMESTAMP "${plDFile}" plDAfter "${timeformat}")
+  if (NOT plCAfter GREATER plCBefore)
+    message(SEND_ERROR "file (${plCFile}) should have changed!")
+  endif()
+  if (NOT plDAfter GREATER plDBefore)
+    message(SEND_ERROR "file (${plDFile}) should have changed!")
+  endif()
+
+endif()
+
+# -- Test
+# Tests various .ui include directories
+add_subdirectory(uicInclude)
+
+# -- Test
 # Complex test case
 add_subdirectory(complex)
diff --git a/Tests/QtAutogen/automoc_rerun/CMakeLists.txt b/Tests/QtAutogen/automoc_rerun/CMakeLists.txt
deleted file mode 100644
index 92a682b..0000000
--- a/Tests/QtAutogen/automoc_rerun/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-cmake_minimum_required(VERSION 3.7)
-project(automoc_rerun CXX)
-
-if (QT_TEST_VERSION STREQUAL 4)
-  find_package(Qt4 REQUIRED)
-  set(QT_CORE_TARGET Qt4::QtCore)
-else()
-  if (NOT QT_TEST_VERSION STREQUAL 5)
-    message(SEND_ERROR "Invalid Qt version specified.")
-  endif()
-
-  find_package(Qt5Core REQUIRED)
-  set(QT_CORE_TARGET Qt5::Core)
-endif()
-
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
-
-configure_file(test1.h.in1 test1.h COPYONLY)
-
-add_executable(test1
-  ${CMAKE_CURRENT_BINARY_DIR}/test1.h
-  test1.cpp
-  res1.qrc
-  )
-target_include_directories(test1 PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
-target_link_libraries(test1 ${QT_CORE_TARGET})
diff --git a/Tests/QtAutogen/automoc_rerun/test1.cpp b/Tests/QtAutogen/automoc_rerun/test1.cpp
deleted file mode 100644
index 4316a91..0000000
--- a/Tests/QtAutogen/automoc_rerun/test1.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "test1.h"
-int main()
-{
-  return 0;
-}
diff --git a/Tests/QtAutogen/automoc_rerun/test1.h.in1 b/Tests/QtAutogen/automoc_rerun/test1.h.in1
deleted file mode 100644
index fee2c09..0000000
--- a/Tests/QtAutogen/automoc_rerun/test1.h.in1
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <QObject>
-class test1 : public QObject
-{
-  Q_OBJECT
- public slots:
-   void onTst1() {}
-   void onTst2() {}
-};
diff --git a/Tests/QtAutogen/automoc_rerun/test1.h.in2 b/Tests/QtAutogen/automoc_rerun/test1.h.in2
deleted file mode 100644
index 6531d10..0000000
--- a/Tests/QtAutogen/automoc_rerun/test1.h.in2
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <QObject>
-class test1 : public QObject
-{
-  Q_OBJECT
- public slots:
-   void onTst1() {}
-};
diff --git a/Tests/QtAutogen/autorcc_depends/CMakeLists.txt b/Tests/QtAutogen/autorcc_depends/CMakeLists.txt
deleted file mode 100644
index 7b51e11..0000000
--- a/Tests/QtAutogen/autorcc_depends/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-cmake_minimum_required(VERSION 3.7)
-project(autorcc_depends)
-
-set(CMAKE_AUTORCC ON)
-
-if (QT_TEST_VERSION STREQUAL 4)
-  find_package(Qt4 REQUIRED)
-  set(QT_CORE_TARGET Qt4::QtCore)
-else()
-  if (NOT QT_TEST_VERSION STREQUAL 5)
-    message(SEND_ERROR "Invalid Qt version specified.")
-  endif()
-
-  find_package(Qt5Core REQUIRED)
-  set(QT_CORE_TARGET Qt5::Core)
-endif()
-
-configure_file(res1.qrc.in res1.qrc @ONLY)
-configure_file(res1/input.txt.in res1/input.txt @ONLY)
-
-add_executable(test_res1
-  test_res1.cpp
-  ${CMAKE_CURRENT_BINARY_DIR}/res1.qrc
-)
-target_link_libraries(test_res1 ${QT_CORE_TARGET})
-add_custom_command(TARGET test_res1 POST_BUILD COMMAND
-  ${CMAKE_COMMAND} -E echo "$<TARGET_FILE:test_res1>" > info_file.txt)
diff --git a/Tests/QtAutogen/autorcc_depends/res1.qrc.in b/Tests/QtAutogen/autorcc_depends/res1.qrc.in
deleted file mode 100644
index 2a5417b..0000000
--- a/Tests/QtAutogen/autorcc_depends/res1.qrc.in
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
-    <qresource prefix="/">
-        <file>res1/input.txt</file>
-    </qresource>
-</RCC>
diff --git a/Tests/QtAutogen/mocDepends/CMakeLists.txt b/Tests/QtAutogen/mocDepends/CMakeLists.txt
new file mode 100644
index 0000000..a67dcfe
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/CMakeLists.txt
@@ -0,0 +1,47 @@
+cmake_minimum_required(VERSION 3.7)
+project(mocDepends)
+
+if (QT_TEST_VERSION STREQUAL 4)
+  find_package(Qt4 REQUIRED)
+  set(QT_CORE_TARGET Qt4::QtCore)
+else()
+  if (NOT QT_TEST_VERSION STREQUAL 5)
+    message(SEND_ERROR "Invalid Qt version specified.")
+  endif()
+
+  find_package(Qt5Core REQUIRED)
+  set(QT_CORE_TARGET Qt5::Core)
+endif()
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+# -- Test 1 using generated header
+# This tests the dependency of AUTOMOC of mocDepends1 to the generated object.hpp
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/object.hpp
+                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/object.hpp
+                   COMMAND ${CMAKE_COMMAND} -E sleep 3
+                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/object.hpp
+                   )
+
+add_executable(mocDepends1 test1.cpp
+  ${CMAKE_CURRENT_BINARY_DIR}/object.hpp
+)
+target_link_libraries(mocDepends1 ${QT_CORE_TARGET})
+set_target_properties(mocDepends1 PROPERTIES AUTOMOC TRUE)
+set_property(TARGET mocDepends1 PROPERTY __UNDOCUMENTED_AUTOGEN_GENERATED_FILES 1)
+
+# -- Test 2 using generated library
+# This tests the dependency of AUTOMOC of mocDepends2 to the
+# generated simpleLib.hpp which belongs to a linked library of mocDepends2
+add_custom_command(OUTPUT simpleLib.hpp simpleLib.cpp
+                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp
+                   COMMAND ${CMAKE_COMMAND} -E sleep 3
+                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp
+                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp
+                   )
+add_library(SimpleLib STATIC simpleLib.hpp simpleLib.cpp)
+
+add_executable(mocDepends2 test2.cpp )
+target_link_libraries(mocDepends2 SimpleLib ${QT_CORE_TARGET})
+set_target_properties(mocDepends2 PROPERTIES AUTOMOC TRUE)
+set_property(TARGET mocDepends2 PROPERTY __UNDOCUMENTED_AUTOGEN_GENERATED_FILES 1)
diff --git a/Tests/QtAutogen/mocDepends/invalid.hpp.in b/Tests/QtAutogen/mocDepends/invalid.hpp.in
new file mode 100644
index 0000000..854d9a1
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/invalid.hpp.in
@@ -0,0 +1 @@
+#ifndef
diff --git a/Tests/QtAutogen/mocDepends/object.hpp.in b/Tests/QtAutogen/mocDepends/object.hpp.in
new file mode 100644
index 0000000..f364f7c
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/object.hpp.in
@@ -0,0 +1,14 @@
+#ifndef OBJECT_HPP
+#define OBJECT_HPP
+
+#include <QObject>
+
+class Object : public QObject
+{
+  Q_OBJECT
+public:
+  Q_SLOT
+  void aSlot(){};
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocDepends/simpleLib.cpp.in b/Tests/QtAutogen/mocDepends/simpleLib.cpp.in
new file mode 100644
index 0000000..fa33bd3
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/simpleLib.cpp.in
@@ -0,0 +1,9 @@
+#include "simpleLib.hpp"
+
+SimpleLib::SimpleLib()
+{
+}
+
+SimpleLib::~SimpleLib()
+{
+}
diff --git a/Tests/QtAutogen/mocDepends/simpleLib.hpp.in b/Tests/QtAutogen/mocDepends/simpleLib.hpp.in
new file mode 100644
index 0000000..758f1f6
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/simpleLib.hpp.in
@@ -0,0 +1,11 @@
+#ifndef SIMPLE_LIB_H
+#define SIMPLE_LIB_H
+
+class SimpleLib
+{
+public:
+  SimpleLib();
+  ~SimpleLib();
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocDepends/test1.cpp b/Tests/QtAutogen/mocDepends/test1.cpp
new file mode 100644
index 0000000..92c259c
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/test1.cpp
@@ -0,0 +1,9 @@
+
+#include "object.hpp"
+
+int main()
+{
+  Object obj;
+
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocDepends/test2.cpp b/Tests/QtAutogen/mocDepends/test2.cpp
new file mode 100644
index 0000000..155b19b
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/test2.cpp
@@ -0,0 +1,10 @@
+
+#include "test2.hpp"
+
+int main()
+{
+  SimpleLib obj;
+  LObject lobject;
+
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocDepends/test2.hpp b/Tests/QtAutogen/mocDepends/test2.hpp
new file mode 100644
index 0000000..0125f07
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/test2.hpp
@@ -0,0 +1,16 @@
+#ifndef TEST2_HPP
+#define TEST2_HPP
+
+#include "simpleLib.hpp"
+#include <QObject>
+
+// This object triggers the AUTOMOC on this file
+class LObject : public QObject
+{
+  Q_OBJECT
+public:
+  Q_SLOT
+  void aSlot(){};
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/ObjA.cpp b/Tests/QtAutogen/mocInclude/ObjA.cpp
new file mode 100644
index 0000000..1b0311d
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjA.cpp
@@ -0,0 +1,24 @@
+#include "ObjA.hpp"
+
+class SubObjA : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjA() {}
+  ~SubObjA() {}
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjA::aSlot()
+{
+}
+
+void ObjA::go()
+{
+  SubObjA subObj;
+}
+
+#include "ObjA.moc"
diff --git a/Tests/QtAutogen/mocInclude/ObjA.hpp b/Tests/QtAutogen/mocInclude/ObjA.hpp
new file mode 100644
index 0000000..281e90d
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjA.hpp
@@ -0,0 +1,13 @@
+#ifndef OBJA_HPP
+#define OBJA_HPP
+
+#include <QObject>
+
+class ObjA : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/ObjB.cpp b/Tests/QtAutogen/mocInclude/ObjB.cpp
new file mode 100644
index 0000000..5ff315d
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjB.cpp
@@ -0,0 +1,25 @@
+#include "ObjB.hpp"
+
+class SubObjB : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjB() {}
+  ~SubObjB() {}
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjB::aSlot()
+{
+}
+
+void ObjB::go()
+{
+  SubObjB subObj;
+}
+
+#include "ObjB.moc"
+#include "moc_ObjB.cpp"
diff --git a/Tests/QtAutogen/mocInclude/ObjB.hpp b/Tests/QtAutogen/mocInclude/ObjB.hpp
new file mode 100644
index 0000000..94f3d49
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjB.hpp
@@ -0,0 +1,13 @@
+#ifndef OBJB_HPP
+#define OBJB_HPP
+
+#include <QObject>
+
+class ObjB : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/ObjC.cpp b/Tests/QtAutogen/mocInclude/ObjC.cpp
new file mode 100644
index 0000000..8ca34cb
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjC.cpp
@@ -0,0 +1,26 @@
+#include "ObjC.hpp"
+
+class SubObjC : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjC() {}
+  ~SubObjC() {}
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjC::aSlot()
+{
+}
+
+void ObjC::go()
+{
+  SubObjC subObj;
+}
+
+#include "ObjC.moc"
+// Not the own header
+#include "moc_ObjD.cpp"
diff --git a/Tests/QtAutogen/mocInclude/ObjC.hpp b/Tests/QtAutogen/mocInclude/ObjC.hpp
new file mode 100644
index 0000000..a8e98eb
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjC.hpp
@@ -0,0 +1,13 @@
+#ifndef OBJC_HPP
+#define OBJC_HPP
+
+#include <QObject>
+
+class ObjC : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/ObjD.cpp b/Tests/QtAutogen/mocInclude/ObjD.cpp
new file mode 100644
index 0000000..c18aec1
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjD.cpp
@@ -0,0 +1,26 @@
+#include "ObjD.hpp"
+
+class SubObjD : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjD() {}
+  ~SubObjD() {}
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjD::aSlot()
+{
+}
+
+void ObjD::go()
+{
+  SubObjD subObj;
+}
+
+#include "ObjD.moc"
+// Header in subdirectory
+#include "subA/moc_SubObjA.cpp"
diff --git a/Tests/QtAutogen/mocInclude/ObjD.hpp b/Tests/QtAutogen/mocInclude/ObjD.hpp
new file mode 100644
index 0000000..b6ee098
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjD.hpp
@@ -0,0 +1,13 @@
+#ifndef OBJD_HPP
+#define OBJD_HPP
+
+#include <QObject>
+
+class ObjD : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp
new file mode 100644
index 0000000..a05f6e3
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp
@@ -0,0 +1,27 @@
+#include "SubObjA.hpp"
+
+namespace subA {
+
+class SubObjA : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjA() {}
+  ~SubObjA() {}
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjA::aSlot()
+{
+}
+
+void ObjA::go()
+{
+  SubObjA subObj;
+}
+}
+
+#include "SubObjA.moc"
diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp
new file mode 100644
index 0000000..31a18b6
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp
@@ -0,0 +1,16 @@
+#ifndef SUBOBJA_HPP
+#define SUBOBJA_HPP
+
+#include <QObject>
+
+namespace subA {
+
+class ObjA : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+}
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp
new file mode 100644
index 0000000..1e77639
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp
@@ -0,0 +1,27 @@
+#include "SubObjB.hpp"
+
+namespace subB {
+
+class SubObjB : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjB() {}
+  ~SubObjB() {}
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjB::aSlot()
+{
+}
+
+void ObjB::go()
+{
+  SubObjB subObj;
+}
+}
+
+#include "SubObjB.moc"
diff --git a/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp
new file mode 100644
index 0000000..3f29fa2
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp
@@ -0,0 +1,16 @@
+#ifndef SUBOBJB_HPP
+#define SUBOBJB_HPP
+
+#include <QObject>
+
+namespace subB {
+
+class ObjB : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+}
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp
new file mode 100644
index 0000000..c2d94ef
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp
@@ -0,0 +1,27 @@
+#include "SubObjC.hpp"
+
+namespace subC {
+
+class SubObjC : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjC() {}
+  ~SubObjC() {}
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjC::aSlot()
+{
+}
+
+void ObjC::go()
+{
+  SubObjC subObj;
+}
+}
+
+#include "SubObjC.moc"
diff --git a/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp
new file mode 100644
index 0000000..dc251fd
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp
@@ -0,0 +1,16 @@
+#ifndef SUBOBJC_HPP
+#define SUBOBJC_HPP
+
+#include <QObject>
+
+namespace subC {
+
+class ObjC : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+}
+
+#endif
diff --git a/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt
new file mode 100644
index 0000000..6a0829d
--- /dev/null
+++ b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Test moc include patterns
+
+set(CMAKE_AUTOMOC_RELAXED_MODE TRUE)
+
+include_directories("../mocInclude")
+
+add_executable(mocIncludeRelaxed
+  ../mocInclude/ObjA.cpp
+  ../mocInclude/ObjB.cpp
+  ../mocInclude/ObjC.cpp
+  ../mocInclude/ObjD.cpp
+  ../mocInclude/subA/SubObjA.cpp
+  ../mocInclude/subB/SubObjB.cpp
+  ../mocInclude/subC/SubObjC.cpp
+  main.cpp
+)
+target_link_libraries(mocIncludeRelaxed ${QT_LIBRARIES})
+set_target_properties(mocIncludeRelaxed PROPERTIES AUTOMOC ON)
diff --git a/Tests/QtAutogen/mocIncludeRelaxed/main.cpp b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp
new file mode 100644
index 0000000..142d59e
--- /dev/null
+++ b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp
@@ -0,0 +1,14 @@
+#include "ObjA.hpp"
+#include "ObjB.hpp"
+#include "ObjC.hpp"
+
+int main(int argv, char** args)
+{
+  ObjA objA;
+  ObjB objB;
+  ObjC objC;
+  return 0;
+}
+
+// Header in global subdirectory
+#include "subB/moc_SubObjB.cpp"
diff --git a/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt
new file mode 100644
index 0000000..22e93a8
--- /dev/null
+++ b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Test moc include patterns
+
+set(CMAKE_AUTOMOC_RELAXED_MODE FALSE)
+
+include_directories("../mocInclude")
+
+add_executable(mocIncludeStrict
+  ../mocInclude/ObjA.cpp
+  ../mocInclude/ObjB.cpp
+  ../mocInclude/ObjC.cpp
+  ../mocInclude/ObjD.cpp
+  ../mocInclude/subA/SubObjA.cpp
+  ../mocInclude/subB/SubObjB.cpp
+  ../mocInclude/subC/SubObjC.cpp
+  main.cpp
+)
+target_link_libraries(mocIncludeStrict ${QT_LIBRARIES})
+set_target_properties(mocIncludeStrict PROPERTIES AUTOMOC ON)
diff --git a/Tests/QtAutogen/mocIncludeStrict/main.cpp b/Tests/QtAutogen/mocIncludeStrict/main.cpp
new file mode 100644
index 0000000..142d59e
--- /dev/null
+++ b/Tests/QtAutogen/mocIncludeStrict/main.cpp
@@ -0,0 +1,14 @@
+#include "ObjA.hpp"
+#include "ObjB.hpp"
+#include "ObjC.hpp"
+
+int main(int argv, char** args)
+{
+  ObjA objA;
+  ObjB objB;
+  ObjC objC;
+  return 0;
+}
+
+// Header in global subdirectory
+#include "subB/moc_SubObjB.cpp"
diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt
new file mode 100644
index 0000000..f80aa29
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.8)
+project(mocPlugin CXX)
+
+set(CMAKE_AUTOMOC_DEPEND_FILTERS
+  "A_CUSTOM_MACRO"
+  "[\n][ \t]*A_CUSTOM_MACRO[ \t\r\n]*\\([^,]+,[ \t\r\n]*\"([^\"]+)\""
+  )
+
+if (NOT QT_TEST_VERSION STREQUAL 5)
+  message(SEND_ERROR "Invalid Qt version specified.")
+endif()
+find_package(Qt5Widgets REQUIRED)
+
+if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC)
+  add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC})
+endif()
+
+configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json)
+configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json)
+configure_file(jsonIn/StyleC.json jsonFiles/StyleC_Custom.json)
+configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD_Custom.json)
+
+# Enable automoc
+set(CMAKE_AUTOMOC TRUE)
+
+include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles")
+link_libraries(Qt5::Widgets)
+
+add_library(PlugA STATIC StyleA.cpp)
+add_library(PlugB STATIC StyleB.cpp)
+add_library(PlugC STATIC StyleC.cpp)
+add_library(PlugD STATIC StyleD.cpp)
+add_library(PlugE STATIC StyleE.cpp)
diff --git a/Tests/QtAutogen/mocPlugin/StyleA.cpp b/Tests/QtAutogen/mocPlugin/StyleA.cpp
new file mode 100644
index 0000000..b5e8753
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleA.cpp
@@ -0,0 +1,6 @@
+#include "StyleA.hpp"
+
+QStyle* StyleA::create(const QString& key)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogen/mocPlugin/StyleA.hpp
new file mode 100644
index 0000000..1b6154d
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleA.hpp
@@ -0,0 +1,17 @@
+#ifndef STYLEA_HPP
+#define STYLEA_HPP
+
+#include "StyleCommon.hpp"
+#include <QStylePlugin>
+
+class StyleA : public QStylePlugin
+{
+  Q_OBJECT
+  // Json file in local directory
+  Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json")
+  A_CUSTOM_MACRO(SomeArg, "StyleA_Custom.json", AnotherArg)
+public:
+  QStyle* create(const QString& key);
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleA.json b/Tests/QtAutogen/mocPlugin/StyleA.json
new file mode 100644
index 0000000..cc33953
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleA.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "Starbuster" ] }
diff --git a/Tests/QtAutogen/mocPlugin/StyleA_Custom.json b/Tests/QtAutogen/mocPlugin/StyleA_Custom.json
new file mode 100644
index 0000000..cc33953
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleA_Custom.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "Starbuster" ] }
diff --git a/Tests/QtAutogen/mocPlugin/StyleB.cpp b/Tests/QtAutogen/mocPlugin/StyleB.cpp
new file mode 100644
index 0000000..17d4400
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleB.cpp
@@ -0,0 +1,6 @@
+#include "StyleB.hpp"
+
+QStyle* StyleB::create(const QString& key)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogen/mocPlugin/StyleB.hpp
new file mode 100644
index 0000000..163c9b2
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleB.hpp
@@ -0,0 +1,17 @@
+#ifndef STYLEB_HPP
+#define STYLEB_HPP
+
+#include "StyleCommon.hpp"
+#include <QStylePlugin>
+
+class StyleB : public QStylePlugin
+{
+  Q_OBJECT
+  // Json file in local subdirectory
+  Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json")
+  A_CUSTOM_MACRO(SomeArg, "jsonIn/StyleB_Custom.json", AnotherArg)
+public:
+  QStyle* create(const QString& key);
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleC.cpp b/Tests/QtAutogen/mocPlugin/StyleC.cpp
new file mode 100644
index 0000000..37e7564
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleC.cpp
@@ -0,0 +1,6 @@
+#include "StyleC.hpp"
+
+QStyle* StyleC::create(const QString& key)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogen/mocPlugin/StyleC.hpp
new file mode 100644
index 0000000..52a887a
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleC.hpp
@@ -0,0 +1,17 @@
+#ifndef STYLEC_HPP
+#define STYLEC_HPP
+
+#include "StyleCommon.hpp"
+#include <QStylePlugin>
+
+class StyleC : public QStylePlugin
+{
+  Q_OBJECT
+  // Json file in global root directory
+  Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json")
+  A_CUSTOM_MACRO(SomeArg, "StyleC_Custom.json", AnotherArg)
+public:
+  QStyle* create(const QString& key);
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleCommon.hpp b/Tests/QtAutogen/mocPlugin/StyleCommon.hpp
new file mode 100644
index 0000000..f1a7ec6
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleCommon.hpp
@@ -0,0 +1,7 @@
+#ifndef STYLECOMMON_HPP
+#define STYLECOMMON_HPP
+
+// Empty test macro definition
+#define A_CUSTOM_MACRO(name, jsonFile, pluginRegistrations)
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp
new file mode 100644
index 0000000..7e4b121
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp
@@ -0,0 +1,6 @@
+#include "StyleD.hpp"
+
+QStyle* StyleD::create(const QString& key)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp
new file mode 100644
index 0000000..df8a439
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp
@@ -0,0 +1,17 @@
+#ifndef STYLED_HPP
+#define STYLED_HPP
+
+#include "StyleCommon.hpp"
+#include <QStylePlugin>
+
+class StyleD : public QStylePlugin
+{
+  Q_OBJECT
+  // Json file in global sub director
+  Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json")
+  A_CUSTOM_MACRO(SomeArg, "sub/StyleD_Custom.json", AnotherArg)
+public:
+  QStyle* create(const QString& key);
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleE.cpp b/Tests/QtAutogen/mocPlugin/StyleE.cpp
new file mode 100644
index 0000000..8fc9a7f
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleE.cpp
@@ -0,0 +1,6 @@
+#include "StyleE.hpp"
+
+QStyle* StyleE::create(const QString& key)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogen/mocPlugin/StyleE.hpp
new file mode 100644
index 0000000..e7915a8
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleE.hpp
@@ -0,0 +1,17 @@
+#ifndef STYLEE_HPP
+#define STYLEE_HPP
+
+#include "StyleCommon.hpp"
+#include <QStylePlugin>
+
+class StyleE : public QStylePlugin
+{
+  Q_OBJECT
+  // No Json file
+  Q_PLUGIN_METADATA(IID "org.styles.E")
+  A_CUSTOM_MACRO(SomeArg, InvalidFileArg, AnotherArg)
+public:
+  QStyle* create(const QString& key);
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json
new file mode 100644
index 0000000..129cac4
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "StarbusterB" ] }
diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json
new file mode 100644
index 0000000..129cac4
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "StarbusterB" ] }
diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json
new file mode 100644
index 0000000..119aaa4
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json
@@ -0,0 +1 @@
+{ "Keys": [ "Boat", "Ship" ] }
diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json
new file mode 100644
index 0000000..732c547
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json
@@ -0,0 +1 @@
+{ "Keys": [ "Bike", "Car" ] }
diff --git a/Tests/QtAutogen/mocPlugin/main.cpp b/Tests/QtAutogen/mocPlugin/main.cpp
new file mode 100644
index 0000000..3ba2ddc
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/main.cpp
@@ -0,0 +1,6 @@
+#include "StyleA.hpp"
+
+int main(int argv, char** args)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocRerun/CMakeLists.txt b/Tests/QtAutogen/mocRerun/CMakeLists.txt
new file mode 100644
index 0000000..14b077b
--- /dev/null
+++ b/Tests/QtAutogen/mocRerun/CMakeLists.txt
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.7)
+project(mocRerun CXX)
+
+if (QT_TEST_VERSION STREQUAL 4)
+  find_package(Qt4 REQUIRED)
+  set(QT_CORE_TARGET Qt4::QtCore)
+else()
+  if (NOT QT_TEST_VERSION STREQUAL 5)
+    message(SEND_ERROR "Invalid Qt version specified.")
+  endif()
+
+  find_package(Qt5Core REQUIRED)
+  set(QT_CORE_TARGET Qt5::Core)
+endif()
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+# Generated source file
+add_custom_command(OUTPUT main.cpp
+                   COMMAND ${CMAKE_COMMAND} -E sleep 2
+                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
+                   )
+
+add_executable(mocRerun
+  ${CMAKE_CURRENT_BINARY_DIR}/test1.h
+  ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
+  res1.qrc
+  )
+set_property(TARGET mocRerun PROPERTY __UNDOCUMENTED_AUTOGEN_GENERATED_FILES 1)
+target_include_directories(mocRerun PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+target_link_libraries(mocRerun ${QT_CORE_TARGET})
+# Write target name to text file
+add_custom_command(TARGET mocRerun POST_BUILD COMMAND
+  ${CMAKE_COMMAND} -E echo "$<TARGET_FILE:mocRerun>" > target1.txt)
diff --git a/Tests/QtAutogen/automoc_rerun/input.txt b/Tests/QtAutogen/mocRerun/input.txt
similarity index 100%
rename from Tests/QtAutogen/automoc_rerun/input.txt
rename to Tests/QtAutogen/mocRerun/input.txt
diff --git a/Tests/QtAutogen/mocRerun/main.cpp.in b/Tests/QtAutogen/mocRerun/main.cpp.in
new file mode 100644
index 0000000..b37ff61
--- /dev/null
+++ b/Tests/QtAutogen/mocRerun/main.cpp.in
@@ -0,0 +1,18 @@
+#include "test1.h"
+
+class Test2 : public QObject
+{
+  Q_OBJECT
+public slots:
+  void onTst1() {}
+};
+
+int main()
+{
+  Test1 test1;
+  Test2 test2;
+
+  return 0;
+}
+
+#include "main.moc"
diff --git a/Tests/QtAutogen/automoc_rerun/res1.qrc b/Tests/QtAutogen/mocRerun/res1.qrc
similarity index 100%
rename from Tests/QtAutogen/automoc_rerun/res1.qrc
rename to Tests/QtAutogen/mocRerun/res1.qrc
diff --git a/Tests/QtAutogen/mocRerun/test1a.h.in b/Tests/QtAutogen/mocRerun/test1a.h.in
new file mode 100644
index 0000000..a335046
--- /dev/null
+++ b/Tests/QtAutogen/mocRerun/test1a.h.in
@@ -0,0 +1,8 @@
+#include <QObject>
+class Test1 : public QObject
+{
+  Q_OBJECT
+public slots:
+  void onTst1() {}
+  void onTst2() {}
+};
diff --git a/Tests/QtAutogen/mocRerun/test1b.h.in b/Tests/QtAutogen/mocRerun/test1b.h.in
new file mode 100644
index 0000000..6128eeb
--- /dev/null
+++ b/Tests/QtAutogen/mocRerun/test1b.h.in
@@ -0,0 +1,7 @@
+#include <QObject>
+class Test1 : public QObject
+{
+  Q_OBJECT
+public slots:
+  void onTst1() {}
+};
diff --git a/Tests/QtAutogen/rccDepends/CMakeLists.txt b/Tests/QtAutogen/rccDepends/CMakeLists.txt
new file mode 100644
index 0000000..878ae5d
--- /dev/null
+++ b/Tests/QtAutogen/rccDepends/CMakeLists.txt
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.7)
+project(rccDepends)
+
+set(CMAKE_AUTORCC ON)
+
+if (QT_TEST_VERSION STREQUAL 4)
+  find_package(Qt4 REQUIRED)
+  set(QT_CORE_TARGET Qt4::QtCore)
+else()
+  if (NOT QT_TEST_VERSION STREQUAL 5)
+    message(SEND_ERROR "Invalid Qt version specified.")
+  endif()
+
+  find_package(Qt5Core REQUIRED)
+  set(QT_CORE_TARGET Qt5::Core)
+endif()
+
+configure_file(res/input1.txt.in res1/input.txt COPYONLY)
+configure_file(res/input1.txt.in res1/inputAdded.txt COPYONLY)
+configure_file(res/input2.txt.in res2/input.txt COPYONLY)
+configure_file(res/input2.txt.in res2/inputAdded.txt COPYONLY)
+# Dependency generated qrc file
+add_custom_command(OUTPUT res2.qrc
+                   DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc.in
+                   COMMAND ${CMAKE_COMMAND} -E sleep 2
+                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc
+                   )
+
+add_executable(rccDepends
+  main.cpp
+  ${CMAKE_CURRENT_BINARY_DIR}/res1.qrc
+  ${CMAKE_CURRENT_BINARY_DIR}/res2.qrc )
+target_link_libraries(rccDepends ${QT_CORE_TARGET})
+add_custom_command(TARGET rccDepends POST_BUILD COMMAND
+  ${CMAKE_COMMAND} -E echo "$<TARGET_FILE:rccDepends>" > target.txt)
diff --git a/Tests/QtAutogen/autorcc_depends/test_res1.cpp b/Tests/QtAutogen/rccDepends/main.cpp
similarity index 100%
rename from Tests/QtAutogen/autorcc_depends/test_res1.cpp
rename to Tests/QtAutogen/rccDepends/main.cpp
diff --git a/Tests/QtAutogen/autorcc_depends/res1/input.txt.in b/Tests/QtAutogen/rccDepends/res/input1.txt.in
similarity index 100%
rename from Tests/QtAutogen/autorcc_depends/res1/input.txt.in
rename to Tests/QtAutogen/rccDepends/res/input1.txt.in
diff --git a/Tests/QtAutogen/rccDepends/res/input2.txt.in b/Tests/QtAutogen/rccDepends/res/input2.txt.in
new file mode 100644
index 0000000..08e14b7
--- /dev/null
+++ b/Tests/QtAutogen/rccDepends/res/input2.txt.in
@@ -0,0 +1 @@
+Res2 input.
diff --git a/Tests/QtAutogen/rccDepends/res1a.qrc.in b/Tests/QtAutogen/rccDepends/res1a.qrc.in
new file mode 100644
index 0000000..d111ffb
--- /dev/null
+++ b/Tests/QtAutogen/rccDepends/res1a.qrc.in
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/Texts1">
+        <file>res1/input.txt</file>
+    </qresource>
+</RCC>
diff --git a/Tests/QtAutogen/rccDepends/res1b.qrc.in b/Tests/QtAutogen/rccDepends/res1b.qrc.in
new file mode 100644
index 0000000..4cb3f04
--- /dev/null
+++ b/Tests/QtAutogen/rccDepends/res1b.qrc.in
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="/Texts1">
+        <file>res1/input.txt</file>
+        <file alias="Added">res1/inputAdded.txt</file>
+    </qresource>
+</RCC>
diff --git a/Tests/QtAutogen/rccDepends/res2a.qrc.in b/Tests/QtAutogen/rccDepends/res2a.qrc.in
new file mode 100644
index 0000000..19f34ac
--- /dev/null
+++ b/Tests/QtAutogen/rccDepends/res2a.qrc.in
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/Texts2">
+        <file>res2/input.txt</file>
+    </qresource>
+</RCC>
diff --git a/Tests/QtAutogen/rccDepends/res2b.qrc.in b/Tests/QtAutogen/rccDepends/res2b.qrc.in
new file mode 100644
index 0000000..19e8ba1
--- /dev/null
+++ b/Tests/QtAutogen/rccDepends/res2b.qrc.in
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="/Texts2">
+        <file>res2/input.txt</file>
+        <file alias="Added">res2/inputAdded.txt</file>
+    </qresource>
+</RCC>
diff --git a/Tests/QtAutogen/sameName/CMakeLists.txt b/Tests/QtAutogen/sameName/CMakeLists.txt
index 9e47a3e..4d2dcd9 100644
--- a/Tests/QtAutogen/sameName/CMakeLists.txt
+++ b/Tests/QtAutogen/sameName/CMakeLists.txt
@@ -18,3 +18,14 @@ add_executable(sameName
 )
 target_link_libraries(sameName ${QT_LIBRARIES})
 set_target_properties(sameName PROPERTIES AUTOMOC TRUE AUTORCC TRUE)
+
+# Set different compression levels
+if (QT_TEST_VERSION STREQUAL 4)
+  set(rccCompress "-compress")
+else()
+  set(rccCompress "--compress")
+endif()
+set_target_properties(sameName PROPERTIES AUTORCC_OPTIONS "${rccCompress};0" )
+set_source_files_properties(aaa/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};1" )
+set_source_files_properties(bbb/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};2" )
+set_source_files_properties(ccc/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};3" )
diff --git a/Tests/QtAutogen/uicInclude/CMakeLists.txt b/Tests/QtAutogen/uicInclude/CMakeLists.txt
new file mode 100644
index 0000000..f62ebb0
--- /dev/null
+++ b/Tests/QtAutogen/uicInclude/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Test moc include patterns
+
+set(CMAKE_AUTOUIC_SEARCH_PATHS "dirA")
+
+add_executable(uicInclude main.cpp)
+target_link_libraries(uicInclude ${QT_LIBRARIES})
+set_target_properties(uicInclude PROPERTIES AUTOUIC ON)
+set_property(TARGET uicInclude APPEND PROPERTY AUTOUIC_SEARCH_PATHS "dirB")
diff --git a/Tests/QtAutogen/uicInclude/PageC.ui b/Tests/QtAutogen/uicInclude/PageC.ui
new file mode 100644
index 0000000..bb2fb5e
--- /dev/null
+++ b/Tests/QtAutogen/uicInclude/PageC.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PageC</class>
+ <widget class="QWidget" name="PageC">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <widget class="QTreeView" name="treeView"/>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Tests/QtAutogen/uicInclude/dirA/PageA.ui b/Tests/QtAutogen/uicInclude/dirA/PageA.ui
new file mode 100644
index 0000000..dd81802
--- /dev/null
+++ b/Tests/QtAutogen/uicInclude/dirA/PageA.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PageA</class>
+ <widget class="QWidget" name="PageA">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <widget class="QTreeView" name="treeView"/>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui b/Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui
new file mode 100644
index 0000000..fa6dfa6
--- /dev/null
+++ b/Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PageB</class>
+ <widget class="QWidget" name="PageB">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <widget class="QTreeView" name="treeView"/>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Tests/QtAutogen/uicInclude/main.cpp b/Tests/QtAutogen/uicInclude/main.cpp
new file mode 100644
index 0000000..4ca66a7
--- /dev/null
+++ b/Tests/QtAutogen/uicInclude/main.cpp
@@ -0,0 +1,10 @@
+
+#include "main.hpp"
+
+int main(int argv, char** args)
+{
+  return 0;
+}
+
+#include "sub/ui_PageB.h"
+#include "ui_PageC.h"
diff --git a/Tests/QtAutogen/uicInclude/main.hpp b/Tests/QtAutogen/uicInclude/main.hpp
new file mode 100644
index 0000000..58ddc26
--- /dev/null
+++ b/Tests/QtAutogen/uicInclude/main.hpp
@@ -0,0 +1,6 @@
+#ifndef MAIN_HPP
+#define MAIN_HPP
+
+#include "ui_PageA.h"
+
+#endif
diff --git a/Tests/RunCMake/Android/android_sysinc.c b/Tests/RunCMake/Android/android_sysinc.c
new file mode 100644
index 0000000..18d73db
--- /dev/null
+++ b/Tests/RunCMake/Android/android_sysinc.c
@@ -0,0 +1,7 @@
+#include <dlfcn.h>
+
+#ifndef NOT_SYSTEM_DLFCN_HEADER
+#error "sysroot /usr/include appears too early"
+#endif
+
+#include "android.c"
diff --git a/Tests/RunCMake/Android/android_sysinc.cxx b/Tests/RunCMake/Android/android_sysinc.cxx
new file mode 100644
index 0000000..5c5694b
--- /dev/null
+++ b/Tests/RunCMake/Android/android_sysinc.cxx
@@ -0,0 +1,7 @@
+#include <dlfcn.h>
+
+#ifndef NOT_SYSTEM_DLFCN_HEADER
+#error "sysroot /usr/include appears too early"
+#endif
+
+#include "android.cxx"
diff --git a/Tests/RunCMake/Android/common.cmake b/Tests/RunCMake/Android/common.cmake
index bef2428..015f202 100644
--- a/Tests/RunCMake/Android/common.cmake
+++ b/Tests/RunCMake/Android/common.cmake
@@ -92,3 +92,19 @@ if(CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a")
 endif()
 add_executable(android_c android.c)
 add_executable(android_cxx android.cxx)
+
+# Test that an explicit /usr/include is ignored in favor of
+# appearing as a standard include directory at the end.
+set(sysinc_dirs)
+if(CMAKE_ANDROID_NDK)
+  if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
+    list(APPEND sysinc_dirs ${CMAKE_SYSROOT_COMPILE}/usr/include)
+  else()
+    list(APPEND sysinc_dirs ${CMAKE_SYSROOT}/usr/include)
+  endif()
+endif()
+list(APPEND sysinc_dirs ${CMAKE_CURRENT_SOURCE_DIR}/sysinc)
+add_executable(android_sysinc_c android_sysinc.c)
+target_include_directories(android_sysinc_c SYSTEM PRIVATE ${sysinc_dirs})
+add_executable(android_sysinc_cxx android_sysinc.cxx)
+target_include_directories(android_sysinc_cxx SYSTEM PRIVATE ${sysinc_dirs})
diff --git a/Tests/RunCMake/Android/sysinc/dlfcn.h b/Tests/RunCMake/Android/sysinc/dlfcn.h
new file mode 100644
index 0000000..273306c
--- /dev/null
+++ b/Tests/RunCMake/Android/sysinc/dlfcn.h
@@ -0,0 +1 @@
+#define NOT_SYSTEM_DLFCN_HEADER
diff --git a/Tests/RunCMake/AutoExportDll/AutoExport.cmake b/Tests/RunCMake/AutoExportDll/AutoExport.cmake
index d37e896..a550005 100644
--- a/Tests/RunCMake/AutoExportDll/AutoExport.cmake
+++ b/Tests/RunCMake/AutoExportDll/AutoExport.cmake
@@ -11,5 +11,11 @@ if(MSVC)
   set_target_properties(say PROPERTIES ENABLE_EXPORTS ON)
   add_library(autoexport_for_exec SHARED hello2.c)
   target_link_libraries(autoexport_for_exec say)
+  if(NOT MSVC_VERSION VERSION_LESS 1600)
+    enable_language(ASM_MASM)
+    target_sources(autoexport PRIVATE nop.asm)
+    set_property(SOURCE nop.asm PROPERTY COMPILE_FLAGS /safeseh)
+    target_compile_definitions(say PRIVATE HAS_JUSTNOP)
+  endif()
 endif()
 target_link_libraries(say autoexport autoexport2)
diff --git a/Tests/RunCMake/AutoExportDll/nop.asm b/Tests/RunCMake/AutoExportDll/nop.asm
new file mode 100644
index 0000000..fd6892f
--- /dev/null
+++ b/Tests/RunCMake/AutoExportDll/nop.asm
@@ -0,0 +1,12 @@
+IFDEF RAX
+ELSE
+.MODEL FLAT,C
+ENDIF
+
+SOME SEGMENT EXECUTE READ
+
+public justnop
+justnop:
+  ret
+
+END
diff --git a/Tests/RunCMake/AutoExportDll/say.cxx b/Tests/RunCMake/AutoExportDll/say.cxx
index e966b1f..51060e8 100644
--- a/Tests/RunCMake/AutoExportDll/say.cxx
+++ b/Tests/RunCMake/AutoExportDll/say.cxx
@@ -12,6 +12,7 @@ int WINAPI foo();
 // test regular C
 int bar();
 int objlib();
+void justnop();
 }
 
 // test c++ functions
@@ -42,5 +43,8 @@ int main()
   bar();
   objlib();
   printf("\n");
+#ifdef HAS_JUSTNOP
+  justnop();
+#endif
   return 0;
 }
diff --git a/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cmake b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cmake
new file mode 100644
index 0000000..0f92e0e
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cmake
@@ -0,0 +1,13 @@
+add_custom_command(
+  OUTPUT output.cxx
+  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/MakeCustomIncludes.cxx output.cxx
+  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/MakeCustomIncludes.cxx
+  IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/MakeCustomIncludes.cxx)
+add_custom_target(generate ALL DEPENDS output.cxx)
+set_property(TARGET generate PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR})
+
+file(GENERATE OUTPUT check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
+set(check_pairs
+  \"${CMAKE_CURRENT_BINARY_DIR}/output.cxx|${CMAKE_CURRENT_BINARY_DIR}/MakeCustomIncludes.h\"
+  )
+")
diff --git a/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cxx b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cxx
new file mode 100644
index 0000000..9a0edef
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.cxx
@@ -0,0 +1,6 @@
+#include "MakeCustomIncludes.h"
+
+int main()
+{
+  return MakeCustomIncludes();
+}
diff --git a/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step1.cmake b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step1.cmake
new file mode 100644
index 0000000..6bb01a6
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step1.cmake
@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/MakeCustomIncludes.h" [[
+inline int MakeCustomIncludes() { return 1; }
+]])
diff --git a/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step2.cmake b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step2.cmake
new file mode 100644
index 0000000..6b3151d
--- /dev/null
+++ b/Tests/RunCMake/BuildDepends/MakeCustomIncludes.step2.cmake
@@ -0,0 +1,3 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/MakeCustomIncludes.h" [[
+inline int MakeCustomIncludes() { return 2; }
+]])
diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
index ffd3ae1..9941c70 100644
--- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
+++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake
@@ -31,7 +31,7 @@ function(run_BuildDepends CASE)
 endfunction()
 
 run_BuildDepends(C-Exe)
-if(NOT RunCMake_GENERATOR MATCHES "Visual Studio 7|Xcode")
+if(NOT RunCMake_GENERATOR STREQUAL "Xcode")
   if(RunCMake_GENERATOR MATCHES "Visual Studio 10")
     # VS 10 forgets to re-link when a manifest changes
     set(run_BuildDepends_skip_step_2 1)
@@ -43,9 +43,11 @@ endif()
 run_BuildDepends(Custom-Symbolic-and-Byproduct)
 run_BuildDepends(Custom-Always)
 
-if(RunCMake_GENERATOR MATCHES "Make" AND
-   NOT "${RunCMake_BINARY_DIR}" STREQUAL "${RunCMake_SOURCE_DIR}")
-  run_BuildDepends(MakeInProjectOnly)
+if(RunCMake_GENERATOR MATCHES "Make")
+  run_BuildDepends(MakeCustomIncludes)
+  if(NOT "${RunCMake_BINARY_DIR}" STREQUAL "${RunCMake_SOURCE_DIR}")
+    run_BuildDepends(MakeInProjectOnly)
+  endif()
 endif()
 
 function(run_ReGeneration)
diff --git a/Tests/RunCMake/CMP0019/CMP0019-OLD-stderr.txt b/Tests/RunCMake/CMP0019/CMP0019-OLD-stderr.txt
new file mode 100644
index 0000000..048762d
--- /dev/null
+++ b/Tests/RunCMake/CMP0019/CMP0019-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0019-OLD.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0019 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/CMP0022/CMP0022-WARN-tll-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt
index f672285..5d39214 100644
--- a/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt
+++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll-stderr.txt
@@ -4,13 +4,13 @@ CMake Warning \(dev\) in CMakeLists.txt:
   cmake_policy command to set the policy and suppress this warning.
 
   Target "bar" has an INTERFACE_LINK_LIBRARIES property which differs from
-  its LINK_INTERFACE_LIBRARIES properties.
+  its LINK_INTERFACE_LIBRARIES(_DEBUG)? properties.
 
   INTERFACE_LINK_LIBRARIES:
 
     foo
 
-  LINK_INTERFACE_LIBRARIES:
+  LINK_INTERFACE_LIBRARIES(_DEBUG)?:
 
     bat
 
diff --git a/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake
index 11b4e22..03223e8 100644
--- a/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake
+++ b/Tests/RunCMake/CMP0022/CMP0022-WARN-tll.cmake
@@ -5,7 +5,9 @@ add_library(foo SHARED empty_vs6_1.cpp)
 add_library(bar SHARED empty_vs6_2.cpp)
 add_library(bat SHARED empty_vs6_3.cpp)
 target_link_libraries(bar LINK_PUBLIC foo)
+# Replace the compatibility values set by target_link_libraries
 set_property(TARGET bar PROPERTY LINK_INTERFACE_LIBRARIES bat)
+set_property(TARGET bar PROPERTY LINK_INTERFACE_LIBRARIES_DEBUG bat)
 
 add_library(user SHARED empty.cpp)
 target_link_libraries(user bar)
diff --git a/Tests/RunCMake/CMP0026/CMP0026-CONFIG-LOCATION-OLD-stderr.txt b/Tests/RunCMake/CMP0026/CMP0026-CONFIG-LOCATION-OLD-stderr.txt
new file mode 100644
index 0000000..edeb337
--- /dev/null
+++ b/Tests/RunCMake/CMP0026/CMP0026-CONFIG-LOCATION-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0026-CONFIG-LOCATION-OLD.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0026 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/CMP0026/CMP0026-LOCATION-CONFIG-OLD-stderr.txt b/Tests/RunCMake/CMP0026/CMP0026-LOCATION-CONFIG-OLD-stderr.txt
new file mode 100644
index 0000000..32ff698
--- /dev/null
+++ b/Tests/RunCMake/CMP0026/CMP0026-LOCATION-CONFIG-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0026-LOCATION-CONFIG-OLD.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0026 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/CMP0026/CMP0026-OLD-stderr.txt b/Tests/RunCMake/CMP0026/CMP0026-OLD-stderr.txt
new file mode 100644
index 0000000..b3f79fc
--- /dev/null
+++ b/Tests/RunCMake/CMP0026/CMP0026-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0026-OLD.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0026 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/CMP0026/CMP0026-OLD.cmake b/Tests/RunCMake/CMP0026/CMP0026-OLD.cmake
new file mode 100644
index 0000000..80497a3
--- /dev/null
+++ b/Tests/RunCMake/CMP0026/CMP0026-OLD.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+
+cmake_policy(SET CMP0026 OLD)
+
+set(out ${CMAKE_CURRENT_BINARY_DIR}/out.txt)
+
+add_library(somelib empty.cpp ${out})
+get_target_property(_loc somelib LOCATION)
+
+file(WRITE "${out}"
+  "source file written by project code after getting target LOCATION\n"
+  )
diff --git a/Tests/RunCMake/CMP0026/RunCMakeTest.cmake b/Tests/RunCMake/CMP0026/RunCMakeTest.cmake
index 6331717..047da28 100644
--- a/Tests/RunCMake/CMP0026/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMP0026/RunCMakeTest.cmake
@@ -1,6 +1,7 @@
 include(RunCMake)
 
 run_cmake(CMP0026-WARN)
+run_cmake(CMP0026-OLD)
 run_cmake(CMP0026-NEW)
 run_cmake(CMP0026-IMPORTED)
 run_cmake(CMP0026-CONFIG-LOCATION-NEW)
diff --git a/Tests/RunCMake/CMP0026/clear-cached-information-stderr.txt b/Tests/RunCMake/CMP0026/clear-cached-information-stderr.txt
new file mode 100644
index 0000000..157a046
--- /dev/null
+++ b/Tests/RunCMake/CMP0026/clear-cached-information-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at clear-cached-information.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0026 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/CMP0028/CMP0028-OLD-iface-stderr.txt b/Tests/RunCMake/CMP0028/CMP0028-OLD-iface-stderr.txt
new file mode 100644
index 0000000..b7a0755
--- /dev/null
+++ b/Tests/RunCMake/CMP0028/CMP0028-OLD-iface-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0028-OLD-iface.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0028 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/CMP0028/CMP0028-OLD-stderr.txt b/Tests/RunCMake/CMP0028/CMP0028-OLD-stderr.txt
new file mode 100644
index 0000000..586a876
--- /dev/null
+++ b/Tests/RunCMake/CMP0028/CMP0028-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0028-OLD.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0028 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/CMP0068/CMP0068-NEW-result.txt b/Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CMP0068/CMP0068-NEW.cmake b/Tests/RunCMake/CMP0068/CMP0068-NEW.cmake
new file mode 100644
index 0000000..eb8cfa1
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/CMP0068-NEW.cmake
@@ -0,0 +1,6 @@
+
+cmake_policy(SET CMP0068 NEW)
+cmake_policy(SET CMP0042 NEW)
+
+add_library(foo SHARED empty.cpp)
+set_target_properties(foo PROPERTIES INSTALL_NAME_DIR "@rpath" INSTALL_RPATH "@loader_path/" BUILD_WITH_INSTALL_RPATH 1)
diff --git a/Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt b/Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CMP0068/CMP0068-OLD.cmake b/Tests/RunCMake/CMP0068/CMP0068-OLD.cmake
new file mode 100644
index 0000000..cf1040f
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/CMP0068-OLD.cmake
@@ -0,0 +1,6 @@
+
+cmake_policy(SET CMP0068 OLD)
+cmake_policy(SET CMP0042 NEW)
+
+add_library(foo SHARED empty.cpp)
+set_target_properties(foo PROPERTIES INSTALL_NAME_DIR "@rpath" INSTALL_RPATH "@loader_path/" BUILD_WITH_INSTALL_RPATH 1)
diff --git a/Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt b/Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt b/Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt
new file mode 100644
index 0000000..3cb5854
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt
@@ -0,0 +1,12 @@
+CMake Warning \(dev\):
+  Policy CMP0068 is not set: RPATH settings on macOS do not affect
+  install_name.  Run "cmake --help-policy CMP0068" for policy details.  Use
+  the cmake_policy command to set the policy and suppress this warning.
+
+  For compatibility with older versions of CMake, the install_name fields for
+  the following targets are still affected by RPATH settings:
+
+   foo3
+   foo4
+
+This warning is for project developers.  Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CMP0068/CMP0068-WARN.cmake b/Tests/RunCMake/CMP0068/CMP0068-WARN.cmake
new file mode 100644
index 0000000..b7ec480
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/CMP0068-WARN.cmake
@@ -0,0 +1,12 @@
+cmake_policy(SET CMP0042 NEW)
+
+add_library(foo SHARED empty.cpp)
+add_library(foo-static STATIC empty.cpp)
+add_library(foo2 SHARED empty.cpp)
+set_target_properties(foo2 PROPERTIES MACOSX_RPATH 1)
+add_library(foo3 SHARED empty.cpp)
+set_target_properties(foo3 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@loader_path")
+add_library(foo4 SHARED empty.cpp)
+set_target_properties(foo4 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@rpath")
+add_library(foo5 SHARED empty.cpp)
+set_target_properties(foo5 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 BUILD_WITH_INSTALL_NAME_DIR 1 INSTALL_NAME_DIR "@rpath")
diff --git a/Tests/RunCMake/CMP0068/CMakeLists.txt b/Tests/RunCMake/CMP0068/CMakeLists.txt
new file mode 100644
index 0000000..375cbdb
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.8)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0068/RunCMakeTest.cmake b/Tests/RunCMake/CMP0068/RunCMakeTest.cmake
new file mode 100644
index 0000000..88a6225
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0068-OLD)
+run_cmake(CMP0068-NEW)
+run_cmake(CMP0068-WARN)
diff --git a/Tests/RunCMake/CMP0068/empty.cpp b/Tests/RunCMake/CMP0068/empty.cpp
new file mode 100644
index 0000000..11ec041
--- /dev/null
+++ b/Tests/RunCMake/CMP0068/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+  int empty()
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-result.txt
diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt
new file mode 100644
index 0000000..ddb3cae
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at CMP0069-NEW-cmake\.cmake:[0-9]+ \(add_executable\):
+  CMake doesn't support IPO for current compiler
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake
new file mode 100644
index 0000000..6968c8b
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake
@@ -0,0 +1,6 @@
+cmake_policy(SET CMP0069 NEW)
+
+set(_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE NO)
+
+add_executable(foo main.cpp)
+set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Tests/RunCMake/ObjectLibrary/Import-result.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-result.txt
similarity index 100%
rename from Tests/RunCMake/ObjectLibrary/Import-result.txt
rename to Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-result.txt
diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt
new file mode 100644
index 0000000..8decfab
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at CMP0069-NEW-compiler\.cmake:[0-9]+ \(add_executable\):
+  Compiler doesn't support IPO
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake
new file mode 100644
index 0000000..ecb197b
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake
@@ -0,0 +1,7 @@
+cmake_policy(SET CMP0069 NEW)
+
+set(_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE YES)
+set(_CMAKE_CXX_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+
+add_executable(foo main.cpp)
+set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Tests/RunCMake/ObjectLibrary/Install-result.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-result.txt
similarity index 100%
rename from Tests/RunCMake/ObjectLibrary/Install-result.txt
rename to Tests/RunCMake/CMP0069/CMP0069-NEW-generator-result.txt
diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt
new file mode 100644
index 0000000..0e05ee7
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at CMP0069-NEW-generator\.cmake:[0-9]+ \(add_executable\):
+  CMake doesn't support IPO for current generator
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake
new file mode 100644
index 0000000..80d4e15
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake
@@ -0,0 +1,7 @@
+cmake_policy(SET CMP0069 NEW)
+
+set(_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE YES)
+set(_CMAKE_CXX_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+
+add_executable(foo main.cpp)
+set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Tests/RunCMake/CMP0069/CMP0069-OLD.cmake b/Tests/RunCMake/CMP0069/CMP0069-OLD.cmake
new file mode 100644
index 0000000..cfe1e9d
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMP0069-OLD.cmake
@@ -0,0 +1,4 @@
+cmake_policy(SET CMP0069 OLD)
+
+add_executable(foo main.cpp)
+set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt b/Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt
new file mode 100644
index 0000000..314e180
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMP0069-WARN-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Warning \(dev\) at CMP0069-WARN\.cmake:[0-9]+ \(add_executable\):
+  Policy CMP0069 is not set: INTERPROCEDURAL_OPTIMIZATION is enforced when
+  enabled.  Run "cmake --help-policy CMP0069" for policy details\.  Use the
+  cmake_policy command to set the policy and suppress this warning\.
+
+  INTERPROCEDURAL_OPTIMIZATION property will be ignored for target 'foo'\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake b/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake
new file mode 100644
index 0000000..2049c9e
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake
@@ -0,0 +1,4 @@
+set(_CMAKE_CXX_IPO_LEGACY_BEHAVIOR NO)
+
+add_executable(foo main.cpp)
+set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Tests/RunCMake/CMP0069/CMakeLists.txt b/Tests/RunCMake/CMP0069/CMakeLists.txt
new file mode 100644
index 0000000..375cbdb
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.8)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0069/RunCMakeTest.cmake b/Tests/RunCMake/CMP0069/RunCMakeTest.cmake
new file mode 100644
index 0000000..f44f840
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/RunCMakeTest.cmake
@@ -0,0 +1,10 @@
+include(RunCMake)
+
+run_cmake(CMP0069-OLD)
+run_cmake(CMP0069-NEW-cmake)
+run_cmake(CMP0069-NEW-compiler)
+run_cmake(CMP0069-WARN)
+
+if(RunCMake_GENERATOR MATCHES "^Visual Studio ")
+  run_cmake(CMP0069-NEW-generator)
+endif()
diff --git a/Tests/RunCMake/CMP0069/main.cpp b/Tests/RunCMake/CMP0069/main.cpp
new file mode 100644
index 0000000..5047a34
--- /dev/null
+++ b/Tests/RunCMake/CMP0069/main.cpp
@@ -0,0 +1,3 @@
+int main()
+{
+}
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index a16efb3..79f487d 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -63,15 +63,6 @@ if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 6.1)
   set(Swift_ARGS -DXCODE_BELOW_6_1=1)
 endif()
 
-if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 3)
-  set(GeneratorToolset_ARGS -DXCODE_BELOW_3=1)
-endif()
-
-if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 2)
-  set(TargetSources_ARGS -DXCODE_BELOW_2=1)
-  set(File_Generate_ARGS -DXCODE_BELOW_2=1)
-endif()
-
 # Test MSVC for older host CMake versions, and test
 # WIN32/CMAKE_C_COMPILER_ID to fix check on Intel for Windows.
 if(MSVC OR (WIN32 AND CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel"))
@@ -104,6 +95,10 @@ add_RunCMake_test(CMP0057)
 add_RunCMake_test(CMP0059)
 add_RunCMake_test(CMP0060)
 add_RunCMake_test(CMP0064)
+if(CMAKE_SYSTEM_NAME MATCHES Darwin AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG)
+  add_RunCMake_test(CMP0068)
+endif()
+add_RunCMake_test(CMP0069)
 
 # The test for Policy 65 requires the use of the
 # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
@@ -115,6 +110,10 @@ if(CMAKE_GENERATOR MATCHES "Make")
   add_RunCMake_test(Make)
 endif()
 if(CMAKE_GENERATOR STREQUAL "Ninja")
+  set(Ninja_ARGS
+    -DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION}
+    -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX}
+    -DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX})
   add_RunCMake_test(Ninja)
 endif()
 add_RunCMake_test(CTest)
@@ -148,7 +147,7 @@ endif()
 add_RunCMake_test(GeneratorExpression)
 add_RunCMake_test(GeneratorPlatform)
 add_RunCMake_test(GeneratorToolset)
-add_RunCMake_test(GNUInstallDirs)
+add_RunCMake_test(GNUInstallDirs -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME})
 add_RunCMake_test(TargetPropertyGeneratorExpressions)
 add_RunCMake_test(Languages)
 add_RunCMake_test(LinkStatic)
@@ -199,6 +198,8 @@ endif()
 add_RunCMake_test(ctest_start)
 add_RunCMake_test(ctest_submit)
 add_RunCMake_test(ctest_test)
+add_RunCMake_test(ctest_disabled_test)
+add_RunCMake_test(ctest_skipped_test)
 add_RunCMake_test(ctest_upload)
 add_RunCMake_test(ctest_fixtures)
 add_RunCMake_test(file)
@@ -216,6 +217,7 @@ add_RunCMake_test(list)
 add_RunCMake_test(message)
 add_RunCMake_test(project -DCMake_TEST_RESOURCES=${CMake_TEST_RESOURCES})
 add_RunCMake_test(return)
+add_RunCMake_test(separate_arguments)
 add_RunCMake_test(set_property)
 add_RunCMake_test(string)
 foreach(var
@@ -265,17 +267,17 @@ endif()
 
 if("${CMAKE_GENERATOR}" MATCHES "Visual Studio")
   add_RunCMake_test(include_external_msproject)
-  if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([789]|10)" AND NOT CMAKE_VS_DEVENV_COMMAND)
+  if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([89]|10)" AND NOT CMAKE_VS_DEVENV_COMMAND)
     set(NO_USE_FOLDERS 1)
   endif()
   add_RunCMake_test(VSSolution -DNO_USE_FOLDERS=${NO_USE_FOLDERS})
 endif()
 
-if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([^789]|[789][0-9])")
+if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([^89]|[89][0-9])")
   add_RunCMake_test(VS10Project)
 endif()
 
-if(XCODE_VERSION AND NOT "${XCODE_VERSION}" VERSION_LESS 3)
+if(XCODE_VERSION)
   add_RunCMake_test(XcodeProject -DXCODE_VERSION=${XCODE_VERSION})
 endif()
 
@@ -290,7 +292,8 @@ add_RunCMake_test(target_link_libraries)
 
 add_RunCMake_test(target_compile_features)
 add_RunCMake_test(CheckModules)
-add_RunCMake_test(CommandLine)
+add_RunCMake_test(CheckIPOSupported)
+add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
 add_RunCMake_test(CommandLineTar)
 
 add_RunCMake_test(install)
@@ -322,19 +325,6 @@ add_executable(pseudo_emulator_custom_command pseudo_emulator_custom_command.c)
 add_RunCMake_test(CrosscompilingEmulator
  -DPSEUDO_EMULATOR=$<TARGET_FILE:pseudo_emulator>
  -DPSEUDO_EMULATOR_CUSTOM_COMMAND=$<TARGET_FILE:pseudo_emulator_custom_command>)
-# Xcode 2.x forgets to create the output directory before linking
-# the individual architectures.
-if(CMAKE_OSX_ARCHITECTURES AND XCODE AND NOT "${XCODE_VERSION}" MATCHES "^[^12]")
-  add_custom_command(
-    TARGET pseudo_emulator
-    PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}"
-    )
-  add_custom_command(
-    TARGET pseudo_emulator_custom_command
-    PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CFG_INTDIR}"
-    )
-endif()
-
 if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
   if(UNIX AND NOT CYGWIN)
     execute_process(COMMAND ldd --help
diff --git a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake
index ce039f5..99d3155 100644
--- a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake
+++ b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake
@@ -33,7 +33,7 @@ function(getPackageContentList FILE RESULT_VAR)
 endfunction()
 
 function(toExpectedContentList FILE_NO CONTENT_VAR)
-  findExpectedFile("${FILE_NO}" "file_")
+  findExpectedFile("${FILE_NO}" "file_" "glob_expr_")
 
   # component and monolithic packages differ for some reason by either having
   # package filename prefix in path or not
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index 65399db..faf151a 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -5,7 +5,7 @@ include("${RunCMake_SOURCE_DIR}/CPackTestHelpers.cmake")
 
 # run_cpack_test args: TEST_NAME "GENERATORS" RUN_CMAKE_BUILD_STEP "PACKAGING_TYPES"
 run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM" false "MONOLITHIC;COMPONENT")
-run_cpack_test(CUSTOM_NAMES "RPM;DEB" true "COMPONENT")
+run_cpack_test(CUSTOM_NAMES "RPM;DEB;TGZ" true "COMPONENT")
 run_cpack_test(DEBUGINFO "RPM" true "COMPONENT")
 run_cpack_test(DEPENDENCIES "RPM;DEB" true "COMPONENT")
 run_cpack_test(DIST "RPM" false "MONOLITHIC")
@@ -21,7 +21,9 @@ run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;
 run_cpack_test(PARTIALLY_RELOCATABLE_WARNING "RPM" false "COMPONENT")
 run_cpack_test(PER_COMPONENT_FIELDS "RPM;DEB" false "COMPONENT")
 run_cpack_test_subtests(SINGLE_DEBUGINFO "no_main_component;one_component;one_component_main;no_debuginfo;one_component_no_debuginfo;no_components;valid" "RPM" true "CUSTOM")
+run_cpack_test(EXTRA_SLASH_IN_PATH "RPM" true "COMPONENT")
 run_cpack_source_test(SOURCE_PACKAGE "RPM")
 run_cpack_test(SUGGESTS "RPM" false "MONOLITHIC")
+run_cpack_test(SYMLINKS "RPM;TGZ" false "MONOLITHIC;COMPONENT")
 run_cpack_test(USER_FILELIST "RPM" false "MONOLITHIC")
 run_cpack_test(MD5SUMS "DEB" false "MONOLITHIC;COMPONENT")
diff --git a/Tests/RunCMake/CPack/STGZ/Helpers.cmake b/Tests/RunCMake/CPack/STGZ/Helpers.cmake
index 08224d3..68b1eab 100644
--- a/Tests/RunCMake/CPack/STGZ/Helpers.cmake
+++ b/Tests/RunCMake/CPack/STGZ/Helpers.cmake
@@ -35,7 +35,7 @@ function(getPackageContentList FILE RESULT_VAR)
 endfunction()
 
 function(toExpectedContentList FILE_NO CONTENT_VAR)
-  findExpectedFile("${FILE_NO}" "file_")
+  findExpectedFile("${FILE_NO}" "file_" "glob_expr_")
 
   get_filename_component(prefix_ "${file_}" NAME)
   # NAME_WE removes everything after the dot and dot is in version so replace instead
diff --git a/Tests/RunCMake/CPack/VerifyResult.cmake b/Tests/RunCMake/CPack/VerifyResult.cmake
index 59751a7..470ebf7 100644
--- a/Tests/RunCMake/CPack/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/VerifyResult.cmake
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION ${CMAKE_VERSION} FATAL_ERROR)
 
-function(findExpectedFile FILE_NO RESULT_VAR)
+function(findExpectedFile FILE_NO RESULT_VAR GLOBING_EXPR_VAR)
   if(NOT DEFINED EXPECTED_FILE_${FILE_NO}) # explicit file name regex was not provided - construct one from other data
     # set defaults if parameters are not provided
     if(NOT DEFINED EXPECTED_FILE_${FILE_NO}_NAME)
@@ -21,6 +21,7 @@ function(findExpectedFile FILE_NO RESULT_VAR)
   file(GLOB found_file_ RELATIVE "${bin_dir}" "${EXPECTED_FILE_${FILE_NO}}")
 
   set(${RESULT_VAR} "${found_file_}" PARENT_SCOPE)
+  set(${GLOBING_EXPR_VAR} "${EXPECTED_FILE_${FILE_NO}}" PARENT_SCOPE)
 endfunction()
 
 include("${config_file}")
@@ -39,7 +40,8 @@ include("${src_dir}/tests/${RunCMake_TEST_FILE_PREFIX}/ExpectedFiles.cmake")
 # check that expected generated files exist and contain expected content
 if(NOT EXPECTED_FILES_COUNT EQUAL 0)
   foreach(file_no_ RANGE 1 ${EXPECTED_FILES_COUNT})
-    findExpectedFile("${file_no_}" "FOUND_FILE_${file_no_}")
+    findExpectedFile("${file_no_}" "FOUND_FILE_${file_no_}"
+      "EXPECTED_FILE_${file_no_}")
     list(APPEND foundFiles_ "${FOUND_FILE_${file_no_}}")
     list(LENGTH FOUND_FILE_${file_no_} foundFilesCount_)
 
diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake
index ae5f0af..5cb280c 100644
--- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake
@@ -9,4 +9,7 @@ set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
 if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM")
   string(TOLOWER "${GENERATOR_TYPE}" file_extension_)
   set(EXPECTED_FILE_3 "pkg_3_abc.${file_extension_}")
+elseif(GENERATOR_TYPE STREQUAL "TGZ")
+  set(EXPECTED_FILE_2 "second.tar.gz")
+  set(EXPECTED_FILE_3 "pkg_3_abc.tar.gz")
 endif()
diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake
index 0c2b37b..4c20e41 100644
--- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake
+++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake
@@ -7,6 +7,9 @@ if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM")
   set(CPACK_${GENERATOR_TYPE}${generator_type_suffix_}_PKG_2_PACKAGE_NAME "second")
   string(TOLOWER "${GENERATOR_TYPE}" file_extension_)
   set(CPACK_${GENERATOR_TYPE}${generator_type_suffix_}_PKG_3_FILE_NAME "pkg_3_abc.${file_extension_}")
+elseif(GENERATOR_TYPE STREQUAL "TGZ")
+  set(CPACK_ARCHIVE_PKG_2_FILE_NAME "second")
+  set(CPACK_ARCHIVE_PKG_3_FILE_NAME "pkg_3_abc")
 endif()
 
 install(FILES CMakeLists.txt DESTINATION foo COMPONENT pkg_1)
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
index 06e56d3..3d8de74 100644
--- a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
@@ -3,14 +3,16 @@ set(whitespaces_ "[\t\n\r ]*")
 set(EXPECTED_FILES_COUNT "5")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
 
+set(EXPECTED_FILE_1_NAME "Debuginfo")
 set(EXPECTED_FILE_1_COMPONENT "applications")
 set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
-set(EXPECTED_FILE_2 "debuginfo*-headers.rpm")
+set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.rpm")
 set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
-set(EXPECTED_FILE_3 "debuginfo*-libs.rpm")
+set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.rpm")
 set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/libtest_lib.so")
 
+set(EXPECTED_FILE_4_NAME "Debuginfo")
 set(EXPECTED_FILE_4_COMPONENT "applications-debuginfo")
 set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*")
-set(EXPECTED_FILE_5_COMPONENT "libs-debuginfo")
+set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm")
 set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*")
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake
index 0642d83..f1b6738 100644
--- a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake
@@ -25,6 +25,16 @@ install(TARGETS test_lib DESTINATION bas COMPONENT libs)
 
 set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT")
 set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON)
+
+# test that components with debuginfo enabled still honor
+# CPACK_PACKAGE_FILE_NAME setting
+set(CPACK_RPM_PACKAGE_NAME "Debuginfo")
+set(CPACK_PACKAGE_FILE_NAME "TestDinfo-pkg")
 set(CPACK_RPM_LIBS_DEBUGINFO_PACKAGE ON)
 
+# test debuginfo package rename
+set(CPACK_RPM_DEBUGINFO_FILE_NAME
+  "@cpack_component at -DebugInfoPackage.rpm")
+set(CPACK_RPM_APPLICATIONS_DEBUGINFO_FILE_NAME "RPM-DEFAULT")
+
 set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/src")
diff --git a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake
new file mode 100644
index 0000000..a45b38d
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake
@@ -0,0 +1,16 @@
+set(whitespaces_ "[\t\n\r ]*")
+
+set(EXPECTED_FILES_COUNT "5")
+set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
+
+set(EXPECTED_FILE_1_COMPONENT "applications")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
+set(EXPECTED_FILE_2 "extra_slash_in_path*-headers.rpm")
+set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
+set(EXPECTED_FILE_3 "extra_slash_in_path*-libs.rpm")
+set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so")
+
+set(EXPECTED_FILE_4_COMPONENT "applications-debuginfo")
+set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*")
+set(EXPECTED_FILE_5_COMPONENT "libs-debuginfo")
+set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*")
diff --git a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/VerifyResult.cmake
new file mode 100644
index 0000000..bfef720
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/VerifyResult.cmake
@@ -0,0 +1,7 @@
+# check that relocation path is /foo and not //foo
+getPackageInfo("${FOUND_FILE_1}" "FILE_INFO_")
+set(whitespaces_ "[\t\n\r ]*")
+if(NOT FILE_INFO_ MATCHES "Relocations${whitespaces_}:${whitespaces_}/${whitespaces_}/foo")
+  message(FATAL_ERROR "Unexpected relocation path in file '${FOUND_FILE_1}';"
+    " file info: '${FILE_INFO_}'")
+endif()
diff --git a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/test.cmake b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/test.cmake
new file mode 100644
index 0000000..4fd1e81
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/test.cmake
@@ -0,0 +1,37 @@
+set(CMAKE_BUILD_WITH_INSTALL_RPATH 1)
+
+# PGI compiler doesn't add build id to binaries by default
+if(CMAKE_CXX_COMPILER_ID STREQUAL "PGI")
+  string(APPEND CMAKE_EXE_LINKER_FLAGS "-Wl,--build-id")
+  string(APPEND CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id")
+endif()
+
+set(CMAKE_BUILD_TYPE Debug)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_lib.hpp"
+    "int test_lib();\n")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp"
+    "#include \"test_lib.hpp\"\nint test_lib() {return 0;}\n")
+add_library(test_lib SHARED "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+    "#include \"test_lib.hpp\"\nint main() {return test_lib();}\n")
+add_executable(test_prog "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+target_link_libraries(test_prog test_lib)
+
+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_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT")
+set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON)
+set(CPACK_RPM_LIBS_DEBUGINFO_PACKAGE ON)
+
+# extra trailing slash at the end that should be removed
+set(CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX "/src/")
+
+# combination should not cause //foo to apper as an relocation path
+# should be only /foo (extra slashes cause path comparisons to fail)
+set(CPACK_PACKAGING_INSTALL_PREFIX "/")
+# extra trailing slash at the end that should be removed
+set(CPACK_RPM_RELOCATION_PATHS "foo/")
diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake
new file mode 100644
index 0000000..05be748
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake
@@ -0,0 +1,13 @@
+set(EXPECTED_FILES_COUNT "1")
+
+set(EXPECTED_FILE_CONTENT_1_LIST
+  "/usr"
+  "/usr/empty_dir"
+  "/usr/non_empty_dir"
+  "/usr/non_empty_dir/CMakeLists.txt"
+  "/usr/symlink_to_empty_dir"
+  "/usr/symlink_to_non_empty_dir")
+
+if(PACKAGING_TYPE STREQUAL "COMPONENT")
+  set(EXPECTED_FILE_1_COMPONENT "links")
+endif()
diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/TGZ-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/TGZ-Prerequirements.cmake
new file mode 100644
index 0000000..f3df46b
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/SYMLINKS/TGZ-Prerequirements.cmake
@@ -0,0 +1,5 @@
+function(get_test_prerequirements found_var config_file)
+  if(UNIX) # limit test to platforms that support symlinks
+    set(${found_var} true PARENT_SCOPE)
+  endif()
+endfunction()
diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake
new file mode 100644
index 0000000..0632319
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/SYMLINKS/VerifyResult.cmake
@@ -0,0 +1,26 @@
+set(whitespaces "[\\t\\n\\r ]*")
+
+#######################
+# verify generated symbolic links
+#######################
+file(GLOB_RECURSE symlink_files RELATIVE "${bin_dir}" "${bin_dir}/*/symlink_*")
+
+foreach(check_symlink IN LISTS symlink_files)
+  get_filename_component(symlink_name "${check_symlink}" NAME)
+  execute_process(COMMAND ls -la "${check_symlink}"
+            WORKING_DIRECTORY "${bin_dir}"
+            OUTPUT_VARIABLE SYMLINK_POINT_
+            OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+  if("${symlink_name}" STREQUAL "symlink_to_empty_dir")
+    string(REGEX MATCH "^.*${whitespaces}->${whitespaces}empty_dir$" check_symlink "${SYMLINK_POINT_}")
+  elseif("${symlink_name}" STREQUAL "symlink_to_non_empty_dir")
+    string(REGEX MATCH "^.*${whitespaces}->${whitespaces}non_empty_dir$" check_symlink "${SYMLINK_POINT_}")
+  else()
+    message(FATAL_ERROR "error: unexpected rpm symbolic link '${check_symlink}'")
+  endif()
+
+  if(NOT check_symlink)
+    message(FATAL_ERROR "symlink points to unexpected location '${SYMLINK_POINT_}'")
+  endif()
+endforeach()
diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/test.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/test.cmake
new file mode 100644
index 0000000..fef765c
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/SYMLINKS/test.cmake
@@ -0,0 +1,14 @@
+install(DIRECTORY DESTINATION empty_dir COMPONENT links)
+install(FILES CMakeLists.txt DESTINATION non_empty_dir COMPONENT links)
+
+# test symbolic link to an empty dir
+execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink empty_dir symlink_to_empty_dir)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_to_empty_dir DESTINATION "." COMPONENT links)
+
+# test symbolic link to a non empty dir
+execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink non_empty_dir symlink_to_non_empty_dir)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_to_non_empty_dir DESTINATION "." COMPONENT links)
+
+if(PACKAGING_TYPE STREQUAL "COMPONENT")
+  set(CPACK_COMPONENTS_ALL links)
+endif()
diff --git a/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt b/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt
new file mode 100644
index 0000000..4a13d29
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.0)
+project(${RunCMake_TEST} NONE)
+
+cmake_policy(SET CMP0069 NEW)
+
+include(CheckIPOSupported)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake b/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake
new file mode 100644
index 0000000..e145569
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake
@@ -0,0 +1,13 @@
+include(RunCMake)
+
+run_cmake(unparsed-arguments)
+run_cmake(user-lang-unknown)
+run_cmake(default-lang-none)
+run_cmake(not-supported-by-cmake)
+run_cmake(not-supported-by-compiler)
+run_cmake(save-to-result)
+run_cmake(cmp0069-is-old)
+
+if(RunCMake_GENERATOR MATCHES "^Visual Studio ")
+  run_cmake(not-supported-by-generator)
+endif()
diff --git a/Tests/RunCMake/TargetObjects/BadContext-result.txt b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-result.txt
similarity index 100%
rename from Tests/RunCMake/TargetObjects/BadContext-result.txt
rename to Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-result.txt
diff --git a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt
new file mode 100644
index 0000000..f183594
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
+  Policy CMP0069 set to OLD
+Call Stack \(most recent call first\):
+  cmp0069-is-old\.cmake:[0-9]+ \(check_ipo_supported\)
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake
new file mode 100644
index 0000000..14fed04
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/cmp0069-is-old.cmake
@@ -0,0 +1,6 @@
+project(${RunCMake_TEST} LANGUAGES C CXX)
+
+cmake_policy(SET CMP0069 OLD)
+
+include(CheckIPOSupported)
+check_ipo_supported()
diff --git a/Tests/RunCMake/find_dependency/EXACT-no-version-result.txt b/Tests/RunCMake/CheckIPOSupported/default-lang-none-result.txt
similarity index 100%
rename from Tests/RunCMake/find_dependency/EXACT-no-version-result.txt
rename to Tests/RunCMake/CheckIPOSupported/default-lang-none-result.txt
diff --git a/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt b/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt
new file mode 100644
index 0000000..dc2c3ad
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
+  IPO is not supported \(no C/CXX/Fortran languages found in ENABLED_LANGUAGES
+  global property\)\.
+Call Stack \(most recent call first\):
+  .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\)
+  default-lang-none\.cmake:[0-9]+ \(check_ipo_supported\)
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CheckIPOSupported/default-lang-none.cmake b/Tests/RunCMake/CheckIPOSupported/default-lang-none.cmake
new file mode 100644
index 0000000..0a2ac69
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/default-lang-none.cmake
@@ -0,0 +1 @@
+check_ipo_supported()
diff --git a/Tests/RunCMake/find_dependency/empty-arg-3-result.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-result.txt
similarity index 100%
rename from Tests/RunCMake/find_dependency/empty-arg-3-result.txt
rename to Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-result.txt
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt
new file mode 100644
index 0000000..c49a024
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
+  IPO is not supported \(CMake doesn't support IPO for current C compiler\)\.
+Call Stack \(most recent call first\):
+  .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\)
+  not-supported-by-cmake\.cmake:[0-9]+ \(check_ipo_supported\)
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake
new file mode 100644
index 0000000..e583dd0
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake
@@ -0,0 +1,3 @@
+project(${RunCMake_TEST} LANGUAGES C)
+set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE NO)
+check_ipo_supported()
diff --git a/Tests/RunCMake/find_dependency/empty-version-result.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-result.txt
similarity index 100%
rename from Tests/RunCMake/find_dependency/empty-version-result.txt
rename to Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-result.txt
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt
new file mode 100644
index 0000000..675c2d3
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
+  IPO is not supported \(C compiler doesn't support IPO\)\.
+Call Stack \(most recent call first\):
+  .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\)
+  not-supported-by-compiler\.cmake:[0-9]+ \(check_ipo_supported\)
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake
new file mode 100644
index 0000000..86c8f8d
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake
@@ -0,0 +1,4 @@
+project(${RunCMake_TEST} LANGUAGES C)
+set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE YES)
+set(_CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+check_ipo_supported()
diff --git a/Tests/RunCMake/find_dependency/extra-args-result.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-result.txt
similarity index 100%
rename from Tests/RunCMake/find_dependency/extra-args-result.txt
rename to Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-result.txt
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt
new file mode 100644
index 0000000..a2aa58c
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
+  IPO is not supported \(CMake doesn't support IPO for current generator\)\.
+Call Stack \(most recent call first\):
+  .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\)
+  not-supported-by-generator\.cmake:[0-9]+ \(check_ipo_supported\)
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake
new file mode 100644
index 0000000..c32af6e
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake
@@ -0,0 +1,6 @@
+project(${RunCMake_TEST} LANGUAGES C)
+
+set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE YES)
+set(_CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+
+check_ipo_supported()
diff --git a/Tests/RunCMake/CheckIPOSupported/save-to-result.cmake b/Tests/RunCMake/CheckIPOSupported/save-to-result.cmake
new file mode 100644
index 0000000..f76db72
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/save-to-result.cmake
@@ -0,0 +1,22 @@
+project(${RunCMake_TEST} LANGUAGES C)
+check_ipo_supported(RESULT result OUTPUT output)
+
+string(COMPARE EQUAL "${result}" "" is_empty)
+if(is_empty)
+  message(FATAL_ERROR "Result variable is empty")
+endif()
+
+string(COMPARE EQUAL "${result}" "YES" is_yes)
+string(COMPARE EQUAL "${result}" "NO" is_no)
+
+if(is_yes)
+  # Compiler supports IPO
+elseif(is_no)
+  # Compiler doesn't support IPO, output should not be empty.
+  string(COMPARE EQUAL "${output}" "" is_empty)
+  if(is_empty)
+    message(FATAL_ERROR "Output is empty")
+  endif()
+else()
+  message(FATAL_ERROR "Unexpected result: ${result}")
+endif()
diff --git a/Tests/RunCMake/find_dependency/invalid-arg-3-result.txt b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-result.txt
similarity index 100%
rename from Tests/RunCMake/find_dependency/invalid-arg-3-result.txt
rename to Tests/RunCMake/CheckIPOSupported/unparsed-arguments-result.txt
diff --git a/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-stderr.txt b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-stderr.txt
new file mode 100644
index 0000000..a3fee53
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
+  Unparsed arguments: xxx
+Call Stack \(most recent call first\):
+  unparsed-arguments\.cmake:[0-9]+ \(check_ipo_supported\)
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CheckIPOSupported/unparsed-arguments.cmake b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments.cmake
new file mode 100644
index 0000000..3ee7326
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments.cmake
@@ -0,0 +1 @@
+check_ipo_supported(RESULT result OUTPUT output xxx)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/CheckIPOSupported/user-lang-unknown-result.txt
diff --git a/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-stderr.txt b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-stderr.txt
new file mode 100644
index 0000000..278ba0b
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
+  IPO is not supported \(language\(s\) 'UnknownLanguage' not supported\)\.
+Call Stack \(most recent call first\):
+  .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\)
+  user-lang-unknown\.cmake:[0-9]+ \(check_ipo_supported\)
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CheckIPOSupported/user-lang-unknown.cmake b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown.cmake
new file mode 100644
index 0000000..ac743ad
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown.cmake
@@ -0,0 +1 @@
+check_ipo_supported(LANGUAGES UnknownLanguage)
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON-stderr.txt
deleted file mode 100644
index 2cb01ff..0000000
--- a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-ON-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-^CMake Warning:
-  The "Visual Studio 7 .NET 2003" generator is deprecated and will be removed
-  in a future version of CMake.
-
-  Add CMAKE_WARN_VS71=OFF to the cache to disable this warning.$
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-OFF.cmake
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/CommandLine/DeprecateVS8-WARN-OFF.cmake
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON-stderr.txt
new file mode 100644
index 0000000..2f2cbd3
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Warning:
+  The "Visual Studio 8 2005" generator is deprecated and will be removed in a
+  future version of CMake.
+
+  Add CMAKE_WARN_VS8=OFF to the cache to disable this warning.$
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON.cmake
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/CommandLine/DeprecateVS8-WARN-ON.cmake
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 0c4f71c..f94b10a 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -1,3 +1,5 @@
+cmake_minimum_required(VERSION 3.1)
+
 include(RunCMake)
 
 run_cmake_command(NoArgs ${CMAKE_COMMAND})
@@ -76,11 +78,11 @@ if(RunCMake_GENERATOR STREQUAL "Ninja")
   unset(RunCMake_TEST_NO_CLEAN)
 endif()
 
-if(RunCMake_GENERATOR STREQUAL "Visual Studio 7 .NET 2003")
-  set(RunCMake_WARN_VS71 1)
-  run_cmake(DeprecateVS71-WARN-ON)
-  unset(RunCMake_WARN_VS71)
-  run_cmake(DeprecateVS71-WARN-OFF)
+if(RunCMake_GENERATOR MATCHES "^Visual Studio 8 2005")
+  set(RunCMake_WARN_VS8 1)
+  run_cmake(DeprecateVS8-WARN-ON)
+  unset(RunCMake_WARN_VS8)
+  run_cmake(DeprecateVS8-WARN-OFF)
 endif()
 
 if(UNIX)
@@ -301,3 +303,14 @@ set(CMAKE_RELATIVE_PATH_TOP_BINARY \"${RunCMake_TEST_BINARY_DIR}\")
     )
 endfunction()
 run_cmake_depends()
+
+function(reject_fifo)
+  find_program(BASH_EXECUTABLE bash)
+  if(BASH_EXECUTABLE)
+    set(BASH_COMMAND_ARGUMENT "'${CMAKE_COMMAND}' -P <(echo 'return()')")
+    run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT})
+  endif()
+endfunction()
+if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN")
+  reject_fifo()
+endif()
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/CommandLine/reject_fifo-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/CommandLine/reject_fifo-result.txt
diff --git a/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt
new file mode 100644
index 0000000..7a335c3
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error in .*
+  Error while reading Byte-Order-Mark\.  File not seekable\?
diff --git a/Tests/RunCMake/CompileFeatures/LinkImplementationFeatureCycle.cmake b/Tests/RunCMake/CompileFeatures/LinkImplementationFeatureCycle.cmake
index 2d14a9e..b24a680 100644
--- a/Tests/RunCMake/CompileFeatures/LinkImplementationFeatureCycle.cmake
+++ b/Tests/RunCMake/CompileFeatures/LinkImplementationFeatureCycle.cmake
@@ -6,9 +6,10 @@ add_library(empty3 INTERFACE)
 target_compile_features(empty3 INTERFACE cxx_std_11)
 
 target_link_libraries(empty1
-  # When starting, $<COMPILE_FEATURES:cxx_auto_type> is '0', so 'freeze' the
+  # When starting, $<COMPILE_FEATURES:cxx_std_11> is '0', so 'freeze' the
   # CXX_STANDARD at 98 during computation.
-  $<$<COMPILE_FEATURES:cxx_auto_type>:empty2>
+  $<$<COMPILE_FEATURES:cxx_std_11>:empty2>
+
   # This would add cxx_std_11, but that would require CXX_STANDARD = 11,
   # which is not allowed after freeze.  Report an error.
   empty3
diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
index 8dc627d..5a70da2 100644
--- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
@@ -1,3 +1,4 @@
+cmake_policy(SET CMP0057 NEW)
 include(RunCMake)
 
 run_cmake(NotAFeature)
@@ -28,13 +29,13 @@ endif()
 if (NOT CXX_FEATURES)
   run_cmake(NoSupportedCxxFeatures)
   run_cmake(NoSupportedCxxFeaturesGenex)
-else()
+elseif (cxx_std_98 IN_LIST CXX_FEATURES AND cxx_std_11 IN_LIST CXX_FEATURES)
   if(CXX_STANDARD_DEFAULT EQUAL 98)
     run_cmake(LinkImplementationFeatureCycle)
   endif()
   run_cmake(LinkImplementationFeatureCycleSolved)
 
-  if (";${CXX_FEATURES};" MATCHES ";cxx_final;")
+  if (cxx_final IN_LIST CXX_FEATURES)
     set(RunCMake_TEST_OPTIONS "-DHAVE_FINAL=1")
   endif()
   run_cmake(NonValidTarget1)
diff --git a/Tests/RunCMake/DisallowedCommands/CMP0029-OLD-stderr.txt b/Tests/RunCMake/DisallowedCommands/CMP0029-OLD-stderr.txt
new file mode 100644
index 0000000..430c865
--- /dev/null
+++ b/Tests/RunCMake/DisallowedCommands/CMP0029-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0029-OLD.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0029 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/DisallowedCommands/CMP0030-OLD-stderr.txt b/Tests/RunCMake/DisallowedCommands/CMP0030-OLD-stderr.txt
index e95e16f..d00b827 100644
--- a/Tests/RunCMake/DisallowedCommands/CMP0030-OLD-stderr.txt
+++ b/Tests/RunCMake/DisallowedCommands/CMP0030-OLD-stderr.txt
@@ -1,4 +1,15 @@
-^CMake Error at CMP0030-OLD.cmake:2 \(use_mangled_mesa\):
+^CMake Deprecation Warning at CMP0030-OLD.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0030 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\)
++
+CMake Error at CMP0030-OLD.cmake:2 \(use_mangled_mesa\):
   use_mangled_mesa called with incorrect number of arguments
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt
new file mode 100644
index 0000000..723c467
--- /dev/null
+++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt
@@ -0,0 +1,91 @@
+-- The following TYPE1 packages have been found:
+
+ \* Foo, The Foo package, <https://foo.example/>
+
+-- The following TYPE2 packages have not been found:
+
+ \* Bar
+
+-- The following TYPE3 packages have not been found:
+
+ \* Baz
+
+--[ ]
+ \* Foo, The Foo package, <https://foo.example/>
+
+--[ ]
+ \* Bar
+
+--[ ]
+ \* Baz
+
+-- TYPE1 pkgs found
+
+ \* Foo, The Foo package, <https://foo.example/>
+
+-- TYPE2 pkgs not found
+
+ \* Bar
+
+-- TYPE3 pkgs not found
+
+ \* Baz
+
+-- The following TYPE1 packages have been found:
+
+ \* Foo, The Foo package, <https://foo.example/>
+
+-- The following TYPE2 packages have not been found:
+
+ \* Bar
+
+-- The following TYPE3 packages have not been found:
+
+ \* Baz
+
+-- The following first type packages have been found:
+
+ \* Foo, The Foo package, <https://foo.example/>
+
+-- The following second type packages have not been found:
+
+ \* Bar
+
+-- The following third type packages have not been found:
+
+ \* Baz
+
+--[ ]
+ \* Foo, The Foo package, <https://foo.example/>
+
+--[ ]
+ \* Bar
+
+--[ ]
+ \* Baz
+
+-- TYPE1 pkgs found
+
+ \* Foo, The Foo package, <https://foo.example/>
+
+-- TYPE2 pkgs not found
+
+ \* Bar
+
+-- TYPE3 pkgs not found
+
+ \* Baz
+
+-- The following first type packages have been found:
+
+ \* Foo, The Foo package, <https://foo.example/>
+
+-- The following second type packages have not been found:
+
+ \* Bar
+
+-- The following third type packages have not been found:
+
+ \* Baz
+
+-- Configuring done
diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake
new file mode 100644
index 0000000..e61b652
--- /dev/null
+++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake
@@ -0,0 +1,158 @@
+include(FeatureSummary)
+set_property(GLOBAL PROPERTY FeatureSummary_PKG_TYPES TYPE1 TYPE2 TYPE3)
+
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
+
+find_package(Foo)
+find_package(Bar)
+find_package(Baz)
+
+set_package_properties(Foo PROPERTIES TYPE TYPE1)
+set_package_properties(Bar PROPERTIES TYPE TYPE2)
+set_package_properties(Baz PROPERTIES TYPE TYPE3)
+
+feature_summary(WHAT ALL)
+
+feature_summary(WHAT TYPE1_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE2_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE3_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+
+feature_summary(WHAT TYPE1_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE1 pkgs found\n")
+feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE1 pkgs not found\n")
+feature_summary(WHAT TYPE2_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE2 pkgs found\n")
+feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE2 pkgs not found\n")
+feature_summary(WHAT TYPE3_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE3 pkgs found\n")
+feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE3 pkgs not found\n")
+
+feature_summary(WHAT TYPE1_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE2_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE3_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+
+set_property(GLOBAL PROPERTY FeatureSummary_TYPE1_DESCRIPTION "first type packages")
+set_property(GLOBAL PROPERTY FeatureSummary_TYPE2_DESCRIPTION "second type packages")
+set_property(GLOBAL PROPERTY FeatureSummary_TYPE3_DESCRIPTION "third type packages")
+
+feature_summary(WHAT ALL)
+
+feature_summary(WHAT TYPE1_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE2_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE3_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+
+feature_summary(WHAT TYPE1_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE1 pkgs found\n")
+feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE1 pkgs not found\n")
+feature_summary(WHAT TYPE2_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE2 pkgs found\n")
+feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE2 pkgs not found\n")
+feature_summary(WHAT TYPE3_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE3 pkgs found\n")
+feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "TYPE3 pkgs not found\n")
+
+feature_summary(WHAT TYPE1_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE2_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE3_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt
new file mode 100644
index 0000000..47bdee3
--- /dev/null
+++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt
@@ -0,0 +1,46 @@
+-- The following RUNTIME packages have been found:
+
+ \* Foo, The Foo package, <https://foo.example/>
+
+-- The following OPTIONAL packages have not been found:
+
+ \* Bar
+
+-- The following REQUIRED packages have not been found:
+
+ \* Baz
+
+--[ ]
+ \* Foo, The Foo package, <https://foo.example/>
+
+--[ ]
+ \* Bar
+
+--[ ]
+ \* Baz
+
+-- RUNTIME pkgs found
+
+ \* Foo, The Foo package, <https://foo.example/>
+
+-- OPTIONAL pkgs not found
+
+ \* Bar
+
+-- REQUIRED pkgs not found
+
+ \* Baz
+
+-- The following RUNTIME packages have been found:
+
+ \* Foo, The Foo package, <https://foo.example/>
+
+-- The following OPTIONAL packages have not been found:
+
+ \* Bar
+
+-- The following REQUIRED packages have not been found:
+
+ \* Baz
+
+-- Configuring done
diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake
new file mode 100644
index 0000000..536fe72
--- /dev/null
+++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake
@@ -0,0 +1,82 @@
+include(FeatureSummary)
+
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
+
+find_package(Foo)
+find_package(Bar)
+find_package(Baz)
+
+set_package_properties(Foo PROPERTIES TYPE RUNTIME)
+set_package_properties(Bar PROPERTIES TYPE OPTIONAL)
+set_package_properties(Baz PROPERTIES TYPE REQUIRED)
+
+feature_summary(WHAT ALL)
+
+feature_summary(WHAT RUNTIME_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT RUNTIME_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT OPTIONAL_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT OPTIONAL_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT REQUIRED_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY)
+
+feature_summary(WHAT RUNTIME_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "RUNTIME pkgs found\n")
+feature_summary(WHAT RUNTIME_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "RUNTIME pkgs not found\n")
+feature_summary(WHAT OPTIONAL_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "OPTIONAL pkgs found\n")
+feature_summary(WHAT OPTIONAL_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "OPTIONAL pkgs not found\n")
+feature_summary(WHAT REQUIRED_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "REQUIRED pkgs found\n")
+feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DESCRIPTION "REQUIRED pkgs not found\n")
+
+feature_summary(WHAT RUNTIME_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT RUNTIME_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT OPTIONAL_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT OPTIONAL_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT REQUIRED_PACKAGES_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
+feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND
+                INCLUDE_QUIET_PACKAGES
+                QUIET_ON_EMPTY
+                DEFAULT_DESCRIPTION)
diff --git a/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake b/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake
index 9caee4c..c672c16 100644
--- a/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake
@@ -14,8 +14,10 @@ run_cmake(FeatureSummaryFatalOnMissingRequiredPackages)
 run_cmake(FeatureSummaryIncludeQuietPackages)
 run_cmake(FeatureSummaryQuietOnEmpty)
 run_cmake(FeatureSummaryMultipleDepends)
+run_cmake(FeatureSummaryDefaultDescription)
 run_cmake(FeatureSummaryCustomTypes)
 run_cmake(FeatureSummaryCustomBadDefault)
 run_cmake(FeatureSummaryCustomRequired)
 run_cmake(FeatureSummaryCustomRequiredListA)
 run_cmake(FeatureSummaryCustomRequiredListB)
+run_cmake(FeatureSummaryCustomDescription)
diff --git a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
index 0abb7df..a242180 100644
--- a/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
+++ b/Tests/RunCMake/File_Generate/OutputConflict-stderr.txt
@@ -1,5 +1,6 @@
 CMake Error in CMakeLists.txt:
-  Evaluation file to be written multiple times for different configurations
-  or languages with different content:
+  Evaluation file to be written multiple times with different content.  This
+  is generally caused by the content evaluating the configuration type,
+  language, or location of object files:
 
   .*output.txt
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt
index d3aa973..b08ef5a 100644
--- a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt
@@ -1,9 +1,8 @@
-CMake Error at OutputNameMatchesObjects.cmake:2 \(file\):
+CMake Error at OutputNameMatchesObjects.cmake:[0-9]+ \(file\):
   Error evaluating generator expression:
 
     \$<TARGET_OBJECTS:foo>
 
-  The evaluation of the TARGET_OBJECTS generator expression is only suitable
-  for consumption by CMake.  It is not suitable for writing out elsewhere.
+  Objects of target "foo" referenced but is not an OBJECT library.
 Call Stack \(most recent call first\):
-  CMakeLists.txt:6 \(include\)
+  CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake
index d807450..daa7c49 100644
--- a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
 
 file(GENERATE
   OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<BOOL:$<TARGET_OBJECTS:foo>>somefile.cpp"
diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
index db344ef..82e903d 100644
--- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
@@ -1,7 +1,7 @@
 include(RunCMake)
 
 run_cmake(CommandConflict)
-if("${RunCMake_GENERATOR}" MATCHES "Visual Studio|Xcode" AND NOT XCODE_BELOW_2)
+if("${RunCMake_GENERATOR}" MATCHES "Visual Studio|Xcode")
   run_cmake(OutputConflict)
 endif()
 run_cmake(EmptyCondition1)
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake
index 4a41533..2687efe 100644
--- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_APPBUNDLE_PATH.cmake
@@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME
     endif()
   else()
     # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties
+    get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS)
     get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS)
     get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
-    if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
+    if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32")
+      set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
+    elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
     elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake
index b66d02f..74cda25 100644
--- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMAKE_FRAMEWORK_PATH.cmake
@@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME
     endif()
   else()
     # not debian, check the FIND_LIBRARY_USE_LIB64_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties
+    get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS)
     get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS)
     get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
-    if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
+    if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32")
+      set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
+    elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
     elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH.cmake
index bdecb8a..1defde8 100644
--- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH.cmake
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH.cmake
@@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME
     endif()
   else()
     # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS propertie
+    get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS)
     get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS)
     get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
-    if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
+    if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32")
+      set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
+    elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
     elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake
index df67235..166a617 100644
--- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH.cmake
@@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME
     endif()
   else()
     # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties
+    get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS)
     get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS)
     get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
-    if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
+    if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32")
+      set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig")
+    elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig")
     elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig")
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake
index 1351b6f..e4673b3 100644
--- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH.cmake
@@ -30,9 +30,12 @@ if(NOT DEFINED CMAKE_SYSTEM_NAME
     endif()
   else()
     # not debian, check the FIND_LIBRARY_USE_LIB64_PATHS and FIND_LIBRARY_USE_LIB32_PATHS properties
+    get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS)
     get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS)
     get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
-    if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
+    if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32")
+      set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
+    elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
     elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
       set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig")
diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat
index f2f86b0..b038370 100755
--- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat
+++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat
@@ -1,7 +1,11 @@
 @ECHO OFF
+
+:LOOP
+
 IF "%1"=="" (
   EXIT /B 255
 )
+
 IF "%1"=="--version" (
   ECHO 0.0-cmake-dummy
   EXIT /B 0
@@ -13,6 +17,11 @@ IF "%1"=="--exists" (
   ECHO Found:    %PKG_CONFIG_PATH%
   IF NOT "%*"=="%PKG_CONFIG_PATH%" (
     EXIT /B 1
+  ) ELSE (
+    EXIT /B 0
   )
 )
-EXIT /B 0
+SHIFT
+IF NOT "%~1"=="" GOTO LOOP
+
+EXIT /B 255
diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh
index abe14bf..56bba30 100755
--- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh
+++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh
@@ -4,18 +4,20 @@
 # to the --exists argument with the PKG_CONFIG_PATH environment variable
 # and returns 1 if they are different.
 
-case $1 in
-  --version)
-    echo "0.0-cmake-dummy"
-    ;;
-  --exists)
-    shift
-    eval last=\${$#}
-    echo "Expected: ${last}"
-    echo "Found:    ${PKG_CONFIG_PATH}"
-    [ "${last}" = "${PKG_CONFIG_PATH}" ] || exit 1
-    ;;
-  *)
-    exit 255
-    ;;
-esac
+while [ $# -gt 0 ]; do
+  case $1 in
+    --version)
+      echo "0.0-cmake-dummy"
+      exit 0
+      ;;
+    --exists)
+      shift
+      eval last=\${$#}
+      echo "Expected: ${last}"
+      echo "Found:    ${PKG_CONFIG_PATH}"
+      [ "${last}" = "${PKG_CONFIG_PATH}" ] && exit 0 || exit 1
+      ;;
+  esac
+  shift
+done
+exit 255
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/FindPkgConfig/pc-bar/libx32/pkgconfig/.placeholder
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/FindPkgConfig/pc-bar/libx32/pkgconfig/.placeholder
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/FindPkgConfig/pc-foo/libx32/pkgconfig/.placeholder
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/FindPkgConfig/pc-foo/libx32/pkgconfig/.placeholder
diff --git a/Tests/RunCMake/Framework/FrameworkLayout.cmake b/Tests/RunCMake/Framework/FrameworkLayout.cmake
index ae32134..3d62a8a 100644
--- a/Tests/RunCMake/Framework/FrameworkLayout.cmake
+++ b/Tests/RunCMake/Framework/FrameworkLayout.cmake
@@ -1,14 +1,25 @@
 cmake_minimum_required(VERSION 3.4)
 enable_language(C)
 
+set(CMAKE_CONFIGURATION_TYPES "Debug" CACHE INTERNAL "Supported configuration types")
+set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}) # get rid of ${EFFECTIVE_PLATFORM_NAME}
+
 add_library(Framework ${FRAMEWORK_TYPE}
             foo.c
             foo.h
-            res.txt)
+            res.txt
+            flatresource.txt
+            deepresource.txt
+            some.txt)
 set_target_properties(Framework PROPERTIES
                       FRAMEWORK TRUE
                       PUBLIC_HEADER foo.h
                       RESOURCE "res.txt")
+set_source_files_properties(flatresource.txt PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
+set_source_files_properties(deepresource.txt PROPERTIES MACOSX_PACKAGE_LOCATION Resources/deep)
+set_source_files_properties(some.txt PROPERTIES MACOSX_PACKAGE_LOCATION somedir)
 
 add_custom_command(TARGET Framework POST_BUILD
                    COMMAND /usr/bin/file $<TARGET_FILE:Framework>)
+
+file(GENERATE OUTPUT FrameworkName.cmake CONTENT "set(framework-dir \"$<TARGET_BUNDLE_DIR:Framework>\")\n")
diff --git a/Tests/RunCMake/Framework/FrameworkTypeSHARED-build-stdout.txt b/Tests/RunCMake/Framework/FrameworkTypeSHARED-build-stdout.txt
index 8d90f5f..f664db9 100644
--- a/Tests/RunCMake/Framework/FrameworkTypeSHARED-build-stdout.txt
+++ b/Tests/RunCMake/Framework/FrameworkTypeSHARED-build-stdout.txt
@@ -1 +1,3 @@
-.*/Framework: Mach-O[^\n]* dynamically linked shared library.*
+.*/Framework:( Mach-O universal binary with [^
+]*)? Mach-O[^
+]* dynamically linked shared library.*
diff --git a/Tests/RunCMake/Framework/FrameworkTypeSTATIC-build-stdout.txt b/Tests/RunCMake/Framework/FrameworkTypeSTATIC-build-stdout.txt
index c9f50b6..532cfed 100644
--- a/Tests/RunCMake/Framework/FrameworkTypeSTATIC-build-stdout.txt
+++ b/Tests/RunCMake/Framework/FrameworkTypeSTATIC-build-stdout.txt
@@ -1 +1,2 @@
-.*/Framework: current ar archive random library.*
+.*/Framework:( Mach-O universal binary with [^
+]*)? current ar archive random library.*
diff --git a/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake b/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake
index da1ccb4..eb71394 100644
--- a/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake
+++ b/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake
@@ -1,8 +1,11 @@
-set(framework-dir "${RunCMake_TEST_BINARY_DIR}/Framework.framework")
+include("${RunCMake_TEST_BINARY_DIR}/FrameworkName.cmake")
 set(framework-resources "${framework-dir}/Resources")
 set(framework-resource-file "${framework-resources}/res.txt")
+set(framework-flat-resource-file "${framework-resources}/flatresource.txt")
+set(framework-deep-resource-file "${framework-resources}/deep/deepresource.txt")
 set(framework-library "${framework-dir}/Framework")
 set(framework-versions "${framework-dir}/Versions")
+set(framework-some-file "${framework-versions}/Current/somedir/some.txt")
 set(plist-file "${framework-resources}/Info.plist")
 set(framework-header "${framework-dir}/Headers/foo.h")
 
@@ -22,6 +25,18 @@ if(NOT EXISTS ${framework-resource-file})
   message(SEND_ERROR "Framework resource file not found at ${framework-resource-file}")
 endif()
 
+if(NOT EXISTS ${framework-flat-resource-file})
+  message(SEND_ERROR "Framework flat resource file not found at ${framework-flat-resource-file}")
+endif()
+
+if(NOT EXISTS ${framework-deep-resource-file})
+  message(SEND_ERROR "Framework deep resource file not found at ${framework-deep-resource-file}")
+endif()
+
+if(NOT EXISTS ${framework-some-file})
+  message(SEND_ERROR "Framework some file not found at ${framework-some-file}")
+endif()
+
 if(NOT EXISTS ${framework-versions})
   message(SEND_ERROR "Framework versions not found at ${framework-versions}")
 endif()
diff --git a/Tests/RunCMake/Framework/RunCMakeTest.cmake b/Tests/RunCMake/Framework/RunCMakeTest.cmake
index e64892d..4fc83f8 100644
--- a/Tests/RunCMake/Framework/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Framework/RunCMakeTest.cmake
@@ -13,13 +13,10 @@ function(framework_layout_test Name Toolchain Type)
   run_cmake_command(${Name} ${CMAKE_COMMAND} --build .)
 endfunction()
 
-# build check cannot cope with multi-configuration generators directory layout
-if(NOT RunCMake_GENERATOR STREQUAL "Xcode")
-  framework_layout_test(iOSFrameworkLayout-build ios SHARED)
-  framework_layout_test(iOSFrameworkLayout-build ios STATIC)
-  framework_layout_test(OSXFrameworkLayout-build osx SHARED)
-  framework_layout_test(OSXFrameworkLayout-build osx STATIC)
-endif()
+framework_layout_test(iOSFrameworkLayout-build ios SHARED)
+framework_layout_test(iOSFrameworkLayout-build ios STATIC)
+framework_layout_test(OSXFrameworkLayout-build osx SHARED)
+framework_layout_test(OSXFrameworkLayout-build osx STATIC)
 
 function(framework_type_test Toolchain Type)
   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${Toolchain}${Type}FrameworkType-build)
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/Framework/deepresource.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/Framework/deepresource.txt
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/Framework/flatresource.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/Framework/flatresource.txt
diff --git a/Tests/RunCMake/Framework/iOSFrameworkLayout-build-check.cmake b/Tests/RunCMake/Framework/iOSFrameworkLayout-build-check.cmake
index b81a5f7..2da60d2 100644
--- a/Tests/RunCMake/Framework/iOSFrameworkLayout-build-check.cmake
+++ b/Tests/RunCMake/Framework/iOSFrameworkLayout-build-check.cmake
@@ -1,6 +1,9 @@
-set(framework-dir "${RunCMake_TEST_BINARY_DIR}/Framework.framework")
+include("${RunCMake_TEST_BINARY_DIR}/FrameworkName.cmake")
 set(framework-resources "${framework-dir}/Resources")
 set(framework-resource-file "${framework-dir}/res.txt")
+set(framework-flat-resource-file "${framework-dir}/flatresource.txt")
+set(framework-deep-resource-file "${framework-dir}/deep/deepresource.txt")
+set(framework-some-file "${framework-dir}/somedir/some.txt")
 set(framework-library "${framework-dir}/Framework")
 set(framework-versions "${framework-dir}/Versions")
 set(plist-file "${framework-dir}/Info.plist")
@@ -22,6 +25,18 @@ if(NOT EXISTS ${framework-resource-file})
   message(SEND_ERROR "Framework resource file not found at ${framework-resource-file}")
 endif()
 
+if(NOT EXISTS ${framework-flat-resource-file})
+  message(SEND_ERROR "Framework flat resource file not found at ${framework-flat-resource-file}")
+endif()
+
+if(NOT EXISTS ${framework-deep-resource-file})
+  message(SEND_ERROR "Framework deep resource file not found at ${framework-deep-resource-file}")
+endif()
+
+if(NOT EXISTS ${framework-some-file})
+  message(SEND_ERROR "Framework some file not found at ${framework-some-file}")
+endif()
+
 if(EXISTS ${framework-versions})
   message(SEND_ERROR "Framework versions found at ${framework-versions}")
 endif()
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/Framework/some.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/Framework/some.txt
diff --git a/Tests/RunCMake/GNUInstallDirs/Common.cmake b/Tests/RunCMake/GNUInstallDirs/Common.cmake
index eff2d54..919cd91 100644
--- a/Tests/RunCMake/GNUInstallDirs/Common.cmake
+++ b/Tests/RunCMake/GNUInstallDirs/Common.cmake
@@ -1,8 +1,5 @@
 set(CMAKE_SIZEOF_VOID_P 8)
 set(CMAKE_LIBRARY_ARCHITECTURE "arch")
-if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
-  set(CMAKE_SYSTEM_NAME "OpenBSD-Fake")
-endif()
 include(GNUInstallDirs)
 set(dirs
   BINDIR
@@ -15,6 +12,7 @@ set(dirs
   LIBEXECDIR
   LOCALEDIR
   LOCALSTATEDIR
+  RUNSTATEDIR
   MANDIR
   SBINDIR
   SHAREDSTATEDIR
diff --git a/Tests/RunCMake/GNUInstallDirs/Opt-BSD-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Opt-BSD-stderr.txt
new file mode 100644
index 0000000..09ae303
--- /dev/null
+++ b/Tests/RunCMake/GNUInstallDirs/Opt-BSD-stderr.txt
@@ -0,0 +1,30 @@
+^CMAKE_INSTALL_BINDIR='bin'
+CMAKE_INSTALL_DATADIR='share'
+CMAKE_INSTALL_DATAROOTDIR='share'
+CMAKE_INSTALL_DOCDIR='share/doc/Opt'
+CMAKE_INSTALL_INCLUDEDIR='include'
+CMAKE_INSTALL_INFODIR='info'
+CMAKE_INSTALL_LIBDIR='(lib|lib64)'
+CMAKE_INSTALL_LIBEXECDIR='libexec'
+CMAKE_INSTALL_LOCALEDIR='share/locale'
+CMAKE_INSTALL_LOCALSTATEDIR='var'
+CMAKE_INSTALL_RUNSTATEDIR='var/run'
+CMAKE_INSTALL_MANDIR='man'
+CMAKE_INSTALL_SBINDIR='sbin'
+CMAKE_INSTALL_SHAREDSTATEDIR='com'
+CMAKE_INSTALL_SYSCONFDIR='etc'
+CMAKE_INSTALL_FULL_BINDIR='/opt/Opt/bin'
+CMAKE_INSTALL_FULL_DATADIR='/opt/Opt/share'
+CMAKE_INSTALL_FULL_DATAROOTDIR='/opt/Opt/share'
+CMAKE_INSTALL_FULL_DOCDIR='/opt/Opt/share/doc/Opt'
+CMAKE_INSTALL_FULL_INCLUDEDIR='/opt/Opt/include'
+CMAKE_INSTALL_FULL_INFODIR='/opt/Opt/info'
+CMAKE_INSTALL_FULL_LIBDIR='/opt/Opt/(lib|lib64)'
+CMAKE_INSTALL_FULL_LIBEXECDIR='/opt/Opt/libexec'
+CMAKE_INSTALL_FULL_LOCALEDIR='/opt/Opt/share/locale'
+CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var/opt/Opt'
+CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run/opt/Opt'
+CMAKE_INSTALL_FULL_MANDIR='/opt/Opt/man'
+CMAKE_INSTALL_FULL_SBINDIR='/opt/Opt/sbin'
+CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/opt/Opt/com'
+CMAKE_INSTALL_FULL_SYSCONFDIR='/etc/opt/Opt'$
diff --git a/Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt
index aee8552..3e18410 100644
--- a/Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt
+++ b/Tests/RunCMake/GNUInstallDirs/Opt-stderr.txt
@@ -8,6 +8,7 @@ CMAKE_INSTALL_LIBDIR='(lib|lib64)'
 CMAKE_INSTALL_LIBEXECDIR='libexec'
 CMAKE_INSTALL_LOCALEDIR='share/locale'
 CMAKE_INSTALL_LOCALSTATEDIR='var'
+CMAKE_INSTALL_RUNSTATEDIR='var/run'
 CMAKE_INSTALL_MANDIR='share/man'
 CMAKE_INSTALL_SBINDIR='sbin'
 CMAKE_INSTALL_SHAREDSTATEDIR='com'
@@ -22,6 +23,7 @@ CMAKE_INSTALL_FULL_LIBDIR='/opt/Opt/(lib|lib64)'
 CMAKE_INSTALL_FULL_LIBEXECDIR='/opt/Opt/libexec'
 CMAKE_INSTALL_FULL_LOCALEDIR='/opt/Opt/share/locale'
 CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var/opt/Opt'
+CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run/opt/Opt'
 CMAKE_INSTALL_FULL_MANDIR='/opt/Opt/share/man'
 CMAKE_INSTALL_FULL_SBINDIR='/opt/Opt/sbin'
 CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/opt/Opt/com'
diff --git a/Tests/RunCMake/GNUInstallDirs/Root-BSD-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Root-BSD-stderr.txt
new file mode 100644
index 0000000..4be66bc
--- /dev/null
+++ b/Tests/RunCMake/GNUInstallDirs/Root-BSD-stderr.txt
@@ -0,0 +1,30 @@
+^CMAKE_INSTALL_BINDIR='usr/bin'
+CMAKE_INSTALL_DATADIR='usr/share'
+CMAKE_INSTALL_DATAROOTDIR='usr/share'
+CMAKE_INSTALL_DOCDIR='usr/share/doc/Root'
+CMAKE_INSTALL_INCLUDEDIR='usr/include'
+CMAKE_INSTALL_INFODIR='usr/info'
+CMAKE_INSTALL_LIBDIR='usr/(lib|lib64)'
+CMAKE_INSTALL_LIBEXECDIR='usr/libexec'
+CMAKE_INSTALL_LOCALEDIR='usr/share/locale'
+CMAKE_INSTALL_LOCALSTATEDIR='var'
+CMAKE_INSTALL_RUNSTATEDIR='var/run'
+CMAKE_INSTALL_MANDIR='usr/man'
+CMAKE_INSTALL_SBINDIR='usr/sbin'
+CMAKE_INSTALL_SHAREDSTATEDIR='usr/com'
+CMAKE_INSTALL_SYSCONFDIR='etc'
+CMAKE_INSTALL_FULL_BINDIR='/usr/bin'
+CMAKE_INSTALL_FULL_DATADIR='/usr/share'
+CMAKE_INSTALL_FULL_DATAROOTDIR='/usr/share'
+CMAKE_INSTALL_FULL_DOCDIR='/usr/share/doc/Root'
+CMAKE_INSTALL_FULL_INCLUDEDIR='/usr/include'
+CMAKE_INSTALL_FULL_INFODIR='/usr/info'
+CMAKE_INSTALL_FULL_LIBDIR='/usr/(lib|lib64)'
+CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec'
+CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale'
+CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var'
+CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run'
+CMAKE_INSTALL_FULL_MANDIR='/usr/man'
+CMAKE_INSTALL_FULL_SBINDIR='/usr/sbin'
+CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/com'
+CMAKE_INSTALL_FULL_SYSCONFDIR='/etc'$
diff --git a/Tests/RunCMake/GNUInstallDirs/Root-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Root-stderr.txt
index a95400e..8c13368 100644
--- a/Tests/RunCMake/GNUInstallDirs/Root-stderr.txt
+++ b/Tests/RunCMake/GNUInstallDirs/Root-stderr.txt
@@ -8,6 +8,7 @@ CMAKE_INSTALL_LIBDIR='usr/(lib|lib64)'
 CMAKE_INSTALL_LIBEXECDIR='usr/libexec'
 CMAKE_INSTALL_LOCALEDIR='usr/share/locale'
 CMAKE_INSTALL_LOCALSTATEDIR='var'
+CMAKE_INSTALL_RUNSTATEDIR='var/run'
 CMAKE_INSTALL_MANDIR='usr/share/man'
 CMAKE_INSTALL_SBINDIR='usr/sbin'
 CMAKE_INSTALL_SHAREDSTATEDIR='usr/com'
@@ -22,6 +23,7 @@ CMAKE_INSTALL_FULL_LIBDIR='/usr/(lib|lib64)'
 CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec'
 CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale'
 CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var'
+CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run'
 CMAKE_INSTALL_FULL_MANDIR='/usr/share/man'
 CMAKE_INSTALL_FULL_SBINDIR='/usr/sbin'
 CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/com'
diff --git a/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake b/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake
index f88569a..b544ba6 100644
--- a/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GNUInstallDirs/RunCMakeTest.cmake
@@ -1,6 +1,17 @@
 include(RunCMake)
 
-run_cmake(Opt)
-run_cmake(Root)
-run_cmake(Usr)
-run_cmake(UsrLocal)
+if(SYSTEM_NAME MATCHES "^(.*BSD|DragonFly)$")
+  set(EXPECT_BSD 1)
+endif()
+
+foreach(case
+    Opt
+    Root
+    Usr
+    UsrLocal
+    )
+  if(EXPECT_BSD)
+    set(RunCMake-stderr-file ${case}-BSD-stderr.txt)
+  endif()
+  run_cmake(${case})
+endforeach()
diff --git a/Tests/RunCMake/GNUInstallDirs/Usr-BSD-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Usr-BSD-stderr.txt
new file mode 100644
index 0000000..3d7b4c8
--- /dev/null
+++ b/Tests/RunCMake/GNUInstallDirs/Usr-BSD-stderr.txt
@@ -0,0 +1,30 @@
+^CMAKE_INSTALL_BINDIR='bin'
+CMAKE_INSTALL_DATADIR='share'
+CMAKE_INSTALL_DATAROOTDIR='share'
+CMAKE_INSTALL_DOCDIR='share/doc/Usr'
+CMAKE_INSTALL_INCLUDEDIR='include'
+CMAKE_INSTALL_INFODIR='info'
+CMAKE_INSTALL_LIBDIR='(lib|lib64|lib/arch)'
+CMAKE_INSTALL_LIBEXECDIR='libexec'
+CMAKE_INSTALL_LOCALEDIR='share/locale'
+CMAKE_INSTALL_LOCALSTATEDIR='var'
+CMAKE_INSTALL_RUNSTATEDIR='var/run'
+CMAKE_INSTALL_MANDIR='man'
+CMAKE_INSTALL_SBINDIR='sbin'
+CMAKE_INSTALL_SHAREDSTATEDIR='com'
+CMAKE_INSTALL_SYSCONFDIR='etc'
+CMAKE_INSTALL_FULL_BINDIR='/usr/bin'
+CMAKE_INSTALL_FULL_DATADIR='/usr/share'
+CMAKE_INSTALL_FULL_DATAROOTDIR='/usr/share'
+CMAKE_INSTALL_FULL_DOCDIR='/usr/share/doc/Usr'
+CMAKE_INSTALL_FULL_INCLUDEDIR='/usr/include'
+CMAKE_INSTALL_FULL_INFODIR='/usr/info'
+CMAKE_INSTALL_FULL_LIBDIR='/usr/(lib|lib64|lib/arch)'
+CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec'
+CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale'
+CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var'
+CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run'
+CMAKE_INSTALL_FULL_MANDIR='/usr/man'
+CMAKE_INSTALL_FULL_SBINDIR='/usr/sbin'
+CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/com'
+CMAKE_INSTALL_FULL_SYSCONFDIR='/etc'$
diff --git a/Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt b/Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt
index e10c4c5..a591436 100644
--- a/Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt
+++ b/Tests/RunCMake/GNUInstallDirs/Usr-stderr.txt
@@ -8,6 +8,7 @@ CMAKE_INSTALL_LIBDIR='(lib|lib64|lib/arch)'
 CMAKE_INSTALL_LIBEXECDIR='libexec'
 CMAKE_INSTALL_LOCALEDIR='share/locale'
 CMAKE_INSTALL_LOCALSTATEDIR='var'
+CMAKE_INSTALL_RUNSTATEDIR='var/run'
 CMAKE_INSTALL_MANDIR='share/man'
 CMAKE_INSTALL_SBINDIR='sbin'
 CMAKE_INSTALL_SHAREDSTATEDIR='com'
@@ -22,6 +23,7 @@ CMAKE_INSTALL_FULL_LIBDIR='/usr/(lib|lib64|lib/arch)'
 CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/libexec'
 CMAKE_INSTALL_FULL_LOCALEDIR='/usr/share/locale'
 CMAKE_INSTALL_FULL_LOCALSTATEDIR='/var'
+CMAKE_INSTALL_FULL_RUNSTATEDIR='/var/run'
 CMAKE_INSTALL_FULL_MANDIR='/usr/share/man'
 CMAKE_INSTALL_FULL_SBINDIR='/usr/sbin'
 CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/com'
diff --git a/Tests/RunCMake/GNUInstallDirs/UsrLocal-BSD-stderr.txt b/Tests/RunCMake/GNUInstallDirs/UsrLocal-BSD-stderr.txt
new file mode 100644
index 0000000..e1425d5
--- /dev/null
+++ b/Tests/RunCMake/GNUInstallDirs/UsrLocal-BSD-stderr.txt
@@ -0,0 +1,30 @@
+^CMAKE_INSTALL_BINDIR='bin'
+CMAKE_INSTALL_DATADIR='share'
+CMAKE_INSTALL_DATAROOTDIR='share'
+CMAKE_INSTALL_DOCDIR='share/doc/UsrLocal'
+CMAKE_INSTALL_INCLUDEDIR='include'
+CMAKE_INSTALL_INFODIR='info'
+CMAKE_INSTALL_LIBDIR='(lib|lib64)'
+CMAKE_INSTALL_LIBEXECDIR='libexec'
+CMAKE_INSTALL_LOCALEDIR='share/locale'
+CMAKE_INSTALL_LOCALSTATEDIR='var'
+CMAKE_INSTALL_RUNSTATEDIR='var/run'
+CMAKE_INSTALL_MANDIR='man'
+CMAKE_INSTALL_SBINDIR='sbin'
+CMAKE_INSTALL_SHAREDSTATEDIR='com'
+CMAKE_INSTALL_SYSCONFDIR='etc'
+CMAKE_INSTALL_FULL_BINDIR='/usr/local/bin'
+CMAKE_INSTALL_FULL_DATADIR='/usr/local/share'
+CMAKE_INSTALL_FULL_DATAROOTDIR='/usr/local/share'
+CMAKE_INSTALL_FULL_DOCDIR='/usr/local/share/doc/UsrLocal'
+CMAKE_INSTALL_FULL_INCLUDEDIR='/usr/local/include'
+CMAKE_INSTALL_FULL_INFODIR='/usr/local/info'
+CMAKE_INSTALL_FULL_LIBDIR='/usr/local/(lib|lib64)'
+CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/local/libexec'
+CMAKE_INSTALL_FULL_LOCALEDIR='/usr/local/share/locale'
+CMAKE_INSTALL_FULL_LOCALSTATEDIR='/usr/local/var'
+CMAKE_INSTALL_FULL_RUNSTATEDIR='/usr/local/var/run'
+CMAKE_INSTALL_FULL_MANDIR='/usr/local/man'
+CMAKE_INSTALL_FULL_SBINDIR='/usr/local/sbin'
+CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/local/com'
+CMAKE_INSTALL_FULL_SYSCONFDIR='/usr/local/etc'$
diff --git a/Tests/RunCMake/GNUInstallDirs/UsrLocal-stderr.txt b/Tests/RunCMake/GNUInstallDirs/UsrLocal-stderr.txt
index 8dcf25b..f957e0e 100644
--- a/Tests/RunCMake/GNUInstallDirs/UsrLocal-stderr.txt
+++ b/Tests/RunCMake/GNUInstallDirs/UsrLocal-stderr.txt
@@ -8,6 +8,7 @@ CMAKE_INSTALL_LIBDIR='(lib|lib64)'
 CMAKE_INSTALL_LIBEXECDIR='libexec'
 CMAKE_INSTALL_LOCALEDIR='share/locale'
 CMAKE_INSTALL_LOCALSTATEDIR='var'
+CMAKE_INSTALL_RUNSTATEDIR='var/run'
 CMAKE_INSTALL_MANDIR='share/man'
 CMAKE_INSTALL_SBINDIR='sbin'
 CMAKE_INSTALL_SHAREDSTATEDIR='com'
@@ -22,6 +23,7 @@ CMAKE_INSTALL_FULL_LIBDIR='/usr/local/(lib|lib64)'
 CMAKE_INSTALL_FULL_LIBEXECDIR='/usr/local/libexec'
 CMAKE_INSTALL_FULL_LOCALEDIR='/usr/local/share/locale'
 CMAKE_INSTALL_FULL_LOCALSTATEDIR='/usr/local/var'
+CMAKE_INSTALL_FULL_RUNSTATEDIR='/usr/local/var/run'
 CMAKE_INSTALL_FULL_MANDIR='/usr/local/share/man'
 CMAKE_INSTALL_FULL_SBINDIR='/usr/local/sbin'
 CMAKE_INSTALL_FULL_SHAREDSTATEDIR='/usr/local/com'
diff --git a/Tests/RunCMake/GenerateExportHeader/GEH.cmake b/Tests/RunCMake/GenerateExportHeader/GEH.cmake
index cddba29..e0677a7 100644
--- a/Tests/RunCMake/GenerateExportHeader/GEH.cmake
+++ b/Tests/RunCMake/GenerateExportHeader/GEH.cmake
@@ -110,7 +110,7 @@ if (WIN32 OR CYGWIN)
   else()
     set(_platform WinEmpty)
   endif()
-elseif(COMPILER_HAS_HIDDEN_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY)
+elseif(COMPILER_HAS_HIDDEN_VISIBILITY)
   set(_platform UNIX)
 elseif(COMPILER_HAS_DEPRECATED)
   set(_platform UNIX_DeprecatedOnly)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt
diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt
new file mode 100644
index 0000000..854447f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake:[0-9]* \(add_custom_target\):
+  Error evaluating generator expression:
+
+    \$<TARGET_BUNDLE_CONTENT_DIR:empty>
+
+  TARGET_BUNDLE_CONTENT_DIR not allowed for IMPORTED targets.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]* \(include\)
diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake
new file mode 100644
index 0000000..ac2d3ce
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_CONTENT_DIR.cmake
@@ -0,0 +1,2 @@
+add_library(empty UNKNOWN IMPORTED)
+add_custom_target(custom COMMAND echo $<TARGET_BUNDLE_CONTENT_DIR:empty>)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-result.txt
diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-stderr.txt b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-stderr.txt
new file mode 100644
index 0000000..9b97df1
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at ImportedTarget-TARGET_BUNDLE_DIR.cmake:[0-9]* \(add_custom_target\):
+  Error evaluating generator expression:
+
+    \$<TARGET_BUNDLE_DIR:empty>
+
+  TARGET_BUNDLE_DIR not allowed for IMPORTED targets.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]* \(include\)
diff --git a/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR.cmake b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR.cmake
new file mode 100644
index 0000000..17c8128
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/ImportedTarget-TARGET_BUNDLE_DIR.cmake
@@ -0,0 +1,2 @@
+add_library(empty UNKNOWN IMPORTED)
+add_custom_target(custom COMMAND echo $<TARGET_BUNDLE_DIR:empty>)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-result.txt
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt
new file mode 100644
index 0000000..03c02d9
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake:[0-9]* \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_BUNDLE_CONTENT_DIR:empty>
+
+  TARGET_BUNDLE_CONTENT_DIR is allowed only for Bundle targets.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]* \(include\)
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake
new file mode 100644
index 0000000..63b3b1b
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_CONTENT_DIR.cmake
@@ -0,0 +1,9 @@
+
+enable_language(C)
+
+add_library(empty STATIC empty.c)
+
+file(GENERATE
+  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
+  CONTENT "[$<TARGET_BUNDLE_CONTENT_DIR:empty>]"
+)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-result.txt
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-stderr.txt b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-stderr.txt
new file mode 100644
index 0000000..f895c88
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at NonValidTarget-TARGET_BUNDLE_DIR.cmake:[0-9]* \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_BUNDLE_DIR:empty>
+
+  TARGET_BUNDLE_DIR is allowed only for Bundle targets.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]* \(include\)
diff --git a/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR.cmake b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR.cmake
new file mode 100644
index 0000000..19f333a
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/NonValidTarget-TARGET_BUNDLE_DIR.cmake
@@ -0,0 +1,9 @@
+
+enable_language(C)
+
+add_library(empty STATIC empty.c)
+
+file(GENERATE
+  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
+  CONTENT "[$<TARGET_BUNDLE_DIR:empty>]"
+)
diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
index 084b5c3..63cd2da 100644
--- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
@@ -17,6 +17,8 @@ run_cmake(NonValidTarget-C_COMPILER_ID)
 run_cmake(NonValidTarget-CXX_COMPILER_ID)
 run_cmake(NonValidTarget-C_COMPILER_VERSION)
 run_cmake(NonValidTarget-CXX_COMPILER_VERSION)
+run_cmake(NonValidTarget-TARGET_BUNDLE_DIR)
+run_cmake(NonValidTarget-TARGET_BUNDLE_CONTENT_DIR)
 run_cmake(NonValidTarget-TARGET_PROPERTY)
 run_cmake(NonValidTarget-TARGET_POLICY)
 run_cmake(COMPILE_LANGUAGE-add_custom_target)
@@ -32,6 +34,8 @@ run_cmake(OUTPUT_NAME-recursion)
 run_cmake(TARGET_PROPERTY-LOCATION)
 run_cmake(LINK_ONLY-not-linking)
 
+run_cmake(ImportedTarget-TARGET_BUNDLE_DIR)
+run_cmake(ImportedTarget-TARGET_BUNDLE_CONTENT_DIR)
 run_cmake(ImportedTarget-TARGET_PDB_FILE)
 if(LINKER_SUPPORTS_PDB)
   run_cmake(NonValidTarget-TARGET_PDB_FILE)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt
new file mode 100644
index 0000000..ab3a98f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+  Generator
+
+    .*
+
+  given toolset specification
+
+    Test Toolset,not_a_key
+
+  that contains a field after the first ',' with no '='\.$
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake
new file mode 100644
index 0000000..2fc38e5
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt
index 5737e95..bd0063a 100644
--- a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt
@@ -3,8 +3,8 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\):
 
     .*
 
-  does not recognize the toolset
+  given toolset specification
 
     Test Toolset,host=x6[45]
 
-  that was specified\.$
+  that contains invalid field 'host=x6[45]'\.$
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt
new file mode 100644
index 0000000..164d3aa
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+  Generator
+
+    .*
+
+  given toolset specification
+
+    Test Toolset,host=x64,host=x64
+
+  that contains duplicate field key 'host'\.$
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake
new file mode 100644
index 0000000..2fc38e5
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt
similarity index 100%
copy from Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt
copy to Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake
new file mode 100644
index 0000000..2fc38e5
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
index e8ce47d..f89100e 100644
--- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
@@ -3,9 +3,15 @@ include(RunCMake)
 set(RunCMake_GENERATOR_TOOLSET "")
 run_cmake(NoToolset)
 
-if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_BELOW_3)
+if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]")
   set(RunCMake_GENERATOR_TOOLSET "Test Toolset")
   run_cmake(TestToolset)
+  set(RunCMake_GENERATOR_TOOLSET "Test Toolset,cuda=Test Cuda")
+  run_cmake(TestToolsetCudaBoth)
+  set(RunCMake_GENERATOR_TOOLSET ",cuda=Test Cuda")
+  run_cmake(TestToolsetCudaOnly)
+  set(RunCMake_GENERATOR_TOOLSET "cuda=Test Cuda")
+  run_cmake(TestToolsetCudaOnly)
   if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[245]")
     set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64")
     run_cmake(TestToolsetHostArchBoth)
@@ -17,10 +23,19 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_
     run_cmake(TestToolsetHostArchNone)
     set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x65")
     run_cmake(BadToolsetHostArch)
+    set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x64")
+    run_cmake(BadToolsetHostArchTwice)
   else()
     set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64")
     run_cmake(BadToolsetHostArch)
   endif()
+  set(RunCMake_GENERATOR_TOOLSET "Test Toolset,not_a_key")
+  run_cmake(BadToolsetFormat)
+elseif("${RunCMake_GENERATOR}" STREQUAL "Xcode")
+  set(RunCMake_GENERATOR_TOOLSET "Test Toolset")
+  run_cmake(TestToolset)
+  set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64")
+  run_cmake(BadToolsetHostArchXcode)
 else()
   set(RunCMake_GENERATOR_TOOLSET "Bad Toolset")
   run_cmake(BadToolset)
@@ -32,7 +47,7 @@ set(RunCMake_TEST_OPTIONS -T "Extra Toolset")
 run_cmake(TwoToolsets)
 unset(RunCMake_TEST_OPTIONS)
 
-if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_BELOW_3)
+if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode")
   set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/TestToolset-toolchain.cmake)
   run_cmake(TestToolsetToolchain)
   unset(RunCMake_TEST_OPTIONS)
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt
new file mode 100644
index 0000000..90503e2
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt
@@ -0,0 +1,2 @@
+-- CMAKE_VS_PLATFORM_TOOLSET='Test Toolset'
+-- CMAKE_VS_PLATFORM_TOOLSET_CUDA='Test Cuda'
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake
new file mode 100644
index 0000000..befa0af
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake
@@ -0,0 +1,2 @@
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_CUDA='${CMAKE_VS_PLATFORM_TOOLSET_CUDA}'")
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt
new file mode 100644
index 0000000..94e1e43
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt
@@ -0,0 +1,2 @@
+-- CMAKE_VS_PLATFORM_TOOLSET='(v[0-9]+|Windows7.1SDK)'
+-- CMAKE_VS_PLATFORM_TOOLSET_CUDA='Test Cuda'
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake
new file mode 100644
index 0000000..befa0af
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake
@@ -0,0 +1,2 @@
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_CUDA='${CMAKE_VS_PLATFORM_TOOLSET_CUDA}'")
diff --git a/Tests/RunCMake/Ninja/AssumedSources.cmake b/Tests/RunCMake/Ninja/AssumedSources.cmake
new file mode 100644
index 0000000..5fb0219
--- /dev/null
+++ b/Tests/RunCMake/Ninja/AssumedSources.cmake
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.8)
+project(AssumedSources)
+
+set_source_files_properties(
+  "${CMAKE_CURRENT_BINARY_DIR}/target.c"
+  "${CMAKE_CURRENT_BINARY_DIR}/target-no-depends.c"
+  PROPERTIES GENERATED 1)
+
+add_executable(working
+  "${CMAKE_CURRENT_BINARY_DIR}/target.c"
+  "${CMAKE_CURRENT_BINARY_DIR}/target-no-depends.c")
+
+add_custom_target(
+  gen-target.c ALL
+  COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/dep.c" "${CMAKE_CURRENT_BINARY_DIR}/target.c")
+add_custom_target(
+  gen-target-no-depends.c ALL
+  COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/dep.c" "${CMAKE_CURRENT_BINARY_DIR}/target-no-depends.c")
+
+add_dependencies(working gen-target.c)
diff --git a/Tests/RunCMake/Ninja/CommandConcat.cmake b/Tests/RunCMake/Ninja/CommandConcat.cmake
new file mode 100644
index 0000000..790cf9d
--- /dev/null
+++ b/Tests/RunCMake/Ninja/CommandConcat.cmake
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.7)
+project(concat_cmd NONE)
+set(output1 ${CMAKE_BINARY_DIR}/out1.txt)
+set(output2 ${CMAKE_BINARY_DIR}/out2.txt)
+file(REMOVE ${output1} ${output2})
+# Check that second command runs if first command contains "||" which has higher precedence than "&&" on Windows
+add_custom_target(concat_cmd ALL
+  COMMAND ${CMAKE_COMMAND} -E echo "Hello || pipe world" && ${CMAKE_COMMAND} -E touch ${output1} || exit 1
+  COMMAND ${CMAKE_COMMAND} -E touch ${output2})
+# Check output
+add_custom_target(check_output ALL
+  COMMAND ${CMAKE_COMMAND} -E copy ${output1} ${output1}.copy
+  COMMAND ${CMAKE_COMMAND} -E copy ${output2} ${output2}.copy)
+add_dependencies(check_output concat_cmd)
diff --git a/Tests/RunCMake/Ninja/LooseObjectDepends.cmake b/Tests/RunCMake/Ninja/LooseObjectDepends.cmake
new file mode 100644
index 0000000..360c7ba
--- /dev/null
+++ b/Tests/RunCMake/Ninja/LooseObjectDepends.cmake
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 3.8)
+project(LooseObjectDepends C)
+
+add_custom_command(
+  OUTPUT  "${CMAKE_CURRENT_BINARY_DIR}/command.h"
+  COMMAND "${CMAKE_COMMAND}" -E touch
+          "${CMAKE_CURRENT_BINARY_DIR}/command.h"
+          COMMENT "Creating command.h")
+add_custom_target(create-command.h
+  DEPENDS
+    "${CMAKE_CURRENT_BINARY_DIR}/command.h")
+
+add_custom_target(create-target.h
+  BYPRODUCTS  "${CMAKE_CURRENT_BINARY_DIR}/target.h"
+  COMMAND "${CMAKE_COMMAND}" -E touch
+          "${CMAKE_CURRENT_BINARY_DIR}/target.h"
+  COMMENT "Creating target.h")
+
+add_library(dep SHARED dep.c)
+add_dependencies(dep create-command.h create-target.h)
+target_include_directories(dep
+  PUBLIC
+    "${CMAKE_CURRENT_BINARY_DIR}")
+
+add_library(top top.c)
+target_link_libraries(top PRIVATE dep)
diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
index 7b4e51e..b3720fb 100644
--- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
@@ -40,6 +40,16 @@ run_CMP0058(NEW-by)
 
 run_cmake(CustomCommandDepfile)
 
+function(run_CommandConcat)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CommandConcat-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  run_cmake(CommandConcat)
+  run_cmake_command(CommandConcat-build ${CMAKE_COMMAND} --build .)
+endfunction()
+run_CommandConcat()
+
 function(run_SubDir)
   # Use a single build tree for a few tests without cleaning.
   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SubDir-build)
@@ -73,7 +83,7 @@ run_SubDir()
 
 function(run_ninja dir)
   execute_process(
-    COMMAND "${RunCMake_MAKE_PROGRAM}"
+    COMMAND "${RunCMake_MAKE_PROGRAM}" ${ARGN}
     WORKING_DIRECTORY "${dir}"
     OUTPUT_VARIABLE ninja_stdout
     ERROR_VARIABLE ninja_stderr
@@ -95,6 +105,39 @@ ${ninja_stderr}
   endif()
 endfunction(run_ninja)
 
+function (run_LooseObjectDepends)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LooseObjectDepends-build)
+  run_cmake(LooseObjectDepends)
+  run_ninja("${RunCMake_TEST_BINARY_DIR}" "CMakeFiles/top.dir/top.c${CMAKE_C_OUTPUT_EXTENSION}")
+  if (EXISTS "${RunCMake_TEST_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}dep${CMAKE_SHARED_LIBRARY_SUFFIX}")
+    message(FATAL_ERROR
+      "The `dep` library was created when requesting an object file to be "
+      "built; this should no longer be necessary.")
+  endif ()
+  if (EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/dep.dir/dep.c${CMAKE_C_OUTPUT_EXTENSION}")
+    message(FATAL_ERROR
+      "The `dep.c` object file was created when requesting an object file to "
+      "be built; this should no longer be necessary.")
+  endif ()
+endfunction ()
+run_LooseObjectDepends()
+
+function (run_AssumedSources)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AssumedSources-build)
+  run_cmake(AssumedSources)
+  run_ninja("${RunCMake_TEST_BINARY_DIR}" "target.c")
+  if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/target.c")
+    message(FATAL_ERROR
+      "Dependencies for an assumed source did not hook up properly for 'target.c'.")
+  endif ()
+  run_ninja("${RunCMake_TEST_BINARY_DIR}" "target-no-depends.c")
+  if (EXISTS "${RunCMake_TEST_BINARY_DIR}/target-no-depends.c")
+    message(FATAL_ERROR
+      "Dependencies for an assumed source were magically hooked up for 'target-no-depends.c'.")
+  endif ()
+endfunction ()
+run_AssumedSources()
+
 function(sleep delay)
   execute_process(
     COMMAND ${CMAKE_COMMAND} -E sleep ${delay}
diff --git a/Tests/RunCMake/Ninja/dep.c b/Tests/RunCMake/Ninja/dep.c
new file mode 100644
index 0000000..728f031
--- /dev/null
+++ b/Tests/RunCMake/Ninja/dep.c
@@ -0,0 +1,4 @@
+int dep()
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/Ninja/top.c b/Tests/RunCMake/Ninja/top.c
new file mode 100644
index 0000000..4a88eb2
--- /dev/null
+++ b/Tests/RunCMake/Ninja/top.c
@@ -0,0 +1,7 @@
+#include "command.h"
+#include "target.h"
+
+int top()
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/ObjectLibrary/Dependencies.cmake b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake
new file mode 100644
index 0000000..6ddf545
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake
@@ -0,0 +1,7 @@
+add_library(myobj OBJECT ${CMAKE_BINARY_DIR}/depends_obj.c)
+add_library(mylib STATIC $<TARGET_OBJECTS:myobj> depends_lib.c)
+add_executable(myexe depends_main.c)
+target_link_libraries(myexe mylib)
+
+enable_testing()
+add_test(NAME myexe COMMAND $<TARGET_FILE:myexe>)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-stderr.txt b/Tests/RunCMake/ObjectLibrary/Export-stderr.txt
deleted file mode 100644
index bdadca4..0000000
--- a/Tests/RunCMake/ObjectLibrary/Export-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at Export.cmake:2 \(export\):
-  export given OBJECT library "A" which may not be exported.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/ObjectLibrary/ExportNotSupported-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/ObjectLibrary/ExportNotSupported-result.txt
diff --git a/Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt b/Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt
new file mode 100644
index 0000000..5420159
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at ExportNotSupported.cmake:[0-9]+ \(export\):
+  export given OBJECT library "A" which may not be exported under Xcode with
+  multiple architectures.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake b/Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake
new file mode 100644
index 0000000..a3f104e
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake
@@ -0,0 +1,2 @@
+add_library(A OBJECT a.c)
+export(TARGETS A FILE AExport.cmake)
diff --git a/Tests/RunCMake/ObjectLibrary/Import-stderr.txt b/Tests/RunCMake/ObjectLibrary/Import-stderr.txt
deleted file mode 100644
index 74b496a..0000000
--- a/Tests/RunCMake/ObjectLibrary/Import-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at Import.cmake:1 \(add_library\):
-  The OBJECT library type may not be used for IMPORTED libraries.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/Import.cmake b/Tests/RunCMake/ObjectLibrary/Import.cmake
index 806b44a..42f4468 100644
--- a/Tests/RunCMake/ObjectLibrary/Import.cmake
+++ b/Tests/RunCMake/ObjectLibrary/Import.cmake
@@ -1 +1,12 @@
+
 add_library(A OBJECT IMPORTED)
+
+# We don't actually build this example so just configure dummy
+# object files to test.  They do not have to exist.
+set_property(TARGET A APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+set_target_properties(A PROPERTIES
+  IMPORTED_OBJECTS_DEBUG "${CMAKE_CURRENT_BINARY_DIR}/does_not_exist.o"
+  IMPORTED_OBJECTS "${CMAKE_CURRENT_BINARY_DIR}/does_not_exist.o"
+  )
+
+add_library(B $<TARGET_OBJECTS:A> b.c)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt
diff --git a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt b/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt
new file mode 100644
index 0000000..0fadac2
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at ImportNotSupported.cmake:[0-9]+ \(add_library\):
+  The OBJECT library type may not be used for IMPORTED libraries under Xcode
+  with multiple architectures.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/Import.cmake b/Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Import.cmake
copy to Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake
diff --git a/Tests/RunCMake/ObjectLibrary/Install-stderr.txt b/Tests/RunCMake/ObjectLibrary/Install-stderr.txt
deleted file mode 100644
index d2f9f4a..0000000
--- a/Tests/RunCMake/ObjectLibrary/Install-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at Install.cmake:2 \(install\):
-  install TARGETS given OBJECT library "A" which may not be installed.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/ObjectLibrary/InstallNotSupported-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/ObjectLibrary/InstallNotSupported-result.txt
diff --git a/Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt b/Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt
new file mode 100644
index 0000000..35a0e4f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at InstallNotSupported.cmake:[0-9]+ \(install\):
+  install TARGETS given OBJECT library "A" which may not be installed under
+  Xcode with multiple architectures.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/InstallNotSupported.cmake b/Tests/RunCMake/ObjectLibrary/InstallNotSupported.cmake
new file mode 100644
index 0000000..c1d214b
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/InstallNotSupported.cmake
@@ -0,0 +1,2 @@
+add_library(A OBJECT a.c)
+install(TARGETS A DESTINATION lib)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/ObjectLibrary/OwnSources-result.txt
diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
new file mode 100644
index 0000000..40d650e
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at OwnSources.cmake:[0-9]+ \(add_library\):
+  The SOURCES of "A" use a generator expression that depends on the SOURCES
+  themselves.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources.cmake b/Tests/RunCMake/ObjectLibrary/OwnSources.cmake
new file mode 100644
index 0000000..e7bdf8d
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/OwnSources.cmake
@@ -0,0 +1,2 @@
+add_library(A OBJECT a.c)
+target_sources(A PRIVATE $<TARGET_OBJECTS:A>)
diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
index 42973f8..b8eed73 100644
--- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
@@ -5,14 +5,46 @@ run_cmake(BadSourceExpression2)
 run_cmake(BadSourceExpression3)
 run_cmake(BadObjSource1)
 run_cmake(BadObjSource2)
-run_cmake(Export)
-run_cmake(Import)
-run_cmake(Install)
+if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
+  run_cmake(ExportNotSupported)
+  run_cmake(ImportNotSupported)
+  run_cmake(InstallNotSupported)
+else()
+  run_cmake(Export)
+  run_cmake(Import)
+  run_cmake(Install)
+endif()
 run_cmake(LinkObjLHS)
 run_cmake(LinkObjRHS1)
 run_cmake(LinkObjRHS2)
 run_cmake(MissingSource)
 run_cmake(ObjWithObj)
+run_cmake(OwnSources)
 run_cmake(PostBuild)
 run_cmake(PreBuild)
 run_cmake(PreLink)
+
+function(run_Dependencies)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Dependencies-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+  if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR
+      RunCMake_GENERATOR STREQUAL "Watcom WMake")
+    set(fs_delay 3)
+  else()
+    set(fs_delay 1.125)
+  endif()
+
+  run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj1.c ${RunCMake_TEST_BINARY_DIR}/depends_obj.c)
+  run_cmake(Dependencies)
+  run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build . --config Debug)
+  run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E sleep ${fs_delay})
+  run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj0.c ${RunCMake_TEST_BINARY_DIR}/depends_obj.c)
+  run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build . --config Debug)
+  run_cmake_command(Dependencies-build ${CMAKE_CTEST_COMMAND} -C Debug -V)
+endfunction()
+
+run_Dependencies()
diff --git a/Tests/RunCMake/ObjectLibrary/b.c b/Tests/RunCMake/ObjectLibrary/b.c
new file mode 100644
index 0000000..6751907
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/b.c
@@ -0,0 +1,4 @@
+int b(void)
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/ObjectLibrary/depends_lib.c b/Tests/RunCMake/ObjectLibrary/depends_lib.c
new file mode 100644
index 0000000..a41b32c
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/depends_lib.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+extern int myobj_foo(void);
+
+void mylib_foo(void)
+{
+  exit(myobj_foo());
+}
diff --git a/Tests/RunCMake/ObjectLibrary/depends_main.c b/Tests/RunCMake/ObjectLibrary/depends_main.c
new file mode 100644
index 0000000..acc66c7
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/depends_main.c
@@ -0,0 +1,7 @@
+extern void mylib_foo(void);
+
+int main(void)
+{
+  mylib_foo();
+  return 0;
+}
diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj0.c b/Tests/RunCMake/ObjectLibrary/depends_obj0.c
new file mode 100644
index 0000000..649d507
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/depends_obj0.c
@@ -0,0 +1,4 @@
+int myobj_foo(void)
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj1.c b/Tests/RunCMake/ObjectLibrary/depends_obj1.c
new file mode 100644
index 0000000..e1f9f6a
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/depends_obj1.c
@@ -0,0 +1,4 @@
+int myobj_foo(void)
+{
+  return 1;
+}
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index 5f66da0..26312c4 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -51,8 +51,8 @@ function(run_cmake test)
   if(APPLE)
     list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0025=NEW)
   endif()
-  if(RunCMake_GENERATOR STREQUAL "Visual Studio 7 .NET 2003" AND NOT RunCMake_WARN_VS71)
-    list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_WARN_VS71=OFF)
+  if(RunCMake_GENERATOR MATCHES "^Visual Studio 8 2005" AND NOT RunCMake_WARN_VS8)
+    list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_WARN_VS8=OFF)
   endif()
   if(RunCMake_MAKE_PROGRAM)
     list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}")
@@ -101,7 +101,7 @@ function(run_cmake test)
   endif()
   foreach(o out err)
     string(REGEX REPLACE "\r\n" "\n" actual_std${o} "${actual_std${o}}")
-    string(REGEX REPLACE "(^|\n)((==[0-9]+==|BullseyeCoverage|[a-z]+\\([0-9]+\\) malloc:|Error kstat returned|[^\n]*is a member of multiple groups|[^\n]*from Time Machine by path|[^\n]*Bullseye Testing Technology)[^\n]*\n)+" "\\1" actual_std${o} "${actual_std${o}}")
+    string(REGEX REPLACE "(^|\n)((==[0-9]+==|BullseyeCoverage|[a-z]+\\([0-9]+\\) malloc:|Error kstat returned|Hit xcodebuild bug|[^\n]*is a member of multiple groups|[^\n]*from Time Machine by path|[^\n]*Bullseye Testing Technology)[^\n]*\n)+" "\\1" actual_std${o} "${actual_std${o}}")
     string(REGEX REPLACE "\n+$" "" actual_std${o} "${actual_std${o}}")
     set(expect_${o} "")
     if(DEFINED expect_std${o})
diff --git a/Tests/RunCMake/TargetObjects/BadContext-stderr.txt b/Tests/RunCMake/TargetObjects/BadContext-stderr.txt
deleted file mode 100644
index b78189e..0000000
--- a/Tests/RunCMake/TargetObjects/BadContext-stderr.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-(CMake Error at BadContext.cmake:4 \(file\):
-  Error evaluating generator expression:
-
-    \$<TARGET_OBJECTS:NoTarget>
-
-  The evaluation of the TARGET_OBJECTS generator expression is only suitable
-  for consumption by CMake.  It is not suitable for writing out elsewhere.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
-*)+
-(CMake Error at BadContext.cmake:5 \(file\):
-  Error evaluating generator expression:
-
-    \$<TARGET_OBJECTS:NoTarget>
-
-  The evaluation of the TARGET_OBJECTS generator expression is only suitable
-  for consumption by CMake.  It is not suitable for writing out elsewhere.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
-*)+
-CMake Error:
-  Error evaluating generator expression:
-
-    \$<TARGET_OBJECTS:NoTarget>
-
-  The evaluation of the TARGET_OBJECTS generator expression is only suitable
-  for consumption by CMake.  It is not suitable for writing out elsewhere.
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/TargetObjects/NoTarget-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/TargetObjects/NoTarget-result.txt
diff --git a/Tests/RunCMake/TargetObjects/NoTarget-stderr.txt b/Tests/RunCMake/TargetObjects/NoTarget-stderr.txt
new file mode 100644
index 0000000..eadccaf
--- /dev/null
+++ b/Tests/RunCMake/TargetObjects/NoTarget-stderr.txt
@@ -0,0 +1,24 @@
+(CMake Error at NoTarget.cmake:4 \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_OBJECTS:NoTarget>
+
+  Objects of target "NoTarget" referenced but no such target exists.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+*)+
+(CMake Error at NoTarget.cmake:5 \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_OBJECTS:NoTarget>
+
+  Objects of target "NoTarget" referenced but no such target exists.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+*)+
+CMake Error:
+  Error evaluating generator expression:
+
+    \$<TARGET_OBJECTS:NoTarget>
+
+  Objects of target "NoTarget" referenced but no such target exists.
diff --git a/Tests/RunCMake/TargetObjects/BadContext.cmake b/Tests/RunCMake/TargetObjects/NoTarget.cmake
similarity index 100%
rename from Tests/RunCMake/TargetObjects/BadContext.cmake
rename to Tests/RunCMake/TargetObjects/NoTarget.cmake
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/TargetObjects/NotObjlibTarget-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/TargetObjects/NotObjlibTarget-result.txt
diff --git a/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt b/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt
new file mode 100644
index 0000000..a66794c
--- /dev/null
+++ b/Tests/RunCMake/TargetObjects/NotObjlibTarget-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at NotObjlibTarget.cmake:3 \(file\):
+  Error evaluating generator expression:
+
+    \$<TARGET_OBJECTS:StaticLib>
+
+  Objects of target "StaticLib" referenced but is not an OBJECT library.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/TargetObjects/NotObjlibTarget.cmake b/Tests/RunCMake/TargetObjects/NotObjlibTarget.cmake
new file mode 100644
index 0000000..8e5fdd0
--- /dev/null
+++ b/Tests/RunCMake/TargetObjects/NotObjlibTarget.cmake
@@ -0,0 +1,3 @@
+add_library(StaticLib empty.cpp)
+
+file(GENERATE OUTPUT test_output CONTENT $<TARGET_OBJECTS:StaticLib>)
diff --git a/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake
index 85c76e2..30b9fee 100644
--- a/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake
@@ -1,3 +1,4 @@
 include(RunCMake)
 
-run_cmake(BadContext)
+run_cmake(NoTarget)
+run_cmake(NotObjlibTarget)
diff --git a/Tests/RunCMake/TargetObjects/empty.cpp b/Tests/RunCMake/TargetObjects/empty.cpp
new file mode 100644
index 0000000..4086dcc
--- /dev/null
+++ b/Tests/RunCMake/TargetObjects/empty.cpp
@@ -0,0 +1,4 @@
+int empty()
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 57047fb..5f6be87 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -20,6 +20,8 @@
    \* CMP0060
    \* CMP0063
    \* CMP0065
+   \* CMP0068
+   \* CMP0069
 
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/TargetSources/CMP0026-LOCATION-stderr.txt b/Tests/RunCMake/TargetSources/CMP0026-LOCATION-stderr.txt
new file mode 100644
index 0000000..d7ccedb
--- /dev/null
+++ b/Tests/RunCMake/TargetSources/CMP0026-LOCATION-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0026-LOCATION.cmake:[0-9]+ \(cmake_policy\):
+  The OLD behavior for policy CMP0026 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/TargetSources/RunCMakeTest.cmake b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake
index 4416ef9..bb55a6e 100644
--- a/Tests/RunCMake/TargetSources/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake
@@ -1,6 +1,6 @@
 include(RunCMake)
 
-if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode" AND NOT XCODE_BELOW_2)
+if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode")
   run_cmake(ConfigNotAllowed)
   run_cmake(OriginDebugIDE)
 else()
diff --git a/Tests/RunCMake/VSSolution/MorePost-check.cmake b/Tests/RunCMake/VSSolution/MorePost-check.cmake
index 0f7e370..d239b28 100644
--- a/Tests/RunCMake/VSSolution/MorePost-check.cmake
+++ b/Tests/RunCMake/VSSolution/MorePost-check.cmake
@@ -1,5 +1,5 @@
 parseGlobalSections(pre post MorePost)
 testGlobalSection(post TestSec2 Key1=Value1 "Key2=Value with spaces")
 testGlobalSection(post TestSec4 Key6=Value1 "Key7=Value with spaces" Key8=ValueWithoutSpaces)
-testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}")
 testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/VSSolution/MorePre-check.cmake b/Tests/RunCMake/VSSolution/MorePre-check.cmake
index 45e7419..89b3c7e 100644
--- a/Tests/RunCMake/VSSolution/MorePre-check.cmake
+++ b/Tests/RunCMake/VSSolution/MorePre-check.cmake
@@ -1,5 +1,5 @@
 parseGlobalSections(pre post MorePre)
 testGlobalSection(pre TestSec1 Key1=Value1 "Key2=Value with spaces")
 testGlobalSection(pre TestSec3 Key3=Value1 "Key4=Value with spaces" Key5=ValueWithoutSpaces)
-testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}")
 testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/VSSolution/OnePost-check.cmake b/Tests/RunCMake/VSSolution/OnePost-check.cmake
index 6af5156..f7d3712 100644
--- a/Tests/RunCMake/VSSolution/OnePost-check.cmake
+++ b/Tests/RunCMake/VSSolution/OnePost-check.cmake
@@ -1,4 +1,4 @@
 parseGlobalSections(pre post OnePost)
 testGlobalSection(post TestSec2 Key1=Value1 "Key2=Value with spaces")
-testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}")
 testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/VSSolution/OnePre-check.cmake b/Tests/RunCMake/VSSolution/OnePre-check.cmake
index 70b18b2..c5db139 100644
--- a/Tests/RunCMake/VSSolution/OnePre-check.cmake
+++ b/Tests/RunCMake/VSSolution/OnePre-check.cmake
@@ -1,4 +1,4 @@
 parseGlobalSections(pre post OnePre)
 testGlobalSection(pre TestSec1 Key1=Value1 "Key2=Value with spaces")
-testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}")
 testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/VSSolution/Override1-check.cmake b/Tests/RunCMake/VSSolution/Override1-check.cmake
index a19e2e1..5905204 100644
--- a/Tests/RunCMake/VSSolution/Override1-check.cmake
+++ b/Tests/RunCMake/VSSolution/Override1-check.cmake
@@ -1,4 +1,4 @@
 parseGlobalSections(pre post Override1)
 testGlobalSection(post TestSec Key2=Value2 Key3=Value3)
-testGlobalSection(post ExtensibilityGlobals Key1=Value1)
+testGlobalSection(post ExtensibilityGlobals Key1=Value1 "SolutionGuid={00000000-0000-0000-0000-000000000000}")
 testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/VSSolution/Override2-check.cmake b/Tests/RunCMake/VSSolution/Override2-check.cmake
index d9656e1..c981ec0 100644
--- a/Tests/RunCMake/VSSolution/Override2-check.cmake
+++ b/Tests/RunCMake/VSSolution/Override2-check.cmake
@@ -1,4 +1,4 @@
 parseGlobalSections(pre post Override2)
 testGlobalSection(pre TestSec Key2=Value2 Key3=Value3)
-testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}")
 testGlobalSection(post ExtensibilityAddIns Key1=Value1)
diff --git a/Tests/RunCMake/VSSolution/Override3-check.cmake b/Tests/RunCMake/VSSolution/Override3-check.cmake
new file mode 100644
index 0000000..baee9ed
--- /dev/null
+++ b/Tests/RunCMake/VSSolution/Override3-check.cmake
@@ -0,0 +1,3 @@
+parseGlobalSections(pre post Override3)
+testGlobalSection(post ExtensibilityGlobals Key1=Value1 "SolutionGuid={custom-guid}")
+testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/VSSolution/Override3.cmake b/Tests/RunCMake/VSSolution/Override3.cmake
new file mode 100644
index 0000000..a59ce19
--- /dev/null
+++ b/Tests/RunCMake/VSSolution/Override3.cmake
@@ -0,0 +1,4 @@
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_POST_ExtensibilityGlobals
+  Key1=Value1
+  SolutionGuid={custom-guid}
+  )
diff --git a/Tests/RunCMake/VSSolution/PrePost-check.cmake b/Tests/RunCMake/VSSolution/PrePost-check.cmake
index 322a689..957c964 100644
--- a/Tests/RunCMake/VSSolution/PrePost-check.cmake
+++ b/Tests/RunCMake/VSSolution/PrePost-check.cmake
@@ -2,5 +2,5 @@ parseGlobalSections(pre post PrePost)
 testGlobalSection(post Postsec Key1=Value2)
 testGlobalSection(pre Presec Key1=Value1 "Key2=Value with some spaces")
 testGlobalSection(post Emptysec)
-testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityGlobals "SolutionGuid={00000000-0000-0000-0000-000000000000}")
 testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/VSSolution/RunCMakeTest.cmake b/Tests/RunCMake/VSSolution/RunCMakeTest.cmake
index 4ec3e3b..c25833d 100644
--- a/Tests/RunCMake/VSSolution/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VSSolution/RunCMakeTest.cmake
@@ -8,10 +8,11 @@ run_cmake(MorePost)
 run_cmake(PrePost)
 run_cmake(Override1)
 run_cmake(Override2)
+run_cmake(Override3)
 run_cmake(StartupProject)
 run_cmake(StartupProjectMissing)
 run_cmake(AddPackageToDefault)
 
-if(RunCMake_GENERATOR MATCHES "Visual Studio ([^7]|[7][0-9])" AND NOT NO_USE_FOLDERS)
+if(NOT NO_USE_FOLDERS)
   run_cmake(StartupProjectUseFolders)
 endif()
diff --git a/Tests/RunCMake/VSSolution/solution_parsing.cmake b/Tests/RunCMake/VSSolution/solution_parsing.cmake
index 4e5bb59..4b27550 100644
--- a/Tests/RunCMake/VSSolution/solution_parsing.cmake
+++ b/Tests/RunCMake/VSSolution/solution_parsing.cmake
@@ -44,6 +44,9 @@ macro(parseGlobalSections arg_out_pre arg_out_post testName)
       endif()
       string(STRIP "${CMAKE_MATCH_1}" key)
       string(STRIP "${CMAKE_MATCH_2}" value)
+      if(key STREQUAL "SolutionGuid" AND value MATCHES "^{[0-9A-F-]+}$")
+        set(value "{00000000-0000-0000-0000-000000000000}")
+      endif()
       list(APPEND ${out_${sectionType}}_${sectionName} "${key}=${value}")
     endif()
   endforeach()
diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
index f51a107..5f4bdc3 100644
--- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
@@ -187,3 +187,19 @@ if(NOT XCODE_VERSION VERSION_LESS 5)
   unset(RunCMake_TEST_NO_CLEAN)
   unset(RunCMake_TEST_OPTIONS)
 endif()
+
+function(XcodeSchemaGeneration)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeSchemaGeneration-build)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake_TEST_OPTIONS "-DCMAKE_XCODE_GENERATE_SCHEME=ON")
+
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+  run_cmake(XcodeSchemaGeneration)
+  run_cmake_command(XcodeSchemaGeneration-build xcodebuild -scheme foo build)
+endfunction()
+
+if(NOT XCODE_VERSION VERSION_LESS 7)
+  XcodeSchemaGeneration()
+endif()
diff --git a/Tests/RunCMake/XcodeProject/XcodeBundles.cmake b/Tests/RunCMake/XcodeProject/XcodeBundles.cmake
index 833eb85..0b854d8 100644
--- a/Tests/RunCMake/XcodeProject/XcodeBundles.cmake
+++ b/Tests/RunCMake/XcodeProject/XcodeBundles.cmake
@@ -58,6 +58,10 @@ if(NOT TEST_IOS OR NOT XCODE_VERSION VERSION_LESS 6)
 
   add_custom_target(SharedFrameworkTest ALL
     COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_DIR:SharedFramework>" "$<TARGET_BUNDLE_DIR:SharedFramework>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_CONTENT_DIR:SharedFramework>" "$<TARGET_BUNDLE_CONTENT_DIR:SharedFramework>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
       "$<TARGET_FILE:SharedFramework>" "$<TARGET_FILE:SharedFramework>.old")
 
   add_dependencies(SharedFrameworkTest SharedFramework)
@@ -71,6 +75,10 @@ if(NOT TEST_IOS OR NOT XCODE_VERSION VERSION_LESS 6)
 
   add_custom_target(SharedFrameworkExtTest ALL
     COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_DIR:SharedFrameworkExt>" "$<TARGET_BUNDLE_DIR:SharedFrameworkExt>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_CONTENT_DIR:SharedFrameworkExt>" "$<TARGET_BUNDLE_CONTENT_DIR:SharedFrameworkExt>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
       "$<TARGET_FILE:SharedFrameworkExt>" "$<TARGET_FILE:SharedFrameworkExt>.old")
 
   add_dependencies(SharedFrameworkExtTest SharedFrameworkExt)
@@ -84,6 +92,10 @@ if(NOT XCODE_VERSION VERSION_LESS 6)
 
   add_custom_target(StaticFrameworkTest ALL
     COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_DIR:StaticFramework>" "$<TARGET_BUNDLE_DIR:StaticFramework>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_CONTENT_DIR:StaticFramework>" "$<TARGET_BUNDLE_CONTENT_DIR:StaticFramework>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
       "$<TARGET_FILE:StaticFramework>" "$<TARGET_FILE:StaticFramework>.old")
 
   add_dependencies(StaticFrameworkTest StaticFramework)
@@ -97,6 +109,10 @@ if(NOT XCODE_VERSION VERSION_LESS 6)
 
   add_custom_target(StaticFrameworkExtTest ALL
     COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_DIR:StaticFrameworkExt>" "$<TARGET_BUNDLE_DIR:StaticFrameworkExt>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_CONTENT_DIR:StaticFrameworkExt>" "$<TARGET_BUNDLE_CONTENT_DIR:StaticFrameworkExt>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
       "$<TARGET_FILE:StaticFrameworkExt>" "$<TARGET_FILE:StaticFrameworkExt>.old")
 
   add_dependencies(StaticFrameworkExtTest StaticFrameworkExt)
@@ -110,6 +126,10 @@ if(NOT CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE)
 
   add_custom_target(BundleTest ALL
     COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_DIR:Bundle>" "$<TARGET_BUNDLE_DIR:Bundle>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_CONTENT_DIR:Bundle>" "$<TARGET_BUNDLE_CONTENT_DIR:Bundle>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
       "$<TARGET_FILE:Bundle>" "$<TARGET_FILE:Bundle>.old")
 
   add_dependencies(BundleTest Bundle)
@@ -123,6 +143,10 @@ if(NOT CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE)
 
   add_custom_target(BundleExtTest ALL
     COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_DIR:BundleExt>" "$<TARGET_BUNDLE_DIR:BundleExt>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
+      "$<TARGET_BUNDLE_CONTENT_DIR:BundleExt>" "$<TARGET_BUNDLE_CONTENT_DIR:BundleExt>.old"
+    COMMAND ${CMAKE_COMMAND} -E copy
       "$<TARGET_FILE:BundleExt>" "$<TARGET_FILE:BundleExt>.old")
 
   add_dependencies(BundleExtTest BundleExt)
diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake
new file mode 100644
index 0000000..2fe5a9f
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/XcodeSchemaGeneration.cmake
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.7)
+
+project(XcodeSchemaGeneration CXX)
+
+add_executable(foo main.cpp)
diff --git a/Tests/RunCMake/ctest_disabled_test/CMakeLists.txt.in b/Tests/RunCMake/ctest_disabled_test/CMakeLists.txt.in
new file mode 100644
index 0000000..d34fcac
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/CMakeLists.txt.in
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.7)
+project(@CASE_NAME@ NONE)
+include(CTest)
+
+add_test(NAME SuccessfulTest COMMAND "${CMAKE_COMMAND}" --version)
+ at CASE_CMAKELISTS_SUFFIX_CODE@
diff --git a/Tests/RunCMake/ctest_disabled_test/CTestConfig.cmake.in b/Tests/RunCMake/ctest_disabled_test/CTestConfig.cmake.in
new file mode 100644
index 0000000..c0d7e42
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/CTestConfig.cmake.in
@@ -0,0 +1 @@
+set(CTEST_PROJECT_NAME "@CASE_NAME@")
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableAllTests-result.txt b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stderr.txt b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stderr.txt
new file mode 100644
index 0000000..eafba1c
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stderr.txt
@@ -0,0 +1 @@
+No tests were found!!!
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stdout.txt
new file mode 100644
index 0000000..6c824f6
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableAllTests-stdout.txt
@@ -0,0 +1,2 @@
+    Start 1: SuccessfulTest
+1/1 Test #1: SuccessfulTest ...................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt
new file mode 100644
index 0000000..9449e65
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableCleanupTest-stdout.txt
@@ -0,0 +1,11 @@
+    Start 1: SuccessfulTest
+1/2 Test #1: SuccessfulTest ...................   Passed +[0-9.]+ sec
+    Start 2: CleanupTest
+2/2 Test #2: CleanupTest ......................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 1
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests did not run:
+.*2 \- CleanupTest \(Disabled\)
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableFailingTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableFailingTest-stdout.txt
new file mode 100644
index 0000000..486722e
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableFailingTest-stdout.txt
@@ -0,0 +1,9 @@
+50% tests passed, 1 tests failed out of 2
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests did not run:
+.*3 \- DisabledFailingTest \(Disabled\)
++
+The following tests FAILED:
+.*2 \- FailingTest \(Failed\)
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-result.txt b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stderr.txt b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stderr.txt
new file mode 100644
index 0000000..83c332b
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stderr.txt
@@ -0,0 +1 @@
+Unable to find executable: invalidCommand
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stdout.txt
new file mode 100644
index 0000000..9078aeb
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableNotRunTest-stdout.txt
@@ -0,0 +1,17 @@
+    Start 1: SuccessfulTest
+1/3 Test #1: SuccessfulTest ...................   Passed +[0-9.]+ sec
+    Start 2: DisabledTest
+2/3 Test #2: DisabledTest .....................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec
+    Start 3: NotRunTest
+.*
+3/3 Test #3: NotRunTest .......................\*\*\*\Not Run +[0-9.]+ sec
++
+50% tests passed, 1 tests failed out of 2
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests did not run:
+.*2 \- DisabledTest \(Disabled\)
++
+The following tests FAILED:
+.*3 - NotRunTest \(Not Run\)
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt
new file mode 100644
index 0000000..10d385e
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableRequiredTest-stdout.txt
@@ -0,0 +1,13 @@
+    Start 1: SuccessfulTest
+1/3 Test #1: SuccessfulTest ...................   Passed +[0-9.]+ sec
+    Start 2: DisabledTest
+2/3 Test #2: DisabledTest .....................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec
+    Start 3: SuccessfulCleanupTest
+3/3 Test #3: SuccessfulCleanupTest ............   Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 2
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests did not run:
+.*2 \- DisabledTest \(Disabled\)
diff --git a/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt
new file mode 100644
index 0000000..2dfd10d
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisableSetupTest-stdout.txt
@@ -0,0 +1,13 @@
+    Start 2: DisabledTest
+1/3 Test #2: DisabledTest .....................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec
+    Start 1: SuccessfulTest
+2/3 Test #1: SuccessfulTest ...................   Passed +[0-9.]+ sec
+    Start 3: SuccessfulCleanupTest
+3/3 Test #3: SuccessfulCleanupTest ............   Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 2
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests did not run:
+.*2 \- DisabledTest \(Disabled\)
diff --git a/Tests/RunCMake/ctest_disabled_test/DisabledTest-result.txt b/Tests/RunCMake/ctest_disabled_test/DisabledTest-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisabledTest-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_disabled_test/DisabledTest-stderr.txt b/Tests/RunCMake/ctest_disabled_test/DisabledTest-stderr.txt
new file mode 100644
index 0000000..83c332b
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisabledTest-stderr.txt
@@ -0,0 +1 @@
+Unable to find executable: invalidCommand
diff --git a/Tests/RunCMake/ctest_disabled_test/DisabledTest-stdout.txt b/Tests/RunCMake/ctest_disabled_test/DisabledTest-stdout.txt
new file mode 100644
index 0000000..9078aeb
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/DisabledTest-stdout.txt
@@ -0,0 +1,17 @@
+    Start 1: SuccessfulTest
+1/3 Test #1: SuccessfulTest ...................   Passed +[0-9.]+ sec
+    Start 2: DisabledTest
+2/3 Test #2: DisabledTest .....................\*\*\*\Not Run \(Disabled\) +[0-9.]+ sec
+    Start 3: NotRunTest
+.*
+3/3 Test #3: NotRunTest .......................\*\*\*\Not Run +[0-9.]+ sec
++
+50% tests passed, 1 tests failed out of 2
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests did not run:
+.*2 \- DisabledTest \(Disabled\)
++
+The following tests FAILED:
+.*3 - NotRunTest \(Not Run\)
diff --git a/Tests/RunCMake/ctest_disabled_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_disabled_test/RunCMakeTest.cmake
new file mode 100644
index 0000000..12541c4
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/RunCMakeTest.cmake
@@ -0,0 +1,89 @@
+include(RunCTest)
+
+function(run_DisableNotRunTest)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME DisabledTest COMMAND notACommand --version)
+add_test(NAME NotRunTest COMMAND invalidCommand --version)
+
+set_tests_properties(SuccessfulTest PROPERTIES DISABLED false)
+set_tests_properties(DisabledTest PROPERTIES DISABLED true)
+  ]])
+  run_ctest(DisableNotRunTest)
+endfunction()
+run_DisableNotRunTest()
+
+function(run_DisableFailingTest)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+set(someFile "${CMAKE_CURRENT_SOURCE_DIR}/test.cmake")
+add_test(NAME FailingTest
+          COMMAND ${CMAKE_COMMAND} -E compare_files "${someFile}" "${someFile}xxx")
+add_test(NAME DisabledFailingTest
+          COMMAND ${CMAKE_COMMAND} -E compare_files "${someFile}" "${someFile}xxx")
+
+set_tests_properties(FailingTest PROPERTIES DISABLED false)
+set_tests_properties(DisabledFailingTest PROPERTIES DISABLED true)
+  ]])
+  run_ctest(DisableFailingTest)
+endfunction()
+run_DisableFailingTest()
+
+function(run_DisableSetupTest)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME DisabledTest COMMAND "${CMAKE_COMMAND}" --version)
+add_test(NAME SuccessfulCleanupTest COMMAND "${CMAKE_COMMAND}" --version)
+
+set_tests_properties(DisabledTest PROPERTIES DISABLED true
+                                             FIXTURES_SETUP "Foo")
+set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_REQUIRED "Foo")
+set_tests_properties(SuccessfulCleanupTest PROPERTIES FIXTURES_CLEANUP "Foo")
+  ]])
+run_ctest(DisableSetupTest)
+endfunction()
+run_DisableSetupTest()
+
+function(run_DisableRequiredTest)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME DisabledTest COMMAND "${CMAKE_COMMAND}" --version)
+add_test(NAME SuccessfulCleanupTest COMMAND "${CMAKE_COMMAND}" --version)
+
+set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_SETUP "Foo")
+set_tests_properties(DisabledTest PROPERTIES DISABLED true
+                                             FIXTURES_REQUIRED "Foo")
+set_tests_properties(SuccessfulCleanupTest PROPERTIES FIXTURES_CLEANUP "Foo")
+  ]])
+run_ctest(DisableRequiredTest)
+endfunction()
+run_DisableRequiredTest()
+
+function(run_DisableCleanupTest)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME CleanupTest COMMAND "${CMAKE_COMMAND}" --version)
+
+set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_REQUIRED "Foo")
+set_tests_properties(CleanupTest PROPERTIES DISABLED true
+                                            FIXTURES_CLEANUP "Foo")
+  ]])
+run_ctest(DisableCleanupTest)
+endfunction()
+run_DisableCleanupTest()
+
+# Consider a fixture that has a setup test, a cleanup test and a disabled test
+# which requires that fixture. Limit the test list with a regular expression
+# that matches the disabled test but not the setup or cleanup tests, so the
+# initial set of tests to be executed contains just the disabled test. Since
+# the only test requiring the fixture is disabled, CTest should not
+# automatically add in the setup and cleanup tests for the fixture, since no
+# enabled test requires them.
+function(run_DisableAllTests)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME SetupTest COMMAND "${CMAKE_COMMAND}" --version)
+add_test(NAME CleanupTest COMMAND "${CMAKE_COMMAND}" --version)
+
+set_tests_properties(SetupTest PROPERTIES FIXTURES_SETUP "Foo")
+set_tests_properties(SuccessfulTest PROPERTIES DISABLED true
+                                               FIXTURES_REQUIRED "Foo")
+set_tests_properties(CleanupTest PROPERTIES FIXTURES_CLEANUP "Foo")
+  ]])
+run_ctest(DisableAllTests -R Successful)
+endfunction()
+run_DisableAllTests()
diff --git a/Tests/RunCMake/ctest_disabled_test/test.cmake.in b/Tests/RunCMake/ctest_disabled_test/test.cmake.in
new file mode 100644
index 0000000..ca23c83
--- /dev/null
+++ b/Tests/RunCMake/ctest_disabled_test/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 at -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_fixtures/CMakeLists.txt.in b/Tests/RunCMake/ctest_fixtures/CMakeLists.txt.in
index ab50fdd..5cb0b4e 100644
--- a/Tests/RunCMake/ctest_fixtures/CMakeLists.txt.in
+++ b/Tests/RunCMake/ctest_fixtures/CMakeLists.txt.in
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 3.6.2)
+cmake_minimum_required (VERSION 3.8.0)
 project(ctest_fixtures LANGUAGES NONE)
 include(CTest)
 
diff --git a/Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake b/Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake
index 673cf57..1754203 100644
--- a/Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake
@@ -19,6 +19,41 @@ run_ctest_test(setupFoo INCLUDE setupFoo)
 run_ctest_test(wontRun  INCLUDE wontRun)
 run_ctest_test(unused   INCLUDE Unused)
 
+run_ctest_test(exclude_setup_foo
+    INCLUDE               "one|two"
+    EXCLUDE_FIXTURE_SETUP "Foo"
+)
+
+run_ctest_test(exclude_setup_bar
+    INCLUDE               "one|two"
+    EXCLUDE_FIXTURE_SETUP "Bar"
+)
+
+run_ctest_test(exclude_cleanup_foo
+    INCLUDE                 "one|two"
+    EXCLUDE_FIXTURE_CLEANUP "Foo"
+)
+
+run_ctest_test(exclude_cleanup_bar
+    INCLUDE                 "one|two"
+    EXCLUDE_FIXTURE_CLEANUP "Bar"
+)
+
+run_ctest_test(exclude_any_foo
+    INCLUDE         "one|two"
+    EXCLUDE_FIXTURE "Foo"
+)
+
+run_ctest_test(exclude_any_bar
+    INCLUDE         "one|two"
+    EXCLUDE_FIXTURE "Bar"
+)
+
+run_ctest_test(exclude_any_foobar
+    INCLUDE         "one|two"
+    EXCLUDE_FIXTURE "Foo|Bar"
+)
+
 #------------------------------------------------------------
 # CMake configure will fail due to cyclic test dependencies
 #------------------------------------------------------------
@@ -35,3 +70,18 @@ set(CASE_CMAKELISTS_CYCLIC_CODE [[
                          FIXTURES_REQUIRED "Foo")
 ]])
 run_ctest(cyclicCleanup)
+
+#------------------------------------------------------------
+# Repeat some of the exclusion tests with ctest command line
+# options instead of arguments to ctest_test(). This verifies
+# that the command line options make it through as well.
+#------------------------------------------------------------
+unset(CASE_CMAKELISTS_CYCLIC_CODE)
+set(CASE_CTEST_FIXTURES_ARGS "")
+
+run_ctest(exclude_setup_foo -R "one|two" -FS Foo)
+run_ctest(exclude_setup_foo -R "one|two" --fixture-exclude-setup Foo)
+run_ctest(exclude_cleanup_foo -R "one|two" -FC Foo)
+run_ctest(exclude_cleanup_foo -R "one|two" --fixture-exclude-cleanup Foo)
+run_ctest(exclude_any_foo -R "one|two" -FA Foo)
+run_ctest(exclude_any_foo -R "one|two" --fixture-exclude-any Foo)
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt
new file mode 100644
index 0000000..82663d5
--- /dev/null
+++ b/Tests/RunCMake/ctest_fixtures/exclude_any_bar-stdout.txt
@@ -0,0 +1,15 @@
+Test project .*/Tests/RunCMake/ctest_fixtures/exclude_any_bar-build
+    Start 3: setupFoo
+1/5 Test #3: setupFoo +\.+ +Passed +[0-9.]+ sec
+    Start 2: setupBoth
+2/5 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec
+    Start 1: one
+3/5 Test #1: one +\.+ +Passed +[0-9.]+ sec
+    Start 5: cleanupFoo
+4/5 Test #5: cleanupFoo +\.+ +Passed +[0-9.]+ sec
+    Start 6: two
+5/5 Test #6: two +\.+ +Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 5
++
+Total Test time \(real\) = +[0-9.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt
new file mode 100644
index 0000000..8c08d08
--- /dev/null
+++ b/Tests/RunCMake/ctest_fixtures/exclude_any_foo-stdout.txt
@@ -0,0 +1,13 @@
+Test project .*/Tests/RunCMake/ctest_fixtures/exclude_any_foo-build
+    Start 2: setupBoth
+1/4 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec
+    Start 1: one
+2/4 Test #1: one +\.+ +Passed +[0-9.]+ sec
+    Start 6: two
+3/4 Test #6: two +\.+ +Passed +[0-9.]+ sec
+    Start 7: cleanupBar
+4/4 Test #7: cleanupBar +\.+ +Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 4
++
+Total Test time \(real\) = +[0-9.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt
new file mode 100644
index 0000000..876768b
--- /dev/null
+++ b/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-stdout.txt
@@ -0,0 +1,9 @@
+Test project .*/Tests/RunCMake/ctest_fixtures/exclude_any_foobar-build
+    Start 1: one
+1/2 Test #1: one +\.+ +Passed +[0-9.]+ sec
+    Start 6: two
+2/2 Test #6: two +\.+ +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/ctest_fixtures/exclude_cleanup_bar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt
new file mode 100644
index 0000000..0d27198
--- /dev/null
+++ b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-stdout.txt
@@ -0,0 +1,15 @@
+Test project .*/Tests/RunCMake/ctest_fixtures/exclude_cleanup_bar-build
+    Start 3: setupFoo
+1/5 Test #3: setupFoo +\.+ +Passed +[0-9.]+ sec
+    Start 2: setupBoth
+2/5 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec
+    Start 1: one
+3/5 Test #1: one +\.+ +Passed +[0-9.]+ sec
+    Start 5: cleanupFoo
+4/5 Test #5: cleanupFoo +\.+ +Passed +[0-9.]+ sec
+    Start 6: two
+5/5 Test #6: two +\.+ +Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 5
++
+Total Test time \(real\) = +[0-9.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt
new file mode 100644
index 0000000..5b201a3
--- /dev/null
+++ b/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-stdout.txt
@@ -0,0 +1,15 @@
+Test project .*/Tests/RunCMake/ctest_fixtures/exclude_cleanup_foo-build
+    Start 3: setupFoo
+1/5 Test #3: setupFoo +\.+ +Passed +[0-9.]+ sec
+    Start 2: setupBoth
+2/5 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec
+    Start 1: one
+3/5 Test #1: one +\.+ +Passed +[0-9.]+ sec
+    Start 6: two
+4/5 Test #6: two +\.+ +Passed +[0-9.]+ sec
+    Start 7: cleanupBar
+5/5 Test #7: cleanupBar +\.+ +Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 5
++
+Total Test time \(real\) = +[0-9.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt
new file mode 100644
index 0000000..5357fef
--- /dev/null
+++ b/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-stdout.txt
@@ -0,0 +1,17 @@
+Test project .*/Tests/RunCMake/ctest_fixtures/exclude_setup_bar-build
+    Start 3: setupFoo
+1/6 Test #3: setupFoo +\.+ +Passed +[0-9.]+ sec
+    Start 2: setupBoth
+2/6 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec
+    Start 1: one
+3/6 Test #1: one +\.+ +Passed +[0-9.]+ sec
+    Start 5: cleanupFoo
+4/6 Test #5: cleanupFoo +\.+ +Passed +[0-9.]+ sec
+    Start 6: two
+5/6 Test #6: two +\.+ +Passed +[0-9.]+ sec
+    Start 7: cleanupBar
+6/6 Test #7: cleanupBar +\.+ +Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 6
++
+Total Test time \(real\) = +[0-9.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt b/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt
new file mode 100644
index 0000000..89f7f44
--- /dev/null
+++ b/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-stdout.txt
@@ -0,0 +1,15 @@
+Test project .*/Tests/RunCMake/ctest_fixtures/exclude_setup_foo-build
+    Start 2: setupBoth
+1/5 Test #2: setupBoth +\.+ +Passed +[0-9.]+ sec
+    Start 1: one
+2/5 Test #1: one +\.+ +Passed +[0-9.]+ sec
+    Start 5: cleanupFoo
+3/5 Test #5: cleanupFoo +\.+ +Passed +[0-9.]+ sec
+    Start 6: two
+4/5 Test #6: two +\.+ +Passed +[0-9.]+ sec
+    Start 7: cleanupBar
+5/5 Test #7: cleanupBar +\.+ +Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 5
++
+Total Test time \(real\) = +[0-9.]+ sec$
diff --git a/Tests/RunCMake/ctest_fixtures/test.cmake.in b/Tests/RunCMake/ctest_fixtures/test.cmake.in
index 43df172..7067117 100644
--- a/Tests/RunCMake/ctest_fixtures/test.cmake.in
+++ b/Tests/RunCMake/ctest_fixtures/test.cmake.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.6.2)
+cmake_minimum_required(VERSION 3.8.0)
 
 set(CTEST_SITE                          "test-site")
 set(CTEST_BUILD_NAME                    "test-build-name")
diff --git a/Tests/RunCMake/ctest_skipped_test/CMakeLists.txt.in b/Tests/RunCMake/ctest_skipped_test/CMakeLists.txt.in
new file mode 100644
index 0000000..cc4b8ed
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/CMakeLists.txt.in
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 3.8)
+project(@CASE_NAME@ C)
+include(CTest)
+
+if (WIN32)
+  set(skip_command "@CMAKE_CURRENT_LIST_DIR@/skip.bat")
+else ()
+  set(skip_command "@CMAKE_CURRENT_LIST_DIR@/skip.sh")
+endif ()
+
+add_test(NAME SuccessfulTest COMMAND "${CMAKE_COMMAND}" --version)
+ at CASE_CMAKELISTS_SUFFIX_CODE@
diff --git a/Tests/RunCMake/ctest_skipped_test/CTestConfig.cmake.in b/Tests/RunCMake/ctest_skipped_test/CTestConfig.cmake.in
new file mode 100644
index 0000000..c0d7e42
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/CTestConfig.cmake.in
@@ -0,0 +1 @@
+set(CTEST_PROJECT_NAME "@CASE_NAME@")
diff --git a/Tests/RunCMake/ctest_skipped_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_skipped_test/RunCMakeTest.cmake
new file mode 100644
index 0000000..dcf5cd4
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/RunCMakeTest.cmake
@@ -0,0 +1,51 @@
+include(RunCTest)
+
+function(run_SkipTest)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME SkipTest COMMAND ${skip_command})
+
+set_tests_properties(SkipTest PROPERTIES SKIP_RETURN_CODE 125)
+  ]])
+  run_ctest(SkipTest)
+endfunction()
+run_SkipTest()
+
+function(run_SkipSetupTest)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME SkipTest COMMAND ${skip_command})
+add_test(NAME SuccessfulCleanupTest COMMAND "${CMAKE_COMMAND}" --version)
+
+set_tests_properties(SkipTest PROPERTIES SKIP_RETURN_CODE 125
+                                         FIXTURES_SETUP "Foo")
+set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_REQUIRED "Foo")
+set_tests_properties(SuccessfulCleanupTest PROPERTIES FIXTURES_CLEANUP "Foo")
+  ]])
+  run_ctest(SkipSetupTest)
+endfunction()
+run_SkipSetupTest()
+
+function(run_SkipRequiredTest)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME SkipTest COMMAND ${skip_command})
+add_test(NAME SuccessfulCleanupTest COMMAND "${CMAKE_COMMAND}" --version)
+
+set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_SETUP "Foo")
+set_tests_properties(SkipTest PROPERTIES SKIP_RETURN_CODE 125
+                                         FIXTURES_REQUIRED "Foo")
+set_tests_properties(SuccessfulCleanupTest PROPERTIES FIXTURES_CLEANUP "Foo")
+  ]])
+  run_ctest(SkipRequiredTest)
+endfunction()
+run_SkipRequiredTest()
+
+function(run_SkipCleanupTest)
+  set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(NAME CleanupTest COMMAND ${skip_command})
+
+set_tests_properties(SuccessfulTest PROPERTIES FIXTURES_REQUIRED "Foo")
+set_tests_properties(CleanupTest PROPERTIES SKIP_RETURN_CODE 125
+                                            FIXTURES_CLEANUP "Foo")
+  ]])
+  run_ctest(SkipCleanupTest)
+endfunction()
+run_SkipCleanupTest()
diff --git a/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt
new file mode 100644
index 0000000..3b14b7a
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/SkipCleanupTest-stdout.txt
@@ -0,0 +1,11 @@
+    Start 1: SuccessfulTest
+1/2 Test #1: SuccessfulTest ...................   Passed +[0-9.]+ sec
+    Start 2: CleanupTest
+2/2 Test #2: CleanupTest ......................\*\*\*\Skipped +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 2
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests did not run:
+.*2 \- CleanupTest \(Skipped\)
diff --git a/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt
new file mode 100644
index 0000000..8ecc6e3
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/SkipRequiredTest-stdout.txt
@@ -0,0 +1,13 @@
+    Start 1: SuccessfulTest
+1/3 Test #1: SuccessfulTest ...................   Passed +[0-9.]+ sec
+    Start 2: SkipTest
+2/3 Test #2: SkipTest .........................\*\*\*\Skipped +[0-9.]+ sec
+    Start 3: SuccessfulCleanupTest
+3/3 Test #3: SuccessfulCleanupTest ............   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:
+.*2 \- SkipTest \(Skipped\)
diff --git a/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt
new file mode 100644
index 0000000..fe9bf34
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/SkipSetupTest-stdout.txt
@@ -0,0 +1,13 @@
+    Start 2: SkipTest
+1/3 Test #2: SkipTest .........................\*\*\*\Skipped +[0-9.]+ sec
+    Start 1: SuccessfulTest
+2/3 Test #1: SuccessfulTest ...................   Passed +[0-9.]+ sec
+    Start 3: SuccessfulCleanupTest
+3/3 Test #3: SuccessfulCleanupTest ............   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:
+.*2 \- SkipTest \(Skipped\)
diff --git a/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt b/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt
new file mode 100644
index 0000000..52e7a0b
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/SkipTest-stdout.txt
@@ -0,0 +1,11 @@
+    Start 1: SuccessfulTest
+1/2 Test #1: SuccessfulTest ...................   Passed +[0-9.]+ sec
+    Start 2: SkipTest
+2/2 Test #2: SkipTest .........................\*\*\*\Skipped +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 2
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests did not run:
+.*2 \- SkipTest \(Skipped\)
diff --git a/Tests/RunCMake/ctest_skipped_test/skip.bat b/Tests/RunCMake/ctest_skipped_test/skip.bat
new file mode 100755
index 0000000..80e1290
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/skip.bat
@@ -0,0 +1 @@
+EXIT 125
diff --git a/Tests/RunCMake/ctest_skipped_test/skip.sh b/Tests/RunCMake/ctest_skipped_test/skip.sh
new file mode 100755
index 0000000..f9c4603
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/skip.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exit 125
diff --git a/Tests/RunCMake/ctest_skipped_test/test.cmake.in b/Tests/RunCMake/ctest_skipped_test/test.cmake.in
new file mode 100644
index 0000000..ca23c83
--- /dev/null
+++ b/Tests/RunCMake/ctest_skipped_test/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 at -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_submit/CDashSubmitHeaders-result.txt b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stderr.txt b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stderr.txt
new file mode 100644
index 0000000..4825d7a
--- /dev/null
+++ b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stderr.txt
@@ -0,0 +1,3 @@
+ *Error when uploading file: .*/Configure.xml
+ *Error message was: ([Cc]ould *n.t resolve host:? '?-no-site-'?.*|The requested URL returned error:.*)
+ *Problems when submitting via HTTP
diff --git a/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stdout.txt b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stdout.txt
new file mode 100644
index 0000000..3973872
--- /dev/null
+++ b/Tests/RunCMake/ctest_submit/CDashSubmitHeaders-stdout.txt
@@ -0,0 +1 @@
+Add HTTP Header: "Authorization: Bearer asdf"
diff --git a/Tests/RunCMake/ctest_submit/CDashUploadHeaders-result.txt b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stderr.txt b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stderr.txt
new file mode 100644
index 0000000..706e1f5
--- /dev/null
+++ b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stderr.txt
@@ -0,0 +1 @@
+Error in HttpRequest
diff --git a/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stdout.txt b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stdout.txt
new file mode 100644
index 0000000..3973872
--- /dev/null
+++ b/Tests/RunCMake/ctest_submit/CDashUploadHeaders-stdout.txt
@@ -0,0 +1 @@
+Add HTTP Header: "Authorization: Bearer asdf"
diff --git a/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake b/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake
index e104f8a..b5d90d2 100644
--- a/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_submit/RunCMakeTest.cmake
@@ -25,6 +25,8 @@ run_ctest_submit(CDashUploadNone CDASH_UPLOAD)
 run_ctest_submit(CDashUploadMissingFile CDASH_UPLOAD bad-upload)
 run_ctest_submit(CDashUploadRetry CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo RETRY_COUNT 2 RETRY_DELAY 1 INTERNAL_TEST_CHECKSUM)
 run_ctest_submit(CDashSubmitQuiet QUIET)
+run_ctest_submit(CDashSubmitHeaders HTTPHEADER "Authorization: Bearer asdf")
+run_ctest_submit(CDashUploadHeaders CDASH_UPLOAD ${CMAKE_CURRENT_LIST_FILE} CDASH_UPLOAD_TYPE foo HTTPHEADER "Authorization: Bearer asdf")
 
 function(run_ctest_CDashUploadFTP)
   set(CASE_DROP_METHOD ftp)
diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake
index ca72692..a91b217 100644
--- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake
+++ b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake
@@ -1,5 +1,8 @@
+if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/")
+  set(slash /)
+endif()
 file(DOWNLOAD
-  "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt"
+  "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt"
   ${CMAKE_CURRENT_BINARY_DIR}/hash-mismatch.txt
   EXPECTED_HASH SHA1=0123456789abcdef0123456789abcdef01234567
   STATUS status
diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake
index 2e3fbe1..2fa5482 100644
--- a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake
+++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake
@@ -1,5 +1,8 @@
+if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/")
+  set(slash /)
+endif()
 file(DOWNLOAD
-  "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt"
+  "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt"
   "${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt"
   JUNK
   )
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-result.txt
diff --git a/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-stderr.txt b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-stderr.txt
new file mode 100644
index 0000000..9d5f876
--- /dev/null
+++ b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-stderr.txt
@@ -0,0 +1,15 @@
+^CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\):
+  file option FILES_FROM_DIR requires all files to be specified as relative
+  paths\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
++
+CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\):
+  file INSTALL option RENAME may not be combined with FILES_FROM_DIR\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
++
+CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\):
+  file option FILES_FROM_DIR may not appear after PATTERN or REGEX\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake
new file mode 100644
index 0000000..807b704
--- /dev/null
+++ b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake
@@ -0,0 +1,5 @@
+set(src ${CMAKE_CURRENT_SOURCE_DIR}/from)
+set(dst ${CMAKE_CURRENT_BINARY_DIR}/from)
+file(INSTALL FILES ${src}/a.txt FILES_FROM_DIR ${src} DESTINATION ${dst})
+file(INSTALL FILES a.txt FILES_FROM_DIR ${src} DESTINATION ${dst} RENAME b.txt)
+file(INSTALL FILES a.txt DESTINATION ${dst} PATTERN *.txt FILES_FROM_DIR)
diff --git a/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-stdout.txt b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-stdout.txt
new file mode 100644
index 0000000..1c3c693
--- /dev/null
+++ b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-stdout.txt
@@ -0,0 +1,8 @@
+-- Before Installing
+-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a.txt
+-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b.txt
+-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b/c.txt
+-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a.txt
+-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b.txt
+-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b/c.txt
+-- After Installing
diff --git a/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake
new file mode 100644
index 0000000..24e5282
--- /dev/null
+++ b/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake
@@ -0,0 +1,7 @@
+set(src ${CMAKE_CURRENT_SOURCE_DIR}/from)
+set(dst ${CMAKE_CURRENT_BINARY_DIR}/from)
+file(REMOVE RECURSE ${dst})
+message(STATUS "Before Installing")
+file(INSTALL FILES a.txt a/b.txt a/b/c.txt FILES_FROM_DIR ${src} DESTINATION ${dst})
+file(INSTALL FILES a.txt a/b.txt a/b/c.txt FILES_FROM_DIR from DESTINATION ${dst})
+message(STATUS "After Installing")
diff --git a/Tests/RunCMake/file/INSTALL-SYMLINK-stdout.txt b/Tests/RunCMake/file/INSTALL-SYMLINK-stdout.txt
new file mode 100644
index 0000000..9fb8e10
--- /dev/null
+++ b/Tests/RunCMake/file/INSTALL-SYMLINK-stdout.txt
@@ -0,0 +1,3 @@
+-- Before Installing
+-- Installing: .*/Tests/RunCMake/file/INSTALL-SYMLINK-build/dst/current_dir_symlink
+-- After Installing
diff --git a/Tests/RunCMake/file/INSTALL-SYMLINK.cmake b/Tests/RunCMake/file/INSTALL-SYMLINK.cmake
new file mode 100644
index 0000000..5a4284a
--- /dev/null
+++ b/Tests/RunCMake/file/INSTALL-SYMLINK.cmake
@@ -0,0 +1,13 @@
+set(src "${CMAKE_CURRENT_BINARY_DIR}/src")
+set(dst "${CMAKE_CURRENT_BINARY_DIR}/dst")
+file(REMOVE RECURSE "${src}")
+file(REMOVE RECURSE "${dst}")
+
+file(MAKE_DIRECTORY "${src}")
+execute_process(COMMAND
+  ${CMAKE_COMMAND} -E create_symlink source "${src}/current_dir_symlink")
+
+message(STATUS "Before Installing")
+file(INSTALL FILES "${src}/current_dir_symlink"
+  DESTINATION ${dst} TYPE DIRECTORY)
+message(STATUS "After Installing")
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/file/READ_ELF-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/file/READ_ELF-result.txt
diff --git a/Tests/RunCMake/file/READ_ELF-stderr.txt b/Tests/RunCMake/file/READ_ELF-stderr.txt
new file mode 100644
index 0000000..7b32804
--- /dev/null
+++ b/Tests/RunCMake/file/READ_ELF-stderr.txt
@@ -0,0 +1,2 @@
+.*file READ_ELF must be called with at least three additional arguments\.
+.*file READ_ELF given FILE "XXX" that does not exist\.
diff --git a/Tests/RunCMake/file/READ_ELF.cmake b/Tests/RunCMake/file/READ_ELF.cmake
new file mode 100644
index 0000000..cd02c9b
--- /dev/null
+++ b/Tests/RunCMake/file/READ_ELF.cmake
@@ -0,0 +1,2 @@
+file(READ_ELF XXX)
+file(READ_ELF XXX RPATH YYY)
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index 7497544..26051b4 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -8,6 +8,8 @@ run_cmake(UPLOAD-unused-argument)
 run_cmake(UPLOAD-httpheader-not-set)
 run_cmake(UPLOAD-pass-not-set)
 run_cmake(INSTALL-DIRECTORY)
+run_cmake(INSTALL-FILES_FROM_DIR)
+run_cmake(INSTALL-FILES_FROM_DIR-bad)
 run_cmake(INSTALL-MESSAGE-bad)
 run_cmake(FileOpenFailRead)
 run_cmake(LOCK)
@@ -25,6 +27,7 @@ run_cmake(LOCK-error-no-timeout)
 run_cmake(LOCK-error-timeout)
 run_cmake(LOCK-error-unknown-option)
 run_cmake(LOCK-lowercase)
+run_cmake(READ_ELF)
 run_cmake(GLOB)
 run_cmake(GLOB_RECURSE)
 # test is valid both for GLOB and GLOB_RECURSE
@@ -35,4 +38,5 @@ run_cmake(GLOB-noexp-LIST_DIRECTORIES)
 
 if(NOT WIN32 OR CYGWIN)
   run_cmake(GLOB_RECURSE-cyclic-recursion)
+  run_cmake(INSTALL-SYMLINK)
 endif()
diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake
index 94ac9ac..92c878c 100644
--- a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake
+++ b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake
@@ -1,5 +1,8 @@
+if(NOT "${CMAKE_CURRENT_BINARY_DIR}" MATCHES "^/")
+  set(slash /)
+endif()
 file(UPLOAD
   "${CMAKE_CURRENT_SOURCE_DIR}/UPLOAD-unused-argument.txt"
-  "file://${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt"
+  "file://${slash}${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt"
   JUNK
   )
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/file/from/a.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/file/from/a.txt
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/file/from/a/b.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/file/from/a/b.txt
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/file/from/a/b/c.txt
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/file/from/a/b/c.txt
diff --git a/Tests/RunCMake/find_dependency/CMakeLists.txt b/Tests/RunCMake/find_dependency/CMakeLists.txt
index 04d09f2..12cd3c7 100644
--- a/Tests/RunCMake/find_dependency/CMakeLists.txt
+++ b/Tests/RunCMake/find_dependency/CMakeLists.txt
@@ -1,4 +1,3 @@
 cmake_minimum_required(VERSION 2.8.4)
 project(${RunCMake_TEST} NONE)
-set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
 include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/find_dependency/EXACT-no-version-stderr.txt b/Tests/RunCMake/find_dependency/EXACT-no-version-stderr.txt
deleted file mode 100644
index 348f8bb..0000000
--- a/Tests/RunCMake/find_dependency/EXACT-no-version-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\):
-  Invalid arguments to find_dependency.  EXACT may only be specified if a
-  VERSION is specified
-Call Stack \(most recent call first\):
-  EXACT-no-version.cmake:4 \(find_dependency\)
-  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/find_dependency/EXACT-no-version.cmake b/Tests/RunCMake/find_dependency/EXACT-no-version.cmake
deleted file mode 100644
index b05665b..0000000
--- a/Tests/RunCMake/find_dependency/EXACT-no-version.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-
-include(CMakeFindDependencyMacro)
-
-find_dependency(Pack1 EXACT)
diff --git a/Tests/RunCMake/find_dependency/RunCMakeTest.cmake b/Tests/RunCMake/find_dependency/RunCMakeTest.cmake
index 9403136..a72d189 100644
--- a/Tests/RunCMake/find_dependency/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_dependency/RunCMakeTest.cmake
@@ -1,7 +1,10 @@
 include(RunCMake)
 
-run_cmake(EXACT-no-version)
-run_cmake(empty-version)
-run_cmake(empty-arg-3)
-run_cmake(invalid-arg-3)
-run_cmake(extra-args)
+# Success tests
+run_cmake(realistic)
+run_cmake(basic)
+
+# Failure tests
+run_cmake(invalid-arg)
+run_cmake(bad-version-fuzzy)
+run_cmake(bad-version-exact)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/find_dependency/bad-version-exact-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/find_dependency/bad-version-exact-result.txt
diff --git a/Tests/RunCMake/find_dependency/bad-version-exact-stderr.txt b/Tests/RunCMake/find_dependency/bad-version-exact-stderr.txt
new file mode 100644
index 0000000..0929f84
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/bad-version-exact-stderr.txt
@@ -0,0 +1,11 @@
+CMake Error at .*/Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(find_package\):
+  Could not find a configuration file for package "Pack1" that exactly
+  matches requested version "1.1".
+
+  The following configuration files were considered but not accepted:
+
+    .*/Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1Config.cmake, version: 1.3
+
+Call Stack \(most recent call first\):
+  bad-version-exact.cmake:5 \(find_dependency\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/find_dependency/bad-version-exact.cmake b/Tests/RunCMake/find_dependency/bad-version-exact.cmake
new file mode 100644
index 0000000..c4ca5e2
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/bad-version-exact.cmake
@@ -0,0 +1,5 @@
+set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
+
+include(CMakeFindDependencyMacro)
+
+find_dependency(Pack1 1.1 EXACT REQUIRED)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/find_dependency/bad-version-fuzzy-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/find_dependency/bad-version-fuzzy-result.txt
diff --git a/Tests/RunCMake/find_dependency/bad-version-fuzzy-stderr.txt b/Tests/RunCMake/find_dependency/bad-version-fuzzy-stderr.txt
new file mode 100644
index 0000000..c63256f
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/bad-version-fuzzy-stderr.txt
@@ -0,0 +1,11 @@
+CMake Error at .*/Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(find_package\):
+  Could not find a configuration file for package "Pack1" that is compatible
+  with requested version "1.4".
+
+  The following configuration files were considered but not accepted:
+
+    .*/Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1Config.cmake, version: 1.3
+
+Call Stack \(most recent call first\):
+  bad-version-fuzzy.cmake:5 \(find_dependency\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/find_dependency/bad-version-fuzzy.cmake b/Tests/RunCMake/find_dependency/bad-version-fuzzy.cmake
new file mode 100644
index 0000000..c7cf4ee
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/bad-version-fuzzy.cmake
@@ -0,0 +1,5 @@
+set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
+
+include(CMakeFindDependencyMacro)
+
+find_dependency(Pack1 1.4 REQUIRED)
diff --git a/Tests/RunCMake/find_dependency/basic.cmake b/Tests/RunCMake/find_dependency/basic.cmake
new file mode 100644
index 0000000..c7795f2
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/basic.cmake
@@ -0,0 +1,5 @@
+set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
+
+include(CMakeFindDependencyMacro)
+
+find_dependency(Pack1 1.1)
diff --git a/Tests/RunCMake/find_dependency/empty-arg-3-stderr.txt b/Tests/RunCMake/find_dependency/empty-arg-3-stderr.txt
deleted file mode 100644
index bf9b02b..0000000
--- a/Tests/RunCMake/find_dependency/empty-arg-3-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\):
-  Invalid arguments to find_dependency
-Call Stack \(most recent call first\):
-  empty-arg-3.cmake:4 \(find_dependency\)
-  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/find_dependency/empty-arg-3.cmake b/Tests/RunCMake/find_dependency/empty-arg-3.cmake
deleted file mode 100644
index b08200a..0000000
--- a/Tests/RunCMake/find_dependency/empty-arg-3.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-
-include(CMakeFindDependencyMacro)
-
-find_dependency(Pack1 1.2 "")
diff --git a/Tests/RunCMake/find_dependency/empty-version-stderr.txt b/Tests/RunCMake/find_dependency/empty-version-stderr.txt
deleted file mode 100644
index b5e9f46..0000000
--- a/Tests/RunCMake/find_dependency/empty-version-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-CMake Error at .*/Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\):
-  Invalid arguments to find_dependency.  VERSION is empty
-Call Stack \(most recent call first\):
-  empty-version.cmake:4 \(find_dependency\)
-  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/find_dependency/empty-version.cmake b/Tests/RunCMake/find_dependency/empty-version.cmake
deleted file mode 100644
index e6f17cd..0000000
--- a/Tests/RunCMake/find_dependency/empty-version.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-
-include(CMakeFindDependencyMacro)
-
-find_dependency(Pack1 "")
diff --git a/Tests/RunCMake/find_dependency/extra-args-stderr.txt b/Tests/RunCMake/find_dependency/extra-args-stderr.txt
deleted file mode 100644
index 83a7f02..0000000
--- a/Tests/RunCMake/find_dependency/extra-args-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\):
-  Invalid arguments to find_dependency
-Call Stack \(most recent call first\):
-  extra-args.cmake:4 \(find_dependency\)
-  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/find_dependency/extra-args.cmake b/Tests/RunCMake/find_dependency/extra-args.cmake
deleted file mode 100644
index 209645a..0000000
--- a/Tests/RunCMake/find_dependency/extra-args.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-
-include(CMakeFindDependencyMacro)
-
-find_dependency(Pack1 1.2 EXACT PATHS "${CMAKE_BINARY_DIR}")
diff --git a/Tests/RunCMake/find_dependency/invalid-arg-3-stderr.txt b/Tests/RunCMake/find_dependency/invalid-arg-3-stderr.txt
deleted file mode 100644
index fee8d5d..0000000
--- a/Tests/RunCMake/find_dependency/invalid-arg-3-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(message\):
-  Invalid arguments to find_dependency
-Call Stack \(most recent call first\):
-  invalid-arg-3.cmake:4 \(find_dependency\)
-  CMakeLists.txt:4 \(include\)
diff --git a/Tests/RunCMake/find_dependency/invalid-arg-3.cmake b/Tests/RunCMake/find_dependency/invalid-arg-3.cmake
deleted file mode 100644
index 40ede07..0000000
--- a/Tests/RunCMake/find_dependency/invalid-arg-3.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-
-include(CMakeFindDependencyMacro)
-
-find_dependency(Pack1 1.2 EXACTYPO)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/find_dependency/invalid-arg-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/find_dependency/invalid-arg-result.txt
diff --git a/Tests/RunCMake/find_dependency/invalid-arg-stderr.txt b/Tests/RunCMake/find_dependency/invalid-arg-stderr.txt
new file mode 100644
index 0000000..16077b2
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/invalid-arg-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at .*Modules/CMakeFindDependencyMacro.cmake:[0-9]+ \(find_package\):
+  find_package called with invalid argument "EXACTYPO"
+Call Stack \(most recent call first\):
+  invalid-arg.cmake:5 \(find_dependency\)
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/find_dependency/invalid-arg.cmake b/Tests/RunCMake/find_dependency/invalid-arg.cmake
new file mode 100644
index 0000000..daaf569
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/invalid-arg.cmake
@@ -0,0 +1,5 @@
+set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
+
+include(CMakeFindDependencyMacro)
+
+find_dependency(Pack1 1.2 EXACTYPO)
diff --git a/Tests/RunCMake/find_dependency/realistic.cmake b/Tests/RunCMake/find_dependency/realistic.cmake
new file mode 100644
index 0000000..e633a31
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/realistic.cmake
@@ -0,0 +1,3 @@
+set(Pack2_DIR "${CMAKE_CURRENT_SOURCE_DIR}/share/cmake/Pack2")
+
+find_package(Pack2 1.2 REQUIRED)
diff --git a/Tests/RunCMake/find_dependency/Pack1/Pack1Config.cmake b/Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1Config.cmake
similarity index 100%
rename from Tests/RunCMake/find_dependency/Pack1/Pack1Config.cmake
rename to Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1Config.cmake
diff --git a/Tests/RunCMake/find_dependency/Pack1/Pack1ConfigVersion.cmake b/Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1ConfigVersion.cmake
similarity index 100%
copy from Tests/RunCMake/find_dependency/Pack1/Pack1ConfigVersion.cmake
copy to Tests/RunCMake/find_dependency/share/cmake/Pack1/Pack1ConfigVersion.cmake
diff --git a/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2Config.cmake b/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2Config.cmake
new file mode 100644
index 0000000..7e8a60b
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2Config.cmake
@@ -0,0 +1,6 @@
+include(CMakeFindDependencyMacro)
+
+find_dependency(Pack1 PATHS ${CMAKE_CURRENT_LIST_DIR}/..)
+
+add_library(Pack2::Lib INTERFACE IMPORTED)
+set_target_properties(Pack2::Lib PROPERTIES INTERFACE_LINK_LIBRARIES Pack1::Lib)
diff --git a/Tests/RunCMake/find_dependency/Pack1/Pack1ConfigVersion.cmake b/Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2ConfigVersion.cmake
similarity index 100%
rename from Tests/RunCMake/find_dependency/Pack1/Pack1ConfigVersion.cmake
rename to Tests/RunCMake/find_dependency/share/cmake/Pack2/Pack2ConfigVersion.cmake
diff --git a/Tests/RunCMake/find_package/MissingConfig-stderr.txt b/Tests/RunCMake/find_package/MissingConfig-stderr.txt
index 1eae0bb..33ff545 100644
--- a/Tests/RunCMake/find_package/MissingConfig-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingConfig-stderr.txt
@@ -1,18 +1,3 @@
-CMake Warning at MissingConfig.cmake:1 \(find_package\):
-  Could not find a package configuration file provided by "NotHere" with any
-  of the following names:
-
-    NotHereConfig.cmake
-    nothere-config.cmake
-
-  Add the installation prefix of "NotHere" to CMAKE_PREFIX_PATH or set
-  "NotHere_DIR" to a directory containing one of the above files.  If
-  "NotHere" provides a separate development package or SDK, be sure it has
-  been installed.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
-
-
 CMake Warning at MissingConfig.cmake:2 \(message\):
   This warning must be reachable.
 Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/find_package/MissingConfig-stdout.txt b/Tests/RunCMake/find_package/MissingConfig-stdout.txt
new file mode 100644
index 0000000..7af632b
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingConfig-stdout.txt
@@ -0,0 +1 @@
+-- Could NOT find NotHere \(missing: NotHere_DIR\)
diff --git a/Tests/RunCMake/find_package/MissingConfigNormal-stdout.txt b/Tests/RunCMake/find_package/MissingConfigNormal-stdout.txt
new file mode 100644
index 0000000..7af632b
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingConfigNormal-stdout.txt
@@ -0,0 +1 @@
+-- Could NOT find NotHere \(missing: NotHere_DIR\)
diff --git a/Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt b/Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt
deleted file mode 100644
index 10e71fa..0000000
--- a/Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-CMake Warning at MissingConfigOneName.cmake:1 \(find_package\):
-  Could not find a package configuration file named "NotHereConfig.cmake"
-  provided by package "NotHere".
-
-  Add the installation prefix of "NotHere" to CMAKE_PREFIX_PATH or set
-  "NotHere_DIR" to a directory containing one of the above files.  If
-  "NotHere" provides a separate development package or SDK, be sure it has
-  been installed.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/find_package/MissingConfigOneName-stdout.txt b/Tests/RunCMake/find_package/MissingConfigOneName-stdout.txt
new file mode 100644
index 0000000..7af632b
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingConfigOneName-stdout.txt
@@ -0,0 +1 @@
+-- Could NOT find NotHere \(missing: NotHere_DIR\)
diff --git a/Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt b/Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt
deleted file mode 100644
index 2f5086e..0000000
--- a/Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-CMake Warning at MissingConfigVersion.cmake:1 \(find_package\):
-  Could not find a package configuration file provided by "NotHere"
-  \(requested version 1\.2\) with any of the following names:
-
-    NotHereConfig.cmake
-    nothere-config.cmake
-
-  Add the installation prefix of "NotHere" to CMAKE_PREFIX_PATH or set
-  "NotHere_DIR" to a directory containing one of the above files.  If
-  "NotHere" provides a separate development package or SDK, be sure it has
-  been installed.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/find_package/MissingConfigVersion-stdout.txt b/Tests/RunCMake/find_package/MissingConfigVersion-stdout.txt
new file mode 100644
index 0000000..7af632b
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingConfigVersion-stdout.txt
@@ -0,0 +1 @@
+-- Could NOT find NotHere \(missing: NotHere_DIR\)
diff --git a/Tests/RunCMake/find_package/PackageRoot-stderr.txt b/Tests/RunCMake/find_package/PackageRoot-stderr.txt
new file mode 100644
index 0000000..409fa89
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot-stderr.txt
@@ -0,0 +1,383 @@
+Foo_ROOT      :
+ENV{Foo_ROOT} :
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_FILE_ZOT :FOO_TEST_FILE_ZOT-NOTFOUND
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PATH_ZOT :FOO_TEST_PATH_ZOT-NOTFOUND
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :
+Bar_ROOT      :
+ENV{Bar_ROOT} :
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND
+BAR_TEST_FILE_BAR :BAR_TEST_FILE_BAR-NOTFOUND
+BAR_TEST_FILE_ZOT :BAR_TEST_FILE_ZOT-NOTFOUND
+BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND
+BAR_TEST_PATH_BAR :BAR_TEST_PATH_BAR-NOTFOUND
+BAR_TEST_PATH_ZOT :BAR_TEST_PATH_ZOT-NOTFOUND
+BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND
+BAR_TEST_PROG_BAR :BAR_TEST_PROG_BAR-NOTFOUND
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :
+Bar_ROOT      :
+ENV{Bar_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+Bar_ROOT      :
+ENV{Bar_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/foo/env_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/foo/env_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/foo/env_root/bin/bar.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+Bar_ROOT      :
+ENV{Bar_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :
+Bar_ROOT      :.*/PackageRoot/bar/cmake_root
+ENV{Bar_ROOT} :
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :
+Bar_ROOT      :
+ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :
+Bar_ROOT      :.*/PackageRoot/bar/cmake_root
+ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :
+Bar_ROOT      :.*/PackageRoot/bar/cmake_root
+ENV{Bar_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+Bar_ROOT      :.*/PackageRoot/bar/cmake_root
+ENV{Bar_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+Bar_ROOT      :.*/PackageRoot/bar/cmake_root
+ENV{Bar_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :
+Bar_ROOT      :
+ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+Bar_ROOT      :
+ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+Bar_ROOT      :
+ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :
+Bar_ROOT      :.*/PackageRoot/bar/cmake_root
+ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+
+Foo_ROOT      :
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+Bar_ROOT      :.*/PackageRoot/bar/cmake_root
+ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+
+Foo_ROOT      :.*/PackageRoot/foo/cmake_root
+ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root
+Bar_ROOT      :.*/PackageRoot/bar/cmake_root
+ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root
+FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h
+BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h
+BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h
+BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include
+BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include
+BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot
+BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe
+BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe
diff --git a/Tests/RunCMake/find_package/PackageRoot.cmake b/Tests/RunCMake/find_package/PackageRoot.cmake
new file mode 100644
index 0000000..421c243
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot.cmake
@@ -0,0 +1,147 @@
+cmake_policy(SET CMP0057 NEW)
+list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
+set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
+
+macro(CleanUpPackageRootTest)
+  unset(Foo_ROOT)
+  unset(ENV{Foo_ROOT})
+  unset(Bar_ROOT)
+  unset(ENV{Bar_ROOT})
+  unset(FOO_TEST_FILE_FOO)
+  unset(FOO_TEST_PATH_FOO)
+  unset(FOO_TEST_PROG_FOO)
+  unset(BAR_TEST_FILE_FOO)
+  unset(BAR_TEST_FILE_BAR)
+  unset(BAR_TEST_PATH_FOO)
+  unset(BAR_TEST_PATH_BAR)
+  unset(BAR_TEST_PROG_FOO)
+  unset(BAR_TEST_PROG_BAR)
+  unset(FOO_TEST_FILE_FOO CACHE)
+  unset(FOO_TEST_PATH_FOO CACHE)
+  unset(FOO_TEST_PROG_FOO CACHE)
+  unset(BAR_TEST_FILE_FOO CACHE)
+  unset(BAR_TEST_FILE_BAR CACHE)
+  unset(BAR_TEST_PATH_FOO CACHE)
+  unset(BAR_TEST_PATH_BAR CACHE)
+  unset(BAR_TEST_PROG_FOO CACHE)
+  unset(BAR_TEST_PROG_BAR CACHE)
+endmacro()
+
+macro(RunPackageRootTest)
+  set(orig_foo_cmake_root ${Foo_ROOT})
+  set(orig_foo_env_root   $ENV{Foo_ROOT})
+  set(orig_bar_cmake_root ${Bar_ROOT})
+  set(orig_bar_env_root   $ENV{Bar_ROOT})
+
+  find_package(Foo)
+  message("Foo_ROOT      :${Foo_ROOT}")
+  message("ENV{Foo_ROOT} :$ENV{Foo_ROOT}")
+  message("FOO_TEST_FILE_FOO :${FOO_TEST_FILE_FOO}")
+  message("FOO_TEST_FILE_ZOT :${FOO_TEST_FILE_ZOT}")
+  message("FOO_TEST_PATH_FOO :${FOO_TEST_PATH_FOO}")
+  message("FOO_TEST_PATH_ZOT :${FOO_TEST_PATH_ZOT}")
+  message("FOO_TEST_PROG_FOO :${FOO_TEST_PROG_FOO}")
+  CleanUpPackageRootTest()
+  message("")
+
+  set(Foo_ROOT      ${orig_foo_cmake_root})
+  set(ENV{Foo_ROOT} ${orig_foo_env_root})
+  set(Bar_ROOT      ${orig_bar_cmake_root})
+  set(ENV{Bar_ROOT} ${orig_bar_env_root})
+
+  find_package(Foo COMPONENTS Bar)
+  message("Foo_ROOT      :${Foo_ROOT}")
+  message("ENV{Foo_ROOT} :$ENV{Foo_ROOT}")
+  message("Bar_ROOT      :${Bar_ROOT}")
+  message("ENV{Bar_ROOT} :$ENV{Bar_ROOT}")
+  message("FOO_TEST_FILE_FOO :${FOO_TEST_FILE_FOO}")
+  message("FOO_TEST_PATH_FOO :${FOO_TEST_PATH_FOO}")
+  message("FOO_TEST_PROG_FOO :${FOO_TEST_PROG_FOO}")
+  message("BAR_TEST_FILE_FOO :${BAR_TEST_FILE_FOO}")
+  message("BAR_TEST_FILE_BAR :${BAR_TEST_FILE_BAR}")
+  message("BAR_TEST_FILE_ZOT :${BAR_TEST_FILE_ZOT}")
+  message("BAR_TEST_PATH_FOO :${BAR_TEST_PATH_FOO}")
+  message("BAR_TEST_PATH_BAR :${BAR_TEST_PATH_BAR}")
+  message("BAR_TEST_PATH_ZOT :${BAR_TEST_PATH_ZOT}")
+  message("BAR_TEST_PROG_FOO :${BAR_TEST_PROG_FOO}")
+  message("BAR_TEST_PROG_BAR :${BAR_TEST_PROG_BAR}")
+  CleanUpPackageRootTest()
+  message("")
+
+  unset(orig_foo_cmake_root)
+  unset(orig_foo_env_root)
+  unset(orig_bar_cmake_root)
+  unset(orig_bar_env_root)
+endmacro()
+
+RunPackageRootTest()
+
+set(Foo_ROOT      ${PackageRoot_BASE}/foo/cmake_root)
+RunPackageRootTest()
+
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+RunPackageRootTest()
+
+set(Foo_ROOT      ${PackageRoot_BASE}/foo/cmake_root)
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+RunPackageRootTest()
+
+##
+
+set(Bar_ROOT      ${PackageRoot_BASE}/bar/cmake_root)
+RunPackageRootTest()
+
+set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root)
+RunPackageRootTest()
+
+set(Bar_ROOT      ${PackageRoot_BASE}/bar/cmake_root)
+set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root)
+RunPackageRootTest()
+
+##
+
+set(Foo_ROOT      ${PackageRoot_BASE}/foo/cmake_root)
+set(Bar_ROOT      ${PackageRoot_BASE}/bar/cmake_root)
+RunPackageRootTest()
+
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+set(Bar_ROOT      ${PackageRoot_BASE}/bar/cmake_root)
+RunPackageRootTest()
+
+set(Foo_ROOT      ${PackageRoot_BASE}/foo/cmake_root)
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+set(Bar_ROOT      ${PackageRoot_BASE}/bar/cmake_root)
+RunPackageRootTest()
+
+##
+
+set(Foo_ROOT      ${PackageRoot_BASE}/foo/cmake_root)
+set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root)
+RunPackageRootTest()
+
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root)
+RunPackageRootTest()
+
+set(Foo_ROOT      ${PackageRoot_BASE}/foo/cmake_root)
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root)
+RunPackageRootTest()
+
+##
+
+set(Foo_ROOT      ${PackageRoot_BASE}/foo/cmake_root)
+set(Bar_ROOT      ${PackageRoot_BASE}/bar/cmake_root)
+set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root)
+RunPackageRootTest()
+
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+set(Bar_ROOT      ${PackageRoot_BASE}/bar/cmake_root)
+set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root)
+RunPackageRootTest()
+
+set(Foo_ROOT      ${PackageRoot_BASE}/foo/cmake_root)
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+set(Bar_ROOT      ${PackageRoot_BASE}/bar/cmake_root)
+set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root)
+RunPackageRootTest()
diff --git a/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake b/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake
new file mode 100644
index 0000000..72774a7
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake
@@ -0,0 +1,8 @@
+find_file(BAR_TEST_FILE_FOO foo.h)
+find_file(BAR_TEST_FILE_BAR bar.h)
+find_file(BAR_TEST_FILE_ZOT zot.h PATH_SUFFIXES zot)
+find_path(BAR_TEST_PATH_FOO foo.h)
+find_path(BAR_TEST_PATH_BAR bar.h)
+find_path(BAR_TEST_PATH_ZOT zot.h PATH_SUFFIXES zot)
+find_program(BAR_TEST_PROG_FOO foo.exe)
+find_program(BAR_TEST_PROG_BAR bar.exe)
diff --git a/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake b/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake
new file mode 100644
index 0000000..e160a1d
--- /dev/null
+++ b/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake
@@ -0,0 +1,9 @@
+find_file(FOO_TEST_FILE_FOO foo.h)
+find_file(FOO_TEST_FILE_ZOT zot.h PATH_SUFFIXES zot)
+find_path(FOO_TEST_PATH_FOO foo.h)
+find_path(FOO_TEST_PATH_ZOT zot.h PATH_SUFFIXES zot)
+find_program(FOO_TEST_PROG_FOO foo.exe)
+
+if ("Bar" IN_LIST Foo_FIND_COMPONENTS)
+  find_package(Bar)
+endif ()
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/bin/bar.exe
old mode 100644
new mode 100755
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/bin/bar.exe
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/bar.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/bar.h
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/zot/zot.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/bar/cmake_root/include/zot/zot.h
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/bar/env_root/bin/bar.exe
old mode 100644
new mode 100755
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/bar/env_root/bin/bar.exe
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/bar.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/bar.h
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/zot/zot.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/bar/env_root/include/zot/zot.h
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/bar.exe
old mode 100644
new mode 100755
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/bar.exe
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/foo.exe
old mode 100644
new mode 100755
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/bin/foo.exe
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/bar.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/bar.h
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/foo.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/foo.h
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/zot/zot.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/include/zot/zot.h
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/bar.exe
old mode 100644
new mode 100755
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/bar.exe
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/foo.exe
old mode 100644
new mode 100755
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/env_root/bin/foo.exe
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/bar.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/bar.h
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/foo.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/foo.h
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/zot/zot.h
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/PackageRoot/foo/env_root/include/zot/zot.h
diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake
index 81b2906..7875db6 100644
--- a/Tests/RunCMake/find_package/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake
@@ -13,6 +13,9 @@ run_cmake(MissingConfigOneName)
 run_cmake(MissingConfigRequired)
 run_cmake(MissingConfigVersion)
 run_cmake(MixedModeOptions)
+run_cmake(PackageRoot)
 run_cmake(PolicyPush)
 run_cmake(PolicyPop)
 run_cmake(SetFoundFALSE)
+run_cmake(WrongVersion)
+run_cmake(WrongVersionConfig)
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/VersionedA-1/VersionedAConfig.cmake
similarity index 100%
copy from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
copy to Tests/RunCMake/find_package/VersionedA-1/VersionedAConfig.cmake
diff --git a/Tests/RunCMake/find_package/VersionedA-1/VersionedAConfigVersion.cmake b/Tests/RunCMake/find_package/VersionedA-1/VersionedAConfigVersion.cmake
new file mode 100644
index 0000000..2dbcfb2
--- /dev/null
+++ b/Tests/RunCMake/find_package/VersionedA-1/VersionedAConfigVersion.cmake
@@ -0,0 +1,4 @@
+set(PACKAGE_VERSION 1)
+if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL 1)
+  set(PACKAGE_VERSION_COMPATIBLE 1)
+endif()
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake b/Tests/RunCMake/find_package/VersionedA-2/VersionedAConfig.cmake
similarity index 100%
rename from Tests/RunCMake/CommandLine/DeprecateVS71-WARN-OFF.cmake
rename to Tests/RunCMake/find_package/VersionedA-2/VersionedAConfig.cmake
diff --git a/Tests/RunCMake/find_package/VersionedA-2/VersionedAConfigVersion.cmake b/Tests/RunCMake/find_package/VersionedA-2/VersionedAConfigVersion.cmake
new file mode 100644
index 0000000..7eb8332
--- /dev/null
+++ b/Tests/RunCMake/find_package/VersionedA-2/VersionedAConfigVersion.cmake
@@ -0,0 +1,4 @@
+set(PACKAGE_VERSION 2)
+if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL 2)
+  set(PACKAGE_VERSION_COMPATIBLE 1)
+endif()
diff --git a/Tests/RunCMake/find_package/WrongVersion-stderr.txt b/Tests/RunCMake/find_package/WrongVersion-stderr.txt
new file mode 100644
index 0000000..ae9fc4a
--- /dev/null
+++ b/Tests/RunCMake/find_package/WrongVersion-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Warning at WrongVersion.cmake:[0-9]+ \(find_package\):
+  Could not find a configuration file for package "VersionedA" that is
+  compatible with requested version "3".
+
+  The following configuration files were considered but not accepted:
+
+    .*/Tests/RunCMake/find_package/VersionedA-[12]/VersionedAConfig.cmake, version: [12]
+    .*/Tests/RunCMake/find_package/VersionedA-[12]/VersionedAConfig.cmake, version: [12]
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/find_package/WrongVersion.cmake b/Tests/RunCMake/find_package/WrongVersion.cmake
new file mode 100644
index 0000000..5bc711f
--- /dev/null
+++ b/Tests/RunCMake/find_package/WrongVersion.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR})
+find_package(VersionedA 3)
diff --git a/Tests/RunCMake/find_package/WrongVersionConfig-stderr.txt b/Tests/RunCMake/find_package/WrongVersionConfig-stderr.txt
new file mode 100644
index 0000000..1b84233
--- /dev/null
+++ b/Tests/RunCMake/find_package/WrongVersionConfig-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Warning at WrongVersionConfig.cmake:[0-9]+ \(find_package\):
+  Could not find a configuration file for package "VersionedA" that is
+  compatible with requested version "3".
+
+  The following configuration files were considered but not accepted:
+
+    .*/Tests/RunCMake/find_package/VersionedA-[12]/VersionedAConfig.cmake, version: [12]
+    .*/Tests/RunCMake/find_package/VersionedA-[12]/VersionedAConfig.cmake, version: [12]
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/find_package/WrongVersionConfig.cmake b/Tests/RunCMake/find_package/WrongVersionConfig.cmake
new file mode 100644
index 0000000..5bc711f
--- /dev/null
+++ b/Tests/RunCMake/find_package/WrongVersionConfig.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR})
+find_package(VersionedA 3)
diff --git a/Tests/RunCMake/get_property/IsMultiConfig-stdout.txt b/Tests/RunCMake/get_property/IsMultiConfig-stdout.txt
new file mode 100644
index 0000000..9808674
--- /dev/null
+++ b/Tests/RunCMake/get_property/IsMultiConfig-stdout.txt
@@ -0,0 +1 @@
+-- GENERATOR_IS_MULTI_CONFIG=1
diff --git a/Tests/RunCMake/get_property/IsMultiConfig.cmake b/Tests/RunCMake/get_property/IsMultiConfig.cmake
new file mode 100644
index 0000000..64d5ff6
--- /dev/null
+++ b/Tests/RunCMake/get_property/IsMultiConfig.cmake
@@ -0,0 +1,2 @@
+get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+message(STATUS "GENERATOR_IS_MULTI_CONFIG=${is_multi_config}")
diff --git a/Tests/RunCMake/get_property/NotMultiConfig-stdout.txt b/Tests/RunCMake/get_property/NotMultiConfig-stdout.txt
new file mode 100644
index 0000000..8e0f895
--- /dev/null
+++ b/Tests/RunCMake/get_property/NotMultiConfig-stdout.txt
@@ -0,0 +1 @@
+-- GENERATOR_IS_MULTI_CONFIG=0
diff --git a/Tests/RunCMake/get_property/NotMultiConfig.cmake b/Tests/RunCMake/get_property/NotMultiConfig.cmake
new file mode 100644
index 0000000..59172d5
--- /dev/null
+++ b/Tests/RunCMake/get_property/NotMultiConfig.cmake
@@ -0,0 +1 @@
+include(IsMultiConfig.cmake)
diff --git a/Tests/RunCMake/get_property/RunCMakeTest.cmake b/Tests/RunCMake/get_property/RunCMakeTest.cmake
index 00eef34..017990f 100644
--- a/Tests/RunCMake/get_property/RunCMakeTest.cmake
+++ b/Tests/RunCMake/get_property/RunCMakeTest.cmake
@@ -22,3 +22,9 @@ run_cmake(NoTarget)
 run_cmake(NoSource)
 run_cmake(NoProperty)
 run_cmake(NoCache)
+
+if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode")
+  run_cmake(IsMultiConfig)
+else()
+  run_cmake(NotMultiConfig)
+endif()
diff --git a/Tests/RunCMake/if/RunCMakeTest.cmake b/Tests/RunCMake/if/RunCMakeTest.cmake
index 077d00a..f54edf7 100644
--- a/Tests/RunCMake/if/RunCMakeTest.cmake
+++ b/Tests/RunCMake/if/RunCMakeTest.cmake
@@ -3,7 +3,11 @@ include(RunCMake)
 run_cmake(InvalidArgument1)
 run_cmake(IsDirectory)
 run_cmake(IsDirectoryLong)
+run_cmake(duplicate-deep-else)
+run_cmake(duplicate-else)
+run_cmake(duplicate-else-after-elseif)
 run_cmake(elseif-message)
+run_cmake(misplaced-elseif)
 
 run_cmake(MatchesSelf)
 
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/if/duplicate-deep-else-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/if/duplicate-deep-else-result.txt
diff --git a/Tests/RunCMake/if/duplicate-deep-else-stderr.txt b/Tests/RunCMake/if/duplicate-deep-else-stderr.txt
new file mode 100644
index 0000000..ac2335c
--- /dev/null
+++ b/Tests/RunCMake/if/duplicate-deep-else-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at duplicate-deep-else.cmake:[0-9]+ \(else\):
+  A duplicate ELSE command was found inside an IF block.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/if/duplicate-deep-else.cmake b/Tests/RunCMake/if/duplicate-deep-else.cmake
new file mode 100644
index 0000000..94f06de
--- /dev/null
+++ b/Tests/RunCMake/if/duplicate-deep-else.cmake
@@ -0,0 +1,7 @@
+if(0)
+else()
+  if(0)
+  else()
+  else()
+  endif()
+endif()
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/if/duplicate-else-after-elseif-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/if/duplicate-else-after-elseif-result.txt
diff --git a/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt b/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt
new file mode 100644
index 0000000..ba6765c
--- /dev/null
+++ b/Tests/RunCMake/if/duplicate-else-after-elseif-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at duplicate-else-after-elseif.cmake:[0-9]+ \(else\):
+  A duplicate ELSE command was found inside an IF block.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/if/duplicate-else-after-elseif.cmake b/Tests/RunCMake/if/duplicate-else-after-elseif.cmake
new file mode 100644
index 0000000..d1d4ac1
--- /dev/null
+++ b/Tests/RunCMake/if/duplicate-else-after-elseif.cmake
@@ -0,0 +1,5 @@
+if(0)
+elseif(0)
+else()
+else()
+endif()
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/if/duplicate-else-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/if/duplicate-else-result.txt
diff --git a/Tests/RunCMake/if/duplicate-else-stderr.txt b/Tests/RunCMake/if/duplicate-else-stderr.txt
new file mode 100644
index 0000000..e0dd01f
--- /dev/null
+++ b/Tests/RunCMake/if/duplicate-else-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at duplicate-else.cmake:[0-9]+ \(else\):
+  A duplicate ELSE command was found inside an IF block.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/if/duplicate-else.cmake b/Tests/RunCMake/if/duplicate-else.cmake
new file mode 100644
index 0000000..14a03ac
--- /dev/null
+++ b/Tests/RunCMake/if/duplicate-else.cmake
@@ -0,0 +1,4 @@
+if(0)
+else()
+else()
+endif()
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/if/misplaced-elseif-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/if/misplaced-elseif-result.txt
diff --git a/Tests/RunCMake/if/misplaced-elseif-stderr.txt b/Tests/RunCMake/if/misplaced-elseif-stderr.txt
new file mode 100644
index 0000000..c4b0266
--- /dev/null
+++ b/Tests/RunCMake/if/misplaced-elseif-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at misplaced-elseif.cmake:[0-9]+ \(elseif\):
+  An ELSEIF command was found after an ELSE command.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/if/misplaced-elseif.cmake b/Tests/RunCMake/if/misplaced-elseif.cmake
new file mode 100644
index 0000000..d27f24e
--- /dev/null
+++ b/Tests/RunCMake/if/misplaced-elseif.cmake
@@ -0,0 +1,4 @@
+if(0)
+else()
+elseif(1)
+endif()
diff --git a/Tests/RunCMake/include_external_msproject/CustomConfig-check.cmake b/Tests/RunCMake/include_external_msproject/CustomConfig-check.cmake
new file mode 100644
index 0000000..1a940b8
--- /dev/null
+++ b/Tests/RunCMake/include_external_msproject/CustomConfig-check.cmake
@@ -0,0 +1 @@
+check_project(CustomConfig external "aaa-bbb-ccc-000" "" "" "Custom - Release")
diff --git a/Tests/RunCMake/include_external_msproject/CustomConfig.cmake b/Tests/RunCMake/include_external_msproject/CustomConfig.cmake
new file mode 100644
index 0000000..1f935cd
--- /dev/null
+++ b/Tests/RunCMake/include_external_msproject/CustomConfig.cmake
@@ -0,0 +1,3 @@
+include_external_msproject(external external.project
+                           GUID aaa-bbb-ccc-000)
+set_target_properties(external PROPERTIES MAP_IMPORTED_CONFIG_RELEASE "Custom - Release")
diff --git a/Tests/RunCMake/include_external_msproject/CustomGuid-check.cmake b/Tests/RunCMake/include_external_msproject/CustomGuid-check.cmake
index 68dec4c..3747934 100644
--- a/Tests/RunCMake/include_external_msproject/CustomGuid-check.cmake
+++ b/Tests/RunCMake/include_external_msproject/CustomGuid-check.cmake
@@ -1 +1 @@
-check_project(CustomGuid external "aaa-bbb-ccc-000" "" "")
+check_project(CustomGuid external "aaa-bbb-ccc-000" "" "" "")
diff --git a/Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform-check.cmake b/Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform-check.cmake
index 614712e..0b2ac1d 100644
--- a/Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform-check.cmake
+++ b/Tests/RunCMake/include_external_msproject/CustomGuidTypePlatform-check.cmake
@@ -1 +1 @@
-check_project(CustomGuidTypePlatform external "aaa-bbb-ccc-111" "aaa-bbb-ccc-ddd-eee" "Custom Platform")
+check_project(CustomGuidTypePlatform external "aaa-bbb-ccc-111" "aaa-bbb-ccc-ddd-eee" "Custom Platform" "")
diff --git a/Tests/RunCMake/include_external_msproject/CustomTypePlatform-check.cmake b/Tests/RunCMake/include_external_msproject/CustomTypePlatform-check.cmake
index 054eeb0..c431b03 100644
--- a/Tests/RunCMake/include_external_msproject/CustomTypePlatform-check.cmake
+++ b/Tests/RunCMake/include_external_msproject/CustomTypePlatform-check.cmake
@@ -1 +1 @@
-check_project(CustomTypePlatform external "" "aaa-bbb-ccc-ddd-eee" "Custom Platform")
+check_project(CustomTypePlatform external "" "aaa-bbb-ccc-ddd-eee" "Custom Platform" "")
diff --git a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake
index 90710f9..47dac34 100644
--- a/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/include_external_msproject/RunCMakeTest.cmake
@@ -4,3 +4,4 @@ include(${CMAKE_CURRENT_LIST_DIR}/check_utils.cmake)
 run_cmake(CustomGuid)
 run_cmake(CustomTypePlatform)
 run_cmake(CustomGuidTypePlatform)
+run_cmake(CustomConfig)
diff --git a/Tests/RunCMake/include_external_msproject/check_utils.cmake b/Tests/RunCMake/include_external_msproject/check_utils.cmake
index 5dd92f9..e9e9cac 100644
--- a/Tests/RunCMake/include_external_msproject/check_utils.cmake
+++ b/Tests/RunCMake/include_external_msproject/check_utils.cmake
@@ -71,8 +71,24 @@ function(check_custom_platform TARGET_FILE PROJECT_NAME PLATFORM_NAME RESULT)
   set(${RESULT} ${IS_FOUND} PARENT_SCOPE)
 endfunction()
 
+# Search project's build configuration line by project name and target configuration name.
+# Returns TRUE if found and FALSE otherwise
+function(check_custom_configuration TARGET_FILE PROJECT_NAME SLN_CONFIG DST_CONFIG RESULT)
+  set(${RESULT} "FALSE" PARENT_SCOPE)
+  # extract project guid
+  parse_project_section(${TARGET_FILE} ${PROJECT_NAME})
+  if(NOT IS_FOUND)
+    return()
+  endif()
+
+  set(REG_EXP "^(\t)*\\{${FOUND_GUID}\\}\\.${SLN_CONFIG}[^ ]*\\.ActiveCfg = ${DST_CONFIG}\\|.*$")
+  check_line_exists(${TARGET_FILE} REG_EXP)
+
+  set(${RESULT} ${IS_FOUND} PARENT_SCOPE)
+endfunction()
+
 # RunCMake test check helper
-function(check_project test name guid type platform)
+function(check_project test name guid type platform imported_release_config_name)
   set(sln "${RunCMake_TEST_BINARY_DIR}/${test}.sln")
   set(sep "")
   set(failed "")
@@ -88,6 +104,9 @@ function(check_project test name guid type platform)
       set(platform "Win32")
     endif()
   endif()
+  if(NOT imported_release_config_name)
+    set(imported_release_config_name "Release")
+  endif()
   if(guid)
     check_project_guid("${sln}" "${name}" "${guid}" passed_guid)
     if(NOT passed_guid)
@@ -107,5 +126,11 @@ function(check_project test name guid type platform)
     string(APPEND failed "${sep}${name} solution has no project with expected PLATFORM=${platform}")
     set(sep "\n")
   endif()
+  check_custom_configuration("${sln}" "${name}" "Release" "${imported_release_config_name}" passed_configuration)
+  if(NOT passed_configuration)
+    string(APPEND failed "${sep}${name} solution has no project with expected CONFIG=${imported_release_config_name}")
+    set(sep "\n")
+  endif()
+
   set(RunCMake_TEST_FAILED "${failed}" PARENT_SCOPE)
 endfunction()
diff --git a/Tests/RunCMake/install/EXPORT-OldIFace.cmake b/Tests/RunCMake/install/EXPORT-OldIFace.cmake
index 033f684..ee3fb23 100644
--- a/Tests/RunCMake/install/EXPORT-OldIFace.cmake
+++ b/Tests/RunCMake/install/EXPORT-OldIFace.cmake
@@ -1,5 +1,6 @@
 enable_language(C)
 set(CMAKE_BUILD_WITH_INSTALL_RPATH 1)
+set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR 1)
 add_subdirectory(EXPORT-OldIFace)
 add_library(foo SHARED empty.c)
 target_link_libraries(foo bar)
diff --git a/Tests/RunCMake/install/FILES-TARGET_OBJECTS-all-check.cmake b/Tests/RunCMake/install/FILES-TARGET_OBJECTS-all-check.cmake
new file mode 100644
index 0000000..f7f2a3a
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-TARGET_OBJECTS-all-check.cmake
@@ -0,0 +1 @@
+check_installed([[^objs;objs/obj1(\.c)?\.(o|obj);objs/obj2(\.c)?\.(o|obj)$]])
diff --git a/Tests/RunCMake/install/FILES-TARGET_OBJECTS.cmake b/Tests/RunCMake/install/FILES-TARGET_OBJECTS.cmake
new file mode 100644
index 0000000..40c58ad
--- /dev/null
+++ b/Tests/RunCMake/install/FILES-TARGET_OBJECTS.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+add_library(objs OBJECT obj1.c obj2.c)
+install(FILES $<TARGET_OBJECTS:objs> DESTINATION objs)
diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake
index 45693b5..1a60f0c 100644
--- a/Tests/RunCMake/install/RunCMakeTest.cmake
+++ b/Tests/RunCMake/install/RunCMakeTest.cmake
@@ -13,12 +13,15 @@ function(run_install_test case)
   # Check "all" components.
   set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-all)
   run_cmake_command(${case}-all ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -P cmake_install.cmake)
-  # Check unspecified component.
-  set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-uns)
-  run_cmake_command(${case}-uns ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=Unspecified -P cmake_install.cmake)
-  # Check explicit component.
-  set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-exc)
-  run_cmake_command(${case}-exc ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=exc -P cmake_install.cmake)
+
+  if(run_install_test_components)
+    # Check unspecified component.
+    set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-uns)
+    run_cmake_command(${case}-uns ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=Unspecified -P cmake_install.cmake)
+    # Check explicit component.
+    set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root-exc)
+    run_cmake_command(${case}-exc ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -DCOMPONENT=exc -P cmake_install.cmake)
+  endif()
 endfunction()
 
 # Function called in *-check.cmake scripts to check installed files.
@@ -57,5 +60,10 @@ run_cmake(CMP0062-OLD)
 run_cmake(CMP0062-NEW)
 run_cmake(CMP0062-WARN)
 
+if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
+  run_install_test(FILES-TARGET_OBJECTS)
+endif()
+
+set(run_install_test_components 1)
 run_install_test(FILES-EXCLUDE_FROM_ALL)
 run_install_test(TARGETS-EXCLUDE_FROM_ALL)
diff --git a/Tests/RunCMake/install/obj1.c b/Tests/RunCMake/install/obj1.c
new file mode 100644
index 0000000..2411aab
--- /dev/null
+++ b/Tests/RunCMake/install/obj1.c
@@ -0,0 +1,4 @@
+int obj1(void)
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/install/obj2.c b/Tests/RunCMake/install/obj2.c
new file mode 100644
index 0000000..2dad71e
--- /dev/null
+++ b/Tests/RunCMake/install/obj2.c
@@ -0,0 +1,4 @@
+int obj2(void)
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/project/ProjectDescription-stdout.txt b/Tests/RunCMake/project/ProjectDescription-stdout.txt
new file mode 100644
index 0000000..ffa9092
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectDescription-stdout.txt
@@ -0,0 +1 @@
+PROJECT_DESCRIPTION=Test Project
diff --git a/Tests/RunCMake/project/ProjectDescription.cmake b/Tests/RunCMake/project/ProjectDescription.cmake
new file mode 100644
index 0000000..3a47362
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectDescription.cmake
@@ -0,0 +1,6 @@
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 DESCRIPTION "Test Project" LANGUAGES)
+if(NOT PROJECT_DESCRIPTION)
+  message(FATAL_ERROR "PROJECT_DESCRIPTION expected to be set")
+endif()
+message(STATUS "PROJECT_DESCRIPTION=${PROJECT_DESCRIPTION}")
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/project/ProjectDescription2-result.txt
similarity index 100%
copy from Tests/RunCMake/ObjectLibrary/Export-result.txt
copy to Tests/RunCMake/project/ProjectDescription2-result.txt
diff --git a/Tests/RunCMake/project/ProjectDescription2-stderr.txt b/Tests/RunCMake/project/ProjectDescription2-stderr.txt
new file mode 100644
index 0000000..558e2df
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectDescription2-stderr.txt
@@ -0,0 +1 @@
+  DESCRITPION may be specified at most once.
diff --git a/Tests/RunCMake/project/ProjectDescription2.cmake b/Tests/RunCMake/project/ProjectDescription2.cmake
new file mode 100644
index 0000000..3f186ba
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectDescription2.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 DESCRIPTION "Test Project" DESCRIPTION "Only once allowed" LANGUAGES)
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index dba97d2..3d13e2e 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -7,6 +7,8 @@ run_cmake(LanguagesImplicit)
 run_cmake(LanguagesEmpty)
 run_cmake(LanguagesNONE)
 run_cmake(LanguagesTwice)
+run_cmake(ProjectDescription)
+run_cmake(ProjectDescription2)
 run_cmake(VersionAndLanguagesEmpty)
 run_cmake(VersionEmpty)
 run_cmake(VersionInvalid)
diff --git a/Tests/RunCMake/separate_arguments/CMakeLists.txt b/Tests/RunCMake/separate_arguments/CMakeLists.txt
new file mode 100644
index 0000000..2897109
--- /dev/null
+++ b/Tests/RunCMake/separate_arguments/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.0)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/separate_arguments/EmptyCommand.cmake b/Tests/RunCMake/separate_arguments/EmptyCommand.cmake
new file mode 100644
index 0000000..895b6ac
--- /dev/null
+++ b/Tests/RunCMake/separate_arguments/EmptyCommand.cmake
@@ -0,0 +1,6 @@
+set(nothing)
+separate_arguments(nothing)
+if(DEFINED nothing)
+  message(FATAL_ERROR "separate_arguments null-case failed: "
+    "nothing=[${nothing}]")
+endif()
diff --git a/Tests/RunCMake/separate_arguments/NativeCommand.cmake b/Tests/RunCMake/separate_arguments/NativeCommand.cmake
new file mode 100644
index 0000000..1cb009e
--- /dev/null
+++ b/Tests/RunCMake/separate_arguments/NativeCommand.cmake
@@ -0,0 +1,19 @@
+set(unix_cmd "a \"b c\" 'd e' \";\" \\ \\'\\\" '\\'' \"\\\"\"")
+set(unix_exp "a;b c;d e;\;; '\";';\"")
+
+set(windows_cmd "a \"b c\" 'd e' \";\" \\ \"c:\\windows\\path\\\\\" \\\"")
+set(windows_exp "a;b c;'d;e';\;;\\;c:\\windows\\path\\;\"")
+
+if(CMAKE_HOST_WIN32)
+  set(native_cmd "${windows_cmd}")
+  set(native_exp "${windows_exp}")
+else()
+  set(native_cmd "${unix_cmd}")
+  set(native_exp "${unix_exp}")
+endif()
+separate_arguments(native_out NATIVE_COMMAND "${native_cmd}")
+
+if(NOT "${native_out}" STREQUAL "${native_exp}")
+  message(FATAL_ERROR "separate_arguments native-style failed.  "
+    "Expected\n  [${native_exp}]\nbut got\n  [${native_out}]\n")
+endif()
diff --git a/Tests/RunCMake/separate_arguments/PlainCommand.cmake b/Tests/RunCMake/separate_arguments/PlainCommand.cmake
new file mode 100644
index 0000000..311a993
--- /dev/null
+++ b/Tests/RunCMake/separate_arguments/PlainCommand.cmake
@@ -0,0 +1,8 @@
+set(old_out "a b  c")
+separate_arguments(old_out)
+set(old_exp "a;b;;c")
+
+if(NOT "${old_out}" STREQUAL "${old_exp}")
+  message(FATAL_ERROR "separate_arguments old-style failed.  "
+    "Expected\n  [${old_exp}]\nbut got\n  [${old_out}]\n")
+endif()
diff --git a/Tests/RunCMake/separate_arguments/RunCMakeTest.cmake b/Tests/RunCMake/separate_arguments/RunCMakeTest.cmake
new file mode 100644
index 0000000..07951bb
--- /dev/null
+++ b/Tests/RunCMake/separate_arguments/RunCMakeTest.cmake
@@ -0,0 +1,7 @@
+include(RunCMake)
+
+run_cmake(EmptyCommand)
+run_cmake(PlainCommand)
+run_cmake(UnixCommand)
+run_cmake(WindowsCommand)
+run_cmake(NativeCommand)
diff --git a/Tests/RunCMake/separate_arguments/UnixCommand.cmake b/Tests/RunCMake/separate_arguments/UnixCommand.cmake
new file mode 100644
index 0000000..0b5767a
--- /dev/null
+++ b/Tests/RunCMake/separate_arguments/UnixCommand.cmake
@@ -0,0 +1,8 @@
+set(unix_cmd "a \"b c\" 'd e' \";\" \\ \\'\\\" '\\'' \"\\\"\"")
+set(unix_exp "a;b c;d e;\;; '\";';\"")
+separate_arguments(unix_out UNIX_COMMAND "${unix_cmd}")
+
+if(NOT "${unix_out}" STREQUAL "${unix_exp}")
+  message(FATAL_ERROR "separate_arguments unix-style failed.  "
+    "Expected\n  [${unix_exp}]\nbut got\n  [${unix_out}]\n")
+endif()
diff --git a/Tests/RunCMake/separate_arguments/WindowsCommand.cmake b/Tests/RunCMake/separate_arguments/WindowsCommand.cmake
new file mode 100644
index 0000000..86aa14a
--- /dev/null
+++ b/Tests/RunCMake/separate_arguments/WindowsCommand.cmake
@@ -0,0 +1,8 @@
+set(windows_cmd "a \"b c\" 'd e' \";\" \\ \"c:\\windows\\path\\\\\" \\\"")
+set(windows_exp "a;b c;'d;e';\;;\\;c:\\windows\\path\\;\"")
+separate_arguments(windows_out WINDOWS_COMMAND "${windows_cmd}")
+
+if(NOT "${windows_out}" STREQUAL "${windows_exp}")
+  message(FATAL_ERROR "separate_arguments windows-style failed.  "
+    "Expected\n  [${windows_exp}]\nbut got\n  [${windows_out}]\n")
+endif()
diff --git a/Tests/RunCMake/target_compile_features/CMakeLists.txt b/Tests/RunCMake/target_compile_features/CMakeLists.txt
index 3482e6b..2897109 100644
--- a/Tests/RunCMake/target_compile_features/CMakeLists.txt
+++ b/Tests/RunCMake/target_compile_features/CMakeLists.txt
@@ -1,3 +1,3 @@
 cmake_minimum_required(VERSION 3.0)
-project(${RunCMake_TEST} CXX)
+project(${RunCMake_TEST} NONE)
 include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
index 33faf2b..1f67f11 100644
--- a/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_compile_features/RunCMakeTest.cmake
@@ -11,3 +11,4 @@ run_cmake(not_a_cxx_feature)
 run_cmake(no_matching_cxx_feature)
 run_cmake(not_a_c_feature)
 run_cmake(no_matching_c_feature)
+run_cmake(cxx_not_enabled)
diff --git a/Tests/RunCMake/target_compile_features/alias_target-stderr.txt b/Tests/RunCMake/target_compile_features/alias_target-stderr.txt
index 417bf62..5ebe170 100644
--- a/Tests/RunCMake/target_compile_features/alias_target-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/alias_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at alias_target.cmake:4 \(target_compile_features\):
+CMake Error at alias_target.cmake:[0-9]+ \(target_compile_features\):
   target_compile_features can not be used on an ALIAS target.
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/alias_target.cmake b/Tests/RunCMake/target_compile_features/alias_target.cmake
index d35ddba..6fcdada 100644
--- a/Tests/RunCMake/target_compile_features/alias_target.cmake
+++ b/Tests/RunCMake/target_compile_features/alias_target.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
 
 add_executable(main empty.cpp)
 add_executable(Alias::Main ALIAS main)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt
similarity index 100%
rename from Tests/RunCMake/ObjectLibrary/Export-result.txt
rename to Tests/RunCMake/target_compile_features/cxx_not_enabled-result.txt
diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt b/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt
new file mode 100644
index 0000000..4f707c7
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt
@@ -0,0 +1,4 @@
+^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:3 \(include\)$
diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake b/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake
new file mode 100644
index 0000000..b7e9119
--- /dev/null
+++ b/Tests/RunCMake/target_compile_features/cxx_not_enabled.cmake
@@ -0,0 +1,2 @@
+add_executable(main empty.c)
+target_compile_features(main PRIVATE cxx_decltype)
diff --git a/Tests/RunCMake/target_compile_features/imported_target-stderr.txt b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
index c6ff5ec..7a07427 100644
--- a/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at imported_target.cmake:3 \(target_compile_features\):
+CMake Error at imported_target.cmake:[0-9]+ \(target_compile_features\):
   Cannot specify compile features for imported target "main".
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/imported_target.cmake b/Tests/RunCMake/target_compile_features/imported_target.cmake
index e248c2f..e886ce9 100644
--- a/Tests/RunCMake/target_compile_features/imported_target.cmake
+++ b/Tests/RunCMake/target_compile_features/imported_target.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
 
 add_library(main INTERFACE IMPORTED)
 target_compile_features(main INTERFACE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt b/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt
index bd5b7b9..9917be7 100644
--- a/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/invalid_args-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at invalid_args.cmake:3 \(target_compile_features\):
+CMake Error at invalid_args.cmake:[0-9]+ \(target_compile_features\):
   target_compile_features called with invalid arguments
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args.cmake b/Tests/RunCMake/target_compile_features/invalid_args.cmake
index 1a7fb37..cc051a4 100644
--- a/Tests/RunCMake/target_compile_features/invalid_args.cmake
+++ b/Tests/RunCMake/target_compile_features/invalid_args.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
 
 add_executable(main empty.cpp)
 target_compile_features(main INVALID cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
index c30209a..3708998 100644
--- a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at invalid_args_on_interface.cmake:3 \(target_compile_features\):
+CMake Error at invalid_args_on_interface.cmake:[0-9]+ \(target_compile_features\):
   target_compile_features may only be set INTERFACE properties on INTERFACE
   targets
 Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake b/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake
index 324d0f3..49d2d82 100644
--- a/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake
+++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
 
 add_library(main INTERFACE)
 target_compile_features(main PRIVATE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt b/Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt
index 96b959c..1875d12 100644
--- a/Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/no_matching_c_feature-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at no_matching_c_feature.cmake:[0-9][0-9]? \((target_compile_features|message)\):
+CMake Error at no_matching_c_feature.cmake:[0-9]+ \((target_compile_features|message)\):
   The compiler feature "gnu_c_dummy" is not known to C compiler
 
   "GNU"
diff --git a/Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake b/Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake
index a44caf2..0e93b41 100644
--- a/Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake
+++ b/Tests/RunCMake/target_compile_features/no_matching_c_feature.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
 
 if (NOT ";${CMAKE_C_COMPILE_FEATURES};" MATCHES ";gnu_c_typeof;")
   # Simulate passing the test.
diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt
index f976dfe..90d41c9 100644
--- a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at no_matching_cxx_feature.cmake:[0-9][0-9]? \((target_compile_features|message)\):
+CMake Error at no_matching_cxx_feature.cmake:[0-9]+ \((target_compile_features|message)\):
   The compiler feature "[^"]+" is not known to CXX compiler
 
   "[^"]*"
diff --git a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake
index ab1fd76..4ee3445 100644
--- a/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake
+++ b/Tests/RunCMake/target_compile_features/no_matching_cxx_feature.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
 
 if (NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";gnu_cxx_typeof;"
     AND NOT ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";msvc_cxx_sealed;" )
diff --git a/Tests/RunCMake/target_compile_features/no_target-stderr.txt b/Tests/RunCMake/target_compile_features/no_target-stderr.txt
index 323ba7a..65974b4 100644
--- a/Tests/RunCMake/target_compile_features/no_target-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/no_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at no_target.cmake:2 \(target_compile_features\):
+CMake Error at no_target.cmake:[0-9]+ \(target_compile_features\):
   Cannot specify compile features for target "main" which is not built by
   this project.
 Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/target_compile_features/no_target.cmake b/Tests/RunCMake/target_compile_features/no_target.cmake
index 3f0afe2..a514de8 100644
--- a/Tests/RunCMake/target_compile_features/no_target.cmake
+++ b/Tests/RunCMake/target_compile_features/no_target.cmake
@@ -1,2 +1,3 @@
+enable_language(CXX)
 
 target_compile_features(main INTERFACE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt b/Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt
index 6dd00f3..493c582 100644
--- a/Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/not_a_c_feature-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at not_a_c_feature.cmake:3 \(target_compile_features\):
+CMake Error at not_a_c_feature.cmake:[0-9]+ \(target_compile_features\):
   target_compile_features specified unknown feature "c_not_a_feature" for
   target "main".
 Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/target_compile_features/not_a_c_feature.cmake b/Tests/RunCMake/target_compile_features/not_a_c_feature.cmake
index 0420698..f5d70d0 100644
--- a/Tests/RunCMake/target_compile_features/not_a_c_feature.cmake
+++ b/Tests/RunCMake/target_compile_features/not_a_c_feature.cmake
@@ -1,3 +1,4 @@
+enable_language(C)
 
 add_executable(main empty.c)
 target_compile_features(main
diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt
index efa2bad..3dbf0e6 100644
--- a/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at not_a_cxx_feature.cmake:3 \(target_compile_features\):
+CMake Error at not_a_cxx_feature.cmake:[0-9]+ \(target_compile_features\):
   target_compile_features specified unknown feature "cxx_not_a_feature" for
   target "main".
 Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake b/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake
index 0207b72..bc3a8c4 100644
--- a/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake
+++ b/Tests/RunCMake/target_compile_features/not_a_cxx_feature.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
 
 add_executable(main empty.cpp)
 target_compile_features(main
diff --git a/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt b/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt
index 2f8d812..c0c2efa 100644
--- a/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/not_enough_args-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at not_enough_args.cmake:3 \(target_compile_features\):
+CMake Error at not_enough_args.cmake:[0-9]+ \(target_compile_features\):
   target_compile_features called with incorrect number of arguments
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_compile_features/not_enough_args.cmake b/Tests/RunCMake/target_compile_features/not_enough_args.cmake
index 9561230..f5b7198 100644
--- a/Tests/RunCMake/target_compile_features/not_enough_args.cmake
+++ b/Tests/RunCMake/target_compile_features/not_enough_args.cmake
@@ -1,3 +1,4 @@
+enable_language(CXX)
 
 add_executable(main empty.cpp)
 target_compile_features(main)
diff --git a/Tests/RunCMake/target_compile_features/utility_target-stderr.txt b/Tests/RunCMake/target_compile_features/utility_target-stderr.txt
index d239059..ff03310 100644
--- a/Tests/RunCMake/target_compile_features/utility_target-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/utility_target-stderr.txt
@@ -1,4 +1,4 @@
-CMake Error at utility_target.cmake:4 \(target_compile_features\):
+CMake Error at utility_target.cmake:[0-9]+ \(target_compile_features\):
   target_compile_features called with non-compilable target type
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/Server/cmakelib.py b/Tests/Server/cmakelib.py
index d11431d..78450d5 100644
--- a/Tests/Server/cmakelib.py
+++ b/Tests/Server/cmakelib.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import sys, subprocess, json
 
 termwidth = 150
@@ -13,8 +14,8 @@ def ordered(obj):
     return obj
 
 def col_print(title, array):
-  print
-  print
+  print()
+  print()
   print(title)
 
   indentwidth = 4
diff --git a/Tests/Server/server-test.py b/Tests/Server/server-test.py
index 14767f4..62d9008 100644
--- a/Tests/Server/server-test.py
+++ b/Tests/Server/server-test.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import sys, cmakelib, json, os, shutil
 
 debug = True
diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt
index 4cf7355..f8068b1 100644
--- a/Tests/SimpleInstall/CMakeLists.txt
+++ b/Tests/SimpleInstall/CMakeLists.txt
@@ -365,6 +365,7 @@ set(CPACK_PACKAGE_EXECUTABLES "SimpleInstall" "Simple Install")
 set(CMAKE_INSTALL_MFC_LIBRARIES 1)
 set(CMAKE_INSTALL_DEBUG_LIBRARIES 1)
 set(CMAKE_INSTALL_UCRT_LIBRARIES 1)
+set(CMAKE_INSTALL_OPENMP_LIBRARIES 1)
 include(InstallRequiredSystemLibraries)
 
 if(CTEST_TEST_CPACK)
diff --git a/Tests/SourceGroups/CMakeLists.txt b/Tests/SourceGroups/CMakeLists.txt
index 9289e84..4e4a030 100644
--- a/Tests/SourceGroups/CMakeLists.txt
+++ b/Tests/SourceGroups/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 3.8)
 project(SourceGroups)
 
 # this is not really a test which can fail
@@ -33,10 +33,11 @@ source_group(EmptyGroup)
 set(root ${CMAKE_CURRENT_SOURCE_DIR})
 
 set(tree_files_without_prefix ${root}/sub1/tree_bar.c
-                              ${root}/sub1/tree_baz.c
-                              ${root}/sub1/tree_subdir/tree_foobar.c)
+                              sub1/tree_baz.c
+                              sub1/../sub1/tree_subdir/tree_foobar.c)
 
-set(tree_files_with_prefix ${root}/tree_foo.c)
+set(tree_files_with_prefix ${root}/tree_prefix_foo.c
+                           tree_prefix_bar.c)
 
 source_group(TREE ${root} FILES ${tree_files_without_prefix})
 
diff --git a/Tests/SourceGroups/main.c b/Tests/SourceGroups/main.c
index b88f2f8..4d84cf2 100644
--- a/Tests/SourceGroups/main.c
+++ b/Tests/SourceGroups/main.c
@@ -5,7 +5,8 @@ extern int bar(void);
 extern int foobar(void);
 extern int barbar(void);
 extern int baz(void);
-extern int tree_foo(void);
+extern int tree_prefix_foo(void);
+extern int tree_prefix_bar(void);
 extern int tree_bar(void);
 extern int tree_foobar(void);
 extern int tree_baz(void);
@@ -15,7 +16,9 @@ int main()
   printf("foo: %d bar: %d foobar: %d barbar: %d baz: %d\n", foo(), bar(),
          foobar(), barbar(), baz());
 
-  printf("tree_foo: %d tree_bar: %d tree_foobar: %d tree_baz: %d\n",
-         tree_foo(), tree_bar(), tree_foobar(), tree_baz());
+  printf("tree_prefix_foo: %d tree_prefix_bar: %d tree_bar: %d tree_foobar: "
+         "%d tree_baz: %d\n",
+         tree_prefix_foo(), tree_prefix_bar(), tree_bar(), tree_foobar(),
+         tree_baz());
   return 0;
 }
diff --git a/Tests/SourceGroups/tree_foo.c b/Tests/SourceGroups/tree_foo.c
deleted file mode 100644
index d392e41..0000000
--- a/Tests/SourceGroups/tree_foo.c
+++ /dev/null
@@ -1,4 +0,0 @@
-int tree_foo(void)
-{
-  return 6;
-}
diff --git a/Tests/SourceGroups/tree_prefix_bar.c b/Tests/SourceGroups/tree_prefix_bar.c
new file mode 100644
index 0000000..bd98476
--- /dev/null
+++ b/Tests/SourceGroups/tree_prefix_bar.c
@@ -0,0 +1,4 @@
+int tree_prefix_bar(void)
+{
+  return 66;
+}
diff --git a/Tests/SourceGroups/tree_prefix_foo.c b/Tests/SourceGroups/tree_prefix_foo.c
new file mode 100644
index 0000000..92c2fd7
--- /dev/null
+++ b/Tests/SourceGroups/tree_prefix_foo.c
@@ -0,0 +1,4 @@
+int tree_prefix_foo(void)
+{
+  return 6;
+}
diff --git a/Tests/VSNASM/CMakeLists.txt b/Tests/VSNASM/CMakeLists.txt
new file mode 100644
index 0000000..c2e29df
--- /dev/null
+++ b/Tests/VSNASM/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(VSNASM C ASM_NASM)
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+  add_definitions(-DTESTx64)
+  string(APPEND CMAKE_ASM_NASM_FLAGS " -DTEST2x64")
+else()
+  add_definitions(-DTESTi386)
+endif()
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
+add_executable(VSNASM main.c foo.asm)
diff --git a/Tests/VSNASM/foo.asm b/Tests/VSNASM/foo.asm
new file mode 100644
index 0000000..aba0673
--- /dev/null
+++ b/Tests/VSNASM/foo.asm
@@ -0,0 +1,7 @@
+section .text
+%ifdef TEST2x64
+global foo
+%else
+global _foo
+%endif
+%include "foo-proc.asm"
diff --git a/Tests/VSNASM/include/foo-proc.asm b/Tests/VSNASM/include/foo-proc.asm
new file mode 100644
index 0000000..450a791
--- /dev/null
+++ b/Tests/VSNASM/include/foo-proc.asm
@@ -0,0 +1,7 @@
+%ifdef TESTx64
+foo:
+%else
+_foo:
+%endif
+    mov  	eax, 0
+    ret
diff --git a/Tests/VSNASM/main.c b/Tests/VSNASM/main.c
new file mode 100644
index 0000000..18ddb78
--- /dev/null
+++ b/Tests/VSNASM/main.c
@@ -0,0 +1,5 @@
+extern int foo(void);
+int main(void)
+{
+  return foo();
+}
diff --git a/Tests/VSResource/CMakeLists.txt b/Tests/VSResource/CMakeLists.txt
index 3b9cfc3..718e624 100644
--- a/Tests/VSResource/CMakeLists.txt
+++ b/Tests/VSResource/CMakeLists.txt
@@ -18,9 +18,8 @@ if(CMAKE_RC_COMPILER MATCHES windres)
   message(STATUS "CMAKE_RC_COMPILER MATCHES windres")
   add_definitions(/DCMAKE_RCDEFINE=test.txt)
   add_definitions(/DCMAKE_RCDEFINE_NO_QUOTED_STRINGS)
-  if(MSYS AND CMAKE_CURRENT_BINARY_DIR MATCHES " ")
-    # windres cannot handle spaces in include dir, and
-    # for the MSys shell we do not convert to shortpath.
+  if(CMAKE_CURRENT_BINARY_DIR MATCHES " ")
+    # windres cannot handle spaces in include dir
     set(CMAKE_RC_NO_INCLUDE 1)
   endif()
 elseif(MSVC60)
@@ -51,5 +50,9 @@ add_library(ResourceLib STATIC lib.cpp lib.rc)
 add_executable(VSResource main.cpp test.rc)
 target_link_libraries(VSResource ResourceLib)
 
+if(MSVC AND NOT MSVC_VERSION VERSION_LESS 1600)
+  set_property(SOURCE test.rc PROPERTY COMPILE_FLAGS /nologo)
+endif()
+
 set_property(TARGET VSResource
   PROPERTY VS_GLOBAL_CMakeTestVsGlobalVariable "test val")
diff --git a/Tests/Wrapping/fakefluid.cxx b/Tests/Wrapping/fakefluid.cxx
index 02c0c52..a118bbd 100644
--- a/Tests/Wrapping/fakefluid.cxx
+++ b/Tests/Wrapping/fakefluid.cxx
@@ -6,7 +6,9 @@ int main(int ac, char** av)
     if (strcmp(av[i], "-o") == 0 || strcmp(av[i], "-h") == 0) {
       fprintf(stdout, "fakefluid is creating file \"%s\"\n", av[i + 1]);
       FILE* file = fopen(av[i + 1], "w");
-      fprintf(file, "// hello\n");
+      fprintf(file, "// Solaris needs non-empty content so ensure\n"
+                    "// we have at least one symbol\n"
+                    "int Solaris_requires_a_symbol_here = 0;\n");
       fclose(file);
     }
   }
diff --git a/Tests/XCTest/CMakeLists.txt b/Tests/XCTest/CMakeLists.txt
index e866623..d40c40e 100644
--- a/Tests/XCTest/CMakeLists.txt
+++ b/Tests/XCTest/CMakeLists.txt
@@ -55,3 +55,19 @@ xctest_add_bundle(CocoaExampleTests CocoaExample
   CocoaExampleTests/CocoaExampleTests.m)
 
 xctest_add_test(XCTest.CocoaExample CocoaExampleTests)
+
+# Static lib
+
+add_library(StaticLibExample STATIC
+  StaticLibExample/StaticLibExample.h
+  StaticLibExample/StaticLibExample.c
+)
+
+target_include_directories(StaticLibExample PUBLIC .)
+
+# XCTest for Static lib
+
+xctest_add_bundle(StaticLibExampleTests StaticLibExample
+  StaticLibExampleTests/StaticLibExampleTests.m)
+
+xctest_add_test(XCTest.StaticLibExample StaticLibExampleTests)
diff --git a/Tests/XCTest/StaticLibExample/StaticLibExample.c b/Tests/XCTest/StaticLibExample/StaticLibExample.c
new file mode 100644
index 0000000..b198f80
--- /dev/null
+++ b/Tests/XCTest/StaticLibExample/StaticLibExample.c
@@ -0,0 +1,6 @@
+#include "StaticLibExample.h"
+
+int FourtyFour()
+{
+  return 44;
+}
diff --git a/Tests/XCTest/StaticLibExample/StaticLibExample.h b/Tests/XCTest/StaticLibExample/StaticLibExample.h
new file mode 100644
index 0000000..147a909
--- /dev/null
+++ b/Tests/XCTest/StaticLibExample/StaticLibExample.h
@@ -0,0 +1 @@
+int FourtyFour();
diff --git a/Tests/XCTest/StaticLibExampleTests/Info.plist b/Tests/XCTest/StaticLibExampleTests/Info.plist
new file mode 100644
index 0000000..6ad9a27
--- /dev/null
+++ b/Tests/XCTest/StaticLibExampleTests/Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>StaticLibExampleTests</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.cmake.StaticLibExampleTests</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>StaticLibExampleTests</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>
diff --git a/Tests/XCTest/StaticLibExampleTests/StaticLibExampleTests.m b/Tests/XCTest/StaticLibExampleTests/StaticLibExampleTests.m
new file mode 100644
index 0000000..5f8a769
--- /dev/null
+++ b/Tests/XCTest/StaticLibExampleTests/StaticLibExampleTests.m
@@ -0,0 +1,16 @@
+#import <XCTest/XCTest.h>
+
+#import "StaticLibExample/StaticLibExample.h"
+
+ at interface StaticLibExampleTests : XCTestCase
+
+ at end
+
+ at implementation StaticLibExampleTests
+
+- (void)testFourtyFour {
+    // This is an example of a functional test case.
+    XCTAssertEqual(44, FourtyFour());
+}
+
+ at end
diff --git a/Utilities/.clang-tidy b/Utilities/.clang-tidy
new file mode 100644
index 0000000..381a0f4
--- /dev/null
+++ b/Utilities/.clang-tidy
@@ -0,0 +1,6 @@
+---
+# We want to disable all checks for 3rd party code.  However, clang-tidy will
+# assume we did not configure it correctly.  Just add one check that will never
+# be found.
+Checks: '-*,llvm-twine-local'
+...
diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt
index 014204b..0564540 100644
--- a/Utilities/CMakeLists.txt
+++ b/Utilities/CMakeLists.txt
@@ -29,3 +29,6 @@ endif()
 if(WIX_CUSTOM_ACTION_ENABLED)
   add_subdirectory(Release/WiX)
 endif()
+
+# Make sure generated files use the same clang-tidy checks (none).
+configure_file(.clang-tidy .clang-tidy COPYONLY)
diff --git a/Utilities/GitSetup/config b/Utilities/GitSetup/config
index d69a679..2b4f037 100644
--- a/Utilities/GitSetup/config
+++ b/Utilities/GitSetup/config
@@ -1,9 +1,2 @@
 [hooks]
-	url = https://cmake.org/cmake.git
-[ssh]
-	host = cmake.org
-	key = id_git_cmake
-	request-url = https://www.kitware.com/Admin/SendPassword.cgi
-[stage]
-        url = git://cmake.org/stage/cmake.git
-        pushurl = git at cmake.org:stage/cmake.git
+	url = https://gitlab.kitware.com/utils/gitsetup.git
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
new file mode 100644
index 0000000..fe0f7df
--- /dev/null
+++ b/Utilities/IWYU/mapping.imp
@@ -0,0 +1,161 @@
+[
+  # C++ alternatives to C standard headers
+  { include: [ "<assert.h>", public, "<cassert>", public ] },
+  { include: [ "<complex.h>", public, "<ccomplex>", public ] },
+  { include: [ "<ctype.h>", public, "<cctype>", public ] },
+  { include: [ "<errno.h>", public, "<cerrno>", public ] },
+  { include: [ "<float.h>", public, "<cfloat>", public ] },
+  { include: [ "<iso646.h>", public, "<ciso646>", public ] },
+  { include: [ "<limits.h>", public, "<climits>", public ] },
+  { include: [ "<locale.h>", public, "<clocale>", public ] },
+  { include: [ "<math.h>", public, "<cmath>", public ] },
+  { include: [ "<setjmp.h>", public, "<csetjmp>", public ] },
+  { include: [ "<signal.h>", public, "<csignal>", public ] },
+  { include: [ "<stdarg.h>", public, "<cstdarg>", public ] },
+  { include: [ "<stddef.h>", public, "<cstddef>", public ] },
+  { include: [ "<stdio.h>", public, "<cstdio>", public ] },
+  { include: [ "<stdlib.h>", public, "<cstdlib>", public ] },
+  { include: [ "<string.h>", public, "<cstring>", public ] },
+  { include: [ "<time.h>", public, "<ctime>", public ] },
+  { include: [ "<wchar.h>", public, "<cwchar>", public ] },
+  { include: [ "<wctype.h>", public, "<cwctype>", public ] },
+
+  # HACK: check whether this can be removed with next iwyu release.
+  { include: [ "<bits/std_function.h>", private, "<functional>", public ] },
+  { include: [ "<bits/time.h>", private, "<time.h>", public ] },
+  { include: [ "<bits/types/clock_t.h>", private, "<time.h>", public ] },
+  { include: [ "<bits/types/struct_timespec.h>", private, "<time.h>", public ] },
+  { include: [ "<bits/types/struct_timeval.h>", private, "<time.h>", public ] },
+  { include: [ "<bits/types/struct_tm.h>", private, "<time.h>", public ] },
+  { include: [ "<bits/types/time_t.h>", private, "<time.h>", public ] },
+
+  # HACK: check whether this can be removed with next iwyu release.
+  { symbol: [ "__GLIBC__", private, "<stdlib.h>", public ] },
+  { symbol: [ "_Noreturn", private, "<stdlib.h>", public ] },
+
+  # HACK: iwyu wrongly thinks that including <iosfwd> is sufficient.
+  { symbol: [ "std::stringstream", private, "<sstream>", public ] },
+  { symbol: [ "std::istringstream", private, "<sstream>", public ] },
+  { symbol: [ "std::ostringstream", private, "<sstream>", public ] },
+
+  # HACK: iwyu suggests those two files each time vector[] is used.
+  # https://github.com/include-what-you-use/include-what-you-use/issues/166
+  { include: [ "<ext/alloc_traits.h>", private, "<vector>", public ] },
+  { include: [ "<memory>", public, "<vector>", public ] },
+
+  # TODO: enable this block and remove some <utility> includes?
+  #{ symbol: [ "std::pair", private, "<utility>", public ] },
+  #{ symbol: [ "std::pair", private, "<map>", public ] },
+  #{ symbol: [ "std::pair", private, "<set>", public ] },
+
+  # IWYU wrongly suggests to include "cm_auto_ptr.hxx" in some places.  This
+  # might be a misinterpretation of a template specialization in <utility>.
+  # As a workaround, map the symbol auto_ptr to "cmConfigure.h".
+  # This will still correctly require "cm_auto_ptr.hxx" for CM_AUTO_PTR.
+  { symbol: [ "cm::auto_ptr", private, "\"cmConfigure.h\"", public ] },
+
+  # __decay_and_strip is used internally in the C++11 standard library.
+  # IWYU does not classify it as internal and suggests to add <type_traits>.
+  # To ignore it, we simply map it to a file that is included anyway.
+  # TODO: Can this be simplified with an @-expression?
+  #{ symbol: [ "@std::__decay_and_strip<.*>::__type", private, "\"cmConfigure.h\"", public ] },
+  { symbol: [ "std::__decay_and_strip<cmCommand *&>::__type", private, "\"cmConfigure.h\"", public ] },
+  { symbol: [ "std::__decay_and_strip<cmGeneratorTarget *&>::__type", private, "\"cmConfigure.h\"", public ] },
+  { symbol: [ "std::__decay_and_strip<cmFindCommon::PathLabel &>::__type", private, "\"cmConfigure.h\"", public ] },
+  { symbol: [ "std::__decay_and_strip<std::basic_string<char> &>::__type", private, "\"cmConfigure.h\"", public ] },
+  { symbol: [ "std::__decay_and_strip<const std::basic_string<char> &>::__type", private, "\"cmConfigure.h\"", public ] },
+  { symbol: [ "std::__decay_and_strip<cmFindPackageCommand::PathLabel &>::__type", private, "\"cmConfigure.h\"", public ] },
+  { symbol: [ "std::__decay_and_strip<__gnu_cxx::__normal_iterator<const cmCTestTestHandler::cmCTestTestProperties *, std::vector<cmCTestTestHandler::cmCTestTestProperties, std::allocator<cmCTestTestHandler::cmCTestTestProperties> > > &>::__type", private, "\"cmConfigure.h\"", public ] },
+
+  # Wrappers for headers added in TR1 / C++11
+  # { include: [ "<array>", public, "\"cm_array.hxx\"", public ] },
+  # { include: [ "<functional>", public, "\"cm_functional.hxx\"", public ] },
+  # { include: [ "<memory>", public, "\"cm_memory.hxx\"", public ] },
+  { include: [ "<unordered_map>", public, "\"cm_unordered_map.hxx\"", public ] },
+  { include: [ "<unordered_set>", public, "\"cm_unordered_set.hxx\"", public ] },
+  # { include: [ "<tr1/array>", public, "\"cm_array.hxx\"", public ] },
+  # { include: [ "<tr1/functional>", public, "\"cm_functional.hxx\"", public ] },
+  # { include: [ "<tr1/memory>", public, "\"cm_memory.hxx\"", public ] },
+  { include: [ "<tr1/unordered_map>", public, "\"cm_unordered_map.hxx\"", public ] },
+  { include: [ "<tr1/unordered_set>", public, "\"cm_unordered_set.hxx\"", public ] },
+
+  # KWIML
+  { include: [ "<stdint.h>", public, "\"cm_kwiml.h\"", public ] },
+  { include: [ "<inttypes.h>", public, "\"cm_kwiml.h\"", public ] },
+
+  # Self-sufficient wrapper for <sys/stat.h>
+  { include: [ "<sys/stat.h>", public, "\"cm_sys_stat.h\"", public ] },
+  { symbol: [ "mode_t", private, "\"cm_sys_stat.h\"", public ] },
+
+  # TODO: remove once TR1 / C++11 is required.
+  { include: [ "\"cmsys/hash_fun.hxx\"", private, "\"cm_unordered_map.hxx\"", public ] },
+  { include: [ "\"cmsys/hash_fun.hxx\"", private, "\"cm_unordered_set.hxx\"", public ] },
+  { include: [ "\"cmsys/hash_map.hxx\"", private, "\"cm_unordered_map.hxx\"", public ] },
+  { include: [ "\"cmsys/hash_set.hxx\"", private, "\"cm_unordered_set.hxx\"", public ] },
+  { include: [ "\"cmsys/hashtable.hxx\"", private, "\"cm_unordered_map.hxx\"", public ] },
+  { include: [ "\"cmsys/hashtable.hxx\"", private, "\"cm_unordered_set.hxx\"", public ] },
+
+  # Wrappers for 3rd-party libraries used from the system.
+  { include: [ "<archive.h>", private, "\"cm_libarchive.h\"", public ] },
+  { include: [ "<archive_entry.h>", private, "\"cm_libarchive.h\"", public ] },
+  { include: [ "@<curl/.+\\.h>", private, "\"cm_curl.h\"", public ] },
+  { include: [ "<expat.h>", private, "\"cm_expat.h\"", public ] },
+  { include: [ "<expat_external.h>", private, "\"cm_expat.h\"", public ] },
+  { include: [ "<json/reader.h>", private, "\"cm_jsoncpp_reader.h\"", public ] },
+  { include: [ "<json/value.h>", private, "\"cm_jsoncpp_value.h\"", public ] },
+  { include: [ "<json/writer.h>", private, "\"cm_jsoncpp_writer.h\"", public ] },
+  { include: [ "<rhash.h>", private, "\"cm_rhash.h\"", public ] },
+  { include: [ "<uv.h>", private, "\"cm_uv.h\"", public ] },
+  { include: [ "@<uv-.+\\.h>", private, "\"cm_uv.h\"", public ] },
+  { include: [ "<kwiml/abi.h>", private, "\"cm_kwiml.h\"", public ] },
+  { include: [ "<kwiml/int.h>", private, "\"cm_kwiml.h\"", public ] },
+  { include: [ "<xmlrpc.h>", private, "\"cm_xmlrpc.h\"", public ] },
+  { include: [ "<xmlrpc_client.h>", private, "\"cm_xmlrpc.h\"", public ] },
+  { include: [ "@<xmlrpc-c/.+\\.h>", private, "\"cm_xmlrpc.h\"", public ] },
+  { include: [ "<zconf.h>", private, "\"cm_zlib.h\"", public ] },
+  { include: [ "<zlib.h>", private, "\"cm_zlib.h\"", public ] },
+
+  # Wrappers for bundled 3rd-party libraries.
+  { include: [ "\"cmlibarchive/libarchive/archive.h\"", private, "\"cm_libarchive.h\"", public ] },
+  { include: [ "\"cmlibarchive/libarchive/archive_entry.h\"", private, "\"cm_libarchive.h\"", public ] },
+  { include: [ "@\"cmcurl/include/curl/.+\\.h\"", private, "\"cm_curl.h\"", public ] },
+  { include: [ "\"cmexpat/lib/expat.h\"", private, "\"cm_expat.h\"", public ] },
+  { include: [ "\"cmexpat/lib/expat_external.h\"", private, "\"cm_expat.h\"", public ] },
+  { include: [ "\"cmjsoncpp/include/json/reader.h\"", private, "\"cm_jsoncpp_reader.h\"", public ] },
+  { include: [ "\"cmjsoncpp/include/json/value.h\"", private, "\"cm_jsoncpp_value.h\"", public ] },
+  { include: [ "\"cmjsoncpp/include/json/writer.h\"", private, "\"cm_jsoncpp_writer.h\"", public ] },
+  { include: [ "\"cmlibrhash/librhash/rhash.h\"", private, "\"cm_rhash.h\"", public ] },
+  { include: [ "\"cmlibuv/include/uv.h\"", private, "\"cm_uv.h\"", public ] },
+  { include: [ "@\"cmlibuv/include/uv-.+\\.h\"", private, "\"cm_uv.h\"", public ] },
+  { include: [ "\"KWIML/include/kwiml/abi.h\"", private, "\"cm_kwiml.h\"", public ] },
+  { include: [ "\"KWIML/include/kwiml/int.h\"", private, "\"cm_kwiml.h\"", public ] },
+  { include: [ "\"cmzlib/cm_zlib_mangle.h\"", private, "\"cm_zlib.h\"", public ] },
+  { include: [ "\"cmzlib/zconf.h\"", private, "\"cm_zlib.h\"", public ] },
+  { include: [ "\"cmzlib/zlib.h\"", private, "\"cm_zlib.h\"", public ] },
+
+  # System symbols used by libuv
+  { symbol: [ "SIGHUP", private, "\"cm_uv.h\"", public ] },
+  { symbol: [ "SIGINT", private, "\"cm_uv.h\"", public ] },
+  { symbol: [ "ssize_t", private, "\"cm_uv.h\"", public ] },
+
+  { symbol: [ "std::ifstream", private, "\"cmsys/FStream.hxx\"", public ] },
+  { symbol: [ "std::ofstream", private, "\"cmsys/FStream.hxx\"", public ] },
+  { symbol: [ "cmsys::ifstream", private, "\"cmsys/FStream.hxx\"", public ] },
+  { symbol: [ "cmsys::ofstream", private, "\"cmsys/FStream.hxx\"", public ] },
+
+  { include: [ "<istream>", public, "\"cmsys/FStream.hxx\"", public ] },
+  { include: [ "<ostream>", public, "\"cmsys/FStream.hxx\"", public ] },
+  { include: [ "<fstream>", public, "\"cmsys/FStream.hxx\"", public ] },
+
+  # major and minor are used as macro arguments. Those are false matches.
+  { symbol: [ "major", private, "\"cm_kwiml.h\"", public ] },
+  { symbol: [ "minor", private, "\"cm_kwiml.h\"", public ] },
+  { symbol: [ "major", private, "\"cmVersion.h\"", public ] },
+  { symbol: [ "minor", private, "\"cmVersion.h\"", public ] },
+
+  { include: [ "<curses.h>", private, "\"cmCursesStandardIncludes.h\"", public ] },
+  { include: [ "\"form.h\"", private, "\"cmCursesStandardIncludes.h\"", public ] },
+  { include: [ "<form.h>", private, "\"cmCursesStandardIncludes.h\"", public ] },
+]
+
+# vim: set ft=toml:
diff --git a/Utilities/KWIML/test/CMakeLists.txt b/Utilities/KWIML/test/CMakeLists.txt
index 1bf93bb..40fe62f 100644
--- a/Utilities/KWIML/test/CMakeLists.txt
+++ b/Utilities/KWIML/test/CMakeLists.txt
@@ -38,6 +38,8 @@ endif()
 
 add_executable(kwiml_test ${test_srcs})
 set_property(TARGET kwiml_test PROPERTY COMPILE_DEFINITIONS ${test_defs})
+set_property(TARGET kwiml_test PROPERTY C_INCLUDE_WHAT_YOU_USE "")
+set_property(TARGET kwiml_test PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
 set_property(TARGET kwiml_test PROPERTY
   RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
 add_test(NAME ${KWIML_TEST_PREFIX}.test COMMAND kwiml_test)
diff --git a/Utilities/Release/consolidate-relnotes.bash b/Utilities/Release/consolidate-relnotes.bash
new file mode 100755
index 0000000..91307ac
--- /dev/null
+++ b/Utilities/Release/consolidate-relnotes.bash
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+
+set -e
+
+usage='usage: consolidate-relnotes.bash <new-release-version> <prev-release-version>'
+
+die() {
+    echo "$@" 1>&2; exit 1
+}
+
+test "$#" = 2 || die "$usage"
+
+files="$(ls Help/release/dev/* | grep -v Help/release/dev/0-sample-topic.rst)"
+title="CMake $1 Release Notes"
+underline="$(echo "$title" | sed 's/./*/g')"
+echo "$title
+$underline
+
+.. only:: html
+
+  .. contents::
+
+Changes made since CMake $2 include the following." > Help/release/"$1".rst
+tail -q -n +3 $files >> Help/release/"$1".rst
+sed -i "/^   $2 / i\\
+   $1 <$1>" Help/release/index.rst
+rm $files
diff --git a/Utilities/Release/hythloth_release.cmake b/Utilities/Release/hythloth_release.cmake
deleted file mode 100644
index d2f4ba5..0000000
--- a/Utilities/Release/hythloth_release.cmake
+++ /dev/null
@@ -1,10 +0,0 @@
-set(PROCESSORS 2)
-set(HOST hythloth)
-set(MAKE_PROGRAM "make")
-set(MAKE "${MAKE_PROGRAM} -j2")
-set(INITIAL_CACHE "
-CMAKE_BUILD_TYPE:STRING=Release
-CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
-")
-get_filename_component(path "${CMAKE_CURRENT_LIST_FILE}" PATH)
-include(${path}/release_cmake.cmake)
diff --git a/Utilities/Release/linux64_release.cmake b/Utilities/Release/linux64_release.cmake
index feba2a5..3d8ddba 100644
--- a/Utilities/Release/linux64_release.cmake
+++ b/Utilities/Release/linux64_release.cmake
@@ -35,6 +35,7 @@ OPENSSL_SSL_LIBRARY:FILEPATH=/home/kitware/openssl-1.0.2j/lib/libssl.a
 PYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3
 CPACK_SYSTEM_NAME:STRING=Linux-x86_64
 BUILD_QtDialog:BOOL:=TRUE
+CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
 CMake_ENABLE_SERVER_MODE:BOOL=TRUE
 CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
 CMake_INSTALL_DEPENDENCIES:BOOL=ON
diff --git a/Utilities/Release/osx_release.cmake b/Utilities/Release/osx_release.cmake
index 88ea39b..36498a7 100644
--- a/Utilities/Release/osx_release.cmake
+++ b/Utilities/Release/osx_release.cmake
@@ -27,7 +27,7 @@ CMAKE_SKIP_RPATH:BOOL=TRUE
 CMake_TEST_NO_FindPackageModeMakefileTest:BOOL=TRUE
 ")
 set(ENV [[
-export CMAKE_PREFIX_PATH='/Users/kitware/SDKs/qt-5.6.0-clang-x64'
+export CMAKE_PREFIX_PATH='/Users/kitware/SDKs/qt-5.6.2-clang-x64'
 ]])
 get_filename_component(path "${CMAKE_CURRENT_LIST_FILE}" PATH)
 include(${path}/release_cmake.cmake)
diff --git a/Utilities/Release/release_cmake.cmake b/Utilities/Release/release_cmake.cmake
index 0db89b5..b2c21b7 100644
--- a/Utilities/Release/release_cmake.cmake
+++ b/Utilities/Release/release_cmake.cmake
@@ -32,9 +32,16 @@ if(NOT DEFINED GIT_COMMAND)
   set(GIT_COMMAND git)
 endif()
 
-if(${CMAKE_CREATE_VERSION} MATCHES "^(release|maint|next|nightly)$")
+if(CMAKE_CREATE_VERSION MATCHES "^(master|release)$")
+  set(GIT_FETCH "")
   set(GIT_BRANCH origin/${CMAKE_CREATE_VERSION})
+elseif(CMAKE_CREATE_VERSION STREQUAL "nightly")
+  set(nightly stage/master/nightly/latest)
+  set(GIT_FETCH "${GIT_COMMAND} fetch origin refs/${nightly}:refs/remotes/origin/${nightly}")
+  set(GIT_BRANCH origin/${nightly})
 else()
+  set(stage stage/master/head)
+  set(GIT_FETCH "${GIT_COMMAND} fetch origin refs/${stage}:refs/remotes/origin/${stage}")
   set(GIT_BRANCH ${CMAKE_CREATE_VERSION})
 endif()
 
diff --git a/Utilities/Release/release_cmake.sh.in b/Utilities/Release/release_cmake.sh.in
index 1465129..f363b3d 100755
--- a/Utilities/Release/release_cmake.sh.in
+++ b/Utilities/Release/release_cmake.sh.in
@@ -94,13 +94,15 @@ cd @CMAKE_RELEASE_DIRECTORY@
 if [ ! -z "@GIT_COMMAND@" ]; then
    # clone the repo without creating any source files in the directory
    # matching the branch being built (i.e. master CMake-2-8, etc)
-   @GIT_COMMAND@ clone -n git://cmake.org/cmake.git @CMAKE_CREATE_VERSION@
-   check_exit_value $? "Checkout git cmake source" || exit 1
+   @GIT_COMMAND@ clone -n https://gitlab.kitware.com/cmake/cmake.git @CMAKE_CREATE_VERSION@
+   check_exit_value $? "git clone cmake source" || exit 1
    # go into the git directory
    cd @CMAKE_CREATE_VERSION@
    # run any extra commands if they exist
    @GIT_EXTRA@
    check_exit_value $? "git extra cmake source" || exit 1
+   @GIT_FETCH@
+   check_exit_value $? "git extra fetch" || exit 1
    # now checkout a copy on the local branch working
    @GIT_COMMAND@ checkout -b working @GIT_BRANCH@
    check_exit_value $? "git checkout" || exit 1
diff --git a/Utilities/Release/upload_release.cmake b/Utilities/Release/upload_release.cmake
index c49cb4f..5b2cc57 100644
--- a/Utilities/Release/upload_release.cmake
+++ b/Utilities/Release/upload_release.cmake
@@ -1,6 +1,6 @@
 set(CTEST_RUN_CURRENT_SCRIPT 0)
 if(NOT VERSION)
- set(VERSION 3.8)
+ set(VERSION 3.9)
 endif()
 if(NOT DEFINED PROJECT_PREFIX)
   set(PROJECT_PREFIX cmake-${VERSION})
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 22d1d8a..465841a 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 at cool.haxx.se>"
 readonly subtree="Utilities/cmcurl"
 readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_51_0"
+readonly tag="curl-7_54_1"
 readonly shortlog=false
 readonly paths="
   CMake/*
@@ -32,6 +32,7 @@ extract_source () {
     git_archive
     pushd "${extractdir}/${name}-reduced"
     rm lib/config-*.h
+    echo "* -whitespace" > .gitattributes
     popd
 }
 
diff --git a/Utilities/Scripts/update-expat.bash b/Utilities/Scripts/update-expat.bash
index 8a2a5fe..4cc8646 100755
--- a/Utilities/Scripts/update-expat.bash
+++ b/Utilities/Scripts/update-expat.bash
@@ -7,8 +7,8 @@ shopt -s dotglob
 readonly name="expat"
 readonly ownership="Expat Upstream <kwrobot at kitware.com>"
 readonly subtree="Utilities/cmexpat"
-readonly repo="http://git.code.sf.net/p/expat/code_git"
-readonly tag="master"
+readonly repo="https://github.com/libexpat/libexpat.git"
+readonly tag="R_2_2_1"
 readonly shortlog=false
 readonly paths="
   expat/lib/asciitab.h
@@ -22,6 +22,7 @@ readonly paths="
   expat/lib/utf8tab.h
   expat/lib/nametab.h
   expat/lib/ascii.h
+  expat/lib/siphash.h
   expat/lib/xmltok_impl.h
   expat/lib/xmltok_ns.c
   expat/lib/winconfig.h
diff --git a/Utilities/Scripts/update-kwsys.bash b/Utilities/Scripts/update-kwsys.bash
index 83da8a4..dfbd366 100755
--- a/Utilities/Scripts/update-kwsys.bash
+++ b/Utilities/Scripts/update-kwsys.bash
@@ -15,6 +15,8 @@ readonly paths="
 
 extract_source () {
     git_archive
+    sed -i -e '/import off/,/import on/d' "$extractdir/$name-reduced/.gitattributes"
+    sed -i -e 's/project=KWSys/project=PublicDashboard/' "$extractdir/$name-reduced/CTestConfig.cmake"
 }
 
 export HOOKS_ALLOW_KWSYS=1
diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash
index 3b42269..41c6a66 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 at googlegroups.com>"
 readonly subtree="Utilities/cmlibarchive"
 readonly repo="https://github.com/libarchive/libarchive.git"
-readonly tag="master"
+readonly tag="v3.3.1"
 readonly shortlog=false
 readonly paths="
   CMakeLists.txt
diff --git a/Utilities/Scripts/update-third-party.bash b/Utilities/Scripts/update-third-party.bash
index 3b8358e..670946e 100644
--- a/Utilities/Scripts/update-third-party.bash
+++ b/Utilities/Scripts/update-third-party.bash
@@ -52,6 +52,14 @@ git_archive () {
         tar -C "$extractdir" -x
 }
 
+disable_custom_gitattributes() {
+    pushd "${extractdir}/${name}-reduced"
+    # Git does not allow custom attributes in a subdirectory where we
+    # are about to merge the `.gitattributes` file, so disable them.
+    sed -i '/^\[attr\]/ {s/^/#/}' .gitattributes
+    popd
+}
+
 die () {
     echo >&2 "$@"
     exit 1
diff --git a/Utilities/SetupForDevelopment.sh b/Utilities/SetupForDevelopment.sh
index 39152bc..ff64a84 100755
--- a/Utilities/SetupForDevelopment.sh
+++ b/Utilities/SetupForDevelopment.sh
@@ -3,9 +3,6 @@
 cd "${BASH_SOURCE%/*}/.." &&
 Utilities/GitSetup/setup-user && echo &&
 Utilities/GitSetup/setup-hooks && echo &&
-Utilities/GitSetup/setup-stage && echo &&
-(Utilities/GitSetup/setup-ssh ||
- echo 'Failed to setup SSH.  Run this again to retry.') && echo &&
 Utilities/GitSetup/tips
 
 # Rebase master by default
@@ -13,5 +10,5 @@ git config rebase.stat true
 git config branch.master.rebase true
 
 # Record the version of this setup so Git/pre-commit can check it.
-SetupForDevelopment_VERSION=1
+SetupForDevelopment_VERSION=2
 git config hooks.SetupForDevelopment ${SetupForDevelopment_VERSION}
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index edb9469..a29380c 100644
--- a/Utilities/Sphinx/CMakeLists.txt
+++ b/Utilities/Sphinx/CMakeLists.txt
@@ -128,18 +128,20 @@ endforeach()
 
 add_custom_target(documentation ALL DEPENDS ${doc_format_outputs})
 
-foreach(t
-    cmake
-    ccmake
-    cmake-gui
-    cpack
-    ctest
-    )
-  if(TARGET ${t})
-    # Build documentation after main executables.
-    add_dependencies(documentation ${t})
-  endif()
-endforeach()
+if(CMake_SPHINX_DEPEND_ON_EXECUTABLES)
+  foreach(t
+      cmake
+      ccmake
+      cmake-gui
+      cpack
+      ctest
+      )
+    if(TARGET ${t})
+      # Build documentation after main executables.
+      add_dependencies(documentation ${t})
+    endif()
+  endforeach()
+endif()
 
 if(SPHINX_MAN)
   file(GLOB man_rst RELATIVE ${CMake_SOURCE_DIR}/Help/manual
diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in
index 9581458..7878ad2 100644
--- a/Utilities/Sphinx/conf.py.in
+++ b/Utilities/Sphinx/conf.py.in
@@ -18,7 +18,9 @@ release = '@conf_release@' # full version string
 
 primary_domain = 'cmake'
 
-exclude_patterns = []
+exclude_patterns = [
+    'dev', # ignore developer-only documentation
+    ]
 
 extensions = ['cmake']
 templates_path = ['@conf_path@/templates']
@@ -52,6 +54,26 @@ html_show_sourcelink = True
 html_static_path = ['@conf_path@/static']
 html_style = 'cmake.css'
 html_theme = 'default'
+html_theme_options = {
+    'footerbgcolor':    '#00182d',
+    'footertextcolor':  '#ffffff',
+    'sidebarbgcolor':   '#e4ece8',
+    'sidebarbtncolor':  '#00a94f',
+    'sidebartextcolor': '#333333',
+    'sidebarlinkcolor': '#00a94f',
+    'relbarbgcolor':    '#00529b',
+    'relbartextcolor':  '#ffffff',
+    'relbarlinkcolor':  '#ffffff',
+    'bgcolor':          '#ffffff',
+    'textcolor':        '#444444',
+    'headbgcolor':      '#f2f2f2',
+    'headtextcolor':    '#003564',
+    'headlinkcolor':    '#3d8ff2',
+    'linkcolor':        '#2b63a8',
+    'visitedlinkcolor': '#2b63a8',
+    'codebgcolor':      '#eeeeee',
+    'codetextcolor':    '#333333',
+}
 html_title = 'CMake %s Documentation' % release
 html_short_title = '%s Documentation' % release
 html_favicon = '@conf_path@/static/cmake-favicon.ico'
diff --git a/Utilities/Sphinx/templates/layout.html b/Utilities/Sphinx/templates/layout.html
index 177e044..be2660c 100644
--- a/Utilities/Sphinx/templates/layout.html
+++ b/Utilities/Sphinx/templates/layout.html
@@ -8,10 +8,22 @@
     <a href="https://cmake.org/">CMake</a>{{ reldelim1 }}
   </li>
   <li>
+    {%- if versionswitch is defined %}
+    <span class="version_switch">{{ release }}</span>
+    <a href="{{ pathto(master_doc) }}">{% trans %}Documentation{% endtrans %}</a>{{ reldelim1 }}
+    {%- else %}
     <a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}
+    {%- endif %}
   </li>
 {% endblock %}
 
+{% block extrahead %}
+  {% if versionswitch is defined %}
+  <script type="text/javascript" src="{{ pathto('../version_switch.js', 1) }}"></script>
+  {% endif %}
+{{ super() }}
+{% endblock %}
+
 {# Put some context in the html title element. Workaround for #}
 {# https://bitbucket.org/birkenfeld/sphinx/issue/1492/qthelp-generate-html-title-element-should #}
 {% block htmltitle %}
diff --git a/Utilities/cmcurl/CMake/CurlTests.c b/Utilities/cmcurl/CMake/CurlTests.c
index ceff391..bc36c8e 100644
--- a/Utilities/cmcurl/CMake/CurlTests.c
+++ b/Utilities/cmcurl/CMake/CurlTests.c
@@ -533,3 +533,19 @@ main () {
     return 0;
 }
 #endif
+#ifdef HAVE_FSETXATTR_6
+#include <sys/xattr.h> /* header from libc, not from libattr */
+int
+main() {
+  fsetxattr(0, 0, 0, 0, 0, 0);
+  return 0;
+}
+#endif
+#ifdef HAVE_FSETXATTR_5
+#include <sys/xattr.h> /* header from libc, not from libattr */
+int
+main() {
+  fsetxattr(0, 0, 0, 0, 0);
+  return 0;
+}
+#endif
diff --git a/Utilities/cmcurl/CMake/FindGSS.cmake b/Utilities/cmcurl/CMake/FindGSS.cmake
index dfaeaf3..60dcb73 100644
--- a/Utilities/cmcurl/CMake/FindGSS.cmake
+++ b/Utilities/cmcurl/CMake/FindGSS.cmake
@@ -12,7 +12,7 @@
 #  GSS_LINKER_FLAGS - Additional linker flags
 #  GSS_COMPILER_FLAGS - Additional compiler flags
 #  GSS_VERSION - This is set to version advertised by pkg-config or read from manifest.
-#                In case the library is found but no version info availabe it'll be set to "unknown"
+#                In case the library is found but no version info available it'll be set to "unknown"
 
 set(_MIT_MODNAME mit-krb5-gssapi)
 set(_HEIMDAL_MODNAME heimdal-gssapi)
diff --git a/Utilities/cmcurl/CMake/FindMbedTLS.cmake b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
new file mode 100644
index 0000000..a916395
--- /dev/null
+++ b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
@@ -0,0 +1,13 @@
+find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h)
+
+find_library(MBEDTLS_LIBRARY mbedtls)
+find_library(MBEDX509_LIBRARY mbedx509)
+find_library(MBEDCRYPTO_LIBRARY mbedcrypto)
+
+set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}")
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(MBEDTLS DEFAULT_MSG
+    MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
+
+mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
diff --git a/Utilities/cmcurl/CMake/OtherTests.cmake b/Utilities/cmcurl/CMake/OtherTests.cmake
index d599498..3b203c5 100644
--- a/Utilities/cmcurl/CMake/OtherTests.cmake
+++ b/Utilities/cmcurl/CMake/OtherTests.cmake
@@ -179,17 +179,20 @@ int main(void) {
 
 
 include(CheckCSourceRuns)
-set(CMAKE_REQUIRED_FLAGS)
-if(HAVE_SYS_POLL_H)
-  set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
-endif(HAVE_SYS_POLL_H)
-check_c_source_runs("
-  #ifdef HAVE_SYS_POLL_H
-  #  include <sys/poll.h>
-  #endif
-  int main(void) {
-    return poll((void *)0, 0, 10 /*ms*/);
-  }" HAVE_POLL_FINE)
+# See HAVE_POLL in CMakeLists.txt for why poll is disabled on macOS
+if(NOT APPLE)
+  set(CMAKE_REQUIRED_FLAGS)
+  if(HAVE_SYS_POLL_H)
+    set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
+  endif(HAVE_SYS_POLL_H)
+  check_c_source_runs("
+    #ifdef HAVE_SYS_POLL_H
+    #  include <sys/poll.h>
+    #endif
+    int main(void) {
+      return poll((void *)0, 0, 10 /*ms*/);
+    }" HAVE_POLL_FINE)
+endif()
 
 set(HAVE_SIG_ATOMIC_T 1)
 set(CMAKE_REQUIRED_FLAGS)
diff --git a/Utilities/cmcurl/CMake/Utilities.cmake b/Utilities/cmcurl/CMake/Utilities.cmake
index 37cdfe3..8b6276d 100644
--- a/Utilities/cmcurl/CMake/Utilities.cmake
+++ b/Utilities/cmcurl/CMake/Utilities.cmake
@@ -29,3 +29,16 @@ function(IN_STR_LIST LIST_NAME ITEM_SEARCHED RETVAL)
     set(${RETVAL} TRUE PARENT_SCOPE)
   endif()
 endfunction()
+
+# Returns a list of arguments that evaluate to true
+function(collect_true output_var output_count_var)
+  set(${output_var})
+  foreach(option_var IN LISTS ARGN)
+    if(${option_var})
+      list(APPEND ${output_var} ${option_var})
+    endif()
+  endforeach()
+  set(${output_var} ${${output_var}} PARENT_SCOPE)
+  list(LENGTH ${output_var} ${output_count_var})
+  set(${output_count_var} ${${output_count_var}} PARENT_SCOPE)
+endfunction()
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 262554d..d85f366 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -34,6 +34,29 @@ set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS look
 set(ENABLE_UNIX_SOCKETS OFF CACHE INTERNAL "No curl Unix domain sockets support")
 set(HTTP_ONLY OFF CACHE INTERNAL "Curl is not http-only")
 set(USE_WIN32_LDAP OFF CACHE INTERNAL "No curl Windows LDAP")
+if(CMAKE_USE_OPENSSL)
+elseif(WIN32)
+  set(CMAKE_USE_WINSSL ON CACHE INTERNAL "enable Windows native SSL/TLS")
+  set(CURL_WINDOWS_SSPI ON CACHE INTERNAL "Use windows libraries to allow NTLM authentication without openssl")
+elseif(APPLE)
+  # Use OS X SSL/TLS native implementation if available on target version.
+  if(CMAKE_OSX_DEPLOYMENT_TARGET)
+    set(OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET})
+  else()
+    execute_process(
+      COMMAND sw_vers -productVersion
+      OUTPUT_VARIABLE OSX_VERSION
+      OUTPUT_STRIP_TRAILING_WHITESPACE
+      )
+  endif()
+  if(NOT OSX_VERSION VERSION_LESS 10.6 AND
+      CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
+    set(CMAKE_USE_DARWINSSL ON CACHE INTERNAL "enable Apple OS native SSL/TLS")
+  else()
+    set(CMAKE_USE_DARWINSSL OFF CACHE INTERNAL "enable Apple OS native SSL/TLS")
+  endif()
+endif()
+set(CMAKE_USE_MBEDTLS OFF CACHE INTERNAL "Enable mbedTLS for SSL/TLS")
 
 # Windows Vista and above have inet_pton, but this will link on
 # older versions and then the executable will fail to launch at
@@ -291,6 +314,11 @@ if(ENABLE_MANUAL)
   endif()
 endif()
 
+if(0) # This code not needed for building within CMake.
+# Required for building manual, docs, tests
+find_package(Perl REQUIRED)
+endif()
+
 # We need ansi c-flags, especially on HP
 set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}")
 set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS})
@@ -316,7 +344,7 @@ include (CheckCSourceCompiles)
 
 # On windows preload settings
 if(WIN32)
-  set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_")
+  set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=")
   include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
 endif(WIN32)
 
@@ -367,62 +395,101 @@ if(WIN32)
   check_library_exists_concat("winmm"  getch        HAVE_LIBWINMM)
 endif()
 
-set(USE_OPENSSL OFF)
-set(HAVE_LIBCRYPTO OFF)
-set(HAVE_LIBSSL OFF)
+# check SSL libraries
+# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL
 
-if(CMAKE_USE_OPENSSL)
-  find_package(OpenSSL)
-  if(OPENSSL_FOUND)
-    list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
-    set(USE_OPENSSL ON)
-    set(HAVE_LIBCRYPTO ON)
-    set(HAVE_LIBSSL ON)
-    include_directories(${OPENSSL_INCLUDE_DIR})
-    set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
-    check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
-    check_include_file("openssl/engine.h" HAVE_OPENSSL_ENGINE_H)
-    check_include_file("openssl/err.h"    HAVE_OPENSSL_ERR_H)
-    check_include_file("openssl/pem.h"    HAVE_OPENSSL_PEM_H)
-    check_include_file("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H)
-    check_include_file("openssl/rsa.h"    HAVE_OPENSSL_RSA_H)
-    check_include_file("openssl/ssl.h"    HAVE_OPENSSL_SSL_H)
-    check_include_file("openssl/x509.h"   HAVE_OPENSSL_X509_H)
-    check_include_file("openssl/rand.h"   HAVE_OPENSSL_RAND_H)
-
-    # Optionally build with a specific CA cert bundle.
-    if(CURL_CA_BUNDLE)
-      add_definitions(-DCURL_CA_BUNDLE="${CURL_CA_BUNDLE}")
-    endif()
-    # Optionally build with a specific CA cert dir.
-    if(CURL_CA_PATH)
-      add_definitions(-DCURL_CA_PATH="${CURL_CA_PATH}")
-    endif()
+if(APPLE)
+  option(CMAKE_USE_DARWINSSL "enable Apple OS native SSL/TLS" OFF)
+endif()
+if(WIN32)
+  option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF)
+  cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON
+    CMAKE_USE_WINSSL OFF)
+endif()
+option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
+
+set(openssl_default ON)
+if(WIN32 OR CMAKE_USE_DARWINSSL OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
+  set(openssl_default OFF)
+endif()
+
+collect_true(enabled_ssl_options enabled_ssl_options_count
+  CMAKE_USE_WINSSL
+  CMAKE_USE_DARWINSSL
+  CMAKE_USE_OPENSSL
+  CMAKE_USE_MBEDTLS
+)
+if(enabled_ssl_options_count GREATER 1)
+  message(FATAL_ERROR "Multiple SSL options specified: ${enabled_ssl_options}. Please pick at most one and disable the rest.")
+endif()
+
+if(CMAKE_USE_WINSSL)
+  set(SSL_ENABLED ON)
+  set(USE_SCHANNEL ON) # Windows native SSL/TLS support
+  set(USE_WINDOWS_SSPI ON) # CMAKE_USE_WINSSL implies CURL_WINDOWS_SSPI
+  list(APPEND CURL_LIBS "crypt32")
+endif()
+if(CURL_WINDOWS_SSPI)
+  set(USE_WINDOWS_SSPI ON)
+  set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32")
+endif()
+
+if(CMAKE_USE_DARWINSSL)
+  find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
+  if(NOT COREFOUNDATION_FRAMEWORK)
+      message(FATAL_ERROR "CoreFoundation framework not found")
   endif()
-elseif(WIN32)
-  # Use Windows SSL/TLS native implementation.
-  set(CURL_WINDOWS_SSPI ON)
-elseif(APPLE)
-  # Use OS X SSL/TLS native implementation if available on target version.
-  if(CMAKE_OSX_DEPLOYMENT_TARGET)
-    set(OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET})
-  else()
-    execute_process(
-      COMMAND sw_vers -productVersion
-      OUTPUT_VARIABLE OSX_VERSION
-      OUTPUT_STRIP_TRAILING_WHITESPACE
-      )
+
+  find_library(SECURITY_FRAMEWORK "Security")
+  if(NOT SECURITY_FRAMEWORK)
+     message(FATAL_ERROR "Security framework not found")
   endif()
-  if(NOT OSX_VERSION VERSION_LESS 10.6 AND
-     CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
-    add_definitions(-DUSE_DARWINSSL)
-    list(APPEND CURL_LIBS
-      "-framework CoreFoundation"
-      "-framework Security"
-      )
+
+  set(SSL_ENABLED ON)
+  set(USE_DARWINSSL ON)
+  list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
+endif()
+
+if(CMAKE_USE_OPENSSL)
+  find_package(OpenSSL REQUIRED)
+  set(SSL_ENABLED ON)
+  set(USE_OPENSSL ON)
+  set(HAVE_LIBCRYPTO ON)
+  set(HAVE_LIBSSL ON)
+  list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
+  include_directories(${OPENSSL_INCLUDE_DIR})
+  set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
+  check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
+  check_include_file("openssl/engine.h" HAVE_OPENSSL_ENGINE_H)
+  check_include_file("openssl/err.h"    HAVE_OPENSSL_ERR_H)
+  check_include_file("openssl/pem.h"    HAVE_OPENSSL_PEM_H)
+  check_include_file("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H)
+  check_include_file("openssl/rsa.h"    HAVE_OPENSSL_RSA_H)
+  check_include_file("openssl/ssl.h"    HAVE_OPENSSL_SSL_H)
+  check_include_file("openssl/x509.h"   HAVE_OPENSSL_X509_H)
+  check_include_file("openssl/rand.h"   HAVE_OPENSSL_RAND_H)
+  check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS)
+  check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
+  check_symbol_exists(RAND_egd    "${CURL_INCLUDES}" HAVE_RAND_EGD)
+
+  # Optionally build with a specific CA cert bundle.
+  if(CURL_CA_BUNDLE)
+    add_definitions(-DCURL_CA_BUNDLE="${CURL_CA_BUNDLE}")
+  endif()
+  # Optionally build with a specific CA cert dir.
+  if(CURL_CA_PATH)
+    add_definitions(-DCURL_CA_PATH="${CURL_CA_PATH}")
   endif()
 endif()
 
+if(CMAKE_USE_MBEDTLS)
+  find_package(MbedTLS REQUIRED)
+  set(SSL_ENABLED ON)
+  set(USE_MBEDTLS ON)
+  list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES})
+  include_directories(${MBEDTLS_INCLUDE_DIRS})
+endif()
+
 option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
 if(USE_NGHTTP2)
   find_package(NGHTTP2 REQUIRED)
@@ -675,24 +742,88 @@ else()
 endif()
 
 
+if(0) # This code not needed for building within CMake.
+#
+# CA handling
+#
+set(CURL_CA_BUNDLE "auto" CACHE STRING
+    "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
+set(CURL_CA_FALLBACK OFF CACHE BOOL
+    "Set ON to use built-in CA store of TLS backend. Defaults to OFF")
+set(CURL_CA_PATH "auto" CACHE STRING
+    "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
+
+if("${CURL_CA_BUNDLE}" STREQUAL "")
+    message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.")
+elseif("${CURL_CA_BUNDLE}" STREQUAL "none")
+    unset(CURL_CA_BUNDLE CACHE)
+elseif("${CURL_CA_BUNDLE}" STREQUAL "auto")
+    unset(CURL_CA_BUNDLE CACHE)
+    set(CURL_CA_BUNDLE_AUTODETECT TRUE)
+else()
+    set(CURL_CA_BUNDLE_SET TRUE)
+endif()
+
+if("${CURL_CA_PATH}" STREQUAL "")
+    message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.")
+elseif("${CURL_CA_PATH}" STREQUAL "none")
+    unset(CURL_CA_PATH CACHE)
+elseif("${CURL_CA_PATH}" STREQUAL "auto")
+    unset(CURL_CA_PATH CACHE)
+    set(CURL_CA_PATH_AUTODETECT TRUE)
+else()
+    set(CURL_CA_PATH_SET TRUE)
+endif()
+
+if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT)
+    # Skip autodetection of unset CA path because CA bundle is set explicitly
+elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT)
+    # Skip autodetection of unset CA bundle because CA path is set explicitly
+elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
+    # first try autodetecting a CA bundle, then a CA path
+
+    if(CURL_CA_BUNDLE_AUTODETECT)
+        set(SEARCH_CA_BUNDLE_PATHS
+            /etc/ssl/certs/ca-certificates.crt
+            /etc/pki/tls/certs/ca-bundle.crt
+            /usr/share/ssl/certs/ca-bundle.crt
+            /usr/local/share/certs/ca-root-nss.crt
+            /etc/ssl/cert.pem)
+
+        foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
+            if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
+                message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
+                set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
+                set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
+                break()
+            endif()
+        endforeach()
+    endif()
+
+    if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET))
+        if(EXISTS "/etc/ssl/certs")
+            set(CURL_CA_PATH "/etc/ssl/certs")
+            set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
+        endif()
+    endif()
+endif()
+
+if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS)
+    message(FATAL_ERROR
+            "CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
+            "Set CURL_CA_PATH=none or enable one of those TLS backends.")
+endif()
+endif()
+
+
 # Check for header files
 if(NOT UNIX)
   check_include_file_concat("windows.h"      HAVE_WINDOWS_H)
   check_include_file_concat("winsock.h"      HAVE_WINSOCK_H)
   check_include_file_concat("ws2tcpip.h"     HAVE_WS2TCPIP_H)
   check_include_file_concat("winsock2.h"     HAVE_WINSOCK2_H)
-  if(CURL_WINDOWS_SSPI)
-    set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32")
-    check_include_file_concat("sspi.h"       HAVE_SSPI_H)
-    if(HAVE_SSPI_H)
-      check_include_file_concat("schannel.h" HAVE_SCHANNEL_H)
-      set(USE_WINDOWS_SSPI ON)
-      if(HAVE_SCHANNEL_H)
-        set(USE_SCHANNEL ON)
-        set(SSL_ENABLED ON)
-        set(CURL_LIBS ${CURL_LIBS} "crypt32")
-      endif()
-    endif()
+  if(NOT CURL_WINDOWS_SSPI AND USE_OPENSSL)
+    set(CURL_LIBS ${CURL_LIBS} "crypt32")
   endif()
 else()
   set(HAVE_WINDOWS_H 0)
@@ -717,6 +848,7 @@ check_include_file_concat("sys/types.h"      HAVE_SYS_TYPES_H)
 check_include_file_concat("sys/uio.h"        HAVE_SYS_UIO_H)
 check_include_file_concat("sys/un.h"         HAVE_SYS_UN_H)
 check_include_file_concat("sys/utime.h"      HAVE_SYS_UTIME_H)
+check_include_file_concat("sys/xattr.h"      HAVE_SYS_XATTR_H)
 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)
@@ -797,11 +929,17 @@ if(HAVE_LIBWS2_32)
   set(CMAKE_REQUIRED_LIBRARIES ws2_32)
 elseif(HAVE_LIBSOCKET)
   set(CMAKE_REQUIRED_LIBRARIES socket)
+elseif(HAVE_LIBNETWORK)
+  set(CMAKE_REQUIRED_LIBRARIES network)
 endif()
 
 check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
 check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
-check_symbol_exists(poll          "${CURL_INCLUDES}" HAVE_POLL)
+# poll on macOS is unreliable, it first did not exist, then was broken until
+# fixed in 10.9 only to break again in 10.12.
+if(NOT APPLE)
+  check_symbol_exists(poll        "${CURL_INCLUDES}" HAVE_POLL)
+endif()
 check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
 check_symbol_exists(strdup        "${CURL_INCLUDES}" HAVE_STRDUP)
 check_symbol_exists(strstr        "${CURL_INCLUDES}" HAVE_STRSTR)
@@ -833,14 +971,6 @@ check_symbol_exists(strlcat       "${CURL_INCLUDES}" HAVE_STRLCAT)
 check_symbol_exists(getpwuid      "${CURL_INCLUDES}" HAVE_GETPWUID)
 check_symbol_exists(geteuid       "${CURL_INCLUDES}" HAVE_GETEUID)
 check_symbol_exists(utime         "${CURL_INCLUDES}" HAVE_UTIME)
-if(CMAKE_USE_OPENSSL)
-  check_symbol_exists(RAND_status   "${CURL_INCLUDES}" HAVE_RAND_STATUS)
-  check_symbol_exists(RAND_screen   "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
-  check_symbol_exists(RAND_egd      "${CURL_INCLUDES}" HAVE_RAND_EGD)
-  if(HAVE_LIBCRYPTO AND HAVE_LIBSSL)
-    set(USE_OPENSSL 1)
-  endif(HAVE_LIBCRYPTO AND HAVE_LIBSSL)
-endif(CMAKE_USE_OPENSSL)
 check_symbol_exists(gmtime_r      "${CURL_INCLUDES}" HAVE_GMTIME_R)
 check_symbol_exists(localtime_r   "${CURL_INCLUDES}" HAVE_LOCALTIME_R)
 
@@ -875,6 +1005,13 @@ check_symbol_exists(setsockopt     "${CURL_INCLUDES}" HAVE_SETSOCKOPT)
 # symbol exists in win32, but function does not.
 check_function_exists(inet_pton HAVE_INET_PTON)
 
+check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR)
+if(HAVE_FSETXATTR)
+  foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6)
+    curl_internal_test_run(${CURL_TEST})
+  endforeach(CURL_TEST)
+endif(HAVE_FSETXATTR)
+
 # sigaction and sigsetjmp are special. Use special mechanism for
 # detecting those, but only if previous attempt failed.
 if(HAVE_SIGNAL_H)
@@ -1088,9 +1225,9 @@ function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
   string(REPLACE "$(top_srcdir)"   "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
   string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 
-  string(REGEX REPLACE "\\\\\n" "�!�" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
+  string(REGEX REPLACE "\\\\\n" "!π!α!" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
   string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
-  string(REPLACE "�!�" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
+  string(REPLACE "!π!α!" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 
   string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace $() with ${}
   string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace @@ with ${}, even if that may not be read by CMake scripts.
@@ -1098,6 +1235,9 @@ function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
 
 endfunction()
 
+if(0) # This code not needed for building within CMake.
+add_subdirectory(docs)
+endif()
 add_subdirectory(lib)
 if(BUILD_CURL_EXE)
   add_subdirectory(src)
@@ -1121,11 +1261,6 @@ if(BUILD_TESTING)
   add_subdirectory(tests)
 endif()
 
-# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL, WINSSL, DARWINSSL
-if(USE_OPENSSL)
-  set(SSL_ENABLED 1)
-endif()
-
 # Helper to populate a list (_items) with a label when conditions (the remaining
 # args) are satisfied
 function(_add_if label)
@@ -1139,6 +1274,8 @@ endfunction()
 set(_items)
 _add_if("WinSSL"        SSL_ENABLED AND USE_WINDOWS_SSPI)
 _add_if("OpenSSL"       SSL_ENABLED AND USE_OPENSSL)
+_add_if("DarwinSSL"     SSL_ENABLED AND USE_DARWINSSL)
+_add_if("mbedTLS"       SSL_ENABLED AND USE_MBEDTLS)
 _add_if("IPv6"          ENABLE_IPV6)
 _add_if("unix-sockets"  USE_UNIX_SOCKETS)
 _add_if("libz"          HAVE_LIBZ)
@@ -1155,9 +1292,8 @@ _add_if("SPNEGO"        NOT CURL_DISABLE_CRYPTO_AUTH AND
 _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, DARWINSSL
-if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR
-   USE_WINDOWS_SSPI OR GNUTLS_ENABLED OR NSS_ENABLED OR DARWINSSL_ENABLED))
+# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
+if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS))
   _add_if("NTLM"        1)
   # TODO missing option (autoconf: --enable-ntlm-wb)
   _add_if("NTLM_WB"     NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
@@ -1206,8 +1342,6 @@ set(CC                      "${CMAKE_C_COMPILER}")
 set(CONFIGURE_OPTIONS       "")
 # TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
 set(CPPFLAG_CURL_STATICLIB  "")
-# TODO need to set this (see CURL_CHECK_CA_BUNDLE in acinclude.m4)
-set(CURL_CA_BUNDLE          "")
 set(CURLVERSION             "${CURL_VERSION}")
 set(ENABLE_SHARED           "yes")
 if(CURL_STATICLIB)
diff --git a/Utilities/cmcurl/COPYING b/Utilities/cmcurl/COPYING
index a98663e..1e45a5e 100644
--- a/Utilities/cmcurl/COPYING
+++ b/Utilities/cmcurl/COPYING
@@ -1,6 +1,6 @@
 COPYRIGHT AND PERMISSION NOTICE
 
-Copyright (c) 1996 - 2016, Daniel Stenberg, <daniel at haxx.se>, and many
+Copyright (c) 1996 - 2017, Daniel Stenberg, <daniel at haxx.se>, and many
 contributors, see the THANKS file.
 
 All rights reserved.
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index aa1034b..3955212 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -35,6 +35,7 @@
 #endif
 
 #include "curlver.h"         /* libcurl version defines   */
+#include "system.h"          /* determine things run-time */
 #include "cmcurl/include/curl/curlbuild.h" /* libcurl build definitions */
 #include "curlrules.h"       /* libcurl rules enforcement */
 
@@ -143,7 +144,7 @@ struct curl_httppost {
   char *buffer;                     /* pointer to allocated buffer contents */
   long bufferlength;                /* length of buffer field */
   char *contenttype;                /* Content-Type */
-  struct curl_slist* contentheader; /* list of extra headers for this form */
+  struct curl_slist *contentheader; /* list of extra headers for this form */
   struct curl_httppost *more;       /* if one field name has more than one
                                        file, this link should link to following
                                        files */
@@ -193,6 +194,11 @@ typedef int (*curl_xferinfo_callback)(void *clientp,
                                       curl_off_t ultotal,
                                       curl_off_t ulnow);
 
+#ifndef CURL_MAX_READ_SIZE
+  /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */
+#define CURL_MAX_READ_SIZE 524288
+#endif
+
 #ifndef CURL_MAX_WRITE_SIZE
   /* Tests have proven that 20K is a very bad buffer size for uploads on
      Windows, while 16K for some odd reason performed a lot better.
@@ -270,7 +276,7 @@ struct curl_fileinfo {
   unsigned int flags;
 
   /* used internally */
-  char * b_data;
+  char *b_data;
   size_t b_size;
   size_t b_used;
 };
@@ -479,7 +485,7 @@ typedef enum {
   CURLE_LDAP_CANNOT_BIND,        /* 38 */
   CURLE_LDAP_SEARCH_FAILED,      /* 39 */
   CURLE_OBSOLETE40,              /* 40 - NOT USED */
-  CURLE_FUNCTION_NOT_FOUND,      /* 41 */
+  CURLE_FUNCTION_NOT_FOUND,      /* 41 - NOT USED starting with 7.53.0 */
   CURLE_ABORTED_BY_CALLBACK,     /* 42 */
   CURLE_BAD_FUNCTION_ARGUMENT,   /* 43 */
   CURLE_OBSOLETE44,              /* 44 - NOT USED */
@@ -640,6 +646,7 @@ typedef enum {
                            CONNECT HTTP/1.1 */
   CURLPROXY_HTTP_1_0 = 1,   /* added in 7.19.4, force to use CONNECT
                                HTTP/1.0  */
+  CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
   CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
                            in 7.10 */
   CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
@@ -1206,7 +1213,8 @@ typedef enum {
   CINIT(SHARE, OBJECTPOINT, 100),
 
   /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
-     CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
+     CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
+     CURLPROXY_SOCKS5. */
   CINIT(PROXYTYPE, LONG, 101),
 
   /* Set the Accept-Encoding string. Use this to tell a server you would like
@@ -1593,7 +1601,7 @@ typedef enum {
   CINIT(DNS_SERVERS, STRINGPOINT, 211),
 
   /* Time-out accept operations (currently for FTP only) after this amount
-     of miliseconds. */
+     of milliseconds. */
   CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
 
   /* Set TCP keepalive */
@@ -1704,6 +1712,76 @@ typedef enum {
    * HTTP status code >= 300 */
   CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
 
+  /* The CApath or CAfile used to validate the proxy certificate
+     this option is used only if PROXY_SSL_VERIFYPEER is true */
+  CINIT(PROXY_CAINFO, STRINGPOINT, 246),
+
+  /* The CApath directory used to validate the proxy certificate
+     this option is used only if PROXY_SSL_VERIFYPEER is true */
+  CINIT(PROXY_CAPATH, STRINGPOINT, 247),
+
+  /* Set if we should verify the proxy in ssl handshake,
+     set 1 to verify. */
+  CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
+
+  /* Set if we should verify the Common name from the proxy certificate in ssl
+   * handshake, set 1 to check existence, 2 to ensure that it matches
+   * the provided hostname. */
+  CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
+
+  /* What version to specifically try to use for proxy.
+     See CURL_SSLVERSION defines below. */
+  CINIT(PROXY_SSLVERSION, LONG, 250),
+
+  /* Set a username for authenticated TLS for proxy */
+  CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
+
+  /* Set a password for authenticated TLS for proxy */
+  CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
+
+  /* Set authentication type for authenticated TLS for proxy */
+  CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
+
+  /* name of the file keeping your private SSL-certificate for proxy */
+  CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
+
+  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
+     proxy */
+  CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
+
+  /* name of the file keeping your private SSL-key for proxy */
+  CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
+
+  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
+     proxy */
+  CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
+
+  /* password for the SSL private key for proxy */
+  CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
+
+  /* Specify which SSL ciphers to use for proxy */
+  CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
+
+  /* CRL file for proxy */
+  CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
+
+  /* Enable/disable specific SSL features with a bitmask for proxy, see
+     CURLSSLOPT_* */
+  CINIT(PROXY_SSL_OPTIONS, LONG, 261),
+
+  /* Name of pre proxy to use. */
+  CINIT(PRE_PROXY, STRINGPOINT, 262),
+
+  /* The public key in DER form used to validate the proxy public key
+     this option is used only if PROXY_SSL_VERIFYPEER is true */
+  CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
+
+  /* Path to an abstract Unix domain socket */
+  CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264),
+
+  /* Suppress proxy CONNECT response headers from user callbacks */
+  CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
@@ -1805,10 +1883,23 @@ enum {
   CURL_SSLVERSION_TLSv1_0,
   CURL_SSLVERSION_TLSv1_1,
   CURL_SSLVERSION_TLSv1_2,
+  CURL_SSLVERSION_TLSv1_3,
 
   CURL_SSLVERSION_LAST /* never use, keep last */
 };
 
+enum {
+  CURL_SSLVERSION_MAX_NONE =     0,
+  CURL_SSLVERSION_MAX_DEFAULT =  (CURL_SSLVERSION_TLSv1   << 16),
+  CURL_SSLVERSION_MAX_TLSv1_0 =  (CURL_SSLVERSION_TLSv1_0 << 16),
+  CURL_SSLVERSION_MAX_TLSv1_1 =  (CURL_SSLVERSION_TLSv1_1 << 16),
+  CURL_SSLVERSION_MAX_TLSv1_2 =  (CURL_SSLVERSION_TLSv1_2 << 16),
+  CURL_SSLVERSION_MAX_TLSv1_3 =  (CURL_SSLVERSION_TLSv1_3 << 16),
+
+  /* never use, keep last */
+  CURL_SSLVERSION_MAX_LAST =     (CURL_SSLVERSION_LAST    << 16)
+};
+
 enum CURL_TLSAUTH {
   CURL_TLSAUTH_NONE,
   CURL_TLSAUTH_SRP,
@@ -1839,7 +1930,10 @@ typedef enum {
 
 
 /* curl_strequal() and curl_strnequal() are subject for removal in a future
-   libcurl, see lib/README.curlx for details */
+   libcurl, see lib/README.curlx for details
+
+   !checksrc! disable SPACEBEFOREPAREN 2
+*/
 CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
 CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
 
@@ -2157,6 +2251,7 @@ struct curl_tlssessioninfo {
 #define CURLINFO_LONG     0x200000
 #define CURLINFO_DOUBLE   0x300000
 #define CURLINFO_SLIST    0x400000
+#define CURLINFO_PTR      0x400000 /* same as SLIST */
 #define CURLINFO_SOCKET   0x500000
 #define CURLINFO_MASK     0x0fffff
 #define CURLINFO_TYPEMASK 0xf00000
@@ -2196,7 +2291,7 @@ typedef enum {
   CURLINFO_REDIRECT_URL     = CURLINFO_STRING + 31,
   CURLINFO_PRIMARY_IP       = CURLINFO_STRING + 32,
   CURLINFO_APPCONNECT_TIME  = CURLINFO_DOUBLE + 33,
-  CURLINFO_CERTINFO         = CURLINFO_SLIST  + 34,
+  CURLINFO_CERTINFO         = CURLINFO_PTR    + 34,
   CURLINFO_CONDITION_UNMET  = CURLINFO_LONG   + 35,
   CURLINFO_RTSP_SESSION_ID  = CURLINFO_STRING + 36,
   CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG   + 37,
@@ -2205,13 +2300,16 @@ typedef enum {
   CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40,
   CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41,
   CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42,
-  CURLINFO_TLS_SESSION      = CURLINFO_SLIST  + 43,
+  CURLINFO_TLS_SESSION      = CURLINFO_PTR    + 43,
   CURLINFO_ACTIVESOCKET     = CURLINFO_SOCKET + 44,
-  CURLINFO_TLS_SSL_PTR      = CURLINFO_SLIST  + 45,
+  CURLINFO_TLS_SSL_PTR      = CURLINFO_PTR    + 45,
   CURLINFO_HTTP_VERSION     = CURLINFO_LONG   + 46,
+  CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
+  CURLINFO_PROTOCOL         = CURLINFO_LONG   + 48,
+  CURLINFO_SCHEME           = CURLINFO_STRING + 49,
   /* Fill in new entries below here! */
 
-  CURLINFO_LASTONE          = 46
+  CURLINFO_LASTONE          = 49
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2365,13 +2463,14 @@ typedef struct {
 #define CURL_VERSION_CURLDEBUG    (1<<13) /* Debug memory tracking supported */
 #define CURL_VERSION_TLSAUTH_SRP  (1<<14) /* TLS-SRP auth is supported */
 #define CURL_VERSION_NTLM_WB      (1<<15) /* NTLM delegation to winbind helper
-                                             is suported */
+                                             is supported */
 #define CURL_VERSION_HTTP2        (1<<16) /* HTTP2 support built-in */
 #define CURL_VERSION_GSSAPI       (1<<17) /* Built against a GSS-API library */
 #define CURL_VERSION_KERBEROS5    (1<<18) /* Kerberos V5 auth is supported */
 #define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
 #define CURL_VERSION_PSL          (1<<20) /* Mozilla's Public Suffix List, used
                                              for cookie domain verification */
+#define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
 
  /*
  * NAME curl_version_info()
diff --git a/Utilities/cmcurl/include/curl/curlrules.h b/Utilities/cmcurl/include/curl/curlrules.h
index 55d21f6..0abd9f7 100644
--- a/Utilities/cmcurl/include/curl/curlrules.h
+++ b/Utilities/cmcurl/include/curl/curlrules.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -105,11 +105,6 @@
    Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
 #endif
 
-#ifndef CURL_FORMAT_OFF_T
-#  error "CURL_FORMAT_OFF_T definition is missing!"
-   Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
-#endif
-
 #ifndef CURL_SIZEOF_CURL_OFF_T
 #  error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
    Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
@@ -241,22 +236,4 @@ typedef char
 #undef CurlchkszEQ
 #undef CurlchkszGE
 
-/*
- * Get rid of macros not intended to exist beyond this point.
- */
-
-#undef CURL_PULL_WS2TCPIP_H
-#undef CURL_PULL_SYS_TYPES_H
-#undef CURL_PULL_SYS_SOCKET_H
-#undef CURL_PULL_SYS_POLL_H
-#undef CURL_PULL_STDINT_H
-#undef CURL_PULL_INTTYPES_H
-
-#undef CURL_TYPEOF_CURL_SOCKLEN_T
-#undef CURL_TYPEOF_CURL_OFF_T
-
-#ifdef CURL_NO_OLDIES
-#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */
-#endif
-
 #endif /* __CURL_CURLRULES_H */
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 2415d1a..667b7eb 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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,17 +26,17 @@
    a script at release-time. This was made its own header file in 7.11.2 */
 
 /* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2016 Daniel Stenberg, <daniel at haxx.se>."
+#define LIBCURL_COPYRIGHT "1996 - 2017 Daniel Stenberg, <daniel at haxx.se>."
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.51.0"
+#define LIBCURL_VERSION "7.54.1"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 51
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_MINOR 54
+#define LIBCURL_VERSION_PATCH 1
 
 /* This is the numeric version of the libcurl version number, meant for easier
    parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -57,18 +57,18 @@
    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 0x073300
+#define LIBCURL_VERSION_NUM 0x073601
 
 /*
  * This is the date and time when the full source package was created. The
  * timestamp is not stored in git, as the timestamp is properly set in the
  * tarballs by the maketgz script.
  *
- * The format of the date should follow this template:
+ * The format of the date follows this template:
  *
- * "Mon Feb 12 11:35:33 UTC 2007"
+ * "2007-11-23"
  */
-#define LIBCURL_TIMESTAMP "DEV"
+#define LIBCURL_TIMESTAMP "[unreleased]"
 
 #define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
 #define CURL_AT_LEAST_VERSION(x,y,z) \
diff --git a/Utilities/cmcurl/include/curl/easy.h b/Utilities/cmcurl/include/curl/easy.h
index afc766c..752c504 100644
--- a/Utilities/cmcurl/include/curl/easy.h
+++ b/Utilities/cmcurl/include/curl/easy.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -58,7 +58,7 @@ CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
  * curl_easy_duphandle() for each new thread to avoid a series of identical
  * curl_easy_setopt() invokes in every thread.
  */
-CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
+CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
 
 /*
  * NAME curl_easy_reset()
diff --git a/Utilities/cmcurl/include/curl/stdcheaders.h b/Utilities/cmcurl/include/curl/stdcheaders.h
index 6f0f7f3..027b6f4 100644
--- a/Utilities/cmcurl/include/curl/stdcheaders.h
+++ b/Utilities/cmcurl/include/curl/stdcheaders.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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,8 +24,8 @@
 
 #include <sys/types.h>
 
-size_t fread (void *, size_t, size_t, FILE *);
-size_t fwrite (const void *, size_t, size_t, FILE *);
+size_t fread(void *, size_t, size_t, FILE *);
+size_t fwrite(const void *, size_t, size_t, FILE *);
 
 int strcasecmp(const char *, const char *);
 int strncasecmp(const char *, const char *, size_t);
diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h
new file mode 100644
index 0000000..ed3a55c
--- /dev/null
+++ b/Utilities/cmcurl/include/curl/system.h
@@ -0,0 +1,484 @@
+#ifndef __CURL_SYSTEM_H
+#define __CURL_SYSTEM_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * This header is supposed to eventually replace curlbuild.h. This little one
+ * is still learning.  During the experimental phase, this header files
+ * defines symbols using the prefixes CURLSYS_ or curlsys_. When we feel
+ * confident enough, we replace curlbuild.h with this file and rename all
+ * prefixes to CURL_ and curl_.
+ */
+
+/*
+ * Try to keep one section per platform, compiler and architecture, otherwise,
+ * if an existing section is reused for a different one and later on the
+ * original is adjusted, probably the piggybacking one can be adversely
+ * changed.
+ *
+ * In order to differentiate between platforms/compilers/architectures use
+ * only compiler built in predefined preprocessor symbols.
+ *
+ * curl_off_t
+ * ----------
+ *
+ * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit
+ * wide signed integral data type. The width of this data type must remain
+ * constant and independent of any possible large file support settings.
+ *
+ * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit
+ * wide signed integral data type if there is no 64-bit type.
+ *
+ * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall
+ * only be violated if off_t is the only 64-bit data type available and the
+ * size of off_t is independent of large file support settings. Keep your
+ * build on the safe side avoiding an off_t gating.  If you have a 64-bit
+ * off_t then take for sure that another 64-bit data type exists, dig deeper
+ * and you will find it.
+ *
+ */
+
+#if defined(__DJGPP__) || defined(__GO32__)
+#  if defined(__DJGPP__) && (__DJGPP__ > 1)
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  else
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     4
+#    define CURLSYS_SUFFIX_CURL_OFF_T     L
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__SALFORDC__)
+#  define CURLSYS_SIZEOF_LONG           4
+#  define CURLSYS_TYPEOF_CURL_OFF_T     long
+#  define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#  define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#  define CURLSYS_SIZEOF_CURL_OFF_T     4
+#  define CURLSYS_SUFFIX_CURL_OFF_T     L
+#  define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__BORLANDC__)
+#  if (__BORLANDC__ < 0x520)
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     4
+#    define CURLSYS_SUFFIX_CURL_OFF_T     L
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  else
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     __int64
+#    define CURLSYS_FORMAT_CURL_OFF_T     "I64d"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     i64
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ui64
+#  endif
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__TURBOC__)
+#  define CURLSYS_SIZEOF_LONG           4
+#  define CURLSYS_TYPEOF_CURL_OFF_T     long
+#  define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#  define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#  define CURLSYS_SIZEOF_CURL_OFF_T     4
+#  define CURLSYS_SUFFIX_CURL_OFF_T     L
+#  define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__WATCOMC__)
+#  if defined(__386__)
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     __int64
+#    define CURLSYS_FORMAT_CURL_OFF_T     "I64d"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     i64
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ui64
+#  else
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     4
+#    define CURLSYS_SUFFIX_CURL_OFF_T     L
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__POCC__)
+#  if (__POCC__ < 280)
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     4
+#    define CURLSYS_SUFFIX_CURL_OFF_T     L
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  elif defined(_MSC_VER)
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     __int64
+#    define CURLSYS_FORMAT_CURL_OFF_T     "I64d"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     i64
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ui64
+#  else
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  endif
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__LCC__)
+#  define CURLSYS_SIZEOF_LONG           4
+#  define CURLSYS_TYPEOF_CURL_OFF_T     long
+#  define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#  define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#  define CURLSYS_SIZEOF_CURL_OFF_T     4
+#  define CURLSYS_SUFFIX_CURL_OFF_T     L
+#  define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__SYMBIAN32__)
+#  if defined(__EABI__)  /* Treat all ARM compilers equally */
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__CW32__)
+#    pragma longlong on
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__VC32__)
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     __int64
+#    define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  endif
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T unsigned int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__MWERKS__)
+#  define CURLSYS_SIZEOF_LONG           4
+#  define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#  define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#  define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#  define CURLSYS_SIZEOF_CURL_OFF_T     8
+#  define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#  define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(_WIN32_WCE)
+#  define CURLSYS_SIZEOF_LONG           4
+#  define CURLSYS_TYPEOF_CURL_OFF_T     __int64
+#  define CURLSYS_FORMAT_CURL_OFF_T     "I64d"
+#  define CURLSYS_FORMAT_CURL_OFF_TU    "I64u"
+#  define CURLSYS_SIZEOF_CURL_OFF_T     8
+#  define CURLSYS_SUFFIX_CURL_OFF_T     i64
+#  define CURLSYS_SUFFIX_CURL_OFF_TU    ui64
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__MINGW32__)
+#  define CURLSYS_SIZEOF_LONG           4
+#  define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#  define CURLSYS_FORMAT_CURL_OFF_T     "I64d"
+#  define CURLSYS_FORMAT_CURL_OFF_TU    "I64u"
+#  define CURLSYS_SIZEOF_CURL_OFF_T     8
+#  define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#  define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+#  define CURLSYS_PULL_SYS_TYPES_H      1
+#  define CURLSYS_PULL_WS2TCPIP_H       1
+
+#elif defined(__VMS)
+#  if defined(__VAX)
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     4
+#    define CURLSYS_SUFFIX_CURL_OFF_T     L
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  else
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  endif
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T unsigned int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__OS400__)
+#  if defined(__ILEC400__)
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#    define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t
+#    define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+#    define CURLSYS_PULL_SYS_TYPES_H      1
+#    define CURLSYS_PULL_SYS_SOCKET_H     1
+#  endif
+
+#elif defined(__MVS__)
+#  if defined(__IBMC__) || defined(__IBMCPP__)
+#    if defined(_ILP32)
+#      define CURLSYS_SIZEOF_LONG           4
+#    elif defined(_LP64)
+#      define CURLSYS_SIZEOF_LONG           8
+#    endif
+#    if defined(_LONG_LONG)
+#      define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#      define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#      define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#      define CURLSYS_SIZEOF_CURL_OFF_T     8
+#      define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#      define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#    elif defined(_LP64)
+#      define CURLSYS_TYPEOF_CURL_OFF_T     long
+#      define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#      define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#      define CURLSYS_SIZEOF_CURL_OFF_T     8
+#      define CURLSYS_SUFFIX_CURL_OFF_T     L
+#      define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#    else
+#      define CURLSYS_TYPEOF_CURL_OFF_T     long
+#      define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#      define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#      define CURLSYS_SIZEOF_CURL_OFF_T     4
+#      define CURLSYS_SUFFIX_CURL_OFF_T     L
+#      define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#    endif
+#    define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t
+#    define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+#    define CURLSYS_PULL_SYS_TYPES_H      1
+#    define CURLSYS_PULL_SYS_SOCKET_H     1
+#  endif
+
+#elif defined(__370__)
+#  if defined(__IBMC__) || defined(__IBMCPP__)
+#    if defined(_ILP32)
+#      define CURLSYS_SIZEOF_LONG           4
+#    elif defined(_LP64)
+#      define CURLSYS_SIZEOF_LONG           8
+#    endif
+#    if defined(_LONG_LONG)
+#      define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#      define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#      define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#      define CURLSYS_SIZEOF_CURL_OFF_T     8
+#      define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#      define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#    elif defined(_LP64)
+#      define CURLSYS_TYPEOF_CURL_OFF_T     long
+#      define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#      define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#      define CURLSYS_SIZEOF_CURL_OFF_T     8
+#      define CURLSYS_SUFFIX_CURL_OFF_T     L
+#      define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#    else
+#      define CURLSYS_TYPEOF_CURL_OFF_T     long
+#      define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#      define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#      define CURLSYS_SIZEOF_CURL_OFF_T     4
+#      define CURLSYS_SUFFIX_CURL_OFF_T     L
+#      define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#    endif
+#    define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t
+#    define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+#    define CURLSYS_PULL_SYS_TYPES_H      1
+#    define CURLSYS_PULL_SYS_SOCKET_H     1
+#  endif
+
+#elif defined(TPF)
+#  define CURLSYS_SIZEOF_LONG           8
+#  define CURLSYS_TYPEOF_CURL_OFF_T     long
+#  define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#  define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#  define CURLSYS_SIZEOF_CURL_OFF_T     8
+#  define CURLSYS_SUFFIX_CURL_OFF_T     L
+#  define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+#elif defined(__TINYC__) /* also known as tcc */
+
+#  define CURLSYS_SIZEOF_LONG           4
+#  define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#  define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#  define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#  define CURLSYS_SIZEOF_CURL_OFF_T     8
+#  define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#  define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURLSYS_PULL_SYS_TYPES_H      1
+#  define CURLSYS_PULL_SYS_SOCKET_H     1
+
+/* ===================================== */
+/*    KEEP MSVC THE PENULTIMATE ENTRY    */
+/* ===================================== */
+
+#elif defined(_MSC_VER)
+#  if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     __int64
+#    define CURLSYS_FORMAT_CURL_OFF_T     "I64d"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "I64u"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     i64
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ui64
+#  else
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     4
+#    define CURLSYS_SUFFIX_CURL_OFF_T     L
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+
+/* ===================================== */
+/*    KEEP GENERIC GCC THE LAST ENTRY    */
+/* ===================================== */
+
+#elif defined(__GNUC__)
+#  if !defined(__LP64__) && (defined(__ILP32__) || \
+      defined(__i386__) || defined(__ppc__) || defined(__arm__) || \
+      defined(__sparc__) || defined(__mips__) || defined(__sh__))
+#    define CURLSYS_SIZEOF_LONG           4
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "lld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "llu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     LL
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    ULL
+#  elif defined(__LP64__) || \
+        defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__)
+#    define CURLSYS_SIZEOF_LONG           8
+#    define CURLSYS_TYPEOF_CURL_OFF_T     long
+#    define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+#    define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+#    define CURLSYS_SIZEOF_CURL_OFF_T     8
+#    define CURLSYS_SUFFIX_CURL_OFF_T     L
+#    define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURLSYS_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+#  define CURLSYS_PULL_SYS_TYPES_H      1
+#  define CURLSYS_PULL_SYS_SOCKET_H     1
+
+#else
+/* generic "safe guess" on old 32 bit style */
+# define CURLSYS_SIZEOF_LONG 4
+# define CURLSYS_SIZEOF_CURL_SOCKLEN_T 4
+# define CURLSYS_SIZEOF_CURL_OFF_T 4
+# define CURLSYS_TYPEOF_CURL_OFF_T     long
+# define CURLSYS_FORMAT_CURL_OFF_T     "ld"
+# define CURLSYS_FORMAT_CURL_OFF_TU    "lu"
+# define CURLSYS_SUFFIX_CURL_OFF_T     L
+# define CURLSYS_SUFFIX_CURL_OFF_TU    UL
+# define CURLSYS_TYPEOF_CURL_SOCKLEN_T int
+#endif
+
+/* CURLSYS_PULL_WS2TCPIP_H is defined above when inclusion of header file  */
+/* ws2tcpip.h is required here to properly make type definitions below. */
+#ifdef CURLSYS_PULL_WS2TCPIP_H
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN
+#  endif
+#  include <windows.h>
+#  include <winsock2.h>
+#  include <ws2tcpip.h>
+#endif
+
+/* CURLSYS_PULL_SYS_TYPES_H is defined above when inclusion of header file  */
+/* sys/types.h is required here to properly make type definitions below. */
+#ifdef CURLSYS_PULL_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+
+/* CURLSYS_PULL_SYS_SOCKET_H is defined above when inclusion of header file  */
+/* sys/socket.h is required here to properly make type definitions below. */
+#ifdef CURLSYS_PULL_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+
+/* Data type definition of curl_socklen_t. */
+#ifdef CURLSYS_TYPEOF_CURL_SOCKLEN_T
+  typedef CURLSYS_TYPEOF_CURL_SOCKLEN_T curlsys_socklen_t;
+#endif
+
+/* Data type definition of curl_off_t. */
+
+#ifdef CURLSYS_TYPEOF_CURL_OFF_T
+  typedef CURLSYS_TYPEOF_CURL_OFF_T curlsys_off_t;
+#endif
+
+#endif /* __CURL_SYSTEM_H */
+
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 6ec8bcf..10b5de2 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -40,7 +40,7 @@
  */
 #define curl_easy_setopt(handle, option, value)                               \
 __extension__ ({                                                              \
-  __typeof__ (option) _curl_opt = option;                                     \
+  __typeof__(option) _curl_opt = option;                                     \
   if(__builtin_constant_p(_curl_opt)) {                                       \
     if(_curl_is_long_option(_curl_opt))                                       \
       if(!_curl_is_long(value))                                               \
@@ -110,7 +110,7 @@ __extension__ ({                                                              \
 /* FIXME: don't allow const pointers */
 #define curl_easy_getinfo(handle, info, arg)                                  \
 __extension__ ({                                                              \
-  __typeof__ (info) _curl_info = info;                                        \
+  __typeof__(info) _curl_info = info;                                        \
   if(__builtin_constant_p(_curl_info)) {                                      \
     if(_curl_is_string_info(_curl_info))                                      \
       if(!_curl_is_arr((arg), char *))                                        \
@@ -124,6 +124,15 @@ __extension__ ({                                                              \
     if(_curl_is_slist_info(_curl_info))                                       \
       if(!_curl_is_arr((arg), struct curl_slist *))                           \
         _curl_easy_getinfo_err_curl_slist();                                  \
+    if(_curl_is_tlssessioninfo_info(_curl_info))                              \
+      if(!_curl_is_arr((arg), struct curl_tlssessioninfo *))                  \
+        _curl_easy_getinfo_err_curl_tlssesssioninfo();                        \
+    if(_curl_is_certinfo_info(_curl_info))                                    \
+      if(!_curl_is_arr((arg), struct curl_certinfo *))                        \
+        _curl_easy_getinfo_err_curl_certinfo();                               \
+   if(_curl_is_socket_info(_curl_info))                                       \
+      if(!_curl_is_arr((arg), curl_socket_t))                                 \
+        _curl_easy_getinfo_err_curl_socket();                                 \
   }                                                                           \
   curl_easy_getinfo(handle, _curl_info, arg);                                 \
 })
@@ -151,7 +160,7 @@ _CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
   "curl_easy_setopt expects a curl_off_t argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_string,
               "curl_easy_setopt expects a "
-              "string (char* or char[]) argument for this option"
+              "string ('char *' or char[]) argument for this option"
   )
 _CURL_WARNING(_curl_easy_setopt_err_write_callback,
   "curl_easy_setopt expects a curl_write_callback argument for this option")
@@ -182,24 +191,33 @@ _CURL_WARNING(_curl_easy_setopt_err_error_buffer,
               "curl_easy_setopt expects a "
               "char buffer of CURL_ERROR_SIZE as argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_FILE,
-  "curl_easy_setopt expects a FILE* argument for this option")
+  "curl_easy_setopt expects a 'FILE *' argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_postfields,
-  "curl_easy_setopt expects a void* or char* argument for this option")
+  "curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
-  "curl_easy_setopt expects a struct curl_httppost* argument for this option")
+              "curl_easy_setopt expects a 'struct curl_httppost *' "
+              "argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_curl_slist,
-  "curl_easy_setopt expects a struct curl_slist* argument for this option")
+  "curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_CURLSH,
   "curl_easy_setopt expects a CURLSH* argument for this option")
 
 _CURL_WARNING(_curl_easy_getinfo_err_string,
-  "curl_easy_getinfo expects a pointer to char * for this info")
+  "curl_easy_getinfo expects a pointer to 'char *' for this info")
 _CURL_WARNING(_curl_easy_getinfo_err_long,
   "curl_easy_getinfo expects a pointer to long for this info")
 _CURL_WARNING(_curl_easy_getinfo_err_double,
   "curl_easy_getinfo expects a pointer to double for this info")
 _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
-  "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
+  "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
+              "curl_easy_getinfo expects a pointer to "
+              "'struct curl_tlssessioninfo *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
+              "curl_easy_getinfo expects a pointer to "
+              "'struct curl_certinfo *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
+  "curl_easy_getinfo expects a pointer to curl_socket_t for this info")
 
 /* groups of curl_easy_setops options that take the same type of argument */
 
@@ -218,7 +236,8 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
 
 /* evaluates to true if option takes a char* argument */
 #define _curl_is_string_option(option)                                        \
-  ((option) == CURLOPT_ACCEPT_ENCODING ||                                     \
+  ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET ||                                \
+   (option) == CURLOPT_ACCEPT_ENCODING ||                                     \
    (option) == CURLOPT_CAINFO ||                                              \
    (option) == CURLOPT_CAPATH ||                                              \
    (option) == CURLOPT_COOKIE ||                                              \
@@ -247,11 +266,25 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
    (option) == CURLOPT_NOPROXY ||                                             \
    (option) == CURLOPT_PASSWORD ||                                            \
    (option) == CURLOPT_PINNEDPUBLICKEY ||                                     \
+   (option) == CURLOPT_PRE_PROXY ||                                           \
    (option) == CURLOPT_PROXY ||                                               \
    (option) == CURLOPT_PROXYPASSWORD ||                                       \
    (option) == CURLOPT_PROXYUSERNAME ||                                       \
    (option) == CURLOPT_PROXYUSERPWD ||                                        \
+   (option) == CURLOPT_PROXY_CAINFO ||                                        \
+   (option) == CURLOPT_PROXY_CAPATH ||                                        \
+   (option) == CURLOPT_PROXY_CRLFILE ||                                       \
+   (option) == CURLOPT_PROXY_KEYPASSWD ||                                     \
+   (option) == CURLOPT_PROXY_PINNEDPUBLICKEY ||                               \
    (option) == CURLOPT_PROXY_SERVICE_NAME ||                                  \
+   (option) == CURLOPT_PROXY_SSLCERT ||                                       \
+   (option) == CURLOPT_PROXY_SSLCERTTYPE ||                                   \
+   (option) == CURLOPT_PROXY_SSLKEY ||                                        \
+   (option) == CURLOPT_PROXY_SSLKEYTYPE ||                                    \
+   (option) == CURLOPT_PROXY_SSL_CIPHER_LIST ||                               \
+   (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD ||                              \
+   (option) == CURLOPT_PROXY_TLSAUTH_USERNAME ||                              \
+   (option) == CURLOPT_PROXY_TLSAUTH_TYPE ||                                  \
    (option) == CURLOPT_RANDOM_FILE ||                                         \
    (option) == CURLOPT_RANGE ||                                               \
    (option) == CURLOPT_REFERER ||                                             \
@@ -346,8 +379,19 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
   (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
 
 /* true if info expects a pointer to struct curl_slist * argument */
-#define _curl_is_slist_info(info)                                             \
-  (CURLINFO_SLIST < (info))
+#define _curl_is_slist_info(info)                                       \
+  (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
+
+/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
+#define _curl_is_tlssessioninfo_info(info)                              \
+  (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
+
+/* true if info expects a pointer to struct curl_certinfo * argument */
+#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
+
+/* true if info expects a pointer to struct curl_socket_t argument */
+#define _curl_is_socket_info(info)                                            \
+  (CURLINFO_SOCKET < (info))
 
 
 /* typecheck helpers -- check whether given expression has requested type*/
@@ -363,7 +407,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
 
 /* XXX: should evaluate to true iff expr is a pointer */
 #define _curl_is_any_ptr(expr)                                                \
-  (sizeof(expr) == sizeof(void*))
+  (sizeof(expr) == sizeof(void *))
 
 /* evaluates to true if expr is NULL */
 /* XXX: must not evaluate expr, so this check is not accurate */
@@ -426,8 +470,9 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
 #endif
 
 /* evaluates to true if expr is of type FILE* */
-#define _curl_is_FILE(expr)                                                   \
-  (__builtin_types_compatible_p(__typeof__(expr), FILE *))
+#define _curl_is_FILE(expr)                                             \
+  (_curl_is_NULL(expr) ||                                              \
+   (__builtin_types_compatible_p(__typeof__(expr), FILE *)))
 
 /* evaluates to true if expr can be passed as POST data (void* or char*) */
 #define _curl_is_postfields(expr)                                             \
@@ -442,102 +487,102 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
  * function pointers, hide it */
 #define _curl_callback_compatible(func, type)                                 \
   (__builtin_types_compatible_p(__typeof__(func), type) ||                    \
-   __builtin_types_compatible_p(__typeof__(func), type*))
+   __builtin_types_compatible_p(__typeof__(func) *, type))
 
 /* evaluates to true if expr is of type curl_read_callback or "similar" */
 #define _curl_is_read_cb(expr)                                          \
   (_curl_is_NULL(expr) ||                                                     \
-   __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) ||       \
-   __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) ||      \
+   _curl_callback_compatible((expr), __typeof__(fread) *) ||                  \
+   _curl_callback_compatible((expr), curl_read_callback) ||                   \
    _curl_callback_compatible((expr), _curl_read_callback1) ||                 \
    _curl_callback_compatible((expr), _curl_read_callback2) ||                 \
    _curl_callback_compatible((expr), _curl_read_callback3) ||                 \
    _curl_callback_compatible((expr), _curl_read_callback4) ||                 \
    _curl_callback_compatible((expr), _curl_read_callback5) ||                 \
    _curl_callback_compatible((expr), _curl_read_callback6))
-typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
-typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
-typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
-typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
-typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
-typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
+typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
+typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
+typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
+typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
+typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
+typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
 
 /* evaluates to true if expr is of type curl_write_callback or "similar" */
 #define _curl_is_write_cb(expr)                                               \
   (_curl_is_read_cb(expr) ||                                            \
-   __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) ||      \
-   __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) ||     \
+   _curl_callback_compatible((expr), __typeof__(fwrite) *) ||                 \
+   _curl_callback_compatible((expr), curl_write_callback) ||                  \
    _curl_callback_compatible((expr), _curl_write_callback1) ||                \
    _curl_callback_compatible((expr), _curl_write_callback2) ||                \
    _curl_callback_compatible((expr), _curl_write_callback3) ||                \
    _curl_callback_compatible((expr), _curl_write_callback4) ||                \
    _curl_callback_compatible((expr), _curl_write_callback5) ||                \
    _curl_callback_compatible((expr), _curl_write_callback6))
-typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
-typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
-                                       const void*);
-typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
-typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
-typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
-                                       const void*);
-typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
+typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
+typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
+                                       const void *);
+typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
+typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
+typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
+                                       const void *);
+typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
 
 /* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
 #define _curl_is_ioctl_cb(expr)                                         \
   (_curl_is_NULL(expr) ||                                                     \
-   __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) ||     \
+   _curl_callback_compatible((expr), curl_ioctl_callback) ||                  \
    _curl_callback_compatible((expr), _curl_ioctl_callback1) ||                \
    _curl_callback_compatible((expr), _curl_ioctl_callback2) ||                \
    _curl_callback_compatible((expr), _curl_ioctl_callback3) ||                \
    _curl_callback_compatible((expr), _curl_ioctl_callback4))
-typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
-typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
-typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
-typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
+typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
+typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
+typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
+typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
 
 /* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
 #define _curl_is_sockopt_cb(expr)                                       \
   (_curl_is_NULL(expr) ||                                                     \
-   __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) ||   \
+   _curl_callback_compatible((expr), curl_sockopt_callback) ||                \
    _curl_callback_compatible((expr), _curl_sockopt_callback1) ||              \
    _curl_callback_compatible((expr), _curl_sockopt_callback2))
-typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
-typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
+typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
+typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
                                       curlsocktype);
 
 /* evaluates to true if expr is of type curl_opensocket_callback or
    "similar" */
 #define _curl_is_opensocket_cb(expr)                                    \
   (_curl_is_NULL(expr) ||                                                     \
-   __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
+   _curl_callback_compatible((expr), curl_opensocket_callback) ||             \
    _curl_callback_compatible((expr), _curl_opensocket_callback1) ||           \
    _curl_callback_compatible((expr), _curl_opensocket_callback2) ||           \
    _curl_callback_compatible((expr), _curl_opensocket_callback3) ||           \
    _curl_callback_compatible((expr), _curl_opensocket_callback4))
-typedef curl_socket_t (_curl_opensocket_callback1)
+typedef curl_socket_t (*_curl_opensocket_callback1)
   (void *, curlsocktype, struct curl_sockaddr *);
-typedef curl_socket_t (_curl_opensocket_callback2)
+typedef curl_socket_t (*_curl_opensocket_callback2)
   (void *, curlsocktype, const struct curl_sockaddr *);
-typedef curl_socket_t (_curl_opensocket_callback3)
+typedef curl_socket_t (*_curl_opensocket_callback3)
   (const void *, curlsocktype, struct curl_sockaddr *);
-typedef curl_socket_t (_curl_opensocket_callback4)
+typedef curl_socket_t (*_curl_opensocket_callback4)
   (const void *, curlsocktype, const struct curl_sockaddr *);
 
 /* evaluates to true if expr is of type curl_progress_callback or "similar" */
 #define _curl_is_progress_cb(expr)                                      \
   (_curl_is_NULL(expr) ||                                                     \
-   __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) ||  \
+   _curl_callback_compatible((expr), curl_progress_callback) ||               \
    _curl_callback_compatible((expr), _curl_progress_callback1) ||             \
    _curl_callback_compatible((expr), _curl_progress_callback2))
-typedef int (_curl_progress_callback1)(void *,
+typedef int (*_curl_progress_callback1)(void *,
     double, double, double, double);
-typedef int (_curl_progress_callback2)(const void *,
+typedef int (*_curl_progress_callback2)(const void *,
     double, double, double, double);
 
 /* evaluates to true if expr is of type curl_debug_callback or "similar" */
 #define _curl_is_debug_cb(expr)                                         \
   (_curl_is_NULL(expr) ||                                                     \
-   __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) ||     \
+   _curl_callback_compatible((expr), curl_debug_callback) ||                  \
    _curl_callback_compatible((expr), _curl_debug_callback1) ||                \
    _curl_callback_compatible((expr), _curl_debug_callback2) ||                \
    _curl_callback_compatible((expr), _curl_debug_callback3) ||                \
@@ -546,28 +591,28 @@ typedef int (_curl_progress_callback2)(const void *,
    _curl_callback_compatible((expr), _curl_debug_callback6) ||                \
    _curl_callback_compatible((expr), _curl_debug_callback7) ||                \
    _curl_callback_compatible((expr), _curl_debug_callback8))
-typedef int (_curl_debug_callback1) (CURL *,
+typedef int (*_curl_debug_callback1) (CURL *,
     curl_infotype, char *, size_t, void *);
-typedef int (_curl_debug_callback2) (CURL *,
+typedef int (*_curl_debug_callback2) (CURL *,
     curl_infotype, char *, size_t, const void *);
-typedef int (_curl_debug_callback3) (CURL *,
+typedef int (*_curl_debug_callback3) (CURL *,
     curl_infotype, const char *, size_t, void *);
-typedef int (_curl_debug_callback4) (CURL *,
+typedef int (*_curl_debug_callback4) (CURL *,
     curl_infotype, const char *, size_t, const void *);
-typedef int (_curl_debug_callback5) (CURL *,
+typedef int (*_curl_debug_callback5) (CURL *,
     curl_infotype, unsigned char *, size_t, void *);
-typedef int (_curl_debug_callback6) (CURL *,
+typedef int (*_curl_debug_callback6) (CURL *,
     curl_infotype, unsigned char *, size_t, const void *);
-typedef int (_curl_debug_callback7) (CURL *,
+typedef int (*_curl_debug_callback7) (CURL *,
     curl_infotype, const unsigned char *, size_t, void *);
-typedef int (_curl_debug_callback8) (CURL *,
+typedef int (*_curl_debug_callback8) (CURL *,
     curl_infotype, const unsigned char *, size_t, const void *);
 
 /* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
 /* this is getting even messier... */
 #define _curl_is_ssl_ctx_cb(expr)                                       \
   (_curl_is_NULL(expr) ||                                                     \
-   __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) ||   \
+   _curl_callback_compatible((expr), curl_ssl_ctx_callback) ||                \
    _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) ||              \
    _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) ||              \
    _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) ||              \
@@ -576,18 +621,19 @@ typedef int (_curl_debug_callback8) (CURL *,
    _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) ||              \
    _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) ||              \
    _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
-typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
-typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
-typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
-typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
+                                            const void *);
 #ifdef HEADER_SSL_H
 /* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
  * this will of course break if we're included before OpenSSL headers...
  */
-typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
-typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
-typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
-typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
+typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
                                            const void *);
 #else
 typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
@@ -599,7 +645,7 @@ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
 /* evaluates to true if expr is of type curl_conv_callback or "similar" */
 #define _curl_is_conv_cb(expr)                                          \
   (_curl_is_NULL(expr) ||                                                     \
-   __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) ||      \
+   _curl_callback_compatible((expr), curl_conv_callback) ||                   \
    _curl_callback_compatible((expr), _curl_conv_callback1) ||                 \
    _curl_callback_compatible((expr), _curl_conv_callback2) ||                 \
    _curl_callback_compatible((expr), _curl_conv_callback3) ||                 \
@@ -612,7 +658,7 @@ typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
 /* evaluates to true if expr is of type curl_seek_callback or "similar" */
 #define _curl_is_seek_cb(expr)                                          \
   (_curl_is_NULL(expr) ||                                                     \
-   __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) ||      \
+   _curl_callback_compatible((expr), curl_seek_callback) ||                   \
    _curl_callback_compatible((expr), _curl_seek_callback1) ||                 \
    _curl_callback_compatible((expr), _curl_seek_callback2))
 typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index 1328cad..19f5800 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -51,7 +51,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
   pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c        \
   openldap.c curl_gethostname.c gopher.c idn_win32.c                    \
   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c      \
-  http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c               \
+  http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c        \
   curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c          \
   x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c
 
@@ -72,7 +72,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   curl_sasl.h curl_multibyte.h hostcheck.h conncache.h                  \
   curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h       \
   x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h           \
-  curl_printf.h system_win32.h
+  curl_printf.h system_win32.h rand.h
 
 LIB_RCFILES = libcurl.rc
 
diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index 2aed94f..11a914f 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -169,7 +169,7 @@ int Curl_resolver_duphandle(void **to, void *from)
   return CURLE_OK;
 }
 
-static void destroy_async_data (struct Curl_async *async);
+static void destroy_async_data(struct Curl_async *async);
 
 /*
  * Cancel all possibly still on-going resolves for this connection.
@@ -184,7 +184,7 @@ void Curl_resolver_cancel(struct connectdata *conn)
 /*
  * destroy_async_data() cleans up async resolver data.
  */
-static void destroy_async_data (struct Curl_async *async)
+static void destroy_async_data(struct Curl_async *async)
 {
   free(async->hostname);
 
@@ -232,7 +232,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
   milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
   if(milli == 0)
     milli += 10;
-  Curl_expire_latest(conn->data, milli);
+  Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME);
 
   return max;
 }
@@ -358,14 +358,21 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
   struct timeval now = Curl_tvnow();
   struct Curl_dns_entry *temp_entry;
 
+  if(entry)
+    *entry = NULL; /* clear on entry */
+
   timeout = Curl_timeleft(data, &now, TRUE);
+  if(timeout < 0) {
+    /* already expired! */
+    connclose(conn, "Timed out before name resolve started");
+    return CURLE_OPERATION_TIMEDOUT;
+  }
   if(!timeout)
     timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
 
   /* Wait for the name resolve query to complete. */
-  for(;;) {
+  while(!result) {
     struct timeval *tvp, tv, store;
-    long timediff;
     int itimeout;
     int timeout_ms;
 
@@ -385,28 +392,30 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
       timeout_ms = 1000;
 
     waitperform(conn, timeout_ms);
-    Curl_resolver_is_resolved(conn, &temp_entry);
+    result = Curl_resolver_is_resolved(conn, &temp_entry);
 
-    if(conn->async.done)
+    if(result || conn->async.done)
       break;
 
-    if(Curl_pgrsUpdate(conn)) {
+    if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
-      timeout = -1; /* trigger the cancel below */
-    }
     else {
       struct timeval now2 = Curl_tvnow();
-      timediff = Curl_tvdiff(now2, now); /* spent time */
-      timeout -= timediff?timediff:1; /* always deduct at least 1 */
+      time_t timediff = Curl_tvdiff(now2, now); /* spent time */
+      if(timediff <= 0)
+        timeout -= 1; /* always deduct at least 1 */
+      else if(timediff > timeout)
+        timeout = -1;
+      else
+        timeout -= (long)timediff;
       now = now2; /* for next loop */
     }
-
-    if(timeout < 0) {
-      /* our timeout, so we cancel the ares operation */
-      ares_cancel((ares_channel)data->state.resolver);
-      break;
-    }
+    if(timeout < 0)
+      result = CURLE_OPERATION_TIMEDOUT;
   }
+  if(result)
+    /* failure, so we cancel the ares operation */
+    ares_cancel((ares_channel)data->state.resolver);
 
   /* Operation complete, if the lookup was successful we now have the entry
      in the cache. */
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 7cce01a..65fa6c5 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -22,6 +22,11 @@
 
 #include "curl_setup.h"
 
+/***********************************************************************
+ * Only for threaded name resolves builds
+ **********************************************************************/
+#ifdef CURLRES_THREADED
+
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -74,11 +79,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-/***********************************************************************
- * Only for threaded name resolves builds
- **********************************************************************/
-#ifdef CURLRES_THREADED
-
 /*
  * Curl_resolver_global_init()
  * Called from curl_global_init() to initialize global resolver environment.
@@ -155,8 +155,8 @@ struct thread_sync_data {
   curl_mutex_t * mtx;
   int done;
 
-  char * hostname;        /* hostname to resolve, Curl_async.hostname
-                             duplicate */
+  char *hostname;        /* hostname to resolve, Curl_async.hostname
+                            duplicate */
   int port;
   int sock_error;
   Curl_addrinfo *res;
@@ -169,7 +169,7 @@ struct thread_sync_data {
 struct thread_data {
   curl_thread_t thread_hnd;
   unsigned int poll_interval;
-  long interval_end;
+  time_t interval_end;
   struct thread_sync_data tsd;
 };
 
@@ -200,7 +200,7 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
 /* Initialize resolver thread synchronization data */
 static
 int init_thread_sync_data(struct thread_data * td,
-                           const char * hostname,
+                           const char *hostname,
                            int port,
                            const struct addrinfo *hints)
 {
@@ -263,7 +263,7 @@ static int getaddrinfo_complete(struct connectdata *conn)
  * For builds without ARES, but with ENABLE_IPV6, create a resolver thread
  * and wait on it.
  */
-static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
+static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
 {
   struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
   struct thread_data *td = tsd->td;
@@ -303,7 +303,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
 /*
  * gethostbyname_thread() resolves a name and then exits.
  */
-static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
+static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
 {
   struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
   struct thread_data *td = tsd->td;
@@ -336,7 +336,7 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
 /*
  * destroy_async_data() cleans up async resolver data and thread handle.
  */
-static void destroy_async_data (struct Curl_async *async)
+static void destroy_async_data(struct Curl_async *async)
 {
   if(async->os_specific) {
     struct thread_data *td = (struct thread_data*) async->os_specific;
@@ -375,14 +375,14 @@ static void destroy_async_data (struct Curl_async *async)
  *
  * Returns FALSE in case of failure, otherwise TRUE.
  */
-static bool init_resolve_thread (struct connectdata *conn,
-                                 const char *hostname, int port,
-                                 const struct addrinfo *hints)
+static bool init_resolve_thread(struct connectdata *conn,
+                                const char *hostname, int port,
+                                const struct addrinfo *hints)
 {
   struct thread_data *td = calloc(1, sizeof(struct thread_data));
   int err = RESOLVER_ENOMEM;
 
-  conn->async.os_specific = (void*) td;
+  conn->async.os_specific = (void *)td;
   if(!td)
     goto err_exit;
 
@@ -525,7 +525,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
   }
   else {
     /* poll for name lookup done with exponential backoff up to 250ms */
-    long elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
+    time_t elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
     if(elapsed < 0)
       elapsed = 0;
 
@@ -540,7 +540,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
       td->poll_interval = 250;
 
     td->interval_end = elapsed + td->poll_interval;
-    Curl_expire(conn->data, td->poll_interval);
+    Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME);
   }
 
   return CURLE_OK;
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index 01b1b44..c79d227 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -5,8 +5,8 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012, 2016, Linus Nielsen Feltzing, <linus at haxx.se>
- * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus at haxx.se>
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at 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
@@ -56,11 +56,7 @@ static CURLcode bundle_create(struct Curl_easy *data,
   (*cb_ptr)->num_connections = 0;
   (*cb_ptr)->multiuse = BUNDLE_UNKNOWN;
 
-  (*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor);
-  if(!(*cb_ptr)->conn_list) {
-    Curl_safefree(*cb_ptr);
-    return CURLE_OUT_OF_MEMORY;
-  }
+  Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor);
   return CURLE_OK;
 }
 
@@ -69,22 +65,18 @@ static void bundle_destroy(struct connectbundle *cb_ptr)
   if(!cb_ptr)
     return;
 
-  if(cb_ptr->conn_list) {
-    Curl_llist_destroy(cb_ptr->conn_list, NULL);
-    cb_ptr->conn_list = NULL;
-  }
+  Curl_llist_destroy(&cb_ptr->conn_list, NULL);
+
   free(cb_ptr);
 }
 
 /* Add a connection to a bundle */
 static CURLcode bundle_add_conn(struct connectbundle *cb_ptr,
-                              struct connectdata *conn)
+                                struct connectdata *conn)
 {
-  if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn))
-    return CURLE_OUT_OF_MEMORY;
-
+  Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn,
+                         &conn->bundle_node);
   conn->bundle = cb_ptr;
-
   cb_ptr->num_connections++;
   return CURLE_OK;
 }
@@ -95,10 +87,10 @@ static int bundle_remove_conn(struct connectbundle *cb_ptr,
 {
   struct curl_llist_element *curr;
 
-  curr = cb_ptr->conn_list->head;
+  curr = cb_ptr->conn_list.head;
   while(curr) {
     if(curr->ptr == conn) {
-      Curl_llist_remove(cb_ptr->conn_list, curr, NULL);
+      Curl_llist_remove(&cb_ptr->conn_list, curr, NULL);
       cb_ptr->num_connections--;
       conn->bundle = NULL;
       return 1; /* we removed a handle */
@@ -127,19 +119,25 @@ void Curl_conncache_destroy(struct conncache *connc)
     Curl_hash_destroy(&connc->hash);
 }
 
-/* returns an allocated key to find a bundle for this connection */
-static char *hashkey(struct connectdata *conn)
+/* creates a key to find a bundle for this connection */
+static void hashkey(struct connectdata *conn, char *buf,
+                    size_t len) /* something like 128 is fine */
 {
   const char *hostname;
 
-  if(conn->bits.proxy)
-    hostname = conn->proxy.name;
+  if(conn->bits.socksproxy)
+    hostname = conn->socks_proxy.host.name;
+  else if(conn->bits.httpproxy)
+    hostname = conn->http_proxy.host.name;
   else if(conn->bits.conn_to_host)
     hostname = conn->conn_to_host.name;
   else
     hostname = conn->host.name;
 
-  return aprintf("%s:%d", hostname, conn->port);
+  DEBUGASSERT(len > 32);
+
+  /* put the number first so that the hostname gets cut off if too long */
+  snprintf(buf, len, "%ld%s", conn->port, hostname);
 }
 
 /* Look up the bundle with all the connections to the same host this
@@ -149,11 +147,9 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
 {
   struct connectbundle *bundle = NULL;
   if(connc) {
-    char *key = hashkey(conn);
-    if(key) {
-      bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
-      free(key);
-    }
+    char key[128];
+    hashkey(conn, key, sizeof(key));
+    bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
   }
 
   return bundle;
@@ -202,21 +198,16 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
 
   bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
   if(!bundle) {
-    char *key;
     int rc;
+    char key[128];
 
     result = bundle_create(data, &new_bundle);
     if(result)
       return result;
 
-    key = hashkey(conn);
-    if(!key) {
-      bundle_destroy(new_bundle);
-      return CURLE_OUT_OF_MEMORY;
-    }
-
+    hashkey(conn, key, sizeof(key));
     rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
-    free(key);
+
     if(!rc) {
       bundle_destroy(new_bundle);
       return CURLE_OUT_OF_MEMORY;
@@ -290,7 +281,7 @@ void Curl_conncache_foreach(struct conncache *connc,
     bundle = he->ptr;
     he = Curl_hash_next_element(&iter);
 
-    curr = bundle->conn_list->head;
+    curr = bundle->conn_list.head;
     while(curr) {
       /* Yes, we need to update curr before calling func(), because func()
          might decide to remove the connection */
@@ -319,7 +310,7 @@ Curl_conncache_find_first_connection(struct conncache *connc)
     struct curl_llist_element *curr;
     bundle = he->ptr;
 
-    curr = bundle->conn_list->head;
+    curr = bundle->conn_list.head;
     if(curr) {
       return curr->ptr;
     }
diff --git a/Utilities/cmcurl/lib/conncache.h b/Utilities/cmcurl/lib/conncache.h
index b1dadf9..f976cfd 100644
--- a/Utilities/cmcurl/lib/conncache.h
+++ b/Utilities/cmcurl/lib/conncache.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2015 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
  * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus at haxx.se>
  *
  * This software is licensed as described in the file COPYING, which
@@ -38,7 +38,7 @@ struct conncache {
 struct connectbundle {
   int multiuse;                 /* supports multi-use */
   size_t num_connections;       /* Number of connections in the bundle */
-  struct curl_llist *conn_list; /* The connectdata members of the bundle */
+  struct curl_llist conn_list;  /* The connectdata members of the bundle */
 };
 
 int Curl_conncache_init(struct conncache *, int size);
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index 3df34d9..d4fd52b 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -179,12 +179,12 @@ singleipconnect(struct connectdata *conn,
  *
  * @unittest: 1303
  */
-long Curl_timeleft(struct Curl_easy *data,
-                   struct timeval *nowp,
-                   bool duringconnect)
+time_t Curl_timeleft(struct Curl_easy *data,
+                     struct timeval *nowp,
+                     bool duringconnect)
 {
   int timeout_set = 0;
-  long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
+  time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
   struct timeval now;
 
   /* if a timeout is set, use the most restrictive one */
@@ -194,7 +194,7 @@ long Curl_timeleft(struct Curl_easy *data,
   if(duringconnect && (data->set.connecttimeout > 0))
     timeout_set |= 2;
 
-  switch (timeout_set) {
+  switch(timeout_set) {
   case 1:
     timeout_ms = data->set.timeout;
     break;
@@ -601,26 +601,28 @@ void Curl_persistconninfo(struct connectdata *conn)
 {
   memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
   memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
+  conn->data->info.conn_scheme = conn->handler->scheme;
+  conn->data->info.conn_protocol = conn->handler->protocol;
   conn->data->info.conn_primary_port = conn->primary_port;
   conn->data->info.conn_local_port = conn->local_port;
 }
 
 /* retrieves ip address and port from a sockaddr structure */
-static bool getaddressinfo(struct sockaddr* sa, char* addr,
-                           long* port)
+static bool getaddressinfo(struct sockaddr *sa, char *addr,
+                           long *port)
 {
   unsigned short us_port;
-  struct sockaddr_in* si = NULL;
+  struct sockaddr_in *si = NULL;
 #ifdef ENABLE_IPV6
-  struct sockaddr_in6* si6 = NULL;
+  struct sockaddr_in6 *si6 = NULL;
 #endif
 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
-  struct sockaddr_un* su = NULL;
+  struct sockaddr_un *su = NULL;
 #endif
 
-  switch (sa->sa_family) {
+  switch(sa->sa_family) {
     case AF_INET:
-      si = (struct sockaddr_in*)(void*) sa;
+      si = (struct sockaddr_in *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
                         addr, MAX_IPADR_LEN)) {
         us_port = ntohs(si->sin_port);
@@ -630,7 +632,7 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr,
       break;
 #ifdef ENABLE_IPV6
     case AF_INET6:
-      si6 = (struct sockaddr_in6*)(void*) sa;
+      si6 = (struct sockaddr_in6 *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
                         addr, MAX_IPADR_LEN)) {
         us_port = ntohs(si6->sin6_port);
@@ -722,7 +724,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 {
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_OK;
-  long allow;
+  time_t allow;
   int error = 0;
   struct timeval now;
   int rc;
@@ -808,8 +810,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 
         return CURLE_OK;
       }
-      else
-        infof(data, "Connection failed\n");
+      infof(data, "Connection failed\n");
     }
     else if(rc & CURL_CSELECT_ERR)
       (void)verifyconnect(conn->tempsock[i], &error);
@@ -843,7 +844,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
   if(result) {
     /* no more addresses to try */
 
-    const char* hostname;
+    const char *hostname;
 
     /* if the first address family runs out of addresses to try before
        the happy eyeball timeout, go ahead and try the next family now */
@@ -853,8 +854,10 @@ CURLcode Curl_is_connected(struct connectdata *conn,
         return result;
     }
 
-    if(conn->bits.proxy)
-      hostname = conn->proxy.name;
+    if(conn->bits.socksproxy)
+      hostname = conn->socks_proxy.host.name;
+    else if(conn->bits.httpproxy)
+      hostname = conn->http_proxy.host.name;
     else if(conn->bits.conn_to_host)
       hostname = conn->conn_to_host.name;
     else
@@ -1067,7 +1070,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
 
   conn->connecttime = Curl_tvnow();
   if(conn->num_addr > 1)
-    Curl_expire_latest(data, conn->timeoutms_per_addr);
+    Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
 
   /* Connect TCP sockets, bind UDP */
   if(!isconnected && (conn->socktype == SOCK_STREAM)) {
@@ -1153,7 +1156,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
   struct timeval before = Curl_tvnow();
   CURLcode result = CURLE_COULDNT_CONNECT;
 
-  long timeout_ms = Curl_timeleft(data, &before, TRUE);
+  time_t timeout_ms = Curl_timeleft(data, &before, TRUE);
 
   if(timeout_ms < 0) {
     /* a precaution, no need to continue if time already is up */
@@ -1166,7 +1169,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
   conn->tempaddr[1] = NULL;
   conn->tempsock[0] = CURL_SOCKET_BAD;
   conn->tempsock[1] = CURL_SOCKET_BAD;
-  Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
+  Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
 
   /* Max time for the next connection attempt */
   conn->timeoutms_per_addr =
@@ -1243,24 +1246,6 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
       /* only store this if the caller cares for it */
       *connp = c;
     sockfd = c->sock[FIRSTSOCKET];
-    /* we have a socket connected, let's determine if the server shut down */
-    /* determine if ssl */
-    if(c->ssl[FIRSTSOCKET].use) {
-      /* use the SSL context */
-      if(!Curl_ssl_check_cxn(c))
-        return CURL_SOCKET_BAD;   /* FIN received */
-    }
-/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
-#ifdef MSG_PEEK
-    else if(sockfd != CURL_SOCKET_BAD) {
-      /* use the socket */
-      char buf;
-      if(recv((RECV_TYPE_ARG1)sockfd, (RECV_TYPE_ARG2)&buf,
-              (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
-        return CURL_SOCKET_BAD;   /* FIN received */
-      }
-    }
-#endif
   }
   else
     return CURL_SOCKET_BAD;
@@ -1269,6 +1254,33 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
 }
 
 /*
+ * Check if a connection seems to be alive.
+ */
+bool Curl_connalive(struct connectdata *conn)
+{
+  /* First determine if ssl */
+  if(conn->ssl[FIRSTSOCKET].use) {
+    /* use the SSL context */
+    if(!Curl_ssl_check_cxn(conn))
+      return false;   /* FIN received */
+  }
+/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
+#ifdef MSG_PEEK
+  else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
+    return false;
+  else {
+    /* use the socket */
+    char buf;
+    if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
+            (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
+      return false;   /* FIN received */
+    }
+  }
+#endif
+  return true;
+}
+
+/*
  * Close a socket.
  *
  * 'conn' can be NULL, beware!
@@ -1373,7 +1385,7 @@ CURLcode Curl_socket(struct connectdata *conn,
  */
 void Curl_conncontrol(struct connectdata *conn,
                       int ctrl /* see defines in header */
-#ifdef DEBUGBUILD
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
                       , const char *reason
 #endif
   )
@@ -1391,3 +1403,16 @@ void Curl_conncontrol(struct connectdata *conn,
                                    should assign this bit */
   }
 }
+
+/* Data received can be cached at various levels, so check them all here. */
+bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
+{
+  int readable;
+
+  if(Curl_ssl_data_pending(conn, sockindex) ||
+     Curl_recv_has_postponed_data(conn, sockindex))
+    return true;
+
+  readable = SOCKET_READABLE(conn->sock[sockindex], 0);
+  return (readable > 0 && (readable & CURL_CSELECT_IN));
+}
diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h
index a7cbc9b..44bdb10 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -35,9 +35,9 @@ CURLcode Curl_connecthost(struct connectdata *conn,
 
 /* generic function that returns how much time there's left to run, according
    to the timeouts set */
-long Curl_timeleft(struct Curl_easy *data,
-                   struct timeval *nowp,
-                   bool duringconnect);
+time_t Curl_timeleft(struct Curl_easy *data,
+                     struct timeval *nowp,
+                     bool duringconnect);
 
 #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
 #define HAPPY_EYEBALLS_TIMEOUT     200 /* milliseconds to wait between
@@ -52,6 +52,11 @@ long Curl_timeleft(struct Curl_easy *data,
 curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
                                   struct connectdata **connp);
 
+/*
+ * Check if a connection seems to be alive.
+ */
+bool Curl_connalive(struct connectdata *conn);
+
 #ifdef USE_WINSOCK
 /* When you run a program that uses the Windows Sockets API, you may
    experience slow performance when you copy data to a TCP server.
@@ -122,19 +127,21 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd);
 
 void Curl_conncontrol(struct connectdata *conn,
                       int closeit
-#ifdef DEBUGBUILD
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
                       , const char *reason
 #endif
   );
 
-#ifdef DEBUGBUILD
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
 #define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM, y)
 #define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y)
 #define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP, y)
-#else /* if !CURLDEBUG */
+#else /* if !DEBUGBUILD || CURL_DISABLE_VERBOSE_STRINGS */
 #define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM)
 #define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION)
 #define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP)
 #endif
 
+bool Curl_conn_data_pending(struct connectdata *conn, int sockindex);
+
 #endif /* HEADER_CURL_CONNECT_H */
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index fa36aca..652ed97 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/lib/content_encoding.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -28,8 +28,8 @@
 #include <curl/curl.h>
 #include "sendf.h"
 #include "content_encoding.h"
+#include "strdup.h"
 #include "curl_memory.h"
-
 #include "memdebug.h"
 
 /* Comment this out if zlib is always going to be at least ver. 1.2.0.4
@@ -69,11 +69,11 @@ process_zlib_error(struct connectdata *conn, z_stream *z)
 {
   struct Curl_easy *data = conn->data;
   if(z->msg)
-    failf (data, "Error while processing content unencoding: %s",
-           z->msg);
+    failf(data, "Error while processing content unencoding: %s",
+          z->msg);
   else
-    failf (data, "Error while processing content unencoding: "
-           "Unknown failure within decompression software.");
+    failf(data, "Error while processing content unencoding: "
+          "Unknown failure within decompression software.");
 
   return CURLE_BAD_CONTENT_ENCODING;
 }
@@ -130,8 +130,7 @@ inflate_stream(struct connectdata *conn,
         free(decomp);
         if(inflateEnd(z) == Z_OK)
           return exit_zlib(z, &k->zlib_init, result);
-        else
-          return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
+        return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
       }
 
       /* Done with these bytes, exit */
@@ -314,7 +313,7 @@ Curl_unencode_gzip_write(struct connectdata *conn,
 #ifndef OLD_ZLIB_SUPPORT
   /* Support for old zlib versions is compiled away and we are running with
      an old version, so return an error. */
-  return exit_zlib(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND);
+  return exit_zlib(z, &k->zlib_init, CURLE_WRITE_ERROR);
 
 #else
   /* This next mess is to get around the potential case where there isn't
@@ -327,14 +326,14 @@ Curl_unencode_gzip_write(struct connectdata *conn,
    * can handle the gzip header themselves.
    */
 
-  switch (k->zlib_init) {
+  switch(k->zlib_init) {
   /* Skip over gzip header? */
   case ZLIB_INIT:
   {
     /* Initial call state */
     ssize_t hlen;
 
-    switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
+    switch(check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
     case GZIP_OK:
       z->next_in = (Bytef *)k->str + hlen;
       z->avail_in = (uInt)(nread - hlen);
@@ -371,18 +370,15 @@ Curl_unencode_gzip_write(struct connectdata *conn,
   {
     /* Need more gzip header data state */
     ssize_t hlen;
-    unsigned char *oldblock = z->next_in;
-
     z->avail_in += (uInt)nread;
-    z->next_in = realloc(z->next_in, z->avail_in);
+    z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
     if(z->next_in == NULL) {
-      free(oldblock);
       return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
     }
     /* Append the new block of data to the previous one */
     memcpy(z->next_in + z->avail_in - nread, k->str, nread);
 
-    switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) {
+    switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) {
     case GZIP_OK:
       /* This is the zlib stream data */
       free(z->next_in);
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 1b3e645..6b678ae 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -146,12 +146,12 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
  * matching cookie path and url path
  * RFC6265 5.1.4 Paths and Path-Match
  */
-static bool pathmatch(const char* cookie_path, const char* request_uri)
+static bool pathmatch(const char *cookie_path, const char *request_uri)
 {
   size_t cookie_path_len;
   size_t uri_path_len;
-  char* uri_path = NULL;
-  char* pos;
+  char *uri_path = NULL;
+  char *pos;
   bool ret = FALSE;
 
   /* cookie_path must not have last '/' separator. ex: /sample */
@@ -492,7 +492,6 @@ Curl_cookie_add(struct Curl_easy *data,
         }
         else if(strcasecompare("domain", name)) {
           bool is_ip;
-          const char *dotp;
 
           /* Now, we make sure that our host is within the given domain,
              or the given domain is not valid and thus cannot be set. */
@@ -500,12 +499,22 @@ Curl_cookie_add(struct Curl_easy *data,
           if('.' == whatptr[0])
             whatptr++; /* ignore preceding dot */
 
-          is_ip = isip(domain ? domain : whatptr);
+#ifndef USE_LIBPSL
+          /*
+           * Without PSL we don't know when the incoming cookie is set on a
+           * TLD or otherwise "protected" suffix. To reduce risk, we require a
+           * dot OR the exact host name being "localhost".
+           */
+          {
+            const char *dotp;
+            /* check for more dots */
+            dotp = strchr(whatptr, '.');
+            if(!dotp && !strcasecompare("localhost", whatptr))
+              domain=":";
+          }
+#endif
 
-          /* check for more dots */
-          dotp = strchr(whatptr, '.');
-          if(!dotp)
-            domain=":";
+          is_ip = isip(domain ? domain : whatptr);
 
           if(!domain
              || (is_ip && !strcmp(whatptr, domain))
@@ -798,8 +807,8 @@ Curl_cookie_add(struct Curl_easy *data,
   /* Check if the domain is a Public Suffix and if yes, ignore the cookie.
      This needs a libpsl compiled with builtin data. */
   if(domain && co->domain && !isip(co->domain)) {
-    if(((psl = psl_builtin()) != NULL)
-        && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
+    psl = psl_builtin();
+    if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
       infof(data,
             "cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n",
             co->name, domain, co->domain);
@@ -920,9 +929,8 @@ static char *get_line(char *buf, int len, FILE *input)
         }
         return b;
       }
-      else
-        /* read a partial, discard the next piece that ends with newline */
-        partial = TRUE;
+      /* read a partial, discard the next piece that ends with newline */
+      partial = TRUE;
     }
     else
       break;
@@ -1055,16 +1063,16 @@ static int cookie_sort(const void *p1, const void *p2)
 #define CLONE(field)                     \
   do {                                   \
     if(src->field) {                     \
-      dup->field = strdup(src->field);   \
-      if(!dup->field)                    \
+      d->field = strdup(src->field);     \
+      if(!d->field)                      \
         goto fail;                       \
     }                                    \
   } while(0)
 
 static struct Cookie *dup_cookie(struct Cookie *src)
 {
-  struct Cookie *dup = calloc(sizeof(struct Cookie), 1);
-  if(dup) {
+  struct Cookie *d = calloc(sizeof(struct Cookie), 1);
+  if(d) {
     CLONE(expirestr);
     CLONE(domain);
     CLONE(path);
@@ -1073,16 +1081,16 @@ static struct Cookie *dup_cookie(struct Cookie *src)
     CLONE(value);
     CLONE(maxage);
     CLONE(version);
-    dup->expires = src->expires;
-    dup->tailmatch = src->tailmatch;
-    dup->secure = src->secure;
-    dup->livecookie = src->livecookie;
-    dup->httponly = src->httponly;
+    d->expires = src->expires;
+    d->tailmatch = src->tailmatch;
+    d->secure = src->secure;
+    d->livecookie = src->livecookie;
+    d->httponly = src->httponly;
   }
-  return dup;
+  return d;
 
   fail:
-  freecookie(dup);
+  freecookie(d);
   return NULL;
 }
 
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 35eb2dd..1adf319 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -47,6 +47,8 @@
 #  define in_addr_t unsigned long
 #endif
 
+#include <stddef.h>
+
 #include "curl_addrinfo.h"
 #include "inet_pton.h"
 #include "warnless.h"
@@ -146,7 +148,8 @@ Curl_getaddrinfo_ex(const char *nodename,
     if((size_t)ai->ai_addrlen < ss_size)
       continue;
 
-    if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) {
+    ca = malloc(sizeof(Curl_addrinfo));
+    if(!ca) {
       error = EAI_MEMORY;
       break;
     }
@@ -163,7 +166,8 @@ Curl_getaddrinfo_ex(const char *nodename,
     ca->ai_canonname = NULL;
     ca->ai_next      = NULL;
 
-    if((ca->ai_addr = malloc(ss_size)) == NULL) {
+    ca->ai_addr = malloc(ss_size);
+    if(!ca->ai_addr) {
       error = EAI_MEMORY;
       free(ca);
       break;
@@ -171,7 +175,8 @@ Curl_getaddrinfo_ex(const char *nodename,
     memcpy(ca->ai_addr, ai->ai_addr, ss_size);
 
     if(ai->ai_canonname != NULL) {
-      if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) {
+      ca->ai_canonname = strdup(ai->ai_canonname);
+      if(!ca->ai_canonname) {
         error = EAI_MEMORY;
         free(ca->ai_addr);
         free(ca);
@@ -286,21 +291,24 @@ Curl_he2ai(const struct hostent *he, int port)
     size_t ss_size;
 #ifdef ENABLE_IPV6
     if(he->h_addrtype == AF_INET6)
-      ss_size = sizeof (struct sockaddr_in6);
+      ss_size = sizeof(struct sockaddr_in6);
     else
 #endif
-      ss_size = sizeof (struct sockaddr_in);
+      ss_size = sizeof(struct sockaddr_in);
 
-    if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) {
+    ai = calloc(1, sizeof(Curl_addrinfo));
+    if(!ai) {
       result = CURLE_OUT_OF_MEMORY;
       break;
     }
-    if((ai->ai_canonname = strdup(he->h_name)) == NULL) {
+    ai->ai_canonname = strdup(he->h_name);
+    if(!ai->ai_canonname) {
       result = CURLE_OUT_OF_MEMORY;
       free(ai);
       break;
     }
-    if((ai->ai_addr = calloc(1, ss_size)) == NULL) {
+    ai->ai_addr = calloc(1, ss_size);
+    if(!ai->ai_addr) {
       result = CURLE_OUT_OF_MEMORY;
       free(ai->ai_canonname);
       free(ai);
@@ -325,7 +333,7 @@ Curl_he2ai(const struct hostent *he, int port)
 
     /* leave the rest of the struct filled with zero */
 
-    switch (ai->ai_family) {
+    switch(ai->ai_family) {
     case AF_INET:
       addr = (void *)ai->ai_addr; /* storage area for this info */
 
@@ -461,7 +469,7 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
     /* This is a dotted IP address 123.123.123.123-style */
     return Curl_ip2addr(AF_INET, &in, address, port);
 #ifdef ENABLE_IPV6
-  else {
+  {
     struct in6_addr in6;
     if(Curl_inet_pton(AF_INET6, address, &in6) > 0)
       /* This is a dotted IPv6 address ::1-style */
@@ -475,34 +483,48 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
 /**
  * Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo
  * struct initialized with this path.
+ * Set '*longpath' to TRUE if the error is a too long path.
  */
-Curl_addrinfo *Curl_unix2addr(const char *path)
+Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
 {
   Curl_addrinfo *ai;
   struct sockaddr_un *sa_un;
   size_t path_len;
 
+  *longpath = FALSE;
+
   ai = calloc(1, sizeof(Curl_addrinfo));
   if(!ai)
     return NULL;
-  if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) {
+  ai->ai_addr = calloc(1, sizeof(struct sockaddr_un));
+  if(!ai->ai_addr) {
     free(ai);
     return NULL;
   }
+
+  sa_un = (void *) ai->ai_addr;
+  sa_un->sun_family = AF_UNIX;
+
   /* sun_path must be able to store the NUL-terminated path */
-  path_len = strlen(path);
-  if(path_len >= sizeof(sa_un->sun_path)) {
+  path_len = strlen(path) + 1;
+  if(path_len > sizeof(sa_un->sun_path)) {
     free(ai->ai_addr);
     free(ai);
+    *longpath = TRUE;
     return NULL;
   }
 
   ai->ai_family = AF_UNIX;
   ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */
-  ai->ai_addrlen = (curl_socklen_t) sizeof(struct sockaddr_un);
-  sa_un = (void *) ai->ai_addr;
-  sa_un->sun_family = AF_UNIX;
-  memcpy(sa_un->sun_path, path, path_len + 1); /* copy NUL byte */
+  ai->ai_addrlen = (curl_socklen_t)
+    ((offsetof(struct sockaddr_un, sun_path) + path_len) & 0x7FFFFFFF);
+
+  /* Abstract Unix domain socket have NULL prefix instead of suffix */
+  if(abstract)
+    memcpy(sa_un->sun_path + 1, path, path_len - 1);
+  else
+    memcpy(sa_un->sun_path, path, path_len); /* copy NUL byte */
+
   return ai;
 }
 #endif
@@ -576,7 +598,7 @@ void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port)
   struct sockaddr_in6 *addr6;
 #endif
   for(ca = addrinfo; ca != NULL; ca = ca->ai_next) {
-    switch (ca->ai_family) {
+    switch(ca->ai_family) {
     case AF_INET:
       addr = (void *)ca->ai_addr; /* storage area for this info */
       addr->sin_port = htons((unsigned short)port);
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.h b/Utilities/cmcurl/lib/curl_addrinfo.h
index 1a681e6..8f6f3d1 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.h
+++ b/Utilities/cmcurl/lib/curl_addrinfo.h
@@ -80,7 +80,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
 Curl_addrinfo *Curl_str2addr(char *dotted, int port);
 
 #ifdef USE_UNIX_SOCKETS
-Curl_addrinfo *Curl_unix2addr(const char *path);
+Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract);
 #endif
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index 13f69b2..f9d54b4 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -512,6 +512,15 @@
 /* Define to 1 if you have the send function. */
 #cmakedefine HAVE_SEND 1
 
+/* Define to 1 if you have the 'fsetxattr' function. */
+#cmakedefine HAVE_FSETXATTR 1
+
+/* fsetxattr() takes 5 args */
+#cmakedefine HAVE_FSETXATTR_5 1
+
+/* fsetxattr() takes 6 args */
+#cmakedefine HAVE_FSETXATTR_6 1
+
 /* Define to 1 if you have the <setjmp.h> header file. */
 #cmakedefine HAVE_SETJMP_H 1
 
@@ -912,6 +921,9 @@
 /* if PolarSSL is enabled */
 #cmakedefine USE_POLARSSL 1
 
+/* if DarwinSSL is enabled */
+#cmakedefine USE_DARWINSSL 1
+
 /* if mbedTLS is enabled */
 #cmakedefine USE_MBEDTLS 1
 
diff --git a/Utilities/cmcurl/lib/curl_des.c b/Utilities/cmcurl/lib/curl_des.c
index 421c9f7..b123a00 100644
--- a/Utilities/cmcurl/lib/curl_des.c
+++ b/Utilities/cmcurl/lib/curl_des.c
@@ -34,7 +34,7 @@
  *
  * The function is a port of the Java based oddParity() function over at:
  *
- * http://davenport.sourceforge.net/ntlm.html
+ * https://davenport.sourceforge.io/ntlm.html
  *
  * Parameters:
  *
diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c
index 76deca6..c25db49 100644
--- a/Utilities/cmcurl/lib/curl_endian.c
+++ b/Utilities/cmcurl/lib/curl_endian.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -37,7 +37,7 @@
  *
  * Returns the integer.
  */
-unsigned short Curl_read16_le(unsigned char *buf)
+unsigned short Curl_read16_le(const unsigned char *buf)
 {
   return (unsigned short)(((unsigned short)buf[0]) |
                           ((unsigned short)buf[1] << 8));
@@ -56,50 +56,12 @@ unsigned short Curl_read16_le(unsigned char *buf)
  *
  * Returns the integer.
  */
-unsigned int Curl_read32_le(unsigned char *buf)
+unsigned int Curl_read32_le(const unsigned char *buf)
 {
   return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
          ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
 }
 
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
-/*
- * Curl_read64_le()
- *
- * This function converts a 64-bit integer from the little endian format, as
- * used in the incoming package to whatever endian format we're using
- * natively.
- *
- * Parameters:
- *
- * buf      [in]     - A pointer to a 8 byte buffer.
- *
- * Returns the integer.
- */
-#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_le(unsigned char *buf)
-{
-  return ((unsigned long long)buf[0]) |
-         ((unsigned long long)buf[1] << 8) |
-         ((unsigned long long)buf[2] << 16) |
-         ((unsigned long long)buf[3] << 24) |
-         ((unsigned long long)buf[4] << 32) |
-         ((unsigned long long)buf[5] << 40) |
-         ((unsigned long long)buf[6] << 48) |
-         ((unsigned long long)buf[7] << 56);
-}
-#else
-unsigned __int64 Curl_read64_le(unsigned char *buf)
-{
-  return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) |
-         ((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) |
-         ((unsigned __int64)buf[4] << 32) | ((unsigned __int64)buf[5] << 40) |
-         ((unsigned __int64)buf[6] << 48) | ((unsigned __int64)buf[7] << 56);
-}
-#endif
-
-#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
-
 /*
  * Curl_read16_be()
  *
@@ -113,87 +75,13 @@ unsigned __int64 Curl_read64_le(unsigned char *buf)
  *
  * Returns the integer.
  */
-unsigned short Curl_read16_be(unsigned char *buf)
+unsigned short Curl_read16_be(const unsigned char *buf)
 {
   return (unsigned short)(((unsigned short)buf[0] << 8) |
                           ((unsigned short)buf[1]));
 }
 
 /*
- * Curl_read32_be()
- *
- * This function converts a 32-bit integer from the big endian format, as
- * used in the incoming package to whatever endian format we're using
- * natively.
- *
- * Parameters:
- *
- * buf      [in]     - A pointer to a 4 byte buffer.
- *
- * Returns the integer.
- */
-unsigned int Curl_read32_be(unsigned char *buf)
-{
-  return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) |
-         ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]);
-}
-
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
-/*
- * Curl_read64_be()
- *
- * This function converts a 64-bit integer from the big endian format, as
- * used in the incoming package to whatever endian format we're using
- * natively.
- *
- * Parameters:
- *
- * buf      [in]     - A pointer to a 8 byte buffer.
- *
- * Returns the integer.
- */
-#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_be(unsigned char *buf)
-{
-  return ((unsigned long long)buf[0] << 56) |
-         ((unsigned long long)buf[1] << 48) |
-         ((unsigned long long)buf[2] << 40) |
-         ((unsigned long long)buf[3] << 32) |
-         ((unsigned long long)buf[4] << 24) |
-         ((unsigned long long)buf[5] << 16) |
-         ((unsigned long long)buf[6] << 8) |
-         ((unsigned long long)buf[7]);
-}
-#else
-unsigned __int64 Curl_read64_be(unsigned char *buf)
-{
-  return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) |
-         ((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) |
-         ((unsigned __int64)buf[4] << 24) | ((unsigned __int64)buf[5] << 16) |
-         ((unsigned __int64)buf[6] << 8) | ((unsigned __int64)buf[7]);
-}
-#endif
-
-#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
-
-/*
- * Curl_write16_le()
- *
- * This function converts a 16-bit integer from the native endian format,
- * to little endian format ready for sending down the wire.
- *
- * Parameters:
- *
- * value    [in]     - The 16-bit integer value.
- * buffer   [in]     - A pointer to the output buffer.
- */
-void Curl_write16_le(const short value, unsigned char *buffer)
-{
-  buffer[0] = (char)(value & 0x00FF);
-  buffer[1] = (char)((value & 0xFF00) >> 8);
-}
-
-/*
  * Curl_write32_le()
  *
  * This function converts a 32-bit integer from the native endian format,
diff --git a/Utilities/cmcurl/lib/curl_endian.h b/Utilities/cmcurl/lib/curl_endian.h
index df8398c..4f345a6 100644
--- a/Utilities/cmcurl/lib/curl_endian.h
+++ b/Utilities/cmcurl/lib/curl_endian.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -23,37 +23,13 @@
  ***************************************************************************/
 
 /* Converts a 16-bit integer from little endian */
-unsigned short Curl_read16_le(unsigned char *buf);
+unsigned short Curl_read16_le(const unsigned char *buf);
 
 /* Converts a 32-bit integer from little endian */
-unsigned int Curl_read32_le(unsigned char *buf);
-
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
-/* Converts a 64-bit integer from little endian */
-#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_le(unsigned char *buf);
-#else
-unsigned __int64 Curl_read64_le(unsigned char *buf);
-#endif
-#endif
+unsigned int Curl_read32_le(const unsigned char *buf);
 
 /* Converts a 16-bit integer from big endian */
-unsigned short Curl_read16_be(unsigned char *buf);
-
-/* Converts a 32-bit integer from big endian */
-unsigned int Curl_read32_be(unsigned char *buf);
-
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
-/* Converts a 64-bit integer from big endian */
-#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_be(unsigned char *buf);
-#else
-unsigned __int64 Curl_read64_be(unsigned char *buf);
-#endif
-#endif
-
-/* Converts a 16-bit integer to little endian */
-void Curl_write16_le(const short value, unsigned char *buffer);
+unsigned short Curl_read16_be(const unsigned char *buf);
 
 /* Converts a 32-bit integer to little endian */
 void Curl_write32_le(const int value, unsigned char *buffer);
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.c b/Utilities/cmcurl/lib/curl_fnmatch.c
index e8108bb..46d3ada 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.c
+++ b/Utilities/cmcurl/lib/curl_fnmatch.c
@@ -145,8 +145,7 @@ static int setcharset(unsigned char **p, unsigned char *charset)
       else if(c == ']') {
         if(something_found)
           return SETCHARSET_OK;
-        else
-          something_found = TRUE;
+        something_found = TRUE;
         state = CURLFNM_SCHS_RIGHTBR;
         charset[c] = 1;
         (*p)++;
@@ -244,7 +243,7 @@ static int setcharset(unsigned char **p, unsigned char *charset)
       if(c == ']') {
         return SETCHARSET_OK;
       }
-      else if(c == '\\') {
+      if(c == '\\') {
         c = *(++(*p));
         if(ISPRINT(c)) {
           charset[c] = 1;
@@ -345,8 +344,7 @@ static int loop(const unsigned char *pattern, const unsigned char *string)
       else if(*p == '\0') {
         if(*s == '\0')
           return CURL_FNMATCH_MATCH;
-        else
-          return CURL_FNMATCH_NOMATCH;
+        return CURL_FNMATCH_NOMATCH;
       }
       else if(*p == '\\') {
         state = CURLFNM_LOOP_BACKSLASH;
diff --git a/Utilities/cmcurl/lib/curl_gethostname.c b/Utilities/cmcurl/lib/curl_gethostname.c
index 2591fd8..8337c72 100644
--- a/Utilities/cmcurl/lib/curl_gethostname.c
+++ b/Utilities/cmcurl/lib/curl_gethostname.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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,8 +48,8 @@
  * For libcurl static library release builds no overriding takes place.
  */
 
-int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
-
+int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen)
+{
 #ifndef HAVE_GETHOSTNAME
 
   /* Allow compilation and return failure when unavailable */
@@ -59,7 +59,7 @@ int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
 
 #else
   int err;
-  char* dot;
+  char *dot;
 
 #ifdef DEBUGBUILD
 
diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index bf7c766..83f3fa0 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/lib/curl_gssapi.c
@@ -94,7 +94,7 @@ static size_t display_gss_error(OM_uint32 status, int type,
     if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
       len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
                       "%.*s. ", (int)status_string.length,
-                      (char*)status_string.value);
+                      (char *)status_string.value);
     }
     gss_release_buffer(&min_stat, &status_string);
   } while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
diff --git a/Utilities/cmcurl/lib/curl_hmac.h b/Utilities/cmcurl/lib/curl_hmac.h
index 41703b4..756dc9e 100644
--- a/Utilities/cmcurl/lib/curl_hmac.h
+++ b/Utilities/cmcurl/lib/curl_hmac.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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,11 +24,11 @@
 
 #ifndef CURL_DISABLE_CRYPTO_AUTH
 
-typedef void    (* HMAC_hinit_func)(void * context);
-typedef void    (* HMAC_hupdate_func)(void * context,
-                                      const unsigned char * data,
+typedef void    (* HMAC_hinit_func)(void *context);
+typedef void    (* HMAC_hupdate_func)(void *context,
+                                      const unsigned char *data,
                                       unsigned int len);
-typedef void    (* HMAC_hfinal_func)(unsigned char * result, void * context);
+typedef void    (* HMAC_hfinal_func)(unsigned char *result, void *context);
 
 
 /* Per-hash function HMAC parameters. */
@@ -46,21 +46,21 @@ typedef struct {
 /* HMAC computation context. */
 
 typedef struct {
-  const HMAC_params *   hmac_hash;      /* Hash function definition. */
-  void *                hmac_hashctxt1; /* Hash function context 1. */
-  void *                hmac_hashctxt2; /* Hash function context 2. */
+  const HMAC_params *hmac_hash; /* Hash function definition. */
+  void *hmac_hashctxt1;         /* Hash function context 1. */
+  void *hmac_hashctxt2;         /* Hash function context 2. */
 } HMAC_context;
 
 
 /* Prototypes. */
 
-HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams,
-                              const unsigned char * key,
+HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams,
+                              const unsigned char *key,
                               unsigned int keylen);
-int Curl_HMAC_update(HMAC_context * context,
-                     const unsigned char * data,
+int Curl_HMAC_update(HMAC_context *context,
+                     const unsigned char *data,
                      unsigned int len);
-int Curl_HMAC_final(HMAC_context * context, unsigned char * result);
+int Curl_HMAC_final(HMAC_context *context, unsigned char *result);
 
 #endif
 
diff --git a/Utilities/cmcurl/lib/curl_md4.h b/Utilities/cmcurl/lib/curl_md4.h
index 8c26d12..e069041 100644
--- a/Utilities/cmcurl/lib/curl_md4.h
+++ b/Utilities/cmcurl/lib/curl_md4.h
@@ -24,12 +24,12 @@
 
 #include "curl_setup.h"
 
-/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
- * that we have a local implementation of it */
-#if defined(USE_NSS) || defined(USE_OS400CRYPTO)
+#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+    (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
 
 void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
 
-#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */
+#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+    (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
 
 #endif /* HEADER_CURL_MD4_H */
diff --git a/Utilities/cmcurl/lib/curl_memory.h b/Utilities/cmcurl/lib/curl_memory.h
index 6f792ff..fccf468 100644
--- a/Utilities/cmcurl/lib/curl_memory.h
+++ b/Utilities/cmcurl/lib/curl_memory.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -70,7 +70,7 @@
  *
  * Programs and libraries in 'tests' subdirectories have specific
  * purposes and needs, and as such each one will use whatever fits
- * best, depending additionally wether it links with libcurl or not.
+ * best, depending additionally whether it links with libcurl or not.
  *
  * Caveat emptor. Proper curlx_* separation is a work in progress
  * the same as CURLX_NO_MEMORY_CALLBACKS usage, some adjustments may
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index 812a073..aea5452 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -27,7 +27,7 @@
 /*
  * NTLM details:
  *
- * http://davenport.sourceforge.net/ntlm.html
+ * https://davenport.sourceforge.io/ntlm.html
  * https://www.innovation.ch/java/ntlm.html
  */
 
@@ -80,6 +80,9 @@
 
 #  include <mbedtls/des.h>
 #  include <mbedtls/md4.h>
+#  if !defined(MBEDTLS_MD4_C)
+#    include "curl_md4.h"
+#  endif
 
 #elif defined(USE_NSS)
 
@@ -501,7 +504,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
 static void ascii_to_unicode_le(unsigned char *dest, const char *src,
                                 size_t srclen)
 {
@@ -512,14 +515,14 @@ static void ascii_to_unicode_le(unsigned char *dest, const char *src,
   }
 }
 
-#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
+#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
 
 static void ascii_uppercase_to_unicode_le(unsigned char *dest,
                                           const char *src, size_t srclen)
 {
   size_t i;
   for(i = 0; i < srclen; i++) {
-    dest[2 * i] = (unsigned char)(toupper(src[i]));
+    dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i]));
     dest[2 * i + 1] = '\0';
   }
 }
@@ -566,12 +569,13 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
     gcry_md_hd_t MD4pw;
     gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
     gcry_md_write(MD4pw, pw, 2 * len);
-    memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
+    memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH);
     gcry_md_close(MD4pw);
+#elif defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+    (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
+    Curl_md4it(ntbuffer, pw, 2 * len);
 #elif defined(USE_MBEDTLS)
     mbedtls_md4(pw, 2 * len, ntbuffer);
-#elif defined(USE_NSS) || defined(USE_OS400CRYPTO)
-    Curl_md4it(ntbuffer, pw, 2 * len);
 #elif defined(USE_DARWINSSL)
     (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
 #elif defined(USE_WIN32_CRYPTO)
@@ -597,7 +601,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
+#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
 
 /* This returns the HMAC MD5 digest */
 CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
@@ -715,8 +719,10 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
 
   /* Create the BLOB structure */
   snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
-           NTLMv2_BLOB_SIGNATURE
+           "%c%c%c%c"   /* NTLMv2_BLOB_SIGNATURE */
            "%c%c%c%c",  /* Reserved = 0 */
+           NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
+           NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
            0, 0, 0, 0);
 
   Curl_write64_le(tw, ptr + 24);
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.h b/Utilities/cmcurl/lib/curl_ntlm_core.h
index c5f90e7..4a83d40 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.h
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.h
@@ -33,31 +33,26 @@
       !defined(HEADER_SSL_H) && !defined(HEADER_MD5_H)
 #    error "curl_ntlm_core.h shall not be included before OpenSSL headers."
 #  endif
-#  ifdef OPENSSL_NO_MD4
-#    define USE_NTRESPONSES 0
-#    define USE_NTLM2SESSION 0
-#    define USE_NTLM_V2 0
-#  endif
 #endif
 
-/* Define USE_NTRESPONSES to 1 in order to make the type-3 message include
+/* Define USE_NTRESPONSES in order to make the type-3 message include
  * the NT response message. */
-#ifndef USE_NTRESPONSES
-#define USE_NTRESPONSES 1
+#if !defined(USE_OPENSSL) || !defined(OPENSSL_NO_MD4)
+#define USE_NTRESPONSES
 #endif
 
-/* Define USE_NTLM2SESSION to 1 in order to make the type-3 message include the
+/* Define USE_NTLM2SESSION in order to make the type-3 message include the
    NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a
    Crypto engine that we have curl_ssl_md5sum() for. */
-#if !defined(USE_NTLM2SESSION) && USE_NTRESPONSES && !defined(USE_WIN32_CRYPTO)
-#define USE_NTLM2SESSION 1
+#if defined(USE_NTRESPONSES) && !defined(USE_WIN32_CRYPTO)
+#define USE_NTLM2SESSION
 #endif
 
-/* Define USE_NTLM_V2 to 1 in order to allow the type-3 message to include the
+/* Define USE_NTLM_V2 in order to allow the type-3 message to include the
    LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1
    and support for 64-bit integers. */
-#if !defined(USE_NTLM_V2) && USE_NTRESPONSES && (CURL_SIZEOF_CURL_OFF_T > 4)
-#define USE_NTLM_V2 1
+#if defined(USE_NTRESPONSES) && (CURL_SIZEOF_CURL_OFF_T > 4)
+#define USE_NTLM_V2
 #endif
 
 void Curl_ntlm_core_lm_resp(const unsigned char *keys,
@@ -68,12 +63,12 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
                                    const char *password,
                                    unsigned char *lmbuffer /* 21 bytes */);
 
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
 CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
                                    const char *password,
                                    unsigned char *ntbuffer /* 21 bytes */);
 
-#if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
+#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
 
 CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
                        const unsigned char *data, unsigned int datalen,
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index afdea16..9f5b87b 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.c
@@ -28,7 +28,7 @@
 /*
  * NTLM details:
  *
- * http://davenport.sourceforge.net/ntlm.html
+ * https://davenport.sourceforge.io/ntlm.html
  * https://www.innovation.ch/java/ntlm.html
  */
 
@@ -51,6 +51,7 @@
 #include "curl_ntlm_wb.h"
 #include "url.h"
 #include "strerror.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -156,7 +157,8 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
   }
   slash = strpbrk(username, "\\/");
   if(slash) {
-    if((domain = strdup(username)) == NULL)
+    domain = strdup(username);
+    if(!domain)
       return CURLE_OUT_OF_MEMORY;
     slash = domain + (slash - username);
     *slash = '\0';
@@ -293,11 +295,10 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
       buf[len_out - 1] = '\0';
       break;
     }
-    newbuf = realloc(buf, len_out + NTLM_BUFSIZE);
-    if(!newbuf) {
-      free(buf);
+    newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE);
+    if(!newbuf)
       return CURLE_OUT_OF_MEMORY;
-    }
+
     buf = newbuf;
   }
 
@@ -349,7 +350,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
 
   if(proxy) {
     allocuserpwd = &conn->allocptr.proxyuserpwd;
-    userp = conn->proxyuser;
+    userp = conn->http_proxy.user;
     ntlm = &conn->proxyntlm;
     authp = &conn->data->state.authproxy;
   }
diff --git a/Utilities/cmcurl/lib/curl_rtmp.c b/Utilities/cmcurl/lib/curl_rtmp.c
index 06dd047..87a6caf 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.c
+++ b/Utilities/cmcurl/lib/curl_rtmp.c
@@ -25,6 +25,7 @@
 
 #ifdef USE_LIBRTMP
 
+#include "curl_rtmp.h"
 #include "urldata.h"
 #include "nonblock.h" /* for curlx_nonblock */
 #include "progress.h" /* for Curl_pgrsSetUploadSize */
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 6b86962..bd574b5 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at 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,7 @@
 #include "memdebug.h"
 
 /* Supported mechanisms */
-const struct {
+static const struct {
   const char   *name;  /* Name */
   size_t        len;   /* Name length */
   unsigned int  bit;   /* Flag bit */
@@ -262,10 +262,13 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
   size_t len = 0;
   saslstate state1 = SASL_STOP;
   saslstate state2 = SASL_FINAL;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
 #if defined(USE_KERBEROS5)
-  const char* service = data->set.str[STRING_SERVICE_NAME] ?
-                        data->set.str[STRING_SERVICE_NAME] :
-                        sasl->params->service;
+  const char *service = data->set.str[STRING_SERVICE_NAME] ?
+    data->set.str[STRING_SERVICE_NAME] :
+    sasl->params->service;
 #endif
 
   sasl->force_ir = force_ir;    /* Latch for future use */
@@ -341,8 +344,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
 
       if(force_ir || data->set.sasl_ir)
         result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                       conn->host.name,
-                                                       conn->port,
+                                                       hostname,
+                                                       port,
                                                        conn->oauth_bearer,
                                                        &resp, &len);
     }
@@ -408,8 +411,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   saslstate newstate = SASL_FINAL;
   char *resp = NULL;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
 #if !defined(CURL_DISABLE_CRYPTO_AUTH)
-  char *serverdata;
   char *chlg = NULL;
   size_t chlglen = 0;
 #endif
@@ -418,6 +423,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
                         data->set.str[STRING_SERVICE_NAME] :
                         sasl->params->service;
 #endif
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
+    defined(USE_NTLM)
+  char *serverdata;
+#endif
   size_t len = 0;
 
   *progress = SASL_INPROGRESS;
@@ -542,8 +551,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
     /* Create the authorisation message */
     if(sasl->authused == SASL_MECH_OAUTHBEARER) {
       result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                     conn->host.name,
-                                                     conn->port,
+                                                     hostname,
+                                                     port,
                                                      conn->oauth_bearer,
                                                      &resp, &len);
 
diff --git a/Utilities/cmcurl/lib/curl_sec.h b/Utilities/cmcurl/lib/curl_sec.h
index 3f94e14..7bdde26 100644
--- a/Utilities/cmcurl/lib/curl_sec.h
+++ b/Utilities/cmcurl/lib/curl_sec.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -30,8 +30,8 @@ struct Curl_sec_client_mech {
   void (*end)(void *);
   int (*check_prot)(void *, int);
   int (*overhead)(void *, int, int);
-  int (*encode)(void *, const void*, int, int, void**);
-  int (*decode)(void *, void*, int, int, struct connectdata *);
+  int (*encode)(void *, const void *, int, int, void **);
+  int (*decode)(void *, void *, int, int, struct connectdata *);
 };
 
 #define AUTH_OK         0
@@ -39,11 +39,11 @@ struct Curl_sec_client_mech {
 #define AUTH_ERROR      2
 
 #ifdef HAVE_GSSAPI
-int Curl_sec_read_msg (struct connectdata *conn, char *,
-                       enum protection_level);
-void Curl_sec_end (struct connectdata *);
-CURLcode Curl_sec_login (struct connectdata *);
-int Curl_sec_request_prot (struct connectdata *conn, const char *level);
+int Curl_sec_read_msg(struct connectdata *conn, char *,
+                      enum protection_level);
+void Curl_sec_end(struct connectdata *);
+CURLcode Curl_sec_login(struct connectdata *);
+int Curl_sec_request_prot(struct connectdata *conn, const char *level);
 
 extern struct Curl_sec_client_mech Curl_krb5_client_mech;
 #endif
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 4eb17a1..a6268ad 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -128,18 +128,7 @@
 /*  please, do it beyond the point further indicated in this file.  */
 /* ================================================================ */
 
-/*
- * libcurl's external interface definitions are also used internally,
- * and might also include required system header files to define them.
- */
-
-#include <curl/curlbuild.h>
-
-/*
- * Compile time sanity checks must also be done when building the library.
- */
-
-#include <curl/curlrules.h>
+#include <curl/curl.h>
 
 /*
  * Ensure that no one is using the old SIZEOF_CURL_OFF_T macro
@@ -482,8 +471,8 @@
 
 #  ifdef __minix
      /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */
-     extern char * strtok_r(char *s, const char *delim, char **last);
-     extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp);
+     extern char *strtok_r(char *s, const char *delim, char **last);
+     extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp);
 #  endif
 
 #  define DIR_CHAR      "/"
@@ -614,11 +603,15 @@ int netware_init(void);
 #endif
 #endif
 
-#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H)
+#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN)
 /* The lib and header are present */
 #define USE_LIBIDN2
 #endif
 
+#if defined(USE_LIBIDN2) && defined(USE_WIN32_IDN)
+#error "Both libidn2 and WinIDN are enabled, choose one."
+#endif
+
 #ifndef SIZEOF_TIME_T
 /* assume default size of time_t to be 32 bit */
 #define SIZEOF_TIME_T 4
@@ -649,14 +642,14 @@ int netware_init(void);
 #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
 #if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
     defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \
-    defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
+    defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
+    defined(USE_MBEDTLS)
 
 #define USE_NTLM
 
-#elif defined(USE_MBEDTLS)
+#  if defined(USE_MBEDTLS)
+/* Get definition of MBEDTLS_MD4_C */
 #  include <mbedtls/md4.h>
-#  if defined(MBEDTLS_MD4_C)
-#define USE_NTLM
 #  endif
 
 #endif
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index 4da8349..684187c 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -196,7 +196,7 @@ struct timeval {
   /* */
 #else
 #define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
-                                    (SEND_TYPE_ARG2)(y), \
+                                    (SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \
                                     (SEND_TYPE_ARG3)(z), \
                                     (SEND_TYPE_ARG4)(SEND_4TH_ARG))
 #endif
diff --git a/Utilities/cmcurl/lib/curl_threads.c b/Utilities/cmcurl/lib/curl_threads.c
index c98d8bb..a78eff5 100644
--- a/Utilities/cmcurl/lib/curl_threads.c
+++ b/Utilities/cmcurl/lib/curl_threads.c
@@ -59,7 +59,7 @@ static void *curl_thread_create_thunk(void *arg)
   return 0;
 }
 
-curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg)
+curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg)
 {
   curl_thread_t t = malloc(sizeof(pthread_t));
   struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
@@ -100,7 +100,8 @@ int Curl_thread_join(curl_thread_t *hnd)
 
 #elif defined(USE_THREADS_WIN32)
 
-curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+/* !checksrc! disable SPACEBEFOREPAREN 1 */
+curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
                                  void *arg)
 {
 #ifdef _WIN32_WCE
diff --git a/Utilities/cmcurl/lib/curl_threads.h b/Utilities/cmcurl/lib/curl_threads.h
index 8cbac63..9e0d14a 100644
--- a/Utilities/cmcurl/lib/curl_threads.h
+++ b/Utilities/cmcurl/lib/curl_threads.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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,8 @@
 
 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
 
-curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+/* !checksrc! disable SPACEBEFOREPAREN 1 */
+curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
                                  void *arg);
 
 void Curl_thread_destroy(curl_thread_t hnd);
diff --git a/Utilities/cmcurl/lib/dict.c b/Utilities/cmcurl/lib/dict.c
index 69defc4..451ec38 100644
--- a/Utilities/cmcurl/lib/dict.c
+++ b/Utilities/cmcurl/lib/dict.c
@@ -92,7 +92,7 @@ const struct Curl_handler Curl_handler_dict = {
 
 static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
 {
-  char *newp;
+  char *newp = NULL;
   char *dictp;
   char *ptr;
   size_t len;
diff --git a/Utilities/cmcurl/lib/dotdot.c b/Utilities/cmcurl/lib/dotdot.c
index ea7c8a0..20603bc 100644
--- a/Utilities/cmcurl/lib/dotdot.c
+++ b/Utilities/cmcurl/lib/dotdot.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -147,6 +147,7 @@ char *Curl_dedotdotify(const char *input)
 
     else if(!strcmp(".", clone) || !strcmp("..", clone)) {
       *clone=0;
+      *out=0;
     }
 
     else {
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index eee1061..2b1ce9e 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -179,7 +179,7 @@ curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
 #endif
 #else
 /*
- * Symbian OS doesn't support initialization to code in writeable static data.
+ * Symbian OS doesn't support initialization to code in writable static data.
  * Initialization will occur in the curl_global_init() call.
  */
 curl_malloc_callback Curl_cmalloc;
@@ -561,7 +561,7 @@ static void events_setup(struct Curl_multi *multi, struct events *ev)
 static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
 {
   bool done = FALSE;
-  CURLMcode mcode;
+  CURLMcode mcode = CURLM_OK;
   CURLcode result = CURLE_OK;
 
   while(!done) {
@@ -615,12 +615,18 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
         }
       }
 
-      if(!ev->msbump)
+      if(!ev->msbump) {
         /* If nothing updated the timeout, we decrease it by the spent time.
          * If it was updated, it has the new timeout time stored already.
          */
-        ev->ms += curlx_tvdiff(after, before);
-
+        time_t timediff = curlx_tvdiff(after, before);
+        if(timediff > 0) {
+          if(timediff > ev->ms)
+            ev->ms = 0;
+          else
+            ev->ms -= (long)timediff;
+        }
+      }
     }
     else
       return CURLE_RECV_ERROR;
@@ -773,8 +779,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
     curl_multi_cleanup(multi);
     if(mcode == CURLM_OUT_OF_MEMORY)
       return CURLE_OUT_OF_MEMORY;
-    else
-      return CURLE_FAILED_INIT;
+    return CURLE_FAILED_INIT;
   }
 
   sigpipe_ignore(data, &pipe_st);
@@ -870,6 +875,11 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
    * get setup on-demand in the code, as that would probably decrease
    * the likeliness of us forgetting to init a buffer here in the future.
    */
+  outcurl->set.buffer_size = data->set.buffer_size;
+  outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1);
+  if(!outcurl->state.buffer)
+    goto fail;
+
   outcurl->state.headerbuff = malloc(HEADERSIZE);
   if(!outcurl->state.headerbuff)
     goto fail;
@@ -927,6 +937,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
 
   Curl_convert_setup(outcurl);
 
+  Curl_initinfo(outcurl);
+
   outcurl->magic = CURLEASY_MAGIC_NUMBER;
 
   /* we reach this point and thus we are OK */
@@ -938,6 +950,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
   if(outcurl) {
     curl_slist_free_all(outcurl->change.cookielist);
     outcurl->change.cookielist = NULL;
+    Curl_safefree(outcurl->state.buffer);
     Curl_safefree(outcurl->state.headerbuff);
     Curl_safefree(outcurl->change.url);
     Curl_safefree(outcurl->change.referer);
@@ -973,6 +986,10 @@ void curl_easy_reset(struct Curl_easy *data)
 
   data->progress.flags |= PGRS_HIDE;
   data->state.current_speed = -1; /* init to negative == impossible */
+
+  /* zero out authentication data: */
+  memset(&data->state.authhost, 0, sizeof(struct auth));
+  memset(&data->state.authproxy, 0, sizeof(struct auth));
 }
 
 /*
@@ -1000,19 +1017,32 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
   /* put it back in the keepon */
   k->keepon = newstate;
 
-  if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) {
-    /* we have a buffer for sending that we now seem to be able to deliver
-       since the receive pausing is lifted! */
-
-    /* get the pointer in local copy since the function may return PAUSE
-       again and then we'll get a new copy allocted and stored in
-       the tempwrite variables */
-    char *tempwrite = data->state.tempwrite;
-
-    data->state.tempwrite = NULL;
-    result = Curl_client_chop_write(data->easy_conn, data->state.tempwritetype,
-                                    tempwrite, data->state.tempwritesize);
-    free(tempwrite);
+  if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) {
+    /* there are buffers for sending that can be delivered as the receive
+       pausing is lifted! */
+    unsigned int i;
+    unsigned int count = data->state.tempcount;
+    struct tempbuf writebuf[3]; /* there can only be three */
+
+    /* copy the structs to allow for immediate re-pausing */
+    for(i=0; i < data->state.tempcount; i++) {
+      writebuf[i] = data->state.tempwrite[i];
+      data->state.tempwrite[i].buf = NULL;
+    }
+    data->state.tempcount = 0;
+
+    for(i=0; i < count; i++) {
+      /* even if one function returns error, this loops through and frees all
+         buffers */
+      if(!result)
+        result = Curl_client_chop_write(data->easy_conn,
+                                        writebuf[i].type,
+                                        writebuf[i].buf,
+                                        writebuf[i].len);
+      free(writebuf[i].buf);
+    }
+    if(result)
+      return result;
   }
 
   /* if there's no error and we're not pausing both directions, we want
@@ -1020,7 +1050,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
   if(!result &&
      ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
       (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
-    Curl_expire(data, 0); /* get this handle going again */
+    Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
 
   return result;
 }
diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c
index 6657007..973aeb6 100644
--- a/Utilities/cmcurl/lib/escape.c
+++ b/Utilities/cmcurl/lib/escape.c
@@ -31,6 +31,7 @@
 #include "warnless.h"
 #include "non-ascii.h"
 #include "escape.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -42,7 +43,7 @@
 */
 static bool Curl_isunreserved(unsigned char in)
 {
-  switch (in) {
+  switch(in) {
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
     case 'a': case 'b': case 'c': case 'd': case 'e':
@@ -109,14 +110,10 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
       newlen += 2; /* the size grows with two, since this'll become a %XX */
       if(newlen > alloc) {
         alloc *= 2;
-        testing_ptr = realloc(ns, alloc);
-        if(!testing_ptr) {
-          free(ns);
+        testing_ptr = Curl_saferealloc(ns, alloc);
+        if(!testing_ptr)
           return NULL;
-        }
-        else {
-          ns = testing_ptr;
-        }
+        ns = testing_ptr;
       }
 
       result = Curl_convert_to_network(data, &in, 1);
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index 272289e..c804d75 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -311,9 +311,8 @@ static CURLcode file_upload(struct connectdata *conn)
   size_t nread;
   size_t nwrite;
   curl_off_t bytecount = 0;
-  struct timeval now = Curl_tvnow();
   struct_stat file_stat;
-  const char* buf2;
+  const char *buf2;
 
   /*
    * Since FILE: doesn't do the full init, we need to provide some extra
@@ -355,13 +354,12 @@ static CURLcode file_upload(struct connectdata *conn)
       failf(data, "Can't get the size of %s", file->path);
       return CURLE_WRITE_ERROR;
     }
-    else
-      data->state.resume_from = (curl_off_t)file_stat.st_size;
+    data->state.resume_from = (curl_off_t)file_stat.st_size;
   }
 
   while(!result) {
     int readcount;
-    result = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
+    result = Curl_fillreadbuffer(conn, (int)data->set.buffer_size, &readcount);
     if(result)
       break;
 
@@ -400,7 +398,7 @@ static CURLcode file_upload(struct connectdata *conn)
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
     else
-      result = Curl_speedcheck(data, now);
+      result = Curl_speedcheck(data, Curl_tvnow());
   }
   if(!result && Curl_pgrsUpdate(conn))
     result = CURLE_ABORTED_BY_CALLBACK;
@@ -437,7 +435,6 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
   char *buf = data->state.buffer;
   curl_off_t bytecount = 0;
   int fd;
-  struct timeval now = Curl_tvnow();
   struct FILEPROTO *file;
 
   *done = TRUE; /* unconditionally */
@@ -476,9 +473,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
     time_t filetime;
     struct tm buffer;
     const struct tm *tm = &buffer;
-    snprintf(buf, sizeof(data->state.buffer),
+    char header[80];
+    snprintf(header, sizeof(header),
              "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
-    result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+    result = Curl_client_write(conn, CLIENTWRITE_BOTH, header, 0);
     if(result)
       return result;
 
@@ -493,7 +491,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
       return result;
 
     /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
-    snprintf(buf, BUFSIZE-1,
+    snprintf(header, sizeof(header),
              "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
              Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
              tm->tm_mday,
@@ -519,8 +517,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
       failf(data, "Can't get the size of file.");
       return CURLE_READ_ERROR;
     }
-    else
-      data->state.resume_from += (curl_off_t)statbuf.st_size;
+    data->state.resume_from += (curl_off_t)statbuf.st_size;
   }
 
   if(data->state.resume_from <= expected_size)
@@ -559,12 +556,11 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
     size_t bytestoread;
 
     if(size_known) {
-      bytestoread =
-        (expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ?
-        curlx_sotouz(expected_size) : BUFSIZE - 1;
+      bytestoread = (expected_size < data->set.buffer_size) ?
+        curlx_sotouz(expected_size) : (size_t)data->set.buffer_size;
     }
     else
-      bytestoread = BUFSIZE-1;
+      bytestoread = data->set.buffer_size-1;
 
     nread = read(fd, buf, bytestoread);
 
@@ -587,7 +583,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
     else
-      result = Curl_speedcheck(data, now);
+      result = Curl_speedcheck(data, Curl_tvnow());
   }
   if(Curl_pgrsUpdate(conn))
     result = CURLE_ABORTED_BY_CALLBACK;
diff --git a/Utilities/cmcurl/lib/fileinfo.c b/Utilities/cmcurl/lib/fileinfo.c
index 144c65b..3872988 100644
--- a/Utilities/cmcurl/lib/fileinfo.c
+++ b/Utilities/cmcurl/lib/fileinfo.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel at 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
@@ -28,23 +28,19 @@
 /* The last #include file should be: */
 #include "memdebug.h"
 
-struct curl_fileinfo *Curl_fileinfo_alloc(void)
+struct fileinfo *Curl_fileinfo_alloc(void)
 {
-  struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo));
-  if(!tmp)
-    return NULL;
-  memset(tmp, 0, sizeof(struct curl_fileinfo));
-  return tmp;
+  return calloc(1, sizeof(struct fileinfo));
 }
 
 void Curl_fileinfo_dtor(void *user, void *element)
 {
-  struct curl_fileinfo *finfo = element;
+  struct fileinfo *finfo = element;
   (void) user;
   if(!finfo)
     return;
 
-  Curl_safefree(finfo->b_data);
+  Curl_safefree(finfo->info.b_data);
 
   free(finfo);
 }
diff --git a/Utilities/cmcurl/lib/fileinfo.h b/Utilities/cmcurl/lib/fileinfo.h
index 5324f1a..c5d0ee5 100644
--- a/Utilities/cmcurl/lib/fileinfo.h
+++ b/Utilities/cmcurl/lib/fileinfo.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2010, 2017, Daniel Stenberg, <daniel at 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
@@ -23,11 +23,15 @@
  ***************************************************************************/
 
 #include <curl/curl.h>
+#include "llist.h"
 
-struct curl_fileinfo *Curl_fileinfo_alloc(void);
+struct fileinfo {
+  struct curl_fileinfo info;
+  struct curl_llist_element list;
+};
 
-void Curl_fileinfo_dtor(void *, void *);
+struct fileinfo *Curl_fileinfo_alloc(void);
 
-struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src);
+void Curl_fileinfo_dtor(void *, void *);
 
 #endif /* HEADER_CURL_FILEINFO_H */
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index 785f1a6..e48a627 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -36,6 +36,7 @@
 #include "strcase.h"
 #include "sendf.h"
 #include "strdup.h"
+#include "rand.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -47,15 +48,12 @@ static char *Curl_basename(char *path);
 #endif
 
 static size_t readfromfile(struct Form *form, char *buffer, size_t size);
-static char *formboundary(struct Curl_easy *data);
+static CURLcode formboundary(struct Curl_easy *data, char *buffer, size_t len);
 
 /* What kind of Content-Type to use on un-specified files with unrecognized
    extensions. */
 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
 
-#define FORM_FILE_SEPARATOR ','
-#define FORM_TYPE_SEPARATOR ';'
-
 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
@@ -80,7 +78,7 @@ AddHttpPost(char *name, size_t namelength,
             char *buffer, size_t bufferlength,
             char *contenttype,
             long flags,
-            struct curl_slist* contentHeader,
+            struct curl_slist *contentHeader,
             char *showfilename, char *userp,
             struct curl_httppost *parent_post,
             struct curl_httppost **httppost,
@@ -98,7 +96,7 @@ AddHttpPost(char *name, size_t namelength,
     post->contenttype = contenttype;
     post->contentheader = contentHeader;
     post->showfilename = showfilename;
-    post->userp = userp,
+    post->userp = userp;
     post->flags = flags | CURL_HTTPPOST_LARGE;
   }
   else
@@ -315,7 +313,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         break;
     }
 
-    switch (option) {
+    switch(option) {
     case CURLFORM_ARRAY:
       if(array_state)
         /* we don't support an array from within an array */
@@ -341,6 +339,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
 #else
       current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
 #endif
+      /* FALLTHROUGH */
     case CURLFORM_COPYNAME:
       if(current_form->name)
         return_value = CURL_FORMADD_OPTION_TWICE;
@@ -547,9 +546,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       {
         /* this "cast increases required alignment of target type" but
            we consider it OK anyway */
-        struct curl_slist* list = array_state?
-          (struct curl_slist*)(void*)array_value:
-          va_arg(params, struct curl_slist*);
+        struct curl_slist *list = array_state?
+          (struct curl_slist *)(void *)array_value:
+          va_arg(params, struct curl_slist *);
 
         if(current_form->contentheader)
           return_value = CURL_FORMADD_OPTION_TWICE;
@@ -628,70 +627,68 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         return_value = CURL_FORMADD_INCOMPLETE;
         break;
       }
-      else {
-        if(((form->flags & HTTPPOST_FILENAME) ||
-            (form->flags & HTTPPOST_BUFFER)) &&
-           !form->contenttype) {
-          char *f = form->flags & HTTPPOST_BUFFER?
-            form->showfilename : form->value;
-
-          /* our contenttype is missing */
-          form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
-          if(!form->contenttype) {
-            return_value = CURL_FORMADD_MEMORY;
-            break;
-          }
-          form->contenttype_alloc = TRUE;
+      if(((form->flags & HTTPPOST_FILENAME) ||
+          (form->flags & HTTPPOST_BUFFER)) &&
+         !form->contenttype) {
+        char *f = form->flags & HTTPPOST_BUFFER?
+          form->showfilename : form->value;
+
+        /* our contenttype is missing */
+        form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
+        if(!form->contenttype) {
+          return_value = CURL_FORMADD_MEMORY;
+          break;
         }
-        if(!(form->flags & HTTPPOST_PTRNAME) &&
-           (form == first_form) ) {
-          /* Note that there's small risk that form->name is NULL here if the
-             app passed in a bad combo, so we better check for that first. */
-          if(form->name) {
-            /* copy name (without strdup; possibly contains null characters) */
-            form->name = Curl_memdup(form->name, form->namelength?
-                                     form->namelength:
-                                     strlen(form->name)+1);
-          }
-          if(!form->name) {
-            return_value = CURL_FORMADD_MEMORY;
-            break;
-          }
-          form->name_alloc = TRUE;
+        form->contenttype_alloc = TRUE;
+      }
+      if(!(form->flags & HTTPPOST_PTRNAME) &&
+         (form == first_form) ) {
+        /* Note that there's small risk that form->name is NULL here if the
+           app passed in a bad combo, so we better check for that first. */
+        if(form->name) {
+          /* copy name (without strdup; possibly contains null characters) */
+          form->name = Curl_memdup(form->name, form->namelength?
+                                   form->namelength:
+                                   strlen(form->name)+1);
         }
-        if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
-                            HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
-                            HTTPPOST_CALLBACK)) && form->value) {
-          /* copy value (without strdup; possibly contains null characters) */
-          size_t clen  = (size_t) form->contentslength;
-          if(!clen)
-            clen = strlen(form->value)+1;
+        if(!form->name) {
+          return_value = CURL_FORMADD_MEMORY;
+          break;
+        }
+        form->name_alloc = TRUE;
+      }
+      if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
+                          HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
+                          HTTPPOST_CALLBACK)) && form->value) {
+        /* copy value (without strdup; possibly contains null characters) */
+        size_t clen  = (size_t) form->contentslength;
+        if(!clen)
+          clen = strlen(form->value)+1;
 
-          form->value = Curl_memdup(form->value, clen);
+        form->value = Curl_memdup(form->value, clen);
 
-          if(!form->value) {
-            return_value = CURL_FORMADD_MEMORY;
-            break;
-          }
-          form->value_alloc = TRUE;
-        }
-        post = AddHttpPost(form->name, form->namelength,
-                           form->value, form->contentslength,
-                           form->buffer, form->bufferlength,
-                           form->contenttype, form->flags,
-                           form->contentheader, form->showfilename,
-                           form->userp,
-                           post, httppost,
-                           last_post);
-
-        if(!post) {
+        if(!form->value) {
           return_value = CURL_FORMADD_MEMORY;
           break;
         }
-
-        if(form->contenttype)
-          prevtype = form->contenttype;
+        form->value_alloc = TRUE;
       }
+      post = AddHttpPost(form->name, form->namelength,
+                         form->value, form->contentslength,
+                         form->buffer, form->bufferlength,
+                         form->contenttype, form->flags,
+                         form->contentheader, form->showfilename,
+                         form->userp,
+                         post, httppost,
+                         last_post);
+
+      if(!post) {
+        return_value = CURL_FORMADD_MEMORY;
+        break;
+      }
+
+      if(form->contenttype)
+        prevtype = form->contenttype;
     }
     if(CURL_FORMADD_OK != return_value) {
       /* On error, free allocated fields for nodes of the FormInfo linked
@@ -761,8 +758,8 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
  * and CD/DVD images should be either a STREAM_LF format or a fixed format.
  *
  */
-curl_off_t VmsRealFileSize(const char * name,
-                           const struct_stat * stat_buf)
+curl_off_t VmsRealFileSize(const char *name,
+                           const struct_stat *stat_buf)
 {
   char buffer[8192];
   curl_off_t count;
@@ -791,8 +788,8 @@ curl_off_t VmsRealFileSize(const char * name,
  *  if not to call a routine to get the correct size.
  *
  */
-static curl_off_t VmsSpecialSize(const char * name,
-                                 const struct_stat * stat_buf)
+static curl_off_t VmsSpecialSize(const char *name,
+                                 const struct_stat *stat_buf)
 {
   switch(stat_buf->st_fab_rfm) {
   case FAB$C_VAR:
@@ -948,8 +945,8 @@ void Curl_formclean(struct FormData **form_ptr)
     if(form->type <= FORM_CONTENT)
       free(form->line); /* free the line */
     free(form);       /* free the struct */
-
-  } while((form = next) != NULL); /* continue */
+    form = next;
+  } while(form); /* continue */
 
   *form_ptr = NULL;
 }
@@ -1030,8 +1027,8 @@ void curl_formfree(struct curl_httppost *form)
     free(form->contenttype); /* free the content type */
     free(form->showfilename); /* free the faked file name */
     free(form);       /* free the struct */
-
-  } while((form = next) != NULL); /* continue */
+    form = next;
+  } while(form); /* continue */
 }
 
 #ifndef HAVE_BASENAME
@@ -1162,20 +1159,19 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
   struct FormData *firstform;
   struct curl_httppost *file;
   CURLcode result = CURLE_OK;
-
   curl_off_t size = 0; /* support potentially ENORMOUS formposts */
-  char *boundary;
-  char *fileboundary = NULL;
-  struct curl_slist* curList;
+  char fileboundary[42];
+  struct curl_slist *curList;
+  char boundary[42];
 
   *finalform = NULL; /* default form is empty */
 
   if(!post)
     return result; /* no input => no output! */
 
-  boundary = formboundary(data);
-  if(!boundary)
-    return CURLE_OUT_OF_MEMORY;
+  result = formboundary(data, boundary, sizeof(boundary));
+  if(result)
+    return result;
 
   /* Make the first line of the output */
   result = AddFormDataf(&form, NULL,
@@ -1185,7 +1181,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
                         boundary);
 
   if(result) {
-    free(boundary);
     return result;
   }
   /* we DO NOT include that line in the total size of the POST, since it'll be
@@ -1228,10 +1223,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
       /* If used, this is a link to more file names, we must then do
          the magic to include several files with the same field name */
 
-      free(fileboundary);
-      fileboundary = formboundary(data);
-      if(!fileboundary) {
-        result = CURLE_OUT_OF_MEMORY;
+      result = formboundary(data, fileboundary, sizeof(fileboundary));
+      if(result) {
         break;
       }
 
@@ -1331,7 +1324,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
             char buffer[512];
             while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
               result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
-              if(result)
+              if(result || feof(fileread) || ferror(fileread))
                 break;
             }
           }
@@ -1373,8 +1366,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
       if(result)
         break;
     }
-
-  } while((post = post->next) != NULL); /* for each field */
+    post = post->next;
+  } while(post); /* for each field */
 
   /* end-boundary for everything */
   if(!result)
@@ -1382,16 +1375,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
 
   if(result) {
     Curl_formclean(&firstform);
-    free(fileboundary);
-    free(boundary);
     return result;
   }
 
   *sizep = size;
-
-  free(fileboundary);
-  free(boundary);
-
   *finalform = firstform;
 
   return result;
@@ -1426,13 +1413,14 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata)
    *
    */
 # define fopen_read vmsfopenread
-static FILE * vmsfopenread(const char *file, const char *mode) {
+static FILE * vmsfopenread(const char *file, const char *mode)
+{
   struct_stat statbuf;
   int result;
 
   result = stat(file, &statbuf);
 
-  switch (statbuf.st_fab_rfm) {
+  switch(statbuf.st_fab_rfm) {
   case FAB$C_VAR:
   case FAB$C_VFC:
   case FAB$C_STMCR:
@@ -1460,8 +1448,7 @@ static size_t readfromfile(struct Form *form, char *buffer,
   if(callback) {
     if(form->fread_func == ZERO_NULL)
       return 0;
-    else
-      nread = form->fread_func(buffer, 1, size, form->data->line);
+    nread = form->fread_func(buffer, 1, size, form->data->line);
   }
   else {
     if(!form->fp) {
@@ -1551,7 +1538,7 @@ char *Curl_formpostheader(void *formp, size_t *len)
   struct Form *form=(struct Form *)formp;
 
   if(!form->data)
-    return 0; /* nothing, ERROR! */
+    return NULL; /* nothing, ERROR! */
 
   header = form->data->line;
   *len = form->data->length;
@@ -1565,12 +1552,18 @@ char *Curl_formpostheader(void *formp, size_t *len)
  * formboundary() creates a suitable boundary string and returns an allocated
  * one.
  */
-static char *formboundary(struct Curl_easy *data)
+static CURLcode formboundary(struct Curl_easy *data,
+                             char *buffer, size_t buflen)
 {
   /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
      combinations */
-  return aprintf("------------------------%08x%08x",
-                 Curl_rand(data), Curl_rand(data));
+  if(buflen < 41)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  memset(buffer, '-', 24);
+  Curl_rand_hex(data, (unsigned char *)&buffer[24], 17);
+
+  return CURLE_OK;
 }
 
 #else  /* CURL_DISABLE_HTTP */
diff --git a/Utilities/cmcurl/lib/formdata.h b/Utilities/cmcurl/lib/formdata.h
index 200470b..69629f6 100644
--- a/Utilities/cmcurl/lib/formdata.h
+++ b/Utilities/cmcurl/lib/formdata.h
@@ -65,7 +65,7 @@ typedef struct FormInfo {
                          file name will be used */
   bool showfilename_alloc;
   char *userp;        /* pointer for the read callback */
-  struct curl_slist* contentheader;
+  struct curl_slist *contentheader;
   struct FormInfo *more;
 } FormInfo;
 
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index 9d0a03c..783dbe1 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -384,10 +384,10 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
  * Curl_pgrsTime(..., TIMER_STARTACCEPT);
  *
  */
-static long ftp_timeleft_accept(struct Curl_easy *data)
+static time_t ftp_timeleft_accept(struct Curl_easy *data)
 {
-  long timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
-  long other;
+  time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
+  time_t other;
   struct timeval now;
 
   if(data->set.accepttimeout > 0)
@@ -430,7 +430,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct pingpong *pp = &ftpc->pp;
   int result;
-  long timeout_ms;
+  time_t timeout_ms;
   ssize_t nread;
   int ftpcode;
 
@@ -455,7 +455,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
   result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
 
   /* see if the connection request is already here */
-  switch (result) {
+  switch(result) {
   case -1: /* error */
     /* let's die here */
     failf(data, "Error while waiting for server connect");
@@ -499,7 +499,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
   struct FTP *ftp = data->req.protop;
   CURLcode result = CURLE_OK;
 
-  if(conn->ssl[SECONDARYSOCKET].use) {
+  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");
@@ -547,7 +547,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
 static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
 {
   struct Curl_easy *data = conn->data;
-  long timeout_ms;
+  time_t timeout_ms;
   CURLcode result = CURLE_OK;
 
   *connected = FALSE;
@@ -580,10 +580,8 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
   else {
     /* Add timeout to multi handle and break out of the loop */
     if(!result && *connected == FALSE) {
-      if(data->set.accepttimeout > 0)
-        Curl_expire(data, data->set.accepttimeout);
-      else
-        Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
+      Curl_expire(data, data->set.accepttimeout > 0 ?
+                  data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0);
     }
   }
 
@@ -687,8 +685,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
    * line in a response or continue reading.  */
 
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
-  long timeout;              /* timeout in milliseconds */
-  long interval_ms;
+  time_t timeout;              /* timeout in milliseconds */
+  time_t interval_ms;
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_OK;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -740,8 +738,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
        * wait for more data anyway.
        */
     }
-    else {
-      switch (SOCKET_READABLE(sockfd, interval_ms)) {
+    else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) {
+      switch(SOCKET_READABLE(sockfd, interval_ms)) {
       case -1: /* select() error, stop reading */
         failf(data, "FTP response aborted due to select/poll error: %d",
               SOCKERRNO);
@@ -916,8 +914,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
 
     return bits;
   }
-  else
-    return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
+  return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
 }
 
 /* This is called after the FTP_QUOTE state is passed.
@@ -1035,7 +1032,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
     if(*string_ftpport == '[') {
       /* [ipv6]:port(-range) */
       ip_start = string_ftpport + 1;
-      if((ip_end = strchr(string_ftpport, ']')) != NULL)
+      ip_end = strchr(string_ftpport, ']');
+      if(ip_end)
         strncpy(addr, ip_start, ip_end - ip_start);
     }
     else
@@ -1043,30 +1041,35 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
       if(*string_ftpport == ':') {
         /* :port */
         ip_end = string_ftpport;
-    }
-    else if((ip_end = strchr(string_ftpport, ':')) != NULL) {
-        /* either ipv6 or (ipv4|domain|interface):port(-range) */
-#ifdef ENABLE_IPV6
-      if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
-        /* ipv6 */
-        port_min = port_max = 0;
-        strcpy(addr, string_ftpport);
-        ip_end = NULL; /* this got no port ! */
       }
-      else
+      else {
+        ip_end = strchr(string_ftpport, ':');
+        if(ip_end) {
+          /* either ipv6 or (ipv4|domain|interface):port(-range) */
+#ifdef ENABLE_IPV6
+          if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
+            /* ipv6 */
+            port_min = port_max = 0;
+            strcpy(addr, string_ftpport);
+            ip_end = NULL; /* this got no port ! */
+          }
+          else
 #endif
-        /* (ipv4|domain|interface):port(-range) */
-        strncpy(addr, string_ftpport, ip_end - ip_start);
-    }
-    else
-      /* ipv4|interface */
-      strcpy(addr, string_ftpport);
+            /* (ipv4|domain|interface):port(-range) */
+            strncpy(addr, string_ftpport, ip_end - ip_start);
+        }
+        else
+          /* ipv4|interface */
+          strcpy(addr, string_ftpport);
+      }
 
     /* parse the port */
     if(ip_end != NULL) {
-      if((port_start = strchr(ip_end, ':')) != NULL) {
+      port_start = strchr(ip_end, ':');
+      if(port_start) {
         port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
-        if((port_sep = strchr(port_start, '-')) != NULL) {
+        port_sep = strchr(port_start, '-');
+        if(port_sep) {
           port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
         }
         else
@@ -1203,7 +1206,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
         possibly_non_local = FALSE; /* don't try this again */
         continue;
       }
-      else if(error != EADDRINUSE && error != EACCES) {
+      if(error != EADDRINUSE && error != EACCES) {
         failf(data, "bind(port=%hu) failed: %s", port,
               Curl_strerror(conn, error) );
         Curl_closesocket(conn, portsock);
@@ -1301,7 +1304,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
       }
       break;
     }
-    else if(PORT == fcmd) {
+    if(PORT == fcmd) {
       char *source = myhost;
       char *dest = tmp;
 
@@ -1668,31 +1671,30 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
     }
 
     if(seekerr != CURL_SEEKFUNC_OK) {
+      curl_off_t passed=0;
       if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
         failf(data, "Could not seek stream");
         return CURLE_FTP_COULDNT_USE_REST;
       }
       /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
-      else {
-        curl_off_t passed=0;
-        do {
-          size_t readthisamountnow =
-            (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
-            BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
-
-          size_t actuallyread =
-            data->state.fread_func(data->state.buffer, 1, readthisamountnow,
-                                   data->state.in);
-
-          passed += actuallyread;
-          if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
-            /* this checks for greater-than only to make sure that the
-               CURL_READFUNC_ABORT return code still aborts */
-            failf(data, "Failed to read data");
-            return CURLE_FTP_COULDNT_USE_REST;
-          }
-        } while(passed < data->state.resume_from);
-      }
+      do {
+        size_t readthisamountnow =
+          (data->state.resume_from - passed > data->set.buffer_size) ?
+          (size_t)data->set.buffer_size :
+          curlx_sotouz(data->state.resume_from - passed);
+
+        size_t actuallyread =
+          data->state.fread_func(data->state.buffer, 1, readthisamountnow,
+                                 data->state.in);
+
+        passed += actuallyread;
+        if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+          /* this checks for greater-than only to make sure that the
+             CURL_READFUNC_ABORT return code still aborts */
+          failf(data, "Failed to read data");
+          return CURLE_FTP_COULDNT_USE_REST;
+        }
+      } while(passed < data->state.resume_from);
     }
     /* now, decrease the size of the read */
     if(data->state.infilesize>0) {
@@ -1751,7 +1753,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
   /*
    * This state uses:
    * 'count1' to iterate over the commands to send
-   * 'count2' to store wether to allow commands to fail
+   * 'count2' to store whether to allow commands to fail
    */
 
   if(init)
@@ -1850,84 +1852,6 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
   return result;
 }
 
-/*
- * Perform the necessary magic that needs to be done once the TCP connection
- * to the proxy has completed.
- */
-static CURLcode proxy_magic(struct connectdata *conn,
-                            char *newhost, unsigned short newport,
-                            bool *magicdone)
-{
-  CURLcode result = CURLE_OK;
-  struct Curl_easy *data = conn->data;
-
-#if defined(CURL_DISABLE_PROXY)
-  (void) newhost;
-  (void) newport;
-#endif
-
-  *magicdone = FALSE;
-
-  switch(conn->proxytype) {
-  case CURLPROXY_SOCKS5:
-  case CURLPROXY_SOCKS5_HOSTNAME:
-    result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
-                         newport, SECONDARYSOCKET, conn);
-    *magicdone = TRUE;
-    break;
-  case CURLPROXY_SOCKS4:
-    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
-                         SECONDARYSOCKET, conn, FALSE);
-    *magicdone = TRUE;
-    break;
-  case CURLPROXY_SOCKS4A:
-    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
-                         SECONDARYSOCKET, conn, TRUE);
-    *magicdone = TRUE;
-    break;
-  case CURLPROXY_HTTP:
-  case CURLPROXY_HTTP_1_0:
-    /* do nothing here. handled later. */
-    break;
-  default:
-    failf(data, "unknown proxytype option given");
-    result = CURLE_COULDNT_CONNECT;
-    break;
-  }
-
-  if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
-    /* BLOCKING */
-    /* We want "seamless" FTP operations through HTTP proxy tunnel */
-
-    /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
-     * member conn->proto.http; we want FTP through HTTP and we have to
-     * change the member temporarily for connecting to the HTTP proxy. After
-     * Curl_proxyCONNECT we have to set back the member to the original
-     * struct FTP pointer
-     */
-    struct HTTP http_proxy;
-    struct FTP *ftp_save = data->req.protop;
-    memset(&http_proxy, 0, sizeof(http_proxy));
-    data->req.protop = &http_proxy;
-
-    result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE);
-
-    data->req.protop = ftp_save;
-
-    if(result)
-      return result;
-
-    if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
-      /* the CONNECT procedure is not complete, the tunnel is not yet up */
-      state(conn, FTP_STOP); /* this phase is completed */
-      return result;
-    }
-    else
-      *magicdone = TRUE;
-  }
-
-  return result;
-}
 
 static char *control_address(struct connectdata *conn)
 {
@@ -1935,11 +1859,7 @@ static char *control_address(struct connectdata *conn)
      If a proxy tunnel is used, returns the original host name instead, because
      the effective control connection address is the proxy address,
      not the ftp host. */
-  if(conn->bits.tunnel_proxy ||
-     conn->proxytype == CURLPROXY_SOCKS5 ||
-     conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
-     conn->proxytype == CURLPROXY_SOCKS4 ||
-     conn->proxytype == CURLPROXY_SOCKS4A)
+  if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
     return conn->host.name;
 
   return conn->ip_addr_str;
@@ -2063,7 +1983,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
      * here. We don't want to rely on a former host lookup that might've
      * expired now, instead we remake the lookup here and now!
      */
-    rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
+    const char * const host_name = conn->bits.socksproxy ?
+      conn->socks_proxy.host.name : conn->http_proxy.host.name;
+    rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
     if(rc == CURLRESOLV_PENDING)
       /* BLOCKING, ignores the return code but 'addr' will be NULL in
          case of failure */
@@ -2073,9 +1995,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
       (unsigned short)conn->port; /* we connect to the proxy's port */
 
     if(!addr) {
-      failf(data, "Can't resolve proxy host %s:%hu",
-            conn->proxy.name, connectport);
-      return CURLE_FTP_CANT_GET_HOST;
+      failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
+      return CURLE_COULDNT_RESOLVE_PROXY;
     }
   }
   else {
@@ -2116,6 +2037,13 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
     ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
 
   Curl_resolv_unlock(data, addr); /* we're done using this address */
+
+  Curl_safefree(conn->secondaryhostname);
+  conn->secondary_port = ftpc->newport;
+  conn->secondaryhostname = strdup(ftpc->newhost);
+  if(!conn->secondaryhostname)
+    return CURLE_OUT_OF_MEMORY;
+
   conn->bits.do_more = TRUE;
   state(conn, FTP_STOP); /* this phase is completed */
 
@@ -2172,17 +2100,17 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
       /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
          last .sss part is optional and means fractions of a second */
       int year, month, day, hour, minute, second;
-      char *buf = data->state.buffer;
-      if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d",
+      if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d",
                      &year, &month, &day, &hour, &minute, &second)) {
         /* we have a time, reformat it */
+        char timebuf[24];
         time_t secs=time(NULL);
-        /* using the good old yacc/bison yuck */
-        snprintf(buf, sizeof(conn->data->state.buffer),
+
+        snprintf(timebuf, sizeof(timebuf),
                  "%04d%02d%02d %02d:%02d:%02d GMT",
                  year, month, day, hour, minute, second);
         /* now, convert this into a time() value: */
-        data->info.filetime = (long)curl_getdate(buf, &secs);
+        data->info.filetime = (long)curl_getdate(timebuf, &secs);
       }
 
 #ifdef CURL_FTP_HTTPSTYLE_HEAD
@@ -2193,6 +2121,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
          ftpc->file &&
          data->set.get_filetime &&
          (data->info.filetime>=0) ) {
+        char headerbuf[128];
         time_t filetime = (time_t)data->info.filetime;
         struct tm buffer;
         const struct tm *tm = &buffer;
@@ -2202,7 +2131,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
           return result;
 
         /* format: "Tue, 15 Nov 1994 12:45:26" */
-        snprintf(buf, BUFSIZE-1,
+        snprintf(headerbuf, sizeof(headerbuf),
                  "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
                  Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
                  tm->tm_mday,
@@ -2211,7 +2140,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
                  tm->tm_hour,
                  tm->tm_min,
                  tm->tm_sec);
-        result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+        result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
         if(result)
           return result;
       } /* end of a ridiculous amount of conditionals */
@@ -2389,9 +2318,10 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
   if(instate == FTP_SIZE) {
 #ifdef CURL_FTP_HTTPSTYLE_HEAD
     if(-1 != filesize) {
-      snprintf(buf, sizeof(data->state.buffer),
+      char clbuf[128];
+      snprintf(clbuf, sizeof(clbuf),
                "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
-      result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+      result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
       if(result)
         return result;
     }
@@ -2480,8 +2410,7 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
 
     return CURLE_OK;
   }
-  else
-    return InitiateTransfer(conn);
+  return InitiateTransfer(conn);
 }
 
 /* for LIST and RETR responses */
@@ -2492,7 +2421,6 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
   struct FTP *ftp = data->req.protop;
-  char *buf = data->state.buffer;
 
   if((ftpcode == 150) || (ftpcode == 125)) {
 
@@ -2536,6 +2464,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
        *
        * Example D above makes this parsing a little tricky */
       char *bytes;
+      char *buf = data->state.buffer;
       bytes=strstr(buf, " bytes");
       if(bytes--) {
         long in=(long)(bytes-buf);
@@ -2763,7 +2692,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
       }
 #endif
 
-      if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+      if(data->set.use_ssl &&
+         (!conn->ssl[FIRSTSOCKET].use ||
+          (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
+           !conn->proxy_ssl[FIRSTSOCKET].use))) {
         /* We don't have a SSL/TLS connection yet, but FTPS is
            requested. Try a FTPS connection now */
 
@@ -2808,7 +2740,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
         /* Curl_ssl_connect is BLOCKING */
         result = Curl_ssl_connect(conn, FIRSTSOCKET);
         if(!result) {
-          conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */
+          conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
           result = ftp_state_user(conn);
         }
       }
@@ -2850,7 +2782,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
     case FTP_PROT:
       if(ftpcode/100 == 2)
         /* We have enabled SSL for the data connection! */
-        conn->ssl[SECONDARYSOCKET].use =
+        conn->bits.ftp_use_data_ssl =
           (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
       /* FTP servers typically responds with 500 if they decide to reject
          our 'P' request */
@@ -2891,6 +2823,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
     case FTP_PWD:
       if(ftpcode == 257) {
         char *ptr=&data->state.buffer[4];  /* start on the first letter */
+        const size_t buf_size = data->set.buffer_size;
         char *dir;
         char *store;
 
@@ -2908,7 +2841,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
         */
 
         /* scan for the first double-quote for non-standard responses */
-        while(ptr < &data->state.buffer[sizeof(data->state.buffer)]
+        while(ptr < &data->state.buffer[buf_size]
               && *ptr != '\n' && *ptr != '\0' && *ptr != '"')
           ptr++;
 
@@ -2938,7 +2871,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
              does not start with a '/'), we probably need some server-dependent
              adjustments. For example, this is the case when connecting to
              an OS400 FTP server: this server supports two name syntaxes,
-             the default one being incompatible with standard pathes. In
+             the default one being incompatible with standard paths. In
              addition, this server switches automatically to the regular path
              syntax when one is encountered in a command: this results in
              having an entrypath in the wrong syntax when later used in CWD.
@@ -3012,12 +2945,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
           state(conn, FTP_NAMEFMT);
           break;
         }
-        else {
-          /* Nothing special for the target server. */
-          /* remember target server OS */
-          Curl_safefree(ftpc->server_os);
-          ftpc->server_os = os;
-        }
+        /* Nothing special for the target server. */
+        /* remember target server OS */
+        Curl_safefree(ftpc->server_os);
+        ftpc->server_os = os;
       }
       else {
         /* Cannot identify server OS. Continue anyway and cross fingers. */
@@ -3250,7 +3181,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
   ssize_t nread;
   int ftpcode;
   CURLcode result = CURLE_OK;
-  char *path;
+  char *path = NULL;
   const char *path_to_use = data->state.path;
 
   if(!ftp)
@@ -3278,6 +3209,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
 
     /* until we cope better with prematurely ended requests, let them
      * fallback as if in complete failure */
+    /* FALLTHROUGH */
   default:       /* by default, an error means the control connection is
                     wedged and should not be used anymore */
     ftpc->ctl_valid = FALSE;
@@ -3621,7 +3553,7 @@ static CURLcode ftp_range(struct connectdata *conn)
                  " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
                  CURL_FORMAT_CURL_OFF_T " bytes\n",
                  from, to, data->req.maxdownload));
-    ftpc->dont_check = TRUE; /* dont check for successful transfer */
+    ftpc->dont_check = TRUE; /* don't check for successful transfer */
   }
   else
     data->req.maxdownload = -1;
@@ -3656,7 +3588,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
     if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
       /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
          aren't used so we blank their arguments. TODO: make this nicer */
-      result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE);
+      result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
 
       return result;
     }
@@ -3666,10 +3598,6 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
     /* Ready to do more? */
     if(connected) {
       DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
-      if(conn->bits.proxy) {
-        infof(data, "Connection to proxy confirmed\n");
-        result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
-      }
     }
     else {
       if(result && (ftpc->count1 == 0)) {
@@ -3681,6 +3609,18 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
     }
   }
 
+  result = Curl_proxy_connect(conn, SECONDARYSOCKET);
+  if(result)
+    return result;
+
+  if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
+    return result;
+
+  if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
+     conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE)
+    return result;
+
+
   if(ftpc->state) {
     /* already in a state so skip the initial commands.
        They are only done to kickstart the do_more state */
@@ -3856,12 +3796,10 @@ static CURLcode init_wc_data(struct connectdata *conn)
       result = ftp_parse_url_path(conn);
       return result;
     }
-    else {
-      wildcard->pattern = strdup(last_slash);
-      if(!wildcard->pattern)
-        return CURLE_OUT_OF_MEMORY;
-      last_slash[0] = '\0'; /* cut file from path */
-    }
+    wildcard->pattern = strdup(last_slash);
+    if(!wildcard->pattern)
+      return CURLE_OUT_OF_MEMORY;
+    last_slash[0] = '\0'; /* cut file from path */
   }
   else { /* there is only 'wildcard pattern' or nothing */
     if(path[0]) {
@@ -3940,14 +3878,13 @@ static CURLcode wc_statemach(struct connectdata *conn)
   struct WildcardData * const wildcard = &(conn->data->wildcard);
   CURLcode result = CURLE_OK;
 
-  switch (wildcard->state) {
+  switch(wildcard->state) {
   case CURLWC_INIT:
     result = init_wc_data(conn);
     if(wildcard->state == CURLWC_CLEAN)
       /* only listing! */
       break;
-    else
-      wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
+    wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
     break;
 
   case CURLWC_MATCHING: {
@@ -3965,7 +3902,7 @@ static CURLcode wc_statemach(struct connectdata *conn)
       wildcard->state = CURLWC_CLEAN;
       return wc_statemach(conn);
     }
-    else if(wildcard->filelist->size == 0) {
+    if(wildcard->filelist.size == 0) {
       /* no corresponding file */
       wildcard->state = CURLWC_CLEAN;
       return CURLE_REMOTE_FILE_NOT_FOUND;
@@ -3976,7 +3913,7 @@ static CURLcode wc_statemach(struct connectdata *conn)
   case CURLWC_DOWNLOADING: {
     /* filelist has at least one file, lets get first one */
     struct ftp_conn *ftpc = &conn->proto.ftpc;
-    struct curl_fileinfo *finfo = wildcard->filelist->head->ptr;
+    struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
 
     char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
     if(!tmp_path)
@@ -3991,7 +3928,7 @@ static CURLcode wc_statemach(struct connectdata *conn)
     infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
     if(conn->data->set.chunk_bgn) {
       long userresponse = conn->data->set.chunk_bgn(
-          finfo, wildcard->customptr, (int)wildcard->filelist->size);
+        finfo, wildcard->customptr, (int)wildcard->filelist.size);
       switch(userresponse) {
       case CURL_CHUNK_BGN_FUNC_SKIP:
         infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
@@ -4016,9 +3953,9 @@ static CURLcode wc_statemach(struct connectdata *conn)
       return result;
 
     /* we don't need the Curl_fileinfo of first file anymore */
-    Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
+    Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
 
-    if(wildcard->filelist->size == 0) { /* remains only one file to down. */
+    if(wildcard->filelist.size == 0) { /* remains only one file to down. */
       wildcard->state = CURLWC_CLEAN;
       /* after that will be ftp_do called once again and no transfer
          will be done because of CURLWC_CLEAN state */
@@ -4029,8 +3966,8 @@ static CURLcode wc_statemach(struct connectdata *conn)
   case CURLWC_SKIP: {
     if(conn->data->set.chunk_end)
       conn->data->set.chunk_end(conn->data->wildcard.customptr);
-    Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
-    wildcard->state = (wildcard->filelist->size == 0) ?
+    Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
+    wildcard->state = (wildcard->filelist.size == 0) ?
                       CURLWC_CLEAN : CURLWC_DOWNLOADING;
     return wc_statemach(conn);
   }
@@ -4046,6 +3983,7 @@ static CURLcode wc_statemach(struct connectdata *conn)
 
   case CURLWC_DONE:
   case CURLWC_ERROR:
+  case CURLWC_CLEAR:
     break;
   }
 
@@ -4247,8 +4185,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
   const char *cur_pos;
   const char *filename = NULL;
 
-  cur_pos = path_to_use; /* current position in path. point at the begin
-                            of next path component */
+  cur_pos = path_to_use; /* current position in path. point at the begin of
+                            next path component */
 
   ftpc->ctl_valid = FALSE;
   ftpc->cwdfail = FALSE;
@@ -4343,7 +4281,6 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
                            &ftpc->dirs[ftpc->dirdepth], NULL,
                            TRUE);
           if(result) {
-            free(ftpc->dirs[ftpc->dirdepth]);
             freedirs(ftpc);
             return result;
           }
@@ -4568,7 +4505,7 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
     command = Curl_raw_toupper(type[6]);
     conn->bits.type_set = TRUE;
 
-    switch (command) {
+    switch(command) {
     case 'A': /* ASCII mode */
       data->set.prefer_ascii = TRUE;
       break;
diff --git a/Utilities/cmcurl/lib/ftp.h b/Utilities/cmcurl/lib/ftp.h
index dbd8567..3bbf262 100644
--- a/Utilities/cmcurl/lib/ftp.h
+++ b/Utilities/cmcurl/lib/ftp.h
@@ -143,7 +143,7 @@ struct ftp_conn {
   ftpstate state_saved; /* transfer type saved to be reloaded after
                            data connection is established */
   curl_off_t retr_size_saved; /* Size of retrieved file saved */
-  char * server_os;     /* The target server operating system. */
+  char *server_os;     /* The target server operating system. */
   curl_off_t known_filesize; /* file size is different from -1, if wildcard
                                 LIST parsing was done and wc_statemach set
                                 it */
diff --git a/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c
index 747dbba..2acce31 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -165,7 +165,7 @@ struct ftp_parselist_data {
   } state;
 
   CURLcode error;
-  struct curl_fileinfo *file_data;
+  struct fileinfo *file_data;
   unsigned int item_length;
   size_t item_offset;
   struct {
@@ -275,14 +275,15 @@ static void PL_ERROR(struct connectdata *conn, CURLcode err)
 }
 
 static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
-                                    struct curl_fileinfo *finfo)
+                                    struct fileinfo *infop)
 {
   curl_fnmatch_callback compare;
   struct WildcardData *wc = &conn->data->wildcard;
   struct ftp_wc_tmpdata *tmpdata = wc->tmp;
-  struct curl_llist *llist = wc->filelist;
+  struct curl_llist *llist = &wc->filelist;
   struct ftp_parselist_data *parser = tmpdata->parser;
   bool add = TRUE;
+  struct curl_fileinfo *finfo = &infop->info;
 
   /* move finfo pointers to b_data */
   char *str = finfo->b_data;
@@ -316,11 +317,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
   }
 
   if(add) {
-    if(!Curl_llist_insert_next(llist, llist->tail, finfo)) {
-      Curl_fileinfo_dtor(NULL, finfo);
-      tmpdata->parser->file_data = NULL;
-      return CURLE_OUT_OF_MEMORY;
-    }
+    Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
   }
   else {
     Curl_fileinfo_dtor(NULL, finfo);
@@ -337,6 +334,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
   struct connectdata *conn = (struct connectdata *)connptr;
   struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
   struct ftp_parselist_data *parser = tmpdata->parser;
+  struct fileinfo *infop;
   struct curl_fileinfo *finfo;
   unsigned long i = 0;
   CURLcode result;
@@ -366,17 +364,18 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
         parser->error = CURLE_OUT_OF_MEMORY;
         return bufflen;
       }
-      parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE);
-      if(!parser->file_data->b_data) {
+      parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE);
+      if(!parser->file_data->info.b_data) {
         PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
         return bufflen;
       }
-      parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE;
+      parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE;
       parser->item_offset = 0;
       parser->item_length = 0;
     }
 
-    finfo = parser->file_data;
+    infop = parser->file_data;
+    finfo = &infop->info;
     finfo->b_data[finfo->b_used++] = c;
 
     if(finfo->b_used >= finfo->b_size - 1) {
@@ -396,9 +395,9 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
       }
     }
 
-    switch (parser->os_type) {
+    switch(parser->os_type) {
     case OS_TYPE_UNIX:
-      switch (parser->state.UNIX.main) {
+      switch(parser->state.UNIX.main) {
       case PL_UNIX_TOTALSIZE:
         switch(parser->state.UNIX.sub.total_dirsize) {
         case PL_UNIX_TOTALSIZE_INIT:
@@ -433,10 +432,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
                 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
                 return bufflen;
               }
-              else {
-                parser->state.UNIX.main = PL_UNIX_FILETYPE;
-                finfo->b_used = 0;
-              }
+              parser->state.UNIX.main = PL_UNIX_FILETYPE;
+              finfo->b_used = 0;
             }
             else {
               PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
@@ -447,7 +444,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
         }
         break;
       case PL_UNIX_FILETYPE:
-        switch (c) {
+        switch(c) {
         case '-':
           finfo->filetype = CURLFILETYPE_FILE;
           break;
@@ -500,8 +497,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
             return bufflen;
           }
-          parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM;
-          parser->file_data->perm = perm;
+          parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM;
+          parser->file_data->info.perm = perm;
           parser->offsets.perm = parser->item_offset;
 
           parser->item_length = 0;
@@ -532,8 +529,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
             hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
             if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
-              parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
-              parser->file_data->hardlinks = hlinks;
+              parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
+              parser->file_data->info.hardlinks = hlinks;
             }
             parser->item_length = 0;
             parser->item_offset = 0;
@@ -615,8 +612,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
             if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
                                fsize != CURL_OFF_T_MIN) {
-              parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
-              parser->file_data->size = fsize;
+              parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
+              parser->file_data->info.size = fsize;
             }
             parser->item_length = 0;
             parser->item_offset = 0;
@@ -733,7 +730,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
             parser->offsets.filename = parser->item_offset;
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
-            result = ftp_pl_insert_finfo(conn, finfo);
+            result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
               PL_ERROR(conn, result);
               return bufflen;
@@ -745,7 +742,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
             parser->offsets.filename = parser->item_offset;
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
-            result = ftp_pl_insert_finfo(conn, finfo);
+            result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
               PL_ERROR(conn, result);
               return bufflen;
@@ -840,7 +837,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
           else if(c == '\n') {
             finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
             parser->offsets.symlink_target = parser->item_offset;
-            result = ftp_pl_insert_finfo(conn, finfo);
+            result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
               PL_ERROR(conn, result);
               return bufflen;
@@ -852,7 +849,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
           if(c == '\n') {
             finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
             parser->offsets.symlink_target = parser->item_offset;
-            result = ftp_pl_insert_finfo(conn, finfo);
+            result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
               PL_ERROR(conn, result);
               return bufflen;
@@ -955,10 +952,10 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
                 return bufflen;
               }
               /* correct file type */
-              parser->file_data->filetype = CURLFILETYPE_FILE;
+              parser->file_data->info.filetype = CURLFILETYPE_FILE;
             }
 
-            parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
+            parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
             parser->item_length = 0;
             parser->state.NT.main = PL_WINNT_FILENAME;
             parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
@@ -967,7 +964,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
         }
         break;
       case PL_WINNT_FILENAME:
-        switch (parser->state.NT.sub.filename) {
+        switch(parser->state.NT.sub.filename) {
         case PL_WINNT_FILENAME_PRESPACE:
           if(c != ' ') {
             parser->item_offset = finfo->b_used -1;
@@ -985,7 +982,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->offsets.filename = parser->item_offset;
             finfo->b_data[finfo->b_used - 1] = 0;
             parser->offsets.filename = parser->item_offset;
-            result = ftp_pl_insert_finfo(conn, finfo);
+            result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
               PL_ERROR(conn, result);
               return bufflen;
@@ -997,7 +994,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
         case PL_WINNT_FILENAME_WINEOL:
           if(c == '\n') {
             parser->offsets.filename = parser->item_offset;
-            result = ftp_pl_insert_finfo(conn, finfo);
+            result = ftp_pl_insert_finfo(conn, infop);
             if(result) {
               PL_ERROR(conn, result);
               return bufflen;
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index 9641d79..a1ce505 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -36,8 +36,11 @@
 #include "memdebug.h"
 
 /*
- * This is supposed to be called in the beginning of a perform() session and
- * in curl_easy_reset() and should reset all session-info variables.
+ * Initialize statistical and informational data.
+ *
+ * This function is called in curl_easy_reset, curl_easy_duphandle and at the
+ * beginning of a perform session. It must reset the session-info variables,
+ * in particular all variables in struct PureInfo.
  */
 CURLcode Curl_initinfo(struct Curl_easy *data)
 {
@@ -75,6 +78,9 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
   info->conn_primary_port = 0;
   info->conn_local_port = 0;
 
+  info->conn_scheme = 0;
+  info->conn_protocol = 0;
+
 #ifdef USE_SSL
   Curl_ssl_free_certinfo(data);
 #endif
@@ -83,7 +89,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
 }
 
 static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
-                             char **param_charp)
+                             const char **param_charp)
 {
   switch(info) {
   case CURLINFO_EFFECTIVE_URL:
@@ -120,6 +126,9 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
   case CURLINFO_RTSP_SESSION_ID:
     *param_charp = data->set.str[STRING_RTSP_SESSION_ID];
     break;
+  case CURLINFO_SCHEME:
+    *param_charp = data->info.conn_scheme;
+    break;
 
   default:
     return CURLE_UNKNOWN_OPTION;
@@ -157,6 +166,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
   case CURLINFO_SSL_VERIFYRESULT:
     *param_longp = data->set.ssl.certverifyresult;
     break;
+  case CURLINFO_PROXY_SSL_VERIFYRESULT:
+    *param_longp = data->set.proxy_ssl.certverifyresult;
+    break;
   case CURLINFO_REDIRECT_COUNT:
     *param_longp = data->set.followlocation;
     break;
@@ -208,7 +220,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
     *param_longp = data->state.rtsp_CSeq_recv;
     break;
   case CURLINFO_HTTP_VERSION:
-    switch (data->info.httpversion) {
+    switch(data->info.httpversion) {
     case 10:
       *param_longp = CURL_HTTP_VERSION_1_0;
       break;
@@ -223,6 +235,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
       break;
     }
     break;
+  case CURLINFO_PROTOCOL:
+    *param_longp = data->info.conn_protocol;
+    break;
 
   default:
     return CURLE_UNKNOWN_OPTION;
@@ -379,7 +394,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
   va_list arg;
   long *param_longp = NULL;
   double *param_doublep = NULL;
-  char **param_charp = NULL;
+  const char **param_charp = NULL;
   struct curl_slist **param_slistp = NULL;
   curl_socket_t *param_socketp = NULL;
   int type;
@@ -393,7 +408,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
   type = CURLINFO_TYPEMASK & (int)info;
   switch(type) {
   case CURLINFO_STRING:
-    param_charp = va_arg(arg, char **);
+    param_charp = va_arg(arg, const char **);
     if(param_charp)
       result = getinfo_char(data, info, param_charp);
     break;
diff --git a/Utilities/cmcurl/lib/gopher.c b/Utilities/cmcurl/lib/gopher.c
index a073d0b..e6d2746 100644
--- a/Utilities/cmcurl/lib/gopher.c
+++ b/Utilities/cmcurl/lib/gopher.c
@@ -78,7 +78,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
 
   curl_off_t *bytecount = &data->req.bytecount;
   char *path = data->state.path;
-  char *sel;
+  char *sel = NULL;
   char *sel_org = NULL;
   ssize_t amount, k;
   size_t len;
@@ -106,8 +106,8 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
 
     /* ... and finally unescape */
     result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
-    if(!sel)
-      return CURLE_OUT_OF_MEMORY;
+    if(result)
+      return result;
     sel_org = sel;
   }
 
diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index 937381b..6afeaa1 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -37,8 +37,6 @@ hash_element_dtor(void *user, void *element)
   struct curl_hash *h = (struct curl_hash *) user;
   struct curl_hash_element *e = (struct curl_hash_element *) element;
 
-  Curl_safefree(e->key);
-
   if(e->ptr) {
     h->dtor(e->ptr);
     e->ptr = NULL;
@@ -74,54 +72,32 @@ Curl_hash_init(struct curl_hash *h,
   h->size = 0;
   h->slots = slots;
 
-  h->table = malloc(slots * sizeof(struct curl_llist *));
+  h->table = malloc(slots * sizeof(struct curl_llist));
   if(h->table) {
-    for(i = 0; i < slots; ++i) {
-      h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
-      if(!h->table[i]) {
-        while(i--) {
-          Curl_llist_destroy(h->table[i], NULL);
-          h->table[i] = NULL;
-        }
-        free(h->table);
-        h->table = NULL;
-        h->slots = 0;
-        return 1; /* failure */
-      }
-    }
+    for(i = 0; i < slots; ++i)
+      Curl_llist_init(&h->table[i], (curl_llist_dtor) hash_element_dtor);
     return 0; /* fine */
   }
-  else {
-    h->slots = 0;
-    return 1; /* failure */
-  }
+  h->slots = 0;
+  return 1; /* failure */
 }
 
 static struct curl_hash_element *
 mk_hash_element(const void *key, size_t key_len, const void *p)
 {
-  struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element));
-
+  /* allocate the struct plus memory after it to store the key */
+  struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element) +
+                                        key_len);
   if(he) {
-    void *dupkey = malloc(key_len);
-    if(dupkey) {
-      /* copy the key */
-      memcpy(dupkey, key, key_len);
-
-      he->key = dupkey;
-      he->key_len = key_len;
-      he->ptr = (void *) p;
-    }
-    else {
-      /* failed to duplicate the key, free memory and fail */
-      free(he);
-      he = NULL;
-    }
+    /* copy the key */
+    memcpy(he->key, key, key_len);
+    he->key_len = key_len;
+    he->ptr = (void *) p;
   }
   return he;
 }
 
-#define FETCH_LIST(x,y,z) x->table[x->hash_func(y, z, x->slots)]
+#define FETCH_LIST(x,y,z) &x->table[x->hash_func(y, z, x->slots)]
 
 /* Insert the data in the hash. If there already was a match in the hash,
  * that data is replaced.
@@ -135,7 +111,7 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
 {
   struct curl_hash_element  *he;
   struct curl_llist_element *le;
-  struct curl_llist *l = FETCH_LIST (h, key, key_len);
+  struct curl_llist *l = FETCH_LIST(h, key, key_len);
 
   for(le = l->head; le; le = le->next) {
     he = (struct curl_hash_element *) le->ptr;
@@ -148,18 +124,9 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
 
   he = mk_hash_element(key, key_len, p);
   if(he) {
-    if(Curl_llist_insert_next(l, l->tail, he)) {
-      ++h->size;
-      return p; /* return the new entry */
-    }
-    /*
-     * Couldn't insert it, destroy the 'he' element and the key again. We
-     * don't call hash_element_dtor() since that would also call the
-     * "destructor" for the actual data 'p'. When we fail, we shall not touch
-     * that data.
-     */
-    free(he->key);
-    free(he);
+    Curl_llist_insert_next(l, l->tail, he, &he->list);
+    ++h->size;
+    return p; /* return the new entry */
   }
 
   return NULL; /* failure */
@@ -243,8 +210,7 @@ Curl_hash_destroy(struct curl_hash *h)
   int i;
 
   for(i = 0; i < h->slots; ++i) {
-    Curl_llist_destroy(h->table[i], (void *) h);
-    h->table[i] = NULL;
+    Curl_llist_destroy(&h->table[i], (void *) h);
   }
 
   Curl_safefree(h->table);
@@ -276,7 +242,7 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
     return;
 
   for(i = 0; i < h->slots; ++i) {
-    list = h->table[i];
+    list = &h->table[i];
     le = list->head; /* get first list entry */
     while(le) {
       struct curl_hash_element *he = le->ptr;
@@ -291,9 +257,9 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
   }
 }
 
-size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num)
+size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num)
 {
-  const char* key_str = (const char *) key;
+  const char *key_str = (const char *) key;
   const char *end = key_str + key_length;
   unsigned long h = 5381;
 
@@ -335,8 +301,8 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
   /* If we have reached the end of the list, find the next one */
   if(!iter->current_element) {
     for(i = iter->slot_index;i < h->slots;i++) {
-      if(h->table[i]->head) {
-        iter->current_element = h->table[i]->head;
+      if(h->table[i].head) {
+        iter->current_element = h->table[i].head;
         iter->slot_index = i+1;
         break;
       }
@@ -347,10 +313,8 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
     struct curl_hash_element *he = iter->current_element->ptr;
     return he;
   }
-  else {
-    iter->current_element = NULL;
-    return NULL;
-  }
+  iter->current_element = NULL;
+  return NULL;
 }
 
 #if 0 /* useful function for debugging hashes and their contents */
diff --git a/Utilities/cmcurl/lib/hash.h b/Utilities/cmcurl/lib/hash.h
index 57a17f0..90a25d1 100644
--- a/Utilities/cmcurl/lib/hash.h
+++ b/Utilities/cmcurl/lib/hash.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -29,22 +29,22 @@
 #include "llist.h"
 
 /* Hash function prototype */
-typedef size_t (*hash_function) (void* key,
+typedef size_t (*hash_function) (void *key,
                                  size_t key_length,
                                  size_t slots_num);
 
 /*
    Comparator function prototype. Compares two keys.
 */
-typedef size_t (*comp_function) (void* key1,
+typedef size_t (*comp_function) (void *key1,
                                  size_t key1_len,
-                                 void*key2,
+                                 void *key2,
                                  size_t key2_len);
 
 typedef void (*curl_hash_dtor)(void *);
 
 struct curl_hash {
-  struct curl_llist **table;
+  struct curl_llist *table;
 
   /* Hash function to be used for this hash table */
   hash_function hash_func;
@@ -57,9 +57,10 @@ struct curl_hash {
 };
 
 struct curl_hash_element {
+  struct curl_llist_element list;
   void   *ptr;
-  char   *key;
   size_t key_len;
+  char   key[1]; /* allocated memory following the struct */
 };
 
 struct curl_hash_iterator {
@@ -76,7 +77,7 @@ int Curl_hash_init(struct curl_hash *h,
 
 void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p);
 int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len);
-void *Curl_hash_pick(struct curl_hash *, void * key, size_t key_len);
+void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len);
 void Curl_hash_apply(struct curl_hash *h, void *user,
                      void (*cb)(void *user, void *ptr));
 int Curl_hash_count(struct curl_hash *h);
@@ -84,10 +85,9 @@ void Curl_hash_destroy(struct curl_hash *h);
 void Curl_hash_clean(struct curl_hash *h);
 void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
                                     int (*comp)(void *, void *));
-size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num);
-size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2,
+size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num);
+size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2,
                             size_t key2_len);
-
 void Curl_hash_start_iterate(struct curl_hash *hash,
                              struct curl_hash_iterator *iter);
 struct curl_hash_element *
diff --git a/Utilities/cmcurl/lib/hmac.c b/Utilities/cmcurl/lib/hmac.c
index 3df4715..dae9505 100644
--- a/Utilities/cmcurl/lib/hmac.c
+++ b/Utilities/cmcurl/lib/hmac.c
@@ -49,12 +49,12 @@ static const unsigned char hmac_opad = 0x5C;
 
 HMAC_context *
 Curl_HMAC_init(const HMAC_params * hashparams,
-               const unsigned char * key,
+               const unsigned char *key,
                unsigned int keylen)
 {
   size_t i;
-  HMAC_context * ctxt;
-  unsigned char * hkey;
+  HMAC_context *ctxt;
+  unsigned char *hkey;
   unsigned char b;
 
   /* Create HMAC context. */
@@ -101,7 +101,7 @@ Curl_HMAC_init(const HMAC_params * hashparams,
 }
 
 int Curl_HMAC_update(HMAC_context * ctxt,
-                     const unsigned char * data,
+                     const unsigned char *data,
                      unsigned int len)
 {
   /* Update first hash calculation. */
@@ -110,7 +110,7 @@ int Curl_HMAC_update(HMAC_context * ctxt,
 }
 
 
-int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result)
+int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result)
 {
   const HMAC_params * hashparams = ctxt->hmac_hash;
 
diff --git a/Utilities/cmcurl/lib/hostcheck.c b/Utilities/cmcurl/lib/hostcheck.c
index f545254..156091c 100644
--- a/Utilities/cmcurl/lib/hostcheck.c
+++ b/Utilities/cmcurl/lib/hostcheck.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -22,7 +22,10 @@
 
 #include "curl_setup.h"
 
-#if defined(USE_OPENSSL) || defined(USE_AXTLS) || defined(USE_GSKIT)
+#if defined(USE_OPENSSL)                                \
+  || defined(USE_AXTLS)                                 \
+  || defined(USE_GSKIT)                                 \
+  || (defined(USE_SCHANNEL) && defined(_WIN32_WCE))
 /* these backends use functions from this file */
 
 #ifdef HAVE_NETINET_IN_H
@@ -84,7 +87,7 @@ static int hostmatch(char *hostname, char *pattern)
   if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0)
     return CURL_HOST_NOMATCH;
 #ifdef ENABLE_IPV6
-  else if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0)
+  if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0)
     return CURL_HOST_NOMATCH;
 #endif
 
@@ -144,4 +147,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
   return res;
 }
 
-#endif /* OPENSSL or AXTLS or GSKIT */
+#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index 24a922e..619ec84 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -143,7 +143,7 @@ void Curl_global_host_cache_dtor(void)
 }
 
 /*
- * Return # of adresses in a Curl_addrinfo struct
+ * Return # of addresses in a Curl_addrinfo struct
  */
 int Curl_num_addresses(const Curl_addrinfo *addr)
 {
@@ -172,7 +172,7 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
   const struct in6_addr *ipaddr6;
 #endif
 
-  switch (ai->ai_family) {
+  switch(ai->ai_family) {
     case AF_INET:
       sa4 = (const void *)ai->ai_addr;
       ipaddr4 = &sa4->sin_addr;
@@ -538,7 +538,6 @@ RETSIGTYPE alarmfunc(int sig)
   /* this is for "-ansi -Wall -pedantic" to stop complaining!   (rabe) */
   (void)sig;
   siglongjmp(curl_jmpenv, 1);
-  return;
 }
 #endif /* USE_ALARM_TIMEOUT */
 
@@ -568,12 +567,12 @@ int Curl_resolv_timeout(struct connectdata *conn,
                         const char *hostname,
                         int port,
                         struct Curl_dns_entry **entry,
-                        long timeoutms)
+                        time_t timeoutms)
 {
 #ifdef USE_ALARM_TIMEOUT
 #ifdef HAVE_SIGACTION
   struct sigaction keep_sigact;   /* store the old struct here */
-  volatile bool keep_copysig = FALSE; /* wether old sigact has been saved */
+  volatile bool keep_copysig = FALSE; /* whether old sigact has been saved */
   struct sigaction sigact;
 #else
 #ifdef HAVE_SIGNAL
@@ -597,7 +596,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
     /* Ignore the timeout when signals are disabled */
     timeout = 0;
   else
-    timeout = timeoutms;
+    timeout = (timeoutms > LONG_MAX) ? LONG_MAX : (long)timeoutms;
 
   if(!timeout)
     /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
@@ -689,10 +688,11 @@ clean_up:
      the time we spent until now! */
   if(prev_alarm) {
     /* there was an alarm() set before us, now put it back */
-    unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
+    unsigned long elapsed_secs = (unsigned long) (Curl_tvdiff(Curl_tvnow(),
+                                   conn->created) / 1000);
 
     /* the alarm period is counted in even number of seconds */
-    unsigned long alarm_set = prev_alarm - elapsed_ms/1000;
+    unsigned long alarm_set = prev_alarm - elapsed_secs;
 
     if(!alarm_set ||
        ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index 9098ee3..298eeee 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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 @@ int Curl_resolv(struct connectdata *conn, const char *hostname,
                 int port, struct Curl_dns_entry **dnsentry);
 int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
                         int port, struct Curl_dns_entry **dnsentry,
-                        long timeoutms);
+                        time_t timeoutms);
 
 #ifdef CURLRES_IPV6
 /*
@@ -130,8 +130,8 @@ int Curl_mk_dnscache(struct curl_hash *hash);
 /* prune old entries from the DNS cache */
 void Curl_hostcache_prune(struct Curl_easy *data);
 
-/* Return # of adresses in a Curl_addrinfo struct */
-int Curl_num_addresses (const Curl_addrinfo *addr);
+/* Return # of addresses in a Curl_addrinfo struct */
+int Curl_num_addresses(const Curl_addrinfo *addr);
 
 #if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
 int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
@@ -143,7 +143,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
 #endif
 
 /* IPv4 threadsafe resolve function used for synch and asynch builds */
-Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port);
+Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
 
 CURLcode Curl_async_resolved(struct connectdata *conn,
                              bool *protocol_connect);
diff --git a/Utilities/cmcurl/lib/hostip4.c b/Utilities/cmcurl/lib/hostip4.c
index 15895d7..e459328 100644
--- a/Utilities/cmcurl/lib/hostip4.c
+++ b/Utilities/cmcurl/lib/hostip4.c
@@ -291,7 +291,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
      * gethostbyname() is the preferred one.
      */
   else {
-    h = gethostbyname((void*)hostname);
+    h = gethostbyname((void *)hostname);
 #endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
   }
 
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index e7788e7..21574e2 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -76,6 +76,7 @@
 #include "pipeline.h"
 #include "http2.h"
 #include "connect.h"
+#include "strdup.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -284,11 +285,12 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
   const char *user;
   const char *pwd;
   CURLcode result;
+  char *out;
 
   if(proxy) {
     userp = &conn->allocptr.proxyuserpwd;
-    user = conn->proxyuser;
-    pwd = conn->proxypasswd;
+    user = conn->http_proxy.user;
+    pwd = conn->http_proxy.passwd;
   }
   else {
     userp = &conn->allocptr.userpwd;
@@ -296,26 +298,32 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
     pwd = conn->passwd;
   }
 
-  snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
+  out = aprintf("%s:%s", user, pwd);
+  if(!out)
+    return CURLE_OUT_OF_MEMORY;
 
-  result = Curl_base64_encode(data,
-                              data->state.buffer, strlen(data->state.buffer),
-                              &authorization, &size);
+  result = Curl_base64_encode(data, out, strlen(out), &authorization, &size);
   if(result)
-    return result;
+    goto fail;
 
-  if(!authorization)
-    return CURLE_REMOTE_ACCESS_DENIED;
+  if(!authorization) {
+    result = CURLE_REMOTE_ACCESS_DENIED;
+    goto fail;
+  }
 
   free(*userp);
   *userp = aprintf("%sAuthorization: Basic %s\r\n",
                    proxy ? "Proxy-" : "",
                    authorization);
   free(authorization);
-  if(!*userp)
-    return CURLE_OUT_OF_MEMORY;
+  if(!*userp) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto fail;
+  }
 
-  return CURLE_OK;
+  fail:
+  free(out);
+  return result;
 }
 
 /* pickoneauth() selects the most favourable authentication method from the
@@ -411,8 +419,6 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
     case HTTPREQ_POST:
       if(data->state.infilesize != -1)
         expectsend = data->state.infilesize;
-      else if(data->set.postfields)
-        expectsend = (curl_off_t)strlen(data->set.postfields);
       break;
     case HTTPREQ_PUT:
       if(data->state.infilesize != -1)
@@ -544,8 +550,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
     }
   }
   if(http_should_fail(conn)) {
-    failf (data, "The requested URL returned error: %d",
-           data->req.httpcode);
+    failf(data, "The requested URL returned error: %d",
+          data->req.httpcode);
     result = CURLE_HTTP_RETURNED_ERROR;
   }
 
@@ -641,12 +647,12 @@ output_auth_headers(struct connectdata *conn,
   if(auth) {
     infof(data, "%s auth using %s with user '%s'\n",
           proxy ? "Proxy" : "Server", auth,
-          proxy ? (conn->proxyuser ? conn->proxyuser : "") :
+          proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") :
                   (conn->user ? conn->user : ""));
-    authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
+    authstatus->multipass = (!authstatus->done) ? TRUE : FALSE;
   }
   else
-    authstatus->multi = FALSE;
+    authstatus->multipass = FALSE;
 
   return CURLE_OK;
 }
@@ -839,9 +845,11 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
                   auth += strlen("NTLM");
                   while(*auth && ISSPACE(*auth))
                     auth++;
-                  if(*auth)
-                    if((conn->challenge_header = strdup(auth)) == NULL)
+                  if(*auth) {
+                    conn->challenge_header = strdup(auth);
+                    if(!conn->challenge_header)
                       return CURLE_OUT_OF_MEMORY;
+                  }
                 }
               }
 #endif
@@ -1098,14 +1106,16 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
     return result;
   }
 
-  if((conn->handler->flags & PROTOPT_SSL) && conn->httpversion != 20) {
+  if((conn->handler->flags & PROTOPT_SSL ||
+     conn->http_proxy.proxytype == CURLPROXY_HTTPS)
+     && conn->httpversion != 20) {
     /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
        when we speak HTTPS, as if only a fraction of it is sent now, this data
        needs to fit into the normal read-callback buffer later on and that
        buffer is using this size.
     */
 
-    sendsize = (size > CURL_MAX_WRITE_SIZE) ? CURL_MAX_WRITE_SIZE : size;
+    sendsize = CURLMIN(size, CURL_MAX_WRITE_SIZE);
 
     /* OpenSSL is very picky and we must send the SAME buffer pointer to the
        library when we attempt to re-send this buffer. Sending the same data
@@ -1191,8 +1201,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
            This needs FIXing.
         */
         return CURLE_SEND_ERROR;
-      else
-        Curl_pipeline_leave_write(conn);
+      Curl_pipeline_leave_write(conn);
     }
   }
   Curl_add_buffer_free(in);
@@ -1255,14 +1264,13 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
 
     if(in->buffer)
       /* we have a buffer, enlarge the existing one */
-      new_rb = realloc(in->buffer, new_size);
+      new_rb = Curl_saferealloc(in->buffer, new_size);
     else
       /* create a new buffer */
       new_rb = malloc(new_size);
 
     if(!new_rb) {
       /* If we failed, we cleanup the whole buffer and return error */
-      Curl_safefree(in->buffer);
       free(in);
       return CURLE_OUT_OF_MEMORY;
     }
@@ -1350,15 +1358,22 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
   connkeep(conn, "HTTP default");
 
   /* the CONNECT procedure might not have been completed */
-  result = Curl_proxy_connect(conn);
+  result = Curl_proxy_connect(conn, FIRSTSOCKET);
   if(result)
     return result;
 
+  if(conn->bits.proxy_connect_closed)
+    /* this is not an error, just part of the connection negotiation */
+    return CURLE_OK;
+
+  if(CONNECT_FIRSTSOCKET_PROXY_SSL())
+    return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
+
   if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
     /* nothing else to do except wait right now - we're not done here. */
     return CURLE_OK;
 
-  if(conn->given->flags & PROTOPT_SSL) {
+  if(conn->given->protocol & CURLPROTO_HTTPS) {
     /* perform SSL initialization */
     result = https_connecting(conn, done);
     if(result)
@@ -1396,50 +1411,16 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
 
   return result;
 }
-#endif
 
-#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
-    defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
-    defined(USE_MBEDTLS)
-/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
-   It should be made to query the generic SSL layer instead. */
 static int https_getsock(struct connectdata *conn,
                          curl_socket_t *socks,
                          int numsocks)
 {
-  if(conn->handler->flags & PROTOPT_SSL) {
-    struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
-
-    if(!numsocks)
-      return GETSOCK_BLANK;
-
-    if(connssl->connecting_state == ssl_connect_2_writing) {
-      /* write mode */
-      socks[0] = conn->sock[FIRSTSOCKET];
-      return GETSOCK_WRITESOCK(0);
-    }
-    else if(connssl->connecting_state == ssl_connect_2_reading) {
-      /* read mode */
-      socks[0] = conn->sock[FIRSTSOCKET];
-      return GETSOCK_READSOCK(0);
-    }
-  }
-
-  return CURLE_OK;
-}
-#else
-#ifdef USE_SSL
-static int https_getsock(struct connectdata *conn,
-                         curl_socket_t *socks,
-                         int numsocks)
-{
-  (void)conn;
-  (void)socks;
-  (void)numsocks;
+  if(conn->handler->flags & PROTOPT_SSL)
+    return Curl_ssl_getsock(conn, socks, numsocks);
   return GETSOCK_BLANK;
 }
 #endif /* USE_SSL */
-#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
 
 /*
  * Curl_http_done() gets called after a single HTTP request has been
@@ -1452,7 +1433,10 @@ CURLcode Curl_http_done(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct HTTP *http = data->req.protop;
 
-  infof(data, "Curl_http_done: called premature == %d\n", premature);
+  /* Clear multipass flag. If authentication isn't done yet, then it will get
+   * a chance to be set back to true when we output the next auth header */
+  data->state.authhost.multipass = FALSE;
+  data->state.authproxy.multipass = FALSE;
 
   Curl_unencode_cleanup(conn);
 
@@ -1538,6 +1522,20 @@ static bool use_http_1_1plus(const struct Curl_easy *data,
           (data->set.httpversion >= CURL_HTTP_VERSION_1_1));
 }
 
+static const char *get_http_string(const struct Curl_easy *data,
+                                   const struct connectdata *conn)
+{
+#ifdef USE_NGHTTP2
+  if(conn->proto.httpc.h2)
+    return "2";
+#endif
+
+  if(use_http_1_1plus(data, conn))
+    return "1.1";
+
+  return "1.0";
+}
+
 /* check and possibly add an Expect: header */
 static CURLcode expect100(struct Curl_easy *data,
                           struct connectdata *conn,
@@ -1695,9 +1693,10 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
                                 Curl_send_buffer *req_buffer)
 {
   const struct tm *tm;
-  char *buf = data->state.buffer;
   struct tm keeptime;
   CURLcode result;
+  char datestr[80];
+  const char *condp;
 
   if(data->set.timecondition == CURL_TIMECOND_NONE)
     /* no condition was asked for */
@@ -1710,6 +1709,21 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
   }
   tm = &keeptime;
 
+  switch(data->set.timecondition) {
+  default:
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  case CURL_TIMECOND_IFMODSINCE:
+    condp = "If-Modified-Since";
+    break;
+  case CURL_TIMECOND_IFUNMODSINCE:
+    condp = "If-Unmodified-Since";
+    break;
+  case CURL_TIMECOND_LASTMOD:
+    condp = "Last-Modified";
+    break;
+  }
+
   /* The If-Modified-Since header family should have their times set in
    * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
    * represented in Greenwich Mean Time (GMT), without exception. For the
@@ -1718,8 +1732,9 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
    */
 
   /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
-  snprintf(buf, BUFSIZE-1,
-           "%s, %02d %s %4d %02d:%02d:%02d GMT",
+  snprintf(datestr, sizeof(datestr),
+           "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+           condp,
            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
            tm->tm_mday,
            Curl_month[tm->tm_mon],
@@ -1728,22 +1743,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
            tm->tm_min,
            tm->tm_sec);
 
-  switch(data->set.timecondition) {
-  default:
-    break;
-  case CURL_TIMECOND_IFMODSINCE:
-    result = Curl_add_bufferf(req_buffer,
-                              "If-Modified-Since: %s\r\n", buf);
-    break;
-  case CURL_TIMECOND_IFUNMODSINCE:
-    result = Curl_add_bufferf(req_buffer,
-                              "If-Unmodified-Since: %s\r\n", buf);
-    break;
-  case CURL_TIMECOND_LASTMOD:
-    result = Curl_add_bufferf(req_buffer,
-                              "Last-Modified: %s\r\n", buf);
-    break;
-  }
+  result = Curl_add_buffer(req_buffer, datestr, strlen(datestr));
 
   return result;
 }
@@ -1876,7 +1876,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   if(result)
     return result;
 
-  if((data->state.authhost.multi || data->state.authproxy.multi) &&
+  if((data->state.authhost.multipass || data->state.authproxy.multipass) &&
      (httpreq != HTTPREQ_GET) &&
      (httpreq != HTTPREQ_HEAD)) {
     /* Auth is required and we are not authenticated yet. Make a PUT or POST
@@ -2092,7 +2092,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         /* when doing ftp, append ;type=<a|i> if not present */
         char *type = strstr(ppath, ";type=");
         if(type && type[6] && type[7] == 0) {
-          switch (Curl_raw_toupper(type[6])) {
+          switch(Curl_raw_toupper(type[6])) {
           case 'A':
           case 'D':
           case 'I':
@@ -2161,32 +2161,32 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       }
 
       if(seekerr != CURL_SEEKFUNC_OK) {
+        curl_off_t passed=0;
+
         if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
           failf(data, "Could not seek stream");
           return CURLE_READ_ERROR;
         }
         /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
-        else {
-          curl_off_t passed=0;
-          do {
-            size_t readthisamountnow =
-              (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
-              BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
-
-            size_t actuallyread =
-              data->state.fread_func(data->state.buffer, 1, readthisamountnow,
-                                     data->state.in);
-
-            passed += actuallyread;
-            if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
-              /* this checks for greater-than only to make sure that the
-                 CURL_READFUNC_ABORT return code still aborts */
-              failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
-                    " bytes from the input", passed);
-              return CURLE_READ_ERROR;
-            }
-          } while(passed < data->state.resume_from);
-        }
+        do {
+          size_t readthisamountnow =
+            (data->state.resume_from - passed > data->set.buffer_size) ?
+            (size_t)data->set.buffer_size :
+            curlx_sotouz(data->state.resume_from - passed);
+
+          size_t actuallyread =
+            data->state.fread_func(data->state.buffer, 1, readthisamountnow,
+                                   data->state.in);
+
+          passed += actuallyread;
+          if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+            /* this checks for greater-than only to make sure that the
+               CURL_READFUNC_ABORT return code still aborts */
+            failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
+                  " bytes from the input", passed);
+            return CURLE_READ_ERROR;
+          }
+        } while(passed < data->state.resume_from);
       }
 
       /* now, decrease the size of the read */
@@ -2252,9 +2252,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     }
   }
 
-  /* Use 1.1 unless the user specifically asked for 1.0 or the server only
-     supports 1.0 */
-  httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
+  httpstring = get_http_string(data, conn);
 
   /* initialize a dynamic send-buffer */
   req_buffer = Curl_add_buffer_init();
@@ -2321,20 +2319,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
                      te
       );
 
-  /* clear userpwd to avoid re-using credentials from re-used connections */
+  /* clear userpwd and proxyuserpwd to avoid re-using old credentials
+   * from re-used connections */
   Curl_safefree(conn->allocptr.userpwd);
-
-  /*
-   * Free proxyuserpwd for Negotiate/NTLM. Cannot reuse as it is associated
-   * with the connection and shouldn't be repeated over it either.
-   */
-  switch (data->state.authproxy.picked) {
-  case CURLAUTH_NEGOTIATE:
-  case CURLAUTH_NTLM:
-  case CURLAUTH_NTLM_WB:
-    Curl_safefree(conn->allocptr.proxyuserpwd);
-    break;
-  }
+  Curl_safefree(conn->allocptr.proxyuserpwd);
 
   if(result)
     return result;
@@ -2528,7 +2516,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       postsize = data->state.infilesize;
 
     if((postsize != -1) && !data->req.upload_chunky &&
-       !Curl_checkheaders(conn, "Content-Length:")) {
+       (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
       /* only add Content-Length if not uploading chunked */
       result = Curl_add_bufferf(req_buffer,
                                 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
@@ -2569,18 +2557,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 
     if(conn->bits.authneg)
       postsize = 0;
-    else {
-      /* figure out the size of the postfields */
-      postsize = (data->state.infilesize != -1)?
-        data->state.infilesize:
-        (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
-    }
+    else
+      /* the size of the post body */
+      postsize = data->state.infilesize;
 
     /* We only set Content-Length and allow a custom Content-Length if
        we don't upload data chunked, as RFC2616 forbids us to set both
        kinds of headers (Transfer-Encoding: chunked and Content-Length) */
     if((postsize != -1) && !data->req.upload_chunky &&
-       !Curl_checkheaders(conn, "Content-Length:")) {
+       (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
       /* we allow replacing this header if not during auth negotiation,
          although it isn't very wise to actually set your own */
       result = Curl_add_bufferf(req_buffer,
@@ -2756,6 +2741,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       data->req.upload_done = TRUE;
       data->req.keepon &= ~KEEP_SEND; /* we're done writing */
       data->req.exp100 = EXP100_SEND_DATA; /* already sent */
+      Curl_expire_done(data, EXPIRE_100_TIMEOUT);
     }
   }
 
@@ -2782,7 +2768,7 @@ checkhttpprefix(struct Curl_easy *data,
   /* convert from the network encoding using a scratch area */
   char *scratch = strdup(s);
   if(NULL == scratch) {
-    failf (data, "Failed to allocate memory for conversion!");
+    failf(data, "Failed to allocate memory for conversion!");
     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
   }
   if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
@@ -2820,7 +2806,7 @@ checkrtspprefix(struct Curl_easy *data,
   /* convert from the network encoding using a scratch area */
   char *scratch = strdup(s);
   if(NULL == scratch) {
-    failf (data, "Failed to allocate memory for conversion!");
+    failf(data, "Failed to allocate memory for conversion!");
     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
   }
   if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
@@ -2834,8 +2820,7 @@ checkrtspprefix(struct Curl_easy *data,
 #endif /* CURL_DOES_CONVERSIONS */
   if(checkprefix("RTSP/", s))
     return TRUE;
-  else
-    return FALSE;
+  return FALSE;
 }
 #endif /* CURL_DISABLE_RTSP */
 
@@ -2872,8 +2857,8 @@ static CURLcode header_append(struct Curl_easy *data,
       /* The reason to have a max limit for this is to avoid the risk of a bad
          server feeding libcurl with a never-ending header that will cause
          reallocs infinitely */
-      failf (data, "Avoided giant realloc for header (max is %d)!",
-             CURL_MAX_HTTP_HEADER);
+      failf(data, "Avoided giant realloc for header (max is %d)!",
+            CURL_MAX_HTTP_HEADER);
       return CURLE_OUT_OF_MEMORY;
     }
 
@@ -2881,7 +2866,7 @@ static CURLcode header_append(struct Curl_easy *data,
     hbufp_index = k->hbufp - data->state.headerbuff;
     newbuff = realloc(data->state.headerbuff, newsize);
     if(!newbuff) {
-      failf (data, "Failed to alloc memory for big header!");
+      failf(data, "Failed to alloc memory for big header!");
       return CURLE_OUT_OF_MEMORY;
     }
     data->state.headersize=newsize;
@@ -3053,6 +3038,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
           if(k->exp100 > EXP100_SEND_DATA) {
             k->exp100 = EXP100_SEND_DATA;
             k->keepon |= KEEP_SEND;
+            Curl_expire_done(data, EXPIRE_100_TIMEOUT);
           }
           break;
         case 101:
@@ -3122,8 +3108,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
        * up and return an error.
        */
       if(http_should_fail(conn)) {
-        failf (data, "The requested URL returned error: %d",
-               k->httpcode);
+        failf(data, "The requested URL returned error: %d",
+              k->httpcode);
         return CURLE_HTTP_RETURNED_ERROR;
       }
 
@@ -3179,6 +3165,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
              * request body has been sent we stop sending and mark the
              * connection for closure after we've read the entire response.
              */
+            Curl_expire_done(data, EXPIRE_100_TIMEOUT);
             if(!k->upload_done) {
               if(data->set.http_keep_sending_on_error) {
                 infof(data, "HTTP error before end of send, keep sending\n");
@@ -3256,9 +3243,17 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
           k->maxdownload = k->size;
         }
 
-        /* If max download size is *zero* (nothing) we already
-           have nothing and can safely return ok now! */
-        if(0 == k->maxdownload)
+        /* If max download size is *zero* (nothing) we already have
+           nothing and can safely return ok now!  But for HTTP/2, we'd
+           like to call http2_handle_stream_close to properly close a
+           stream.  In order to do this, we keep reading until we
+           close the stream. */
+        if(0 == k->maxdownload
+#if defined(USE_NGHTTP2)
+           && !((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+                conn->httpversion == 20)
+#endif
+           )
           *stop_reading = TRUE;
 
         if(*stop_reading) {
@@ -3315,7 +3310,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         /*
          * https://tools.ietf.org/html/rfc7230#section-3.1.2
          *
-         * The reponse code is always a three-digit number in HTTP as the spec
+         * 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
          * guarantees on future behaviors since it isn't within the protocol.
          */
diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h
index 9fb669c..7ce4bd9 100644
--- a/Utilities/cmcurl/lib/http.h
+++ b/Utilities/cmcurl/lib/http.h
@@ -219,6 +219,10 @@ struct http_conn {
 
   /* this is a hash of all individual streams (Curl_easy structs) */
   struct h2settings settings;
+
+  /* list of settings that will be sent */
+  nghttp2_settings_entry local_settings[3];
+  size_t local_settings_num;
 #else
   int unused; /* prevent a compiler warning */
 #endif
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index cfdb327..f8e23c5 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -35,7 +35,7 @@
 #include "url.h"
 #include "connect.h"
 #include "strtoofft.h"
-
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -59,6 +59,12 @@
 #define nghttp2_session_callbacks_set_error_callback(x,y)
 #endif
 
+#if (NGHTTP2_VERSION_NUM >= 0x010c00)
+#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1
+#endif
+
+#define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
+
 /*
  * Curl_http2_init_state() is called when the easy handle is created and
  * allows for HTTP/2 specific init of state.
@@ -110,18 +116,11 @@ static int http2_getsock(struct connectdata *conn,
   return http2_perform_getsock(conn, sock, numsocks);
 }
 
-static CURLcode http2_disconnect(struct connectdata *conn,
-                                 bool dead_connection)
+/*
+ * http2_stream_free() free HTTP2 stream related data
+ */
+static void http2_stream_free(struct HTTP *http)
 {
-  struct HTTP *http = conn->data->req.protop;
-  struct http_conn *c = &conn->proto.httpc;
-  (void)dead_connection;
-
-  DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
-
-  nghttp2_session_del(c->h2);
-  Curl_safefree(c->inbuf);
-
   if(http) {
     Curl_add_buffer_free(http->header_recvbuf);
     http->header_recvbuf = NULL; /* clear the pointer */
@@ -133,6 +132,19 @@ static CURLcode http2_disconnect(struct connectdata *conn,
     free(http->push_headers);
     http->push_headers = NULL;
   }
+}
+
+static CURLcode http2_disconnect(struct connectdata *conn,
+                                 bool dead_connection)
+{
+  struct http_conn *c = &conn->proto.httpc;
+  (void)dead_connection;
+
+  DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
+
+  nghttp2_session_del(c->h2);
+  Curl_safefree(c->inbuf);
+  http2_stream_free(conn->data->req.protop);
 
   DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
 
@@ -153,7 +165,7 @@ void Curl_http2_setup_req(struct Curl_easy *data)
   http->closed = FALSE;
   http->close_handled = FALSE;
   http->mem = data->state.buffer;
-  http->len = BUFSIZE;
+  http->len = data->set.buffer_size;
   http->memlen = 0;
 }
 
@@ -169,7 +181,7 @@ void Curl_http2_setup_conn(struct connectdata *conn)
  * but will be used at run-time when the protocol is dynamically switched from
  * HTTP to HTTP2.
  */
-const struct Curl_handler Curl_handler_http2 = {
+static const struct Curl_handler Curl_handler_http2 = {
   "HTTP",                               /* scheme */
   ZERO_NULL,                            /* setup_connection */
   Curl_http,                            /* do_it */
@@ -189,7 +201,7 @@ const struct Curl_handler Curl_handler_http2 = {
   PROTOPT_STREAM                        /* flags */
 };
 
-const struct Curl_handler Curl_handler_http2_ssl = {
+static const struct Curl_handler Curl_handler_http2_ssl = {
   "HTTPS",                              /* scheme */
   ZERO_NULL,                            /* setup_connection */
   Curl_http,                            /* do_it */
@@ -223,7 +235,8 @@ int Curl_http2_ver(char *p, size_t len)
 https://tools.ietf.org/html/rfc7540#page-77
 nghttp2_error_code enums are identical.
 */
-const char *Curl_http2_strerror(uint32_t err) {
+const char *Curl_http2_strerror(uint32_t err)
+{
 #ifndef NGHTTP2_HAS_HTTP2_STRERROR
   const char *str[] = {
     "NO_ERROR",             /* 0x0 */
@@ -395,6 +408,7 @@ static int push_promise(struct Curl_easy *data,
     stream = data->req.protop;
     if(!stream) {
       failf(data, "Internal NULL stream!\n");
+      (void)Curl_close(newhandle);
       rv = 1;
       goto fail;
     }
@@ -408,9 +422,11 @@ static int push_promise(struct Curl_easy *data,
       free(stream->push_headers[i]);
     free(stream->push_headers);
     stream->push_headers = NULL;
+    stream->push_headers_used = 0;
 
     if(rv) {
       /* denied, kill off the new handle again */
+      http2_stream_free(newhandle->req.protop);
       (void)Curl_close(newhandle);
       goto fail;
     }
@@ -425,6 +441,7 @@ static int push_promise(struct Curl_easy *data,
     rc = Curl_multi_add_perform(data->multi, newhandle, conn);
     if(rc) {
       infof(data, "failed to add handle to multi\n");
+      http2_stream_free(newhandle->req.protop);
       Curl_close(newhandle);
       rv = 1;
       goto fail;
@@ -552,7 +569,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
 
       /* if we receive data for another handle, wake that up */
       if(conn_s->data != data_s)
-        Curl_expire(data_s, 0);
+        Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
     }
     break;
   case NGHTTP2_PUSH_PROMISE:
@@ -580,6 +597,9 @@ static int on_invalid_frame_recv(nghttp2_session *session,
 {
   struct Curl_easy *data_s = NULL;
   (void)userp;
+#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS)
+  (void)lib_error_code;
+#endif
 
   data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
   if(data_s) {
@@ -626,7 +646,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
 
   /* if we receive data for another handle, wake that up */
   if(conn->data != data_s)
-    Curl_expire(data_s, 0);
+    Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
 
   DEBUGF(infof(data_s, "%zu data received for stream %u "
                "(%zu left in buffer %p, total %zu)\n",
@@ -690,6 +710,9 @@ static int on_frame_not_send(nghttp2_session *session,
 {
   struct Curl_easy *data_s;
   (void)userp;
+#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS)
+  (void)lib_error_code;
+#endif
 
   data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
   if(data_s) {
@@ -761,7 +784,7 @@ static int on_begin_headers(nghttp2_session *session,
   /* This is trailer HEADERS started.  Allocate buffer for them. */
   DEBUGF(infof(data_s, "trailer field started\n"));
 
-  assert(stream->trailer_recvbuf == NULL);
+  DEBUGASSERT(stream->trailer_recvbuf == NULL);
 
   stream->trailer_recvbuf = Curl_add_buffer_init();
   if(!stream->trailer_recvbuf) {
@@ -841,10 +864,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
             stream->push_headers_alloc) {
       char **headp;
       stream->push_headers_alloc *= 2;
-      headp = realloc(stream->push_headers,
-                      stream->push_headers_alloc * sizeof(char *));
+      headp = Curl_saferealloc(stream->push_headers,
+                               stream->push_headers_alloc * sizeof(char *));
       if(!headp) {
-        free(stream->push_headers);
         stream->push_headers = NULL;
         return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
       }
@@ -887,7 +909,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
     Curl_add_buffer(stream->header_recvbuf, " \r\n", 3);
     /* if we receive data for another handle, wake that up */
     if(conn->data != data_s)
-      Curl_expire(data_s, 0);
+      Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
 
     DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
                  stream->status_code, data_s));
@@ -903,7 +925,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
   Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
   /* if we receive data for another handle, wake that up */
   if(conn->data != data_s)
-    Curl_expire(data_s, 0);
+    Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
 
   DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
                value));
@@ -961,14 +983,6 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
   return nread;
 }
 
-/*
- * The HTTP2 settings we send in the Upgrade request
- */
-static nghttp2_settings_entry settings[] = {
-  { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
-  { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
-};
-
 #define H2_BUFSIZE 32768
 
 #ifdef NGHTTP2_HAS_ERROR_CALLBACK
@@ -984,6 +998,23 @@ static int error_callback(nghttp2_session *session,
 }
 #endif
 
+static void populate_settings(struct connectdata *conn,
+                              struct http_conn *httpc)
+{
+  nghttp2_settings_entry *iv = httpc->local_settings;
+
+  iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
+  iv[0].value = 100;
+
+  iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
+  iv[1].value = HTTP2_HUGE_WINDOW_SIZE;
+
+  iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
+  iv[2].value = conn->data->multi->push_cb != NULL;
+
+  httpc->local_settings_num = 3;
+}
+
 void Curl_http2_done(struct connectdata *conn, bool premature)
 {
   struct Curl_easy *data = conn->data;
@@ -1097,16 +1128,14 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
   size_t blen;
   struct SingleRequest *k = &conn->data->req;
   uint8_t *binsettings = conn->proto.httpc.binsettings;
+  struct http_conn *httpc = &conn->proto.httpc;
 
-  /* As long as we have a fixed set of settings, we don't have to dynamically
-   * figure out the base64 strings since it'll always be the same. However,
-   * the settings will likely not be fixed every time in the future.
-   */
+  populate_settings(conn, httpc);
 
   /* this returns number of bytes it wrote */
   binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
-                                         settings,
-                                         sizeof(settings)/sizeof(settings[0]));
+                                         httpc->local_settings,
+                                         httpc->local_settings_num);
   if(!binlen) {
     failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
     return CURLE_FAILED_INIT;
@@ -1424,7 +1453,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
     infof(data, "%zu data bytes written\n", nread);
     if(stream->pauselen == 0) {
       DEBUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
-      assert(httpc->pause_stream_id == stream->stream_id);
+      DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
       httpc->pause_stream_id = 0;
 
       stream->pausedata = NULL;
@@ -1572,6 +1601,72 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
 #define HEADER_OVERFLOW(x) \
   (x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen)
 
+/*
+ * Check header memory for the token "trailers".
+ * Parse the tokens as separated by comma and surrounded by whitespace.
+ * Returns TRUE if found or FALSE if not.
+ */
+static bool contains_trailers(const char *p, size_t len)
+{
+  const char *end = p + len;
+  for(;;) {
+    for(; p != end && (*p == ' ' || *p == '\t'); ++p)
+      ;
+    if(p == end || (size_t)(end - p) < sizeof("trailers") - 1)
+      return FALSE;
+    if(strncasecompare("trailers", p, sizeof("trailers") - 1)) {
+      p += sizeof("trailers") - 1;
+      for(; p != end && (*p == ' ' || *p == '\t'); ++p)
+        ;
+      if(p == end || *p == ',')
+        return TRUE;
+    }
+    /* skip to next token */
+    for(; p != end && *p != ','; ++p)
+      ;
+    if(p == end)
+      return FALSE;
+    ++p;
+  }
+}
+
+typedef enum {
+  /* Send header to server */
+  HEADERINST_FORWARD,
+  /* Don't send header to server */
+  HEADERINST_IGNORE,
+  /* Discard header, and replace it with "te: trailers" */
+  HEADERINST_TE_TRAILERS
+} header_instruction;
+
+/* Decides how to treat given header field. */
+static header_instruction inspect_header(const char *name, size_t namelen,
+                                         const char *value, size_t valuelen) {
+  switch(namelen) {
+  case 2:
+    if(!strncasecompare("te", name, namelen))
+      return HEADERINST_FORWARD;
+
+    return contains_trailers(value, valuelen) ?
+           HEADERINST_TE_TRAILERS : HEADERINST_IGNORE;
+  case 7:
+    return strncasecompare("upgrade", name, namelen) ?
+           HEADERINST_IGNORE : HEADERINST_FORWARD;
+  case 10:
+    return (strncasecompare("connection", name, namelen) ||
+            strncasecompare("keep-alive", name, namelen)) ?
+           HEADERINST_IGNORE : HEADERINST_FORWARD;
+  case 16:
+    return strncasecompare("proxy-connection", name, namelen) ?
+           HEADERINST_IGNORE : HEADERINST_FORWARD;
+  case 17:
+    return strncasecompare("transfer-encoding", name, namelen) ?
+           HEADERINST_IGNORE : HEADERINST_FORWARD;
+  default:
+    return HEADERINST_FORWARD;
+  }
+}
+
 static ssize_t http2_send(struct connectdata *conn, int sockindex,
                           const void *mem, size_t len, CURLcode *err)
 {
@@ -1587,7 +1682,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
   size_t nheader;
   size_t i;
   size_t authority_idx;
-  char *hdbuf = (char*)mem;
+  char *hdbuf = (char *)mem;
   char *end, *line_end;
   nghttp2_data_provider data_prd;
   int32_t stream_id;
@@ -1725,7 +1820,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
   i = 3;
   while(i < nheader) {
     size_t hlen;
-    int skip = 0;
 
     hdbuf = line_end + 2;
 
@@ -1743,12 +1837,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
       goto fail;
     hlen = end - hdbuf;
 
-    if(hlen == 10 && strncasecompare("connection", hdbuf, 10)) {
-      /* skip Connection: headers! */
-      skip = 1;
-      --nheader;
-    }
-    else if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
+    if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
       authority_idx = i;
       nva[i].name = (unsigned char *)":authority";
       nva[i].namelen = strlen((char *)nva[i].name);
@@ -1761,16 +1850,28 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
     while(*hdbuf == ' ' || *hdbuf == '\t')
       ++hdbuf;
     end = line_end;
-    if(!skip) {
+
+    switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf,
+                          end - hdbuf)) {
+    case HEADERINST_IGNORE:
+      /* skip header fields prohibited by HTTP/2 specification. */
+      --nheader;
+      continue;
+    case HEADERINST_TE_TRAILERS:
+      nva[i].value = (uint8_t*)"trailers";
+      nva[i].valuelen = sizeof("trailers") - 1;
+      break;
+    default:
       nva[i].value = (unsigned char *)hdbuf;
       nva[i].valuelen = (size_t)(end - hdbuf);
-      nva[i].flags = NGHTTP2_NV_FLAG_NONE;
-      if(HEADER_OVERFLOW(nva[i])) {
-        failf(conn->data, "Failed sending HTTP request: Header overflow");
-        goto fail;
-      }
-      ++i;
     }
+
+    nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+    if(HEADER_OVERFLOW(nva[i])) {
+      failf(conn->data, "Failed sending HTTP request: Header overflow");
+      goto fail;
+    }
+    ++i;
   }
 
   /* :authority must come before non-pseudo header fields */
@@ -1784,28 +1885,22 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
 
   /* Warn stream may be rejected if cumulative length of headers is too large.
      It appears nghttp2 will not send a header frame larger than 64KB. */
+#define MAX_ACC 60000  /* <64KB to account for some overhead */
   {
     size_t acc = 0;
-    const size_t max_acc = 60000;  /* <64KB to account for some overhead */
 
     for(i = 0; i < nheader; ++i) {
-      if(nva[i].namelen > max_acc - acc)
-        break;
-      acc += nva[i].namelen;
-
-      if(nva[i].valuelen > max_acc - acc)
-        break;
-      acc += nva[i].valuelen;
+      acc += nva[i].namelen + nva[i].valuelen;
 
       DEBUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
                    nva[i].namelen, nva[i].name,
                    nva[i].valuelen, nva[i].value));
     }
 
-    if(i != nheader) {
+    if(acc > MAX_ACC) {
       infof(conn->data, "http2_send: Warning: The cumulative length of all "
-                        "headers exceeds %zu bytes and that could cause the "
-                        "stream to be rejected.\n", max_acc);
+            "headers exceeds %zu bytes and that could cause the "
+            "stream to be rejected.\n", MAX_ACC);
     }
   }
 
@@ -1959,9 +2054,13 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
                                          conn->data);
   }
   else {
+    populate_settings(conn, httpc);
+
     /* stream ID is unknown at this point */
     stream->stream_id = -1;
-    rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
+    rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE,
+                                 httpc->local_settings,
+                                 httpc->local_settings_num);
     if(rv != 0) {
       failf(data, "nghttp2_submit_settings() failed: %s(%d)",
             nghttp2_strerror(rv), rv);
@@ -1969,6 +2068,16 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
     }
   }
 
+#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
+  rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
+                                             HTTP2_HUGE_WINDOW_SIZE);
+  if(rv != 0) {
+    failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
+          nghttp2_strerror(rv), rv);
+    return CURLE_HTTP2;
+  }
+#endif
+
   /* we are going to copy mem to httpc->inbuf.  This is required since
      mem is part of buffer pointed by stream->mem, and callbacks
      called by nghttp2_session_mem_recv() will write stream specific
@@ -1984,7 +2093,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
                     " after upgrade: len=%zu\n",
         nread);
 
-  memcpy(httpc->inbuf, mem, nread);
+  if(nread)
+    memcpy(httpc->inbuf, mem, nread);
   httpc->inbuflen = nread;
 
   nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf,
@@ -2024,6 +2134,84 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
   return CURLE_OK;
 }
 
+void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
+                          bool exclusive)
+{
+  if(parent) {
+    struct Curl_http2_dep **tail;
+    struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
+    dep->data = child;
+
+    if(parent->set.stream_dependents && exclusive) {
+      struct Curl_http2_dep *node = parent->set.stream_dependents;
+      while(node) {
+        node->data->set.stream_depends_on = child;
+        node = node->next;
+      }
+
+      tail = &child->set.stream_dependents;
+      while(*tail)
+        tail = &(*tail)->next;
+
+      DEBUGASSERT(!*tail);
+      *tail = parent->set.stream_dependents;
+      parent->set.stream_dependents = 0;
+    }
+
+    tail = &parent->set.stream_dependents;
+    while(*tail) {
+      (*tail)->data->set.stream_depends_e = FALSE;
+      tail = &(*tail)->next;
+    }
+
+    DEBUGASSERT(!*tail);
+    *tail = dep;
+  }
+
+  child->set.stream_depends_on = parent;
+  child->set.stream_depends_e = exclusive;
+}
+
+void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child)
+{
+  struct Curl_http2_dep *last = 0;
+  struct Curl_http2_dep *data = parent->set.stream_dependents;
+  DEBUGASSERT(child->set.stream_depends_on == parent);
+
+  while(data && data->data != child) {
+    last = data;
+    data = data->next;
+  }
+
+  DEBUGASSERT(data);
+
+  if(data) {
+    if(last) {
+      last->next = data->next;
+    }
+    else {
+      parent->set.stream_dependents = data->next;
+    }
+    free(data);
+  }
+
+  child->set.stream_depends_on = 0;
+  child->set.stream_depends_e = FALSE;
+}
+
+void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
+{
+  while(data->set.stream_dependents) {
+    struct Curl_easy *tmp = data->set.stream_dependents->data;
+    Curl_http2_remove_child(data, tmp);
+    if(data->set.stream_depends_on)
+      Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE);
+  }
+
+  if(data->set.stream_depends_on)
+    Curl_http2_remove_child(data->set.stream_depends_on, data);
+}
+
 #else /* !USE_NGHTTP2 */
 
 /* Satisfy external references even if http2 is not compiled in. */
diff --git a/Utilities/cmcurl/lib/http2.h b/Utilities/cmcurl/lib/http2.h
index 8917535..f405b3a 100644
--- a/Utilities/cmcurl/lib/http2.h
+++ b/Utilities/cmcurl/lib/http2.h
@@ -53,6 +53,11 @@ void Curl_http2_setup_conn(struct connectdata *conn);
 void Curl_http2_setup_req(struct Curl_easy *data);
 void Curl_http2_done(struct connectdata *conn, bool premature);
 CURLcode Curl_http2_done_sending(struct connectdata *conn);
+void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
+                          bool exclusive);
+void Curl_http2_remove_child(struct Curl_easy *parent,
+                             struct Curl_easy *child);
+void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
 #else /* USE_NGHTTP2 */
 #define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
@@ -65,6 +70,9 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn);
 #define Curl_http2_init_userset(x)
 #define Curl_http2_done(x,y)
 #define Curl_http2_done_sending(x)
+#define Curl_http2_add_child(x, y, z)
+#define Curl_http2_remove_child(x, y)
+#define Curl_http2_cleanup_dependencies(x)
 #endif
 
 #endif /* HEADER_CURL_HTTP2_H */
diff --git a/Utilities/cmcurl/lib/http_chunks.c b/Utilities/cmcurl/lib/http_chunks.c
index ea17109..1bdf697 100644
--- a/Utilities/cmcurl/lib/http_chunks.c
+++ b/Utilities/cmcurl/lib/http_chunks.c
@@ -190,8 +190,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
 
       /* Write the data portion available */
 #ifdef HAVE_LIBZ
-      switch (conn->data->set.http_ce_skip?
-              IDENTITY : data->req.auto_decoding) {
+      switch(conn->data->set.http_ce_skip?
+             IDENTITY : data->req.auto_decoding) {
       case IDENTITY:
 #endif
         if(!k->ignorebody) {
@@ -219,10 +219,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
         break;
 
       default:
-        failf (conn->data,
-               "Unrecognized content encoding type. "
-               "libcurl understands `identity', `deflate' and `gzip' "
-               "content encodings.");
+        failf(conn->data,
+              "Unrecognized content encoding type. "
+              "libcurl understands `identity', `deflate' and `gzip' "
+              "content encodings.");
         return CHUNKE_BAD_ENCODING;
       }
 #endif
@@ -360,7 +360,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
 
 const char *Curl_chunked_strerror(CHUNKcode code)
 {
-  switch (code) {
+  switch(code) {
   default:
     return "OK";
   case CHUNKE_TOO_LONG_HEX:
diff --git a/Utilities/cmcurl/lib/http_digest.c b/Utilities/cmcurl/lib/http_digest.c
index 184d00b..e2d865b 100644
--- a/Utilities/cmcurl/lib/http_digest.c
+++ b/Utilities/cmcurl/lib/http_digest.c
@@ -74,8 +74,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
 {
   CURLcode result;
   struct Curl_easy *data = conn->data;
-  unsigned char *path;
-  char *tmp;
+  unsigned char *path = NULL;
+  char *tmp = NULL;
   char *response;
   size_t len;
   bool have_chlg;
@@ -95,8 +95,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
   if(proxy) {
     digest = &data->state.proxydigest;
     allocuserpwd = &conn->allocptr.proxyuserpwd;
-    userp = conn->proxyuser;
-    passwdp = conn->proxypasswd;
+    userp = conn->http_proxy.user;
+    passwdp = conn->http_proxy.passwd;
     authp = &data->state.authproxy;
   }
   else {
@@ -140,12 +140,14 @@ CURLcode Curl_output_digest(struct connectdata *conn,
      http://www.fngtps.com/2006/09/http-authentication
   */
 
-  if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) {
-    size_t urilen = tmp - (char *)uripath;
-
-    path = (unsigned char *) aprintf("%.*s", urilen, uripath);
+  if(authp->iestyle) {
+    tmp = strchr((char *)uripath, '?');
+    if(tmp) {
+      size_t urilen = tmp - (char *)uripath;
+      path = (unsigned char *) aprintf("%.*s", urilen, uripath);
+    }
   }
-  else
+  if(!tmp)
     path = (unsigned char *) strdup((char *) uripath);
 
   if(!path)
diff --git a/Utilities/cmcurl/lib/http_negotiate.c b/Utilities/cmcurl/lib/http_negotiate.c
index eb17ed4..51375e8 100644
--- a/Utilities/cmcurl/lib/http_negotiate.c
+++ b/Utilities/cmcurl/lib/http_negotiate.c
@@ -37,6 +37,7 @@
 CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
                               const char *header)
 {
+  CURLcode result;
   struct Curl_easy *data = conn->data;
   size_t len;
 
@@ -50,11 +51,11 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
   struct negotiatedata *neg_ctx;
 
   if(proxy) {
-    userp = conn->proxyuser;
-    passwdp = conn->proxypasswd;
+    userp = conn->http_proxy.user;
+    passwdp = conn->http_proxy.passwd;
     service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
               data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
-    host = conn->proxy.name;
+    host = conn->http_proxy.host.name;
     neg_ctx = &data->state.proxyneg;
   }
   else {
@@ -89,8 +90,13 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
   }
 
   /* Initilise the security context and decode our challenge */
-  return Curl_auth_decode_spnego_message(data, userp, passwdp, service, host,
-                                         header, neg_ctx);
+  result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
+                                           host, header, neg_ctx);
+
+  if(result)
+    Curl_auth_spnego_cleanup(neg_ctx);
+
+  return result;
 }
 
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index e424040..8a78bd2 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -27,7 +27,7 @@
 /*
  * NTLM details:
  *
- * http://davenport.sourceforge.net/ntlm.html
+ * https://davenport.sourceforge.io/ntlm.html
  * https://www.innovation.ch/java/ntlm.html
  */
 
@@ -136,8 +136,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
 
   if(proxy) {
     allocuserpwd = &conn->allocptr.proxyuserpwd;
-    userp = conn->proxyuser;
-    passwdp = conn->proxypasswd;
+    userp = conn->http_proxy.user;
+    passwdp = conn->http_proxy.passwd;
     ntlm = &conn->proxyntlm;
     authp = &conn->data->state.authproxy;
   }
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index 8f5e9b4..9894e2e 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -35,14 +35,50 @@
 #include "non-ascii.h"
 #include "connect.h"
 #include "curlx.h"
+#include "vtls/vtls.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
-CURLcode Curl_proxy_connect(struct connectdata *conn)
+/*
+ * Perform SSL initialization for HTTPS proxy.  Sets
+ * proxy_ssl_connected connection bit when complete.  Can be
+ * called multiple times.
+ */
+static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
+{
+#ifdef USE_SSL
+  CURLcode result = CURLE_OK;
+  DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
+  if(!conn->bits.proxy_ssl_connected[sockindex]) {
+    /* perform SSL initialization for this socket */
+    result =
+      Curl_ssl_connect_nonblocking(conn, sockindex,
+                                   &conn->bits.proxy_ssl_connected[sockindex]);
+    if(result)
+      conn->bits.close = TRUE; /* a failed connection is marked for closure to
+                                  prevent (bad) re-use or similar */
+  }
+  return result;
+#else
+  (void) conn;
+  (void) sockindex;
+  return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
 {
+  if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
+    const CURLcode result = https_proxy_connect(conn, sockindex);
+    if(result)
+      return result;
+    if(!conn->bits.proxy_ssl_connected[sockindex])
+      return result; /* wait for HTTPS proxy SSL initialization to complete */
+  }
+
   if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
 #ifndef CURL_DISABLE_PROXY
     /* for [protocol] tunneled through HTTP proxy */
@@ -62,22 +98,31 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
      * original pointer
      *
      * This function might be called several times in the multi interface case
-     * if the proxy's CONNTECT response is not instant.
+     * if the proxy's CONNECT response is not instant.
      */
     prot_save = conn->data->req.protop;
     memset(&http_proxy, 0, sizeof(http_proxy));
     conn->data->req.protop = &http_proxy;
     connkeep(conn, "HTTP proxy CONNECT");
+
+    /* for the secondary socket (FTP), use the "connect to host"
+     * but ignore the "connect to port" (use the secondary port)
+     */
+
     if(conn->bits.conn_to_host)
       hostname = conn->conn_to_host.name;
+    else if(sockindex == SECONDARYSOCKET)
+      hostname = conn->secondaryhostname;
     else
       hostname = conn->host.name;
-    if(conn->bits.conn_to_port)
+
+    if(sockindex == SECONDARYSOCKET)
+      remote_port = conn->secondary_port;
+    else if(conn->bits.conn_to_port)
       remote_port = conn->conn_to_port;
     else
       remote_port = conn->remote_port;
-    result = Curl_proxyCONNECT(conn, FIRSTSOCKET, hostname,
-                               remote_port, FALSE);
+    result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port);
     conn->data->req.protop = prot_save;
     if(CURLE_OK != result)
       return result;
@@ -90,20 +135,12 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
   return CURLE_OK;
 }
 
-/*
- * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
- * function will issue the necessary commands to get a seamless tunnel through
- * this proxy. After that, the socket can be used just as a normal socket.
- *
- * 'blocking' set to TRUE means that this function will do the entire CONNECT
- * + response in a blocking fashion. Should be avoided!
- */
+#define CONNECT_BUFFER_SIZE 16384
 
-CURLcode Curl_proxyCONNECT(struct connectdata *conn,
-                           int sockindex,
-                           const char *hostname,
-                           int remote_port,
-                           bool blocking)
+static CURLcode CONNECT(struct connectdata *conn,
+                        int sockindex,
+                        const char *hostname,
+                        int remote_port)
 {
   int subversion=0;
   struct Curl_easy *data=conn->data;
@@ -113,7 +150,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
   curl_off_t cl=0;
   bool closeConnection = FALSE;
   bool chunked_encoding = FALSE;
-  long check;
+  time_t check;
 
 #define SELECT_OK      0
 #define SELECT_ERROR   1
@@ -158,10 +195,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
       free(host_port);
 
       if(!result) {
-        char *host=(char *)"";
+        char *host = NULL;
         const char *proxyconn="";
         const char *useragent="";
-        const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
+        const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ?
           "1.0" : "1.1";
         bool ipv6_ip = conn->bits.ipv6_ip;
         char *hostheader;
@@ -201,13 +238,13 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
                            "%s", /* Proxy-Connection */
                            hostheader,
                            http,
-                           host,
+                           host?host:"",
                            conn->allocptr.proxyuserpwd?
                            conn->allocptr.proxyuserpwd:"",
                            useragent,
                            proxyconn);
 
-        if(host && *host)
+        if(host)
           free(host);
         free(hostheader);
 
@@ -243,15 +280,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
       return CURLE_RECV_ERROR;
     }
 
-    if(!blocking) {
-      if(0 == SOCKET_READABLE(tunnelsocket, 0))
-        /* return so we'll be called again polling-style */
-        return CURLE_OK;
-      else {
-        DEBUGF(infof(data,
-               "Read response immediately from proxy CONNECT\n"));
-      }
-    }
+    if(!Curl_conn_data_pending(conn, sockindex))
+      /* return so we'll be called again polling-style */
+      return CURLE_OK;
+    DEBUGF(infof(data, "Read response immediately from proxy CONNECT\n"));
 
     /* at this point, the tunnel_connecting phase is over. */
 
@@ -263,13 +295,20 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
       char *ptr;
       char *line_start;
 
-      ptr=data->state.buffer;
+      ptr = conn->connect_buffer;
       line_start = ptr;
 
-      nread=0;
-      perline=0;
+      nread = 0;
+      perline = 0;
+
+      while(nread < (size_t)CONNECT_BUFFER_SIZE && keepon && !error) {
+        if(Curl_pgrsUpdate(conn))
+          return CURLE_ABORTED_BY_CALLBACK;
 
-      while((nread<BUFSIZE) && (keepon && !error)) {
+        if(ptr >= &conn->connect_buffer[CONNECT_BUFFER_SIZE]) {
+          failf(data, "CONNECT response too large!");
+          return CURLE_RECV_ERROR;
+        }
 
         check = Curl_timeleft(data, NULL, TRUE);
         if(check <= 0) {
@@ -278,253 +317,235 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
           break;
         }
 
-        /* loop every second at least, less if the timeout is near */
-        switch (SOCKET_READABLE(tunnelsocket, check<1000L?check:1000)) {
-        case -1: /* select() error, stop reading */
-          error = SELECT_ERROR;
-          failf(data, "Proxy CONNECT aborted due to select/poll error");
+        /* Read one byte at a time to avoid a race condition. Wait at most one
+           second before looping to ensure continuous pgrsUpdates. */
+        result = Curl_read(conn, tunnelsocket, ptr, 1, &gotbytes);
+        if(result == CURLE_AGAIN) {
+          if(SOCKET_READABLE(tunnelsocket, check<1000L?check:1000) == -1) {
+            error = SELECT_ERROR;
+            failf(data, "Proxy CONNECT aborted due to select/poll error");
+            break;
+          }
+          continue;
+        }
+        if(result) {
+          keepon = FALSE;
           break;
-        case 0: /* timeout */
+        }
+        else if(gotbytes <= 0) {
+          if(data->set.proxyauth && data->state.authproxy.avail) {
+            /* 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");
+          }
+          else {
+            error = SELECT_ERROR;
+            failf(data, "Proxy CONNECT aborted");
+          }
+          keepon = FALSE;
           break;
-        default:
-          DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
-          result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
-                             &gotbytes);
-          if(result==CURLE_AGAIN)
-            continue; /* go loop yourself */
-          else if(result)
-            keepon = FALSE;
-          else if(gotbytes <= 0) {
-            keepon = FALSE;
-            if(data->set.proxyauth && data->state.authproxy.avail) {
-              /* 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");
-            }
-            else {
-              error = SELECT_ERROR;
-              failf(data, "Proxy CONNECT aborted");
+        }
+
+        /* We got a byte of data */
+        nread++;
+
+        if(keepon > TRUE) {
+          /* This means we are currently ignoring a response-body */
+
+          nread = 0; /* make next read start over in the read buffer */
+          ptr = conn->connect_buffer;
+          if(cl) {
+            /* A Content-Length based body: simply count down the counter
+               and make sure to break out of the loop when we're done! */
+            cl--;
+            if(cl <= 0) {
+              keepon = FALSE;
+              break;
             }
           }
           else {
-            /*
-             * We got a whole chunk of data, which can be anything from one
-             * byte to a set of lines and possibly just a piece of the last
-             * line.
-             */
-            int i;
-
-            nread += gotbytes;
-
-            if(keepon > TRUE) {
-              /* This means we are currently ignoring a response-body */
-
-              nread = 0; /* make next read start over in the read buffer */
-              ptr=data->state.buffer;
-              if(cl) {
-                /* A Content-Length based body: simply count down the counter
-                   and make sure to break out of the loop when we're done! */
-                cl -= gotbytes;
-                if(cl<=0) {
-                  keepon = FALSE;
-                  break;
-                }
+            /* chunked-encoded body, so we need to do the chunked dance
+               properly to know when the end of the body is reached */
+            CHUNKcode r;
+            ssize_t tookcareof = 0;
+
+            /* now parse the chunked piece of data so that we can
+               properly tell when the stream ends */
+            r = Curl_httpchunk_read(conn, ptr, 1, &tookcareof);
+            if(r == CHUNKE_STOP) {
+              /* we're done reading chunks! */
+              infof(data, "chunk reading DONE\n");
+              keepon = FALSE;
+              /* we did the full CONNECT treatment, go COMPLETE */
+              conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+            }
+          }
+          continue;
+        }
+
+        perline++; /* amount of bytes in this line so far */
+
+        /* if this is not the end of a header line then continue */
+        if(*ptr != 0x0a) {
+          ptr++;
+          continue;
+        }
+
+        /* convert from the network encoding */
+        result = Curl_convert_from_network(data, line_start, perline);
+        /* Curl_convert_from_network calls failf if unsuccessful */
+        if(result)
+          return result;
+
+        /* output debug if that is requested */
+        if(data->set.verbose)
+          Curl_debug(data, CURLINFO_HEADER_IN,
+                     line_start, (size_t)perline, conn);
+
+        if(!data->set.suppress_connect_headers) {
+          /* send the header to the callback */
+          int writetype = CLIENTWRITE_HEADER;
+          if(data->set.include_header)
+            writetype |= CLIENTWRITE_BODY;
+
+          result = Curl_client_write(conn, writetype, line_start, perline);
+          if(result)
+            return result;
+        }
+
+        data->info.header_size += (long)perline;
+        data->req.headerbytecount += (long)perline;
+
+        /* Newlines are CRLF, so the CR is ignored as the line isn't
+           really terminated until the LF comes. Treat a following CR
+           as end-of-headers as well.*/
+
+        if(('\r' == line_start[0]) ||
+           ('\n' == line_start[0])) {
+          /* end of response-headers from the proxy */
+          nread = 0; /* make next read start over in the read
+                        buffer */
+          ptr = conn->connect_buffer;
+          if((407 == k->httpcode) && !data->state.authproblem) {
+            /* If we get a 407 response code with content length
+               when we have no auth problem, we must ignore the
+               whole response-body */
+            keepon = 2;
+
+            if(cl) {
+              infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
+                    " bytes of response-body\n", cl);
+            }
+            else if(chunked_encoding) {
+              CHUNKcode r;
+
+              infof(data, "Ignore chunked response-body\n");
+
+              /* We set ignorebody true here since the chunked
+                 decoder function will acknowledge that. Pay
+                 attention so that this is cleared again when this
+                 function returns! */
+              k->ignorebody = TRUE;
+
+              if(line_start[1] == '\n') {
+                /* this can only be a LF if the letter at index 0
+                   was a CR */
+                line_start++;
               }
-              else {
-                /* chunked-encoded body, so we need to do the chunked dance
-                   properly to know when the end of the body is reached */
-                CHUNKcode r;
-                ssize_t tookcareof=0;
-
-                /* now parse the chunked piece of data so that we can
-                   properly tell when the stream ends */
-                r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof);
-                if(r == CHUNKE_STOP) {
-                  /* we're done reading chunks! */
-                  infof(data, "chunk reading DONE\n");
-                  keepon = FALSE;
-                  /* we did the full CONNECT treatment, go COMPLETE */
-                  conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
-                }
-                else
-                  infof(data, "Read %zd bytes of chunk, continue\n",
-                        tookcareof);
+
+              /* now parse the chunked piece of data so that we can
+                 properly tell when the stream ends */
+              r = Curl_httpchunk_read(conn, line_start + 1, 1, &gotbytes);
+              if(r == CHUNKE_STOP) {
+                /* we're done reading chunks! */
+                infof(data, "chunk reading DONE\n");
+                keepon = FALSE;
+                /* we did the full CONNECT treatment, go to
+                   COMPLETE */
+                conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
               }
             }
-            else
-              for(i = 0; i < gotbytes; ptr++, i++) {
-                perline++; /* amount of bytes in this line so far */
-                if(*ptr == 0x0a) {
-                  char letter;
-                  int writetype;
-
-                  /* convert from the network encoding */
-                  result = Curl_convert_from_network(data, line_start,
-                                                     perline);
-                  /* Curl_convert_from_network calls failf if unsuccessful */
-                  if(result)
-                    return result;
-
-                  /* output debug if that is requested */
-                  if(data->set.verbose)
-                    Curl_debug(data, CURLINFO_HEADER_IN,
-                               line_start, (size_t)perline, conn);
-
-                  /* send the header to the callback */
-                  writetype = CLIENTWRITE_HEADER;
-                  if(data->set.include_header)
-                    writetype |= CLIENTWRITE_BODY;
-
-                  result = Curl_client_write(conn, writetype, line_start,
-                                             perline);
-
-                  data->info.header_size += (long)perline;
-                  data->req.headerbytecount += (long)perline;
-
-                  if(result)
-                    return result;
-
-                  /* Newlines are CRLF, so the CR is ignored as the line isn't
-                     really terminated until the LF comes. Treat a following CR
-                     as end-of-headers as well.*/
-
-                  if(('\r' == line_start[0]) ||
-                     ('\n' == line_start[0])) {
-                    /* end of response-headers from the proxy */
-                    nread = 0; /* make next read start over in the read
-                                  buffer */
-                    ptr=data->state.buffer;
-                    if((407 == k->httpcode) && !data->state.authproblem) {
-                      /* If we get a 407 response code with content length
-                         when we have no auth problem, we must ignore the
-                         whole response-body */
-                      keepon = 2;
-
-                      if(cl) {
-                        infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
-                              " bytes of response-body\n", cl);
-
-                        /* remove the remaining chunk of what we already
-                           read */
-                        cl -= (gotbytes - i);
-
-                        if(cl<=0)
-                          /* if the whole thing was already read, we are done!
-                           */
-                          keepon=FALSE;
-                      }
-                      else if(chunked_encoding) {
-                        CHUNKcode r;
-                        /* We set ignorebody true here since the chunked
-                           decoder function will acknowledge that. Pay
-                           attention so that this is cleared again when this
-                           function returns! */
-                        k->ignorebody = TRUE;
-                        infof(data, "%zd bytes of chunk left\n", gotbytes-i);
-
-                        if(line_start[1] == '\n') {
-                          /* this can only be a LF if the letter at index 0
-                             was a CR */
-                          line_start++;
-                          i++;
-                        }
-
-                        /* now parse the chunked piece of data so that we can
-                           properly tell when the stream ends */
-                        r = Curl_httpchunk_read(conn, line_start+1,
-                                                  gotbytes -i, &gotbytes);
-                        if(r == CHUNKE_STOP) {
-                          /* we're done reading chunks! */
-                          infof(data, "chunk reading DONE\n");
-                          keepon = FALSE;
-                          /* we did the full CONNECT treatment, go to
-                             COMPLETE */
-                          conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
-                        }
-                        else
-                          infof(data, "Read %zd bytes of chunk, continue\n",
-                                gotbytes);
-                      }
-                      else {
-                        /* without content-length or chunked encoding, we
-                           can't keep the connection alive since the close is
-                           the end signal so we bail out at once instead */
-                        keepon=FALSE;
-                      }
-                    }
-                    else {
-                      keepon = FALSE;
-                      if(200 == data->info.httpproxycode) {
-                        if(gotbytes - (i+1))
-                          failf(data, "Proxy CONNECT followed by %zd bytes "
-                                "of opaque data. Data ignored (known bug #39)",
-                                gotbytes - (i+1));
-                      }
-                    }
-                    /* we did the full CONNECT treatment, go to COMPLETE */
-                    conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
-                    break; /* breaks out of for-loop, not switch() */
-                  }
-
-                  /* keep a backup of the position we are about to blank */
-                  letter = line_start[perline];
-                  line_start[perline]=0; /* zero terminate the buffer */
-                  if((checkprefix("WWW-Authenticate:", line_start) &&
-                      (401 == k->httpcode)) ||
-                     (checkprefix("Proxy-authenticate:", line_start) &&
-                      (407 == k->httpcode))) {
-
-                    bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
-                    char *auth = Curl_copy_header_value(line_start);
-                    if(!auth)
-                      return CURLE_OUT_OF_MEMORY;
-
-                    result = Curl_http_input_auth(conn, proxy, auth);
-
-                    free(auth);
-
-                    if(result)
-                      return result;
-                  }
-                  else if(checkprefix("Content-Length:", line_start)) {
-                    cl = curlx_strtoofft(line_start +
-                                         strlen("Content-Length:"), NULL, 10);
-                  }
-                  else if(Curl_compareheader(line_start,
-                                             "Connection:", "close"))
-                    closeConnection = TRUE;
-                  else if(Curl_compareheader(line_start,
-                                             "Transfer-Encoding:",
-                                             "chunked")) {
-                    infof(data, "CONNECT responded chunked\n");
-                    chunked_encoding = TRUE;
-                    /* init our chunky engine */
-                    Curl_httpchunk_init(conn);
-                  }
-                  else if(Curl_compareheader(line_start,
-                                             "Proxy-Connection:", "close"))
-                    closeConnection = TRUE;
-                  else if(2 == sscanf(line_start, "HTTP/1.%d %d",
-                                      &subversion,
-                                      &k->httpcode)) {
-                    /* store the HTTP code from the proxy */
-                    data->info.httpproxycode = k->httpcode;
-                  }
-                  /* put back the letter we blanked out before */
-                  line_start[perline]= letter;
-
-                  perline=0; /* line starts over here */
-                  line_start = ptr+1; /* this skips the zero byte we wrote */
-                }
-              }
+            else {
+              /* without content-length or chunked encoding, we
+                 can't keep the connection alive since the close is
+                 the end signal so we bail out at once instead */
+              keepon = FALSE;
+            }
           }
-          break;
-        } /* switch */
-        if(Curl_pgrsUpdate(conn))
-          return CURLE_ABORTED_BY_CALLBACK;
+          else
+            keepon = FALSE;
+          /* we did the full CONNECT treatment, go to COMPLETE */
+          conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+          continue;
+        }
+
+        line_start[perline] = 0; /* zero terminate the buffer */
+        if((checkprefix("WWW-Authenticate:", line_start) &&
+            (401 == k->httpcode)) ||
+           (checkprefix("Proxy-authenticate:", line_start) &&
+            (407 == k->httpcode))) {
+
+          bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+          char *auth = Curl_copy_header_value(line_start);
+          if(!auth)
+            return CURLE_OUT_OF_MEMORY;
+
+          result = Curl_http_input_auth(conn, proxy, auth);
+
+          free(auth);
+
+          if(result)
+            return result;
+        }
+        else if(checkprefix("Content-Length:", line_start)) {
+          if(k->httpcode/100 == 2) {
+            /* 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",
+                  k->httpcode);
+          }
+          else {
+            cl = curlx_strtoofft(line_start +
+                                 strlen("Content-Length:"), NULL, 10);
+          }
+        }
+        else if(Curl_compareheader(line_start, "Connection:", "close"))
+          closeConnection = TRUE;
+        else if(checkprefix("Transfer-Encoding:", line_start)) {
+          if(k->httpcode/100 == 2) {
+            /* 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 Transfer-Encoding in "
+                  "CONNECT %03d response\n", k->httpcode);
+          }
+          else if(Curl_compareheader(line_start,
+                                     "Transfer-Encoding:", "chunked")) {
+            infof(data, "CONNECT responded chunked\n");
+            chunked_encoding = TRUE;
+            /* init our chunky engine */
+            Curl_httpchunk_init(conn);
+          }
+        }
+        else if(Curl_compareheader(line_start, "Proxy-Connection:", "close"))
+          closeConnection = TRUE;
+        else if(2 == sscanf(line_start, "HTTP/1.%d %d",
+                            &subversion,
+                            &k->httpcode)) {
+          /* store the HTTP code from the proxy */
+          data->info.httpproxycode = k->httpcode;
+        }
+
+        perline = 0; /* line starts over here */
+        ptr = conn->connect_buffer;
+        line_start = ptr;
       } /* while there's buffer left and loop is requested */
 
+      if(Curl_pgrsUpdate(conn))
+        return CURLE_ABORTED_BY_CALLBACK;
+
       if(error)
         return CURLE_RECV_ERROR;
 
@@ -538,8 +559,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
         if(conn->bits.close)
           /* the connection has been marked for closure, most likely in the
              Curl_http_auth_act() function and thus we can kill it at once
-             below
-          */
+             below */
           closeConnection = TRUE;
       }
 
@@ -583,11 +603,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
     if(conn->bits.proxy_connect_closed)
       /* this is not an error, just part of the connection negotiation */
       return CURLE_OK;
-    else {
-      failf(data, "Received HTTP code %d from proxy after CONNECT",
-            data->req.httpcode);
-      return CURLE_RECV_ERROR;
-    }
+    failf(data, "Received HTTP code %d from proxy after CONNECT",
+          data->req.httpcode);
+    return CURLE_RECV_ERROR;
   }
 
   conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
@@ -600,10 +618,39 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
 
   data->state.authproxy.done = TRUE;
 
-  infof (data, "Proxy replied OK to CONNECT request\n");
+  infof(data, "Proxy replied OK to CONNECT request\n");
   data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
   conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
                                          document request  */
   return CURLE_OK;
 }
+
+/*
+ * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
+ * function will issue the necessary commands to get a seamless tunnel through
+ * this proxy. After that, the socket can be used just as a normal socket.
+ */
+
+CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+                           int sockindex,
+                           const char *hostname,
+                           int remote_port)
+{
+  CURLcode result;
+  if(TUNNEL_INIT == conn->tunnel_state[sockindex]) {
+    if(!conn->connect_buffer) {
+      conn->connect_buffer = malloc(CONNECT_BUFFER_SIZE);
+      if(!conn->connect_buffer)
+        return CURLE_OUT_OF_MEMORY;
+    }
+  }
+  result = CONNECT(conn, sockindex, hostname, remote_port);
+
+  if(result || (TUNNEL_COMPLETE == conn->tunnel_state[sockindex]))
+    Curl_safefree(conn->connect_buffer);
+
+  return result;
+}
+
+
 #endif /* CURL_DISABLE_PROXY */
diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h
index fd04330..cbb1ab4 100644
--- a/Utilities/cmcurl/lib/http_proxy.h
+++ b/Utilities/cmcurl/lib/http_proxy.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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,17 +26,16 @@
 /* ftp can use this as well */
 CURLcode Curl_proxyCONNECT(struct connectdata *conn,
                            int tunnelsocket,
-                           const char *hostname, int remote_port,
-                           bool blocking);
+                           const char *hostname, int remote_port);
 
 /* Default proxy timeout in milliseconds */
 #define PROXY_TIMEOUT (3600*1000)
 
-CURLcode Curl_proxy_connect(struct connectdata *conn);
+CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
 
 #else
-#define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN
-#define Curl_proxy_connect(x) CURLE_OK
+#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
+#define Curl_proxy_connect(x,y) CURLE_OK
 #endif
 
 #endif /* HEADER_CURL_HTTP_PROXY_H */
diff --git a/Utilities/cmcurl/lib/if2ip.c b/Utilities/cmcurl/lib/if2ip.c
index e6faa4b..4de81be 100644
--- a/Utilities/cmcurl/lib/if2ip.c
+++ b/Utilities/cmcurl/lib/if2ip.c
@@ -68,7 +68,7 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
 #else
   if(sa->sa_family == AF_INET6) {
     const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *)(void *) sa;
-    const unsigned char * b = sa6->sin6_addr.s6_addr;
+    const unsigned char *b = sa6->sin6_addr.s6_addr;
     unsigned short w = (unsigned short) ((b[0] << 8) | b[1]);
 
     switch(w & 0xFFC0) {
@@ -239,7 +239,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
     return IF2IP_NOT_FOUND;
   }
 
-  s = (struct sockaddr_in *)&req.ifr_addr;
+  s = (struct sockaddr_in *)(void *)&req.ifr_addr;
   memcpy(&in, &s->sin_addr, sizeof(in));
   Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
 
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index 4aa7dcc..b528f77 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -107,7 +107,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn,
                                           const char *initresp);
 static CURLcode imap_continue_authenticate(struct connectdata *conn,
                                            const char *resp);
-static void imap_get_message(char *buffer, char** outptr);
+static void imap_get_message(char *buffer, char **outptr);
 
 /*
  * IMAP protocol handler.
@@ -130,7 +130,8 @@ const struct Curl_handler Curl_handler_imap = {
   ZERO_NULL,                        /* readwrite */
   PORT_IMAP,                        /* defport */
   CURLPROTO_IMAP,                   /* protocol */
-  PROTOPT_CLOSEACTION               /* flags */
+  PROTOPT_CLOSEACTION|              /* flags */
+  PROTOPT_URLOPTIONS
 };
 
 #ifdef USE_SSL
@@ -390,10 +391,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
  *
  * Gets the authentication message from the response buffer.
  */
-static void imap_get_message(char *buffer, char** outptr)
+static void imap_get_message(char *buffer, char **outptr)
 {
   size_t len = 0;
-  char* message = NULL;
+  char *message = NULL;
 
   /* Find the start of the message */
   for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
@@ -952,7 +953,7 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn,
 
   if(imapcode != 'O') {
     if(data->set.use_ssl != CURLUSESSL_TRY) {
-      failf(data, "STARTTLS denied. %c", imapcode);
+      failf(data, "STARTTLS denied");
       result = CURLE_USE_SSL_FAILED;
     }
     else
@@ -1748,7 +1749,7 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
  *
  * imap_sendf()
  *
- * Sends the formated string as an IMAP command to the server.
+ * Sends the formatted string as an IMAP command to the server.
  *
  * Designed to never block.
  */
diff --git a/Utilities/cmcurl/lib/inet_ntop.c b/Utilities/cmcurl/lib/inet_ntop.c
index 416005c..9afbdbb 100644
--- a/Utilities/cmcurl/lib/inet_ntop.c
+++ b/Utilities/cmcurl/lib/inet_ntop.c
@@ -182,12 +182,12 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
  */
 char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
 {
-  switch (af) {
+  switch(af) {
   case AF_INET:
-    return inet_ntop4((const unsigned char*)src, buf, size);
+    return inet_ntop4((const unsigned char *)src, buf, size);
 #ifdef ENABLE_IPV6
   case AF_INET6:
-    return inet_ntop6((const unsigned char*)src, buf, size);
+    return inet_ntop6((const unsigned char *)src, buf, size);
 #endif
   default:
     SET_ERRNO(EAFNOSUPPORT);
diff --git a/Utilities/cmcurl/lib/inet_pton.c b/Utilities/cmcurl/lib/inet_pton.c
index cf8b88a..475f44a 100644
--- a/Utilities/cmcurl/lib/inet_pton.c
+++ b/Utilities/cmcurl/lib/inet_pton.c
@@ -65,7 +65,7 @@ static int      inet_pton6(const char *src, unsigned char *dst);
 int
 Curl_inet_pton(int af, const char *src, void *dst)
 {
-  switch (af) {
+  switch(af) {
   case AF_INET:
     return (inet_pton4(src, (unsigned char *)dst));
 #ifdef ENABLE_IPV6
@@ -103,7 +103,8 @@ inet_pton4(const char *src, unsigned char *dst)
   while((ch = *src++) != '\0') {
     const char *pch;
 
-    if((pch = strchr(digits, ch)) != NULL) {
+    pch = strchr(digits, ch);
+    if(pch) {
       unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
 
       if(saw_digit && *tp == 0)
@@ -169,7 +170,8 @@ inet_pton6(const char *src, unsigned char *dst)
   while((ch = *src++) != '\0') {
     const char *pch;
 
-    if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+    pch = strchr((xdigits = xdigits_l), ch);
+    if(!pch)
       pch = strchr((xdigits = xdigits_u), ch);
     if(pch != NULL) {
       val <<= 4;
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index 5d5c003..69a3597 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -121,7 +121,7 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to)
   /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal
    * libraries modify the input buffer in gss_seal()
    */
-  dec.value = (void*)from;
+  dec.value = (void *)from;
   dec.length = length;
   maj = gss_seal(&min, *context,
                  level == PROT_PRIVATE,
@@ -164,6 +164,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
   size_t base64_sz = 0;
   struct sockaddr_in **remote_addr =
     (struct sockaddr_in **)&conn->ip_addr->ai_addr;
+  char *stringp;
 
   if(getsockname(conn->sock[FIRSTSOCKET],
                  (struct sockaddr *)&conn->local_addr, &l) < 0)
@@ -193,16 +194,19 @@ krb5_auth(void *app_data, struct connectdata *conn)
         return -1;
     }
 
-    input_buffer.value = data->state.buffer;
-    input_buffer.length = snprintf(input_buffer.value, BUFSIZE, "%s@%s",
-                                   service, host);
+    stringp = aprintf("%s@%s", service, host);
+    if(!stringp)
+      return -2;
+
+    input_buffer.value = stringp;
+    input_buffer.length = strlen(stringp);
     maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE,
                           &gssname);
+    free(stringp);
     if(maj != GSS_S_COMPLETE) {
       gss_release_name(&min, &gssname);
       if(service == srv_host) {
-        Curl_failf(data, "Error importing service name %s",
-                   input_buffer.value);
+        Curl_failf(data, "Error importing service name %s@%s", service, host);
         return AUTH_ERROR;
       }
       service = srv_host;
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 7dbc1b0..79e84d9 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -109,9 +109,9 @@ typedef struct {
 #undef LDAPURLDesc
 #define LDAPURLDesc             CURL_LDAPURLDesc
 
-static int  _ldap_url_parse (const struct connectdata *conn,
-                             LDAPURLDesc **ludp);
-static void _ldap_free_urldesc (LDAPURLDesc *ludp);
+static int  _ldap_url_parse(const struct connectdata *conn,
+                            LDAPURLDesc **ludp);
+static void _ldap_free_urldesc(LDAPURLDesc *ludp);
 
 #undef ldap_free_urldesc
 #define ldap_free_urldesc       _ldap_free_urldesc
@@ -119,11 +119,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp);
 
 #ifdef DEBUG_LDAP
   #define LDAP_TRACE(x)   do { \
-                            _ldap_trace ("%u: ", __LINE__); \
+                            _ldap_trace("%u: ", __LINE__); \
                             _ldap_trace x; \
                           } WHILE_FALSE
 
-  static void _ldap_trace (const char *fmt, ...);
+  static void _ldap_trace(const char *fmt, ...);
 #else
   #define LDAP_TRACE(x)   Curl_nop_stmt
 #endif
@@ -181,6 +181,81 @@ const struct Curl_handler Curl_handler_ldaps = {
 };
 #endif
 
+#if defined(USE_WIN32_LDAP)
+
+#if defined(USE_WINDOWS_SSPI)
+static int ldap_win_bind_auth(LDAP *server, const char *user,
+                              const char *passwd, unsigned long authflags)
+{
+  ULONG method = 0;
+  SEC_WINNT_AUTH_IDENTITY cred = { 0, };
+  int rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
+
+#if defined(USE_SPNEGO)
+  if(authflags & CURLAUTH_NEGOTIATE) {
+    method = LDAP_AUTH_NEGOTIATE;
+  }
+  else
+#endif
+#if defined(USE_NTLM)
+  if(authflags & CURLAUTH_NTLM) {
+    method = LDAP_AUTH_NTLM;
+  }
+  else
+#endif
+#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+  if(authflags & CURLAUTH_DIGEST) {
+    method = LDAP_AUTH_DIGEST;
+  }
+  else
+#endif
+  {
+    /* required anyway if one of upper preprocessor definitions enabled */
+  }
+
+  if(method && user && passwd) {
+    rc = Curl_create_sspi_identity(user, passwd, &cred);
+    if(!rc) {
+      rc = ldap_bind_s(server, NULL, (TCHAR *)&cred, method);
+      Curl_sspi_free_identity(&cred);
+    }
+  }
+  else {
+    /* proceed with current user credentials */
+    method = LDAP_AUTH_NEGOTIATE;
+    rc = ldap_bind_s(server, NULL, NULL, method);
+  }
+  return rc;
+}
+#endif /* #if defined(USE_WINDOWS_SSPI) */
+
+static int ldap_win_bind(struct connectdata *conn, LDAP *server,
+                         const char *user, const char *passwd)
+{
+  int rc = LDAP_INVALID_CREDENTIALS;
+  ULONG method = LDAP_AUTH_SIMPLE;
+
+  PTCHAR inuser = NULL;
+  PTCHAR inpass = NULL;
+
+  if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
+    inuser = Curl_convert_UTF8_to_tchar((char *) user);
+    inpass = Curl_convert_UTF8_to_tchar((char *) passwd);
+
+    rc = ldap_bind_s(server, inuser, inpass, method);
+
+    Curl_unicodefree(inuser);
+    Curl_unicodefree(inpass);
+  }
+#if defined(USE_WINDOWS_SSPI)
+  else {
+    rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth);
+  }
+#endif
+
+  return rc;
+}
+#endif /* #if defined(USE_WIN32_LDAP) */
 
 static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 {
@@ -202,13 +277,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 #endif
 #if defined(USE_WIN32_LDAP)
   TCHAR *host = NULL;
-  TCHAR *user = NULL;
-  TCHAR *passwd = NULL;
 #else
   char *host = NULL;
+#endif
   char *user = NULL;
   char *passwd = NULL;
-#endif
 
   *done = TRUE; /* unconditionally */
   infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
@@ -239,24 +312,14 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 
     goto quit;
   }
-
-  if(conn->bits.user_passwd) {
-    user = Curl_convert_UTF8_to_tchar(conn->user);
-    passwd = Curl_convert_UTF8_to_tchar(conn->passwd);
-    if(!user || !passwd) {
-      result = CURLE_OUT_OF_MEMORY;
-
-      goto quit;
-    }
-  }
 #else
   host = conn->host.name;
+#endif
 
   if(conn->bits.user_passwd) {
     user = conn->user;
     passwd = conn->passwd;
   }
-#endif
 
 #ifdef LDAP_OPT_NETWORK_TIMEOUT
   ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout);
@@ -271,7 +334,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
     ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
 #else
     int ldap_option;
-    char* ldap_ca = data->set.str[STRING_SSL_CAFILE];
+    char *ldap_ca = conn->ssl_config.CAfile;
 #if defined(CURL_HAS_NOVELL_LDAPSDK)
     rc = ldapssl_client_init(NULL, NULL);
     if(rc != LDAP_SUCCESS) {
@@ -279,11 +342,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       result = CURLE_SSL_CERTPROBLEM;
       goto quit;
     }
-    if(data->set.ssl.verifypeer) {
+    if(conn->ssl_config.verifypeer) {
       /* Novell SDK supports DER or BASE64 files. */
       int cert_type = LDAPSSL_CERT_FILETYPE_B64;
-      if((data->set.str[STRING_CERT_TYPE]) &&
-         (strcasecompare(data->set.str[STRING_CERT_TYPE], "DER")))
+      if((data->set.ssl.cert_type) &&
+         (strcasecompare(data->set.ssl.cert_type, "DER")))
         cert_type = LDAPSSL_CERT_FILETYPE_DER;
       if(!ldap_ca) {
         failf(data, "LDAP local: ERROR %s CA cert not set!",
@@ -321,10 +384,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       goto quit;
     }
 #elif defined(LDAP_OPT_X_TLS)
-    if(data->set.ssl.verifypeer) {
+    if(conn->ssl_config.verifypeer) {
       /* OpenLDAP SDK supports BASE64 files. */
-      if((data->set.str[STRING_CERT_TYPE]) &&
-         (!strcasecompare(data->set.str[STRING_CERT_TYPE], "PEM"))) {
+      if((data->set.ssl.cert_type) &&
+         (!strcasecompare(data->set.ssl.cert_type, "PEM"))) {
         failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
         result = CURLE_SSL_CERTPROBLEM;
         goto quit;
@@ -402,11 +465,19 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
   ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
 #endif
 
+#ifdef USE_WIN32_LDAP
+  rc = ldap_win_bind(conn, server, user, passwd);
+#else
   rc = ldap_simple_bind_s(server, user, passwd);
+#endif
   if(!ldap_ssl && rc != 0) {
     ldap_proto = LDAP_VERSION2;
     ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
+#ifdef USE_WIN32_LDAP
+    rc = ldap_win_bind(conn, server, user, passwd);
+#else
     rc = ldap_simple_bind_s(server, user, passwd);
+#endif
   }
   if(rc != 0) {
     failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc));
@@ -655,7 +726,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 quit:
   if(ldapmsg) {
     ldap_msgfree(ldapmsg);
-    LDAP_TRACE (("Received %d entries\n", num));
+    LDAP_TRACE(("Received %d entries\n", num));
   }
   if(rc == LDAP_SIZELIMIT_EXCEEDED)
     infof(data, "There are more than %d entries\n", num);
@@ -669,8 +740,6 @@ quit:
 #endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
 
 #if defined(USE_WIN32_LDAP)
-  Curl_unicodefree(passwd);
-  Curl_unicodefree(user);
   Curl_unicodefree(host);
 #endif
 
@@ -682,7 +751,7 @@ quit:
 }
 
 #ifdef DEBUG_LDAP
-static void _ldap_trace (const char *fmt, ...)
+static void _ldap_trace(const char *fmt, ...)
 {
   static int do_trace = -1;
   va_list args;
@@ -694,9 +763,9 @@ static void _ldap_trace (const char *fmt, ...)
   if(!do_trace)
     return;
 
-  va_start (args, fmt);
-  vfprintf (stderr, fmt, args);
-  va_end (args);
+  va_start(args, fmt);
+  vfprintf(stderr, fmt, args);
+  va_end(args);
 }
 #endif
 
@@ -705,7 +774,7 @@ static void _ldap_trace (const char *fmt, ...)
 /*
  * Return scope-value for a scope-string.
  */
-static int str2scope (const char *p)
+static int str2scope(const char *p)
 {
   if(strcasecompare(p, "one"))
     return LDAP_SCOPE_ONELEVEL;
@@ -799,7 +868,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
     char *unescaped;
     CURLcode result;
 
-    LDAP_TRACE (("DN '%s'\n", dn));
+    LDAP_TRACE(("DN '%s'\n", dn));
 
     /* Unescape the DN */
     result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
@@ -864,7 +933,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
       char *unescaped;
       CURLcode result;
 
-      LDAP_TRACE (("attr[%d] '%s'\n", i, attributes[i]));
+      LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i]));
 
       /* Unescape the attribute */
       result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
@@ -917,7 +986,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
       goto quit;
     }
-    LDAP_TRACE (("scope %d\n", ludp->lud_scope));
+    LDAP_TRACE(("scope %d\n", ludp->lud_scope));
   }
 
   p = q;
@@ -934,7 +1003,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
     char *unescaped;
     CURLcode result;
 
-    LDAP_TRACE (("filter '%s'\n", filter));
+    LDAP_TRACE(("filter '%s'\n", filter));
 
     /* Unescape the filter */
     result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
@@ -1009,7 +1078,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp)
     free(ludp->lud_attrs);
   }
 
-  free (ludp);
+  free(ludp);
 }
 #endif  /* !HAVE_LDAP_URL_PARSE */
 #endif  /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */
diff --git a/Utilities/cmcurl/lib/libcurl.rc b/Utilities/cmcurl/lib/libcurl.rc
index c1efbad..3316fba 100644
--- a/Utilities/cmcurl/lib/libcurl.rc
+++ b/Utilities/cmcurl/lib/libcurl.rc
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -51,7 +51,7 @@ BEGIN
       VALUE "OriginalFilename", "libcurl.dll\0"
       VALUE "ProductName",      "The curl library\0"
       VALUE "ProductVersion",   LIBCURL_VERSION "\0"
-      VALUE "LegalCopyright",   "� " LIBCURL_COPYRIGHT "\0"
+      VALUE "LegalCopyright",   "\xa9 " LIBCURL_COPYRIGHT "\0"  /* a9: Copyright symbol */
       VALUE "License",          "https://curl.haxx.se/docs/copyright.html\0"
     END
   END
diff --git a/Utilities/cmcurl/lib/llist.c b/Utilities/cmcurl/lib/llist.c
index 482aaa0..4bb0a51 100644
--- a/Utilities/cmcurl/lib/llist.c
+++ b/Utilities/cmcurl/lib/llist.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -33,8 +33,8 @@
 /*
  * @unittest: 1300
  */
-static void
-llist_init(struct curl_llist *l, curl_llist_dtor dtor)
+void
+Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor)
 {
   l->size = 0;
   l->dtor = dtor;
@@ -42,20 +42,6 @@ llist_init(struct curl_llist *l, curl_llist_dtor dtor)
   l->tail = NULL;
 }
 
-struct curl_llist *
-Curl_llist_alloc(curl_llist_dtor dtor)
-{
-  struct curl_llist *list;
-
-  list = malloc(sizeof(struct curl_llist));
-  if(!list)
-    return NULL;
-
-  llist_init(list, dtor);
-
-  return list;
-}
-
 /*
  * Curl_llist_insert_next()
  *
@@ -63,18 +49,15 @@ Curl_llist_alloc(curl_llist_dtor dtor)
  * entry is NULL and the list already has elements, the new one will be
  * inserted first in the list.
  *
- * Returns: 1 on success and 0 on failure.
+ * The 'ne' argument should be a pointer into the object to store.
  *
  * @unittest: 1300
  */
-int
+void
 Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
-                       const void *p)
+                       const void *p,
+                       struct curl_llist_element *ne)
 {
-  struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element));
-  if(!ne)
-    return 0;
-
   ne->ptr = (void *) p;
   if(list->size == 0) {
     list->head = ne;
@@ -101,19 +84,18 @@ Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
   }
 
   ++list->size;
-
-  return 1;
 }
 
 /*
  * @unittest: 1300
  */
-int
+void
 Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
                   void *user)
 {
+  void *ptr;
   if(e == NULL || list->size == 0)
-    return 1;
+    return;
 
   if(e == list->head) {
     list->head = e->next;
@@ -131,16 +113,17 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
       e->next->prev = e->prev;
   }
 
-  list->dtor(user, e->ptr);
+  ptr = e->ptr;
 
   e->ptr  = NULL;
   e->prev = NULL;
   e->next = NULL;
 
-  free(e);
   --list->size;
 
-  return 1;
+  /* call the dtor() last for when it actually frees the 'e' memory itself */
+  if(list->dtor)
+    list->dtor(user, ptr);
 }
 
 void
@@ -149,8 +132,6 @@ Curl_llist_destroy(struct curl_llist *list, void *user)
   if(list) {
     while(list->size > 0)
       Curl_llist_remove(list, list->tail, user);
-
-    free(list);
   }
 }
 
@@ -163,13 +144,13 @@ Curl_llist_count(struct curl_llist *list)
 /*
  * @unittest: 1300
  */
-int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
-                    struct curl_llist *to_list,
-                    struct curl_llist_element *to_e)
+void Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
+                     struct curl_llist *to_list,
+                     struct curl_llist_element *to_e)
 {
   /* Remove element from list */
   if(e == NULL || list->size == 0)
-    return 0;
+    return;
 
   if(e == list->head) {
     list->head = e->next;
@@ -209,6 +190,4 @@ int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
   }
 
   ++to_list->size;
-
-  return 1;
 }
diff --git a/Utilities/cmcurl/lib/llist.h b/Utilities/cmcurl/lib/llist.h
index 39ff408..6b644b9 100644
--- a/Utilities/cmcurl/lib/llist.h
+++ b/Utilities/cmcurl/lib/llist.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -29,7 +29,6 @@ typedef void (*curl_llist_dtor)(void *, void *);
 
 struct curl_llist_element {
   void *ptr;
-
   struct curl_llist_element *prev;
   struct curl_llist_element *next;
 };
@@ -37,21 +36,19 @@ struct curl_llist_element {
 struct curl_llist {
   struct curl_llist_element *head;
   struct curl_llist_element *tail;
-
   curl_llist_dtor dtor;
-
   size_t size;
 };
 
-struct curl_llist *Curl_llist_alloc(curl_llist_dtor);
-int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
-                           const void *);
-int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
-                      void *);
+void Curl_llist_init(struct curl_llist *, curl_llist_dtor);
+void Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
+                            const void *, struct curl_llist_element *node);
+void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
+                       void *);
 size_t Curl_llist_count(struct curl_llist *);
 void Curl_llist_destroy(struct curl_llist *, void *);
-int Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
-                    struct curl_llist *, struct curl_llist_element *);
+void Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
+                     struct curl_llist *, struct curl_llist_element *);
 
 #endif /* HEADER_CURL_LLIST_H */
 
diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c
index 60f73a2..2bb7dcc 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -37,9 +37,10 @@
 
 #include "curl_setup.h"
 
-/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
- * that we have a local implementation of it */
-#if defined(USE_NSS) || defined(USE_OS400CRYPTO)
+/* The NSS, OS/400 and sometimes mbed TLS crypto libraries do not provide the
+ * MD4 hash algorithm, so we have a local implementation of it */
+#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+    (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
 
 #include "curl_md4.h"
 #include "warnless.h"
@@ -89,7 +90,7 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
  */
 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
 #define SET(n) \
-        (*(MD4_u32plus *)&ptr[(n) * 4])
+        (*(MD4_u32plus *)(void *)&ptr[(n) * 4])
 #define GET(n) \
         SET(n)
 #else
@@ -213,7 +214,8 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
   unsigned long used, available;
 
   saved_lo = ctx->lo;
-  if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+  ctx->lo = (saved_lo + size) & 0x1fffffff;
+  if(ctx->lo < saved_lo)
     ctx->hi++;
   ctx->hi += (MD4_u32plus)size >> 29;
 
@@ -301,4 +303,5 @@ void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
   MD4_Update(&ctx, input, curlx_uztoui(len));
   MD4_Final(output, &ctx);
 }
-#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */
+#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+    (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index f818d32..80301a1 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -45,7 +45,7 @@ static void MD5_Init(MD5_CTX * ctx)
 }
 
 static void MD5_Update(MD5_CTX * ctx,
-                       const unsigned char * input,
+                       const unsigned char *input,
                        unsigned int inputLen)
 {
   md5_update(ctx, inputLen, input);
@@ -71,7 +71,7 @@ static void MD5_Init(MD5_CTX * ctx)
 }
 
 static void MD5_Update(MD5_CTX * ctx,
-                       const unsigned char * input,
+                       const unsigned char *input,
                        unsigned int inputLen)
 {
   gcry_md_write(*ctx, input, inputLen);
@@ -260,7 +260,7 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx);
  */
 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
 #define SET(n) \
-        (*(MD5_u32plus *)&ptr[(n) * 4])
+        (*(MD5_u32plus *)(void *)&ptr[(n) * 4])
 #define GET(n) \
         SET(n)
 #else
@@ -402,7 +402,8 @@ static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
   unsigned long used, available;
 
   saved_lo = ctx->lo;
-  if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+  ctx->lo = (saved_lo + size) & 0x1fffffff;
+  if(ctx->lo < saved_lo)
     ctx->hi++;
   ctx->hi += (MD5_u32plus)size >> 29;
 
diff --git a/Utilities/cmcurl/lib/memdebug.c b/Utilities/cmcurl/lib/memdebug.c
index ccbf461..2b8808a 100644
--- a/Utilities/cmcurl/lib/memdebug.c
+++ b/Utilities/cmcurl/lib/memdebug.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -35,10 +35,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifndef HAVE_ASSERT_H
-#  define assert(x) Curl_nop_stmt
-#endif
-
 /*
  * Until 2011-08-17 libcurl's Memory Tracking feature also performed
  * automatic malloc and free filling operations using 0xA5 and 0x13
@@ -90,7 +86,7 @@ struct memdebug {
   union {
     curl_off_t o;
     double d;
-    void * p;
+    void *p;
   } mem[1];
   /* I'm hoping this is the thing with the strictest alignment
    * requirements.  That also means we waste some space :-( */
@@ -167,7 +163,7 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
   struct memdebug *mem;
   size_t size;
 
-  assert(wantedsize != 0);
+  DEBUGASSERT(wantedsize != 0);
 
   if(countcheck("malloc", line, source))
     return NULL;
@@ -196,8 +192,8 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
   struct memdebug *mem;
   size_t size, user_size;
 
-  assert(wanted_elements != 0);
-  assert(wanted_size != 0);
+  DEBUGASSERT(wanted_elements != 0);
+  DEBUGASSERT(wanted_size != 0);
 
   if(countcheck("calloc", line, source))
     return NULL;
@@ -223,7 +219,7 @@ char *curl_dostrdup(const char *str, int line, const char *source)
   char *mem;
   size_t len;
 
-  assert(str != NULL);
+  DEBUGASSERT(str != NULL);
 
   if(countcheck("strdup", line, source))
     return NULL;
@@ -236,7 +232,7 @@ char *curl_dostrdup(const char *str, int line, const char *source)
 
   if(source)
     curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
-                source, line, (void *)str, len, (void *)mem);
+                source, line, (const void *)str, len, (const void *)mem);
 
   return mem;
 }
@@ -247,7 +243,7 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
   wchar_t *mem;
   size_t wsiz, bsiz;
 
-  assert(str != NULL);
+  DEBUGASSERT(str != NULL);
 
   if(countcheck("wcsdup", line, source))
     return NULL;
@@ -276,7 +272,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
 
   size_t size = sizeof(struct memdebug)+wantedsize;
 
-  assert(wantedsize != 0);
+  DEBUGASSERT(wantedsize != 0);
 
   if(countcheck("realloc", line, source))
     return NULL;
@@ -445,7 +441,7 @@ int curl_fclose(FILE *file, int line, const char *source)
 {
   int res;
 
-  assert(file != NULL);
+  DEBUGASSERT(file != NULL);
 
   res=fclose(file);
 
@@ -458,7 +454,7 @@ int curl_fclose(FILE *file, int line, const char *source)
 
 #define LOGLINE_BUFSIZE  1024
 
-/* this does the writting to the memory tracking log file */
+/* this does the writing to the memory tracking log file */
 void curl_memlog(const char *format, ...)
 {
   char *buf;
@@ -480,7 +476,7 @@ void curl_memlog(const char *format, ...)
     nchars = LOGLINE_BUFSIZE - 1;
 
   if(nchars > 0)
-    fwrite(buf, 1, nchars, logfile);
+    fwrite(buf, 1, (size_t)nchars, logfile);
 
   (Curl_cfree)(buf);
 }
diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c
index 3cdd41a..eb7ee0c 100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1999 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1999 - 2017, Daniel Stenberg, <daniel at 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
@@ -88,7 +88,8 @@
 #  define mp_uintmax_t unsigned long
 #endif
 
-#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
+#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
+                        fit negative DBL_MAX (317 letters) */
 #define MAX_PARAMETERS 128 /* lame static limit */
 
 #ifdef __AMIGA__
@@ -299,7 +300,6 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
           flags |= FLAGS_ALT;
           break;
         case '.':
-          flags |= FLAGS_PREC;
           if('*' == *fmt) {
             /* The precision is picked from a specified parameter */
 
@@ -498,7 +498,7 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
         (mp_intmax_t)va_arg(arglist, int);
     }
 
-    switch (vto[i].type) {
+    switch(vto[i].type) {
     case FORMAT_STRING:
       vto[i].data.str = va_arg(arglist, char *);
       break;
@@ -610,7 +610,7 @@ static int dprintf_formatf(
     int is_neg;
 
     /* Base of a number to be written.  */
-    long base;
+    unsigned long base;
 
     /* Integral values to be written.  */
     mp_uintmax_t num;
@@ -688,7 +688,7 @@ static int dprintf_formatf(
 
     is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
 
-    switch (p->type) {
+    switch(p->type) {
     case FORMAT_INT:
       num = p->data.num.as_unsigned;
       if(p->flags & FLAGS_CHAR) {
@@ -913,12 +913,25 @@ static int dprintf_formatf(
         *fptr = 0;
 
         if(width >= 0) {
+          if(width >= (long)sizeof(work))
+            width = sizeof(work)-1;
           /* RECURSIVE USAGE */
           len = curl_msnprintf(fptr, left, "%ld", width);
           fptr += len;
           left -= len;
         }
         if(prec >= 0) {
+          /* for each digit in the integer part, we can have one less
+             precision */
+          size_t maxprec = sizeof(work) - 2;
+          double val = p->data.dnum;
+          while(val >= 10.0) {
+            val /= 10;
+            maxprec--;
+          }
+
+          if(prec > (long)maxprec)
+            prec = (long)maxprec-1;
           /* RECURSIVE USAGE */
           len = curl_msnprintf(fptr, left, ".%ld", prec);
           fptr += len;
@@ -938,7 +951,7 @@ static int dprintf_formatf(
         /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
            output characters */
         (sprintf)(work, formatbuf, p->data.dnum);
-
+        DEBUGASSERT(strlen(work) <= sizeof(work));
         for(fptr=work; *fptr; fptr++)
           OUTCHAR(*fptr);
       }
@@ -1077,8 +1090,7 @@ char *curl_maprintf(const char *format, ...)
     info.buffer[info.len] = 0; /* we terminate this with a zero byte */
     return info.buffer;
   }
-  else
-    return strdup("");
+  return strdup("");
 }
 
 char *curl_mvaprintf(const char *format, va_list ap_save)
@@ -1102,8 +1114,7 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
     info.buffer[info.len] = 0; /* we terminate this with a zero byte */
     return info.buffer;
   }
-  else
-    return strdup("");
+  return strdup("");
 }
 
 static int storebuffer(int output, FILE *data)
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 2432b15..c3a0d12 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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,6 +42,7 @@
 #include "multihandle.h"
 #include "pipeline.h"
 #include "sigpipe.h"
+#include "vtls/vtls.h"
 #include "connect.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -98,8 +99,6 @@ static const char * const statename[]={
 };
 #endif
 
-static void multi_freetimeout(void *a, void *b);
-
 /* function pointer called once when switching TO a state */
 typedef void (*init_multistate_func)(struct Curl_easy *data);
 
@@ -279,9 +278,8 @@ static int sh_init(struct curl_hash *hash, int hashsize)
 static CURLMcode multi_addmsg(struct Curl_multi *multi,
                               struct Curl_message *msg)
 {
-  if(!Curl_llist_insert_next(multi->msglist, multi->msglist->tail, msg))
-    return CURLM_OUT_OF_MEMORY;
-
+  Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
+                         &msg->list);
   return CURLM_OK;
 }
 
@@ -315,13 +313,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
   if(Curl_conncache_init(&multi->conn_cache, chashsize))
     goto error;
 
-  multi->msglist = Curl_llist_alloc(multi_freeamsg);
-  if(!multi->msglist)
-    goto error;
-
-  multi->pending = Curl_llist_alloc(multi_freeamsg);
-  if(!multi->pending)
-    goto error;
+  Curl_llist_init(&multi->msglist, multi_freeamsg);
+  Curl_llist_init(&multi->pending, multi_freeamsg);
 
   /* allocate a new easy handle to use when closing cached connections */
   multi->closure_handle = curl_easy_init();
@@ -344,8 +337,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
   Curl_conncache_destroy(&multi->conn_cache);
   Curl_close(multi->closure_handle);
   multi->closure_handle = NULL;
-  Curl_llist_destroy(multi->msglist, NULL);
-  Curl_llist_destroy(multi->pending, NULL);
+  Curl_llist_destroy(&multi->msglist, NULL);
+  Curl_llist_destroy(&multi->pending, NULL);
 
   free(multi);
   return NULL;
@@ -360,8 +353,6 @@ struct Curl_multi *curl_multi_init(void)
 CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
                                 struct Curl_easy *data)
 {
-  struct curl_llist *timeoutlist;
-
   /* First, make some basic checks that the CURLM handle is a good handle */
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
@@ -375,10 +366,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
   if(data->multi)
     return CURLM_ADDED_ALREADY;
 
-  /* Allocate and initialize timeout list for easy handle */
-  timeoutlist = Curl_llist_alloc(multi_freetimeout);
-  if(!timeoutlist)
-    return CURLM_OUT_OF_MEMORY;
+  /* Initialize timeout list for this handle */
+  Curl_llist_init(&data->state.timeoutlist, NULL);
 
   /*
    * No failure allowed in this function beyond this point. And no
@@ -387,10 +376,6 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
    * function no matter what.
    */
 
-  /* Make easy handle use timeout list initialized above */
-  data->state.timeoutlist = timeoutlist;
-  timeoutlist = NULL;
-
   /* set the easy handle */
   multistate(data, CURLM_STATE_INIT);
 
@@ -443,7 +428,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
      sockets that time-out or have actions will be dealt with. Since this
      handle has no action yet, we make sure it times out to get things to
      happen. */
-  Curl_expire(data, 0);
+  Curl_expire(data, 0, EXPIRE_RUN_NOW);
 
   /* increase the node-counter */
   multi->num_easy++;
@@ -531,6 +516,7 @@ static CURLcode multi_done(struct connectdata **connp,
   CURLcode result;
   struct connectdata *conn;
   struct Curl_easy *data;
+  unsigned int i;
 
   DEBUGASSERT(*connp);
 
@@ -578,7 +564,7 @@ static CURLcode multi_done(struct connectdata **connp,
       result = CURLE_ABORTED_BY_CALLBACK;
   }
 
-  if(conn->send_pipe->size + conn->recv_pipe->size != 0 &&
+  if(conn->send_pipe.size + conn->recv_pipe.size != 0 &&
      !data->set.reuse_forbid &&
      !conn->bits.close) {
     /* Stop if pipeline is not empty and we do not have to close
@@ -597,9 +583,11 @@ static CURLcode multi_done(struct connectdata **connp,
   }
 
   /* if the transfer was completed in a paused state there can be buffered
-     data left to write and then kill */
-  free(data->state.tempwrite);
-  data->state.tempwrite = NULL;
+     data left to free */
+  for(i=0; i < data->state.tempcount; i++) {
+    free(data->state.tempwrite[i].buf);
+  }
+  data->state.tempcount = 0;
 
   /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
      forced us to close this connection. This is ignored for requests taking
@@ -637,7 +625,10 @@ static CURLcode multi_done(struct connectdata **connp,
 
       infof(data, "Connection #%ld to host %s left intact\n",
             conn->connection_id,
-            conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
+            conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
+            conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+            conn->bits.conn_to_host ? conn->conn_to_host.dispname :
+            conn->host.dispname);
     }
     else
       data->state.lastconnect = NULL;
@@ -691,13 +682,13 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
   if(data->easy_conn &&
      data->mstate > CURLM_STATE_DO &&
      data->mstate < CURLM_STATE_COMPLETED) {
+    /* Set connection owner so that the DONE function closes it.  We can
+       safely do this here since connection is killed. */
+    data->easy_conn->data = easy;
     /* If the handle is in a pipeline and has started sending off its
        request but not received its response yet, we need to close
        connection. */
     streamclose(data->easy_conn, "Removed with partial response");
-    /* Set connection owner so that the DONE function closes it.  We can
-       safely do this here since connection is killed. */
-    data->easy_conn->data = easy;
     easy_owns_conn = TRUE;
   }
 
@@ -734,10 +725,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
 
   /* destroy the timeout list that is held in the easy handle, do this *after*
      multi_done() as that may actually call Curl_expire that uses this */
-  if(data->state.timeoutlist) {
-    Curl_llist_destroy(data->state.timeoutlist, NULL);
-    data->state.timeoutlist = NULL;
-  }
+  Curl_llist_destroy(&data->state.timeoutlist, NULL);
 
   /* as this was using a shared connection cache we clear the pointer to that
      since we're not part of that multi handle anymore */
@@ -760,11 +748,11 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
   /* make sure there's no pending message in the queue sent from this easy
      handle */
 
-  for(e = multi->msglist->head; e; e = e->next) {
+  for(e = multi->msglist.head; e; e = e->next) {
     struct Curl_message *msg = e->ptr;
 
     if(msg->extmsg.easy_handle == easy) {
-      Curl_llist_remove(multi->msglist, e, NULL);
+      Curl_llist_remove(&multi->msglist, e, NULL);
       /* there can only be one from this specific handle */
       break;
     }
@@ -812,6 +800,11 @@ static int waitconnect_getsock(struct connectdata *conn,
   if(!numsocks)
     return GETSOCK_BLANK;
 
+#ifdef USE_SSL
+  if(CONNECT_FIRSTSOCKET_PROXY_SSL())
+    return Curl_ssl_getsock(conn, sock, numsocks);
+#endif
+
   for(i=0; i<2; i++) {
     if(conn->tempsock[i] != CURL_SOCKET_BAD) {
       sock[s] = conn->tempsock[i];
@@ -950,10 +943,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
       if(s == CURL_SOCKET_BAD)
         /* this socket is unused, break out of loop */
         break;
-      else {
-        if((int)s > this_max_fd)
-          this_max_fd = (int)s;
-      }
+      if((int)s > this_max_fd)
+        this_max_fd = (int)s;
     }
 
     data = data->next; /* check next handle */
@@ -964,6 +955,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
   return CURLM_OK;
 }
 
+#define NUM_POLLS_ON_STACK 10
+
 CURLMcode curl_multi_wait(struct Curl_multi *multi,
                           struct curl_waitfd extra_fds[],
                           unsigned int extra_nfds,
@@ -977,8 +970,10 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
   unsigned int nfds = 0;
   unsigned int curlfds;
   struct pollfd *ufds = NULL;
+  bool ufds_malloc = FALSE;
   long timeout_internal;
   int retcode = 0;
+  struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
 
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
@@ -1017,10 +1012,15 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
   curlfds = nfds; /* number of internal file descriptors */
   nfds += extra_nfds; /* add the externally provided ones */
 
-  if(nfds || extra_nfds) {
-    ufds = malloc(nfds * sizeof(struct pollfd));
-    if(!ufds)
-      return CURLM_OUT_OF_MEMORY;
+  if(nfds) {
+    if(nfds > NUM_POLLS_ON_STACK) {
+      ufds = malloc(nfds * sizeof(struct pollfd));
+      if(!ufds)
+        return CURLM_OUT_OF_MEMORY;
+      ufds_malloc = TRUE;
+    }
+    else
+      ufds = &a_few_on_stack[0];
   }
   nfds = 0;
 
@@ -1098,7 +1098,8 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
     }
   }
 
-  free(ufds);
+  if(ufds_malloc)
+    free(ufds);
   if(ret)
     *ret = retcode;
   return CURLM_OK;
@@ -1300,7 +1301,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
   CURLMcode rc;
   CURLcode result = CURLE_OK;
   struct SingleRequest *k;
-  long timeout_ms;
+  time_t timeout_ms;
+  time_t recv_timeout_ms;
+  time_t send_timeout_ms;
   int control;
 
   if(!GOOD_EASY_HANDLE(data))
@@ -1426,10 +1429,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         multistate(data, CURLM_STATE_CONNECT_PEND);
 
         /* add this handle to the list of connect-pending handles */
-        if(!Curl_llist_insert_next(multi->pending, multi->pending->tail, data))
-          result = CURLE_OUT_OF_MEMORY;
-        else
-          result = CURLE_OK;
+        Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
+                               &data->connect_queue);
+        result = CURLE_OK;
         break;
       }
 
@@ -1471,8 +1473,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       struct connectdata *conn = data->easy_conn;
       const char *hostname;
 
-      if(conn->bits.proxy)
-        hostname = conn->proxy.name;
+      if(conn->bits.httpproxy)
+        hostname = conn->http_proxy.host.name;
       else if(conn->bits.conn_to_host)
         hostname = conn->conn_to_host.name;
       else
@@ -1548,7 +1550,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         multistate(data, CURLM_STATE_CONNECT);
       }
       else if(!result) {
-        if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE) {
+        if((data->easy_conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
+           data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
+           (data->easy_conn->tunnel_state[FIRSTSOCKET] != TUNNEL_CONNECT)) {
           rc = CURLM_CALL_MULTI_PERFORM;
           /* initiate protocol connect phase */
           multistate(data, CURLM_STATE_SENDPROTOCONNECT);
@@ -1561,6 +1565,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       /* awaiting a completion of an asynch TCP connect */
       result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
       if(connected && !result) {
+#ifndef CURL_DISABLE_HTTP
+        if((data->easy_conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
+            !data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
+            (data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)) {
+          multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+          break;
+        }
+#endif
         rc = CURLM_CALL_MULTI_PERFORM;
         multistate(data, data->easy_conn->bits.tunnel_proxy?
                    CURLM_STATE_WAITPROXYCONNECT:
@@ -1703,20 +1715,18 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
               else {
                 /* Follow failed */
                 result = drc;
-                free(newurl);
               }
             }
             else {
               /* done didn't return OK or SEND_ERROR */
               result = drc;
-              free(newurl);
             }
           }
           else {
             /* Have error handler disconnect conn if we can't retry */
             stream_error = TRUE;
-            free(newurl);
           }
+          free(newurl);
         }
         else {
           /* failure detected */
@@ -1810,19 +1820,30 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       else
         result = Curl_speedcheck(data, now);
 
-      if(( (data->set.max_send_speed == 0) ||
-           (Curl_pgrsLimitWaitTime(data->progress.uploaded,
-                                   data->progress.ul_limit_size,
-                                   data->set.max_send_speed,
-                                   data->progress.ul_limit_start,
-                                   now) <= 0))  &&
-         ( (data->set.max_recv_speed == 0) ||
-           (Curl_pgrsLimitWaitTime(data->progress.downloaded,
-                                   data->progress.dl_limit_size,
-                                   data->set.max_recv_speed,
-                                   data->progress.dl_limit_start,
-                                   now) <= 0)))
-        multistate(data, CURLM_STATE_PERFORM);
+      if(!result) {
+        send_timeout_ms = 0;
+        if(data->set.max_send_speed > 0)
+          send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
+                                data->progress.ul_limit_size,
+                                data->set.max_send_speed,
+                                data->progress.ul_limit_start,
+                                now);
+
+        recv_timeout_ms = 0;
+        if(data->set.max_recv_speed > 0)
+          recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
+                                data->progress.dl_limit_size,
+                                data->set.max_recv_speed,
+                                data->progress.dl_limit_start,
+                                now);
+
+        if(send_timeout_ms <= 0 && recv_timeout_ms <= 0)
+          multistate(data, CURLM_STATE_PERFORM);
+        else if(send_timeout_ms >= recv_timeout_ms)
+          Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
+        else
+          Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
+      }
       break;
 
     case CURLM_STATE_PERFORM:
@@ -1832,31 +1853,30 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       bool comeback = FALSE;
 
       /* check if over send speed */
-      if(data->set.max_send_speed > 0) {
-        timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
-                                            data->progress.ul_limit_size,
-                                            data->set.max_send_speed,
-                                            data->progress.ul_limit_start,
-                                            now);
-        if(timeout_ms > 0) {
-          multistate(data, CURLM_STATE_TOOFAST);
-          Curl_expire_latest(data, timeout_ms);
-          break;
-        }
-      }
+      send_timeout_ms = 0;
+      if(data->set.max_send_speed > 0)
+        send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
+                                                 data->progress.ul_limit_size,
+                                                 data->set.max_send_speed,
+                                                 data->progress.ul_limit_start,
+                                                 now);
 
       /* check if over recv speed */
-      if(data->set.max_recv_speed > 0) {
-        timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
-                                            data->progress.dl_limit_size,
-                                            data->set.max_recv_speed,
-                                            data->progress.dl_limit_start,
-                                            now);
-        if(timeout_ms > 0) {
-          multistate(data, CURLM_STATE_TOOFAST);
-          Curl_expire_latest(data, timeout_ms);
-          break;
-        }
+      recv_timeout_ms = 0;
+      if(data->set.max_recv_speed > 0)
+        recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
+                                                 data->progress.dl_limit_size,
+                                                 data->set.max_recv_speed,
+                                                 data->progress.dl_limit_start,
+                                                 now);
+
+      if(send_timeout_ms > 0 || recv_timeout_ms > 0) {
+        multistate(data, CURLM_STATE_TOOFAST);
+        if(send_timeout_ms >= recv_timeout_ms)
+          Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
+        else
+          Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
+        break;
       }
 
       /* read/write data if it is ready to do so */
@@ -1912,11 +1932,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         Curl_posttransfer(data);
 
         /* we're no longer receiving */
-        Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
+        Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe);
 
         /* expire the new receiving pipeline head */
-        if(data->easy_conn->recv_pipe->head)
-          Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 0);
+        if(data->easy_conn->recv_pipe.head)
+          Curl_expire(data->easy_conn->recv_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
 
         /* Check if we can move pending requests to send pipe */
         Curl_multi_process_pending_handles(multi);
@@ -1940,9 +1960,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
             if(!result) {
               multistate(data, CURLM_STATE_CONNECT);
               rc = CURLM_CALL_MULTI_PERFORM;
-              newurl = NULL; /* handed over the memory ownership to
-                                Curl_follow(), make sure we don't free() it
-                                here */
             }
           }
         }
@@ -1956,9 +1973,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
             newurl = data->req.location;
             data->req.location = NULL;
             result = Curl_follow(data, newurl, FOLLOW_FAKE);
-            if(!result)
-              newurl = NULL; /* allocation was handed over Curl_follow() */
-            else
+            if(result)
               stream_error = TRUE;
           }
 
@@ -1981,7 +1996,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         CURLcode res;
 
         /* Remove ourselves from the receive pipeline, if we are there. */
-        Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
+        Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe);
         /* Check if we can move pending requests to send pipe */
         Curl_multi_process_pending_handles(multi);
 
@@ -2057,8 +2072,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           /* if this has a connection, unsubscribe from the pipelines */
           Curl_pipeline_leave_write(data->easy_conn);
           Curl_pipeline_leave_read(data->easy_conn);
-          Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe);
-          Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
+          Curl_removeHandleFromPipeline(data, &data->easy_conn->send_pipe);
+          Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe);
 
           if(stream_error) {
             /* Don't attempt to send data over a connection that timed out */
@@ -2213,8 +2228,8 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
 
     Curl_hash_destroy(&multi->sockhash);
     Curl_conncache_destroy(&multi->conn_cache);
-    Curl_llist_destroy(multi->msglist, NULL);
-    Curl_llist_destroy(multi->pending, NULL);
+    Curl_llist_destroy(&multi->msglist, NULL);
+    Curl_llist_destroy(&multi->pending, NULL);
 
     /* remove all easy handles */
     data = multi->easyp;
@@ -2246,8 +2261,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
 
     return CURLM_OK;
   }
-  else
-    return CURLM_BAD_HANDLE;
+  return CURLM_BAD_HANDLE;
 }
 
 /*
@@ -2266,24 +2280,23 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
 
   *msgs_in_queue = 0; /* default to none */
 
-  if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(multi->msglist)) {
+  if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(&multi->msglist)) {
     /* there is one or more messages in the list */
     struct curl_llist_element *e;
 
     /* extract the head of the list to return */
-    e = multi->msglist->head;
+    e = multi->msglist.head;
 
     msg = e->ptr;
 
     /* remove the extracted entry */
-    Curl_llist_remove(multi->msglist, e, NULL);
+    Curl_llist_remove(&multi->msglist, e, NULL);
 
-    *msgs_in_queue = curlx_uztosi(Curl_llist_count(multi->msglist));
+    *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
 
     return &msg->extmsg;
   }
-  else
-    return NULL;
+  return NULL;
 }
 
 /*
@@ -2378,7 +2391,7 @@ static void singlesocket(struct Curl_multi *multi,
          removed. */
       struct connectdata *easy_conn = data->easy_conn;
       if(easy_conn) {
-        if(easy_conn->recv_pipe && easy_conn->recv_pipe->size > 1) {
+        if(easy_conn->recv_pipe.size > 1) {
           /* the handle should not be removed from the pipe yet */
           remove_sock_from_hash = FALSE;
 
@@ -2387,12 +2400,12 @@ static void singlesocket(struct Curl_multi *multi,
              isn't already) */
           if(entry->easy == data) {
             if(Curl_recvpipe_head(data, easy_conn))
-              entry->easy = easy_conn->recv_pipe->head->next->ptr;
+              entry->easy = easy_conn->recv_pipe.head->next->ptr;
             else
-              entry->easy = easy_conn->recv_pipe->head->ptr;
+              entry->easy = easy_conn->recv_pipe.head->ptr;
           }
         }
-        if(easy_conn->send_pipe  && easy_conn->send_pipe->size > 1) {
+        if(easy_conn->send_pipe.size > 1) {
           /* the handle should not be removed from the pipe yet */
           remove_sock_from_hash = FALSE;
 
@@ -2401,9 +2414,9 @@ static void singlesocket(struct Curl_multi *multi,
              isn't already) */
           if(entry->easy == data) {
             if(Curl_sendpipe_head(data, easy_conn))
-              entry->easy = easy_conn->send_pipe->head->next->ptr;
+              entry->easy = easy_conn->send_pipe.head->next->ptr;
             else
-              entry->easy = easy_conn->send_pipe->head->ptr;
+              entry->easy = easy_conn->send_pipe.head->ptr;
           }
         }
         /* Don't worry about overwriting recv_pipe head with send_pipe_head,
@@ -2459,8 +2472,6 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
   }
 }
 
-
-
 /*
  * add_next_timeout()
  *
@@ -2478,15 +2489,18 @@ static CURLMcode add_next_timeout(struct timeval now,
                                   struct Curl_easy *d)
 {
   struct timeval *tv = &d->state.expiretime;
-  struct curl_llist *list = d->state.timeoutlist;
+  struct curl_llist *list = &d->state.timeoutlist;
   struct curl_llist_element *e;
+  struct time_node *node = NULL;
 
   /* move over the timeout list for this specific handle and remove all
      timeouts that are now passed tense and store the next pending
      timeout in *tv */
   for(e = list->head; e;) {
     struct curl_llist_element *n = e->next;
-    long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
+    time_t diff;
+    node = (struct time_node *)e->ptr;
+    diff = curlx_tvdiff(node->time, now);
     if(diff <= 0)
       /* remove outdated entry */
       Curl_llist_remove(list, e, NULL);
@@ -2504,7 +2518,7 @@ static CURLMcode add_next_timeout(struct timeval now,
   }
   else {
     /* copy the first entry to 'tv' */
-    memcpy(tv, e->ptr, sizeof(*tv));
+    memcpy(tv, &node->time, sizeof(*tv));
 
     /* remove first entry from list */
     Curl_llist_remove(list, e, NULL);
@@ -2544,7 +2558,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
     /* or should we fall-through and do the timer-based stuff? */
     return result;
   }
-  else if(s != CURL_SOCKET_TIMEOUT) {
+  if(s != CURL_SOCKET_TIMEOUT) {
 
     struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
 
@@ -2569,13 +2583,11 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
          head.  If we should read from the socket, take the recv_pipe head. */
       if(data->easy_conn) {
         if((ev_bitmask & CURL_POLL_OUT) &&
-           data->easy_conn->send_pipe &&
-           data->easy_conn->send_pipe->head)
-          data = data->easy_conn->send_pipe->head->ptr;
+           data->easy_conn->send_pipe.head)
+          data = data->easy_conn->send_pipe.head->ptr;
         else if((ev_bitmask & CURL_POLL_IN) &&
-                data->easy_conn->recv_pipe &&
-                data->easy_conn->recv_pipe->head)
-          data = data->easy_conn->recv_pipe->head->ptr;
+                data->easy_conn->recv_pipe.head)
+          data = data->easy_conn->recv_pipe.head->ptr;
       }
 
       if(data->easy_conn &&
@@ -2764,7 +2776,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
 
     if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
       /* some time left before expiration */
-      *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
+      *timeout_ms = (long)curlx_tvdiff(multi->timetree->key, now);
       if(!*timeout_ms)
         /*
          * Since we only provide millisecond resolution on the returned value
@@ -2832,17 +2844,23 @@ static int update_timer(struct Curl_multi *multi)
 }
 
 /*
- * multi_freetimeout()
+ * multi_deltimeout()
  *
- * Callback used by the llist system when a single timeout list entry is
- * destroyed.
+ * Remove a given timestamp from the list of timeouts.
  */
-static void multi_freetimeout(void *user, void *entryptr)
+static void
+multi_deltimeout(struct Curl_easy *data, expire_id eid)
 {
-  (void)user;
-
-  /* the entry was plain malloc()'ed */
-  free(entryptr);
+  struct curl_llist_element *e;
+  struct curl_llist *timeoutlist = &data->state.timeoutlist;
+  /* find and remove the specific node from the list */
+  for(e = timeoutlist->head; e; e = e->next) {
+    struct time_node *n = (struct time_node *)e->ptr;
+    if(n->eid == eid) {
+      Curl_llist_remove(timeoutlist, e, NULL);
+      return;
+    }
+  }
 }
 
 /*
@@ -2853,25 +2871,28 @@ static void multi_freetimeout(void *user, void *entryptr)
  *
  */
 static CURLMcode
-multi_addtimeout(struct curl_llist *timeoutlist,
-                 struct timeval *stamp)
+multi_addtimeout(struct Curl_easy *data,
+                 struct timeval *stamp,
+                 expire_id eid)
 {
   struct curl_llist_element *e;
-  struct timeval *timedup;
+  struct time_node *node;
   struct curl_llist_element *prev = NULL;
+  size_t n;
+  struct curl_llist *timeoutlist = &data->state.timeoutlist;
 
-  timedup = malloc(sizeof(*timedup));
-  if(!timedup)
-    return CURLM_OUT_OF_MEMORY;
+  node = &data->state.expires[eid];
 
-  /* copy the timestamp */
-  memcpy(timedup, stamp, sizeof(*timedup));
+  /* copy the timestamp and id */
+  memcpy(&node->time, stamp, sizeof(*stamp));
+  node->eid = eid; /* also marks it as in use */
 
-  if(Curl_llist_count(timeoutlist)) {
+  n = Curl_llist_count(timeoutlist);
+  if(n) {
     /* find the correct spot in the list */
     for(e = timeoutlist->head; e; e = e->next) {
-      struct timeval *checktime = e->ptr;
-      long diff = curlx_tvdiff(*checktime, *timedup);
+      struct time_node *check = (struct time_node *)e->ptr;
+      time_t diff = curlx_tvdiff(check->time, node->time);
       if(diff > 0)
         break;
       prev = e;
@@ -2881,11 +2902,7 @@ multi_addtimeout(struct curl_llist *timeoutlist,
   /* else
      this is the first timeout on the list */
 
-  if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
-    free(timedup);
-    return CURLM_OUT_OF_MEMORY;
-  }
-
+  Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
   return CURLM_OK;
 }
 
@@ -2897,8 +2914,10 @@ multi_addtimeout(struct curl_llist *timeoutlist,
  *
  * The timeout will be added to a queue of timeouts if it defines a moment in
  * time that is later than the current head of queue.
+ *
+ * Expire replaces a former timeout using the same id if already set.
  */
-void Curl_expire(struct Curl_easy *data, long milli)
+void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
 {
   struct Curl_multi *multi = data->multi;
   struct timeval *nowp = &data->state.expiretime;
@@ -2910,9 +2929,11 @@ void Curl_expire(struct Curl_easy *data, long milli)
   if(!multi)
     return;
 
+  DEBUGASSERT(id < EXPIRE_LAST);
+
   set = Curl_tvnow();
-  set.tv_sec += milli/1000;
-  set.tv_usec += (milli%1000)*1000;
+  set.tv_sec += (long)(milli/1000);
+  set.tv_usec += (long)(milli%1000)*1000;
 
   if(set.tv_usec >= 1000000) {
     set.tv_sec++;
@@ -2923,17 +2944,21 @@ void Curl_expire(struct Curl_easy *data, long milli)
     /* This means that the struct is added as a node in the splay tree.
        Compare if the new time is earlier, and only remove-old/add-new if it
        is. */
-    long diff = curlx_tvdiff(set, *nowp);
+    time_t diff = curlx_tvdiff(set, *nowp);
+
+    /* remove the previous timer first, if there */
+    multi_deltimeout(data, id);
+
     if(diff > 0) {
       /* the new expire time was later so just add it to the queue
          and get out */
-      multi_addtimeout(data->state.timeoutlist, &set);
+      multi_addtimeout(data, &set, id);
       return;
     }
 
     /* the new time is newer than the presently set one, so add the current
        to the queue and update the head */
-    multi_addtimeout(data->state.timeoutlist, nowp);
+    multi_addtimeout(data, nowp, id);
 
     /* Since this is an updated time, we must remove the previous entry from
        the splay tree first and then re-add the new value */
@@ -2951,46 +2976,17 @@ void Curl_expire(struct Curl_easy *data, long milli)
 }
 
 /*
- * Curl_expire_latest()
- *
- * This is like Curl_expire() but will only add a timeout node to the list of
- * timers if there is no timeout that will expire before the given time.
+ * Curl_expire_done()
  *
- * Use this function if the code logic risks calling this function many times
- * or if there's no particular conditional wait in the code for this specific
- * time-out period to expire.
+ * Removes the expire timer. Marks it as done.
  *
  */
-void Curl_expire_latest(struct Curl_easy *data, long milli)
+void Curl_expire_done(struct Curl_easy *data, expire_id id)
 {
-  struct timeval *expire = &data->state.expiretime;
-
-  struct timeval set;
-
-  set = Curl_tvnow();
-  set.tv_sec += milli / 1000;
-  set.tv_usec += (milli % 1000) * 1000;
-
-  if(set.tv_usec >= 1000000) {
-    set.tv_sec++;
-    set.tv_usec -= 1000000;
-  }
-
-  if(expire->tv_sec || expire->tv_usec) {
-    /* This means that the struct is added as a node in the splay tree.
-       Compare if the new time is earlier, and only remove-old/add-new if it
-         is. */
-    long diff = curlx_tvdiff(set, *expire);
-    if(diff > 0)
-      /* the new expire time was later than the top time, so just skip this */
-      return;
-  }
-
-  /* Just add the timeout like normal */
-  Curl_expire(data, milli);
+  /* remove the timer, if there */
+  multi_deltimeout(data, id);
 }
 
-
 /*
  * Curl_expire_clear()
  *
@@ -3010,7 +3006,7 @@ void Curl_expire_clear(struct Curl_easy *data)
   if(nowp->tv_sec || nowp->tv_usec) {
     /* Since this is an cleared time, we must remove the previous entry from
        the splay tree */
-    struct curl_llist *list = data->state.timeoutlist;
+    struct curl_llist *list = &data->state.timeoutlist;
 
     rc = Curl_splayremovebyaddr(multi->timetree,
                                 &data->state.timenode,
@@ -3019,8 +3015,9 @@ void Curl_expire_clear(struct Curl_easy *data)
       infof(data, "Internal error clearing splay node = %d\n", rc);
 
     /* flush the timeout list too */
-    while(list->size > 0)
+    while(list->size > 0) {
       Curl_llist_remove(list, list->tail, NULL);
+    }
 
 #ifdef DEBUGBUILD
     infof(data, "Expire cleared\n");
@@ -3070,17 +3067,17 @@ curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
 
 struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
 {
-  return multi->pipelining_site_bl;
+  return &multi->pipelining_site_bl;
 }
 
 struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
 {
-  return multi->pipelining_server_bl;
+  return &multi->pipelining_server_bl;
 }
 
 void Curl_multi_process_pending_handles(struct Curl_multi *multi)
 {
-  struct curl_llist_element *e = multi->pending->head;
+  struct curl_llist_element *e = multi->pending.head;
 
   while(e) {
     struct Curl_easy *data = e->ptr;
@@ -3090,10 +3087,10 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
       multistate(data, CURLM_STATE_CONNECT);
 
       /* Remove this node from the list */
-      Curl_llist_remove(multi->pending, e, NULL);
+      Curl_llist_remove(&multi->pending, e, NULL);
 
       /* Make sure that the handle will be processed soonish. */
-      Curl_expire_latest(data, 0);
+      Curl_expire(data, 0, EXPIRE_RUN_NOW);
     }
 
     e = next; /* operate on next handle */
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index c56b6ae..e6ffbf5 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -25,6 +25,7 @@
 #include "conncache.h"
 
 struct Curl_message {
+  struct curl_llist_element list;
   /* the 'CURLMsg' is the part that is visible to the external user */
   struct CURLMsg extmsg;
 };
@@ -38,7 +39,9 @@ typedef enum {
   CURLM_STATE_CONNECT,      /* 2 - resolve/connect has been sent off */
   CURLM_STATE_WAITRESOLVE,  /* 3 - awaiting the resolve to finalize */
   CURLM_STATE_WAITCONNECT,  /* 4 - awaiting the TCP connect to finalize */
-  CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */
+  CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization
+                                   to complete and/or proxy CONNECT to
+                                   finalize */
   CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
   CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
                                    phase */
@@ -78,10 +81,10 @@ struct Curl_multi {
   int num_alive; /* amount of easy handles that are added but have not yet
                     reached COMPLETE state */
 
-  struct curl_llist *msglist; /* a list of messages from completed transfers */
+  struct curl_llist msglist; /* a list of messages from completed transfers */
 
-  struct curl_llist *pending; /* Curl_easys that are in the
-                                 CURLM_STATE_CONNECT_PEND state */
+  struct curl_llist pending; /* Curl_easys that are in the
+                                CURLM_STATE_CONNECT_PEND state */
 
   /* callback function and user data pointer for the *socket() API */
   curl_socket_callback socket_cb;
@@ -136,11 +139,11 @@ struct Curl_multi {
                                      bigger than this is not
                                      considered for pipelining */
 
-  struct curl_llist *pipelining_site_bl; /* List of sites that are blacklisted
-                                            from pipelining */
+  struct curl_llist pipelining_site_bl; /* List of sites that are blacklisted
+                                           from pipelining */
 
-  struct curl_llist *pipelining_server_bl; /* List of server types that are
-                                              blacklisted from pipelining */
+  struct curl_llist pipelining_server_bl; /* List of server types that are
+                                             blacklisted from pipelining */
 
   /* timer callback and user data pointer for the *socket() API */
   curl_multi_timer_callback timer_cb;
diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index eaff496..a877571 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -25,9 +25,10 @@
 /*
  * Prototypes for library-wide functions provided by multi.c
  */
-void Curl_expire(struct Curl_easy *data, long milli);
+
+void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
 void Curl_expire_clear(struct Curl_easy *data);
-void Curl_expire_latest(struct Curl_easy *data, long milli);
+void Curl_expire_done(struct Curl_easy *data, expire_id id);
 bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
 void Curl_multi_handlePipeBreak(struct Curl_easy *data);
 
diff --git a/Utilities/cmcurl/lib/non-ascii.c b/Utilities/cmcurl/lib/non-ascii.c
index ed14618..2f5de4c 100644
--- a/Utilities/cmcurl/lib/non-ascii.c
+++ b/Utilities/cmcurl/lib/non-ascii.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -117,7 +117,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
     /* call iconv */
     input_ptr = output_ptr = buffer;
     in_bytes = out_bytes = length;
-    rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
+    rc = iconv(data->outbound_cd, (const char **)&input_ptr, &in_bytes,
                &output_ptr, &out_bytes);
     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
       error = ERRNO;
diff --git a/Utilities/cmcurl/lib/nonblock.c b/Utilities/cmcurl/lib/nonblock.c
index b764278..5959281 100644
--- a/Utilities/cmcurl/lib/nonblock.c
+++ b/Utilities/cmcurl/lib/nonblock.c
@@ -58,8 +58,7 @@ int curlx_nonblock(curl_socket_t sockfd,    /* operate on this */
   flags = sfcntl(sockfd, F_GETFL, 0);
   if(nonblock)
     return sfcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
-  else
-    return sfcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
+  return sfcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
 
 #elif defined(HAVE_IOCTL_FIONBIO)
 
diff --git a/Utilities/cmcurl/lib/nwlib.c b/Utilities/cmcurl/lib/nwlib.c
index 42b6aa0..290cbe3 100644
--- a/Utilities/cmcurl/lib/nwlib.c
+++ b/Utilities/cmcurl/lib/nwlib.c
@@ -184,7 +184,8 @@ int GetOrSetUpData(int id, libdata_t **appData,
      */
     NXLock(gLibLock);
 
-    if(!(app_data = (libdata_t *) get_app_data(id))) {
+    app_data = (libdata_t *) get_app_data(id);
+    if(!app_data) {
       app_data = malloc(sizeof(libdata_t));
 
       if(app_data) {
@@ -259,7 +260,8 @@ int GetOrSetUpData(int id, libdata_t **appData,
           err         = ENOMEM;
         }
 
-        if((err = NXKeySetValue(key, thread_data))) {
+        err = NXKeySetValue(key, thread_data);
+        if(err) {
           free(thread_data->twentybytes);
           free(thread_data);
           thread_data = (libthreaddata_t *) NULL;
@@ -303,14 +305,14 @@ void DisposeThreadData(void *data)
 /* For native CLib-based NLM seems we can do a bit more simple. */
 #include <nwthread.h>
 
-int main (void)
+int main(void)
 {
   /* initialize any globals here... */
 
   /* do this if any global initializing was done
   SynchronizeStart();
   */
-  ExitThread (TSR_THREAD, 0);
+  ExitThread(TSR_THREAD, 0);
   return 0;
 }
 
diff --git a/Utilities/cmcurl/lib/nwos.c b/Utilities/cmcurl/lib/nwos.c
index 385f9c8..c6c22cc 100644
--- a/Utilities/cmcurl/lib/nwos.c
+++ b/Utilities/cmcurl/lib/nwos.c
@@ -26,7 +26,7 @@
 
 #ifdef __NOVELL_LIBC__
 /* For native LibC-based NLM we need to do nothing. */
-int netware_init (void)
+int netware_init(void)
 {
   return 0;
 }
@@ -45,7 +45,7 @@ NETDB_DEFINE_CONTEXT
 #include <arpa/inet.h>
 NETINET_DEFINE_CONTEXT
 
-int netware_init (void)
+int netware_init(void)
 {
   int rc = 0;
   unsigned int myHandle = GetNLMHandle();
@@ -72,13 +72,13 @@ int netware_init (void)
 }
 
 /* dummy function to satisfy newer prelude */
-int __init_environment (void)
+int __init_environment(void)
 {
   return 0;
 }
 
 /* dummy function to satisfy newer prelude */
-int __deinit_environment (void)
+int __deinit_environment(void)
 {
   return 0;
 }
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index bf2c8fd..5ed79b7 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -44,12 +44,12 @@
 
 /* Returns timeout in ms. 0 or negative number means the timeout has already
    triggered */
-long Curl_pp_state_timeout(struct pingpong *pp)
+time_t Curl_pp_state_timeout(struct pingpong *pp)
 {
   struct connectdata *conn = pp->conn;
   struct Curl_easy *data=conn->data;
-  long timeout_ms; /* in milliseconds */
-  long timeout2_ms; /* in milliseconds */
+  time_t timeout_ms; /* in milliseconds */
+  time_t timeout2_ms; /* in milliseconds */
   long response_time= (data->set.server_response_timeout)?
     data->set.server_response_timeout: pp->response_time;
 
@@ -83,8 +83,8 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
   struct connectdata *conn = pp->conn;
   curl_socket_t sock = conn->sock[FIRSTSOCKET];
   int rc;
-  long interval_ms;
-  long timeout_ms = Curl_pp_state_timeout(pp);
+  time_t interval_ms;
+  time_t timeout_ms = Curl_pp_state_timeout(pp);
   struct Curl_easy *data=conn->data;
   CURLcode result = CURLE_OK;
 
@@ -101,7 +101,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
   else
     interval_ms = 0; /* immediate */
 
-  if(Curl_pp_moredata(pp))
+  if(Curl_ssl_data_pending(conn, FIRSTSOCKET))
+    rc = 1;
+  else if(Curl_pp_moredata(pp))
     /* We are receiving and there is data in the cache so just read it */
     rc = 1;
   else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
@@ -150,7 +152,7 @@ void Curl_pp_init(struct pingpong *pp)
  *
  * Curl_pp_vsendf()
  *
- * Send the formated string as a command to a pingpong server. Note that
+ * Send the formatted string as a command to a pingpong server. Note that
  * the string should not have any CRLF appended, as this function will
  * append the necessary things itself.
  *
@@ -237,7 +239,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
  *
  * Curl_pp_sendf()
  *
- * Send the formated string as a command to a pingpong server. Note that
+ * Send the formatted string as a command to a pingpong server. Note that
  * the string should not have any CRLF appended, as this function will
  * append the necessary things itself.
  *
@@ -284,7 +286,8 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
   /* number of bytes in the current line, so far */
   perline = (ssize_t)(ptr-pp->linestart_resp);
 
-  while((pp->nread_resp<BUFSIZE) && (keepon && !result)) {
+  while((pp->nread_resp < (size_t)data->set.buffer_size) &&
+        (keepon && !result)) {
 
     if(pp->cache) {
       /* we had data in the "cache", copy that instead of doing an actual
@@ -294,7 +297,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
        * it would have been populated with something of size int to begin
        * with, even though its datatype may be larger than an int.
        */
-      DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1));
+      DEBUGASSERT((ptr+pp->cache_size) <= (buf+data->set.buffer_size+1));
       memcpy(ptr, pp->cache, pp->cache_size);
       gotbytes = (ssize_t)pp->cache_size;
       free(pp->cache);    /* free the cache */
@@ -306,8 +309,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
       enum protection_level prot = conn->data_prot;
       conn->data_prot = PROT_CLEAR;
 #endif
-      DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1));
-      result = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp,
+      DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
+                  (buf + data->set.buffer_size + 1));
+      result = Curl_read(conn, sockfd, ptr,
+                         data->set.buffer_size - pp->nread_resp,
                          &gotbytes);
 #ifdef HAVE_GSSAPI
       DEBUGASSERT(prot  > PROT_NONE && prot < PROT_LAST);
@@ -400,7 +405,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
       }
       else if(keepon) {
 
-        if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) {
+        if((perline == gotbytes) && (gotbytes > data->set.buffer_size/2)) {
           /* We got an excessive line without newlines and we need to deal
              with it. We keep the first bytes of the line then we throw
              away the rest. */
@@ -412,7 +417,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
              interested in the first piece */
           clipamount = 40;
         }
-        else if(pp->nread_resp > BUFSIZE/2) {
+        else if(pp->nread_resp > (size_t)data->set.buffer_size/2) {
           /* We got a large chunk of data and there's potentially still
              trailing data to take care of, so we put any such part in the
              "cache", clear the buffer to make space and restart. */
diff --git a/Utilities/cmcurl/lib/pingpong.h b/Utilities/cmcurl/lib/pingpong.h
index 2f649d5..ee1a59b 100644
--- a/Utilities/cmcurl/lib/pingpong.h
+++ b/Utilities/cmcurl/lib/pingpong.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -88,14 +88,14 @@ void Curl_pp_init(struct pingpong *pp);
 
 /* Returns timeout in ms. 0 or negative number means the timeout has already
    triggered */
-long Curl_pp_state_timeout(struct pingpong *pp);
+time_t Curl_pp_state_timeout(struct pingpong *pp);
 
 
 /***********************************************************************
  *
  * Curl_pp_sendf()
  *
- * Send the formated string as a command to a pingpong server. Note that
+ * Send the formatted string as a command to a pingpong server. Note that
  * the string should not have any CRLF appended, as this function will
  * append the necessary things itself.
  *
@@ -108,7 +108,7 @@ CURLcode Curl_pp_sendf(struct pingpong *pp,
  *
  * Curl_pp_vsendf()
  *
- * Send the formated string as a command to a pingpong server. Note that
+ * Send the formatted string as a command to a pingpong server. Note that
  * the string should not have any CRLF appended, as this function will
  * append the necessary things itself.
  *
diff --git a/Utilities/cmcurl/lib/pipeline.c b/Utilities/cmcurl/lib/pipeline.c
index 40a5e82..b8d2037 100644
--- a/Utilities/cmcurl/lib/pipeline.c
+++ b/Utilities/cmcurl/lib/pipeline.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2013, Linus Nielsen Feltzing, <linus at haxx.se>
- * Copyright (C) 2013-2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2013 - 2017, Daniel Stenberg, <daniel at 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
@@ -38,16 +38,15 @@
 #include "memdebug.h"
 
 struct site_blacklist_entry {
-  char *hostname;
+  struct curl_llist_element list;
   unsigned short port;
+  char hostname[1];
 };
 
 static void site_blacklist_llist_dtor(void *user, void *element)
 {
   struct site_blacklist_entry *entry = element;
   (void)user;
-
-  Curl_safefree(entry->hostname);
   free(entry);
 }
 
@@ -69,8 +68,8 @@ bool Curl_pipeline_penalized(struct Curl_easy *data,
     curl_off_t recv_size = -2; /* Make it easy to spot in the log */
 
     /* Find the head of the recv pipe, if any */
-    if(conn->recv_pipe && conn->recv_pipe->head) {
-      struct Curl_easy *recv_handle = conn->recv_pipe->head->ptr;
+    if(conn->recv_pipe.head) {
+      struct Curl_easy *recv_handle = conn->recv_pipe.head->ptr;
 
       recv_size = recv_handle->req.size;
 
@@ -94,8 +93,8 @@ bool Curl_pipeline_penalized(struct Curl_easy *data,
 static CURLcode addHandleToPipeline(struct Curl_easy *data,
                                     struct curl_llist *pipeline)
 {
-  if(!Curl_llist_insert_next(pipeline, pipeline->tail, data))
-    return CURLE_OUT_OF_MEMORY;
+  Curl_llist_insert_next(pipeline, pipeline->tail, data,
+                         &data->pipeline_queue);
   return CURLE_OK;
 }
 
@@ -103,18 +102,18 @@ static CURLcode addHandleToPipeline(struct Curl_easy *data,
 CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle,
                                      struct connectdata *conn)
 {
-  struct curl_llist_element *sendhead = conn->send_pipe->head;
+  struct curl_llist_element *sendhead = conn->send_pipe.head;
   struct curl_llist *pipeline;
   CURLcode result;
 
-  pipeline = conn->send_pipe;
+  pipeline = &conn->send_pipe;
 
   result = addHandleToPipeline(handle, pipeline);
 
-  if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
+  if(pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head) {
     /* this is a new one as head, expire it */
     Curl_pipeline_leave_write(conn); /* not in use yet */
-    Curl_expire(conn->send_pipe->head->ptr, 0);
+    Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
   }
 
 #if 0 /* enable for pipeline debugging */
@@ -135,21 +134,21 @@ void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle,
 {
   struct curl_llist_element *curr;
 
-  curr = conn->send_pipe->head;
+  curr = conn->send_pipe.head;
   while(curr) {
     if(curr->ptr == handle) {
-      Curl_llist_move(conn->send_pipe, curr,
-                      conn->recv_pipe, conn->recv_pipe->tail);
+      Curl_llist_move(&conn->send_pipe, curr,
+                      &conn->recv_pipe, conn->recv_pipe.tail);
 
-      if(conn->send_pipe->head) {
+      if(conn->send_pipe.head) {
         /* Since there's a new easy handle at the start of the send pipeline,
            set its timeout value to 1ms to make it trigger instantly */
         Curl_pipeline_leave_write(conn); /* not used now */
 #ifdef DEBUGBUILD
         infof(conn->data, "%p is at send pipe head B!\n",
-              (void *)conn->send_pipe->head->ptr);
+              (void *)conn->send_pipe.head->ptr);
 #endif
-        Curl_expire(conn->send_pipe->head->ptr, 0);
+        Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
       }
 
       /* The receiver's list is not really interesting here since either this
@@ -191,36 +190,28 @@ bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle,
 }
 
 CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
-                                           struct curl_llist **list_ptr)
+                                           struct curl_llist *list)
 {
-  struct curl_llist *old_list = *list_ptr;
-  struct curl_llist *new_list = NULL;
+  /* Free the old list */
+  if(list->size)
+    Curl_llist_destroy(list, NULL);
 
   if(sites) {
-    new_list = Curl_llist_alloc((curl_llist_dtor) site_blacklist_llist_dtor);
-    if(!new_list)
-      return CURLM_OUT_OF_MEMORY;
+    Curl_llist_init(list, (curl_llist_dtor) site_blacklist_llist_dtor);
 
     /* Parse the URLs and populate the list */
     while(*sites) {
-      char *hostname;
       char *port;
       struct site_blacklist_entry *entry;
 
-      hostname = strdup(*sites);
-      if(!hostname) {
-        Curl_llist_destroy(new_list, NULL);
-        return CURLM_OUT_OF_MEMORY;
-      }
-
-      entry = malloc(sizeof(struct site_blacklist_entry));
+      entry = malloc(sizeof(struct site_blacklist_entry) + strlen(*sites));
       if(!entry) {
-        free(hostname);
-        Curl_llist_destroy(new_list, NULL);
+        Curl_llist_destroy(list, NULL);
         return CURLM_OUT_OF_MEMORY;
       }
+      strcpy(entry->hostname, *sites);
 
-      port = strchr(hostname, ':');
+      port = strchr(entry->hostname, ':');
       if(port) {
         *port = '\0';
         port++;
@@ -231,26 +222,11 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
         entry->port = 80;
       }
 
-      entry->hostname = hostname;
-
-      if(!Curl_llist_insert_next(new_list, new_list->tail, entry)) {
-        site_blacklist_llist_dtor(NULL, entry);
-        Curl_llist_destroy(new_list, NULL);
-        return CURLM_OUT_OF_MEMORY;
-      }
-
+      Curl_llist_insert_next(list, list->tail, entry, &entry->list);
       sites++;
     }
   }
 
-  /* Free the old list */
-  if(old_list) {
-    Curl_llist_destroy(old_list, NULL);
-  }
-
-  /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
-  *list_ptr = new_list;
-
   return CURLM_OK;
 }
 
@@ -283,44 +259,39 @@ bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle,
   return FALSE;
 }
 
+struct blacklist_node {
+  struct curl_llist_element list;
+  char server_name[1];
+};
+
 CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
-                                             struct curl_llist **list_ptr)
+                                             struct curl_llist *list)
 {
-  struct curl_llist *old_list = *list_ptr;
-  struct curl_llist *new_list = NULL;
+  /* Free the old list */
+  if(list->size)
+    Curl_llist_destroy(list, NULL);
 
   if(servers) {
-    new_list = Curl_llist_alloc((curl_llist_dtor) server_blacklist_llist_dtor);
-    if(!new_list)
-      return CURLM_OUT_OF_MEMORY;
+    Curl_llist_init(list, (curl_llist_dtor) server_blacklist_llist_dtor);
 
     /* Parse the URLs and populate the list */
     while(*servers) {
-      char *server_name;
+      struct blacklist_node *n;
+      size_t len = strlen(*servers);
 
-      server_name = strdup(*servers);
-      if(!server_name) {
-        Curl_llist_destroy(new_list, NULL);
-        return CURLM_OUT_OF_MEMORY;
-      }
-
-      if(!Curl_llist_insert_next(new_list, new_list->tail, server_name)) {
-        Curl_llist_destroy(new_list, NULL);
-        Curl_safefree(server_name);
+      n = malloc(sizeof(struct blacklist_node) + len);
+      if(!n) {
+        Curl_llist_destroy(list, NULL);
         return CURLM_OUT_OF_MEMORY;
       }
+      strcpy(n->server_name, *servers);
 
+      Curl_llist_insert_next(list, list->tail, n->server_name,
+                             &n->list);
       servers++;
     }
   }
 
-  /* Free the old list */
-  if(old_list) {
-    Curl_llist_destroy(old_list, NULL);
-  }
-
-  /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
-  *list_ptr = new_list;
 
   return CURLM_OK;
 }
@@ -340,14 +311,14 @@ static bool pipe_head(struct Curl_easy *data,
 bool Curl_recvpipe_head(struct Curl_easy *data,
                         struct connectdata *conn)
 {
-  return pipe_head(data, conn->recv_pipe);
+  return pipe_head(data, &conn->recv_pipe);
 }
 
 /* returns TRUE if the given handle is head of the send pipe */
 bool Curl_sendpipe_head(struct Curl_easy *data,
                         struct connectdata *conn)
 {
-  return pipe_head(data, conn->send_pipe);
+  return pipe_head(data, &conn->send_pipe);
 }
 
 
diff --git a/Utilities/cmcurl/lib/pipeline.h b/Utilities/cmcurl/lib/pipeline.h
index a64f710..413ba31 100644
--- a/Utilities/cmcurl/lib/pipeline.h
+++ b/Utilities/cmcurl/lib/pipeline.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2015 - 2017, Daniel Stenberg, <daniel at haxx.se>, et al.
  * Copyright (C) 2013 - 2014, Linus Nielsen Feltzing, <linus at haxx.se>
  *
  * This software is licensed as described in the file COPYING, which
@@ -34,13 +34,13 @@ bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle,
                                     struct connectdata *conn);
 
 CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
-                                           struct curl_llist **list_ptr);
+                                           struct curl_llist *list_ptr);
 
 bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle,
                                       char *server_name);
 
 CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
-                                             struct curl_llist **list_ptr);
+                                             struct curl_llist *list_ptr);
 
 bool Curl_pipeline_checkget_write(struct Curl_easy *data,
                                   struct connectdata *conn);
diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 8486519..3feb3be 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -104,7 +104,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn);
 static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech,
                                   const char *initresp);
 static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp);
-static void pop3_get_message(char *buffer, char** outptr);
+static void pop3_get_message(char *buffer, char **outptr);
 
 /*
  * POP3 protocol handler.
@@ -127,7 +127,8 @@ const struct Curl_handler Curl_handler_pop3 = {
   ZERO_NULL,                        /* readwrite */
   PORT_POP3,                        /* defport */
   CURLPROTO_POP3,                   /* protocol */
-  PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
+  PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
+  PROTOPT_URLOPTIONS
 };
 
 #ifdef USE_SSL
@@ -153,7 +154,7 @@ const struct Curl_handler Curl_handler_pop3s = {
   PORT_POP3S,                       /* defport */
   CURLPROTO_POP3S,                  /* protocol */
   PROTOPT_CLOSEACTION | PROTOPT_SSL
-  | PROTOPT_NOURLQUERY              /* flags */
+  | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */
 };
 #endif
 
@@ -290,10 +291,10 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
  *
  * Gets the authentication message from the response buffer.
  */
-static void pop3_get_message(char *buffer, char** outptr)
+static void pop3_get_message(char *buffer, char **outptr)
 {
   size_t len = 0;
-  char* message = NULL;
+  char *message = NULL;
 
   /* Find the start of the message */
   for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
@@ -799,7 +800,7 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
 
   if(pop3code != '+') {
     if(data->set.use_ssl != CURLUSESSL_TRY) {
-      failf(data, "STARTTLS denied. %c", pop3code);
+      failf(data, "STARTTLS denied");
       result = CURLE_USE_SSL_FAILED;
     }
     else
@@ -1572,7 +1573,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
       if(prev) {
         /* If the partial match was the CRLF and dot then only write the CRLF
            as the server would have inserted the dot */
-        result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB,
+        result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB,
                                    strip_dot ? prev - 1 : prev);
 
         if(result)
diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index 0f67ef2..cfaf404 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -229,16 +229,16 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
  * need to wait until we're back under the speed limit, if needed.
  *
  * The way it works is by having a "starting point" (time & amount of data
- * transfered by then) used in the speed computation, to be used instead of the
- * start of the transfer.
- * This starting point is regularly moved as transfer goes on, to keep getting
- * accurate values (instead of average over the entire tranfer).
+ * transferred by then) used in the speed computation, to be used instead of
+ * the start of the transfer.  This starting point is regularly moved as
+ * transfer goes on, to keep getting accurate values (instead of average over
+ * the entire transfer).
  *
- * This function takes the current amount of data transfered, the amount at the
- * starting point, the limit (in bytes/s), the time of the starting point and
- * the current time.
+ * This function takes the current amount of data transferred, the amount at
+ * the starting point, the limit (in bytes/s), the time of the starting point
+ * and the current time.
  *
- * Returns -1 if no waiting is needed (not enough data transfered since
+ * Returns -1 if no waiting is needed (not enough data transferred since
  * starting point yet), 0 when no waiting is needed but the starting point
  * should be reset (to current), or the number of milliseconds to wait to get
  * back under the speed limit.
@@ -249,24 +249,26 @@ long Curl_pgrsLimitWaitTime(curl_off_t cursize,
                             struct timeval start,
                             struct timeval now)
 {
-    curl_off_t size = cursize - startsize;
-    long minimum, actual;
+  curl_off_t size = cursize - startsize;
+  time_t minimum;
+  time_t actual;
 
-    /* we don't have a starting point yet -- return 0 so it gets (re)set */
-    if(start.tv_sec == 0 && start.tv_usec == 0)
-        return 0;
+  /* we don't have a starting point yet -- return 0 so it gets (re)set */
+  if(start.tv_sec == 0 && start.tv_usec == 0)
+    return 0;
 
-    /* not enough data yet */
-    if(size < limit)
-      return -1;
+  /* not enough data yet */
+  if(size < limit)
+    return -1;
 
-    minimum = (long) (CURL_OFF_T_C(1000) * size / limit);
-    actual = Curl_tvdiff(now, start);
+  minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+  actual = Curl_tvdiff(now, start);
 
-    if(actual < minimum)
-      return minimum - actual;
-    else
-      return 0;
+  if(actual < minimum)
+    /* this is a conversion on some systems (64bit time_t => 32bit long) */
+    return (long)(minimum - actual);
+
+  return 0;
 }
 
 void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
@@ -359,9 +361,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
   now = Curl_tvnow(); /* what time is it */
 
   /* The time spent so far (from the start) */
-  data->progress.timespent =
-    (double)(now.tv_sec - data->progress.start.tv_sec) +
-    (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0;
+  data->progress.timespent = curlx_tvdiff_secs(now, data->progress.start);
   timespent = (curl_off_t)data->progress.timespent;
 
   /* The average download speed this far */
@@ -375,7 +375,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
      (data->progress.timespent>0?data->progress.timespent:1));
 
   /* Calculations done at most once a second, unless end is reached */
-  if(data->progress.lastshow != (long)now.tv_sec) {
+  if(data->progress.lastshow != now.tv_sec) {
     shownow = TRUE;
 
     data->progress.lastshow = now.tv_sec;
@@ -402,7 +402,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
 
     /* first of all, we don't do this if there's no counted seconds yet */
     if(countindex) {
-      long span_ms;
+      time_t span_ms;
 
       /* Get the index position to compare with the 'nowindex' position.
          Get the oldest entry possible. While we have less than CURR_TIME
@@ -454,7 +454,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
         failf(data, "Callback aborted");
       return result;
     }
-    else if(data->set.fprogress) {
+    if(data->set.fprogress) {
       /* The older deprecated callback is set, call that */
       result= data->set.fprogress(data->set.progress_client,
                                   (double)data->progress.size_dl,
diff --git a/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c
new file mode 100644
index 0000000..b6f40ac
--- /dev/null
+++ b/Utilities/cmcurl/lib/rand.c
@@ -0,0 +1,179 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <curl/curl.h>
+#include "vtls/vtls.h"
+#include "sendf.h"
+#include "rand.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
+{
+  unsigned int r;
+  CURLcode result = CURLE_OK;
+  static unsigned int randseed;
+  static bool seeded = FALSE;
+
+#ifdef CURLDEBUG
+  char *force_entropy = getenv("CURL_ENTROPY");
+  if(force_entropy) {
+    if(!seeded) {
+      unsigned int seed = 0;
+      size_t elen = strlen(force_entropy);
+      size_t clen = sizeof(seed);
+      size_t min = elen < clen ? elen : clen;
+      memcpy((char *)&seed, force_entropy, min);
+      randseed = ntohl(seed);
+      seeded = TRUE;
+    }
+    else
+      randseed++;
+    *rnd = randseed;
+    return CURLE_OK;
+  }
+#endif
+
+  /* data may be NULL! */
+  result = Curl_ssl_random(data, (unsigned char *)rnd, sizeof(*rnd));
+  if(result != CURLE_NOT_BUILT_IN)
+    /* only if there is no random function in the TLS backend do the non crypto
+       version, otherwise return result */
+    return result;
+
+  /* ---- non-cryptographic version following ---- */
+
+#ifdef RANDOM_FILE
+  if(!seeded) {
+    /* if there's a random file to read a seed from, use it */
+    int fd = open(RANDOM_FILE, O_RDONLY);
+    if(fd > -1) {
+      /* read random data into the randseed variable */
+      ssize_t nread = read(fd, &randseed, sizeof(randseed));
+      if(nread == sizeof(randseed))
+        seeded = TRUE;
+      close(fd);
+    }
+  }
+#endif
+
+  if(!seeded) {
+    struct timeval now = curlx_tvnow();
+    infof(data, "WARNING: Using weak random seed\n");
+    randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
+    randseed = randseed * 1103515245 + 12345;
+    randseed = randseed * 1103515245 + 12345;
+    randseed = randseed * 1103515245 + 12345;
+    seeded = TRUE;
+  }
+
+  /* Return an unsigned 32-bit pseudo-random number. */
+  r = randseed = randseed * 1103515245 + 12345;
+  *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
+  return CURLE_OK;
+}
+
+/*
+ * Curl_rand() stores 'num' number of random unsigned integers in the buffer
+ * 'rndptr' points to.
+ *
+ * If libcurl is built without TLS support or with a TLS backend that lacks a
+ * proper random API (Gskit, PolarSSL or mbedTLS), this function will use
+ * "weak" random.
+ *
+ * When built *with* TLS support and a backend that offers strong random, it
+ * will return error if it cannot provide strong random values.
+ *
+ * NOTE: 'data' may be passed in as NULL when coming from external API without
+ * easy handle!
+ *
+ */
+
+CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
+{
+  CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+
+  DEBUGASSERT(num > 0);
+
+  while(num) {
+    unsigned int r;
+    size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int);
+
+    result = randit(data, &r);
+    if(result)
+      return result;
+
+    while(left) {
+      *rnd++ = (unsigned char)(r & 0xFF);
+      r >>= 8;
+      --num;
+      --left;
+    }
+  }
+
+  return result;
+}
+
+/*
+ * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
+ * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
+ * size.
+ */
+
+CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
+                       size_t num)
+{
+  CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+  const char *hex = "0123456789abcdef";
+  unsigned char buffer[128];
+  unsigned char *bufp = buffer;
+  DEBUGASSERT(num > 1);
+
+  if((num/2 >= sizeof(buffer)) || !(num&1))
+    /* make sure it fits in the local buffer and that it is an odd number! */
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  num--; /* save one for zero termination */
+
+  result = Curl_rand(data, buffer, num/2);
+  if(result)
+    return result;
+
+  while(num) {
+    *rnd++ = hex[(*bufp & 0xF0)>>4];
+    *rnd++ = hex[*bufp & 0x0F];
+    bufp++;
+    num -= 2;
+  }
+  *rnd = 0;
+
+  return result;
+}
diff --git a/Utilities/cmcurl/lib/rand.h b/Utilities/cmcurl/lib/rand.h
new file mode 100644
index 0000000..c6fae35
--- /dev/null
+++ b/Utilities/cmcurl/lib/rand.h
@@ -0,0 +1,47 @@
+#ifndef HEADER_CURL_RAND_H
+#define HEADER_CURL_RAND_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Curl_rand() stores 'num' number of random unsigned characters in the buffer
+ * 'rnd' points to.
+ *
+ * If libcurl is built without TLS support or with a TLS backend that lacks a
+ * proper random API (Gskit, PolarSSL or mbedTLS), this function will use
+ * "weak" random.
+ *
+ * When built *with* TLS support and a backend that offers strong random, it
+ * will return error if it cannot provide strong random values.
+ *
+ * NOTE: 'data' may be passed in as NULL when coming from external API without
+ * easy handle!
+ *
+ */
+CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
+
+/* Same as above but outputs only random lowercase hex characters.
+   Does NOT terminate.*/
+CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
+                       size_t num);
+
+#endif /* HEADER_CURL_RAND_H */
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index d1bad19..1810cda 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -36,6 +36,7 @@
 #include "strcase.h"
 #include "select.h"
 #include "connect.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -139,7 +140,7 @@ static CURLcode rtsp_setup_connection(struct connectdata *conn)
  * want to block the application forever while receiving a stream. Therefore,
  * we cannot assume that an RTSP socket is dead just because it is readable.
  *
- * Instead, if it is readable, run Curl_getconnectinfo() to peek at the socket
+ * Instead, if it is readable, run Curl_connalive() to peek at the socket
  * and distinguish between closed and data.
  */
 bool Curl_rtsp_connisdead(struct connectdata *check)
@@ -156,12 +157,9 @@ bool Curl_rtsp_connisdead(struct connectdata *check)
     /* socket is in an error state */
     ret_val = TRUE;
   }
-  else if((sval & CURL_CSELECT_IN) && check->data) {
-    /* readable with no error. could be closed or could be alive but we can
-       only check if we have a proper Curl_easy for the connection */
-    curl_socket_t connectinfo = Curl_getconnectinfo(check->data, &check);
-    if(connectinfo != CURL_SOCKET_BAD)
-      ret_val = FALSE;
+  else if(sval & CURL_CSELECT_IN) {
+    /* readable with no error. could still be closed */
+    ret_val = !Curl_connalive(check);
   }
 
   return ret_val;
@@ -218,7 +216,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
             CSeq_sent, CSeq_recv);
       return CURLE_RTSP_CSEQ_ERROR;
     }
-    else if(data->set.rtspreq == RTSPREQ_RECEIVE &&
+    if(data->set.rtspreq == RTSPREQ_RECEIVE &&
             (conn->proto.rtspc.rtp_channel == -1)) {
       infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
       /* TODO CPC: Server -> Client logic here */
@@ -488,7 +486,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
    * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
    * with basic and digest, it will be freed anyway by the next request
    */
-  Curl_safefree (conn->allocptr.userpwd);
+  Curl_safefree(conn->allocptr.userpwd);
   conn->allocptr.userpwd = NULL;
 
   if(result)
@@ -614,9 +612,9 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
 
   if(rtspc->rtp_buf) {
     /* There was some leftover data the last time. Merge buffers */
-    char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread);
+    char *newptr = Curl_saferealloc(rtspc->rtp_buf,
+                                    rtspc->rtp_bufsize + *nread);
     if(!newptr) {
-      Curl_safefree(rtspc->rtp_buf);
       rtspc->rtp_buf = NULL;
       rtspc->rtp_bufsize = 0;
       return CURLE_OUT_OF_MEMORY;
@@ -650,31 +648,29 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
         *readmore = TRUE;
         break;
       }
-      else {
-        /* 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",
-              rtspc->rtp_channel, rtp_length));
-        result = rtp_client_write(conn, &rtp[0], rtp_length + 4);
-        if(result) {
-          failf(data, "Got an error writing an RTP packet");
-          *readmore = FALSE;
-          Curl_safefree(rtspc->rtp_buf);
-          rtspc->rtp_buf = NULL;
-          rtspc->rtp_bufsize = 0;
-          return result;
-        }
+      /* 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",
+             rtspc->rtp_channel, rtp_length));
+      result = rtp_client_write(conn, &rtp[0], rtp_length + 4);
+      if(result) {
+        failf(data, "Got an error writing an RTP packet");
+        *readmore = FALSE;
+        Curl_safefree(rtspc->rtp_buf);
+        rtspc->rtp_buf = NULL;
+        rtspc->rtp_bufsize = 0;
+        return result;
+      }
 
-        /* Move forward in the buffer */
-        rtp_dataleft -= rtp_length + 4;
-        rtp += rtp_length + 4;
+      /* Move forward in the buffer */
+      rtp_dataleft -= rtp_length + 4;
+      rtp += rtp_length + 4;
 
-        if(data->set.rtspreq == RTSPREQ_RECEIVE) {
-          /* If we are in a passive receive, give control back
-           * to the app as often as we can.
-           */
-          k->keepon &= ~KEEP_RECV;
-        }
+      if(data->set.rtspreq == RTSPREQ_RECEIVE) {
+        /* If we are in a passive receive, give control back
+         * to the app as often as we can.
+         */
+        k->keepon &= ~KEEP_RECV;
       }
     }
     else {
@@ -705,20 +701,18 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
     *nread = 0;
     return CURLE_OK;
   }
-  else {
-    /* Fix up k->str to point just after the last RTP packet */
-    k->str += *nread - rtp_dataleft;
+  /* Fix up k->str to point just after the last RTP packet */
+  k->str += *nread - rtp_dataleft;
 
-    /* either all of the data has been read or...
-     * rtp now points at the next byte to parse
-     */
-    if(rtp_dataleft > 0)
-      DEBUGASSERT(k->str[0] == rtp[0]);
+  /* either all of the data has been read or...
+   * rtp now points at the next byte to parse
+   */
+  if(rtp_dataleft > 0)
+    DEBUGASSERT(k->str[0] == rtp[0]);
 
-    DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */
+  DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */
 
-    *nread = rtp_dataleft;
-  }
+  *nread = rtp_dataleft;
 
   /* If we get here, we have finished with the leftover/merge buffer */
   Curl_safefree(rtspc->rtp_buf);
@@ -736,7 +730,7 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
   curl_write_callback writeit;
 
   if(len == 0) {
-    failf (data, "Cannot write a 0 size RTP packet.");
+    failf(data, "Cannot write a 0 size RTP packet.");
     return CURLE_WRITE_ERROR;
   }
 
@@ -744,12 +738,12 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
   wrote = writeit(ptr, 1, len, data->set.rtp_out);
 
   if(CURL_WRITEFUNC_PAUSE == wrote) {
-    failf (data, "Cannot pause RTP");
+    failf(data, "Cannot pause RTP");
     return CURLE_WRITE_ERROR;
   }
 
   if(wrote != len) {
-    failf (data, "Failed writing RTP data");
+    failf(data, "Failed writing RTP data");
     return CURLE_WRITE_ERROR;
   }
 
@@ -799,7 +793,7 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
       /* If the Session ID is not set, and we find it in a response, then set
        * it.
        *
-       * Allow any non whitespace content, up to the field seperator or end of
+       * Allow any non whitespace content, up to the field separator or end of
        * line. RFC 2326 isn't 100% clear on the session ID and for example
        * gstreamer does url-encoded session ID's not covered by the standard.
        */
diff --git a/Utilities/cmcurl/lib/security.c b/Utilities/cmcurl/lib/security.c
index ff26066..f4a8763 100644
--- a/Utilities/cmcurl/lib/security.c
+++ b/Utilities/cmcurl/lib/security.c
@@ -62,7 +62,7 @@
 #include "sendf.h"
 #include "strcase.h"
 #include "warnless.h"
-
+#include "strdup.h"
 /* The last #include file should be: */
 #include "memdebug.h"
 
@@ -88,7 +88,8 @@ name_to_level(const char *name)
 
 /* Convert a protocol |level| to its char representation.
    We take an int to catch programming mistakes. */
-static char level_to_char(int level) {
+static char level_to_char(int level)
+{
   switch(level) {
   case PROT_CLEAR:
     return 'C';
@@ -202,7 +203,7 @@ static CURLcode read_data(struct connectdata *conn,
   if(len) {
     /* only realloc if there was a length */
     len = ntohl(len);
-    tmp = realloc(buf->data, len);
+    tmp = Curl_saferealloc(buf->data, len);
   }
   if(tmp == NULL)
     return CURLE_OUT_OF_MEMORY;
@@ -222,7 +223,7 @@ buffer_read(struct krb5buffer *buf, void *data, size_t len)
 {
   if(buf->size - buf->index < len)
     len = buf->size - buf->index;
-  memcpy(data, (char*)buf->data + buf->index, len);
+  memcpy(data, (char *)buf->data + buf->index, len);
   buf->index += len;
   return len;
 }
@@ -291,7 +292,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
       prot_level = conn->command_prot;
   }
   bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
-                             (void**)&buffer);
+                             (void **)&buffer);
   if(!buffer || bytes <= 0)
     return; /* error */
 
@@ -366,6 +367,10 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
   size_t decoded_sz = 0;
   CURLcode error;
 
+  if(!conn->mech)
+    /* not inititalized, return error */
+    return -1;
+
   DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
 
   error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
@@ -411,7 +416,7 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
 static int sec_set_protection_level(struct connectdata *conn)
 {
   int code;
-  char* pbsz;
+  char *pbsz;
   static unsigned int buffer_size = 1 << 20; /* 1048576 */
   enum protection_level level = conn->request_data_prot;
 
diff --git a/Utilities/cmcurl/lib/select.c b/Utilities/cmcurl/lib/select.c
index d5caa70..4430072 100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -129,7 +129,7 @@ int Curl_wait_ms(int timeout_ms)
  * and a file descriptor is too large for FD_SETSIZE.
  *
  * A negative timeout value makes this function wait indefinitely,
- * unles no valid file descriptor is given, when this happens the
+ * unless no valid file descriptor is given, when this happens the
  * negative timeout is ignored and the function times out immediately.
  *
  * Return values:
@@ -145,7 +145,7 @@ int Curl_wait_ms(int timeout_ms)
 int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
                       curl_socket_t readfd1,
                       curl_socket_t writefd, /* socket to write to */
-                      long timeout_ms)       /* milliseconds to wait */
+                      time_t timeout_ms)     /* milliseconds to wait */
 {
 #ifdef HAVE_POLL_FINE
   struct pollfd pfd[3];
@@ -164,7 +164,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
   int r;
   int ret;
 
-#if SIZEOF_LONG != SIZEOF_INT
+#if SIZEOF_TIME_T != SIZEOF_INT
   /* wrap-around precaution */
   if(timeout_ms >= INT_MAX)
     timeout_ms = INT_MAX;
@@ -380,7 +380,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
  * select() is used instead.  An error is returned if select() is
  * being used and a file descriptor is too large for FD_SETSIZE.
  * A negative timeout value makes this function wait indefinitely,
- * unles no valid file descriptor is given, when this happens the
+ * unless no valid file descriptor is given, when this happens the
  * negative timeout is ignored and the function times out immediately.
  *
  * Return values:
diff --git a/Utilities/cmcurl/lib/select.h b/Utilities/cmcurl/lib/select.h
index 1d26f49..4ed5dd2 100644
--- a/Utilities/cmcurl/lib/select.h
+++ b/Utilities/cmcurl/lib/select.h
@@ -24,10 +24,10 @@
 
 #include "curl_setup.h"
 
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#elif defined(HAVE_POLL_H)
+#ifdef HAVE_POLL_H
 #include <poll.h>
+#elif defined(HAVE_SYS_POLL_H)
+#include <sys/poll.h>
 #endif
 
 /*
@@ -73,7 +73,7 @@ struct pollfd
 
 int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
                       curl_socket_t writefd,
-                      long timeout_ms);
+                      time_t timeout_ms);
 
 #define SOCKET_READABLE(x,z) \
   Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z)
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index 2101797..595c361 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -33,6 +33,7 @@
 #include "non-ascii.h"
 #include "strerror.h"
 #include "select.h"
+#include "strdup.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -122,6 +123,13 @@ static size_t convert_lineends(struct Curl_easy *data,
 #endif /* CURL_DO_LINEEND_CONV */
 
 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
+bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
+{
+  struct postponed_data * const psnd = &(conn->postponed[sockindex]);
+  return psnd->buffer && psnd->allocated_size &&
+         psnd->recv_size > psnd->recv_processed;
+}
+
 static void pre_receive_plain(struct connectdata *conn, int num)
 {
   const curl_socket_t sockfd = conn->sock[num];
@@ -141,7 +149,7 @@ static void pre_receive_plain(struct connectdata *conn, int num)
       /* Have some incoming data */
       if(!psnd->buffer) {
         /* Use buffer double default size for intermediate buffer */
-        psnd->allocated_size = 2 * BUFSIZE;
+        psnd->allocated_size = 2 * conn->data->set.buffer_size;
         psnd->buffer = malloc(psnd->allocated_size);
         psnd->recv_size = 0;
         psnd->recv_processed = 0;
@@ -201,6 +209,12 @@ static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
 }
 #else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
 /* Use "do-nothing" macros instead of functions when workaround not used */
+bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
+{
+  (void)conn;
+  (void)sockindex;
+  return false;
+}
 #define pre_receive_plain(c,n) do {} WHILE_FALSE
 #define get_pre_recved(c,n,b,l) 0
 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
@@ -229,27 +243,26 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
 {
   va_list ap;
   size_t len;
+  char error[CURL_ERROR_SIZE + 2];
   va_start(ap, fmt);
 
-  vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
+  vsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
+  len = strlen(error);
 
   if(data->set.errorbuffer && !data->state.errorbuf) {
-    snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
+    strcpy(data->set.errorbuffer, error);
     data->state.errorbuf = TRUE; /* wrote error string */
   }
   if(data->set.verbose) {
-    len = strlen(data->state.buffer);
-    if(len < BUFSIZE - 1) {
-      data->state.buffer[len] = '\n';
-      data->state.buffer[++len] = '\0';
-    }
-    Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
+    error[len] = '\n';
+    error[++len] = '\0';
+    Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
   }
 
   va_end(ap);
 }
 
-/* Curl_sendf() sends formated data to the server */
+/* Curl_sendf() sends formatted data to the server */
 CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
                     const char *fmt, ...)
 {
@@ -461,21 +474,58 @@ static CURLcode pausewrite(struct Curl_easy *data,
      we want to send we need to dup it to save a copy for when the sending
      is again enabled */
   struct SingleRequest *k = &data->req;
-  char *dupl = malloc(len);
-  if(!dupl)
-    return CURLE_OUT_OF_MEMORY;
+  struct UrlState *s = &data->state;
+  char *dupl;
+  unsigned int i;
+  bool newtype = TRUE;
+
+  if(s->tempcount) {
+    for(i=0; i< s->tempcount; i++) {
+      if(s->tempwrite[i].type == type) {
+        /* data for this type exists */
+        newtype = FALSE;
+        break;
+      }
+    }
+    DEBUGASSERT(i < 3);
+  }
+  else
+    i = 0;
+
+  if(!newtype) {
+    /* append new data to old data */
+
+    /* figure out the new size of the data to save */
+    size_t newlen = len + s->tempwrite[i].len;
+    /* allocate the new memory area */
+    char *newptr = realloc(s->tempwrite[i].buf, newlen);
+    if(!newptr)
+      return CURLE_OUT_OF_MEMORY;
+    /* copy the new data to the end of the new area */
+    memcpy(newptr + s->tempwrite[i].len, ptr, len);
+
+    /* update the pointer and the size */
+    s->tempwrite[i].buf = newptr;
+    s->tempwrite[i].len = newlen;
+  }
+  else {
+    dupl = Curl_memdup(ptr, len);
+    if(!dupl)
+      return CURLE_OUT_OF_MEMORY;
 
-  memcpy(dupl, ptr, len);
+    /* store this information in the state struct for later use */
+    s->tempwrite[i].buf = dupl;
+    s->tempwrite[i].len = len;
+    s->tempwrite[i].type = type;
 
-  /* store this information in the state struct for later use */
-  data->state.tempwrite = dupl;
-  data->state.tempwritesize = len;
-  data->state.tempwritetype = type;
+    if(newtype)
+      s->tempcount++;
+  }
 
   /* mark the connection as RECV paused */
   k->keepon |= KEEP_RECV_PAUSE;
 
-  DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
+  DEBUGF(infof(data, "Paused %zu bytes in buffer for type %02x\n",
                len, type));
 
   return CURLE_OK;
@@ -488,7 +538,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
  */
 CURLcode Curl_client_chop_write(struct connectdata *conn,
                                 int type,
-                                char * ptr,
+                                char *ptr,
                                 size_t len)
 {
   struct Curl_easy *data = conn->data;
@@ -498,31 +548,10 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
   if(!len)
     return CURLE_OK;
 
-  /* If reading is actually paused, we're forced to append this chunk of data
-     to the already held data, but only if it is the same type as otherwise it
-     can't work and it'll return error instead. */
-  if(data->req.keepon & KEEP_RECV_PAUSE) {
-    size_t newlen;
-    char *newptr;
-    if(type != data->state.tempwritetype)
-      /* major internal confusion */
-      return CURLE_RECV_ERROR;
-
-    DEBUGASSERT(data->state.tempwrite);
-
-    /* figure out the new size of the data to save */
-    newlen = len + data->state.tempwritesize;
-    /* allocate the new memory area */
-    newptr = realloc(data->state.tempwrite, newlen);
-    if(!newptr)
-      return CURLE_OUT_OF_MEMORY;
-    /* copy the new data to the end of the new area */
-    memcpy(newptr + data->state.tempwritesize, ptr, len);
-    /* update the pointer and the size */
-    data->state.tempwrite = newptr;
-    data->state.tempwritesize = newlen;
-    return CURLE_OK;
-  }
+  /* If reading is paused, append this data to the already held data for this
+     type. */
+  if(data->req.keepon & KEEP_RECV_PAUSE)
+    return pausewrite(data, type, ptr, len);
 
   /* Determine the callback(s) to use. */
   if(type & CLIENTWRITE_BODY)
@@ -552,10 +581,9 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
           failf(data, "Write callback asked for PAUSE when not supported!");
           return CURLE_WRITE_ERROR;
         }
-        else
-          return pausewrite(data, type, ptr, len);
+        return pausewrite(data, type, ptr, len);
       }
-      else if(wrote != chunklen) {
+      if(wrote != chunklen) {
         failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
         return CURLE_WRITE_ERROR;
       }
@@ -571,7 +599,7 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
         return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
 
       if(wrote != chunklen) {
-        failf (data, "Failed writing header");
+        failf(data, "Failed writing header");
         return CURLE_WRITE_ERROR;
       }
     }
@@ -603,6 +631,8 @@ CURLcode Curl_client_write(struct connectdata *conn,
   if(0 == len)
     len = strlen(ptr);
 
+  DEBUGASSERT(type <= 3);
+
   /* FTP data may need conversion. */
   if((type & CLIENTWRITE_BODY) &&
     (conn->handler->protocol & PROTO_FAMILY_FTP) &&
@@ -639,8 +669,7 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
 #endif
     if(return_error)
       return CURLE_AGAIN;
-    else
-      return CURLE_RECV_ERROR;
+    return CURLE_RECV_ERROR;
   }
 
   /* we only return number of bytes read when we return OK */
@@ -664,9 +693,10 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
   ssize_t nread = 0;
   size_t bytesfromsocket = 0;
   char *buffertofill = NULL;
+  struct Curl_easy *data = conn->data;
 
   /* if HTTP/1 pipelining is both wanted and possible */
-  bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1) &&
+  bool pipelining = Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
     (conn->bundle->multiuse == BUNDLE_PIPELINING);
 
   /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
@@ -692,13 +722,11 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
     }
     /* If we come here, it means that there is no data to read from the buffer,
      * so we read from the socket */
-    bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
+    bytesfromsocket = CURLMIN(sizerequested, MASTERBUF_SIZE);
     buffertofill = conn->master_buffer;
   }
   else {
-    bytesfromsocket = CURLMIN((long)sizerequested,
-                              conn->data->set.buffer_size ?
-                              conn->data->set.buffer_size : BUFSIZE);
+    bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
     buffertofill = buf;
   }
 
@@ -723,21 +751,19 @@ static int showit(struct Curl_easy *data, curl_infotype type,
 {
   static const char s_infotype[CURLINFO_END][3] = {
     "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
+  int rc = 0;
 
 #ifdef CURL_DOES_CONVERSIONS
-  char buf[BUFSIZE+1];
+  char *buf = NULL;
   size_t conv_size = 0;
 
   switch(type) {
   case CURLINFO_HEADER_OUT:
-    /* assume output headers are ASCII */
-    /* copy the data into my buffer so the original is unchanged */
-    if(size > BUFSIZE) {
-      size = BUFSIZE; /* truncate if necessary */
-      buf[BUFSIZE] = '\0';
-    }
+    buf = Curl_memdup(ptr, size);
+    if(!buf)
+      return 1;
     conv_size = size;
-    memcpy(buf, ptr, size);
+
     /* Special processing is needed for this block if it
      * contains both headers and data (separated by CRLFCRLF).
      * We want to convert just the headers, leaving the data as-is.
@@ -765,26 +791,29 @@ static int showit(struct Curl_easy *data, curl_infotype type,
 #endif /* CURL_DOES_CONVERSIONS */
 
   if(data->set.fdebug)
-    return (*data->set.fdebug)(data, type, ptr, size,
-                               data->set.debugdata);
-
-  switch(type) {
-  case CURLINFO_TEXT:
-  case CURLINFO_HEADER_OUT:
-  case CURLINFO_HEADER_IN:
-    fwrite(s_infotype[type], 2, 1, data->set.err);
-    fwrite(ptr, size, 1, data->set.err);
+    rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+  else {
+    switch(type) {
+    case CURLINFO_TEXT:
+    case CURLINFO_HEADER_OUT:
+    case CURLINFO_HEADER_IN:
+      fwrite(s_infotype[type], 2, 1, data->set.err);
+      fwrite(ptr, size, 1, data->set.err);
 #ifdef CURL_DOES_CONVERSIONS
-    if(size != conv_size) {
-      /* we had untranslated data so we need an explicit newline */
-      fwrite("\n", 1, 1, data->set.err);
-    }
+      if(size != conv_size) {
+        /* we had untranslated data so we need an explicit newline */
+        fwrite("\n", 1, 1, data->set.err);
+      }
 #endif
-    break;
-  default: /* nada */
-    break;
+      break;
+    default: /* nada */
+      break;
+    }
   }
-  return 0;
+#ifdef CURL_DOES_CONVERSIONS
+  free(buf);
+#endif
+  return rc;
 }
 
 int Curl_debug(struct Curl_easy *data, curl_infotype type,
@@ -796,7 +825,7 @@ int Curl_debug(struct Curl_easy *data, curl_infotype type,
     char buffer[160];
     const char *t=NULL;
     const char *w="Data";
-    switch (type) {
+    switch(type) {
     case CURLINFO_HEADER_IN:
       w = "Header";
       /* FALLTHROUGH */
diff --git a/Utilities/cmcurl/lib/sendf.h b/Utilities/cmcurl/lib/sendf.h
index a951a0b..fbe4f99 100644
--- a/Utilities/cmcurl/lib/sendf.h
+++ b/Utilities/cmcurl/lib/sendf.h
@@ -56,6 +56,8 @@ CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr,
 CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
                            size_t len) WARN_UNUSED_RESULT;
 
+bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex);
+
 /* internal read-function, does plain socket only */
 CURLcode Curl_read_plain(curl_socket_t sockfd,
                          char *buf,
diff --git a/Utilities/cmcurl/lib/setup-os400.h b/Utilities/cmcurl/lib/setup-os400.h
index e32b72f..a3c2a7b 100644
--- a/Utilities/cmcurl/lib/setup-os400.h
+++ b/Utilities/cmcurl/lib/setup-os400.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -41,18 +41,18 @@ typedef unsigned long   u_int32_t;
 #include <qsoasync.h>
 #include <gssapi.h>
 
-extern int      Curl_getaddrinfo_a(const char * nodename,
-                                   const char * servname,
-                                   const struct addrinfo * hints,
-                                   struct addrinfo * * res);
+extern int Curl_getaddrinfo_a(const char *nodename,
+                              const char *servname,
+                              const struct addrinfo *hints,
+                              struct addrinfo **res);
 #define getaddrinfo             Curl_getaddrinfo_a
 
 
-extern int      Curl_getnameinfo_a(const struct sockaddr * sa,
-                                   curl_socklen_t salen,
-                                   char * nodename, curl_socklen_t nodenamelen,
-                                   char * servname, curl_socklen_t servnamelen,
-                                   int flags);
+extern int Curl_getnameinfo_a(const struct sockaddr *sa,
+                              curl_socklen_t salen,
+                              char *nodename, curl_socklen_t nodenamelen,
+                              char *servname, curl_socklen_t servnamelen,
+                              int flags);
 #define getnameinfo             Curl_getnameinfo_a
 
 
@@ -79,7 +79,7 @@ extern int      Curl_gsk_secure_soc_init(gsk_handle my_session_handle);
 
 extern int      Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,
                                                 GSK_BUF_ID bufID,
-                                                const char * buffer,
+                                                const char *buffer,
                                                 int bufSize);
 #define gsk_attribute_set_buffer        Curl_gsk_attribute_set_buffer_a
 
@@ -95,29 +95,29 @@ extern int      Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
 
 extern int      Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
                                                 GSK_CALLBACK_ID callBackID,
-                                                void * callBackAreaPtr);
+                                                void *callBackAreaPtr);
 #define gsk_attribute_set_callback      Curl_gsk_attribute_set_callback
 
 extern int      Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,
                                                 GSK_BUF_ID bufID,
-                                                const char * * buffer,
-                                                int * bufSize);
+                                                const char **buffer,
+                                                int *bufSize);
 #define gsk_attribute_get_buffer        Curl_gsk_attribute_get_buffer_a
 
 extern int      Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,
                                             GSK_ENUM_ID enumID,
-                                            GSK_ENUM_VALUE * enumValue);
+                                            GSK_ENUM_VALUE *enumValue);
 #define gsk_attribute_get_enum  Curl_gsk_attribute_get_enum
 
 extern int      Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
                                                      GSK_NUM_ID numID,
-                                                     int * numValue);
+                                                     int *numValue);
 #define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value
 
 extern int      Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
                                  GSK_CERT_ID certID,
-                                 const gsk_cert_data_elem * * certDataElem,
-                                 int * certDataElementCount);
+                                 const gsk_cert_data_elem **certDataElem,
+                                 int *certDataElementCount);
 #define gsk_attribute_get_cert_info     Curl_gsk_attribute_get_cert_info
 
 extern int      Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
@@ -125,13 +125,13 @@ extern int      Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
 #define gsk_secure_soc_misc     Curl_gsk_secure_soc_misc
 
 extern int      Curl_gsk_secure_soc_read(gsk_handle my_session_handle,
-                                         char * readBuffer,
-                                         int readBufSize, int * amtRead);
+                                         char *readBuffer,
+                                         int readBufSize, int *amtRead);
 #define gsk_secure_soc_read     Curl_gsk_secure_soc_read
 
 extern int      Curl_gsk_secure_soc_write(gsk_handle my_session_handle,
-                                          char * writeBuffer,
-                                          int writeBufSize, int * amtWritten);
+                                          char *writeBuffer,
+                                          int writeBufSize, int *amtWritten);
 #define gsk_secure_soc_write    Curl_gsk_secure_soc_write
 
 extern const char *     Curl_gsk_strerror_a(int gsk_return_value);
@@ -202,10 +202,10 @@ extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
 
 extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen);
 extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen);
-extern int Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
-            struct sockaddr * dstaddr, int addrlen);
-extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
-                                struct sockaddr * fromaddr, int * addrlen);
+extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags,
+                             struct sockaddr * dstaddr, int addrlen);
+extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags,
+                               struct sockaddr *fromaddr, int *addrlen);
 
 #define connect                 Curl_os400_connect
 #define bind                    Curl_os400_bind
diff --git a/Utilities/cmcurl/lib/setup-vms.h b/Utilities/cmcurl/lib/setup-vms.h
index 4b78e0b..6c454ae 100644
--- a/Utilities/cmcurl/lib/setup-vms.h
+++ b/Utilities/cmcurl/lib/setup-vms.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -41,7 +41,7 @@
 #   endif
 #endif
 #include <stdlib.h>
-    char * decc$getenv(const char * __name);
+char *decc$getenv(const char *__name);
 #include <pwd.h>
 
 #include <string.h>
@@ -79,23 +79,24 @@
 #   if __INITIAL_POINTER_SIZE == 32
 /* Translate the path, but only if the path is a VMS file specification */
 /* The translation is usually only needed for older versions of VMS */
-static char * vms_translate_path(const char * path) {
-char * unix_path;
-char * test_str;
-
-    /* See if the result is in VMS format, if not, we are done */
-    /* Assume that this is a PATH, not just some data */
-    test_str = strpbrk(path, ":[<^");
-    if(test_str == NULL) {
-      return (char *)path;
-    }
-
-    unix_path = decc$translate_vms(path);
-
-    if((int)unix_path <= 0) {
-      /* We can not translate it, so return the original string */
-      return (char *)path;
-    }
+static char *vms_translate_path(const char *path)
+{
+  char *unix_path;
+  char *test_str;
+
+  /* See if the result is in VMS format, if not, we are done */
+  /* Assume that this is a PATH, not just some data */
+  test_str = strpbrk(path, ":[<^");
+  if(test_str == NULL) {
+    return (char *)path;
+  }
+
+  unix_path = decc$translate_vms(path);
+
+  if((int)unix_path <= 0) {
+    /* We can not translate it, so return the original string */
+    return (char *)path;
+  }
 }
 #   else
     /* VMS translate path is actually not needed on the current 64 bit */
@@ -111,74 +112,74 @@ char * test_str;
 #   endif
 #endif
 
-static char * vms_getenv(const char * envvar) {
+static char *vms_getenv(const char *envvar)
+{
+  char *result;
+  char *vms_path;
 
-char * result;
-char * vms_path;
-
-    /* first use the DECC getenv() function */
-    result = decc$getenv(envvar);
-    if(result == NULL) {
-      return result;
-    }
+  /* first use the DECC getenv() function */
+  result = decc$getenv(envvar);
+  if(result == NULL) {
+    return result;
+  }
 
-    vms_path = result;
-    result = vms_translate_path(vms_path);
+  vms_path = result;
+  result = vms_translate_path(vms_path);
 
-    /* note that if you backport this to use VAX C RTL, that the VAX C RTL */
-    /* may do a malloc(2048) for each call to getenv(), so you will need   */
-    /* to add a free(vms_path) */
-    /* Do not do a free() for DEC C RTL builds, which should be used for */
-    /* VMS 5.5-2 and later, even if using GCC */
+  /* note that if you backport this to use VAX C RTL, that the VAX C RTL */
+  /* may do a malloc(2048) for each call to getenv(), so you will need   */
+  /* to add a free(vms_path) */
+  /* Do not do a free() for DEC C RTL builds, which should be used for */
+  /* VMS 5.5-2 and later, even if using GCC */
 
-    return result;
+  return result;
 }
 
 
 static struct passwd vms_passwd_cache;
 
-static struct passwd * vms_getpwuid(uid_t uid) {
-
-struct passwd * my_passwd;
+static struct passwd * vms_getpwuid(uid_t uid)
+{
+  struct passwd * my_passwd;
 
 /* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */
 #ifdef __DECC
 #   if __INITIAL_POINTER_SIZE
-__char_ptr32 unix_path;
+  __char_ptr32 unix_path;
 #   else
-char * unix_path;
+  char *unix_path;
 #   endif
 #else
-char * unix_path;
+  char *unix_path;
 #endif
 
-    my_passwd = decc_getpwuid(uid);
-    if(my_passwd == NULL) {
-      return my_passwd;
-    }
-
-    unix_path = vms_translate_path(my_passwd->pw_dir);
-
-    if((long)unix_path <= 0) {
-      /* We can not translate it, so return the original string */
-      return my_passwd;
-    }
-
-    /* If no changes needed just return it */
-    if(unix_path == my_passwd->pw_dir) {
-      return my_passwd;
-    }
-
-    /* Need to copy the structure returned */
-    /* Since curl is only using pw_dir, no need to fix up *
-    /* the pw_shell when running under Bash */
-    vms_passwd_cache.pw_name = my_passwd->pw_name;
-    vms_passwd_cache.pw_uid = my_passwd->pw_uid;
-    vms_passwd_cache.pw_gid = my_passwd->pw_uid;
-    vms_passwd_cache.pw_dir = unix_path;
-    vms_passwd_cache.pw_shell = my_passwd->pw_shell;
-
-    return &vms_passwd_cache;
+  my_passwd = decc_getpwuid(uid);
+  if(my_passwd == NULL) {
+    return my_passwd;
+  }
+
+  unix_path = vms_translate_path(my_passwd->pw_dir);
+
+  if((long)unix_path <= 0) {
+    /* We can not translate it, so return the original string */
+    return my_passwd;
+  }
+
+  /* If no changes needed just return it */
+  if(unix_path == my_passwd->pw_dir) {
+    return my_passwd;
+  }
+
+  /* Need to copy the structure returned */
+  /* Since curl is only using pw_dir, no need to fix up */
+  /* the pw_shell when running under Bash */
+  vms_passwd_cache.pw_name = my_passwd->pw_name;
+  vms_passwd_cache.pw_uid = my_passwd->pw_uid;
+  vms_passwd_cache.pw_gid = my_passwd->pw_uid;
+  vms_passwd_cache.pw_dir = unix_path;
+  vms_passwd_cache.pw_shell = my_passwd->pw_shell;
+
+  return &vms_passwd_cache;
 }
 
 #ifdef __DECC
diff --git a/Utilities/cmcurl/lib/share.h b/Utilities/cmcurl/lib/share.h
index e689ff2..c039a16 100644
--- a/Utilities/cmcurl/lib/share.h
+++ b/Utilities/cmcurl/lib/share.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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,8 +54,8 @@ struct Curl_share {
   long sessionage;
 };
 
-CURLSHcode Curl_share_lock (struct Curl_easy *, curl_lock_data,
-                            curl_lock_access);
-CURLSHcode Curl_share_unlock (struct Curl_easy *, curl_lock_data);
+CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data,
+                           curl_lock_access);
+CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data);
 
 #endif /* HEADER_CURL_SHARE_H */
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index 7cb0c96..5b1ffa9 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2014, Bill Nagel <wnagel at tycoint.com>, Exacq Technologies
- * Copyright (C) 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2016-2017, Daniel Stenberg, <daniel at 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
@@ -23,8 +23,8 @@
 
 #include "curl_setup.h"
 
-#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
-    (CURL_SIZEOF_CURL_OFF_T > 4)
+#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) &&  \
+  (CURL_SIZEOF_CURL_OFF_T > 4)
 
 #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
 
@@ -32,8 +32,12 @@
 
 #ifdef HAVE_PROCESS_H
 #include <process.h>
+#ifdef CURL_WINDOWS_APP
+#define getpid GetCurrentProcessId
+#else
 #define getpid _getpid
 #endif
+#endif
 
 #include "smb.h"
 #include "urldata.h"
@@ -117,18 +121,18 @@ const struct Curl_handler Curl_handler_smbs = {
 #define SERVICENAME       "?????"
 
 /* Append a string to an SMB message */
-#define MSGCAT(str) \
-  strcpy(p, (str)); \
+#define MSGCAT(str)                             \
+  strcpy(p, (str));                             \
   p += strlen(str);
 
 /* Append a null-terminated string to an SMB message */
-#define MSGCATNULL(str) \
-  strcpy(p, (str)); \
+#define MSGCATNULL(str)                         \
+  strcpy(p, (str));                             \
   p += strlen(str) + 1;
 
 /* SMB is mostly little endian */
 #if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
-   defined(__OS400__)
+  defined(__OS400__)
 static unsigned short smb_swap16(unsigned short x)
 {
   return (unsigned short) ((x << 8) | ((x >> 8) & 0xff));
@@ -137,20 +141,20 @@ static unsigned short smb_swap16(unsigned short x)
 static unsigned int smb_swap32(unsigned int x)
 {
   return (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) |
-         ((x >> 24) & 0xff);
+    ((x >> 24) & 0xff);
 }
 
 #ifdef HAVE_LONGLONG
 static unsigned long long smb_swap64(unsigned long long x)
 {
   return ((unsigned long long) smb_swap32((unsigned int) x) << 32) |
-          smb_swap32((unsigned int) (x >> 32));
+    smb_swap32((unsigned int) (x >> 32));
 }
 #else
 static unsigned __int64 smb_swap64(unsigned __int64 x)
 {
   return ((unsigned __int64) smb_swap32((unsigned int) x) << 32) |
-          smb_swap32((unsigned int) (x >> 32));
+    smb_swap32((unsigned int) (x >> 32));
 }
 #endif
 #else
@@ -197,7 +201,7 @@ static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
 
   if(smb->state != newstate)
     infof(conn->data, "SMB conn %p state change from %s to %s\n",
-    (void *)smb, names[smb->state], names[newstate]);
+          (void *)smb, names[smb->state], names[newstate]);
 #endif
 
   smb->state = newstate;
@@ -223,7 +227,7 @@ static void request_state(struct connectdata *conn,
 
   if(req->state != newstate)
     infof(conn->data, "SMB request %p state change from %s to %s\n",
-    (void *)req, names[req->state], names[newstate]);
+          (void *)req, names[req->state], names[newstate]);
 #endif
 
   req->state = newstate;
@@ -308,8 +312,9 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
   if(smbc->got < sizeof(unsigned int))
     return CURLE_OK;
 
-  nbt_size = Curl_read16_be((unsigned char *)(buf + sizeof(unsigned short))) +
-             sizeof(unsigned int);
+  nbt_size = Curl_read16_be((const unsigned char *)
+                            (buf + sizeof(unsigned short))) +
+    sizeof(unsigned int);
   if(smbc->got < nbt_size)
     return CURLE_OK;
 
@@ -320,7 +325,7 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
     if(nbt_size >= msg_size + sizeof(unsigned short)) {
       /* Add the byte count */
       msg_size += sizeof(unsigned short) +
-                  Curl_read16_le((unsigned char *)&buf[msg_size]);
+        Curl_read16_le((const unsigned char *)&buf[msg_size]);
       if(nbt_size < msg_size)
         return CURLE_READ_ERROR;
     }
@@ -441,7 +446,7 @@ static CURLcode smb_send_setup(struct connectdata *conn)
 
   Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash);
   Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm);
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
   Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash);
   Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt);
 #else
@@ -602,8 +607,8 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
 
   /* Check if there is data in the transfer buffer */
   if(!smbc->send_size && smbc->upload_size) {
-    int nread = smbc->upload_size > BUFSIZE ? BUFSIZE :
-                                              (int) smbc->upload_size;
+    int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE :
+      (int) smbc->upload_size;
     conn->data->req.upload_fromhere = conn->data->state.uploadbuffer;
     result = Curl_fillreadbuffer(conn, nread, &nread);
     if(result && result != CURLE_AGAIN)
@@ -781,9 +786,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
       next_state = SMB_CLOSE;
       break;
     }
-    len = Curl_read16_le(((unsigned char *) msg) +
+    len = Curl_read16_le(((const unsigned char *) msg) +
                          sizeof(struct smb_header) + 11);
-    off = Curl_read16_le(((unsigned char *) msg) +
+    off = Curl_read16_le(((const unsigned char *) msg) +
                          sizeof(struct smb_header) + 13);
     if(len > 0) {
       if(off + sizeof(unsigned int) + len > smbc->got) {
@@ -812,7 +817,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
       next_state = SMB_CLOSE;
       break;
     }
-    len = Curl_read16_le(((unsigned char *) msg) +
+    len = Curl_read16_le(((const unsigned char *) msg) +
                          sizeof(struct smb_header) + 5);
     conn->data->req.bytecount += len;
     conn->data->req.offset += len;
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index a4fc2c2..fe064cb 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -103,7 +103,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn);
 static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech,
                                   const char *initresp);
 static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp);
-static void smtp_get_message(char *buffer, char** outptr);
+static void smtp_get_message(char *buffer, char **outptr);
 
 /*
  * SMTP protocol handler.
@@ -126,7 +126,8 @@ const struct Curl_handler Curl_handler_smtp = {
   ZERO_NULL,                        /* readwrite */
   PORT_SMTP,                        /* defport */
   CURLPROTO_SMTP,                   /* protocol */
-  PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
+  PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
+  PROTOPT_URLOPTIONS
 };
 
 #ifdef USE_SSL
@@ -152,7 +153,7 @@ const struct Curl_handler Curl_handler_smtps = {
   PORT_SMTPS,                       /* defport */
   CURLPROTO_SMTPS,                  /* protocol */
   PROTOPT_CLOSEACTION | PROTOPT_SSL
-  | PROTOPT_NOURLQUERY              /* flags */
+  | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */
 };
 #endif
 
@@ -278,10 +279,10 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
  *
  * Gets the authentication message from the response buffer.
  */
-static void smtp_get_message(char *buffer, char** outptr)
+static void smtp_get_message(char *buffer, char **outptr)
 {
   size_t len = 0;
-  char* message = NULL;
+  char *message = NULL;
 
   /* Find the start of the message */
   for(message = buffer + 4; *message == ' ' || *message == '\t'; message++)
@@ -692,7 +693,7 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
 
   if(smtpcode != 220) {
     if(data->set.use_ssl != CURLUSESSL_TRY) {
-      failf(data, "STARTTLS denied. %c", smtpcode);
+      failf(data, "STARTTLS denied, code %d", smtpcode);
       result = CURLE_USE_SSL_FAILED;
     }
     else
@@ -1590,7 +1591,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
   if(!scratch || data->set.crlf) {
     oldscratch = scratch;
 
-    scratch = newscratch = malloc(2 * BUFSIZE);
+    scratch = newscratch = malloc(2 * data->set.buffer_size);
     if(!newscratch) {
       failf(data, "Failed to alloc scratch buffer!");
 
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index 742d411..97a44b2 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.c
@@ -57,7 +57,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
   ssize_t nread;
   ssize_t allread = 0;
   int result;
-  long timeleft;
+  time_t timeleft;
   *n = 0;
   for(;;) {
     timeleft = Curl_timeleft(conn->data, NULL, TRUE);
@@ -73,7 +73,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
     result = Curl_read_plain(sockfd, buf, buffersize, &nread);
     if(CURLE_AGAIN == result)
       continue;
-    else if(result)
+    if(result)
       break;
 
     if(buffersize == nread) {
@@ -109,9 +109,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn,
-                     bool protocol4a)
+                     struct connectdata *conn)
 {
+  const bool protocol4a =
+    (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
 #define SOCKS4REQLEN 262
   unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
                                            id */
@@ -126,6 +127,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
     return CURLE_OPERATION_TIMEDOUT;
   }
 
+  if(conn->bits.httpproxy)
+    infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
+          protocol4a ? "a" : "", hostname, remote_port);
+
   (void)curlx_nonblock(sock, FALSE);
 
   infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
@@ -174,11 +179,11 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
       if(hp->ai_family == AF_INET) {
         struct sockaddr_in *saddr_in;
 
-        saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr;
-        socksreq[4] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[0];
-        socksreq[5] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[1];
-        socksreq[6] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[2];
-        socksreq[7] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[3];
+        saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
+        socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0];
+        socksreq[5] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[1];
+        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);
       }
@@ -219,7 +224,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
     ssize_t written;
     ssize_t hostnamelen = 0;
     int packetsize = 9 +
-      (int)strlen((char*)socksreq + 8); /* size including NUL */
+      (int)strlen((char *)socksreq + 8); /* size including NUL */
 
     /* If SOCKS4a, set special invalid IP address 0.0.0.x */
     if(protocol4a) {
@@ -230,7 +235,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
       /* If still enough room in buffer, also append hostname */
       hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
       if(packetsize + hostnamelen <= SOCKS4REQLEN)
-        strcpy((char*)socksreq + packetsize, hostname);
+        strcpy((char *)socksreq + packetsize, hostname);
       else
         hostnamelen = 0; /* Flag: hostname did not fit in buffer */
     }
@@ -376,11 +381,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
   CURLcode code;
   curl_socket_t sock = conn->sock[sockindex];
   struct Curl_easy *data = conn->data;
-  long timeout;
-  bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE;
+  time_t timeout;
+  bool socks5_resolve_local =
+    (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
   const size_t hostname_len = strlen(hostname);
   ssize_t len = 0;
 
+  if(conn->bits.httpproxy)
+    infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
+          hostname, remote_port);
+
   /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
   if(!socks5_resolve_local && hostname_len > 255) {
     infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
@@ -406,7 +416,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
     failf(conn->data, "SOCKS5: no connection here");
     return CURLE_COULDNT_CONNECT;
   }
-  else if(0 == result) {
+  if(0 == result) {
     failf(conn->data, "SOCKS5: connection timeout");
     return CURLE_OPERATION_TIMEDOUT;
   }
@@ -447,7 +457,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
     failf(conn->data, "SOCKS5 nothing to read");
     return CURLE_COULDNT_CONNECT;
   }
-  else if(0 == result) {
+  if(0 == result) {
     failf(conn->data, "SOCKS5 read timeout");
     return CURLE_OPERATION_TIMEDOUT;
   }
@@ -543,7 +553,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
             "SOCKS5 GSSAPI per-message authentication is not supported.");
       return CURLE_COULDNT_CONNECT;
     }
-    else if(socksreq[1] == 255) {
+    if(socksreq[1] == 255) {
 #endif
       if(!proxy_name || !*proxy_name) {
         failf(data,
@@ -605,9 +615,9 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
         struct sockaddr_in *saddr_in;
         socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
 
-        saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr;
+        saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
         for(i = 0; i < 4; i++) {
-          socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i];
+          socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
         }
 
         infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf);
@@ -617,9 +627,10 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
         struct sockaddr_in6 *saddr_in6;
         socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
 
-        saddr_in6 = (struct sockaddr_in6*)(void*)hp->ai_addr;
+        saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr;
         for(i = 0; i < 16; i++) {
-          socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i];
+          socksreq[len++] =
+            ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
         }
 
         infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf);
@@ -761,9 +772,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
     }
     return CURLE_COULDNT_CONNECT;
   }
-  else {
-    infof(data, "SOCKS5 request granted.\n");
-  }
+  infof(data, "SOCKS5 request granted.\n");
 
   (void)curlx_nonblock(sock, TRUE);
   return CURLE_OK; /* Proxy was successful! */
diff --git a/Utilities/cmcurl/lib/socks.h b/Utilities/cmcurl/lib/socks.h
index a44ada6..348707e 100644
--- a/Utilities/cmcurl/lib/socks.h
+++ b/Utilities/cmcurl/lib/socks.h
@@ -25,7 +25,7 @@
 #include "curl_setup.h"
 
 #ifdef CURL_DISABLE_PROXY
-#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
+#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN
 #define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
 #else
 /*
@@ -49,8 +49,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn,
-                     bool protocol4a);
+                     struct connectdata *conn);
 
 /*
  * This function logs in to a SOCKS5 proxy and sends the specifics to the
diff --git a/Utilities/cmcurl/lib/socks_gssapi.c b/Utilities/cmcurl/lib/socks_gssapi.c
index 369245a..54d0635 100644
--- a/Utilities/cmcurl/lib/socks_gssapi.c
+++ b/Utilities/cmcurl/lib/socks_gssapi.c
@@ -46,7 +46,7 @@ static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
 static int check_gss_err(struct Curl_easy *data,
                          OM_uint32 major_status,
                          OM_uint32 minor_status,
-                         const char* function)
+                         const char *function)
 {
   if(GSS_ERROR(major_status)) {
     OM_uint32 maj_stat, min_stat;
@@ -65,7 +65,7 @@ static int check_gss_err(struct Curl_easy *data,
                                     &msg_ctx, &status_string);
       if(maj_stat == GSS_S_COMPLETE) {
         if(sizeof(buf) > len + status_string.length + 1) {
-          strcpy(buf+len, (char*) status_string.value);
+          strcpy(buf+len, (char *) status_string.value);
           len += status_string.length;
         }
         gss_release_buffer(&min_stat, &status_string);
@@ -86,7 +86,7 @@ static int check_gss_err(struct Curl_easy *data,
                                     &msg_ctx, &status_string);
       if(maj_stat == GSS_S_COMPLETE) {
         if(sizeof(buf) > len + status_string.length)
-          strcpy(buf+len, (char*) status_string.value);
+          strcpy(buf+len, (char *) status_string.value);
         gss_release_buffer(&min_stat, &status_string);
         break;
       }
@@ -123,6 +123,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   unsigned char socksreq[4]; /* room for GSS-API exchange header only */
   const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ?
                            data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
+  const size_t serviceptr_length = strlen(serviceptr);
 
   /*   GSS-API request looks like
    * +----+------+-----+----------------+
@@ -134,22 +135,23 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
 
   /* prepare service name */
   if(strchr(serviceptr, '/')) {
-    service.value = malloc(strlen(serviceptr));
+    service.length = serviceptr_length;
+    service.value = malloc(service.length);
     if(!service.value)
       return CURLE_OUT_OF_MEMORY;
-    service.length = strlen(serviceptr);
     memcpy(service.value, serviceptr, service.length);
 
     gss_major_status = gss_import_name(&gss_minor_status, &service,
                                        (gss_OID) GSS_C_NULL_OID, &server);
   }
   else {
-    service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2);
+    service.value = malloc(serviceptr_length +
+                           strlen(conn->socks_proxy.host.name)+2);
     if(!service.value)
       return CURLE_OUT_OF_MEMORY;
-    service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1;
+    service.length = serviceptr_length + strlen(conn->socks_proxy.host.name)+1;
     snprintf(service.value, service.length+1, "%s@%s",
-             serviceptr, conn->proxy.name);
+             serviceptr, conn->socks_proxy.host.name);
 
     gss_major_status = gss_import_name(&gss_minor_status, &service,
                                        GSS_C_NT_HOSTBASED_SERVICE, &server);
@@ -290,9 +292,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   gss_release_name(&gss_status, &server);
 
   /* Everything is good so far, user was authenticated! */
-  gss_major_status = gss_inquire_context (&gss_minor_status, gss_context,
-                                          &gss_client_name, NULL, NULL, NULL,
-                                          NULL, NULL, NULL);
+  gss_major_status = gss_inquire_context(&gss_minor_status, gss_context,
+                                         &gss_client_name, NULL, NULL, NULL,
+                                         NULL, NULL, NULL);
   if(check_gss_err(data, gss_major_status,
                    gss_minor_status, "gss_inquire_context")) {
     gss_delete_sec_context(&gss_status, &gss_context, NULL);
diff --git a/Utilities/cmcurl/lib/socks_sspi.c b/Utilities/cmcurl/lib/socks_sspi.c
index 6053490..edc73ad 100644
--- a/Utilities/cmcurl/lib/socks_sspi.c
+++ b/Utilities/cmcurl/lib/socks_sspi.c
@@ -45,7 +45,7 @@
  */
 static int check_sspi_err(struct connectdata *conn,
                           SECURITY_STATUS status,
-                          const char* function)
+                          const char *function)
 {
   if(status != SEC_E_OK &&
      status != SEC_I_COMPLETE_AND_CONTINUE &&
@@ -86,6 +86,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   unsigned char socksreq[4]; /* room for GSS-API exchange header only */
   const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
                         data->set.str[STRING_PROXY_SERVICE_NAME]  : "rcmd";
+  const size_t service_length = strlen(service);
 
   /*   GSS-API request looks like
    * +----+------+-----+----------------+
@@ -102,11 +103,13 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
       return CURLE_OUT_OF_MEMORY;
   }
   else {
-    service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2);
+    service_name = malloc(service_length +
+                          strlen(conn->socks_proxy.host.name) + 2);
     if(!service_name)
       return CURLE_OUT_OF_MEMORY;
-    snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2,
-             "%s/%s", service, conn->proxy.name);
+    snprintf(service_name, service_length +
+             strlen(conn->socks_proxy.host.name)+2, "%s/%s",
+             service, conn->socks_proxy.host.name);
   }
 
   input_desc.cBuffers = 1;
diff --git a/Utilities/cmcurl/lib/speedcheck.c b/Utilities/cmcurl/lib/speedcheck.c
index 13c34af..8addedd 100644
--- a/Utilities/cmcurl/lib/speedcheck.c
+++ b/Utilities/cmcurl/lib/speedcheck.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -33,42 +33,41 @@ void Curl_speedinit(struct Curl_easy *data)
   memset(&data->state.keeps_speed, 0, sizeof(struct timeval));
 }
 
+/*
+ * @unittest: 1606
+ */
 CURLcode Curl_speedcheck(struct Curl_easy *data,
                          struct timeval now)
 {
-  if((data->progress.current_speed >= 0) &&
-     data->set.low_speed_time &&
-     (Curl_tvlong(data->state.keeps_speed) != 0) &&
-     (data->progress.current_speed < data->set.low_speed_limit)) {
-    long howlong = Curl_tvdiff(now, data->state.keeps_speed);
-    long nextcheck = (data->set.low_speed_time * 1000) - howlong;
+  if((data->progress.current_speed >= 0) && data->set.low_speed_time) {
+    if(data->progress.current_speed < data->set.low_speed_limit) {
+      if(!data->state.keeps_speed.tv_sec)
+        /* under the limit at this very moment */
+        data->state.keeps_speed = now;
+      else {
+        /* how long has it been under the limit */
+        time_t howlong = Curl_tvdiff(now, data->state.keeps_speed);
 
-    /* We are now below the "low speed limit". If we are below it
-       for "low speed time" seconds we consider that enough reason
-       to abort the download. */
-    if(nextcheck <= 0) {
-      /* we have been this slow for long enough, now die */
-      failf(data,
-            "Operation too slow. "
-            "Less than %ld bytes/sec transferred the last %ld seconds",
-            data->set.low_speed_limit,
-            data->set.low_speed_time);
-      return CURLE_OPERATION_TIMEDOUT;
-    }
-    else {
-      /* wait complete low_speed_time */
-      Curl_expire_latest(data, nextcheck);
+        if(howlong >= data->set.low_speed_time * 1000) {
+          /* too long */
+          failf(data,
+                "Operation too slow. "
+                "Less than %ld bytes/sec transferred the last %ld seconds",
+                data->set.low_speed_limit,
+                data->set.low_speed_time);
+          return CURLE_OPERATION_TIMEDOUT;
+        }
+      }
     }
+    else
+      /* faster right now */
+      data->state.keeps_speed.tv_sec = 0;
   }
-  else {
-    /* we keep up the required speed all right */
-    data->state.keeps_speed = now;
 
-    if(data->set.low_speed_limit)
-      /* if there is a low speed limit enabled, we set the expire timer to
-         make this connection's speed get checked again no later than when
-         this time is up */
-      Curl_expire_latest(data, data->set.low_speed_time*1000);
-  }
+  if(data->set.low_speed_limit)
+    /* if low speed limit is enabled, set the expire timer to make this
+       connection's speed get checked again in a second */
+    Curl_expire(data, 1000, EXPIRE_SPEEDCHECK);
+
   return CURLE_OK;
 }
diff --git a/Utilities/cmcurl/lib/splay.c b/Utilities/cmcurl/lib/splay.c
index 7aa2e4b..1b301f9 100644
--- a/Utilities/cmcurl/lib/splay.c
+++ b/Utilities/cmcurl/lib/splay.c
@@ -110,22 +110,17 @@ struct Curl_tree *Curl_splayinsert(struct timeval i,
     t = Curl_splay(i, t);
     if(compare(i, t->key)==0) {
       /* There already exists a node in the tree with the very same key. Build
-         a linked list of nodes. We make the new 'node' struct the new master
-         node and make the previous node the first one in the 'same' list. */
+         a doubly-linked circular list of nodes. We add the new 'node' struct
+         to the end of this list. */
 
-      node->same = t;
-      node->key = i;
-      node->smaller = t->smaller;
-      node->larger = t->larger;
-
-      t->smaller = node; /* in the sub node for this same key, we use the
-                            smaller pointer to point back to the master
-                            node */
-
-      t->key = KEY_NOTUSED; /* and we set the key in the sub node to NOTUSED
+      node->key = KEY_NOTUSED; /* we set the key in the sub node to NOTUSED
                                to quickly identify this node as a subnode */
+      node->samen = t;
+      node->samep = t->samep;
+      t->samep->samen = node;
+      t->samep = node;
 
-      return node; /* new root node */
+      return t; /* the root node always stays the same */
     }
   }
 
@@ -145,16 +140,20 @@ struct Curl_tree *Curl_splayinsert(struct timeval i,
   }
   node->key = i;
 
-  node->same = NULL; /* no identical node (yet) */
+  /* no identical nodes (yet), we are the only one in the list of nodes */
+  node->samen = node;
+  node->samep = node;
   return node;
 }
 
 /* Finds and deletes the best-fit node from the tree. Return a pointer to the
-   resulting tree.  best-fit means the node with the given or lower key */
+   resulting tree.  best-fit means the smallest node if it is not larger than
+   the key */
 struct Curl_tree *Curl_splaygetbest(struct timeval i,
-                                    struct Curl_tree *t,
-                                    struct Curl_tree **removed)
+                                       struct Curl_tree *t,
+                                       struct Curl_tree **removed)
 {
+  static struct timeval tv_zero = {0, 0};
   struct Curl_tree *x;
 
   if(!t) {
@@ -162,49 +161,36 @@ struct Curl_tree *Curl_splaygetbest(struct timeval i,
     return NULL;
   }
 
-  t = Curl_splay(i, t);
+  /* find smallest */
+  t = Curl_splay(tv_zero, t);
   if(compare(i, t->key) < 0) {
-    /* too big node, try the smaller chain */
-    if(t->smaller)
-      t=Curl_splay(t->smaller->key, t);
-    else {
-      /* fail */
-      *removed = NULL;
-      return t;
-    }
+    /* even the smallest is too big */
+    *removed = NULL;
+    return t;
   }
 
-  if(compare(i, t->key) >= 0) {               /* found it */
-    /* FIRST! Check if there is a list with identical keys */
-    x = t->same;
-    if(x) {
-      /* there is, pick one from the list */
+  /* FIRST! Check if there is a list with identical keys */
+  x = t->samen;
+  if(x != t) {
+    /* there is, pick one from the list */
 
-      /* 'x' is the new root node */
+    /* 'x' is the new root node */
 
-      x->key = t->key;
-      x->larger = t->larger;
-      x->smaller = t->smaller;
-
-      *removed = t;
-      return x; /* new root */
-    }
+    x->key = t->key;
+    x->larger = t->larger;
+    x->smaller = t->smaller;
+    x->samep = t->samep;
+    t->samep->samen = x;
 
-    if(t->smaller == NULL) {
-      x = t->larger;
-    }
-    else {
-      x = Curl_splay(i, t->smaller);
-      x->larger = t->larger;
-    }
     *removed = t;
-
-    return x;
-  }
-  else {
-    *removed = NULL; /* no match */
-    return t;        /* It wasn't there */
+    return x; /* new root */
   }
+
+  /* we splayed the tree to the smallest element, there is no smaller */
+  x = t->larger;
+  *removed = t;
+
+  return x;
 }
 
 
@@ -231,19 +217,17 @@ int Curl_splayremovebyaddr(struct Curl_tree *t,
 
   if(compare(KEY_NOTUSED, removenode->key) == 0) {
     /* Key set to NOTUSED means it is a subnode within a 'same' linked list
-       and thus we can unlink it easily. The 'smaller' link of a subnode
-       links to the parent node. */
-    if(removenode->smaller == NULL)
+       and thus we can unlink it easily. */
+    if(removenode->samen == removenode)
+      /* A non-subnode should never be set to KEY_NOTUSED */
       return 3;
 
-    removenode->smaller->same = removenode->same;
-    if(removenode->same)
-      removenode->same->smaller = removenode->smaller;
+    removenode->samep->samen = removenode->samen;
+    removenode->samen->samep = removenode->samep;
 
     /* Ensures that double-remove gets caught. */
-    removenode->smaller = NULL;
+    removenode->samen = removenode;
 
-    /* voila, we're done! */
     *newroot = t; /* return the same root */
     return 0;
   }
@@ -262,14 +246,16 @@ int Curl_splayremovebyaddr(struct Curl_tree *t,
 
   /* Check if there is a list with identical sizes, as then we're trying to
      remove the root node of a list of nodes with identical keys. */
-  x = t->same;
-  if(x) {
+  x = t->samen;
+  if(x != t) {
     /* 'x' is the new root node, we just make it use the root node's
        smaller/larger links */
 
     x->key = t->key;
     x->larger = t->larger;
     x->smaller = t->smaller;
+    x->samep = t->samep;
+    t->samep->samen = x;
   }
   else {
     /* Remove the root node */
diff --git a/Utilities/cmcurl/lib/splay.h b/Utilities/cmcurl/lib/splay.h
index 427bfc8..da81894 100644
--- a/Utilities/cmcurl/lib/splay.h
+++ b/Utilities/cmcurl/lib/splay.h
@@ -26,7 +26,8 @@
 struct Curl_tree {
   struct Curl_tree *smaller; /* smaller node */
   struct Curl_tree *larger;  /* larger node */
-  struct Curl_tree *same;    /* points to a node with identical key */
+  struct Curl_tree *samen;   /* points to the next node with identical key */
+  struct Curl_tree *samep;   /* points to the prev node with identical key */
   struct timeval key;        /* this node's "sort" key */
   void *payload;             /* data the splay code doesn't care about */
 };
diff --git a/Utilities/cmcurl/lib/ssh.c b/Utilities/cmcurl/lib/ssh.c
index 43c8283..00aeca9 100644
--- a/Utilities/cmcurl/lib/ssh.c
+++ b/Utilities/cmcurl/lib/ssh.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -71,7 +71,7 @@
 #include "url.h"
 #include "speedcheck.h"
 #include "getinfo.h"
-
+#include "strdup.h"
 #include "strcase.h"
 #include "vtls/vtls.h"
 #include "connect.h"
@@ -113,6 +113,7 @@
         libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
                                 (t), (m), LIBSSH2_SFTP_REALPATH)
 
+
 /* Local functions: */
 static const char *sftp_libssh2_strerror(int err);
 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
@@ -239,7 +240,7 @@ kbd_callback(const char *name, int name_len, const char *instruction,
 
 static CURLcode sftp_libssh2_error_to_CURLE(int err)
 {
-  switch (err) {
+  switch(err) {
     case LIBSSH2_FX_OK:
       return CURLE_OK;
 
@@ -271,7 +272,7 @@ static CURLcode sftp_libssh2_error_to_CURLE(int err)
 
 static CURLcode libssh2_session_error_to_CURLE(int err)
 {
-  switch (err) {
+  switch(err) {
     /* Ordered by order of appearance in libssh2.h */
     case LIBSSH2_ERROR_NONE:
       return CURLE_OK;
@@ -676,7 +677,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
    * against a known fingerprint, if available.
    */
   if(pubkey_md5 && strlen(pubkey_md5) == 32) {
-    if(!fingerprint || strcmp(md5buffer, pubkey_md5)) {
+    if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) {
       if(fingerprint)
         failf(data,
             "Denied establishing ssh session: mismatch md5 fingerprint. "
@@ -688,14 +689,11 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
       sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
       return sshc->actualcode;
     }
-    else {
-      infof(data, "MD5 checksum match!\n");
-      /* as we already matched, we skip the check for known hosts */
-      return CURLE_OK;
-    }
+    infof(data, "MD5 checksum match!\n");
+    /* as we already matched, we skip the check for known hosts */
+    return CURLE_OK;
   }
-  else
-    return ssh_knownhost(conn);
+  return ssh_knownhost(conn);
 }
 
 /*
@@ -738,7 +736,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc) {
+      if(rc) {
         failf(data, "Failure establishing ssh session");
         state(conn, SSH_SESSION_FREE);
         sshc->actualcode = CURLE_FAILED_INIT;
@@ -782,16 +780,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           state(conn, SSH_AUTH_DONE);
           break;
         }
-        else if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
-           LIBSSH2_ERROR_EAGAIN) {
+        err = libssh2_session_last_errno(sshc->ssh_session);
+        if(err == LIBSSH2_ERROR_EAGAIN)
           rc = LIBSSH2_ERROR_EAGAIN;
-          break;
-        }
         else {
           state(conn, SSH_SESSION_FREE);
           sshc->actualcode = libssh2_session_error_to_CURLE(err);
-          break;
         }
+        break;
       }
       infof(data, "SSH authentication methods available: %s\n",
             sshc->authlist);
@@ -874,7 +870,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           break;
         }
 
-        sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
+        sshc->passphrase = data->set.ssl.key_passwd;
         if(!sshc->passphrase)
           sshc->passphrase = "";
 
@@ -918,6 +914,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
                                          &err_msg, NULL, 0);
         infof(data, "SSH public key authentication failed: %s\n", err_msg);
         state(conn, SSH_AUTH_PASS_INIT);
+        rc = 0; /* clear rc and continue */
       }
       break;
 
@@ -928,6 +925,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       }
       else {
         state(conn, SSH_AUTH_HOST_INIT);
+        rc = 0; /* clear rc and continue */
       }
       break;
 
@@ -940,7 +938,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc == 0) {
+      if(rc == 0) {
         sshc->authed = TRUE;
         infof(data, "Initialized password authentication\n");
         state(conn, SSH_AUTH_DONE);
@@ -989,6 +987,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc < 0) {
           infof(data, "Failure connecting to agent\n");
           state(conn, SSH_AUTH_KEY_INIT);
+          rc = 0; /* clear rc and continue */
         }
         else {
           state(conn, SSH_AUTH_AGENT_LIST);
@@ -1008,6 +1007,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc < 0) {
         infof(data, "Failure requesting identities to agent\n");
         state(conn, SSH_AUTH_KEY_INIT);
+        rc = 0; /* clear rc and continue */
       }
       else {
         state(conn, SSH_AUTH_AGENT);
@@ -1077,7 +1077,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc == 0) {
+      if(rc == 0) {
         sshc->authed = TRUE;
         infof(data, "Initialized keyboard interactive authentication\n");
       }
@@ -1116,21 +1116,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
        */
       sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
       if(!sshc->sftp_session) {
+        char *err_msg;
         if(libssh2_session_last_errno(sshc->ssh_session) ==
            LIBSSH2_ERROR_EAGAIN) {
           rc = LIBSSH2_ERROR_EAGAIN;
           break;
         }
-        else {
-          char *err_msg;
 
-          (void)libssh2_session_last_error(sshc->ssh_session,
-                                           &err_msg, NULL, 0);
-          failf(data, "Failure initializing sftp session: %s", err_msg);
-          state(conn, SSH_SESSION_FREE);
-          sshc->actualcode = CURLE_FAILED_INIT;
-          break;
-        }
+        (void)libssh2_session_last_error(sshc->ssh_session,
+                                         &err_msg, NULL, 0);
+        failf(data, "Failure initializing sftp session: %s", err_msg);
+        state(conn, SSH_SESSION_FREE);
+        sshc->actualcode = CURLE_FAILED_INIT;
+        break;
       }
       state(conn, SSH_SFTP_REALPATH);
       break;
@@ -1147,7 +1145,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc > 0) {
+      if(rc > 0) {
         /* It seems that this string is not always NULL terminated */
         tempHome[rc] = '\0';
         sshc->homedir = strdup(tempHome);
@@ -1261,7 +1259,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           state(conn, SSH_SFTP_NEXT_QUOTE);
         break;
       }
-      else if(cmd) {
+      if(cmd) {
         /*
          * the arguments following the command must be separated from the
          * command with a space so we can check for it unconditionally
@@ -1321,7 +1319,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           state(conn, SSH_SFTP_QUOTE_STAT);
           break;
         }
-        else if(strncasecompare(cmd, "ln ", 3) ||
+        if(strncasecompare(cmd, "ln ", 3) ||
                 strncasecompare(cmd, "symlink ", 8)) {
           /* symbolic linking */
           /* sshc->quote_path1 is the source */
@@ -1443,7 +1441,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
+        if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
           err = sftp_libssh2_last_error(sshc->sftp_session);
           Curl_safefree(sshc->quote_path1);
           Curl_safefree(sshc->quote_path2);
@@ -1514,7 +1512,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0 && !sshc->acceptfail) {
+      if(rc != 0 && !sshc->acceptfail) {
         err = sftp_libssh2_last_error(sshc->sftp_session);
         Curl_safefree(sshc->quote_path1);
         Curl_safefree(sshc->quote_path2);
@@ -1537,7 +1535,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0 && !sshc->acceptfail) {
+      if(rc != 0 && !sshc->acceptfail) {
         err = sftp_libssh2_last_error(sshc->sftp_session);
         Curl_safefree(sshc->quote_path1);
         Curl_safefree(sshc->quote_path2);
@@ -1558,7 +1556,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0 && !sshc->acceptfail) {
+      if(rc != 0 && !sshc->acceptfail) {
         err = sftp_libssh2_last_error(sshc->sftp_session);
         Curl_safefree(sshc->quote_path1);
         failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
@@ -1582,7 +1580,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0 && !sshc->acceptfail) {
+      if(rc != 0 && !sshc->acceptfail) {
         err = sftp_libssh2_last_error(sshc->sftp_session);
         Curl_safefree(sshc->quote_path1);
         Curl_safefree(sshc->quote_path2);
@@ -1601,7 +1599,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0 && !sshc->acceptfail) {
+      if(rc != 0 && !sshc->acceptfail) {
         err = sftp_libssh2_last_error(sshc->sftp_session);
         Curl_safefree(sshc->quote_path1);
         failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
@@ -1619,7 +1617,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0 && !sshc->acceptfail) {
+      if(rc != 0 && !sshc->acceptfail) {
         err = sftp_libssh2_last_error(sshc->sftp_session);
         Curl_safefree(sshc->quote_path1);
         failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
@@ -1642,7 +1640,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc != 0 && !sshc->acceptfail) {
+      if(rc != 0 && !sshc->acceptfail) {
         err = sftp_libssh2_last_error(sshc->sftp_session);
         Curl_safefree(sshc->quote_path1);
         failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(err));
@@ -1705,7 +1703,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc == 0) {
+      if(rc == 0) {
         data->info.filetime = (long)attrs.mtime;
       }
 
@@ -1743,7 +1741,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           if(rc == LIBSSH2_ERROR_EAGAIN) {
             break;
           }
-          else if(rc) {
+          if(rc) {
             data->state.resume_from = 0;
           }
           else {
@@ -1778,47 +1776,47 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
 
         if(LIBSSH2_ERROR_EAGAIN == rc)
           break;
-        else {
-          if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
-            /* only when there was an SFTP protocol error can we extract
-               the sftp error! */
-            err = sftp_libssh2_last_error(sshc->sftp_session);
-          else
-            err = -1; /* not an sftp error at all */
 
-          if(sshc->secondCreateDirs) {
-            state(conn, SSH_SFTP_CLOSE);
-            sshc->actualcode = err>= LIBSSH2_FX_OK?
-              sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
-            failf(data, "Creating the dir/file failed: %s",
-                  sftp_libssh2_strerror(err));
-            break;
-          }
-          else if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
-                   (err == LIBSSH2_FX_FAILURE) ||
-                   (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
-                  (data->set.ftp_create_missing_dirs &&
-                   (strlen(sftp_scp->path) > 1))) {
-            /* try to create the path remotely */
-            sshc->secondCreateDirs = 1;
-            state(conn, SSH_SFTP_CREATE_DIRS_INIT);
-            break;
-          }
+        if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
+          /* only when there was an SFTP protocol error can we extract
+             the sftp error! */
+          err = sftp_libssh2_last_error(sshc->sftp_session);
+        else
+          err = -1; /* not an sftp error at all */
+
+        if(sshc->secondCreateDirs) {
           state(conn, SSH_SFTP_CLOSE);
           sshc->actualcode = err>= LIBSSH2_FX_OK?
             sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
-          if(!sshc->actualcode) {
-            /* Sometimes, for some reason libssh2_sftp_last_error() returns
-               zero even though libssh2_sftp_open() failed previously! We need
-               to work around that! */
-            sshc->actualcode = CURLE_SSH;
-            err=-1;
-          }
-          failf(data, "Upload failed: %s (%d/%d)",
-                err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
-                err, rc);
+          failf(data, "Creating the dir/file failed: %s",
+                sftp_libssh2_strerror(err));
+          break;
+        }
+        if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
+            (err == LIBSSH2_FX_FAILURE) ||
+            (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
+           (data->set.ftp_create_missing_dirs &&
+            (strlen(sftp_scp->path) > 1))) {
+          /* try to create the path remotely */
+          rc = 0; /* clear rc and continue */
+          sshc->secondCreateDirs = 1;
+          state(conn, SSH_SFTP_CREATE_DIRS_INIT);
           break;
         }
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->actualcode = err>= LIBSSH2_FX_OK?
+          sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
+        if(!sshc->actualcode) {
+          /* Sometimes, for some reason libssh2_sftp_last_error() returns
+             zero even though libssh2_sftp_open() failed previously! We need
+             to work around that! */
+          sshc->actualcode = CURLE_SSH;
+          err=-1;
+        }
+        failf(data, "Upload failed: %s (%d/%d)",
+              err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
+              err, rc);
+        break;
       }
 
       /* If we have a restart point then we need to seek to the correct
@@ -1831,32 +1829,31 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         }
 
         if(seekerr != CURL_SEEKFUNC_OK) {
+          curl_off_t passed=0;
 
           if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
             failf(data, "Could not seek stream");
             return CURLE_FTP_COULDNT_USE_REST;
           }
           /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
-          else {
-            curl_off_t passed=0;
-            do {
-              size_t readthisamountnow =
-                (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
-                BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
-
-              size_t actuallyread =
-                data->state.fread_func(data->state.buffer, 1,
-                                       readthisamountnow, data->state.in);
-
-              passed += actuallyread;
-              if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
-                /* this checks for greater-than only to make sure that the
-                   CURL_READFUNC_ABORT return code still aborts */
-                failf(data, "Failed to read data");
-                return CURLE_FTP_COULDNT_USE_REST;
-              }
-            } while(passed < data->state.resume_from);
-          }
+          do {
+            size_t readthisamountnow =
+              (data->state.resume_from - passed > data->set.buffer_size) ?
+              (size_t)data->set.buffer_size :
+              curlx_sotouz(data->state.resume_from - passed);
+
+            size_t actuallyread =
+              data->state.fread_func(data->state.buffer, 1,
+                                     readthisamountnow, data->state.in);
+
+            passed += actuallyread;
+            if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+              /* this checks for greater-than only to make sure that the
+                 CURL_READFUNC_ABORT return code still aborts */
+              failf(data, "Failed to read data");
+              return CURLE_FTP_COULDNT_USE_REST;
+            }
+          } while(passed < data->state.resume_from);
         }
 
         /* now, decrease the size of the read */
@@ -1895,7 +1892,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         /* since we don't really wait for anything at this point, we want the
            state machine to move on as soon as possible so we set a very short
            timeout here */
-        Curl_expire(data, 0);
+        Curl_expire(data, 0, EXPIRE_RUN_NOW);
 
         state(conn, SSH_STOP);
       }
@@ -1921,9 +1918,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
         break;
       }
-      else {
-        state(conn, SSH_SFTP_UPLOAD_INIT);
-      }
+      state(conn, SSH_SFTP_UPLOAD_INIT);
       break;
 
     case SSH_SFTP_CREATE_DIRS_MKDIR:
@@ -1936,7 +1931,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       }
       *sshc->slash_pos = '/';
       ++sshc->slash_pos;
-      if(rc == -1) {
+      if(rc < 0) {
         /*
          * Abort if failure wasn't that the dir already exists or the
          * permission was denied (creation might succeed further down the
@@ -1951,6 +1946,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           sshc->actualcode = result?result:CURLE_SSH;
           break;
         }
+        rc = 0; /* clear rc and continue */
       }
       state(conn, SSH_SFTP_CREATE_DIRS);
       break;
@@ -1977,22 +1973,22 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           rc = LIBSSH2_ERROR_EAGAIN;
           break;
         }
-        else {
-          err = sftp_libssh2_last_error(sshc->sftp_session);
-          failf(data, "Could not open directory for reading: %s",
-                sftp_libssh2_strerror(err));
-          state(conn, SSH_SFTP_CLOSE);
-          result = sftp_libssh2_error_to_CURLE(err);
-          sshc->actualcode = result?result:CURLE_SSH;
-          break;
-        }
+        err = sftp_libssh2_last_error(sshc->sftp_session);
+        failf(data, "Could not open directory for reading: %s",
+              sftp_libssh2_strerror(err));
+        state(conn, SSH_SFTP_CLOSE);
+        result = sftp_libssh2_error_to_CURLE(err);
+        sshc->actualcode = result?result:CURLE_SSH;
+        break;
       }
-      if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) {
+      sshc->readdir_filename = malloc(PATH_MAX+1);
+      if(!sshc->readdir_filename) {
         state(conn, SSH_SFTP_CLOSE);
         sshc->actualcode = CURLE_OUT_OF_MEMORY;
         break;
       }
-      if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) {
+      sshc->readdir_longentry = malloc(PATH_MAX+1);
+      if(!sshc->readdir_longentry) {
         Curl_safefree(sshc->readdir_filename);
         state(conn, SSH_SFTP_CLOSE);
         sshc->actualcode = CURLE_OUT_OF_MEMORY;
@@ -2112,9 +2108,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
 
       /* get room for the filename and extra output */
       sshc->readdir_totalLen += 4 + sshc->readdir_len;
-      new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen);
+      new_readdir_line = Curl_saferealloc(sshc->readdir_line,
+                                          sshc->readdir_totalLen);
       if(!new_readdir_line) {
-        Curl_safefree(sshc->readdir_line);
+        sshc->readdir_line = NULL;
         Curl_safefree(sshc->readdir_filename);
         Curl_safefree(sshc->readdir_longentry);
         state(conn, SSH_SFTP_CLOSE);
@@ -2189,15 +2186,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           rc = LIBSSH2_ERROR_EAGAIN;
           break;
         }
-        else {
-          err = sftp_libssh2_last_error(sshc->sftp_session);
-          failf(data, "Could not open remote file for reading: %s",
-                sftp_libssh2_strerror(err));
-          state(conn, SSH_SFTP_CLOSE);
-          result = sftp_libssh2_error_to_CURLE(err);
-          sshc->actualcode = result?result:CURLE_SSH;
-          break;
-        }
+        err = sftp_libssh2_last_error(sshc->sftp_session);
+        failf(data, "Could not open remote file for reading: %s",
+              sftp_libssh2_strerror(err));
+        state(conn, SSH_SFTP_CLOSE);
+        result = sftp_libssh2_error_to_CURLE(err);
+        sshc->actualcode = result?result:CURLE_SSH;
+        break;
       }
       state(conn, SSH_SFTP_DOWNLOAD_STAT);
       break;
@@ -2212,7 +2207,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      else if(rc ||
+      if(rc ||
               !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
               (attrs.filesize == 0)) {
         /*
@@ -2310,18 +2305,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       state(conn, SSH_STOP);
       break;
     }
-    else {
-      Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
-                          FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
+                        FALSE, NULL, -1, NULL);
 
-      /* not set by Curl_setup_transfer to preserve keepon bits */
-      conn->writesockfd = conn->sockfd;
+    /* not set by Curl_setup_transfer to preserve keepon bits */
+    conn->writesockfd = conn->sockfd;
+
+    /* we want to use the _receiving_ function even when the socket turns
+       out writableable as the underlying libssh2 recv function will deal
+       with both accordingly */
+    conn->cselect_bits = CURL_CSELECT_IN;
 
-      /* we want to use the _receiving_ function even when the socket turns
-         out writableable as the underlying libssh2 recv function will deal
-         with both accordingly */
-      conn->cselect_bits = CURL_CSELECT_IN;
-    }
     if(result) {
       /* this should never occur; the close state should be entered
          at the time the error occurs */
@@ -2339,7 +2333,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc < 0) {
+        if(rc < 0) {
           infof(data, "Failed to close libssh2 file\n");
         }
         sshc->sftp_handle = NULL;
@@ -2373,7 +2367,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc < 0) {
+        if(rc < 0) {
           infof(data, "Failed to close libssh2 file\n");
         }
         sshc->sftp_handle = NULL;
@@ -2383,7 +2377,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc < 0) {
+        if(rc < 0) {
           infof(data, "Failed to stop libssh2 sftp subsystem\n");
         }
         sshc->sftp_session = NULL;
@@ -2428,22 +2422,21 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
                  data->state.infilesize);
       if(!sshc->ssh_channel) {
+        int ssh_err;
+        char *err_msg;
+
         if(libssh2_session_last_errno(sshc->ssh_session) ==
            LIBSSH2_ERROR_EAGAIN) {
           rc = LIBSSH2_ERROR_EAGAIN;
           break;
         }
-        else {
-          int ssh_err;
-          char *err_msg;
 
-          ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
-                                                     &err_msg, NULL, 0));
-          failf(conn->data, "%s", err_msg);
-          state(conn, SSH_SCP_CHANNEL_FREE);
-          sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
-          break;
-        }
+        ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
+                                                   &err_msg, NULL, 0));
+        failf(conn->data, "%s", err_msg);
+        state(conn, SSH_SCP_CHANNEL_FREE);
+        sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
+        break;
       }
 
       /* upload data */
@@ -2498,22 +2491,22 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
 #endif
 
       if(!sshc->ssh_channel) {
+        int ssh_err;
+        char *err_msg;
+
         if(libssh2_session_last_errno(sshc->ssh_session) ==
            LIBSSH2_ERROR_EAGAIN) {
           rc = LIBSSH2_ERROR_EAGAIN;
           break;
         }
-        else {
-          int ssh_err;
-          char *err_msg;
 
-          ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
-                                                     &err_msg, NULL, 0));
-          failf(conn->data, "%s", err_msg);
-          state(conn, SSH_SCP_CHANNEL_FREE);
-          sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
-          break;
-        }
+
+        ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
+                                                   &err_msg, NULL, 0));
+        failf(conn->data, "%s", err_msg);
+        state(conn, SSH_SCP_CHANNEL_FREE);
+        sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
+        break;
       }
 
       /* download data */
@@ -2551,7 +2544,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc) {
+        if(rc) {
           infof(data, "Failed to send libssh2 channel EOF\n");
         }
       }
@@ -2564,7 +2557,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc) {
+        if(rc) {
           infof(data, "Failed to get channel EOF: %d\n", rc);
         }
       }
@@ -2577,7 +2570,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc) {
+        if(rc) {
           infof(data, "Channel failed to close: %d\n", rc);
         }
       }
@@ -2590,7 +2583,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc < 0) {
+        if(rc < 0) {
           infof(data, "Failed to free libssh2 scp subsystem\n");
         }
         sshc->ssh_channel = NULL;
@@ -2612,7 +2605,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc < 0) {
+        if(rc < 0) {
           infof(data, "Failed to free libssh2 scp subsystem\n");
         }
         sshc->ssh_channel = NULL;
@@ -2623,7 +2616,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc < 0) {
+        if(rc < 0) {
           infof(data, "Failed to disconnect libssh2 session\n");
         }
       }
@@ -2648,10 +2641,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc < 0) {
+        if(rc < 0) {
           infof(data, "Failed to disconnect from libssh2 agent\n");
         }
-        libssh2_agent_free (sshc->ssh_agent);
+        libssh2_agent_free(sshc->ssh_agent);
         sshc->ssh_agent = NULL;
 
         /* NB: there is no need to free identities, they are part of internal
@@ -2666,7 +2659,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc == LIBSSH2_ERROR_EAGAIN) {
           break;
         }
-        else if(rc < 0) {
+        if(rc < 0) {
           infof(data, "Failed to free libssh2 session\n");
         }
         sshc->ssh_session = NULL;
@@ -2788,13 +2781,16 @@ static int ssh_getsock(struct connectdata *conn,
 static void ssh_block2waitfor(struct connectdata *conn, bool block)
 {
   struct ssh_conn *sshc = &conn->proto.sshc;
-  int dir;
-  if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
-    /* translate the libssh2 define bits into our own bit defines */
-    conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
-      ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
+  int dir = 0;
+  if(block) {
+    dir = libssh2_session_block_directions(sshc->ssh_session);
+    if(dir) {
+      /* translate the libssh2 define bits into our own bit defines */
+      conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
+        ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
+    }
   }
-  else
+  if(!dir)
     /* It didn't block or libssh2 didn't reveal in which direction, put back
        the original set */
     conn->waitfor = sshc->orig_waitfor;
@@ -2820,7 +2816,7 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
 }
 
 static CURLcode ssh_block_statemach(struct connectdata *conn,
-                                   bool duringconnect)
+                                    bool disconnect)
 {
   struct ssh_conn *sshc = &conn->proto.sshc;
   CURLcode result = CURLE_OK;
@@ -2828,25 +2824,26 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
 
   while((sshc->state != SSH_STOP) && !result) {
     bool block;
-    long left;
+    time_t left = 1000;
+    struct timeval now = Curl_tvnow();
 
     result = ssh_statemach_act(conn, &block);
     if(result)
       break;
 
-    if(Curl_pgrsUpdate(conn))
-      return CURLE_ABORTED_BY_CALLBACK;
-    else {
-      struct timeval now = Curl_tvnow();
+    if(!disconnect) {
+      if(Curl_pgrsUpdate(conn))
+        return CURLE_ABORTED_BY_CALLBACK;
+
       result = Curl_speedcheck(data, now);
       if(result)
         break;
-    }
 
-    left = Curl_timeleft(data, NULL, duringconnect);
-    if(left < 0) {
-      failf(data, "Operation timed out");
-      return CURLE_OPERATION_TIMEDOUT;
+      left = Curl_timeleft(data, NULL, FALSE);
+      if(left < 0) {
+        failf(data, "Operation timed out");
+        return CURLE_OPERATION_TIMEDOUT;
+      }
     }
 
 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
@@ -2860,8 +2857,8 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
       if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
         fd_write = sock;
       /* wait for the socket to become ready */
-      Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
-                        left>1000?1000:left); /* ignore result */
+      (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
+                              left>1000?1000:left); /* ignore result */
     }
 #endif
 
@@ -3062,7 +3059,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
 
     state(conn, SSH_SESSION_DISCONNECT);
 
-    result = ssh_block_statemach(conn, FALSE);
+    result = ssh_block_statemach(conn, TRUE);
   }
 
   return result;
@@ -3216,7 +3213,7 @@ static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
   if(conn->proto.sshc.ssh_session) {
     /* only if there's a session still around to use! */
     state(conn, SSH_SFTP_SHUTDOWN);
-    result = ssh_block_statemach(conn, FALSE);
+    result = ssh_block_statemach(conn, TRUE);
   }
 
   DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
@@ -3383,7 +3380,7 @@ get_pathname(const char **cpp, char **path)
 
 static const char *sftp_libssh2_strerror(int err)
 {
-  switch (err) {
+  switch(err) {
     case LIBSSH2_FX_NO_SUCH_FILE:
       return "No such file or directory";
 
diff --git a/Utilities/cmcurl/lib/strcase.c b/Utilities/cmcurl/lib/strcase.c
index 807689e..a74a4be 100644
--- a/Utilities/cmcurl/lib/strcase.c
+++ b/Utilities/cmcurl/lib/strcase.c
@@ -34,7 +34,7 @@ char Curl_raw_toupper(char in)
   if(in >= 'a' && in <= 'z')
     return (char)('A' + in - 'a');
 #else
-  switch (in) {
+  switch(in) {
   case 'a':
     return 'A';
   case 'b':
@@ -120,6 +120,16 @@ int Curl_strcasecompare(const char *first, const char *second)
   return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
 }
 
+int Curl_safe_strcasecompare(const char *first, const char *second)
+{
+  if(first && second)
+    /* both pointers point to something then compare them */
+    return Curl_strcasecompare(first, second);
+
+  /* if both pointers are NULL then treat them as equal */
+  return (NULL == first && NULL == second);
+}
+
 /*
  * @unittest: 1301
  */
diff --git a/Utilities/cmcurl/lib/strcase.h b/Utilities/cmcurl/lib/strcase.h
index bf057b1..ea2abc8 100644
--- a/Utilities/cmcurl/lib/strcase.h
+++ b/Utilities/cmcurl/lib/strcase.h
@@ -36,6 +36,7 @@
 #define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c)
 
 int Curl_strcasecompare(const char *first, const char *second);
+int Curl_safe_strcasecompare(const char *first, const char *second);
 int Curl_strncasecompare(const char *first, const char *second, size_t max);
 
 char Curl_raw_toupper(char in);
diff --git a/Utilities/cmcurl/lib/strdup.c b/Utilities/cmcurl/lib/strdup.c
index 5a15c2b..136b693 100644
--- a/Utilities/cmcurl/lib/strdup.c
+++ b/Utilities/cmcurl/lib/strdup.c
@@ -75,3 +75,26 @@ void *Curl_memdup(const void *src, size_t length)
 
   return buffer;
 }
+
+/***************************************************************************
+ *
+ * Curl_saferealloc(ptr, size)
+ *
+ * Does a normal realloc(), but will free the data pointer if the realloc
+ * fails. If 'size' is zero, it will free the data and return a failure.
+ *
+ * This convenience function is provided and used to help us avoid a common
+ * mistake pattern when we could pass in a zero, catch the NULL return and end
+ * up free'ing the memory twice.
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+void *Curl_saferealloc(void *ptr, size_t size)
+{
+  void *datap = realloc(ptr, size);
+  if(size && !datap)
+    /* only free 'ptr' if size was non-zero */
+    free(ptr);
+  return datap;
+}
diff --git a/Utilities/cmcurl/lib/strdup.h b/Utilities/cmcurl/lib/strdup.h
index c74a3b7..ae3d5d0 100644
--- a/Utilities/cmcurl/lib/strdup.h
+++ b/Utilities/cmcurl/lib/strdup.h
@@ -27,5 +27,6 @@
 extern char *curlx_strdup(const char *str);
 #endif
 void *Curl_memdup(const void *src, size_t buffer_length);
+void *Curl_saferealloc(void *ptr, size_t size);
 
 #endif /* HEADER_CURL_STRDUP_H */
diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index db50c7d..7e5cde4 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -53,7 +53,7 @@ const char *
 curl_easy_strerror(CURLcode error)
 {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (error) {
+  switch(error) {
   case CURLE_OK:
     return "No error";
 
@@ -348,7 +348,7 @@ const char *
 curl_multi_strerror(CURLMcode error)
 {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (error) {
+  switch(error) {
   case CURLM_CALL_MULTI_PERFORM:
     return "Please call curl_multi_perform() soon";
 
@@ -393,7 +393,7 @@ const char *
 curl_share_strerror(CURLSHcode error)
 {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (error) {
+  switch(error) {
   case CURLSHE_OK:
     return "No error";
 
@@ -435,7 +435,7 @@ get_winsock_error (int err, char *buf, size_t len)
   const char *p;
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (err) {
+  switch(err) {
   case WSAEINTR:
     p = "Call interrupted";
     break;
@@ -609,7 +609,7 @@ get_winsock_error (int err, char *buf, size_t len)
   else
     p = "error";
 #endif
-  strncpy (buf, p, len);
+  strncpy(buf, p, len);
   buf [len-1] = '\0';
   return buf;
 }
@@ -715,10 +715,12 @@ const char *Curl_strerror(struct connectdata *conn, int err)
   buf[max] = '\0'; /* make sure the string is zero terminated */
 
   /* strip trailing '\r\n' or '\n'. */
-  if((p = strrchr(buf, '\n')) != NULL && (p - buf) >= 2)
-     *p = '\0';
-  if((p = strrchr(buf, '\r')) != NULL && (p - buf) >= 1)
-     *p = '\0';
+  p = strrchr(buf, '\n');
+  if(p && (p - buf) >= 2)
+    *p = '\0';
+  p = strrchr(buf, '\r');
+  if(p && (p - buf) >= 1)
+    *p = '\0';
 
   if(old_errno != ERRNO)
     SET_ERRNO(old_errno);
@@ -750,7 +752,7 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
 
   old_errno = ERRNO;
 
-  switch (err) {
+  switch(err) {
     case SEC_E_OK:
       txt = "No error";
       break;
@@ -1035,10 +1037,12 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
     if(msg_formatted) {
       msgbuf[sizeof(msgbuf)-1] = '\0';
       /* strip trailing '\r\n' or '\n' */
-      if((p = strrchr(msgbuf, '\n')) != NULL && (p - msgbuf) >= 2)
-         *p = '\0';
-      if((p = strrchr(msgbuf, '\r')) != NULL && (p - msgbuf) >= 1)
-         *p = '\0';
+      p = strrchr(msgbuf, '\n');
+      if(p && (p - msgbuf) >= 2)
+        *p = '\0';
+      p = strrchr(msgbuf, '\r');
+      if(p && (p - msgbuf) >= 1)
+        *p = '\0';
       msg = msgbuf;
     }
     if(msg)
diff --git a/Utilities/cmcurl/lib/strtoofft.c b/Utilities/cmcurl/lib/strtoofft.c
index 6d5d2d5..b854bf4 100644
--- a/Utilities/cmcurl/lib/strtoofft.c
+++ b/Utilities/cmcurl/lib/strtoofft.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -165,7 +165,7 @@ static int get_char(char c, int base)
     value = c - 'a' + 10;
   }
 #else
-  const char * cp;
+  const char *cp;
   int value;
 
   cp = memchr(valchars, c, 10 + 26 + 26);
diff --git a/Utilities/cmcurl/lib/system_win32.c b/Utilities/cmcurl/lib/system_win32.c
index 7873759..cfbbf32 100644
--- a/Utilities/cmcurl/lib/system_win32.c
+++ b/Utilities/cmcurl/lib/system_win32.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2016, Steve Holme, <steve_holme at hotmail.com>.
+ * Copyright (C) 2016 - 2017, Steve Holme, <steve_holme at hotmail.com>.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -68,7 +68,7 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
  *
  * majorVersion [in] - The major version number.
  * minorVersion [in] - The minor version number.
- * platform     [in] - The optional platform identifer.
+ * platform     [in] - The optional platform identifier.
  * condition    [in] - The test condition used to specifier whether we are
  *                     checking a version less then, equal to or greater than
  *                     what is specified in the major and minor version
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index c37242d..155d4b2 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -81,17 +81,19 @@
   } WHILE_FALSE
 
 #define  CURL_SB_GET(x) ((*x->subpointer++)&0xff)
-#define  CURL_SB_PEEK(x)   ((*x->subpointer)&0xff)
-#define  CURL_SB_EOF(x) (x->subpointer >= x->subend)
 #define  CURL_SB_LEN(x) (x->subend - x->subpointer)
 
+/* For posterity:
+#define  CURL_SB_PEEK(x) ((*x->subpointer)&0xff)
+#define  CURL_SB_EOF(x) (x->subpointer >= x->subend) */
+
 #ifdef CURL_DISABLE_VERBOSE_STRINGS
 #define printoption(a,b,c,d)  Curl_nop_stmt
 #endif
 
 #ifdef USE_WINSOCK
 typedef FARPROC WSOCK2_FUNC;
-static CURLcode check_wsock2 (struct Curl_easy *data);
+static CURLcode check_wsock2(struct Curl_easy *data);
 #endif
 
 static
@@ -872,7 +874,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
         continue;
       }
 
-          /* Window Size */
+      /* Window Size */
       if(strcasecompare(option_keyword, "WS")) {
         if(sscanf(option_arg, "%hu%*[xX]%hu",
                   &tn->subopt_wsx, &tn->subopt_wsy) == 2)
@@ -899,11 +901,9 @@ static CURLcode check_telnet_options(struct connectdata *conn)
       result = CURLE_UNKNOWN_TELNET_OPTION;
       break;
     }
-    else {
-      failf(data, "Syntax error in telnet option: %s", head->data);
-      result = CURLE_TELNET_OPTION_SYNTAX;
-      break;
-    }
+    failf(data, "Syntax error in telnet option: %s", head->data);
+    result = CURLE_TELNET_OPTION_SYNTAX;
+    break;
   }
 
   if(result) {
@@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn)
   struct TELNET *tn = (struct TELNET *)data->req.protop;
 
   printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
-  switch (CURL_SB_GET(tn)) {
+  switch(CURL_SB_GET(tn)) {
     case CURL_TELOPT_TTYPE:
       len = strlen(tn->subopt_ttype) + 4 + 2;
       snprintf((char *)temp, sizeof(temp),
@@ -1004,24 +1004,24 @@ static void sendsuboption(struct connectdata *conn, int option)
   ssize_t bytes_written;
   int err;
   unsigned short x, y;
-  unsigned char*uc1, *uc2;
+  unsigned char *uc1, *uc2;
 
   struct Curl_easy *data = conn->data;
   struct TELNET *tn = (struct TELNET *)data->req.protop;
 
-  switch (option) {
+  switch(option) {
   case CURL_TELOPT_NAWS:
     /* We prepare data to be sent */
     CURL_SB_CLEAR(tn);
     CURL_SB_ACCUM(tn, CURL_IAC);
     CURL_SB_ACCUM(tn, CURL_SB);
     CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS);
-    /* We must deal either with litte or big endien processors */
+    /* We must deal either with litte or big endian processors */
     /* Window size must be sent according to the 'network order' */
     x=htons(tn->subopt_wsx);
     y=htons(tn->subopt_wsy);
-    uc1 = (unsigned char*)&x;
-    uc2 = (unsigned char*)&y;
+    uc1 = (unsigned char *)&x;
+    uc2 = (unsigned char *)&y;
     CURL_SB_ACCUM(tn, uc1[0]);
     CURL_SB_ACCUM(tn, uc1[1]);
     CURL_SB_ACCUM(tn, uc2[0]);
@@ -1087,7 +1087,7 @@ CURLcode telrcv(struct connectdata *conn,
   while(count--) {
     c = inbuf[in];
 
-    switch (tn->telrcv_state) {
+    switch(tn->telrcv_state) {
     case CURL_TS_CR:
       tn->telrcv_state = CURL_TS_DATA;
       if(c == '\0') {
@@ -1111,7 +1111,7 @@ CURLcode telrcv(struct connectdata *conn,
     case CURL_TS_IAC:
     process_iac:
       DEBUGASSERT(startwrite < 0);
-      switch (c) {
+      switch(c) {
       case CURL_WILL:
         tn->telrcv_state = CURL_TS_WILL;
         break;
@@ -1186,7 +1186,7 @@ CURLcode telrcv(struct connectdata *conn,
              * IAC SE was left off, or another option got inserted into the
              * suboption are all possibilities.  If we assume that the IAC was
              * not doubled, and really the IAC SE was left off, we could get
-             * into an infinate loop here.  So, instead, we terminate the
+             * into an infinite loop here.  So, instead, we terminate the
              * suboption, and process the partial suboption if we can.
              */
             CURL_SB_ACCUM(tn, CURL_IAC);
@@ -1220,43 +1220,63 @@ CURLcode telrcv(struct connectdata *conn,
 }
 
 /* Escape and send a telnet data block */
-/* TODO: write large chunks of data instead of one byte at a time */
 static CURLcode send_telnet_data(struct connectdata *conn,
                                  char *buffer, ssize_t nread)
 {
-  unsigned char outbuf[2];
-  ssize_t bytes_written, total_written;
-  int out_count;
+  ssize_t escapes, i, j, outlen;
+  unsigned char *outbuf = NULL;
   CURLcode result = CURLE_OK;
+  ssize_t bytes_written, total_written;
 
-  while(!result && nread--) {
-    outbuf[0] = *buffer++;
-    out_count = 1;
-    if(outbuf[0] == CURL_IAC)
-      outbuf[out_count++] = CURL_IAC;
-
-    total_written = 0;
-    do {
-      /* Make sure socket is writable to avoid EWOULDBLOCK condition */
-      struct pollfd pfd[1];
-      pfd[0].fd = conn->sock[FIRSTSOCKET];
-      pfd[0].events = POLLOUT;
-      switch (Curl_poll(pfd, 1, -1)) {
-        case -1:                    /* error, abort writing */
-        case 0:                     /* timeout (will never happen) */
-          result = CURLE_SEND_ERROR;
-          break;
-        default:                    /* write! */
-          bytes_written = 0;
-          result = Curl_write(conn, conn->sock[FIRSTSOCKET],
-                              outbuf+total_written, out_count-total_written,
-                              &bytes_written);
-          total_written += bytes_written;
-          break;
-      }
-      /* handle partial write */
-    } while(!result && total_written < out_count);
+  /* Determine size of new buffer after escaping */
+  escapes = 0;
+  for(i = 0; i < nread; i++)
+    if((unsigned char)buffer[i] == CURL_IAC)
+      escapes++;
+  outlen = nread + escapes;
+
+  if(outlen == nread)
+    outbuf = (unsigned char *)buffer;
+  else {
+    outbuf = malloc(nread + escapes + 1);
+    if(!outbuf)
+      return CURLE_OUT_OF_MEMORY;
+
+    j = 0;
+    for(i = 0; i < nread; i++) {
+      outbuf[j++] = buffer[i];
+      if((unsigned char)buffer[i] == CURL_IAC)
+        outbuf[j++] = CURL_IAC;
+    }
+    outbuf[j] = '\0';
+  }
+
+  total_written = 0;
+  while(!result && total_written < outlen) {
+    /* Make sure socket is writable to avoid EWOULDBLOCK condition */
+    struct pollfd pfd[1];
+    pfd[0].fd = conn->sock[FIRSTSOCKET];
+    pfd[0].events = POLLOUT;
+    switch(Curl_poll(pfd, 1, -1)) {
+      case -1:                    /* error, abort writing */
+      case 0:                     /* timeout (will never happen) */
+        result = CURLE_SEND_ERROR;
+        break;
+      default:                    /* write! */
+        bytes_written = 0;
+        result = Curl_write(conn, conn->sock[FIRSTSOCKET],
+                            outbuf + total_written,
+                            outlen - total_written,
+                            &bytes_written);
+        total_written += bytes_written;
+        break;
+    }
   }
+
+  /* Free malloc copy if escaped */
+  if(outbuf != (unsigned char *)buffer)
+    free(outbuf);
+
   return result;
 }
 
@@ -1326,7 +1346,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
 #ifdef USE_WINSOCK
   /*
   ** This functionality only works with WinSock >= 2.0.  So,
-  ** make sure have it.
+  ** make sure we have it.
   */
   result = check_wsock2(data);
   if(result)
@@ -1416,28 +1436,29 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
 
   /* Keep on listening and act on events */
   while(keepon) {
+    const DWORD buf_size = (DWORD)data->set.buffer_size;
     waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
     switch(waitret) {
     case WAIT_TIMEOUT:
     {
       for(;;) {
         if(data->set.is_fread_set) {
+          size_t n;
           /* read from user-supplied method */
-          result = (int)data->state.fread_func(buf, 1, BUFSIZE - 1,
-                                               data->state.in);
-          if(result == CURL_READFUNC_ABORT) {
+          n = data->state.fread_func(buf, 1, buf_size, data->state.in);
+          if(n == CURL_READFUNC_ABORT) {
             keepon = FALSE;
             result = CURLE_READ_ERROR;
             break;
           }
 
-          if(result == CURL_READFUNC_PAUSE)
+          if(n == CURL_READFUNC_PAUSE)
             break;
 
-          if(result == 0)                        /* no bytes */
+          if(n == 0)                        /* no bytes */
             break;
 
-          readfile_read = result; /* fall thru with number of bytes read */
+          readfile_read = (DWORD)n; /* fall thru with number of bytes read */
         }
         else {
           /* read from stdin */
@@ -1451,7 +1472,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
           if(!readfile_read)
             break;
 
-          if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
+          if(!ReadFile(stdin_handle, buf, buf_size,
                        &readfile_read, NULL)) {
             keepon = FALSE;
             result = CURLE_READ_ERROR;
@@ -1470,7 +1491,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
 
     case WAIT_OBJECT_0 + 1:
     {
-      if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
+      if(!ReadFile(stdin_handle, buf, buf_size,
                    &readfile_read, NULL)) {
         keepon = FALSE;
         result = CURLE_READ_ERROR;
@@ -1489,7 +1510,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
 
       events.lNetworkEvents = 0;
       if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
-        if((err = SOCKERRNO) != EINPROGRESS) {
+        err = SOCKERRNO;
+        if(err != EINPROGRESS) {
           infof(data, "WSAEnumNetworkEvents failed (%d)", err);
           keepon = FALSE;
           result = CURLE_READ_ERROR;
@@ -1498,7 +1520,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
       }
       if(events.lNetworkEvents & FD_READ) {
         /* read data from network */
-        result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
+        result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
         /* read would've blocked. Loop again */
         if(result == CURLE_AGAIN)
           break;
@@ -1576,7 +1598,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
   }
 
   while(keepon) {
-    switch (Curl_poll(pfd, poll_cnt, interval_ms)) {
+    switch(Curl_poll(pfd, poll_cnt, interval_ms)) {
     case -1:                    /* error, stop reading */
       keepon = FALSE;
       continue;
@@ -1587,12 +1609,12 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
     default:                    /* read! */
       if(pfd[0].revents & POLLIN) {
         /* read data from network */
-        result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
+        result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
         /* read would've blocked. Loop again */
         if(result == CURLE_AGAIN)
           break;
         /* returned not-zero, this an error */
-        else if(result) {
+        if(result) {
           keepon = FALSE;
           break;
         }
@@ -1623,12 +1645,12 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
       nread = 0;
       if(poll_cnt == 2) {
         if(pfd[1].revents & POLLIN) { /* read from in file */
-          nread = read(pfd[1].fd, buf, BUFSIZE - 1);
+          nread = read(pfd[1].fd, buf, data->set.buffer_size);
         }
       }
       else {
         /* read from user-supplied method */
-        nread = (int)data->state.fread_func(buf, 1, BUFSIZE - 1,
+        nread = (int)data->state.fread_func(buf, 1, data->set.buffer_size,
                                             data->state.in);
         if(nread == CURL_READFUNC_ABORT) {
           keepon = FALSE;
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index deee394..b2b3efe 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -199,7 +199,7 @@ const struct Curl_handler Curl_handler_tftp = {
 static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
 {
   time_t maxtime, timeout;
-  long timeout_ms;
+  time_t timeout_ms;
   bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
 
   time(&state->start_time);
@@ -304,7 +304,7 @@ static unsigned short getrpacketblock(const tftp_packet_t *packet)
 
 static size_t Curl_strnlen(const char *string, size_t maxlen)
 {
-  const char *end = memchr (string, '\0', maxlen);
+  const char *end = memchr(string, '\0', maxlen);
   return end ? (size_t) (end - string) : maxlen;
 }
 
@@ -359,7 +359,7 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
         failf(data, "invalid blocksize value in OACK packet");
         return CURLE_TFTP_ILLEGAL;
       }
-      else if(blksize > TFTP_BLKSIZE_MAX) {
+      if(blksize > TFTP_BLKSIZE_MAX) {
         failf(data, "%s (%d)", "blksize is larger than max supported",
               TFTP_BLKSIZE_MAX);
         return CURLE_TFTP_ILLEGAL;
@@ -1119,7 +1119,8 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
   }
   else {
     /* The event is given by the TFTP packet time */
-    state->event = (tftp_event_t)getrpacketevent(&state->rpacket);
+    unsigned short event = getrpacketevent(&state->rpacket);
+    state->event = (tftp_event_t)event;
 
     switch(state->event) {
     case TFTP_EVENT_DATA:
@@ -1138,9 +1139,12 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
       }
       break;
     case TFTP_EVENT_ERROR:
-      state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
+    {
+      unsigned short error = getrpacketblock(&state->rpacket);
+      state->error = (tftp_error_t)error;
       infof(data, "%s\n", (const char *)state->rpacket.data+4);
       break;
+    }
     case TFTP_EVENT_ACK:
       break;
     case TFTP_EVENT_OACK:
@@ -1189,7 +1193,7 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
     state->state = TFTP_STATE_FIN;
     return 0;
   }
-  else if(current > state->rx_time+state->retry_time) {
+  if(current > state->rx_time+state->retry_time) {
     if(event)
       *event = TFTP_EVENT_TIMEOUT;
     time(&state->rx_time); /* update even though we received nothing */
@@ -1223,7 +1227,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
     failf(data, "TFTP response timeout");
     return CURLE_OPERATION_TIMEDOUT;
   }
-  else if(event != TFTP_EVENT_NONE) {
+  if(event != TFTP_EVENT_NONE) {
     result = tftp_state_machine(state, event);
     if(result)
       return result;
@@ -1356,7 +1360,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
 static CURLcode tftp_setup_connection(struct connectdata * conn)
 {
   struct Curl_easy *data = conn->data;
-  char * type;
+  char *type;
   char command;
 
   conn->socktype = SOCK_DGRAM;   /* UDP datagram based */
@@ -1372,7 +1376,7 @@ static CURLcode tftp_setup_connection(struct connectdata * conn)
     *type = 0;                   /* it was in the middle of the hostname */
     command = Curl_raw_toupper(type[6]);
 
-    switch (command) {
+    switch(command) {
     case 'A': /* ASCII mode */
     case 'N': /* NETASCII mode */
       data->set.prefer_ascii = TRUE;
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index 629f1c8..bed44c5 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -116,7 +116,7 @@ struct timeval curlx_tvnow(void)
  * Returns: the time difference in number of milliseconds. For large diffs it
  * returns 0x7fffffff on 32bit time_t systems.
  */
-long curlx_tvdiff(struct timeval newer, struct timeval older)
+time_t curlx_tvdiff(struct timeval newer, struct timeval older)
 {
 #if SIZEOF_TIME_T < 8
   /* for 32bit time_t systems, add a precaution to avoid overflow for really
@@ -126,7 +126,7 @@ long curlx_tvdiff(struct timeval newer, struct timeval older)
     return 0x7fffffff;
 #endif
   return (newer.tv_sec-older.tv_sec)*1000+
-    (long)(newer.tv_usec-older.tv_usec)/1000;
+    (time_t)(newer.tv_usec-older.tv_usec)/1000;
 }
 
 /*
@@ -139,12 +139,5 @@ double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
   if(newer.tv_sec != older.tv_sec)
     return (double)(newer.tv_sec-older.tv_sec)+
       (double)(newer.tv_usec-older.tv_usec)/1000000.0;
-  else
-    return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
-}
-
-/* return the number of seconds in the given input timeval struct */
-long Curl_tvlong(struct timeval t1)
-{
-  return t1.tv_sec;
+  return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
 }
diff --git a/Utilities/cmcurl/lib/timeval.h b/Utilities/cmcurl/lib/timeval.h
index 50c31a2..3396935 100644
--- a/Utilities/cmcurl/lib/timeval.h
+++ b/Utilities/cmcurl/lib/timeval.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -37,7 +37,7 @@ struct timeval curlx_tvnow(void);
  *
  * Returns: the time difference in number of milliseconds.
  */
-long curlx_tvdiff(struct timeval t1, struct timeval t2);
+time_t curlx_tvdiff(struct timeval t1, struct timeval t2);
 
 /*
  * Same as curlx_tvdiff but with full usec resolution.
@@ -46,8 +46,6 @@ long curlx_tvdiff(struct timeval t1, struct timeval t2);
  */
 double curlx_tvdiff_secs(struct timeval t1, struct timeval t2);
 
-long Curl_tvlong(struct timeval t1);
-
 /* These two defines below exist to provide the older API for library
    internals only. */
 #define Curl_tvnow() curlx_tvnow()
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index 6245ee4..43e8f64 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -117,7 +117,8 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
     *nreadp = 0;
     return CURLE_ABORTED_BY_CALLBACK;
   }
-  else if(nread == CURL_READFUNC_PAUSE) {
+  if(nread == CURL_READFUNC_PAUSE) {
+    struct SingleRequest *k = &data->req;
 
     if(conn->handler->flags & PROTOPT_NONETWORK) {
       /* protocols that work without network cannot be paused. This is
@@ -126,16 +127,15 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
       failf(data, "Read callback asked for PAUSE when not supported!");
       return CURLE_READ_ERROR;
     }
-    else {
-      struct SingleRequest *k = &data->req;
-      /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
-      k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
-      if(data->req.upload_chunky) {
+
+    /* CURL_READFUNC_PAUSE pauses read callbacks that feed socket writes */
+    k->keepon |= KEEP_SEND_PAUSE; /* mark socket send as paused */
+    if(data->req.upload_chunky) {
         /* Back out the preallocation done above */
-        data->req.upload_fromhere -= (8 + 2);
-      }
-      *nreadp = 0;
+      data->req.upload_fromhere -= (8 + 2);
     }
+    *nreadp = 0;
+
     return CURLE_OK; /* nothing was read */
   }
   else if((size_t)nread > buffersize) {
@@ -405,8 +405,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
   /* This is where we loop until we have read everything there is to
      read or we get a CURLE_AGAIN */
   do {
-    size_t buffersize = data->set.buffer_size?
-      data->set.buffer_size : BUFSIZE;
+    size_t buffersize = data->set.buffer_size;
     size_t bytestoread = buffersize;
 
     if(
@@ -642,7 +641,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
           failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
           return CURLE_RECV_ERROR;
         }
-        else if(CHUNKE_STOP == res) {
+        if(CHUNKE_STOP == res) {
           size_t dataleft;
           /* we're done reading chunks! */
           k->keepon &= ~KEEP_RECV; /* read no more */
@@ -681,8 +680,6 @@ static CURLcode readwrite_data(struct Curl_easy *data,
         excess = (size_t)(k->bytecount + nread - k->maxdownload);
         if(excess > 0 && !k->ignorebody) {
           if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
-            /* The 'excess' amount below can't be more than BUFSIZE which
-               always will fit in a size_t */
             infof(data,
                   "Rewinding stream by : %zu"
                   " bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T
@@ -741,8 +738,8 @@ static CURLcode readwrite_data(struct Curl_easy *data,
              Make sure that ALL_CONTENT_ENCODINGS contains all the
              encodings handled here. */
 #ifdef HAVE_LIBZ
-          switch (conn->data->set.http_ce_skip ?
-                  IDENTITY : k->auto_decoding) {
+          switch(conn->data->set.http_ce_skip ?
+                 IDENTITY : k->auto_decoding) {
           case IDENTITY:
 #endif
             /* This is the default when the server sends no
@@ -775,9 +772,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
             break;
 
           default:
-            failf (data, "Unrecognized content encoding type. "
-                   "libcurl understands `identity', `deflate' and `gzip' "
-                   "content encodings.");
+            failf(data, "Unrecognized content encoding type. "
+                  "libcurl understands `identity', `deflate' and `gzip' "
+                  "content encodings.");
             result = CURLE_BAD_CONTENT_ENCODING;
             break;
           }
@@ -853,7 +850,6 @@ static CURLcode done_sending(struct connectdata *conn,
  */
 static CURLcode readwrite_upload(struct Curl_easy *data,
                                  struct connectdata *conn,
-                                 struct SingleRequest *k,
                                  int *didwhat)
 {
   ssize_t i, si;
@@ -861,6 +857,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
   CURLcode result;
   ssize_t nread; /* number of bytes read */
   bool sending_http_headers = FALSE;
+  struct SingleRequest *k = &data->req;
 
   if((k->bytecount == 0) && (k->writebytecount == 0))
     Curl_pgrsTime(data, TIMER_STARTTRANSFER);
@@ -871,15 +868,15 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
 
     /* only read more data if there's no upload data already
        present in the upload buffer */
-    if(0 == data->req.upload_present) {
+    if(0 == k->upload_present) {
       /* init the "upload from here" pointer */
-      data->req.upload_fromhere = k->uploadbuf;
+      k->upload_fromhere = data->state.uploadbuffer;
 
       if(!k->upload_done) {
         /* HTTP pollution, this should be written nicer to become more
            protocol agnostic. */
         int fillcount;
-        struct HTTP *http = data->req.protop;
+        struct HTTP *http = k->protop;
 
         if((k->exp100 == EXP100_SENDING_REQUEST) &&
            (http->sending == HTTPSEND_BODY)) {
@@ -892,7 +889,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
           *didwhat &= ~KEEP_SEND;  /* we didn't write anything actually */
 
           /* set a timeout for the multi interface */
-          Curl_expire(data, data->set.expect_100_timeout);
+          Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
           break;
         }
 
@@ -905,7 +902,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
             sending_http_headers = FALSE;
         }
 
-        result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount);
+        result = Curl_fillreadbuffer(conn, UPLOAD_BUFSIZE, &fillcount);
         if(result)
           return result;
 
@@ -918,7 +915,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
         /* this is a paused transfer */
         break;
       }
-      else if(nread<=0) {
+      if(nread<=0) {
         result = done_sending(conn, k);
         if(result)
           return result;
@@ -926,7 +923,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
       }
 
       /* store number of bytes available for upload */
-      data->req.upload_present = nread;
+      k->upload_present = nread;
 
       /* convert LF to CRLF if so asked */
       if((!sending_http_headers) && (
@@ -937,7 +934,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
          (data->set.crlf))) {
         /* Do we need to allocate a scratch buffer? */
         if(!data->state.scratch) {
-          data->state.scratch = malloc(2 * BUFSIZE);
+          data->state.scratch = malloc(2 * data->set.buffer_size);
           if(!data->state.scratch) {
             failf(data, "Failed to alloc scratch buffer!");
 
@@ -952,7 +949,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
          * must be used instead of the escape sequences \r & \n.
          */
         for(i = 0, si = 0; i < nread; i++, si++) {
-          if(data->req.upload_fromhere[i] == 0x0a) {
+          if(k->upload_fromhere[i] == 0x0a) {
             data->state.scratch[si++] = 0x0d;
             data->state.scratch[si] = 0x0a;
             if(!data->set.crlf) {
@@ -963,7 +960,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
             }
           }
           else
-            data->state.scratch[si] = data->req.upload_fromhere[i];
+            data->state.scratch[si] = k->upload_fromhere[i];
         }
 
         if(si != nread) {
@@ -972,10 +969,10 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
           nread = si;
 
           /* upload from the new (replaced) buffer instead */
-          data->req.upload_fromhere = data->state.scratch;
+          k->upload_fromhere = data->state.scratch;
 
           /* set the new amount too */
-          data->req.upload_present = nread;
+          k->upload_present = nread;
         }
       }
 
@@ -986,7 +983,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
           return result;
       }
 #endif /* CURL_DISABLE_SMTP */
-    } /* if 0 == data->req.upload_present */
+    } /* if 0 == k->upload_present */
     else {
       /* We have a partial buffer left from a previous "round". Use
          that instead of reading more data */
@@ -994,17 +991,17 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
 
     /* write to socket (send away data) */
     result = Curl_write(conn,
-                        conn->writesockfd,     /* socket to send to */
-                        data->req.upload_fromhere, /* buffer pointer */
-                        data->req.upload_present,  /* buffer size */
-                        &bytes_written);           /* actually sent */
+                        conn->writesockfd,  /* socket to send to */
+                        k->upload_fromhere, /* buffer pointer */
+                        k->upload_present,  /* buffer size */
+                        &bytes_written);    /* actually sent */
 
     if(result)
       return result;
 
     if(data->set.verbose)
       /* show the data before we change the pointer upload_fromhere */
-      Curl_debug(data, CURLINFO_DATA_OUT, data->req.upload_fromhere,
+      Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,
                  (size_t)bytes_written, conn);
 
     k->writebytecount += bytes_written;
@@ -1015,20 +1012,20 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
       infof(data, "We are completely uploaded and fine\n");
     }
 
-    if(data->req.upload_present != bytes_written) {
+    if(k->upload_present != bytes_written) {
       /* we only wrote a part of the buffer (if anything), deal with it! */
 
       /* store the amount of bytes left in the buffer to write */
-      data->req.upload_present -= bytes_written;
+      k->upload_present -= bytes_written;
 
       /* advance the pointer where to find the buffer when the next send
          is to happen */
-      data->req.upload_fromhere += bytes_written;
+      k->upload_fromhere += bytes_written;
     }
     else {
       /* we've uploaded that buffer now */
-      data->req.upload_fromhere = k->uploadbuf;
-      data->req.upload_present = 0; /* no more bytes left */
+      k->upload_fromhere = data->state.uploadbuffer;
+      k->upload_present = 0; /* no more bytes left */
 
       if(k->upload_done) {
         result = done_sending(conn, k);
@@ -1108,7 +1105,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
   if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
     /* write */
 
-    result = readwrite_upload(data, conn, k, &didwhat);
+    result = readwrite_upload(data, conn, &didwhat);
     if(result)
       return result;
   }
@@ -1137,11 +1134,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
 
       */
 
-      long ms = Curl_tvdiff(k->now, k->start100);
+      time_t ms = Curl_tvdiff(k->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\n");
       }
     }
@@ -1186,15 +1184,13 @@ CURLcode Curl_readwrite(struct connectdata *conn,
        */
        (k->bytecount != (k->size + data->state.crlf_conversions)) &&
 #endif /* CURL_DO_LINEEND_CONV */
-       !data->req.newurl) {
+       !k->newurl) {
       failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T
-            " bytes remaining to read",
-            k->size - k->bytecount);
+            " bytes remaining to read", k->size - k->bytecount);
       return CURLE_PARTIAL_FILE;
     }
-    else if(!(data->set.opt_no_body) &&
-            k->chunk &&
-            (conn->chunk.state != CHUNK_STOP)) {
+    if(!(data->set.opt_no_body) && k->chunk &&
+       (conn->chunk.state != CHUNK_STOP)) {
       /*
        * In chunked mode, return an error if the connection is closed prior to
        * the empty (terminating) chunk is read.
@@ -1296,7 +1292,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
   /* Init the SSL session ID cache here. We do it here since we want to do it
      after the *_setopt() calls (that could specify the size of the cache) but
      before any transfer takes place. */
-  result = Curl_ssl_initsessions(data, data->set.ssl.max_ssl_sessions);
+  result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions);
   if(result)
     return result;
 
@@ -1313,8 +1309,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
 
   if(data->set.httpreq == HTTPREQ_PUT)
     data->state.infilesize = data->set.filesize;
-  else
+  else {
     data->state.infilesize = data->set.postfieldsize;
+    if(data->set.postfields && (data->state.infilesize == -1))
+      data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
+  }
 
   /* If there is a list of cookie files to read, do it now! */
   if(data->change.cookielist)
@@ -1343,10 +1342,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
     Curl_pgrsStartNow(data);
 
     if(data->set.timeout)
-      Curl_expire(data, data->set.timeout);
+      Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
 
     if(data->set.connecttimeout)
-      Curl_expire(data, data->set.connecttimeout);
+      Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
 
     /* In case the handle is re-used and an authentication method was picked
        in the session we need to make sure we only use the one(s) we now
@@ -1356,13 +1355,12 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
 
     if(data->set.wildcardmatch) {
       struct WildcardData *wc = &data->wildcard;
-      if(!wc->filelist) {
+      if(wc->state < CURLWC_INIT) {
         result = Curl_wildcard_init(wc); /* init wildcard structures */
         if(result)
           return CURLE_OUT_OF_MEMORY;
       }
     }
-
   }
 
   return result;
@@ -1629,9 +1627,7 @@ static char *concat_url(const char *base, const char *relurl)
  * as given by the remote server and set up the new URL to request.
  */
 CURLcode Curl_follow(struct Curl_easy *data,
-                     char *newurl, /* this 'newurl' is the Location: string,
-                                      and it must be malloc()ed before passed
-                                      here */
+                     char *newurl,    /* the Location: string */
                      followtype type) /* see transfer.h */
 {
 #ifdef CURL_DISABLE_HTTP
@@ -1644,33 +1640,36 @@ CURLcode Curl_follow(struct Curl_easy *data,
 
   /* Location: redirect */
   bool disallowport = FALSE;
+  bool reachedmax = FALSE;
 
   if(type == FOLLOW_REDIR) {
     if((data->set.maxredirs != -1) &&
-        (data->set.followlocation >= data->set.maxredirs)) {
-      failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
-      return CURLE_TOO_MANY_REDIRECTS;
+       (data->set.followlocation >= data->set.maxredirs)) {
+      reachedmax = TRUE;
+      type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
+                             to URL */
     }
+    else {
+      /* mark the next request as a followed location: */
+      data->state.this_is_a_follow = TRUE;
 
-    /* mark the next request as a followed location: */
-    data->state.this_is_a_follow = TRUE;
+      data->set.followlocation++; /* count location-followers */
 
-    data->set.followlocation++; /* count location-followers */
+      if(data->set.http_auto_referer) {
+        /* We are asked to automatically set the previous URL as the referer
+           when we get the next URL. We pick the ->url field, which may or may
+           not be 100% correct */
 
-    if(data->set.http_auto_referer) {
-      /* We are asked to automatically set the previous URL as the referer
-         when we get the next URL. We pick the ->url field, which may or may
-         not be 100% correct */
+        if(data->change.referer_alloc) {
+          Curl_safefree(data->change.referer);
+          data->change.referer_alloc = FALSE;
+        }
 
-      if(data->change.referer_alloc) {
-        Curl_safefree(data->change.referer);
-        data->change.referer_alloc = FALSE;
+        data->change.referer = strdup(data->change.url);
+        if(!data->change.referer)
+          return CURLE_OUT_OF_MEMORY;
+        data->change.referer_alloc = TRUE; /* yes, free this later */
       }
-
-      data->change.referer = strdup(data->change.url);
-      if(!data->change.referer)
-        return CURLE_OUT_OF_MEMORY;
-      data->change.referer_alloc = TRUE; /* yes, free this later */
     }
   }
 
@@ -1682,7 +1681,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
     char *absolute = concat_url(data->change.url, newurl);
     if(!absolute)
       return CURLE_OUT_OF_MEMORY;
-    free(newurl);
     newurl = absolute;
   }
   else {
@@ -1698,8 +1696,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
     if(!newest)
       return CURLE_OUT_OF_MEMORY;
     strcpy_url(newest, newurl); /* create a space-free URL */
-
-    free(newurl); /* that was no good */
     newurl = newest; /* use this instead now */
 
   }
@@ -1708,6 +1704,11 @@ CURLcode Curl_follow(struct Curl_easy *data,
     /* we're only figuring out the new url if we would've followed locations
        but now we're done so we can get out! */
     data->info.wouldredirect = newurl;
+
+    if(reachedmax) {
+      failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
+      return CURLE_TOO_MANY_REDIRECTS;
+    }
     return CURLE_OK;
   }
 
@@ -1721,7 +1722,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
 
   data->change.url = newurl;
   data->change.url_alloc = TRUE;
-  newurl = NULL; /* don't free! */
 
   infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
 
@@ -1795,7 +1795,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
     break;
 
   case 303: /* See Other */
-    /* Disable both types of POSTs, unless the user explicitely
+    /* Disable both types of POSTs, unless the user explicitly
        asks for POST after POST */
     if(data->set.httpreq != HTTPREQ_GET
       && !(data->set.keep_post & CURL_REDIR_POST_303)) {
@@ -1843,12 +1843,17 @@ CURLcode Curl_retry_request(struct connectdata *conn,
     return CURLE_OK;
 
   if((data->req.bytecount + data->req.headerbytecount == 0) &&
-     conn->bits.reuse &&
-     (data->set.rtspreq != RTSPREQ_RECEIVE)) {
-    /* We didn't get a single byte when we attempted to re-use a
-       connection. This might happen if the connection was left alive when we
-       were done using it before, but that was closed when we wanted to use it
-       again. Bad luck. Retry the same request on a fresh connect! */
+      conn->bits.reuse &&
+      (!data->set.opt_no_body
+        || (conn->handler->protocol & PROTO_FAMILY_HTTP)) &&
+      (data->set.rtspreq != RTSPREQ_RECEIVE)) {
+    /* We got no data, we attempted to re-use a connection. For HTTP this
+       can be a retry so we try again regardless if we expected a body.
+       For other protocols we only try again only if we expected a body.
+
+       This might happen if the connection was left alive when we were
+       done using it before, but that was closed when we wanted to read from
+       it again. Bad luck. Retry the same request on a fresh connect! */
     infof(conn->data, "Connection died, retrying a fresh connect\n");
     *url = strdup(conn->data->change.url);
     if(!*url)
@@ -1943,7 +1948,7 @@ Curl_setup_transfer(
 
         /* Set a timeout for the multi interface. Add the inaccuracy margin so
            that we don't fire slightly too early and get denied to run. */
-        Curl_expire(data, data->set.expect_100_timeout);
+        Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
       }
       else {
         if(data->state.expect100header)
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index b997f41..87446db 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -92,6 +92,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 #include "warnless.h"
 #include "non-ascii.h"
 #include "inet_pton.h"
+#include "getinfo.h"
 
 /* And now for the protocols */
 #include "ftp.h"
@@ -139,6 +140,19 @@ static CURLcode parse_login_details(const char *login, const size_t len,
                                     char **optionsptr);
 static unsigned int get_protocol_family(unsigned int protocol);
 
+#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
+#define READBUFFER_MAX  CURL_MAX_READ_SIZE
+#define READBUFFER_MIN  1024
+
+/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
+ * more than just a few bytes to play with. Don't let it become too small or
+ * bad things will happen.
+ */
+#if READBUFFER_SIZE < READBUFFER_MIN
+# error READBUFFER_SIZE is too small
+#endif
+
+
 /*
  * Protocol table.
  */
@@ -410,10 +424,7 @@ CURLcode Curl_close(struct Curl_easy *data)
   /* Destroy the timeout list that is held in the easy handle. It is
      /normally/ done by curl_multi_remove_handle() but this is "just in
      case" */
-  if(data->state.timeoutlist) {
-    Curl_llist_destroy(data->state.timeoutlist, NULL);
-    data->state.timeoutlist = NULL;
-  }
+  Curl_llist_destroy(&data->state.timeoutlist, NULL);
 
   data->magic = 0; /* force a clear AFTER the possibly enforced removal from
                       the multi handle, since that function uses the magic
@@ -451,6 +462,7 @@ CURLcode Curl_close(struct Curl_easy *data)
   }
   data->change.url = NULL;
 
+  Curl_safefree(data->state.buffer);
   Curl_safefree(data->state.headerbuff);
 
   Curl_flush_cookies(data, 1);
@@ -463,6 +475,7 @@ CURLcode Curl_close(struct Curl_easy *data)
   /* this destroys the channel and we cannot use it anymore after this */
   Curl_resolver_cleanup(data->state.resolver);
 
+  Curl_http2_cleanup_dependencies(data);
   Curl_convert_close(data);
 
   /* No longer a dirty share, if it exists */
@@ -525,9 +538,9 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
   set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
 
   /* Set the default size of the SSL session ID cache */
-  set->ssl.max_ssl_sessions = 5;
+  set->general_ssl.max_ssl_sessions = 5;
 
-  set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
+  set->proxyport = 0;
   set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
   set->httpauth = CURLAUTH_BASIC;  /* defaults to basic */
   set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
@@ -539,14 +552,16 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
    * switched off unless wanted.
    */
-  set->ssl.verifypeer = TRUE;
-  set->ssl.verifyhost = TRUE;
+  set->ssl.primary.verifypeer = TRUE;
+  set->ssl.primary.verifyhost = TRUE;
 #ifdef USE_TLS_SRP
   set->ssl.authtype = CURL_TLSAUTH_NONE;
 #endif
   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
                                                       type */
-  set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
+  set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
+                                        default */
+  set->proxy_ssl = set->ssl;
 
   set->new_file_perms = 0644;    /* Default permissions */
   set->new_directory_perms = 0755; /* Default permissions */
@@ -569,12 +584,20 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
 
   /* This is our preferred CA cert bundle/path since install time */
 #if defined(CURL_CA_BUNDLE)
-  result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
+  result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
+  if(result)
+    return result;
+
+  result = setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE);
   if(result)
     return result;
 #endif
 #if defined(CURL_CA_PATH)
-  result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
+  result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
+  if(result)
+    return result;
+
+  result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
   if(result)
     return result;
 #endif
@@ -597,6 +620,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
 
   set->expect_100_timeout = 1000L; /* Wait for a second by default. */
   set->sep_headers = TRUE; /* separated header lists by default */
+  set->buffer_size = READBUFFER_SIZE;
 
   Curl_http2_init_userset(set);
   return result;
@@ -634,6 +658,12 @@ CURLcode Curl_open(struct Curl_easy **curl)
 
   /* We do some initial setup here, all those fields that can't be just 0 */
 
+  data->state.buffer = malloc(READBUFFER_SIZE + 1);
+  if(!data->state.buffer) {
+    DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
+    result = CURLE_OUT_OF_MEMORY;
+  }
+
   data->state.headerbuff = malloc(HEADERSIZE);
   if(!data->state.headerbuff) {
     DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
@@ -646,14 +676,13 @@ CURLcode Curl_open(struct Curl_easy **curl)
 
     Curl_convert_init(data);
 
+    Curl_initinfo(data);
+
     /* most recent connection is not yet defined */
     data->state.lastconnect = NULL;
 
     data->progress.flags |= PGRS_HIDE;
     data->state.current_speed = -1; /* init to negative == impossible */
-
-    data->wildcard.state = CURLWC_INIT;
-    data->wildcard.filelist = NULL;
     data->set.fnmatch = ZERO_NULL;
     data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
 
@@ -662,6 +691,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
 
   if(result) {
     Curl_resolver_cleanup(data->state.resolver);
+    free(data->state.buffer);
     free(data->state.headerbuff);
     Curl_freeset(data);
     free(data);
@@ -673,6 +703,9 @@ CURLcode Curl_open(struct Curl_easy **curl)
   return result;
 }
 
+#define C_SSLVERSION_VALUE(x) (x & 0xffff)
+#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
+
 CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
                      va_list param)
 {
@@ -694,7 +727,12 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     break;
   case CURLOPT_SSL_CIPHER_LIST:
     /* set a list of cipher we want to use in the SSL connection */
-    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
+    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSL_CIPHER_LIST:
+    /* set a list of cipher we want to use in the SSL connection for proxy */
+    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
                        va_arg(param, char *));
     break;
 
@@ -900,7 +938,22 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * implementations are lame.
      */
 #ifdef USE_SSL
-    data->set.ssl.version = va_arg(param, long);
+    arg = va_arg(param, long);
+    data->set.ssl.primary.version = C_SSLVERSION_VALUE(arg);
+    data->set.ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
+#else
+    result = CURLE_UNKNOWN_OPTION;
+#endif
+    break;
+  case CURLOPT_PROXY_SSLVERSION:
+    /*
+     * Set explicit SSL version to try to connect with for proxy, as some SSL
+     * implementations are lame.
+     */
+#ifdef USE_SSL
+    arg = va_arg(param, long);
+    data->set.proxy_ssl.primary.version = C_SSLVERSION_VALUE(arg);
+    data->set.proxy_ssl.primary.version_max = C_SSLVERSION_MAX_VALUE(arg);
 #else
     result = CURLE_UNKNOWN_OPTION;
 #endif
@@ -970,8 +1023,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
      * other - POST is kept as POST after 301 and 302
      */
-    int postRedir = curlx_sltosi(va_arg(param, long));
-    data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
+    arg = va_arg(param, long);
+    data->set.keep_post = arg & CURL_REDIR_POST_ALL;
   }
   break;
 
@@ -1007,7 +1060,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
           (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
         result = CURLE_OUT_OF_MEMORY;
       else {
-        char * p;
+        char *p;
 
         (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
 
@@ -1434,18 +1487,30 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
 
   case CURLOPT_PROXY:
     /*
-     * Set proxy server:port to use as HTTP proxy.
+     * Set proxy server:port to use as proxy.
      *
-     * If the proxy is set to "" we explicitly say that we don't want to use a
-     * proxy (even though there might be environment variables saying so).
+     * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
+     * we explicitly say that we don't want to use a proxy
+     * (even though there might be environment variables saying so).
      *
      * Setting it to NULL, means no proxy but allows the environment variables
-     * to decide for us.
+     * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
      */
     result = setstropt(&data->set.str[STRING_PROXY],
                        va_arg(param, char *));
     break;
 
+  case CURLOPT_PRE_PROXY:
+    /*
+     * Set proxy server:port to use as SOCKS proxy.
+     *
+     * If the proxy is set to "" or NULL we explicitly say that we don't want
+     * to use the socks proxy.
+     */
+    result = setstropt(&data->set.str[STRING_PRE_PROXY],
+                       va_arg(param, char *));
+    break;
+
   case CURLOPT_PROXYTYPE:
     /*
      * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
@@ -1457,7 +1522,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
      */
-    switch (va_arg(param, long)) {
+    switch(va_arg(param, long)) {
     case 0:
       data->set.proxy_transfer_mode = FALSE;
       break;
@@ -1910,35 +1975,70 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * String that holds file name of the SSL certificate to use
      */
-    result = setstropt(&data->set.str[STRING_CERT],
+    result = setstropt(&data->set.str[STRING_CERT_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLCERT:
+    /*
+     * String that holds file name of the SSL certificate to use for proxy
+     */
+    result = setstropt(&data->set.str[STRING_CERT_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLCERTTYPE:
     /*
      * String that holds file type of the SSL certificate to use
      */
-    result = setstropt(&data->set.str[STRING_CERT_TYPE],
+    result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLCERTTYPE:
+    /*
+     * String that holds file type of the SSL certificate to use for proxy
+     */
+    result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLKEY:
     /*
      * String that holds file name of the SSL key to use
      */
-    result = setstropt(&data->set.str[STRING_KEY],
+    result = setstropt(&data->set.str[STRING_KEY_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLKEY:
+    /*
+     * String that holds file name of the SSL key to use for proxy
+     */
+    result = setstropt(&data->set.str[STRING_KEY_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLKEYTYPE:
     /*
      * String that holds file type of the SSL key to use
      */
-    result = setstropt(&data->set.str[STRING_KEY_TYPE],
+    result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLKEYTYPE:
+    /*
+     * String that holds file type of the SSL key to use for proxy
+     */
+    result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_KEYPASSWD:
     /*
      * String that holds the SSL or SSH private key password.
      */
-    result = setstropt(&data->set.str[STRING_KEY_PASSWD],
+    result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_KEYPASSWD:
+    /*
+     * String that holds the SSL private key password for proxy.
+     */
+    result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLENGINE:
@@ -1975,13 +2075,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * Set what local port to bind the socket to when performing an operation.
      */
-    data->set.localport = curlx_sltous(va_arg(param, long));
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 65535))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.localport = curlx_sltous(arg);
     break;
   case CURLOPT_LOCALPORTRANGE:
     /*
      * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
      */
-    data->set.localportrange = curlx_sltosi(va_arg(param, long));
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 65535))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.localportrange = curlx_sltosi(arg);
     break;
   case CURLOPT_KRBLEVEL:
     /*
@@ -2001,7 +2107,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * Enable peer SSL verifying.
      */
-    data->set.ssl.verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
+                                       TRUE : FALSE;
+    break;
+  case CURLOPT_PROXY_SSL_VERIFYPEER:
+    /*
+     * Enable peer SSL verifying for proxy.
+     */
+    data->set.proxy_ssl.primary.verifypeer =
+      (0 != va_arg(param, long))?TRUE:FALSE;
     break;
   case CURLOPT_SSL_VERIFYHOST:
     /*
@@ -2019,7 +2133,25 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
 
-    data->set.ssl.verifyhost = (0 != arg) ? TRUE : FALSE;
+    data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
+    break;
+  case CURLOPT_PROXY_SSL_VERIFYHOST:
+    /*
+     * Enable verification of the host name in the peer certificate for proxy
+     */
+    arg = va_arg(param, long);
+
+    /* Obviously people are not reading documentation and too many thought
+       this argument took a boolean when it wasn't and misused it. We thus ban
+       1 as a sensible input and we warn about its use. Then we only have the
+       2 action internally stored as TRUE. */
+
+    if(1 == arg) {
+      failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    }
+
+    data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
     break;
   case CURLOPT_SSL_VERIFYSTATUS:
     /*
@@ -2030,7 +2162,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
       break;
     }
 
-    data->set.ssl.verifystatus = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
+                                         TRUE : FALSE;
     break;
   case CURLOPT_SSL_CTX_FUNCTION:
 #ifdef have_curlssl_ssl_ctx
@@ -2076,7 +2209,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * Set pinned public key for SSL connection.
      * Specify file name of the public key in DER format.
      */
-    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+                       va_arg(param, char *));
+#else
+    result = CURLE_NOT_BUILT_IN;
+#endif
+    break;
+  case CURLOPT_PROXY_PINNEDPUBLICKEY:
+#ifdef have_curlssl_pinnedpubkey /* only by supported backends */
+    /*
+     * Set pinned public key for SSL connection.
+     * Specify file name of the public key in DER format.
+     */
+    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
                        va_arg(param, char *));
 #else
     result = CURLE_NOT_BUILT_IN;
@@ -2086,7 +2231,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * Set CA info for SSL connection. Specify file name of the CA certificate
      */
-    result = setstropt(&data->set.str[STRING_SSL_CAFILE],
+    result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_CAINFO:
+    /*
+     * Set CA info SSL connection for proxy. Specify file name of the
+     * CA certificate
+     */
+    result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_CAPATH:
@@ -2096,7 +2249,20 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * certificates which have been prepared using openssl c_rehash utility.
      */
     /* This does not work on windows. */
-    result = setstropt(&data->set.str[STRING_SSL_CAPATH],
+    result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+                       va_arg(param, char *));
+#else
+    result = CURLE_NOT_BUILT_IN;
+#endif
+    break;
+  case CURLOPT_PROXY_CAPATH:
+#ifdef have_curlssl_ca_path /* not supported by all backends */
+    /*
+     * Set CA path info for SSL connection proxy. Specify directory name of the
+     * CA certificates which have been prepared using openssl c_rehash utility.
+     */
+    /* This does not work on windows. */
+    result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
                        va_arg(param, char *));
 #else
     result = CURLE_NOT_BUILT_IN;
@@ -2107,7 +2273,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * Set CRL file info for SSL connection. Specify file name of the CRL
      * to check certificates revocation
      */
-    result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
+    result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_CRLFILE:
+    /*
+     * Set CRL file info for SSL connection for proxy. Specify file name of the
+     * CRL to check certificates revocation
+     */
+    result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_ISSUERCERT:
@@ -2115,7 +2289,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * Set Issuer certificate file
      * to check certificates issuer
      */
-    result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
+    result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
                        va_arg(param, char *));
     break;
   case CURLOPT_TELNETOPTIONS:
@@ -2130,11 +2304,26 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * The application kindly asks for a differently sized receive buffer.
      * If it seems reasonable, we'll use it.
      */
-    data->set.buffer_size = va_arg(param, long);
+    arg = va_arg(param, long);
 
-    if((data->set.buffer_size> (BUFSIZE -1)) ||
-       (data->set.buffer_size < 1))
-      data->set.buffer_size = 0; /* huge internal default */
+    if(arg > READBUFFER_MAX)
+      arg = READBUFFER_MAX;
+    else if(arg < 1)
+      arg = READBUFFER_SIZE;
+    else if(arg < READBUFFER_MIN)
+      arg = READBUFFER_MIN;
+
+    /* Resize if new size */
+    if(arg != data->set.buffer_size) {
+      char *newbuff = realloc(data->state.buffer, arg + 1);
+      if(!newbuff) {
+        DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
+        result = CURLE_OUT_OF_MEMORY;
+      }
+      else
+        data->state.buffer = newbuff;
+    }
+    data->set.buffer_size = arg;
 
     break;
 
@@ -2196,7 +2385,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
       }
 #endif   /* CURL_DISABLE_HTTP */
       if(data->share->sslsession) {
-        data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions;
+        data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
         data->state.session = data->share->sslsession;
       }
       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
@@ -2231,8 +2420,14 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
 
   case CURLOPT_SSL_OPTIONS:
     arg = va_arg(param, long);
-    data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
-    data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+    data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+    data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+    break;
+
+  case CURLOPT_PROXY_SSL_OPTIONS:
+    arg = va_arg(param, long);
+    data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+    data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
     break;
 
 #endif
@@ -2328,7 +2523,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     break;
 
   case CURLOPT_SSL_SESSIONID_CACHE:
-    data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
+                                      TRUE : FALSE;
+    data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
     break;
 
 #ifdef USE_LIBSSH2
@@ -2419,7 +2616,10 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * know that an unsigned int will always hold the value so we blindly
      * typecast to this type
      */
-    data->set.scope_id = curlx_sltoui(va_arg(param, long));
+    arg = va_arg(param, long);
+    if((arg < 0) || (arg > 0xf))
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    data->set.scope_id = curlx_sltoui(arg);
     break;
 
   case CURLOPT_PROTOCOLS:
@@ -2595,23 +2795,47 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     break;
 #ifdef USE_TLS_SRP
   case CURLOPT_TLSAUTH_USERNAME:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
+    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
                        va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
     break;
+  case CURLOPT_PROXY_TLSAUTH_USERNAME:
+    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
+                       va_arg(param, char *));
+    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+       !data->set.proxy_ssl.authtype)
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    break;
   case CURLOPT_TLSAUTH_PASSWORD:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
+    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
                        va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
     break;
+  case CURLOPT_PROXY_TLSAUTH_PASSWORD:
+    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
+                       va_arg(param, char *));
+    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+       !data->set.proxy_ssl.authtype)
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    break;
   case CURLOPT_TLSAUTH_TYPE:
-    if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+    argptr = va_arg(param, char *);
+    if(!argptr ||
+       strncasecompare(argptr, "SRP", strlen("SRP")))
       data->set.ssl.authtype = CURL_TLSAUTH_SRP;
     else
       data->set.ssl.authtype = CURL_TLSAUTH_NONE;
     break;
+  case CURLOPT_PROXY_TLSAUTH_TYPE:
+    argptr = va_arg(param, char *);
+    if(!argptr ||
+       strncasecompare(argptr, "SRP", strlen("SRP")))
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
+    else
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
+    break;
 #endif
   case CURLOPT_DNS_SERVERS:
     result = Curl_set_dns_servers(data, va_arg(param, char *));
@@ -2651,6 +2875,12 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
 
 #ifdef USE_UNIX_SOCKETS
   case CURLOPT_UNIX_SOCKET_PATH:
+    data->set.abstract_unix_socket = FALSE;
+    result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_ABSTRACT_UNIX_SOCKET:
+    data->set.abstract_unix_socket = TRUE;
     result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
                        va_arg(param, char *));
     break;
@@ -2678,9 +2908,11 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     return CURLE_NOT_BUILT_IN;
 #else
     struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
-    if(dep && GOOD_EASY_HANDLE(dep)) {
-      data->set.stream_depends_on = dep;
-      data->set.stream_depends_e = (option == CURLOPT_STREAM_DEPENDS_E);
+    if(!dep || GOOD_EASY_HANDLE(dep)) {
+      if(data->set.stream_depends_on) {
+        Curl_http2_remove_child(data->set.stream_depends_on, data);
+      }
+      Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
     }
     break;
 #endif
@@ -2688,6 +2920,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
   case CURLOPT_CONNECT_TO:
     data->set.connect_to = va_arg(param, struct curl_slist *);
     break;
+  case CURLOPT_SUPPRESS_CONNECT_HEADERS:
+    data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
+    break;
   default:
     /* unknown tag and its companion, just ignore: */
     result = CURLE_UNKNOWN_OPTION;
@@ -2718,10 +2953,10 @@ static void conn_reset_postponed_data(struct connectdata *conn, int num)
 #endif /* DEBUGBUILD */
   }
   else {
-    DEBUGASSERT (psnd->allocated_size == 0);
-    DEBUGASSERT (psnd->recv_size == 0);
-    DEBUGASSERT (psnd->recv_processed == 0);
-    DEBUGASSERT (psnd->bindsock == CURL_SOCKET_BAD);
+    DEBUGASSERT(psnd->allocated_size == 0);
+    DEBUGASSERT(psnd->recv_size == 0);
+    DEBUGASSERT(psnd->recv_processed == 0);
+    DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
   }
 }
 
@@ -2731,8 +2966,7 @@ static void conn_reset_all_postponed_data(struct connectdata *conn)
   conn_reset_postponed_data(conn, 1);
 }
 #else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
-/* Use "do-nothing" macros instead of functions when workaround not used */
-#define conn_reset_postponed_data(c,n) do {} WHILE_FALSE
+/* Use "do-nothing" macro instead of function when workaround not used */
 #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE
 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
 
@@ -2768,8 +3002,10 @@ static void conn_free(struct connectdata *conn)
   Curl_safefree(conn->passwd);
   Curl_safefree(conn->oauth_bearer);
   Curl_safefree(conn->options);
-  Curl_safefree(conn->proxyuser);
-  Curl_safefree(conn->proxypasswd);
+  Curl_safefree(conn->http_proxy.user);
+  Curl_safefree(conn->socks_proxy.user);
+  Curl_safefree(conn->http_proxy.passwd);
+  Curl_safefree(conn->socks_proxy.passwd);
   Curl_safefree(conn->allocptr.proxyuserpwd);
   Curl_safefree(conn->allocptr.uagent);
   Curl_safefree(conn->allocptr.userpwd);
@@ -2783,19 +3019,24 @@ static void conn_free(struct connectdata *conn)
   Curl_safefree(conn->trailer);
   Curl_safefree(conn->host.rawalloc); /* host name buffer */
   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
-  Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
+  Curl_safefree(conn->secondaryhostname);
+  Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
+  Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
   Curl_safefree(conn->master_buffer);
+  Curl_safefree(conn->connect_buffer);
 
   conn_reset_all_postponed_data(conn);
 
-  Curl_llist_destroy(conn->send_pipe, NULL);
-  Curl_llist_destroy(conn->recv_pipe, NULL);
-
-  conn->send_pipe = NULL;
-  conn->recv_pipe = NULL;
+  Curl_llist_destroy(&conn->send_pipe, NULL);
+  Curl_llist_destroy(&conn->recv_pipe, NULL);
 
   Curl_safefree(conn->localdev);
-  Curl_free_ssl_config(&conn->ssl_config);
+  Curl_free_primary_ssl_config(&conn->ssl_config);
+  Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
+
+#ifdef USE_UNIX_SOCKETS
+  Curl_safefree(conn->unix_domain_socket);
+#endif
 
   free(conn); /* free all the connection oriented data */
 }
@@ -2827,9 +3068,9 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
    * are other users of it
    */
   if(!conn->bits.close &&
-     (conn->send_pipe->size + conn->recv_pipe->size)) {
+     (conn->send_pipe.size + conn->recv_pipe.size)) {
     DEBUGF(infof(data, "Curl_disconnect, usecounter: %d\n",
-                 conn->send_pipe->size + conn->recv_pipe->size));
+                 conn->send_pipe.size + conn->recv_pipe.size));
     return CURLE_OK;
   }
 
@@ -2855,14 +3096,15 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
 
   free_fixed_hostname(&conn->host);
   free_fixed_hostname(&conn->conn_to_host);
-  free_fixed_hostname(&conn->proxy);
+  free_fixed_hostname(&conn->http_proxy.host);
+  free_fixed_hostname(&conn->socks_proxy.host);
 
   Curl_ssl_close(conn, FIRSTSOCKET);
 
   /* Indicate to all handles on the pipe that we're dead */
   if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) {
-    signalPipeClose(conn->send_pipe, TRUE);
-    signalPipeClose(conn->recv_pipe, TRUE);
+    signalPipeClose(&conn->send_pipe, TRUE);
+    signalPipeClose(&conn->recv_pipe, TRUE);
   }
 
   conn_free(conn);
@@ -2889,12 +3131,16 @@ static bool SocketIsDead(curl_socket_t sock)
 }
 
 /*
- * IsPipeliningPossible() returns TRUE if the options set would allow
- * pipelining/multiplexing and the connection is using a HTTP protocol.
+ * IsPipeliningPossible()
+ *
+ * Return a bitmask with the available pipelining and multiplexing options for
+ * the given requested connection.
  */
-static bool IsPipeliningPossible(const struct Curl_easy *handle,
-                                 const struct connectdata *conn)
+static int IsPipeliningPossible(const struct Curl_easy *handle,
+                                const struct connectdata *conn)
 {
+  int avail = 0;
+
   /* If a HTTP protocol and pipelining is enabled */
   if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
      (!conn->bits.protoconnstart || !conn->bits.close)) {
@@ -2904,14 +3150,14 @@ static bool IsPipeliningPossible(const struct Curl_easy *handle,
        (handle->set.httpreq == HTTPREQ_GET ||
         handle->set.httpreq == HTTPREQ_HEAD))
       /* didn't ask for HTTP/1.0 and a GET or HEAD */
-      return TRUE;
+      avail |= CURLPIPE_HTTP1;
 
     if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) &&
        (handle->set.httpversion >= CURL_HTTP_VERSION_2))
       /* allows HTTP/2 */
-      return TRUE;
+      avail |= CURLPIPE_MULTIPLEX;
   }
-  return FALSE;
+  return avail;
 }
 
 int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
@@ -2967,9 +3213,9 @@ void Curl_getoff_all_pipelines(struct Curl_easy *data,
   bool send_head = (conn->writechannel_inuse &&
                     Curl_sendpipe_head(data, conn));
 
-  if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
+  if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head)
     Curl_pipeline_leave_read(conn);
-  if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head)
+  if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head)
     Curl_pipeline_leave_write(conn);
 }
 
@@ -3014,8 +3260,8 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
   struct curl_hash_iterator iter;
   struct curl_llist_element *curr;
   struct curl_hash_element *he;
-  long highscore=-1;
-  long score;
+  time_t highscore=-1;
+  time_t score;
   struct timeval now;
   struct connectdata *conn_candidate = NULL;
   struct connectbundle *bundle;
@@ -3030,7 +3276,7 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
 
     bundle = he->ptr;
 
-    curr = bundle->conn_list->head;
+    curr = bundle->conn_list.head;
     while(curr) {
       conn = curr->ptr;
 
@@ -3052,6 +3298,19 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
   return conn_candidate;
 }
 
+static bool
+proxy_info_matches(const struct proxy_info* data,
+                   const struct proxy_info* needle)
+{
+  if((data->proxytype == needle->proxytype) &&
+     (data->port == needle->port) &&
+     Curl_safe_strcasecompare(data->host.name, needle->host.name))
+    return TRUE;
+
+  return FALSE;
+}
+
+
 /*
  * This function finds the connection in the connection
  * bundle that has been unused for the longest time.
@@ -3064,8 +3323,8 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
                                       struct connectbundle *bundle)
 {
   struct curl_llist_element *curr;
-  long highscore=-1;
-  long score;
+  time_t highscore=-1;
+  time_t score;
   struct timeval now;
   struct connectdata *conn_candidate = NULL;
   struct connectdata *conn;
@@ -3074,7 +3333,7 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
 
   now = Curl_tvnow();
 
-  curr = bundle->conn_list->head;
+  curr = bundle->conn_list.head;
   while(curr) {
     conn = curr->ptr;
 
@@ -3102,7 +3361,7 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
 static bool disconnect_if_dead(struct connectdata *conn,
                                struct Curl_easy *data)
 {
-  size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
+  size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size;
   if(!pipeLen && !conn->inuse) {
     /* The check for a dead socket makes sense only if there are no
        handles in pipeline and the connection isn't already marked in
@@ -3147,7 +3406,7 @@ static int call_disconnect_if_dead(struct connectdata *conn,
 static void prune_dead_connections(struct Curl_easy *data)
 {
   struct timeval now = Curl_tvnow();
-  long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
+  time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
 
   if(elapsed >= 1000L) {
     Curl_conncache_foreach(data->state.conn_cache, data,
@@ -3185,7 +3444,7 @@ ConnectionExists(struct Curl_easy *data,
   struct connectdata *check;
   struct connectdata *chosen = 0;
   bool foundPendingCandidate = FALSE;
-  bool canPipeline = IsPipeliningPossible(data, needle);
+  int canpipe = IsPipeliningPossible(data, needle);
   struct connectbundle *bundle;
 
 #ifdef USE_NTLM
@@ -3201,10 +3460,10 @@ ConnectionExists(struct Curl_easy *data,
   *force_reuse = FALSE;
   *waitpipe = FALSE;
 
-  /* We can't pipe if the site is blacklisted */
-  if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) {
-    canPipeline = FALSE;
-  }
+  /* We can't pipeline if the site is blacklisted */
+  if((canpipe & CURLPIPE_HTTP1) &&
+     Curl_pipeline_site_blacklisted(data, needle))
+    canpipe &= ~ CURLPIPE_HTTP1;
 
   /* Look up the bundle with all the connections to this
      particular host */
@@ -3215,22 +3474,17 @@ ConnectionExists(struct Curl_easy *data,
       max_pipeline_length(data->multi):0;
     size_t best_pipe_len = max_pipe_len;
     struct curl_llist_element *curr;
-    const char *hostname;
-
-    if(needle->bits.conn_to_host)
-      hostname = needle->conn_to_host.name;
-    else
-      hostname = needle->host.name;
 
     infof(data, "Found bundle for host %s: %p [%s]\n",
-          hostname, (void *)bundle,
-          (bundle->multiuse== BUNDLE_PIPELINING?
-           "can pipeline":
-           (bundle->multiuse== BUNDLE_MULTIPLEX?
-            "can multiplex":"serially")));
-
-    /* We can't pipe if we don't know anything about the server */
-    if(canPipeline) {
+          (needle->bits.conn_to_host ? needle->conn_to_host.name :
+           needle->host.name), (void *)bundle,
+          (bundle->multiuse == BUNDLE_PIPELINING ?
+           "can pipeline" :
+           (bundle->multiuse == BUNDLE_MULTIPLEX ?
+            "can multiplex" : "serially")));
+
+    /* We can't pipeline if we don't know anything about the server */
+    if(canpipe) {
       if(bundle->multiuse <= BUNDLE_UNKNOWN) {
         if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
           infof(data, "Server doesn't support multi-use yet, wait\n");
@@ -3239,22 +3493,22 @@ ConnectionExists(struct Curl_easy *data,
         }
 
         infof(data, "Server doesn't support multi-use (yet)\n");
-        canPipeline = FALSE;
+        canpipe = 0;
       }
       if((bundle->multiuse == BUNDLE_PIPELINING) &&
          !Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) {
         /* not asked for, switch off */
         infof(data, "Could pipeline, but not asked to!\n");
-        canPipeline = FALSE;
+        canpipe = 0;
       }
       else if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
               !Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) {
         infof(data, "Could multiplex, but not asked to!\n");
-        canPipeline = FALSE;
+        canpipe = 0;
       }
     }
 
-    curr = bundle->conn_list->head;
+    curr = bundle->conn_list.head;
     while(curr) {
       bool match = FALSE;
       size_t pipeLen;
@@ -3269,22 +3523,23 @@ ConnectionExists(struct Curl_easy *data,
       if(disconnect_if_dead(check, data))
         continue;
 
-      pipeLen = check->send_pipe->size + check->recv_pipe->size;
+      pipeLen = check->send_pipe.size + check->recv_pipe.size;
 
-      if(canPipeline) {
+      if(canpipe) {
         if(check->bits.protoconnstart && check->bits.close)
           continue;
 
         if(!check->bits.multiplex) {
-          /* If not multiplexing, make sure the pipe has only GET requests */
-          struct Curl_easy* sh = gethandleathead(check->send_pipe);
-          struct Curl_easy* rh = gethandleathead(check->recv_pipe);
+          /* If not multiplexing, make sure the connection is fine for HTTP/1
+             pipelining */
+          struct Curl_easy* sh = gethandleathead(&check->send_pipe);
+          struct Curl_easy* rh = gethandleathead(&check->recv_pipe);
           if(sh) {
-            if(!IsPipeliningPossible(sh, check))
+            if(!(IsPipeliningPossible(sh, check) & CURLPIPE_HTTP1))
               continue;
           }
           else if(rh) {
-            if(!IsPipeliningPossible(rh, check))
+            if(!(IsPipeliningPossible(rh, check) & CURLPIPE_HTTP1))
               continue;
           }
         }
@@ -3316,7 +3571,7 @@ ConnectionExists(struct Curl_easy *data,
           infof(data, "Connection #%ld isn't open enough, can't reuse\n",
                 check->connection_id);
 #ifdef DEBUGBUILD
-          if(check->recv_pipe->size > 0) {
+          if(check->recv_pipe.size > 0) {
             infof(data,
                   "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
                   check->connection_id);
@@ -3326,6 +3581,19 @@ ConnectionExists(struct Curl_easy *data,
         }
       }
 
+#ifdef USE_UNIX_SOCKETS
+      if(needle->unix_domain_socket) {
+        if(!check->unix_domain_socket)
+          continue;
+        if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
+          continue;
+        if(needle->abstract_unix_socket != check->abstract_unix_socket)
+          continue;
+      }
+      else if(check->unix_domain_socket)
+        continue;
+#endif
+
       if((needle->handler->flags&PROTOPT_SSL) !=
          (check->handler->flags&PROTOPT_SSL))
         /* don't do mixed SSL and non-SSL connections */
@@ -3334,23 +3602,12 @@ ConnectionExists(struct Curl_easy *data,
           /* except protocols that have been upgraded via TLS */
           continue;
 
-      if(needle->handler->flags&PROTOPT_SSL) {
-        if((data->set.ssl.verifypeer != check->verifypeer) ||
-           (data->set.ssl.verifyhost != check->verifyhost))
-          continue;
-      }
-
-      if(needle->bits.proxy != check->bits.proxy)
-        /* don't do mixed proxy and non-proxy connections */
+      if(needle->bits.httpproxy != check->bits.httpproxy ||
+         needle->bits.socksproxy != check->bits.socksproxy)
         continue;
 
-      if(needle->bits.proxy &&
-         (needle->proxytype != check->proxytype ||
-          needle->bits.httpproxy != check->bits.httpproxy ||
-          needle->bits.tunnel_proxy != check->bits.tunnel_proxy ||
-          !strcasecompare(needle->proxy.name, check->proxy.name) ||
-          needle->port != check->port))
-        /* don't mix connections that use different proxies */
+      if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
+                                                        &check->socks_proxy))
         continue;
 
       if(needle->bits.conn_to_host != check->bits.conn_to_host)
@@ -3363,7 +3620,34 @@ ConnectionExists(struct Curl_easy *data,
          * connections that don't use this feature */
         continue;
 
-      if(!canPipeline && check->inuse)
+      if(needle->bits.httpproxy) {
+        if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
+          continue;
+
+        if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
+          continue;
+
+        if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
+          /* use https proxy */
+          if(needle->handler->flags&PROTOPT_SSL) {
+            /* use double layer ssl */
+            if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
+                                        &check->proxy_ssl_config))
+              continue;
+            if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
+              continue;
+          }
+          else {
+            if(!Curl_ssl_config_matches(&needle->ssl_config,
+                                        &check->ssl_config))
+              continue;
+            if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
+              continue;
+          }
+        }
+      }
+
+      if(!canpipe && check->inuse)
         /* this request can't be pipelined but the checked connection is
            already in use so we skip it */
         continue;
@@ -3382,9 +3666,8 @@ ConnectionExists(struct Curl_easy *data,
         */
         if((check->localport != needle->localport) ||
            (check->localportrange != needle->localportrange) ||
-           !check->localdev ||
-           !needle->localdev ||
-           strcmp(check->localdev, needle->localdev))
+           (needle->localdev &&
+            (!check->localdev || strcmp(check->localdev, needle->localdev))))
           continue;
       }
 
@@ -3399,10 +3682,11 @@ ConnectionExists(struct Curl_easy *data,
       }
 
       if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
-         (needle->bits.httpproxy && needle->bits.tunnel_proxy)) {
+         needle->bits.tunnel_proxy) {
         /* The requested connection does not use a HTTP proxy or it uses SSL or
-           it is a non-SSL protocol tunneled over the same HTTP proxy name and
-           port number */
+           it is a non-SSL protocol tunneled or it is a non-SSL protocol which
+           is allowed to be upgraded via TLS */
+
         if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
             (get_protocol_family(check->handler->protocol) ==
              needle->handler->protocol && check->tls_upgraded)) &&
@@ -3426,7 +3710,7 @@ ConnectionExists(struct Curl_easy *data,
                            check->connection_id));
               continue;
             }
-            else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
+            if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
               foundPendingCandidate = TRUE;
               DEBUGF(infof(data,
                            "Connection #%ld has not started SSL connect, "
@@ -3463,12 +3747,13 @@ ConnectionExists(struct Curl_easy *data,
 
         /* Same for Proxy NTLM authentication */
         if(wantProxyNTLMhttp) {
-          /* Both check->proxyuser and check->proxypasswd can be NULL */
-          if(!check->proxyuser || !check->proxypasswd)
+          /* Both check->http_proxy.user and check->http_proxy.passwd can be
+           * NULL */
+          if(!check->http_proxy.user || !check->http_proxy.passwd)
             continue;
 
-          if(strcmp(needle->proxyuser, check->proxyuser) ||
-             strcmp(needle->proxypasswd, check->proxypasswd))
+          if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
+             strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
             continue;
         }
         else if(check->proxyntlm.state != NTLMSTATE_NONE) {
@@ -3493,7 +3778,7 @@ ConnectionExists(struct Curl_easy *data,
           continue;
         }
 #endif
-        if(canPipeline) {
+        if(canpipe) {
           /* We can pipeline if we want to. Let's continue looking for
              the optimal connection to use, i.e the shortest pipe that is not
              blacklisted. */
@@ -3572,51 +3857,50 @@ ConnectionExists(struct Curl_easy *data,
    Note: this function's sub-functions call failf()
 
 */
-CURLcode Curl_connected_proxy(struct connectdata *conn,
-                              int sockindex)
+CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
 {
-  if(!conn->bits.proxy || sockindex)
-    /* this magic only works for the primary socket as the secondary is used
-       for FTP only and it has FTP specific magic in ftp.c */
-    return CURLE_OK;
+  CURLcode result = CURLE_OK;
 
-  switch(conn->proxytype) {
+  if(conn->bits.socksproxy) {
 #ifndef CURL_DISABLE_PROXY
-  case CURLPROXY_SOCKS5:
-  case CURLPROXY_SOCKS5_HOSTNAME:
-    return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
-                       conn->bits.conn_to_host ? conn->conn_to_host.name :
-                       conn->host.name,
-                       conn->bits.conn_to_port ? conn->conn_to_port :
-                       conn->remote_port,
-                       FIRSTSOCKET, conn);
-
-  case CURLPROXY_SOCKS4:
-    return Curl_SOCKS4(conn->proxyuser,
-                       conn->bits.conn_to_host ? conn->conn_to_host.name :
-                       conn->host.name,
-                       conn->bits.conn_to_port ? conn->conn_to_port :
-                       conn->remote_port,
-                       FIRSTSOCKET, conn, FALSE);
-
-  case CURLPROXY_SOCKS4A:
-    return Curl_SOCKS4(conn->proxyuser,
-                       conn->bits.conn_to_host ? conn->conn_to_host.name :
-                       conn->host.name,
-                       conn->bits.conn_to_port ? conn->conn_to_port :
-                       conn->remote_port,
-                       FIRSTSOCKET, conn, TRUE);
+    /* for the secondary socket (FTP), use the "connect to host"
+     * but ignore the "connect to port" (use the secondary port)
+     */
+    const char * const host = conn->bits.httpproxy ?
+                              conn->http_proxy.host.name :
+                              conn->bits.conn_to_host ?
+                              conn->conn_to_host.name :
+                              sockindex == SECONDARYSOCKET ?
+                              conn->secondaryhostname : conn->host.name;
+    const int port = conn->bits.httpproxy ? (int)conn->http_proxy.port :
+                     sockindex == SECONDARYSOCKET ? conn->secondary_port :
+                     conn->bits.conn_to_port ? conn->conn_to_port :
+                     conn->remote_port;
+    conn->bits.socksproxy_connecting = TRUE;
+    switch(conn->socks_proxy.proxytype) {
+    case CURLPROXY_SOCKS5:
+    case CURLPROXY_SOCKS5_HOSTNAME:
+      result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
+                         host, port, sockindex, conn);
+      break;
+
+    case CURLPROXY_SOCKS4:
+    case CURLPROXY_SOCKS4A:
+      result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
+                           conn);
+      break;
 
+    default:
+      failf(conn->data, "unknown proxytype option given");
+      result = CURLE_COULDNT_CONNECT;
+    } /* switch proxytype */
+    conn->bits.socksproxy_connecting = FALSE;
+#else
+  (void)sockindex;
 #endif /* CURL_DISABLE_PROXY */
-  case CURLPROXY_HTTP:
-  case CURLPROXY_HTTP_1_0:
-    /* do nothing here. handled later. */
-    break;
-  default:
-    break;
-  } /* switch proxytype */
+  }
 
-  return CURLE_OK;
+  return result;
 }
 
 /*
@@ -3627,7 +3911,10 @@ void Curl_verboseconnect(struct connectdata *conn)
 {
   if(conn->data->set.verbose)
     infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
-          conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
+          conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
+          conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+          conn->bits.conn_to_host ? conn->conn_to_host.dispname :
+          conn->host.dispname,
           conn->ip_addr_str, conn->port, conn->connection_id);
 }
 #endif
@@ -3717,10 +4004,14 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
 
   if(!conn->bits.protoconnstart) {
 
-    result = Curl_proxy_connect(conn);
+    result = Curl_proxy_connect(conn, FIRSTSOCKET);
     if(result)
       return result;
 
+    if(CONNECT_FIRSTSOCKET_PROXY_SSL())
+      /* wait for HTTPS proxy SSL initialization to complete */
+      return CURLE_OK;
+
     if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
        (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
       /* when using an HTTP tunnel proxy, await complete tunnel establishment
@@ -3746,11 +4037,11 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
 }
 
 /*
- * Helpers for IDNA convertions.
+ * Helpers for IDNA conversions.
  */
 static bool is_ASCII_name(const char *hostname)
 {
-  const unsigned char *ch = (const unsigned char*)hostname;
+  const unsigned char *ch = (const unsigned char *)hostname;
 
   while(*ch) {
     if(*ch++ & 0x80)
@@ -3788,7 +4079,15 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host)
 #ifdef USE_LIBIDN2
     if(idn2_check_version(IDN2_VERSION)) {
       char *ace_hostname = NULL;
-      int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, 0);
+#if IDN2_VERSION_NUMBER >= 0x00140000
+      /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
+         IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
+         processing. */
+      int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
+#else
+      int flags = IDN2_NFC_INPUT;
+#endif
+      int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
       if(rc == IDN2_OK) {
         host->encalloc = (char *)ace_hostname;
         /* change the name pointer to point to the encoded hostname */
@@ -3862,7 +4161,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
   conn->connection_id = -1;    /* no ID */
   conn->port = -1; /* unknown at this point */
-  conn->remote_port = -1; /* unknown */
+  conn->remote_port = -1; /* unknown at this point */
 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
   conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
   conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
@@ -3879,12 +4178,14 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->data = data; /* Setup the association between this connection
                         and the Curl_easy */
 
-  conn->proxytype = data->set.proxytype; /* type */
+  conn->http_proxy.proxytype = data->set.proxytype;
+  conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
 
 #ifdef CURL_DISABLE_PROXY
 
   conn->bits.proxy = FALSE;
   conn->bits.httpproxy = FALSE;
+  conn->bits.socksproxy = FALSE;
   conn->bits.proxy_user_passwd = FALSE;
   conn->bits.tunnel_proxy = FALSE;
 
@@ -3895,11 +4196,20 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
                       *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
   conn->bits.httpproxy = (conn->bits.proxy &&
-                          (conn->proxytype == CURLPROXY_HTTP ||
-                           conn->proxytype == CURLPROXY_HTTP_1_0)) ?
-                          TRUE : FALSE;
-  conn->bits.proxy_user_passwd = (data->set.str[STRING_PROXYUSERNAME]) ?
-                                 TRUE : FALSE;
+                          (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
+                           conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
+                           conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
+                           TRUE : FALSE;
+  conn->bits.socksproxy = (conn->bits.proxy &&
+                           !conn->bits.httpproxy) ? TRUE : FALSE;
+
+  if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
+    conn->bits.proxy = TRUE;
+    conn->bits.socksproxy = TRUE;
+  }
+
+  conn->bits.proxy_user_passwd =
+    (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
 
 #endif /* CURL_DISABLE_PROXY */
@@ -3908,8 +4218,13 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
 
-  conn->verifypeer = data->set.ssl.verifypeer;
-  conn->verifyhost = data->set.ssl.verifyhost;
+  conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
+  conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
+  conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
+  conn->proxy_ssl_config.verifystatus =
+    data->set.proxy_ssl.primary.verifystatus;
+  conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
+  conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
 
   conn->ip_version = data->set.ipver;
 
@@ -3924,16 +4239,14 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
      !conn->master_buffer) {
     /* Allocate master_buffer to be used for HTTP/1 pipelining */
-    conn->master_buffer = calloc(BUFSIZE, sizeof (char));
+    conn->master_buffer = calloc(MASTERBUF_SIZE, sizeof(char));
     if(!conn->master_buffer)
       goto error;
   }
 
   /* Initialize the pipeline lists */
-  conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
-  conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
-  if(!conn->send_pipe || !conn->recv_pipe)
-    goto error;
+  Curl_llist_init(&conn->send_pipe, (curl_llist_dtor) llist_dtor);
+  Curl_llist_init(&conn->recv_pipe, (curl_llist_dtor) llist_dtor);
 
 #ifdef HAVE_GSSAPI
   conn->data_prot = PROT_CLEAR;
@@ -3956,11 +4269,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   return conn;
   error:
 
-  Curl_llist_destroy(conn->send_pipe, NULL);
-  Curl_llist_destroy(conn->recv_pipe, NULL);
-
-  conn->send_pipe = NULL;
-  conn->recv_pipe = NULL;
+  Curl_llist_destroy(&conn->send_pipe, NULL);
+  Curl_llist_destroy(&conn->recv_pipe, NULL);
 
   free(conn->master_buffer);
   free(conn->localdev);
@@ -4023,11 +4333,13 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   char *fragment;
   char *path = data->state.path;
   char *query;
+  int i;
   int rc;
-  char protobuf[16] = "";
   const char *protop = "";
   CURLcode result;
   bool rebuild_url = FALSE;
+  bool url_has_scheme = FALSE;
+  char protobuf[16];
 
   *prot_missing = FALSE;
 
@@ -4046,10 +4358,47 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
    * proxy -- and we don't know if we will need to use SSL until we parse the
    * url ...
    ************************************************************/
-  if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
-                  protobuf, path)) &&
-     strcasecompare(protobuf, "file")) {
-    if(path[0] == '/' && path[1] == '/') {
+  if(data->change.url[0] == ':') {
+    failf(data, "Bad URL, colon is first character");
+    return CURLE_URL_MALFORMAT;
+  }
+
+  /* Make sure we don't mistake a drive letter for a scheme, for example:
+     curld --proto-default file c:/foo/bar.txt */
+  if((('a' <= data->change.url[0] && data->change.url[0] <= 'z') ||
+      ('A' <= data->change.url[0] && data->change.url[0] <= 'Z')) &&
+     data->change.url[1] == ':' && data->set.str[STRING_DEFAULT_PROTOCOL] &&
+     strcasecompare(data->set.str[STRING_DEFAULT_PROTOCOL], "file")) {
+    ; /* do nothing */
+  }
+  else { /* check for a scheme */
+    for(i = 0; i < 16 && data->change.url[i]; ++i) {
+      if(data->change.url[i] == '/')
+        break;
+      if(data->change.url[i] == ':') {
+        url_has_scheme = TRUE;
+        break;
+      }
+    }
+  }
+
+  /* handle the file: scheme */
+  if((url_has_scheme && strncasecompare(data->change.url, "file:", 5)) ||
+     (!url_has_scheme && data->set.str[STRING_DEFAULT_PROTOCOL] &&
+      strcasecompare(data->set.str[STRING_DEFAULT_PROTOCOL], "file"))) {
+    bool path_has_drive = FALSE;
+
+    if(url_has_scheme)
+      rc = sscanf(data->change.url, "%*15[^\n/:]:%[^\n]", path);
+    else
+      rc = sscanf(data->change.url, "%[^\n]", path);
+
+    if(rc != 1) {
+      failf(data, "Bad URL");
+      return CURLE_URL_MALFORMAT;
+    }
+
+    if(url_has_scheme && path[0] == '/' && path[1] == '/') {
       /* Allow omitted hostname (e.g. file:/<path>).  This is not strictly
        * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
        * file://localhost/<path> is similar to how other schemes treat missing
@@ -4059,42 +4408,65 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
          memory areas overlap! */
       memmove(path, path + 2, strlen(path + 2)+1);
     }
+
+    /* the path may start with a drive letter. for backwards compatibility
+       we skip some processing on those paths. */
+    path_has_drive = (('a' <= path[0] && path[0] <= 'z') ||
+                      ('A' <= path[0] && path[0] <= 'Z')) && path[1] == ':';
+
     /*
      * we deal with file://<host>/<path> differently since it supports no
      * hostname other than "localhost" and "127.0.0.1", which is unique among
      * the URL protocols specified in RFC 1738
      */
-    if(path[0] != '/') {
-      /* the URL included a host name, we ignore host names in file:// URLs
-         as the standards don't define what to do with them */
-      char *ptr=strchr(path, '/');
-      if(ptr) {
-        /* there was a slash present
+    if(path[0] != '/' && !path_has_drive) {
+      /* the URL includes a host name, it must match "localhost" or
+         "127.0.0.1" to be valid */
+      char *ptr;
+      if(!checkprefix("localhost/", path) &&
+         !checkprefix("127.0.0.1/", path)) {
+        failf(data, "Invalid file://hostname/, "
+                    "expected localhost or 127.0.0.1 or none");
+        return CURLE_URL_MALFORMAT;
+      }
+      ptr = &path[9]; /* now points to the slash after the host */
 
-           RFC1738 (section 3.1, page 5) says:
+      /* there was a host name and slash present
 
-           The rest of the locator consists of data specific to the scheme,
-           and is known as the "url-path". It supplies the details of how the
-           specified resource can be accessed. Note that the "/" between the
-           host (or port) and the url-path is NOT part of the url-path.
+         RFC1738 (section 3.1, page 5) says:
 
-           As most agents use file://localhost/foo to get '/foo' although the
-           slash preceding foo is a separator and not a slash for the path,
-           a URL as file://localhost//foo must be valid as well, to refer to
-           the same file with an absolute path.
-        */
+         The rest of the locator consists of data specific to the scheme,
+         and is known as the "url-path". It supplies the details of how the
+         specified resource can be accessed. Note that the "/" between the
+         host (or port) and the url-path is NOT part of the url-path.
 
-        if(ptr[1] && ('/' == ptr[1]))
-          /* if there was two slashes, we skip the first one as that is then
-             used truly as a separator */
-          ptr++;
+         As most agents use file://localhost/foo to get '/foo' although the
+         slash preceding foo is a separator and not a slash for the path,
+         a URL as file://localhost//foo must be valid as well, to refer to
+         the same file with an absolute path.
+      */
 
-        /* This cannot be made with strcpy, as the memory chunks overlap! */
-        memmove(path, ptr, strlen(ptr)+1);
-      }
+      if('/' == ptr[1])
+        /* if there was two slashes, we skip the first one as that is then
+           used truly as a separator */
+        ptr++;
+
+      /* This cannot be made with strcpy, as the memory chunks overlap! */
+      memmove(path, ptr, strlen(ptr)+1);
+
+      path_has_drive = (('a' <= path[0] && path[0] <= 'z') ||
+                        ('A' <= path[0] && path[0] <= 'Z')) && path[1] == ':';
+    }
+
+#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
+    if(path_has_drive) {
+      failf(data, "File drive letters are only accepted in MSDOS/Windows.");
+      return CURLE_URL_MALFORMAT;
     }
+#endif
 
     protop = "file"; /* protocol string */
+    *prot_missing = !url_has_scheme;
   }
   else {
     /* clear path */
@@ -4102,7 +4474,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     path[0]=0;
 
     rc = sscanf(data->change.url,
-                "%15[^\n:]:%3[/]%[^\n/?#]%[^\n]",
+                "%15[^\n/:]:%3[/]%[^\n/?#]%[^\n]",
                 protobuf, slashbuf, conn->host.name, path);
     if(2 == rc) {
       failf(data, "Bad URL");
@@ -4258,14 +4630,30 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
 
     size_t plen = strlen(path); /* new path, should be 1 byte longer than
                                    the original */
-    size_t urllen = strlen(data->change.url); /* original URL length */
-
     size_t prefixlen = strlen(conn->host.name);
 
-    if(!*prot_missing)
-      prefixlen += strlen(protop) + strlen("://");
+    if(!*prot_missing) {
+      size_t protolen = strlen(protop);
+
+      if(curl_strnequal(protop, data->change.url, protolen))
+        prefixlen += protolen;
+      else {
+        failf(data, "<url> malformed");
+        return CURLE_URL_MALFORMAT;
+      }
+
+      if(curl_strnequal("://", &data->change.url[protolen], 3))
+        prefixlen += 3;
+      /* only file: is allowed to omit one or both slashes */
+      else if(curl_strnequal("file:", data->change.url, 5))
+        prefixlen += 1 + (data->change.url[5] == '/');
+      else {
+        failf(data, "<url> malformed");
+        return CURLE_URL_MALFORMAT;
+      }
+    }
 
-    reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
+    reurl = malloc(prefixlen + plen + 1);
     if(!reurl)
       return CURLE_OUT_OF_MEMORY;
 
@@ -4287,6 +4675,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     data->change.url_alloc = TRUE; /* free this later */
   }
 
+  result = findprotocol(data, conn, protop);
+  if(result)
+    return result;
+
   /*
    * Parse the login details from the URL and strip them out of
    * the host name
@@ -4373,8 +4765,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
    *   conn->host.name is B
    *   data->state.path is /C
    */
-
-  return findprotocol(data, conn, protop);
+  return CURLE_OK;
 }
 
 /*
@@ -4473,7 +4864,7 @@ void Curl_free_request_state(struct Curl_easy *data)
 * Checks if the host is in the noproxy list. returns true if it matches
 * and therefore the proxy should NOT be used.
 ****************************************************************/
-static bool check_noproxy(const char* name, const char* no_proxy)
+static bool check_noproxy(const char *name, const char *no_proxy)
 {
   /* no_proxy=domain1.dom,host.domain2.dom
    *   (a comma-separated list of hosts which should
@@ -4482,7 +4873,7 @@ static bool check_noproxy(const char* name, const char* no_proxy)
    */
   size_t tok_start;
   size_t tok_end;
-  const char* separator = ", ";
+  const char *separator = ", ";
   size_t no_proxy_len;
   size_t namelen;
   char *endptr;
@@ -4543,6 +4934,7 @@ static bool check_noproxy(const char* name, const char* no_proxy)
   return FALSE;
 }
 
+#ifndef CURL_DISABLE_HTTP
 /****************************************************************
 * Detect what (if any) proxy to use. Remember that this selects a host
 * name and is not limited to HTTP proxies only.
@@ -4552,7 +4944,6 @@ static char *detect_proxy(struct connectdata *conn)
 {
   char *proxy = NULL;
 
-#ifndef CURL_DISABLE_HTTP
   /* If proxy was not specified, we check for default proxy environment
    * variables, to enable i.e Lynx compliance:
    *
@@ -4570,65 +4961,50 @@ static char *detect_proxy(struct connectdata *conn)
    * For compatibility, the all-uppercase versions of these variables are
    * checked if the lowercase versions don't exist.
    */
-  char *no_proxy=NULL;
   char proxy_env[128];
+  const char *protop = conn->handler->scheme;
+  char *envp = proxy_env;
+  char *prox;
 
-  no_proxy=curl_getenv("no_proxy");
-  if(!no_proxy)
-    no_proxy=curl_getenv("NO_PROXY");
-
-  if(!check_noproxy(conn->host.name, no_proxy)) {
-    /* It was not listed as without proxy */
-    const char *protop = conn->handler->scheme;
-    char *envp = proxy_env;
-    char *prox;
+  /* Now, build <protocol>_proxy and check for such a one to use */
+  while(*protop)
+    *envp++ = (char)tolower((int)*protop++);
 
-    /* Now, build <protocol>_proxy and check for such a one to use */
-    while(*protop)
-      *envp++ = (char)tolower((int)*protop++);
+  /* append _proxy */
+  strcpy(envp, "_proxy");
 
-    /* append _proxy */
-    strcpy(envp, "_proxy");
+  /* read the protocol proxy: */
+  prox=curl_getenv(proxy_env);
 
-    /* read the protocol proxy: */
+  /*
+   * We don't try the uppercase version of HTTP_PROXY because of
+   * security reasons:
+   *
+   * When curl is used in a webserver application
+   * environment (cgi or php), this environment variable can
+   * be controlled by the web server user by setting the
+   * http header 'Proxy:' to some value.
+   *
+   * This can cause 'internal' http/ftp requests to be
+   * arbitrarily redirected by any external attacker.
+   */
+  if(!prox && !strcasecompare("http_proxy", proxy_env)) {
+    /* There was no lowercase variable, try the uppercase version: */
+    Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
     prox=curl_getenv(proxy_env);
+  }
 
-    /*
-     * We don't try the uppercase version of HTTP_PROXY because of
-     * security reasons:
-     *
-     * When curl is used in a webserver application
-     * environment (cgi or php), this environment variable can
-     * be controlled by the web server user by setting the
-     * http header 'Proxy:' to some value.
-     *
-     * This can cause 'internal' http/ftp requests to be
-     * arbitrarily redirected by any external attacker.
-     */
-    if(!prox && !strcasecompare("http_proxy", proxy_env)) {
-      /* There was no lowercase variable, try the uppercase version: */
-      Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
-      prox=curl_getenv(proxy_env);
-    }
-
-    if(prox)
-      proxy = prox; /* use this */
-    else {
-      proxy = curl_getenv("all_proxy"); /* default proxy to use */
-      if(!proxy)
-        proxy=curl_getenv("ALL_PROXY");
-    }
-  } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified
-       non-proxy */
-  free(no_proxy);
-
-#else /* !CURL_DISABLE_HTTP */
-
-  (void)conn;
-#endif /* CURL_DISABLE_HTTP */
+  if(prox)
+    proxy = prox; /* use this */
+  else {
+    proxy = curl_getenv("all_proxy"); /* default proxy to use */
+    if(!proxy)
+      proxy=curl_getenv("ALL_PROXY");
+  }
 
   return proxy;
 }
+#endif /* CURL_DISABLE_HTTP */
 
 /*
  * If this is supposed to use a proxy, we need to figure out the proxy
@@ -4636,7 +5012,8 @@ static char *detect_proxy(struct connectdata *conn)
  * that may exist registered to the same proxy host.
  */
 static CURLcode parse_proxy(struct Curl_easy *data,
-                            struct connectdata *conn, char *proxy)
+                            struct connectdata *conn, char *proxy,
+                            curl_proxytype proxytype)
 {
   char *prox_portno;
   char *endofprot;
@@ -4645,6 +5022,10 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   char *proxyptr;
   char *portptr;
   char *atsign;
+  long port = -1;
+  char *proxyuser = NULL;
+  char *proxypasswd = NULL;
+  bool sockstype;
 
   /* We do the proxy host string parsing here. We want the host name and the
    * port name. Accept a protocol:// prefix
@@ -4654,14 +5035,16 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   endofprot = strstr(proxy, "://");
   if(endofprot) {
     proxyptr = endofprot+3;
-    if(checkprefix("socks5h", proxy))
-      conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
+    if(checkprefix("https", proxy))
+      proxytype = CURLPROXY_HTTPS;
+    else if(checkprefix("socks5h", proxy))
+      proxytype = CURLPROXY_SOCKS5_HOSTNAME;
     else if(checkprefix("socks5", proxy))
-      conn->proxytype = CURLPROXY_SOCKS5;
+      proxytype = CURLPROXY_SOCKS5;
     else if(checkprefix("socks4a", proxy))
-      conn->proxytype = CURLPROXY_SOCKS4A;
+      proxytype = CURLPROXY_SOCKS4A;
     else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
-      conn->proxytype = CURLPROXY_SOCKS4;
+      proxytype = CURLPROXY_SOCKS4;
     else if(checkprefix("http:", proxy))
       ; /* leave it as HTTP or HTTP/1.0 */
     else {
@@ -4673,54 +5056,28 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   else
     proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
 
+#ifndef HTTPS_PROXY_SUPPORT
+  if(proxytype == CURLPROXY_HTTPS) {
+    failf(data, "Unsupported proxy \'%s\'"
+                ", libcurl is built without the HTTPS-proxy support.", proxy);
+    return CURLE_NOT_BUILT_IN;
+  }
+#endif
+
+  sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
+              proxytype == CURLPROXY_SOCKS5 ||
+              proxytype == CURLPROXY_SOCKS4A ||
+              proxytype == CURLPROXY_SOCKS4;
+
   /* Is there a username and password given in this proxy url? */
   atsign = strchr(proxyptr, '@');
   if(atsign) {
-    char *proxyuser = NULL;
-    char *proxypasswd = NULL;
     CURLcode result =
       parse_login_details(proxyptr, atsign - proxyptr,
-                          &proxyuser, &proxypasswd, NULL);
-    if(!result) {
-      /* found user and password, rip them out.  note that we are
-         unescaping them, as there is otherwise no way to have a
-         username or password with reserved characters like ':' in
-         them. */
-      Curl_safefree(conn->proxyuser);
-      if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
-        result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL,
-                                FALSE);
-      else {
-        conn->proxyuser = strdup("");
-        if(!conn->proxyuser)
-          result = CURLE_OUT_OF_MEMORY;
-      }
-
-      if(!result) {
-        Curl_safefree(conn->proxypasswd);
-        if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
-          result = Curl_urldecode(data, proxypasswd, 0,
-                                  &conn->proxypasswd, NULL, FALSE);
-        else {
-          conn->proxypasswd = strdup("");
-          if(!conn->proxypasswd)
-            result = CURLE_OUT_OF_MEMORY;
-        }
-      }
-
-      if(!result) {
-        conn->bits.proxy_user_passwd = TRUE; /* enable it */
-        atsign++; /* the right side of the @-letter */
-
-        proxyptr = atsign; /* now use this instead */
-      }
-    }
-
-    free(proxyuser);
-    free(proxypasswd);
-
+                              &proxyuser, &proxypasswd, NULL);
     if(result)
       return result;
+    proxyptr = atsign + 1;
   }
 
   /* start scanning for port number at this point */
@@ -4757,7 +5114,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   prox_portno = strchr(portptr, ':');
   if(prox_portno) {
     char *endp = NULL;
-    long port = 0;
+
     *prox_portno = 0x0; /* cut off number from host name */
     prox_portno ++;
     /* now set the local port number */
@@ -4791,15 +5148,63 @@ static CURLcode parse_proxy(struct Curl_easy *data,
     if(data->set.proxyport)
       /* None given in the proxy string, then get the default one if it is
          given */
-      conn->port = data->set.proxyport;
+      port = data->set.proxyport;
+    else {
+      if(proxytype == CURLPROXY_HTTPS)
+        port = CURL_DEFAULT_HTTPS_PROXY_PORT;
+      else
+        port = CURL_DEFAULT_PROXY_PORT;
+    }
   }
 
-  /* now, clone the cleaned proxy host name */
-  conn->proxy.rawalloc = strdup(proxyptr);
-  conn->proxy.name = conn->proxy.rawalloc;
+  if(*proxyptr) {
+    struct proxy_info *proxyinfo =
+      sockstype ? &conn->socks_proxy : &conn->http_proxy;
+    proxyinfo->proxytype = proxytype;
 
-  if(!conn->proxy.rawalloc)
-    return CURLE_OUT_OF_MEMORY;
+    if(proxyuser) {
+      /* found user and password, rip them out.  note that we are unescaping
+         them, as there is otherwise no way to have a username or password
+         with reserved characters like ':' in them. */
+      Curl_safefree(proxyinfo->user);
+      proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL);
+      Curl_safefree(proxyuser);
+
+      if(!proxyinfo->user) {
+        Curl_safefree(proxypasswd);
+        return CURLE_OUT_OF_MEMORY;
+      }
+
+      Curl_safefree(proxyinfo->passwd);
+      if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
+        proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+      else
+        proxyinfo->passwd = strdup("");
+      Curl_safefree(proxypasswd);
+
+      if(!proxyinfo->passwd)
+        return CURLE_OUT_OF_MEMORY;
+
+      conn->bits.proxy_user_passwd = TRUE; /* enable it */
+    }
+
+    if(port >= 0) {
+      proxyinfo->port = port;
+      if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
+        conn->port = port;
+    }
+
+    /* now, clone the cleaned proxy host name */
+    Curl_safefree(proxyinfo->host.rawalloc);
+    proxyinfo->host.rawalloc = strdup(proxyptr);
+    proxyinfo->host.name = proxyinfo->host.rawalloc;
+
+    if(!proxyinfo->host.rawalloc)
+      return CURLE_OUT_OF_MEMORY;
+  }
+
+  Curl_safefree(proxyuser);
+  Curl_safefree(proxypasswd);
 
   return CURLE_OK;
 }
@@ -4825,10 +5230,173 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
     proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
   }
 
-  result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, FALSE);
+  result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
+                          FALSE);
   if(!result)
-    result = Curl_urldecode(data, proxypasswd, 0, &conn->proxypasswd, NULL,
-                            FALSE);
+    result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
+                            NULL, FALSE);
+  return result;
+}
+
+/* create_conn helper to parse and init proxy values. to be called after unix
+   socket init but before any proxy vars are evaluated. */
+static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
+{
+  char *proxy = NULL;
+  char *socksproxy = NULL;
+  char *no_proxy = NULL;
+  CURLcode result = CURLE_OK;
+  struct Curl_easy *data = conn->data;
+
+  /*************************************************************
+   * Extract the user and password from the authentication string
+   *************************************************************/
+  if(conn->bits.proxy_user_passwd) {
+    result = parse_proxy_auth(data, conn);
+    if(result)
+      goto out;
+  }
+
+  /*************************************************************
+   * Detect what (if any) proxy to use
+   *************************************************************/
+  if(data->set.str[STRING_PROXY]) {
+    proxy = strdup(data->set.str[STRING_PROXY]);
+    /* if global proxy is set, this is it */
+    if(NULL == proxy) {
+      failf(data, "memory shortage");
+      result = CURLE_OUT_OF_MEMORY;
+      goto out;
+    }
+  }
+
+  if(data->set.str[STRING_PRE_PROXY]) {
+    socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
+    /* if global socks proxy is set, this is it */
+    if(NULL == socksproxy) {
+      failf(data, "memory shortage");
+      result = CURLE_OUT_OF_MEMORY;
+      goto out;
+    }
+  }
+
+  no_proxy = curl_getenv("no_proxy");
+  if(!no_proxy)
+    no_proxy = curl_getenv("NO_PROXY");
+
+  if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY]) ||
+     (!data->set.str[STRING_NOPROXY] &&
+      check_noproxy(conn->host.name, no_proxy))) {
+    Curl_safefree(proxy);
+    Curl_safefree(socksproxy);
+  }
+  else if(!proxy && !socksproxy)
+#ifndef CURL_DISABLE_HTTP
+    /* if the host is not in the noproxy list, detect proxy. */
+    proxy = detect_proxy(conn);
+#else  /* !CURL_DISABLE_HTTP */
+    proxy = NULL;
+#endif /* CURL_DISABLE_HTTP */
+
+  Curl_safefree(no_proxy);
+
+#ifdef USE_UNIX_SOCKETS
+  /* For the time being do not mix proxy and unix domain sockets. See #1274 */
+  if(proxy && conn->unix_domain_socket) {
+    free(proxy);
+    proxy = NULL;
+  }
+#endif
+
+  if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
+    free(proxy);  /* Don't bother with an empty proxy string or if the
+                     protocol doesn't work with network */
+    proxy = NULL;
+  }
+  if(socksproxy && (!*socksproxy ||
+                    (conn->handler->flags & PROTOPT_NONETWORK))) {
+    free(socksproxy);  /* Don't bother with an empty socks proxy string or if
+                          the protocol doesn't work with network */
+    socksproxy = NULL;
+  }
+
+  /***********************************************************************
+   * If this is supposed to use a proxy, we need to figure out the proxy host
+   * name, proxy type and port number, so that we can re-use an existing
+   * connection that may exist registered to the same proxy host.
+   ***********************************************************************/
+  if(proxy || socksproxy) {
+    if(proxy) {
+      result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
+      Curl_safefree(proxy); /* parse_proxy copies the proxy string */
+      if(result)
+        goto out;
+    }
+
+    if(socksproxy) {
+      result = parse_proxy(data, conn, socksproxy,
+                           conn->socks_proxy.proxytype);
+      /* parse_proxy copies the socks proxy string */
+      Curl_safefree(socksproxy);
+      if(result)
+        goto out;
+    }
+
+    if(conn->http_proxy.host.rawalloc) {
+#ifdef CURL_DISABLE_HTTP
+      /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
+      result = CURLE_UNSUPPORTED_PROTOCOL;
+      goto out;
+#else
+      /* force this connection's protocol to become HTTP if not already
+         compatible - if it isn't tunneling through */
+      if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+         !conn->bits.tunnel_proxy)
+        conn->handler = &Curl_handler_http;
+
+      conn->bits.httpproxy = TRUE;
+#endif
+    }
+    else {
+      conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
+      conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
+    }
+
+    if(conn->socks_proxy.host.rawalloc) {
+      if(!conn->http_proxy.host.rawalloc) {
+        /* once a socks proxy */
+        if(!conn->socks_proxy.user) {
+          conn->socks_proxy.user = conn->http_proxy.user;
+          conn->http_proxy.user = NULL;
+          Curl_safefree(conn->socks_proxy.passwd);
+          conn->socks_proxy.passwd = conn->http_proxy.passwd;
+          conn->http_proxy.passwd = NULL;
+        }
+      }
+      conn->bits.socksproxy = TRUE;
+    }
+    else
+      conn->bits.socksproxy = FALSE; /* not a socks proxy */
+  }
+  else {
+    conn->bits.socksproxy = FALSE;
+    conn->bits.httpproxy = FALSE;
+  }
+  conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
+
+  if(!conn->bits.proxy) {
+    /* we aren't using the proxy after all... */
+    conn->bits.proxy = FALSE;
+    conn->bits.httpproxy = FALSE;
+    conn->bits.socksproxy = FALSE;
+    conn->bits.proxy_user_passwd = FALSE;
+    conn->bits.tunnel_proxy = FALSE;
+  }
+
+out:
+
+  free(socksproxy);
+  free(proxy);
   return result;
 }
 #endif /* CURL_DISABLE_PROXY */
@@ -4871,6 +5439,7 @@ static CURLcode parse_url_login(struct Curl_easy *data,
   DEBUGASSERT(!**user);
   DEBUGASSERT(!**passwd);
   DEBUGASSERT(!**options);
+  DEBUGASSERT(conn->handler);
 
   if(!ptr)
     goto out;
@@ -4889,9 +5458,12 @@ static CURLcode parse_url_login(struct Curl_easy *data,
   if(data->set.use_netrc == CURL_NETRC_REQUIRED)
     goto out;
 
-  /* We could use the login information in the URL so extract it */
+  /* We could use the login information in the URL so extract it. Only parse
+     options if the handler says we should. */
   result = parse_login_details(login, ptr - login - 1,
-                               &userp, &passwdp, &optionsp);
+                               &userp, &passwdp,
+                               (conn->handler->flags & PROTOPT_URLOPTIONS)?
+                               &optionsp:NULL);
   if(result)
     goto out;
 
@@ -5121,7 +5693,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
     }
 #endif
 
-    portptr = strrchr(conn->host.name, ':');
+    portptr = strchr(conn->host.name, ':');
   }
 
   if(data->set.use_port && data->state.allow_port) {
@@ -5176,15 +5748,21 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
       return CURLE_URL_MALFORMAT;
     }
 
-    else if(rest != &portptr[1]) {
+    if(rest[0]) {
+      failf(data, "Port number ended with '%c'", rest[0]);
+      return CURLE_URL_MALFORMAT;
+    }
+
+    if(rest != &portptr[1]) {
       *portptr = '\0'; /* cut off the name there */
       conn->remote_port = curlx_ultous(port);
     }
-    else
+    else {
       /* Browser behavior adaptation. If there's a colon with no digits after,
          just cut off the name there which makes us ignore the colon and just
          use the default port. Firefox and Chrome both do that. */
       *portptr = '\0';
+    }
   }
 
   /* only if remote_port was not already parsed off the URL we use the
@@ -5313,6 +5891,10 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
   char *portptr;
   int port = -1;
 
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+  (void) data;
+#endif
+
   *hostname_result = NULL;
   *port_result = -1;
 
@@ -5404,6 +5986,9 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
   int host_match = FALSE;
   int port_match = FALSE;
 
+  *host_result = NULL;
+  *port_result = -1;
+
   if(*ptr == ':') {
     /* an empty hostname always matches */
     host_match = TRUE;
@@ -5466,28 +6051,25 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
 {
   CURLcode result = CURLE_OK;
   char *host = NULL;
-  int port = 0;
+  int port = -1;
 
-  while(conn_to_host && !host) {
+  while(conn_to_host && !host && port == -1) {
     result = parse_connect_to_string(data, conn, conn_to_host->data,
                                      &host, &port);
     if(result)
       return result;
 
     if(host && *host) {
-      bool ipv6host;
       conn->conn_to_host.rawalloc = host;
       conn->conn_to_host.name = host;
       conn->bits.conn_to_host = TRUE;
 
-      ipv6host = strchr(host, ':') != NULL;
-      infof(data, "Connecting to hostname: %s%s%s\n",
-            ipv6host ? "[" : "", host, ipv6host ? "]" : "");
+      infof(data, "Connecting to hostname: %s\n", host);
     }
     else {
       /* no "connect to host" */
       conn->bits.conn_to_host = FALSE;
-      free(host);
+      Curl_safefree(host);
     }
 
     if(port >= 0) {
@@ -5498,6 +6080,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
     else {
       /* no "connect to port" */
       conn->bits.conn_to_port = FALSE;
+      port = -1;
     }
 
     conn_to_host = conn_to_host->next;
@@ -5514,7 +6097,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
                                bool *async)
 {
   CURLcode result=CURLE_OK;
-  long timeout_ms = Curl_timeleft(data, NULL, TRUE);
+  time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
 
   /*************************************************************
    * Resolve the name of the server or proxy
@@ -5531,32 +6114,37 @@ static CURLcode resolve_server(struct Curl_easy *data,
     struct Curl_dns_entry *hostaddr;
 
 #ifdef USE_UNIX_SOCKETS
-    if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+    if(conn->unix_domain_socket) {
       /* Unix domain sockets are local. The host gets ignored, just use the
        * specified domain socket address. Do not cache "DNS entries". There is
        * no DNS involved and we already have the filesystem path available */
-      const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
+      const char *path = conn->unix_domain_socket;
 
       hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
       if(!hostaddr)
         result = CURLE_OUT_OF_MEMORY;
-      else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
-        hostaddr->inuse++;
       else {
-        /* Long paths are not supported for now */
-        if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
-          failf(data, "Unix socket path too long: '%s'", path);
-          result = CURLE_COULDNT_RESOLVE_HOST;
+        bool longpath = FALSE;
+        hostaddr->addr = Curl_unix2addr(path, &longpath,
+                                        conn->abstract_unix_socket);
+        if(hostaddr->addr)
+          hostaddr->inuse++;
+        else {
+          /* Long paths are not supported for now */
+          if(longpath) {
+            failf(data, "Unix socket path too long: '%s'", path);
+            result = CURLE_COULDNT_RESOLVE_HOST;
+          }
+          else
+            result = CURLE_OUT_OF_MEMORY;
+          free(hostaddr);
+          hostaddr = NULL;
         }
-        else
-          result = CURLE_OUT_OF_MEMORY;
-        free(hostaddr);
-        hostaddr = NULL;
       }
     }
     else
 #endif
-    if(!conn->proxy.name || !*conn->proxy.name) {
+    if(!conn->bits.proxy) {
       struct hostname *connhost;
       if(conn->bits.conn_to_host)
         connhost = &conn->conn_to_host;
@@ -5568,7 +6156,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
       if(conn->bits.conn_to_port)
         conn->port = conn->conn_to_port;
       else
-        conn->port = conn->remote_port; /* it is the same port */
+        conn->port = conn->remote_port;
 
       /* Resolve target host right on */
       rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port,
@@ -5588,8 +6176,11 @@ static CURLcode resolve_server(struct Curl_easy *data,
     else {
       /* This is a proxy that hasn't been resolved yet. */
 
+      struct hostname * const host = conn->bits.socksproxy ?
+        &conn->socks_proxy.host : &conn->http_proxy.host;
+
       /* resolve proxy */
-      rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port,
+      rc = Curl_resolv_timeout(conn, host->name, (int)conn->port,
                                &hostaddr, timeout_ms);
 
       if(rc == CURLRESOLV_PENDING)
@@ -5599,7 +6190,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
         result = CURLE_OPERATION_TIMEDOUT;
 
       else if(!hostaddr) {
-        failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
+        failf(data, "Couldn't resolve proxy '%s'", host->dispname);
         result = CURLE_COULDNT_RESOLVE_PROXY;
         /* don't return yet, we need to clean up the timeout first */
       }
@@ -5619,12 +6210,16 @@ static CURLcode resolve_server(struct Curl_easy *data,
 static void reuse_conn(struct connectdata *old_conn,
                        struct connectdata *conn)
 {
-  free_fixed_hostname(&old_conn->proxy);
-  free(old_conn->proxy.rawalloc);
+  free_fixed_hostname(&old_conn->http_proxy.host);
+  free_fixed_hostname(&old_conn->socks_proxy.host);
+
+  free(old_conn->http_proxy.host.rawalloc);
+  free(old_conn->socks_proxy.host.rawalloc);
 
   /* free the SSL config struct from this connection struct as this was
      allocated in vain and is targeted for destruction */
-  Curl_free_ssl_config(&old_conn->ssl_config);
+  Curl_free_primary_ssl_config(&old_conn->ssl_config);
+  Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
 
   conn->data = old_conn->data;
 
@@ -5644,12 +6239,18 @@ static void reuse_conn(struct connectdata *old_conn,
   conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
   if(conn->bits.proxy_user_passwd) {
     /* use the new proxy user name and proxy password though */
-    Curl_safefree(conn->proxyuser);
-    Curl_safefree(conn->proxypasswd);
-    conn->proxyuser = old_conn->proxyuser;
-    conn->proxypasswd = old_conn->proxypasswd;
-    old_conn->proxyuser = NULL;
-    old_conn->proxypasswd = NULL;
+    Curl_safefree(conn->http_proxy.user);
+    Curl_safefree(conn->socks_proxy.user);
+    Curl_safefree(conn->http_proxy.passwd);
+    Curl_safefree(conn->socks_proxy.passwd);
+    conn->http_proxy.user = old_conn->http_proxy.user;
+    conn->socks_proxy.user = old_conn->socks_proxy.user;
+    conn->http_proxy.passwd = old_conn->http_proxy.passwd;
+    conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
+    old_conn->http_proxy.user = NULL;
+    old_conn->socks_proxy.user = NULL;
+    old_conn->http_proxy.passwd = NULL;
+    old_conn->socks_proxy.passwd = NULL;
   }
 
   /* host can change, when doing keepalive with a proxy or if the case is
@@ -5668,24 +6269,26 @@ static void reuse_conn(struct connectdata *old_conn,
   Curl_persistconninfo(conn);
 
   conn_reset_all_postponed_data(old_conn); /* free buffers */
-  conn_reset_all_postponed_data(conn);     /* reset unprocessed data */
 
   /* re-use init */
   conn->bits.reuse = TRUE; /* yes, we're re-using here */
 
   Curl_safefree(old_conn->user);
   Curl_safefree(old_conn->passwd);
-  Curl_safefree(old_conn->proxyuser);
-  Curl_safefree(old_conn->proxypasswd);
+  Curl_safefree(old_conn->http_proxy.user);
+  Curl_safefree(old_conn->socks_proxy.user);
+  Curl_safefree(old_conn->http_proxy.passwd);
+  Curl_safefree(old_conn->socks_proxy.passwd);
   Curl_safefree(old_conn->localdev);
 
-  Curl_llist_destroy(old_conn->send_pipe, NULL);
-  Curl_llist_destroy(old_conn->recv_pipe, NULL);
-
-  old_conn->send_pipe = NULL;
-  old_conn->recv_pipe = NULL;
+  Curl_llist_destroy(&old_conn->send_pipe, NULL);
+  Curl_llist_destroy(&old_conn->recv_pipe, NULL);
 
   Curl_safefree(old_conn->master_buffer);
+
+#ifdef USE_UNIX_SOCKETS
+  Curl_safefree(old_conn->unix_domain_socket);
+#endif
 }
 
 /**
@@ -5716,7 +6319,6 @@ static CURLcode create_conn(struct Curl_easy *data,
   char *passwd = NULL;
   char *options = NULL;
   bool reuse;
-  char *proxy = NULL;
   bool prot_missing = FALSE;
   bool connections_available = TRUE;
   bool force_reuse = FALSE;
@@ -5860,95 +6462,24 @@ static CURLcode create_conn(struct Curl_easy *data,
     }
   }
 
-#ifndef CURL_DISABLE_PROXY
-  /*************************************************************
-   * Extract the user and password from the authentication string
-   *************************************************************/
-  if(conn->bits.proxy_user_passwd) {
-    result = parse_proxy_auth(data, conn);
-    if(result)
-      goto out;
-  }
-
-  /*************************************************************
-   * Detect what (if any) proxy to use
-   *************************************************************/
-  if(data->set.str[STRING_PROXY]) {
-    proxy = strdup(data->set.str[STRING_PROXY]);
-    /* if global proxy is set, this is it */
-    if(NULL == proxy) {
-      failf(data, "memory shortage");
+#ifdef USE_UNIX_SOCKETS
+  if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+    conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
+    if(conn->unix_domain_socket == NULL) {
       result = CURLE_OUT_OF_MEMORY;
       goto out;
     }
-  }
-
-  if(data->set.str[STRING_NOPROXY] &&
-     check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
-    free(proxy);  /* proxy is in exception list */
-    proxy = NULL;
-  }
-  else if(!proxy)
-    proxy = detect_proxy(conn);
-
-#ifdef USE_UNIX_SOCKETS
-  if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
-    free(proxy);  /* Unix domain sockets cannot be proxied, so disable it */
-    proxy = NULL;
+    conn->abstract_unix_socket = data->set.abstract_unix_socket;
   }
 #endif
 
-  if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
-    free(proxy);  /* Don't bother with an empty proxy string or if the
-                     protocol doesn't work with network */
-    proxy = NULL;
-  }
-
-  /***********************************************************************
-   * If this is supposed to use a proxy, we need to figure out the proxy host
-   * name, proxy type and port number, so that we can re-use an existing
-   * connection that may exist registered to the same proxy host.
-   ***********************************************************************/
-  if(proxy) {
-    result = parse_proxy(data, conn, proxy);
-
-    free(proxy); /* parse_proxy copies the proxy string */
-    proxy = NULL;
-
-    if(result)
-      goto out;
-
-    if((conn->proxytype == CURLPROXY_HTTP) ||
-       (conn->proxytype == CURLPROXY_HTTP_1_0)) {
-#ifdef CURL_DISABLE_HTTP
-      /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
-      result = CURLE_UNSUPPORTED_PROTOCOL;
-      goto out;
-#else
-      /* force this connection's protocol to become HTTP if not already
-         compatible - if it isn't tunneling through */
-      if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
-         !conn->bits.tunnel_proxy)
-        conn->handler = &Curl_handler_http;
-
-      conn->bits.httpproxy = TRUE;
+  /* After the unix socket init but before the proxy vars are used, parse and
+     initialize the proxy vars */
+#ifndef CURL_DISABLE_PROXY
+  result = create_conn_helper_init_proxy(conn);
+  if(result)
+    goto out;
 #endif
-    }
-    else {
-      conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
-      conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
-    }
-    conn->bits.proxy = TRUE;
-  }
-  else {
-    /* we aren't using the proxy after all... */
-    conn->bits.proxy = FALSE;
-    conn->bits.httpproxy = FALSE;
-    conn->bits.proxy_user_passwd = FALSE;
-    conn->bits.tunnel_proxy = FALSE;
-  }
-
-#endif /* CURL_DISABLE_PROXY */
 
   /*************************************************************
    * If the protocol is using SSL and HTTP proxy is used, we set
@@ -5987,12 +6518,14 @@ static CURLcode create_conn(struct Curl_easy *data,
   fix_hostname(conn, &conn->host);
   if(conn->bits.conn_to_host)
     fix_hostname(conn, &conn->conn_to_host);
-  if(conn->proxy.name && *conn->proxy.name)
-    fix_hostname(conn, &conn->proxy);
+  if(conn->bits.httpproxy)
+    fix_hostname(conn, &conn->http_proxy.host);
+  if(conn->bits.socksproxy)
+    fix_hostname(conn, &conn->socks_proxy.host);
 
   /*************************************************************
    * Check whether the host and the "connect to host" are equal.
-   * Do this after the hostnames have been IDN-fixed .
+   * Do this after the hostnames have been IDN-fixed.
    *************************************************************/
   if(conn->bits.conn_to_host &&
      strcasecompare(conn->conn_to_host.name, conn->host.name)) {
@@ -6079,20 +6612,51 @@ static CURLcode create_conn(struct Curl_easy *data,
      that will be freed as part of the Curl_easy struct, but all cloned
      copies will be separately allocated.
   */
-  data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
-  data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
-  data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
-  data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
-  data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
-  data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
-  data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
-  data->set.ssl.clientcert = data->set.str[STRING_CERT];
+  data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
+  data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
+  data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
+  data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
+  data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
+  data->set.proxy_ssl.primary.random_file =
+    data->set.str[STRING_SSL_RANDOM_FILE];
+  data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+  data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+  data->set.ssl.primary.cipher_list =
+    data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
+  data->set.proxy_ssl.primary.cipher_list =
+    data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
+
+  data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
+  data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
+  data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
+  data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+  data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
+  data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
+  data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
+  data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
+  data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
+  data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
+  data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
+  data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
+  data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
+  data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
+  data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
+  data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
 #ifdef USE_TLS_SRP
-  data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
-  data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+  data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
+  data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+  data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
+  data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
 #endif
 
-  if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
+  if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
+     &conn->ssl_config)) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto out;
+  }
+
+  if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
+                                    &conn->proxy_ssl_config)) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
   }
@@ -6117,7 +6681,7 @@ static CURLcode create_conn(struct Curl_easy *data,
   /* If we found a reusable connection, we may still want to
      open a new connection if we are pipelining. */
   if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
-    size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size;
+    size_t pipelen = conn_temp->send_pipe.size + conn_temp->recv_pipe.size;
     if(pipelen > 0) {
       infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
             conn_temp->connection_id, pipelen);
@@ -6149,7 +6713,9 @@ static CURLcode create_conn(struct Curl_easy *data,
     infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
           conn->connection_id,
           conn->bits.proxy?"proxy":"host",
-          conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
+          conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
+          conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
+                                       conn->host.dispname);
   }
   else {
     /* We have decided that we want a new connection. However, we may not
@@ -6275,12 +6841,11 @@ static CURLcode create_conn(struct Curl_easy *data,
    *************************************************************/
   result = resolve_server(data, conn, async);
 
-  out:
+out:
 
   free(options);
   free(passwd);
   free(user);
-  free(proxy);
   return result;
 }
 
@@ -6384,7 +6949,7 @@ CURLcode Curl_connect(struct Curl_easy *data,
 
   if(!result) {
     /* no error */
-    if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size)
+    if((*in_connect)->send_pipe.size || (*in_connect)->recv_pipe.size)
       /* pipelining */
       *protocol_done = TRUE;
     else if(!*asyncp) {
@@ -6449,7 +7014,6 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
   k->bytecount = 0;
 
   k->buf = data->state.buffer;
-  k->uploadbuf = data->state.uploadbuffer;
   k->hbufp = data->state.headerbuff;
   k->ignorebody=FALSE;
 
@@ -6473,7 +7037,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
 * Returns the family as a single bit protocol identifier.
 */
 
-unsigned int get_protocol_family(unsigned int protocol)
+static unsigned int get_protocol_family(unsigned int protocol)
 {
   unsigned int family;
 
diff --git a/Utilities/cmcurl/lib/url.h b/Utilities/cmcurl/lib/url.h
index 90d9db3..f13c8e6 100644
--- a/Utilities/cmcurl/lib/url.h
+++ b/Utilities/cmcurl/lib/url.h
@@ -67,6 +67,8 @@ void Curl_getoff_all_pipelines(struct Curl_easy *data,
 void Curl_close_connections(struct Curl_easy *data);
 
 #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
+#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
+                                             specified */
 
 CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
 
@@ -76,5 +78,16 @@ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
 void Curl_verboseconnect(struct connectdata *conn);
 #endif
 
+#define CONNECT_PROXY_SSL()\
+  (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
+  !conn->bits.proxy_ssl_connected[sockindex])
+
+#define CONNECT_FIRSTSOCKET_PROXY_SSL()\
+  (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
+  !conn->bits.proxy_ssl_connected[FIRSTSOCKET])
+
+#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\
+  (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
+  !conn->bits.proxy_ssl_connected[SECONDARYSOCKET])
 
 #endif /* HEADER_CURL_URL_H */
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 7c7bf1b..d4a4a98 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -136,8 +136,10 @@
 #undef realloc
 #endif /* USE_AXTLS */
 
-#ifdef USE_SCHANNEL
+#if defined(USE_SCHANNEL) || defined(USE_WINDOWS_SSPI)
 #include "curl_sspi.h"
+#endif
+#ifdef USE_SCHANNEL
 #include <schnlsp.h>
 #include <schannel.h>
 #endif
@@ -198,9 +200,12 @@
 #include <libssh2_sftp.h>
 #endif /* HAVE_LIBSSH2_H */
 
-/* Download buffer size, keep it fairly big for speed reasons */
-#undef BUFSIZE
-#define BUFSIZE CURL_MAX_WRITE_SIZE
+/* The upload buffer size, should not be smaller than CURL_MAX_WRITE_SIZE, as
+   it needs to hold a full buffer as could be sent in a write callback */
+#define UPLOAD_BUFSIZE CURL_MAX_WRITE_SIZE
+
+/* The "master buffer" is for HTTP pipelining */
+#define MASTERBUF_SIZE 16384
 
 /* Initial size of the buffer to store headers in, it'll be enlarged in case
    of need. */
@@ -311,11 +316,13 @@ struct ssl_connect_data {
   PRFileDesc *handle;
   char *client_nickname;
   struct Curl_easy *data;
-  struct curl_llist *obj_list;
+  struct curl_llist obj_list;
   PK11GenericObject *obj_clicert;
 #elif defined(USE_GSKIT)
   gsk_handle handle;
   int iocport;
+  int localfd;
+  int remotefd;
 #elif defined(USE_AXTLS)
   SSL_CTX* ssl_ctx;
   SSL*     ssl;
@@ -326,6 +333,11 @@ struct ssl_connect_data {
   size_t encdata_length, decdata_length;
   size_t encdata_offset, decdata_offset;
   unsigned char *encdata_buffer, *decdata_buffer;
+  /* encdata_is_incomplete: if encdata contains only a partial record that
+     can't be decrypted without another Curl_read_plain (that is, status is
+     SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
+     more bytes into encdata then set this back to false. */
+  bool encdata_is_incomplete;
   unsigned long req_flags, ret_flags;
   CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
   bool recv_sspi_close_notify; /* true if connection closed by close_notify */
@@ -341,28 +353,40 @@ struct ssl_connect_data {
 #endif
 };
 
-struct ssl_config_data {
+struct ssl_primary_config {
   long version;          /* what version the client wants to use */
-  long certverifyresult; /* result from the certificate verification */
-
+  long version_max;      /* max supported version the client wants to use*/
   bool verifypeer;       /* set TRUE if this is desired */
   bool verifyhost;       /* set TRUE if CN/SAN must match hostname */
   bool verifystatus;     /* set TRUE if certificate status must be checked */
   char *CApath;          /* certificate dir (doesn't work on windows) */
   char *CAfile;          /* certificate to verify peer against */
-  const char *CRLfile;   /* CRL to check certificate revocation */
-  const 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 */
   char *cipher_list;     /* list of ciphers to use */
-  size_t max_ssl_sessions; /* SSL session id cache size */
+  bool sessionid;        /* cache session IDs or not */
+};
+
+struct ssl_config_data {
+  struct ssl_primary_config primary;
+  bool enable_beast; /* especially allow this flaw for interoperability's
+                        sake*/
+  bool no_revoke;    /* disable SSL certificate revocation checks */
+  long certverifyresult; /* result from the certificate verification */
+  char *CRLfile;   /* CRL to check certificate revocation */
+  char *issuercert;/* optional issuer certificate filename */
   curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
   void *fsslctxp;        /* parameter for call back */
-  bool sessionid;        /* cache session IDs or not */
   bool certinfo;         /* gather lots of certificate info */
   bool falsestart;
 
+  char *cert; /* client certificate file name */
+  char *cert_type; /* format for certificate (default: PEM)*/
+  char *key; /* private key file name */
+  char *key_type; /* format for private key (default: PEM) */
+  char *key_passwd; /* plain text private key password */
+
 #ifdef USE_TLS_SRP
   char *username; /* TLS username (for, e.g., SRP) */
   char *password; /* TLS password (for, e.g., SRP) */
@@ -370,6 +394,10 @@ struct ssl_config_data {
 #endif
 };
 
+struct ssl_general_config {
+  size_t max_ssl_sessions; /* SSL session id cache size */
+};
+
 /* information stored about one single SSL session */
 struct curl_ssl_session {
   char *name;       /* host name for which this ID was used */
@@ -380,7 +408,7 @@ struct curl_ssl_session {
   long age;         /* just a number, the higher the more recent */
   int remote_port;  /* remote port */
   int conn_to_port; /* remote port for the connection (may be -1) */
-  struct ssl_config_data ssl_config; /* setup for this session */
+  struct ssl_primary_config ssl_config; /* setup for this session */
 };
 
 /* Struct used for Digest challenge-response authentication */
@@ -388,6 +416,7 @@ struct digestdata {
 #if defined(USE_WINDOWS_SSPI)
   BYTE *input_token;
   size_t input_token_len;
+  CtxtHandle *http_context;
 #else
   char *nonce;
   char *cnonce;
@@ -451,7 +480,7 @@ struct ntlmdata {
 #else
   unsigned int flags;
   unsigned char nonce[8];
-  void* target_info; /* TargetInfo received in the ntlm type-2 message */
+  void *target_info; /* TargetInfo received in the ntlm type-2 message */
   unsigned int target_info_len;
 #endif
 };
@@ -497,6 +526,7 @@ struct ConnectBits {
                         that overrides the port in the URL (remote port) */
   bool proxy; /* if set, this transfer is done through a proxy - any type */
   bool httpproxy;    /* if set, this transfer is done through a http proxy */
+  bool socksproxy;   /* if set, this transfer is done through a socks proxy */
   bool user_passwd;    /* do we use user+password for this connection? */
   bool proxy_user_passwd; /* user+password for the proxy? */
   bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6
@@ -531,6 +561,7 @@ struct ConnectBits {
   bool ftp_use_eprt;  /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
                          EPRT doesn't work we disable it for the forthcoming
                          requests */
+  bool ftp_use_data_ssl; /* Enabled SSL for the data connection */
   bool netrc;         /* name+password provided by netrc */
   bool userpwd_in_url; /* name+password found in url */
   bool stream_was_rewound; /* Indicates that the stream was rewound after a
@@ -547,6 +578,9 @@ struct ConnectBits {
   bool tcp_fastopen; /* use TCP Fast Open */
   bool tls_enable_npn;  /* TLS NPN extension? */
   bool tls_enable_alpn; /* TLS ALPN extension? */
+  bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
+                                  is complete */
+  bool socksproxy_connecting; /* connecting through a socks proxy */
 };
 
 struct hostname {
@@ -687,7 +721,6 @@ struct SingleRequest {
   long bodywrites;
 
   char *buf;
-  char *uploadbuf;
   curl_socket_t maxfd;
 
   int keepon;
@@ -732,7 +765,7 @@ struct SingleRequest {
  */
 
 struct Curl_handler {
-  const char * scheme;        /* URL scheme name. */
+  const char *scheme;        /* URL scheme name. */
 
   /* Complement to setup_connection_internals(). */
   CURLcode (*setup_connection)(struct connectdata *);
@@ -820,6 +853,8 @@ struct Curl_handler {
                                           request instead of per connection */
 #define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */
 #define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */
+#define PROTOPT_URLOPTIONS (1<<10) /* allow options part in the userinfo field
+                                      of the URL */
 
 /* return the count of bytes sent, or -1 on error */
 typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
@@ -849,6 +884,14 @@ struct postponed_data {
 };
 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
 
+struct proxy_info {
+  struct hostname host;
+  long port;
+  curl_proxytype proxytype; /* what kind of proxy that is in use */
+  char *user;    /* proxy user name string, allocated */
+  char *passwd;  /* proxy password string, allocated */
+};
+
 /*
  * The connectdata struct contains all fields and variables that should be
  * unique for an entire connection.
@@ -859,6 +902,8 @@ struct connectdata {
      connection is used! */
   struct Curl_easy *data;
 
+  struct curl_llist_element bundle_node; /* conncache */
+
   /* chunk is for HTTP chunked encoding, but is in the general connectdata
      struct only because we can do just about any protocol through a HTTP proxy
      and a HTTP proxy may in fact respond using chunked encoding */
@@ -898,14 +943,19 @@ struct connectdata {
   int socktype;  /* SOCK_STREAM or SOCK_DGRAM */
 
   struct hostname host;
+  char *secondaryhostname; /* secondary socket host name (ftp) */
   struct hostname conn_to_host; /* the host to connect to. valid only if
                                    bits.conn_to_host is set */
-  struct hostname proxy;
+
+  struct proxy_info socks_proxy;
+  struct proxy_info http_proxy;
 
   long port;       /* which port to use locally */
   int remote_port; /* the remote port, not the proxy port! */
   int conn_to_port; /* the remote port to connect to. valid only if
                        bits.conn_to_port is set */
+  unsigned short secondary_port; /* secondary socket remote port to connect to
+                                    (ftp) */
 
   /* 'primary_ip' and 'primary_port' get filled with peer's numerical
      ip address and port number whenever an outgoing connection is
@@ -930,10 +980,6 @@ struct connectdata {
 
   char *oauth_bearer; /* bearer token for OAuth 2.0, allocated */
 
-  char *proxyuser;    /* proxy user name string, allocated */
-  char *proxypasswd;  /* proxy password string, allocated */
-  curl_proxytype proxytype; /* what kind of proxy that is in use */
-
   int httpversion;        /* the HTTP version*10 reported by the server */
   int rtspversion;        /* the RTSP version*10 reported by the server */
 
@@ -951,7 +997,9 @@ struct connectdata {
   struct postponed_data postponed[2]; /* two buffers for two sockets */
 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
   struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
-  struct ssl_config_data ssl_config;
+  struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */
+  struct ssl_primary_config ssl_config;
+  struct ssl_primary_config proxy_ssl_config;
   bool tls_upgraded;
 
   struct ConnectBits bits;    /* various state-flags for this connection */
@@ -962,8 +1010,8 @@ struct connectdata {
   struct timeval connecttime;
   /* The two fields below get set in Curl_connecthost */
   int num_addr; /* number of addresses to try to connect to */
-  long timeoutms_per_addr; /* how long time in milliseconds to spend on
-                              trying to connect to each IP address */
+  time_t timeoutms_per_addr; /* how long time in milliseconds to spend on
+                                trying to connect to each IP address */
 
   const struct Curl_handler *handler; /* Connection's protocol handler */
   const struct Curl_handler *given;   /* The protocol first given */
@@ -1016,11 +1064,11 @@ struct connectdata {
                               handle */
   bool writechannel_inuse; /* whether the write channel is in use by an easy
                               handle */
-  struct curl_llist *send_pipe; /* List of handles waiting to
-                                   send on this pipeline */
-  struct curl_llist *recv_pipe; /* List of handles waiting to read
-                                   their responses on this pipeline */
-  char* master_buffer; /* The master buffer allocated on-demand;
+  struct curl_llist send_pipe; /* List of handles waiting to send on this
+                                  pipeline */
+  struct curl_llist recv_pipe; /* List of handles waiting to read their
+                                  responses on this pipeline */
+  char *master_buffer; /* The master buffer allocated on-demand;
                           used for pipelining. */
   size_t read_pos; /* Current read position in the master buffer */
   size_t buf_len; /* Length of the buffer?? */
@@ -1041,8 +1089,8 @@ struct connectdata {
   /* used for communication with Samba's winbind daemon helper ntlm_auth */
   curl_socket_t ntlm_auth_hlpr_socket;
   pid_t ntlm_auth_hlpr_pid;
-  char* challenge_header;
-  char* response_header;
+  char *challenge_header;
+  char *response_header;
 #endif
 #endif
 
@@ -1078,9 +1126,6 @@ struct connectdata {
   int socks5_gssapi_enctype;
 #endif
 
-  bool verifypeer;
-  bool verifyhost;
-
   /* When this connection is created, store the conditions for the local end
      bind. This is stored before the actual bind and before any connection is
      made and will serve the purpose of being used for comparison reasons so
@@ -1099,13 +1144,19 @@ struct connectdata {
   struct connectbundle *bundle; /* The bundle we are member of */
 
   int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
+  char *connect_buffer; /* for CONNECT business */
+
+#ifdef USE_UNIX_SOCKETS
+  char *unix_domain_socket;
+  bool abstract_unix_socket;
+#endif
 };
 
 /* The end of connectdata. */
 
 /*
  * Struct to keep statistical and informational data.
- * All variables in this struct must be reset in Curl_initinfo().
+ * All variables in this struct must be initialized/reset in Curl_initinfo().
  */
 struct PureInfo {
   int httpcode;  /* Recent HTTP, FTP, RTSP or SMTP response code */
@@ -1139,6 +1190,9 @@ struct PureInfo {
   char conn_local_ip[MAX_IPADR_LEN];
   long conn_local_port;
 
+  const char *conn_scheme;
+  unsigned int conn_protocol;
+
   struct curl_certinfo certs; /* info about the certs, only populated in
                                  OpenSSL builds. Asked for with
                                  CURLOPT_CERTINFO / CURLINFO_CERTINFO */
@@ -1146,8 +1200,8 @@ struct PureInfo {
 
 
 struct Progress {
-  long lastshow; /* time() of the last displayed progress meter or NULL to
-                    force redraw at next call */
+  time_t lastshow; /* time() of the last displayed progress meter or NULL to
+                      force redraw at next call */
   curl_off_t size_dl; /* total expected size */
   curl_off_t size_ul; /* total expected size */
   curl_off_t downloaded; /* transferred so far */
@@ -1236,12 +1290,54 @@ struct auth {
                           this resource */
   bool done;  /* TRUE when the auth phase is done and ready to do the *actual*
                  request */
-  bool multi; /* TRUE if this is not yet authenticated but within the auth
-                 multipass negotiation */
+  bool multipass; /* TRUE if this is not yet authenticated but within the
+                     auth multipass negotiation */
   bool iestyle; /* TRUE if digest should be done IE-style or FALSE if it should
                    be RFC compliant */
 };
 
+struct Curl_http2_dep {
+  struct Curl_http2_dep *next;
+  struct Curl_easy *data;
+};
+
+/*
+ * This struct is for holding data that was attemped to get sent to the user's
+ * callback but is held due to pausing. One instance per type (BOTH, HEADER,
+ * BODY).
+ */
+struct tempbuf {
+  char *buf;  /* allocated buffer to keep data in when a write callback
+                 returns to make the connection paused */
+  size_t len; /* size of the 'tempwrite' allocated buffer */
+  int type;   /* type of the 'tempwrite' buffer as a bitmask that is used with
+                 Curl_client_write() */
+};
+
+/* Timers */
+typedef enum {
+  EXPIRE_100_TIMEOUT,
+  EXPIRE_ASYNC_NAME,
+  EXPIRE_CONNECTTIMEOUT,
+  EXPIRE_DNS_PER_NAME,
+  EXPIRE_HAPPY_EYEBALLS,
+  EXPIRE_MULTI_PENDING,
+  EXPIRE_RUN_NOW,
+  EXPIRE_SPEEDCHECK,
+  EXPIRE_TIMEOUT,
+  EXPIRE_TOOFAST,
+  EXPIRE_LAST /* not an actual timer, used as a marker only */
+} expire_id;
+
+/*
+ * One instance for each timeout an easy handle can set.
+ */
+struct time_node {
+  struct curl_llist_element list;
+  struct timeval time;
+  expire_id eid;
+};
+
 struct UrlState {
 
   /* Points to the connection cache */
@@ -1260,9 +1356,9 @@ struct UrlState {
   char *headerbuff; /* allocated buffer to store headers in */
   size_t headersize;   /* size of the allocation */
 
-  char buffer[BUFSIZE+1]; /* download buffer */
-  char uploadbuffer[BUFSIZE+1]; /* upload buffer */
-  curl_off_t current_speed;  /* the ProgressShow() funcion sets this,
+  char *buffer; /* download buffer */
+  char uploadbuffer[UPLOAD_BUFSIZE+1]; /* upload buffer */
+  curl_off_t current_speed;  /* the ProgressShow() function sets this,
                                 bytes / second */
   bool this_is_a_follow; /* this is a followed Location: request */
 
@@ -1275,12 +1371,9 @@ struct UrlState {
   int first_remote_port; /* remote port of the first (not followed) request */
   struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
   long sessionage;                  /* number of the most recent session */
-  char *tempwrite;      /* allocated buffer to keep data in when a write
-                           callback returns to make the connection paused */
-  size_t tempwritesize; /* size of the 'tempwrite' allocated buffer */
-  int tempwritetype;    /* type of the 'tempwrite' buffer as a bitmask that is
-                           used with Curl_client_write() */
-  char *scratch; /* huge buffer[BUFSIZE*2] when doing upload CRLF replacing */
+  unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
+  struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */
+  char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
   bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
                     This must be set to FALSE every time _easy_perform() is
                     called. */
@@ -1312,7 +1405,8 @@ struct UrlState {
 #endif /* USE_OPENSSL */
   struct timeval expiretime; /* set this with Curl_expire() only */
   struct Curl_tree timenode; /* for the splay stuff */
-  struct curl_llist *timeoutlist; /* list of pending timeouts */
+  struct curl_llist timeoutlist; /* list of pending timeouts */
+  struct time_node expires[EXPIRE_LAST]; /* nodes for each expire type */
 
   /* a place to store the most recently set FTP entrypath */
   char *most_recent_ftp_entrypath;
@@ -1402,8 +1496,10 @@ struct DynamicStatic {
 struct Curl_multi;    /* declared and used only in multi.c */
 
 enum dupstring {
-  STRING_CERT,            /* client certificate file name */
-  STRING_CERT_TYPE,       /* format for certificate (default: PEM)*/
+  STRING_CERT_ORIG,       /* client certificate file name */
+  STRING_CERT_PROXY,      /* client certificate file name */
+  STRING_CERT_TYPE_ORIG,  /* format for certificate (default: PEM)*/
+  STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/
   STRING_COOKIE,          /* HTTP cookie string to send */
   STRING_COOKIEJAR,       /* dump all cookies to this file */
   STRING_CUSTOMREQUEST,   /* HTTP/FTP/RTSP request/method to use */
@@ -1413,25 +1509,35 @@ enum dupstring {
   STRING_FTP_ACCOUNT,     /* ftp account data */
   STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
   STRING_FTPPORT,         /* port to send with the FTP PORT command */
-  STRING_KEY,             /* private key file name */
-  STRING_KEY_PASSWD,      /* plain text private key password */
-  STRING_KEY_TYPE,        /* format for private key (default: PEM) */
+  STRING_KEY_ORIG,        /* private key file name */
+  STRING_KEY_PROXY,       /* private key file name */
+  STRING_KEY_PASSWD_ORIG, /* plain text private key password */
+  STRING_KEY_PASSWD_PROXY, /* plain text private key password */
+  STRING_KEY_TYPE_ORIG,   /* format for private key (default: PEM) */
+  STRING_KEY_TYPE_PROXY,  /* format for private key (default: PEM) */
   STRING_KRB_LEVEL,       /* krb security level */
   STRING_NETRC_FILE,      /* if not NULL, use this instead of trying to find
                              $HOME/.netrc */
   STRING_PROXY,           /* proxy to use */
+  STRING_PRE_PROXY,       /* pre socks proxy to use */
   STRING_SET_RANGE,       /* range, if used */
   STRING_SET_REFERER,     /* custom string for the HTTP referer field */
   STRING_SET_URL,         /* what original URL to work on */
-  STRING_SSL_CAPATH,      /* CA directory name (doesn't work on windows) */
-  STRING_SSL_CAFILE,      /* certificate file to verify peer against */
-  STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */
-  STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
+  STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */
+  STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */
+  STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */
+  STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */
+  STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */
+  STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */
+  STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */
+  STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */
   STRING_SSL_EGDSOCKET,   /* path to file containing the EGD daemon socket */
   STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
   STRING_USERAGENT,       /* User-Agent string */
-  STRING_SSL_CRLFILE,     /* crl file to check certificate */
-  STRING_SSL_ISSUERCERT,  /* issuer cert file to check certificate */
+  STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */
+  STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
+  STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */
+  STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */
   STRING_USERNAME,        /* <username>, if used */
   STRING_PASSWORD,        /* <password>, if used */
   STRING_OPTIONS,         /* <options>, if used */
@@ -1459,8 +1565,10 @@ enum dupstring {
   STRING_MAIL_AUTH,
 
 #ifdef USE_TLS_SRP
-  STRING_TLSAUTH_USERNAME,      /* TLS auth <username> */
-  STRING_TLSAUTH_PASSWORD,      /* TLS auth <password> */
+  STRING_TLSAUTH_USERNAME_ORIG,  /* TLS auth <username> */
+  STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth <username> */
+  STRING_TLSAUTH_PASSWORD_ORIG,  /* TLS auth <password> */
+  STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth <password> */
 #endif
   STRING_BEARER,                /* <bearer>, if used */
 #ifdef USE_UNIX_SOCKETS
@@ -1524,10 +1632,10 @@ struct UserDefined {
   curl_opensocket_callback fopensocket; /* function for checking/translating
                                            the address and opening the
                                            socket */
-  void* opensocket_client;
+  void *opensocket_client;
   curl_closesocket_callback fclosesocket; /* function for closing the
                                              socket */
-  void* closesocket_client;
+  void *closesocket_client;
 
   void *seek_client;    /* pointer to pass to the seek callback */
   /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */
@@ -1578,6 +1686,8 @@ struct UserDefined {
   long httpversion; /* when non-zero, a specific HTTP version requested to
                        be used in the library's request(s) */
   struct ssl_config_data ssl;  /* user defined SSL stuff */
+  struct ssl_config_data proxy_ssl;  /* user defined SSL stuff for proxy */
+  struct ssl_general_config general_ssl; /* general user defined SSL stuff */
   curl_proxytype proxytype; /* what kind of proxy that is in use */
   long dns_cache_timeout; /* DNS cache timeout */
   long buffer_size;      /* size of receive buffer to use */
@@ -1642,9 +1752,6 @@ struct UserDefined {
   bool ftp_skip_ip;      /* skip the IP address the FTP server passes on to
                             us */
   bool connect_only;     /* make connection, let application use the socket */
-  bool ssl_enable_beast; /* especially allow this flaw for interoperability's
-                            sake*/
-  bool ssl_no_revoke;    /* disable SSL certificate revocation checks */
   long ssh_auth_types;   /* allowed SSH auth types */
   bool http_te_skip;     /* pass the raw body data to the user, even when
                             transfer-encoded (chunked, compressed) */
@@ -1691,10 +1798,16 @@ struct UserDefined {
   bool pipewait;        /* wait for pipe/multiplex status before starting a
                            new connection */
   long expect_100_timeout; /* in milliseconds */
+  bool suppress_connect_headers;  /* suppress proxy CONNECT response headers
+                                     from user callbacks */
 
   struct Curl_easy *stream_depends_on;
   bool stream_depends_e; /* set or don't set the Exclusive bit */
   int stream_weight;
+
+  struct Curl_http2_dep *stream_dependents;
+
+  bool abstract_unix_socket;
 };
 
 struct Names {
@@ -1723,6 +1836,8 @@ struct Curl_easy {
   struct Curl_easy *prev;
 
   struct connectdata *easy_conn;     /* the "unit's" connection */
+  struct curl_llist_element connect_queue;
+  struct curl_llist_element pipeline_queue;
 
   CURLMstate mstate;  /* the handle's state */
   CURLcode result;   /* previous result */
diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c
index 6df419a..a761ae7 100644
--- a/Utilities/cmcurl/lib/vauth/cleartext.c
+++ b/Utilities/cmcurl/lib/vauth/cleartext.c
@@ -66,16 +66,27 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
   char *plainauth;
   size_t ulen;
   size_t plen;
+  size_t plainlen;
 
+  *outlen = 0;
+  *outptr = NULL;
   ulen = strlen(userp);
   plen = strlen(passwdp);
 
-  plainauth = malloc(2 * ulen + plen + 2);
-  if(!plainauth) {
-    *outlen = 0;
-    *outptr = NULL;
+  /* Compute binary message length, checking for overflows. */
+  plainlen = 2 * ulen;
+  if(plainlen < ulen)
+    return CURLE_OUT_OF_MEMORY;
+  plainlen += plen;
+  if(plainlen < plen)
+    return CURLE_OUT_OF_MEMORY;
+  plainlen += 2;
+  if(plainlen < 2)
+    return CURLE_OUT_OF_MEMORY;
+
+  plainauth = malloc(plainlen);
+  if(!plainauth)
     return CURLE_OUT_OF_MEMORY;
-  }
 
   /* Calculate the reply */
   memcpy(plainauth, userp, ulen);
@@ -85,8 +96,7 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
   memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
 
   /* Base64 encode the reply */
-  result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
-                              outlen);
+  result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen);
   free(plainauth);
 
   return result;
diff --git a/Utilities/cmcurl/lib/vauth/digest.c b/Utilities/cmcurl/lib/vauth/digest.c
index 0a11a30..185098e 100644
--- a/Utilities/cmcurl/lib/vauth/digest.c
+++ b/Utilities/cmcurl/lib/vauth/digest.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -40,6 +40,7 @@
 #include "strcase.h"
 #include "non-ascii.h" /* included for Curl_convert_... prototypes */
 #include "curl_printf.h"
+#include "rand.h"
 
 /* The last #include files should be: */
 #include "curl_memory.h"
@@ -59,7 +60,7 @@
    what ultimately goes over the network.
 */
 #define CURL_OUTPUT_DIGEST_CONV(a, b) \
-  result = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \
+  result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \
   if(result) { \
     free(b); \
     return result; \
@@ -204,7 +205,7 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value)
 {
   char *tmp;
   char *token;
-  char *tok_buf;
+  char *tok_buf = NULL;
 
   /* Initialise the output */
   *value = 0;
@@ -236,7 +237,7 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value)
  * auth_decode_digest_md5_message()
  *
  * This is used internally to decode an already encoded DIGEST-MD5 challenge
- * message into the seperate attributes.
+ * message into the separate attributes.
  *
  * Parameters:
  *
@@ -359,13 +360,12 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
   char qop_options[64];
   int qop_values;
   char cnonce[33];
-  unsigned int entropy[4];
   char nonceCount[] = "00000001";
   char method[]     = "AUTHENTICATE";
   char qop[]        = DIGEST_QOP_VALUE_STRING_AUTH;
   char *spn         = NULL;
 
-  /* Decode the challange message */
+  /* Decode the challenge message */
   result = auth_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
                                           realm, sizeof(realm),
                                           algorithm, sizeof(algorithm),
@@ -386,15 +386,10 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
   if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
     return CURLE_BAD_CONTENT_ENCODING;
 
-  /* Generate 16 bytes of random data */
-  entropy[0] = Curl_rand(data);
-  entropy[1] = Curl_rand(data);
-  entropy[2] = Curl_rand(data);
-  entropy[3] = Curl_rand(data);
-
-  /* Convert the random data into a 32 byte hex string */
-  snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
-           entropy[0], entropy[1], entropy[2], entropy[3]);
+  /* Generate 32 random hex chars, 32 bytes + 1 zero termination */
+  result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce));
+  if(result)
+    return result;
 
   /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
   ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
@@ -502,7 +497,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
 /*
  * Curl_auth_decode_digest_http_message()
  *
- * This is used to decode a HTTP DIGEST challenge message into the seperate
+ * This is used to decode a HTTP DIGEST challenge message into the separate
  * attributes.
  *
  * Parameters:
@@ -563,7 +558,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
           return CURLE_OUT_OF_MEMORY;
       }
       else if(strcasecompare(value, "qop")) {
-        char *tok_buf;
+        char *tok_buf = NULL;
         /* Tokenize the list and choose auth if possible, use a temporary
            clone of the buffer since strtok_r() ruins it */
         tmp = strdup(content);
@@ -684,9 +679,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
     digest->nc = 1;
 
   if(!digest->cnonce) {
-    snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
-             Curl_rand(data), Curl_rand(data),
-             Curl_rand(data), Curl_rand(data));
+    result = Curl_rand_hex(data, (unsigned char *)cnoncebuf,
+                           sizeof(cnoncebuf));
+    if(result)
+      return result;
 
     result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
                                 &cnonce, &cnonce_sz);
diff --git a/Utilities/cmcurl/lib/vauth/digest_sspi.c b/Utilities/cmcurl/lib/vauth/digest_sspi.c
index 29526fc..0bd9444 100644
--- a/Utilities/cmcurl/lib/vauth/digest_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/digest_sspi.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2014 - 2016, Steve Holme, <steve_holme at hotmail.com>.
- * Copyright (C) 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2015 - 2017, Daniel Stenberg, <daniel at 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
@@ -320,7 +320,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
 /*
  * Curl_auth_decode_digest_http_message()
  *
- * This is used to decode a HTTP DIGEST challenge message into the seperate
+ * This is used to decode a HTTP DIGEST challenge message into the separate
  * attributes.
  *
  * Parameters:
@@ -335,13 +335,44 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
 {
   size_t chlglen = strlen(chlg);
 
-  /* We had an input token before and we got another one now. This means we
-     provided bad credentials in the previous request. */
-  if(digest->input_token)
-    return CURLE_BAD_CONTENT_ENCODING;
+  /* We had an input token before so if there's another one now that means we
+     provided bad credentials in the previous request or it's stale. */
+  if(digest->input_token) {
+    bool stale = false;
+    const char *p = chlg;
+
+    /* Check for the 'stale' directive */
+    for(;;) {
+      char value[DIGEST_MAX_VALUE_LENGTH];
+      char content[DIGEST_MAX_CONTENT_LENGTH];
+
+      while(*p && ISSPACE(*p))
+        p++;
+
+      if(!Curl_auth_digest_get_pair(p, value, content, &p))
+        break;
+
+      if(Curl_strcasecompare(value, "stale")
+         && Curl_strcasecompare(content, "true")) {
+        stale = true;
+        break;
+      }
+
+      while(*p && ISSPACE(*p))
+        p++;
+
+      if(',' == *p)
+        p++;
+    }
+
+    if(stale)
+      Curl_auth_digest_cleanup(digest);
+    else
+      return CURLE_LOGIN_DENIED;
+  }
 
-  /* Simply store the challenge for use later */
-  digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen);
+  /* Store the challenge for use later */
+  digest->input_token = (BYTE *) Curl_memdup(chlg, chlglen + 1);
   if(!digest->input_token)
     return CURLE_OUT_OF_MEMORY;
 
@@ -379,21 +410,13 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
                                               char **outptr, size_t *outlen)
 {
   size_t token_max;
-  CredHandle credentials;
-  CtxtHandle context;
   char *resp;
   BYTE *output_token;
+  size_t output_token_len = 0;
   PSecPkgInfo SecurityPackage;
-  SEC_WINNT_AUTH_IDENTITY identity;
-  SEC_WINNT_AUTH_IDENTITY *p_identity;
-  SecBuffer chlg_buf[3];
-  SecBuffer resp_buf;
+  SecBuffer chlg_buf[5];
   SecBufferDesc chlg_desc;
-  SecBufferDesc resp_desc;
   SECURITY_STATUS status;
-  unsigned long attrs;
-  TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
-  TCHAR *spn;
 
   (void) data;
 
@@ -408,123 +431,168 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
   /* Release the package buffer as it is not required anymore */
   s_pSecFn->FreeContextBuffer(SecurityPackage);
 
-  if(userp && *userp) {
-    /* Populate our identity structure */
-    if(Curl_create_sspi_identity(userp, passwdp, &identity))
-      return CURLE_OUT_OF_MEMORY;
-
-    /* Populate our identity domain */
-    if(Curl_override_sspi_http_realm((const char*) digest->input_token,
-                                     &identity))
-      return CURLE_OUT_OF_MEMORY;
+  /* Allocate the output buffer according to the max token size as indicated
+     by the security package */
+  output_token = malloc(token_max);
+  if(!output_token) {
+    return CURLE_OUT_OF_MEMORY;
+  }
 
-    /* Allow proper cleanup of the identity structure */
-    p_identity = &identity;
+  if(digest->http_context) {
+    chlg_desc.ulVersion    = SECBUFFER_VERSION;
+    chlg_desc.cBuffers     = 5;
+    chlg_desc.pBuffers     = chlg_buf;
+    chlg_buf[0].BufferType = SECBUFFER_TOKEN;
+    chlg_buf[0].pvBuffer   = NULL;
+    chlg_buf[0].cbBuffer   = 0;
+    chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS;
+    chlg_buf[1].pvBuffer   = (void *) request;
+    chlg_buf[1].cbBuffer   = curlx_uztoul(strlen((const char *) request));
+    chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS;
+    chlg_buf[2].pvBuffer   = (void *) uripath;
+    chlg_buf[2].cbBuffer   = curlx_uztoul(strlen((const char *) uripath));
+    chlg_buf[3].BufferType = SECBUFFER_PKG_PARAMS;
+    chlg_buf[3].pvBuffer   = NULL;
+    chlg_buf[3].cbBuffer   = 0;
+    chlg_buf[4].BufferType = SECBUFFER_PADDING;
+    chlg_buf[4].pvBuffer   = output_token;
+    chlg_buf[4].cbBuffer   = curlx_uztoul(token_max);
+
+    status = s_pSecFn->MakeSignature(digest->http_context, 0, &chlg_desc, 0);
+    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",
+            (long)status);
+      s_pSecFn->DeleteSecurityContext(digest->http_context);
+      Curl_safefree(digest->http_context);
+    }
   }
-  else
-    /* Use the current Windows user */
-    p_identity = NULL;
 
-  /* Acquire our credentials handle */
-  status = s_pSecFn->AcquireCredentialsHandle(NULL,
-                                              (TCHAR *) TEXT(SP_NAME_DIGEST),
-                                              SECPKG_CRED_OUTBOUND, NULL,
-                                              p_identity, NULL, NULL,
-                                              &credentials, &expiry);
-  if(status != SEC_E_OK) {
-    Curl_sspi_free_identity(p_identity);
+  if(!digest->http_context) {
+    CredHandle credentials;
+    SEC_WINNT_AUTH_IDENTITY identity;
+    SEC_WINNT_AUTH_IDENTITY *p_identity;
+    SecBuffer resp_buf;
+    SecBufferDesc resp_desc;
+    unsigned long attrs;
+    TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
+    TCHAR *spn;
+
+    if(userp && *userp) {
+      /* Populate our identity structure */
+      if(Curl_create_sspi_identity(userp, passwdp, &identity)) {
+        free(output_token);
+        return CURLE_OUT_OF_MEMORY;
+      }
 
-    return CURLE_LOGIN_DENIED;
-  }
+      /* Populate our identity domain */
+      if(Curl_override_sspi_http_realm((const char *) digest->input_token,
+                                       &identity)) {
+        free(output_token);
+        return CURLE_OUT_OF_MEMORY;
+      }
 
-  /* Allocate the output buffer according to the max token size as indicated
-     by the security package */
-  output_token = malloc(token_max);
-  if(!output_token) {
-    s_pSecFn->FreeCredentialsHandle(&credentials);
+      /* Allow proper cleanup of the identity structure */
+      p_identity = &identity;
+    }
+    else
+      /* Use the current Windows user */
+      p_identity = NULL;
+
+    /* Acquire our credentials handle */
+    status = s_pSecFn->AcquireCredentialsHandle(NULL,
+                                                (TCHAR *) TEXT(SP_NAME_DIGEST),
+                                                SECPKG_CRED_OUTBOUND, NULL,
+                                                p_identity, NULL, NULL,
+                                                &credentials, &expiry);
+    if(status != SEC_E_OK) {
+      Curl_sspi_free_identity(p_identity);
+      free(output_token);
 
-    Curl_sspi_free_identity(p_identity);
+      return CURLE_LOGIN_DENIED;
+    }
 
-    return CURLE_OUT_OF_MEMORY;
-  }
+    /* Setup the challenge "input" security buffer if present */
+    chlg_desc.ulVersion    = SECBUFFER_VERSION;
+    chlg_desc.cBuffers     = 3;
+    chlg_desc.pBuffers     = chlg_buf;
+    chlg_buf[0].BufferType = SECBUFFER_TOKEN;
+    chlg_buf[0].pvBuffer   = digest->input_token;
+    chlg_buf[0].cbBuffer   = curlx_uztoul(digest->input_token_len);
+    chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS;
+    chlg_buf[1].pvBuffer   = (void *) request;
+    chlg_buf[1].cbBuffer   = curlx_uztoul(strlen((const char *) request));
+    chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS;
+    chlg_buf[2].pvBuffer   = NULL;
+    chlg_buf[2].cbBuffer   = 0;
+
+    /* Setup the response "output" security buffer */
+    resp_desc.ulVersion = SECBUFFER_VERSION;
+    resp_desc.cBuffers  = 1;
+    resp_desc.pBuffers  = &resp_buf;
+    resp_buf.BufferType = SECBUFFER_TOKEN;
+    resp_buf.pvBuffer   = output_token;
+    resp_buf.cbBuffer   = curlx_uztoul(token_max);
+
+    spn = Curl_convert_UTF8_to_tchar((char *) uripath);
+    if(!spn) {
+      s_pSecFn->FreeCredentialsHandle(&credentials);
+
+      Curl_sspi_free_identity(p_identity);
+      free(output_token);
 
-  /* Setup the challenge "input" security buffer if present */
-  chlg_desc.ulVersion    = SECBUFFER_VERSION;
-  chlg_desc.cBuffers     = 3;
-  chlg_desc.pBuffers     = chlg_buf;
-  chlg_buf[0].BufferType = SECBUFFER_TOKEN;
-  chlg_buf[0].pvBuffer   = digest->input_token;
-  chlg_buf[0].cbBuffer   = curlx_uztoul(digest->input_token_len);
-  chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS;
-  chlg_buf[1].pvBuffer   = (void *) request;
-  chlg_buf[1].cbBuffer   = curlx_uztoul(strlen((const char *) request));
-  chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS;
-  chlg_buf[2].pvBuffer   = NULL;
-  chlg_buf[2].cbBuffer   = 0;
+      return CURLE_OUT_OF_MEMORY;
+    }
 
-  /* Setup the response "output" security buffer */
-  resp_desc.ulVersion = SECBUFFER_VERSION;
-  resp_desc.cBuffers  = 1;
-  resp_desc.pBuffers  = &resp_buf;
-  resp_buf.BufferType = SECBUFFER_TOKEN;
-  resp_buf.pvBuffer   = output_token;
-  resp_buf.cbBuffer   = curlx_uztoul(token_max);
+    /* Allocate our new context handle */
+    digest->http_context = calloc(1, sizeof(CtxtHandle));
+    if(!digest->http_context)
+      return CURLE_OUT_OF_MEMORY;
 
-  spn = Curl_convert_UTF8_to_tchar((char *) uripath);
-  if(!spn) {
-    s_pSecFn->FreeCredentialsHandle(&credentials);
+    /* Generate our response message */
+    status = s_pSecFn->InitializeSecurityContext(&credentials, NULL,
+                                                 spn,
+                                                 ISC_REQ_USE_HTTP_STYLE, 0, 0,
+                                                 &chlg_desc, 0,
+                                                 digest->http_context,
+                                                 &resp_desc, &attrs, &expiry);
+    Curl_unicodefree(spn);
+
+    if(status == SEC_I_COMPLETE_NEEDED ||
+       status == SEC_I_COMPLETE_AND_CONTINUE)
+      s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
+    else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+      s_pSecFn->FreeCredentialsHandle(&credentials);
+
+      Curl_sspi_free_identity(p_identity);
+      free(output_token);
 
-    Curl_sspi_free_identity(p_identity);
-    free(output_token);
+      Curl_safefree(digest->http_context);
 
-    return CURLE_OUT_OF_MEMORY;
-  }
+      return CURLE_OUT_OF_MEMORY;
+    }
 
-  /* Generate our reponse message */
-  status = s_pSecFn->InitializeSecurityContext(&credentials, NULL,
-                                               spn,
-                                               ISC_REQ_USE_HTTP_STYLE, 0, 0,
-                                               &chlg_desc, 0, &context,
-                                               &resp_desc, &attrs, &expiry);
-  Curl_unicodefree(spn);
+    output_token_len = resp_buf.cbBuffer;
 
-  if(status == SEC_I_COMPLETE_NEEDED ||
-     status == SEC_I_COMPLETE_AND_CONTINUE)
-    s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
-  else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
     s_pSecFn->FreeCredentialsHandle(&credentials);
-
     Curl_sspi_free_identity(p_identity);
-    free(output_token);
-
-    return CURLE_OUT_OF_MEMORY;
   }
 
-  resp = malloc(resp_buf.cbBuffer + 1);
+  resp = malloc(output_token_len + 1);
   if(!resp) {
-    s_pSecFn->DeleteSecurityContext(&context);
-    s_pSecFn->FreeCredentialsHandle(&credentials);
-
-    Curl_sspi_free_identity(p_identity);
     free(output_token);
 
     return CURLE_OUT_OF_MEMORY;
   }
 
-  /* Copy the generated reponse */
-  memcpy(resp, resp_buf.pvBuffer, resp_buf.cbBuffer);
-  resp[resp_buf.cbBuffer] = 0x00;
+  /* Copy the generated response */
+  memcpy(resp, output_token, output_token_len);
+  resp[output_token_len] = 0;
 
   /* Return the response */
   *outptr = resp;
-  *outlen = resp_buf.cbBuffer;
-
-  /* Free our handles */
-  s_pSecFn->DeleteSecurityContext(&context);
-  s_pSecFn->FreeCredentialsHandle(&credentials);
-
-  /* Free the identity structure */
-  Curl_sspi_free_identity(p_identity);
+  *outlen = output_token_len;
 
   /* Free the response buffer */
   free(output_token);
@@ -549,6 +617,12 @@ void Curl_auth_digest_cleanup(struct digestdata *digest)
 
   /* Reset any variables */
   digest->input_token_len = 0;
+
+  /* Delete security context */
+  if(digest->http_context) {
+    s_pSecFn->DeleteSecurityContext(digest->http_context);
+    Curl_safefree(digest->http_context);
+  }
 }
 
 #endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_CRYPTO_AUTH */
diff --git a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
index c754fae..560ecc5 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2014 - 2016, Steve Holme, <steve_holme at hotmail.com>.
+ * Copyright (C) 2014 - 2017, Steve Holme, <steve_holme at hotmail.com>.
  * Copyright (C) 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
@@ -68,7 +68,7 @@ bool Curl_auth_is_gssapi_supported(void)
  * passdwp     [in]     - The user's password.
  * service     [in]     - The service type such as http, smtp, pop or imap.
  * host        [in[     - The host name.
- * mutual_auth [in]     - Flag specifing whether or not mutual authentication
+ * mutual_auth [in]     - Flag specifying whether or not mutual authentication
  *                        is enabled.
  * chlg64      [in]     - Pointer to the optional base64 encoded challenge
  *                        message.
diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
index 151794e..1b4cef4 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2014 - 2016, Steve Holme, <steve_holme at hotmail.com>.
+ * Copyright (C) 2014 - 2017, Steve Holme, <steve_holme at hotmail.com>.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -74,7 +74,7 @@ bool Curl_auth_is_gssapi_supported(void)
  * passdwp     [in]     - The user's password.
  * service     [in]     - The service type such as http, smtp, pop or imap.
  * host        [in]     - The host name.
- * mutual_auth [in]     - Flag specifing whether or not mutual authentication
+ * mutual_auth [in]     - Flag specifying whether or not mutual authentication
  *                        is enabled.
  * chlg64      [in]     - The optional base64 encoded challenge message.
  * krb5        [in/out] - The Kerberos 5 data struct being used and modified.
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index b484a01..4219645 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -27,7 +27,7 @@
 /*
  * NTLM details:
  *
- * http://davenport.sourceforge.net/ntlm.html
+ * https://davenport.sourceforge.io/ntlm.html
  * https://www.innovation.ch/java/ntlm.html
  */
 
@@ -41,7 +41,7 @@
 #include "curl_gethostname.h"
 #include "curl_multibyte.h"
 #include "warnless.h"
-
+#include "rand.h"
 #include "vtls/vtls.h"
 
 #ifdef USE_NSS
@@ -394,7 +394,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
   /* Clean up any former leftovers and initialise to defaults */
   Curl_auth_ntlm_cleanup(ntlm);
 
-#if USE_NTRESPONSES && USE_NTLM2SESSION
+#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
 #else
 #define NTLM2FLAG 0
@@ -509,7 +509,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   unsigned char ntlmbuf[NTLM_BUFSIZE];
   int lmrespoff;
   unsigned char lmresp[24]; /* fixed-size */
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
   int ntrespoff;
   unsigned int ntresplen = 24;
   unsigned char ntresp[24]; /* fixed-size */
@@ -552,14 +552,15 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
     hostlen = strlen(host);
   }
 
-#if USE_NTRESPONSES && USE_NTLM_V2
+#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2)
   if(ntlm->target_info_len) {
     unsigned char ntbuffer[0x18];
-    unsigned int entropy[2];
+    unsigned char entropy[8];
     unsigned char ntlmv2hash[0x18];
 
-    entropy[0] = Curl_rand(data);
-    entropy[1] = Curl_rand(data);
+    result = Curl_rand(data, entropy, 8);
+    if(result)
+      return result;
 
     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
     if(result)
@@ -571,15 +572,13 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
       return result;
 
     /* LMv2 response */
-    result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
-                                         (unsigned char *)&entropy[0],
+    result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy,
                                          &ntlm->nonce[0], lmresp);
     if(result)
       return result;
 
     /* NTLMv2 response */
-    result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
-                                           (unsigned char *)&entropy[0],
+    result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy,
                                            ntlm, &ntlmv2resp, &ntresplen);
     if(result)
       return result;
@@ -589,17 +588,18 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   else
 #endif
 
-#if USE_NTRESPONSES && USE_NTLM2SESSION
+#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
   /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
   if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
     unsigned char ntbuffer[0x18];
     unsigned char tmp[0x18];
     unsigned char md5sum[MD5_DIGEST_LENGTH];
-    unsigned int entropy[2];
+    unsigned char entropy[8];
 
     /* Need to create 8 bytes random data */
-    entropy[0] = Curl_rand(data);
-    entropy[1] = Curl_rand(data);
+    result = Curl_rand(data, entropy, 8);
+    if(result)
+      return result;
 
     /* 8 bytes random data as challenge in lmresp */
     memcpy(lmresp, entropy, 8);
@@ -628,12 +628,12 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
 #endif
   {
 
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
     unsigned char ntbuffer[0x18];
 #endif
     unsigned char lmbuffer[0x18];
 
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
     if(result)
       return result;
@@ -649,7 +649,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
 
     /* A safer but less compatible alternative is:
      *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
-     * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
+     * See https://davenport.sourceforge.io/ntlm.html#ntlmVersion2 */
   }
 
   if(unicode) {
@@ -659,7 +659,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   }
 
   lmrespoff = 64; /* size of the message header */
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
   ntrespoff = lmrespoff + 0x18;
   domoff = ntrespoff + ntresplen;
 #else
@@ -719,7 +719,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
                   SHORTPAIR(lmrespoff),
                   0x0, 0x0,
 
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
                   SHORTPAIR(ntresplen),
                   SHORTPAIR(ntrespoff),
@@ -766,7 +766,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
     ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
   });
 
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
   if(size < (NTLM_BUFSIZE - ntresplen)) {
     DEBUGASSERT(size == (size_t)ntrespoff);
     memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.h b/Utilities/cmcurl/lib/vauth/ntlm.h
index b14e7a5..f906a3c 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.h
+++ b/Utilities/cmcurl/lib/vauth/ntlm.h
@@ -32,7 +32,7 @@
 /* Stuff only required for curl_ntlm_msgs.c */
 #ifdef BUILDING_CURL_NTLM_MSGS_C
 
-/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
+/* Flag bits definitions based on https://davenport.sourceforge.io/ntlm.html */
 
 #define NTLMFLAG_NEGOTIATE_UNICODE               (1<<0)
 /* Indicates that Unicode strings are supported for use in security buffer
diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index 672b43f..a6797cd 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -34,6 +34,7 @@
 #include "warnless.h"
 #include "curl_multibyte.h"
 #include "sendf.h"
+#include "strerror.h"
 
 /* The last #include files should be: */
 #include "curl_memory.h"
@@ -224,6 +225,8 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
   free(chlg);
 
   if(GSS_ERROR(nego->status)) {
+    failf(data, "InitializeSecurityContext failed: %s",
+          Curl_sspi_strerror(data->easy_conn, nego->status));
     return CURLE_OUT_OF_MEMORY;
   }
 
@@ -264,7 +267,7 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
 
   /* Base64 encode the already generated response */
   result = Curl_base64_encode(data,
-                              (const char*) nego->output_token,
+                              (const char *) nego->output_token,
                               nego->output_token_length,
                               outptr, outlen);
 
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index a434a62..3d17768 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -324,6 +324,9 @@ static curl_version_info_data version_info = {
 #if defined(USE_LIBPSL)
   | CURL_VERSION_PSL
 #endif
+#if defined(HTTPS_PROXY_SUPPORT)
+  | CURL_VERSION_HTTPS_PROXY
+#endif
   ,
   NULL, /* ssl_version */
   0,    /* ssl_version_num, this is kept at zero */
diff --git a/Utilities/cmcurl/lib/vtls/axtls.c b/Utilities/cmcurl/lib/vtls/axtls.c
index 85b8bc4..f0e3766 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.c
+++ b/Utilities/cmcurl/lib/vtls/axtls.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu at directv.com>.
- * Copyright (C) 2010 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel at 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
@@ -65,7 +65,7 @@ int Curl_axtls_cleanup(void)
 
 static CURLcode map_error_to_curl(int axtls_err)
 {
-  switch (axtls_err) {
+  switch(axtls_err) {
   case SSL_ERROR_NOT_SUPPORTED:
   case SSL_ERROR_INVALID_VERSION:
   case -70:                       /* protocol version alert from server */
@@ -121,7 +121,7 @@ static Curl_send axtls_send;
 static void free_ssl_structs(struct ssl_connect_data *connssl)
 {
   if(connssl->ssl) {
-    ssl_free (connssl->ssl);
+    ssl_free(connssl->ssl);
     connssl->ssl = NULL;
   }
   if(connssl->ssl_ctx) {
@@ -156,9 +156,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
        same connection */
     return CURLE_OK;
 
+  if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
+    failf(data, "axtls does not support CURL_SSLVERSION_MAX");
+    return CURLE_SSL_CONNECT_ERROR;
+  }
+
+
   /* axTLS only supports TLSv1 */
   /* check to see if we've been told to use an explicit SSL/TLS version */
-  switch(data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
     break;
@@ -183,17 +189,17 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
   conn->ssl[sockindex].ssl = NULL;
 
   /* Load the trusted CA cert bundle file */
-  if(data->set.ssl.CAfile) {
-    if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
-       != SSL_OK) {
+  if(SSL_CONN_CONFIG(CAfile)) {
+    if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
+                    SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
       infof(data, "error reading ca cert file %s \n",
-            data->set.ssl.CAfile);
-      if(data->set.ssl.verifypeer) {
+            SSL_CONN_CONFIG(CAfile));
+      if(SSL_CONN_CONFIG(verifypeer)) {
         return CURLE_SSL_CACERT_BADFILE;
       }
     }
     else
-      infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
+      infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile));
   }
 
   /* gtls.c tasks we're skipping for now:
@@ -205,15 +211,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
    */
 
   /* Load client certificate */
-  if(data->set.str[STRING_CERT]) {
+  if(SSL_SET_OPTION(cert)) {
     i=0;
     /* Instead of trying to analyze cert type here, let axTLS try them all. */
     while(cert_types[i] != 0) {
       ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
-                                    data->set.str[STRING_CERT], NULL);
+                                    SSL_SET_OPTION(cert), NULL);
       if(ssl_fcn_return == SSL_OK) {
         infof(data, "successfully read cert file %s \n",
-              data->set.str[STRING_CERT]);
+              SSL_SET_OPTION(cert));
         break;
       }
       i++;
@@ -221,7 +227,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
     /* Tried all cert types, none worked. */
     if(cert_types[i] == 0) {
       failf(data, "%s is not x509 or pkcs12 format",
-            data->set.str[STRING_CERT]);
+            SSL_SET_OPTION(cert));
       return CURLE_SSL_CERTPROBLEM;
     }
   }
@@ -229,15 +235,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
   /* Load client key.
      If a pkcs12 file successfully loaded a cert, then there's nothing to do
      because the key has already been loaded. */
-  if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
+  if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
     i=0;
     /* Instead of trying to analyze key type here, let axTLS try them all. */
     while(key_types[i] != 0) {
       ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
-                                    data->set.str[STRING_KEY], NULL);
+                                    SSL_SET_OPTION(key), NULL);
       if(ssl_fcn_return == SSL_OK) {
         infof(data, "successfully read key file %s \n",
-              data->set.str[STRING_KEY]);
+              SSL_SET_OPTION(key));
         break;
       }
       i++;
@@ -245,7 +251,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
     /* Tried all key types, none worked. */
     if(key_types[i] == 0) {
       failf(data, "Failure: %s is not a supported key file",
-            data->set.str[STRING_KEY]);
+            SSL_SET_OPTION(key));
       return CURLE_SSL_CONNECT_ERROR;
     }
   }
@@ -256,23 +262,24 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
    * 2) setting up callbacks.  these seem gnutls specific
    */
 
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     const uint8_t *ssl_sessionid;
     size_t ssl_idsize;
 
     /* In axTLS, handshaking happens inside ssl_client_new. */
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
+    if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize,
+                              sockindex)) {
       /* we got a session id, use it! */
-      infof (data, "SSL re-using session ID\n");
+      infof(data, "SSL re-using session ID\n");
       ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
-                           ssl_sessionid, (uint8_t)ssl_idsize);
+                           ssl_sessionid, (uint8_t)ssl_idsize, NULL);
     }
     Curl_ssl_sessionid_unlock(conn);
   }
 
   if(!ssl)
-    ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
+    ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
 
   conn->ssl[sockindex].ssl = ssl;
   return CURLE_OK;
@@ -291,13 +298,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
   const char *dns_altname;
   int8_t found_subject_alt_names = 0;
   int8_t found_subject_alt_name_matching_conn = 0;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const char * const dispname = SSL_IS_PROXY() ?
+    conn->http_proxy.host.dispname : conn->host.dispname;
 
   /* Here, gtls.c gets the peer certificates and fails out depending on
    * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
    */
 
   /* Verify server's certificate */
-  if(data->set.ssl.verifypeer) {
+  if(SSL_CONN_CONFIG(verifypeer)) {
     if(ssl_verify_cert(ssl) != SSL_OK) {
       Curl_axtls_close(conn, sockindex);
       failf(data, "server cert verify failed");
@@ -328,8 +339,8 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
     found_subject_alt_names = 1;
 
     infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
-          dns_altname, conn->host.name);
-    if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
+          dns_altname, hostname);
+    if(Curl_cert_hostcheck(dns_altname, hostname)) {
       found_subject_alt_name_matching_conn = 1;
       break;
     }
@@ -337,23 +348,21 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
 
   /* RFC2818 checks */
   if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
-    if(data->set.ssl.verifyhost) {
+    if(SSL_CONN_CONFIG(verifyhost)) {
       /* Break connection ! */
       Curl_axtls_close(conn, sockindex);
-      failf(data, "\tsubjectAltName(s) do not match %s\n",
-            conn->host.dispname);
+      failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
     else
-      infof(data, "\tsubjectAltName(s) do not match %s\n",
-            conn->host.dispname);
+      infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
   }
   else if(found_subject_alt_names == 0) {
     /* Per RFC2818, when no Subject Alt Names were available, examine the peer
        CN as a legacy fallback */
     peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
     if(peer_CN == NULL) {
-      if(data->set.ssl.verifyhost) {
+      if(SSL_CONN_CONFIG(verifyhost)) {
         Curl_axtls_close(conn, sockindex);
         failf(data, "unable to obtain common name from peer certificate");
         return CURLE_PEER_FAILED_VERIFICATION;
@@ -362,17 +371,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
         infof(data, "unable to obtain common name from peer certificate");
     }
     else {
-      if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
-        if(data->set.ssl.verifyhost) {
+      if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
+        if(SSL_CONN_CONFIG(verifyhost)) {
           /* Break connection ! */
           Curl_axtls_close(conn, sockindex);
           failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
-                peer_CN, conn->host.dispname);
+                peer_CN, dispname);
           return CURLE_PEER_FAILED_VERIFICATION;
         }
         else
           infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
-                peer_CN, conn->host.dispname);
+                peer_CN, dispname);
       }
     }
   }
@@ -383,13 +392,13 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
   conn->send[sockindex] = axtls_send;
 
   /* Put our freshly minted SSL session in cache */
-  if(conn->ssl_config.sessionid) {
-    const uint8_t *ssl_sessionid = ssl_get_session_id_size(ssl);
-    size_t ssl_idsize = ssl_get_session_id(ssl);
+  if(SSL_SET_OPTION(primary.sessionid)) {
+    const uint8_t *ssl_sessionid = ssl_get_session_id(ssl);
+    size_t ssl_idsize = ssl_get_session_id_size(ssl);
     Curl_ssl_sessionid_lock(conn);
-    if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
-       != CURLE_OK)
-      infof (data, "failed to add session to cache\n");
+    if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize,
+                             sockindex) != CURLE_OK)
+      infof(data, "failed to add session to cache\n");
     Curl_ssl_sessionid_unlock(conn);
   }
 
@@ -437,7 +446,7 @@ CURLcode Curl_axtls_connect_nonblocking(
         return CURLE_OK;
       }
     }
-    infof (conn->data, "handshake completed successfully\n");
+    infof(conn->data, "handshake completed successfully\n");
     conn->ssl[sockindex].connecting_state = ssl_connect_3;
   }
 
@@ -503,7 +512,7 @@ Curl_axtls_connect(struct connectdata *conn,
     /* TODO: avoid polling */
     Curl_wait_ms(10);
   }
-  infof (conn->data, "handshake completed successfully\n");
+  infof(conn->data, "handshake completed successfully\n");
 
   conn_step = connect_finish(conn, sockindex);
   if(conn_step != CURLE_OK) {
@@ -677,9 +686,9 @@ size_t Curl_axtls_version(char *buffer, size_t size)
   return snprintf(buffer, size, "axTLS/%s", ssl_version());
 }
 
-int Curl_axtls_random(struct Curl_easy *data,
-                      unsigned char *entropy,
-                      size_t length)
+CURLcode Curl_axtls_random(struct Curl_easy *data,
+                           unsigned char *entropy,
+                           size_t length)
 {
   static bool ssl_seeded = FALSE;
   (void)data;
@@ -691,7 +700,7 @@ int Curl_axtls_random(struct Curl_easy *data,
     RNG_initialize();
   }
   get_random((int)length, entropy);
-  return 0;
+  return CURLE_OK;
 }
 
 #endif /* USE_AXTLS */
diff --git a/Utilities/cmcurl/lib/vtls/axtls.h b/Utilities/cmcurl/lib/vtls/axtls.h
index b16d051..53797ea 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.h
+++ b/Utilities/cmcurl/lib/vtls/axtls.h
@@ -8,7 +8,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2010, DirecTV, Contact: Eric Hu <ehu at directv.com>
- * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel at 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,9 +42,9 @@ void Curl_axtls_session_free(void *ptr);
 size_t Curl_axtls_version(char *buffer, size_t size);
 int Curl_axtls_shutdown(struct connectdata *conn, int sockindex);
 int Curl_axtls_check_cxn(struct connectdata *conn);
-int Curl_axtls_random(struct Curl_easy *data,
-                      unsigned char *entropy,
-                      size_t length);
+CURLcode Curl_axtls_random(struct Curl_easy *data,
+                           unsigned char *entropy,
+                           size_t length);
 
 /* Set the API backend definition to axTLS */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c
index 5d6dbfb..01bfdab 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -44,6 +44,38 @@ and that's a problem since options.h hasn't been included yet. */
 #include <cyassl/options.h>
 #endif
 
+/* To determine what functions are available we rely on one or both of:
+   - the user's options.h generated by CyaSSL/wolfSSL
+   - the symbols detected by curl's configure
+   Since they are markedly different from one another, and one or the other may
+   not be available, we do some checking below to bring things in sync. */
+
+/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
+#ifndef HAVE_ALPN
+#ifdef HAVE_WOLFSSL_USEALPN
+#define HAVE_ALPN
+#endif
+#endif
+
+/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in
+   options.h, but is only seen in >= 3.6.6 since that's when they started
+   disabling SSLv3 by default. */
+#ifndef WOLFSSL_ALLOW_SSLV3
+#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \
+    defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
+#define WOLFSSL_ALLOW_SSLV3
+#endif
+#endif
+
+/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC
+   supported curve extension in options.h. Note ECC is enabled separately. */
+#ifndef HAVE_SUPPORTED_CURVES
+#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \
+    defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE)
+#define HAVE_SUPPORTED_CURVES
+#endif
+#endif
+
 #ifdef HAVE_LIMITS_H
 #include <limits.h>
 #endif
@@ -78,38 +110,6 @@ and that's a problem since options.h hasn't been included yet. */
 #define CYASSL_MAX_ERROR_SZ 80
 #endif
 
-/* To determine what functions are available we rely on one or both of:
-   - the user's options.h generated by CyaSSL/wolfSSL
-   - the symbols detected by curl's configure
-   Since they are markedly different from one another, and one or the other may
-   not be available, we do some checking below to bring things in sync. */
-
-/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
-#ifndef HAVE_ALPN
-#ifdef HAVE_WOLFSSL_USEALPN
-#define HAVE_ALPN
-#endif
-#endif
-
-/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in
-   options.h, but is only seen in >= 3.6.6 since that's when they started
-   disabling SSLv3 by default. */
-#ifndef WOLFSSL_ALLOW_SSLV3
-#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \
-    defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
-#define WOLFSSL_ALLOW_SSLV3
-#endif
-#endif
-
-/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC
-   supported curve extension in options.h. Note ECC is enabled separately. */
-#ifndef HAVE_SUPPORTED_CURVES
-#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \
-    defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE)
-#define HAVE_SUPPORTED_CURVES
-#endif
-#endif
-
 static Curl_recv cyassl_recv;
 static Curl_send cyassl_send;
 
@@ -134,6 +134,7 @@ cyassl_connect_step1(struct connectdata *conn,
                      int sockindex)
 {
   char error_buffer[CYASSL_MAX_ERROR_SZ];
+  char *ciphers;
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* conssl = &conn->ssl[sockindex];
   SSL_METHOD* req_method = NULL;
@@ -148,8 +149,13 @@ cyassl_connect_step1(struct connectdata *conn,
   if(conssl->state == ssl_connection_complete)
     return CURLE_OK;
 
+  if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
+    failf(data, "CyaSSL does not support to set maximum SSL/TLS version");
+    return CURLE_SSL_CONNECT_ERROR;
+  }
+
   /* check to see if we've been told to use an explicit SSL/TLS version */
-  switch(data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
 #if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
@@ -174,12 +180,15 @@ cyassl_connect_step1(struct connectdata *conn,
     req_method = TLSv1_2_client_method();
     use_sni(TRUE);
     break;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "CyaSSL: TLS 1.3 is not yet supported");
+    return CURLE_SSL_CONNECT_ERROR;
   case CURL_SSLVERSION_SSLv3:
 #ifdef WOLFSSL_ALLOW_SSLV3
     req_method = SSLv3_client_method();
     use_sni(FALSE);
 #else
-    failf(data, "No support for SSLv3");
+    failf(data, "CyaSSL does not support SSLv3");
     return CURLE_NOT_BUILT_IN;
 #endif
     break;
@@ -205,7 +214,7 @@ cyassl_connect_step1(struct connectdata *conn,
     return CURLE_OUT_OF_MEMORY;
   }
 
-  switch(data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
 #if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
@@ -226,20 +235,29 @@ cyassl_connect_step1(struct connectdata *conn,
     break;
   }
 
+  ciphers = SSL_CONN_CONFIG(cipher_list);
+  if(ciphers) {
+    if(!SSL_CTX_set_cipher_list(conssl->ctx, ciphers)) {
+      failf(data, "failed setting cipher list: %s", ciphers);
+      return CURLE_SSL_CIPHER;
+    }
+    infof(data, "Cipher selection: %s\n", ciphers);
+  }
+
 #ifndef NO_FILESYSTEM
   /* load trusted cacert */
-  if(data->set.str[STRING_SSL_CAFILE]) {
+  if(SSL_CONN_CONFIG(CAfile)) {
     if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
-                                          data->set.str[STRING_SSL_CAFILE],
-                                          data->set.str[STRING_SSL_CAPATH])) {
-      if(data->set.ssl.verifypeer) {
+                                      SSL_CONN_CONFIG(CAfile),
+                                      SSL_CONN_CONFIG(CApath))) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         /* Fail if we insist on successfully verifying the server. */
         failf(data, "error setting certificate verify locations:\n"
               "  CAfile: %s\n  CApath: %s",
-              data->set.str[STRING_SSL_CAFILE]?
-              data->set.str[STRING_SSL_CAFILE]: "none",
-              data->set.str[STRING_SSL_CAPATH]?
-              data->set.str[STRING_SSL_CAPATH] : "none");
+              SSL_CONN_CONFIG(CAfile)?
+              SSL_CONN_CONFIG(CAfile): "none",
+              SSL_CONN_CONFIG(CApath)?
+              SSL_CONN_CONFIG(CApath) : "none");
         return CURLE_SSL_CACERT_BADFILE;
       }
       else {
@@ -256,25 +274,25 @@ cyassl_connect_step1(struct connectdata *conn,
     infof(data,
           "  CAfile: %s\n"
           "  CApath: %s\n",
-          data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
+          SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
           "none",
-          data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
+          SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath):
           "none");
   }
 
   /* Load the client certificate, and private key */
-  if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
-    int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);
+  if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
+    int file_type = do_file_type(SSL_SET_OPTION(cert_type));
 
-    if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
+    if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert),
                                      file_type) != 1) {
       failf(data, "unable to use client certificate (no key or wrong pass"
             " phrase?)");
       return CURLE_SSL_CONNECT_ERROR;
     }
 
-    file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
-    if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
+    file_type = do_file_type(SSL_SET_OPTION(key_type));
+    if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key),
                                     file_type) != 1) {
       failf(data, "unable to set private key");
       return CURLE_SSL_CONNECT_ERROR;
@@ -287,7 +305,8 @@ cyassl_connect_step1(struct connectdata *conn,
    * anyway. In the latter case the result of the verification is checked with
    * SSL_get_verify_result() below. */
   SSL_CTX_set_verify(conssl->ctx,
-                     data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
+                     SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
+                                                 SSL_VERIFY_NONE,
                      NULL);
 
 #ifdef HAVE_SNI
@@ -296,13 +315,15 @@ cyassl_connect_step1(struct connectdata *conn,
 #ifdef ENABLE_IPV6
     struct in6_addr addr6;
 #endif
-    size_t hostname_len = strlen(conn->host.name);
+    const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+      conn->host.name;
+    size_t hostname_len = strlen(hostname);
     if((hostname_len < USHRT_MAX) &&
-       (0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) &&
+       (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
 #ifdef ENABLE_IPV6
-       (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) &&
+       (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
 #endif
-       (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name,
+       (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname,
                           (unsigned short)hostname_len) != 1)) {
       infof(data, "WARNING: failed to configure server name indication (SNI) "
             "TLS extension\n");
@@ -331,7 +352,7 @@ cyassl_connect_step1(struct connectdata *conn,
     }
   }
 #ifdef NO_FILESYSTEM
-  else if(data->set.ssl.verifypeer) {
+  else if(SSL_CONN_CONFIG(verifypeer)) {
     failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built"
           " with \"no filesystem\". Either disable peer verification"
           " (insecure) or if you are building an application with libcurl you"
@@ -377,11 +398,11 @@ cyassl_connect_step1(struct connectdata *conn,
 #endif /* HAVE_ALPN */
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     void *ssl_sessionid = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
       /* we got a session id, use it! */
       if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
         Curl_ssl_sessionid_unlock(conn);
@@ -391,7 +412,7 @@ cyassl_connect_step1(struct connectdata *conn,
         return CURLE_SSL_CONNECT_ERROR;
       }
       /* Informational message */
-      infof (data, "SSL re-using session ID\n");
+      infof(data, "SSL re-using session ID\n");
     }
     Curl_ssl_sessionid_unlock(conn);
   }
@@ -414,13 +435,20 @@ cyassl_connect_step2(struct connectdata *conn,
   int ret = -1;
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const char * const dispname = SSL_IS_PROXY() ?
+    conn->http_proxy.host.dispname : conn->host.dispname;
+  const char * const pinnedpubkey = SSL_IS_PROXY() ?
+                        data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+                        data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
 
   conn->recv[sockindex] = cyassl_recv;
   conn->send[sockindex] = cyassl_send;
 
   /* Enable RFC2818 checks */
-  if(data->set.ssl.verifyhost) {
-    ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name);
+  if(SSL_CONN_CONFIG(verifyhost)) {
+    ret = CyaSSL_check_domain_name(conssl->handle, hostname);
     if(ret == SSL_FAILURE)
       return CURLE_OUT_OF_MEMORY;
   }
@@ -444,31 +472,31 @@ cyassl_connect_step2(struct connectdata *conn,
     else if(DOMAIN_NAME_MISMATCH == detail) {
 #if 1
       failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
-            conn->host.dispname);
+            dispname);
       return CURLE_PEER_FAILED_VERIFICATION;
 #else
       /* When the CyaSSL_check_domain_name() is used and you desire to continue
-       * on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0',
+       * on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost == 0',
        * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only
        * way to do this is currently to switch the CyaSSL_check_domain_name()
-       * in and out based on the 'data->set.ssl.verifyhost' value. */
-      if(data->set.ssl.verifyhost) {
+       * in and out based on the 'conn->ssl_config.verifyhost' value. */
+      if(SSL_CONN_CONFIG(verifyhost)) {
         failf(data,
               "\tsubject alt name(s) or common name do not match \"%s\"\n",
-              conn->host.dispname);
+              dispname);
         return CURLE_PEER_FAILED_VERIFICATION;
       }
       else {
         infof(data,
               "\tsubject alt name(s) and/or common name do not match \"%s\"\n",
-              conn->host.dispname);
+              dispname);
         return CURLE_OK;
       }
 #endif
     }
 #if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
     else if(ASN_NO_SIGNER_E == detail) {
-      if(data->set.ssl.verifypeer) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         failf(data, "\tCA signer not available for verification\n");
         return CURLE_SSL_CACERT_BADFILE;
       }
@@ -487,7 +515,7 @@ cyassl_connect_step2(struct connectdata *conn,
     }
   }
 
-  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+  if(pinnedpubkey) {
 #ifdef KEEP_PEER_CERT
     X509 *x509;
     const char *x509_der;
@@ -509,7 +537,8 @@ cyassl_connect_step2(struct connectdata *conn,
     }
 
     memset(&x509_parsed, 0, sizeof x509_parsed);
-    Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len);
+    if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
+      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
 
     pubkey = &x509_parsed.subjectPublicKeyInfo;
     if(!pubkey->header || pubkey->end <= pubkey->header) {
@@ -518,7 +547,7 @@ cyassl_connect_step2(struct connectdata *conn,
     }
 
     result = Curl_pin_peer_pubkey(data,
-                                  data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+                                  pinnedpubkey,
                                   (const unsigned char *)pubkey->header,
                                   (size_t)(pubkey->end - pubkey->header));
     if(result) {
@@ -567,7 +596,13 @@ cyassl_connect_step2(struct connectdata *conn,
 #endif /* HAVE_ALPN */
 
   conssl->connecting_state = ssl_connect_3;
+#if (LIBCYASSL_VERSION_HEX >= 0x03009010)
+  infof(data, "SSL connection using %s / %s\n",
+        wolfSSL_get_version(conssl->handle),
+        wolfSSL_get_cipher_name(conssl->handle));
+#else
   infof(data, "SSL connected\n");
+#endif
 
   return CURLE_OK;
 }
@@ -583,7 +618,7 @@ cyassl_connect_step3(struct connectdata *conn,
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     bool incache;
     SSL_SESSION *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -591,7 +626,8 @@ cyassl_connect_step3(struct connectdata *conn,
     our_ssl_sessionid = SSL_get_session(connssl->handle);
 
     Curl_ssl_sessionid_lock(conn);
-    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+    incache = !(Curl_ssl_getsessionid(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");
@@ -602,7 +638,7 @@ cyassl_connect_step3(struct connectdata *conn,
 
     if(!incache) {
       result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
-                                     0 /* unknown size */);
+                                     0 /* unknown size */, sockindex);
       if(result) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "failed to store ssl session");
@@ -654,11 +690,11 @@ void Curl_cyassl_close(struct connectdata *conn, int sockindex)
 
   if(conssl->handle) {
     (void)SSL_shutdown(conssl->handle);
-    SSL_free (conssl->handle);
+    SSL_free(conssl->handle);
     conssl->handle = NULL;
   }
   if(conssl->ctx) {
-    SSL_CTX_free (conssl->ctx);
+    SSL_CTX_free(conssl->ctx);
     conssl->ctx = NULL;
   }
 }
@@ -705,7 +741,9 @@ void Curl_cyassl_session_free(void *ptr)
 
 size_t Curl_cyassl_version(char *buffer, size_t size)
 {
-#ifdef WOLFSSL_VERSION
+#if LIBCYASSL_VERSION_HEX >= 0x03006000
+  return snprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
+#elif defined(WOLFSSL_VERSION)
   return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
 #elif defined(CYASSL_VERSION)
   return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
@@ -740,7 +778,7 @@ int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
   if(connssl->handle) {
-    SSL_free (connssl->handle);
+    SSL_free(connssl->handle);
     connssl->handle = NULL;
   }
   return retval;
@@ -757,7 +795,7 @@ cyassl_connect_common(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   curl_socket_t sockfd = conn->sock[sockindex];
-  long timeout_ms;
+  time_t timeout_ms;
   int what;
 
   /* check if the connection has already been established */
@@ -886,19 +924,19 @@ Curl_cyassl_connect(struct connectdata *conn,
   return CURLE_OK;
 }
 
-int Curl_cyassl_random(struct Curl_easy *data,
-                       unsigned char *entropy,
-                       size_t length)
+CURLcode Curl_cyassl_random(struct Curl_easy *data,
+                            unsigned char *entropy,
+                            size_t length)
 {
   RNG rng;
   (void)data;
   if(InitRng(&rng))
-    return 1;
+    return CURLE_FAILED_INIT;
   if(length > UINT_MAX)
-    return 1;
+    return CURLE_FAILED_INIT;
   if(RNG_GenerateBlock(&rng, entropy, (unsigned)length))
-    return 1;
-  return 0;
+    return CURLE_FAILED_INIT;
+  return CURLE_OK;
 }
 
 void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.h b/Utilities/cmcurl/lib/vtls/cyassl.h
index 508dfaa..f47719e 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.h
+++ b/Utilities/cmcurl/lib/vtls/cyassl.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -51,15 +51,15 @@ int Curl_cyassl_init(void);
 CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
                                          int sockindex,
                                          bool *done);
-int Curl_cyassl_random(struct Curl_easy *data,
-                       unsigned char *entropy,
-                       size_t length);
+CURLcode Curl_cyassl_random(struct Curl_easy *data,
+                            unsigned char *entropy,
+                            size_t length);
 void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
                      size_t tmplen,
                      unsigned char *sha256sum, /* output */
                      size_t unused);
 
-/* Set the API backend definition to Schannel */
+/* Set the API backend definition to CyaSSL */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
 
 /* this backend supports CURLOPT_SSL_CTX_* */
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c
index 66e74f1..0417665 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.c
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman at gmail.com>.
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at 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
@@ -113,6 +113,36 @@
 #define ioErr -36
 #define paramErr -50
 
+#ifdef DARWIN_SSL_PINNEDPUBKEY
+/* both new and old APIs return rsa keys missing the spki header (not DER) */
+static const unsigned char rsa4096SpkiHeader[] = {
+                                       0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
+                                       0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+                                       0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+                                       0x00, 0x03, 0x82, 0x02, 0x0f, 0x00};
+
+static const unsigned char rsa2048SpkiHeader[] = {
+                                       0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+                                       0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+                                       0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+                                       0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
+#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
+/* the *new* version doesn't return DER encoded ecdsa certs like the old... */
+static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
+                                       0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
+                                       0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+                                       0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
+                                       0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+                                       0x42, 0x00};
+
+static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
+                                       0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
+                                       0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+                                       0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
+                                       0x00, 0x22, 0x03, 0x62, 0x00};
+#endif /* DARWIN_SSL_PINNEDPUBKEY_V1 */
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
 /* The following two functions were ripped from Apple sample code,
  * with some modifications: */
 static OSStatus SocketRead(SSLConnectionRef connection,
@@ -197,7 +227,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
 
   do {
     length = write(sock,
-                   (char*)dataPtr + bytesSent,
+                   (char *)dataPtr + bytesSent,
                    dataLen - bytesSent);
   } while((length > 0) &&
            ( (bytesSent += length) < dataLen) );
@@ -219,8 +249,10 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
   return ortn;
 }
 
-CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
-  switch (cipher) {
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher)
+{
+  switch(cipher) {
     /* SSL version 3.0 */
     case SSL_RSA_WITH_NULL_MD5:
       return "SSL_RSA_WITH_NULL_MD5";
@@ -364,7 +396,8 @@ CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
   return "SSL_NULL_WITH_NULL_NULL";
 }
 
-CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
+CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
+{
   switch(cipher) {
     /* TLS 1.0 with AES (RFC 3268) */
     case TLS_RSA_WITH_AES_128_CBC_SHA:
@@ -774,6 +807,7 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
   }
   return "TLS_NULL_WITH_NULL_NULL";
 }
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
 
 #if CURL_BUILD_MAC
 CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
@@ -885,12 +919,17 @@ static OSStatus CopyIdentityWithLabel(char *label,
   OSStatus status = errSecItemNotFound;
 
 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
+  CFArrayRef keys_list;
+  CFIndex keys_list_count;
+  CFIndex i;
+  CFStringRef common_name;
+
   /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
      kSecClassIdentity was introduced in Lion. If both exist, let's use them
      to find the certificate. */
   if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
-    CFTypeRef keys[4];
-    CFTypeRef values[4];
+    CFTypeRef keys[5];
+    CFTypeRef values[5];
     CFDictionaryRef query_dict;
     CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
       kCFStringEncodingUTF8);
@@ -900,21 +939,60 @@ static OSStatus CopyIdentityWithLabel(char *label,
     keys[0] = kSecClass;
     values[1] = kCFBooleanTrue;    /* we want a reference */
     keys[1] = kSecReturnRef;
-    values[2] = kSecMatchLimitOne; /* one is enough, thanks */
+    values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
+                                    * label matching below worked correctly */
     keys[2] = kSecMatchLimit;
     /* identity searches need a SecPolicyRef in order to work */
-    values[3] = SecPolicyCreateSSL(false, label_cf);
+    values[3] = SecPolicyCreateSSL(false, NULL);
     keys[3] = kSecMatchPolicy;
+    /* match the name of the certificate (doesn't work in macOS 10.12.1) */
+    values[4] = label_cf;
+    keys[4] = kSecAttrLabel;
     query_dict = CFDictionaryCreate(NULL, (const void **)keys,
-                                   (const void **)values, 4L,
-                                   &kCFCopyStringDictionaryKeyCallBacks,
-                                   &kCFTypeDictionaryValueCallBacks);
+                                    (const void **)values, 5L,
+                                    &kCFCopyStringDictionaryKeyCallBacks,
+                                    &kCFTypeDictionaryValueCallBacks);
     CFRelease(values[3]);
-    CFRelease(label_cf);
 
     /* Do we have a match? */
-    status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key);
+    status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
+
+    /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity,
+     * we need to find the correct identity ourselves */
+    if(status == noErr) {
+      keys_list_count = CFArrayGetCount(keys_list);
+      *out_cert_and_key = NULL;
+      status = 1;
+      for(i=0; i<keys_list_count; i++) {
+        OSStatus err = noErr;
+        SecCertificateRef cert = NULL;
+        SecIdentityRef identity =
+          (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
+        err = SecIdentityCopyCertificate(identity, &cert);
+        if(err == noErr) {
+#if CURL_BUILD_IOS
+          common_name = SecCertificateCopySubjectSummary(cert);
+#elif CURL_BUILD_MAC_10_7
+          SecCertificateCopyCommonName(cert, &common_name);
+#endif
+          if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
+            CFRelease(cert);
+            CFRelease(common_name);
+            CFRetain(identity);
+            *out_cert_and_key = identity;
+            status = noErr;
+            break;
+          }
+          CFRelease(common_name);
+        }
+        CFRelease(cert);
+      }
+    }
+
+    if(keys_list)
+      CFRelease(keys_list);
     CFRelease(query_dict);
+    CFRelease(label_cf);
   }
   else {
 #if CURL_SUPPORT_MAC_10_6
@@ -996,12 +1074,121 @@ CF_INLINE bool is_file(const char *filename)
   return false;
 }
 
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+static CURLcode darwinssl_version_from_curl(long *darwinver, long ssl_version)
+{
+  switch(ssl_version) {
+    case CURL_SSLVERSION_TLSv1_0:
+      *darwinver = kTLSProtocol1;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_1:
+      *darwinver = kTLSProtocol11;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_2:
+      *darwinver = kTLSProtocol12;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_3:
+      break;
+  }
+  return CURLE_SSL_CONNECT_ERROR;
+}
+#endif
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+{
+  struct Curl_easy *data = conn->data;
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  long ssl_version = SSL_CONN_CONFIG(version);
+  long ssl_version_max = SSL_CONN_CONFIG(version_max);
+
+  switch(ssl_version) {
+    case CURL_SSLVERSION_DEFAULT:
+    case CURL_SSLVERSION_TLSv1:
+      ssl_version = CURL_SSLVERSION_TLSv1_0;
+      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      break;
+  }
+
+  switch(ssl_version_max) {
+    case CURL_SSLVERSION_MAX_NONE:
+      ssl_version_max = ssl_version << 16;
+      break;
+    case CURL_SSLVERSION_MAX_DEFAULT:
+      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      break;
+  }
+
+#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
+  if(SSLSetProtocolVersionMax != NULL) {
+    SSLProtocol darwin_ver_min = kTLSProtocol1;
+    SSLProtocol darwin_ver_max = kTLSProtocol1;
+    CURLcode result = darwinssl_version_from_curl(&darwin_ver_min,
+                                                  ssl_version);
+    if(result) {
+      failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+      return result;
+    }
+    result = darwinssl_version_from_curl(&darwin_ver_max,
+                                         ssl_version_max >> 16);
+    if(result) {
+      failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+      return result;
+    }
+
+    (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, darwin_ver_min);
+    (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, darwin_ver_max);
+    return result;
+  }
+  else {
+#if CURL_SUPPORT_MAC_10_8
+    long i = ssl_version;
+    (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                       kSSLProtocolAll,
+                                       false);
+    for(; i <= (ssl_version_max >> 16); i++) {
+      switch(i) {
+        case CURL_SSLVERSION_TLSv1_0:
+          (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                            kTLSProtocol1,
+                                            true);
+          break;
+        case CURL_SSLVERSION_TLSv1_1:
+          (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                            kTLSProtocol11,
+                                            true);
+          break;
+        case CURL_SSLVERSION_TLSv1_2:
+          (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                            kTLSProtocol12,
+                                            true);
+          break;
+        case CURL_SSLVERSION_TLSv1_3:
+          failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
+          return CURLE_SSL_CONNECT_ERROR;
+      }
+    }
+    return CURLE_OK;
+#endif  /* CURL_SUPPORT_MAC_10_8 */
+  }
+#endif  /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+  failf(data, "DarwinSSL: cannot set SSL protocol");
+  return CURLE_SSL_CONNECT_ERROR;
+}
+
+
 static CURLcode darwinssl_connect_step1(struct connectdata *conn,
                                         int sockindex)
 {
   struct Curl_easy *data = conn->data;
   curl_socket_t sockfd = conn->sock[sockindex];
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+  char * const ssl_cert = SSL_SET_OPTION(cert);
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
 #ifdef ENABLE_IPV6
   struct in6_addr addr;
 #else
@@ -1052,40 +1239,41 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   /* check to see if we've been told to use an explicit SSL/TLS version */
 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
   if(SSLSetProtocolVersionMax != NULL) {
-    switch(data->set.ssl.version) {
-      default:
-      case CURL_SSLVERSION_DEFAULT:
-      case CURL_SSLVERSION_TLSv1:
-        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
-        break;
-      case CURL_SSLVERSION_TLSv1_0:
-        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
-        break;
-      case CURL_SSLVERSION_TLSv1_1:
-        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
-        break;
-      case CURL_SSLVERSION_TLSv1_2:
-        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
-        break;
-      case CURL_SSLVERSION_SSLv3:
-        err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
-        if(err != noErr) {
-          failf(data, "Your version of the OS does not support SSLv3");
-          return CURLE_SSL_CONNECT_ERROR;
-        }
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
+    switch(conn->ssl_config.version) {
+    case CURL_SSLVERSION_DEFAULT:
+    case CURL_SSLVERSION_TLSv1:
+      (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
+      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+      break;
+    case CURL_SSLVERSION_TLSv1_0:
+    case CURL_SSLVERSION_TLSv1_1:
+    case CURL_SSLVERSION_TLSv1_2:
+    case CURL_SSLVERSION_TLSv1_3:
+      {
+        CURLcode result = set_ssl_version_min_max(conn, sockindex);
+        if(result != CURLE_OK)
+          return result;
         break;
-      case CURL_SSLVERSION_SSLv2:
-        err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
-        if(err != noErr) {
-          failf(data, "Your version of the OS does not support SSLv2");
-          return CURLE_SSL_CONNECT_ERROR;
-        }
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+      }
+    case CURL_SSLVERSION_SSLv3:
+      err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+      if(err != noErr) {
+        failf(data, "Your version of the OS does not support SSLv3");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
+      break;
+    case CURL_SSLVERSION_SSLv2:
+      err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
+      if(err != noErr) {
+        failf(data, "Your version of the OS does not support SSLv2");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+      break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
     }
   }
   else {
@@ -1093,123 +1281,130 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
     (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                        kSSLProtocolAll,
                                        false);
-    switch (data->set.ssl.version) {
-      default:
-      case CURL_SSLVERSION_DEFAULT:
-      case CURL_SSLVERSION_TLSv1:
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol1,
-                                           true);
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol11,
-                                           true);
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol12,
-                                           true);
-        break;
-      case CURL_SSLVERSION_TLSv1_0:
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol1,
-                                           true);
-        break;
-      case CURL_SSLVERSION_TLSv1_1:
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol11,
-                                           true);
-        break;
-      case CURL_SSLVERSION_TLSv1_2:
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol12,
-                                           true);
-        break;
-      case CURL_SSLVERSION_SSLv3:
-        err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kSSLProtocol3,
-                                           true);
-        if(err != noErr) {
-          failf(data, "Your version of the OS does not support SSLv3");
-          return CURLE_SSL_CONNECT_ERROR;
-        }
-        break;
-      case CURL_SSLVERSION_SSLv2:
-        err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kSSLProtocol2,
-                                           true);
-        if(err != noErr) {
-          failf(data, "Your version of the OS does not support SSLv2");
-          return CURLE_SSL_CONNECT_ERROR;
-        }
-        break;
-    }
-#endif  /* CURL_SUPPORT_MAC_10_8 */
-  }
-#else
-  (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
-  switch(data->set.ssl.version) {
-    default:
+    switch(conn->ssl_config.version) {
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
-    case CURL_SSLVERSION_TLSv1_0:
       (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                          kTLSProtocol1,
                                          true);
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kTLSProtocol11,
+                                         true);
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kTLSProtocol12,
+                                         true);
       break;
+    case CURL_SSLVERSION_TLSv1_0:
     case CURL_SSLVERSION_TLSv1_1:
-      failf(data, "Your version of the OS does not support TLSv1.1");
-      return CURLE_SSL_CONNECT_ERROR;
     case CURL_SSLVERSION_TLSv1_2:
-      failf(data, "Your version of the OS does not support TLSv1.2");
-      return CURLE_SSL_CONNECT_ERROR;
-    case CURL_SSLVERSION_SSLv2:
+    case CURL_SSLVERSION_TLSv1_3:
+      {
+        CURLcode result = set_ssl_version_min_max(conn, sockindex);
+        if(result != CURLE_OK)
+          return result;
+        break;
+      }
+    case CURL_SSLVERSION_SSLv3:
       err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                         kSSLProtocol2,
+                                         kSSLProtocol3,
                                          true);
       if(err != noErr) {
-        failf(data, "Your version of the OS does not support SSLv2");
+        failf(data, "Your version of the OS does not support SSLv3");
         return CURLE_SSL_CONNECT_ERROR;
       }
       break;
-    case CURL_SSLVERSION_SSLv3:
+    case CURL_SSLVERSION_SSLv2:
       err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                         kSSLProtocol3,
+                                         kSSLProtocol2,
                                          true);
       if(err != noErr) {
-        failf(data, "Your version of the OS does not support SSLv3");
+        failf(data, "Your version of the OS does not support SSLv2");
         return CURLE_SSL_CONNECT_ERROR;
       }
       break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+#endif  /* CURL_SUPPORT_MAC_10_8 */
+  }
+#else
+  if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) {
+    failf(data, "Your version of the OS does not support to set maximum"
+                " SSL/TLS version");
+    return CURLE_SSL_CONNECT_ERROR;
+  }
+  (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
+  switch(conn->ssl_config.version) {
+  case CURL_SSLVERSION_DEFAULT:
+  case CURL_SSLVERSION_TLSv1:
+  case CURL_SSLVERSION_TLSv1_0:
+    (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                       kTLSProtocol1,
+                                       true);
+    break;
+  case CURL_SSLVERSION_TLSv1_1:
+    failf(data, "Your version of the OS does not support TLSv1.1");
+    return CURLE_SSL_CONNECT_ERROR;
+  case CURL_SSLVERSION_TLSv1_2:
+    failf(data, "Your version of the OS does not support TLSv1.2");
+    return CURLE_SSL_CONNECT_ERROR;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "Your version of the OS does not support TLSv1.3");
+    return CURLE_SSL_CONNECT_ERROR;
+  case CURL_SSLVERSION_SSLv2:
+    err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                       kSSLProtocol2,
+                                       true);
+    if(err != noErr) {
+      failf(data, "Your version of the OS does not support SSLv2");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    break;
+  case CURL_SSLVERSION_SSLv3:
+    err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                       kSSLProtocol3,
+                                       true);
+    if(err != noErr) {
+      failf(data, "Your version of the OS does not support SSLv3");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    break;
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
 
-  if(data->set.str[STRING_KEY]) {
+  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.\n");
   }
 
-  if(data->set.str[STRING_CERT]) {
+  if(ssl_cert) {
     SecIdentityRef cert_and_key = NULL;
-    bool is_cert_file = is_file(data->set.str[STRING_CERT]);
+    bool is_cert_file = is_file(ssl_cert);
 
     /* 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) {
-      if(!data->set.str[STRING_CERT_TYPE])
+      if(!SSL_SET_OPTION(cert_type))
         infof(data, "WARNING: SSL: Certificate type not set, assuming "
                     "PKCS#12 format.\n");
-      else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12",
-        strlen(data->set.str[STRING_CERT_TYPE])) != 0)
+      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");
 
-      err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT],
-        data->set.str[STRING_KEY_PASSWD], &cert_and_key);
+      err = CopyIdentityFromPKCS12File(ssl_cert,
+        SSL_SET_OPTION(key_passwd), &cert_and_key);
     }
     else
-      err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
+      err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
 
-    if(err == noErr) {
+    if(err == noErr && cert_and_key) {
       SecCertificateRef cert = NULL;
       CFTypeRef certs_c[1];
       CFArrayRef certs;
@@ -1246,27 +1441,27 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
     }
     else {
       switch(err) {
-        case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
-          failf(data, "SSL: Incorrect password for the certificate \"%s\" "
-                      "and its private key.", data->set.str[STRING_CERT]);
-          break;
-        case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
-          failf(data, "SSL: Couldn't make sense of the data in the "
-                      "certificate \"%s\" and its private key.",
-                      data->set.str[STRING_CERT]);
-          break;
-        case -25260: /* errSecPassphraseRequired */
-          failf(data, "SSL The certificate \"%s\" requires a password.",
-                      data->set.str[STRING_CERT]);
-          break;
-        case errSecItemNotFound:
-          failf(data, "SSL: Can't find the certificate \"%s\" and its private "
-                      "key in the Keychain.", data->set.str[STRING_CERT]);
-          break;
-        default:
-          failf(data, "SSL: Can't load the certificate \"%s\" and its private "
-                      "key: OSStatus %d", data->set.str[STRING_CERT], err);
-          break;
+      case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
+        failf(data, "SSL: Incorrect password for the certificate \"%s\" "
+                    "and its private key.", ssl_cert);
+        break;
+      case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
+        failf(data, "SSL: Couldn't make sense of the data in the "
+                    "certificate \"%s\" and its private key.",
+                    ssl_cert);
+        break;
+      case -25260: /* errSecPassphraseRequired */
+        failf(data, "SSL The certificate \"%s\" requires a password.",
+                    ssl_cert);
+        break;
+      case errSecItemNotFound:
+        failf(data, "SSL: Can't find the certificate \"%s\" and its private "
+                    "key in the Keychain.", ssl_cert);
+        break;
+      default:
+        failf(data, "SSL: Can't load the certificate \"%s\" and its private "
+                    "key: OSStatus %d", ssl_cert, err);
+        break;
       }
       return CURLE_SSL_CERTPROBLEM;
     }
@@ -1297,8 +1492,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
 #else
   if(SSLSetSessionOption != NULL) {
 #endif /* CURL_BUILD_MAC */
-    bool break_on_auth = !data->set.ssl.verifypeer ||
-      data->set.str[STRING_SSL_CAFILE];
+    bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile;
     err = SSLSetSessionOption(connssl->ssl_ctx,
                               kSSLSessionOptionBreakOnServerAuth,
                               break_on_auth);
@@ -1310,7 +1504,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   else {
 #if CURL_SUPPORT_MAC_10_8
     err = SSLSetEnableCertVerify(connssl->ssl_ctx,
-                                 data->set.ssl.verifypeer?true:false);
+                                 conn->ssl_config.verifypeer?true:false);
     if(err != noErr) {
       failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
       return CURLE_SSL_CONNECT_ERROR;
@@ -1319,49 +1513,46 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   }
 #else
   err = SSLSetEnableCertVerify(connssl->ssl_ctx,
-                               data->set.ssl.verifypeer?true:false);
+                               conn->ssl_config.verifypeer?true:false);
   if(err != noErr) {
     failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
     return CURLE_SSL_CONNECT_ERROR;
   }
 #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
 
-  if(data->set.str[STRING_SSL_CAFILE]) {
-    bool is_cert_file = is_file(data->set.str[STRING_SSL_CAFILE]);
+  if(ssl_cafile && verifypeer) {
+    bool is_cert_file = is_file(ssl_cafile);
 
     if(!is_cert_file) {
-      failf(data, "SSL: can't load CA certificate file %s",
-            data->set.str[STRING_SSL_CAFILE]);
+      failf(data, "SSL: can't load CA certificate file %s", ssl_cafile);
       return CURLE_SSL_CACERT_BADFILE;
     }
-    if(!data->set.ssl.verifypeer) {
-      failf(data, "SSL: CA certificate set, but certificate verification "
-            "is disabled");
-      return CURLE_SSL_CONNECT_ERROR;
-    }
   }
 
   /* Configure hostname check. SNI is used if available.
    * Both hostname check and SNI require SSLSetPeerDomainName().
    * Also: the verifyhost setting influences SNI usage */
-  if(data->set.ssl.verifyhost) {
-    err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
-    strlen(conn->host.name));
+  if(conn->ssl_config.verifyhost) {
+    err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname,
+    strlen(hostname));
 
     if(err != noErr) {
       infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
             err);
     }
 
-    if((Curl_inet_pton(AF_INET, conn->host.name, &addr))
+    if((Curl_inet_pton(AF_INET, hostname, &addr))
   #ifdef ENABLE_IPV6
-    || (Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+    || (Curl_inet_pton(AF_INET6, hostname, &addr))
   #endif
        ) {
-         infof(data, "WARNING: using IP address, SNI is being disabled by "
-         "the OS.\n");
+      infof(data, "WARNING: using IP address, SNI is being disabled by "
+            "the OS.\n");
     }
   }
+  else {
+    infof(data, "WARNING: disabling hostname validation also disables SNI.\n");
+  }
 
   /* Disable cipher suites that ST supports but are not safe. These ciphers
      are unlikely to be used in any case since ST gives other ciphers a much
@@ -1382,7 +1573,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
         running in an affected version of OS X. */
       if(darwinver_maj == 12 && darwinver_min <= 3 &&
          all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
-           continue;
+        continue;
       }
 #endif /* CURL_BUILD_MAC */
       switch(all_ciphers[i]) {
@@ -1474,21 +1665,22 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   /* We want to enable 1/n-1 when using a CBC cipher unless the user
      specifically doesn't want us doing that: */
   if(SSLSetSessionOption != NULL) {
+    /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */
     SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
-                      !data->set.ssl_enable_beast);
+                      !data->set.ssl.enable_beast);
     SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart,
                       data->set.ssl.falsestart); /* false start support */
   }
 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     char *ssl_sessionid;
     size_t ssl_sessionid_len;
 
     Curl_ssl_sessionid_lock(conn);
     if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
-                              &ssl_sessionid_len)) {
+                              &ssl_sessionid_len, sockindex)) {
       /* we got a session id, use it! */
       err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
       Curl_ssl_sessionid_unlock(conn);
@@ -1504,9 +1696,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
     else {
       CURLcode result;
       ssl_sessionid =
-        aprintf("%s:%d:%d:%s:%hu", data->set.str[STRING_SSL_CAFILE],
-                data->set.ssl.verifypeer, data->set.ssl.verifyhost,
-                conn->host.name, conn->remote_port);
+        aprintf("%s:%d:%d:%s:%hu", ssl_cafile,
+                verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
       ssl_sessionid_len = strlen(ssl_sessionid);
 
       err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
@@ -1516,7 +1707,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
         return CURLE_SSL_CONNECT_ERROR;
       }
 
-      result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len);
+      result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len,
+                                     sockindex);
       Curl_ssl_sessionid_unlock(conn);
       if(result) {
         failf(data, "failed to store ssl session");
@@ -1820,7 +2012,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
     return sslerr_to_curlerr(data, ret);
   }
 
-  switch (trust_eval) {
+  switch(trust_eval) {
     case kSecTrustResultUnspecified:
     case kSecTrustResultProceed:
       return CURLE_OK;
@@ -1834,6 +2026,112 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
   }
 }
 
+#ifdef DARWIN_SSL_PINNEDPUBKEY
+static CURLcode pkp_pin_peer_pubkey(struct SessionHandle *data,
+                                    SSLContextRef ctx,
+                                    const char *pinnedpubkey)
+{  /* Scratch */
+  size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
+  unsigned char *pubkey = NULL, *realpubkey = NULL, *spkiHeader = NULL;
+  CFDataRef publicKeyBits = NULL;
+
+  /* Result is returned to caller */
+  CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+
+  /* if a path wasn't specified, don't pin */
+  if(!pinnedpubkey)
+    return CURLE_OK;
+
+
+  if(!ctx)
+    return result;
+
+  do {
+    SecTrustRef trust;
+    OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
+    if(ret != noErr || trust == NULL)
+      break;
+
+    SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
+    CFRelease(trust);
+    if(keyRef == NULL)
+      break;
+
+#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
+
+    publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
+    CFRelease(keyRef);
+    if(publicKeyBits == NULL)
+      break;
+
+#elif DARWIN_SSL_PINNEDPUBKEY_V2
+
+    OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
+                                     &publicKeyBits);
+    CFRelease(keyRef);
+    if(success != errSecSuccess || publicKeyBits == NULL)
+      break;
+
+#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */
+
+    pubkeylen = CFDataGetLength(publicKeyBits);
+    pubkey = CFDataGetBytePtr(publicKeyBits);
+
+    switch(pubkeylen) {
+      case 526:
+        /* 4096 bit RSA pubkeylen == 526 */
+        spkiHeader = rsa4096SpkiHeader;
+        break;
+      case 270:
+        /* 2048 bit RSA pubkeylen == 270 */
+        spkiHeader = rsa2048SpkiHeader;
+        break;
+#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
+      case 65:
+        /* ecDSA secp256r1 pubkeylen == 65 */
+        spkiHeader = ecDsaSecp256r1SpkiHeader;
+        spkiHeaderLength = 26;
+        break;
+      case 97:
+        /* ecDSA secp384r1 pubkeylen == 97 */
+        spkiHeader = ecDsaSecp384r1SpkiHeader;
+        spkiHeaderLength = 23;
+        break;
+      default:
+        infof(data, "SSL: unhandled public key length: %d\n", pubkeylen);
+#elif DARWIN_SSL_PINNEDPUBKEY_V2
+      default:
+        /* ecDSA secp256r1 pubkeylen == 91 header already included?
+         * ecDSA secp384r1 header already included too
+         * we assume rest of algorithms do same, so do nothing
+         */
+        result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
+                                    pubkeylen);
+#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */
+        continue; /* break from loop */
+    }
+
+    realpubkeylen = pubkeylen + spkiHeaderLength;
+    realpubkey = malloc(realpubkeylen);
+    if(!realpubkey)
+      break;
+
+    memcpy(realpubkey, spkiHeader, spkiHeaderLength);
+    memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
+
+    result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
+                                  realpubkeylen);
+
+  } while(0);
+
+  Curl_safefree(realpubkey);
+  if(publicKeyBits != NULL)
+    CFRelease(publicKeyBits);
+
+  return result;
+}
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
 static CURLcode
 darwinssl_connect_step2(struct connectdata *conn, int sockindex)
 {
@@ -1842,6 +2140,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
   OSStatus err;
   SSLCipherSuite cipher;
   SSLProtocol protocol = 0;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
               || ssl_connect_2_reading == connssl->connecting_state
@@ -1851,7 +2151,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
   err = SSLHandshake(connssl->ssl_ctx);
 
   if(err != noErr) {
-    switch (err) {
+    switch(err) {
       case errSSLWouldBlock:  /* they're not done with us yet */
         connssl->connecting_state = connssl->ssl_direction ?
             ssl_connect_2_writing : ssl_connect_2_reading;
@@ -1860,8 +2160,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
       /* The below is errSSLServerAuthCompleted; it's not defined in
         Leopard's headers */
       case -9841:
-        if(data->set.str[STRING_SSL_CAFILE]) {
-          int res = verify_cert(data->set.str[STRING_SSL_CAFILE], data,
+        if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
+          int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
                                 connssl->ssl_ctx);
           if(res != CURLE_OK)
             return res;
@@ -1930,7 +2230,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
         return CURLE_SSL_CONNECT_ERROR;
       default:
         failf(data, "Unknown SSL protocol error in connection to %s:%d",
-              conn->host.name, err);
+              hostname, err);
         return CURLE_SSL_CONNECT_ERROR;
     }
   }
@@ -1938,10 +2238,21 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
     /* we have been connected fine, we're not waiting for anything else. */
     connssl->connecting_state = ssl_connect_3;
 
+#ifdef DARWIN_SSL_PINNEDPUBKEY
+    if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
+      CURLcode result = pkp_pin_peer_pubkey(data, connssl->ssl_ctx,
+                            data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
+      if(result) {
+        failf(data, "SSL: public key does not match pinned public key!");
+        return result;
+      }
+    }
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
     /* Informational message */
     (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
     (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
-    switch (protocol) {
+    switch(protocol) {
       case kSSLProtocol2:
         infof(data, "SSL 2.0 connection using %s\n",
               SSLCipherNameForNumber(cipher));
@@ -1973,9 +2284,11 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
   }
 }
 
-static CURLcode
-darwinssl_connect_step3(struct connectdata *conn,
-                        int sockindex)
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+/* This should be called during step3 of the connection at the earliest */
+static void
+show_verbose_server_cert(struct connectdata *conn,
+                         int sockindex)
 {
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -1987,9 +2300,9 @@ darwinssl_connect_step3(struct connectdata *conn,
   CFIndex i, count;
   SecTrustRef trust = NULL;
 
-  /* There is no step 3!
-   * Well, okay, if verbose mode is on, let's print the details of the
-   * server certificates. */
+  if(!connssl->ssl_ctx)
+    return;
+
 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
 #if CURL_BUILD_IOS
 #pragma unused(server_certs)
@@ -2086,6 +2399,23 @@ darwinssl_connect_step3(struct connectdata *conn,
     CFRelease(server_certs);
   }
 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+}
+#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
+
+static CURLcode
+darwinssl_connect_step3(struct connectdata *conn,
+                        int sockindex)
+{
+  struct Curl_easy *data = conn->data;
+  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(conn, sockindex);
+#endif
 
   connssl->connecting_state = ssl_connect_done;
   return CURLE_OK;
@@ -2363,8 +2693,8 @@ bool Curl_darwinssl_data_pending(const struct connectdata *conn,
     return false;
 }
 
-int Curl_darwinssl_random(unsigned char *entropy,
-                          size_t length)
+CURLcode Curl_darwinssl_random(unsigned char *entropy,
+                               size_t length)
 {
   /* arc4random_buf() isn't available on cats older than Lion, so let's
      do this manually for the benefit of the older cats. */
@@ -2378,7 +2708,7 @@ int Curl_darwinssl_random(unsigned char *entropy,
     random_number >>= 8;
   }
   i = random_number = 0;
-  return 0;
+  return CURLE_OK;
 }
 
 void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
@@ -2390,7 +2720,17 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
   (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
 }
 
-bool Curl_darwinssl_false_start(void) {
+void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
+                           size_t tmplen,
+                           unsigned char *sha256sum, /* output */
+                           size_t sha256len)
+{
+  assert(sha256len >= SHA256_DIGEST_LENGTH);
+  (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
+}
+
+bool Curl_darwinssl_false_start(void)
+{
 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
   if(SSLSetSessionOption != NULL)
     return TRUE;
@@ -2427,7 +2767,7 @@ static ssize_t darwinssl_send(struct connectdata *conn,
   if(connssl->ssl_write_buffered_length) {
     /* Write the buffered data: */
     err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
-    switch (err) {
+    switch(err) {
       case noErr:
         /* processed is always going to be 0 because we didn't write to
            the buffer, so return how much was written to the socket */
@@ -2447,7 +2787,7 @@ static ssize_t darwinssl_send(struct connectdata *conn,
     /* We've got new data to write: */
     err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
     if(err != noErr) {
-      switch (err) {
+      switch(err) {
         case errSSLWouldBlock:
           /* Data was buffered but not sent, we have to tell the caller
              to try sending again, and remember how much was buffered */
@@ -2476,7 +2816,7 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
   OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
 
   if(err != noErr) {
-    switch (err) {
+    switch(err) {
       case errSSLWouldBlock:  /* return how much we read (if anything) */
         if(processed)
           return (ssize_t)processed;
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.h b/Utilities/cmcurl/lib/vtls/darwinssl.h
index 8b185b6..fd372ff 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.h
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.h
@@ -8,7 +8,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman at gmail.com>.
- * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at 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,17 +42,40 @@ int Curl_darwinssl_check_cxn(struct connectdata *conn);
 bool Curl_darwinssl_data_pending(const struct connectdata *conn,
                                  int connindex);
 
-int Curl_darwinssl_random(unsigned char *entropy,
-                          size_t length);
+CURLcode Curl_darwinssl_random(unsigned char *entropy,
+                               size_t length);
 void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
                            size_t tmplen,
                            unsigned char *md5sum, /* output */
                            size_t md5len);
+void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
+                           size_t tmplen,
+                           unsigned char *sha256sum, /* output */
+                           size_t sha256len);
 bool Curl_darwinssl_false_start(void);
 
 /* Set the API backend definition to SecureTransport */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL
 
+/* pinned public key support tests */
+
+/* version 1 supports macOS 10.12+ and iOS 10+ */
+#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
+    (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED  >= 101200))
+#define DARWIN_SSL_PINNEDPUBKEY_V1 1
+#endif
+
+/* version 2 supports MacOSX 10.7+ */
+#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
+#define DARWIN_SSL_PINNEDPUBKEY_V2 1
+#endif
+
+#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
+/* this backend supports CURLOPT_PINNEDPUBLICKEY */
+#define DARWIN_SSL_PINNEDPUBKEY 1
+#define have_curlssl_pinnedpubkey 1
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
 /* API setup for SecureTransport */
 #define curlssl_init() (1)
 #define curlssl_cleanup() Curl_nop_stmt
@@ -70,6 +93,7 @@ bool Curl_darwinssl_false_start(void);
 #define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y)
 #define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z))
 #define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d)
+#define curlssl_sha256sum(a,b,c,d) Curl_darwinssl_sha256sum(a,b,c,d)
 #define curlssl_false_start() Curl_darwinssl_false_start()
 
 #endif /* USE_DARWINSSL */
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 3b0cfd5..bf75bdd 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -81,6 +81,10 @@
 #include "memdebug.h"
 
 
+/* Directions. */
+#define SOS_READ        0x01
+#define SOS_WRITE       0x02
+
 /* SSL version flags. */
 #define CURL_GSKPROTO_SSLV2     0
 #define CURL_GSKPROTO_SSLV2_MASK        (1 << CURL_GSKPROTO_SSLV2)
@@ -151,7 +155,7 @@ static const gskit_cipher  ciphertable[] = {
 static bool is_separator(char c)
 {
   /* Return whether character is a cipher list separator. */
-  switch (c) {
+  switch(c) {
   case ' ':
   case '\t':
   case ':':
@@ -167,7 +171,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
                              const char *procname, CURLcode defcode)
 {
   /* Process GSKit status and map it to a CURLcode. */
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
   case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
     return CURLE_OK;
@@ -190,7 +194,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
   case GSK_OS400_ERROR_NOT_REGISTERED:
     break;
   case GSK_ERROR_IO:
-    switch (errno) {
+    switch(errno) {
     case ENOMEM:
       return CURLE_OUT_OF_MEMORY;
     default:
@@ -211,7 +215,7 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
 {
   int rc = gsk_attribute_set_enum(h, id, value);
 
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
@@ -233,7 +237,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
 {
   int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
 
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
@@ -255,7 +259,7 @@ static CURLcode set_numeric(struct Curl_easy *data,
 {
   int rc = gsk_attribute_set_numeric_value(h, id, value);
 
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
@@ -275,7 +279,7 @@ static CURLcode set_callback(struct Curl_easy *data,
 {
   int rc = gsk_attribute_set_callback(h, id, info);
 
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
@@ -289,10 +293,11 @@ static CURLcode set_callback(struct Curl_easy *data,
 }
 
 
-static CURLcode set_ciphers(struct Curl_easy *data,
+static CURLcode set_ciphers(struct connectdata *conn,
                                         gsk_handle h, unsigned int *protoflags)
 {
-  const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST];
+  struct Curl_easy *data = conn->data;
+  const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
   const char *clp;
   const gskit_cipher *ctp;
   int i;
@@ -315,7 +320,7 @@ static CURLcode set_ciphers(struct Curl_easy *data,
 
   /* We allocate GSKit buffers of the same size as the input string: since
      GSKit tokens are always shorter than their cipher names, allocated buffers
-     will always be large enough to accomodate the result. */
+     will always be large enough to accommodate the result. */
   l = strlen(cipherlist) + 1;
   memset((char *) ciphers, 0, sizeof ciphers);
   for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
@@ -340,7 +345,7 @@ static CURLcode set_ciphers(struct Curl_easy *data,
       break;
     /* Search the cipher in our table. */
     for(ctp = ciphertable; ctp->name; ctp++)
-      if(strnequal(ctp->name, clp, l) && !ctp->name[l])
+      if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
         break;
     if(!ctp->name) {
       failf(data, "Unknown cipher %.*s", l, clp);
@@ -448,7 +453,7 @@ static CURLcode init_environment(struct Curl_easy *data,
   /* Creates the GSKit environment. */
 
   rc = gsk_environment_open(&h);
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     break;
   case GSK_INSUFFICIENT_STORAGE:
@@ -500,17 +505,195 @@ static void close_async_handshake(struct ssl_connect_data *connssl)
   connssl->iocport = -1;
 }
 
+/* SSL over SSL
+ * Problems:
+ * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To
+ *    pipe an SSL stream into another, it is therefore needed to have a pair
+ *    of such communicating sockets and handle the pipelining explicitly.
+ * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot
+ *    be used to produce the pipeline.
+ * The solution is to simulate socketpair() for AF_INET with low-level API
+ *    listen(), bind() and connect().
+ */
+
+static int
+inetsocketpair(int sv[2])
+{
+  int lfd;      /* Listening socket. */
+  int sfd;      /* Server socket. */
+  int cfd;      /* Client socket. */
+  int len;
+  struct sockaddr_in addr1;
+  struct sockaddr_in addr2;
+
+  /* Create listening socket on a local dynamic port. */
+  lfd = socket(AF_INET, SOCK_STREAM, 0);
+  if(lfd < 0)
+    return -1;
+  memset((char *) &addr1, 0, sizeof addr1);
+  addr1.sin_family = AF_INET;
+  addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  addr1.sin_port = 0;
+  if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) ||
+     listen(lfd, 2) < 0) {
+    close(lfd);
+    return -1;
+  }
+
+  /* Get the allocated port. */
+  len = sizeof addr1;
+  if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
+    close(lfd);
+    return -1;
+  }
+
+  /* Create the client socket. */
+  cfd = socket(AF_INET, SOCK_STREAM, 0);
+  if(cfd < 0) {
+    close(lfd);
+    return -1;
+  }
+
+  /* Request unblocking connection to the listening socket. */
+  curlx_nonblock(cfd, TRUE);
+  if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
+     errno != EINPROGRESS) {
+    close(lfd);
+    close(cfd);
+    return -1;
+  }
+
+  /* Get the client dynamic port for intrusion check below. */
+  len = sizeof addr2;
+  if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
+    close(lfd);
+    close(cfd);
+    return -1;
+  }
+
+  /* Accept the incoming connection and get the server socket. */
+  curlx_nonblock(lfd, TRUE);
+  for(;;) {
+    len = sizeof addr1;
+    sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
+    if(sfd < 0) {
+      close(lfd);
+      close(cfd);
+      return -1;
+    }
+
+    /* Check for possible intrusion from an external process. */
+    if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
+       addr1.sin_port == addr2.sin_port)
+      break;
+
+    /* Intrusion: reject incoming connection. */
+    close(sfd);
+  }
+
+  /* Done, return sockets and succeed. */
+  close(lfd);
+  curlx_nonblock(cfd, FALSE);
+  sv[0] = cfd;
+  sv[1] = sfd;
+  return 0;
+}
+
+static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
+                           int directions)
+{
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
+  fd_set fds_read;
+  fd_set fds_write;
+  int n;
+  int m;
+  int i;
+  int ret = 0;
+  struct timeval tv = {0, 0};
+  char buf[CURL_MAX_WRITE_SIZE];
+
+  if(!connssl->use || !connproxyssl->use)
+    return 0;   /* No SSL over SSL: OK. */
+
+  FD_ZERO(&fds_read);
+  FD_ZERO(&fds_write);
+  n = -1;
+  if(directions & SOS_READ) {
+    FD_SET(connssl->remotefd, &fds_write);
+    n = connssl->remotefd;
+  }
+  if(directions & SOS_WRITE) {
+    FD_SET(connssl->remotefd, &fds_read);
+    n = connssl->remotefd;
+    FD_SET(conn->sock[sockindex], &fds_write);
+    if(n < conn->sock[sockindex])
+      n = conn->sock[sockindex];
+  }
+  i = select(n + 1, &fds_read, &fds_write, NULL, &tv);
+  if(i < 0)
+    return -1;  /* Select error. */
+
+  if(FD_ISSET(connssl->remotefd, &fds_write)) {
+    /* Try getting data from HTTPS proxy and pipe it upstream. */
+    n = 0;
+    i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
+    switch(i) {
+    case GSK_OK:
+      if(n) {
+        i = write(connssl->remotefd, buf, n);
+        if(i < 0)
+          return -1;
+        ret = 1;
+      }
+      break;
+    case GSK_OS400_ERROR_TIMED_OUT:
+    case GSK_WOULD_BLOCK:
+      break;
+    default:
+      return -1;
+    }
+  }
+
+  if(FD_ISSET(connssl->remotefd, &fds_read) &&
+     FD_ISSET(conn->sock[sockindex], &fds_write)) {
+    /* Pipe data to HTTPS proxy. */
+    n = read(connssl->remotefd, buf, sizeof buf);
+    if(n < 0)
+      return -1;
+    if(n) {
+      i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
+      if(i != GSK_OK || n != m)
+        return -1;
+      ret = 1;
+    }
+  }
+
+  return ret;  /* OK */
+}
+
 
-static void close_one(struct ssl_connect_data *conn,
-                      struct Curl_easy *data)
+static void close_one(struct ssl_connect_data *connssl,
+                      struct connectdata *conn, int sockindex)
 {
-  if(conn->handle) {
-    gskit_status(data, gsk_secure_soc_close(&conn->handle),
+  if(connssl->handle) {
+    gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
               "gsk_secure_soc_close()", 0);
-    conn->handle = (gsk_handle) NULL;
+    /* Last chance to drain output. */
+    while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
+      ;
+    connssl->handle = (gsk_handle) NULL;
+    if(connssl->localfd >= 0) {
+      close(connssl->localfd);
+      connssl->localfd = -1;
+    }
+    if(connssl->remotefd >= 0) {
+      close(connssl->remotefd);
+      connssl->remotefd = -1;
+    }
   }
-  if(conn->iocport >= 0)
-    close_async_handshake(conn);
+  if(connssl->iocport >= 0)
+    close_async_handshake(connssl);
 }
 
 
@@ -518,13 +701,18 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
                            const void *mem, size_t len, CURLcode *curlcode)
 {
   struct Curl_easy *data = conn->data;
-  CURLcode cc;
+  CURLcode cc = CURLE_SEND_ERROR;
   int written;
 
-  cc = gskit_status(data,
-                    gsk_secure_soc_write(conn->ssl[sockindex].handle,
-                                         (char *) mem, (int) len, &written),
-                    "gsk_secure_soc_write()", CURLE_SEND_ERROR);
+  if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
+    cc = gskit_status(data,
+                      gsk_secure_soc_write(conn->ssl[sockindex].handle,
+                                           (char *) mem, (int) len, &written),
+                      "gsk_secure_soc_write()", CURLE_SEND_ERROR);
+    if(cc == CURLE_OK)
+      if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
+        cc = CURLE_SEND_ERROR;
+  }
   if(cc != CURLE_OK) {
     *curlcode = cc;
     written = -1;
@@ -539,19 +727,61 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
   struct Curl_easy *data = conn->data;
   int buffsize;
   int nread;
-  CURLcode cc;
+  CURLcode cc = CURLE_RECV_ERROR;
 
-  buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
-  cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
-                                              buf, buffsize, &nread),
-                    "gsk_secure_soc_read()", CURLE_RECV_ERROR);
-  if(cc != CURLE_OK) {
+  if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
+    buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
+    cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+                                                buf, buffsize, &nread),
+                      "gsk_secure_soc_read()", CURLE_RECV_ERROR);
+  }
+  switch(cc) {
+  case CURLE_OK:
+    break;
+  case CURLE_OPERATION_TIMEDOUT:
+    cc = CURLE_AGAIN;
+  default:
     *curlcode = cc;
     nread = -1;
+    break;
   }
   return (ssize_t) nread;
 }
 
+static CURLcode
+set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
+{
+  struct Curl_easy *data = conn->data;
+  long ssl_version = SSL_CONN_CONFIG(version);
+  long ssl_version_max = SSL_CONN_CONFIG(version_max);
+  long i = ssl_version;
+  switch(ssl_version_max) {
+    case CURL_SSLVERSION_MAX_NONE:
+      ssl_version_max = ssl_version;
+      break;
+    case CURL_SSLVERSION_MAX_DEFAULT:
+      ssl_version_max = CURL_SSLVERSION_TLSv1_2;
+      break;
+  }
+  for(; i <= (ssl_version_max >> 16); ++i) {
+    switch(i) {
+      case CURL_SSLVERSION_TLSv1_0:
+        *protoflags |= CURL_GSKPROTO_TLSV10_MASK;
+        break;
+      case CURL_SSLVERSION_TLSv1_1:
+        *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
+        break;
+      case CURL_SSLVERSION_TLSv1_2:
+        *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
+        break;
+      case CURL_SSLVERSION_TLSv1_3:
+        failf(data, "GSKit: TLS 1.3 is not yet supported");
+        return CURLE_SSL_CONNECT_ERROR;
+    }
+  }
+
+  return CURLE_OK;
+}
 
 static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
 {
@@ -560,18 +790,26 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   gsk_handle envir;
   CURLcode result;
   int rc;
-  char *keyringfile;
-  char *keyringpwd;
-  char *keyringlabel;
-  char *sni;
-  unsigned int protoflags;
+  const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
+  const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
+  const char * const keyringlabel = SSL_SET_OPTION(cert);
+  const long int ssl_version = SSL_CONN_CONFIG(version);
+  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+  const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
+    conn->host.name;
+  const char *sni;
+  unsigned int protoflags = 0;
   long timeout;
   Qso_OverlappedIO_t commarea;
+  int sockpair[2];
+  static const int sobufsize = CURL_MAX_WRITE_SIZE;
 
   /* Create SSL environment, start (preferably asynchronous) handshake. */
 
   connssl->handle = (gsk_handle) NULL;
   connssl->iocport = -1;
+  connssl->localfd = -1;
+  connssl->remotefd = -1;
 
   /* GSKit supports two ways of specifying an SSL context: either by
    *  application identifier (that should have been defined at the system
@@ -586,9 +824,6 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
    *  application identifier mode is tried first, as recommended in IBM doc.
    */
 
-  keyringfile = data->set.str[STRING_SSL_CAFILE];
-  keyringpwd = data->set.str[STRING_KEY_PASSWD];
-  keyringlabel = data->set.str[STRING_CERT];
   envir = (gsk_handle) NULL;
 
   if(keyringlabel && *keyringlabel && !keyringpwd &&
@@ -613,32 +848,51 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   if(result)
     return result;
 
+  /* Establish a pipelining socket pair for SSL over SSL. */
+  if(conn->proxy_ssl[sockindex].use) {
+    if(inetsocketpair(sockpair))
+      return CURLE_SSL_CONNECT_ERROR;
+    connssl->localfd = sockpair[0];
+    connssl->remotefd = sockpair[1];
+    setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
+               (void *) sobufsize, sizeof sobufsize);
+    setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
+               (void *) sobufsize, sizeof sobufsize);
+    setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
+               (void *) sobufsize, sizeof sobufsize);
+    setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
+               (void *) sobufsize, sizeof sobufsize);
+    curlx_nonblock(connssl->localfd, TRUE);
+    curlx_nonblock(connssl->remotefd, TRUE);
+  }
+
   /* Determine which SSL/TLS version should be enabled. */
-  protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
-               CURL_GSKPROTO_TLSV12_MASK;
-  sni = conn->host.name;
-  switch (data->set.ssl.version) {
+  sni = hostname;
+  switch(ssl_version) {
   case CURL_SSLVERSION_SSLv2:
     protoflags = CURL_GSKPROTO_SSLV2_MASK;
-    sni = (char *) NULL;
+    sni = NULL;
     break;
   case CURL_SSLVERSION_SSLv3:
     protoflags = CURL_GSKPROTO_SSLV3_MASK;
-    sni = (char *) NULL;
+    sni = NULL;
     break;
+  case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
     protoflags = CURL_GSKPROTO_TLSV10_MASK |
                  CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
     break;
   case CURL_SSLVERSION_TLSv1_0:
-    protoflags = CURL_GSKPROTO_TLSV10_MASK;
-    break;
   case CURL_SSLVERSION_TLSv1_1:
-    protoflags = CURL_GSKPROTO_TLSV11_MASK;
-    break;
   case CURL_SSLVERSION_TLSv1_2:
-    protoflags = CURL_GSKPROTO_TLSV12_MASK;
+  case CURL_SSLVERSION_TLSv1_3:
+    result = set_ssl_version_min_max(&protoflags, conn);
+    if(result != CURLE_OK)
+      return result;
     break;
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
   /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
@@ -661,9 +915,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
                            (timeout + 999) / 1000);
   }
   if(!result)
-    result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
+    result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
   if(!result)
-    result = set_ciphers(data, connssl->handle, &protoflags);
+    result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
+                         connssl->localfd: conn->sock[sockindex]);
+  if(!result)
+    result = set_ciphers(conn, connssl->handle, &protoflags);
   if(!protoflags) {
     failf(data, "No SSL protocol/cipher combination enabled");
     result = CURLE_SSL_CIPHER;
@@ -706,7 +963,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   }
   if(!result)
     result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
-                      data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
+                      verifypeer? GSK_SERVER_AUTH_FULL:
                       GSK_SERVER_AUTH_PASSTHRU, FALSE);
 
   if(!result) {
@@ -730,6 +987,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
     else if(errno != ENOBUFS)
       result = gskit_status(data, GSK_ERROR_IO,
                             "QsoCreateIOCompletionPort()", 0);
+    else if(conn->proxy_ssl[sockindex].use) {
+      /* Cannot pipeline while handshaking synchronously. */
+      result = CURLE_SSL_CONNECT_ERROR;
+    }
     else {
       /* No more completion port available. Use synchronous IO. */
       result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
@@ -742,7 +1003,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   }
 
   /* Error: rollback. */
-  close_one(connssl, data);
+  close_one(connssl, conn, sockindex);
   return result;
 }
 
@@ -765,7 +1026,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
       timeout_ms = 0;
     stmv.tv_sec = timeout_ms / 1000;
     stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
-    switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
+    switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
     case 1:             /* Operation complete. */
       break;
     case -1:            /* An error occurred: handshake still in progress. */
@@ -822,7 +1083,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
     infof(data, "Server certificate:\n");
     p = cdev;
     for(i = 0; i++ < cdec; p++)
-      switch (p->cert_data_id) {
+      switch(p->cert_data_id) {
       case CERT_BODY_DER:
         cert = p->cert_data_p;
         certend = cert + cdev->cert_data_l;
@@ -865,14 +1126,14 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
   }
 
   /* Check pinned public key. */
-  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+  ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+                         data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
   if(!result && ptr) {
     curl_X509certificate x509;
     curl_asn1Element *p;
 
-    if(!cert)
+    if(Curl_parseX509(&x509, cert, certend))
       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-    Curl_parseX509(&x509, cert, certend);
     p = &x509.subjectPublicKeyInfo;
     result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
     if(result) {
@@ -913,6 +1174,11 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
       result = gskit_connect_step1(conn, sockindex);
   }
 
+  /* Handle handshake pipelining. */
+  if(!result)
+    if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
+      result = CURLE_SSL_CONNECT_ERROR;
+
   /* Step 2: check if handshake is over. */
   if(!result && connssl->connecting_state == ssl_connect_2) {
     /* check allowed time left */
@@ -927,12 +1193,17 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
       result = gskit_connect_step2(conn, sockindex, nonblocking);
   }
 
+  /* Handle handshake pipelining. */
+  if(!result)
+    if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
+      result = CURLE_SSL_CONNECT_ERROR;
+
   /* Step 3: gather certificate info, verify host. */
   if(!result && connssl->connecting_state == ssl_connect_3)
     result = gskit_connect_step3(conn, sockindex);
 
   if(result)
-    close_one(connssl, data);
+    close_one(connssl, conn, sockindex);
   else if(connssl->connecting_state == ssl_connect_done) {
     connssl->state = ssl_connection_complete;
     connssl->connecting_state = ssl_connect_1;
@@ -976,11 +1247,8 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
 
 void Curl_gskit_close(struct connectdata *conn, int sockindex)
 {
-  struct Curl_easy *data = conn->data;
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
-  if(connssl->use)
-    close_one(connssl, data);
+  close_one(&conn->ssl[sockindex], conn, sockindex);
+  close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
 }
 
 
@@ -999,7 +1267,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
     return 0;
 
-  close_one(connssl, data);
+  close_one(connssl, conn, sockindex);
   rc = 0;
   what = SOCKET_READABLE(conn->sock[sockindex],
                          SSL_SHUTDOWN_TIMEOUT);
diff --git a/Utilities/cmcurl/lib/vtls/gskit.h b/Utilities/cmcurl/lib/vtls/gskit.h
index 41483cb..2297592 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.h
+++ b/Utilities/cmcurl/lib/vtls/gskit.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -41,6 +41,9 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex);
 size_t Curl_gskit_version(char *buffer, size_t size);
 int Curl_gskit_check_cxn(struct connectdata *cxn);
 
+/* Support HTTPS-proxy */
+/* TODO: add '#define HTTPS_PROXY_SUPPORT 1' and fix test #1014 (if need) */
+
 /* Set the API backend definition to GSKit */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT
 
@@ -64,7 +67,7 @@ int Curl_gskit_check_cxn(struct connectdata *cxn);
 #define curlssl_version Curl_gskit_version
 #define curlssl_check_cxn(x) Curl_gskit_check_cxn(x)
 #define curlssl_data_pending(x,y) 0
-#define curlssl_random(x,y,z) -1
+#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN)
 
 #endif /* USE_GSKIT */
 
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 5c87c7f..844be2d 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -68,7 +68,7 @@
 #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
 #endif
 #ifndef GNUTLS_INT_TO_POINTER_CAST
-#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
+#define GNUTLS_INT_TO_POINTER_CAST(i) ((void *) (long) (i))
 #endif
 
 /* Enable GnuTLS debugging by defining GTLSDEBUG */
@@ -92,11 +92,11 @@ static bool gtls_inited = FALSE;
 #    define GNUTLS_MAPS_WINSOCK_ERRORS 1
 #  endif
 
-#  if (GNUTLS_VERSION_NUMBER >= 0x030200)
+#  if HAVE_GNUTLS_ALPN_SET_PROTOCOLS
 #    define HAS_ALPN
 #  endif
 
-#  if (GNUTLS_VERSION_NUMBER >= 0x03020d)
+#  if HAVE_GNUTLS_OCSP_REQ_INIT
 #    define HAS_OCSP
 #  endif
 
@@ -171,6 +171,16 @@ static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
   return ret;
 }
 
+static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
+{
+  return gnutls_record_send((gnutls_session_t) s, buf, len);
+}
+
+static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
+{
+  return gnutls_record_recv((gnutls_session_t) s, buf, len);
+}
+
 /* Curl_gtls_init()
  *
  * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
@@ -201,18 +211,20 @@ int Curl_gtls_cleanup(void)
   return 1;
 }
 
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
 static void showtime(struct Curl_easy *data,
                      const char *text,
                      time_t stamp)
 {
   struct tm buffer;
   const struct tm *tm = &buffer;
+  char str[96];
   CURLcode result = Curl_gmtime(stamp, &buffer);
   if(result)
     return;
 
-  snprintf(data->state.buffer,
-           BUFSIZE,
+  snprintf(str,
+           sizeof(str),
            "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
            text,
            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
@@ -222,17 +234,19 @@ static void showtime(struct Curl_easy *data,
            tm->tm_hour,
            tm->tm_min,
            tm->tm_sec);
-  infof(data, "%s\n", data->state.buffer);
+  infof(data, "%s\n", str);
 }
+#endif
 
-static gnutls_datum_t load_file (const char *file)
+static gnutls_datum_t load_file(const char *file)
 {
   FILE *f;
   gnutls_datum_t loaded_file = { NULL, 0 };
   long filelen;
   void *ptr;
 
-  if(!(f = fopen(file, "rb")))
+  f = fopen(file, "rb");
+  if(!f)
     return loaded_file;
   if(fseek(f, 0, SEEK_END) != 0
      || (filelen = ftell(f)) < 0
@@ -251,7 +265,8 @@ out:
   return loaded_file;
 }
 
-static void unload_file(gnutls_datum_t data) {
+static void unload_file(gnutls_datum_t data)
+{
   free(data.data);
 }
 
@@ -266,7 +281,7 @@ static CURLcode handshake(struct connectdata *conn,
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   gnutls_session_t session = conn->ssl[sockindex].session;
   curl_socket_t sockfd = conn->sock[sockindex];
-  long timeout_ms;
+  time_t timeout_ms;
   int rc;
   int what;
 
@@ -302,7 +317,7 @@ static CURLcode handshake(struct connectdata *conn,
           return CURLE_OK;
         else if(timeout_ms) {
           /* timeout */
-          failf(data, "SSL connection timeout at %ld", timeout_ms);
+          failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
           return CURLE_OPERATION_TIMEDOUT;
         }
       }
@@ -363,14 +378,112 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
   return -1;
 }
 
+#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
+static CURLcode
+set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn)
+{
+  struct Curl_easy *data = conn->data;
+  long ssl_version = SSL_CONN_CONFIG(version);
+  long ssl_version_max = SSL_CONN_CONFIG(version_max);
+  long i = ssl_version;
+  long protocol_priority_idx = 0;
+
+  switch(ssl_version_max) {
+    case CURL_SSLVERSION_MAX_NONE:
+      ssl_version_max = ssl_version << 16;
+      break;
+    case CURL_SSLVERSION_MAX_DEFAULT:
+      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      break;
+  }
+
+  for(; i <= (ssl_version_max >> 16) &&
+        protocol_priority_idx < list_size; ++i) {
+    switch(i) {
+      case CURL_SSLVERSION_TLSv1_0:
+        protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0;
+        break;
+      case CURL_SSLVERSION_TLSv1_1:
+        protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1;
+        break;
+      case CURL_SSLVERSION_TLSv1_2:
+        protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2;
+        break;
+      case CURL_SSLVERSION_TLSv1_3:
+        failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+        return CURLE_SSL_CONNECT_ERROR;
+    }
+  }
+  return CURLE_OK;
+}
+#else
+#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
+/* If GnuTLS was compiled without support for SRP it will error out if SRP is
+   requested in the priority string, so treat it specially
+ */
+#define GNUTLS_SRP "+SRP"
+
+static CURLcode
+set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
+{
+  struct Curl_easy *data = conn->data;
+  long ssl_version = SSL_CONN_CONFIG(version);
+  long ssl_version_max = SSL_CONN_CONFIG(version_max);
+  if(ssl_version == CURL_SSLVERSION_TLSv1_3 ||
+     ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) {
+    failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+    return CURLE_SSL_CONNECT_ERROR;
+  }
+  if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
+    ssl_version_max = ssl_version << 16;
+  }
+  switch(ssl_version | ssl_version_max) {
+    case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
+      *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+                      "+VERS-TLS1.0:" GNUTLS_SRP;
+      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:" GNUTLS_SRP;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
+    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:" GNUTLS_SRP;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
+      *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+                      "+VERS-TLS1.1:" GNUTLS_SRP;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
+    case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
+      *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+                      "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
+    case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
+      *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
+                      "+VERS-TLS1.2:" GNUTLS_SRP;
+      return CURLE_OK;
+  }
+
+  failf(data, "GnuTLS: cannot set ssl protocol");
+  return CURLE_SSL_CONNECT_ERROR;
+}
+#endif
+
 static CURLcode
 gtls_connect_step1(struct connectdata *conn,
                    int sockindex)
 {
   struct Curl_easy *data = conn->data;
+  unsigned int init_flags;
   gnutls_session_t session;
   int rc;
   bool sni = TRUE; /* default is SNI enabled */
+  void *transport_ptr = NULL;
+  gnutls_push_func gnutls_transport_push = NULL;
+  gnutls_pull_func gnutls_transport_pull = NULL;
 #ifdef ENABLE_IPV6
   struct in6_addr addr;
 #else
@@ -390,17 +503,15 @@ gtls_connect_step1(struct connectdata *conn,
     GNUTLS_CIPHER_3DES_CBC,
   };
   static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
-  static int protocol_priority[] = { 0, 0, 0, 0 };
+  int protocol_priority[] = { 0, 0, 0, 0 };
 #else
-#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
-/* If GnuTLS was compiled without support for SRP it will error out if SRP is
-   requested in the priority string, so treat it specially
- */
-#define GNUTLS_SRP "+SRP"
-  const char* prioritylist;
+  const char *prioritylist;
   const char *err = NULL;
 #endif
 
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+
   if(conn->ssl[sockindex].state == ssl_connection_complete)
     /* to make us tolerant against being called more than once for the
        same connection */
@@ -409,12 +520,11 @@ gtls_connect_step1(struct connectdata *conn,
   if(!gtls_inited)
     Curl_gtls_init();
 
-  /* GnuTLS only supports SSLv3 and TLSv1 */
-  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
     failf(data, "GnuTLS does not support SSLv2");
     return CURLE_SSL_CONNECT_ERROR;
   }
-  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
+  else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
     sni = FALSE; /* SSLv3 has no SNI */
 
   /* allocate a cred struct */
@@ -425,8 +535,8 @@ gtls_connect_step1(struct connectdata *conn,
   }
 
 #ifdef USE_TLS_SRP
-  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
-    infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+  if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
+    infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
 
     rc = gnutls_srp_allocate_client_credentials(
            &conn->ssl[sockindex].srp_client_cred);
@@ -438,8 +548,8 @@ gtls_connect_step1(struct connectdata *conn,
 
     rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
                                            srp_client_cred,
-                                           data->set.ssl.username,
-                                           data->set.ssl.password);
+                                           SSL_SET_OPTION(username),
+                                           SSL_SET_OPTION(password));
     if(rc != GNUTLS_E_SUCCESS) {
       failf(data, "gnutls_srp_set_client_cred() failed: %s",
             gnutls_strerror(rc));
@@ -448,68 +558,75 @@ gtls_connect_step1(struct connectdata *conn,
   }
 #endif
 
-  if(data->set.ssl.CAfile) {
+  if(SSL_CONN_CONFIG(CAfile)) {
     /* set the trusted CA cert bundle file */
     gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
 
     rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
-                                                data->set.ssl.CAfile,
+                                                SSL_CONN_CONFIG(CAfile),
                                                 GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
       infof(data, "error reading ca cert file %s (%s)\n",
-            data->set.ssl.CAfile, gnutls_strerror(rc));
-      if(data->set.ssl.verifypeer)
+            SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
+      if(SSL_CONN_CONFIG(verifypeer))
         return CURLE_SSL_CACERT_BADFILE;
     }
     else
-      infof(data, "found %d certificates in %s\n",
-            rc, data->set.ssl.CAfile);
+      infof(data, "found %d certificates in %s\n", rc,
+            SSL_CONN_CONFIG(CAfile));
   }
 
 #ifdef HAS_CAPATH
-  if(data->set.ssl.CApath) {
+  if(SSL_CONN_CONFIG(CApath)) {
     /* set the trusted CA cert directory */
     rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
-                                                data->set.ssl.CApath,
-                                                GNUTLS_X509_FMT_PEM);
+                                               SSL_CONN_CONFIG(CApath),
+                                               GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
       infof(data, "error reading ca cert file %s (%s)\n",
-            data->set.ssl.CAfile, gnutls_strerror(rc));
-      if(data->set.ssl.verifypeer)
+            SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
+      if(SSL_CONN_CONFIG(verifypeer))
         return CURLE_SSL_CACERT_BADFILE;
     }
     else
       infof(data, "found %d certificates in %s\n",
-            rc, data->set.ssl.CApath);
+            rc, SSL_CONN_CONFIG(CApath));
   }
 #endif
 
 #ifdef CURL_CA_FALLBACK
   /* use system ca certificate store as fallback */
-  if(data->set.ssl.verifypeer &&
-     !(data->set.ssl.CAfile || data->set.ssl.CApath)) {
+  if(SSL_CONN_CONFIG(verifypeer) &&
+     !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
     gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred);
   }
 #endif
 
-  if(data->set.ssl.CRLfile) {
+  if(SSL_SET_OPTION(CRLfile)) {
     /* set the CRL list file */
     rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
-                                              data->set.ssl.CRLfile,
+                                              SSL_SET_OPTION(CRLfile),
                                               GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
       failf(data, "error reading crl file %s (%s)",
-            data->set.ssl.CRLfile, gnutls_strerror(rc));
+            SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
       return CURLE_SSL_CRL_BADFILE;
     }
     else
       infof(data, "found %d CRL in %s\n",
-            rc, data->set.ssl.CRLfile);
+            rc, SSL_SET_OPTION(CRLfile));
   }
 
   /* Initialize TLS session as a client */
-  rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
+  init_flags = GNUTLS_CLIENT;
+
+#if defined(GNUTLS_NO_TICKETS)
+  /* Disable TLS session tickets */
+  init_flags |= GNUTLS_NO_TICKETS;
+#endif
+
+  rc = gnutls_init(&conn->ssl[sockindex].session, init_flags);
   if(rc != GNUTLS_E_SUCCESS) {
     failf(data, "gnutls_init() failed: %d", rc);
     return CURLE_SSL_CONNECT_ERROR;
@@ -518,13 +635,13 @@ gtls_connect_step1(struct connectdata *conn,
   /* convenient assign */
   session = conn->ssl[sockindex].session;
 
-  if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+  if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
 #ifdef ENABLE_IPV6
-     (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+     (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
 #endif
      sni &&
-     (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
-                             strlen(conn->host.name)) < 0))
+     (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");
 
@@ -545,13 +662,13 @@ gtls_connect_step1(struct connectdata *conn,
   if(rc != GNUTLS_E_SUCCESS)
     return CURLE_SSL_CONNECT_ERROR;
 
-  if(data->set.ssl.cipher_list != NULL) {
+  if(SSL_CONN_CONFIG(cipher_list) != NULL) {
     failf(data, "can't pass a custom cipher list to older GnuTLS"
           " versions");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  switch (data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
     case CURL_SSLVERSION_SSLv3:
       protocol_priority[0] = GNUTLS_SSL3;
       break;
@@ -562,19 +679,22 @@ gtls_connect_step1(struct connectdata *conn,
       protocol_priority[2] = GNUTLS_TLS1_2;
       break;
     case CURL_SSLVERSION_TLSv1_0:
-      protocol_priority[0] = GNUTLS_TLS1_0;
-      break;
     case CURL_SSLVERSION_TLSv1_1:
-      protocol_priority[0] = GNUTLS_TLS1_1;
-      break;
     case CURL_SSLVERSION_TLSv1_2:
-      protocol_priority[0] = GNUTLS_TLS1_2;
-    break;
-      case CURL_SSLVERSION_SSLv2:
-    default:
+    case CURL_SSLVERSION_TLSv1_3:
+      {
+        CURLcode result = set_ssl_version_min_max(protocol_priority,
+                sizeof(protocol_priority)/sizeof(protocol_priority[0]), conn);
+        if(result != CURLE_OK)
+          return result;
+        break;
+      }
+    case CURL_SSLVERSION_SSLv2:
       failf(data, "GnuTLS does not support SSLv2");
       return CURLE_SSL_CONNECT_ERROR;
-      break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
   }
   rc = gnutls_protocol_set_priority(session, protocol_priority);
   if(rc != GNUTLS_E_SUCCESS) {
@@ -586,7 +706,7 @@ gtls_connect_step1(struct connectdata *conn,
   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
    * removed if a run-time error indicates that SRP is not supported by this
    * GnuTLS version */
-  switch (data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
     case CURL_SSLVERSION_SSLv3:
       prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
       sni = false;
@@ -596,22 +716,21 @@ gtls_connect_step1(struct connectdata *conn,
       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
       break;
     case CURL_SSLVERSION_TLSv1_0:
-      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
-                     "+VERS-TLS1.0:" GNUTLS_SRP;
-      break;
     case CURL_SSLVERSION_TLSv1_1:
-      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
-                     "+VERS-TLS1.1:" GNUTLS_SRP;
-      break;
     case CURL_SSLVERSION_TLSv1_2:
-      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
-                     "+VERS-TLS1.2:" GNUTLS_SRP;
-      break;
+    case CURL_SSLVERSION_TLSv1_3:
+      {
+        CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
+        if(result != CURLE_OK)
+          return result;
+        break;
+      }
     case CURL_SSLVERSION_SSLv2:
-    default:
       failf(data, "GnuTLS does not support SSLv2");
       return CURLE_SSL_CONNECT_ERROR;
-      break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
   }
   rc = gnutls_priority_set_direct(session, prioritylist, &err);
   if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
@@ -661,8 +780,8 @@ gtls_connect_step1(struct connectdata *conn,
   }
 #endif
 
-  if(data->set.str[STRING_CERT]) {
-    if(data->set.str[STRING_KEY_PASSWD]) {
+  if(SSL_SET_OPTION(cert)) {
+    if(SSL_SET_OPTION(key_passwd)) {
 #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
       const unsigned int supported_key_encryption_algorithms =
         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
@@ -671,11 +790,11 @@ gtls_connect_step1(struct connectdata *conn,
         GNUTLS_PKCS_USE_PBES2_AES_256;
       rc = gnutls_certificate_set_x509_key_file2(
            conn->ssl[sockindex].cred,
-           data->set.str[STRING_CERT],
-           data->set.str[STRING_KEY] ?
-           data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
-           do_file_type(data->set.str[STRING_CERT_TYPE]),
-           data->set.str[STRING_KEY_PASSWD],
+           SSL_SET_OPTION(cert),
+           SSL_SET_OPTION(key) ?
+           SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+           do_file_type(SSL_SET_OPTION(cert_type)),
+           SSL_SET_OPTION(key_passwd),
            supported_key_encryption_algorithms);
       if(rc != GNUTLS_E_SUCCESS) {
         failf(data,
@@ -689,15 +808,14 @@ gtls_connect_step1(struct connectdata *conn,
 #endif
     }
     else {
-      rc = gnutls_certificate_set_x509_key_file(
+      if(gnutls_certificate_set_x509_key_file(
            conn->ssl[sockindex].cred,
-           data->set.str[STRING_CERT],
-           data->set.str[STRING_KEY] ?
-           data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
-           do_file_type(data->set.str[STRING_CERT_TYPE]) );
-      if(rc != GNUTLS_E_SUCCESS) {
-        failf(data, "error reading X.509 key or certificate file: %s",
-              gnutls_strerror(rc));
+           SSL_SET_OPTION(cert),
+           SSL_SET_OPTION(key) ?
+           SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+           do_file_type(SSL_SET_OPTION(cert_type)) ) !=
+         GNUTLS_E_SUCCESS) {
+        failf(data, "error reading X.509 key or certificate file");
         return CURLE_SSL_CONNECT_ERROR;
       }
     }
@@ -705,7 +823,7 @@ gtls_connect_step1(struct connectdata *conn,
 
 #ifdef USE_TLS_SRP
   /* put the credentials to the current session */
-  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+  if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
                                 conn->ssl[sockindex].srp_client_cred);
     if(rc != GNUTLS_E_SUCCESS) {
@@ -724,19 +842,30 @@ gtls_connect_step1(struct connectdata *conn,
     }
   }
 
-  /* set the connection handle (file descriptor for the socket) */
-  gnutls_transport_set_ptr(session,
-                           GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
+  if(conn->proxy_ssl[sockindex].use) {
+    transport_ptr = conn->proxy_ssl[sockindex].session;
+    gnutls_transport_push = Curl_gtls_push_ssl;
+    gnutls_transport_pull = Curl_gtls_pull_ssl;
+  }
+  else {
+    /* file descriptor for the socket */
+    transport_ptr = GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]);
+    gnutls_transport_push = Curl_gtls_push;
+    gnutls_transport_pull = Curl_gtls_pull;
+  }
+
+  /* set the connection handle */
+  gnutls_transport_set_ptr(session, transport_ptr);
 
   /* register callback functions to send and receive data. */
-  gnutls_transport_set_push_function(session, Curl_gtls_push);
-  gnutls_transport_set_pull_function(session, Curl_gtls_pull);
+  gnutls_transport_set_push_function(session, gnutls_transport_push);
+  gnutls_transport_set_pull_function(session, gnutls_transport_pull);
 
   /* lowat must be set to zero when using custom push and pull functions. */
   gnutls_transport_set_lowat(session, 0);
 
 #ifdef HAS_OCSP
-  if(data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
     if(rc != GNUTLS_E_SUCCESS) {
       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
@@ -747,17 +876,17 @@ gtls_connect_step1(struct connectdata *conn,
 
   /* This might be a reconnect, so we check for a session ID in the cache
      to speed up things */
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     void *ssl_sessionid;
     size_t ssl_idsize;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
+    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
       /* we got a session id, use it! */
       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\n");
     }
     Curl_ssl_sessionid_unlock(conn);
   }
@@ -836,8 +965,6 @@ gtls_connect_step3(struct connectdata *conn,
   gnutls_datum_t issuerp;
   char certbuf[256] = ""; /* big enough? */
   size_t size;
-  unsigned int algo;
-  unsigned int bits;
   time_t certclock;
   const char *ptr;
   struct Curl_easy *data = conn->data;
@@ -847,8 +974,13 @@ gtls_connect_step3(struct connectdata *conn,
   gnutls_datum_t proto;
 #endif
   CURLcode result = CURLE_OK;
-
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+  unsigned int algo;
+  unsigned int bits;
   gnutls_protocol_t version = gnutls_protocol_get_version(session);
+#endif
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
@@ -866,13 +998,13 @@ gtls_connect_step3(struct connectdata *conn,
 
   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
   if(!chainp) {
-    if(data->set.ssl.verifypeer ||
-       data->set.ssl.verifyhost ||
-       data->set.ssl.issuercert) {
+    if(SSL_CONN_CONFIG(verifypeer) ||
+       SSL_CONN_CONFIG(verifyhost) ||
+       SSL_SET_OPTION(issuercert)) {
 #ifdef USE_TLS_SRP
-      if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
-         && data->set.ssl.username != NULL
-         && !data->set.ssl.verifypeer
+      if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
+         && SSL_SET_OPTION(username) != NULL
+         && !SSL_CONN_CONFIG(verifypeer)
          && gnutls_cipher_get(session)) {
         /* no peer cert, but auth is ok if we have SRP user and cipher and no
            peer verify */
@@ -905,7 +1037,7 @@ gtls_connect_step3(struct connectdata *conn,
     }
   }
 
-  if(data->set.ssl.verifypeer) {
+  if(SSL_CONN_CONFIG(verifypeer)) {
     /* This function will try to verify the peer's certificate and return its
        status (trusted, invalid etc.). The value of status should be one or
        more of the gnutls_certificate_status_t enumerated elements bitwise
@@ -921,10 +1053,11 @@ gtls_connect_step3(struct connectdata *conn,
 
     /* verify_status is a bitmask of gnutls_certificate_status bits */
     if(verify_status & GNUTLS_CERT_INVALID) {
-      if(data->set.ssl.verifypeer) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         failf(data, "server certificate verification failed. CAfile: %s "
-              "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
-              data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
+              "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
+              "none",
+              SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
         return CURLE_SSL_CACERT;
       }
       else
@@ -937,7 +1070,7 @@ gtls_connect_step3(struct connectdata *conn,
     infof(data, "\t server certificate verification SKIPPED\n");
 
 #ifdef HAS_OCSP
-  if(data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
       gnutls_datum_t status_request;
       gnutls_ocsp_resp_t ocsp_resp;
@@ -1049,21 +1182,21 @@ gtls_connect_step3(struct connectdata *conn,
        gnutls_x509_crt_t format */
     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
 
-  if(data->set.ssl.issuercert) {
+  if(SSL_SET_OPTION(issuercert)) {
     gnutls_x509_crt_init(&x509_issuer);
-    issuerp = load_file(data->set.ssl.issuercert);
+    issuerp = load_file(SSL_SET_OPTION(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)",
-            data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+            SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(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",
-          data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+          SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
   }
 
   size=sizeof(certbuf);
@@ -1082,7 +1215,7 @@ gtls_connect_step3(struct connectdata *conn,
      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
      alternative name PKIX extension. Returns non zero on success, and zero on
      failure. */
-  rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
+  rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
 #if GNUTLS_VERSION_NUMBER < 0x030306
   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
      addresses. */
@@ -1098,10 +1231,10 @@ gtls_connect_step3(struct connectdata *conn,
     int i;
     int ret = 0;
 
-    if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0)
+    if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
       addrlen = 4;
 #ifdef ENABLE_IPV6
-    else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0)
+    else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
       addrlen = 16;
 #endif
 
@@ -1126,15 +1259,18 @@ gtls_connect_step3(struct connectdata *conn,
   }
 #endif
   if(!rc) {
-    if(data->set.ssl.verifyhost) {
+    const char * const dispname = SSL_IS_PROXY() ?
+      conn->http_proxy.host.dispname : conn->host.dispname;
+
+    if(SSL_CONN_CONFIG(verifyhost)) {
       failf(data, "SSL: certificate subject name (%s) does not match "
-            "target host name '%s'", certbuf, conn->host.dispname);
+            "target host name '%s'", certbuf, dispname);
       gnutls_x509_crt_deinit(x509_cert);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
     else
       infof(data, "\t common name: %s (does not match '%s')\n",
-            certbuf, conn->host.dispname);
+            certbuf, dispname);
   }
   else
     infof(data, "\t common name: %s (matched)\n", certbuf);
@@ -1143,7 +1279,7 @@ gtls_connect_step3(struct connectdata *conn,
   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
 
   if(certclock == (time_t)-1) {
-    if(data->set.ssl.verifypeer) {
+    if(SSL_CONN_CONFIG(verifypeer)) {
       failf(data, "server cert expiration date verify failed");
       gnutls_x509_crt_deinit(x509_cert);
       return CURLE_SSL_CONNECT_ERROR;
@@ -1153,7 +1289,7 @@ gtls_connect_step3(struct connectdata *conn,
   }
   else {
     if(certclock < time(NULL)) {
-      if(data->set.ssl.verifypeer) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         failf(data, "server certificate expiration date has passed.");
         gnutls_x509_crt_deinit(x509_cert);
         return CURLE_PEER_FAILED_VERIFICATION;
@@ -1168,7 +1304,7 @@ gtls_connect_step3(struct connectdata *conn,
   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
 
   if(certclock == (time_t)-1) {
-    if(data->set.ssl.verifypeer) {
+    if(SSL_CONN_CONFIG(verifypeer)) {
       failf(data, "server cert activation date verify failed");
       gnutls_x509_crt_deinit(x509_cert);
       return CURLE_SSL_CONNECT_ERROR;
@@ -1178,7 +1314,7 @@ gtls_connect_step3(struct connectdata *conn,
   }
   else {
     if(certclock > time(NULL)) {
-      if(data->set.ssl.verifypeer) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         failf(data, "server certificate not activated yet.");
         gnutls_x509_crt_deinit(x509_cert);
         return CURLE_PEER_FAILED_VERIFICATION;
@@ -1190,7 +1326,8 @@ gtls_connect_step3(struct connectdata *conn,
       infof(data, "\t server certificate activation date OK\n");
   }
 
-  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+  ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+        data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
   if(ptr) {
     result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
     if(result != CURLE_OK) {
@@ -1210,6 +1347,7 @@ gtls_connect_step3(struct connectdata *conn,
 
   */
 
+#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",
@@ -1234,12 +1372,13 @@ gtls_connect_step3(struct connectdata *conn,
   gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
   infof(data, "\t issuer: %s\n", certbuf);
 
-  gnutls_x509_crt_deinit(x509_cert);
-
   /* compression algorithm (if any) */
   ptr = gnutls_compression_get_name(gnutls_compression_get(session));
   /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
   infof(data, "\t compression: %s\n", ptr);
+#endif
+
+  gnutls_x509_crt_deinit(x509_cert);
 
 #ifdef HAS_ALPN
   if(conn->bits.tls_enable_alpn) {
@@ -1270,7 +1409,7 @@ gtls_connect_step3(struct connectdata *conn,
   conn->recv[sockindex] = gtls_recv;
   conn->send[sockindex] = gtls_send;
 
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     /* we always unconditionally get the session id here, as even if we
        already got it from the cache and asked to use it in the connection, it
        might've been rejected and then a new one is in use now and we need to
@@ -1289,7 +1428,8 @@ gtls_connect_step3(struct connectdata *conn,
       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
 
       Curl_ssl_sessionid_lock(conn);
-      incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
+      incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
+                                        sockindex));
       if(incache) {
         /* there was one before in the cache, so instead of risking that the
            previous one was rejected, we just kill that and store the new */
@@ -1297,7 +1437,8 @@ gtls_connect_step3(struct connectdata *conn,
       }
 
       /* store this session id */
-      result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
+      result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
+                                     sockindex);
       Curl_ssl_sessionid_unlock(conn);
       if(result) {
         free(connect_sessionid);
@@ -1332,7 +1473,7 @@ gtls_connect_common(struct connectdata *conn,
 
   /* Initiate the connection, if not already done */
   if(ssl_connect_1==connssl->connecting_state) {
-    rc = gtls_connect_step1 (conn, sockindex);
+    rc = gtls_connect_step1(conn, sockindex);
     if(rc)
       return rc;
   }
@@ -1379,6 +1520,20 @@ Curl_gtls_connect(struct connectdata *conn,
   return CURLE_OK;
 }
 
+bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex)
+{
+  bool res = FALSE;
+  if(conn->ssl[connindex].session &&
+     0 != gnutls_record_check_pending(conn->ssl[connindex].session))
+    res = TRUE;
+
+  if(conn->proxy_ssl[connindex].session &&
+     0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session))
+    res = TRUE;
+
+  return res;
+}
+
 static ssize_t gtls_send(struct connectdata *conn,
                          int sockindex,
                          const void *mem,
@@ -1398,29 +1553,29 @@ static ssize_t gtls_send(struct connectdata *conn,
   return rc;
 }
 
-static void close_one(struct connectdata *conn,
-                      int idx)
+static void close_one(struct ssl_connect_data *ssl)
 {
-  if(conn->ssl[idx].session) {
-    gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
-    gnutls_deinit(conn->ssl[idx].session);
-    conn->ssl[idx].session = NULL;
+  if(ssl->session) {
+    gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
+    gnutls_deinit(ssl->session);
+    ssl->session = NULL;
   }
-  if(conn->ssl[idx].cred) {
-    gnutls_certificate_free_credentials(conn->ssl[idx].cred);
-    conn->ssl[idx].cred = NULL;
+  if(ssl->cred) {
+    gnutls_certificate_free_credentials(ssl->cred);
+    ssl->cred = NULL;
   }
 #ifdef USE_TLS_SRP
-  if(conn->ssl[idx].srp_client_cred) {
-    gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
-    conn->ssl[idx].srp_client_cred = NULL;
+  if(ssl->srp_client_cred) {
+    gnutls_srp_free_client_credentials(ssl->srp_client_cred);
+    ssl->srp_client_cred = NULL;
   }
 #endif
 }
 
 void Curl_gtls_close(struct connectdata *conn, int sockindex)
 {
-  close_one(conn, sockindex);
+  close_one(&conn->ssl[sockindex]);
+  close_one(&conn->proxy_ssl[sockindex]);
 }
 
 /*
@@ -1486,8 +1641,8 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
   gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
 
 #ifdef USE_TLS_SRP
-  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
-     && data->set.ssl.username != NULL)
+  if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
+     && SSL_SET_OPTION(username) != NULL)
     gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
 #endif
 
@@ -1568,19 +1723,21 @@ static int Curl_gtls_seed(struct Curl_easy *data)
 #endif
 
 /* data might be NULL! */
-int Curl_gtls_random(struct Curl_easy *data,
-                     unsigned char *entropy,
-                     size_t length)
+CURLcode Curl_gtls_random(struct Curl_easy *data,
+                          unsigned char *entropy,
+                          size_t length)
 {
 #if defined(USE_GNUTLS_NETTLE)
+  int rc;
   (void)data;
-  gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
+  rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
+  return rc?CURLE_FAILED_INIT:CURLE_OK;
 #elif defined(USE_GNUTLS)
   if(data)
     Curl_gtls_seed(data); /* Initiate the seed if not already done */
   gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
 #endif
-  return 0;
+  return CURLE_OK;
 }
 
 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
@@ -1597,7 +1754,7 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
   gcry_md_hd_t MD5pw;
   gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
   gcry_md_write(MD5pw, tmp, tmplen);
-  memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len);
+  memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
   gcry_md_close(MD5pw);
 #endif
 }
@@ -1616,7 +1773,7 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
   gcry_md_hd_t SHA256pw;
   gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
   gcry_md_write(SHA256pw, tmp, tmplen);
-  memcpy(sha256sum, gcry_md_read (SHA256pw, 0), sha256len);
+  memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
   gcry_md_close(SHA256pw);
 #endif
 }
diff --git a/Utilities/cmcurl/lib/vtls/gtls.h b/Utilities/cmcurl/lib/vtls/gtls.h
index e0a95a7..462c048 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.h
+++ b/Utilities/cmcurl/lib/vtls/gtls.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -34,6 +34,8 @@ CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
 CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
                                        int sockindex,
                                        bool *done);
+bool Curl_gtls_data_pending(const struct connectdata *conn,
+                            int connindex);
 
  /* close a SSL connection */
 void Curl_gtls_close(struct connectdata *conn, int sockindex);
@@ -41,9 +43,9 @@ void Curl_gtls_close(struct connectdata *conn, int sockindex);
 void Curl_gtls_session_free(void *ptr);
 size_t Curl_gtls_version(char *buffer, size_t size);
 int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
-int Curl_gtls_random(struct Curl_easy *data,
-                     unsigned char *entropy,
-                     size_t length);
+CURLcode Curl_gtls_random(struct Curl_easy *data,
+                          unsigned char *entropy,
+                          size_t length);
 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
                       size_t tmplen,
                       unsigned char *md5sum, /* output */
@@ -55,6 +57,9 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
 
 bool Curl_gtls_cert_status_request(void);
 
+/* Support HTTPS-proxy */
+#define HTTPS_PROXY_SUPPORT 1
+
 /* Set the API backend definition to GnuTLS */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS
 
@@ -81,7 +86,7 @@ bool Curl_gtls_cert_status_request(void);
 #define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
 #define curlssl_version Curl_gtls_version
 #define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
+#define curlssl_data_pending(x,y) Curl_gtls_data_pending(x,y)
 #define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
 #define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
 #define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d)
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 24249dd..037babe 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan at gmail.com>
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at 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
@@ -31,11 +31,15 @@
 
 #ifdef USE_MBEDTLS
 
+#include <mbedtls/version.h>
+#if MBEDTLS_VERSION_NUMBER >= 0x02040000
 #include <mbedtls/net_sockets.h>
+#else
+#include <mbedtls/net.h>
+#endif
 #include <mbedtls/ssl.h>
 #include <mbedtls/certs.h>
 #include <mbedtls/x509.h>
-#include <mbedtls/version.h>
 
 #include <mbedtls/error.h>
 #include <mbedtls/entropy.h>
@@ -63,7 +67,7 @@
 #endif
 
 #if defined(THREADING_SUPPORT)
-static mbedtls_entropy_context entropy;
+static mbedtls_entropy_context ts_entropy;
 
 static int entropy_init_initialized = 0;
 
@@ -127,7 +131,7 @@ static void mbed_debug(void *context, int level, const char *f_name,
 /*
  *  profile
  */
-const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
+static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
 {
   /* Hashes from SHA-1 and above */
   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
@@ -153,29 +157,101 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
 static Curl_recv mbed_recv;
 static Curl_send mbed_send;
 
+static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
+{
+  switch(version) {
+    case CURL_SSLVERSION_TLSv1_0:
+      *mbedver = MBEDTLS_SSL_MINOR_VERSION_1;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_1:
+      *mbedver = MBEDTLS_SSL_MINOR_VERSION_2;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_2:
+      *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_3:
+      break;
+  }
+  return CURLE_SSL_CONNECT_ERROR;
+}
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+{
+  struct Curl_easy *data = conn->data;
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
+  int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
+  long ssl_version = SSL_CONN_CONFIG(version);
+  long ssl_version_max = SSL_CONN_CONFIG(version_max);
+  CURLcode result = CURLE_OK;
+
+  switch(ssl_version) {
+    case CURL_SSLVERSION_DEFAULT:
+    case CURL_SSLVERSION_TLSv1:
+      ssl_version = CURL_SSLVERSION_TLSv1_0;
+      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      break;
+  }
+
+  switch(ssl_version_max) {
+    case CURL_SSLVERSION_MAX_NONE:
+      ssl_version_max = ssl_version << 16;
+      break;
+    case CURL_SSLVERSION_MAX_DEFAULT:
+      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      break;
+  }
+
+  result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version);
+  if(result) {
+    failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+    return result;
+  }
+  result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16);
+  if(result) {
+    failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+    return result;
+  }
+
+  mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+                               mbedtls_ver_min);
+  mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+                               mbedtls_ver_max);
+
+  return result;
+}
+
 static CURLcode
 mbed_connect_step1(struct connectdata *conn,
                    int sockindex)
 {
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
-
+  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+  const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+  char * const ssl_cert = SSL_SET_OPTION(cert);
+  const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
   int ret = -1;
   char errorbuf[128];
   errorbuf[0]=0;
 
   /* mbedTLS only supports SSLv3 and TLSv1 */
-  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
     failf(data, "mbedTLS does not support SSLv2");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
 #ifdef THREADING_SUPPORT
-  entropy_init_mutex(&entropy);
+  entropy_init_mutex(&ts_entropy);
   mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
 
   ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
-                              &entropy, NULL, 0);
+                              &ts_entropy, NULL, 0);
   if(ret) {
 #ifdef MBEDTLS_ERROR_C
     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -201,34 +277,32 @@ mbed_connect_step1(struct connectdata *conn,
   /* Load the trusted CA */
   mbedtls_x509_crt_init(&connssl->cacert);
 
-  if(data->set.str[STRING_SSL_CAFILE]) {
-    ret = mbedtls_x509_crt_parse_file(&connssl->cacert,
-                                      data->set.str[STRING_SSL_CAFILE]);
+  if(ssl_cafile) {
+    ret = mbedtls_x509_crt_parse_file(&connssl->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",
-            data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
+            ssl_cafile, -ret, errorbuf);
 
-      if(data->set.ssl.verifypeer)
+      if(verifypeer)
         return CURLE_SSL_CACERT_BADFILE;
     }
   }
 
-  if(data->set.str[STRING_SSL_CAPATH]) {
-    ret = mbedtls_x509_crt_parse_path(&connssl->cacert,
-                                      data->set.str[STRING_SSL_CAPATH]);
+  if(ssl_capath) {
+    ret = mbedtls_x509_crt_parse_path(&connssl->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",
-            data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
+            ssl_capath, -ret, errorbuf);
 
-      if(data->set.ssl.verifypeer)
+      if(verifypeer)
         return CURLE_SSL_CACERT_BADFILE;
     }
   }
@@ -236,16 +310,15 @@ mbed_connect_step1(struct connectdata *conn,
   /* Load the client certificate */
   mbedtls_x509_crt_init(&connssl->clicert);
 
-  if(data->set.str[STRING_CERT]) {
-    ret = mbedtls_x509_crt_parse_file(&connssl->clicert,
-                                      data->set.str[STRING_CERT]);
+  if(ssl_cert) {
+    ret = mbedtls_x509_crt_parse_file(&connssl->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",
-            data->set.str[STRING_CERT], -ret, errorbuf);
+            ssl_cert, -ret, errorbuf);
 
       return CURLE_SSL_CERTPROBLEM;
     }
@@ -254,9 +327,9 @@ mbed_connect_step1(struct connectdata *conn,
   /* Load the client private key */
   mbedtls_pk_init(&connssl->pk);
 
-  if(data->set.str[STRING_KEY]) {
-    ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY],
-                                   data->set.str[STRING_KEY_PASSWD]);
+  if(SSL_SET_OPTION(key)) {
+    ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key),
+                                   SSL_SET_OPTION(key_passwd));
     if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
       ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
 
@@ -265,7 +338,7 @@ mbed_connect_step1(struct connectdata *conn,
       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
 #endif /* MBEDTLS_ERROR_C */
       failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
-            data->set.str[STRING_KEY], -ret, errorbuf);
+            SSL_SET_OPTION(key), -ret, errorbuf);
 
       return CURLE_SSL_CERTPROBLEM;
     }
@@ -274,23 +347,21 @@ mbed_connect_step1(struct connectdata *conn,
   /* Load the CRL */
   mbedtls_x509_crl_init(&connssl->crl);
 
-  if(data->set.str[STRING_SSL_CRLFILE]) {
-    ret = mbedtls_x509_crl_parse_file(&connssl->crl,
-                                      data->set.str[STRING_SSL_CRLFILE]);
+  if(ssl_crlfile) {
+    ret = mbedtls_x509_crl_parse_file(&connssl->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",
-            data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
+            ssl_crlfile, -ret, errorbuf);
 
       return CURLE_SSL_CRL_BADFILE;
     }
   }
 
-  infof(data, "mbedTLS: Connecting to %s:%d\n",
-        conn->host.name, conn->remote_port);
+  infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
 
   mbedtls_ssl_config_init(&connssl->config);
 
@@ -312,7 +383,7 @@ mbed_connect_step1(struct connectdata *conn,
   mbedtls_ssl_conf_cert_profile(&connssl->config,
                                 &mbedtls_x509_crt_profile_fr);
 
-  switch(data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
     mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
@@ -327,28 +398,17 @@ mbed_connect_step1(struct connectdata *conn,
     infof(data, "mbedTLS: Set SSL version to SSLv3\n");
     break;
   case CURL_SSLVERSION_TLSv1_0:
-    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
-                                 MBEDTLS_SSL_MINOR_VERSION_1);
-    mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
-                                 MBEDTLS_SSL_MINOR_VERSION_1);
-    infof(data, "mbedTLS: Set SSL version to TLS 1.0\n");
-    break;
   case CURL_SSLVERSION_TLSv1_1:
-    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
-                                 MBEDTLS_SSL_MINOR_VERSION_2);
-    mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
-                                 MBEDTLS_SSL_MINOR_VERSION_2);
-    infof(data, "mbedTLS: Set SSL version to TLS 1.1\n");
-    break;
   case CURL_SSLVERSION_TLSv1_2:
-    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
-                                 MBEDTLS_SSL_MINOR_VERSION_3);
-    mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
-                                 MBEDTLS_SSL_MINOR_VERSION_3);
-    infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
-    break;
+  case CURL_SSLVERSION_TLSv1_3:
+    {
+      CURLcode result = set_ssl_version_min_max(conn, sockindex);
+      if(result != CURLE_OK)
+        return result;
+      break;
+    }
   default:
-    failf(data, "mbedTLS: Unsupported SSL protocol version");
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
@@ -364,12 +424,22 @@ mbed_connect_step1(struct connectdata *conn,
   mbedtls_ssl_conf_ciphersuites(&connssl->config,
                                 mbedtls_ssl_list_ciphersuites());
 
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+  mbedtls_ssl_conf_renegotiation(&connssl->config,
+                                 MBEDTLS_SSL_RENEGOTIATION_ENABLED);
+#endif
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+  mbedtls_ssl_conf_session_tickets(&connssl->config,
+                                   MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
+#endif
+
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     void *old_session = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
       ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
       if(ret) {
         Curl_ssl_sessionid_unlock(conn);
@@ -385,11 +455,11 @@ mbed_connect_step1(struct connectdata *conn,
                             &connssl->cacert,
                             &connssl->crl);
 
-  if(data->set.str[STRING_KEY]) {
+  if(SSL_SET_OPTION(key)) {
     mbedtls_ssl_conf_own_cert(&connssl->config,
                               &connssl->clicert, &connssl->pk);
   }
-  if(mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) {
+  if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) {
     /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
        the name to set in the SNI extension. So even if curl connects to a
        host specified as an IP address, this function must be used. */
@@ -430,6 +500,16 @@ mbed_connect_step1(struct connectdata *conn,
   mbedtls_debug_set_threshold(4);
 #endif
 
+  /* give application a chance to interfere with mbedTLS set up. */
+  if(data->set.ssl.fsslctx) {
+    ret = (*data->set.ssl.fsslctx)(data, &connssl->config,
+                                   data->set.ssl.fsslctxp);
+    if(ret) {
+      failf(data, "error signaled by ssl ctx callback");
+      return ret;
+    }
+  }
+
   connssl->connecting_state = ssl_connect_2;
 
   return CURLE_OK;
@@ -443,9 +523,12 @@ mbed_connect_step2(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
   const mbedtls_x509_crt *peercert;
+  const char * const pinnedpubkey = SSL_IS_PROXY() ?
+        data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+        data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
 
 #ifdef HAS_ALPN
-  const char* next_protocol;
+  const char *next_protocol;
 #endif
 
   char errorbuf[128];
@@ -479,7 +562,7 @@ mbed_connect_step2(struct connectdata *conn,
 
   ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
 
-  if(ret && data->set.ssl.verifypeer) {
+  if(ret && SSL_CONN_CONFIG(verifypeer)) {
     if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
       failf(data, "Cert verify failed: BADCERT_EXPIRED");
 
@@ -514,7 +597,7 @@ mbed_connect_step2(struct connectdata *conn,
     free(buffer);
   }
 
-  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+  if(pinnedpubkey) {
     int size;
     CURLcode result;
     mbedtls_x509_crt *p;
@@ -553,7 +636,7 @@ mbed_connect_step2(struct connectdata *conn,
 
     /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
     result = Curl_pin_peer_pubkey(data,
-                                  data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+                                  pinnedpubkey,
                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
     if(result) {
       mbedtls_x509_crt_free(p);
@@ -606,7 +689,7 @@ mbed_connect_step3(struct connectdata *conn,
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     int ret;
     mbedtls_ssl_session *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -619,16 +702,17 @@ mbed_connect_step3(struct connectdata *conn,
 
     ret = mbedtls_ssl_get_session(&connssl->ssl, our_ssl_sessionid);
     if(ret) {
+      free(our_ssl_sessionid);
       failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
       return CURLE_SSL_CONNECT_ERROR;
     }
 
     /* If there's already a matching session in the cache, delete it */
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL))
+    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
       Curl_ssl_delsessionid(conn, old_ssl_sessionid);
 
-    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0);
+    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
     Curl_ssl_sessionid_unlock(conn);
     if(retcode) {
       free(our_ssl_sessionid);
@@ -717,6 +801,55 @@ size_t Curl_mbedtls_version(char *buffer, size_t size)
                   (version>>16)&0xff, (version>>8)&0xff);
 }
 
+CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
+                             size_t length)
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+  int ret = -1;
+  char errorbuf[128];
+  mbedtls_entropy_context ctr_entropy;
+  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\n",
+          -ret, errorbuf);
+  }
+  else {
+    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\n",
+            -ret, errorbuf);
+    }
+  }
+
+  mbedtls_ctr_drbg_free(&ctr_drbg);
+  mbedtls_entropy_free(&ctr_entropy);
+
+  return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
+#elif defined(MBEDTLS_HAVEGE_C)
+  mbedtls_havege_state hs;
+  mbedtls_havege_init(&hs);
+  mbedtls_havege_random(&hs, entropy, length);
+  mbedtls_havege_free(&hs);
+  return CURLE_OK;
+#else
+  return CURLE_NOT_BUILT_IN;
+#endif
+}
+
 static CURLcode
 mbed_connect_common(struct connectdata *conn,
                     int sockindex,
@@ -871,9 +1004,7 @@ void Curl_mbedtls_cleanup(void)
 
 int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex)
 {
-  mbedtls_ssl_context *ssl =
-    (mbedtls_ssl_context *)&conn->ssl[sockindex].ssl;
-  return ssl->in_msglen != 0;
+  return mbedtls_ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
 }
 
 #endif /* USE_MBEDTLS */
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.h b/Utilities/cmcurl/lib/vtls/mbedtls.h
index 1021d54..71d17a4 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.h
@@ -50,9 +50,15 @@ void Curl_mbedtls_session_free(void *ptr);
 size_t Curl_mbedtls_version(char *buffer, size_t size);
 int Curl_mbedtls_shutdown(struct connectdata *conn, int sockindex);
 
+CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
+                     size_t length);
+
 /* this backends supports CURLOPT_PINNEDPUBLICKEY */
 #define have_curlssl_pinnedpubkey 1
 
+/* this backend supports CURLOPT_SSL_CTX_* */
+#define have_curlssl_ssl_ctx 1
+
 /* API setup for mbedTLS */
 #define curlssl_init() Curl_mbedtls_init()
 #define curlssl_cleanup() Curl_mbedtls_cleanup()
@@ -70,11 +76,7 @@ int Curl_mbedtls_shutdown(struct connectdata *conn, int sockindex);
 #define curlssl_data_pending(x,y) Curl_mbedtls_data_pending(x, y)
 #define CURL_SSL_BACKEND CURLSSLBACKEND_MBEDTLS
 #define curlssl_sha256sum(a,b,c,d) mbedtls_sha256(a,b,c,0)
-
-/* This might cause libcurl to use a weeker random!
-   TODO: implement proper use of Polarssl's CTR-DRBG or HMAC-DRBG and use that
-*/
-#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN)
+#define curlssl_random(x,y,z) Curl_mbedtls_random(x, y, z)
 
 #endif /* USE_MBEDTLS */
 #endif /* HEADER_CURL_MBEDTLS_H */
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index dff1575..cd01389 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -56,7 +56,8 @@
 #include <base64.h>
 #include <cert.h>
 #include <prerror.h>
-#include <keyhi.h>        /* for SECKEY_DestroyPublicKey() */
+#include <keyhi.h>         /* for SECKEY_DestroyPublicKey() */
+#include <private/pprio.h> /* for PR_ImportTCPSocket */
 
 #define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH)
 
@@ -77,14 +78,20 @@
 /* enough to fit the string "PEM Token #[0|1]" */
 #define SLOTSIZE 13
 
-PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
 static PRLock *nss_initlock = NULL;
 static PRLock *nss_crllock = NULL;
 static PRLock *nss_findslot_lock = NULL;
-static struct curl_llist *nss_crl_list = NULL;
+static PRLock *nss_trustload_lock = NULL;
+static struct curl_llist nss_crl_list;
 static NSSInitContext *nss_context = NULL;
 static volatile int initialized = 0;
 
+/* type used to wrap pointers as list nodes */
+struct ptr_list_wrap {
+  void *ptr;
+  struct curl_llist_element node;
+};
+
 typedef struct {
   const char *name;
   int num;
@@ -200,14 +207,17 @@ static const cipher_s cipherlist[] = {
 #endif
 };
 
-static const char* pem_library = "libnsspem.so";
-static SECMODModule* mod = NULL;
+static const char *pem_library = "libnsspem.so";
+static SECMODModule *pem_module = NULL;
+
+static const char *trust_library = "libnssckbi.so";
+static SECMODModule *trust_module = NULL;
 
 /* NSPR I/O layer we use to detect blocking direction during SSL handshake */
 static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
 static PRIOMethods nspr_io_methods;
 
-static const char* nss_error_to_name(PRErrorCode code)
+static const char *nss_error_to_name(PRErrorCode code)
 {
   const char *name = PR_ErrorToName(code);
   if(name)
@@ -254,7 +264,8 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
     while((*cipher) && (ISSPACE(*cipher)))
       ++cipher;
 
-    if((cipher_list = strchr(cipher, ','))) {
+    cipher_list = strchr(cipher, ',');
+    if(cipher_list) {
       *cipher_list++ = '\0';
     }
 
@@ -337,9 +348,8 @@ static int is_file(const char *filename)
  * should be later deallocated using free().  If the OOM failure occurs, we
  * return NULL, too.
  */
-static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind)
+static char *dup_nickname(struct Curl_easy *data, const char *str)
 {
-  const char *str = data->set.str[cert_kind];
   const char *n;
 
   if(!is_file(str))
@@ -365,12 +375,24 @@ static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind)
 static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
 {
   PK11SlotInfo *slot;
-  PR_Lock(nss_initlock);
+  PR_Lock(nss_findslot_lock);
   slot = PK11_FindSlotByName(slot_name);
-  PR_Unlock(nss_initlock);
+  PR_Unlock(nss_findslot_lock);
   return slot;
 }
 
+/* wrap 'ptr' as list node and tail-insert into 'list' */
+static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
+{
+  struct ptr_list_wrap *wrap = malloc(sizeof *wrap);
+  if(!wrap)
+    return CURLE_OUT_OF_MEMORY;
+
+  wrap->ptr = ptr;
+  Curl_llist_insert_next(list, list->tail, wrap, &wrap->node);
+  return CURLE_OK;
+}
+
 /* Call PK11_CreateGenericObject() with the given obj_class and filename.  If
  * the call succeeds, append the object handle to the list of objects so that
  * the object can be destroyed in Curl_nss_close(). */
@@ -401,7 +423,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
   PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
   PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
   PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
-                strlen(filename) + 1);
+                (CK_ULONG)strlen(filename) + 1);
 
   if(CKO_CERTIFICATE == obj_class) {
     CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
@@ -413,7 +435,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
   if(!obj)
     return result;
 
-  if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
+  if(insert_wrapped_ptr(&ssl->obj_list, obj) != CURLE_OK) {
     PK11_DestroyGenericObject(obj);
     return CURLE_OUT_OF_MEMORY;
   }
@@ -430,17 +452,21 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
  * NSS objects in Curl_nss_close() */
 static void nss_destroy_object(void *user, void *ptr)
 {
-  PK11GenericObject *obj = (PK11GenericObject *)ptr;
+  struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
+  PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr;
   (void) user;
   PK11_DestroyGenericObject(obj);
+  free(wrap);
 }
 
 /* same as nss_destroy_object() but for CRL items */
 static void nss_destroy_crl_item(void *user, void *ptr)
 {
-  SECItem *crl_der = (SECItem *)ptr;
+  struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
+  SECItem *crl_der = (SECItem *) wrap->ptr;
   (void) user;
   SECITEM_FreeItem(crl_der, PR_TRUE);
+  free(wrap);
 }
 
 static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
@@ -496,7 +522,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
   PR_Lock(nss_crllock);
 
   /* store the CRL item so that we can free it in Curl_nss_cleanup() */
-  if(!Curl_llist_insert_next(nss_crl_list, nss_crl_list->tail, crl_der)) {
+  if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
     SECITEM_FreeItem(crl_der, PR_TRUE);
     PR_Unlock(nss_crllock);
     return CURLE_OUT_OF_MEMORY;
@@ -514,7 +540,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
   return CURLE_OK;
 }
 
-static CURLcode nss_load_crl(const char* crlfilename)
+static CURLcode nss_load_crl(const char *crlfilename)
 {
   PRFileDesc *infile;
   PRFileInfo  info;
@@ -540,7 +566,7 @@ static CURLcode nss_load_crl(const char* crlfilename)
     goto fail;
 
   /* place a trailing zero right after the visible data */
-  body = (char*)filedata.data;
+  body = (char *)filedata.data;
   body[--filedata.len] = '\0';
 
   body = strstr(body, "-----BEGIN");
@@ -581,10 +607,11 @@ fail:
 static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
                              char *key_file)
 {
-  PK11SlotInfo *slot;
+  PK11SlotInfo *slot, *tmp;
   SECStatus status;
   CURLcode result;
   struct ssl_connect_data *ssl = conn->ssl;
+  struct Curl_easy *data = conn->data;
 
   (void)sockindex; /* unused */
 
@@ -599,11 +626,12 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
     return CURLE_SSL_CERTPROBLEM;
 
   /* This will force the token to be seen as re-inserted */
-  SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
+  tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0);
+  if(tmp)
+    PK11_FreeSlot(tmp);
   PK11_IsPresent(slot);
 
-  status = PK11_Authenticate(slot, PR_TRUE,
-                             conn->data->set.str[STRING_KEY_PASSWD]);
+  status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
   PK11_FreeSlot(slot);
 
   return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
@@ -664,7 +692,7 @@ static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
   return CURLE_OK;
 }
 
-static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
+static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg)
 {
   (void)slot; /* unused */
 
@@ -682,7 +710,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
   struct connectdata *conn = (struct connectdata *)arg;
 
 #ifdef SSL_ENABLE_OCSP_STAPLING
-  if(conn->data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     SECStatus cacheResult;
 
     const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
@@ -708,7 +736,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
   }
 #endif
 
-  if(!conn->data->set.ssl.verifypeer) {
+  if(!SSL_CONN_CONFIG(verifypeer)) {
     infof(conn->data, "skipping SSL peer certificate verification\n");
     return SECSuccess;
   }
@@ -734,6 +762,11 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
   if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
 
     switch(state) {
+#if NSSVERNUM >= 0x031a00 /* 3.26.0 */
+    /* used by NSS internally to implement 0-RTT */
+    case SSL_NEXT_PROTO_EARLY_VALUE:
+      /* fall through! */
+#endif
     case SSL_NEXT_PROTO_NO_SUPPORT:
     case SSL_NEXT_PROTO_NO_OVERLAP:
       infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n");
@@ -928,9 +961,12 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
   CERTCertificate *cert;
 
   /* remember the cert verification result */
-  data->set.ssl.certverifyresult = err;
+  if(SSL_IS_PROXY())
+    data->set.proxy_ssl.certverifyresult = err;
+  else
+    data->set.ssl.certverifyresult = err;
 
-  if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
+  if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
     /* we are asked not to verify the host name */
     return SECSuccess;
 
@@ -1170,6 +1206,50 @@ static PRStatus nspr_io_close(PRFileDesc *fd)
   return close_fn(fd);
 }
 
+/* load a PKCS #11 module */
+static CURLcode nss_load_module(SECMODModule **pmod, const char *library,
+                                const char *name)
+{
+  char *config_string;
+  SECMODModule *module = *pmod;
+  if(module)
+    /* already loaded */
+    return CURLE_OK;
+
+  config_string = aprintf("library=%s name=%s", library, name);
+  if(!config_string)
+    return CURLE_OUT_OF_MEMORY;
+
+  module = SECMOD_LoadUserModule(config_string, NULL, PR_FALSE);
+  free(config_string);
+
+  if(module && module->loaded) {
+    /* loaded successfully */
+    *pmod = module;
+    return CURLE_OK;
+  }
+
+  if(module)
+    SECMOD_DestroyModule(module);
+  return CURLE_FAILED_INIT;
+}
+
+/* unload a PKCS #11 module */
+static void nss_unload_module(SECMODModule **pmod)
+{
+  SECMODModule *module = *pmod;
+  if(!module)
+    /* not loaded */
+    return;
+
+  if(SECMOD_UnloadUserModule(module) != SECSuccess)
+    /* unload failed */
+    return;
+
+  SECMOD_DestroyModule(module);
+  *pmod = NULL;
+}
+
 /* data might be NULL */
 static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
 {
@@ -1219,9 +1299,7 @@ static CURLcode nss_init(struct Curl_easy *data)
     return CURLE_OK;
 
   /* list of all CRL items we need to destroy in Curl_nss_cleanup() */
-  nss_crl_list = Curl_llist_alloc(nss_destroy_crl_item);
-  if(!nss_crl_list)
-    return CURLE_OUT_OF_MEMORY;
+  Curl_llist_init(&nss_crl_list, nss_destroy_crl_item);
 
   /* First we check if $SSL_DIR points to a valid dir */
   cert_dir = getenv("SSL_DIR");
@@ -1281,6 +1359,7 @@ int Curl_nss_init(void)
     nss_initlock = PR_NewLock();
     nss_crllock = PR_NewLock();
     nss_findslot_lock = PR_NewLock();
+    nss_trustload_lock = PR_NewLock();
   }
 
   /* We will actually initialize NSS later */
@@ -1319,23 +1398,21 @@ void Curl_nss_cleanup(void)
      * the certificates. */
     SSL_ClearSessionCache();
 
-    if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) {
-      SECMOD_DestroyModule(mod);
-      mod = NULL;
-    }
+    nss_unload_module(&pem_module);
+    nss_unload_module(&trust_module);
     NSS_ShutdownContext(nss_context);
     nss_context = NULL;
   }
 
   /* destroy all CRL items */
-  Curl_llist_destroy(nss_crl_list, NULL);
-  nss_crl_list = NULL;
+  Curl_llist_destroy(&nss_crl_list, NULL);
 
   PR_Unlock(nss_initlock);
 
   PR_DestroyLock(nss_initlock);
   PR_DestroyLock(nss_crllock);
   PR_DestroyLock(nss_findslot_lock);
+  PR_DestroyLock(nss_trustload_lock);
   nss_initlock = NULL;
 
   initialized = 0;
@@ -1367,36 +1444,54 @@ Curl_nss_check_cxn(struct connectdata *conn)
   return -1;  /* connection status unknown */
 }
 
+static void nss_close(struct ssl_connect_data *connssl)
+{
+  /* before the cleanup, check whether we are using a client certificate */
+  const bool client_cert = (connssl->client_nickname != NULL)
+    || (connssl->obj_clicert != NULL);
+
+  free(connssl->client_nickname);
+  connssl->client_nickname = NULL;
+
+  /* destroy all NSS objects in order to avoid failure of NSS shutdown */
+  Curl_llist_destroy(&connssl->obj_list, NULL);
+  connssl->obj_clicert = NULL;
+
+  if(connssl->handle) {
+    if(client_cert)
+      /* A server might require different authentication based on the
+       * particular path being requested by the client.  To support this
+       * scenario, we must ensure that a connection will never reuse the
+       * authentication data from a previous connection. */
+      SSL_InvalidateSession(connssl->handle);
+
+    PR_Close(connssl->handle);
+    connssl->handle = NULL;
+  }
+}
+
 /*
  * This function is called when an SSL connection is closed.
  */
 void Curl_nss_close(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
 
-  if(connssl->handle) {
+  if(connssl->handle || connssl_proxy->handle) {
     /* NSS closes the socket we previously handed to it, so we must mark it
        as closed to avoid double close */
     fake_sclose(conn->sock[sockindex]);
     conn->sock[sockindex] = CURL_SOCKET_BAD;
+  }
 
-    if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
-      /* A server might require different authentication based on the
-       * particular path being requested by the client.  To support this
-       * scenario, we must ensure that a connection will never reuse the
-       * authentication data from a previous connection. */
-      SSL_InvalidateSession(connssl->handle);
-
-    free(connssl->client_nickname);
-    connssl->client_nickname = NULL;
-    /* destroy all NSS objects in order to avoid failure of NSS shutdown */
-    Curl_llist_destroy(connssl->obj_list, NULL);
-    connssl->obj_list = NULL;
-    connssl->obj_clicert = NULL;
+  if(connssl->handle)
+    /* nss_close(connssl) will transitively close also connssl_proxy->handle
+       if both are used. Clear it to avoid a double close leading to crash. */
+    connssl_proxy->handle = NULL;
 
-    PR_Close(connssl->handle);
-    connssl->handle = NULL;
-  }
+  nss_close(connssl);
+  nss_close(connssl_proxy);
 }
 
 /* return true if NSS can provide error code (and possibly msg) for the
@@ -1437,14 +1532,46 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
                                          int sockindex)
 {
   struct Curl_easy *data = conn->data;
-  const char *cafile = data->set.ssl.CAfile;
-  const char *capath = data->set.ssl.CApath;
+  const char *cafile = SSL_CONN_CONFIG(CAfile);
+  const char *capath = SSL_CONN_CONFIG(CApath);
+  bool use_trust_module;
+  CURLcode result = CURLE_OK;
 
-  if(cafile) {
-    CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
-    if(result)
-      return result;
+  /* treat empty string as unset */
+  if(cafile && !cafile[0])
+    cafile = NULL;
+  if(capath && !capath[0])
+    capath = NULL;
+
+  infof(data, "  CAfile: %s\n  CApath: %s\n",
+      cafile ? cafile : "none",
+      capath ? capath : "none");
+
+  /* load libnssckbi.so if no other trust roots were specified */
+  use_trust_module = !cafile && !capath;
+
+  PR_Lock(nss_trustload_lock);
+  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",
+          trust_library);
+    if(result == CURLE_FAILED_INIT)
+      /* make the error non-fatal if we are not going to verify peer */
+      result = CURLE_SSL_CACERT_BADFILE;
   }
+  else if(!use_trust_module && trust_module) {
+    /* libnssckbi.so not needed but already loaded --> unload it! */
+    infof(data, "unloading %s\n", trust_library);
+    nss_unload_module(&trust_module);
+  }
+  PR_Unlock(nss_trustload_lock);
+
+  if(cafile)
+    result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
+
+  if(result)
+    return result;
 
   if(capath) {
     struct_stat st;
@@ -1478,64 +1605,111 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
       infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
   }
 
-  infof(data, "  CAfile: %s\n  CApath: %s\n",
-      cafile ? cafile : "none",
-      capath ? capath : "none");
-
   return CURLE_OK;
 }
 
-static CURLcode nss_init_sslver(SSLVersionRange *sslver,
-                                struct Curl_easy *data)
+static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version)
 {
-  switch(data->set.ssl.version) {
-  default:
-  case CURL_SSLVERSION_DEFAULT:
+  switch(version) {
   case CURL_SSLVERSION_TLSv1:
-    sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+    /* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */
 #ifdef SSL_LIBRARY_VERSION_TLS_1_2
-    sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+    *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
 #elif defined SSL_LIBRARY_VERSION_TLS_1_1
-    sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+    *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
 #else
-    sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+    *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
 #endif
     return CURLE_OK;
 
   case CURL_SSLVERSION_SSLv2:
-    sslver->min = SSL_LIBRARY_VERSION_2;
-    sslver->max = SSL_LIBRARY_VERSION_2;
+    *nssver = SSL_LIBRARY_VERSION_2;
     return CURLE_OK;
 
   case CURL_SSLVERSION_SSLv3:
-    sslver->min = SSL_LIBRARY_VERSION_3_0;
-    sslver->max = SSL_LIBRARY_VERSION_3_0;
+    *nssver = SSL_LIBRARY_VERSION_3_0;
     return CURLE_OK;
 
   case CURL_SSLVERSION_TLSv1_0:
-    sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
-    sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
+    *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
     return CURLE_OK;
 
   case CURL_SSLVERSION_TLSv1_1:
 #ifdef SSL_LIBRARY_VERSION_TLS_1_1
-    sslver->min = SSL_LIBRARY_VERSION_TLS_1_1;
-    sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
+    *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
     return CURLE_OK;
+#else
+    return CURLE_SSL_CONNECT_ERROR;
 #endif
-    break;
 
   case CURL_SSLVERSION_TLSv1_2:
 #ifdef SSL_LIBRARY_VERSION_TLS_1_2
-    sslver->min = SSL_LIBRARY_VERSION_TLS_1_2;
-    sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
+    *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
+    return CURLE_OK;
+#else
+    return CURLE_SSL_CONNECT_ERROR;
+#endif
+
+  case CURL_SSLVERSION_TLSv1_3:
+#ifdef SSL_LIBRARY_VERSION_TLS_1_3
+    *nssver = SSL_LIBRARY_VERSION_TLS_1_3;
     return CURLE_OK;
+#else
+    return CURLE_SSL_CONNECT_ERROR;
 #endif
+
+  default:
+    return CURLE_SSL_CONNECT_ERROR;
+  }
+}
+
+static CURLcode nss_init_sslver(SSLVersionRange *sslver,
+                                struct Curl_easy *data,
+                                struct connectdata *conn)
+{
+  CURLcode result;
+  const long min = SSL_CONN_CONFIG(version);
+  const long max = SSL_CONN_CONFIG(version_max);
+
+  /* map CURL_SSLVERSION_DEFAULT to NSS default */
+  if(min == CURL_SSLVERSION_DEFAULT || max == CURL_SSLVERSION_MAX_DEFAULT) {
+    /* map CURL_SSLVERSION_DEFAULT to NSS default */
+    if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess)
+      return CURLE_SSL_CONNECT_ERROR;
+    /* ... but make sure we use at least TLSv1.0 according to libcurl API */
+    if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0)
+      sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+  }
+
+  switch(min) {
+  case CURL_SSLVERSION_DEFAULT:
     break;
+  case CURL_SSLVERSION_TLSv1:
+    sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+    break;
+  default:
+    result = nss_sslver_from_curl(&sslver->min, min);
+    if(result) {
+      failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+      return result;
+    }
+    if(max == CURL_SSLVERSION_MAX_NONE)
+      sslver->max = sslver->min;
   }
 
-  failf(data, "TLS minor version cannot be set");
-  return CURLE_SSL_CONNECT_ERROR;
+  switch(max) {
+  case CURL_SSLVERSION_MAX_NONE:
+  case CURL_SSLVERSION_MAX_DEFAULT:
+    break;
+  default:
+    result = nss_sslver_from_curl(&sslver->max, max >> 16);
+    if(result) {
+      failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+      return result;
+    }
+  }
+
+  return CURLE_OK;
 }
 
 static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
@@ -1558,19 +1732,19 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
   }
 
   /* cleanup on connection failure */
-  Curl_llist_destroy(connssl->obj_list, NULL);
-  connssl->obj_list = NULL;
+  Curl_llist_destroy(&connssl->obj_list, NULL);
 
   return curlerr;
 }
 
-/* Switch the SSL socket into non-blocking mode. */
-static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl,
-                                 struct Curl_easy *data)
+/* Switch the SSL socket into blocking or non-blocking mode. */
+static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
+                                 struct Curl_easy *data,
+                                 bool blocking)
 {
   static PRSocketOptionData sock_opt;
   sock_opt.option = PR_SockOpt_Nonblocking;
-  sock_opt.value.non_blocking = PR_TRUE;
+  sock_opt.value.non_blocking = !blocking;
 
   if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
     return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
@@ -1589,6 +1763,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   curl_socket_t sockfd = conn->sock[sockindex];
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   CURLcode result;
+  bool second_layer = FALSE;
 
   SSLVersionRange sslver = {
     SSL_LIBRARY_VERSION_TLS_1_0,  /* min */
@@ -1598,9 +1773,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   connssl->data = data;
 
   /* list of all NSS objects we need to destroy in Curl_nss_close() */
-  connssl->obj_list = Curl_llist_alloc(nss_destroy_object);
-  if(!connssl->obj_list)
-    return CURLE_OUT_OF_MEMORY;
+  Curl_llist_init(&connssl->obj_list, nss_destroy_object);
 
   /* FIXME. NSS doesn't support multiple databases open at the same time. */
   PR_Lock(nss_initlock);
@@ -1610,29 +1783,17 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
   }
 
-  result = CURLE_SSL_CONNECT_ERROR;
-
-  if(!mod) {
-    char *configstring = aprintf("library=%s name=PEM", pem_library);
-    if(!configstring) {
-      PR_Unlock(nss_initlock);
-      goto error;
-    }
-    mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
-    free(configstring);
-
-    if(!mod || !mod->loaded) {
-      if(mod) {
-        SECMOD_DestroyModule(mod);
-        mod = NULL;
-      }
-      infof(data, "WARNING: failed to load NSS PEM library %s. Using "
-                  "OpenSSL PEM certificates will not work.\n", pem_library);
-    }
-  }
-
   PK11_SetPasswordFunc(nss_get_password);
+
+  result = nss_load_module(&pem_module, pem_library, "PEM");
   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);
+  else if(result)
+    goto error;
+
+  result = CURLE_SSL_CONNECT_ERROR;
 
   model = PR_NewTCPSocket();
   if(!model)
@@ -1647,18 +1808,18 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
 
   /* do not use SSL cache if disabled or we are not going to verify peer */
-  ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ?
-    PR_FALSE : PR_TRUE;
+  ssl_no_cache = (SSL_SET_OPTION(primary.sessionid)
+                  && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE;
   if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
     goto error;
 
   /* enable/disable the requested SSL version(s) */
-  if(nss_init_sslver(&sslver, data) != CURLE_OK)
+  if(nss_init_sslver(&sslver, data, conn) != CURLE_OK)
     goto error;
   if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
     goto error;
 
-  ssl_cbc_random_iv = !data->set.ssl_enable_beast;
+  ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast);
 #ifdef SSL_CBC_RANDOM_IV
   /* unless the user explicitly asks to allow the protocol vulnerability, we
      use the work-around */
@@ -1670,14 +1831,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
 #endif
 
-  if(data->set.ssl.cipher_list) {
-    if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
+  if(SSL_CONN_CONFIG(cipher_list)) {
+    if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) {
       result = CURLE_SSL_CIPHER;
       goto error;
     }
   }
 
-  if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
+  if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost))
     infof(data, "warning: ignoring value of ssl.verifyhost\n");
 
   /* bypass the default SSL_AuthCertificate() hook in case we do not want to
@@ -1685,39 +1846,47 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
     goto error;
 
-  data->set.ssl.certverifyresult=0; /* not checked yet */
+  /* not checked yet */
+  if(SSL_IS_PROXY())
+    data->set.proxy_ssl.certverifyresult = 0;
+  else
+    data->set.ssl.certverifyresult = 0;
+
   if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
     goto error;
 
   if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
     goto error;
 
-  if(data->set.ssl.verifypeer) {
+  {
     const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
-    if(rv) {
+    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");
+    else if(rv) {
       result = rv;
       goto error;
     }
   }
 
-  if(data->set.ssl.CRLfile) {
-    const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile);
+  if(SSL_SET_OPTION(CRLfile)) {
+    const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile));
     if(rv) {
       result = rv;
       goto error;
     }
-    infof(data, "  CRLfile: %s\n", data->set.ssl.CRLfile);
+    infof(data, "  CRLfile: %s\n", SSL_SET_OPTION(CRLfile));
   }
 
-  if(data->set.str[STRING_CERT]) {
-    char *nickname = dup_nickname(data, STRING_CERT);
+  if(SSL_SET_OPTION(cert)) {
+    char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
     if(nickname) {
       /* we are not going to use libnsspem.so to read the client cert */
       connssl->obj_clicert = NULL;
     }
     else {
-      CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
-                               data->set.str[STRING_KEY]);
+      CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
+                               SSL_SET_OPTION(key));
       if(rv) {
         /* failf() is already done in cert_stuff() */
         result = rv;
@@ -1737,15 +1906,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
   }
 
-  /* wrap OS file descriptor by NSPR's file descriptor abstraction */
-  nspr_io = PR_ImportTCPSocket(sockfd);
-  if(!nspr_io)
-    goto error;
+  if(conn->proxy_ssl[sockindex].use) {
+    DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
+    DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
+    nspr_io = conn->proxy_ssl[sockindex].handle;
+    second_layer = TRUE;
+  }
+  else {
+    /* wrap OS file descriptor by NSPR's file descriptor abstraction */
+    nspr_io = PR_ImportTCPSocket(sockfd);
+    if(!nspr_io)
+      goto error;
+  }
 
   /* create our own NSPR I/O layer */
   nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
   if(!nspr_io_stub) {
-    PR_Close(nspr_io);
+    if(!second_layer)
+      PR_Close(nspr_io);
     goto error;
   }
 
@@ -1754,7 +1932,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
 
   /* push our new layer to the NSPR I/O stack */
   if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
-    PR_Close(nspr_io);
+    if(!second_layer)
+      PR_Close(nspr_io);
     PR_Close(nspr_io_stub);
     goto error;
   }
@@ -1762,7 +1941,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   /* import our model socket onto the current I/O stack */
   connssl->handle = SSL_ImportFD(model, nspr_io);
   if(!connssl->handle) {
-    PR_Close(nspr_io);
+    if(!second_layer)
+      PR_Close(nspr_io);
     goto error;
   }
 
@@ -1770,12 +1950,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   model = NULL;
 
   /* This is the password associated with the cert that we're using */
-  if(data->set.str[STRING_KEY_PASSWD]) {
-    SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
+  if(SSL_SET_OPTION(key_passwd)) {
+    SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd));
   }
 
 #ifdef SSL_ENABLE_OCSP_STAPLING
-  if(data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
         != SECSuccess)
       goto error;
@@ -1835,11 +2015,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
 
   /* propagate hostname to the TLS layer */
-  if(SSL_SetURL(connssl->handle, conn->host.name) != SECSuccess)
+  if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
+                conn->host.name) != SECSuccess)
     goto error;
 
   /* prevent NSS from re-using the session for a different hostname */
-  if(SSL_SetSockPeerID(connssl->handle, conn->host.name) != SECSuccess)
+  if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ?
+                       conn->http_proxy.host.name : conn->host.name)
+     != SECSuccess)
     goto error;
 
   return CURLE_OK;
@@ -1857,10 +2040,16 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_SSL_CONNECT_ERROR;
   PRUint32 timeout;
+  long * const certverifyresult = SSL_IS_PROXY() ?
+    &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+  const char * const pinnedpubkey = SSL_IS_PROXY() ?
+              data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+              data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+
 
   /* check timeout situation */
-  const long time_left = Curl_timeleft(data, NULL, TRUE);
-  if(time_left < 0L) {
+  const time_t time_left = Curl_timeleft(data, NULL, TRUE);
+  if(time_left < 0) {
     failf(data, "timed out before SSL handshake");
     result = CURLE_OPERATION_TIMEDOUT;
     goto error;
@@ -1872,9 +2061,9 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
     if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
       /* blocking direction is updated by nss_update_connecting_state() */
       return CURLE_AGAIN;
-    else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
+    else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
       result = CURLE_PEER_FAILED_VERIFICATION;
-    else if(conn->data->set.ssl.certverifyresult!=0)
+    else if(*certverifyresult != 0)
       result = CURLE_SSL_CACERT;
     goto error;
   }
@@ -1883,11 +2072,11 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
   if(result)
     goto error;
 
-  if(data->set.str[STRING_SSL_ISSUERCERT]) {
+  if(SSL_SET_OPTION(issuercert)) {
     SECStatus ret = SECFailure;
-    char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
+    char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
     if(nickname) {
-      /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
+      /* we support only nicknames in case of issuercert for now */
       ret = check_issuer_cert(connssl->handle, nickname);
       free(nickname);
     }
@@ -1902,7 +2091,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
     }
   }
 
-  result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
+  result = cmp_peer_pubkey(connssl, pinnedpubkey);
   if(result)
     /* status already printed */
     goto error;
@@ -1933,16 +2122,14 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
       /* we do not expect CURLE_AGAIN from nss_setup_connect() */
       return result;
 
-    if(!blocking) {
-      /* in non-blocking mode, set NSS non-blocking mode before handshake */
-      result = nss_set_nonblock(connssl, data);
-      if(result)
-        return result;
-    }
-
     connssl->connecting_state = ssl_connect_2;
   }
 
+  /* enable/disable blocking mode before handshake */
+  result = nss_set_blocking(connssl, data, blocking);
+  if(result)
+    return result;
+
   result = nss_do_connect(conn, sockindex);
   switch(result) {
   case CURLE_OK:
@@ -1958,7 +2145,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
 
   if(blocking) {
     /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
-    result = nss_set_nonblock(connssl, data);
+    result = nss_set_blocking(connssl, data, /* blocking */ FALSE);
     if(result)
       return result;
   }
@@ -2064,17 +2251,17 @@ int Curl_nss_seed(struct Curl_easy *data)
 }
 
 /* data might be NULL */
-int Curl_nss_random(struct Curl_easy *data,
-                    unsigned char *entropy,
-                    size_t length)
+CURLcode Curl_nss_random(struct Curl_easy *data,
+                         unsigned char *entropy,
+                         size_t length)
 {
   Curl_nss_seed(data);  /* Initiate the seed if not already done */
 
   if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length)))
     /* signal a failure */
-    return -1;
+    return CURLE_FAILED_INIT;
 
-  return 0;
+  return CURLE_OK;
 }
 
 void Curl_nss_md5sum(unsigned char *tmp, /* input */
@@ -2112,7 +2299,8 @@ bool Curl_nss_cert_status_request(void)
 #endif
 }
 
-bool Curl_nss_false_start(void) {
+bool Curl_nss_false_start(void)
+{
 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
   return TRUE;
 #else
diff --git a/Utilities/cmcurl/lib/vtls/nssg.h b/Utilities/cmcurl/lib/vtls/nssg.h
index ac67e6a..8c46929 100644
--- a/Utilities/cmcurl/lib/vtls/nssg.h
+++ b/Utilities/cmcurl/lib/vtls/nssg.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -47,9 +47,9 @@ int Curl_nss_seed(struct Curl_easy *data);
 /* initialize NSS library if not already */
 CURLcode Curl_nss_force_init(struct Curl_easy *data);
 
-int Curl_nss_random(struct Curl_easy *data,
-                    unsigned char *entropy,
-                    size_t length);
+CURLcode Curl_nss_random(struct Curl_easy *data,
+                         unsigned char *entropy,
+                         size_t length);
 
 void Curl_nss_md5sum(unsigned char *tmp, /* input */
                      size_t tmplen,
@@ -65,6 +65,9 @@ bool Curl_nss_cert_status_request(void);
 
 bool Curl_nss_false_start(void);
 
+/* Support HTTPS-proxy */
+#define HTTPS_PROXY_SUPPORT 1
+
 /* Set the API backend definition to NSS */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
 
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index c040928..dbee369 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -55,7 +55,9 @@
 #include <openssl/ssl.h>
 #include <openssl/rand.h>
 #include <openssl/x509v3.h>
+#ifndef OPENSSL_NO_DSA
 #include <openssl/dsa.h>
+#endif
 #include <openssl/dh.h>
 #include <openssl/err.h>
 #include <openssl/md5.h>
@@ -156,10 +158,56 @@ static unsigned long OpenSSL_version_num(void)
  * Number of bytes to read from the random number seed file. This must be
  * a finite value (because some entropy "files" like /dev/urandom have
  * an infinite length), but must be large enough to provide enough
- * entopy to properly seed OpenSSL's PRNG.
+ * entropy to properly seed OpenSSL's PRNG.
  */
 #define RAND_LOAD_LENGTH 1024
 
+static const char *SSL_ERROR_to_str(int err)
+{
+  switch(err) {
+  case SSL_ERROR_NONE:
+    return "SSL_ERROR_NONE";
+  case SSL_ERROR_SSL:
+    return "SSL_ERROR_SSL";
+  case SSL_ERROR_WANT_READ:
+    return "SSL_ERROR_WANT_READ";
+  case SSL_ERROR_WANT_WRITE:
+    return "SSL_ERROR_WANT_WRITE";
+  case SSL_ERROR_WANT_X509_LOOKUP:
+    return "SSL_ERROR_WANT_X509_LOOKUP";
+  case SSL_ERROR_SYSCALL:
+    return "SSL_ERROR_SYSCALL";
+  case SSL_ERROR_ZERO_RETURN:
+    return "SSL_ERROR_ZERO_RETURN";
+  case SSL_ERROR_WANT_CONNECT:
+    return "SSL_ERROR_WANT_CONNECT";
+  case SSL_ERROR_WANT_ACCEPT:
+    return "SSL_ERROR_WANT_ACCEPT";
+#if defined(SSL_ERROR_WANT_ASYNC)
+  case SSL_ERROR_WANT_ASYNC:
+    return "SSL_ERROR_WANT_ASYNC";
+#endif
+#if defined(SSL_ERROR_WANT_ASYNC_JOB)
+  case SSL_ERROR_WANT_ASYNC_JOB:
+    return "SSL_ERROR_WANT_ASYNC_JOB";
+#endif
+#if defined(SSL_ERROR_WANT_EARLY)
+  case SSL_ERROR_WANT_EARLY:
+    return "SSL_ERROR_WANT_EARLY";
+#endif
+  default:
+    return "SSL_ERROR unknown";
+  }
+}
+
+/* Return error string for last OpenSSL error
+ */
+static char *ossl_strerror(unsigned long error, char *buf, size_t size)
+{
+  ERR_error_string_n(error, buf, size);
+  return buf;
+}
+
 static int passwd_callback(char *buf, int num, int encrypting,
                            void *global_passwd)
 {
@@ -176,39 +224,34 @@ static int passwd_callback(char *buf, int num, int encrypting,
 }
 
 /*
- * rand_enough() is a function that returns TRUE if we have seeded the random
- * engine properly. We use some preprocessor magic to provide a seed_enough()
- * macro to use, just to prevent a compiler warning on this function if we
- * pass in an argument that is never used.
+ * rand_enough() returns TRUE if we have seeded the random engine properly.
  */
-
-#ifdef HAVE_RAND_STATUS
-#define seed_enough(x) rand_enough()
 static bool rand_enough(void)
 {
   return (0 != RAND_status()) ? TRUE : FALSE;
 }
-#else
-#define seed_enough(x) rand_enough(x)
-static bool rand_enough(int nread)
-{
-  /* this is a very silly decision to make */
-  return (nread > 500) ? TRUE : FALSE;
-}
-#endif
 
-static int ossl_seed(struct Curl_easy *data)
+static CURLcode Curl_ossl_seed(struct Curl_easy *data)
 {
-  char *buf = data->state.buffer; /* point to the big buffer */
+  /* we have the "SSL is seeded" boolean static to prevent multiple
+     time-consuming seedings in vain */
+  static bool ssl_seeded = FALSE;
   int nread=0;
+  char fname[256];
 
-  /* Q: should we add support for a random file name as a libcurl option?
-     A: Yes, it is here */
+  if(ssl_seeded)
+    return CURLE_OK;
+
+  if(rand_enough()) {
+    /* OpenSSL 1.1.0+ will return here */
+    ssl_seeded = TRUE;
+    return CURLE_OK;
+  }
 
 #ifndef RANDOM_FILE
   /* if RANDOM_FILE isn't defined, we only perform this if an option tells
      us to! */
-  if(data->set.ssl.random_file)
+  if(data->set.str[STRING_SSL_RANDOM_FILE])
 #define RANDOM_FILE "" /* doesn't matter won't be used */
 #endif
   {
@@ -217,7 +260,7 @@ static int ossl_seed(struct Curl_easy *data)
                              data->set.str[STRING_SSL_RANDOM_FILE]:
                              RANDOM_FILE),
                             RAND_LOAD_LENGTH);
-    if(seed_enough(nread))
+    if(rand_enough())
       return nread;
   }
 
@@ -237,7 +280,7 @@ static int ossl_seed(struct Curl_easy *data)
                        data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
     if(-1 != ret) {
       nread += ret;
-      if(seed_enough(nread))
+      if(rand_enough())
         return nread;
     }
   }
@@ -248,35 +291,23 @@ static int ossl_seed(struct Curl_easy *data)
   do {
     unsigned char randb[64];
     int len = sizeof(randb);
-    RAND_bytes(randb, len);
+    if(!RAND_bytes(randb, len))
+      break;
     RAND_add(randb, len, (len >> 1));
-  } while(!RAND_status());
+  } while(!rand_enough());
 
   /* generates a default path for the random seed file */
-  buf[0]=0; /* blank it first */
-  RAND_file_name(buf, BUFSIZE);
-  if(buf[0]) {
+  fname[0]=0; /* blank it first */
+  RAND_file_name(fname, sizeof(fname));
+  if(fname[0]) {
     /* we got a file name to try */
-    nread += RAND_load_file(buf, RAND_LOAD_LENGTH);
-    if(seed_enough(nread))
+    nread += RAND_load_file(fname, RAND_LOAD_LENGTH);
+    if(rand_enough())
       return nread;
   }
 
   infof(data, "libcurl is now using a weak random seed!\n");
-  return nread;
-}
-
-static void Curl_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;
-
-  if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
-     data->set.str[STRING_SSL_EGDSOCKET]) {
-    ossl_seed(data);
-    ssl_seeded = TRUE;
-  }
+  return CURLE_SSL_CONNECT_ERROR; /* confusing error code */
 }
 
 #ifndef SSL_FILETYPE_ENGINE
@@ -312,7 +343,7 @@ static int ssl_ui_reader(UI *ui, UI_STRING *uis)
   switch(UI_get_string_type(uis)) {
   case UIT_PROMPT:
   case UIT_VERIFY:
-    password = (const char*)UI_get0_user_data(ui);
+    password = (const char *)UI_get0_user_data(ui);
     if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
       UI_set_result(ui, uis, password);
       return 1;
@@ -348,9 +379,11 @@ int cert_stuff(struct connectdata *conn,
                char *cert_file,
                const char *cert_type,
                char *key_file,
-               const char *key_type)
+               const char *key_type,
+               char *key_passwd)
 {
   struct Curl_easy *data = conn->data;
+  char error_buffer[256];
 
   int file_type = do_file_type(cert_type);
 
@@ -359,10 +392,9 @@ int cert_stuff(struct connectdata *conn,
     X509 *x509;
     int cert_done = 0;
 
-    if(data->set.str[STRING_KEY_PASSWD]) {
+    if(key_passwd) {
       /* set the password in the callback userdata */
-      SSL_CTX_set_default_passwd_cb_userdata(ctx,
-                                             data->set.str[STRING_KEY_PASSWD]);
+      SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd);
       /* Set passwd callback: */
       SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
     }
@@ -377,7 +409,8 @@ int cert_stuff(struct connectdata *conn,
               "could not load PEM client certificate, " OSSL_PACKAGE
               " error %s, "
               "(no key found, wrong pass phrase, or wrong file format?)",
-              ERR_error_string(ERR_get_error(), NULL) );
+              ossl_strerror(ERR_get_error(), error_buffer,
+                            sizeof(error_buffer)) );
         return 0;
       }
       break;
@@ -393,7 +426,8 @@ int cert_stuff(struct connectdata *conn,
               "could not load ASN1 client certificate, " OSSL_PACKAGE
               " error %s, "
               "(no key found, wrong pass phrase, or wrong file format?)",
-              ERR_error_string(ERR_get_error(), NULL) );
+              ossl_strerror(ERR_get_error(), error_buffer,
+                            sizeof(error_buffer)) );
         return 0;
       }
       break;
@@ -422,7 +456,8 @@ int cert_stuff(struct connectdata *conn,
                               0, &params, NULL, 1)) {
             failf(data, "ssl engine cannot load client cert with id"
                   " '%s' [%s]", cert_file,
-                  ERR_error_string(ERR_get_error(), NULL));
+                  ossl_strerror(ERR_get_error(), error_buffer,
+                                sizeof(error_buffer)));
             return 0;
           }
 
@@ -473,12 +508,13 @@ int cert_stuff(struct connectdata *conn,
 
       PKCS12_PBE_add();
 
-      if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
+      if(!PKCS12_parse(p12, key_passwd, &pri, &x509,
                        &ca)) {
         failf(data,
               "could not parse PKCS12 file, check password, " OSSL_PACKAGE
               " error %s",
-              ERR_error_string(ERR_get_error(), NULL) );
+              ossl_strerror(ERR_get_error(), error_buffer,
+                            sizeof(error_buffer)) );
         PKCS12_free(p12);
         return 0;
       }
@@ -489,7 +525,8 @@ int cert_stuff(struct connectdata *conn,
         failf(data,
               "could not load PKCS12 client certificate, " OSSL_PACKAGE
               " error %s",
-              ERR_error_string(ERR_get_error(), NULL) );
+              ossl_strerror(ERR_get_error(), error_buffer,
+                            sizeof(error_buffer)) );
         goto fail;
       }
 
@@ -510,21 +547,19 @@ int cert_stuff(struct connectdata *conn,
           /*
            * Note that sk_X509_pop() is used below to make sure the cert is
            * removed from the stack properly before getting passed to
-           * SSL_CTX_add_extra_chain_cert(). Previously we used
-           * sk_X509_value() instead, but then we'd clean it in the subsequent
-           * sk_X509_pop_free() call.
+           * SSL_CTX_add_extra_chain_cert(), which takes ownership. Previously
+           * we used sk_X509_value() instead, but then we'd clean it in the
+           * subsequent sk_X509_pop_free() call.
            */
           X509 *x = sk_X509_pop(ca);
-          if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
+          if(!SSL_CTX_add_client_CA(ctx, x)) {
             X509_free(x);
-            failf(data, "cannot add certificate to certificate chain");
+            failf(data, "cannot add certificate to client CA list");
             goto fail;
           }
-          /* SSL_CTX_add_client_CA() seems to work with either sk_* function,
-           * presumably because it duplicates what we pass to it.
-           */
-          if(!SSL_CTX_add_client_CA(ctx, x)) {
-            failf(data, "cannot add certificate to client CA list");
+          if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
+            X509_free(x);
+            failf(data, "cannot add certificate to certificate chain");
             goto fail;
           }
         }
@@ -558,6 +593,7 @@ int cert_stuff(struct connectdata *conn,
       if(!key_file)
         /* cert & key can only be in PEM case in the same file */
         key_file=cert_file;
+      /* FALLTHROUGH */
     case SSL_FILETYPE_ASN1:
       if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
         failf(data, "unable to set private key file: '%s' type %s",
@@ -571,7 +607,7 @@ int cert_stuff(struct connectdata *conn,
         EVP_PKEY *priv_key = NULL;
         if(data->state.engine) {
           UI_METHOD *ui_method =
-            UI_create_method((char *)"cURL user interface");
+            UI_create_method((char *)"curl user interface");
           if(!ui_method) {
             failf(data, "unable do create " OSSL_PACKAGE
                   " user-interface method");
@@ -585,7 +621,7 @@ int cert_stuff(struct connectdata *conn,
           priv_key = (EVP_PKEY *)
             ENGINE_load_private_key(data->state.engine, key_file,
                                     ui_method,
-                                    data->set.str[STRING_KEY_PASSWD]);
+                                    key_passwd);
           UI_destroy_method(ui_method);
           if(!priv_key) {
             failf(data, "failed to load private key from crypto engine");
@@ -681,17 +717,6 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
 #endif
 }
 
-/* Return error string for last OpenSSL error
- */
-static char *ossl_strerror(unsigned long error, char *buf, size_t size)
-{
-  /* OpenSSL 0.9.6 and later has a function named
-     ERR_error_string_n() that takes the size of the buffer as a
-     third argument */
-  ERR_error_string_n(error, buf, size);
-  return buf;
-}
-
 /**
  * Global SSL init
  *
@@ -793,7 +818,7 @@ int Curl_ossl_check_cxn(struct connectdata *conn)
                (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK);
   if(nread == 0)
     return 0; /* connection has been closed */
-  else if(nread == 1)
+  if(nread == 1)
     return 1; /* connection still in place */
   else if(nread == -1) {
       int err = SOCKERRNO;
@@ -916,27 +941,31 @@ struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
 }
 
 
-/*
- * This function is called when an SSL connection is closed.
- */
-void Curl_ossl_close(struct connectdata *conn, int sockindex)
+static void ossl_close(struct ssl_connect_data *connssl)
 {
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
   if(connssl->handle) {
     (void)SSL_shutdown(connssl->handle);
     SSL_set_connect_state(connssl->handle);
 
-    SSL_free (connssl->handle);
+    SSL_free(connssl->handle);
     connssl->handle = NULL;
   }
   if(connssl->ctx) {
-    SSL_CTX_free (connssl->ctx);
+    SSL_CTX_free(connssl->ctx);
     connssl->ctx = NULL;
   }
 }
 
 /*
+ * This function is called when an SSL connection is closed.
+ */
+void Curl_ossl_close(struct connectdata *conn, int sockindex)
+{
+  ossl_close(&conn->ssl[sockindex]);
+  ossl_close(&conn->proxy_ssl[sockindex]);
+}
+
+/*
  * This function is called to shut down the SSL layer but keep the
  * socket open (CCC - Clear Command Channel)
  */
@@ -994,8 +1023,10 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
         default:
           /* openssl/ssl.h says "look at error stack/return value/errno" */
           sslerror = ERR_get_error();
-          failf(conn->data, OSSL_PACKAGE " SSL read: %s, errno %d",
-                ossl_strerror(sslerror, buf, sizeof(buf)),
+          failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
+                (sslerror ?
+                 ossl_strerror(sslerror, buf, sizeof(buf)) :
+                 SSL_ERROR_to_str(err)),
                 SOCKERRNO);
           done = 1;
           break;
@@ -1031,7 +1062,7 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
 #endif
     }
 
-    SSL_free (connssl->handle);
+    SSL_free(connssl->handle);
     connssl->handle = NULL;
   }
   return retval;
@@ -1107,16 +1138,20 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
   CURLcode result = CURLE_OK;
   bool dNSName = FALSE; /* if a dNSName field exists in the cert */
   bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const char * const dispname = SSL_IS_PROXY() ?
+    conn->http_proxy.host.dispname : conn->host.dispname;
 
 #ifdef ENABLE_IPV6
   if(conn->bits.ipv6_ip &&
-     Curl_inet_pton(AF_INET6, conn->host.name, &addr)) {
+     Curl_inet_pton(AF_INET6, hostname, &addr)) {
     target = GEN_IPADD;
     addrlen = sizeof(struct in6_addr);
   }
   else
 #endif
-    if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) {
+    if(Curl_inet_pton(AF_INET, hostname, &addr)) {
       target = GEN_IPADD;
       addrlen = sizeof(struct in_addr);
     }
@@ -1165,11 +1200,11 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
           if((altlen == strlen(altptr)) &&
              /* if this isn't true, there was an embedded zero in the name
                 string and we cannot match it. */
-             Curl_cert_hostcheck(altptr, conn->host.name)) {
+             Curl_cert_hostcheck(altptr, hostname)) {
             dnsmatched = TRUE;
             infof(data,
                   " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
-                  conn->host.dispname, altptr);
+                  dispname, altptr);
           }
           break;
 
@@ -1180,7 +1215,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
             ipmatched = TRUE;
             infof(data,
                   " subjectAltName: host \"%s\" matched cert's IP address!\n",
-                  conn->host.dispname);
+                  dispname);
           }
           break;
         }
@@ -1196,9 +1231,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
     /* an alternative name matched */
     ;
   else if(dNSName || iPAddress) {
-    infof(data, " subjectAltName does not match %s\n", conn->host.dispname);
+    infof(data, " subjectAltName does not match %s\n", dispname);
     failf(data, "SSL: no alternative certificate subject name matches "
-          "target host name '%s'", conn->host.dispname);
+          "target host name '%s'", dispname);
     result = CURLE_PEER_FAILED_VERIFICATION;
   }
   else {
@@ -1272,9 +1307,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
             "SSL: unable to obtain common name from peer certificate");
       result = CURLE_PEER_FAILED_VERIFICATION;
     }
-    else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
+    else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
       failf(data, "SSL: certificate subject name '%s' does not match "
-            "target host name '%s'", peer_CN, conn->host.dispname);
+            "target host name '%s'", peer_CN, dispname);
       result = CURLE_PEER_FAILED_VERIFICATION;
     }
     else {
@@ -1336,7 +1371,8 @@ static CURLcode verifystatus(struct connectdata *conn,
   st = SSL_CTX_get_cert_store(connssl->ctx);
 
 #if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
-     defined(LIBRESSL_VERSION_NUMBER))
+     (defined(LIBRESSL_VERSION_NUMBER) &&                               \
+      LIBRESSL_VERSION_NUMBER <= 0x2040200fL))
   /* The authorized responder cert in the OCSP response MUST be signed by the
      peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert,
      no problem, but if it's an intermediate cert OpenSSL has a bug where it
@@ -1425,7 +1461,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
 {
 #ifdef SSL2_VERSION_MAJOR
   if(ssl_ver == SSL2_VERSION_MAJOR) {
-    switch (msg) {
+    switch(msg) {
       case SSL2_MT_ERROR:
         return "Error";
       case SSL2_MT_CLIENT_HELLO:
@@ -1449,7 +1485,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
   else
 #endif
   if(ssl_ver == SSL3_VERSION_MAJOR) {
-    switch (msg) {
+    switch(msg) {
       case SSL3_MT_HELLO_REQUEST:
         return "Hello request";
       case SSL3_MT_CLIENT_HELLO:
@@ -1549,6 +1585,11 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
     verstr = "TLSv1.2";
     break;
 #endif
+#ifdef TLS1_3_VERSION
+  case TLS1_3_VERSION:
+    verstr = "TLSv1.3";
+    break;
+#endif
   case 0:
     break;
   default:
@@ -1571,7 +1612,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
     else
       tls_rt_name = "";
 
-    msg_type = *(char*)buf;
+    msg_type = *(char *)buf;
     msg_name = ssl_msg_type(ssl_ver, msg_type);
 
     txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
@@ -1613,7 +1654,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
 #ifdef HAS_NPN
 
 /*
- * in is a list of lenght prefixed strings. this function has to select
+ * in is a list of length prefixed strings. this function has to select
  * the protocol we want to use from the list and write its string into out.
  */
 
@@ -1677,6 +1718,10 @@ get_ssl_version_txt(SSL *ssl)
     return "";
 
   switch(SSL_version(ssl)) {
+#ifdef TLS1_3_VERSION
+  case TLS1_3_VERSION:
+    return "TLSv1.3";
+#endif
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
   case TLS1_2_VERSION:
     return "TLSv1.2";
@@ -1693,6 +1738,85 @@ get_ssl_version_txt(SSL *ssl)
   return "unknown";
 }
 
+static CURLcode
+set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
+                        int sockindex)
+{
+#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION)
+  /* convoluted #if condition just to avoid compiler warnings on unused
+     variable */
+  struct Curl_easy *data = conn->data;
+#endif
+  long ssl_version = SSL_CONN_CONFIG(version);
+  long ssl_version_max = SSL_CONN_CONFIG(version_max);
+
+  if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
+    ssl_version_max = ssl_version << 16;
+  }
+
+  switch(ssl_version) {
+    case CURL_SSLVERSION_TLSv1_3:
+#ifdef TLS1_3_VERSION
+    {
+      struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+      SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
+      *ctx_options |= SSL_OP_NO_TLSv1_2;
+    }
+#else
+      (void)sockindex;
+      failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+      return CURLE_NOT_BUILT_IN;
+#endif
+    case CURL_SSLVERSION_TLSv1_2:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+      *ctx_options |= SSL_OP_NO_TLSv1_1;
+#else
+      failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
+      return CURLE_NOT_BUILT_IN;
+#endif
+      /* FALLTHROUGH */
+    case CURL_SSLVERSION_TLSv1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+      *ctx_options |= SSL_OP_NO_TLSv1;
+#else
+      failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
+      return CURLE_NOT_BUILT_IN;
+#endif
+      /* FALLTHROUGH */
+    case CURL_SSLVERSION_TLSv1_0:
+      *ctx_options |= SSL_OP_NO_SSLv2;
+      *ctx_options |= SSL_OP_NO_SSLv3;
+      break;
+  }
+
+  switch(ssl_version_max) {
+    case CURL_SSLVERSION_MAX_TLSv1_0:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+      *ctx_options |= SSL_OP_NO_TLSv1_1;
+#endif
+      /* FALLTHROUGH */
+    case CURL_SSLVERSION_MAX_TLSv1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+      *ctx_options |= SSL_OP_NO_TLSv1_2;
+#endif
+      /* FALLTHROUGH */
+    case CURL_SSLVERSION_MAX_TLSv1_2:
+    case CURL_SSLVERSION_MAX_DEFAULT:
+#ifdef TLS1_3_VERSION
+      *ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
+      break;
+    case CURL_SSLVERSION_MAX_TLSv1_3:
+#ifdef TLS1_3_VERSION
+      break;
+#else
+      failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+      return CURLE_NOT_BUILT_IN;
+#endif
+  }
+  return CURLE_OK;
+}
+
 static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 {
   CURLcode result = CURLE_OK;
@@ -1702,32 +1826,49 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   X509_LOOKUP *lookup = NULL;
   curl_socket_t sockfd = conn->sock[sockindex];
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  long ctx_options;
+  long ctx_options = 0;
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
   bool sni;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 #ifdef ENABLE_IPV6
   struct in6_addr addr;
 #else
   struct in_addr addr;
 #endif
 #endif
+  long * const certverifyresult = SSL_IS_PROXY() ?
+    &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+  const long int ssl_version = SSL_CONN_CONFIG(version);
+#ifdef USE_TLS_SRP
+  const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
+#endif
+  char * const ssl_cert = SSL_SET_OPTION(cert);
+  const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
+  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+  const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+  const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+  char error_buffer[256];
 
   DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
 
   /* Make funny stuff to get random input */
-  Curl_ossl_seed(data);
+  result = Curl_ossl_seed(data);
+  if(result)
+    return result;
 
-  data->set.ssl.certverifyresult = !X509_V_OK;
+  *certverifyresult = !X509_V_OK;
 
   /* check to see if we've been told to use an explicit SSL/TLS version */
 
-  switch(data->set.ssl.version) {
-  default:
+  switch(ssl_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:
     /* it will be handled later with the context options */
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
     !defined(LIBRESSL_VERSION_NUMBER)
@@ -1743,7 +1884,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     return CURLE_NOT_BUILT_IN;
 #else
 #ifdef USE_TLS_SRP
-    if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+    if(ssl_authtype == CURL_TLSAUTH_SRP)
       return CURLE_SSL_CONNECT_ERROR;
 #endif
     req_method = SSLv2_client_method();
@@ -1756,13 +1897,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     return CURLE_NOT_BUILT_IN;
 #else
 #ifdef USE_TLS_SRP
-    if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+    if(ssl_authtype == CURL_TLSAUTH_SRP)
       return CURLE_SSL_CONNECT_ERROR;
 #endif
     req_method = SSLv3_client_method();
     use_sni(FALSE);
     break;
 #endif
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
   if(connssl->ctx)
@@ -1771,7 +1915,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 
   if(!connssl->ctx) {
     failf(data, "SSL: couldn't create a context: %s",
-          ERR_error_string(ERR_peek_error(), NULL));
+          ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
     return CURLE_OUT_OF_MEMORY;
   }
 
@@ -1841,14 +1985,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
   /* unless the user explicitly ask to allow the protocol vulnerability we
      use the work-around */
-  if(!conn->data->set.ssl_enable_beast)
+  if(!SSL_SET_OPTION(enable_beast))
     ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
 #endif
 
-  switch(data->set.ssl.version) {
+  switch(ssl_version) {
   case CURL_SSLVERSION_SSLv3:
 #ifdef USE_TLS_SRP
-    if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+    if(ssl_authtype == CURL_TLSAUTH_SRP) {
       infof(data, "Set version TLSv1.x for SRP authorisation\n");
     }
 #endif
@@ -1857,6 +2001,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     ctx_options |= SSL_OP_NO_TLSv1_1;
     ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+    ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
 #endif
     break;
 
@@ -1867,43 +2014,33 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     break;
 
   case CURL_SSLVERSION_TLSv1_0:
-    ctx_options |= SSL_OP_NO_SSLv2;
-    ctx_options |= SSL_OP_NO_SSLv3;
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
-    ctx_options |= SSL_OP_NO_TLSv1_1;
-    ctx_options |= SSL_OP_NO_TLSv1_2;
-#endif
-    break;
-
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
   case CURL_SSLVERSION_TLSv1_1:
-    ctx_options |= SSL_OP_NO_SSLv2;
-    ctx_options |= SSL_OP_NO_SSLv3;
-    ctx_options |= SSL_OP_NO_TLSv1;
-    ctx_options |= SSL_OP_NO_TLSv1_2;
-    break;
-
   case CURL_SSLVERSION_TLSv1_2:
-    ctx_options |= SSL_OP_NO_SSLv2;
-    ctx_options |= SSL_OP_NO_SSLv3;
-    ctx_options |= SSL_OP_NO_TLSv1;
-    ctx_options |= SSL_OP_NO_TLSv1_1;
+  case CURL_SSLVERSION_TLSv1_3:
+    result = set_ssl_version_min_max(&ctx_options, conn, sockindex);
+    if(result != CURLE_OK)
+       return result;
     break;
-#endif
 
-#ifndef OPENSSL_NO_SSL2
   case CURL_SSLVERSION_SSLv2:
+#ifndef OPENSSL_NO_SSL2
     ctx_options |= SSL_OP_NO_SSLv3;
     ctx_options |= SSL_OP_NO_TLSv1;
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     ctx_options |= SSL_OP_NO_TLSv1_1;
     ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+    ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
 #endif
     break;
+#else
+    failf(data, OSSL_PACKAGE " was built without SSLv2 support");
+    return CURLE_NOT_BUILT_IN;
 #endif
 
   default:
-    failf(data, "Unsupported SSL protocol version");
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
@@ -1942,19 +2079,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   }
 #endif
 
-  if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
-    if(!cert_stuff(conn,
-                   connssl->ctx,
-                   data->set.str[STRING_CERT],
-                   data->set.str[STRING_CERT_TYPE],
-                   data->set.str[STRING_KEY],
-                   data->set.str[STRING_KEY_TYPE])) {
+  if(ssl_cert || ssl_cert_type) {
+    if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type,
+                   SSL_SET_OPTION(key), SSL_SET_OPTION(key_type),
+                   SSL_SET_OPTION(key_passwd))) {
       /* failf() is already done in cert_stuff() */
       return CURLE_SSL_CERTPROBLEM;
     }
   }
 
-  ciphers = data->set.str[STRING_SSL_CIPHER_LIST];
+  ciphers = SSL_CONN_CONFIG(cipher_list);
   if(!ciphers)
     ciphers = (char *)DEFAULT_CIPHER_SELECTION;
   if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) {
@@ -1964,18 +2098,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   infof(data, "Cipher selection: %s\n", ciphers);
 
 #ifdef USE_TLS_SRP
-  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
-    infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+  if(ssl_authtype == CURL_TLSAUTH_SRP) {
+    char * const ssl_username = SSL_SET_OPTION(username);
 
-    if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) {
+    infof(data, "Using TLS-SRP username: %s\n", ssl_username);
+
+    if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) {
       failf(data, "Unable to set SRP user name");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
-    if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) {
+    if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_SET_OPTION(password))) {
       failf(data, "failed setting SRP password");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
-    if(!data->set.str[STRING_SSL_CIPHER_LIST]) {
+    if(!SSL_CONN_CONFIG(cipher_list)) {
       infof(data, "Setting cipher list SRP\n");
 
       if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
@@ -1985,28 +2121,23 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     }
   }
 #endif
-  if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) {
+
+  if(ssl_cafile || ssl_capath) {
     /* tell SSL where to find CA certificates that are used to verify
        the servers certificate. */
-    if(!SSL_CTX_load_verify_locations(connssl->ctx,
-                                       data->set.str[STRING_SSL_CAFILE],
-                                       data->set.str[STRING_SSL_CAPATH])) {
-      if(data->set.ssl.verifypeer) {
+    if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) {
+      if(verifypeer) {
         /* Fail if we insist on successfully verifying the server. */
         failf(data, "error setting certificate verify locations:\n"
               "  CAfile: %s\n  CApath: %s",
-              data->set.str[STRING_SSL_CAFILE]?
-              data->set.str[STRING_SSL_CAFILE]: "none",
-              data->set.str[STRING_SSL_CAPATH]?
-              data->set.str[STRING_SSL_CAPATH] : "none");
+              ssl_cafile ? ssl_cafile : "none",
+              ssl_capath ? ssl_capath : "none");
         return CURLE_SSL_CACERT_BADFILE;
       }
-      else {
-        /* Just continue with a warning if no strict  certificate verification
-           is required. */
-        infof(data, "error setting certificate verify locations,"
-              " continuing anyway:\n");
-      }
+      /* Just continue with a warning if no strict  certificate verification
+         is required. */
+      infof(data, "error setting certificate verify locations,"
+            " continuing anyway:\n");
     }
     else {
       /* Everything is fine. */
@@ -2015,40 +2146,33 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     infof(data,
           "  CAfile: %s\n"
           "  CApath: %s\n",
-          data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
-          "none",
-          data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
-          "none");
+          ssl_cafile ? ssl_cafile : "none",
+          ssl_capath ? ssl_capath : "none");
   }
 #ifdef CURL_CA_FALLBACK
-  else if(data->set.ssl.verifypeer) {
+  else if(verifypeer) {
     /* verfying the peer without any CA certificates won't
        work so use openssl's built in default as fallback */
     SSL_CTX_set_default_verify_paths(connssl->ctx);
   }
 #endif
 
-  if(data->set.str[STRING_SSL_CRLFILE]) {
+  if(ssl_crlfile) {
     /* tell SSL where to find CRL file that is used to check certificate
      * revocation */
     lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx),
                                  X509_LOOKUP_file());
     if(!lookup ||
-       (!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE],
-                            X509_FILETYPE_PEM)) ) {
-      failf(data, "error loading CRL file: %s",
-            data->set.str[STRING_SSL_CRLFILE]);
+       (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
+      failf(data, "error loading CRL file: %s", ssl_crlfile);
       return CURLE_SSL_CRL_BADFILE;
     }
-    else {
-      /* Everything is fine. */
-      infof(data, "successfully load CRL file:\n");
-      X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
-                           X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
-    }
-    infof(data,
-          "  CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ?
-          data->set.str[STRING_SSL_CRLFILE]: "none");
+    /* Everything is fine. */
+    infof(data, "successfully load CRL file:\n");
+    X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
+                         X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+
+    infof(data, "  CRLfile: %s\n", ssl_crlfile);
   }
 
   /* Try building a chain using issuers in the trusted store first to avoid
@@ -2059,7 +2183,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
   */
 #if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
-  if(data->set.ssl.verifypeer) {
+  if(verifypeer) {
     X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
                          X509_V_FLAG_TRUSTED_FIRST);
   }
@@ -2070,8 +2194,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
    * anyway. In the latter case the result of the verification is checked with
    * SSL_get_verify_result() below. */
   SSL_CTX_set_verify(connssl->ctx,
-                     data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
-                     NULL);
+                     verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
 
   /* give application a chance to interfere with SSL set up. */
   if(data->set.ssl.fsslctx) {
@@ -2094,48 +2217,56 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
     !defined(OPENSSL_NO_OCSP)
-  if(data->set.ssl.verifystatus)
+  if(SSL_CONN_CONFIG(verifystatus))
     SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp);
 #endif
 
   SSL_set_connect_state(connssl->handle);
 
   connssl->server_cert = 0x0;
-
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-  if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+  if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
 #ifdef ENABLE_IPV6
-     (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+     (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
 #endif
      sni &&
-     !SSL_set_tlsext_host_name(connssl->handle, conn->host.name))
+     !SSL_set_tlsext_host_name(connssl->handle, hostname))
     infof(data, "WARNING: failed to configure server name indication (SNI) "
           "TLS extension\n");
 #endif
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     void *ssl_sessionid = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
       /* we got a session id, use it! */
       if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "SSL: SSL_set_session failed: %s",
-              ERR_error_string(ERR_get_error(), NULL));
+              ossl_strerror(ERR_get_error(), error_buffer,
+                            sizeof(error_buffer)));
         return CURLE_SSL_CONNECT_ERROR;
       }
       /* Informational message */
-      infof (data, "SSL re-using session ID\n");
+      infof(data, "SSL re-using session ID\n");
     }
     Curl_ssl_sessionid_unlock(conn);
   }
 
-  /* pass the raw socket into the SSL layers */
-  if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+  if(conn->proxy_ssl[sockindex].use) {
+    BIO *const bio = BIO_new(BIO_f_ssl());
+    DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
+    DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
+    DEBUGASSERT(bio != NULL);
+    BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE);
+    SSL_set_bio(connssl->handle, bio, bio);
+  }
+  else if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+    /* pass the raw socket into the SSL layers */
     failf(data, "SSL: SSL_set_fd failed: %s",
-          ERR_error_string(ERR_get_error(), NULL));
+          ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
     return CURLE_SSL_CONNECT_ERROR;
   }
 
@@ -2149,9 +2280,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
   struct Curl_easy *data = conn->data;
   int err;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  long * const certverifyresult = SSL_IS_PROXY() ?
+    &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
   DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
-             || ssl_connect_2_reading == connssl->connecting_state
-             || ssl_connect_2_writing == connssl->connecting_state);
+              || ssl_connect_2_reading == connssl->connecting_state
+              || ssl_connect_2_writing == connssl->connecting_state);
 
   ERR_clear_error();
 
@@ -2167,15 +2300,14 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
       connssl->connecting_state = ssl_connect_2_reading;
       return CURLE_OK;
     }
-    else if(SSL_ERROR_WANT_WRITE == detail) {
+    if(SSL_ERROR_WANT_WRITE == detail) {
       connssl->connecting_state = ssl_connect_2_writing;
       return CURLE_OK;
     }
     else {
       /* untreated error */
       unsigned long errdetail;
-      char error_buffer[256]=""; /* OpenSSL documents that this must be at
-                                    least 256 bytes long. */
+      char error_buffer[256]="";
       CURLcode result;
       long lerr;
       int lib;
@@ -2198,7 +2330,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
 
         lerr = SSL_get_verify_result(connssl->handle);
         if(lerr != X509_V_OK) {
-          data->set.ssl.certverifyresult = lerr;
+          *certverifyresult = lerr;
           snprintf(error_buffer, sizeof(error_buffer),
                    "SSL certificate problem: %s",
                    X509_verify_cert_error_string(lerr));
@@ -2220,8 +2352,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
        * the SO_ERROR is also lost.
        */
       if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
-        failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
-              conn->host.name, conn->remote_port);
+        const char * const hostname = SSL_IS_PROXY() ?
+          conn->http_proxy.host.name : conn->host.name;
+        const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+        failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%ld ",
+              SSL_ERROR_to_str(detail), hostname, port);
         return result;
       }
 
@@ -2245,7 +2380,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
      * negotiated
      */
     if(conn->bits.tls_enable_alpn) {
-      const unsigned char* neg_protocol;
+      const unsigned char *neg_protocol;
       unsigned int len;
       SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len);
       if(len != 0) {
@@ -2276,7 +2411,8 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
 {
   int i, ilen;
 
-  if((ilen = (int)len) < 0)
+  ilen = (int)len;
+  if(ilen < 0)
     return 1; /* buffer too big */
 
   i = i2t_ASN1_OBJECT(buf, ilen, a);
@@ -2493,44 +2629,25 @@ static CURLcode get_cert_chain(struct connectdata *conn,
         {
           const BIGNUM *n;
           const BIGNUM *e;
-          const BIGNUM *d;
-          const BIGNUM *p;
-          const BIGNUM *q;
-          const BIGNUM *dmp1;
-          const BIGNUM *dmq1;
-          const BIGNUM *iqmp;
 
-          RSA_get0_key(rsa, &n, &e, &d);
-          RSA_get0_factors(rsa, &p, &q);
-          RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
+          RSA_get0_key(rsa, &n, &e, NULL);
           BN_print(mem, n);
           push_certinfo("RSA Public Key", i);
           print_pubkey_BN(rsa, n, i);
           print_pubkey_BN(rsa, e, i);
-          print_pubkey_BN(rsa, d, i);
-          print_pubkey_BN(rsa, p, i);
-          print_pubkey_BN(rsa, q, i);
-          print_pubkey_BN(rsa, dmp1, i);
-          print_pubkey_BN(rsa, dmq1, i);
-          print_pubkey_BN(rsa, iqmp, i);
         }
 #else
         BIO_printf(mem, "%d", BN_num_bits(rsa->n));
         push_certinfo("RSA Public Key", i);
         print_pubkey_BN(rsa, n, i);
         print_pubkey_BN(rsa, e, i);
-        print_pubkey_BN(rsa, d, i);
-        print_pubkey_BN(rsa, p, i);
-        print_pubkey_BN(rsa, q, i);
-        print_pubkey_BN(rsa, dmp1, i);
-        print_pubkey_BN(rsa, dmq1, i);
-        print_pubkey_BN(rsa, iqmp, i);
 #endif
 
         break;
       }
       case EVP_PKEY_DSA:
       {
+#ifndef OPENSSL_NO_DSA
         DSA *dsa;
 #ifdef HAVE_OPAQUE_EVP_PKEY
         dsa = EVP_PKEY_get0_DSA(pubkey);
@@ -2542,25 +2659,23 @@ static CURLcode get_cert_chain(struct connectdata *conn,
           const BIGNUM *p;
           const BIGNUM *q;
           const BIGNUM *g;
-          const BIGNUM *priv_key;
           const BIGNUM *pub_key;
 
           DSA_get0_pqg(dsa, &p, &q, &g);
-          DSA_get0_key(dsa, &pub_key, &priv_key);
+          DSA_get0_key(dsa, &pub_key, NULL);
 
           print_pubkey_BN(dsa, p, i);
           print_pubkey_BN(dsa, q, i);
           print_pubkey_BN(dsa, g, i);
-          print_pubkey_BN(dsa, priv_key, i);
           print_pubkey_BN(dsa, pub_key, i);
         }
 #else
         print_pubkey_BN(dsa, p, i);
         print_pubkey_BN(dsa, q, i);
         print_pubkey_BN(dsa, g, i);
-        print_pubkey_BN(dsa, priv_key, i);
         print_pubkey_BN(dsa, pub_key, i);
 #endif
+#endif /* !OPENSSL_NO_DSA */
         break;
       }
       case EVP_PKEY_DH:
@@ -2576,20 +2691,17 @@ static CURLcode get_cert_chain(struct connectdata *conn,
           const BIGNUM *p;
           const BIGNUM *q;
           const BIGNUM *g;
-          const BIGNUM *priv_key;
           const BIGNUM *pub_key;
           DH_get0_pqg(dh, &p, &q, &g);
-          DH_get0_key(dh, &pub_key, &priv_key);
+          DH_get0_key(dh, &pub_key, NULL);
           print_pubkey_BN(dh, p, i);
           print_pubkey_BN(dh, q, i);
           print_pubkey_BN(dh, g, i);
-          print_pubkey_BN(dh, priv_key, i);
           print_pubkey_BN(dh, pub_key, i);
        }
 #else
         print_pubkey_BN(dh, p, i);
         print_pubkey_BN(dh, g, i);
-        print_pubkey_BN(dh, priv_key, i);
         print_pubkey_BN(dh, pub_key, i);
 #endif
         break;
@@ -2696,8 +2808,10 @@ static CURLcode servercert(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   X509 *issuer;
   FILE *fp;
-  char *buffer = data->state.buffer;
+  char buffer[2048];
   const char *ptr;
+  long * const certverifyresult = SSL_IS_PROXY() ?
+    &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
   BIO *mem = BIO_new(BIO_s_mem());
 
   if(data->set.ssl.certinfo)
@@ -2706,6 +2820,7 @@ static CURLcode servercert(struct connectdata *conn,
 
   connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
   if(!connssl->server_cert) {
+    BIO_free(mem);
     if(!strict)
       return CURLE_OK;
 
@@ -2713,10 +2828,10 @@ static CURLcode servercert(struct connectdata *conn,
     return CURLE_PEER_FAILED_VERIFICATION;
   }
 
-  infof(data, "Server certificate:\n");
+  infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
 
   rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
-                         buffer, BUFSIZE);
+                         buffer, sizeof(buffer));
   infof(data, " subject: %s\n", rc?"[NONE]":buffer);
 
   ASN1_TIME_print(mem, X509_get0_notBefore(connssl->server_cert));
@@ -2731,7 +2846,7 @@ static CURLcode servercert(struct connectdata *conn,
 
   BIO_free(mem);
 
-  if(data->set.ssl.verifyhost) {
+  if(SSL_CONN_CONFIG(verifyhost)) {
     result = verifyhost(conn, connssl->server_cert);
     if(result) {
       X509_free(connssl->server_cert);
@@ -2741,7 +2856,7 @@ static CURLcode servercert(struct connectdata *conn,
   }
 
   rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert),
-                         buffer, BUFSIZE);
+                         buffer, sizeof(buffer));
   if(rc) {
     if(strict)
       failf(data, "SSL: couldn't get X509-issuer name!");
@@ -2754,12 +2869,12 @@ static CURLcode servercert(struct connectdata *conn,
        deallocating the certificate. */
 
     /* e.g. match issuer name with provided issuer certificate */
-    if(data->set.str[STRING_SSL_ISSUERCERT]) {
-      fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], FOPEN_READTEXT);
+    if(SSL_SET_OPTION(issuercert)) {
+      fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT);
       if(!fp) {
         if(strict)
           failf(data, "SSL: Unable to open issuer cert (%s)",
-                data->set.str[STRING_SSL_ISSUERCERT]);
+                SSL_SET_OPTION(issuercert));
         X509_free(connssl->server_cert);
         connssl->server_cert = NULL;
         return CURLE_SSL_ISSUER_ERROR;
@@ -2769,7 +2884,7 @@ static CURLcode servercert(struct connectdata *conn,
       if(!issuer) {
         if(strict)
           failf(data, "SSL: Unable to read issuer cert (%s)",
-                data->set.str[STRING_SSL_ISSUERCERT]);
+                SSL_SET_OPTION(issuercert));
         X509_free(connssl->server_cert);
         X509_free(issuer);
         fclose(fp);
@@ -2781,7 +2896,7 @@ static CURLcode servercert(struct connectdata *conn,
       if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) {
         if(strict)
           failf(data, "SSL: Certificate issuer check failed (%s)",
-                data->set.str[STRING_SSL_ISSUERCERT]);
+                SSL_SET_OPTION(issuercert));
         X509_free(connssl->server_cert);
         X509_free(issuer);
         connssl->server_cert = NULL;
@@ -2789,15 +2904,14 @@ static CURLcode servercert(struct connectdata *conn,
       }
 
       infof(data, " SSL certificate issuer check ok (%s)\n",
-            data->set.str[STRING_SSL_ISSUERCERT]);
+            SSL_SET_OPTION(issuercert));
       X509_free(issuer);
     }
 
-    lerr = data->set.ssl.certverifyresult =
-      SSL_get_verify_result(connssl->handle);
+    lerr = *certverifyresult = SSL_get_verify_result(connssl->handle);
 
-    if(data->set.ssl.certverifyresult != X509_V_OK) {
-      if(data->set.ssl.verifypeer) {
+    if(*certverifyresult != X509_V_OK) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         /* We probably never reach this, because SSL_connect() will fail
            and we return earlier if verifypeer is set? */
         if(strict)
@@ -2816,7 +2930,7 @@ static CURLcode servercert(struct connectdata *conn,
 
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
     !defined(OPENSSL_NO_OCSP)
-  if(data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     result = verifystatus(conn, connssl);
     if(result) {
       X509_free(connssl->server_cert);
@@ -2830,7 +2944,8 @@ static CURLcode servercert(struct connectdata *conn,
     /* when not strict, we don't bother about the verify cert problems */
     result = CURLE_OK;
 
-  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+  ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+                         data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
   if(!result && ptr) {
     result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr);
     if(result)
@@ -2852,7 +2967,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     bool incache;
     SSL_SESSION *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -2864,7 +2979,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
         regardless of its state. */
 
     Curl_ssl_sessionid_lock(conn);
-    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+    incache = !(Curl_ssl_getsessionid(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");
@@ -2875,7 +2991,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
 
     if(!incache) {
       result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
-                                      0 /* unknown size */);
+                                      0 /* unknown size */, sockindex);
       if(result) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "failed to store ssl session");
@@ -2899,8 +3015,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
    * operations.
    */
 
-  result = servercert(conn, connssl,
-                      (data->set.ssl.verifypeer || data->set.ssl.verifyhost));
+  result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
+                                      SSL_CONN_CONFIG(verifyhost)));
 
   if(!result)
     connssl->connecting_state = ssl_connect_done;
@@ -2920,7 +3036,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   curl_socket_t sockfd = conn->sock[sockindex];
-  long timeout_ms;
+  time_t timeout_ms;
   int what;
 
   /* check if the connection has already been established */
@@ -2973,16 +3089,14 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
         return CURLE_SSL_CONNECT_ERROR;
       }
-      else if(0 == what) {
+      if(0 == what) {
         if(nonblocking) {
           *done = FALSE;
           return CURLE_OK;
         }
-        else {
-          /* timeout */
-          failf(data, "SSL connection timeout");
-          return CURLE_OPERATION_TIMEDOUT;
-        }
+        /* timeout */
+        failf(data, "SSL connection timeout");
+        return CURLE_OPERATION_TIMEDOUT;
       }
       /* socket is readable or writable */
     }
@@ -3048,9 +3162,11 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex)
 {
   if(conn->ssl[connindex].handle)
     /* SSL is in use */
-    return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
-  else
-    return FALSE;
+    return (0 != SSL_pending(conn->ssl[connindex].handle) ||
+           (conn->proxy_ssl[connindex].handle &&
+            0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ?
+           TRUE : FALSE;
+  return FALSE;
 }
 
 static ssize_t ossl_send(struct connectdata *conn,
@@ -3062,8 +3178,7 @@ static ssize_t ossl_send(struct connectdata *conn,
   /* SSL_write() is said to return 'int' while write() and send() returns
      'size_t' */
   int err;
-  char error_buffer[256]; /* OpenSSL documents that this must be at least 256
-                             bytes long. */
+  char error_buffer[256];
   unsigned long sslerror;
   int memlen;
   int rc;
@@ -3093,13 +3208,24 @@ static ssize_t ossl_send(struct connectdata *conn,
       /*  A failure in the SSL library occurred, usually a protocol error.
           The OpenSSL error queue contains more information on the error. */
       sslerror = ERR_get_error();
-      failf(conn->data, "SSL_write() error: %s",
-            ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
+      if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
+         ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
+         conn->ssl[sockindex].state == ssl_connection_complete &&
+         conn->proxy_ssl[sockindex].state == ssl_connection_complete) {
+        char ver[120];
+        Curl_ossl_version(ver, 120);
+        failf(conn->data, "Error: %s does not support double SSL tunneling.",
+              ver);
+      }
+      else
+        failf(conn->data, "SSL_write() error: %s",
+              ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
       *curlcode = CURLE_SEND_ERROR;
       return -1;
     }
     /* a true error */
-    failf(conn->data, "SSL_write() return error %d", err);
+    failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
+          SSL_ERROR_to_str(err), SOCKERRNO);
     *curlcode = CURLE_SEND_ERROR;
     return -1;
   }
@@ -3113,8 +3239,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
                          size_t buffersize,        /* max amount to read */
                          CURLcode *curlcode)
 {
-  char error_buffer[256]; /* OpenSSL documents that this must be at
-                             least 256 bytes long. */
+  char error_buffer[256];
   unsigned long sslerror;
   ssize_t nread;
   int buffsize;
@@ -3144,8 +3269,10 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
       if((nread < 0) || sslerror) {
         /* If the return code was negative or there actually is an error in the
            queue */
-        failf(conn->data, "SSL read: %s, errno %d",
-              ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)),
+        failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d",
+              (sslerror ?
+               ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)) :
+               SSL_ERROR_to_str(err)),
               SOCKERRNO);
         *curlcode = CURLE_RECV_ERROR;
         return -1;
@@ -3178,7 +3305,7 @@ size_t Curl_ossl_version(char *buffer, size_t size)
         sub[0] = 'z';
       }
       else {
-        sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1);
+        sub[0] = (char) (minor_ver + 'a' - 1);
       }
     }
     else
@@ -3195,14 +3322,21 @@ size_t Curl_ossl_version(char *buffer, size_t size)
 }
 
 /* can be called with data == NULL */
-int Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
-                     size_t length)
+CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
+                          size_t length)
 {
+  int rc;
   if(data) {
-    Curl_ossl_seed(data); /* Initiate the seed if not already done */
+    if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */
+      return CURLE_FAILED_INIT; /* couldn't seed for some reason */
+  }
+  else {
+    if(!rand_enough())
+      return CURLE_FAILED_INIT;
   }
-  RAND_bytes(entropy, curlx_uztosi(length));
-  return 0; /* 0 as in no problem */
+  /* RAND_bytes() returns 1 on success, 0 otherwise.  */
+  rc = RAND_bytes(entropy, curlx_uztosi(length));
+  return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
 }
 
 void Curl_ossl_md5sum(unsigned char *tmp, /* input */
diff --git a/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h
index ee18e71..b9648d5 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.h
+++ b/Utilities/cmcurl/lib/vtls/openssl.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -66,8 +66,8 @@ bool Curl_ossl_data_pending(const struct connectdata *conn,
                             int connindex);
 
 /* return 0 if a find random is filled in */
-int Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
-                     size_t length);
+CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
+                          size_t length);
 void Curl_ossl_md5sum(unsigned char *tmp, /* input */
                       size_t tmplen,
                       unsigned char *md5sum /* output */,
@@ -79,6 +79,9 @@ void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
 
 bool Curl_ossl_cert_status_request(void);
 
+/* Support HTTPS-proxy */
+#define HTTPS_PROXY_SUPPORT 1
+
 /* Set the API backend definition to OpenSSL */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL
 
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.c b/Utilities/cmcurl/lib/vtls/polarssl.c
index 18b564e..669091c 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.c
+++ b/Utilities/cmcurl/lib/vtls/polarssl.c
@@ -140,6 +140,68 @@ static void polarssl_debug(void *context, int level, const char *line)
 static Curl_recv polarssl_recv;
 static Curl_send polarssl_send;
 
+static CURLcode polarssl_version_from_curl(int *polarver, long ssl_version)
+{
+  switch(ssl_version) {
+    case CURL_SSLVERSION_TLSv1_0:
+      *polarver = SSL_MINOR_VERSION_1;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_1:
+      *polarver = SSL_MINOR_VERSION_2;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_2:
+      *polarver = SSL_MINOR_VERSION_3;
+      return CURLE_OK;
+    case CURL_SSLVERSION_TLSv1_3:
+      break;
+  }
+  return CURLE_SSL_CONNECT_ERROR;
+}
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+{
+  struct Curl_easy *data = conn->data;
+  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+  long ssl_version = SSL_CONN_CONFIG(version);
+  long ssl_version_max = SSL_CONN_CONFIG(version_max);
+  int ssl_min_ver = SSL_MINOR_VERSION_1;
+  int ssl_max_ver = SSL_MINOR_VERSION_1;
+  CURLcode result = CURLE_OK;
+
+  switch(ssl_version) {
+    case CURL_SSLVERSION_DEFAULT:
+    case CURL_SSLVERSION_TLSv1:
+      ssl_version = CURL_SSLVERSION_TLSv1_0;
+      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      break;
+  }
+
+  switch(ssl_version_max) {
+    case CURL_SSLVERSION_MAX_NONE:
+      ssl_version_max = ssl_version << 16;
+      break;
+    case CURL_SSLVERSION_MAX_DEFAULT:
+      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      break;
+  }
+
+  result = polarssl_version_from_curl(&ssl_min_ver, ssl_version);
+  if(result) {
+    failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+    return result;
+  }
+  result = polarssl_version_from_curl(&ssl_max_ver, ssl_version_max >> 16);
+  if(result) {
+    failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+    return result;
+  }
+
+  ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
+  ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
+
+  return result;
+}
 
 static CURLcode
 polarssl_connect_step1(struct connectdata *conn,
@@ -147,12 +209,16 @@ polarssl_connect_step1(struct connectdata *conn,
 {
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+  const char *capath = SSL_CONN_CONFIG(CApath);
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
   int ret = -1;
   char errorbuf[128];
   errorbuf[0]=0;
 
   /* PolarSSL only supports SSLv3 and TLSv1 */
-  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
     failf(data, "PolarSSL does not support SSLv2");
     return CURLE_SSL_CONNECT_ERROR;
   }
@@ -180,30 +246,29 @@ polarssl_connect_step1(struct connectdata *conn,
   /* Load the trusted CA */
   memset(&connssl->cacert, 0, sizeof(x509_crt));
 
-  if(data->set.str[STRING_SSL_CAFILE]) {
+  if(SSL_CONN_CONFIG(CAfile)) {
     ret = x509_crt_parse_file(&connssl->cacert,
-                              data->set.str[STRING_SSL_CAFILE]);
+                              SSL_CONN_CONFIG(CAfile));
 
     if(ret<0) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
+            SSL_CONN_CONFIG(CAfile), -ret, errorbuf);
 
-      if(data->set.ssl.verifypeer)
+      if(SSL_CONN_CONFIG(verifypeer))
         return CURLE_SSL_CACERT_BADFILE;
     }
   }
 
-  if(data->set.str[STRING_SSL_CAPATH]) {
-    ret = x509_crt_parse_path(&connssl->cacert,
-                              data->set.str[STRING_SSL_CAPATH]);
+  if(capath) {
+    ret = x509_crt_parse_path(&connssl->cacert, capath);
 
     if(ret<0) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
+            capath, -ret, errorbuf);
 
-      if(data->set.ssl.verifypeer)
+      if(SSL_CONN_CONFIG(verifypeer))
         return CURLE_SSL_CACERT_BADFILE;
     }
   }
@@ -211,25 +276,25 @@ polarssl_connect_step1(struct connectdata *conn,
   /* Load the client certificate */
   memset(&connssl->clicert, 0, sizeof(x509_crt));
 
-  if(data->set.str[STRING_CERT]) {
+  if(SSL_SET_OPTION(cert)) {
     ret = x509_crt_parse_file(&connssl->clicert,
-                              data->set.str[STRING_CERT]);
+                              SSL_SET_OPTION(cert));
 
     if(ret) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_CERT], -ret, errorbuf);
+            SSL_SET_OPTION(cert), -ret, errorbuf);
 
       return CURLE_SSL_CERTPROBLEM;
     }
   }
 
   /* Load the client private key */
-  if(data->set.str[STRING_KEY]) {
+  if(SSL_SET_OPTION(key)) {
     pk_context pk;
     pk_init(&pk);
-    ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
-                           data->set.str[STRING_KEY_PASSWD]);
+    ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key),
+                           SSL_SET_OPTION(key_passwd));
     if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
       ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
     if(ret == 0)
@@ -241,7 +306,7 @@ polarssl_connect_step1(struct connectdata *conn,
     if(ret) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_KEY], -ret, errorbuf);
+            SSL_SET_OPTION(key), -ret, errorbuf);
 
       return CURLE_SSL_CERTPROBLEM;
     }
@@ -250,29 +315,27 @@ polarssl_connect_step1(struct connectdata *conn,
   /* Load the CRL */
   memset(&connssl->crl, 0, sizeof(x509_crl));
 
-  if(data->set.str[STRING_SSL_CRLFILE]) {
+  if(SSL_SET_OPTION(CRLfile)) {
     ret = x509_crl_parse_file(&connssl->crl,
-                              data->set.str[STRING_SSL_CRLFILE]);
+                              SSL_SET_OPTION(CRLfile));
 
     if(ret) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
+            SSL_SET_OPTION(CRLfile), -ret, errorbuf);
 
       return CURLE_SSL_CRL_BADFILE;
     }
   }
 
-  infof(data, "PolarSSL: Connecting to %s:%d\n",
-        conn->host.name, conn->remote_port);
+  infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
 
   if(ssl_init(&connssl->ssl)) {
     failf(data, "PolarSSL: ssl_init failed");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  switch(data->set.ssl.version) {
-  default:
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
@@ -286,26 +349,18 @@ polarssl_connect_step1(struct connectdata *conn,
     infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
     break;
   case CURL_SSLVERSION_TLSv1_0:
-    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
-                        SSL_MINOR_VERSION_1);
-    ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
-                        SSL_MINOR_VERSION_1);
-    infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n");
-    break;
   case CURL_SSLVERSION_TLSv1_1:
-    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
-                        SSL_MINOR_VERSION_2);
-    ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
-                        SSL_MINOR_VERSION_2);
-    infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n");
-    break;
   case CURL_SSLVERSION_TLSv1_2:
-    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
-                        SSL_MINOR_VERSION_3);
-    ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
-                        SSL_MINOR_VERSION_3);
-    infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
-    break;
+  case CURL_SSLVERSION_TLSv1_3:
+    {
+      CURLcode result = set_ssl_version_min_max(conn, sockindex);
+      if(result != CURLE_OK)
+        return result;
+      break;
+    }
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
   ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
@@ -320,11 +375,11 @@ polarssl_connect_step1(struct connectdata *conn,
   ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     void *old_session = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
       ret = ssl_set_session(&connssl->ssl, old_session);
       if(ret) {
         Curl_ssl_sessionid_unlock(conn);
@@ -339,12 +394,12 @@ polarssl_connect_step1(struct connectdata *conn,
   ssl_set_ca_chain(&connssl->ssl,
                    &connssl->cacert,
                    &connssl->crl,
-                   conn->host.name);
+                   hostname);
 
   ssl_set_own_cert_rsa(&connssl->ssl,
                        &connssl->clicert, &connssl->rsa);
 
-  if(ssl_set_hostname(&connssl->ssl, conn->host.name)) {
+  if(ssl_set_hostname(&connssl->ssl, hostname)) {
     /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name
        to set in the SNI extension. So even if curl connects to a host
        specified as an IP address, this function must be used. */
@@ -354,7 +409,7 @@ polarssl_connect_step1(struct connectdata *conn,
 
 #ifdef HAS_ALPN
   if(conn->bits.tls_enable_alpn) {
-    static const char* protocols[3];
+    static const char *protocols[3];
     int cur = 0;
 
 #ifdef USE_NGHTTP2
@@ -390,6 +445,10 @@ polarssl_connect_step2(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
   char buffer[1024];
+  const char * const pinnedpubkey = SSL_IS_PROXY() ?
+            data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+            data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+
 
   char errorbuf[128];
   errorbuf[0] = 0;
@@ -423,7 +482,7 @@ polarssl_connect_step2(struct connectdata *conn,
 
   ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
 
-  if(ret && data->set.ssl.verifypeer) {
+  if(ret && SSL_CONN_CONFIG(verifypeer)) {
     if(ret & BADCERT_EXPIRED)
       failf(data, "Cert verify failed: BADCERT_EXPIRED");
 
@@ -451,7 +510,7 @@ polarssl_connect_step2(struct connectdata *conn,
   }
 
   /* adapted from mbedtls.c */
-  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+  if(pinnedpubkey) {
     int size;
     CURLcode result;
     x509_crt *p;
@@ -493,7 +552,7 @@ polarssl_connect_step2(struct connectdata *conn,
 
     /* pk_write_pubkey_der writes data at the end of the buffer. */
     result = Curl_pin_peer_pubkey(data,
-                                  data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+                                  pinnedpubkey,
                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
     if(result) {
       x509_crt_free(p);
@@ -544,7 +603,7 @@ polarssl_connect_step3(struct connectdata *conn,
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     int ret;
     ssl_session *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -553,7 +612,7 @@ polarssl_connect_step3(struct connectdata *conn,
     if(!our_ssl_sessionid)
       return CURLE_OUT_OF_MEMORY;
 
-    ssl_session_init(our_ssl_sessionid);
+    memset(our_ssl_sessionid, 0, sizeof(ssl_session));
 
     ret = ssl_get_session(&connssl->ssl, our_ssl_sessionid);
     if(ret) {
@@ -563,10 +622,10 @@ polarssl_connect_step3(struct connectdata *conn,
 
     /* If there's already a matching session in the cache, delete it */
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL))
+    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
       Curl_ssl_delsessionid(conn, old_ssl_sessionid);
 
-    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0);
+    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
     Curl_ssl_sessionid_unlock(conn);
     if(retcode) {
       free(our_ssl_sessionid);
@@ -805,4 +864,10 @@ void Curl_polarssl_cleanup(void)
   (void)Curl_polarsslthreadlock_thread_cleanup();
 }
 
+
+int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex)
+{
+  return ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
+}
+
 #endif /* USE_POLARSSL */
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.h b/Utilities/cmcurl/lib/vtls/polarssl.h
index 7098b24..47af7b4 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.h
+++ b/Utilities/cmcurl/lib/vtls/polarssl.h
@@ -31,6 +31,7 @@
 /* Called on first use PolarSSL, setup threading if supported */
 int  Curl_polarssl_init(void);
 void Curl_polarssl_cleanup(void);
+int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex);
 
 
 CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
@@ -69,7 +70,7 @@ int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
 #define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
 #define curlssl_version Curl_polarssl_version
 #define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
+#define curlssl_data_pending(x,y) Curl_polarssl_data_pending(x, y)
 #define curlssl_sha256sum(a,b,c,d) sha256(a,b,c,0)
 
 /* This might cause libcurl to use a weeker random!
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index f731eeb..9460301 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2012 - 2016, Marc Hoersken, <info at marc-hoersken.de>
  * Copyright (C) 2012, Mark Salisbury, <mark.salisbury at hp.com>
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at 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
@@ -59,6 +59,7 @@
 #include "x509asn1.h"
 #include "curl_printf.h"
 #include "system_win32.h"
+#include "hostcheck.h"
 
  /* The last #include file should be: */
 #include "curl_memory.h"
@@ -102,6 +103,41 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
 }
 
 static CURLcode
+set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
+{
+  struct Curl_easy *data = conn->data;
+  long ssl_version = SSL_CONN_CONFIG(version);
+  long ssl_version_max = SSL_CONN_CONFIG(version_max);
+  long i = ssl_version;
+
+  switch(ssl_version_max) {
+    case CURL_SSLVERSION_MAX_NONE:
+      ssl_version_max = ssl_version << 16;
+      break;
+    case CURL_SSLVERSION_MAX_DEFAULT:
+      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+      break;
+  }
+  for(; i <= (ssl_version_max >> 16); ++i) {
+    switch(i) {
+      case CURL_SSLVERSION_TLSv1_0:
+        schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT;
+        break;
+      case CURL_SSLVERSION_TLSv1_1:
+        schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT;
+        break;
+      case CURL_SSLVERSION_TLSv1_2:
+        schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
+        break;
+      case CURL_SSLVERSION_TLSv1_3:
+        failf(data, "Schannel: TLS 1.3 is not yet supported");
+        return CURLE_SSL_CONNECT_ERROR;
+    }
+  }
+  return CURLE_OK;
+}
+
+static CURLcode
 schannel_connect_step1(struct connectdata *conn, int sockindex)
 {
   ssize_t written = -1;
@@ -123,9 +159,19 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
 #endif
   TCHAR *host_name;
   CURLcode result;
+  char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
-        conn->host.name, conn->remote_port);
+        hostname, conn->remote_port);
+
+  if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT,
+                                 VERSION_LESS_THAN_EQUAL)) {
+     /* SChannel in Windows XP (OS version 5.1) uses legacy handshakes and
+        algorithms that may not be supported by all servers. */
+     infof(data, "schannel: WinSSL version is old and may not be able to "
+           "connect to some servers due to lack of SNI, algorithms, etc.\n");
+  }
 
 #ifdef HAS_ALPN
   /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
@@ -142,9 +188,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   connssl->cred = NULL;
 
   /* check for an existing re-usable credential handle */
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
       connssl->cred = old_cred;
       infof(data, "schannel: re-using existing credential handle\n");
 
@@ -161,7 +207,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
     memset(&schannel_cred, 0, sizeof(schannel_cred));
     schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
 
-    if(data->set.ssl.verifypeer) {
+    if(conn->ssl_config.verifypeer) {
 #ifdef _WIN32_WCE
       /* certificate validation on CE doesn't seem to work right; we'll
          do it following a more manual process. */
@@ -170,13 +216,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
         SCH_CRED_IGNORE_REVOCATION_OFFLINE;
 #else
       schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
-      if(data->set.ssl_no_revoke)
+      /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
+      if(data->set.ssl.no_revoke)
         schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
                                  SCH_CRED_IGNORE_REVOCATION_OFFLINE;
       else
         schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
 #endif
-      if(data->set.ssl_no_revoke)
+      if(data->set.ssl.no_revoke)
         infof(data, "schannel: disabled server certificate revocation "
                     "checks\n");
       else
@@ -189,15 +236,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
       infof(data, "schannel: disabled server certificate revocation checks\n");
     }
 
-    if(!data->set.ssl.verifyhost) {
+    if(!conn->ssl_config.verifyhost) {
       schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
       infof(data, "schannel: verifyhost setting prevents Schannel from "
             "comparing the supplied target name with the subject "
-            "names in server certificates. Also disables SNI.\n");
+            "names in server certificates.\n");
     }
 
-    switch(data->set.ssl.version) {
-    default:
+    switch(conn->ssl_config.version) {
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
       schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
@@ -205,20 +251,24 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
         SP_PROT_TLS1_2_CLIENT;
       break;
     case CURL_SSLVERSION_TLSv1_0:
-      schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT;
-      break;
     case CURL_SSLVERSION_TLSv1_1:
-      schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT;
-      break;
     case CURL_SSLVERSION_TLSv1_2:
-      schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
-      break;
+    case CURL_SSLVERSION_TLSv1_3:
+      {
+        result = set_ssl_version_min_max(&schannel_cred, conn);
+        if(result != CURLE_OK)
+          return result;
+        break;
+      }
     case CURL_SSLVERSION_SSLv3:
       schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
       break;
     case CURL_SSLVERSION_SSLv2:
       schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
       break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
     }
 
     /* allocate memory for the re-usable credential handle */
@@ -253,9 +303,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   }
 
   /* Warn if SNI is disabled due to use of an IP address */
-  if(Curl_inet_pton(AF_INET, conn->host.name, &addr)
+  if(Curl_inet_pton(AF_INET, hostname, &addr)
 #ifdef ENABLE_IPV6
-     || Curl_inet_pton(AF_INET6, conn->host.name, &addr6)
+     || Curl_inet_pton(AF_INET6, hostname, &addr6)
 #endif
     ) {
     infof(data, "schannel: using IP address, SNI is not supported by OS.\n");
@@ -265,17 +315,17 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   if(connssl->use_alpn) {
     int cur = 0;
     int list_start_index = 0;
-    unsigned int* extension_len = NULL;
+    unsigned int *extension_len = NULL;
     unsigned short* list_len = NULL;
 
     /* The first four bytes will be an unsigned int indicating number
        of bytes of data in the rest of the the buffer. */
-    extension_len = (unsigned int*)(&alpn_buffer[cur]);
+    extension_len = (unsigned int *)(&alpn_buffer[cur]);
     cur += sizeof(unsigned int);
 
     /* The next four bytes are an indicator that this buffer will contain
        ALPN data, as opposed to NPN, for example. */
-    *(unsigned int*)&alpn_buffer[cur] =
+    *(unsigned int *)&alpn_buffer[cur] =
       SecApplicationProtocolNegotiationExt_ALPN;
     cur += sizeof(unsigned int);
 
@@ -333,7 +383,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   }
   memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
 
-  host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+  host_name = Curl_convert_UTF8_to_tchar(hostname);
   if(!host_name)
     return CURLE_OUT_OF_MEMORY;
 
@@ -382,6 +432,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   connssl->recv_unrecoverable_err = CURLE_OK;
   connssl->recv_sspi_close_notify = false;
   connssl->recv_connection_closed = false;
+  connssl->encdata_is_incomplete = false;
 
   /* continue to second handshake step */
   connssl->connecting_state = ssl_connect_2;
@@ -406,11 +457,13 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
   TCHAR *host_name;
   CURLcode result;
   bool doread;
+  char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
 
   infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
-        conn->host.name, conn->remote_port);
+        hostname, conn->remote_port);
 
   if(!connssl->cred || !connssl->ctxt)
     return CURLE_SSL_CONNECT_ERROR;
@@ -428,6 +481,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
 
   /* buffer to store previously received and encrypted data */
   if(connssl->encdata_buffer == NULL) {
+    connssl->encdata_is_incomplete = false;
     connssl->encdata_offset = 0;
     connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
     connssl->encdata_buffer = malloc(connssl->encdata_length);
@@ -480,6 +534,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
 
       /* increase encrypted data buffer offset */
       connssl->encdata_offset += nread;
+      connssl->encdata_is_incomplete = false;
+      infof(data, "schannel: encrypted data got %zd\n", nread);
     }
 
     infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
@@ -506,7 +562,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
     memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
            connssl->encdata_offset);
 
-    host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+    host_name = Curl_convert_UTF8_to_tchar(hostname);
     if(!host_name)
       return CURLE_OUT_OF_MEMORY;
 
@@ -524,6 +580,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
 
     /* check if the handshake was incomplete */
     if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
+      connssl->encdata_is_incomplete = true;
       connssl->connecting_state = ssl_connect_2_reading;
       infof(data, "schannel: received incomplete message, need more data\n");
       return CURLE_OK;
@@ -573,7 +630,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
       else
         failf(data, "schannel: next InitializeSecurityContext failed: %s",
               Curl_sspi_strerror(conn, sspi_status));
-      return CURLE_SSL_CONNECT_ERROR;
+      return sspi_status == SEC_E_UNTRUSTED_ROOT ?
+          CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CONNECT_ERROR;
     }
 
     /* check if there was additional remaining encrypted data */
@@ -623,7 +681,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
 #ifdef _WIN32_WCE
   /* Windows CE doesn't do any server certificate validation.
      We have to do it manually. */
-  if(data->set.ssl.verifypeer)
+  if(conn->ssl_config.verifypeer)
     return verify_certificate(conn, sockindex);
 #endif
 
@@ -638,6 +696,10 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   SECURITY_STATUS sspi_status = SEC_E_OK;
   CERT_CONTEXT *ccert_context = NULL;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+#endif
 #ifdef HAS_ALPN
   SecPkgContext_ApplicationProtocol alpn_result;
 #endif
@@ -645,7 +707,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
   infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
-        conn->host.name, conn->remote_port);
+        hostname, conn->remote_port);
 
   if(!connssl->cred)
     return CURLE_SSL_CONNECT_ERROR;
@@ -701,12 +763,13 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
 #endif
 
   /* save the current session data for possible re-use */
-  if(conn->ssl_config.sessionid) {
+  if(SSL_SET_OPTION(primary.sessionid)) {
     bool incache;
     struct curl_schannel_cred *old_cred = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL));
+    incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
+                                      sockindex));
     if(incache) {
       if(old_cred != connssl->cred) {
         infof(data, "schannel: old credential handle is stale, removing\n");
@@ -717,7 +780,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
     }
     if(!incache) {
       result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
-                                     sizeof(struct curl_schannel_cred));
+                                     sizeof(struct curl_schannel_cred),
+                                     sockindex);
       if(result) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "schannel: failed to store credential handle");
@@ -769,7 +833,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   curl_socket_t sockfd = conn->sock[sockindex];
-  long timeout_ms;
+  time_t timeout_ms;
   int what;
 
   /* check if the connection has already been established */
@@ -957,7 +1021,7 @@ schannel_send(struct connectdata *conn, int sockindex,
     /* send entire message or fail */
     while(len > (size_t)written) {
       ssize_t this_write;
-      long timeleft;
+      time_t timeleft;
       int what;
 
       this_write = 0;
@@ -1119,6 +1183,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
     }
     else if(nread > 0) {
       connssl->encdata_offset += (size_t)nread;
+      connssl->encdata_is_incomplete = false;
       infof(data, "schannel: encrypted data got %zd\n", nread);
     }
   }
@@ -1255,6 +1320,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
       }
     }
     else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
+      connssl->encdata_is_incomplete = true;
       if(!*err)
         *err = CURLE_AGAIN;
       infof(data, "schannel: failed to decrypt data, need more data\n");
@@ -1356,8 +1422,8 @@ bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
   const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
   if(connssl->use) /* SSL/TLS is in use */
-    return (connssl->encdata_offset > 0 ||
-            connssl->decdata_offset > 0) ? TRUE : FALSE;
+    return (connssl->decdata_offset > 0 ||
+            (connssl->encdata_offset > 0 && !connssl->encdata_is_incomplete));
   else
     return FALSE;
 }
@@ -1376,9 +1442,11 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
    */
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
-        conn->host.name, conn->remote_port);
+        hostname, conn->remote_port);
 
   if(connssl->cred && connssl->ctxt) {
     SecBufferDesc BuffDesc;
@@ -1400,7 +1468,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
       failf(data, "schannel: ApplyControlToken failure: %s",
             Curl_sspi_strerror(conn, sspi_status));
 
-    host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+    host_name = Curl_convert_UTF8_to_tchar(hostname);
     if(!host_name)
       return CURLE_OUT_OF_MEMORY;
 
@@ -1458,6 +1526,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
     Curl_safefree(connssl->encdata_buffer);
     connssl->encdata_length = 0;
     connssl->encdata_offset = 0;
+    connssl->encdata_is_incomplete = false;
   }
 
   /* free internal buffer for received decrypted data */
@@ -1499,21 +1568,21 @@ size_t Curl_schannel_version(char *buffer, size_t size)
   return size;
 }
 
-int Curl_schannel_random(unsigned char *entropy, size_t length)
+CURLcode Curl_schannel_random(unsigned char *entropy, size_t length)
 {
   HCRYPTPROV hCryptProv = 0;
 
   if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
                           CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
-    return 1;
+    return CURLE_FAILED_INIT;
 
   if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
     CryptReleaseContext(hCryptProv, 0UL);
-    return 1;
+    return CURLE_FAILED_INIT;
   }
 
   CryptReleaseContext(hCryptProv, 0UL);
-  return 0;
+  return CURLE_OK;
 }
 
 #ifdef _WIN32_WCE
@@ -1525,6 +1594,9 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
   CURLcode result = CURLE_OK;
   CERT_CONTEXT *pCertContextServer = NULL;
   const CERT_CHAIN_CONTEXT *pChainContext = NULL;
+  const char * const conn_hostname = SSL_IS_PROXY() ?
+    conn->http_proxy.host.name :
+    conn->host.name;
 
   status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
                                             SECPKG_ATTR_REMOTE_CERT_CONTEXT,
@@ -1546,7 +1618,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
                                 NULL,
                                 pCertContextServer->hCertStore,
                                 &ChainPara,
-                                (data->set.ssl_no_revoke ? 0 :
+                                (data->set.ssl.no_revoke ? 0 :
                                  CERT_CHAIN_REVOCATION_CHECK_CHAIN),
                                 NULL,
                                 &pChainContext)) {
@@ -1582,15 +1654,10 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
   }
 
   if(result == CURLE_OK) {
-    if(data->set.ssl.verifyhost) {
-      TCHAR cert_hostname_buff[128];
-      xcharp_u hostname;
-      xcharp_u cert_hostname;
+    if(conn->ssl_config.verifyhost) {
+      TCHAR cert_hostname_buff[256];
       DWORD len;
 
-      cert_hostname.const_tchar_ptr = cert_hostname_buff;
-      hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name);
-
       /* TODO: Fix this for certificates with multiple alternative names.
       Right now we're only asking for the first preferred alternative name.
       Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG
@@ -1601,31 +1668,50 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
       */
       len = CertGetNameString(pCertContextServer,
                               CERT_NAME_DNS_TYPE,
-                              0,
+                              CERT_NAME_DISABLE_IE4_UTF8_FLAG,
                               NULL,
-                              cert_hostname.tchar_ptr,
-                              128);
-      if(len > 0 && *cert_hostname.tchar_ptr == '*') {
-        /* this is a wildcard cert.  try matching the last len - 1 chars */
-        int hostname_len = strlen(conn->host.name);
-        cert_hostname.tchar_ptr++;
-        if(_tcsicmp(cert_hostname.const_tchar_ptr,
-                    hostname.const_tchar_ptr + hostname_len - len + 2) != 0)
-          result = CURLE_PEER_FAILED_VERIFICATION;
+                              cert_hostname_buff,
+                              256);
+      if(len > 0) {
+        const char *cert_hostname;
+
+        /* Comparing the cert name and the connection hostname encoded as UTF-8
+         * is acceptable since both values are assumed to use ASCII
+         * (or some equivalent) encoding
+         */
+        cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname_buff);
+        if(!cert_hostname) {
+          result = CURLE_OUT_OF_MEMORY;
+        }
+        else{
+          int match_result;
+
+          match_result = Curl_cert_hostcheck(cert_hostname, conn->host.name);
+          if(match_result == CURL_HOST_MATCH) {
+            infof(data,
+                  "schannel: connection hostname (%s) validated "
+                  "against certificate name (%s)\n",
+                  conn->host.name,
+                  cert_hostname);
+            result = CURLE_OK;
+          }
+          else{
+            failf(data,
+                  "schannel: connection hostname (%s) "
+                  "does not match certificate name (%s)",
+                  conn->host.name,
+                  cert_hostname);
+            result = CURLE_PEER_FAILED_VERIFICATION;
+          }
+          Curl_unicodefree(cert_hostname);
+        }
       }
-      else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr,
-                                   cert_hostname.const_tchar_ptr) != 0) {
+      else {
+        failf(data,
+              "schannel: CertGetNameString did not provide any "
+              "certificate name information");
         result = CURLE_PEER_FAILED_VERIFICATION;
       }
-      if(result == CURLE_PEER_FAILED_VERIFICATION) {
-        char *_cert_hostname;
-        _cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr);
-        failf(data, "schannel: CertGetNameString() certificate hostname "
-              "(%s) did not match connection (%s)",
-              _cert_hostname, conn->host.name);
-        Curl_unicodefree(_cert_hostname);
-      }
-      Curl_unicodefree(hostname.tchar_ptr);
     }
   }
 
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index 8a4991e..8627c63 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -8,7 +8,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012, Marc Hoersken, <info at marc-hoersken.de>, et al.
- * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel at 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
@@ -92,7 +92,7 @@ int Curl_schannel_init(void);
 void Curl_schannel_cleanup(void);
 size_t Curl_schannel_version(char *buffer, size_t size);
 
-int Curl_schannel_random(unsigned char *entropy, size_t length);
+CURLcode Curl_schannel_random(unsigned char *entropy, size_t length);
 
 /* Set the API backend definition to Schannel */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index 56a8823..d5d0971 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -65,6 +65,7 @@
 #include "url.h"
 #include "progress.h"
 #include "share.h"
+#include "multiif.h"
 #include "timeval.h"
 #include "curl_md5.h"
 #include "warnless.h"
@@ -80,94 +81,54 @@
                                  (data->share->specifier &             \
                                   (1<<CURL_LOCK_DATA_SSL_SESSION)))
 
-static bool safe_strequal(char* str1, char* str2)
-{
-  if(str1 && str2)
-    /* both pointers point to something then compare them */
-    return (0 != strcasecompare(str1, str2)) ? TRUE : FALSE;
-  else
-    /* if both pointers are NULL then treat them as equal */
-    return (!str1 && !str2) ? TRUE : FALSE;
-}
+#define CLONE_STRING(var)                    \
+  if(source->var) {                          \
+    dest->var = strdup(source->var);         \
+    if(!dest->var)                           \
+      return FALSE;                          \
+  }                                          \
+  else                                       \
+    dest->var = NULL;
 
 bool
-Curl_ssl_config_matches(struct ssl_config_data* data,
-                        struct ssl_config_data* needle)
+Curl_ssl_config_matches(struct ssl_primary_config* data,
+                        struct ssl_primary_config* needle)
 {
   if((data->version == needle->version) &&
+     (data->version_max == needle->version_max) &&
      (data->verifypeer == needle->verifypeer) &&
      (data->verifyhost == needle->verifyhost) &&
-     safe_strequal(data->CApath, needle->CApath) &&
-     safe_strequal(data->CAfile, needle->CAfile) &&
-     safe_strequal(data->clientcert, needle->clientcert) &&
-     safe_strequal(data->cipher_list, needle->cipher_list))
+     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->cipher_list, needle->cipher_list))
     return TRUE;
 
   return FALSE;
 }
 
 bool
-Curl_clone_ssl_config(struct ssl_config_data *source,
-                      struct ssl_config_data *dest)
+Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
+                              struct ssl_primary_config *dest)
 {
-  dest->sessionid = source->sessionid;
   dest->verifyhost = source->verifyhost;
   dest->verifypeer = source->verifypeer;
   dest->version = source->version;
+  dest->version_max = source->version_max;
 
-  if(source->CAfile) {
-    dest->CAfile = strdup(source->CAfile);
-    if(!dest->CAfile)
-      return FALSE;
-  }
-  else
-    dest->CAfile = NULL;
-
-  if(source->CApath) {
-    dest->CApath = strdup(source->CApath);
-    if(!dest->CApath)
-      return FALSE;
-  }
-  else
-    dest->CApath = NULL;
-
-  if(source->cipher_list) {
-    dest->cipher_list = strdup(source->cipher_list);
-    if(!dest->cipher_list)
-      return FALSE;
-  }
-  else
-    dest->cipher_list = NULL;
-
-  if(source->egdsocket) {
-    dest->egdsocket = strdup(source->egdsocket);
-    if(!dest->egdsocket)
-      return FALSE;
-  }
-  else
-    dest->egdsocket = NULL;
-
-  if(source->random_file) {
-    dest->random_file = strdup(source->random_file);
-    if(!dest->random_file)
-      return FALSE;
-  }
-  else
-    dest->random_file = NULL;
-
-  if(source->clientcert) {
-    dest->clientcert = strdup(source->clientcert);
-    if(!dest->clientcert)
-      return FALSE;
-    dest->sessionid = FALSE;
-  }
-  else
-    dest->clientcert = NULL;
+  CLONE_STRING(CAfile);
+  CLONE_STRING(CApath);
+  CLONE_STRING(cipher_list);
+  CLONE_STRING(egdsocket);
+  CLONE_STRING(random_file);
+  CLONE_STRING(clientcert);
 
+  /* Disable dest sessionid cache if a client cert is used, CVE-2016-5419. */
+  dest->sessionid = (dest->clientcert ? false : source->sessionid);
   return TRUE;
 }
 
-void Curl_free_ssl_config(struct ssl_config_data* sslc)
+void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
 {
   Curl_safefree(sslc->CAfile);
   Curl_safefree(sslc->CApath);
@@ -177,77 +138,6 @@ void Curl_free_ssl_config(struct ssl_config_data* sslc)
   Curl_safefree(sslc->clientcert);
 }
 
-
-/*
- * Curl_rand() returns a random unsigned integer, 32bit.
- *
- * This non-SSL function is put here only because this file is the only one
- * with knowledge of what the underlying SSL libraries provide in terms of
- * randomizers.
- *
- * NOTE: 'data' may be passed in as NULL when coming from external API without
- * easy handle!
- *
- */
-
-unsigned int Curl_rand(struct Curl_easy *data)
-{
-  unsigned int r = 0;
-  static unsigned int randseed;
-  static bool seeded = FALSE;
-
-#ifdef CURLDEBUG
-  char *force_entropy = getenv("CURL_ENTROPY");
-  if(force_entropy) {
-    if(!seeded) {
-      size_t elen = strlen(force_entropy);
-      size_t clen = sizeof(randseed);
-      size_t min = elen < clen ? elen : clen;
-      memcpy((char *)&randseed, force_entropy, min);
-      seeded = TRUE;
-    }
-    else
-      randseed++;
-    return randseed;
-  }
-#endif
-
-  /* data may be NULL! */
-  if(!Curl_ssl_random(data, (unsigned char *)&r, sizeof(r)))
-    return r;
-
-  /* If Curl_ssl_random() returns non-zero it couldn't offer randomness and we
-     instead perform a "best effort" */
-
-#ifdef RANDOM_FILE
-  if(!seeded) {
-    /* if there's a random file to read a seed from, use it */
-    int fd = open(RANDOM_FILE, O_RDONLY);
-    if(fd > -1) {
-      /* read random data into the randseed variable */
-      ssize_t nread = read(fd, &randseed, sizeof(randseed));
-      if(nread == sizeof(randseed))
-        seeded = TRUE;
-      close(fd);
-    }
-  }
-#endif
-
-  if(!seeded) {
-    struct timeval now = curlx_tvnow();
-    infof(data, "WARNING: Using weak random seed\n");
-    randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
-    randseed = randseed * 1103515245 + 12345;
-    randseed = randseed * 1103515245 + 12345;
-    randseed = randseed * 1103515245 + 12345;
-    seeded = TRUE;
-  }
-
-  /* Return an unsigned 32-bit pseudo-random number. */
-  r = randseed = randseed * 1103515245 + 12345;
-  return (r << 16) | ((r >> 16) & 0xFFFF);
-}
-
 int Curl_ssl_backend(void)
 {
   return (int)CURL_SSL_BACKEND;
@@ -288,19 +178,54 @@ void Curl_ssl_cleanup(void)
 static bool ssl_prefs_check(struct Curl_easy *data)
 {
   /* check for CURLOPT_SSLVERSION invalid parameter value */
-  if((data->set.ssl.version < 0)
-     || (data->set.ssl.version >= CURL_SSLVERSION_LAST)) {
+  const long sslver = data->set.ssl.primary.version;
+  if((sslver < 0) || (sslver >= CURL_SSLVERSION_LAST)) {
     failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
     return FALSE;
   }
+
+  switch(data->set.ssl.primary.version_max) {
+  case CURL_SSLVERSION_MAX_NONE:
+  case CURL_SSLVERSION_MAX_DEFAULT:
+    break;
+
+  default:
+    if((data->set.ssl.primary.version_max >> 16) < sslver) {
+      failf(data, "CURL_SSLVERSION_MAX incompatible with CURL_SSLVERSION");
+      return FALSE;
+    }
+  }
+
   return TRUE;
 }
 
+static CURLcode
+ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
+{
+  DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
+  if(ssl_connection_complete == conn->ssl[sockindex].state &&
+     !conn->proxy_ssl[sockindex].use) {
+#if defined(HTTPS_PROXY_SUPPORT)
+    conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
+    memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
+#else
+    return CURLE_NOT_BUILT_IN;
+#endif
+  }
+  return CURLE_OK;
+}
+
 CURLcode
 Curl_ssl_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
 
+  if(conn->bits.proxy_ssl_connected[sockindex]) {
+    result = ssl_connect_init_proxy(conn, sockindex);
+    if(result)
+      return result;
+  }
+
   if(!ssl_prefs_check(conn->data))
     return CURLE_SSL_CONNECT_ERROR;
 
@@ -321,6 +246,11 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
                              bool *done)
 {
   CURLcode result;
+  if(conn->bits.proxy_ssl_connected[sockindex]) {
+    result = ssl_connect_init_proxy(conn, sockindex);
+    if(result)
+      return result;
+  }
 
   if(!ssl_prefs_check(conn->data))
     return CURLE_SSL_CONNECT_ERROR;
@@ -363,7 +293,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn)
  */
 bool Curl_ssl_getsessionid(struct connectdata *conn,
                            void **ssl_sessionid,
-                           size_t *idsize) /* set 0 if unknown */
+                           size_t *idsize, /* set 0 if unknown */
+                           int sockindex)
 {
   struct curl_ssl_session *check;
   struct Curl_easy *data = conn->data;
@@ -371,11 +302,18 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
   long *general_age;
   bool no_match = TRUE;
 
+  const bool isProxy = CONNECT_PROXY_SSL();
+  struct ssl_primary_config * const ssl_config = isProxy ?
+    &conn->proxy_ssl_config :
+    &conn->ssl_config;
+  const char * const name = isProxy ? conn->http_proxy.host.name :
+    conn->host.name;
+  int port = isProxy ? (int)conn->port : conn->remote_port;
   *ssl_sessionid = NULL;
 
-  DEBUGASSERT(conn->ssl_config.sessionid);
+  DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
 
-  if(!conn->ssl_config.sessionid)
+  if(!SSL_SET_OPTION(primary.sessionid))
     /* session ID re-use is disabled */
     return TRUE;
 
@@ -385,21 +323,21 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
   else
     general_age = &data->state.sessionage;
 
-  for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+  for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
     check = &data->state.session[i];
     if(!check->sessionid)
       /* not session ID means blank entry */
       continue;
-    if(strcasecompare(conn->host.name, check->name) &&
+    if(strcasecompare(name, check->name) &&
        ((!conn->bits.conn_to_host && !check->conn_to_host) ||
         (conn->bits.conn_to_host && check->conn_to_host &&
          strcasecompare(conn->conn_to_host.name, check->conn_to_host))) &&
        ((!conn->bits.conn_to_port && check->conn_to_port == -1) ||
         (conn->bits.conn_to_port && check->conn_to_port != -1 &&
          conn->conn_to_port == check->conn_to_port)) &&
-       (conn->remote_port == check->remote_port) &&
+       (port == check->remote_port) &&
        strcasecompare(conn->handler->scheme, check->scheme) &&
-       Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
+       Curl_ssl_config_matches(ssl_config, &check->ssl_config)) {
       /* yes, we have a session ID! */
       (*general_age)++;          /* increase general age */
       check->age = *general_age; /* set this as used in this age */
@@ -428,7 +366,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
     session->sessionid = NULL;
     session->age = 0; /* fresh */
 
-    Curl_free_ssl_config(&session->ssl_config);
+    Curl_free_primary_ssl_config(&session->ssl_config);
 
     Curl_safefree(session->name);
     Curl_safefree(session->conn_to_host);
@@ -443,7 +381,7 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
   size_t i;
   struct Curl_easy *data=conn->data;
 
-  for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+  for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
     struct curl_ssl_session *check = &data->state.session[i];
 
     if(check->sessionid == ssl_sessionid) {
@@ -461,7 +399,8 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
  */
 CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
                                void *ssl_sessionid,
-                               size_t idsize)
+                               size_t idsize,
+                               int sockindex)
 {
   size_t i;
   struct Curl_easy *data=conn->data; /* the mother of all structs */
@@ -471,10 +410,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
   char *clone_conn_to_host;
   int conn_to_port;
   long *general_age;
+  const bool isProxy = CONNECT_PROXY_SSL();
+  struct ssl_primary_config * const ssl_config = isProxy ?
+    &conn->proxy_ssl_config :
+    &conn->ssl_config;
 
-  DEBUGASSERT(conn->ssl_config.sessionid);
+  DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
 
-  clone_host = strdup(conn->host.name);
+  clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name);
   if(!clone_host)
     return CURLE_OUT_OF_MEMORY; /* bail out */
 
@@ -505,14 +448,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
   }
 
   /* find an empty slot for us, or find the oldest */
-  for(i = 1; (i < data->set.ssl.max_ssl_sessions) &&
+  for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) &&
         data->state.session[i].sessionid; i++) {
     if(data->state.session[i].age < oldest_age) {
       oldest_age = data->state.session[i].age;
       store = &data->state.session[i];
     }
   }
-  if(i == data->set.ssl.max_ssl_sessions)
+  if(i == data->set.general_ssl.max_ssl_sessions)
     /* cache is full, we must "kill" the oldest entry! */
     Curl_ssl_kill_session(store);
   else
@@ -522,16 +465,17 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
   store->sessionid = ssl_sessionid;
   store->idsize = idsize;
   store->age = *general_age;    /* set current age */
-    /* free it if there's one already present */
+  /* free it if there's one already present */
   free(store->name);
   free(store->conn_to_host);
   store->name = clone_host;               /* clone host name */
   store->conn_to_host = clone_conn_to_host; /* clone connect to host name */
   store->conn_to_port = conn_to_port; /* connect to port number */
-  store->remote_port = conn->remote_port; /* port number */
+  /* port number */
+  store->remote_port = isProxy ? (int)conn->port : conn->remote_port;
   store->scheme = conn->handler->scheme;
 
-  if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) {
+  if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) {
     store->sessionid = NULL; /* let caller free sessionid */
     free(clone_host);
     free(clone_conn_to_host);
@@ -547,7 +491,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
   size_t i;
   /* kill the session ID cache if not shared */
   if(data->state.session && !SSLSESSION_SHARED(data)) {
-    for(i = 0; i < data->set.ssl.max_ssl_sessions; i++)
+    for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++)
       /* the single-killer function handles empty table slots */
       Curl_ssl_kill_session(&data->state.session[i]);
 
@@ -558,6 +502,43 @@ void Curl_ssl_close_all(struct Curl_easy *data)
   curlssl_close_all(data);
 }
 
+#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
+  defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
+  defined(USE_MBEDTLS)
+int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
+                     int numsocks)
+{
+  struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
+
+  if(!numsocks)
+    return GETSOCK_BLANK;
+
+  if(connssl->connecting_state == ssl_connect_2_writing) {
+    /* write mode */
+    socks[0] = conn->sock[FIRSTSOCKET];
+    return GETSOCK_WRITESOCK(0);
+  }
+  if(connssl->connecting_state == ssl_connect_2_reading) {
+    /* read mode */
+    socks[0] = conn->sock[FIRSTSOCKET];
+    return GETSOCK_READSOCK(0);
+  }
+
+  return GETSOCK_BLANK;
+}
+#else
+int Curl_ssl_getsock(struct connectdata *conn,
+                     curl_socket_t *socks,
+                     int numsocks)
+{
+  (void)conn;
+  (void)socks;
+  (void)numsocks;
+  return GETSOCK_BLANK;
+}
+/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */
+#endif
+
 void Curl_ssl_close(struct connectdata *conn, int sockindex)
 {
   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
@@ -615,7 +596,7 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
     return CURLE_OUT_OF_MEMORY;
 
   /* store the info in the SSL section */
-  data->set.ssl.max_ssl_sessions = amount;
+  data->set.general_ssl.max_ssl_sessions = amount;
   data->state.session = session;
   data->state.sessionage = 1; /* this is brand new */
   return CURLE_OK;
@@ -691,9 +672,9 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
                                     const char *value,
                                     size_t valuelen)
 {
-  struct curl_certinfo * ci = &data->info.certs;
-  char * output;
-  struct curl_slist * nl;
+  struct curl_certinfo *ci = &data->info.certs;
+  char *output;
+  struct curl_slist *nl;
   CURLcode result = CURLE_OK;
   size_t labellen = strlen(label);
   size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
@@ -736,9 +717,9 @@ CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data,
   return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
 }
 
-int Curl_ssl_random(struct Curl_easy *data,
-                     unsigned char *entropy,
-                     size_t length)
+CURLcode Curl_ssl_random(struct Curl_easy *data,
+                         unsigned char *entropy,
+                         size_t length)
 {
   return curlssl_random(data, entropy, length);
 }
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index a41ecc3..2aabeda 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -50,13 +50,24 @@
 #define ALPN_HTTP_1_1_LENGTH 8
 #define ALPN_HTTP_1_1 "http/1.1"
 
-bool Curl_ssl_config_matches(struct ssl_config_data* data,
-                             struct ssl_config_data* needle);
-bool Curl_clone_ssl_config(struct ssl_config_data* source,
-                           struct ssl_config_data* dest);
-void Curl_free_ssl_config(struct ssl_config_data* sslc);
-
-unsigned int Curl_rand(struct Curl_easy *);
+/* set of helper macros for the backends to access the correct fields. For the
+   proxy or for the remote host - to properly support HTTPS proxy */
+
+#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \
+  ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \
+  CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state)
+#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \
+                             data->set.ssl.var)
+#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ?          \
+  conn->proxy_ssl_config.var : conn->ssl_config.var)
+
+bool Curl_ssl_config_matches(struct ssl_primary_config* data,
+                             struct ssl_primary_config* needle);
+bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
+                                   struct ssl_primary_config *dest);
+void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc);
+int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
+                     int numsocks);
 
 int Curl_ssl_backend(void);
 
@@ -87,12 +98,12 @@ int Curl_ssl_check_cxn(struct connectdata *conn);
 /* Certificate information list handling. */
 
 void Curl_ssl_free_certinfo(struct Curl_easy *data);
-CURLcode Curl_ssl_init_certinfo(struct Curl_easy * data, int num);
-CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy * data, int certnum,
-                                    const char * label, const char * value,
+CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num);
+CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, int certnum,
+                                    const char *label, const char *value,
                                     size_t valuelen);
-CURLcode Curl_ssl_push_certinfo(struct Curl_easy * data, int certnum,
-                                const char * label, const char * value);
+CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum,
+                                const char *label, const char *value);
 
 /* Functions to be used by SSL library adaptation functions */
 
@@ -116,7 +127,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn);
  */
 bool Curl_ssl_getsessionid(struct connectdata *conn,
                            void **ssl_sessionid,
-                           size_t *idsize); /* set 0 if unknown */
+                           size_t *idsize, /* set 0 if unknown */
+                           int sockindex);
 /* add a new session ID
  * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
  * Caller must ensure that it has properly shared ownership of this sessionid
@@ -124,7 +136,8 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
  */
 CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
                                void *ssl_sessionid,
-                               size_t idsize);
+                               size_t idsize,
+                               int sockindex);
 /* Kill a single session ID entry in the cache
  * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
  * This will call engine-specific curlssl_session_free function, which must
@@ -140,10 +153,9 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session);
  */
 void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
 
-/* get N random bytes into the buffer, return 0 if a find random is filled
-   in */
-int Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
-                    size_t length);
+/* get N random bytes into the buffer */
+CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
+                         size_t length);
 CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
                          size_t tmplen,
                          unsigned char *md5sum, /* output */
diff --git a/Utilities/cmcurl/lib/warnless.c b/Utilities/cmcurl/lib/warnless.c
index 0c4472e..fb085c8 100644
--- a/Utilities/cmcurl/lib/warnless.c
+++ b/Utilities/cmcurl/lib/warnless.c
@@ -183,12 +183,15 @@ curl_off_t curlx_uztoso(size_t uznum)
 #ifdef __INTEL_COMPILER
 #  pragma warning(push)
 #  pragma warning(disable:810) /* conversion may lose significant bits */
+#elif defined(_MSC_VER)
+#  pragma warning(push)
+#  pragma warning(disable:4310) /* cast truncates constant value */
 #endif
 
   DEBUGASSERT(uznum <= (size_t) CURL_MASK_SCOFFT);
   return (curl_off_t)(uznum & (size_t) CURL_MASK_SCOFFT);
 
-#ifdef __INTEL_COMPILER
+#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
 #  pragma warning(pop)
 #endif
 }
diff --git a/Utilities/cmcurl/lib/wildcard.c b/Utilities/cmcurl/lib/wildcard.c
index dbbe45f..af45c79 100644
--- a/Utilities/cmcurl/lib/wildcard.c
+++ b/Utilities/cmcurl/lib/wildcard.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel at 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
@@ -32,13 +32,9 @@
 
 CURLcode Curl_wildcard_init(struct WildcardData *wc)
 {
-  DEBUGASSERT(wc->filelist == NULL);
-  /* now allocate only wc->filelist, everything else
-     will be allocated if it is needed. */
-  wc->filelist = Curl_llist_alloc(Curl_fileinfo_dtor);
-  if(!wc->filelist) {;
-    return CURLE_OUT_OF_MEMORY;
-  }
+  Curl_llist_init(&wc->filelist, Curl_fileinfo_dtor);
+  wc->state = CURLWC_INIT;
+
   return CURLE_OK;
 }
 
@@ -54,10 +50,8 @@ void Curl_wildcard_dtor(struct WildcardData *wc)
   }
   DEBUGASSERT(wc->tmp == NULL);
 
-  if(wc->filelist) {
-    Curl_llist_destroy(wc->filelist, NULL);
-    wc->filelist = NULL;
-  }
+  Curl_llist_destroy(&wc->filelist, NULL);
+
 
   free(wc->path);
   wc->path = NULL;
diff --git a/Utilities/cmcurl/lib/wildcard.h b/Utilities/cmcurl/lib/wildcard.h
index 7f61cd1..8a5e4b7 100644
--- a/Utilities/cmcurl/lib/wildcard.h
+++ b/Utilities/cmcurl/lib/wildcard.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010 - 2013, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel at 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,9 +24,12 @@
 
 #include <curl/curl.h>
 
+#include "llist.h"
+
 /* list of wildcard process states */
 typedef enum {
-  CURLWC_INIT = 0,
+  CURLWC_CLEAR = 0,
+  CURLWC_INIT = 1,
   CURLWC_MATCHING, /* library is trying to get list of addresses for
                       downloading */
   CURLWC_DOWNLOADING,
@@ -44,7 +47,7 @@ struct WildcardData {
   curl_wildcard_states state;
   char *path; /* path to the directory, where we trying wildcard-match */
   char *pattern; /* wildcard pattern */
-  struct curl_llist *filelist; /* llist with struct Curl_fileinfo */
+  struct curl_llist filelist; /* llist with struct Curl_fileinfo */
   void *tmp; /* pointer to protocol specific temporary data */
   curl_wildcard_tmp_dtor tmp_dtor;
   void *customptr;  /* for CURLOPT_CHUNK_DATA pointer */
diff --git a/Utilities/cmcurl/lib/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c
index 74a511b..bba2023 100644
--- a/Utilities/cmcurl/lib/x509asn1.c
+++ b/Utilities/cmcurl/lib/x509asn1.c
@@ -40,6 +40,9 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+/* For overflow checks. */
+#define CURL_SIZE_T_MAX         ((size_t)-1)
+
 
 /* ASN.1 OIDs. */
 static const char       cnOID[] = "2.5.4.3";    /* Common name. */
@@ -105,8 +108,8 @@ static const curl_OID   OIDtable[] = {
  */
 
 
-const char * Curl_getASN1Element(curl_asn1Element * elem,
-                                 const char * beg, const char * end)
+const char *Curl_getASN1Element(curl_asn1Element *elem,
+                                const char *beg, const char *end)
 {
   unsigned char b;
   unsigned long len;
@@ -116,8 +119,8 @@ const char * Curl_getASN1Element(curl_asn1Element * elem,
      ending at `end'.
      Returns a pointer in source string after the parsed element, or NULL
      if an error occurs. */
-
-  if(beg >= end || !*beg)
+  if(!beg || !end || beg >= end || !*beg ||
+     (size_t)(end - beg) > CURL_ASN1_MAX)
     return (const char *) NULL;
 
   /* Process header byte. */
@@ -152,7 +155,7 @@ const char * Curl_getASN1Element(curl_asn1Element * elem,
     elem->end = beg;
     return beg + 1;
   }
-  else if(beg + b > end)
+  else if((unsigned)b > (size_t)(end - beg))
     return (const char *) NULL; /* Does not fit in source. */
   else {
     /* Get long length. */
@@ -163,16 +166,16 @@ const char * Curl_getASN1Element(curl_asn1Element * elem,
       len = (len << 8) | (unsigned char) *beg++;
     } while(--b);
   }
-  if((unsigned long) (end - beg) < len)
+  if(len > (size_t)(end - beg))
     return (const char *) NULL;  /* Element data does not fit in source. */
   elem->beg = beg;
   elem->end = beg + len;
   return elem->end;
 }
 
-static const curl_OID * searchOID(const char * oid)
+static const curl_OID * searchOID(const char *oid)
 {
-  const curl_OID * op;
+  const curl_OID *op;
 
   /* Search the null terminated OID or OID identifier in local table.
      Return the table entry pointer or NULL if not found. */
@@ -184,7 +187,7 @@ static const curl_OID * searchOID(const char * oid)
   return (const curl_OID *) NULL;
 }
 
-static const char * bool2str(const char * beg, const char * end)
+static const char *bool2str(const char *beg, const char *end)
 {
   /* Convert an ASN.1 Boolean value into its string representation.
      Return the dynamically allocated string, or NULL if source is not an
@@ -195,22 +198,24 @@ static const char * bool2str(const char * beg, const char * end)
   return strdup(*beg? "TRUE": "FALSE");
 }
 
-static const char * octet2str(const char * beg, const char * end)
+static const char *octet2str(const char *beg, const char *end)
 {
   size_t n = end - beg;
-  char * buf;
+  char *buf = NULL;
 
   /* Convert an ASN.1 octet string to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
 
-  buf = malloc(3 * n + 1);
-  if(buf)
-    for(n = 0; beg < end; n += 3)
-      snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+  if(n <= (CURL_SIZE_T_MAX - 1) / 3) {
+    buf = malloc(3 * n + 1);
+    if(buf)
+      for(n = 0; beg < end; n += 3)
+        snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+  }
   return buf;
 }
 
-static const char * bit2str(const char * beg, const char * end)
+static const char *bit2str(const char *beg, const char *end)
 {
   /* Convert an ASN.1 bit string to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -220,7 +225,7 @@ static const char * bit2str(const char * beg, const char * end)
   return octet2str(beg, end);
 }
 
-static const char * int2str(const char * beg, const char * end)
+static const char *int2str(const char *beg, const char *end)
 {
   long val = 0;
   size_t n = end - beg;
@@ -246,14 +251,14 @@ static const char * int2str(const char * beg, const char * end)
 }
 
 static ssize_t
-utf8asn1str(char * * to, int type, const char * from, const char * end)
+utf8asn1str(char **to, int type, const char *from, const char *end)
 {
   size_t inlength = end - from;
   int size = 1;
   size_t outlength;
   int charsize;
   unsigned int wc;
-  char * buf;
+  char *buf;
 
   /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the
      destination buffer dynamically. The allocation size will normally be too
@@ -262,7 +267,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
      string length. */
 
   *to = (char *) NULL;
-  switch (type) {
+  switch(type) {
   case CURL_ASN1_BMP_STRING:
     size = 2;
     break;
@@ -282,6 +287,8 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
 
   if(inlength % size)
     return -1;  /* Length inconsistent with character size. */
+  if(inlength / size > (CURL_SIZE_T_MAX - 1) / 4)
+    return -1;  /* Too big. */
   buf = malloc(4 * (inlength / size) + 1);
   if(!buf)
     return -1;  /* Not enough memory. */
@@ -295,7 +302,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
   else {
     for(outlength = 0; from < end;) {
       wc = 0;
-      switch (size) {
+      switch(size) {
       case 4:
         wc = (wc << 8) | *(const unsigned char *) from++;
         wc = (wc << 8) | *(const unsigned char *) from++;
@@ -335,9 +342,9 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
   return outlength;
 }
 
-static const char * string2str(int type, const char * beg, const char * end)
+static const char *string2str(int type, const char *beg, const char *end)
 {
-  char * buf;
+  char *buf;
 
   /* Convert an ASN.1 String into its UTF-8 string representation.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -347,7 +354,7 @@ static const char * string2str(int type, const char * beg, const char * end)
   return buf;
 }
 
-static int encodeUint(char * buf, int n, unsigned int x)
+static int encodeUint(char *buf, int n, unsigned int x)
 {
   int i = 0;
   unsigned int y = x / 10;
@@ -367,7 +374,7 @@ static int encodeUint(char * buf, int n, unsigned int x)
   return i;
 }
 
-static int encodeOID(char * buf, int n, const char * beg, const char * end)
+static int encodeOID(char *buf, int n, const char *beg, const char *end)
 {
   int i = 0;
   unsigned int x;
@@ -406,9 +413,9 @@ static int encodeOID(char * buf, int n, const char * beg, const char * end)
   return i;
 }
 
-static const char * OID2str(const char * beg, const char * end, bool symbolic)
+static const char *OID2str(const char *beg, const char *end, bool symbolic)
 {
-  char * buf = (char *) NULL;
+  char *buf = (char *) NULL;
   const curl_OID * op;
   int n;
 
@@ -436,14 +443,14 @@ static const char * OID2str(const char * beg, const char * end, bool symbolic)
   return buf;
 }
 
-static const char * GTime2str(const char * beg, const char * end)
+static const char *GTime2str(const char *beg, const char *end)
 {
-  const char * tzp;
-  const char * fracp;
+  const char *tzp;
+  const char *fracp;
   char sec1, sec2;
   size_t fracl;
   size_t tzl;
-  const char * sep = "";
+  const char *sep = "";
 
   /* Convert an ASN.1 Generalized time to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -453,12 +460,13 @@ static const char * GTime2str(const char * beg, const char * end)
 
   /* Get seconds digits. */
   sec1 = '0';
-  switch (fracp - beg - 12) {
+  switch(fracp - beg - 12) {
   case 0:
     sec2 = '0';
     break;
   case 2:
     sec1 = fracp[-2];
+    /* FALLTHROUGH */
   case 1:
     sec2 = fracp[-1];
     break;
@@ -499,11 +507,11 @@ static const char * GTime2str(const char * beg, const char * end)
                        sep, tzl, tzp);
 }
 
-static const char * UTime2str(const char * beg, const char * end)
+static const char *UTime2str(const char *beg, const char *end)
 {
-  const char * tzp;
+  const char *tzp;
   size_t tzl;
-  const char * sec;
+  const char *sec;
 
   /* Convert an ASN.1 UTC time to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -512,7 +520,7 @@ static const char * UTime2str(const char * beg, const char * end)
     ;
   /* Get the seconds. */
   sec = beg + 10;
-  switch (tzp - sec) {
+  switch(tzp - sec) {
   case 0:
     sec = "00";
   case 2:
@@ -538,7 +546,7 @@ static const char * UTime2str(const char * beg, const char * end)
                        tzl, tzp);
 }
 
-const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
+const char *Curl_ASN1tostr(curl_asn1Element *elem, int type)
 {
   /* Convert an ASN.1 element to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -549,7 +557,7 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
   if(!type)
     type = elem->tag;   /* Type not forced: use element tag as type. */
 
-  switch (type) {
+  switch(type) {
   case CURL_ASN1_BOOLEAN:
     return bool2str(elem->beg, elem->end);
   case CURL_ASN1_INTEGER:
@@ -581,17 +589,17 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
   return (const char *) NULL;   /* Unsupported. */
 }
 
-static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn)
+static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
 {
   curl_asn1Element rdn;
   curl_asn1Element atv;
   curl_asn1Element oid;
   curl_asn1Element value;
   size_t l = 0;
-  const char * p1;
-  const char * p2;
-  const char * p3;
-  const char * str;
+  const char *p1;
+  const char *p2;
+  const char *p3;
+  const char *str;
 
   /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'.
      Return the total string length, even if larger than `n'. */
@@ -647,9 +655,9 @@ static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn)
   return l;
 }
 
-const char * Curl_DNtostr(curl_asn1Element * dn)
+const char *Curl_DNtostr(curl_asn1Element *dn)
 {
-  char * buf = (char *) NULL;
+  char *buf = (char *) NULL;
   ssize_t n = encodeDN(buf, 0, dn);
 
   /* Convert an ASN.1 distinguished name into a printable string.
@@ -669,12 +677,12 @@ const char * Curl_DNtostr(curl_asn1Element * dn)
  * X509 parser.
  */
 
-void Curl_parseX509(curl_X509certificate * cert,
-                    const char * beg, const char * end)
+int Curl_parseX509(curl_X509certificate *cert,
+                   const char *beg, const char *end)
 {
   curl_asn1Element elem;
   curl_asn1Element tbsCertificate;
-  const char * ccp;
+  const char *ccp;
   static const char defaultVersion = 0;  /* v1. */
 
   /* ASN.1 parse an X509 certificate into structure subfields.
@@ -686,7 +694,8 @@ void Curl_parseX509(curl_X509certificate * cert,
   cert->certificate.end = end;
 
   /* Get the sequence content. */
-  Curl_getASN1Element(&elem, beg, end);
+  if(!Curl_getASN1Element(&elem, beg, end))
+    return -1;  /* Invalid bounds/size. */
   beg = elem.beg;
   end = elem.end;
 
@@ -749,9 +758,10 @@ void Curl_parseX509(curl_X509certificate * cert,
   }
   if(elem.tag == 3)
     Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
+  return 0;
 }
 
-static size_t copySubstring(char * to, const char * from)
+static size_t copySubstring(char *to, const char *from)
 {
   size_t i;
 
@@ -768,8 +778,8 @@ static size_t copySubstring(char * to, const char * from)
   return i;
 }
 
-static const char * dumpAlgo(curl_asn1Element * param,
-                             const char * beg, const char * end)
+static const char *dumpAlgo(curl_asn1Element *param,
+                            const char *beg, const char *end)
 {
   curl_asn1Element oid;
 
@@ -784,10 +794,10 @@ static const char * dumpAlgo(curl_asn1Element * param,
   return OID2str(oid.beg, oid.end, TRUE);
 }
 
-static void do_pubkey_field(struct Curl_easy * data, int certnum,
-                            const char * label, curl_asn1Element * elem)
+static void do_pubkey_field(struct Curl_easy *data, int certnum,
+                            const char *label, curl_asn1Element *elem)
 {
-  const char * output;
+  const char *output;
 
   /* Generate a certificate information record for the public key. */
 
@@ -801,14 +811,14 @@ static void do_pubkey_field(struct Curl_easy * data, int certnum,
   }
 }
 
-static void do_pubkey(struct Curl_easy * data, int certnum,
-                      const char * algo, curl_asn1Element * param,
-                      curl_asn1Element * pubkey)
+static void do_pubkey(struct Curl_easy *data, int certnum,
+                      const char *algo, curl_asn1Element *param,
+                      curl_asn1Element *pubkey)
 {
   curl_asn1Element elem;
   curl_asn1Element pk;
-  const char * p;
-  const char * q;
+  const char *p;
+  const char *q;
   unsigned long len;
   unsigned int i;
 
@@ -865,18 +875,18 @@ static void do_pubkey(struct Curl_easy * data, int certnum,
 #endif
 }
 
-CURLcode Curl_extract_certinfo(struct connectdata * conn,
+CURLcode Curl_extract_certinfo(struct connectdata *conn,
                                int certnum,
-                               const char * beg,
-                               const char * end)
+                               const char *beg,
+                               const char *end)
 {
   curl_X509certificate cert;
-  struct Curl_easy * data = conn->data;
+  struct Curl_easy *data = conn->data;
   curl_asn1Element param;
-  const char * ccp;
-  char * cp1;
+  const char *ccp;
+  char *cp1;
   size_t cl1;
-  char * cp2;
+  char *cp2;
   CURLcode result;
   unsigned long version;
   size_t i;
@@ -889,7 +899,8 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
   /* Prepare the certificate information for curl_easy_getinfo(). */
 
   /* Extract the certificate ASN.1 elements. */
-  Curl_parseX509(&cert, beg, end);
+  if(Curl_parseX509(&cert, beg, end))
+    return CURLE_OUT_OF_MEMORY;
 
   /* Subject. */
   ccp = Curl_DNtostr(&cert.subject);
@@ -1029,12 +1040,12 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
 
 #if defined(USE_GSKIT)
 
-static const char * checkOID(const char * beg, const char * end,
-                             const char * oid)
+static const char *checkOID(const char *beg, const char *end,
+                            const char *oid)
 {
   curl_asn1Element e;
-  const char * ccp;
-  const char * p;
+  const char *ccp;
+  const char *p;
   bool matched;
 
   /* Check if first ASN.1 element at `beg' is the given OID.
@@ -1053,21 +1064,26 @@ static const char * checkOID(const char * beg, const char * end,
   return matched? ccp: (const char *) NULL;
 }
 
-CURLcode Curl_verifyhost(struct connectdata * conn,
-                         const char * beg, const char * end)
+CURLcode Curl_verifyhost(struct connectdata *conn,
+                         const char *beg, const char *end)
 {
-  struct Curl_easy * data = conn->data;
+  struct Curl_easy *data = conn->data;
   curl_X509certificate cert;
   curl_asn1Element dn;
   curl_asn1Element elem;
   curl_asn1Element ext;
   curl_asn1Element name;
-  const char * p;
-  const char * q;
-  char * dnsname;
+  const char *p;
+  const char *q;
+  char *dnsname;
   int matched = -1;
   size_t addrlen = (size_t) -1;
   ssize_t len;
+  const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
+                                                conn->host.name;
+  const char * const dispname = SSL_IS_PROXY()?
+                                  conn->http_proxy.host.dispname:
+                                  conn->host.dispname;
 #ifdef ENABLE_IPV6
   struct in6_addr addr;
 #else
@@ -1077,20 +1093,19 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
   /* Verify that connection server matches info in X509 certificate at
      `beg'..`end'. */
 
-  if(!data->set.ssl.verifyhost)
+  if(!SSL_CONN_CONFIG(verifyhost))
     return CURLE_OK;
 
-  if(!beg)
+  if(Curl_parseX509(&cert, beg, end))
     return CURLE_PEER_FAILED_VERIFICATION;
-  Curl_parseX509(&cert, beg, end);
 
   /* Get the server IP address. */
 #ifdef ENABLE_IPV6
-  if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+  if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr))
     addrlen = sizeof(struct in6_addr);
   else
 #endif
-  if(Curl_inet_pton(AF_INET, conn->host.name, &addr))
+  if(Curl_inet_pton(AF_INET, hostname, &addr))
     addrlen = sizeof(struct in_addr);
 
   /* Process extensions. */
@@ -1108,12 +1123,12 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
       /* Check all GeneralNames. */
       for(q = elem.beg; matched != 1 && q < elem.end;) {
         q = Curl_getASN1Element(&name, q, elem.end);
-        switch (name.tag) {
+        switch(name.tag) {
         case 2: /* DNS name. */
           len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
                             name.beg, name.end);
           if(len > 0 && (size_t)len == strlen(dnsname))
-            matched = Curl_cert_hostcheck(dnsname, conn->host.name);
+            matched = Curl_cert_hostcheck(dnsname, hostname);
           else
             matched = 0;
           free(dnsname);
@@ -1128,15 +1143,15 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
     }
   }
 
-  switch (matched) {
+  switch(matched) {
   case 1:
     /* an alternative name matched the server hostname */
-    infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
+    infof(data, "\t subjectAltName: %s matched\n", 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", conn->host.dispname);
+    infof(data, "\t subjectAltName does not match %s\n", dispname);
     return CURLE_PEER_FAILED_VERIFICATION;
   }
 
@@ -1168,14 +1183,14 @@ CURLcode Curl_verifyhost(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, conn->host.name)) {
+    else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) {
       infof(data, "\t common name: %s (matched)\n", dnsname);
       free(dnsname);
       return CURLE_OK;
     }
     else
       failf(data, "SSL: certificate subject name '%s' does not match "
-            "target host name '%s'", dnsname, conn->host.dispname);
+            "target host name '%s'", dnsname, dispname);
     free(dnsname);
   }
 
diff --git a/Utilities/cmcurl/lib/x509asn1.h b/Utilities/cmcurl/lib/x509asn1.h
index 0f2b930..ce40297 100644
--- a/Utilities/cmcurl/lib/x509asn1.h
+++ b/Utilities/cmcurl/lib/x509asn1.h
@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -34,6 +34,9 @@
  * Constants.
  */
 
+/* Largest supported ASN.1 structure. */
+#define CURL_ASN1_MAX                   ((size_t) 0x40000)      /* 256K */
+
 /* ASN.1 classes. */
 #define CURL_ASN1_UNIVERSAL             0
 #define CURL_ASN1_APPLICATION           1
@@ -117,16 +120,15 @@ typedef struct {
  * Prototypes.
  */
 
-const char * Curl_getASN1Element(curl_asn1Element * elem,
-                                 const char * beg, const char * end);
-const char * Curl_ASN1tostr(curl_asn1Element * elem, int type);
-const char * Curl_DNtostr(curl_asn1Element * dn);
-void Curl_parseX509(curl_X509certificate * cert,
-                    const char * beg, const char * end);
-CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
-                               const char * beg, const char * end);
-CURLcode Curl_verifyhost(struct connectdata * conn,
-                         const char * beg, const char * end);
-
+const char *Curl_getASN1Element(curl_asn1Element *elem,
+                                 const char *beg, const char *end);
+const char *Curl_ASN1tostr(curl_asn1Element *elem, int type);
+const char *Curl_DNtostr(curl_asn1Element *dn);
+int Curl_parseX509(curl_X509certificate *cert,
+                   const char *beg, const char *end);
+CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum,
+                               const char *beg, const char *end);
+CURLcode Curl_verifyhost(struct connectdata *conn,
+                         const char *beg, const char *end);
 #endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL or USE_SCHANNEL */
 #endif /* HEADER_CURL_X509ASN1_H */
diff --git a/Utilities/cmexpat/COPYING b/Utilities/cmexpat/COPYING
index dcb4506..8d288f0 100644
--- a/Utilities/cmexpat/COPYING
+++ b/Utilities/cmexpat/COPYING
@@ -1,6 +1,5 @@
-Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
-                               and Clark Cooper
-Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
+Copyright (c) 2001-2017 Expat maintainers
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
diff --git a/Utilities/cmexpat/README b/Utilities/cmexpat/README
index 9ec8d0c..cd11a22 100644
--- a/Utilities/cmexpat/README
+++ b/Utilities/cmexpat/README
@@ -1,5 +1,5 @@
 
-                        Expat, Release 2.1.1
+                        Expat, Release 2.2.1
 
 This is Expat, a C library for parsing XML, written by James Clark.
 Expat is a stream-oriented XML parser.  This means that you register
@@ -114,7 +114,7 @@ Note for Solaris users:  The "ar" command is usually located in
 "/usr/ccs/bin", which is not in the default PATH.  You will need to
 add this to your path for the "make" command, and probably also switch
 to GNU make (the "make" found in /usr/ccs/bin does not seem to work
-properly -- appearantly it does not understand .PHONY directives).  If
+properly -- apparently it does not understand .PHONY directives).  If
 you're using ksh or bash, use this command to build:
 
         PATH=/usr/ccs/bin:$PATH make
diff --git a/Utilities/cmexpat/lib/expat.h b/Utilities/cmexpat/lib/expat.h
index 5abcefd..28b0f95 100644
--- a/Utilities/cmexpat/lib/expat.h
+++ b/Utilities/cmexpat/lib/expat.h
@@ -95,7 +95,9 @@ enum XML_Error {
   /* Added in 2.0. */
   XML_ERROR_RESERVED_PREFIX_XML,
   XML_ERROR_RESERVED_PREFIX_XMLNS,
-  XML_ERROR_RESERVED_NAMESPACE_URI
+  XML_ERROR_RESERVED_NAMESPACE_URI,
+  /* Added in 2.2.1. */
+  XML_ERROR_INVALID_ARGUMENT
 };
 
 enum XML_Content_Type {
@@ -342,7 +344,7 @@ XML_SetEntityDeclHandler(XML_Parser parser,
                          XML_EntityDeclHandler handler);
 
 /* OBSOLETE -- OBSOLETE -- OBSOLETE
-   This handler has been superceded by the EntityDeclHandler above.
+   This handler has been superseded by the EntityDeclHandler above.
    It is provided here for backward compatibility.
 
    This is called for a declaration of an unparsed (NDATA) entity.
@@ -706,6 +708,7 @@ XML_UseParserAsHandlerArg(XML_Parser parser);
      be called, despite an external subset being parsed.
    Note: If XML_DTD is not defined when Expat is compiled, returns
      XML_ERROR_FEATURE_REQUIRES_XML_DTD.
+   Note: If parser == NULL, returns XML_ERROR_INVALID_ARGUMENT.
 */
 XMLPARSEAPI(enum XML_Error)
 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD);
@@ -729,15 +732,16 @@ XML_GetBase(XML_Parser parser);
    to the XML_StartElementHandler that were specified in the start-tag
    rather than defaulted. Each attribute/value pair counts as 2; thus
    this correspondds to an index into the atts array passed to the
-   XML_StartElementHandler.
+   XML_StartElementHandler.  Returns -1 if parser == NULL.
 */
 XMLPARSEAPI(int)
 XML_GetSpecifiedAttributeCount(XML_Parser parser);
 
 /* Returns the index of the ID attribute passed in the last call to
-   XML_StartElementHandler, or -1 if there is no ID attribute.  Each
-   attribute/value pair counts as 2; thus this correspondds to an
-   index into the atts array passed to the XML_StartElementHandler.
+   XML_StartElementHandler, or -1 if there is no ID attribute or
+   parser == NULL.  Each attribute/value pair counts as 2; thus this
+   correspondds to an index into the atts array passed to the
+   XML_StartElementHandler.
 */
 XMLPARSEAPI(int)
 XML_GetIdAttributeIndex(XML_Parser parser);
@@ -901,6 +905,7 @@ enum XML_ParamEntityParsing {
    entities is requested; otherwise it will return non-zero.
    Note: If XML_SetParamEntityParsing is called after XML_Parse or
       XML_ParseBuffer, then it has no effect and will always return 0.
+   Note: If parser == NULL, the function will do nothing and return 0.
 */
 XMLPARSEAPI(int)
 XML_SetParamEntityParsing(XML_Parser parser,
@@ -910,6 +915,7 @@ XML_SetParamEntityParsing(XML_Parser parser,
    Helps in preventing DoS attacks based on predicting hash
    function behavior. This must be called before parsing is started.
    Returns 1 if successful, 0 when called after parsing has started.
+   Note: If parser == NULL, the function will do nothing and return 0.
 */
 XMLPARSEAPI(int)
 XML_SetHashSalt(XML_Parser parser,
@@ -936,6 +942,10 @@ XML_GetErrorCode(XML_Parser parser);
    the location is the location of the character at which the error
    was detected; otherwise the location is the location of the last
    parse event, as described above.
+
+   Note: XML_GetCurrentLineNumber and XML_GetCurrentColumnNumber
+   return 0 to indicate an error.
+   Note: XML_GetCurrentByteIndex returns -1 to indicate an error.
 */
 XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser);
 XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser);
@@ -1034,13 +1044,11 @@ XMLPARSEAPI(const XML_Feature *)
 XML_GetFeatureList(void);
 
 
-/* Expat follows the GNU/Linux convention of odd number minor version for
-   beta/development releases and even number minor version for stable
-   releases. Micro is bumped with each release, and set to 0 with each
-   change to major or minor version.
+/* Expat follows the semantic versioning convention.
+   See http://semver.org.
 */
 #define XML_MAJOR_VERSION 2
-#define XML_MINOR_VERSION 1
+#define XML_MINOR_VERSION 2
 #define XML_MICRO_VERSION 1
 
 #ifdef __cplusplus
diff --git a/Utilities/cmexpat/lib/expat_external.h b/Utilities/cmexpat/lib/expat_external.h
index 07a3c5c..d60eecc 100644
--- a/Utilities/cmexpat/lib/expat_external.h
+++ b/Utilities/cmexpat/lib/expat_external.h
@@ -95,7 +95,10 @@ extern "C" {
 #endif
 
 #ifdef XML_UNICODE_WCHAR_T
-#define XML_UNICODE
+# define XML_UNICODE
+# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2)
+#  error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc"
+# endif
 #endif
 
 #ifdef XML_UNICODE     /* Information is UTF-16 encoded. */
diff --git a/Utilities/cmexpat/lib/siphash.h b/Utilities/cmexpat/lib/siphash.h
new file mode 100644
index 0000000..db17458
--- /dev/null
+++ b/Utilities/cmexpat/lib/siphash.h
@@ -0,0 +1,354 @@
+/* ==========================================================================
+ * siphash.h - SipHash-2-4 in a single header file
+ * --------------------------------------------------------------------------
+ * Derived by William Ahern from the reference implementation[1] published[2]
+ * by Jean-Philippe Aumasson and Daniel J. Berstein. Licensed in kind.
+ * by Jean-Philippe Aumasson and Daniel J. Berstein.
+ * Minimal changes by Sebastian Pipping on top, details below.
+ * Licensed under the CC0 Public Domain Dedication license.
+ *
+ * 1. https://www.131002.net/siphash/siphash24.c
+ * 2. https://www.131002.net/siphash/
+ * --------------------------------------------------------------------------
+ * HISTORY:
+ *
+ * 2017-06-10  (Sebastian Pipping)
+ *   - Clarify license note in the header
+ *   - Address C89 issues:
+ *     - Stop using inline keyword (and let compiler decide)
+ *     - Turn integer suffix ULL to UL
+ *     - Replace _Bool by int
+ *     - Turn macro siphash24 into a function
+ *     - Address invalid conversion (void pointer) by explicit cast
+ *   - Always expose sip24_valid (for self-tests)
+ *
+ * 2012-11-04 - Born.  (William Ahern)
+ * --------------------------------------------------------------------------
+ * USAGE:
+ *
+ * SipHash-2-4 takes as input two 64-bit words as the key, some number of
+ * message bytes, and outputs a 64-bit word as the message digest. This
+ * implementation employs two data structures: a struct sipkey for
+ * representing the key, and a struct siphash for representing the hash
+ * state.
+ *
+ * For converting a 16-byte unsigned char array to a key, use either the
+ * macro sip_keyof or the routine sip_tokey. The former instantiates a
+ * compound literal key, while the latter requires a key object as a
+ * parameter.
+ *
+ * 	unsigned char secret[16];
+ * 	arc4random_buf(secret, sizeof secret);
+ * 	struct sipkey *key = sip_keyof(secret);
+ *
+ * For hashing a message, use either the convenience macro siphash24 or the
+ * routines sip24_init, sip24_update, and sip24_final.
+ *
+ * 	struct siphash state;
+ * 	void *msg;
+ * 	size_t len;
+ * 	uint64_t hash;
+ *
+ * 	sip24_init(&state, key);
+ * 	sip24_update(&state, msg, len);
+ * 	hash = sip24_final(&state);
+ *
+ * or
+ *
+ * 	hash = siphash24(msg, len, key);
+ *
+ * To convert the 64-bit hash value to a canonical 8-byte little-endian
+ * binary representation, use either the macro sip_binof or the routine
+ * sip_tobin. The former instantiates and returns a compound literal array,
+ * while the latter requires an array object as a parameter.
+ * --------------------------------------------------------------------------
+ * NOTES:
+ *
+ * o Neither sip_keyof, sip_binof, nor siphash24 will work with compilers
+ *   lacking compound literal support. Instead, you must use the lower-level
+ *   interfaces which take as parameters the temporary state objects.
+ *
+ * o Uppercase macros may evaluate parameters more than once. Lowercase
+ *   macros should not exhibit any such side effects.
+ * ==========================================================================
+ */
+#ifndef SIPHASH_H
+#define SIPHASH_H
+
+#include <stddef.h> /* size_t */
+
+#include <cm_kwiml.h>
+
+#ifndef KWIML_INT_HAVE_UINT64_T
+# define uint64_t KWIML_INT_uint64_t
+#endif
+#ifndef KWIML_INT_HAVE_UINT32_T
+# define uint32_t KWIML_INT_uint32_t
+#endif
+#ifndef KWIML_INT_HAVE_UINT8_T
+# define uint8_t KWIML_INT_uint8_t
+#endif
+
+#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ( (x) >> (64 - (b))))
+
+#define SIP_U32TO8_LE(p, v) \
+	(p)[0] = (uint8_t)((v) >>  0); (p)[1] = (uint8_t)((v) >>  8); \
+	(p)[2] = (uint8_t)((v) >> 16); (p)[3] = (uint8_t)((v) >> 24);
+
+#define SIP_U64TO8_LE(p, v) \
+	SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >>  0)); \
+	SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+
+#define SIP_U8TO64_LE(p) \
+	(((uint64_t)((p)[0]) <<  0) | \
+	 ((uint64_t)((p)[1]) <<  8) | \
+	 ((uint64_t)((p)[2]) << 16) | \
+	 ((uint64_t)((p)[3]) << 24) | \
+	 ((uint64_t)((p)[4]) << 32) | \
+	 ((uint64_t)((p)[5]) << 40) | \
+	 ((uint64_t)((p)[6]) << 48) | \
+	 ((uint64_t)((p)[7]) << 56))
+
+
+#define SIPHASH_INITIALIZER { 0, 0, 0, 0, { 0 }, 0, 0 }
+
+struct siphash {
+	uint64_t v0, v1, v2, v3;
+
+	unsigned char buf[8], *p;
+	uint64_t c;
+}; /* struct siphash */
+
+
+#define SIP_KEYLEN 16
+
+struct sipkey {
+	uint64_t k[2];
+}; /* struct sipkey */
+
+#define sip_keyof(k) sip_tokey(&(struct sipkey){ { 0 } }, (k))
+
+static struct sipkey *sip_tokey(struct sipkey *key, const void *src) {
+	key->k[0] = SIP_U8TO64_LE((const unsigned char *)src);
+	key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8);
+	return key;
+} /* sip_tokey() */
+
+
+#define sip_binof(v) sip_tobin((unsigned char[8]){ 0 }, (v))
+
+static void *sip_tobin(void *dst, uint64_t u64) {
+	SIP_U64TO8_LE((unsigned char *)dst, u64);
+	return dst;
+} /* sip_tobin() */
+
+
+static void sip_round(struct siphash *H, const int rounds) {
+	int i;
+
+	for (i = 0; i < rounds; i++) {
+		H->v0 += H->v1;
+		H->v1 = SIP_ROTL(H->v1, 13);
+		H->v1 ^= H->v0;
+		H->v0 = SIP_ROTL(H->v0, 32);
+
+		H->v2 += H->v3;
+		H->v3 = SIP_ROTL(H->v3, 16);
+		H->v3 ^= H->v2;
+
+		H->v0 += H->v3;
+		H->v3 = SIP_ROTL(H->v3, 21);
+		H->v3 ^= H->v0;
+
+		H->v2 += H->v1;
+		H->v1 = SIP_ROTL(H->v1, 17);
+		H->v1 ^= H->v2;
+		H->v2 = SIP_ROTL(H->v2, 32);
+	}
+} /* sip_round() */
+
+
+static struct siphash *sip24_init(struct siphash *H, const struct sipkey *key) {
+	H->v0 = 0x736f6d6570736575UL ^ key->k[0];
+	H->v1 = 0x646f72616e646f6dUL ^ key->k[1];
+	H->v2 = 0x6c7967656e657261UL ^ key->k[0];
+	H->v3 = 0x7465646279746573UL ^ key->k[1];
+
+	H->p = H->buf;
+	H->c = 0;
+
+	return H;
+} /* sip24_init() */
+
+
+#define sip_endof(a) (&(a)[sizeof (a) / sizeof *(a)])
+
+static struct siphash *sip24_update(struct siphash *H, const void *src, size_t len) {
+	const unsigned char *p = (const unsigned char *)src, *pe = p + len;
+	uint64_t m;
+
+	do {
+		while (p < pe && H->p < sip_endof(H->buf))
+			*H->p++ = *p++;
+
+		if (H->p < sip_endof(H->buf))
+			break;
+
+		m = SIP_U8TO64_LE(H->buf);
+		H->v3 ^= m;
+		sip_round(H, 2);
+		H->v0 ^= m;
+
+		H->p = H->buf;
+		H->c += 8;
+	} while (p < pe);
+
+	return H;
+} /* sip24_update() */
+
+
+static uint64_t sip24_final(struct siphash *H) {
+	char left = H->p - H->buf;
+	uint64_t b = (H->c + left) << 56;
+
+	switch (left) {
+	case 7: b |= (uint64_t)H->buf[6] << 48;
+	case 6: b |= (uint64_t)H->buf[5] << 40;
+	case 5: b |= (uint64_t)H->buf[4] << 32;
+	case 4: b |= (uint64_t)H->buf[3] << 24;
+	case 3: b |= (uint64_t)H->buf[2] << 16;
+	case 2: b |= (uint64_t)H->buf[1] << 8;
+	case 1: b |= (uint64_t)H->buf[0] << 0;
+	case 0: break;
+	}
+
+	H->v3 ^= b;
+	sip_round(H, 2);
+	H->v0 ^= b;
+	H->v2 ^= 0xff;
+	sip_round(H, 4);
+
+	return H->v0 ^ H->v1 ^ H->v2  ^ H->v3;
+} /* sip24_final() */
+
+
+static uint64_t siphash24(const void *src, size_t len, const struct sipkey *key) {
+	struct siphash state = SIPHASH_INITIALIZER;
+	return sip24_final(sip24_update(sip24_init(&state, key), src, len));
+} /* siphash24() */
+
+
+/*
+ * SipHash-2-4 output with
+ * k = 00 01 02 ...
+ * and
+ * in = (empty string)
+ * in = 00 (1 byte)
+ * in = 00 01 (2 bytes)
+ * in = 00 01 02 (3 bytes)
+ * ...
+ * in = 00 01 02 ... 3e (63 bytes)
+ */
+static int sip24_valid(void) {
+	static const unsigned char vectors[64][8] = {
+		{ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
+		{ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
+		{ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
+		{ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
+		{ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
+		{ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
+		{ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
+		{ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
+		{ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
+		{ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
+		{ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
+		{ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
+		{ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
+		{ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
+		{ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
+		{ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
+		{ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
+		{ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
+		{ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
+		{ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
+		{ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
+		{ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
+		{ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
+		{ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
+		{ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
+		{ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
+		{ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
+		{ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
+		{ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
+		{ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
+		{ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
+		{ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
+		{ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
+		{ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
+		{ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
+		{ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
+		{ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
+		{ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
+		{ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
+		{ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
+		{ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
+		{ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
+		{ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
+		{ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
+		{ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
+		{ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
+		{ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
+		{ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
+		{ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
+		{ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
+		{ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
+		{ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
+		{ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
+		{ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
+		{ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
+		{ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
+		{ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
+		{ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
+		{ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
+		{ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
+		{ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
+		{ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
+		{ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
+		{ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
+	};
+	unsigned char in[64];
+	struct sipkey k;
+	size_t i;
+
+	sip_tokey(&k, "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017");
+
+	for (i = 0; i < sizeof in; ++i) {
+		in[i] = i;
+
+		if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i]))
+			return 0;
+	}
+
+	return 1;
+} /* sip24_valid() */
+
+
+#if SIPHASH_MAIN
+
+#include <stdio.h>
+
+int main(void) {
+	int ok = sip24_valid();
+
+	if (ok)
+		puts("OK");
+	else
+		puts("FAIL");
+
+	return !ok;
+} /* main() */
+
+#endif /* SIPHASH_MAIN */
+
+
+#endif /* SIPHASH_H */
diff --git a/Utilities/cmexpat/lib/winconfig.h b/Utilities/cmexpat/lib/winconfig.h
index d7dad38..c9dbfea 100644
--- a/Utilities/cmexpat/lib/winconfig.h
+++ b/Utilities/cmexpat/lib/winconfig.h
@@ -17,7 +17,24 @@
 #include <memory.h>
 #include <string.h>
 
-#include "expat_config.h"
+
+#if defined(HAVE_EXPAT_CONFIG_H)  /* e.g. MinGW */
+# include <expat_config.h>
+#else  /* !defined(HAVE_EXPAT_CONFIG_H) */
+
+
+#define XML_NS 1
+#define XML_DTD 1
+#define XML_CONTEXT_BYTES 1024
+
+/* we will assume all Windows platforms are little endian */
+#define BYTEORDER 1234
+
+/* Windows has memmove() available. */
+#define HAVE_MEMMOVE
+
+
+#endif /* !defined(HAVE_EXPAT_CONFIG_H) */
 
 #if defined(_MSC_VER)
 # pragma warning(push,1)
diff --git a/Utilities/cmexpat/lib/xmlparse.c b/Utilities/cmexpat/lib/xmlparse.c
index b56b66a..76f078e 100644
--- a/Utilities/cmexpat/lib/xmlparse.c
+++ b/Utilities/cmexpat/lib/xmlparse.c
@@ -1,13 +1,19 @@
 /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
    See the file COPYING for copying permission.
+
+   77fea421d361dca90041d0040ecf1dca651167fadf2af79e990e35168d70d933 (2.2.1+)
 */
 
+#define _GNU_SOURCE                     /* syscall prototype */
+
 #include <stddef.h>
 #include <string.h>                     /* memset(), memcpy() */
 #include <assert.h>
 #include <limits.h>                     /* UINT_MAX */
+#include <stdio.h>                      /* fprintf */
+#include <stdlib.h>                     /* getenv */
 
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
 #define getpid GetCurrentProcessId
 #else
 #include <sys/time.h>                   /* gettimeofday() */
@@ -17,20 +23,15 @@
 
 #define XML_BUILDING_EXPAT 1
 
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
 #include "winconfig.h"
-#elif defined(MACOS_CLASSIC)
-#include "macconfig.h"
-#elif defined(__amigaos__)
-#include "amigaconfig.h"
-#elif defined(__WATCOMC__)
-#include "watcomconfig.h"
 #elif defined(HAVE_EXPAT_CONFIG_H)
 #include <expat_config.h>
-#endif /* ndef COMPILING_FOR_WINDOWS */
+#endif /* ndef _WIN32 */
 
 #include "ascii.h"
 #include "expat.h"
+#include "siphash.h"
 
 #ifdef XML_UNICODE
 #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
@@ -109,17 +110,11 @@ typedef struct {
   const XML_Memory_Handling_Suite *mem;
 } HASH_TABLE;
 
-/* Basic character hash algorithm, taken from Python's string hash:
-   h = h * 1000003 ^ character, the constant being a prime number.
+static size_t
+keylen(KEY s);
 
-*/
-#ifdef XML_UNICODE
-#define CHAR_HASH(h, c) \
-  (((h) * 0xF4243) ^ (unsigned short)(c))
-#else
-#define CHAR_HASH(h, c) \
-  (((h) * 0xF4243) ^ (unsigned char)(c))
-#endif
+static void
+copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key);
 
 /* For probing (after a collision) we need a step size relative prime
    to the hash table size, which is a power of 2. We use double-hashing,
@@ -355,6 +350,8 @@ doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
                 const char *end, const char **nextPtr, XML_Bool haveMore);
 #endif /* XML_DTD */
 
+static void
+freeBindings(XML_Parser parser, BINDING *bindings);
 static enum XML_Error
 storeAtts(XML_Parser parser, const ENCODING *, const char *s,
           TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
@@ -697,10 +694,84 @@ static const XML_Char implicitContext[] = {
   ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
 };
 
+
+#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+# include <errno.h>
+
+# if defined(HAVE_GETRANDOM)
+#  include <sys/random.h>    /* getrandom */
+# else
+#  include <unistd.h>        /* syscall */
+#  include <sys/syscall.h>   /* SYS_getrandom */
+# endif
+
+/* Obtain entropy on Linux 3.17+ */
+static int
+writeRandomBytes_getrandom(void * target, size_t count) {
+  int success = 0;  /* full count bytes written? */
+  size_t bytesWrittenTotal = 0;
+  const unsigned int getrandomFlags = 0;
+
+  do {
+    void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
+    const size_t bytesToWrite = count - bytesWrittenTotal;
+
+    const int bytesWrittenMore =
+#if defined(HAVE_GETRANDOM)
+        getrandom(currentTarget, bytesToWrite, getrandomFlags);
+#else
+        syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
+#endif
+
+    if (bytesWrittenMore > 0) {
+      bytesWrittenTotal += bytesWrittenMore;
+      if (bytesWrittenTotal >= count)
+        success = 1;
+    }
+  } while (! success && (errno == EINTR || errno == EAGAIN));
+
+  return success;
+}
+
+#endif  /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
+
+
+#ifdef _WIN32
+
+typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
+
+/* Obtain entropy on Windows XP / Windows Server 2003 and later.
+ * Hint on RtlGenRandom and the following article from libsodioum.
+ *
+ * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
+ * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
+ */
+static int
+writeRandomBytes_RtlGenRandom(void * target, size_t count) {
+  int success = 0;  /* full count bytes written? */
+  const HMODULE advapi32 = LoadLibrary("ADVAPI32.DLL");
+
+  if (advapi32) {
+    const RTLGENRANDOM_FUNC RtlGenRandom
+        = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
+    if (RtlGenRandom) {
+      if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
+        success = 1;
+      }
+    }
+    FreeLibrary(advapi32);
+  }
+
+  return success;
+}
+
+#endif /* _WIN32 */
+
+
 static unsigned long
 gather_time_entropy(void)
 {
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
   FILETIME ft;
   GetSystemTimeAsFileTime(&ft); /* never fails */
   return ft.dwHighDateTime ^ ft.dwLowDateTime;
@@ -716,20 +787,62 @@ gather_time_entropy(void)
 #endif
 }
 
+#if defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_LIBBSD)
+# include <bsd/stdlib.h>
+#endif
+
+static unsigned long
+ENTROPY_DEBUG(const char * label, unsigned long entropy) {
+  const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
+  if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
+    fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
+        label,
+        (int)sizeof(entropy) * 2, entropy,
+        (unsigned long)sizeof(entropy));
+  }
+  return entropy;
+}
+
 static unsigned long
 generate_hash_secret_salt(XML_Parser parser)
 {
-  /* Process ID is 0 bits entropy if attacker has local access
-   * XML_Parser address is few bits of entropy if attacker has local access */
-  const unsigned long entropy =
-      gather_time_entropy() ^ getpid() ^ (unsigned long)parser;
+  unsigned long entropy;
+  (void)parser;
+#if defined(HAVE_ARC4RANDOM_BUF) || defined(__CloudABI__)
+  (void)gather_time_entropy;
+  arc4random_buf(&entropy, sizeof(entropy));
+  return ENTROPY_DEBUG("arc4random_buf", entropy);
+#else
+  /* Try high quality providers first .. */
+#ifdef _WIN32
+  if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
+    return ENTROPY_DEBUG("RtlGenRandom", entropy);
+  }
+#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+  if (writeRandomBytes_getrandom((void *)&entropy, sizeof(entropy))) {
+    return ENTROPY_DEBUG("getrandom", entropy);
+  }
+#endif
+  /* .. and self-made low quality for backup: */
+
+  /* Process ID is 0 bits entropy if attacker has local access */
+  entropy = gather_time_entropy() ^ getpid();
 
   /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
   if (sizeof(unsigned long) == 4) {
-    return entropy * 2147483647;
+    return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
   } else {
-    return entropy * 2305843009213693951;
+    return ENTROPY_DEBUG("fallback(8)",
+        entropy * (unsigned long)2305843009213693951);
   }
+#endif
+}
+
+static unsigned long
+get_hash_secret_salt(XML_Parser parser) {
+  if (parser->m_parentParser != NULL)
+    return get_hash_secret_salt(parser->m_parentParser);
+  return parser->m_hash_secret_salt;
 }
 
 static XML_Bool  /* only valid for root parser */
@@ -960,6 +1073,10 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
 {
   TAG *tStk;
   OPEN_INTERNAL_ENTITY *openEntityList;
+
+  if (parser == NULL)
+      return XML_FALSE;
+
   if (parentParser)
     return XML_FALSE;
   /* move tagStack to freeTagList */
@@ -994,6 +1111,8 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
 enum XML_Status XMLCALL
 XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
 {
+  if (parser == NULL)
+      return XML_STATUS_ERROR;
   /* Block after XML_Parse()/XML_ParseBuffer() has been called.
      XXX There's no way for the caller to determine which of the
      XXX possible error cases caused the XML_STATUS_ERROR return.
@@ -1017,52 +1136,88 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser,
 {
   XML_Parser parser = oldParser;
   DTD *newDtd = NULL;
-  DTD *oldDtd = _dtd;
-  XML_StartElementHandler oldStartElementHandler = startElementHandler;
-  XML_EndElementHandler oldEndElementHandler = endElementHandler;
-  XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
-  XML_ProcessingInstructionHandler oldProcessingInstructionHandler
-      = processingInstructionHandler;
-  XML_CommentHandler oldCommentHandler = commentHandler;
-  XML_StartCdataSectionHandler oldStartCdataSectionHandler
-      = startCdataSectionHandler;
-  XML_EndCdataSectionHandler oldEndCdataSectionHandler
-      = endCdataSectionHandler;
-  XML_DefaultHandler oldDefaultHandler = defaultHandler;
-  XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
-      = unparsedEntityDeclHandler;
-  XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
-  XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
-      = startNamespaceDeclHandler;
-  XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
-      = endNamespaceDeclHandler;
-  XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
-  XML_ExternalEntityRefHandler oldExternalEntityRefHandler
-      = externalEntityRefHandler;
-  XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
-  XML_UnknownEncodingHandler oldUnknownEncodingHandler
-      = unknownEncodingHandler;
-  XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
-  XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
-  XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
-  XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
-  ELEMENT_TYPE * oldDeclElementType = declElementType;
-
-  void *oldUserData = userData;
-  void *oldHandlerArg = handlerArg;
-  XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
-  XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+  DTD *oldDtd;
+  XML_StartElementHandler oldStartElementHandler;
+  XML_EndElementHandler oldEndElementHandler;
+  XML_CharacterDataHandler oldCharacterDataHandler;
+  XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
+  XML_CommentHandler oldCommentHandler;
+  XML_StartCdataSectionHandler oldStartCdataSectionHandler;
+  XML_EndCdataSectionHandler oldEndCdataSectionHandler;
+  XML_DefaultHandler oldDefaultHandler;
+  XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
+  XML_NotationDeclHandler oldNotationDeclHandler;
+  XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
+  XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
+  XML_NotStandaloneHandler oldNotStandaloneHandler;
+  XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
+  XML_SkippedEntityHandler oldSkippedEntityHandler;
+  XML_UnknownEncodingHandler oldUnknownEncodingHandler;
+  XML_ElementDeclHandler oldElementDeclHandler;
+  XML_AttlistDeclHandler oldAttlistDeclHandler;
+  XML_EntityDeclHandler oldEntityDeclHandler;
+  XML_XmlDeclHandler oldXmlDeclHandler;
+  ELEMENT_TYPE * oldDeclElementType;
+
+  void *oldUserData;
+  void *oldHandlerArg;
+  XML_Bool oldDefaultExpandInternalEntities;
+  XML_Parser oldExternalEntityRefHandlerArg;
 #ifdef XML_DTD
-  enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
-  int oldInEntityValue = prologState.inEntityValue;
+  enum XML_ParamEntityParsing oldParamEntityParsing;
+  int oldInEntityValue;
 #endif
-  XML_Bool oldns_triplets = ns_triplets;
+  XML_Bool oldns_triplets;
   /* Note that the new parser shares the same hash secret as the old
      parser, so that dtdCopy and copyEntityTable can lookup values
      from hash tables associated with either parser without us having
      to worry which hash secrets each table has.
   */
-  unsigned long oldhash_secret_salt = hash_secret_salt;
+  unsigned long oldhash_secret_salt;
+
+  /* Validate the oldParser parameter before we pull everything out of it */
+  if (oldParser == NULL)
+    return NULL;
+
+  /* Stash the original parser contents on the stack */
+  oldDtd = _dtd;
+  oldStartElementHandler = startElementHandler;
+  oldEndElementHandler = endElementHandler;
+  oldCharacterDataHandler = characterDataHandler;
+  oldProcessingInstructionHandler = processingInstructionHandler;
+  oldCommentHandler = commentHandler;
+  oldStartCdataSectionHandler = startCdataSectionHandler;
+  oldEndCdataSectionHandler = endCdataSectionHandler;
+  oldDefaultHandler = defaultHandler;
+  oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
+  oldNotationDeclHandler = notationDeclHandler;
+  oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
+  oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
+  oldNotStandaloneHandler = notStandaloneHandler;
+  oldExternalEntityRefHandler = externalEntityRefHandler;
+  oldSkippedEntityHandler = skippedEntityHandler;
+  oldUnknownEncodingHandler = unknownEncodingHandler;
+  oldElementDeclHandler = elementDeclHandler;
+  oldAttlistDeclHandler = attlistDeclHandler;
+  oldEntityDeclHandler = entityDeclHandler;
+  oldXmlDeclHandler = xmlDeclHandler;
+  oldDeclElementType = declElementType;
+
+  oldUserData = userData;
+  oldHandlerArg = handlerArg;
+  oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+  oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+#ifdef XML_DTD
+  oldParamEntityParsing = paramEntityParsing;
+  oldInEntityValue = prologState.inEntityValue;
+#endif
+  oldns_triplets = ns_triplets;
+  /* Note that the new parser shares the same hash secret as the old
+     parser, so that dtdCopy and copyEntityTable can lookup values
+     from hash tables associated with either parser without us having
+     to worry which hash secrets each table has.
+  */
+  oldhash_secret_salt = hash_secret_salt;
 
 #ifdef XML_DTD
   if (!context)
@@ -1228,12 +1383,15 @@ XML_ParserFree(XML_Parser parser)
 void XMLCALL
 XML_UseParserAsHandlerArg(XML_Parser parser)
 {
-  handlerArg = parser;
+  if (parser != NULL)
+    handlerArg = parser;
 }
 
 enum XML_Error XMLCALL
 XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
 {
+  if (parser == NULL)
+    return XML_ERROR_INVALID_ARGUMENT;
 #ifdef XML_DTD
   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
@@ -1248,6 +1406,8 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
 void XMLCALL
 XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
 {
+  if (parser == NULL)
+    return;
   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
     return;
@@ -1257,6 +1417,8 @@ XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
 void XMLCALL
 XML_SetUserData(XML_Parser parser, void *p)
 {
+  if (parser == NULL)
+    return;
   if (handlerArg == userData)
     handlerArg = userData = p;
   else
@@ -1266,6 +1428,8 @@ XML_SetUserData(XML_Parser parser, void *p)
 enum XML_Status XMLCALL
 XML_SetBase(XML_Parser parser, const XML_Char *p)
 {
+  if (parser == NULL)
+    return XML_STATUS_ERROR;
   if (p) {
     p = poolCopyString(&_dtd->pool, p);
     if (!p)
@@ -1280,18 +1444,24 @@ XML_SetBase(XML_Parser parser, const XML_Char *p)
 const XML_Char * XMLCALL
 XML_GetBase(XML_Parser parser)
 {
+  if (parser == NULL)
+    return NULL;
   return curBase;
 }
 
 int XMLCALL
 XML_GetSpecifiedAttributeCount(XML_Parser parser)
 {
+  if (parser == NULL)
+    return -1;
   return nSpecifiedAtts;
 }
 
 int XMLCALL
 XML_GetIdAttributeIndex(XML_Parser parser)
 {
+  if (parser == NULL)
+    return -1;
   return idAttIndex;
 }
 
@@ -1299,6 +1469,8 @@ XML_GetIdAttributeIndex(XML_Parser parser)
 const XML_AttrInfo * XMLCALL
 XML_GetAttributeInfo(XML_Parser parser)
 {
+  if (parser == NULL)
+    return NULL;
   return attInfo;
 }
 #endif
@@ -1308,6 +1480,8 @@ XML_SetElementHandler(XML_Parser parser,
                       XML_StartElementHandler start,
                       XML_EndElementHandler end)
 {
+  if (parser == NULL)
+    return;
   startElementHandler = start;
   endElementHandler = end;
 }
@@ -1315,34 +1489,39 @@ XML_SetElementHandler(XML_Parser parser,
 void XMLCALL
 XML_SetStartElementHandler(XML_Parser parser,
                            XML_StartElementHandler start) {
-  startElementHandler = start;
+  if (parser != NULL)
+    startElementHandler = start;
 }
 
 void XMLCALL
 XML_SetEndElementHandler(XML_Parser parser,
                          XML_EndElementHandler end) {
-  endElementHandler = end;
+  if (parser != NULL)
+    endElementHandler = end;
 }
 
 void XMLCALL
 XML_SetCharacterDataHandler(XML_Parser parser,
                             XML_CharacterDataHandler handler)
 {
-  characterDataHandler = handler;
+  if (parser != NULL)
+    characterDataHandler = handler;
 }
 
 void XMLCALL
 XML_SetProcessingInstructionHandler(XML_Parser parser,
                                     XML_ProcessingInstructionHandler handler)
 {
-  processingInstructionHandler = handler;
+  if (parser != NULL)
+    processingInstructionHandler = handler;
 }
 
 void XMLCALL
 XML_SetCommentHandler(XML_Parser parser,
                       XML_CommentHandler handler)
 {
-  commentHandler = handler;
+  if (parser != NULL)
+    commentHandler = handler;
 }
 
 void XMLCALL
@@ -1350,6 +1529,8 @@ XML_SetCdataSectionHandler(XML_Parser parser,
                            XML_StartCdataSectionHandler start,
                            XML_EndCdataSectionHandler end)
 {
+  if (parser == NULL)
+    return;
   startCdataSectionHandler = start;
   endCdataSectionHandler = end;
 }
@@ -1357,19 +1538,23 @@ XML_SetCdataSectionHandler(XML_Parser parser,
 void XMLCALL
 XML_SetStartCdataSectionHandler(XML_Parser parser,
                                 XML_StartCdataSectionHandler start) {
-  startCdataSectionHandler = start;
+  if (parser != NULL)
+    startCdataSectionHandler = start;
 }
 
 void XMLCALL
 XML_SetEndCdataSectionHandler(XML_Parser parser,
                               XML_EndCdataSectionHandler end) {
-  endCdataSectionHandler = end;
+  if (parser != NULL)
+    endCdataSectionHandler = end;
 }
 
 void XMLCALL
 XML_SetDefaultHandler(XML_Parser parser,
                       XML_DefaultHandler handler)
 {
+  if (parser == NULL)
+    return;
   defaultHandler = handler;
   defaultExpandInternalEntities = XML_FALSE;
 }
@@ -1378,6 +1563,8 @@ void XMLCALL
 XML_SetDefaultHandlerExpand(XML_Parser parser,
                             XML_DefaultHandler handler)
 {
+  if (parser == NULL)
+    return;
   defaultHandler = handler;
   defaultExpandInternalEntities = XML_TRUE;
 }
@@ -1387,6 +1574,8 @@ XML_SetDoctypeDeclHandler(XML_Parser parser,
                           XML_StartDoctypeDeclHandler start,
                           XML_EndDoctypeDeclHandler end)
 {
+  if (parser == NULL)
+    return;
   startDoctypeDeclHandler = start;
   endDoctypeDeclHandler = end;
 }
@@ -1394,27 +1583,31 @@ XML_SetDoctypeDeclHandler(XML_Parser parser,
 void XMLCALL
 XML_SetStartDoctypeDeclHandler(XML_Parser parser,
                                XML_StartDoctypeDeclHandler start) {
-  startDoctypeDeclHandler = start;
+  if (parser != NULL)
+    startDoctypeDeclHandler = start;
 }
 
 void XMLCALL
 XML_SetEndDoctypeDeclHandler(XML_Parser parser,
                              XML_EndDoctypeDeclHandler end) {
-  endDoctypeDeclHandler = end;
+  if (parser != NULL)
+    endDoctypeDeclHandler = end;
 }
 
 void XMLCALL
 XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
                                  XML_UnparsedEntityDeclHandler handler)
 {
-  unparsedEntityDeclHandler = handler;
+  if (parser != NULL)
+    unparsedEntityDeclHandler = handler;
 }
 
 void XMLCALL
 XML_SetNotationDeclHandler(XML_Parser parser,
                            XML_NotationDeclHandler handler)
 {
-  notationDeclHandler = handler;
+  if (parser != NULL)
+    notationDeclHandler = handler;
 }
 
 void XMLCALL
@@ -1422,6 +1615,8 @@ XML_SetNamespaceDeclHandler(XML_Parser parser,
                             XML_StartNamespaceDeclHandler start,
                             XML_EndNamespaceDeclHandler end)
 {
+  if (parser == NULL)
+    return;
   startNamespaceDeclHandler = start;
   endNamespaceDeclHandler = end;
 }
@@ -1429,32 +1624,38 @@ XML_SetNamespaceDeclHandler(XML_Parser parser,
 void XMLCALL
 XML_SetStartNamespaceDeclHandler(XML_Parser parser,
                                  XML_StartNamespaceDeclHandler start) {
-  startNamespaceDeclHandler = start;
+  if (parser != NULL)
+    startNamespaceDeclHandler = start;
 }
 
 void XMLCALL
 XML_SetEndNamespaceDeclHandler(XML_Parser parser,
                                XML_EndNamespaceDeclHandler end) {
-  endNamespaceDeclHandler = end;
+  if (parser != NULL)
+    endNamespaceDeclHandler = end;
 }
 
 void XMLCALL
 XML_SetNotStandaloneHandler(XML_Parser parser,
                             XML_NotStandaloneHandler handler)
 {
-  notStandaloneHandler = handler;
+  if (parser != NULL)
+    notStandaloneHandler = handler;
 }
 
 void XMLCALL
 XML_SetExternalEntityRefHandler(XML_Parser parser,
                                 XML_ExternalEntityRefHandler handler)
 {
-  externalEntityRefHandler = handler;
+  if (parser != NULL)
+    externalEntityRefHandler = handler;
 }
 
 void XMLCALL
 XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
 {
+  if (parser == NULL)
+    return;
   if (arg)
     externalEntityRefHandlerArg = (XML_Parser)arg;
   else
@@ -1465,7 +1666,8 @@ void XMLCALL
 XML_SetSkippedEntityHandler(XML_Parser parser,
                             XML_SkippedEntityHandler handler)
 {
-  skippedEntityHandler = handler;
+  if (parser != NULL)
+    skippedEntityHandler = handler;
 }
 
 void XMLCALL
@@ -1473,6 +1675,8 @@ XML_SetUnknownEncodingHandler(XML_Parser parser,
                               XML_UnknownEncodingHandler handler,
                               void *data)
 {
+  if (parser == NULL)
+    return;
   unknownEncodingHandler = handler;
   unknownEncodingHandlerData = data;
 }
@@ -1481,33 +1685,39 @@ void XMLCALL
 XML_SetElementDeclHandler(XML_Parser parser,
                           XML_ElementDeclHandler eldecl)
 {
-  elementDeclHandler = eldecl;
+  if (parser != NULL)
+    elementDeclHandler = eldecl;
 }
 
 void XMLCALL
 XML_SetAttlistDeclHandler(XML_Parser parser,
                           XML_AttlistDeclHandler attdecl)
 {
-  attlistDeclHandler = attdecl;
+  if (parser != NULL)
+    attlistDeclHandler = attdecl;
 }
 
 void XMLCALL
 XML_SetEntityDeclHandler(XML_Parser parser,
                          XML_EntityDeclHandler handler)
 {
-  entityDeclHandler = handler;
+  if (parser != NULL)
+    entityDeclHandler = handler;
 }
 
 void XMLCALL
 XML_SetXmlDeclHandler(XML_Parser parser,
                       XML_XmlDeclHandler handler) {
-  xmlDeclHandler = handler;
+  if (parser != NULL)
+    xmlDeclHandler = handler;
 }
 
 int XMLCALL
 XML_SetParamEntityParsing(XML_Parser parser,
                           enum XML_ParamEntityParsing peParsing)
 {
+  if (parser == NULL)
+    return 0;
   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
     return 0;
@@ -1523,6 +1733,10 @@ int XMLCALL
 XML_SetHashSalt(XML_Parser parser,
                 unsigned long hash_salt)
 {
+  if (parser == NULL)
+    return 0;
+  if (parser->m_parentParser)
+    return XML_SetHashSalt(parser->m_parentParser, hash_salt);
   /* block after XML_Parse()/XML_ParseBuffer() has been called */
   if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
     return 0;
@@ -1533,6 +1747,10 @@ XML_SetHashSalt(XML_Parser parser,
 enum XML_Status XMLCALL
 XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
 {
+  if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
+    errorCode = XML_ERROR_INVALID_ARGUMENT;
+    return XML_STATUS_ERROR;
+  }
   switch (ps_parsing) {
   case XML_SUSPENDED:
     errorCode = XML_ERROR_SUSPENDED;
@@ -1585,6 +1803,13 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
     const char *end;
     int nLeftOver;
     enum XML_Status result;
+    /* Detect overflow (a+b > MAX <==> b > MAX-a) */
+    if (len > ((XML_Size)-1) / 2 - parseEndByteIndex) {
+       errorCode = XML_ERROR_NO_MEMORY;
+       eventPtr = eventEndPtr = NULL;
+       processor = errorProcessor;
+       return XML_STATUS_ERROR;
+    }
     parseEndByteIndex += len;
     positionPtr = s;
     ps_finalBuffer = (XML_Bool)isFinal;
@@ -1617,11 +1842,14 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
     nLeftOver = s + len - end;
     if (nLeftOver) {
       if (buffer == NULL || nLeftOver > bufferLim - buffer) {
-        /* FIXME avoid integer overflow */
-        char *temp;
-        temp = (buffer == NULL
-                ? (char *)MALLOC(len * 2)
-                : (char *)REALLOC(buffer, len * 2));
+        /* avoid _signed_ integer overflow */
+        char *temp = NULL;
+        const int bytesToAllocate = (int)((unsigned)len * 2U);
+        if (bytesToAllocate > 0) {
+          temp = (buffer == NULL
+                ? (char *)MALLOC(bytesToAllocate)
+                : (char *)REALLOC(buffer, bytesToAllocate));
+        }
         if (temp == NULL) {
           errorCode = XML_ERROR_NO_MEMORY;
           eventPtr = eventEndPtr = NULL;
@@ -1629,7 +1857,7 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
           return XML_STATUS_ERROR;
         }
         buffer = temp;
-        bufferLim = buffer + len * 2;
+        bufferLim = buffer + bytesToAllocate;
       }
       memcpy(buffer, end, nLeftOver);
     }
@@ -1659,6 +1887,8 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
   const char *start;
   enum XML_Status result = XML_STATUS_OK;
 
+  if (parser == NULL)
+    return XML_STATUS_ERROR;
   switch (ps_parsing) {
   case XML_SUSPENDED:
     errorCode = XML_ERROR_SUSPENDED;
@@ -1712,6 +1942,8 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
 void * XMLCALL
 XML_GetBuffer(XML_Parser parser, int len)
 {
+  if (parser == NULL)
+    return NULL;
   if (len < 0) {
     errorCode = XML_ERROR_NO_MEMORY;
     return NULL;
@@ -1808,6 +2040,8 @@ XML_GetBuffer(XML_Parser parser, int len)
 enum XML_Status XMLCALL
 XML_StopParser(XML_Parser parser, XML_Bool resumable)
 {
+  if (parser == NULL)
+    return XML_STATUS_ERROR;
   switch (ps_parsing) {
   case XML_SUSPENDED:
     if (resumable) {
@@ -1840,6 +2074,8 @@ XML_ResumeParser(XML_Parser parser)
 {
   enum XML_Status result = XML_STATUS_OK;
 
+  if (parser == NULL)
+    return XML_STATUS_ERROR;
   if (ps_parsing != XML_SUSPENDED) {
     errorCode = XML_ERROR_NOT_SUSPENDED;
     return XML_STATUS_ERROR;
@@ -1876,6 +2112,8 @@ XML_ResumeParser(XML_Parser parser)
 void XMLCALL
 XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
 {
+  if (parser == NULL)
+    return;
   assert(status != NULL);
   *status = parser->m_parsingStatus;
 }
@@ -1883,20 +2121,26 @@ XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
 enum XML_Error XMLCALL
 XML_GetErrorCode(XML_Parser parser)
 {
+  if (parser == NULL)
+    return XML_ERROR_INVALID_ARGUMENT;
   return errorCode;
 }
 
 XML_Index XMLCALL
 XML_GetCurrentByteIndex(XML_Parser parser)
 {
+  if (parser == NULL)
+    return -1;
   if (eventPtr)
-    return parseEndByteIndex - (parseEndPtr - eventPtr);
+    return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr));
   return -1;
 }
 
 int XMLCALL
 XML_GetCurrentByteCount(XML_Parser parser)
 {
+  if (parser == NULL)
+    return 0;
   if (eventEndPtr && eventPtr)
     return (int)(eventEndPtr - eventPtr);
   return 0;
@@ -1906,11 +2150,19 @@ const char * XMLCALL
 XML_GetInputContext(XML_Parser parser, int *offset, int *size)
 {
 #ifdef XML_CONTEXT_BYTES
+  if (parser == NULL)
+    return NULL;
   if (eventPtr && buffer) {
-    *offset = (int)(eventPtr - buffer);
-    *size   = (int)(bufferEnd - buffer);
+    if (offset != NULL)
+      *offset = (int)(eventPtr - buffer);
+    if (size != NULL)
+      *size   = (int)(bufferEnd - buffer);
     return buffer;
   }
+#else
+  (void)parser;
+  (void)offset;
+  (void)size;
 #endif /* defined XML_CONTEXT_BYTES */
   return (char *) 0;
 }
@@ -1918,6 +2170,8 @@ XML_GetInputContext(XML_Parser parser, int *offset, int *size)
 XML_Size XMLCALL
 XML_GetCurrentLineNumber(XML_Parser parser)
 {
+  if (parser == NULL)
+    return 0;
   if (eventPtr && eventPtr >= positionPtr) {
     XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
     positionPtr = eventPtr;
@@ -1928,6 +2182,8 @@ XML_GetCurrentLineNumber(XML_Parser parser)
 XML_Size XMLCALL
 XML_GetCurrentColumnNumber(XML_Parser parser)
 {
+  if (parser == NULL)
+    return 0;
   if (eventPtr && eventPtr >= positionPtr) {
     XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
     positionPtr = eventPtr;
@@ -1938,30 +2194,38 @@ XML_GetCurrentColumnNumber(XML_Parser parser)
 void XMLCALL
 XML_FreeContentModel(XML_Parser parser, XML_Content *model)
 {
-  FREE(model);
+  if (parser != NULL)
+    FREE(model);
 }
 
 void * XMLCALL
 XML_MemMalloc(XML_Parser parser, size_t size)
 {
+  if (parser == NULL)
+    return NULL;
   return MALLOC(size);
 }
 
 void * XMLCALL
 XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
 {
+  if (parser == NULL)
+    return NULL;
   return REALLOC(ptr, size);
 }
 
 void XMLCALL
 XML_MemFree(XML_Parser parser, void *ptr)
 {
-  FREE(ptr);
+  if (parser != NULL)
+    FREE(ptr);
 }
 
 void XMLCALL
 XML_DefaultCurrent(XML_Parser parser)
 {
+  if (parser == NULL)
+    return;
   if (defaultHandler) {
     if (openInternalEntities)
       reportDefault(parser,
@@ -2468,7 +2732,7 @@ doContent(XML_Parser parser,
                        &fromPtr, rawNameEnd,
                        (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
             convLen = (int)(toPtr - (XML_Char *)tag->buf);
-            if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
+            if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
               tag->name.strLen = convLen;
               break;
             }
@@ -2511,8 +2775,10 @@ doContent(XML_Parser parser,
           return XML_ERROR_NO_MEMORY;
         poolFinish(&tempPool);
         result = storeAtts(parser, enc, s, &name, &bindings);
-        if (result)
+        if (result != XML_ERROR_NONE) {
+          freeBindings(parser, bindings);
           return result;
+        }
         poolFinish(&tempPool);
         if (startElementHandler) {
           startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
@@ -2527,15 +2793,7 @@ doContent(XML_Parser parser,
         if (noElmHandlers && defaultHandler)
           reportDefault(parser, enc, s, next);
         poolClear(&tempPool);
-        while (bindings) {
-          BINDING *b = bindings;
-          if (endNamespaceDeclHandler)
-            endNamespaceDeclHandler(handlerArg, b->prefix->name);
-          bindings = bindings->nextTagBinding;
-          b->nextTagBinding = freeBindingList;
-          freeBindingList = b;
-          b->prefix->binding = b->prevPrefixBinding;
-        }
+        freeBindings(parser, bindings);
       }
       if (tagLevel == 0)
         return epilogProcessor(parser, next, end, nextPtr);
@@ -2733,6 +2991,29 @@ doContent(XML_Parser parser,
   /* not reached */
 }
 
+/* This function does not call free() on the allocated memory, merely
+ * moving it to the parser's freeBindingList where it can be freed or
+ * reused as appropriate.
+ */
+static void
+freeBindings(XML_Parser parser, BINDING *bindings)
+{
+  while (bindings) {
+    BINDING *b = bindings;
+
+    /* startNamespaceDeclHandler will have been called for this
+     * binding in addBindings(), so call the end handler now.
+     */
+    if (endNamespaceDeclHandler)
+        endNamespaceDeclHandler(handlerArg, b->prefix->name);
+
+    bindings = bindings->nextTagBinding;
+    b->nextTagBinding = freeBindingList;
+    freeBindingList = b;
+    b->prefix->binding = b->prevPrefixBinding;
+  }
+}
+
 /* Precondition: all arguments must be non-NULL;
    Purpose:
    - normalize attributes
@@ -2957,7 +3238,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
       if (s[-1] == 2) {  /* prefixed */
         ATTRIBUTE_ID *id;
         const BINDING *b;
-        unsigned long uriHash = hash_secret_salt;
+        unsigned long uriHash;
+        struct siphash sip_state;
+        struct sipkey sip_key;
+
+        copy_salt_to_sipkey(parser, &sip_key);
+        sip24_init(&sip_state, &sip_key);
+
         ((XML_Char *)s)[-1] = 0;  /* clear flag */
         id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
         if (!id || !id->prefix)
@@ -2966,22 +3253,26 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
         if (!b)
           return XML_ERROR_UNBOUND_PREFIX;
 
-        /* as we expand the name we also calculate its hash value */
         for (j = 0; j < b->uriLen; j++) {
           const XML_Char c = b->uri[j];
           if (!poolAppendChar(&tempPool, c))
             return XML_ERROR_NO_MEMORY;
-          uriHash = CHAR_HASH(uriHash, c);
         }
+
+        sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
+
         while (*s++ != XML_T(ASCII_COLON))
           ;
+
+        sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
+
         do {  /* copies null terminator */
-          const XML_Char c = *s;
           if (!poolAppendChar(&tempPool, *s))
             return XML_ERROR_NO_MEMORY;
-          uriHash = CHAR_HASH(uriHash, c);
         } while (*s++);
 
+        uriHash = (unsigned long)sip24_final(&sip_state);
+
         { /* Check hash table for duplicate of expanded name (uriName).
              Derived from code in lookup(parser, HASH_TABLE *table, ...).
           */
@@ -3695,6 +3986,14 @@ entityValueInitProcessor(XML_Parser parser,
       *nextPtr = next;
       return XML_ERROR_NONE;
     }
+    /* If we get this token, we have the start of what might be a
+       normal tag, but not a declaration (i.e. it doesn't begin with
+       "<!").  In a DTD context, that isn't legal.
+    */
+    else if (tok == XML_TOK_INSTANCE_START) {
+      *nextPtr = next;
+      return XML_ERROR_SYNTAX;
+    }
     start = next;
     eventPtr = start;
   }
@@ -4871,6 +5170,8 @@ processInternalEntity(XML_Parser parser, ENTITY *entity,
   openEntity->internalEventEndPtr = NULL;
   textStart = (char *)entity->textPtr;
   textEnd = (char *)(entity->textPtr + entity->textLen);
+  /* Set a safe default value in case 'next' does not get set */
+  next = textStart;
 
 #ifdef XML_DTD
   if (entity->is_param) {
@@ -4916,6 +5217,8 @@ internalEntityProcessor(XML_Parser parser,
   entity = openEntity->entity;
   textStart = ((char *)entity->textPtr) + entity->processed;
   textEnd = (char *)(entity->textPtr + entity->textLen);
+  /* Set a safe default value in case 'next' does not get set */
+  next = textStart;
 
 #ifdef XML_DTD
   if (entity->is_param) {
@@ -5876,7 +6179,6 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_H
       newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
           ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
       if (!newE->defaultAtts) {
-        ms->free_fcn(newE);
         return 0;
       }
     }
@@ -6011,13 +6313,32 @@ keyeq(KEY s1, KEY s2)
   return XML_FALSE;
 }
 
+static size_t
+keylen(KEY s)
+{
+  size_t len = 0;
+  for (; *s; s++, len++);
+  return len;
+}
+
+static void
+copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key)
+{
+  key->k[0] = 0;
+  key->k[1] = get_hash_secret_salt(parser);
+}
+
 static unsigned long FASTCALL
 hash(XML_Parser parser, KEY s)
 {
-  unsigned long h = hash_secret_salt;
-  while (*s)
-    h = CHAR_HASH(h, *s++);
-  return h;
+  struct siphash state;
+  struct sipkey key;
+  (void)sip_tobin;
+  (void)sip24_valid;
+  copy_salt_to_sipkey(parser, &key);
+  sip24_init(&state, &key);
+  sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
+  return (unsigned long)sip24_final(&state);
 }
 
 static NAMED *
@@ -6260,6 +6581,35 @@ poolStoreString(STRING_POOL *pool, const ENCODING *enc,
   return pool->start;
 }
 
+static size_t
+poolBytesToAllocateFor(int blockSize)
+{
+  /* Unprotected math would be:
+  ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
+  **
+  ** Detect overflow, avoiding _signed_ overflow undefined behavior
+  ** For a + b * c we check b * c in isolation first, so that addition of a
+  ** on top has no chance of making us accept a small non-negative number
+  */
+  const size_t stretch = sizeof(XML_Char);  /* can be 4 bytes */
+
+  if (blockSize <= 0)
+    return 0;
+
+  if (blockSize > (int)(INT_MAX / stretch))
+    return 0;
+
+  {
+    const int stretchedBlockSize = blockSize * (int)stretch;
+    const int bytesToAllocate = (int)(
+        offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
+    if (bytesToAllocate < 0)
+      return 0;
+
+    return (size_t)bytesToAllocate;
+  }
+}
+
 static XML_Bool FASTCALL
 poolGrow(STRING_POOL *pool)
 {
@@ -6289,14 +6639,17 @@ poolGrow(STRING_POOL *pool)
   if (pool->blocks && pool->start == pool->blocks->s) {
     BLOCK *temp;
     int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
+    size_t bytesToAllocate;
 
     if (blockSize < 0)
       return XML_FALSE;
 
+    bytesToAllocate = poolBytesToAllocateFor(blockSize);
+    if (bytesToAllocate == 0)
+      return XML_FALSE;
+
     temp = (BLOCK *)
-      pool->mem->realloc_fcn(pool->blocks,
-                             (offsetof(BLOCK, s)
-                              + blockSize * sizeof(XML_Char)));
+      pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate);
     if (temp == NULL)
       return XML_FALSE;
     pool->blocks = temp;
@@ -6308,16 +6661,26 @@ poolGrow(STRING_POOL *pool)
   else {
     BLOCK *tem;
     int blockSize = (int)(pool->end - pool->start);
+    size_t bytesToAllocate;
 
     if (blockSize < 0)
       return XML_FALSE;
 
     if (blockSize < INIT_BLOCK_SIZE)
       blockSize = INIT_BLOCK_SIZE;
-    else
+    else {
+      /* Detect overflow, avoiding _signed_ overflow undefined behavior */
+      if ((int)((unsigned)blockSize * 2U) < 0) {
+        return XML_FALSE;
+      }
       blockSize *= 2;
-    tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
-                                        + blockSize * sizeof(XML_Char));
+    }
+
+    bytesToAllocate = poolBytesToAllocateFor(blockSize);
+    if (bytesToAllocate == 0)
+      return XML_FALSE;
+
+    tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
     if (!tem)
       return XML_FALSE;
     tem->size = blockSize;
diff --git a/Utilities/cmexpat/lib/xmlrole.c b/Utilities/cmexpat/lib/xmlrole.c
index 4e79ffd..a7c5630 100644
--- a/Utilities/cmexpat/lib/xmlrole.c
+++ b/Utilities/cmexpat/lib/xmlrole.c
@@ -4,19 +4,13 @@
 
 #include <stddef.h>
 
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
 #include "winconfig.h"
-#elif defined(MACOS_CLASSIC)
-#include "macconfig.h"
-#elif defined(__amigaos__)
-#include "amigaconfig.h"
-#elif defined(__WATCOMC__)
-#include "watcomconfig.h"
 #else
 #ifdef HAVE_EXPAT_CONFIG_H
 #include <expat_config.h>
 #endif
-#endif /* ndef COMPILING_FOR_WINDOWS */
+#endif /* ndef _WIN32 */
 
 #include "expat_external.h"
 #include "internal.h"
diff --git a/Utilities/cmexpat/lib/xmltok.c b/Utilities/cmexpat/lib/xmltok.c
index 4195279..cdf0720 100644
--- a/Utilities/cmexpat/lib/xmltok.c
+++ b/Utilities/cmexpat/lib/xmltok.c
@@ -4,19 +4,13 @@
 
 #include <stddef.h>
 
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
 #include "winconfig.h"
-#elif defined(MACOS_CLASSIC)
-#include "macconfig.h"
-#elif defined(__amigaos__)
-#include "amigaconfig.h"
-#elif defined(__WATCOMC__)
-#include "watcomconfig.h"
 #else
 #ifdef HAVE_EXPAT_CONFIG_H
 #include <expat_config.h>
 #endif
-#endif /* ndef COMPILING_FOR_WINDOWS */
+#endif /* ndef _WIN32 */
 
 #include "expat_external.h"
 #include "internal.h"
@@ -369,24 +363,24 @@ utf8_toUtf8(const ENCODING *UNUSED_P(enc),
             const char **fromP, const char *fromLim,
             char **toP, const char *toLim)
 {
-  enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
   char *to;
   const char *from;
-  if (fromLim - *fromP > toLim - *toP) {
-    /* Avoid copying partial characters. */
-    res = XML_CONVERT_OUTPUT_EXHAUSTED;
-    fromLim = *fromP + (toLim - *toP);
-    align_limit_to_full_utf8_characters(*fromP, &fromLim);
-  }
+  const char *fromLimInitial = fromLim;
+
+  /* Avoid copying partial characters. */
+  align_limit_to_full_utf8_characters(*fromP, &fromLim);
+
   for (to = *toP, from = *fromP; (from < fromLim) && (to < toLim); from++, to++)
     *to = *from;
   *fromP = from;
   *toP = to;
 
-  if ((to == toLim) && (from < fromLim))
+  if (fromLim < fromLimInitial)
+    return XML_CONVERT_INPUT_INCOMPLETE;
+  else if ((to == toLim) && (from < fromLim))
     return XML_CONVERT_OUTPUT_EXHAUSTED;
   else
-    return res;
+    return XML_CONVERT_COMPLETED;
 }
 
 static enum XML_Convert_Result PTRCALL
@@ -402,7 +396,7 @@ utf8_toUtf16(const ENCODING *enc,
     case BT_LEAD2:
       if (fromLim - from < 2) {
         res = XML_CONVERT_INPUT_INCOMPLETE;
-        break;
+        goto after;
       }
       *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
       from += 2;
@@ -410,7 +404,7 @@ utf8_toUtf16(const ENCODING *enc,
     case BT_LEAD3:
       if (fromLim - from < 3) {
         res = XML_CONVERT_INPUT_INCOMPLETE;
-        break;
+        goto after;
       }
       *to++ = (unsigned short)(((from[0] & 0xf) << 12)
                                | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f));
@@ -441,6 +435,8 @@ utf8_toUtf16(const ENCODING *enc,
       break;
     }
   }
+  if (from < fromLim)
+    res = XML_CONVERT_OUTPUT_EXHAUSTED;
 after:
   *fromP = from;
   *toP = to;
diff --git a/Utilities/cmexpat/lib/xmltok_impl.c b/Utilities/cmexpat/lib/xmltok_impl.c
index fd0ee22..5f779c0 100644
--- a/Utilities/cmexpat/lib/xmltok_impl.c
+++ b/Utilities/cmexpat/lib/xmltok_impl.c
@@ -1198,6 +1198,8 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr,
   const char *start;
   if (ptr >= end)
     return XML_TOK_NONE;
+  else if (! HAS_CHAR(enc, ptr, end))
+    return XML_TOK_PARTIAL;
   start = ptr;
   while (HAS_CHAR(enc, ptr, end)) {
     switch (BYTE_TYPE(enc, ptr)) {
@@ -1256,6 +1258,8 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr,
   const char *start;
   if (ptr >= end)
     return XML_TOK_NONE;
+  else if (! HAS_CHAR(enc, ptr, end))
+    return XML_TOK_PARTIAL;
   start = ptr;
   while (HAS_CHAR(enc, ptr, end)) {
     switch (BYTE_TYPE(enc, ptr)) {
diff --git a/Utilities/cmjsoncpp/CMakeLists.txt b/Utilities/cmjsoncpp/CMakeLists.txt
index d0114e7..bc9076e 100644
--- a/Utilities/cmjsoncpp/CMakeLists.txt
+++ b/Utilities/cmjsoncpp/CMakeLists.txt
@@ -24,3 +24,4 @@ include_directories(
 
 add_library(cmjsoncpp ${JSONCPP_SOURCES})
 target_link_libraries(cmjsoncpp ${CMake_KWIML_LIBRARIES})
+set_property(TARGET cmjsoncpp PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt
index 09bef51..bfe6b13 100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@ -17,13 +17,13 @@ SET(CMAKE_MACOSX_RPATH ON)
 #
 FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version)
 STRING(REGEX REPLACE
- "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version})
+ "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]*$" "\\1" _major ${_version})
 STRING(REGEX REPLACE
- "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version})
+ "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]*$" "\\1" _minor ${_version})
 STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version})
+ "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]*$" "\\1" _revision ${_version})
 STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version})
+ "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]*)$" "\\1" _quality ${_version})
 SET(_version_number ${_major}${_minor}${_revision})
 STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor})
 STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision})
@@ -71,13 +71,15 @@ include(CTest)
 
 OPTION(ENABLE_NETTLE "Enable use of Nettle" ON)
 OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
-OPTION(ENABLE_LZMA "Enable the use of the system found LZMA library if found" ON)
-OPTION(ENABLE_ZLIB "Enable the use of the system found ZLIB library if found" ON)
-OPTION(ENABLE_BZip2 "Enable the use of the system found BZip2 library if found" ON)
-OPTION(ENABLE_LIBXML2 "Enable the use of the system found libxml2 library if found" ON)
-OPTION(ENABLE_EXPAT "Enable the use of the system found EXPAT library if found" ON)
-OPTION(ENABLE_PCREPOSIX "Enable the use of the system found PCREPOSIX library if found" ON)
-OPTION(ENABLE_LibGCC "Enable the use of the system found LibGCC library if found" ON)
+OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF)
+OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON)
+
+OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON)
+OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON)
+OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON)
+OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON)
+OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON)
+OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON)
 # CNG is used for encrypt/decrypt Zip archives on Windows.
 OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON)
 
@@ -107,7 +109,7 @@ INCLUDE(CheckHeaderDirent)
 INCLUDE(CheckIncludeFile)
 INCLUDE(CheckIncludeFiles)
 INCLUDE(CheckLibraryExists)
-INCLUDE(CheckStructMember)
+INCLUDE(CheckStructHasMember)
 INCLUDE(CheckSymbolExists)
 INCLUDE(CheckTypeExists)
 INCLUDE(CheckTypeSize)
@@ -285,21 +287,20 @@ MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES)
 # Find LZMA
 #
 IF(ENABLE_LZMA)
-  FIND_PACKAGE(LZMA)
+  FIND_PACKAGE(LibLZMA)
 ELSE()
-  SET(LZMA_FOUND FALSE) # Override cached value
-  SET(LZMADEC_FOUND FALSE) # Override cached value
+  SET(LIBZMA_FOUND FALSE) # Override cached value
 ENDIF()
 
-IF(LZMA_FOUND)
+IF(LIBLZMA_FOUND)
   SET(HAVE_LIBLZMA 1)
   SET(HAVE_LZMA_H 1)
-  INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR})
-  LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES})
+  INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
+  LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES})
   IF(CMAKE_USE_SYSTEM_LIBLZMA)
     # Test if a macro is needed for the library.
     TRY_MACRO_FOR_LIBRARY(
-      "${LZMA_INCLUDE_DIR}" "${LZMA_LIBRARIES}"
+      "${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}"
       COMPILES
       "#include <lzma.h>\nint main() {return (int)lzma_version_number(); }"
       "WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC")
@@ -309,27 +310,26 @@ IF(LZMA_FOUND)
   ELSE()
     ADD_DEFINITIONS(-DLZMA_API_STATIC)
   ENDIF()
-ELSEIF(LZMADEC_FOUND)
-  SET(HAVE_LIBLZMADEC 1)
-  SET(HAVE_LZMADEC_H 1)
-  INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR})
-  LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES})
-ELSE(LZMA_FOUND)
+ELSE(LIBLZMA_FOUND)
 # LZMA not found and will not be used.
-ENDIF(LZMA_FOUND)
+ENDIF(LIBLZMA_FOUND)
 IF(0) # CMake does not need LZO2 support in libarchive
 #
 # Find LZO2
 #
-IF (LZO2_INCLUDE_DIR)
-  # Already in cache, be silent
-  SET(LZO2_FIND_QUIETLY TRUE)
-ENDIF (LZO2_INCLUDE_DIR)
-
-FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
-FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
+IF(ENABLE_LZO)
+  IF (LZO2_INCLUDE_DIR)
+    # Already in cache, be silent
+    SET(LZO2_FIND_QUIETLY TRUE)
+  ENDIF (LZO2_INCLUDE_DIR)
+
+  FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
+  FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
+  INCLUDE(FindPackageHandleStandardArgs)
+  FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
+ELSE(ENABLE_LZO)
+  SET(LIBZMA_FOUND FALSE) # Override cached value
+ENDIF(ENABLE_LZO)
 IF(LZO2_FOUND)
   SET(HAVE_LIBLZO2 1)
   SET(HAVE_LZO_LZOCONF_H 1)
@@ -415,6 +415,11 @@ LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H)
 LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H)
 LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H)
 LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H)
+
+CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
+#include <linux/fs.h>
+int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS)
+
 LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
 LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
 LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H)
@@ -459,7 +464,7 @@ IF(ENABLE_CNG)
 ELSE(ENABLE_CNG)
   UNSET(HAVE_BCRYPT_H CACHE)
 ENDIF(ENABLE_CNG)
-# Following files need windwos.h, so we should test it after windows.h test.
+# Following files need windows.h, so we should test it after windows.h test.
 LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H)
 LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H)
 
@@ -1005,6 +1010,14 @@ CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE)
 
 CMAKE_POP_CHECK_STATE()	# Restore the state of the variables
 
+CHECK_C_SOURCE_COMPILES(
+  "#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct vfsconf v; return sizeof(v);}"
+  HAVE_STRUCT_VFSCONF)
+
+CHECK_C_SOURCE_COMPILES(
+  "#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct xvfsconf v; return sizeof(v);}"
+  HAVE_STRUCT_XVFSCONF)
+
 # Make sure we have the POSIX version of readdir_r, not the
 # older 2-argument version.
 CHECK_C_SOURCE_COMPILES(
@@ -1030,6 +1043,10 @@ CHECK_C_SOURCE_COMPILES(
   "#include <sys/sysmacros.h>\nint main() { return major(256); }"
   MAJOR_IN_SYSMACROS)
 
+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)
+
 IF(HAVE_STRERROR_R)
   SET(HAVE_DECL_STRERROR_R 1)
 ENDIF(HAVE_STRERROR_R)
@@ -1063,47 +1080,47 @@ CHECK_SYMBOL_EXISTS(SSIZE_MAX        "limits.h"   HAVE_DECL_SSIZE_MAX)
 # Check struct members
 #
 # Check for tm_gmtoff in struct tm
-CHECK_STRUCT_MEMBER("struct tm" tm_gmtoff
+CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff
     "time.h" HAVE_STRUCT_TM_TM_GMTOFF)
-CHECK_STRUCT_MEMBER("struct tm" __tm_gmtoff
+CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff
     "time.h" HAVE_STRUCT_TM___TM_GMTOFF)
 
 # Check for f_namemax in struct statfs
-CHECK_STRUCT_MEMBER("struct statfs" f_namemax
+CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax
     "sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX)
 
 # Check for birthtime in struct stat
-CHECK_STRUCT_MEMBER("struct stat" st_birthtime
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime
     "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME)
 
 # Check for high-resolution timestamps in struct stat
-CHECK_STRUCT_MEMBER("struct stat" st_birthtimespec.tv_nsec
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtimespec.tv_nsec
     "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
-CHECK_STRUCT_MEMBER("struct stat" st_mtimespec.tv_nsec
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec
     "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
-CHECK_STRUCT_MEMBER("struct stat" st_mtim.tv_nsec
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec
     "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
-CHECK_STRUCT_MEMBER("struct stat" st_mtime_n
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_n
     "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N)
-CHECK_STRUCT_MEMBER("struct stat" st_umtime
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_umtime
     "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME)
-CHECK_STRUCT_MEMBER("struct stat" st_mtime_usec
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_usec
     "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC)
 # Check for block size support in struct stat
-CHECK_STRUCT_MEMBER("struct stat" st_blksize
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_blksize
     "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE)
 # Check for st_flags in struct stat (BSD fflags)
-CHECK_STRUCT_MEMBER("struct stat" st_flags
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_flags
     "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS)
 
 IF(HAVE_SYS_STATVFS_H)
-  CHECK_STRUCT_MEMBER("struct statvfs" f_iosize
+  CHECK_STRUCT_HAS_MEMBER("struct statvfs" f_iosize
     "sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE)
 ENDIF()
 
 #
 #
-CHECK_STRUCT_MEMBER("struct tm" tm_sec
+CHECK_STRUCT_HAS_MEMBER("struct tm" tm_sec
     "sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME)
 
 #
@@ -1323,16 +1340,36 @@ IF(ENABLE_ACL)
   # test for specific permissions in a permset.)  Linux uses the obvious
   # name, FreeBSD adds _np to mark it as "non-Posix extension."
   # Test for both as a double-check that we really have POSIX-style ACL support.
+  CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP)
   CHECK_FUNCTION_EXISTS(acl_get_perm HAVE_ACL_GET_PERM)
   CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
   CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK)
   CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
   CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
   CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
+  CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "${INCLUDES}" HAVE_ACL_TYPE_NFS4)
 
   # MacOS has an acl.h that isn't POSIX.  It can be detected by
   # checking for ACL_USER
   CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_ACL_USER)
+  CHECK_C_SOURCE_COMPILES("#include <sys/types.h>
+#include <sys/acl.h>
+int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED)
+
+  # Solaris and derivates ACLs
+  CHECK_LIBRARY_EXISTS(sec "acl_get" "" HAVE_LIBSEC)
+  IF(HAVE_LIBSEC)
+    SET(CMAKE_REQUIRED_LIBRARIES "sec")
+    FIND_LIBRARY(SEC_LIBRARY NAMES sec)
+    LIST(APPEND ADDITIONAL_LIBS ${SEC_LIBRARY})
+  ENDIF(HAVE_LIBSEC)
+  #
+  CHECK_TYPE_EXISTS(aclent_t "${INCLUDES}" HAVE_ACLENT_T)
+  CHECK_TYPE_EXISTS(ace_t "${INCLUDES}" HAVE_ACE_T)
+  CHECK_FUNCTION_EXISTS(acl_get HAVE_FACL_GET)
+  CHECK_FUNCTION_EXISTS(facl_get HAVE_FACL_GET)
+  CHECK_FUNCTION_EXISTS(acl_set HAVE_FACL_SET)
+  CHECK_FUNCTION_EXISTS(facl_set HAVE_FACL_SET)
 ELSE(ENABLE_ACL)
   # If someone runs cmake, then disables ACL support, we need
   # to forcibly override the cached values for these.
@@ -1347,7 +1384,15 @@ ELSE(ENABLE_ACL)
   SET(HAVE_ACL_SET_FD FALSE)
   SET(HAVE_ACL_SET_FD_NP FALSE)
   SET(HAVE_ACL_SET_FILE FALSE)
+  SET(HAVE_ACL_TYPE_NFS4 FALSE)
   SET(HAVE_ACL_USER FALSE)
+  SET(HAVE_ACL_TYPE_EXTENDED FALSE)
+  SET(HAVE_ACL_GET FALSE)
+  SET(HAVE_ACLENT_T FALSE)
+  SET(HAVE_ACE_T FALSE)
+  SET(HAVE_FACL_GET FALSE)
+  SET(HAVE_ACL_SET FALSE)
+  SET(HAVE_FACL_SET FALSE)
 ENDIF(ENABLE_ACL)
 
 #
diff --git a/Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake b/Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake
deleted file mode 100644
index 05ddb3a..0000000
--- a/Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake
+++ /dev/null
@@ -1,43 +0,0 @@
-# - Check if the given struct or class has the specified member variable
-# CHECK_STRUCT_MEMBER (STRUCT MEMBER HEADER VARIABLE)
-#
-#  STRUCT - the name of the struct or class you are interested in
-#  MEMBER - the member which existence you want to check
-#  HEADER - the header(s) where the prototype should be declared
-#  VARIABLE - variable to store the result
-#
-# The following variables may be set before calling this macro to
-# modify the way the check is run:
-#
-#  CMAKE_REQUIRED_FLAGS = string of compile command line flags
-#  CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
-#  CMAKE_REQUIRED_INCLUDES = list of include directories
-
-# Copyright (c) 2006, Alexander Neundorf, <neundorf at kde.org>
-#
-# Redistribution and use is allowed according to the terms of the BSD license.
-# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
-
-
-INCLUDE(CheckCSourceCompiles)
-
-MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
-   SET(_INCLUDE_FILES)
-   FOREACH (it ${_HEADER})
-      SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
-   ENDFOREACH (it)
-
-   SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE "
-${_INCLUDE_FILES}
-int main()
-{
-   static ${_STRUCT} tmp;
-   if (sizeof(tmp.${_MEMBER}))
-      return 0;
-  return 0;
-}
-")
-   CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
-
-ENDMACRO (CHECK_STRUCT_MEMBER)
-
diff --git a/Utilities/cmlibarchive/build/cmake/FindLZMA.cmake b/Utilities/cmlibarchive/build/cmake/FindLZMA.cmake
deleted file mode 100644
index 0b46b2c..0000000
--- a/Utilities/cmlibarchive/build/cmake/FindLZMA.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-# - Find lzma and lzmadec
-# Find the native LZMA includes and library
-#
-#  LZMA_INCLUDE_DIR    - where to find lzma.h, etc.
-#  LZMA_LIBRARIES      - List of libraries when using liblzma.
-#  LZMA_FOUND          - True if liblzma found.
-#  LZMADEC_INCLUDE_DIR - where to find lzmadec.h, etc.
-#  LZMADEC_LIBRARIES   - List of libraries when using liblzmadec.
-#  LZMADEC_FOUND       - True if liblzmadec found.
-
-IF (LZMA_INCLUDE_DIR)
-  # Already in cache, be silent
-  SET(LZMA_FIND_QUIETLY TRUE)
-ENDIF (LZMA_INCLUDE_DIR)
-
-FIND_PATH(LZMA_INCLUDE_DIR lzma.h)
-FIND_LIBRARY(LZMA_LIBRARY NAMES lzma liblzma)
-
-# handle the QUIETLY and REQUIRED arguments and set LZMA_FOUND to TRUE if 
-# all listed variables are TRUE
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMA DEFAULT_MSG LZMA_LIBRARY LZMA_INCLUDE_DIR)
-
-IF(LZMA_FOUND)
-  SET( LZMA_LIBRARIES ${LZMA_LIBRARY} )
-ELSE(LZMA_FOUND)
-  SET( LZMA_LIBRARIES )
-
-  IF (LZMADEC_INCLUDE_DIR)
-    # Already in cache, be silent
-    SET(LZMADEC_FIND_QUIETLY TRUE)
-  ENDIF (LZMADEC_INCLUDE_DIR)
-
-  FIND_PATH(LZMADEC_INCLUDE_DIR lzmadec.h)
-  FIND_LIBRARY(LZMADEC_LIBRARY NAMES lzmadec )
-
-  # handle the QUIETLY and REQUIRED arguments and set LZMADEC_FOUND to TRUE if 
-  # all listed variables are TRUE
-  INCLUDE(FindPackageHandleStandardArgs)
-  FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMADEC DEFAULT_MSG LZMADEC_LIBRARY
-    LZMADEC_INCLUDE_DIR)
-
-  IF(LZMADEC_FOUND)
-    SET( LZMADEC_LIBRARIES ${LZMADEC_LIBRARY} )
-  ELSE(LZMADEC_FOUND)
-    SET( LZMADEC_LIBRARIES )
-  ENDIF(LZMADEC_FOUND)
-ENDIF(LZMA_FOUND)
diff --git a/Utilities/cmlibarchive/build/cmake/config.h.in b/Utilities/cmlibarchive/build/cmake/config.h.in
index 9843875..55e04b9 100644
--- a/Utilities/cmlibarchive/build/cmake/config.h.in
+++ b/Utilities/cmlibarchive/build/cmake/config.h.in
@@ -296,6 +296,9 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if you have the `acl_create_entry' function. */
 #cmakedefine HAVE_ACL_CREATE_ENTRY 1
 
+/* Define to 1 if you have the `acl_get_fd_np' function. */
+#cmakedefine HAVE_ACL_GET_FD_NP 1
+
 /* Define to 1 if you have the `acl_get_link' function. */
 #cmakedefine HAVE_ACL_GET_LINK 1
 
@@ -326,6 +329,12 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if you have the `acl_set_file' function. */
 #cmakedefine HAVE_ACL_SET_FILE 1
 
+/* True for FreeBSD with NFSv4 ACL support */
+#cmakedefine HAVE_ACL_TYPE_NFS4 1
+
+/* True for MacOS ACL support */
+#cmakedefine HAVE_ACL_TYPE_EXTENDED 1
+
 /* True for systems with POSIX ACL support */
 #cmakedefine HAVE_ACL_USER 1
 
@@ -727,6 +736,9 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if you have the <lzma.h> header file. */
 #cmakedefine HAVE_LZMA_H 1
 
+/* Define to 1 if you have a working `lzma_stream_encoder_mt' function. */
+#cmakedefine HAVE_LZMA_STREAM_ENCODER_MT 1
+
 /* Define to 1 if you have the <lzo/lzo1x.h> header file. */
 #cmakedefine HAVE_LZO_LZO1X_H 1
 
@@ -929,6 +941,12 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
 #cmakedefine HAVE_STRUCT_TM___TM_GMTOFF 1
 
+/* Define to 1 if you have `struct vfsconf'. */
+#cmakedefine HAVE_STRUCT_VFSCONF 1
+
+/* Define to 1 if you have `struct xvfsconf'. */
+#cmakedefine HAVE_STRUCT_XVFSCONF 1
+
 /* Define to 1 if you have the `symlink' function. */
 #cmakedefine HAVE_SYMLINK 1
 
@@ -1087,6 +1105,9 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if you have a working EXT2_IOC_GETFLAGS */
 #cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1
 
+/* Define to 1 if you have a working FS_IOC_GETFLAGS */
+#cmakedefine HAVE_WORKING_FS_IOC_GETFLAGS 1
+
 /* Define to 1 if you have the <zlib.h> header file. */
 #cmakedefine HAVE_ZLIB_H 1
 
diff --git a/Utilities/cmlibarchive/build/version b/Utilities/cmlibarchive/build/version
index f293156..ef83457 100644
--- a/Utilities/cmlibarchive/build/version
+++ b/Utilities/cmlibarchive/build/version
@@ -1 +1 @@
-3002001
+3003001
diff --git a/Utilities/cmlibarchive/libarchive/CMakeLists.txt b/Utilities/cmlibarchive/libarchive/CMakeLists.txt
index eaa7b20..d412c80 100644
--- a/Utilities/cmlibarchive/libarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/libarchive/CMakeLists.txt
@@ -168,15 +168,33 @@ SET(libarchive_MANS
   archive_entry_time.3
   archive_read.3
   archive_read_add_passphrase.3
+  archive_read_data.3
   archive_read_disk.3
+  archive_read_extract.3
+  archive_read_filter.3
+  archive_read_format.3
+  archive_read_free.3
+  archive_read_header.3
+  archive_read_new.3
+  archive_read_open.3
   archive_read_set_options.3
   archive_util.3
   archive_write.3
+  archive_write_blocksize.3
+  archive_write_data.3
   archive_write_disk.3
+  archive_write_filter.3
+  archive_write_finish_entry.3
+  archive_write_format.3
+  archive_write_free.3
+  archive_write_header.3
+  archive_write_new.3
+  archive_write_open.3
   archive_write_set_options.3
   archive_write_set_passphrase.3
   cpio.5
   libarchive.3
+  libarchive_changes.3
   libarchive_internals.3
   libarchive-formats.5
   mtree.5
diff --git a/Utilities/cmlibarchive/libarchive/archive.h b/Utilities/cmlibarchive/libarchive/archive.h
index 3b5104b..cfb5c48 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 3002001
+#define	ARCHIVE_VERSION_NUMBER 3003001
 
 #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.2.1"
+#define	ARCHIVE_VERSION_ONLY_STRING "3.3.1"
 #define	ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
 __LA_DECL const char *	archive_version_string(void);
 
@@ -370,7 +370,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
  *   4) Repeatedly call archive_read_next_header to get information about
  *      successive archive entries.  Call archive_read_data to extract
  *      data for entries of interest.
- *   5) Call archive_read_finish to end processing.
+ *   5) Call archive_read_free to end processing.
  */
 __LA_DECL struct archive	*archive_read_new(void);
 
@@ -559,7 +559,7 @@ __LA_DECL la_int64_t		 archive_read_header_position(struct archive *);
  * we cannot say whether there are encrypted entries, then
  * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
  * In general, this function will return values below zero when the
- * reader is uncertain or totally uncapable of encryption support.
+ * reader is uncertain or totally incapable of encryption support.
  * When this function returns 0 you can be sure that the reader
  * supports encryption detection but no encrypted entries have
  * been found yet.
@@ -981,12 +981,12 @@ __LA_DECL int	archive_read_disk_can_descend(struct archive *);
 __LA_DECL int	archive_read_disk_current_filesystem(struct archive *);
 __LA_DECL int	archive_read_disk_current_filesystem_is_synthetic(struct archive *);
 __LA_DECL int	archive_read_disk_current_filesystem_is_remote(struct archive *);
-/* Request that the access time of the entry visited by travesal be restored. */
+/* Request that the access time of the entry visited by traversal be restored. */
 __LA_DECL int  archive_read_disk_set_atime_restored(struct archive *);
 /*
  * Set behavior. The "flags" argument selects optional behavior.
  */
-/* Request that the access time of the entry visited by travesal be restored.
+/* Request that the access time of the entry visited by traversal be restored.
  * This is the same as archive_read_disk_set_atime_restored. */
 #define	ARCHIVE_READDISK_RESTORE_ATIME		(0x0001)
 /* Default: Do not skip an entry which has nodump flags. */
@@ -998,6 +998,10 @@ __LA_DECL int  archive_read_disk_set_atime_restored(struct archive *);
 #define	ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS	(0x0008)
 /* Default: Xattrs are read from disk. */
 #define	ARCHIVE_READDISK_NO_XATTR		(0x0010)
+/* Default: ACLs are read from disk. */
+#define	ARCHIVE_READDISK_NO_ACL			(0x0020)
+/* Default: File flags are read from disk. */
+#define	ARCHIVE_READDISK_NO_FFLAGS		(0x0040)
 
 __LA_DECL int  archive_read_disk_set_behavior(struct archive *,
 		    int flags);
@@ -1121,7 +1125,7 @@ __LA_DECL int	archive_match_time_excluded(struct archive *,
 
 /*
  * Flags to tell a matching type of time stamps. These are used for
- * following functinos.
+ * following functions.
  */
 /* Time flag: mtime to be tested. */
 #define ARCHIVE_MATCH_MTIME	(0x0100)
@@ -1141,7 +1145,7 @@ __LA_DECL int	archive_match_include_date(struct archive *, int _flag,
 		    const char *_datestr);
 __LA_DECL int	archive_match_include_date_w(struct archive *, int _flag,
 		    const wchar_t *_datestr);
-/* Set inclusion time by a particluar file. */
+/* Set inclusion time by a particular file. */
 __LA_DECL int	archive_match_include_file_time(struct archive *,
 		    int _flag, const char *_pathname);
 __LA_DECL int	archive_match_include_file_time_w(struct archive *,
diff --git a/Utilities/cmlibarchive/libarchive/archive_acl.c b/Utilities/cmlibarchive/libarchive/archive_acl.c
index bf4b610..b8b6b63 100644
--- a/Utilities/cmlibarchive/libarchive/archive_acl.c
+++ b/Utilities/cmlibarchive/libarchive/archive_acl.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2003-2010 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,25 +56,77 @@ static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl,
 static int	archive_acl_add_entry_len_l(struct archive_acl *acl,
 		    int type, int permset, int tag, int id, const char *name,
 		    size_t len, struct archive_string_conv *sc);
+static int	archive_acl_text_want_type(struct archive_acl *acl, int flags);
+static ssize_t	archive_acl_text_len(struct archive_acl *acl, int want_type,
+		    int flags, int wide, struct archive *a,
+		    struct archive_string_conv *sc);
 static int	isint_w(const wchar_t *start, const wchar_t *end, int *result);
 static int	ismode_w(const wchar_t *start, const wchar_t *end, int *result);
+static int	is_nfs4_flags_w(const wchar_t *start, const wchar_t *end,
+		    int *result);
+static int	is_nfs4_perms_w(const wchar_t *start, const wchar_t *end,
+		    int *result);
 static void	next_field_w(const wchar_t **wp, const wchar_t **start,
 		    const wchar_t **end, wchar_t *sep);
-static int	prefix_w(const wchar_t *start, const wchar_t *end,
-		    const wchar_t *test);
-static void	append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
-		    const wchar_t *wname, int perm, int id);
+static void	append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+		    int tag, int flags, const wchar_t *wname, int perm, int id);
 static void	append_id_w(wchar_t **wp, int id);
 static int	isint(const char *start, const char *end, int *result);
 static int	ismode(const char *start, const char *end, int *result);
+static int	is_nfs4_flags(const char *start, const char *end,
+		    int *result);
+static int	is_nfs4_perms(const char *start, const char *end,
+		    int *result);
 static void	next_field(const char **p, const char **start,
 		    const char **end, char *sep);
-static int	prefix_c(const char *start, const char *end,
-		    const char *test);
-static void	append_entry(char **p, const char *prefix, int tag,
-		    const char *name, int perm, int id);
+static void	append_entry(char **p, const char *prefix, int type,
+		    int tag, int flags, const char *name, int perm, int id);
 static void	append_id(char **p, int id);
 
+static const struct {
+	const int perm;
+	const char c;
+	const wchar_t wc;
+} nfsv4_acl_perm_map[] = {
+	{ ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, 'r',
+	    L'r' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_ADD_FILE, 'w',
+	    L'w' },
+	{ ARCHIVE_ENTRY_ACL_EXECUTE, 'x', L'x' },
+	{ ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
+	    'p', L'p' },
+	{ ARCHIVE_ENTRY_ACL_DELETE, 'd', L'd' },
+	{ ARCHIVE_ENTRY_ACL_DELETE_CHILD, 'D', L'D' },
+	{ ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, 'a', L'a' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, 'A', L'A' },
+	{ ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, 'R', L'R' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, 'W', L'W' },
+	{ ARCHIVE_ENTRY_ACL_READ_ACL, 'c', L'c' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_ACL, 'C', L'C' },
+	{ ARCHIVE_ENTRY_ACL_WRITE_OWNER, 'o', L'o' },
+	{ ARCHIVE_ENTRY_ACL_SYNCHRONIZE, 's', L's' }
+};
+
+static const int nfsv4_acl_perm_map_size = (int)(sizeof(nfsv4_acl_perm_map) /
+    sizeof(nfsv4_acl_perm_map[0]));
+
+static const struct {
+	const int perm;
+	const char c;
+	const wchar_t wc;
+} nfsv4_acl_flag_map[] = {
+	{ ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, 'f', L'f' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 'd', L'd' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, 'i', L'i' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 'n', L'n' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 'S', L'S' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, 'F', L'F' },
+	{ ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, 'I', L'I' }
+};
+
+static const int nfsv4_acl_flag_map_size = (int)(sizeof(nfsv4_acl_flag_map) /
+    sizeof(nfsv4_acl_flag_map[0]));
+
 void
 archive_acl_clear(struct archive_acl *acl)
 {
@@ -94,6 +147,7 @@ archive_acl_clear(struct archive_acl *acl)
 		acl->acl_text = NULL;
 	}
 	acl->acl_p = NULL;
+	acl->acl_types = 0;
 	acl->acl_state = 0; /* Not counting. */
 }
 
@@ -279,23 +333,31 @@ acl_new_entry(struct archive_acl *acl,
 		acl->acl_text = NULL;
 	}
 
-	/* If there's a matching entry already in the list, overwrite it. */
+	/*
+	 * If there's a matching entry already in the list, overwrite it.
+	 * NFSv4 entries may be repeated and are not overwritten.
+	 *
+	 * TODO: compare names of no id is provided (needs more rework)
+	 */
 	ap = acl->acl_head;
 	aq = NULL;
 	while (ap != NULL) {
-		if (ap->type == type && ap->tag == tag && ap->id == id) {
-			ap->permset = permset;
-			return (ap);
+		if (((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) &&
+		    ap->type == type && ap->tag == tag && ap->id == id) {
+			if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER &&
+			    tag != ARCHIVE_ENTRY_ACL_GROUP)) {
+				ap->permset = permset;
+				return (ap);
+			}
 		}
 		aq = ap;
 		ap = ap->next;
 	}
 
 	/* Add a new entry to the end of the list. */
-	ap = (struct archive_acl_entry *)malloc(sizeof(*ap));
+	ap = (struct archive_acl_entry *)calloc(1, sizeof(*ap));
 	if (ap == NULL)
 		return (NULL);
-	memset(ap, 0, sizeof(*ap));
 	if (aq == NULL)
 		acl->acl_head = ap;
 	else
@@ -331,6 +393,15 @@ archive_acl_count(struct archive_acl *acl, int want_type)
 }
 
 /*
+ * Return a bitmask of stored ACL types in an ACL list
+ */
+int
+archive_acl_types(struct archive_acl *acl)
+{
+	return (acl->acl_types);
+}
+
+/*
  * Prepare for reading entries from the ACL data.  Returns a count
  * of entries matching "want_type", or zero if there are no
  * non-extended ACL entries of that type.
@@ -366,8 +437,8 @@ archive_acl_reset(struct archive_acl *acl, int want_type)
  * standard permissions and include them in the returned list.
  */
 int
-archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int *type,
-    int *permset, int *tag, int *id, const char **name)
+archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type,
+    int *type, int *permset, int *tag, int *id, const char **name)
 {
 	*name = NULL;
 	*id = -1;
@@ -432,130 +503,273 @@ archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int
 }
 
 /*
- * Generate a text version of the ACL.  The flags parameter controls
- * the style of the generated ACL.
+ * Determine what type of ACL do we want
  */
-const wchar_t *
-archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
+static int
+archive_acl_text_want_type(struct archive_acl *acl, int flags)
 {
-	int count;
-	size_t length;
-	const wchar_t *wname;
-	const wchar_t *prefix;
-	wchar_t separator;
-	struct archive_acl_entry *ap;
-	int id, r;
-	wchar_t *wp;
+	int want_type;
 
-	if (acl->acl_text_w != NULL) {
-		free (acl->acl_text_w);
-		acl->acl_text_w = NULL;
+	/* Check if ACL is NFSv4 */
+	if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+		/* NFSv4 should never mix with POSIX.1e */
+		if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
+			return (0);
+		else
+			return (ARCHIVE_ENTRY_ACL_TYPE_NFS4);
 	}
 
-	separator = L',';
+	/* Now deal with POSIX.1e ACLs */
+
+	want_type = 0;
+	if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
+		want_type |= ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+	if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+		want_type |= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+
+	/* By default we want both access and default ACLs */
+	if (want_type == 0)
+		return (ARCHIVE_ENTRY_ACL_TYPE_POSIX1E);
+
+	return (want_type);
+}
+
+/*
+ * Calculate ACL text string length
+ */
+static ssize_t
+archive_acl_text_len(struct archive_acl *acl, int want_type, int flags,
+    int wide, struct archive *a, struct archive_string_conv *sc) {
+	struct archive_acl_entry *ap;
+	const char *name;
+	const wchar_t *wname;
+	int count, idlen, tmp, r;
+	ssize_t length;
+	size_t len;
+
 	count = 0;
 	length = 0;
-	ap = acl->acl_head;
-	while (ap != NULL) {
-		if ((ap->type & flags) != 0) {
-			count++;
-			if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
-			    (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
-				length += 8; /* "default:" */
-			length += 5; /* tag name */
-			length += 1; /* colon */
-			r = archive_mstring_get_wcs(a, &ap->name, &wname);
-			if (r == 0 && wname != NULL)
-				length += wcslen(wname);
-			else if (r < 0 && errno == ENOMEM)
-				return (NULL);
-			else
-				length += sizeof(uid_t) * 3 + 1;
-			length ++; /* colon */
+	for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
+		if ((ap->type & want_type) == 0)
+			continue;
+		/*
+		 * Filemode-mapping ACL entries are stored exclusively in
+		 * ap->mode so they should not be in the list
+		 */
+		if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
+		    && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
+		    || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
+		    || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
+			continue;
+		count++;
+		if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0
+		    && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+			length += 8; /* "default:" */
+		switch (ap->tag) {
+		case ARCHIVE_ENTRY_ACL_USER_OBJ:
+			if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+				length += 6; /* "owner@" */
+				break;
+			}
+			/* FALLTHROUGH */
+		case ARCHIVE_ENTRY_ACL_USER:
+		case ARCHIVE_ENTRY_ACL_MASK:
+			length += 4; /* "user", "mask" */
+			break;
+		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+			if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+				length += 6; /* "group@" */
+				break;
+			}
+			/* FALLTHROUGH */
+		case ARCHIVE_ENTRY_ACL_GROUP:
+		case ARCHIVE_ENTRY_ACL_OTHER:
+			length += 5; /* "group", "other" */
+			break;
+		case ARCHIVE_ENTRY_ACL_EVERYONE:
+			length += 9; /* "everyone@" */
+			break;
+		}
+		length += 1; /* colon after tag */
+		if (ap->tag == ARCHIVE_ENTRY_ACL_USER ||
+		    ap->tag == ARCHIVE_ENTRY_ACL_GROUP) {
+			if (wide) {
+				r = archive_mstring_get_wcs(a, &ap->name,
+				    &wname);
+				if (r == 0 && wname != NULL)
+					length += wcslen(wname);
+				else if (r < 0 && errno == ENOMEM)
+					return (0);
+				else
+					length += sizeof(uid_t) * 3 + 1;
+			} else {
+				r = archive_mstring_get_mbs_l(&ap->name, &name,
+				    &len, sc);
+				if (r != 0)
+					return (0);
+				if (len > 0 && name != NULL)
+					length += len;
+				else
+					length += sizeof(uid_t) * 3 + 1;
+			}
+			length += 1; /* colon after user or group name */
+		} else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4)
+			length += 1; /* 2nd colon empty user,group or other */
+
+		if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0)
+		    && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0)
+		    && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER
+		    || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) {
+			/* Solaris has no colon after other: and mask: */
+			length = length - 1;
+		}
+
+		if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+			/* rwxpdDaARWcCos:fdinSFI:deny */
+			length += 27;
+			if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0)
+				length += 1; /* allow, alarm, audit */
+		} else
 			length += 3; /* rwx */
+
+		if ((ap->tag == ARCHIVE_ENTRY_ACL_USER ||
+		    ap->tag == ARCHIVE_ENTRY_ACL_GROUP) &&
+		    (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) {
 			length += 1; /* colon */
-			length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
-			length ++; /* newline */
+			/* ID digit count */
+			idlen = 1;
+			tmp = ap->id;
+			while (tmp > 9) {
+				tmp = tmp / 10;
+				idlen++;
+			}
+			length += idlen;
 		}
-		ap = ap->next;
+		length ++; /* entry separator */
 	}
 
-	if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
-		length += 10; /* "user::rwx\n" */
-		length += 11; /* "group::rwx\n" */
-		length += 11; /* "other::rwx\n" */
-	}
+	/* Add filemode-mapping access entries to the length */
+	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+		if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) {
+			/* "user::rwx\ngroup::rwx\nother:rwx\n" */
+			length += 31;
+		} else {
+			/* "user::rwx\ngroup::rwx\nother::rwx\n" */
+			length += 32;
+		}
+	} else if (count == 0)
+		return (0);
+
+	/* The terminating character is included in count */
+	return (length);
+}
+
+/*
+ * Generate a wide text version of the ACL. The flags parameter controls
+ * the type and style of the generated ACL.
+ */
+wchar_t *
+archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
+    struct archive *a)
+{
+	int count;
+	ssize_t length;
+	size_t len;
+	const wchar_t *wname;
+	const wchar_t *prefix;
+	wchar_t separator;
+	struct archive_acl_entry *ap;
+	int id, r, want_type;
+	wchar_t *wp, *ws;
+
+	want_type = archive_acl_text_want_type(acl, flags);
+
+	/* Both NFSv4 and POSIX.1 types found */
+	if (want_type == 0)
+		return (NULL);
+
+	if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
+		flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
+
+	length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL);
 
-	if (count == 0)
+	if (length == 0)
 		return (NULL);
 
+	if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
+		separator = L',';
+	else
+		separator = L'\n';
+
 	/* Now, allocate the string and actually populate it. */
-	wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t));
-	if (wp == NULL)
+	wp = ws = (wchar_t *)malloc(length * sizeof(wchar_t));
+	if (wp == NULL) {
+		if (errno == ENOMEM)
+			__archive_errx(1, "No memory");
 		return (NULL);
+	}
 	count = 0;
-	if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
+
+	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		    ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
 		    acl->mode & 0700, -1);
-		*wp++ = ',';
-		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
+		*wp++ = separator;
+		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		    ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
 		    acl->mode & 0070, -1);
-		*wp++ = ',';
-		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
+		*wp++ = separator;
+		append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		    ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
 		    acl->mode & 0007, -1);
 		count += 3;
-
-		ap = acl->acl_head;
-		while (ap != NULL) {
-			if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-				r = archive_mstring_get_wcs(a, &ap->name, &wname);
-				if (r == 0) {
-					*wp++ = separator;
-					if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
-						id = ap->id;
-					else
-						id = -1;
-					append_entry_w(&wp, NULL, ap->tag, wname,
-					    ap->permset, id);
-					count++;
-				} else if (r < 0 && errno == ENOMEM)
-					return (NULL);
-			}
-			ap = ap->next;
-		}
 	}
 
-
-	if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
-		if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT)
+	for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
+		if ((ap->type & want_type) == 0)
+			continue;
+		/*
+		 * Filemode-mapping ACL entries are stored exclusively in
+		 * ap->mode so they should not be in the list
+		 */
+		if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
+		    && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
+		    || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
+		    || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
+			continue;
+		if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT &&
+		    (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
 			prefix = L"default:";
 		else
 			prefix = NULL;
-		ap = acl->acl_head;
-		count = 0;
-		while (ap != NULL) {
-			if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
-				r = archive_mstring_get_wcs(a, &ap->name, &wname);
-				if (r == 0) {
-					if (count > 0)
-						*wp++ = separator;
-					if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
-						id = ap->id;
-					else
-						id = -1;
-					append_entry_w(&wp, prefix, ap->tag,
-					    wname, ap->permset, id);
-					count ++;
-				} else if (r < 0 && errno == ENOMEM)
-					return (NULL);
-			}
-			ap = ap->next;
-		}
+		r = archive_mstring_get_wcs(a, &ap->name, &wname);
+		if (r == 0) {
+			if (count > 0)
+				*wp++ = separator;
+			if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+				id = ap->id;
+			else
+				id = -1;
+			append_entry_w(&wp, prefix, ap->type, ap->tag, flags,
+			    wname, ap->permset, id);
+			count++;
+		} else if (r < 0 && errno == ENOMEM)
+			return (NULL);
 	}
 
-	return (acl->acl_text_w);
-}
+	/* Add terminating character */
+	*wp++ = L'\0';
+
+	len = wcslen(ws);
 
+	if ((ssize_t)len > (length - 1))
+		__archive_errx(1, "Buffer overrun");
+
+	if (text_len != NULL)
+		*text_len = len;
+
+	return (ws);
+}
 
 static void
 append_id_w(wchar_t **wp, int id)
@@ -568,9 +782,11 @@ append_id_w(wchar_t **wp, int id)
 }
 
 static void
-append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
-    const wchar_t *wname, int perm, int id)
+append_entry_w(wchar_t **wp, const wchar_t *prefix, int type,
+    int tag, int flags, const wchar_t *wname, int perm, int id)
 {
+	int i;
+
 	if (prefix != NULL) {
 		wcscpy(*wp, prefix);
 		*wp += wcslen(*wp);
@@ -579,6 +795,10 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
 	case ARCHIVE_ENTRY_ACL_USER_OBJ:
 		wname = NULL;
 		id = -1;
+		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+			wcscpy(*wp, L"owner@");
+			break;
+		}
 		/* FALLTHROUGH */
 	case ARCHIVE_ENTRY_ACL_USER:
 		wcscpy(*wp, L"user");
@@ -586,6 +806,10 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
 	case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
 		wname = NULL;
 		id = -1;
+		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+			wcscpy(*wp, L"group@");
+			break;
+		}
 		/* FALLTHROUGH */
 	case ARCHIVE_ENTRY_ACL_GROUP:
 		wcscpy(*wp, L"group");
@@ -600,153 +824,184 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag,
 		wname = NULL;
 		id = -1;
 		break;
+	case ARCHIVE_ENTRY_ACL_EVERYONE:
+		wcscpy(*wp, L"everyone@");
+		wname = NULL;
+		id = -1;
+		break;
 	}
 	*wp += wcslen(*wp);
 	*(*wp)++ = L':';
-	if (wname != NULL) {
-		wcscpy(*wp, wname);
+	if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
+	    tag == ARCHIVE_ENTRY_ACL_USER ||
+	    tag == ARCHIVE_ENTRY_ACL_GROUP) {
+		if (wname != NULL) {
+			wcscpy(*wp, wname);
+			*wp += wcslen(*wp);
+		} else if (tag == ARCHIVE_ENTRY_ACL_USER
+		    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
+			append_id_w(wp, id);
+			if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
+				id = -1;
+		}
+		/* Solaris style has no second colon after other and mask */
+		if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
+		    || (tag != ARCHIVE_ENTRY_ACL_OTHER
+		    && tag != ARCHIVE_ENTRY_ACL_MASK))
+			*(*wp)++ = L':';
+	}
+	if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+		/* POSIX.1e ACL perms */
+		*(*wp)++ = (perm & 0444) ? L'r' : L'-';
+		*(*wp)++ = (perm & 0222) ? L'w' : L'-';
+		*(*wp)++ = (perm & 0111) ? L'x' : L'-';
+	} else {
+		/* NFSv4 ACL perms */
+		for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
+			if (perm & nfsv4_acl_perm_map[i].perm)
+				*(*wp)++ = nfsv4_acl_perm_map[i].wc;
+			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+				*(*wp)++ = L'-';
+		}
+		*(*wp)++ = L':';
+		for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
+			if (perm & nfsv4_acl_flag_map[i].perm)
+				*(*wp)++ = nfsv4_acl_flag_map[i].wc;
+			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+				*(*wp)++ = L'-';
+		}
+		*(*wp)++ = L':';
+		switch (type) {
+		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+			wcscpy(*wp, L"allow");
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+			wcscpy(*wp, L"deny");
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+			wcscpy(*wp, L"audit");
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+			wcscpy(*wp, L"alarm");
+			break;
+		default:
+			break;
+		}
 		*wp += wcslen(*wp);
-	} else if (tag == ARCHIVE_ENTRY_ACL_USER
-	    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
-		append_id_w(wp, id);
-		id = -1;
 	}
-	*(*wp)++ = L':';
-	*(*wp)++ = (perm & 0444) ? L'r' : L'-';
-	*(*wp)++ = (perm & 0222) ? L'w' : L'-';
-	*(*wp)++ = (perm & 0111) ? L'x' : L'-';
 	if (id != -1) {
 		*(*wp)++ = L':';
 		append_id_w(wp, id);
 	}
-	**wp = L'\0';
 }
 
-int
-archive_acl_text_l(struct archive_acl *acl, int flags,
-    const char **acl_text, size_t *acl_text_len,
+/*
+ * Generate a text version of the ACL. The flags parameter controls
+ * the type and style of the generated ACL.
+ */
+char *
+archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
     struct archive_string_conv *sc)
 {
 	int count;
-	size_t length;
+	ssize_t length;
+	size_t len;
 	const char *name;
 	const char *prefix;
 	char separator;
 	struct archive_acl_entry *ap;
-	size_t len;
-	int id, r;
-	char *p;
+	int id, r, want_type;
+	char *p, *s;
 
-	if (acl->acl_text != NULL) {
-		free (acl->acl_text);
-		acl->acl_text = NULL;
-	}
+	want_type = archive_acl_text_want_type(acl, flags);
 
-	*acl_text = NULL;
-	if (acl_text_len != NULL)
-		*acl_text_len = 0;
-	separator = ',';
-	count = 0;
-	length = 0;
-	ap = acl->acl_head;
-	while (ap != NULL) {
-		if ((ap->type & flags) != 0) {
-			count++;
-			if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) &&
-			    (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT))
-				length += 8; /* "default:" */
-			length += 5; /* tag name */
-			length += 1; /* colon */
-			r = archive_mstring_get_mbs_l(
-			    &ap->name, &name, &len, sc);
-			if (r != 0)
-				return (-1);
-			if (len > 0 && name != NULL)
-				length += len;
-			else
-				length += sizeof(uid_t) * 3 + 1;
-			length ++; /* colon */
-			length += 3; /* rwx */
-			length += 1; /* colon */
-			length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
-			length ++; /* newline */
-		}
-		ap = ap->next;
-	}
+	/* Both NFSv4 and POSIX.1 types found */
+	if (want_type == 0)
+		return (NULL);
 
-	if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) {
-		length += 10; /* "user::rwx\n" */
-		length += 11; /* "group::rwx\n" */
-		length += 11; /* "other::rwx\n" */
-	}
+	if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)
+		flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
 
-	if (count == 0)
-		return (0);
+	length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc);
+
+	if (length == 0)
+		return (NULL);
+
+	if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA)
+		separator = ',';
+	else
+		separator = '\n';
 
 	/* Now, allocate the string and actually populate it. */
-	p = acl->acl_text = (char *)malloc(length);
-	if (p == NULL)
-		return (-1);
+	p = s = (char *)malloc(length * sizeof(char));
+	if (p == NULL) {
+		if (errno == ENOMEM)
+			__archive_errx(1, "No memory");
+		return (NULL);
+	}
 	count = 0;
-	if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
-		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
+
+	if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		    ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL,
 		    acl->mode & 0700, -1);
-		*p++ = ',';
-		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL,
+		*p++ = separator;
+		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		    ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL,
 		    acl->mode & 0070, -1);
-		*p++ = ',';
-		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL,
+		*p++ = separator;
+		append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+		    ARCHIVE_ENTRY_ACL_OTHER, flags, NULL,
 		    acl->mode & 0007, -1);
 		count += 3;
-
-		for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
-			if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) == 0)
-				continue;
-			r = archive_mstring_get_mbs_l(
-			    &ap->name, &name, &len, sc);
-			if (r != 0)
-				return (-1);
-			*p++ = separator;
-			if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
-				id = ap->id;
-			else
-				id = -1;
-			append_entry(&p, NULL, ap->tag, name,
-			    ap->permset, id);
-			count++;
-		}
 	}
 
-
-	if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
-		if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT)
+	for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
+		if ((ap->type & want_type) == 0)
+			continue;
+		/*
+		 * Filemode-mapping ACL entries are stored exclusively in
+		 * ap->mode so they should not be in the list
+		 */
+		if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS)
+		    && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ
+		    || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ
+		    || ap->tag == ARCHIVE_ENTRY_ACL_OTHER))
+			continue;
+		if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT &&
+		    (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
 			prefix = "default:";
 		else
 			prefix = NULL;
-		count = 0;
-		for (ap = acl->acl_head; ap != NULL; ap = ap->next) {
-			if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) == 0)
-				continue;
-			r = archive_mstring_get_mbs_l(
-			    &ap->name, &name, &len, sc);
-			if (r != 0)
-				return (-1);
-			if (count > 0)
-				*p++ = separator;
-			if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
-				id = ap->id;
-			else
-				id = -1;
-			append_entry(&p, prefix, ap->tag,
-			    name, ap->permset, id);
-			count ++;
+		r = archive_mstring_get_mbs_l(
+		    &ap->name, &name, &len, sc);
+		if (r != 0)
+			return (NULL);
+		if (count > 0)
+			*p++ = separator;
+		if (name == NULL ||
+		    (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) {
+			id = ap->id;
+		} else {
+			id = -1;
 		}
+		append_entry(&p, prefix, ap->type, ap->tag, flags, name,
+		    ap->permset, id);
+		count++;
 	}
 
-	*acl_text = acl->acl_text;
-	if (acl_text_len != NULL)
-		*acl_text_len = strlen(acl->acl_text);
-	return (0);
+	/* Add terminating character */
+	*p++ = '\0';
+
+	len = strlen(s);
+
+	if ((ssize_t)len > (length - 1))
+		__archive_errx(1, "Buffer overrun");
+
+	if (text_len != NULL)
+		*text_len = len;
+
+	return (s);
 }
 
 static void
@@ -760,9 +1015,11 @@ append_id(char **p, int id)
 }
 
 static void
-append_entry(char **p, const char *prefix, int tag,
-    const char *name, int perm, int id)
+append_entry(char **p, const char *prefix, int type,
+    int tag, int flags, const char *name, int perm, int id)
 {
+	int i;
+
 	if (prefix != NULL) {
 		strcpy(*p, prefix);
 		*p += strlen(*p);
@@ -771,6 +1028,10 @@ append_entry(char **p, const char *prefix, int tag,
 	case ARCHIVE_ENTRY_ACL_USER_OBJ:
 		name = NULL;
 		id = -1;
+		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+			strcpy(*p, "owner@");
+			break;
+		}
 		/* FALLTHROUGH */
 	case ARCHIVE_ENTRY_ACL_USER:
 		strcpy(*p, "user");
@@ -778,6 +1039,10 @@ append_entry(char **p, const char *prefix, int tag,
 	case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
 		name = NULL;
 		id = -1;
+		if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+			strcpy(*p, "group@");
+			break;
+		}
 		/* FALLTHROUGH */
 	case ARCHIVE_ENTRY_ACL_GROUP:
 		strcpy(*p, "group");
@@ -792,48 +1057,120 @@ append_entry(char **p, const char *prefix, int tag,
 		name = NULL;
 		id = -1;
 		break;
+	case ARCHIVE_ENTRY_ACL_EVERYONE:
+		strcpy(*p, "everyone@");
+		name = NULL;
+		id = -1;
+		break;
 	}
 	*p += strlen(*p);
 	*(*p)++ = ':';
-	if (name != NULL) {
-		strcpy(*p, name);
+	if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) ||
+	    tag == ARCHIVE_ENTRY_ACL_USER ||
+	    tag == ARCHIVE_ENTRY_ACL_GROUP) {
+		if (name != NULL) {
+			strcpy(*p, name);
+			*p += strlen(*p);
+		} else if (tag == ARCHIVE_ENTRY_ACL_USER
+		    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
+			append_id(p, id);
+			if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0)
+				id = -1;
+		}
+		/* Solaris style has no second colon after other and mask */
+		if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0)
+		    || (tag != ARCHIVE_ENTRY_ACL_OTHER
+		    && tag != ARCHIVE_ENTRY_ACL_MASK))
+			*(*p)++ = ':';
+	}
+	if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+		/* POSIX.1e ACL perms */
+		*(*p)++ = (perm & 0444) ? 'r' : '-';
+		*(*p)++ = (perm & 0222) ? 'w' : '-';
+		*(*p)++ = (perm & 0111) ? 'x' : '-';
+	} else {
+		/* NFSv4 ACL perms */
+		for (i = 0; i < nfsv4_acl_perm_map_size; i++) {
+			if (perm & nfsv4_acl_perm_map[i].perm)
+				*(*p)++ = nfsv4_acl_perm_map[i].c;
+			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+				*(*p)++ = '-';
+		}
+		*(*p)++ = ':';
+		for (i = 0; i < nfsv4_acl_flag_map_size; i++) {
+			if (perm & nfsv4_acl_flag_map[i].perm)
+				*(*p)++ = nfsv4_acl_flag_map[i].c;
+			else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0)
+				*(*p)++ = '-';
+		}
+		*(*p)++ = ':';
+		switch (type) {
+		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+			strcpy(*p, "allow");
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+			strcpy(*p, "deny");
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+			strcpy(*p, "audit");
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+			strcpy(*p, "alarm");
+			break;
+		}
 		*p += strlen(*p);
-	} else if (tag == ARCHIVE_ENTRY_ACL_USER
-	    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
-		append_id(p, id);
-		id = -1;
 	}
-	*(*p)++ = ':';
-	*(*p)++ = (perm & 0444) ? 'r' : '-';
-	*(*p)++ = (perm & 0222) ? 'w' : '-';
-	*(*p)++ = (perm & 0111) ? 'x' : '-';
 	if (id != -1) {
 		*(*p)++ = ':';
 		append_id(p, id);
 	}
-	**p = '\0';
 }
 
 /*
- * Parse a textual ACL.  This automatically recognizes and supports
- * extensions described above.  The 'type' argument is used to
- * indicate the type that should be used for any entries not
- * explicitly marked as "default:".
+ * Parse a wide ACL text string.
+ *
+ * The want_type argument may be one of the following:
+ * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT
+ * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL
+ *
+ * POSIX.1e ACL entries prefixed with "default:" are treated as
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4
  */
 int
-archive_acl_parse_w(struct archive_acl *acl,
-    const wchar_t *text, int default_type)
+archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
+    int want_type)
 {
 	struct {
 		const wchar_t *start;
 		const wchar_t *end;
-	} field[4], name;
+	} field[6], name;
+
+	const wchar_t *s, *st;
 
-	int fields, n;
-	int type, tag, permset, id;
+	int numfields, fields, n, r, sol, ret;
+	int type, types, tag, permset, id;
+	size_t len;
 	wchar_t sep;
 
-	while (text != NULL  &&  *text != L'\0') {
+	ret = ARCHIVE_OK;
+	types = 0;
+
+	switch (want_type) {
+	case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
+		want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+		numfields = 5;
+		break;
+	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+		numfields = 6;
+		break;
+	default:
+		return (ARCHIVE_FATAL);
+	}
+
+	while (text != NULL && *text != L'\0') {
 		/*
 		 * Parse the fields out of the next entry,
 		 * advance 'text' to start of next entry.
@@ -842,7 +1179,7 @@ archive_acl_parse_w(struct archive_acl *acl,
 		do {
 			const wchar_t *start, *end;
 			next_field_w(&text, &start, &end, &sep);
-			if (fields < 4) {
+			if (fields < numfields) {
 				field[fields].start = start;
 				field[fields].end = end;
 			}
@@ -850,78 +1187,210 @@ archive_acl_parse_w(struct archive_acl *acl,
 		} while (sep == L':');
 
 		/* Set remaining fields to blank. */
-		for (n = fields; n < 4; ++n)
+		for (n = fields; n < numfields; ++n)
 			field[n].start = field[n].end = NULL;
 
-		/* Check for a numeric ID in field 1 or 3. */
-		id = -1;
-		isint_w(field[1].start, field[1].end, &id);
-		/* Field 3 is optional. */
-		if (id == -1 && fields > 3)
-			isint_w(field[3].start, field[3].end, &id);
-
-		/*
-		 * Solaris extension:  "defaultuser::rwx" is the
-		 * default ACL corresponding to "user::rwx", etc.
-		 */
-		if (field[0].end - field[0].start > 7
-		    && wmemcmp(field[0].start, L"default", 7) == 0) {
-			type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
-			field[0].start += 7;
-		} else
-			type = default_type;
+		if (field[0].start != NULL && *(field[0].start) == L'#') {
+			/* Comment, skip entry */
+			continue;
+		}
 
+		n = 0;
+		sol = 0;
+		id = -1;
+		permset = 0;
 		name.start = name.end = NULL;
-		if (prefix_w(field[0].start, field[0].end, L"user")) {
-			if (!ismode_w(field[2].start, field[2].end, &permset))
-				return (ARCHIVE_WARN);
-			if (id != -1 || field[1].start < field[1].end) {
-				tag = ARCHIVE_ENTRY_ACL_USER;
-				name = field[1];
+
+		if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+			/* POSIX.1e ACLs */
+			/*
+			 * Default keyword "default:user::rwx"
+			 * if found, we have one more field
+			 *
+			 * We also support old Solaris extension:
+			 * "defaultuser::rwx" is the default ACL corresponding
+			 * to "user::rwx", etc. valid only for first field
+			 */
+			s = field[0].start;
+			len = field[0].end - field[0].start;
+			if (*s == L'd' && (len == 1 || (len >= 7
+			    && wmemcmp((s + 1), L"efault", 6) == 0))) {
+				type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+				if (len > 7)
+					field[0].start += 7;
+				else
+					n = 1;
 			} else
-				tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-		} else if (prefix_w(field[0].start, field[0].end, L"group")) {
-			if (!ismode_w(field[2].start, field[2].end, &permset))
-				return (ARCHIVE_WARN);
-			if (id != -1 || field[1].start < field[1].end) {
-				tag = ARCHIVE_ENTRY_ACL_GROUP;
+				type = want_type;
+
+			/* Check for a numeric ID in field n+1 or n+3. */
+			isint_w(field[n + 1].start, field[n + 1].end, &id);
+			/* Field n+3 is optional. */
+			if (id == -1 && fields > n+3)
+				isint_w(field[n + 3].start, field[n + 3].end,
+				    &id);
+
+			tag = 0;
+			s = field[n].start;
+			st = field[n].start + 1;
+			len = field[n].end - field[n].start;
+
+			switch (*s) {
+			case L'u':
+				if (len == 1 || (len == 4
+				    && wmemcmp(st, L"ser", 3) == 0))
+					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+				break;
+			case L'g':
+				if (len == 1 || (len == 5
+				    && wmemcmp(st, L"roup", 4) == 0))
+					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+				break;
+			case L'o':
+				if (len == 1 || (len == 5
+				    && wmemcmp(st, L"ther", 4) == 0))
+					tag = ARCHIVE_ENTRY_ACL_OTHER;
+				break;
+			case L'm':
+				if (len == 1 || (len == 4
+				    && wmemcmp(st, L"ask", 3) == 0))
+					tag = ARCHIVE_ENTRY_ACL_MASK;
+				break;
+			default:
+					break;
+			}
+
+			switch (tag) {
+			case ARCHIVE_ENTRY_ACL_OTHER:
+			case ARCHIVE_ENTRY_ACL_MASK:
+				if (fields == (n + 2)
+				    && field[n + 1].start < field[n + 1].end
+				    && ismode_w(field[n + 1].start,
+				    field[n + 1].end, &permset)) {
+					/* This is Solaris-style "other:rwx" */
+					sol = 1;
+				} else if (fields == (n + 3) &&
+				    field[n + 1].start < field[n + 1].end) {
+					/* Invalid mask or other field */
+					ret = ARCHIVE_WARN;
+					continue;
+				}
+				break;
+			case ARCHIVE_ENTRY_ACL_USER_OBJ:
+			case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+				if (id != -1 ||
+				    field[n + 1].start < field[n + 1].end) {
+					name = field[n + 1];
+					if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
+						tag = ARCHIVE_ENTRY_ACL_USER;
+					else
+						tag = ARCHIVE_ENTRY_ACL_GROUP;
+				}
+				break;
+			default:
+				/* Invalid tag, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+
+			/*
+			 * Without "default:" we expect mode in field 2
+			 * Exception: Solaris other and mask fields
+			 */
+			if (permset == 0 && !ismode_w(field[n + 2 - sol].start,
+			    field[n + 2 - sol].end, &permset)) {
+				/* Invalid mode, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+		} else {
+			/* NFS4 ACLs */
+			s = field[0].start;
+			len = field[0].end - field[0].start;
+			tag = 0;
+
+			switch (len) {
+			case 4:
+				if (wmemcmp(s, L"user", 4) == 0)
+					tag = ARCHIVE_ENTRY_ACL_USER;
+				break;
+			case 5:
+				if (wmemcmp(s, L"group", 5) == 0)
+					tag = ARCHIVE_ENTRY_ACL_GROUP;
+				break;
+			case 6:
+				if (wmemcmp(s, L"owner@", 6) == 0)
+					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+				else if (wmemcmp(s, L"group@", len) == 0)
+					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+				break;
+			case 9:
+				if (wmemcmp(s, L"everyone@", 9) == 0)
+					tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+			default:
+				break;
+			}
+
+			if (tag == 0) {
+				/* Invalid tag, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			} else if (tag == ARCHIVE_ENTRY_ACL_USER ||
+			    tag == ARCHIVE_ENTRY_ACL_GROUP) {
+				n = 1;
 				name = field[1];
+				isint_w(name.start, name.end, &id);
 			} else
-				tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-		} else if (prefix_w(field[0].start, field[0].end, L"other")) {
-			if (fields == 2
-			    && field[1].start < field[1].end
-			    && ismode_w(field[1].start, field[1].end, &permset)) {
-				/* This is Solaris-style "other:rwx" */
-			} else if (fields == 3
-			    && field[1].start == field[1].end
-			    && field[2].start < field[2].end
-			    && ismode_w(field[2].start, field[2].end, &permset)) {
-				/* This is FreeBSD-style "other::rwx" */
-			} else
-				return (ARCHIVE_WARN);
-			tag = ARCHIVE_ENTRY_ACL_OTHER;
-		} else if (prefix_w(field[0].start, field[0].end, L"mask")) {
-			if (fields == 2
-			    && field[1].start < field[1].end
-			    && ismode_w(field[1].start, field[1].end, &permset)) {
-				/* This is Solaris-style "mask:rwx" */
-			} else if (fields == 3
-			    && field[1].start == field[1].end
-			    && field[2].start < field[2].end
-			    && ismode_w(field[2].start, field[2].end, &permset)) {
-				/* This is FreeBSD-style "mask::rwx" */
-			} else
-				return (ARCHIVE_WARN);
-			tag = ARCHIVE_ENTRY_ACL_MASK;
-		} else
-			return (ARCHIVE_WARN);
+				n = 0;
+
+			if (!is_nfs4_perms_w(field[1 + n].start,
+			    field[1 + n].end, &permset)) {
+				/* Invalid NFSv4 perms, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			if (!is_nfs4_flags_w(field[2 + n].start,
+			    field[2 + n].end, &permset)) {
+				/* Invalid NFSv4 flags, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			s = field[3 + n].start;
+			len = field[3 + n].end - field[3 + n].start;
+			type = 0;
+			if (len == 4) {
+				if (wmemcmp(s, L"deny", 4) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+			} else if (len == 5) {
+				if (wmemcmp(s, L"allow", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+				else if (wmemcmp(s, L"audit", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+				else if (wmemcmp(s, L"alarm", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+			}
+			if (type == 0) {
+				/* Invalid entry type, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			isint_w(field[4 + n].start, field[4 + n].end, &id);
+		}
 
 		/* Add entry to the internal list. */
-		archive_acl_add_entry_w_len(acl, type, permset,
+		r = archive_acl_add_entry_w_len(acl, type, permset,
 		    tag, id, name.start, name.end - name.start);
+		if (r < ARCHIVE_WARN)
+			return (r);
+		if (r != ARCHIVE_OK)
+			ret = ARCHIVE_WARN;
+		types |= type;
 	}
-	return (ARCHIVE_OK);
+
+	/* Reset ACL */
+	archive_acl_reset(acl, types);
+
+	return (ret);
 }
 
 /*
@@ -967,16 +1436,122 @@ ismode_w(const wchar_t *start, const wchar_t *end, int *permset)
 	*permset = 0;
 	while (p < end) {
 		switch (*p++) {
-		case 'r': case 'R':
+		case L'r': case L'R':
 			*permset |= ARCHIVE_ENTRY_ACL_READ;
 			break;
-		case 'w': case 'W':
+		case L'w': case L'W':
 			*permset |= ARCHIVE_ENTRY_ACL_WRITE;
 			break;
-		case 'x': case 'X':
+		case L'x': case L'X':
 			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
 			break;
-		case '-':
+		case L'-':
+			break;
+		default:
+			return (0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL permission field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * permission characters, false otherwise
+ */
+static int
+is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+	const wchar_t *p = start;
+
+	while (p < end) {
+		switch (*p++) {
+		case L'r':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
+			break;
+		case L'w':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
+			break;
+		case L'x':
+			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+			break;
+		case L'p':
+			*permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
+			break;
+		case L'D':
+			*permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
+			break;
+		case L'd':
+			*permset |= ARCHIVE_ENTRY_ACL_DELETE;
+			break;
+		case L'a':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
+			break;
+		case L'A':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
+			break;
+		case L'R':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
+			break;
+		case L'W':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
+			break;
+		case L'c':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
+			break;
+		case L'C':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
+			break;
+		case L'o':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+			break;
+		case L's':
+			*permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+			break;
+		case L'-':
+			break;
+		default:
+			return(0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL flags field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * flag characters, false otherwise
+ */
+static int
+is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, int *permset)
+{
+	const wchar_t *p = start;
+
+	while (p < end) {
+		switch(*p++) {
+		case L'f':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
+			break;
+		case L'd':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
+			break;
+		case L'i':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
+			break;
+		case L'n':
+			*permset |=
+			    ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
+			break;
+		case L'S':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
+			break;
+		case L'F':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
+			break;
+		case L'I':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
+			break;
+		case L'-':
 			break;
 		default:
 			return (0);
@@ -1023,46 +1598,48 @@ next_field_w(const wchar_t **wp, const wchar_t **start,
 }
 
 /*
- * Return true if the characters [start...end) are a prefix of 'test'.
- * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
- */
-static int
-prefix_w(const wchar_t *start, const wchar_t *end, const wchar_t *test)
-{
-	if (start == end)
-		return (0);
-
-	if (*start++ != *test++)
-		return (0);
-
-	while (start < end  &&  *start++ == *test++)
-		;
-
-	if (start < end)
-		return (0);
-
-	return (1);
-}
-
-/*
- * Parse a textual ACL.  This automatically recognizes and supports
- * extensions described above.  The 'type' argument is used to
- * indicate the type that should be used for any entries not
- * explicitly marked as "default:".
+ * Parse an ACL text string.
+ *
+ * The want_type argument may be one of the following:
+ * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT
+ * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL
+ *
+ * POSIX.1e ACL entries prefixed with "default:" are treated as
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4
  */
 int
-archive_acl_parse_l(struct archive_acl *acl,
-    const char *text, int default_type, struct archive_string_conv *sc)
+archive_acl_from_text_l(struct archive_acl *acl, const char *text,
+    int want_type, struct archive_string_conv *sc)
 {
 	struct {
 		const char *start;
 		const char *end;
-	} field[4], name;
+	} field[6], name;
 
-	int fields, n, r, ret = ARCHIVE_OK;
-	int type, tag, permset, id;
+	const char *s, *st;
+	int numfields, fields, n, r, sol, ret;
+	int type, types, tag, permset, id;
+	size_t len;
 	char sep;
 
+	switch (want_type) {
+	case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
+		want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+		numfields = 5;
+		break;
+	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+		numfields = 6;
+		break;
+	default:
+		return (ARCHIVE_FATAL);
+	}
+
+	ret = ARCHIVE_OK;
+	types = 0;
+
 	while (text != NULL  &&  *text != '\0') {
 		/*
 		 * Parse the fields out of the next entry,
@@ -1072,7 +1649,7 @@ archive_acl_parse_l(struct archive_acl *acl,
 		do {
 			const char *start, *end;
 			next_field(&text, &start, &end, &sep);
-			if (fields < 4) {
+			if (fields < numfields) {
 				field[fields].start = start;
 				field[fields].end = end;
 			}
@@ -1080,72 +1657,197 @@ archive_acl_parse_l(struct archive_acl *acl,
 		} while (sep == ':');
 
 		/* Set remaining fields to blank. */
-		for (n = fields; n < 4; ++n)
+		for (n = fields; n < numfields; ++n)
 			field[n].start = field[n].end = NULL;
 
-		/* Check for a numeric ID in field 1 or 3. */
-		id = -1;
-		isint(field[1].start, field[1].end, &id);
-		/* Field 3 is optional. */
-		if (id == -1 && fields > 3)
-			isint(field[3].start, field[3].end, &id);
-
-		/*
-		 * Solaris extension:  "defaultuser::rwx" is the
-		 * default ACL corresponding to "user::rwx", etc.
-		 */
-		if (field[0].end - field[0].start > 7
-		    && memcmp(field[0].start, "default", 7) == 0) {
-			type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
-			field[0].start += 7;
-		} else
-			type = default_type;
+		if (field[0].start != NULL && *(field[0].start) == '#') {
+			/* Comment, skip entry */
+			continue;
+		}
 
+		n = 0;
+		sol = 0;
+		id = -1;
+		permset = 0;
 		name.start = name.end = NULL;
-		if (prefix_c(field[0].start, field[0].end, "user")) {
-			if (!ismode(field[2].start, field[2].end, &permset))
-				return (ARCHIVE_WARN);
-			if (id != -1 || field[1].start < field[1].end) {
-				tag = ARCHIVE_ENTRY_ACL_USER;
-				name = field[1];
+
+		if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+			/* POSIX.1e ACLs */
+			/*
+			 * Default keyword "default:user::rwx"
+			 * if found, we have one more field
+			 *
+			 * We also support old Solaris extension:
+			 * "defaultuser::rwx" is the default ACL corresponding
+			 * to "user::rwx", etc. valid only for first field
+			 */
+			s = field[0].start;
+			len = field[0].end - field[0].start;
+			if (*s == 'd' && (len == 1 || (len >= 7
+			    && memcmp((s + 1), "efault", 6) == 0))) {
+				type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+				if (len > 7)
+					field[0].start += 7;
+				else
+					n = 1;
 			} else
-				tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
-		} else if (prefix_c(field[0].start, field[0].end, "group")) {
-			if (!ismode(field[2].start, field[2].end, &permset))
-				return (ARCHIVE_WARN);
-			if (id != -1 || field[1].start < field[1].end) {
-				tag = ARCHIVE_ENTRY_ACL_GROUP;
+				type = want_type;
+
+			/* Check for a numeric ID in field n+1 or n+3. */
+			isint(field[n + 1].start, field[n + 1].end, &id);
+			/* Field n+3 is optional. */
+			if (id == -1 && fields > (n + 3))
+				isint(field[n + 3].start, field[n + 3].end,
+				    &id);
+
+			tag = 0;
+			s = field[n].start;
+			st = field[n].start + 1;
+			len = field[n].end - field[n].start;
+
+			switch (*s) {
+			case 'u':
+				if (len == 1 || (len == 4
+				    && memcmp(st, "ser", 3) == 0))
+					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+				break;
+			case 'g':
+				if (len == 1 || (len == 5
+				    && memcmp(st, "roup", 4) == 0))
+					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+				break;
+			case 'o':
+				if (len == 1 || (len == 5
+				    && memcmp(st, "ther", 4) == 0))
+					tag = ARCHIVE_ENTRY_ACL_OTHER;
+				break;
+			case 'm':
+				if (len == 1 || (len == 4
+				    && memcmp(st, "ask", 3) == 0))
+					tag = ARCHIVE_ENTRY_ACL_MASK;
+				break;
+			default:
+					break;
+			}
+
+			switch (tag) {
+			case ARCHIVE_ENTRY_ACL_OTHER:
+			case ARCHIVE_ENTRY_ACL_MASK:
+				if (fields == (n + 2)
+				    && field[n + 1].start < field[n + 1].end
+				    && ismode(field[n + 1].start,
+				    field[n + 1].end, &permset)) {
+					/* This is Solaris-style "other:rwx" */
+					sol = 1;
+				} else if (fields == (n + 3) &&
+				    field[n + 1].start < field[n + 1].end) {
+					/* Invalid mask or other field */
+					ret = ARCHIVE_WARN;
+					continue;
+				}
+				break;
+			case ARCHIVE_ENTRY_ACL_USER_OBJ:
+			case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+				if (id != -1 ||
+				    field[n + 1].start < field[n + 1].end) {
+					name = field[n + 1];
+					if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ)
+						tag = ARCHIVE_ENTRY_ACL_USER;
+					else
+						tag = ARCHIVE_ENTRY_ACL_GROUP;
+				}
+				break;
+			default:
+				/* Invalid tag, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+
+			/*
+			 * Without "default:" we expect mode in field 3
+			 * Exception: Solaris other and mask fields
+			 */
+			if (permset == 0 && !ismode(field[n + 2 - sol].start,
+			    field[n + 2 - sol].end, &permset)) {
+				/* Invalid mode, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+		} else {
+			/* NFS4 ACLs */
+			s = field[0].start;
+			len = field[0].end - field[0].start;
+			tag = 0;
+
+			switch (len) {
+			case 4:
+				if (memcmp(s, "user", 4) == 0)
+					tag = ARCHIVE_ENTRY_ACL_USER;
+				break;
+			case 5:
+				if (memcmp(s, "group", 5) == 0)
+					tag = ARCHIVE_ENTRY_ACL_GROUP;
+				break;
+			case 6:
+				if (memcmp(s, "owner@", 6) == 0)
+					tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+				else if (memcmp(s, "group@", 6) == 0)
+					tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+				break;
+			case 9:
+				if (memcmp(s, "everyone@", 9) == 0)
+					tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+				break;
+			default:
+				break;
+			}
+
+			if (tag == 0) {
+				/* Invalid tag, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			} else if (tag == ARCHIVE_ENTRY_ACL_USER ||
+			    tag == ARCHIVE_ENTRY_ACL_GROUP) {
+				n = 1;
 				name = field[1];
+				isint(name.start, name.end, &id);
 			} else
-				tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
-		} else if (prefix_c(field[0].start, field[0].end, "other")) {
-			if (fields == 2
-			    && field[1].start < field[1].end
-			    && ismode(field[1].start, field[1].end, &permset)) {
-				/* This is Solaris-style "other:rwx" */
-			} else if (fields == 3
-			    && field[1].start == field[1].end
-			    && field[2].start < field[2].end
-			    && ismode(field[2].start, field[2].end, &permset)) {
-				/* This is FreeBSD-style "other::rwx" */
-			} else
-				return (ARCHIVE_WARN);
-			tag = ARCHIVE_ENTRY_ACL_OTHER;
-		} else if (prefix_c(field[0].start, field[0].end, "mask")) {
-			if (fields == 2
-			    && field[1].start < field[1].end
-			    && ismode(field[1].start, field[1].end, &permset)) {
-				/* This is Solaris-style "mask:rwx" */
-			} else if (fields == 3
-			    && field[1].start == field[1].end
-			    && field[2].start < field[2].end
-			    && ismode(field[2].start, field[2].end, &permset)) {
-				/* This is FreeBSD-style "mask::rwx" */
-			} else
-				return (ARCHIVE_WARN);
-			tag = ARCHIVE_ENTRY_ACL_MASK;
-		} else
-			return (ARCHIVE_WARN);
+				n = 0;
+
+			if (!is_nfs4_perms(field[1 + n].start,
+			    field[1 + n].end, &permset)) {
+				/* Invalid NFSv4 perms, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			if (!is_nfs4_flags(field[2 + n].start,
+			    field[2 + n].end, &permset)) {
+				/* Invalid NFSv4 flags, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			s = field[3 + n].start;
+			len = field[3 + n].end - field[3 + n].start;
+			type = 0;
+			if (len == 4) {
+				if (memcmp(s, "deny", 4) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+			} else if (len == 5) {
+				if (memcmp(s, "allow", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+				else if (memcmp(s, "audit", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+				else if (memcmp(s, "alarm", 5) == 0)
+					type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+			}
+			if (type == 0) {
+				/* Invalid entry type, skip entry */
+				ret = ARCHIVE_WARN;
+				continue;
+			}
+			isint(field[4 + n].start, field[4 + n].end,
+			    &id);
+		}
 
 		/* Add entry to the internal list. */
 		r = archive_acl_add_entry_len_l(acl, type, permset,
@@ -1154,7 +1856,12 @@ archive_acl_parse_l(struct archive_acl *acl,
 			return (r);
 		if (r != ARCHIVE_OK)
 			ret = ARCHIVE_WARN;
+		types |= type;
 	}
+
+	/* Reset ACL */
+	archive_acl_reset(acl, types);
+
 	return (ret);
 }
 
@@ -1220,6 +1927,112 @@ ismode(const char *start, const char *end, int *permset)
 }
 
 /*
+ * Parse a string as a NFS4 ACL permission field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * permission characters, false otherwise
+ */
+static int
+is_nfs4_perms(const char *start, const char *end, int *permset)
+{
+	const char *p = start;
+
+	while (p < end) {
+		switch (*p++) {
+		case 'r':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_DATA;
+			break;
+		case 'w':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA;
+			break;
+		case 'x':
+			*permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
+			break;
+		case 'p':
+			*permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA;
+			break;
+		case 'D':
+			*permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD;
+			break;
+		case 'd':
+			*permset |= ARCHIVE_ENTRY_ACL_DELETE;
+			break;
+		case 'a':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES;
+			break;
+		case 'A':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES;
+			break;
+		case 'R':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS;
+			break;
+		case 'W':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS;
+			break;
+		case 'c':
+			*permset |= ARCHIVE_ENTRY_ACL_READ_ACL;
+			break;
+		case 'C':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL;
+			break;
+		case 'o':
+			*permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+			break;
+		case 's':
+			*permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+			break;
+		case '-':
+			break;
+		default:
+			return(0);
+		}
+	}
+	return (1);
+}
+
+/*
+ * Parse a string as a NFS4 ACL flags field.
+ * Returns true if the string is non-empty and consists only of NFS4 ACL
+ * flag characters, false otherwise
+ */
+static int
+is_nfs4_flags(const char *start, const char *end, int *permset)
+{
+	const char *p = start;
+
+	while (p < end) {
+		switch(*p++) {
+		case 'f':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT;
+			break;
+		case 'd':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT;
+			break;
+		case 'i':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY;
+			break;
+		case 'n':
+			*permset |=
+			    ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT;
+			break;
+		case 'S':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS;
+			break;
+		case 'F':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS;
+			break;
+		case 'I':
+			*permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED;
+			break;
+		case '-':
+			break;
+		default:
+			return (0);
+		}
+	}
+	return (1);
+}
+
+/*
  * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]".  *wp is updated
  * to point to just after the separator.  *start points to the first
  * character of the matched text and *end just after the last
@@ -1254,25 +2067,3 @@ next_field(const char **p, const char **start,
 	if (**p != '\0')
 		(*p)++;
 }
-
-/*
- * Return true if the characters [start...end) are a prefix of 'test'.
- * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
- */
-static int
-prefix_c(const char *start, const char *end, const char *test)
-{
-	if (start == end)
-		return (0);
-
-	if (*start++ != *test++)
-		return (0);
-
-	while (start < end  &&  *start++ == *test++)
-		;
-
-	if (start < end)
-		return (0);
-
-	return (1);
-}
diff --git a/Utilities/cmlibarchive/libarchive/archive_acl_private.h b/Utilities/cmlibarchive/libarchive/archive_acl_private.h
index 1421adb..ef0b023 100644
--- a/Utilities/cmlibarchive/libarchive/archive_acl_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_acl_private.h
@@ -56,6 +56,7 @@ struct archive_acl {
 void archive_acl_clear(struct archive_acl *);
 void archive_acl_copy(struct archive_acl *, struct archive_acl *);
 int archive_acl_count(struct archive_acl *, int);
+int archive_acl_types(struct archive_acl *);
 int archive_acl_reset(struct archive_acl *, int);
 int archive_acl_next(struct archive *, struct archive_acl *, int,
     int *, int *, int *, int *, const char **);
@@ -66,22 +67,17 @@ int archive_acl_add_entry_w_len(struct archive_acl *,
 int archive_acl_add_entry_len(struct archive_acl *,
     int, int, int, int, const char *, size_t);
 
-const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int);
-int archive_acl_text_l(struct archive_acl *, int, const char **, size_t *,
+wchar_t *archive_acl_to_text_w(struct archive_acl *, ssize_t *, int,
+    struct archive *);
+char *archive_acl_to_text_l(struct archive_acl *, ssize_t *, int,
     struct archive_string_conv *);
 
 /*
- * Private ACL parser.  This is private because it handles some
- * very weird formats that clients should not be messing with.
- * Clients should only deal with their platform-native formats.
- * Because of the need to support many formats cleanly, new arguments
- * are likely to get added on a regular basis.  Clients who try to use
- * this interface are likely to be surprised when it changes.
+ * ACL text parser.
  */
-int archive_acl_parse_w(struct archive_acl *,
-		    const wchar_t *, int /* type */);
-int archive_acl_parse_l(struct archive_acl *,
-		    const char *, int /* type */,
-		    struct archive_string_conv *);
+int archive_acl_from_text_w(struct archive_acl *, const wchar_t * /* wtext */,
+    int /* type */);
+int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
+    int /* type */, struct archive_string_conv *);
 
 #endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
diff --git a/Utilities/cmlibarchive/libarchive/archive_cryptor.c b/Utilities/cmlibarchive/libarchive/archive_cryptor.c
index 2a51dfe..ced52fd 100644
--- a/Utilities/cmlibarchive/libarchive/archive_cryptor.c
+++ b/Utilities/cmlibarchive/libarchive/archive_cryptor.c
@@ -302,7 +302,8 @@ aes_ctr_release(archive_crypto_ctx *ctx)
 static int
 aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
 {
-	ctx->ctx = EVP_CIPHER_CTX_new();
+	if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL)
+		return -1;
 
 	switch (key_len) {
 	case 16: ctx->type = EVP_aes_128_ecb(); break;
diff --git a/Utilities/cmlibarchive/libarchive/archive_digest_private.h b/Utilities/cmlibarchive/libarchive/archive_digest_private.h
index b58ffb3..b4fd6ca 100644
--- a/Utilities/cmlibarchive/libarchive/archive_digest_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_digest_private.h
@@ -143,6 +143,7 @@
   defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
   defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
   defined(ARCHIVE_CRYPTO_SHA512_WIN)
+#include <windows.h>
 #include <wincrypt.h>
 typedef struct {
   int   valid;
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.c b/Utilities/cmlibarchive/libarchive/archive_entry.c
index 4ac1966..10eff11 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -248,10 +249,9 @@ archive_entry_new2(struct archive *a)
 {
 	struct archive_entry *entry;
 
-	entry = (struct archive_entry *)malloc(sizeof(*entry));
+	entry = (struct archive_entry *)calloc(1, sizeof(*entry));
 	if (entry == NULL)
 		return (NULL);
-	memset(entry, 0, sizeof(*entry));
 	entry->archive = a;
 	return (entry);
 }
@@ -1442,6 +1442,15 @@ archive_entry_acl_add_entry_w(struct archive_entry *entry,
 }
 
 /*
+ * Return a bitmask of ACL types in an archive entry ACL list
+ */
+int
+archive_entry_acl_types(struct archive_entry *entry)
+{
+	return (archive_acl_types(&entry->acl));
+}
+
+/*
  * Return a count of entries matching "want_type".
  */
 int
@@ -1478,34 +1487,121 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
 }
 
 /*
- * Generate a text version of the ACL.  The flags parameter controls
+ * Generate a text version of the ACL. The flags parameter controls
  * the style of the generated ACL.
  */
+wchar_t *
+archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
+    int flags)
+{
+	return (archive_acl_to_text_w(&entry->acl, len, flags,
+	    entry->archive));
+}
+
+char *
+archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
+    int flags)
+{
+	return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
+}
+
+char *
+_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
+   int flags, struct archive_string_conv *sc)
+{
+	return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
+}
+
+/*
+ * ACL text parser.
+ */
+int
+archive_entry_acl_from_text_w(struct archive_entry *entry,
+    const wchar_t *wtext, int type)
+{
+	return (archive_acl_from_text_w(&entry->acl, wtext, type));
+}
+
+int
+archive_entry_acl_from_text(struct archive_entry *entry,
+    const char *text, int type)
+{
+	return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
+}
+
+int
+_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
+    int type, struct archive_string_conv *sc)
+{
+	return (archive_acl_from_text_l(&entry->acl, text, type, sc));
+}
+
+/* Deprecated */
+static int
+archive_entry_acl_text_compat(int *flags)
+{
+	if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
+		return (1);
+
+	/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
+	if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
+		*flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
+
+	/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
+	if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
+		*flags |=  ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
+
+	*flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
+
+	return (0);
+}
+
+/* Deprecated */
 const wchar_t *
 archive_entry_acl_text_w(struct archive_entry *entry, int flags)
 {
-	const wchar_t *r;
-	r = archive_acl_text_w(entry->archive, &entry->acl, flags);
-	if (r == NULL && errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (r);
+	if (entry->acl.acl_text_w != NULL) {
+		free(entry->acl.acl_text_w);
+		entry->acl.acl_text_w = NULL;
+	}
+	if (archive_entry_acl_text_compat(&flags) == 0)
+		entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
+		    NULL, flags, entry->archive);
+	return (entry->acl.acl_text_w);
 }
 
+/* Deprecated */
 const char *
 archive_entry_acl_text(struct archive_entry *entry, int flags)
 {
-	const char *p;
-	if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0
-	    && errno == ENOMEM)
-		__archive_errx(1, "No memory");
-	return (p);
+	if (entry->acl.acl_text != NULL) {
+		free(entry->acl.acl_text);
+		entry->acl.acl_text = NULL;
+	}
+	if (archive_entry_acl_text_compat(&flags) == 0)
+		entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
+		    flags, NULL);
+
+	return (entry->acl.acl_text);
 }
 
+/* Deprecated */
 int
 _archive_entry_acl_text_l(struct archive_entry *entry, int flags,
     const char **acl_text, size_t *len, struct archive_string_conv *sc)
 {
-	return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc));
+	if (entry->acl.acl_text != NULL) {
+		free(entry->acl.acl_text);
+		entry->acl.acl_text = NULL;
+        }
+
+	if (archive_entry_acl_text_compat(&flags) == 0)
+		entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
+		    (ssize_t *)len, flags, sc);
+
+	*acl_text = entry->acl.acl_text;
+
+	return (0);
 }
 
 /*
@@ -1553,7 +1649,10 @@ static struct flag {
 	{ "nosappnd",	L"nosappnd",		SF_APPEND,	0 },
 	{ "nosappend",	L"nosappend",		SF_APPEND,	0 },
 #endif
-#ifdef  EXT2_APPEND_FL				/* 'a' */
+#if defined(FS_APPEND_FL)			/* 'a' */
+	{ "nosappnd",	L"nosappnd",		FS_APPEND_FL,	0 },
+	{ "nosappend",	L"nosappend",		FS_APPEND_FL,	0 },
+#elif defined(EXT2_APPEND_FL)			/* 'a' */
 	{ "nosappnd",	L"nosappnd",		EXT2_APPEND_FL,	0 },
 	{ "nosappend",	L"nosappend",		EXT2_APPEND_FL,	0 },
 #endif
@@ -1566,7 +1665,11 @@ static struct flag {
 	{ "noschange",	L"noschange",		SF_IMMUTABLE,	0 },
 	{ "nosimmutable",	L"nosimmutable",	SF_IMMUTABLE,	0 },
 #endif
-#ifdef EXT2_IMMUTABLE_FL			/* 'i' */
+#if defined(FS_IMMUTABLE_FL)			/* 'i' */
+	{ "noschg",	L"noschg",		FS_IMMUTABLE_FL,	0 },
+	{ "noschange",	L"noschange",		FS_IMMUTABLE_FL,	0 },
+	{ "nosimmutable",	L"nosimmutable",	FS_IMMUTABLE_FL,	0 },
+#elif defined(EXT2_IMMUTABLE_FL)		/* 'i' */
 	{ "noschg",	L"noschg",		EXT2_IMMUTABLE_FL,	0 },
 	{ "noschange",	L"noschange",		EXT2_IMMUTABLE_FL,	0 },
 	{ "nosimmutable",	L"nosimmutable",	EXT2_IMMUTABLE_FL,	0 },
@@ -1590,7 +1693,9 @@ static struct flag {
 #ifdef UF_NODUMP
 	{ "nodump",	L"nodump",		0,		UF_NODUMP},
 #endif
-#ifdef EXT2_NODUMP_FL				/* 'd' */
+#if defined(FS_NODUMP_FL)	/* 'd' */
+	{ "nodump",	L"nodump",		0,		FS_NODUMP_FL},
+#elif defined(EXT2_NODUMP_FL) 	/* 'd' */
 	{ "nodump",	L"nodump",		0,		EXT2_NODUMP_FL},
 #endif
 #ifdef UF_OPAQUE
@@ -1603,65 +1708,124 @@ static struct flag {
 #ifdef UF_COMPRESSED
 	{ "nocompressed",L"nocompressed",	UF_COMPRESSED,	0 },
 #endif
-#ifdef EXT2_UNRM_FL
+#if defined(FS_UNRM_FL)
+        { "nouunlink",	L"nouunlink",		FS_UNRM_FL,	0},
+#elif defined(EXT2_UNRM_FL)
         { "nouunlink",	L"nouunlink",		EXT2_UNRM_FL,	0},
 #endif
 
-#ifdef EXT2_BTREE_FL
+#if defined(FS_BTREE_FL)
+        { "nobtree",	L"nobtree",       	FS_BTREE_FL,	0 },
+#elif defined(EXT2_BTREE_FL)
         { "nobtree",	L"nobtree",       	EXT2_BTREE_FL,	0 },
 #endif
 
-#ifdef EXT2_ECOMPR_FL
+#if defined(FS_ECOMPR_FL)
+        { "nocomperr",	L"nocomperr",       	FS_ECOMPR_FL,	0 },
+#elif defined(EXT2_ECOMPR_FL)
         { "nocomperr",	L"nocomperr",       	EXT2_ECOMPR_FL,	0 },
 #endif
 
-#ifdef EXT2_COMPR_FL				/* 'c' */
+#if defined(FS_COMPR_FL)			/* 'c' */
+        { "nocompress",	L"nocompress",       	FS_COMPR_FL,	0 },
+#elif defined(EXT2_COMPR_FL)			/* 'c' */
         { "nocompress",	L"nocompress",       	EXT2_COMPR_FL,	0 },
 #endif
 
-#ifdef EXT2_NOATIME_FL				/* 'A' */
+#if defined(FS_NOATIME_FL)			/* 'A' */
+        { "noatime",	L"noatime",		0,		FS_NOATIME_FL},
+#elif defined(EXT2_NOATIME_FL)			/* 'A' */
         { "noatime",	L"noatime",		0,		EXT2_NOATIME_FL},
 #endif
 
-#ifdef EXT2_DIRTY_FL
+#if defined(FS_DIRTY_FL)
+        { "nocompdirty",L"nocompdirty",		FS_DIRTY_FL,		0},
+#elif defined(EXT2_DIRTY_FL)
         { "nocompdirty",L"nocompdirty",		EXT2_DIRTY_FL,		0},
 #endif
 
-#ifdef EXT2_COMPRBLK_FL
-#ifdef EXT2_NOCOMPR_FL
+#if defined(FS_COMPRBLK_FL)
+#if defined(FS_NOCOMPR_FL)
+        { "nocomprblk",	L"nocomprblk",		FS_COMPRBLK_FL, FS_NOCOMPR_FL},
+#else
+        { "nocomprblk",	L"nocomprblk",		FS_COMPRBLK_FL,	0},
+#endif
+#elif defined(EXT2_COMPRBLK_FL)
+#if defined(EXT2_NOCOMPR_FL)
         { "nocomprblk",	L"nocomprblk",		EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL},
 #else
         { "nocomprblk",	L"nocomprblk",		EXT2_COMPRBLK_FL,	0},
 #endif
 #endif
-#ifdef EXT2_DIRSYNC_FL
+#if defined(FS_DIRSYNC_FL)
+        { "nodirsync",	L"nodirsync",		FS_DIRSYNC_FL,	0},
+#elif defined(EXT2_DIRSYNC_FL)
         { "nodirsync",	L"nodirsync",		EXT2_DIRSYNC_FL,	0},
 #endif
-#ifdef EXT2_INDEX_FL
+#if defined(FS_INDEX_FL)
+        { "nohashidx",	L"nohashidx",		FS_INDEX_FL,		0},
+#elif defined(EXT2_INDEX_FL)
         { "nohashidx",	L"nohashidx",		EXT2_INDEX_FL,		0},
 #endif
-#ifdef EXT2_IMAGIC_FL
+#if defined(FS_IMAGIC_FL)
+        { "noimagic",	L"noimagic",		FS_IMAGIC_FL,		0},
+#elif defined(EXT2_IMAGIC_FL)
         { "noimagic",	L"noimagic",		EXT2_IMAGIC_FL,		0},
 #endif
-#ifdef EXT3_JOURNAL_DATA_FL
+#if defined(FS_JOURNAL_DATA_FL)
+        { "nojournal",	L"nojournal",		FS_JOURNAL_DATA_FL,	0},
+#elif defined(EXT3_JOURNAL_DATA_FL)
         { "nojournal",	L"nojournal",		EXT3_JOURNAL_DATA_FL,	0},
 #endif
-#ifdef EXT2_SECRM_FL
+#if defined(FS_SECRM_FL)
+        { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL,		0},
+#elif defined(EXT2_SECRM_FL)
         { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL,		0},
 #endif
-#ifdef EXT2_SYNC_FL
+#if defined(FS_SYNC_FL)
+        { "nosync",	L"nosync",		FS_SYNC_FL,		0},
+#elif defined(EXT2_SYNC_FL)
         { "nosync",	L"nosync",		EXT2_SYNC_FL,		0},
 #endif
-#ifdef EXT2_NOTAIL_FL
+#if defined(FS_NOTAIL_FL)
+        { "notail",	L"notail",		0,		FS_NOTAIL_FL},
+#elif defined(EXT2_NOTAIL_FL)
         { "notail",	L"notail",		0,		EXT2_NOTAIL_FL},
 #endif
-#ifdef EXT2_TOPDIR_FL
+#if defined(FS_TOPDIR_FL)
+        { "notopdir",	L"notopdir",		FS_TOPDIR_FL,		0},
+#elif defined(EXT2_TOPDIR_FL)
         { "notopdir",	L"notopdir",		EXT2_TOPDIR_FL,		0},
 #endif
-#ifdef EXT2_RESERVED_FL
+#ifdef FS_ENCRYPT_FL
+        { "noencrypt",	L"noencrypt",		FS_ENCRYPT_FL,	0},
+#endif
+#ifdef FS_HUGE_FILE_FL
+        { "nohugefile",	L"nohugefile",		FS_HUGE_FILE_FL,	0},
+#endif
+#ifdef FS_EXTENT_FL
+        { "noextent",	L"noextent",		FS_EXTENT_FL,	0},
+#endif
+#ifdef FS_EA_INODE_FL
+        { "noeainode",	L"noeainode",		FS_EA_INODE_FL,	0},
+#endif
+#ifdef FS_EOFBLOCKS_FL
+        { "noeofblocks",L"noeofblocks",		FS_EOFBLOCKS_FL,	0},
+#endif
+#ifdef FS_NOCOW_FL
+        { "nocow",	L"nocow",		FS_NOCOW_FL,	0},
+#endif
+#ifdef FS_INLINE_DATA_FL
+        { "noinlinedata",L"noinlinedata",	FS_INLINE_DATA_FL,	0},
+#endif
+#ifdef FS_PROJINHERIT_FL
+        { "noprojinherit",L"noprojinherit",	FS_PROJINHERIT_FL,	0},
+#endif
+#if defined(FS_RESERVED_FL)
+        { "noreserved",	L"noreserved",		FS_RESERVED_FL,	0},
+#elif defined(EXT2_RESERVED_FL)
         { "noreserved",	L"noreserved",		EXT2_RESERVED_FL,	0},
 #endif
-
 	{ NULL,		NULL,			0,		0 }
 };
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h
index 81cd425..6e0225b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.h
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.h
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2003-2008 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,7 +30,7 @@
 #define	ARCHIVE_ENTRY_H_INCLUDED
 
 /* Note: Compiler will complain if this does not match archive.h! */
-#define	ARCHIVE_VERSION_NUMBER 3002001
+#define	ARCHIVE_VERSION_NUMBER 3003001
 
 /*
  * Note: archive_entry.h is for use outside of libarchive; the
@@ -65,6 +66,27 @@ typedef int64_t la_int64_t;
 # endif
 #endif
 
+/* The la_ssize_t should match the type used in 'struct stat' */
+#if !defined(__LA_SSIZE_T_DEFINED)
+/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_SSIZE_T la_ssize_t
+# endif
+#define __LA_SSIZE_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+#  if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
+typedef ssize_t la_ssize_t;
+#  elif defined(_WIN64)
+typedef __int64 la_ssize_t;
+#  else
+typedef long la_ssize_t;
+#  endif
+# else
+# include <unistd.h>  /* ssize_t */
+typedef ssize_t la_ssize_t;
+# endif
+#endif
+
 /* Get a suitable definition for mode_t */
 #if ARCHIVE_VERSION_NUMBER >= 3999000
 /* Switch to plain 'int' for libarchive 4.0.  It's less broken than 'mode_t' */
@@ -104,6 +126,9 @@ typedef int64_t la_int64_t;
 # define __LA_DECL
 #endif
 
+/* CMake uses some deprecated APIs to build with old libarchive versions.  */
+#define __LA_DEPRECATED
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -420,6 +445,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
 /*
  * Inheritance values (NFS4 ACLs only); included in permset.
  */
+#define	ARCHIVE_ENTRY_ACL_ENTRY_INHERITED                   0x01000000
 #define	ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT                0x02000000
 #define	ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT           0x04000000
 #define	ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT        0x08000000
@@ -433,15 +459,16 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
 	    | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT	\
 	    | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY		\
 	    | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS		\
-	    | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS)
+	    | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS		\
+	    | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED)
 
 /* We need to be able to specify combinations of these. */
-#define	ARCHIVE_ENTRY_ACL_TYPE_ACCESS	256  /* POSIX.1e only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_DEFAULT	512  /* POSIX.1e only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_ALLOW	1024 /* NFS4 only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_DENY	2048 /* NFS4 only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_AUDIT	4096 /* NFS4 only */
-#define	ARCHIVE_ENTRY_ACL_TYPE_ALARM	8192 /* NFS4 only */
+#define	ARCHIVE_ENTRY_ACL_TYPE_ACCESS	0x00000100  /* POSIX.1e only */
+#define	ARCHIVE_ENTRY_ACL_TYPE_DEFAULT	0x00000200  /* POSIX.1e only */
+#define	ARCHIVE_ENTRY_ACL_TYPE_ALLOW	0x00000400 /* NFS4 only */
+#define	ARCHIVE_ENTRY_ACL_TYPE_DENY	0x00000800 /* NFS4 only */
+#define	ARCHIVE_ENTRY_ACL_TYPE_AUDIT	0x00001000 /* NFS4 only */
+#define	ARCHIVE_ENTRY_ACL_TYPE_ALARM	0x00002000 /* NFS4 only */
 #define	ARCHIVE_ENTRY_ACL_TYPE_POSIX1E	(ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
 	    | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
 #define	ARCHIVE_ENTRY_ACL_TYPE_NFS4	(ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
@@ -492,21 +519,51 @@ __LA_DECL int	 archive_entry_acl_next_w(struct archive_entry *, int /* want_type
  * Construct a text-format ACL.  The flags argument is a bitmask that
  * can include any of the following:
  *
+ * Flags only for archive entries with POSIX.1e ACL:
  * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
  * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
- * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries.
- * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
- *    each ACL entry.  ('star' introduced this for POSIX.1e, this flag
- *    also applies to NFS4.)
  * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
- *    default ACL entry, as used in old Solaris ACLs.
+ *    default ACL entry.
+ * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and
+ *    "mask" entries.
+ *
+ * Flags only for archive entries with NFSv4 ACL:
+ * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for
+ *    unset permissions and flags in NFSv4 ACL permission and flag fields
+ *
+ * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL:
+ * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
+ *    each ACL entry.
+ * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma
+ *    instead of newline.
  */
-#define	ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID	1024
-#define	ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT	2048
+#define	ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID	0x00000001
+#define	ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT	0x00000002
+#define	ARCHIVE_ENTRY_ACL_STYLE_SOLARIS		0x00000004
+#define	ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA	0x00000008
+#define	ARCHIVE_ENTRY_ACL_STYLE_COMPACT		0x00000010
+
+__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
+	    la_ssize_t * /* len */, int /* flags */);
+__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
+	    la_ssize_t * /* len */, int /* flags */);
+__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
+	    const wchar_t * /* wtext */, int /* type */);
+__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
+	    const char * /* text */, int /* type */);
+
+/* Deprecated constants */
+#define	OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID		1024
+#define	OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT	2048
+
+/* Deprecated functions */
 __LA_DECL const wchar_t	*archive_entry_acl_text_w(struct archive_entry *,
-		    int /* flags */);
+		    int /* flags */) __LA_DEPRECATED;
 __LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
-		    int /* flags */);
+		    int /* flags */) __LA_DEPRECATED;
+
+/* Return bitmask of ACL types in an archive entry */
+__LA_DECL int	 archive_entry_acl_types(struct archive_entry *);
 
 /* Return a count of entries matching 'want_type' */
 __LA_DECL int	 archive_entry_acl_count(struct archive_entry *, int /* want_type */);
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3
index 5aff996..c5115f7 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3
@@ -1,4 +1,5 @@
 .\" Copyright (c) 2010 Joerg Sonnenberger
+.\" Copyright (c) 2016 Martin Matuska
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd February 2, 2012
+.Dd February 15, 2017
 .Dt ARCHIVE_ENTRY_ACL 3
 .Os
 .Sh NAME
@@ -30,10 +31,14 @@
 .Nm archive_entry_acl_add_entry_w ,
 .Nm archive_entry_acl_clear ,
 .Nm archive_entry_acl_count ,
+.Nm archive_entry_acl_from_text ,
+.Nm archive_entry_acl_from_text_w,
 .Nm archive_entry_acl_next ,
 .Nm archive_entry_acl_next_w ,
 .Nm archive_entry_acl_reset ,
-.Nm archive_entry_acl_text_w
+.Nm archive_entry_acl_to_text ,
+.Nm archive_entry_acl_to_text_w ,
+.Nm archive_entry_acl_types
 .Nd functions for manipulating Access Control Lists in archive entry descriptions
 .Sh LIBRARY
 Streaming Archive Library (libarchive, -larchive)
@@ -62,6 +67,18 @@ Streaming Archive Library (libarchive, -larchive)
 .Ft int
 .Fn archive_entry_acl_count "struct archive_entry *a" "int type"
 .Ft int
+.Fo archive_entry_acl_from_text
+.Fa "struct archive_entry *a"
+.Fa "const char *text"
+.Fa "int type"
+.Fc
+.Ft int
+.Fo archive_entry_acl_from_text_w
+.Fa "struct archive_entry *a"
+.Fa "const wchar_t *text"
+.Fa "int type"
+.Fc
+.Ft int
 .Fo archive_entry_acl_next
 .Fa "struct archive_entry *a"
 .Fa "int type"
@@ -83,31 +100,48 @@ Streaming Archive Library (libarchive, -larchive)
 .Fc
 .Ft int
 .Fn archive_entry_acl_reset "struct archive_entry *a" "int type"
-.Ft const wchar_t *
-.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags"
+.Ft char *
+.Fo archive_entry_acl_to_text
+.Fa "struct archive_entry *a"
+.Fa "ssize_t *len_p"
+.Fa "int flags"
+.Fc
+.Ft wchar_t *
+.Fo archive_entry_acl_to_text_w
+.Fa "struct archive_entry *a"
+.Fa "ssize_t *len_p"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fn archive_entry_acl_types "struct archive_entry *a"
 .\" enum?
 .Sh DESCRIPTION
-An
-.Dq Access Control List
-is a generalisation of the classic Unix permission system.
+The
+.Dq Access Control Lists (ACLs)
+extend the standard Unix perssion model.
 The ACL interface of
 .Nm libarchive
-is derived from the POSIX.1e draft, but restricted to simplify dealing
-with practical implementations in various Operating Systems and archive formats.
-.Pp
-An ACL consists of a number of independent entries.
+supports both POSIX.1e and NFSv4 style ACLs. Use of ACLs is restricted by
+various levels of ACL support in operating systems, file systems and archive
+formats.
+.Ss POSIX.1e Access Control Lists
+A POSIX.1e ACL consists of a number of independent entries.
 Each entry specifies the permission set as bitmask of basic permissions.
-Valid permissions are:
+Valid permissions in the
+.Fa permset
+are:
 .Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE"
-.It Dv ARCHIVE_ENTRY_ACL_EXECUTE
-.It Dv ARCHIVE_ENTRY_ACL_WRITE
-.It Dv ARCHIVE_ENTRY_ACL_READ
+.It Dv ARCHIVE_ENTRY_ACL_READ ( Sy r )
+.It Dv ARCHIVE_ENTRY_ACL_WRITE ( Sy w )
+.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
 .El
 The permissions correspond to the normal Unix permissions.
 .Pp
-The tag specifies the principal to which the permission applies.
+The
+.Fa tag
+specifies the principal to which the permission applies.
 Valid values are:
-.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
+.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
 .It Dv ARCHIVE_ENTRY_ACL_USER
 The user specified by the name field.
 .It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
@@ -119,8 +153,9 @@ The group who owns the file.
 .It Dv ARCHIVE_ENTRY_ACL_MASK
 The maximum permissions to be obtained via group permissions.
 .It Dv ARCHIVE_ENTRY_ACL_OTHER
-Any principal who doesn't have a user or group entry.
+Any principal who is not file owner or a member of the owning group.
 .El
+.Pp
 The principals
 .Dv ARCHIVE_ENTRY_ACL_USER_OBJ ,
 .Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
@@ -129,19 +164,123 @@ and
 are equivalent to user, group and other in the classic Unix permission
 model and specify non-extended ACL entries.
 .Pp
-All files have an access ACL
+All files with have an access ACL
 .Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS .
 This specifies the permissions required for access to the file itself.
 Directories have an additional ACL
 .Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
 which controls the initial access ACL for newly created directory entries.
+.Ss NFSv4 Access Control Lists
+A NFSv4 ACL consists of multiple individual entries called Access Control
+Entries (ACEs).
+.Pp
+There are four possible types of a NFSv4 ACE:
+.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYE_ALLOW"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
+Allow principal to perform actions requiring given permissions.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
+Prevent principal from performing actions requiring given permissions.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
+Log access attempts by principal which require given permissions.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
+Trigger a system alarm on access attempts by principal which require given
+permissions.
+.El
+.Pp
+The
+.Fa tag
+specifies the principal to which the permission applies.
+Valid values are:
+.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
+.It Dv ARCHIVE_ENTRY_ACL_USER
+The user specified by the name field.
+.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
+The owner of the file.
+.It Dv ARCHIVE_ENTRY_ACL_GROUP
+The group specied by the name field.
+.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
+The group who owns the file.
+.It Dv ARCHIVE_ENTRY_ACL_EVERYONE
+Any principal who is not file owner or a member of the owning group.
+.El
+.Pp
+Entries with the
+.Dv ARCHIVE_ENTRY_ACL_USER
+or
+.Dv ARCHIVE_ENTRY_ACL_GROUP
+tag store the user and group name in the
+.Fa name
+string and optionally the user or group ID in the
+.Fa qualifier
+integer.
+.Pp
+NFSv4 ACE permissions and flags are stored in the same
+.Fa permset
+bitfield. Some permissions share the same constant and permission character but
+have different effect on directories than on files. The following ACE
+permissions are supported:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_READ_DATA ( Sy r )
+Read data (file).
+.It Dv ARCHIVE_ENTRY_ACL_LIST_DIRECTORY ( Sy r )
+List entries (directory).
+.It ARCHIVE_ENTRY_ACL_WRITE_DATA ( Sy w )
+Write data (file).
+.It ARCHIVE_ENTRY_ACL_ADD_FILE ( Sy w )
+Create files (directory).
+.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
+Execute file or change into a directory.
+.It Dv ARCHIVE_ENTRY_ACL_APPEND_DATA ( Sy p )
+Append data (file).
+.It Dv ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY ( Sy p )
+Create subdirectories (directory).
+.It Dv ARCHIVE_ENTRY_ACL_DELETE_CHILD ( Sy D )
+Remove files and subdirectories inside a directory.
+.It Dv ARCHIVE_ENTRY_ACL_DELETE ( Sy d )
+Remove file or directory.
+.It Dv ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES ( Sy a )
+Read file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES ( Sy A )
+Write file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS ( Sy R )
+Read named file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS ( Sy W )
+Write named file or directory attributes.
+.It Dv ARCHIVE_ENTRY_ACL_READ_ACL ( Sy c )
+Read file or directory ACL.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_ACL ( Sy C )
+Write file or directory ACL.
+.It Dv ARCHIVE_ENTRY_ACL_WRITE_OWNER ( Sy o )
+Change owner of a file or directory.
+.It Dv ARCHIVE_ENTRY_ACL_SYNCHRONIZE ( Sy s )
+Use synchronous I/O.
+.El
 .Pp
+The following NFSv4 ACL inheritance flags are supported:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT ( Sy f )
+Inherit parent directory ACE to files.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT ( Sy d )
+Inherit parent directory ACE to subdirectories.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY ( Sy i )
+Only inherit, do not apply the permission on the directory itself.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n )
+Do not propagate inherit flags. Only first-level entries inherit ACLs.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S )
+Trigger alarm or audit on succesful access.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F )
+Trigger alarm or audit on failed access.
+.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I )
+Mark that ACE was inherited.
+.El
+.Ss Functions
 .Fn archive_entry_acl_add_entry
 and
 .Fn archive_entry_acl_add_entry_w
 add a single ACL entry.
 For the access ACL and non-extended principals, the classic Unix permissions
-are updated.
+are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
+entries.
 .Pp
 .Fn archive_entry_acl_clear
 removes all ACL entries and resets the enumeration pointer.
@@ -150,14 +289,58 @@ removes all ACL entries and resets the enumeration pointer.
 counts the ACL entries that have the given type mask.
 .Fa type
 can be the bitwise-or of
-.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
-and
-.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT .
-If
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+.El
+for POSIX.1e ACLs and
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_ALLOW"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
+.El
+for NFSv4 ACLs. For POSIX.1e ACLs if
 .Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
 is included and at least one extended ACL entry is found,
 the three non-extened ACLs are added.
 .Pp
+.Fn archive_entry_acl_from_text
+and
+.Fn archive_entry_acl_from_text_w
+add new
+.Pq or merge with existing
+ACL entries from
+.Pq wide
+text. The argument
+.Fa type
+may take one of the following values:
+.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4
+.El
+Supports all formats that can be created with
+.Fn archive_entry_acl_to_text
+or respective
+.Fn archive_entry_acl_to_text_w .
+Existing ACL entries are preserved. To get a clean new ACL from text
+.Fn archive_entry_acl_clear
+must be called first. Entries prefixed with
+.Dq default:
+are treated as
+.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+unless
+.Fa type
+is
+.Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 .
+Invalid entries, non-parseable ACL entries and entries beginning with
+the
+.Sq #
+character
+.Pq comments
+are skipped.
+.Pp
 .Fn archive_entry_acl_next
 and
 .Fn archive_entry_acl_next_w
@@ -179,29 +362,81 @@ or set using
 Otherwise, the function returns the same value as
 .Fn archive_entry_acl_count .
 .Pp
-.Fn archive_entry_acl_text_w
-converts the ACL entries for the given type mask into a wide string.
-In addition to the normal type flags,
-.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
+.Fn archive_entry_acl_to_text
 and
-.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
-can be specified to further customize the result.
-The returned long string is valid until the next call to
-.Fn archive_entry_acl_clear ,
-.Fn archive_entry_acl_add_entry ,
-.Fn archive_entry_acl_add_entry_w
+.Fn archive_entry_acl_to_text_w
+convert the ACL entries for the given type into a
+.Pq wide
+string of ACL entries separated by newline. If the the pointer
+.Fa len_p
+is not NULL, then the function shall return the length of the string
+.Pq not including the NULL terminator
+in the location pointed to by
+.Fa len_p .
+The
+.Fa flag
+argument is a bitwise-or.
+.Pp
+The following flags are effective only on POSIX.1e ACL:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
+Output access ACLs.
+.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+Output POSIX.1e default ACLs.
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
+Prefix each default ACL entry with the word
+.Dq default: .
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_SOLARIS
+The mask and other ACLs don not contain a double colon.
+.El
+.Pp
+The following flags are effecive only on NFSv4 ACL:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_COMPACT
+Do not output minus characters for unset permissions and flags in NFSv4 ACL
+permission and flag fields.
+.El
+.Pp
+The following flags are effective on both POSIX.1e and NFSv4 ACL:
+.Bl -tag -offset indent -compact -width ARCHIV
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
+Add an additional colon-separated field containing the user or group id.
+.It Dv ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
+Separate ACL entries with comma instead of newline.
+.El
+.Pp
+If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned.
+It the entry contains POSIX.1e ACLs and none of the flags
+.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
 or
-.Fn archive_entry_acl_text_w .
+.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
+are specified, both access and default entries are returned and default entries
+are prefixed with
+.Dq default: .
+.Pp
+.Fn archive_entry_acl_types
+get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4
+ACL entries cannot be mixed, this function is a very efficient way to detect if
+an ACL already contains POSIX.1e or NFSv4 ACL entries.
 .Sh RETURN VALUES
 .Fn archive_entry_acl_count
 and
 .Fn archive_entry_acl_reset
 returns the number of ACL entries that match the given type mask.
-If the type mask includes
+For POSIX.1e ACLS if the type mask includes
 .Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
 and at least one extended ACL entry exists, the three classic Unix
 permissions are counted.
 .Pp
+.Fn archive_entry_acl_from_text
+and
+.Fn archive_entry_acl_from_text_w
+return
+.Dv ARCHIVE_OK
+if all entries were successfully parsed and
+.Dv ARCHIVE_WARN
+if one or more entries were invalid or non-parseable.
+.Pp
 .Fn archive_entry_acl_next
 and
 .Fn archive_entry_acl_next_w
@@ -216,20 +451,16 @@ if
 .Fn archive_entry_acl_reset
 has not been called first.
 .Pp
-.Fn archive_entry_text_w
-returns a wide string representation of the ACL entrise matching the
-given type mask.
-The returned long string is valid until the next call to
-.Fn archive_entry_acl_clear ,
-.Fn archive_entry_acl_add_entry ,
-.Fn archive_entry_acl_add_entry_w
-or
-.Fn archive_entry_acl_text_w .
+.Fn archive_entry_acl_to_text
+returns a string representing the ACL entries matching the given type and
+flags on success or NULL on error.
+.Pp
+.Fn archive_entry_acl_to_text_w
+returns a wide string representing the ACL entries matching the given type
+and flags on success or NULL on error.
+.Pp
+.Fn archive_entry_acl_types
+returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries.
 .Sh SEE ALSO
-.Xr archive_entry 3
-.Xr libarchive 3 ,
-.Sh BUGS
-.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
-and
-.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
-are not documented.
+.Xr archive_entry 3 ,
+.Xr libarchive 3
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_locale.h b/Utilities/cmlibarchive/libarchive/archive_entry_locale.h
index 02e024a..44550c5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_locale.h
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_locale.h
@@ -63,9 +63,13 @@ int _archive_entry_uname_l(struct archive_entry *,
     const char **, size_t *, struct archive_string_conv *);
 #define archive_entry_acl_text_l _archive_entry_acl_text_l
 int _archive_entry_acl_text_l(struct archive_entry *, int,
-    const char **, size_t *, struct archive_string_conv *);
-
-
+const char **, size_t *, struct archive_string_conv *) __LA_DEPRECATED;
+#define archive_entry_acl_to_text_l _archive_entry_acl_to_text_l
+char *_archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int,
+    struct archive_string_conv *);
+#define archive_entry_acl_from_text_l _archive_entry_acl_from_text_l
+int _archive_entry_acl_from_text_l(struct archive_entry *, const char* text,
+    int type, struct archive_string_conv *);
 #define archive_entry_copy_gname_l	_archive_entry_copy_gname_l
 int _archive_entry_copy_gname_l(struct archive_entry *,
     const char *, size_t, struct archive_string_conv *);
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c b/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c
index 16cb3f7..af2517a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_strmode.c
@@ -80,7 +80,7 @@ archive_entry_strmode(struct archive_entry *entry)
 		if (mode & 0001) bp[9] = 't';
 		else bp[9] = 'T';
 	}
-	if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS))
+	if (archive_entry_acl_types(entry) != 0)
 		bp[10] = '+';
 
 	return (bp);
diff --git a/Utilities/cmlibarchive/libarchive/archive_hmac.c b/Utilities/cmlibarchive/libarchive/archive_hmac.c
index 1e0ae28..f299655 100644
--- a/Utilities/cmlibarchive/libarchive/archive_hmac.c
+++ b/Utilities/cmlibarchive/libarchive/archive_hmac.c
@@ -76,6 +76,10 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
 
 #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
 
+#ifndef BCRYPT_HASH_REUSABLE_FLAG
+# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020
+#endif
+
 static int
 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
 {
diff --git a/Utilities/cmlibarchive/libarchive/archive_match.c b/Utilities/cmlibarchive/libarchive/archive_match.c
index 4c41bad..be72066 100644
--- a/Utilities/cmlibarchive/libarchive/archive_match.c
+++ b/Utilities/cmlibarchive/libarchive/archive_match.c
@@ -471,7 +471,7 @@ archive_match_path_excluded(struct archive *_a,
 }
 
 /*
- * Utilty functions to get statistic information for inclusion patterns.
+ * Utility functions to get statistic information for inclusion patterns.
  */
 int
 archive_match_path_unmatched_inclusions(struct archive *_a)
@@ -655,7 +655,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
 		}
 	}
 
-	/* If something error happend, report it immediately. */ 
+	/* If an error occurred, report it immediately. */
 	if (r < ARCHIVE_OK) {
 		archive_copy_error(&(a->archive), ar);
 		archive_read_free(ar);
@@ -1270,7 +1270,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
 #endif /* _WIN32 && !__CYGWIN__ */
 
 /*
- * Call back funtions for archive_rb.
+ * Call back functions for archive_rb.
  */
 static int
 cmp_node_mbs(const struct archive_rb_node *n1,
@@ -1405,7 +1405,7 @@ add_entry(struct archive_match *a, int flag,
 			&(a->exclusion_tree), pathname);
 
 		/*
-		 * We always overwrite comparison condision.
+		 * We always overwrite comparison condition.
 		 * If you do not want to overwrite it, you should not
 		 * call archive_match_exclude_entry(). We cannot know
 		 * what behavior you really expect since overwriting
@@ -1481,7 +1481,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
 			if (nsec == a->older_ctime_nsec &&
 			    (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
 			      == 0)
-				return (1); /* Eeual, skip it. */
+				return (1); /* Equal, skip it. */
 		}
 	}
 	if (a->newer_mtime_filter) {
@@ -1513,7 +1513,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
 		}
 	}
 
-	/* If there is no excluson list, include the file. */
+	/* If there is no exclusion list, include the file. */
 	if (a->exclusion_entry_list.count == 0)
 		return (0);
 
@@ -1700,7 +1700,7 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
 			break;
 	}
 
-	/* Add oowner id. */
+	/* Add owner id. */
 	if (i == ids->count)
 		ids->ids[ids->count++] = id;
 	else if (ids->ids[i] != id) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h b/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
index 0e97e27..43a3ccc 100644
--- a/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_openssl_evp_private.h
@@ -33,10 +33,7 @@
 #include <string.h> /* memset */
 static inline EVP_MD_CTX *EVP_MD_CTX_new(void)
 {
-	EVP_MD_CTX *ctx = (EVP_MD_CTX *)malloc(sizeof(EVP_MD_CTX));
-	if (ctx != NULL) {
-		memset(ctx, 0, sizeof(*ctx));
-	}
+	EVP_MD_CTX *ctx = (EVP_MD_CTX *)calloc(1, sizeof(EVP_MD_CTX));
 	return ctx;
 }
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h b/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h
index d4ae0d1..2deeb5f 100644
--- a/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h
@@ -33,11 +33,7 @@
 #include <string.h> /* memset */
 static inline HMAC_CTX *HMAC_CTX_new(void)
 {
-	HMAC_CTX *ctx = (HMAC_CTX *)malloc(sizeof(HMAC_CTX));
-	if (ctx != NULL) {
-		memset(ctx, 0, sizeof(*ctx));
-		HMAC_CTX_init(ctx);
-	}
+	HMAC_CTX *ctx = (HMAC_CTX *)calloc(1, sizeof(HMAC_CTX));
 	return ctx;
 }
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_options.c b/Utilities/cmlibarchive/libarchive/archive_options.c
index dbf3e80..6496025 100644
--- a/Utilities/cmlibarchive/libarchive/archive_options.c
+++ b/Utilities/cmlibarchive/libarchive/archive_options.c
@@ -26,6 +26,10 @@
 #include "archive_platform.h"
 __FBSDID("$FreeBSD$");
 
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
 #include "archive_options_private.h"
 
 static const char *
@@ -105,8 +109,11 @@ _archive_set_options(struct archive *a, const char *options,
 	if (options == NULL || options[0] == '\0')
 		return ARCHIVE_OK;
 
-	data = (char *)malloc(strlen(options) + 1);
-	strcpy(data, options);
+	if ((data = strdup(options)) == NULL) {
+		archive_set_error(a,
+		    ENOMEM, "Out of memory adding file to list");
+		return (ARCHIVE_FATAL);
+	}
 	s = (const char *)data;
 
 	do {
diff --git a/Utilities/cmlibarchive/libarchive/archive_platform.h b/Utilities/cmlibarchive/libarchive/archive_platform.h
index 08a384c..47d144b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_platform.h
+++ b/Utilities/cmlibarchive/libarchive/archive_platform.h
@@ -152,8 +152,25 @@
  * acl_set_file(), and ACL_USER, we assume it has the rest of the
  * POSIX.1e draft functions used in archive_read_extract.c.
  */
-#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER
+#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
+#if HAVE_ACL_USER
 #define	HAVE_POSIX_ACL	1
+#elif HAVE_ACL_TYPE_EXTENDED
+#define HAVE_DARWIN_ACL 1
+#endif
+#endif
+
+/*
+ * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
+ * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
+ */
+#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
+#define	HAVE_SUN_ACL	1
+#endif
+
+/* Define if platform supports NFSv4 ACLs */
+#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL
+#define HAVE_NFS4_ACL	1
 #endif
 
 /*
@@ -164,6 +181,15 @@
 #define	CAN_RESTORE_METADATA_FD
 #endif
 
+/*
+ * glibc 2.24 deprecates readdir_r
+ */
+#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24))
+#define	USE_READDIR_R	1
+#else
+#undef	USE_READDIR_R
+#endif
+
 /* Set up defaults for internal error codes. */
 #ifndef ARCHIVE_ERRNO_FILE_FORMAT
 #if HAVE_EFTYPE
diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h b/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
index 3a6b9eb..06c99e8 100644
--- a/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
@@ -19,7 +19,7 @@ If you need the compatibility with original PPMd var.H, you can use external Ran
 #define PPMD7_MAX_ORDER 64
 
 #define PPMD7_MIN_MEM_SIZE (1 << 11)
-#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
+#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFFu - 12 * 3)
 
 struct CPpmd7_Context_;
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_random.c b/Utilities/cmlibarchive/libarchive/archive_random.c
index fcea6c6..90ee7c6 100644
--- a/Utilities/cmlibarchive/libarchive/archive_random.c
+++ b/Utilities/cmlibarchive/libarchive/archive_random.c
@@ -80,7 +80,7 @@ archive_random(void *buf, size_t nbytes)
 
 	success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
 	    CRYPT_VERIFYCONTEXT);
-	if (!success && GetLastError() == NTE_BAD_KEYSET) {
+	if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) {
 		success = CryptAcquireContext(&hProv, NULL, NULL,
 		    PROV_RSA_FULL, CRYPT_NEWKEYSET);
 	}
diff --git a/Utilities/cmlibarchive/libarchive/archive_rb.c b/Utilities/cmlibarchive/libarchive/archive_rb.c
index 5b5da20..cf58ac3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_rb.c
+++ b/Utilities/cmlibarchive/libarchive/archive_rb.c
@@ -312,7 +312,7 @@ __archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt,
 		father = RB_FATHER(self);
 		if (RB_BLACK_P(father)) {
 			/*
-			 * If our greatgrandpa is black, we're done.
+			 * If our great-grandpa is black, we're done.
 			 */
 			return;
 		}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read.c b/Utilities/cmlibarchive/libarchive/archive_read.c
index 0bbacc8..d1feceb 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2
 
 static int	choose_filters(struct archive_read *);
 static int	choose_format(struct archive_read *);
+static int	close_filters(struct archive_read *);
 static struct archive_vtable *archive_read_vtable(void);
 static int64_t	_archive_filter_bytes(struct archive *, int);
 static int	_archive_filter_code(struct archive *, int);
@@ -528,7 +529,7 @@ archive_read_open1(struct archive *_a)
 	{
 		slot = choose_format(a);
 		if (slot < 0) {
-			__archive_read_close_filters(a);
+			close_filters(a);
 			a->archive.state = ARCHIVE_STATE_FATAL;
 			return (ARCHIVE_FATAL);
 		}
@@ -582,7 +583,6 @@ choose_filters(struct archive_read *a)
 			/* Verify the filter by asking it for some data. */
 			__archive_read_filter_ahead(a->filter, 1, &avail);
 			if (avail < 0) {
-				__archive_read_close_filters(a);
 				__archive_read_free_filters(a);
 				return (ARCHIVE_FATAL);
 			}
@@ -601,7 +601,6 @@ choose_filters(struct archive_read *a)
 		a->filter = filter;
 		r = (best_bidder->init)(a->filter);
 		if (r != ARCHIVE_OK) {
-			__archive_read_close_filters(a);
 			__archive_read_free_filters(a);
 			return (ARCHIVE_FATAL);
 		}
@@ -765,7 +764,7 @@ archive_read_header_position(struct archive *_a)
  * we cannot say whether there are encrypted entries, then
  * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
  * In general, this function will return values below zero when the
- * reader is uncertain or totally uncapable of encryption support.
+ * reader is uncertain or totally incapable of encryption support.
  * When this function returns 0 you can be sure that the reader
  * supports encryption detection but no encrypted entries have
  * been found yet.
@@ -986,8 +985,8 @@ _archive_read_data_block(struct archive *_a,
 	return (a->format->read_data)(a, buff, size, offset);
 }
 
-int
-__archive_read_close_filters(struct archive_read *a)
+static int
+close_filters(struct archive_read *a)
 {
 	struct archive_read_filter *f = a->filter;
 	int r = ARCHIVE_OK;
@@ -1010,6 +1009,9 @@ __archive_read_close_filters(struct archive_read *a)
 void
 __archive_read_free_filters(struct archive_read *a)
 {
+	/* Make sure filters are closed and their buffers are freed */
+	close_filters(a);
+
 	while (a->filter != NULL) {
 		struct archive_read_filter *t = a->filter->upstream;
 		free(a->filter);
@@ -1052,7 +1054,7 @@ _archive_read_close(struct archive *_a)
 	/* TODO: Clean up the formatters. */
 
 	/* Release the filter objects. */
-	r1 = __archive_read_close_filters(a);
+	r1 = close_filters(a);
 	if (r1 < r)
 		r = r1;
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c b/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c
index f67f1eb..cf821b5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c
@@ -125,7 +125,7 @@ void
 __archive_read_reset_passphrase(struct archive_read *a)
 {
 
-	a->passphrases.candiate = -1;
+	a->passphrases.candidate = -1;
 }
 
 /*
@@ -137,31 +137,31 @@ __archive_read_next_passphrase(struct archive_read *a)
 	struct archive_read_passphrase *p;
 	const char *passphrase;
 
-	if (a->passphrases.candiate < 0) {
+	if (a->passphrases.candidate < 0) {
 		/* Count out how many passphrases we have. */
 		int cnt = 0;
 
 		for (p = a->passphrases.first; p != NULL; p = p->next)
 			cnt++;
-		a->passphrases.candiate = cnt;
+		a->passphrases.candidate = cnt;
 		p = a->passphrases.first;
-	} else if (a->passphrases.candiate > 1) {
+	} else if (a->passphrases.candidate > 1) {
 		/* Rotate a passphrase list. */
-		a->passphrases.candiate--;
+		a->passphrases.candidate--;
 		p = remove_passphrases_from_head(a);
 		add_passphrase_to_tail(a, p);
-		/* Pick a new passphrase candiate up. */
+		/* Pick a new passphrase candidate up. */
 		p = a->passphrases.first;
-	} else if (a->passphrases.candiate == 1) {
-		/* This case is that all cadiates failed to decryption. */
-		a->passphrases.candiate = 0;
+	} else if (a->passphrases.candidate == 1) {
+		/* This case is that all candidates failed to decrypt. */
+		a->passphrases.candidate = 0;
 		if (a->passphrases.first->next != NULL) {
 			/* Rotate a passphrase list. */
 			p = remove_passphrases_from_head(a);
 			add_passphrase_to_tail(a, p);
 		}
 		p = NULL;
-	} else  /* There is no passphrase candaite. */
+	} else  /* There is no passphrase candidate. */
 		p = NULL;
 
 	if (p != NULL)
@@ -177,7 +177,7 @@ __archive_read_next_passphrase(struct archive_read *a)
 			if (p == NULL)
 				return (NULL);
 			insert_passphrase_to_head(a, p);
-			a->passphrases.candiate = 1;
+			a->passphrases.candidate = 1;
 		}
 	} else
 		passphrase = NULL;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
index 3a0d4d6..5e4d163 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
@@ -133,7 +133,6 @@ archive_read_append_filter(struct archive *_a, int code)
     a->filter = filter;
     r2 = (bidder->init)(a->filter);
     if (r2 != ARCHIVE_OK) {
-      __archive_read_close_filters(a);
       __archive_read_free_filters(a);
       return (ARCHIVE_FATAL);
     }
@@ -191,7 +190,6 @@ archive_read_append_filter_program_signature(struct archive *_a,
   a->filter = filter;
   r = (bidder->init)(a->filter);
   if (r != ARCHIVE_OK) {
-    __archive_read_close_filters(a);
     __archive_read_free_filters(a);
     return (ARCHIVE_FATAL);
   }
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk.3 b/Utilities/cmlibarchive/libarchive/archive_read_disk.3
index 525dc59..2a5c130 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk.3
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 2, 2012
+.Dd December 30, 2016
 .Dt ARCHIVE_READ_DISK 3
 .Os
 .Sh NAME
@@ -54,9 +54,9 @@ Streaming Archive Library (libarchive, -larchive)
 .Fn archive_read_disk_set_symlink_physical "struct archive *"
 .Ft int
 .Fn archive_read_disk_set_symlink_hybrid "struct archive *"
-.Ft int
+.Ft const char *
 .Fn archive_read_disk_gname "struct archive *" "gid_t"
-.Ft int
+.Ft const char *
 .Fn archive_read_disk_uname "struct archive *" "uid_t"
 .Ft int
 .Fo archive_read_disk_set_gname_lookup
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 74fe353..b2f1d17 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2003-2009 Tim Kientzle
  * Copyright (c) 2010-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2016 Martin Matuska
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,6 +38,11 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
 #ifdef HAVE_SYS_ACL_H
 #include <sys/acl.h>
 #endif
+#ifdef HAVE_DARWIN_ACL
+#include <membership.h>
+#include <grp.h>
+#include <pwd.h>
+#endif
 #ifdef HAVE_SYS_EXTATTR_H
 #include <sys/extattr.h>
 #endif
@@ -117,6 +123,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
 #define	ACL_GET_PERM acl_get_perm_np
 #endif
 
+/* NFSv4 platform ACL type */
+#if HAVE_SUN_ACL
+#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACE_T
+#elif HAVE_DARWIN_ACL
+#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACL_TYPE_EXTENDED
+#elif HAVE_ACL_TYPE_NFS4
+#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACL_TYPE_NFS4
+#endif
+
 static int setup_acls(struct archive_read_disk *,
     struct archive_entry *, int *fd);
 static int setup_mac_metadata(struct archive_read_disk *,
@@ -125,6 +140,10 @@ static int setup_xattrs(struct archive_read_disk *,
     struct archive_entry *, int *fd);
 static int setup_sparse(struct archive_read_disk *,
     struct archive_entry *, int *fd);
+#if defined(HAVE_LINUX_FIEMAP_H)
+static int setup_sparse_fiemap(struct archive_read_disk *,
+    struct archive_entry *, int *fd);
+#endif
 
 int
 archive_read_disk_entry_from_file(struct archive *_a,
@@ -184,15 +203,17 @@ archive_read_disk_entry_from_file(struct archive *_a,
 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
 	/* On FreeBSD, we get flags for free with the stat. */
 	/* TODO: Does this belong in copy_stat()? */
-	if (st->st_flags != 0)
+	if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0)
 		archive_entry_set_fflags(entry, st->st_flags, 0);
 #endif
 
-#if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+    (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
 	/* Linux requires an extra ioctl to pull the flags.  Although
 	 * this is an extra step, it has a nice side-effect: We get an
 	 * open file descriptor which we can use in the subsequent lookups. */
-	if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
+	if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 &&
+	    (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
 		if (fd < 0) {
 			if (a->tree != NULL)
 				fd = a->open_on_current_dir(a->tree, path,
@@ -204,7 +225,13 @@ archive_read_disk_entry_from_file(struct archive *_a,
 		}
 		if (fd >= 0) {
 			int stflags;
-			r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
+			r = ioctl(fd,
+#if defined(FS_IOC_GETFLAGS)
+			    FS_IOC_GETFLAGS,
+#else
+			    EXT2_IOC_GETFLAGS,
+#endif
+			    &stflags);
 			if (r == 0 && stflags != 0)
 				archive_entry_set_fflags(entry, stflags, 0);
 		}
@@ -250,13 +277,15 @@ archive_read_disk_entry_from_file(struct archive *_a,
 	}
 #endif /* HAVE_READLINK || HAVE_READLINKAT */
 
-	r = setup_acls(a, entry, &fd);
-	if (!a->suppress_xattr) {
+	r = 0;
+	if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
+		r = setup_acls(a, entry, &fd);
+	if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
 		r1 = setup_xattrs(a, entry, &fd);
 		if (r1 < r)
 			r = r1;
 	}
-	if (a->enable_copyfile) {
+	if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
 		r1 = setup_mac_metadata(a, entry, &fd);
 		if (r1 < r)
 			r = r1;
@@ -302,20 +331,17 @@ setup_mac_metadata(struct archive_read_disk *a,
 	name = archive_entry_sourcepath(entry);
 	if (name == NULL)
 		name = archive_entry_pathname(entry);
+	else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
+		archive_set_error(&a->archive, errno,
+			    "Can't change dir to read extended attributes");
+			return (ARCHIVE_FAILED);
+	}
 	if (name == NULL) {
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 		    "Can't open file to read extended attributes: No name");
 		return (ARCHIVE_WARN);
 	}
 
-	if (a->tree != NULL) {
-		if (a->tree_enter_working_dir(a->tree) != 0) {
-			archive_set_error(&a->archive, errno,
-				    "Couldn't change dir");
-				return (ARCHIVE_FAILED);
-		}
-	}
-
 	/* Short-circuit if there's nothing to do. */
 	have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
 	if (have_attrs == -1) {
@@ -400,34 +426,87 @@ setup_mac_metadata(struct archive_read_disk *a,
 }
 #endif
 
+#if HAVE_DARWIN_ACL
+static int translate_guid(struct archive *, acl_entry_t,
+    int *, int *, const char **);
 
-#ifdef HAVE_POSIX_ACL
+static void add_trivial_nfs4_acl(struct archive_entry *);
+#endif
+
+#if HAVE_SUN_ACL
+static int
+sun_acl_is_trivial(acl_t *, mode_t, int *trivialp);
+#endif
+
+#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
 static int translate_acl(struct archive_read_disk *a,
-    struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
+    struct archive_entry *entry,
+#if HAVE_SUN_ACL
+    acl_t *acl,
+#else
+    acl_t acl,
+#endif
+    int archive_entry_acl_type);
 
 static int
 setup_acls(struct archive_read_disk *a,
     struct archive_entry *entry, int *fd)
 {
 	const char	*accpath;
-	acl_t		 acl;
-#if HAVE_ACL_IS_TRIVIAL_NP
-	int		r;
+#if HAVE_SUN_ACL
+	acl_t		*acl;
+#else
+	acl_t		acl;
 #endif
+	int		r;
 
-	accpath = archive_entry_sourcepath(entry);
-	if (accpath == NULL)
-		accpath = archive_entry_pathname(entry);
+	accpath = NULL;
+
+#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP
+	if (*fd < 0)
+#else
+	/* For default ACLs on Linux we need reachable accpath */
+	if (*fd < 0 || S_ISDIR(archive_entry_mode(entry)))
+#endif
+	{
+		accpath = archive_entry_sourcepath(entry);
+		if (accpath == NULL || (a->tree != NULL &&
+		    a->tree_enter_working_dir(a->tree) != 0))
+			accpath = archive_entry_pathname(entry);
+		if (accpath == NULL) {
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+			    "Couldn't determine file path to read ACLs");
+			return (ARCHIVE_WARN);
+		}
+		if (a->tree != NULL &&
+#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP
+		    *fd < 0 &&
+#endif
+		    (a->follow_symlinks ||
+		    archive_entry_filetype(entry) != AE_IFLNK)) {
+			*fd = a->open_on_current_dir(a->tree,
+			    accpath, O_RDONLY | O_NONBLOCK);
+		}
+	}
 
 	archive_entry_acl_clear(entry);
 
-#ifdef ACL_TYPE_NFS4
-	/* Try NFS4 ACL first. */
+	acl = NULL;
+
+#if HAVE_NFS4_ACL
+	/* Try NFSv4 ACL first. */
 	if (*fd >= 0)
+#if HAVE_SUN_ACL
+		/* Solaris reads both POSIX.1e and NFSv4 ACL here */
+		facl_get(*fd, 0, &acl);
+#elif HAVE_ACL_GET_FD_NP
+		acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
+#else
 		acl = acl_get_fd(*fd);
+#endif
 #if HAVE_ACL_GET_LINK_NP
 	else if (!a->follow_symlinks)
-		acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
+		acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
 #else
 	else if ((!a->follow_symlinks)
 	    && (archive_entry_filetype(entry) == AE_IFLNK))
@@ -436,21 +515,62 @@ setup_acls(struct archive_read_disk *a,
 		acl = NULL;
 #endif
 	else
-		acl = acl_get_file(accpath, ACL_TYPE_NFS4);
-#if HAVE_ACL_IS_TRIVIAL_NP
+#if HAVE_SUN_ACL
+		/* Solaris reads both POSIX.1e and NFSv4 ACLs here */
+		acl_get(accpath, 0, &acl);
+#else
+		acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
+#endif
+
+
+#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL
 	/* Ignore "trivial" ACLs that just mirror the file mode. */
-	acl_is_trivial_np(acl, &r);
-	if (r) {
-		acl_free(acl);
-		acl = NULL;
-	}
+	if (acl != NULL) {
+#if HAVE_SUN_ACL
+		if (sun_acl_is_trivial(acl, archive_entry_mode(entry),
+		    &r) == 0 && r == 1)
+#elif HAVE_ACL_IS_TRIVIAL_NP
+		if (acl_is_trivial_np(acl, &r) == 0 && r == 1)
 #endif
+		{
+			acl_free(acl);
+			acl = NULL;
+			/*
+			 * Simultaneous NFSv4 and POSIX.1e ACLs for the same
+			 * entry are not allowed, so we should return here
+			 */
+			return (ARCHIVE_OK);
+		}
+	}
+#endif	/* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */
 	if (acl != NULL) {
-		translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
 		acl_free(acl);
-		return (ARCHIVE_OK);
-	}
+		if (r != ARCHIVE_OK) {
+			archive_set_error(&a->archive, errno,
+			    "Couldn't translate "
+#if !HAVE_SUN_ACL
+			    "NFSv4 "
+#endif
+			    "ACLs");
+		}
+#if HAVE_DARWIN_ACL
+		/*
+		 * Because Mac OS doesn't support owner@, group@ and everyone@
+		 * ACLs we need to add NFSv4 ACLs mirroring the file mode to
+		 * the archive entry. Otherwise extraction on non-Mac platforms
+		 * would lead to an invalid file mode.
+		 */
+		if ((archive_entry_acl_types(entry) &
+		    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
+			add_trivial_nfs4_acl(entry);
 #endif
+		return (r);
+	}
+#endif	/* HAVE_NFS4_ACL */
+
+#if HAVE_POSIX_ACL
+	/* This code path is skipped on MacOS and Solaris */
 
 	/* Retrieve access ACL from file. */
 	if (*fd >= 0)
@@ -467,88 +587,609 @@ setup_acls(struct archive_read_disk *a,
 #endif
 	else
 		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
+
+#if HAVE_ACL_IS_TRIVIAL_NP
+	/* Ignore "trivial" ACLs that just mirror the file mode. */
+	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) {
+		if (r) {
+			acl_free(acl);
+			acl = NULL;
+		}
+	}
+#endif
+
 	if (acl != NULL) {
-		translate_acl(a, entry, acl,
-		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
 		acl_free(acl);
+		acl = NULL;
+		if (r != ARCHIVE_OK) {
+			archive_set_error(&a->archive, errno,
+			    "Couldn't translate access ACLs");
+			return (r);
+		}
 	}
 
 	/* Only directories can have default ACLs. */
 	if (S_ISDIR(archive_entry_mode(entry))) {
+#if HAVE_ACL_GET_FD_NP
+		if (*fd >= 0)
+			acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
+		else
+#endif
 		acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
 		if (acl != NULL) {
-			translate_acl(a, entry, acl,
+			r = translate_acl(a, entry, acl,
 			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
 			acl_free(acl);
+			if (r != ARCHIVE_OK) {
+				archive_set_error(&a->archive, errno,
+				    "Couldn't translate default ACLs");
+				return (r);
+			}
 		}
 	}
+#endif	/* HAVE_POSIX_ACL */
 	return (ARCHIVE_OK);
 }
 
 /*
- * Translate system ACL into libarchive internal structure.
+ * Translate system ACL permissions into libarchive internal structure
  */
-
-static struct {
-        int archive_perm;
-        int platform_perm;
+static const struct {
+	const int archive_perm;
+	const int platform_perm;
 } acl_perm_map[] = {
-        {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
-        {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
-        {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
-#ifdef ACL_TYPE_NFS4
-        {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
-        {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
-        {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
-        {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
-        {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
-        {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
-        {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
-        {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
-        {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
-        {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
-        {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
-        {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
-        {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
-        {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
-        {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
-        {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#if HAVE_SUN_ACL	/* Solaris NFSv4 ACL permissions */
+	{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
+	{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
+	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
+	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
+	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
+	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
+	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
+	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
+	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
+	{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
+	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
+	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
+	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
+#elif HAVE_DARWIN_ACL	/* MacOS ACL permissions */
+	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
+	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
+	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
+	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#else	/* POSIX.1e ACL permissions */
+	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+	{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
+	{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+#if HAVE_ACL_TYPE_NFS4	/* FreeBSD NFSv4 ACL permissions */
+	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
+	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
+	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
+	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
+	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
+	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
 #endif
+#endif	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
 };
 
-#ifdef ACL_TYPE_NFS4
-static struct {
-        int archive_inherit;
-        int platform_inherit;
+#if HAVE_NFS4_ACL
+/*
+ * Translate system NFSv4 inheritance flags into libarchive internal structure
+ */
+static const struct {
+	const int archive_inherit;
+	const int platform_inherit;
 } acl_inherit_map[] = {
-        {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+#if HAVE_SUN_ACL	/* Solaris ACL inheritance flags */
+	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
+	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
+	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
+	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
+	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
+#elif HAVE_DARWIN_ACL	/* MacOS NFSv4 inheritance flags */
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
+	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
+	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
+#else	/* FreeBSD NFSv4 ACL inheritance flags */
+	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
 	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
 	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
+	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
+	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
+#endif	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
 };
-#endif
+#endif	/* HAVE_NFS4_ACL */
+
+#if HAVE_DARWIN_ACL
+static int translate_guid(struct archive *a, acl_entry_t acl_entry,
+    int *ae_id, int *ae_tag, const char **ae_name)
+{
+	void *q;
+	uid_t ugid;
+	int r, idtype;
+	struct passwd *pwd;
+	struct group *grp;
+
+	q = acl_get_qualifier(acl_entry);
+	if (q == NULL)
+		return (1);
+	r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
+	if (r != 0) {
+		acl_free(q);
+		return (1);
+	}
+	if (idtype == ID_TYPE_UID) {
+		*ae_tag = ARCHIVE_ENTRY_ACL_USER;
+		pwd = getpwuuid(q);
+		if (pwd == NULL) {
+			*ae_id = ugid;
+			*ae_name = NULL;
+		} else {
+			*ae_id = pwd->pw_uid;
+			*ae_name = archive_read_disk_uname(a, *ae_id);
+		}
+	} else if (idtype == ID_TYPE_GID) {
+		*ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+		grp = getgruuid(q);
+		if (grp == NULL) {
+			*ae_id = ugid;
+			*ae_name = NULL;
+		} else {
+			*ae_id = grp->gr_gid;
+			*ae_name = archive_read_disk_gname(a, *ae_id);
+		}
+	} else
+		r = 1;
+
+	acl_free(q);
+	return (r);
+}
+
+/*
+ * Add trivial NFSv4 ACL entries from mode
+ */
+static void
+add_trivial_nfs4_acl(struct archive_entry *entry)
+{
+	mode_t mode;
+	int i;
+	const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
+	const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
+	    ARCHIVE_ENTRY_ACL_APPEND_DATA;
+	const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
+	const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
+	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
+	    ARCHIVE_ENTRY_ACL_READ_ACL |
+	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
+	const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
+	    ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
+	    ARCHIVE_ENTRY_ACL_WRITE_ACL |
+	    ARCHIVE_ENTRY_ACL_WRITE_OWNER;
+
+	struct {
+	    const int type;
+	    const int tag;
+	    int permset;
+	} tacl_entry[] = {
+	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
+	    {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
+	    {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
+	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
+	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
+	    {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
+	};
+
+	mode = archive_entry_mode(entry);
+
+	/* Permissions for everyone@ */
+	if (mode & 0004)
+		tacl_entry[5].permset |= rperm;
+	if (mode & 0002)
+		tacl_entry[5].permset |= wperm;
+	if (mode & 0001)
+		tacl_entry[5].permset |= eperm;
+
+	/* Permissions for group@ */
+	if (mode & 0040)
+		tacl_entry[4].permset |= rperm;
+	else if (mode & 0004)
+		tacl_entry[2].permset |= rperm;
+	if (mode & 0020)
+		tacl_entry[4].permset |= wperm;
+	else if (mode & 0002)
+		tacl_entry[2].permset |= wperm;
+	if (mode & 0010)
+		tacl_entry[4].permset |= eperm;
+	else if (mode & 0001)
+		tacl_entry[2].permset |= eperm;
+
+	/* Permissions for owner@ */
+	if (mode & 0400) {
+		tacl_entry[3].permset |= rperm;
+		if (!(mode & 0040) && (mode & 0004))
+			tacl_entry[0].permset |= rperm;
+	} else if ((mode & 0040) || (mode & 0004))
+		tacl_entry[1].permset |= rperm;
+	if (mode & 0200) {
+		tacl_entry[3].permset |= wperm;
+		if (!(mode & 0020) && (mode & 0002))
+			tacl_entry[0].permset |= wperm;
+	} else if ((mode & 0020) || (mode & 0002))
+		tacl_entry[1].permset |= wperm;
+	if (mode & 0100) {
+		tacl_entry[3].permset |= eperm;
+		if (!(mode & 0010) && (mode & 0001))
+			tacl_entry[0].permset |= eperm;
+	} else if ((mode & 0010) || (mode & 0001))
+		tacl_entry[1].permset |= eperm;
+
+	for (i = 0; i < 6; i++) {
+		if (tacl_entry[i].permset != 0) {
+			archive_entry_acl_add_entry(entry,
+			    tacl_entry[i].type, tacl_entry[i].permset,
+			    tacl_entry[i].tag, -1, NULL);
+		}
+	}
+
+	return;
+}
+#elif HAVE_SUN_ACL
+/*
+ * Check if acl is trivial
+ * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
+ */
+static int
+sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp)
+{
+	int i, p;
+	const uint32_t rperm = ACE_READ_DATA;
+	const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
+	const uint32_t eperm = ACE_EXECUTE;
+	const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
+	    ACE_READ_ACL | ACE_SYNCHRONIZE;
+	const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
+	    ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
+
+	ace_t *ace;
+	ace_t tace[6];
+
+	if (acl == NULL || trivialp == NULL)
+		return (-1);
+
+	*trivialp = 0;
+
+	/* ACL_IS_TRIVIAL flag must be set for both POSIX.1e and NFSv4 ACLs */
+	if ((acl->acl_flags & ACL_IS_TRIVIAL) == 0)
+		return (0);
+
+	/*
+	 * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
+	 * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
+	 * including mask.
+	 */
+	if (acl->acl_type == ACLENT_T) {
+		if (acl->acl_cnt == 4)
+			*trivialp = 1;
+		return (0);
+	}
+
+	if (acl->acl_type != ACE_T || acl->acl_entry_size != sizeof(ace_t))
+		return (-1);
+
+	/*
+	 * Continue with checking NFSv4 ACLs
+	 *
+	 * Create list of trivial ace's to be compared
+	 */
+
+	/* owner@ allow pre */
+	tace[0].a_flags = ACE_OWNER;
+	tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+	tace[0].a_access_mask = 0;
+
+	/* owner@ deny */
+	tace[1].a_flags = ACE_OWNER;
+	tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+	tace[1].a_access_mask = 0;
+
+	/* group@ deny */
+	tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
+	tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+	tace[2].a_access_mask = 0;
+
+	/* owner@ allow */
+	tace[3].a_flags = ACE_OWNER;
+	tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+	tace[3].a_access_mask = ownset;
+
+	/* group@ allow */
+	tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
+	tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+	tace[4].a_access_mask = pubset;
+
+	/* everyone@ allow */
+	tace[5].a_flags = ACE_EVERYONE;
+	tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+	tace[5].a_access_mask = pubset;
+
+	/* Permissions for everyone@ */
+	if (mode & 0004)
+		tace[5].a_access_mask |= rperm;
+	if (mode & 0002)
+		tace[5].a_access_mask |= wperm;
+	if (mode & 0001)
+		tace[5].a_access_mask |= eperm;
+
+	/* Permissions for group@ */
+	if (mode & 0040)
+		tace[4].a_access_mask |= rperm;
+	else if (mode & 0004)
+		tace[2].a_access_mask |= rperm;
+	if (mode & 0020)
+		tace[4].a_access_mask |= wperm;
+	else if (mode & 0002)
+		tace[2].a_access_mask |= wperm;
+	if (mode & 0010)
+		tace[4].a_access_mask |= eperm;
+	else if (mode & 0001)
+		tace[2].a_access_mask |= eperm;
+
+	/* Permissions for owner@ */
+	if (mode & 0400) {
+		tace[3].a_access_mask |= rperm;
+		if (!(mode & 0040) && (mode & 0004))
+			tace[0].a_access_mask |= rperm;
+	} else if ((mode & 0040) || (mode & 0004))
+		tace[1].a_access_mask |= rperm;
+	if (mode & 0200) {
+		tace[3].a_access_mask |= wperm;
+		if (!(mode & 0020) && (mode & 0002))
+			tace[0].a_access_mask |= wperm;
+	} else if ((mode & 0020) || (mode & 0002))
+		tace[1].a_access_mask |= wperm;
+	if (mode & 0100) {
+		tace[3].a_access_mask |= eperm;
+		if (!(mode & 0010) && (mode & 0001))
+			tace[0].a_access_mask |= eperm;
+	} else if ((mode & 0010) || (mode & 0001))
+		tace[1].a_access_mask |= eperm;
+
+	/* Check if the acl count matches */
+	p = 3;
+	for (i = 0; i < 3; i++) {
+		if (tace[i].a_access_mask != 0)
+			p++;
+	}
+	if (acl->acl_cnt != p)
+		return (0);
+
+	p = 0;
+	for (i = 0; i < 6; i++) {
+		if (tace[i].a_access_mask != 0) {
+			ace = &((ace_t *)acl->acl_aclp)[p];
+			/*
+			 * Illumos added ACE_DELETE_CHILD to write perms for
+			 * directories. We have to check against that, too.
+			 */
+			if (ace->a_flags != tace[i].a_flags ||
+			    ace->a_type != tace[i].a_type ||
+			    (ace->a_access_mask != tace[i].a_access_mask &&
+			    ((acl->acl_flags & ACL_IS_DIR) == 0 ||
+			    (tace[i].a_access_mask & wperm) == 0 ||
+			    ace->a_access_mask !=
+			    (tace[i].a_access_mask | ACE_DELETE_CHILD))))
+				return (0);
+			p++;
+		}
+	}
+
+	*trivialp = 1;
+	return (0);
+}
+#endif	/* HAVE_SUN_ACL */
+
+#if HAVE_SUN_ACL
+/*
+ * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
+ */
+static int
+translate_acl(struct archive_read_disk *a,
+    struct archive_entry *entry, acl_t *acl, int default_entry_acl_type)
+{
+	int e, i;
+	int ae_id, ae_tag, ae_perm;
+	int entry_acl_type;
+	const char *ae_name;
+	aclent_t *aclent;
+	ace_t *ace;
+
+	(void)default_entry_acl_type;
+
+	if (acl->acl_cnt <= 0)
+		return (ARCHIVE_OK);
+
+	for (e = 0; e < acl->acl_cnt; e++) {
+		ae_name = NULL;
+		ae_tag = 0;
+		ae_perm = 0;
+
+		if (acl->acl_type == ACE_T) {
+			ace = &((ace_t *)acl->acl_aclp)[e];
+			ae_id = ace->a_who;
+
+			switch(ace->a_type) {
+			case ACE_ACCESS_ALLOWED_ACE_TYPE:
+				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+				break;
+			case ACE_ACCESS_DENIED_ACE_TYPE:
+				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+				break;
+			case ACE_SYSTEM_AUDIT_ACE_TYPE:
+				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+				break;
+			case ACE_SYSTEM_ALARM_ACE_TYPE:
+				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+				break;
+			default:
+				/* Unknown entry type, skip */
+				continue;
+			}
+
+			if ((ace->a_flags & ACE_OWNER) != 0)
+				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+			else if ((ace->a_flags & ACE_GROUP) != 0)
+				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+			else if ((ace->a_flags & ACE_EVERYONE) != 0)
+				ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+			else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
+				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+				ae_name = archive_read_disk_gname(&a->archive,
+				    ae_id);
+			} else {
+				ae_tag = ARCHIVE_ENTRY_ACL_USER;
+				ae_name = archive_read_disk_uname(&a->archive,
+				    ae_id);
+			}
+
+			for (i = 0; i < (int)(sizeof(acl_inherit_map) /
+			    sizeof(acl_inherit_map[0])); ++i) {
+				if ((ace->a_flags &
+				    acl_inherit_map[i].platform_inherit) != 0)
+					ae_perm |=
+					    acl_inherit_map[i].archive_inherit;
+			}
+
+			for (i = 0; i < (int)(sizeof(acl_perm_map) /
+			    sizeof(acl_perm_map[0])); ++i) {
+				if ((ace->a_access_mask &
+				    acl_perm_map[i].platform_perm) != 0)
+					ae_perm |=
+					    acl_perm_map[i].archive_perm;
+			}
+		} else {
+			aclent = &((aclent_t *)acl->acl_aclp)[e];
+			if ((aclent->a_type & ACL_DEFAULT) != 0)
+				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
+			else
+				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
+			ae_id = aclent->a_id;
+
+			switch(aclent->a_type) {
+			case DEF_USER:
+			case USER:
+				ae_name = archive_read_disk_uname(&a->archive,
+				    ae_id);
+				ae_tag = ARCHIVE_ENTRY_ACL_USER;
+				break;
+			case DEF_GROUP:
+			case GROUP:
+				ae_name = archive_read_disk_gname(&a->archive,
+				    ae_id);
+				ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
+				break;
+			case DEF_CLASS_OBJ:
+			case CLASS_OBJ:
+				ae_tag = ARCHIVE_ENTRY_ACL_MASK;
+				break;
+			case DEF_USER_OBJ:
+			case USER_OBJ:
+				ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
+				break;
+			case DEF_GROUP_OBJ:
+			case GROUP_OBJ:
+				ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
+				break;
+			case DEF_OTHER_OBJ:
+			case OTHER_OBJ:
+				ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
+				break;
+			default:
+				/* Unknown tag type, skip */
+				continue;
+			}
+
+			if ((aclent->a_perm & 1) != 0)
+				ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
+			if ((aclent->a_perm & 2) != 0)
+				ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
+			if ((aclent->a_perm & 4) != 0)
+				ae_perm |= ARCHIVE_ENTRY_ACL_READ;
+		} /* default_entry_acl_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4 */
+
+		archive_entry_acl_add_entry(entry, entry_acl_type,
+		    ae_perm, ae_tag, ae_id, ae_name);
+	}
+	return (ARCHIVE_OK);
+}
+#else	/* !HAVE_SUN_ACL */
+/*
+ * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and
+ * MacOS (NFSv4 only) ACLs into libarchive internal structure
+ */
 static int
 translate_acl(struct archive_read_disk *a,
     struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
 {
 	acl_tag_t	 acl_tag;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4
 	acl_entry_type_t acl_type;
+	int brand;
+#endif
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
 	acl_flagset_t	 acl_flagset;
-	int brand, r;
 #endif
 	acl_entry_t	 acl_entry;
 	acl_permset_t	 acl_permset;
 	int		 i, entry_acl_type;
-	int		 s, ae_id, ae_tag, ae_perm;
+	int		 r, s, ae_id, ae_tag, ae_perm;
+#if !HAVE_DARWIN_ACL
+	void		*q;
+#endif
 	const char	*ae_name;
 
-
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4
 	// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
 	// Make sure the "brand" on this ACL is consistent
 	// with the default_entry_acl_type bits provided.
-	acl_get_brand_np(acl, &brand);
+	if (acl_get_brand_np(acl, &brand) != 0) {
+		archive_set_error(&a->archive, errno,
+		    "Failed to read ACL brand");
+		return (ARCHIVE_WARN);
+	}
 	switch (brand) {
 	case ACL_BRAND_POSIX:
 		switch (default_entry_acl_type) {
@@ -556,40 +1197,67 @@ translate_acl(struct archive_read_disk *a,
 		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
 			break;
 		default:
-			// XXX set warning message?
-			return ARCHIVE_FAILED;
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+			    "Invalid ACL entry type for POSIX.1e ACL");
+			return (ARCHIVE_WARN);
 		}
 		break;
 	case ACL_BRAND_NFS4:
 		if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
-			// XXX set warning message?
-			return ARCHIVE_FAILED;
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+			    "Invalid ACL entry type for NFSv4 ACL");
+			return (ARCHIVE_WARN);
 		}
 		break;
 	default:
-		// XXX set warning message?
-		return ARCHIVE_FAILED;
-		break;
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+		    "Unknown ACL brand");
+		return (ARCHIVE_WARN);
 	}
 #endif
 
-
 	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
-	while (s == 1) {
+	if (s == -1) {
+		archive_set_error(&a->archive, errno,
+		    "Failed to get first ACL entry");
+		return (ARCHIVE_WARN);
+	}
+
+#if HAVE_DARWIN_ACL
+	while (s == 0)
+#else	/* FreeBSD, Linux */
+	while (s == 1)
+#endif
+	{
 		ae_id = -1;
 		ae_name = NULL;
 		ae_perm = 0;
 
-		acl_get_tag_type(acl_entry, &acl_tag);
+		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
+			archive_set_error(&a->archive, errno,
+			    "Failed to get ACL tag type");
+			return (ARCHIVE_WARN);
+		}
 		switch (acl_tag) {
+#if !HAVE_DARWIN_ACL	/* FreeBSD, Linux */
 		case ACL_USER:
-			ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
-			ae_name = archive_read_disk_uname(&a->archive, ae_id);
+			q = acl_get_qualifier(acl_entry);
+			if (q != NULL) {
+				ae_id = (int)*(uid_t *)q;
+				acl_free(q);
+				ae_name = archive_read_disk_uname(&a->archive,
+				    ae_id);
+			}
 			ae_tag = ARCHIVE_ENTRY_ACL_USER;
 			break;
 		case ACL_GROUP:
-			ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
-			ae_name = archive_read_disk_gname(&a->archive, ae_id);
+			q = acl_get_qualifier(acl_entry);
+			if (q != NULL) {
+				ae_id = (int)*(gid_t *)q;
+				acl_free(q);
+				ae_name = archive_read_disk_gname(&a->archive,
+				    ae_id);
+			}
 			ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
 			break;
 		case ACL_MASK:
@@ -604,24 +1272,52 @@ translate_acl(struct archive_read_disk *a,
 		case ACL_OTHER:
 			ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
 			break;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4
 		case ACL_EVERYONE:
 			ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
 			break;
 #endif
+#else	/* HAVE_DARWIN_ACL */
+		case ACL_EXTENDED_ALLOW:
+			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+			r = translate_guid(&a->archive, acl_entry, &ae_id,
+			    &ae_tag, &ae_name);
+			break;
+		case ACL_EXTENDED_DENY:
+			entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+			r = translate_guid(&a->archive, acl_entry, &ae_id,
+			    &ae_tag, &ae_name);
+			break;
+#endif	/* HAVE_DARWIN_ACL */
 		default:
 			/* Skip types that libarchive can't support. */
 			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
 			continue;
 		}
 
-		// XXX acl type maps to allow/deny/audit/YYYY bits
-		// XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
-		// non-NFSv4 ACLs
+#if HAVE_DARWIN_ACL
+		/* Skip if translate_guid() above failed */
+		if (r != 0) {
+			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+			continue;
+		}
+#endif
+
+#if !HAVE_DARWIN_ACL
+		// XXX acl_type maps to allow/deny/audit/YYYY bits
 		entry_acl_type = default_entry_acl_type;
-#ifdef ACL_TYPE_NFS4
-		r = acl_get_entry_type_np(acl_entry, &acl_type);
-		if (r == 0) {
+#endif
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
+		if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+#if HAVE_ACL_TYPE_NFS4
+			/*
+			 * acl_get_entry_type_np() fails with non-NFSv4 ACLs
+			 */
+			if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
+				archive_set_error(&a->archive, errno, "Failed "
+				    "to get ACL type from a NFSv4 ACL entry");
+				return (ARCHIVE_WARN);
+			}
 			switch (acl_type) {
 			case ACL_ENTRY_TYPE_ALLOW:
 				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
@@ -635,29 +1331,54 @@ translate_acl(struct archive_read_disk *a,
 			case ACL_ENTRY_TYPE_ALARM:
 				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
 				break;
+			default:
+				archive_set_error(&a->archive, errno,
+				    "Invalid NFSv4 ACL entry type");
+				return (ARCHIVE_WARN);
 			}
-		}
-
-		/*
-		 * Libarchive stores "flag" (NFSv4 inheritance bits)
-		 * in the ae_perm bitmap.
-		 */
-		acl_get_flagset_np(acl_entry, &acl_flagset);
-                for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
-			if (acl_get_flag_np(acl_flagset,
-					    acl_inherit_map[i].platform_inherit))
-				ae_perm |= acl_inherit_map[i].archive_inherit;
+#endif	/* HAVE_ACL_TYPE_NFS4 */
 
-                }
-#endif
+			/*
+			 * Libarchive stores "flag" (NFSv4 inheritance bits)
+			 * in the ae_perm bitmap.
+			 *
+			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
+			 */
+			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+				archive_set_error(&a->archive, errno,
+				    "Failed to get flagset from a NFSv4 ACL entry");
+				return (ARCHIVE_WARN);
+			}
+			for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
+				r = acl_get_flag_np(acl_flagset,
+				    acl_inherit_map[i].platform_inherit);
+				if (r == -1) {
+					archive_set_error(&a->archive, errno,
+					    "Failed to check flag in a NFSv4 "
+					    "ACL flagset");
+					return (ARCHIVE_WARN);
+				} else if (r)
+					ae_perm |= acl_inherit_map[i].archive_inherit;
+			}
+		}
+#endif	/* HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL */
 
-		acl_get_permset(acl_entry, &acl_permset);
+		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+			archive_set_error(&a->archive, errno,
+			    "Failed to get ACL permission set");
+			return (ARCHIVE_WARN);
+		}
 		for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
 			/*
 			 * acl_get_perm() is spelled differently on different
 			 * platforms; see above.
 			 */
-			if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
+			r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm);
+			if (r == -1) {
+				archive_set_error(&a->archive, errno,
+				    "Failed to check permission in an ACL permission set");
+				return (ARCHIVE_WARN);
+			} else if (r)
 				ae_perm |= acl_perm_map[i].archive_perm;
 		}
 
@@ -666,10 +1387,18 @@ translate_acl(struct archive_read_disk *a,
 					    ae_id, ae_name);
 
 		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
+#if !HAVE_DARWIN_ACL
+		if (s == -1) {
+			archive_set_error(&a->archive, errno,
+			    "Failed to get next ACL entry");
+			return (ARCHIVE_WARN);
+		}
+#endif
 	}
 	return (ARCHIVE_OK);
 }
-#else
+#endif	/* !HAVE_SUN_ACL */
+#else	/* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
 static int
 setup_acls(struct archive_read_disk *a,
     struct archive_entry *entry, int *fd)
@@ -679,7 +1408,7 @@ setup_acls(struct archive_read_disk *a,
 	(void)fd;     /* UNUSED */
 	return (ARCHIVE_OK);
 }
-#endif
+#endif	/* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
 
 #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
     HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
@@ -699,15 +1428,10 @@ setup_acls(struct archive_read_disk *a,
 
 static int
 setup_xattr(struct archive_read_disk *a,
-    struct archive_entry *entry, const char *name, int fd)
+    struct archive_entry *entry, const char *name, int fd, const char *accpath)
 {
 	ssize_t size;
 	void *value = NULL;
-	const char *accpath;
-
-	accpath = archive_entry_sourcepath(entry);
-	if (accpath == NULL)
-		accpath = archive_entry_pathname(entry);
 
 #if HAVE_FGETXATTR
 	if (fd >= 0)
@@ -772,21 +1496,23 @@ setup_xattrs(struct archive_read_disk *a,
 	const char *path;
 	ssize_t list_size;
 
-	path = archive_entry_sourcepath(entry);
-	if (path == NULL)
-		path = archive_entry_pathname(entry);
+	path = NULL;
 
-	if (*fd < 0 && a->tree != NULL) {
-		if (a->follow_symlinks ||
-		    archive_entry_filetype(entry) != AE_IFLNK)
-			*fd = a->open_on_current_dir(a->tree, path,
-				O_RDONLY | O_NONBLOCK);
-		if (*fd < 0) {
-			if (a->tree_enter_working_dir(a->tree) != 0) {
-				archive_set_error(&a->archive, errno,
-				    "Couldn't access %s", path);
-				return (ARCHIVE_FAILED);
-			}
+	if (*fd < 0) {
+		path = archive_entry_sourcepath(entry);
+		if (path == NULL || (a->tree != NULL &&
+		    a->tree_enter_working_dir(a->tree) != 0))
+			path = archive_entry_pathname(entry);
+		if (path == NULL) {
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+			    "Couldn't determine file path to read "
+			    "extended attributes");
+			return (ARCHIVE_WARN);
+		}
+		if (a->tree != NULL && (a->follow_symlinks ||
+		    archive_entry_filetype(entry) != AE_IFLNK)) {
+			*fd = a->open_on_current_dir(a->tree,
+			    path, O_RDONLY | O_NONBLOCK);
 		}
 	}
 
@@ -849,7 +1575,7 @@ setup_xattrs(struct archive_read_disk *a,
 		if (strncmp(p, "system.", 7) == 0 ||
 				strncmp(p, "xfsroot.", 8) == 0)
 			continue;
-		setup_xattr(a, entry, p, *fd);
+		setup_xattr(a, entry, p, *fd, path);
 	}
 
 	free(list);
@@ -870,19 +1596,16 @@ setup_xattrs(struct archive_read_disk *a,
  */
 static int
 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
-    int namespace, const char *name, const char *fullname, int fd);
+    int namespace, const char *name, const char *fullname, int fd,
+    const char *path);
 
 static int
 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
-    int namespace, const char *name, const char *fullname, int fd)
+    int namespace, const char *name, const char *fullname, int fd,
+    const char *accpath)
 {
 	ssize_t size;
 	void *value = NULL;
-	const char *accpath;
-
-	accpath = archive_entry_sourcepath(entry);
-	if (accpath == NULL)
-		accpath = archive_entry_pathname(entry);
 
 	if (fd >= 0)
 		size = extattr_get_fd(fd, namespace, name, NULL, 0);
@@ -932,21 +1655,23 @@ setup_xattrs(struct archive_read_disk *a,
 	const char *path;
 	int namespace = EXTATTR_NAMESPACE_USER;
 
-	path = archive_entry_sourcepath(entry);
-	if (path == NULL)
-		path = archive_entry_pathname(entry);
+	path = NULL;
 
-	if (*fd < 0 && a->tree != NULL) {
-		if (a->follow_symlinks ||
-		    archive_entry_filetype(entry) != AE_IFLNK)
-			*fd = a->open_on_current_dir(a->tree, path,
-				O_RDONLY | O_NONBLOCK);
-		if (*fd < 0) {
-			if (a->tree_enter_working_dir(a->tree) != 0) {
-				archive_set_error(&a->archive, errno,
-				    "Couldn't access %s", path);
-				return (ARCHIVE_FAILED);
-			}
+	if (*fd < 0) {
+		path = archive_entry_sourcepath(entry);
+		if (path == NULL || (a->tree != NULL &&
+		    a->tree_enter_working_dir(a->tree) != 0))
+			path = archive_entry_pathname(entry);
+		if (path == NULL) {
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+			    "Couldn't determine file path to read "
+			    "extended attributes");
+			return (ARCHIVE_WARN);
+		}
+		if (a->tree != NULL && (a->follow_symlinks ||
+		    archive_entry_filetype(entry) != AE_IFLNK)) {
+			*fd = a->open_on_current_dir(a->tree,
+			    path, O_RDONLY | O_NONBLOCK);
 		}
 	}
 
@@ -996,7 +1721,7 @@ setup_xattrs(struct archive_read_disk *a,
 		name = buff + strlen(buff);
 		memcpy(name, p + 1, len);
 		name[len] = '\0';
-		setup_xattr(a, entry, namespace, name, buff, *fd);
+		setup_xattr(a, entry, namespace, name, buff, *fd, path);
 		p += 1 + len;
 	}
 
@@ -1024,7 +1749,7 @@ setup_xattrs(struct archive_read_disk *a,
 #if defined(HAVE_LINUX_FIEMAP_H)
 
 /*
- * Linux sparse interface.
+ * Linux FIEMAP sparse interface.
  *
  * The FIEMAP ioctl returns an "extent" for each physical allocation
  * on disk.  We need to process those to generate a more compact list
@@ -1039,7 +1764,7 @@ setup_xattrs(struct archive_read_disk *a,
  */
 
 static int
-setup_sparse(struct archive_read_disk *a,
+setup_sparse_fiemap(struct archive_read_disk *a,
     struct archive_entry *entry, int *fd)
 {
 	char buff[4096];
@@ -1090,8 +1815,8 @@ setup_sparse(struct archive_read_disk *a,
 		if (r < 0) {
 			/* When something error happens, it is better we
 			 * should return ARCHIVE_OK because an earlier
-			 * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
-			goto exit_setup_sparse;
+			 * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */
+			goto exit_setup_sparse_fiemap;
 		}
 		if (fm->fm_mapped_extents == 0) {
 			if (iters == 0) {
@@ -1126,14 +1851,24 @@ setup_sparse(struct archive_read_disk *a,
 		} else
 			break;
 	}
-exit_setup_sparse:
+exit_setup_sparse_fiemap:
 	return (exit_sts);
 }
 
-#elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
+#if !defined(SEEK_HOLE) || !defined(SEEK_DATA)
+static int
+setup_sparse(struct archive_read_disk *a,
+    struct archive_entry *entry, int *fd)
+{
+	return setup_sparse_fiemap(a, entry, fd);
+}
+#endif
+#endif	/* defined(HAVE_LINUX_FIEMAP_H) */
+
+#if defined(SEEK_HOLE) && defined(SEEK_DATA)
 
 /*
- * FreeBSD and Solaris sparse interface.
+ * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris)
  */
 
 static int
@@ -1141,8 +1876,8 @@ setup_sparse(struct archive_read_disk *a,
     struct archive_entry *entry, int *fd)
 {
 	int64_t size;
-	off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
-	off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
+	off_t initial_off;
+	off_t off_s, off_e;
 	int exit_sts = ARCHIVE_OK;
 	int check_fully_sparse = 0;
 
@@ -1168,8 +1903,10 @@ setup_sparse(struct archive_read_disk *a,
 	}
 
 	if (*fd >= 0) {
+#ifdef _PC_MIN_HOLE_SIZE
 		if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
 			return (ARCHIVE_OK);
+#endif
 		initial_off = lseek(*fd, 0, SEEK_CUR);
 		if (initial_off != 0)
 			lseek(*fd, 0, SEEK_SET);
@@ -1180,8 +1917,10 @@ setup_sparse(struct archive_read_disk *a,
 		if (path == NULL)
 			path = archive_entry_pathname(entry);
 			
+#ifdef _PC_MIN_HOLE_SIZE
 		if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
 			return (ARCHIVE_OK);
+#endif
 		*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
 		if (*fd < 0) {
 			archive_set_error(&a->archive, errno,
@@ -1192,6 +1931,19 @@ setup_sparse(struct archive_read_disk *a,
 		initial_off = 0;
 	}
 
+#ifndef _PC_MIN_HOLE_SIZE
+	/* Check if the underlying filesystem supports seek hole */
+	off_s = lseek(*fd, 0, SEEK_HOLE);
+	if (off_s < 0)
+#if defined(HAVE_LINUX_FIEMAP_H)
+		return setup_sparse_fiemap(a, entry, fd);
+#else
+		goto exit_setup_sparse;
+#endif
+	else if (off_s > 0)
+		lseek(*fd, 0, SEEK_SET);
+#endif
+
 	off_s = 0;
 	size = archive_entry_size(entry);
 	while (off_s < size) {
@@ -1223,7 +1975,7 @@ setup_sparse(struct archive_read_disk *a,
 			goto exit_setup_sparse;
 		}
 		if (off_s == 0 && off_e == size)
-			break;/* This is not spase. */
+			break;/* This is not sparse. */
 		archive_entry_sparse_add_entry(entry, off_s,
 			off_e - off_s);
 		off_s = off_e;
@@ -1241,7 +1993,7 @@ exit_setup_sparse:
 	return (exit_sts);
 }
 
-#else
+#elif !defined(HAVE_LINUX_FIEMAP_H)
 
 /*
  * Generic (stub) sparse support.
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
index 22a1f14..6961ae6 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
@@ -165,7 +165,7 @@ struct filesystem {
 	int		synthetic;
 	int		remote;
 	int		noatime;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	size_t		name_max;
 #endif
 	long		incr_xfer_size;
@@ -200,7 +200,7 @@ struct tree {
 	DIR			*d;
 #define	INVALID_DIR_HANDLE NULL
 	struct dirent		*de;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	struct dirent		*dirent;
 	size_t			 dirent_allocated;
 #endif
@@ -244,7 +244,7 @@ struct tree {
 	int			 initial_filesystem_id;
 	int			 current_filesystem_id;
 	int			 max_filesystem_id;
-	int			 allocated_filesytem;
+	int			 allocated_filesystem;
 
 	int			 entry_fd;
 	int			 entry_eof;
@@ -465,8 +465,7 @@ archive_read_disk_new(void)
 	a->entry = archive_entry_new2(&a->archive);
 	a->lookup_uname = trivial_lookup_uname;
 	a->lookup_gname = trivial_lookup_gname;
-	a->enable_copyfile = 1;
-	a->traverse_mount_points = 1;
+	a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
 	a->open_on_current_dir = open_on_current_dir;
 	a->tree_current_dir_fd = tree_current_dir_fd;
 	a->tree_enter_working_dir = tree_enter_working_dir;
@@ -563,25 +562,19 @@ archive_read_disk_set_symlink_hybrid(struct archive *_a)
 int
 archive_read_disk_set_atime_restored(struct archive *_a)
 {
-#ifndef HAVE_UTIMES
-	static int warning_done = 0;
-#endif
 	struct archive_read_disk *a = (struct archive_read_disk *)_a;
 	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
 	    ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
 #ifdef HAVE_UTIMES
-	a->restore_time = 1;
+	a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
 	if (a->tree != NULL)
 		a->tree->flags |= needsRestoreTimes;
 	return (ARCHIVE_OK);
 #else
-	if (warning_done)
-		/* Warning was already emitted; suppress further warnings. */
-		return (ARCHIVE_OK);
-
+	/* Display warning and unset flag */
 	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 	    "Cannot restore access time on this system");
-	warning_done = 1;
+	a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME;
 	return (ARCHIVE_WARN);
 #endif
 }
@@ -595,29 +588,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
 	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
 	    ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
 
+	a->flags = flags;
+
 	if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
 		r = archive_read_disk_set_atime_restored(_a);
 	else {
-		a->restore_time = 0;
 		if (a->tree != NULL)
 			a->tree->flags &= ~needsRestoreTimes;
 	}
-	if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
-		a->honor_nodump = 1;
-	else
-		a->honor_nodump = 0;
-	if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
-		a->enable_copyfile = 1;
-	else
-		a->enable_copyfile = 0;
-	if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
-		a->traverse_mount_points = 0;
-	else
-		a->traverse_mount_points = 1;
-	if (flags & ARCHIVE_READDISK_NO_XATTR)
-		a->suppress_xattr = 1;
-	else
-		a->suppress_xattr = 0;
 	return (r);
 }
 
@@ -675,7 +653,7 @@ setup_suitable_read_buffer(struct archive_read_disk *a)
 				asize = cf->min_xfer_size;
 
 			/* Increase a buffer size up to 64K bytes in
-			 * a proper incremant size. */
+			 * a proper increment size. */
 			while (asize < 1024*64)
 				asize += incr;
 			/* Take a margin to adjust to the filesystem
@@ -918,7 +896,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 	} while (lst == NULL);
 
 #ifdef __APPLE__
-	if (a->enable_copyfile) {
+	if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
 		/* If we're using copyfile(), ignore "._XXX" files. */
 		const char *bname = strrchr(tree_current_path(t), '/');
 		if (bname == NULL)
@@ -938,7 +916,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 		r = archive_match_path_excluded(a->matching, entry);
 		if (r < 0) {
 			archive_set_error(&(a->archive), errno,
-			    "Faild : %s", archive_error_string(a->matching));
+			    "Failed : %s", archive_error_string(a->matching));
 			return (r);
 		}
 		if (r) {
@@ -989,7 +967,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 	}
 	if (t->initial_filesystem_id == -1)
 		t->initial_filesystem_id = t->current_filesystem_id;
-	if (!a->traverse_mount_points) {
+	if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
 		if (t->initial_filesystem_id != t->current_filesystem_id)
 			descend = 0;
 	}
@@ -999,12 +977,14 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 	 * Honor nodump flag.
 	 * If the file is marked with nodump flag, do not return this entry.
 	 */
-	if (a->honor_nodump) {
+	if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) {
 #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
 		if (st->st_flags & UF_NODUMP)
 			return (ARCHIVE_RETRY);
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
-      defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \
+       defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+      (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \
+       defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
 		if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
 			int stflags;
 
@@ -1013,9 +993,18 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 			    O_RDONLY | O_NONBLOCK | O_CLOEXEC);
 			__archive_ensure_cloexec_flag(t->entry_fd);
 			if (t->entry_fd >= 0) {
-				r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS,
+				r = ioctl(t->entry_fd,
+#ifdef FS_IOC_GETFLAGS
+				FS_IOC_GETFLAGS,
+#else
+				EXT2_IOC_GETFLAGS,
+#endif
 					&stflags);
+#ifdef FS_NODUMP_FL
+				if (r == 0 && (stflags & FS_NODUMP_FL) != 0)
+#else
 				if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0)
+#endif
 					return (ARCHIVE_RETRY);
 			}
 		}
@@ -1026,7 +1015,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 
 	/* Save the times to be restored. This must be in before
 	 * calling archive_read_disk_descend() or any chance of it,
-	 * especially, invokng a callback. */
+	 * especially, invoking a callback. */
 	t->restore_time.mtime = archive_entry_mtime(entry);
 	t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry);
 	t->restore_time.atime = archive_entry_atime(entry);
@@ -1041,7 +1030,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 		r = archive_match_time_excluded(a->matching, entry);
 		if (r < 0) {
 			archive_set_error(&(a->archive), errno,
-			    "Faild : %s", archive_error_string(a->matching));
+			    "Failed : %s", archive_error_string(a->matching));
 			return (r);
 		}
 		if (r) {
@@ -1067,7 +1056,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 		r = archive_match_owner_excluded(a->matching, entry);
 		if (r < 0) {
 			archive_set_error(&(a->archive), errno,
-			    "Faild : %s", archive_error_string(a->matching));
+			    "Failed : %s", archive_error_string(a->matching));
 			return (r);
 		}
 		if (r) {
@@ -1340,10 +1329,11 @@ _archive_read_disk_open(struct archive *_a, const char *pathname)
 	struct archive_read_disk *a = (struct archive_read_disk *)_a;
 
 	if (a->tree != NULL)
-		a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+		a->tree = tree_reopen(a->tree, pathname,
+		    a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
 	else
 		a->tree = tree_open(pathname, a->symlink_mode,
-		    a->restore_time);
+		    a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
 	if (a->tree == NULL) {
 		archive_set_error(&a->archive, ENOMEM,
 		    "Can't allocate tar data");
@@ -1382,7 +1372,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
 
 	for (i = 0; i < t->max_filesystem_id; i++) {
 		if (t->filesystem_table[i].dev == dev) {
-			/* There is the filesytem ID we've already generated. */
+			/* There is the filesystem ID we've already generated. */
 			t->current_filesystem_id = i;
 			t->current_filesystem = &(t->filesystem_table[i]);
 			return (ARCHIVE_OK);
@@ -1390,10 +1380,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
 	}
 
 	/*
-	 * This is the new filesytem which we have to generate a new ID for.
+	 * This is the new filesystem which we have to generate a new ID for.
 	 */
 	fid = t->max_filesystem_id++;
-	if (t->max_filesystem_id > t->allocated_filesytem) {
+	if (t->max_filesystem_id > t->allocated_filesystem) {
 		size_t s;
 		void *p;
 
@@ -1406,7 +1396,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
 			return (ARCHIVE_FATAL);
 		}
 		t->filesystem_table = (struct filesystem *)p;
-		t->allocated_filesytem = s;
+		t->allocated_filesystem = s;
 	}
 	t->current_filesystem_id = fid;
 	t->current_filesystem = &(t->filesystem_table[fid]);
@@ -1504,7 +1494,20 @@ setup_current_filesystem(struct archive_read_disk *a)
 	struct tree *t = a->tree;
 	struct statfs sfs;
 #if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
+/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make
+ * this accurate; some platforms have both and we need the one that's
+ * used by getvfsbyname()
+ *
+ * Then the following would become:
+ *  #if defined(GETVFSBYNAME_ARG_TYPE)
+ *   GETVFSBYNAME_ARG_TYPE vfc;
+ *  #endif
+ */
+#  if defined(HAVE_STRUCT_XVFSCONF)
 	struct xvfsconf vfc;
+#  else
+	struct vfsconf vfc;
+#  endif
 #endif
 	int r, xr = 0;
 #if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
@@ -1579,7 +1582,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 #endif
 		t->current_filesystem->noatime = 0;
 
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	/* Set maximum filename length. */
 #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
 	t->current_filesystem->name_max = sfs.f_namemax;
@@ -1602,7 +1605,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 	else
 		t->current_filesystem->name_max = nm;
 #endif
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
 	return (ARCHIVE_OK);
 }
 
@@ -1643,7 +1646,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 		archive_set_error(&a->archive, errno, "statvfs failed");
 		return (ARCHIVE_FAILED);
 	} else if (xr == 1) {
-		/* Usuall come here unless NetBSD supports _PC_REC_XFER_ALIGN
+		/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
 		 * for pathconf() function. */
 		t->current_filesystem->xfer_align = sfs.f_frsize;
 		t->current_filesystem->max_xfer_size = -1;
@@ -1804,7 +1807,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 #endif
 		t->current_filesystem->noatime = 0;
 
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	/* Set maximum filename length. */
 	t->current_filesystem->name_max = sfs.f_namelen;
 #endif
@@ -1888,7 +1891,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 #endif
 		t->current_filesystem->noatime = 0;
 
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	/* Set maximum filename length. */
 	t->current_filesystem->name_max = sfs.f_namemax;
 #endif
@@ -1905,7 +1908,7 @@ static int
 setup_current_filesystem(struct archive_read_disk *a)
 {
 	struct tree *t = a->tree;
-#if defined(_PC_NAME_MAX) && defined(HAVE_READDIR_R)
+#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
 	long nm;
 #endif
 	t->current_filesystem->synthetic = -1;/* Not supported */
@@ -1917,7 +1920,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 	t->current_filesystem->min_xfer_size = -1;
 	t->current_filesystem->incr_xfer_size = -1;
 
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	/* Set maximum filename length. */
 #  if defined(_PC_NAME_MAX)
 	if (tree_current_is_symblic_link_target(t)) {
@@ -1931,7 +1934,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 	if (nm == -1)
 #  endif /* _PC_NAME_MAX */
 		/*
-		 * Some sysmtes (HP-UX or others?) incorrectly defined
+		 * Some systems (HP-UX or others?) incorrectly defined
 		 * NAME_MAX macro to be a smaller value.
 		 */
 #  if defined(NAME_MAX) && NAME_MAX >= 255
@@ -1945,7 +1948,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 	else
 		t->current_filesystem->name_max = nm;
 #  endif /* _PC_NAME_MAX */
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
 	return (ARCHIVE_OK);
 }
 
@@ -2050,8 +2053,7 @@ tree_push(struct tree *t, const char *path, int filesystem_id,
 {
 	struct tree_entry *te;
 
-	te = malloc(sizeof(*te));
-	memset(te, 0, sizeof(*te));
+	te = calloc(1, sizeof(*te));
 	te->next = t->stack;
 	te->parent = t->current;
 	if (te->parent)
@@ -2109,9 +2111,8 @@ tree_open(const char *path, int symlink_mode, int restore_time)
 {
 	struct tree *t;
 
-	if ((t = malloc(sizeof(*t))) == NULL)
+	if ((t = calloc(1, sizeof(*t))) == NULL)
 		return (NULL);
-	memset(t, 0, sizeof(*t));
 	archive_string_init(&t->path);
 	archive_string_ensure(&t->path, 31);
 	t->initial_symlink_mode = symlink_mode;
@@ -2121,7 +2122,7 @@ tree_open(const char *path, int symlink_mode, int restore_time)
 static struct tree *
 tree_reopen(struct tree *t, const char *path, int restore_time)
 {
-	t->flags = (restore_time)?needsRestoreTimes:0;
+	t->flags = (restore_time != 0)?needsRestoreTimes:0;
 	t->flags |= onInitialDir;
 	t->visit_type = 0;
 	t->tree_errno = 0;
@@ -2353,7 +2354,7 @@ tree_dir_next_posix(struct tree *t)
 	size_t namelen;
 
 	if (t->d == NULL) {
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 		size_t dirent_size;
 #endif
 
@@ -2374,7 +2375,7 @@ tree_dir_next_posix(struct tree *t)
 			t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
 			return (t->visit_type);
 		}
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 		dirent_size = offsetof(struct dirent, d_name) +
 		  t->filesystem_table[t->current->filesystem_id].name_max + 1;
 		if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
@@ -2391,11 +2392,11 @@ tree_dir_next_posix(struct tree *t)
 			}
 			t->dirent_allocated = dirent_size;
 		}
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
 	}
 	for (;;) {
 		errno = 0;
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 		r = readdir_r(t->d, t->dirent, &t->de);
 #ifdef _AIX
 		/* Note: According to the man page, return value 9 indicates
@@ -2647,7 +2648,7 @@ tree_free(struct tree *t)
 	if (t == NULL)
 		return;
 	archive_string_free(&t->path);
-#if defined(HAVE_READDIR_R)
+#if defined(USE_READDIR_R)
 	free(t->dirent);
 #endif
 	free(t->sparse_list);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
index 2569321..b5a8328 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
@@ -63,16 +63,8 @@ struct archive_read_disk {
 	int	(*tree_current_dir_fd)(struct tree*);
 	int	(*tree_enter_working_dir)(struct tree*);
 
-	/* Set 1 if users request to restore atime . */
-	int		 restore_time;
-	/* Set 1 if users request to honor nodump flag . */
-	int		 honor_nodump;
-	/* Set 1 if users request to enable mac copyfile. */
-	int		 enable_copyfile;
-	/* Set 1 if users request to traverse mount points. */
-	int		 traverse_mount_points;
-	/* Set 1 if users want to suppress xattr information. */
-	int		 suppress_xattr;
+	/* Bitfield with ARCHIVE_READDISK_* tunables */
+	int	flags;
 
 	const char * (*lookup_gname)(void *private, int64_t gid);
 	void	(*cleanup_gname)(void *private);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c
index d6b2d55..c7fd247 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_set_standard_lookup.c
@@ -232,6 +232,7 @@ static const char *
 lookup_uname_helper(struct name_cache *cache, id_t id)
 {
 	struct passwd	*result;
+	(void)cache; /* UNUSED */
 
 	result = getpwuid((uid_t)id);
 
@@ -298,6 +299,7 @@ static const char *
 lookup_gname_helper(struct name_cache *cache, id_t id)
 {
 	struct group	*result;
+	(void)cache; /* UNUSED */
 
 	result = getgrgid((gid_t)id);
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
index 566d264..3b90330 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
@@ -168,7 +168,7 @@ struct tree {
 	int			 initial_filesystem_id;
 	int			 current_filesystem_id;
 	int			 max_filesystem_id;
-	int			 allocated_filesytem;
+	int			 allocated_filesystem;
 
 	HANDLE			 entry_fh;
 	int			 entry_eof;
@@ -389,18 +389,16 @@ archive_read_disk_new(void)
 {
 	struct archive_read_disk *a;
 
-	a = (struct archive_read_disk *)malloc(sizeof(*a));
+	a = (struct archive_read_disk *)calloc(1, sizeof(*a));
 	if (a == NULL)
 		return (NULL);
-	memset(a, 0, sizeof(*a));
 	a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
 	a->archive.state = ARCHIVE_STATE_NEW;
 	a->archive.vtable = archive_read_disk_vtable();
 	a->entry = archive_entry_new2(&a->archive);
 	a->lookup_uname = trivial_lookup_uname;
 	a->lookup_gname = trivial_lookup_gname;
-	a->enable_copyfile = 1;
-	a->traverse_mount_points = 1;
+	a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
 	return (&a->archive);
 }
 
@@ -496,7 +494,7 @@ archive_read_disk_set_atime_restored(struct archive *_a)
 	struct archive_read_disk *a = (struct archive_read_disk *)_a;
 	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
 	    ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
-	a->restore_time = 1;
+	a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
 	if (a->tree != NULL)
 		a->tree->flags |= needsRestoreTimes;
 	return (ARCHIVE_OK);
@@ -511,25 +509,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
 	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
 	    ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
 
+	a->flags = flags;
+
 	if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
 		r = archive_read_disk_set_atime_restored(_a);
 	else {
-		a->restore_time = 0;
 		if (a->tree != NULL)
 			a->tree->flags &= ~needsRestoreTimes;
 	}
-	if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
-		a->honor_nodump = 1;
-	else
-		a->honor_nodump = 0;
-	if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
-		a->enable_copyfile = 1;
-	else
-		a->enable_copyfile = 0;
-	if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
-		a->traverse_mount_points = 0;
-	else
-		a->traverse_mount_points = 1;
 	return (r);
 }
 
@@ -803,7 +790,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 		r = archive_match_path_excluded(a->matching, entry);
 		if (r < 0) {
 			archive_set_error(&(a->archive), errno,
-			    "Faild : %s", archive_error_string(a->matching));
+			    "Failed : %s", archive_error_string(a->matching));
 			return (r);
 		}
 		if (r) {
@@ -853,7 +840,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 	}
 	if (t->initial_filesystem_id == -1)
 		t->initial_filesystem_id = t->current_filesystem_id;
-	if (!a->traverse_mount_points) {
+	if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
 		if (t->initial_filesystem_id != t->current_filesystem_id)
 			return (ARCHIVE_RETRY);
 	}
@@ -863,7 +850,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 
 	/* Save the times to be restored. This must be in before
 	 * calling archive_read_disk_descend() or any chance of it,
-	 * especially, invokng a callback. */
+	 * especially, invoking a callback. */
 	t->restore_time.lastWriteTime = st->ftLastWriteTime;
 	t->restore_time.lastAccessTime = st->ftLastAccessTime;
 	t->restore_time.filetype = archive_entry_filetype(entry);
@@ -875,7 +862,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 		r = archive_match_time_excluded(a->matching, entry);
 		if (r < 0) {
 			archive_set_error(&(a->archive), errno,
-			    "Faild : %s", archive_error_string(a->matching));
+			    "Failed : %s", archive_error_string(a->matching));
 			return (r);
 		}
 		if (r) {
@@ -901,7 +888,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
 		r = archive_match_owner_excluded(a->matching, entry);
 		if (r < 0) {
 			archive_set_error(&(a->archive), errno,
-			    "Faild : %s", archive_error_string(a->matching));
+			    "Failed : %s", archive_error_string(a->matching));
 			return (r);
 		}
 		if (r) {
@@ -1220,9 +1207,11 @@ _archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
 	struct archive_read_disk *a = (struct archive_read_disk *)_a;
 
 	if (a->tree != NULL)
-		a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+		a->tree = tree_reopen(a->tree, pathname,
+		    a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
 	else
-		a->tree = tree_open(pathname, a->symlink_mode, a->restore_time);
+		a->tree = tree_open(pathname, a->symlink_mode,
+		    a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
 	if (a->tree == NULL) {
 		archive_set_error(&a->archive, ENOMEM,
 		    "Can't allocate directory traversal data");
@@ -1261,7 +1250,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
 
 	for (i = 0; i < t->max_filesystem_id; i++) {
 		if (t->filesystem_table[i].dev == dev) {
-			/* There is the filesytem ID we've already generated. */
+			/* There is the filesystem ID we've already generated. */
 			t->current_filesystem_id = i;
 			t->current_filesystem = &(t->filesystem_table[i]);
 			return (ARCHIVE_OK);
@@ -1269,10 +1258,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
 	}
 
 	/*
-	 * There is a new filesytem, we generate a new ID for.
+	 * There is a new filesystem, we generate a new ID for.
 	 */
 	fid = t->max_filesystem_id++;
-	if (t->max_filesystem_id > t->allocated_filesytem) {
+	if (t->max_filesystem_id > t->allocated_filesystem) {
 		size_t s;
 		void *p;
 
@@ -1285,7 +1274,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
 			return (ARCHIVE_FATAL);
 		}
 		t->filesystem_table = (struct filesystem *)p;
-		t->allocated_filesytem = (int)s;
+		t->allocated_filesystem = (int)s;
 	}
 	t->current_filesystem_id = fid;
 	t->current_filesystem = &(t->filesystem_table[fid]);
@@ -1402,7 +1391,7 @@ close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt)
 	if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype)
 		return (0);
 
-	/* Close a file descritor.
+	/* Close a file descriptor.
 	 * It will not be used for SetFileTime() because it has been opened
 	 * by a read only mode.
 	 */
@@ -1437,8 +1426,7 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path,
 {
 	struct tree_entry *te;
 
-	te = malloc(sizeof(*te));
-	memset(te, 0, sizeof(*te));
+	te = calloc(1, sizeof(*te));
 	te->next = t->stack;
 	te->parent = t->current;
 	if (te->parent)
@@ -1507,8 +1495,7 @@ tree_open(const wchar_t *path, int symlink_mode, int restore_time)
 {
 	struct tree *t;
 
-	t = malloc(sizeof(*t));
-	memset(t, 0, sizeof(*t));
+	t = calloc(1, sizeof(*t));
 	archive_string_init(&(t->full_path));
 	archive_string_init(&t->path);
 	archive_wstring_ensure(&t->path, 15);
@@ -1522,7 +1509,7 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
 	struct archive_wstring ws;
 	wchar_t *pathname, *p, *base;
 
-	t->flags = (restore_time)?needsRestoreTimes:0;
+	t->flags = (restore_time != 0)?needsRestoreTimes:0;
 	t->visit_type = 0;
 	t->tree_errno = 0;
 	t->full_path_dir_length = 0;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_extract2.c b/Utilities/cmlibarchive/libarchive/archive_read_extract2.c
index 7b2c126..4febd8c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_extract2.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_extract2.c
@@ -52,12 +52,11 @@ struct archive_read_extract *
 __archive_read_get_extract(struct archive_read *a)
 {
 	if (a->extract == NULL) {
-		a->extract = (struct archive_read_extract *)malloc(sizeof(*a->extract));
+		a->extract = (struct archive_read_extract *)calloc(1, sizeof(*a->extract));
 		if (a->extract == NULL) {
 			archive_set_error(&a->archive, ENOMEM, "Can't extract");
 			return (NULL);
 		}
-		memset(a->extract, 0, sizeof(*a->extract));
 		a->cleanup_archive_extract = archive_read_extract_cleanup;
 	}
 	return (a->extract);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
index 5611aa8..86635e2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
@@ -222,7 +222,7 @@ file_open(struct archive *a, void *client_data)
 	void *buffer;
 	const char *filename = NULL;
 	const wchar_t *wfilename = NULL;
-	int fd;
+	int fd = -1;
 	int is_disk_like = 0;
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 	off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */
@@ -277,7 +277,7 @@ file_open(struct archive *a, void *client_data)
 #else
 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
 		    "Unexpedted operation in archive_read_open_filename");
-		return (ARCHIVE_FATAL);
+		goto fail;
 #endif
 	}
 	if (fstat(fd, &st) != 0) {
@@ -287,7 +287,7 @@ file_open(struct archive *a, void *client_data)
 		else
 			archive_set_error(a, errno, "Can't stat '%s'",
 			    filename);
-		return (ARCHIVE_FATAL);
+		goto fail;
 	}
 
 	/*
@@ -356,11 +356,9 @@ file_open(struct archive *a, void *client_data)
 		mine->block_size = new_block_size;
 	}
 	buffer = malloc(mine->block_size);
-	if (mine == NULL || buffer == NULL) {
+	if (buffer == NULL) {
 		archive_set_error(a, ENOMEM, "No memory");
-		free(mine);
-		free(buffer);
-		return (ARCHIVE_FATAL);
+		goto fail;
 	}
 	mine->buffer = buffer;
 	mine->fd = fd;
@@ -372,6 +370,14 @@ file_open(struct archive *a, void *client_data)
 		mine->use_lseek = 1;
 
 	return (ARCHIVE_OK);
+fail:
+	/*
+	 * Don't close file descriptors not opened or ones pointing referring
+	 * to `FNT_STDIN`.
+	 */
+	if (fd != -1 && fd != 0)
+		close(fd);
+	return (ARCHIVE_FATAL);
 }
 
 static ssize_t
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
index ff935a7..311be47 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
@@ -70,12 +70,11 @@ archive_read_open_memory2(struct archive *a, const void *buff,
 {
 	struct read_memory_data *mine;
 
-	mine = (struct read_memory_data *)malloc(sizeof(*mine));
+	mine = (struct read_memory_data *)calloc(1, sizeof(*mine));
 	if (mine == NULL) {
 		archive_set_error(a, ENOMEM, "No memory");
 		return (ARCHIVE_FATAL);
 	}
-	memset(mine, 0, sizeof(*mine));
 	mine->start = mine->p = (const unsigned char *)buff;
 	mine->end = mine->start + size;
 	mine->read_size = read_size;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_private.h b/Utilities/cmlibarchive/libarchive/archive_read_private.h
index 9b61a53..78546dc 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_read_private.h
@@ -221,7 +221,7 @@ struct archive_read {
 	struct {
 		struct archive_read_passphrase *first;
 		struct archive_read_passphrase **last;
-		int candiate;
+		int candidate;
 		archive_passphrase_callback *callback;
 		void *client_data;
 	}		passphrases;
@@ -252,7 +252,6 @@ int64_t	__archive_read_consume(struct archive_read *, int64_t);
 int64_t	__archive_read_filter_consume(struct archive_read_filter *, int64_t);
 int __archive_read_program(struct archive_read_filter *, const char *);
 void __archive_read_free_filters(struct archive_read *);
-int  __archive_read_close_filters(struct archive_read *);
 struct archive_read_extract *__archive_read_get_extract(struct archive_read *);
 
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c
index e877917..663e2d3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c
@@ -180,7 +180,7 @@ lz4_reader_bid(struct archive_read_filter_bidder *self,
 			return (0);
 		bits_checked += 8;
 		BD = buffer[5];
-		/* A block maximum size shuld be more than 3. */
+		/* A block maximum size should be more than 3. */
 		if (((BD & 0x70) >> 4) < 4)
 			return (0);
 		/* Reserved bits must be "0". */
@@ -417,7 +417,7 @@ lz4_filter_read_descriptor(struct archive_read_filter *self)
 	/* Reserved bits must be zero. */
 	if (bd & 0x8f)
 		goto malformed_error;
-	/* Get a maxinum block size. */
+	/* Get a maximum block size. */
 	switch (read_buf[1] >> 4) {
 	case 4: /* 64 KB */
 		state->flags.block_maximum_size = 64 * 1024;
@@ -595,7 +595,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
 #endif
 	}
 
-	/* Check if an error happend in decompression process. */
+	/* Check if an error occurred in the decompression process. */
 	if (uncompressed_size < 0) {
 		archive_set_error(&(self->archive->archive),
 		    ARCHIVE_ERRNO_MISC, "lz4 decompression failed");
@@ -627,7 +627,7 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p)
 
 	if (state->stage == SELECT_STREAM) {
 		state->stage = READ_DEFAULT_STREAM;
-		/* First, read a desciprtor. */
+		/* First, read a descriptor. */
 		if((ret = lz4_filter_read_descriptor(self)) != ARCHIVE_OK)
 			return (ret);
 		state->stage = READ_DEFAULT_BLOCK;
@@ -706,6 +706,11 @@ lz4_filter_read_legacy_stream(struct archive_read_filter *self, const void **p)
 	/* Make sure we have a whole block. */
 	read_buf = __archive_read_filter_ahead(self->upstream,
 	    4 + compressed, NULL);
+	if (read_buf == NULL) {
+		archive_set_error(&(self->archive->archive),
+		    ARCHIVE_ERRNO_MISC, "truncated lz4 input");
+		return (ARCHIVE_FATAL);
+	}
 	ret = LZ4_decompress_safe(read_buf + 4, state->out_block,
 	    compressed, (int)state->out_block_size);
 	if (ret < 0) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c
index 23c18c7..4356b82 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c
@@ -436,7 +436,7 @@ lzop_filter_read(struct archive_read_filter *self, const void **p)
 	}
 
 	/*
-	 * Drive lzo uncompresison.
+	 * Drive lzo uncompression.
 	 */
 	out_size = (lzo_uint)state->uncompressed_size;
 	r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size,
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
index 66dc2f4..b8bf128 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
@@ -430,6 +430,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
 	    &state->child_stdout);
 	if (child == -1) {
 		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\"",
@@ -441,6 +442,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
 	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\"",
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
index 787a619..6412979 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
@@ -312,6 +312,7 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
 	avail -= len;
 
 	if (l == 6) {
+		/* "begin " */
 		if (!uuchar[*b])
 			return (0);
 		/* Get a length of decoded bytes. */
@@ -319,30 +320,14 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
 		if (l > 45)
 			/* Normally, maximum length is 45(character 'M'). */
 			return (0);
-		while (l && len-nl > 0) {
-			if (l > 0) {
-				if (!uuchar[*b++])
-					return (0);
-				if (!uuchar[*b++])
-					return (0);
-				len -= 2;
-				--l;
-			}
-			if (l > 0) {
-				if (!uuchar[*b++])
-					return (0);
-				--len;
-				--l;
-			}
-			if (l > 0) {
-				if (!uuchar[*b++])
-					return (0);
-				--len;
-				--l;
-			}
+		if (l > len - nl)
+			return (0); /* Line too short. */
+		while (l) {
+			if (!uuchar[*b++])
+				return (0);
+			--len;
+			--l;
 		}
-		if (len-nl < 0)
-			return (0);
 		if (len-nl == 1 &&
 		    (uuchar[*b] ||		 /* Check sum. */
 		     (*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */
@@ -352,8 +337,8 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
 		b += nl;
 		if (avail && uuchar[*b])
 			return (firstline+30);
-	}
-	if (l == 13) {
+	} else if (l == 13) {
+		/* "begin-base64 " */
 		while (len-nl > 0) {
 			if (!base64[*b++])
 				return (0);
@@ -510,6 +495,13 @@ read_more:
 		}
 		llen = len;
 		if ((nl == 0) && (uudecode->state != ST_UUEND)) {
+			if (total == 0 && ravail <= 0) {
+				/* There is nothing more to read, fail */
+				archive_set_error(&self->archive->archive,
+				    ARCHIVE_ERRNO_FILE_FORMAT,
+				    "Missing format data");
+				return (ARCHIVE_FATAL);
+			}
 			/*
 			 * Save remaining data which does not contain
 			 * NL('\n','\r').
@@ -566,7 +558,7 @@ read_more:
 				    "Insufficient compressed data");
 				return (ARCHIVE_FATAL);
 			}
-			/* Get length of undecoded bytes of curent line. */
+			/* Get length of undecoded bytes of current line. */
 			l = UUDECODE(*b++);
 			body--;
 			if (l > body) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c
index 8f48273..a188186 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
 #endif
 #if HAVE_LZMA_H
 #include <cm_lzma.h>
-#elif HAVE_LZMADEC_H
-#include <lzmadec.h>
 #endif
 
 #include "archive.h"
@@ -82,19 +80,6 @@ static ssize_t	xz_filter_read(struct archive_read_filter *, const void **);
 static int	xz_filter_close(struct archive_read_filter *);
 static int	xz_lzma_bidder_init(struct archive_read_filter *);
 
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-
-struct private_data {
-	lzmadec_stream	 stream;
-	unsigned char	*out_block;
-	size_t		 out_block_size;
-	int64_t		 total_out;
-	char		 eof; /* True = found end of compressed data. */
-};
-
-/* Lzma-only filter */
-static ssize_t	lzma_filter_read(struct archive_read_filter *, const void **);
-static int	lzma_filter_close(struct archive_read_filter *);
 #endif
 
 /*
@@ -178,8 +163,6 @@ archive_read_support_filter_lzma(struct archive *_a)
 	bidder->free = NULL;
 #if HAVE_LZMA_H && HAVE_LIBLZMA
 	return (ARCHIVE_OK);
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-	return (ARCHIVE_OK);
 #else
 	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
 	    "Using external lzma program for lzma decompression");
@@ -310,7 +293,7 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self,
 	/* Second through fifth bytes are dictionary size, stored in
 	 * little-endian order. The minimum dictionary size is
 	 * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
-	 * -d12 and the maxinam dictionary size is 1 << 27(128MiB)
+	 * -d12 and the maximum dictionary size is 1 << 27(128MiB)
 	 * which the one uses with option -d27.
 	 * NOTE: A comment of LZMA SDK source code says this dictionary
 	 * range is from 1 << 12 to 1 << 30. */
@@ -601,9 +584,7 @@ lzip_init(struct archive_read_filter *self)
 		return (ARCHIVE_FATAL);
 	}
 	ret = lzma_raw_decoder(&(state->stream), filters);
-#if LZMA_VERSION < 50010000
 	free(filters[0].options);
-#endif
 	if (ret != LZMA_OK) {
 		set_error(self, ret);
 		return (ARCHIVE_FATAL);
@@ -763,175 +744,6 @@ xz_filter_close(struct archive_read_filter *self)
 
 #else
 
-#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-
-/*
- * If we have the older liblzmadec library, then we can handle
- * LZMA streams but not XZ streams.
- */
-
-/*
- * Setup the callbacks.
- */
-static int
-lzma_bidder_init(struct archive_read_filter *self)
-{
-	static const size_t out_block_size = 64 * 1024;
-	void *out_block;
-	struct private_data *state;
-	ssize_t ret, avail_in;
-
-	self->code = ARCHIVE_FILTER_LZMA;
-	self->name = "lzma";
-
-	state = (struct private_data *)calloc(sizeof(*state), 1);
-	out_block = (unsigned char *)malloc(out_block_size);
-	if (state == NULL || out_block == NULL) {
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Can't allocate data for lzma decompression");
-		free(out_block);
-		free(state);
-		return (ARCHIVE_FATAL);
-	}
-
-	self->data = state;
-	state->out_block_size = out_block_size;
-	state->out_block = out_block;
-	self->read = lzma_filter_read;
-	self->skip = NULL; /* not supported */
-	self->close = lzma_filter_close;
-
-	/* Prime the lzma library with 18 bytes of input. */
-	state->stream.next_in = (unsigned char *)(uintptr_t)
-	    __archive_read_filter_ahead(self->upstream, 18, &avail_in);
-	if (state->stream.next_in == NULL)
-		return (ARCHIVE_FATAL);
-	state->stream.avail_in = avail_in;
-	state->stream.next_out = state->out_block;
-	state->stream.avail_out = state->out_block_size;
-
-	/* Initialize compression library. */
-	ret = lzmadec_init(&(state->stream));
-	__archive_read_filter_consume(self->upstream,
-	    avail_in - state->stream.avail_in);
-	if (ret == LZMADEC_OK)
-		return (ARCHIVE_OK);
-
-	/* Library setup failed: Clean up. */
-	archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
-	    "Internal error initializing lzma library");
-
-	/* Override the error message if we know what really went wrong. */
-	switch (ret) {
-	case LZMADEC_HEADER_ERROR:
-		archive_set_error(&self->archive->archive,
-		    ARCHIVE_ERRNO_MISC,
-		    "Internal error initializing compression library: "
-		    "invalid header");
-		break;
-	case LZMADEC_MEM_ERROR:
-		archive_set_error(&self->archive->archive, ENOMEM,
-		    "Internal error initializing compression library: "
-		    "out of memory");
-		break;
-	}
-
-	free(state->out_block);
-	free(state);
-	self->data = NULL;
-	return (ARCHIVE_FATAL);
-}
-
-/*
- * Return the next block of decompressed data.
- */
-static ssize_t
-lzma_filter_read(struct archive_read_filter *self, const void **p)
-{
-	struct private_data *state;
-	size_t decompressed;
-	ssize_t avail_in, ret;
-
-	state = (struct private_data *)self->data;
-
-	/* Empty our output buffer. */
-	state->stream.next_out = state->out_block;
-	state->stream.avail_out = state->out_block_size;
-
-	/* Try to fill the output buffer. */
-	while (state->stream.avail_out > 0 && !state->eof) {
-		state->stream.next_in = (unsigned char *)(uintptr_t)
-		    __archive_read_filter_ahead(self->upstream, 1, &avail_in);
-		if (state->stream.next_in == NULL && avail_in < 0) {
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "truncated lzma input");
-			return (ARCHIVE_FATAL);
-		}
-		state->stream.avail_in = avail_in;
-
-		/* Decompress as much as we can in one pass. */
-		ret = lzmadec_decode(&(state->stream), avail_in == 0);
-		switch (ret) {
-		case LZMADEC_STREAM_END: /* Found end of stream. */
-			state->eof = 1;
-			/* FALL THROUGH */
-		case LZMADEC_OK: /* Decompressor made some progress. */
-			__archive_read_filter_consume(self->upstream,
-			    avail_in - state->stream.avail_in);
-			break;
-		case LZMADEC_BUF_ERROR: /* Insufficient input data? */
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Insufficient compressed data");
-			return (ARCHIVE_FATAL);
-		default:
-			/* Return an error. */
-			archive_set_error(&self->archive->archive,
-			    ARCHIVE_ERRNO_MISC,
-			    "Lzma decompression failed");
-			return (ARCHIVE_FATAL);
-		}
-	}
-
-	decompressed = state->stream.next_out - state->out_block;
-	state->total_out += decompressed;
-	if (decompressed == 0)
-		*p = NULL;
-	else
-		*p = state->out_block;
-	return (decompressed);
-}
-
-/*
- * Clean up the decompressor.
- */
-static int
-lzma_filter_close(struct archive_read_filter *self)
-{
-	struct private_data *state;
-	int ret;
-
-	state = (struct private_data *)self->data;
-	ret = ARCHIVE_OK;
-	switch (lzmadec_end(&(state->stream))) {
-	case LZMADEC_OK:
-		break;
-	default:
-		archive_set_error(&(self->archive->archive),
-		    ARCHIVE_ERRNO_MISC,
-		    "Failed to clean up %s compressor",
-		    self->archive->archive.compression_name);
-		ret = ARCHIVE_FATAL;
-	}
-
-	free(state->out_block);
-	free(state);
-	return (ret);
-}
-
-#else
-
 /*
  *
  * If we have no suitable library on this system, we can't actually do
@@ -953,9 +765,6 @@ lzma_bidder_init(struct archive_read_filter *self)
 	return (r);
 }
 
-#endif /* HAVE_LZMADEC_H */
-
-
 static int
 xz_bidder_init(struct archive_read_filter *self)
 {
@@ -984,5 +793,4 @@ lzip_bidder_init(struct archive_read_filter *self)
 	return (r);
 }
 
-
 #endif /* HAVE_LZMA_H */
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
index a33ea4f..96774f4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
@@ -213,7 +213,7 @@ struct _7zip {
 	int			 header_is_encoded;
 	uint64_t		 header_bytes_remaining;
 	unsigned long		 header_crc32;
-	/* Header offset to check that reading pointes of the file contens
+	/* Header offset to check that reading points of the file contents
 	 * will not exceed the header. */
 	uint64_t		 header_offset;
 	/* Base offset of the archive file for a seek in case reading SFX. */
@@ -263,22 +263,22 @@ struct _7zip {
 	/*
 	 * Decompressor controllers.
 	 */
-	/* Decording LZMA1 and LZMA2 data. */
+	/* Decoding LZMA1 and LZMA2 data. */
 #ifdef HAVE_LZMA_H
 	lzma_stream		 lzstream;
 	int			 lzstream_valid;
 #endif
-	/* Decording bzip2 data. */
+	/* Decoding bzip2 data. */
 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
 	bz_stream		 bzstream;
 	int			 bzstream_valid;
 #endif
-	/* Decording deflate data. */
+	/* Decoding deflate data. */
 #ifdef HAVE_ZLIB_H
 	z_stream		 stream;
 	int			 stream_valid;
 #endif
-	/* Decording PPMd data. */
+	/* Decoding PPMd data. */
 	int			 ppmd7_stat;
 	CPpmd7			 ppmd7_context;
 	CPpmd7z_RangeDec	 range_dec;
@@ -552,7 +552,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
 	/*
 	 * If bytes_avail > SFX_MIN_ADDR we do not have to call
 	 * __archive_read_seek() at this time since we have
-	 * alredy had enough data.
+	 * already had enough data.
 	 */
 	if (bytes_avail > SFX_MIN_ADDR)
 		__archive_read_consume(a, SFX_MIN_ADDR);
@@ -760,7 +760,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
 			symsize += size;
 		}
 		if (symsize == 0) {
-			/* If there is no synname, handle it as a regular
+			/* If there is no symname, handle it as a regular
 			 * file. */
 			zip_entry->mode &= ~AE_IFMT;
 			zip_entry->mode |= AE_IFREG;
@@ -1056,10 +1056,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
 #endif
 	{
 		lzma_options_delta delta_opt;
-		lzma_filter filters[LZMA_FILTERS_MAX];
-#if LZMA_VERSION < 50010000
-		lzma_filter *ff;
-#endif
+		lzma_filter filters[LZMA_FILTERS_MAX], *ff;
 		int fi = 0;
 
 		if (zip->lzstream_valid) {
@@ -1144,9 +1141,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
 		else
 			filters[fi].id = LZMA_FILTER_LZMA1;
 		filters[fi].options = NULL;
-#if LZMA_VERSION < 50010000
 		ff = &filters[fi];
-#endif
 		r = lzma_properties_decode(&filters[fi], NULL,
 		    coder1->properties, (size_t)coder1->propertiesSize);
 		if (r != LZMA_OK) {
@@ -1158,9 +1153,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
 		filters[fi].id = LZMA_VLI_UNKNOWN;
 		filters[fi].options = NULL;
 		r = lzma_raw_decoder(&(zip->lzstream), filters);
-#if LZMA_VERSION < 50010000
 		free(ff->options);
-#endif
 		if (r != LZMA_OK) {
 			set_error(a, r);
 			return (ARCHIVE_FAILED);
@@ -2431,6 +2424,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
 
 		switch (type) {
 		case kEmptyStream:
+			if (h->emptyStreamBools != NULL)
+				return (-1);
 			h->emptyStreamBools = calloc((size_t)zip->numFiles,
 			    sizeof(*h->emptyStreamBools));
 			if (h->emptyStreamBools == NULL)
@@ -2451,6 +2446,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
 					return (-1);
 				break;
 			}
+			if (h->emptyFileBools != NULL)
+				return (-1);
 			h->emptyFileBools = calloc(empty_streams,
 			    sizeof(*h->emptyFileBools));
 			if (h->emptyFileBools == NULL)
@@ -2465,6 +2462,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
 					return (-1);
 				break;
 			}
+			if (h->antiBools != NULL)
+				return (-1);
 			h->antiBools = calloc(empty_streams,
 			    sizeof(*h->antiBools));
 			if (h->antiBools == NULL)
@@ -2491,6 +2490,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
 			if ((ll & 1) || ll < zip->numFiles * 4)
 				return (-1);
 
+			if (zip->entry_names != NULL)
+				return (-1);
 			zip->entry_names = malloc(ll);
 			if (zip->entry_names == NULL)
 				return (-1);
@@ -2543,6 +2544,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
 			if ((p = header_bytes(a, 2)) == NULL)
 				return (-1);
 			allAreDefined = *p;
+			if (h->attrBools != NULL)
+				return (-1);
 			h->attrBools = calloc((size_t)zip->numFiles,
 			    sizeof(*h->attrBools));
 			if (h->attrBools == NULL)
@@ -3285,7 +3288,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
 		return (r);
 
 	/*
-	 * Skip the bytes we alrady has skipped in skip_stream().
+	 * Skip the bytes we already has skipped in skip_stream().
 	 */
 	while (skip_bytes) {
 		ssize_t skipped;
@@ -3503,7 +3506,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
 				return (ARCHIVE_FATAL);
 			}
 
-			/* Allocate memory for the decorded data of a sub
+			/* Allocate memory for the decoded data of a sub
 			 * stream. */
 			b[i] = malloc((size_t)zip->folder_outbytes_remaining);
 			if (b[i] == NULL) {
@@ -3588,7 +3591,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes)
 	if (zip->folder_index == 0) {
 		/*
 		 * Optimization for a list mode.
-		 * Avoid unncecessary decoding operations.
+		 * Avoid unnecessary decoding operations.
 		 */
 		zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes
 		    += skip_bytes;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c
index 4b5b66b..b6b9fc3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c
@@ -104,13 +104,12 @@ archive_read_support_format_ar(struct archive *_a)
 	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
 	    ARCHIVE_STATE_NEW, "archive_read_support_format_ar");
 
-	ar = (struct ar *)malloc(sizeof(*ar));
+	ar = (struct ar *)calloc(1, sizeof(*ar));
 	if (ar == NULL) {
 		archive_set_error(&a->archive, ENOMEM,
 		    "Can't allocate ar data");
 		return (ARCHIVE_FATAL);
 	}
-	memset(ar, 0, sizeof(*ar));
 	ar->strtab = NULL;
 
 	r = __archive_read_register_format(a,
@@ -260,7 +259,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
 		archive_entry_set_filetype(entry, AE_IFREG);
 		/* Get the size of the filename table. */
 		number = ar_atol10(h + AR_size_offset, AR_size_size);
-		if (number > SIZE_MAX) {
+		if (number > SIZE_MAX || number > 1024 * 1024 * 1024) {
 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 			    "Filename table too large");
 			return (ARCHIVE_FATAL);
@@ -316,7 +315,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
 		 * If we can't look up the real name, warn and return
 		 * the entry with the wrong name.
 		 */
-		if (ar->strtab == NULL || number > ar->strtab_size) {
+		if (ar->strtab == NULL || number >= ar->strtab_size) {
 			archive_set_error(&a->archive, EINVAL,
 			    "Can't find long filename for GNU/SVR4 archive entry");
 			archive_entry_copy_pathname(entry, filename);
@@ -342,16 +341,19 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
 
 		/* Parse the size of the name, adjust the file size. */
 		number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
-		bsd_name_length = (size_t)number;
-		/* Guard against the filename + trailing NUL
-		 * overflowing a size_t and against the filename size
-		 * being larger than the entire entry. */
-		if (number > (uint64_t)(bsd_name_length + 1)
-		    || (int64_t)bsd_name_length > ar->entry_bytes_remaining) {
+		/* Sanity check the filename length:
+		 *   = Must be <= SIZE_MAX - 1
+		 *   = Must be <= 1MB
+		 *   = Cannot be bigger than the entire entry
+		 */
+		if (number > SIZE_MAX - 1
+		    || number > 1024 * 1024
+		    || (int64_t)number > ar->entry_bytes_remaining) {
 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 			    "Bad input file size");
 			return (ARCHIVE_FATAL);
 		}
+		bsd_name_length = (size_t)number;
 		ar->entry_bytes_remaining -= bsd_name_length;
 		/* Adjust file size reported to client. */
 		archive_entry_set_size(entry, ar->entry_bytes_remaining);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
index 6356963..20eb157 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
@@ -67,7 +67,7 @@ struct lzx_dec {
 	/* The length how many bytes we can copy decoded code from
 	 * the window. */
 	int     		 copy_len;
-	/* Translation reversal for x86 proccessor CALL byte sequence(E8).
+	/* Translation reversal for x86 processor CALL byte sequence(E8).
 	 * This is used for LZX only. */
 	uint32_t		 translation_size;
 	char			 translation;
@@ -645,12 +645,13 @@ cab_read_header(struct archive_read *a)
 	cab = (struct cab *)(a->format->data);
 	if (cab->found_header == 0 &&
 	    p[0] == 'M' && p[1] == 'Z') {
-		/* This is an executable?  Must be self-extracting... 	*/
+		/* This is an executable?  Must be self-extracting... */
 		err = cab_skip_sfx(a);
 		if (err < ARCHIVE_WARN)
 			return (err);
 
-		if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL)
+		/* Re-read header after processing the SFX. */
+		if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
 			return (truncated_error(a));
 	}
 
@@ -1494,6 +1495,8 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
 
 		/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
 		if (mszip > 0) {
+			if (bytes_avail <= 0)
+				goto nomszip;
 			if (bytes_avail <= mszip) {
 				if (mszip == 2) {
 					if (cab->stream.next_in[0] != 0x43)
@@ -1554,7 +1557,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
 	/*
 	 * Note: I suspect there is a bug in makecab.exe because, in rare
 	 * case, compressed bytes are still remaining regardless we have
-	 * gotten all uncompressed bytes, which size is recoded in CFDATA,
+	 * gotten all uncompressed bytes, which size is recorded in CFDATA,
 	 * as much as we need, and we have to use the garbage so as to
 	 * correctly compute the sum of CFDATA accordingly.
 	 */
@@ -1741,7 +1744,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
 	}
 
 	/*
-	 * Translation reversal of x86 proccessor CALL byte sequence(E8).
+	 * Translation reversal of x86 processor CALL byte sequence(E8).
 	 */
 	lzx_translation(&cab->xstrm, cab->uncompressed_buffer,
 	    cfdata->uncompressed_size,
@@ -2270,7 +2273,7 @@ static int
 lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
 {
 /*
- * x86 proccessor family can read misaligned data without an access error.
+ * x86 processor family can read misaligned data without an access error.
  */
 	int n = CACHE_BITS - br->cache_avail;
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
index b09db0e..ffd4a85 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
@@ -326,7 +326,7 @@ archive_read_format_cpio_options(struct archive_read *a,
 
 	cpio = (struct cpio *)(a->format->data);
 	if (strcmp(key, "compat-2x")  == 0) {
-		/* Handle filnames as libarchive 2.x */
+		/* Handle filenames as libarchive 2.x */
 		cpio->init_default_conversion = (val != NULL)?1:0;
 		return (ARCHIVE_OK);
 	} else if (strcmp(key, "hdrcharset")  == 0) {
@@ -356,7 +356,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
     struct archive_entry *entry)
 {
 	struct cpio *cpio;
-	const void *h;
+	const void *h, *hl;
 	struct archive_string_conv *sconv;
 	size_t namelength;
 	size_t name_pad;
@@ -406,11 +406,11 @@ archive_read_format_cpio_read_header(struct archive_read *a,
 			    "Rejecting malformed cpio archive: symlink contents exceed 1 megabyte");
 			return (ARCHIVE_FATAL);
 		}
-		h = __archive_read_ahead(a,
+		hl = __archive_read_ahead(a,
 			(size_t)cpio->entry_bytes_remaining, NULL);
-		if (h == NULL)
+		if (hl == NULL)
 			return (ARCHIVE_FATAL);
-		if (archive_entry_copy_symlink_l(entry, (const char *)h,
+		if (archive_entry_copy_symlink_l(entry, (const char *)hl,
 		    (size_t)cpio->entry_bytes_remaining, sconv) != 0) {
 			if (errno == ENOMEM) {
 				archive_set_error(&a->archive, ENOMEM,
@@ -434,7 +434,8 @@ archive_read_format_cpio_read_header(struct archive_read *a,
 	 * header.  XXX */
 
 	/* Compare name to "TRAILER!!!" to test for end-of-archive. */
-	if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) {
+	if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!",
+	    11) == 0) {
 		/* TODO: Store file location of start of block. */
 		archive_clear_error(&a->archive);
 		return (ARCHIVE_EOF);
@@ -814,8 +815,8 @@ header_odc(struct archive_read *a, struct cpio *cpio,
  * NOTE: if a filename suffix is ".z", it is the file gziped by afio.
  * it would be nice that we can show uncompressed file size and we can
  * uncompressed file contents automatically, unfortunately we have nothing
- * to get a uncompressed file size while reading each header. it means
- * we also cannot uncompressed file contens under the our framework.
+ * to get a uncompressed file size while reading each header. It means
+ * we also cannot uncompress file contents under our framework.
  */
 static int
 header_afiol(struct archive_read *a, struct cpio *cpio,
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
index c19614a..3541330 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
@@ -322,7 +322,7 @@ struct iso9660 {
 
 	struct archive_string pathname;
 	char	seenRockridge;	/* Set true if RR extensions are used. */
-	char	seenSUSP;	/* Set true if SUSP is beging used. */
+	char	seenSUSP;	/* Set true if SUSP is being used. */
 	char	seenJoliet;
 
 	unsigned char	suspOffset;
@@ -374,7 +374,7 @@ struct iso9660 {
 	size_t		 utf16be_path_len;
 	unsigned char *utf16be_previous_path;
 	size_t		 utf16be_previous_path_len;
-	/* Null buufer used in bidder to improve its performance. */
+	/* Null buffer used in bidder to improve its performance. */
 	unsigned char	 null[2048];
 };
 
@@ -1199,7 +1199,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
 			    archive_string_conversion_from_charset(
 				&(a->archive), "UTF-16BE", 1);
 			if (iso9660->sconv_utf16be == NULL)
-				/* Coundn't allocate memory */
+				/* Couldn't allocate memory */
 				return (ARCHIVE_FATAL);
 		}
 		if (iso9660->utf16be_path == NULL) {
@@ -1864,7 +1864,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 		if ((file->utf16be_name = malloc(name_len)) == NULL) {
 			archive_set_error(&a->archive, ENOMEM,
 			    "No memory for file name");
-			return (NULL);
+			goto fail;
 		}
 		memcpy(file->utf16be_name, p, name_len);
 		file->utf16be_bytes = name_len;
@@ -1943,10 +1943,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 			file->symlink_continues = 0;
 			rr_start += iso9660->suspOffset;
 			r = parse_rockridge(a, file, rr_start, rr_end);
-			if (r != ARCHIVE_OK) {
-				free(file);
-				return (NULL);
-			}
+			if (r != ARCHIVE_OK)
+				goto fail;
 			/*
 			 * A file size of symbolic link files in ISO images
 			 * made by makefs is not zero and its location is
@@ -1990,7 +1988,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    "Invalid Rockridge RE");
-				return (NULL);
+				goto fail;
 			}
 			/*
 			 * Sanity check: file does not have "CL" extension.
@@ -1999,7 +1997,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    "Invalid Rockridge RE and CL");
-				return (NULL);
+				goto fail;
 			}
 			/*
 			 * Sanity check: The file type must be a directory.
@@ -2008,7 +2006,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    "Invalid Rockridge RE");
-				return (NULL);
+				goto fail;
 			}
 		} else if (parent != NULL && parent->rr_moved)
 			file->rr_moved_has_re_only = 0;
@@ -2022,7 +2020,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    "Invalid Rockridge CL");
-				return (NULL);
+				goto fail;
 			}
 			/*
 			 * Sanity check: The file type must be a regular file.
@@ -2031,7 +2029,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    "Invalid Rockridge CL");
-				return (NULL);
+				goto fail;
 			}
 			parent->subdirs++;
 			/* Overwrite an offset and a number of this "CL" entry
@@ -2049,7 +2047,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 					archive_set_error(&a->archive,
 					    ARCHIVE_ERRNO_MISC,
 					    "Invalid Rockridge CL");
-					return (NULL);
+					goto fail;
 				}
 			}
 			if (file->cl_offset == file->offset ||
@@ -2057,7 +2055,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    "Invalid Rockridge CL");
-				return (NULL);
+				goto fail;
 			}
 		}
 	}
@@ -2088,6 +2086,10 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 #endif
 	register_file(iso9660, file);
 	return (file);
+fail:
+	archive_string_free(&file->name);
+	free(file);
+	return (NULL);
 }
 
 static int
@@ -2407,7 +2409,7 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660)
 				return (ARCHIVE_FATAL);
 		} while (heap->cnt &&
 		    heap->reqs[0].offset == iso9660->current_position);
-		/* NOTE: Do not move this consume's code to fron of
+		/* NOTE: Do not move this consume's code to front of
 		 * do-while loop. Registration of nested CE extension
 		 * might cause error because of current position. */
 		__archive_read_consume(a, step);
@@ -2729,7 +2731,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
 		if (file == NULL) {
 			/*
 			 * If directory entries all which are descendant of
-			 * rr_moved are stil remaning, expose their. 
+			 * rr_moved are still remaining, expose their.
 			 */
 			if (iso9660->re_files.first != NULL && 
 			    iso9660->rr_moved != NULL &&
@@ -2852,7 +2854,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
 	empty_files.last = &empty_files.first;
 	/* Collect files which has the same file serial number.
 	 * Peek pending_files so that file which number is different
-	 * is not put bak. */
+	 * is not put back. */
 	while (iso9660->pending_files.used > 0 &&
 	    (iso9660->pending_files.files[0]->number == -1 ||
 	     iso9660->pending_files.files[0]->number == number)) {
@@ -2860,7 +2862,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
 			/* This file has the same offset
 			 * but it's wrong offset which empty files
 			 * and symlink files have.
-			 * NOTE: This wrong offse was recorded by
+			 * NOTE: This wrong offset was recorded by
 			 * old mkisofs utility. If ISO images is
 			 * created by latest mkisofs, this does not
 			 * happen.
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
index eff02d8..ebd7f2c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
@@ -924,6 +924,9 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
 	/* Get a real compressed file size. */
 	lha->compsize -= extdsize - 2;
 
+	if (lha->compsize < 0)
+		goto invalid;	/* Invalid compressed file size */
+
 	if (sum_calculated != headersum) {
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 		    "LHa header sum error");
@@ -1711,14 +1714,18 @@ lha_crc16(uint16_t crc, const void *pp, size_t len)
 	 */
 	for (;len >= 8; len -= 8) {
 		/* This if statement expects compiler optimization will
-		 * remove the stament which will not be executed. */
+		 * remove the statement which will not be executed. */
+#undef bswap16
 #ifndef __has_builtin
 #  define __has_builtin(x) 0
 #endif
 #if defined(_MSC_VER) && _MSC_VER >= 1400  /* Visual Studio */
 #  define bswap16(x) _byteswap_ushort(x)
-#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \
-      || (defined(__clang__) && __has_builtin(__builtin_bswap16))
+#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4)
+/* GCC 4.8 and later has __builtin_bswap16() */
+#  define bswap16(x) __builtin_bswap16(x)
+#elif defined(__clang__) && __has_builtin(__builtin_bswap16)
+/* All clang versions have __builtin_bswap16() */
 #  define bswap16(x) __builtin_bswap16(x)
 #else
 #  define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8))
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
index 8c3be9a..4231ff5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
@@ -75,6 +75,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
 #define	MTREE_HAS_OPTIONAL	0x0800
 #define	MTREE_HAS_NOCHANGE	0x1000 /* FreeBSD specific */
 
+#define	MTREE_HASHTABLE_SIZE 1024
+
 struct mtree_option {
 	struct mtree_option *next;
 	char *value;
@@ -86,6 +88,8 @@ struct mtree_entry {
 	char *name;
 	char full;
 	char used;
+	unsigned int name_hash;
+	struct mtree_entry *hashtable_next;
 };
 
 struct mtree {
@@ -98,6 +102,7 @@ struct mtree {
 	const char		*archive_format_name;
 	struct mtree_entry	*entries;
 	struct mtree_entry	*this_entry;
+	struct mtree_entry	*entry_hashtable[MTREE_HASHTABLE_SIZE];
 	struct archive_string	 current_dir;
 	struct archive_string	 contents_name;
 
@@ -110,6 +115,7 @@ struct mtree {
 static int	bid_keycmp(const char *, const char *, ssize_t);
 static int	cleanup(struct archive_read *);
 static int	detect_form(struct archive_read *, int *);
+static unsigned int	hash(const char *);
 static int	mtree_bid(struct archive_read *, int);
 static int	parse_file(struct archive_read *, struct archive_entry *,
 		    struct mtree *, struct mtree_entry *, int *);
@@ -223,13 +229,12 @@ archive_read_support_format_mtree(struct archive *_a)
 	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
 	    ARCHIVE_STATE_NEW, "archive_read_support_format_mtree");
 
-	mtree = (struct mtree *)malloc(sizeof(*mtree));
+	mtree = (struct mtree *)calloc(1, sizeof(*mtree));
 	if (mtree == NULL) {
 		archive_set_error(&a->archive, ENOMEM,
 		    "Can't allocate mtree data");
 		return (ARCHIVE_FATAL);
 	}
-	memset(mtree, 0, sizeof(*mtree));
 	mtree->fd = -1;
 
 	r = __archive_read_register_format(a, mtree, "mtree",
@@ -301,6 +306,15 @@ get_line_size(const char *b, ssize_t avail, ssize_t *nlsize)
 	return (avail);
 }
 
+/*
+ *  <---------------- ravail --------------------->
+ *  <-- diff ------> <---  avail ----------------->
+ *                   <---- len ----------->
+ * | Previous lines | line being parsed  nl extra |
+ *                  ^
+ *                  b
+ *
+ */
 static ssize_t
 next_line(struct archive_read *a,
     const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
@@ -339,7 +353,7 @@ next_line(struct archive_read *a,
 		*b += diff;
 		*avail -= diff;
 		tested = len;/* Skip some bytes we already determinated. */
-		len = get_line_size(*b, *avail, nl);
+		len = get_line_size(*b + len, *avail - len, nl);
 		if (len >= 0)
 			len += tested;
 	}
@@ -701,13 +715,13 @@ detect_form(struct archive_read *a, int *is_form_d)
 				}
 			} else
 				break;
-		} else if (strncmp(p, "/set", 4) == 0) {
+		} else if (len > 4 && strncmp(p, "/set", 4) == 0) {
 			if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
 				break;
 			/* This line continues. */
 			if (p[len-nl-1] == '\\')
 				multiline = 2;
-		} else if (strncmp(p, "/unset", 6) == 0) {
+		} else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
 			if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
 				break;
 			/* This line continues. */
@@ -853,11 +867,12 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
     struct mtree_option **global, const char *line, ssize_t line_len,
     struct mtree_entry **last_entry, int is_form_d)
 {
-	struct mtree_entry *entry;
+	struct mtree_entry *entry, *ht_iter;
 	struct mtree_option *iter;
 	const char *next, *eq, *name, *end;
 	size_t name_len, len;
 	int r, i;
+	unsigned int ht_idx;
 
 	if ((entry = malloc(sizeof(*entry))) == NULL) {
 		archive_set_error(&a->archive, errno, "Can't allocate memory");
@@ -868,6 +883,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
 	entry->name = NULL;
 	entry->used = 0;
 	entry->full = 0;
+	entry->name_hash = 0;
+	entry->hashtable_next = NULL;
 
 	/* Add this entry to list. */
 	if (*last_entry == NULL)
@@ -920,6 +937,16 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
 	memcpy(entry->name, name, name_len);
 	entry->name[name_len] = '\0';
 	parse_escapes(entry->name, entry);
+	entry->name_hash = hash(entry->name);
+
+	ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE;
+	if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) {
+		while (ht_iter->hashtable_next)
+			ht_iter = ht_iter->hashtable_next;
+		ht_iter->hashtable_next = entry;
+	} else {
+		mtree->entry_hashtable[ht_idx] = entry;
+	}
 
 	for (iter = *global; iter != NULL; iter = iter->next) {
 		r = add_option(a, &entry->options, iter->value,
@@ -992,11 +1019,11 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
 		if (*p != '/') {
 			r = process_add_entry(a, mtree, &global, p, len,
 			    &last_entry, is_form_d);
-		} else if (strncmp(p, "/set", 4) == 0) {
+		} else if (len > 4 && strncmp(p, "/set", 4) == 0) {
 			if (p[4] != ' ' && p[4] != '\t')
 				break;
 			r = process_global_set(a, &global, p);
-		} else if (strncmp(p, "/unset", 6) == 0) {
+		} else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
 			if (p[6] != ' ' && p[6] != '\t')
 				break;
 			r = process_global_unset(a, &global, p);
@@ -1113,9 +1140,10 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
 		 * with pathname canonicalization, which is a very
 		 * tricky subject.)
 		 */
-		for (mp = mentry->next; mp != NULL; mp = mp->next) {
+		for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) {
 			if (mp->full && !mp->used
-			    && strcmp(mentry->name, mp->name) == 0) {
+					&& mentry->name_hash == mp->name_hash
+					&& strcmp(mentry->name, mp->name) == 0) {
 				/* Later lines override earlier ones. */
 				mp->used = 1;
 				r1 = parse_line(a, entry, mtree, mp,
@@ -1580,8 +1608,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
 			if (*val == '.') {
 				++val;
 				ns = (long)mtree_atol10(&val);
-			} else
-				ns = 0;
+				if (ns < 0)
+					ns = 0;
+				else if (ns > 999999999)
+					ns = 999999999;
+			}
 			if (m > my_time_t_max)
 				m = my_time_t_max;
 			else if (m < my_time_t_min)
@@ -1991,3 +2022,19 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
 		find_off = u - mtree->line.s;
 	}
 }
+
+static unsigned int
+hash(const char *p)
+{
+	/* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
+	   as used by ELF for hashing function names. */
+	unsigned g, h = 0;
+	while (*p != '\0') {
+		h = (h << 4) + *p++;
+		if ((g = h & 0xF0000000) != 0) {
+			h ^= g >> 24;
+			h &= 0x0FFFFFFF;
+		}
+	}
+	return h;
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
index fc8153f..658d49d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
@@ -647,13 +647,12 @@ archive_read_support_format_rar(struct archive *_a)
   archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
                       "archive_read_support_format_rar");
 
-  rar = (struct rar *)malloc(sizeof(*rar));
+  rar = (struct rar *)calloc(sizeof(*rar), 1);
   if (rar == NULL)
   {
     archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data");
     return (ARCHIVE_FATAL);
   }
-  memset(rar, 0, sizeof(*rar));
 
 	/*
 	 * Until enough data has been read, we cannot tell about
@@ -907,7 +906,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
                             sizeof(rar->reserved2));
       }
 
-      /* Main header is password encrytped, so we cannot read any
+      /* Main header is password encrypted, so we cannot read any
          file names or any other info about files from the header. */
       if (rar->main_flags & MHD_PASSWORD)
       {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
index b0521a6..bd7f13d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2003-2007 Tim Kientzle
  * Copyright (c) 2011-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2016 Martin Matuska
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -136,6 +137,7 @@ struct tar {
 	int64_t			 entry_padding;
 	int64_t 		 entry_bytes_unconsumed;
 	int64_t			 realsize;
+	int			 sparse_allowed;
 	struct sparse_block	*sparse_list;
 	struct sparse_block	*sparse_last;
 	int64_t			 sparse_offset;
@@ -202,9 +204,14 @@ static int	archive_read_format_tar_read_header(struct archive_read *,
 		    struct archive_entry *);
 static int	checksum(struct archive_read *, const void *);
 static int 	pax_attribute(struct archive_read *, struct tar *,
-		    struct archive_entry *, const char *key, const char *value);
+		    struct archive_entry *, const char *key, const char *value,
+		    size_t value_length);
+static int	pax_attribute_acl(struct archive_read *, struct tar *,
+		    struct archive_entry *, const char *, int);
+static int	pax_attribute_xattr(struct archive_entry *, const char *,
+		    const char *);
 static int 	pax_header(struct archive_read *, struct tar *,
-		    struct archive_entry *, char *attr);
+		    struct archive_entry *, struct archive_string *);
 static void	pax_time(const char *, int64_t *sec, long *nanos);
 static ssize_t	readline(struct archive_read *, struct tar *, const char **,
 		    ssize_t limit, size_t *);
@@ -293,6 +300,57 @@ archive_read_format_tar_cleanup(struct archive_read *a)
 	return (ARCHIVE_OK);
 }
 
+/*
+ * Validate number field
+ *
+ * This has to be pretty lenient in order to accommodate the enormous
+ * variety of tar writers in the world:
+ *  = POSIX (IEEE Std 1003.1-1988) ustar requires octal values with leading
+ *    zeros and allows fields to be terminated with space or null characters
+ *  = Many writers use different termination (in particular, libarchive
+ *    omits terminator bytes to squeeze one or two more digits)
+ *  = Many writers pad with space and omit leading zeros
+ *  = GNU tar and star write base-256 values if numbers are too
+ *    big to be represented in octal
+ *
+ *  Examples of specific tar headers that we should support:
+ *  = Perl Archive::Tar terminates uid, gid, devminor and devmajor with two
+ *    null bytes, pads size with spaces and other numeric fields with zeroes
+ *  = plexus-archiver prior to 2.6.3 (before switching to commons-compress)
+ *    may have uid and gid fields filled with spaces without any octal digits
+ *    at all and pads all numeric fields with spaces
+ *
+ * This should tolerate all variants in use.  It will reject a field
+ * where the writer just left garbage after a trailing NUL.
+ */
+static int
+validate_number_field(const char* p_field, size_t i_size)
+{
+	unsigned char marker = (unsigned char)p_field[0];
+	if (marker == 128 || marker == 255 || marker == 0) {
+		/* Base-256 marker, there's nothing we can check. */
+		return 1;
+	} else {
+		/* Must be octal */
+		size_t i = 0;
+		/* Skip any leading spaces */
+		while (i < i_size && p_field[i] == ' ') {
+			++i;
+		}
+		/* Skip octal digits. */
+		while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') {
+			++i;
+		}
+		/* Any remaining characters must be space or NUL padding. */
+		while (i < i_size) {
+			if (p_field[i] != ' ' && p_field[i] != 0) {
+				return 0;
+			}
+			++i;
+		}
+		return 1;
+	}
+}
 
 static int
 archive_read_format_tar_bid(struct archive_read *a, int best_bid)
@@ -345,23 +403,19 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid)
 		return (0);
 	bid += 2;  /* 6 bits of variation in an 8-bit field leaves 2 bits. */
 
-	/* Sanity check: Look at first byte of mode field. */
-	switch (255 & (unsigned)header->mode[0]) {
-	case 0: case 255:
-		/* Base-256 value: No further verification possible! */
-		break;
-	case ' ': /* Not recommended, but not illegal, either. */
-		break;
-	case '0': case '1': case '2': case '3':
-	case '4': case '5': case '6': case '7':
-		/* Octal Value. */
-		/* TODO: Check format of remainder of this field. */
-		break;
-	default:
-		/* Not a valid mode; bail out here. */
-		return (0);
+	/*
+	 * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
+	 */
+	if (bid > 0 && (
+	    validate_number_field(header->mode, sizeof(header->mode)) == 0
+	    || validate_number_field(header->uid, sizeof(header->uid)) == 0
+	    || validate_number_field(header->gid, sizeof(header->gid)) == 0
+	    || validate_number_field(header->mtime, sizeof(header->mtime)) == 0
+	    || validate_number_field(header->size, sizeof(header->size)) == 0
+	    || validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0
+	    || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) {
+		bid = 0;
 	}
-	/* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */
 
 	return (bid);
 }
@@ -375,7 +429,7 @@ archive_read_format_tar_options(struct archive_read *a,
 
 	tar = (struct tar *)(a->format->data);
 	if (strcmp(key, "compat-2x")  == 0) {
-		/* Handle UTF-8 filnames as libarchive 2.x */
+		/* Handle UTF-8 filenames as libarchive 2.x */
 		tar->compat_2x = (val != NULL && val[0] != 0);
 		tar->init_default_conversion = tar->compat_2x;
 		return (ARCHIVE_OK);
@@ -793,9 +847,9 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 				tar->sparse_gnu_pending = 0;
 				/* Read initial sparse map. */
 				bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
-				tar->entry_bytes_remaining -= bytes_read;
 				if (bytes_read < 0)
 					return ((int)bytes_read);
+				tar->entry_bytes_remaining -= bytes_read;
 			} else {
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
@@ -890,7 +944,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
 {
 	const struct archive_entry_header_ustar *header;
 	size_t size;
-	int err;
+	int err, acl_type;
 	int64_t type;
 	char *acl, *p;
 
@@ -935,11 +989,12 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
 	switch ((int)type & ~0777777) {
 	case 01000000:
 		/* POSIX.1e ACL */
+		acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
 		break;
 	case 03000000:
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Solaris NFSv4 ACLs not supported");
-		return (ARCHIVE_WARN);
+		/* NFSv4 ACL */
+		acl_type = ARCHIVE_ENTRY_ACL_TYPE_NFS4;
+		break;
 	default:
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 		    "Malformed Solaris ACL attribute (unsupported type %o)",
@@ -968,8 +1023,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
 			return (ARCHIVE_FATAL);
 	}
 	archive_strncpy(&(tar->localname), acl, p - acl);
-	err = archive_acl_parse_l(archive_entry_acl(entry),
-	    tar->localname.s, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, tar->sconv_acl);
+	err = archive_acl_from_text_l(archive_entry_acl(entry),
+	    tar->localname.s, acl_type, tar->sconv_acl);
 	if (err != ARCHIVE_OK) {
 		if (errno == ENOMEM) {
 			archive_set_error(&a->archive, ENOMEM,
@@ -1128,8 +1183,15 @@ header_common(struct archive_read *a, struct tar *tar,
 	if (tar->entry_bytes_remaining < 0) {
 		tar->entry_bytes_remaining = 0;
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Tar entry has negative size?");
-		err = ARCHIVE_WARN;
+		    "Tar entry has negative size");
+		return (ARCHIVE_FATAL);
+	}
+	if (tar->entry_bytes_remaining == INT64_MAX) {
+		/* Note: tar_atol returns INT64_MAX on overflow */
+		tar->entry_bytes_remaining = 0;
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+		    "Tar entry size overflow");
+		return (ARCHIVE_FATAL);
 	}
 	tar->realsize = tar->entry_bytes_remaining;
 	archive_entry_set_size(entry, tar->entry_bytes_remaining);
@@ -1264,6 +1326,14 @@ header_common(struct archive_read *a, struct tar *tar,
 		 * sparse information in the extended area.
 		 */
 		/* FALLTHROUGH */
+	case '0':
+		/*
+		 * Enable sparse file "read" support only for regular
+		 * files and explicit GNU sparse files.  However, we
+		 * don't allow non-standard file types to be sparse.
+		 */
+		tar->sparse_allowed = 1;
+		/* FALLTHROUGH */
 	default: /* Regular file  and non-standard types */
 		/*
 		 * Per POSIX: non-recognized types should always be
@@ -1415,7 +1485,7 @@ header_pax_extensions(struct archive_read *a, struct tar *tar,
 	 * and then skip any fields in the standard header that were
 	 * defined in the pax header.
 	 */
-	err2 = pax_header(a, tar, entry, tar->pax_header.s);
+	err2 = pax_header(a, tar, entry, &tar->pax_header);
 	err =  err_combine(err, err2);
 	tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
 	return (err);
@@ -1496,16 +1566,17 @@ header_ustar(struct archive_read *a, struct tar *tar,
  */
 static int
 pax_header(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, char *attr)
+    struct archive_entry *entry, struct archive_string *in_as)
 {
-	size_t attr_length, l, line_length;
+	size_t attr_length, l, line_length, value_length;
 	char *p;
 	char *key, *value;
 	struct archive_string *as;
 	struct archive_string_conv *sconv;
 	int err, err2;
+	char *attr = in_as->s;
 
-	attr_length = strlen(attr);
+	attr_length = in_as->length;
 	tar->pax_hdrcharset_binary = 0;
 	archive_string_empty(&(tar->entry_gname));
 	archive_string_empty(&(tar->entry_linkpath));
@@ -1570,11 +1641,13 @@ pax_header(struct archive_read *a, struct tar *tar,
 		}
 		*p = '\0';
 
-		/* Identify null-terminated 'value' portion. */
 		value = p + 1;
 
+		/* Some values may be binary data */
+		value_length = attr + line_length - 1 - value;
+
 		/* Identify this attribute and set it in the entry. */
-		err2 = pax_attribute(a, tar, entry, key, value);
+		err2 = pax_attribute(a, tar, entry, key, value, value_length);
 		if (err2 == ARCHIVE_FATAL)
 			return (err2);
 		err = err_combine(err, err2);
@@ -1695,6 +1768,66 @@ pax_attribute_xattr(struct archive_entry *entry,
 	return 0;
 }
 
+static int
+pax_attribute_schily_xattr(struct archive_entry *entry,
+	const char *name, const char *value, size_t value_length)
+{
+	if (strlen(name) < 14 || (memcmp(name, "SCHILY.xattr.", 13)) != 0)
+		return 1;
+
+	name += 13;
+
+	archive_entry_xattr_add_entry(entry, name, 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)
+{
+	int r;
+	const char* errstr;
+
+	switch (type) {
+	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+		errstr = "SCHILY.acl.access";
+		break;
+	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+		errstr = "SCHILY.acl.default";
+		break;
+	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
+		errstr = "SCHILY.acl.ace";
+		break;
+	default:
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+		    "Unknown ACL type: %d", type);
+		return(ARCHIVE_FATAL);
+	}
+
+	if (tar->sconv_acl == NULL) {
+		tar->sconv_acl =
+		    archive_string_conversion_from_charset(
+			&(a->archive), "UTF-8", 1);
+		if (tar->sconv_acl == NULL)
+			return (ARCHIVE_FATAL);
+	}
+
+	r = archive_acl_from_text_l(archive_entry_acl(entry), value, type,
+	    tar->sconv_acl);
+	if (r != ARCHIVE_OK) {
+		if (r == ARCHIVE_FATAL) {
+			archive_set_error(&a->archive, ENOMEM,
+			    "%s %s", "Can't allocate memory for ",
+			    errstr);
+			return (r);
+		}
+		archive_set_error(&a->archive,
+		    ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr);
+	}
+	return (r);
+}
+
 /*
  * Parse a single key=value attribute.  key/value pointers are
  * assumed to point into reasonably long-lived storage.
@@ -1710,7 +1843,7 @@ pax_attribute_xattr(struct archive_entry *entry,
  */
 static int
 pax_attribute(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const char *key, const char *value)
+    struct archive_entry *entry, const char *key, const char *value, size_t value_length)
 {
 	int64_t s;
 	long n;
@@ -1721,6 +1854,14 @@ pax_attribute(struct archive_read *a, struct tar *tar,
 				 * NULL pointer to strlen().  */
 	switch (key[0]) {
 	case 'G':
+		/* Reject GNU.sparse.* headers on non-regular files. */
+		if (strncmp(key, "GNU.sparse", 10) == 0 &&
+		    !tar->sparse_allowed) {
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+			    "Non-regular file cannot be sparse");
+			return (ARCHIVE_FATAL);
+		}
+
 		/* GNU "0.0" sparse pax format. */
 		if (strcmp(key, "GNU.sparse.numblocks") == 0) {
 			tar->sparse_offset = -1;
@@ -1803,53 +1944,20 @@ pax_attribute(struct archive_read *a, struct tar *tar,
 	case 'S':
 		/* We support some keys used by the "star" archiver */
 		if (strcmp(key, "SCHILY.acl.access") == 0) {
-			if (tar->sconv_acl == NULL) {
-				tar->sconv_acl =
-				    archive_string_conversion_from_charset(
-					&(a->archive), "UTF-8", 1);
-				if (tar->sconv_acl == NULL)
-					return (ARCHIVE_FATAL);
-			}
-
-			r = archive_acl_parse_l(archive_entry_acl(entry),
-			    value, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
-			    tar->sconv_acl);
-			if (r != ARCHIVE_OK) {
-				err = r;
-				if (err == ARCHIVE_FATAL) {
-					archive_set_error(&a->archive, ENOMEM,
-					    "Can't allocate memory for "
-					    "SCHILY.acl.access");
-					return (err);
-				}
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Parse error: SCHILY.acl.access");
-			}
+			r = pax_attribute_acl(a, tar, entry, value,
+			    ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+			if (r == ARCHIVE_FATAL)
+				return (r);
 		} else if (strcmp(key, "SCHILY.acl.default") == 0) {
-			if (tar->sconv_acl == NULL) {
-				tar->sconv_acl =
-				    archive_string_conversion_from_charset(
-					&(a->archive), "UTF-8", 1);
-				if (tar->sconv_acl == NULL)
-					return (ARCHIVE_FATAL);
-			}
-
-			r = archive_acl_parse_l(archive_entry_acl(entry),
-			    value, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
-			    tar->sconv_acl);
-			if (r != ARCHIVE_OK) {
-				err = r;
-				if (err == ARCHIVE_FATAL) {
-					archive_set_error(&a->archive, ENOMEM,
-					    "Can't allocate memory for "
-					    "SCHILY.acl.default");
-					return (err);
-				}
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Parse error: SCHILY.acl.default");
-			}
+			r = pax_attribute_acl(a, tar, entry, value,
+			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
+			if (r == ARCHIVE_FATAL)
+				return (r);
+		} else if (strcmp(key, "SCHILY.acl.ace") == 0) {
+			r = pax_attribute_acl(a, tar, entry, value,
+			    ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+			if (r == ARCHIVE_FATAL)
+				return (r);
 		} else if (strcmp(key, "SCHILY.devmajor") == 0) {
 			archive_entry_set_rdevmajor(entry,
 			    (dev_t)tar_atol10(value, strlen(value)));
@@ -1870,6 +1978,9 @@ pax_attribute(struct archive_read *a, struct tar *tar,
 		} else if (strcmp(key, "SCHILY.realsize") == 0) {
 			tar->realsize = tar_atol10(value, strlen(value));
 			archive_entry_set_size(entry, tar->realsize);
+		} else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
+			pax_attribute_schily_xattr(entry, key, value,
+			    value_length);
 		} else if (strcmp(key, "SUN.holesdata") == 0) {
 			/* A Solaris extension for sparse. */
 			r = solaris_sparse_parse(a, tar, entry, value);
@@ -2116,12 +2227,11 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
 {
 	struct sparse_block *p;
 
-	p = (struct sparse_block *)malloc(sizeof(*p));
+	p = (struct sparse_block *)calloc(1, sizeof(*p));
 	if (p == NULL) {
 		archive_set_error(&a->archive, ENOMEM, "Out of memory");
 		return (ARCHIVE_FATAL);
 	}
-	memset(p, 0, sizeof(*p));
 	if (tar->sparse_last != NULL)
 		tar->sparse_last->next = p;
 	else
@@ -2377,6 +2487,9 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
 	tar_flush_unconsumed(a, unconsumed);
 	bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
 	to_skip = 0x1ff & -bytes_read;
+	/* Fail if tar->entry_bytes_remaing would get negative */
+	if (to_skip > remaining)
+		return (ARCHIVE_FATAL);
 	if (to_skip != __archive_read_consume(a, to_skip))
 		return (ARCHIVE_FATAL);
 	return ((ssize_t)(bytes_read + to_skip));
@@ -2472,7 +2585,7 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
 	last_digit_limit = INT64_MAX % base;
 
 	/* the pointer will not be dereferenced if char_cnt is zero
-	 * due to the way the && operator is evaulated.
+	 * due to the way the && operator is evaluated.
 	 */
 	while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
 		p++;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
index 46a59ea..b162465 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
@@ -88,7 +88,7 @@ typedef enum {
 	WT_RVIS,
 	/* conversion, unsupported */
 	WT_CONV,
-	/* continutation, unsupported at the moment */
+	/* continuation, unsupported at the moment */
 	WT_CONT,
 	/* invalid type */
 	LAST_WT
@@ -134,8 +134,8 @@ static ssize_t _warc_rdlen(const char *buf, size_t bsz);
 static time_t _warc_rdrtm(const char *buf, size_t bsz);
 static time_t _warc_rdmtm(const char *buf, size_t bsz);
 static const char *_warc_find_eoh(const char *buf, size_t bsz);
+static const char *_warc_find_eol(const char *buf, size_t bsz);
 
-

 int
 archive_read_support_format_warc(struct archive *_a)
 {
@@ -146,12 +146,11 @@ archive_read_support_format_warc(struct archive *_a)
 	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
 	    ARCHIVE_STATE_NEW, "archive_read_support_format_warc");
 
-	if ((w = malloc(sizeof(*w))) == NULL) {
+	if ((w = calloc(1, sizeof(*w))) == NULL) {
 		archive_set_error(&a->archive, ENOMEM,
 		    "Can't allocate warc data");
 		return (ARCHIVE_FATAL);
 	}
-	memset(w, 0, sizeof(*w));
 
 	r = __archive_read_register_format(
 		a, w, "warc",
@@ -199,8 +198,8 @@ _warc_bid(struct archive_read *a, int best_bid)
 
 	/* otherwise snarf the record's version number */
 	ver = _warc_rdver(hdr, nrd);
-	if (ver == 0U || ver > 10000U) {
-		/* oh oh oh, best not to wager ... */
+	if (ver < 1200U || ver > 10000U) {
+		/* we only support WARC 0.12 to 1.0 */
 		return -1;
 	}
 
@@ -255,23 +254,32 @@ start_over:
 			&a->archive, ARCHIVE_ERRNO_MISC,
 			"Bad record header");
 		return (ARCHIVE_FATAL);
-	} else if ((ver = _warc_rdver(buf, eoh - buf)) > 10000U) {
-		/* nawww, I wish they promised backward compatibility
-		 * anyhoo, in their infinite wisdom the 28500 guys might
-		 * come up with something we can't possibly handle so
-		 * best end things here */
+	}
+	ver = _warc_rdver(buf, eoh - buf);
+	/* we currently support WARC 0.12 to 1.0 */
+	if (ver == 0U) {
 		archive_set_error(
 			&a->archive, ARCHIVE_ERRNO_MISC,
-			"Unsupported record version");
+			"Invalid record version");
 		return (ARCHIVE_FATAL);
-	} else if ((cntlen = _warc_rdlen(buf, eoh - buf)) < 0) {
+	} else if (ver < 1200U || ver > 10000U) {
+		archive_set_error(
+			&a->archive, ARCHIVE_ERRNO_MISC,
+			"Unsupported record version: %u.%u",
+			ver / 10000, (ver % 10000) / 100);
+		return (ARCHIVE_FATAL);
+	}
+	cntlen = _warc_rdlen(buf, eoh - buf);
+	if (cntlen < 0) {
 		/* nightmare!  the specs say content-length is mandatory
 		 * so I don't feel overly bad stopping the reader here */
 		archive_set_error(
 			&a->archive, EINVAL,
 			"Bad content length");
 		return (ARCHIVE_FATAL);
-	} else if ((rtime = _warc_rdrtm(buf, eoh - buf)) == (time_t)-1) {
+	}
+	rtime = _warc_rdrtm(buf, eoh - buf);
+	if (rtime == (time_t)-1) {
 		/* record time is mandatory as per WARC/1.0,
 		 * so just barf here, fast and loud */
 		archive_set_error(
@@ -285,7 +293,7 @@ start_over:
 	if (ver != w->pver) {
 		/* stringify this entry's version */
 		archive_string_sprintf(&w->sver,
-			"WARC/%u.%u", ver / 10000, ver % 10000);
+			"WARC/%u.%u", ver / 10000, (ver % 10000) / 100);
 		/* remember the version */
 		w->pver = ver;
 	}
@@ -318,7 +326,7 @@ start_over:
 		}
 		memcpy(w->pool.str, fnam.str, fnam.len);
 		w->pool.str[fnam.len] = '\0';
-		/* let noone else know about the pool, it's a secret, shhh */
+		/* let no one else know about the pool, it's a secret, shhh */
 		fnam.str = w->pool.str;
 
 		/* snarf mtime or deduce from rtime
@@ -535,7 +543,8 @@ xstrpisotime(const char *s, char **endptr)
 
 	/* as a courtesy to our callers, and since this is a non-standard
 	 * routine, we skip leading whitespace */
-	for (; isspace(*s); s++);
+	while (*s == ' ' || *s == '\t')
+		++s;
 
 	/* read year */
 	if ((tm.tm_year = strtoi_lim(s, &s, 1583, 4095)) < 0 || *s++ != '-') {
@@ -562,7 +571,7 @@ xstrpisotime(const char *s, char **endptr)
 		goto out;
 	}
 
-	/* massage TM to fulfill some of POSIX' contraints */
+	/* massage TM to fulfill some of POSIX' constraints */
 	tm.tm_year -= 1900;
 	tm.tm_mon--;
 
@@ -577,51 +586,43 @@ out:
 }
 
 static unsigned int
-_warc_rdver(const char buf[10], size_t bsz)
+_warc_rdver(const char *buf, size_t bsz)
 {
 	static const char magic[] = "WARC/";
-	unsigned int ver;
-
-	(void)bsz; /* UNUSED */
+	const char *c;
+	unsigned int ver = 0U;
+	unsigned int end = 0U;
 
-	if (memcmp(buf, magic, sizeof(magic) - 1U) != 0) {
-		/* nope */
-		return 99999U;
+	if (bsz < 12 || memcmp(buf, magic, sizeof(magic) - 1U) != 0) {
+		/* buffer too small or invalid magic */
+		return ver;
 	}
 	/* looks good so far, read the version number for a laugh */
 	buf += sizeof(magic) - 1U;
-	/* most common case gets a quick-check here */
-	if (memcmp(buf, "1.0\r\n", 5U) == 0) {
-		ver = 10000U;
-	} else {
-		switch (*buf) {
-		case '0':
-		case '1':
-		case '2':
-		case '3':
-		case '4':
-		case '5':
-		case '6':
-		case '7':
-		case '8':
-			if (buf[1U] == '.') {
-				char *on;
-
-				/* set up major version */
-				ver = (buf[0U] - '0') * 10000U;
-				/* minor version, anyone? */
-				ver += (strtol(buf + 2U, &on, 10)) * 100U;
-				/* don't parse anything else */
-				if (on > buf + 2U) {
-					break;
-				}
-			}
-			/* FALLTHROUGH */
-		case '9':
-		default:
-			/* just make the version ridiculously high */
-			ver = 999999U;
-			break;
+
+	if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) {
+		/* we support a maximum of 2 digits in the minor version */
+		if (isdigit(buf[3U]))
+			end = 1U;
+		/* set up major version */
+		ver = (buf[0U] - '0') * 10000U;
+		/* set up minor version */
+		if (end == 1U) {
+			ver += (buf[2U] - '0') * 1000U;
+			ver += (buf[3U] - '0') * 100U;
+		} else
+			ver += (buf[2U] - '0') * 100U;
+		/*
+		 * WARC below version 0.12 has a space-separated header
+		 * WARC 0.12 and above terminates the version with a CRLF
+		 */
+		c = buf + 3U + end;
+		if (ver >= 1200U) {
+			if (memcmp(c, "\r\n", 2U) != 0)
+				ver = 0U;
+		} else if (ver < 1200U) {
+			if (*c != ' ' && *c != '\t')
+				ver = 0U;
 		}
 	}
 	return ver;
@@ -631,32 +632,27 @@ static unsigned int
 _warc_rdtyp(const char *buf, size_t bsz)
 {
 	static const char _key[] = "\r\nWARC-Type:";
-	const char *const eob = buf + bsz;
-	const char *val;
+	const char *val, *eol;
 
 	if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
 		/* no bother */
 		return WT_NONE;
 	}
+	val += sizeof(_key) - 1U;
+	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+		/* no end of line */
+		return WT_NONE;
+	}
+
 	/* overread whitespace */
-	for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++);
-
-	if (val + 8U > eob) {
-		;
-	} else if (memcmp(val, "resource", 8U) == 0) {
-		return WT_RSRC;
-	} else if (memcmp(val, "warcinfo", 8U) == 0) {
-		return WT_INFO;
-	} else if (memcmp(val, "metadata", 8U) == 0) {
-		return WT_META;
-	} else if (memcmp(val, "request", 7U) == 0) {
-		return WT_REQ;
-	} else if (memcmp(val, "response", 8U) == 0) {
-		return WT_RSP;
-	} else if (memcmp(val, "conversi", 8U) == 0) {
-		return WT_CONV;
-	} else if (memcmp(val, "continua", 8U) == 0) {
-		return WT_CONT;
+	while (val < eol && (*val == ' ' || *val == '\t'))
+		++val;
+
+	if (val + 8U == eol) {
+		if (memcmp(val, "resource", 8U) == 0)
+			return WT_RSRC;
+		else if (memcmp(val, "response", 8U) == 0)
+			return WT_RSP;
 	}
 	return WT_NONE;
 }
@@ -665,10 +661,7 @@ static warc_string_t
 _warc_rduri(const char *buf, size_t bsz)
 {
 	static const char _key[] = "\r\nWARC-Target-URI:";
-	const char *const eob = buf + bsz;
-	const char *val;
-	const char *uri;
-	const char *eol;
+	const char *val, *uri, *eol, *p;
 	warc_string_t res = {0U, NULL};
 
 	if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
@@ -676,23 +669,33 @@ _warc_rduri(const char *buf, size_t bsz)
 		return res;
 	}
 	/* overread whitespace */
-	for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++);
+	val += sizeof(_key) - 1U;
+	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+		/* no end of line */
+		return res;
+	}
+
+	while (val < eol && (*val == ' ' || *val == '\t'))
+		++val;
 
 	/* overread URL designators */
-	if ((uri = xmemmem(val, eob - val, "://", 3U)) == NULL) {
+	if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) {
 		/* not touching that! */
 		return res;
-	} else if ((eol = memchr(uri, '\n', eob - uri)) == NULL) {
-		/* no end of line? :O */
-		return res;
 	}
 
-	/* massage uri to point to after :// */
+	/* spaces inside uri are not allowed, CRLF should follow */
+	for (p = val; p < eol; p++) {
+		if (isspace(*p))
+			return res;
+	}
+
+	/* there must be at least space for ftp */
+	if (uri < (val + 3U))
+		return res;
+
+	/* move uri to point to after :// */
 	uri += 3U;
-	/* also massage eol to point to the first whitespace
-	 * after the last non-whitespace character before
-	 * the end of the line */
-	for (; eol > uri && isspace(eol[-1]); eol--);
 
 	/* now then, inspect the URI */
 	if (memcmp(val, "file", 4U) == 0) {
@@ -715,7 +718,7 @@ static ssize_t
 _warc_rdlen(const char *buf, size_t bsz)
 {
 	static const char _key[] = "\r\nContent-Length:";
-	const char *val;
+	const char *val, *eol;
 	char *on = NULL;
 	long int len;
 
@@ -723,14 +726,24 @@ _warc_rdlen(const char *buf, size_t bsz)
 		/* no bother */
 		return -1;
 	}
-
-	/* strtol kindly overreads whitespace for us, so use that */
 	val += sizeof(_key) - 1U;
+	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+		/* no end of line */
+		return -1;
+	}
+
+	/* skip leading whitespace */
+	while (val < eol && (*val == ' ' || *val == '\t'))
+		val++;
+	/* there must be at least one digit */
+	if (!isdigit(*val))
+		return -1;
 	len = strtol(val, &on, 10);
-	if (on == NULL || !isspace(*on)) {
-		/* hm, can we trust that number?  Best not. */
+	if (on != eol) {
+		/* line must end here */
 		return -1;
 	}
+
 	return (size_t)len;
 }
 
@@ -738,7 +751,7 @@ static time_t
 _warc_rdrtm(const char *buf, size_t bsz)
 {
 	static const char _key[] = "\r\nWARC-Date:";
-	const char *val;
+	const char *val, *eol;
 	char *on = NULL;
 	time_t res;
 
@@ -746,13 +759,17 @@ _warc_rdrtm(const char *buf, size_t bsz)
 		/* no bother */
 		return (time_t)-1;
 	}
+	val += sizeof(_key) - 1U;
+	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
+		/* no end of line */
+		return -1;
+	}
 
 	/* xstrpisotime() kindly overreads whitespace for us, so use that */
-	val += sizeof(_key) - 1U;
 	res = xstrpisotime(val, &on);
-	if (on == NULL || !isspace(*on)) {
-		/* hm, can we trust that number?  Best not. */
-		return (time_t)-1;
+	if (on != eol) {
+		/* line must end here */
+		return -1;
 	}
 	return res;
 }
@@ -761,7 +778,7 @@ static time_t
 _warc_rdmtm(const char *buf, size_t bsz)
 {
 	static const char _key[] = "\r\nLast-Modified:";
-	const char *val;
+	const char *val, *eol;
 	char *on = NULL;
 	time_t res;
 
@@ -769,13 +786,17 @@ _warc_rdmtm(const char *buf, size_t bsz)
 		/* no bother */
 		return (time_t)-1;
 	}
+	val += sizeof(_key) - 1U;
+	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
+		/* no end of line */
+		return -1;
+	}
 
 	/* xstrpisotime() kindly overreads whitespace for us, so use that */
-	val += sizeof(_key) - 1U;
 	res = xstrpisotime(val, &on);
-	if (on == NULL || !isspace(*on)) {
-		/* hm, can we trust that number?  Best not. */
-		return (time_t)-1;
+	if (on != eol) {
+		/* line must end here */
+		return -1;
 	}
 	return res;
 }
@@ -792,4 +813,12 @@ _warc_find_eoh(const char *buf, size_t bsz)
 	return hit;
 }
 
+static const char*
+_warc_find_eol(const char *buf, size_t bsz)
+{
+	static const char _marker[] = "\r\n";
+	const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U);
+
+	return hit;
+}
 /* archive_read_support_format_warc.c ends here */
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
index ec623c6..eeac1c8 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
 #endif
 #if HAVE_LZMA_H
 #include <cm_lzma.h>
-#elif HAVE_LZMADEC_H
-#include <lzmadec.h>
 #endif
 #ifdef HAVE_ZLIB_H
 #include <cm_zlib.h>
@@ -334,9 +332,6 @@ struct xar {
 #if HAVE_LZMA_H && HAVE_LIBLZMA
 	lzma_stream		 lzstream;
 	int			 lzstream_valid;
-#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
-	lzmadec_stream		 lzstream;
-	int			 lzstream_valid;
 #endif
 	/*
 	 * For Checksum data.
@@ -399,6 +394,7 @@ static void	checksum_update(struct archive_read *, const void *,
 		    size_t, const void *, size_t);
 static int	checksum_final(struct archive_read *, const void *,
 		    size_t, const void *, size_t);
+static void	checksum_cleanup(struct archive_read *);
 static int	decompression_init(struct archive_read *, enum enctype);
 static int	decompress(struct archive_read *, const void **,
 		    size_t *, const void *, size_t *);
@@ -928,6 +924,7 @@ xar_cleanup(struct archive_read *a)
 	int r;
 
 	xar = (struct xar *)(a->format->data);
+	checksum_cleanup(a);
 	r = decompression_cleanup(a);
 	hdlink = xar->hdlink_list;
 	while (hdlink != NULL) {
@@ -938,6 +935,7 @@ xar_cleanup(struct archive_read *a)
 	}
 	for (i = 0; i < xar->file_queue.used; i++)
 		file_free(xar->file_queue.files[i]);
+	free(xar->file_queue.files);
 	while (xar->unknowntags != NULL) {
 		struct unknown_tag *tag;
 
@@ -1526,34 +1524,6 @@ decompression_init(struct archive_read *a, enum enctype encoding)
 		xar->lzstream.total_in = 0;
 		xar->lzstream.total_out = 0;
 		break;
-#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
-	case LZMA:
-		if (xar->lzstream_valid)
-			lzmadec_end(&(xar->lzstream));
-		r = lzmadec_init(&(xar->lzstream));
-		if (r != LZMADEC_OK) {
-			switch (r) {
-			case LZMADEC_HEADER_ERROR:
-				archive_set_error(&a->archive,
-				    ARCHIVE_ERRNO_MISC,
-				    "Internal error initializing "
-				    "compression library: "
-				    "invalid header");
-				break;
-			case LZMADEC_MEM_ERROR:
-				archive_set_error(&a->archive,
-				    ENOMEM,
-				    "Internal error initializing "
-				    "compression library: "
-				    "out of memory");
-				break;
-			}
-			return (ARCHIVE_FATAL);
-		}
-		xar->lzstream_valid = 1;
-		xar->lzstream.total_in = 0;
-		xar->lzstream.total_out = 0;
-		break;
 #endif
 	/*
 	 * Unsupported compression.
@@ -1563,9 +1533,7 @@ decompression_init(struct archive_read *a, enum enctype encoding)
 	case BZIP2:
 #endif
 #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
 	case LZMA:
-#endif
 	case XZ:
 #endif
 		switch (xar->entry_encoding) {
@@ -1685,46 +1653,12 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes,
 		*used = avail_in - xar->lzstream.avail_in;
 		*outbytes = avail_out - xar->lzstream.avail_out;
 		break;
-#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
-	case LZMA:
-		xar->lzstream.next_in = (unsigned char *)(uintptr_t)b;
-		xar->lzstream.avail_in = avail_in;
-		xar->lzstream.next_out = (unsigned char *)outbuff;
-		xar->lzstream.avail_out = avail_out;
-		r = lzmadec_decode(&(xar->lzstream), 0);
-		switch (r) {
-		case LZMADEC_STREAM_END: /* Found end of stream. */
-			switch (lzmadec_end(&(xar->lzstream))) {
-			case LZMADEC_OK:
-				break;
-			default:
-				archive_set_error(&(a->archive),
-				    ARCHIVE_ERRNO_MISC,
-				    "Failed to clean up lzmadec decompressor");
-				return (ARCHIVE_FATAL);
-			}
-			xar->lzstream_valid = 0;
-			/* FALLTHROUGH */
-		case LZMADEC_OK: /* Decompressor made some progress. */
-			break;
-		default:
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "lzmadec decompression failed(%d)",
-			    r);
-			return (ARCHIVE_FATAL);
-		}
-		*used = avail_in - xar->lzstream.avail_in;
-		*outbytes = avail_out - xar->lzstream.avail_out;
-		break;
 #endif
 #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
 	case BZIP2:
 #endif
 #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
-#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
 	case LZMA:
-#endif
 	case XZ:
 #endif
 	case NONE:
@@ -1788,6 +1722,16 @@ decompression_cleanup(struct archive_read *a)
 }
 
 static void
+checksum_cleanup(struct archive_read *a) {
+	struct xar *xar;
+
+	xar = (struct xar *)(a->format->data);
+
+	_checksum_final(&(xar->a_sumwrk), NULL, 0);
+	_checksum_final(&(xar->e_sumwrk), NULL, 0);
+}
+
+static void
 xmlattr_cleanup(struct xmlattr_list *list)
 {
 	struct xmlattr *attr, *next;
@@ -3116,7 +3060,7 @@ xml2_read_cb(void *context, char *buffer, int len)
 	struct xar *xar;
 	const void *d;
 	size_t outbytes;
-	size_t used;
+	size_t used = 0;
 	int r;
 
 	a = (struct archive_read *)context;
@@ -3240,6 +3184,9 @@ expat_xmlattr_setup(struct archive_read *a,
 		value = strdup(atts[1]);
 		if (attr == NULL || name == NULL || value == NULL) {
 			archive_set_error(&a->archive, ENOMEM, "Out of memory");
+			free(attr);
+			free(name);
+			free(value);
 			return (ARCHIVE_FATAL);
 		}
 		attr->name = name;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
index 8df52c3..e56bd63 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
@@ -199,7 +199,7 @@ struct zip {
 	struct trad_enc_ctx	tctx;
 	char			tctx_valid;
 
-	/* WinZip AES decyption. */
+	/* WinZip AES decryption. */
 	/* Contexts used for AES decryption. */
 	archive_crypto_ctx	cctx;
 	char			cctx_valid;
@@ -242,7 +242,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
 }
 
 static uint8_t
-trad_enc_decypt_byte(struct trad_enc_ctx *ctx)
+trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
 {
 	unsigned temp = ctx->keys[2] | 2;
 	return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
@@ -257,7 +257,7 @@ trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
 	max = (unsigned)((in_len < out_len)? in_len: out_len);
 
 	for (i = 0; i < max; i++) {
-		uint8_t t = in[i] ^ trad_enc_decypt_byte(ctx);
+		uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx);
 		out[i] = t;
 		trad_enc_update_keys(ctx, t);
 	}
@@ -418,18 +418,30 @@ zip_time(const char *p)
  *	id1+size1+data1 + id2+size2+data2 ...
  *  triplets.  id and size are 2 bytes each.
  */
-static void
-process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
+static int
+process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry)
 {
 	unsigned offset = 0;
 
-	while (offset < extra_length - 4) {
+	if (extra_length == 0) {
+		return ARCHIVE_OK;
+	}
+
+	if (extra_length < 4) {
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+		    "Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length);
+		return ARCHIVE_FAILED;
+	}
+	while (offset <= extra_length - 4) {
 		unsigned short headerid = archive_le16dec(p + offset);
 		unsigned short datasize = archive_le16dec(p + offset + 2);
 
 		offset += 4;
 		if (offset + datasize > extra_length) {
-			break;
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+			    "Extra data overflow: Need %d bytes but only found %d bytes",
+			    (int)datasize, (int)(extra_length - offset));
+			return ARCHIVE_FAILED;
 		}
 #ifdef DEBUG
 		fprintf(stderr, "Header id 0x%04x, length %d\n",
@@ -440,26 +452,38 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
 			/* Zip64 extended information extra field. */
 			zip_entry->flags |= LA_USED_ZIP64;
 			if (zip_entry->uncompressed_size == 0xffffffff) {
-				if (datasize < 8)
-					break;
-				zip_entry->uncompressed_size =
-				    archive_le64dec(p + offset);
+				uint64_t t = 0;
+				if (datasize < 8
+				    || (t = archive_le64dec(p + offset)) > INT64_MAX) {
+					archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+					    "Malformed 64-bit uncompressed size");
+					return ARCHIVE_FAILED;
+				}
+				zip_entry->uncompressed_size = t;
 				offset += 8;
 				datasize -= 8;
 			}
 			if (zip_entry->compressed_size == 0xffffffff) {
-				if (datasize < 8)
-					break;
-				zip_entry->compressed_size =
-				    archive_le64dec(p + offset);
+				uint64_t t = 0;
+				if (datasize < 8
+				    || (t = archive_le64dec(p + offset)) > INT64_MAX) {
+					archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+					    "Malformed 64-bit compressed size");
+					return ARCHIVE_FAILED;
+				}
+				zip_entry->compressed_size = t;
 				offset += 8;
 				datasize -= 8;
 			}
 			if (zip_entry->local_header_offset == 0xffffffff) {
-				if (datasize < 8)
-					break;
-				zip_entry->local_header_offset =
-				    archive_le64dec(p + offset);
+				uint64_t t = 0;
+				if (datasize < 8
+				    || (t = archive_le64dec(p + offset)) > INT64_MAX) {
+					archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+					    "Malformed 64-bit local header offset");
+					return ARCHIVE_FAILED;
+				}
+				zip_entry->local_header_offset = t;
 				offset += 8;
 				datasize -= 8;
 			}
@@ -698,7 +722,7 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
 			break;
 		}
 		case 0x9901:
-			/* WinZIp AES extra data field. */
+			/* WinZip AES extra data field. */
 			if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
 				/* Vendor version. */
 				zip_entry->aes_extra.vendor =
@@ -715,13 +739,13 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
 		}
 		offset += datasize;
 	}
-#ifdef DEBUG
-	if (offset != extra_length)
-	{
-		fprintf(stderr,
-		    "Extra data field contents do not match reported size!\n");
+	if (offset != extra_length) {
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+		    "Malformed extra data: Consumed %d bytes of %d bytes",
+		    (int)offset, (int)extra_length);
+		return ARCHIVE_FAILED;
 	}
-#endif
+	return ARCHIVE_OK;
 }
 
 /*
@@ -840,7 +864,9 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
 		return (ARCHIVE_FATAL);
 	}
 
-	process_extra(h, extra_length, zip_entry);
+	if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) {
+		return ARCHIVE_FATAL;
+	}
 	__archive_read_consume(a, extra_length);
 
 	/* Work around a bug in Info-Zip: When reading from a pipe, it
@@ -891,6 +917,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
 				archive_wstrcat(&s, wp);
 				archive_wstrappend_wchar(&s, L'/');
 				archive_entry_copy_pathname_w(entry, s.s);
+				archive_wstring_free(&s);
 			}
 		} else {
 			cp = archive_entry_pathname(entry);
@@ -901,6 +928,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
 				archive_strcat(&s, cp);
 				archive_strappend_char(&s, '/');
 				archive_entry_set_pathname(entry, s.s);
+				archive_string_free(&s);
 			}
 		}
 	}
@@ -1140,11 +1168,18 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
 			|| (zip->hctx_valid
 			 && zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) {
 			if (zip->entry->flags & LA_USED_ZIP64) {
+				uint64_t compressed, uncompressed;
 				zip->entry->crc32 = archive_le32dec(p + 4);
-				zip->entry->compressed_size =
-					archive_le64dec(p + 8);
-				zip->entry->uncompressed_size =
-					archive_le64dec(p + 16);
+				compressed = archive_le64dec(p + 8);
+				uncompressed = archive_le64dec(p + 16);
+				if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
+					archive_set_error(&a->archive,
+					    ARCHIVE_ERRNO_FILE_FORMAT,
+					    "Overflow of 64-bit file sizes");
+					return ARCHIVE_FAILED;
+				}
+				zip->entry->compressed_size = compressed;
+				zip->entry->uncompressed_size = uncompressed;
 				zip->unconsumed = 24;
 			} else {
 				zip->entry->crc32 = archive_le32dec(p + 4);
@@ -1297,7 +1332,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
 	    && bytes_avail > zip->entry_bytes_remaining) {
 		bytes_avail = (ssize_t)zip->entry_bytes_remaining;
 	}
-	if (bytes_avail <= 0) {
+	if (bytes_avail < 0) {
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
 		    "Truncated ZIP file body");
 		return (ARCHIVE_FATAL);
@@ -1421,9 +1456,18 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
 			zip->unconsumed = 4;
 		}
 		if (zip->entry->flags & LA_USED_ZIP64) {
+			uint64_t compressed, uncompressed;
 			zip->entry->crc32 = archive_le32dec(p);
-			zip->entry->compressed_size = archive_le64dec(p + 4);
-			zip->entry->uncompressed_size = archive_le64dec(p + 12);
+			compressed = archive_le64dec(p + 4);
+			uncompressed = archive_le64dec(p + 12);
+			if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
+				archive_set_error(&a->archive,
+				    ARCHIVE_ERRNO_FILE_FORMAT,
+				    "Overflow of 64-bit file sizes");
+				return ARCHIVE_FAILED;
+			}
+			zip->entry->compressed_size = compressed;
+			zip->entry->uncompressed_size = uncompressed;
 			zip->unconsumed += 20;
 		} else {
 			zip->entry->crc32 = archive_le32dec(p);
@@ -1504,7 +1548,7 @@ read_decryption_header(struct archive_read *a)
 	case 0x6720:/* Blowfish */
 	case 0x6721:/* Twofish */
 	case 0x6801:/* RC4 */
-		/* Suuported encryption algorithm. */
+		/* Supported encryption algorithm. */
 		break;
 	default:
 		archive_set_error(&a->archive,
@@ -1613,7 +1657,7 @@ read_decryption_header(struct archive_read *a)
 	__archive_read_consume(a, 4);
 
 	/*return (ARCHIVE_OK);
-	 * This is not fully implemnted yet.*/
+	 * This is not fully implemented yet.*/
 	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
 	    "Encrypted file is unsupported");
 	return (ARCHIVE_FAILED);
@@ -1695,7 +1739,7 @@ init_traditional_PKWARE_decryption(struct archive_read *a)
 		}
 
 		/*
-		 * Initialize ctx for Traditional PKWARE Decyption.
+		 * Initialize ctx for Traditional PKWARE Decryption.
 		 */
 		r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase),
 			p, ENC_HEADER_SIZE, &crcchk);
@@ -2695,7 +2739,9 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
 			    "Truncated ZIP file header");
 			return ARCHIVE_FATAL;
 		}
-		process_extra(p + filename_length, extra_length, zip_entry);
+		if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) {
+			return ARCHIVE_FATAL;
+		}
 
 		/*
 		 * Mac resource fork files are stored under the
diff --git a/Utilities/cmlibarchive/libarchive/archive_string.c b/Utilities/cmlibarchive/libarchive/archive_string.c
index 282c58e..592ead2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string.c
+++ b/Utilities/cmlibarchive/libarchive/archive_string.c
@@ -219,6 +219,12 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s)
 	return (as);
 }
 
+struct archive_string *
+archive_array_append(struct archive_string *as, const char *p, size_t s)
+{
+	return archive_string_append(as, p, s);
+}
+
 void
 archive_string_concat(struct archive_string *dest, struct archive_string *src)
 {
@@ -559,7 +565,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
 			}
 			if (count == 0 && length != 0)
 				ret = -1;
-		} while (0);
+			break;
+		} while (1);
 	}
 	dest->length += count;
 	dest->s[dest->length] = L'\0';
@@ -596,7 +603,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
 	wcs = dest->s + dest->length;
 	/*
 	 * We cannot use mbsrtowcs/mbstowcs here because those may convert
-	 * extra MBS when strlen(p) > len and one wide character consis of
+	 * extra MBS when strlen(p) > len and one wide character consists of
 	 * multi bytes.
 	 */
 	while (*mbs && mbs_length > 0) {
@@ -1247,7 +1254,7 @@ create_sconv_object(const char *fc, const char *tc,
 		sc->cd = iconv_open(tc, fc);
 		if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) {
 			/*
-			 * Unfortunaly, all of iconv implements do support 
+			 * Unfortunately, all of iconv implements do support
 			 * "CP932" character-set, so we should use "SJIS"
 			 * instead if iconv_open failed.
 			 */
@@ -1260,7 +1267,7 @@ create_sconv_object(const char *fc, const char *tc,
 		/*
 		 * archive_mstring on Windows directly convert multi-bytes
 		 * into archive_wstring in order not to depend on locale
-		 * so that you can do a I18N programing. This will be
+		 * so that you can do a I18N programming. This will be
 		 * used only in archive_mstring_copy_mbs_len_l so far.
 		 */
 		if (flag & SCONV_FROM_CHARSET) {
@@ -1725,7 +1732,7 @@ archive_string_conversion_from_charset(struct archive *a, const char *charset,
  * in tar or zip files. But mbstowcs/wcstombs(CRT) usually use CP_ACP
  * unless you use setlocale(LC_ALL, ".OCP")(specify CP_OEMCP).
  * So we should make a string conversion between CP_ACP and CP_OEMCP
- * for compatibillty.
+ * for compatibility.
  */
 #if defined(_WIN32) && !defined(__CYGWIN__)
 struct archive_string_conv *
@@ -1826,7 +1833,7 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt)
 	 * A filename in UTF-8 was made with libarchive 2.x in a wrong
 	 * assumption that wchar_t was Unicode.
 	 * This option enables simulating the assumption in order to read
-	 * that filname correctly.
+	 * that filename correctly.
 	 */
 	case SCONV_SET_OPT_UTF8_LIBARCHIVE2X:
 #if (defined(_WIN32) && !defined(__CYGWIN__)) \
@@ -1938,12 +1945,19 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
     struct archive_string_conv *sc)
 {
 	const void *s;
-	size_t length;
+	size_t length = 0;
 	int i, r = 0, r2;
 
+	if (_p != NULL && n > 0) {
+		if (sc != NULL && (sc->flag & SCONV_FROM_UTF16))
+			length = utf16nbytes(_p, n);
+		else
+			length = mbsnbytes(_p, n);
+	}
+
 	/* We must allocate memory even if there is no data for conversion
 	 * or copy. This simulates archive_string_append behavior. */
-	if (_p == NULL || n == 0) {
+	if (length == 0) {
 		int tn = 1;
 		if (sc != NULL && (sc->flag & SCONV_TO_UTF16))
 			tn = 2;
@@ -1959,16 +1973,11 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
 	 * If sc is NULL, we just make a copy.
 	 */
 	if (sc == NULL) {
-		length = mbsnbytes(_p, n);
 		if (archive_string_append(as, _p, length) == NULL)
 			return (-1);/* No memory */
 		return (0);
 	}
 
-	if (sc->flag & SCONV_FROM_UTF16)
-		length = utf16nbytes(_p, n);
-	else
-		length = mbsnbytes(_p, n);
 	s = _p;
 	i = 0;
 	if (sc->nconverter > 1) {
@@ -1991,7 +2000,7 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
 #if HAVE_ICONV
 
 /*
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
  */
 static int
 iconv_strncat_in_locale(struct archive_string *as, const void *_p,
@@ -2093,7 +2102,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
 
 /*
  * Translate a string from a some CodePage to an another CodePage by
- * Windows APIs, and copy the result. Return -1 if conversion failes.
+ * Windows APIs, and copy the result. Return -1 if conversion fails.
  */
 static int
 strncat_in_codepage(struct archive_string *as,
@@ -2217,7 +2226,7 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
 
 	/*
 	 * If a character is ASCII, this just copies it. If not, this
-	 * assigns '?' charater instead but in UTF-8 locale this assigns
+	 * assigns '?' character instead but in UTF-8 locale this assigns
 	 * byte sequence 0xEF 0xBD 0xBD, which are code point U+FFFD,
 	 * a Replacement Character in Unicode.
 	 */
@@ -2297,7 +2306,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
 		return (0); /* Standard:  return 0 for end-of-string. */
 	cnt = utf8_count[ch];
 
-	/* Invalide sequence or there are not plenty bytes. */
+	/* Invalid sequence or there are not plenty bytes. */
 	if ((int)n < cnt) {
 		cnt = (int)n;
 		for (i = 1; i < cnt; i++) {
@@ -2378,7 +2387,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
 		goto invalid_sequence;
 	}
 
-	/* The code point larger than 0x10FFFF is not leagal
+	/* The code point larger than 0x10FFFF is not legal
 	 * Unicode values. */
 	if (wc > UNICODE_MAX)
 		goto invalid_sequence;
@@ -2396,7 +2405,7 @@ utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
 	int cnt;
 
 	cnt = _utf8_to_unicode(pwc, s, n);
-	/* Any of Surrogate pair is not leagal Unicode values. */
+	/* Any of Surrogate pair is not legal Unicode values. */
 	if (cnt == 3 && IS_SURROGATE_PAIR_LA(*pwc))
 		return (-3);
 	return (cnt);
@@ -2457,7 +2466,7 @@ invalid_sequence:
 /*
  * Convert a Unicode code point to a single UTF-8 sequence.
  *
- * NOTE:This function does not check if the Unicode is leagal or not.
+ * NOTE:This function does not check if the Unicode is legal or not.
  * Please you definitely check it before calling this.
  */
 static size_t
@@ -2551,9 +2560,9 @@ utf16_to_unicode(uint32_t *pwc, const char *s, size_t n, int be)
 
 	/*
 	 * Surrogate pair values(0xd800 through 0xdfff) are only
-	 * used by UTF-16, so, after above culculation, the code
+	 * used by UTF-16, so, after above calculation, the code
 	 * must not be surrogate values, and Unicode has no codes
-	 * larger than 0x10ffff. Thus, those are not leagal Unicode
+	 * larger than 0x10ffff. Thus, those are not legal Unicode
 	 * values.
 	 */
 	if (IS_SURROGATE_PAIR_LA(uc) || uc > UNICODE_MAX) {
@@ -2900,7 +2909,7 @@ get_nfc(uint32_t uc, uint32_t uc2)
 /*
  * Normalize UTF-8/UTF-16BE characters to Form C and copy the result.
  *
- * TODO: Convert composition exclusions,which are never converted
+ * TODO: Convert composition exclusions, which are never converted
  * from NFC,NFD,NFKC and NFKD, to Form C.
  */
 static int
@@ -3434,7 +3443,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
 		}
 
 		/*
-		 * As libarchie 2.x, translates the UTF-8 characters into
+		 * As libarchive 2.x, translates the UTF-8 characters into
 		 * wide-characters in the assumption that WCS is Unicode.
 		 */
 		if (n < 0) {
@@ -3473,7 +3482,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
 
 /*
  * Convert a UTF-16BE/LE string to current locale and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
  */
 static int
 win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
@@ -3552,18 +3561,19 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
 		ll = WideCharToMultiByte(sc->to_cp, 0,
 		    (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
 			NULL, &defchar);
-		if (ll == 0 &&
-		    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
-			/* Need more buffer for MBS. */
-			ll = WideCharToMultiByte(sc->to_cp, 0,
-			    (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
-			if (archive_string_ensure(as, ll +1) == NULL)
-				return (-1);
-			mbs = as->s + as->length;
-			mbs_size = as->buffer_length - as->length -1;
-			continue;
+		/* Exit loop if we succeeded */
+		if (ll != 0 ||
+		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+			break;
 		}
-	} while (0);
+		/* Else expand buffer and loop to try again. */
+		ll = WideCharToMultiByte(sc->to_cp, 0,
+		    (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
+		if (archive_string_ensure(as, ll +1) == NULL)
+			return (-1);
+		mbs = as->s + as->length;
+		mbs_size = as->buffer_length - as->length -1;
+	} while (1);
 	archive_string_free(&tmp);
 	as->length += ll;
 	as->s[as->length] = '\0';
@@ -3596,7 +3606,7 @@ is_big_endian(void)
 
 /*
  * Convert a current locale string to UTF-16BE/LE and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
  */
 static int
 win_strncat_to_utf16(struct archive_string *as16, const void *_p,
@@ -3634,19 +3644,20 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
 	do {
 		count = MultiByteToWideChar(sc->from_cp,
 		    MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
-		if (count == 0 &&
-		    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
-			/* Need more buffer for UTF-16 string */
-			count = MultiByteToWideChar(sc->from_cp,
-			    MB_PRECOMPOSED, s, (int)length, NULL, 0);
-			if (archive_string_ensure(as16, (count +1) * 2)
-			    == NULL)
-				return (-1);
-			u16 = as16->s + as16->length;
-			avail = as16->buffer_length - 2;
-			continue;
+		/* Exit loop if we succeeded */
+		if (count != 0 ||
+		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+			break;
 		}
-	} while (0);
+		/* Expand buffer and try again */
+		count = MultiByteToWideChar(sc->from_cp,
+		    MB_PRECOMPOSED, s, (int)length, NULL, 0);
+		if (archive_string_ensure(as16, (count +1) * 2)
+		    == NULL)
+			return (-1);
+		u16 = as16->s + as16->length;
+		avail = as16->buffer_length - 2;
+	} while (1);
 	as16->length += count * 2;
 	as16->s[as16->length] = 0;
 	as16->s[as16->length+1] = 0;
@@ -3700,7 +3711,7 @@ win_strncat_to_utf16le(struct archive_string *as16, const void *_p,
 
 /*
  * Convert a UTF-16BE string to current locale and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
  */
 static int
 best_effort_strncat_from_utf16(struct archive_string *as, const void *_p,
@@ -3758,7 +3769,7 @@ best_effort_strncat_from_utf16le(struct archive_string *as, const void *_p,
 
 /*
  * Convert a current locale string to UTF-16BE/LE and copy the result.
- * Return -1 if conversion failes.
+ * Return -1 if conversion fails.
  */
 static int
 best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p,
@@ -3942,7 +3953,7 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes,
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 	/*
-	 * Internationalization programing on Windows must use Wide
+	 * Internationalization programming on Windows must use Wide
 	 * characters because Windows platform cannot make locale UTF-8.
 	 */
 	if (sc != NULL && (aes->aes_set & AES_SET_WCS) != 0) {
@@ -4074,7 +4085,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes,
 	archive_string_empty(&(aes->aes_utf8));
 #if defined(_WIN32) && !defined(__CYGWIN__)
 	/*
-	 * Internationalization programing on Windows must use Wide
+	 * Internationalization programming on Windows must use Wide
 	 * characters because Windows platform cannot make locale UTF-8.
 	 */
 	if (sc == NULL) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_string.h b/Utilities/cmlibarchive/libarchive/archive_string.h
index 23f4916..56dfbb2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string.h
+++ b/Utilities/cmlibarchive/libarchive/archive_string.h
@@ -81,6 +81,10 @@ archive_strappend_char(struct archive_string *, char);
 struct archive_wstring *
 archive_wstrappend_wchar(struct archive_wstring *, wchar_t);
 
+/* Append a raw array to an archive_string, resizing as necessary */
+struct archive_string *
+archive_array_append(struct archive_string *, const char *, size_t);
+
 /* Convert a Unicode string to current locale and append the result. */
 /* Returns -1 if conversion fails. */
 int
@@ -115,13 +119,13 @@ archive_string_conversion_set_opt(struct archive_string_conv *, int);
 
 
 /* Copy one archive_string to another in locale conversion.
- * Return -1 if conversion failes. */
+ * Return -1 if conversion fails. */
 int
 archive_strncpy_l(struct archive_string *, const void *, size_t,
     struct archive_string_conv *);
 
 /* Copy one archive_string to another in locale conversion.
- * Return -1 if conversion failes. */
+ * Return -1 if conversion fails. */
 int
 archive_strncat_l(struct archive_string *, const void *, size_t,
     struct archive_string_conv *);
diff --git a/Utilities/cmlibarchive/libarchive/archive_string_composition.h b/Utilities/cmlibarchive/libarchive/archive_string_composition.h
index be41e33..8902ac1 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string_composition.h
+++ b/Utilities/cmlibarchive/libarchive/archive_string_composition.h
@@ -1009,7 +1009,7 @@ static const char u_decomposable_blocks[0x1D2+1] = {
 	(((uc) > 0x1D244)?0:\
 	ccc_val[ccc_val_index[ccc_index[(uc)>>8]][((uc)>>4)&0x0F]][(uc)&0x0F])
 
-/* The table of the value of Canonical Cimbining Class */
+/* The table of the value of Canonical Combining Class */
 static const unsigned char ccc_val[][16] = {
  /* idx=0: XXXX0 - XXXXF */
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
diff --git a/Utilities/cmlibarchive/libarchive/archive_util.c b/Utilities/cmlibarchive/libarchive/archive_util.c
index f89df1d..f56ca33 100644
--- a/Utilities/cmlibarchive/libarchive/archive_util.c
+++ b/Utilities/cmlibarchive/libarchive/archive_util.c
@@ -580,7 +580,7 @@ void
 __archive_ensure_cloexec_flag(int fd)
 {
 #if defined(_WIN32) && !defined(__CYGWIN__)
-	(void)fd; /* UNSED */
+	(void)fd; /* UNUSED */
 #else
 	int flags;
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.c b/Utilities/cmlibarchive/libarchive/archive_windows.c
index d4e93fe..6ff8749 100644
--- a/Utilities/cmlibarchive/libarchive/archive_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_windows.c
@@ -766,7 +766,7 @@ __la_win_entry_in_posix_pathseparator(struct archive_entry *entry)
 			has_backslash = 1;
 	}
 	/*
-	 * If there is no backslach chars, return the original.
+	 * If there is no backslash chars, return the original.
 	 */
 	if (!has_backslash)
 		return (entry);
@@ -891,7 +891,7 @@ __la_dosmaperr(unsigned long e)
 		return;
 	}
 
-	for (i = 0; i < (int)sizeof(doserrors); i++)
+	for (i = 0; i < (int)(sizeof(doserrors)/sizeof(doserrors[0])); i++)
 	{
 		if (doserrors[i].winerr == e)
 		{
diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.h b/Utilities/cmlibarchive/libarchive/archive_windows.h
index 7c31a16..c3aed0c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_windows.h
+++ b/Utilities/cmlibarchive/libarchive/archive_windows.h
@@ -224,16 +224,20 @@
 #define	S_IWUSR	     _S_IWUSR
 #define	S_IRUSR	     _S_IRUSR
 #endif
+#ifndef S_IRWXG
 #define	S_IRWXG        _S_IRWXG
 #define	S_IXGRP        _S_IXGRP
 #define	S_IWGRP        _S_IWGRP
+#endif
 #ifndef S_IRGRP
 #define	S_IRGRP        _S_IRGRP
 #endif
+#ifndef S_IRWXO
 #define	S_IRWXO        _S_IRWXO
 #define	S_IXOTH        _S_IXOTH
 #define	S_IWOTH        _S_IWOTH
 #define	S_IROTH        _S_IROTH
+#endif
 
 #endif
 
diff --git a/Utilities/cmlibarchive/libarchive/archive_write.c b/Utilities/cmlibarchive/libarchive/archive_write.c
index e3fa335..0634a22 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write.c
@@ -109,10 +109,9 @@ archive_write_new(void)
 	struct archive_write *a;
 	unsigned char *nulls;
 
-	a = (struct archive_write *)malloc(sizeof(*a));
+	a = (struct archive_write *)calloc(1, sizeof(*a));
 	if (a == NULL)
 		return (NULL);
-	memset(a, 0, sizeof(*a));
 	a->archive.magic = ARCHIVE_WRITE_MAGIC;
 	a->archive.state = ARCHIVE_STATE_NEW;
 	a->archive.vtable = archive_write_vtable();
@@ -126,12 +125,11 @@ archive_write_new(void)
 
 	/* Initialize a block of nulls for padding purposes. */
 	a->null_length = 1024;
-	nulls = (unsigned char *)malloc(a->null_length);
+	nulls = (unsigned char *)calloc(1, a->null_length);
 	if (nulls == NULL) {
 		free(a);
 		return (NULL);
 	}
-	memset(nulls, 0, a->null_length);
 	a->nulls = nulls;
 	return (&a->archive);
 }
@@ -233,7 +231,7 @@ __archive_write_filter(struct archive_write_filter *f,
 	if (length == 0)
 		return(ARCHIVE_OK);
 	if (f->write == NULL)
-		/* If unset, a fatal error has already ocuured, so this filter
+		/* If unset, a fatal error has already occurred, so this filter
 		 * didn't open. We cannot write anything. */
 		return(ARCHIVE_FATAL);
 	r = (f->write)(f, buff, length);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c
index 1d0ab8c..e655185 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c
@@ -523,7 +523,7 @@ drive_compressor_independence(struct archive_write_filter *f, const char *p,
 		archive_le32enc(data->out, outsize);
 		data->out += 4;
 	} else {
-		/* The buffer is not compressed. The commpressed size was
+		/* The buffer is not compressed. The compressed size was
 		 * bigger than its uncompressed size. */
 		archive_le32enc(data->out, length | 0x80000000);
 		data->out += 4;
@@ -608,7 +608,7 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
 		archive_le32enc(data->out, outsize);
 		data->out += 4;
 	} else {
-		/* The buffer is not compressed. The commpressed size was
+		/* The buffer is not compressed. The compressed size was
 		 * bigger than its uncompressed size. */
 		archive_le32enc(data->out, length | 0x80000000);
 		data->out += 4;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
index 31a1b6f..55b5e8e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
@@ -200,6 +200,7 @@ __archive_write_program_free(struct archive_write_program_data *data)
 		if (data->child)
 			CloseHandle(data->child);
 #endif
+		free(data->program_name);
 		free(data->child_buf);
 		free(data);
 	}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
index 4f849ce..e4a3535 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
@@ -233,7 +233,7 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f,
 	if (f->code == ARCHIVE_FILTER_XZ) {
 #ifdef HAVE_LZMA_STREAM_ENCODER_MT
 		if (data->threads != 1) {
-			bzero(&mt_options, sizeof(mt_options));
+			memset(&mt_options, 0, sizeof(mt_options));
 			mt_options.threads = data->threads;
 			mt_options.timeout = 300;
 			mt_options.filters = data->lzmafilters;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c
index 5cbba54..144ab7e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c
@@ -34,6 +34,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
 #define _ACL_PRIVATE /* For debugging */
 #include <sys/acl.h>
 #endif
+#if HAVE_DARWIN_ACL
+#include <membership.h>
+#endif
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
@@ -43,7 +46,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
 #include "archive_acl_private.h"
 #include "archive_write_disk_private.h"
 
-#ifndef HAVE_POSIX_ACL
+#if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL
 /* Default empty function body to satisfy mainline code. */
 int
 archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
@@ -56,47 +59,111 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
 	return (ARCHIVE_OK);
 }
 
-#else
+#else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
+
+#if HAVE_SUN_ACL
+#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACE_T
+#elif HAVE_DARWIN_ACL
+#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACL_TYPE_EXTENDED
+#elif HAVE_ACL_TYPE_NFS4
+#define	ARCHIVE_PLATFORM_ACL_TYPE_NFS4	ACL_TYPE_NFS4
+#endif
 
 static int	set_acl(struct archive *, int fd, const char *,
 			struct archive_acl *,
 			acl_type_t, int archive_entry_acl_type, const char *tn);
 
-/*
- * XXX TODO: What about ACL types other than ACCESS and DEFAULT?
- */
 int
 archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
 	 struct archive_acl *abstract_acl)
 {
-	int		 ret;
+	int		ret = ARCHIVE_OK;
 
-	if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) > 0) {
-		ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS,
-		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
-		if (ret != ARCHIVE_OK)
-			return (ret);
-		ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT,
-		    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
+#if !HAVE_DARWIN_ACL
+	if ((archive_acl_types(abstract_acl)
+	    & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
+#if HAVE_SUN_ACL
+		/* Solaris writes POSIX.1e access and default ACLs together */
+		ret = set_acl(a, fd, name, abstract_acl, ACLENT_T,
+		    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
+#else	/* HAVE_POSIX_ACL */
+		if ((archive_acl_types(abstract_acl)
+		    & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+			ret = set_acl(a, fd, name, abstract_acl,
+			    ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
+			    "access");
+			if (ret != ARCHIVE_OK)
+				return (ret);
+		}
+		if ((archive_acl_types(abstract_acl)
+		    & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+			ret = set_acl(a, fd, name, abstract_acl,
+			    ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
+			    "default");
+#endif	/* !HAVE_SUN_ACL */
+		/* Simultaneous POSIX.1e and NFSv4 is not supported */
 		return (ret);
-#ifdef ACL_TYPE_NFS4
-	} else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) {
-		ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4,
+	}
+#endif	/* !HAVE_DARWIN_ACL */
+#if HAVE_NFS4_ACL
+	if ((archive_acl_types(abstract_acl) &
+	    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+		ret = set_acl(a, fd, name, abstract_acl,
+		    ARCHIVE_PLATFORM_ACL_TYPE_NFS4,
 		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
-		return (ret);
-#endif
-	} else
-		return ARCHIVE_OK;
+	}
+#endif	/* HAVE_NFS4_ACL */
+	return (ret);
 }
 
-static struct {
-	int archive_perm;
-	int platform_perm;
+/*
+ * Translate system ACL permissions into libarchive internal structure
+ */
+static const struct {
+	const int archive_perm;
+	const int platform_perm;
 } acl_perm_map[] = {
+#if HAVE_SUN_ACL	/* Solaris NFSv4 ACL permissions */
+	{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
+	{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
+	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
+	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
+	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
+	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
+	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
+	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
+	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
+	{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
+	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
+	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
+	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
+#elif HAVE_DARWIN_ACL	/* MacOS ACL permissions */
+	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
+	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
+	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
+	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
+	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+#else	/* POSIX.1e ACL permissions */
 	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
 	{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
 	{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4	/* FreeBSD NFSv4 ACL permissions */
 	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
 	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
 	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
@@ -114,33 +181,69 @@ static struct {
 	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
 	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
 #endif
+#endif	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
 };
 
-#ifdef ACL_TYPE_NFS4
-static struct {
-	int archive_inherit;
-	int platform_inherit;
+#if HAVE_NFS4_ACL
+/*
+ * Translate system NFSv4 inheritance flags into libarchive internal structure
+ */
+static const struct {
+	const int archive_inherit;
+	const int platform_inherit;
 } acl_inherit_map[] = {
+#if HAVE_SUN_ACL	/* Solaris NFSv4 inheritance flags */
+	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
+	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
+	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
+	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
+	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
+#elif HAVE_DARWIN_ACL	/* MacOS NFSv4 inheritance flags */
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
+	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
+	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
+#else	/* FreeBSD NFSv4 ACL inheritance flags */
 	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
 	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
 	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
-	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
+	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
+	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
+	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
+#endif	/* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
 };
-#endif
+#endif	/* HAVE_NFS4_ACL */
 
 static int
 set_acl(struct archive *a, int fd, const char *name,
     struct archive_acl *abstract_acl,
     acl_type_t acl_type, int ae_requested_type, const char *tname)
 {
+#if HAVE_SUN_ACL
+	aclent_t	 *aclent;
+	ace_t		 *ace;
+	int		 e, r;
+	acl_t		 *acl;
+#else
 	acl_t		 acl;
 	acl_entry_t	 acl_entry;
 	acl_permset_t	 acl_permset;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
 	acl_flagset_t	 acl_flagset;
 #endif
+#endif	/* HAVE_SUN_ACL */
+#if HAVE_ACL_TYPE_NFS4
+	int		r;
+#endif
 	int		 ret;
 	int		 ae_type, ae_permset, ae_tag, ae_id;
+#if HAVE_DARWIN_ACL
+	uuid_t		ae_uuid;
+#endif
 	uid_t		 ae_uid;
 	gid_t		 ae_gid;
 	const char	*ae_name;
@@ -151,22 +254,165 @@ set_acl(struct archive *a, int fd, const char *name,
 	entries = archive_acl_reset(abstract_acl, ae_requested_type);
 	if (entries == 0)
 		return (ARCHIVE_OK);
+
+#if HAVE_SUN_ACL
+	acl = NULL;
+	acl = malloc(sizeof(acl_t));
+	if (acl == NULL) {
+		archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			"Invalid ACL type");
+		return (ARCHIVE_FAILED);
+	}
+	if (acl_type == ACE_T)
+		acl->acl_entry_size = sizeof(ace_t);
+	else if (acl_type == ACLENT_T)
+		acl->acl_entry_size = sizeof(aclent_t);
+	else {
+		archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			"Invalid ACL type");
+		acl_free(acl);
+		return (ARCHIVE_FAILED);
+	}
+	acl->acl_type = acl_type;
+	acl->acl_cnt = entries;
+
+	acl->acl_aclp = malloc(entries * acl->acl_entry_size);
+	if (acl->acl_aclp == NULL) {
+		archive_set_error(a, errno,
+		    "Can't allocate memory for acl buffer");
+		acl_free(acl);
+		return (ARCHIVE_FAILED);
+	}
+#else	/* !HAVE_SUN_ACL */
 	acl = acl_init(entries);
+	if (acl == (acl_t)NULL) {
+		archive_set_error(a, errno,
+		    "Failed to initialize ACL working storage");
+		return (ARCHIVE_FAILED);
+	}
+#endif	/* !HAVE_SUN_ACL */
+#if HAVE_SUN_ACL
+	e = 0;
+#endif
 	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
 		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
-		acl_create_entry(&acl, &acl_entry);
-
+#if HAVE_SUN_ACL
+		ace = NULL;
+		aclent = NULL;
+		if (acl->acl_type == ACE_T)  {
+			ace = &((ace_t *)acl->acl_aclp)[e];
+			ace->a_who = -1;
+			ace->a_access_mask = 0;
+			ace->a_flags = 0;
+		} else {
+			aclent = &((aclent_t *)acl->acl_aclp)[e];
+			aclent->a_id = -1;
+			aclent->a_type = 0;
+			aclent->a_perm = 0;
+		}
+#else	/* !HAVE_SUN_ACL  */
+#if HAVE_DARWIN_ACL
+		/*
+		 * Mac OS doesn't support NFSv4 ACLs for
+		 * owner@, group@ and everyone at .
+		 * We skip any of these ACLs found.
+		 */
+		if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
+		    ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
+		    ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
+			continue;
+#endif
+		if (acl_create_entry(&acl, &acl_entry) != 0) {
+			archive_set_error(a, errno,
+			    "Failed to create a new ACL entry");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
+		}
+#endif	/* !HAVE_SUN_ACL */
+#if HAVE_DARWIN_ACL
+		switch (ae_type) {
+		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+			acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+			acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
+			break;
+		default:
+			/* We don't support any other types on MacOS */
+			continue;
+		}
+#endif
 		switch (ae_tag) {
+#if HAVE_SUN_ACL
+		case ARCHIVE_ENTRY_ACL_USER:
+			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+			if (acl->acl_type == ACE_T)
+				ace->a_who = ae_uid;
+			else {
+				aclent->a_id = ae_uid;
+				aclent->a_type |= USER;
+			}
+			break;
+		case ARCHIVE_ENTRY_ACL_GROUP:
+			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+			if (acl->acl_type == ACE_T) {
+				ace->a_who = ae_gid;
+				ace->a_flags |= ACE_IDENTIFIER_GROUP;
+			} else {
+				aclent->a_id = ae_gid;
+				aclent->a_type |= GROUP;
+			}
+			break;
+		case ARCHIVE_ENTRY_ACL_USER_OBJ:
+			if (acl->acl_type == ACE_T)
+				ace->a_flags |= ACE_OWNER;
+			else
+				aclent->a_type |= USER_OBJ;
+			break;
+		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+			if (acl->acl_type == ACE_T) {
+				ace->a_flags |= ACE_GROUP;
+				ace->a_flags |= ACE_IDENTIFIER_GROUP;
+			} else
+				aclent->a_type |= GROUP_OBJ;
+			break;
+		case ARCHIVE_ENTRY_ACL_MASK:
+			aclent->a_type |= CLASS_OBJ;
+			break;
+		case ARCHIVE_ENTRY_ACL_OTHER:
+			aclent->a_type |= OTHER_OBJ;
+			break;
+		case ARCHIVE_ENTRY_ACL_EVERYONE:
+			ace->a_flags |= ACE_EVERYONE;
+			break;
+#else	/* !HAVE_SUN_ACL */
 		case ARCHIVE_ENTRY_ACL_USER:
-			acl_set_tag_type(acl_entry, ACL_USER);
 			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+#if !HAVE_DARWIN_ACL	/* FreeBSD, Linux */
+			acl_set_tag_type(acl_entry, ACL_USER);
 			acl_set_qualifier(acl_entry, &ae_uid);
+#else	/* MacOS */
+			if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid,
+			    sizeof(uid_t), ae_uuid) != 0)
+				continue;
+			if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
+				continue;
+#endif	/* HAVE_DARWIN_ACL */
 			break;
 		case ARCHIVE_ENTRY_ACL_GROUP:
-			acl_set_tag_type(acl_entry, ACL_GROUP);
 			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+#if !HAVE_DARWIN_ACL	/* FreeBSD, Linux */
+			acl_set_tag_type(acl_entry, ACL_GROUP);
 			acl_set_qualifier(acl_entry, &ae_gid);
+#else	/* MacOS */
+			if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid,
+			    sizeof(gid_t), ae_uuid) != 0)
+				continue;
+			if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
+				continue;
+#endif	/* HAVE_DARWIN_ACL */
 			break;
+#if !HAVE_DARWIN_ACL	/* FreeBSD, Linux */
 		case ARCHIVE_ENTRY_ACL_USER_OBJ:
 			acl_set_tag_type(acl_entry, ACL_USER_OBJ);
 			break;
@@ -179,85 +425,230 @@ set_acl(struct archive *a, int fd, const char *name,
 		case ARCHIVE_ENTRY_ACL_OTHER:
 			acl_set_tag_type(acl_entry, ACL_OTHER);
 			break;
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4	/* FreeBSD only */
 		case ARCHIVE_ENTRY_ACL_EVERYONE:
 			acl_set_tag_type(acl_entry, ACL_EVERYONE);
 			break;
 #endif
+#endif	/* !HAVE_DARWIN_ACL */
+#endif	/* !HAVE_SUN_ACL */
 		default:
-			/* XXX */
-			break;
+			archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			    "Unknown ACL tag");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
 		}
 
-#ifdef ACL_TYPE_NFS4
+#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL
+		r = 0;
 		switch (ae_type) {
+#if HAVE_SUN_ACL
+		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+			if (ace != NULL)
+				ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+			else
+				r = -1;
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+			if (ace != NULL)
+				ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+			else
+				r = -1;
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+			if (ace != NULL)
+				ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
+			else
+				r = -1;
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+			if (ace != NULL)
+				ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
+			else
+				r = -1;
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+			if (aclent == NULL)
+				r = -1;
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+			if (aclent != NULL)
+				aclent->a_type |= ACL_DEFAULT;
+			else
+				r = -1;
+			break;
+#else	/* !HAVE_SUN_ACL */
 		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
 		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
 			// These don't translate directly into the system ACL.
 			break;
+#endif	/* !HAVE_SUN_ACL */
 		default:
-			// XXX error handling here.
-			break;
+			archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			    "Unknown ACL entry type");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
 		}
-#endif
 
-		acl_get_permset(acl_entry, &acl_permset);
-		acl_clear_perms(acl_permset);
+		if (r != 0) {
+#if HAVE_SUN_ACL
+			errno = EINVAL;
+#endif
+			archive_set_error(a, errno,
+			    "Failed to set ACL entry type");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
+		}
+#endif	/* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */
 
+#if HAVE_SUN_ACL
+		if (acl->acl_type == ACLENT_T) {
+			if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
+				aclent->a_perm |= 1;
+			if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
+				aclent->a_perm |= 2;
+			if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
+				aclent->a_perm |= 4;
+		} else
+#else
+		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
+			archive_set_error(a, errno,
+			    "Failed to get ACL permission set");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
+		}
+		if (acl_clear_perms(acl_permset) != 0) {
+			archive_set_error(a, errno,
+			    "Failed to clear ACL permissions");
+			ret = ARCHIVE_FAILED;
+			goto exit_free;
+		}
+#endif	/* !HAVE_SUN_ACL */
 		for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
-			if (ae_permset & acl_perm_map[i].archive_perm)
-				acl_add_perm(acl_permset,
-					     acl_perm_map[i].platform_perm);
+			if (ae_permset & acl_perm_map[i].archive_perm) {
+#if HAVE_SUN_ACL
+				ace->a_access_mask |=
+				    acl_perm_map[i].platform_perm;
+#else
+				if (acl_add_perm(acl_permset,
+				    acl_perm_map[i].platform_perm) != 0) {
+					archive_set_error(a, errno,
+					    "Failed to add ACL permission");
+					ret = ARCHIVE_FAILED;
+					goto exit_free;
+				}
+#endif
+			}
 		}
 
-#ifdef ACL_TYPE_NFS4
-		acl_get_flagset_np(acl_entry, &acl_flagset);
-		acl_clear_flags_np(acl_flagset);
-		for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
-			if (ae_permset & acl_inherit_map[i].archive_inherit)
-				acl_add_flag_np(acl_flagset,
-						acl_inherit_map[i].platform_inherit);
+#if HAVE_NFS4_ACL
+#if HAVE_SUN_ACL
+		if (acl_type == ACE_T)
+#elif HAVE_DARWIN_ACL
+		if (acl_type == ACL_TYPE_EXTENDED)
+#else	/* FreeBSD */
+		if (acl_type == ACL_TYPE_NFS4)
+#endif
+		{
+#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
+			/*
+			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
+			 */
+			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
+				archive_set_error(a, errno,
+				    "Failed to get flagset from an NFSv4 ACL entry");
+				ret = ARCHIVE_FAILED;
+				goto exit_free;
+			}
+			if (acl_clear_flags_np(acl_flagset) != 0) {
+				archive_set_error(a, errno,
+				    "Failed to clear flags from an NFSv4 ACL flagset");
+				ret = ARCHIVE_FAILED;
+				goto exit_free;
+			}
+#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
+			for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) {
+				if (ae_permset & acl_inherit_map[i].archive_inherit) {
+#if HAVE_SUN_ACL
+					ace->a_flags |=
+					    acl_inherit_map[i].platform_inherit;
+#else	/* !HAVE_SUN_ACL */
+					if (acl_add_flag_np(acl_flagset,
+							acl_inherit_map[i].platform_inherit) != 0) {
+						archive_set_error(a, errno,
+						    "Failed to add flag to NFSv4 ACL flagset");
+						ret = ARCHIVE_FAILED;
+						goto exit_free;
+					}
+#endif	/* HAVE_SUN_ACL */
+				}
+			}
 		}
+#endif	/* HAVE_NFS4_ACL */
+#if HAVE_SUN_ACL
+	e++;
 #endif
 	}
 
+#if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL
 	/* Try restoring the ACL through 'fd' if we can. */
-#if HAVE_ACL_SET_FD
-	if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0)
-		ret = ARCHIVE_OK;
-	else
-#else
-#if HAVE_ACL_SET_FD_NP
-	if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0)
-		ret = ARCHIVE_OK;
-	else
+#if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP
+	if (fd >= 0)
+#else	/* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
+	if (fd >= 0 && acl_type == ACL_TYPE_ACCESS)
 #endif
+	{
+#if HAVE_SUN_ACL
+		if (facl_set(fd, acl) == 0)
+#elif HAVE_ACL_SET_FD_NP
+		if (acl_set_fd_np(fd, acl, acl_type) == 0)
+#else	/* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
+		if (acl_set_fd(fd, acl) == 0)
 #endif
-#if HAVE_ACL_SET_LINK_NP
-	  if (acl_set_link_np(name, acl_type, acl) != 0) {
-		archive_set_error(a, errno, "Failed to set %s acl", tname);
-		ret = ARCHIVE_WARN;
-	  }
+			ret = ARCHIVE_OK;
+		else {
+			if (errno == EOPNOTSUPP) {
+				/* Filesystem doesn't support ACLs */
+				ret = ARCHIVE_OK;
+			} else {
+				archive_set_error(a, errno,
+				    "Failed to set %s acl on fd", tname);
+			}
+		}
+	} else
+#endif	/* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */
+#if HAVE_SUN_ACL
+	if (acl_set(name, acl) != 0)
+#elif HAVE_ACL_SET_LINK_NP
+	if (acl_set_link_np(name, acl_type, acl) != 0)
 #else
 	/* TODO: Skip this if 'name' is a symlink. */
-	if (acl_set_file(name, acl_type, acl) != 0) {
-		archive_set_error(a, errno, "Failed to set %s acl", tname);
-		ret = ARCHIVE_WARN;
-	}
+	if (acl_set_file(name, acl_type, acl) != 0)
 #endif
+	{
+		if (errno == EOPNOTSUPP) {
+			/* Filesystem doesn't support ACLs */
+			ret = ARCHIVE_OK;
+		} else {
+			archive_set_error(a, errno, "Failed to set %s acl",
+			    tname);
+			ret = ARCHIVE_WARN;
+		}
+	}
+exit_free:
 	acl_free(acl);
 	return (ret);
 }
-#endif
+#endif	/* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
index 5946683..a5f3067 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
@@ -110,6 +110,18 @@ __FBSDID("$FreeBSD$");
 #include <sys/fcntl1.h>
 #endif
 
+/*
+ * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared.
+ *
+ * It assumes that the input is an integer type of no more than 64 bits.
+ * If the number is less than zero, t must be a signed type, so it fits in
+ * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t
+ * without loss. But it could be a large unsigned value, so we have to clip it
+ * to INT64_MAX.*
+ */
+#define to_int64_time(t) \
+   ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t))
+
 #if __APPLE__
 #include <TargetConditionals.h>
 #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H
@@ -140,7 +152,17 @@ __FBSDID("$FreeBSD$");
 #define O_BINARY 0
 #endif
 #ifndef O_CLOEXEC
-#define O_CLOEXEC	0
+#define O_CLOEXEC 0
+#endif
+
+/* Ignore non-int O_NOFOLLOW constant. */
+/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
+#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
+#undef O_NOFOLLOW
+#endif
+
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 0
 #endif
 
 struct fixup_entry {
@@ -298,7 +320,7 @@ struct archive_write_disk {
 #define	MAXIMUM_DIR_MODE 0775
 
 /*
- * Maxinum uncompressed size of a decmpfs block.
+ * Maximum uncompressed size of a decmpfs block.
  */
 #define MAX_DECMPFS_BLOCK_SIZE	(64 * 1024)
 /*
@@ -313,7 +335,7 @@ struct archive_write_disk {
 #define RSRC_F_SIZE	50	/* Size of Resource fork footer. */
 /* Size to write compressed data to resource fork. */
 #define COMPRESSED_W_SIZE	(64 * 1024)
-/* decmpfs difinitions. */
+/* decmpfs definitions. */
 #define MAX_DECMPFS_XATTR_SIZE		3802
 #ifndef DECMPFS_XATTR_NAME
 #define DECMPFS_XATTR_NAME		"com.apple.decmpfs"
@@ -326,12 +348,19 @@ struct archive_write_disk {
 
 #define HFS_BLOCKS(s)	((s) >> 12)
 
+static void	fsobj_error(int *, struct archive_string *, int, const char *,
+		    const char *);
+static int	check_symlinks_fsobj(char *, int *, struct archive_string *,
+		    int);
 static int	check_symlinks(struct archive_write_disk *);
 static int	create_filesystem_object(struct archive_write_disk *);
-static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
+static struct fixup_entry *current_fixup(struct archive_write_disk *,
+		    const char *pathname);
 #if defined(HAVE_FCHDIR) && defined(PATH_MAX)
 static void	edit_deep_directories(struct archive_write_disk *ad);
 #endif
+static int	cleanup_pathname_fsobj(char *, int *, struct archive_string *,
+		    int);
 static int	cleanup_pathname(struct archive_write_disk *);
 static int	create_dir(struct archive_write_disk *, char *);
 static int	create_parent_dir(struct archive_write_disk *, char *);
@@ -362,11 +391,14 @@ static struct archive_vtable *archive_write_disk_vtable(void);
 
 static int	_archive_write_disk_close(struct archive *);
 static int	_archive_write_disk_free(struct archive *);
-static int	_archive_write_disk_header(struct archive *, struct archive_entry *);
+static int	_archive_write_disk_header(struct archive *,
+		    struct archive_entry *);
 static int64_t	_archive_write_disk_filter_bytes(struct archive *, int);
 static int	_archive_write_disk_finish_entry(struct archive *);
-static ssize_t	_archive_write_disk_data(struct archive *, const void *, size_t);
-static ssize_t	_archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t);
+static ssize_t	_archive_write_disk_data(struct archive *, const void *,
+		    size_t);
+static ssize_t	_archive_write_disk_data_block(struct archive *, const void *,
+		    size_t, int64_t);
 
 static int
 lazy_stat(struct archive_write_disk *a)
@@ -612,9 +644,9 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
 		/*
 		 * NOTE: UF_COMPRESSED is ignored even if the filesystem
 		 * supports HFS+ Compression because the file should
-		 * have at least an extended attriute "com.apple.decmpfs"
+		 * have at least an extended attribute "com.apple.decmpfs"
 		 * before the flag is set to indicate that the file have
-		 * been compressed. If hte filesystem does not support
+		 * been compressed. If the filesystem does not support
 		 * HFS+ Compression the system call will fail.
 		 */
 		if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0)
@@ -637,7 +669,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
 	if (a->restore_pwd >= 0) {
 		r = fchdir(a->restore_pwd);
 		if (r != 0) {
-			archive_set_error(&a->archive, errno, "chdir() failure");
+			archive_set_error(&a->archive, errno,
+			    "chdir() failure");
 			ret = ARCHIVE_FATAL;
 		}
 		close(a->restore_pwd);
@@ -685,7 +718,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
 		}
 		if (archive_entry_birthtime_is_set(entry)) {
 			fe->birthtime = archive_entry_birthtime(entry);
-			fe->birthtime_nanos = archive_entry_birthtime_nsec(entry);
+			fe->birthtime_nanos = archive_entry_birthtime_nsec(
+			    entry);
 		} else {
 			/* If birthtime is unset, use mtime. */
 			fe->birthtime = fe->mtime;
@@ -711,7 +745,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
 				return (ARCHIVE_FATAL);
 			fe->mac_metadata = malloc(metadata_size);
 			if (fe->mac_metadata != NULL) {
-				memcpy(fe->mac_metadata, metadata, metadata_size);
+				memcpy(fe->mac_metadata, metadata,
+				    metadata_size);
 				fe->mac_metadata_size = metadata_size;
 				fe->fixup |= TODO_MAC_METADATA;
 			}
@@ -1224,7 +1259,7 @@ hfs_drive_compressor(struct archive_write_disk *a, const char *buff,
 		ret = hfs_write_compressed_data(a, bytes_used + rsrc_size);
 		a->compressed_buffer_remaining = a->compressed_buffer_size;
 
-		/* If the compressed size is not enouph smaller than
+		/* If the compressed size is not enough smaller than
 		 * the uncompressed size. cancel HFS+ compression.
 		 * TODO: study a behavior of ditto utility and improve
 		 * the condition to fall back into no HFS+ compression. */
@@ -1329,7 +1364,7 @@ hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
 		    (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
 		/* Set the block count to the resource fork. */
 		archive_le32enc(a->decmpfs_block_info++, block_count);
-		/* Get the position where we are goint to set compressed
+		/* Get the position where we are going to set compressed
 		 * data. */
 		a->compressed_rsrc_position =
 		    RSRC_H_SIZE + 4 + (block_count * 8);
@@ -1402,7 +1437,7 @@ hfs_write_data_block(struct archive_write_disk *a, const char *buff,
 		bytes_to_write = size;
 		/* Seek if necessary to the specified offset. */
 		if (a->offset < a->fd_offset) {
-			/* Can't support backword move. */
+			/* Can't support backward move. */
 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 			    "Seek failed");
 			return (ARCHIVE_FATAL);
@@ -1468,7 +1503,8 @@ _archive_write_disk_data_block(struct archive *_a,
 		return (r);
 	if ((size_t)r < size) {
 		archive_set_error(&a->archive, 0,
-		    "Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize);
+		    "Too much data: Truncating file at %ju bytes",
+		    (uintmax_t)a->filesize);
 		return (ARCHIVE_WARN);
 	}
 #if ARCHIVE_VERSION_NUMBER < 3999000
@@ -1666,10 +1702,26 @@ _archive_write_disk_finish_entry(struct archive *_a)
 	 * ACLs that prevent attribute changes (including time).
 	 */
 	if (a->todo & TODO_ACLS) {
-		int r2 = archive_write_disk_set_acls(&a->archive, a->fd,
-				  archive_entry_pathname(a->entry),
-				  archive_entry_acl(a->entry));
+		int r2;
+#ifdef HAVE_DARWIN_ACL
+		/*
+		 * On Mac OS, platform ACLs are stored also in mac_metadata by
+		 * the operating system. If mac_metadata is present it takes
+		 * precedence and we skip extracting libarchive NFSv4 ACLs
+		 */
+		const void *metadata;
+		size_t metadata_size;
+		metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
+		if ((a->todo & TODO_MAC_METADATA) == 0 ||
+		    metadata == NULL || metadata_size == 0) {
+#endif
+		r2 = archive_write_disk_set_acls(&a->archive, a->fd,
+		    archive_entry_pathname(a->entry),
+		    archive_entry_acl(a->entry));
 		if (r2 < ret) ret = r2;
+#ifdef HAVE_DARWIN_ACL
+		}
+#endif
 	}
 
 finish_metadata:
@@ -1755,10 +1807,9 @@ archive_write_disk_new(void)
 {
 	struct archive_write_disk *a;
 
-	a = (struct archive_write_disk *)malloc(sizeof(*a));
+	a = (struct archive_write_disk *)calloc(1, sizeof(*a));
 	if (a == NULL)
 		return (NULL);
-	memset(a, 0, sizeof(*a));
 	a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
 	/* We're ready to write a header immediately. */
 	a->archive.state = ARCHIVE_STATE_HEADER;
@@ -1796,7 +1847,7 @@ edit_deep_directories(struct archive_write_disk *a)
 	char *tail = a->name;
 
 	/* If path is short, avoid the open() below. */
-	if (strlen(tail) <= PATH_MAX)
+	if (strlen(tail) < PATH_MAX)
 		return;
 
 	/* Try to record our starting dir. */
@@ -1806,7 +1857,7 @@ edit_deep_directories(struct archive_write_disk *a)
 		return;
 
 	/* As long as the path is too long... */
-	while (strlen(tail) > PATH_MAX) {
+	while (strlen(tail) >= PATH_MAX) {
 		/* Locate a dir prefix shorter than PATH_MAX. */
 		tail += PATH_MAX - 8;
 		while (tail > a->name && *tail != '/')
@@ -1993,8 +2044,9 @@ restore_entry(struct archive_write_disk *a)
 
 	if (en) {
 		/* Everything failed; give up here. */
-		archive_set_error(&a->archive, en, "Can't create '%s'",
-		    a->name);
+		if ((&a->archive)->error == NULL)
+			archive_set_error(&a->archive, en, "Can't create '%s'",
+			    a->name);
 		return (ARCHIVE_FAILED);
 	}
 
@@ -2014,6 +2066,11 @@ create_filesystem_object(struct archive_write_disk *a)
 	const char *linkname;
 	mode_t final_mode, mode;
 	int r;
+	/* these for check_symlinks_fsobj */
+	char *linkname_copy;	/* non-const copy of linkname */
+	struct stat st;
+	struct archive_string error_string;
+	int error_number;
 
 	/* We identify hard/symlinks according to the link names. */
 	/* Since link(2) and symlink(2) don't handle modes, we're done here. */
@@ -2022,6 +2079,43 @@ create_filesystem_object(struct archive_write_disk *a)
 #if !HAVE_LINK
 		return (EPERM);
 #else
+		archive_string_init(&error_string);
+		linkname_copy = strdup(linkname);
+		if (linkname_copy == NULL) {
+		    return (EPERM);
+		}
+		/*
+		 * TODO: consider using the cleaned-up path as the link
+		 * target?
+		 */
+		r = cleanup_pathname_fsobj(linkname_copy, &error_number,
+		    &error_string, a->flags);
+		if (r != ARCHIVE_OK) {
+			archive_set_error(&a->archive, error_number, "%s",
+			    error_string.s);
+			free(linkname_copy);
+			archive_string_free(&error_string);
+			/*
+			 * EPERM is more appropriate than error_number for our
+			 * callers
+			 */
+			return (EPERM);
+		}
+		r = check_symlinks_fsobj(linkname_copy, &error_number,
+		    &error_string, a->flags);
+		if (r != ARCHIVE_OK) {
+			archive_set_error(&a->archive, error_number, "%s",
+			    error_string.s);
+			free(linkname_copy);
+			archive_string_free(&error_string);
+			/*
+			 * EPERM is more appropriate than error_number for our
+			 * callers
+			 */
+			return (EPERM);
+		}
+		free(linkname_copy);
+		archive_string_free(&error_string);
 		r = link(linkname, a->name) ? errno : 0;
 		/*
 		 * New cpio and pax formats allow hardlink entries
@@ -2039,11 +2133,20 @@ create_filesystem_object(struct archive_write_disk *a)
 			a->todo = 0;
 			a->deferred = 0;
 		} else if (r == 0 && a->filesize > 0) {
-			a->fd = open(a->name,
-				     O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC);
-			__archive_ensure_cloexec_flag(a->fd);
-			if (a->fd < 0)
+#ifdef HAVE_LSTAT
+			r = lstat(a->name, &st);
+#else
+			r = stat(a->name, &st);
+#endif
+			if (r != 0)
 				r = errno;
+			else if ((st.st_mode & AE_IFMT) == AE_IFREG) {
+				a->fd = open(a->name, O_WRONLY | O_TRUNC |
+				    O_BINARY | O_CLOEXEC | O_NOFOLLOW);
+				__archive_ensure_cloexec_flag(a->fd);
+				if (a->fd < 0)
+					r = errno;
+			}
 		}
 		return (r);
 #endif
@@ -2190,8 +2293,13 @@ _archive_write_disk_close(struct archive *_a)
 		if (p->fixup & TODO_MODE_BASE)
 			chmod(p->name, p->mode);
 		if (p->fixup & TODO_ACLS)
-			archive_write_disk_set_acls(&a->archive,
-						    -1, p->name, &p->acl);
+#ifdef HAVE_DARWIN_ACL
+			if ((p->fixup & TODO_MAC_METADATA) == 0 ||
+			    p->mac_metadata == NULL ||
+			    p->mac_metadata_size == 0)
+#endif
+				archive_write_disk_set_acls(&a->archive,
+				    -1, p->name, &p->acl);
 		if (p->fixup & TODO_FFLAGS)
 			set_fflags_platform(a, -1, p->name,
 			    p->mode, p->fflags_set, 0);
@@ -2351,116 +2459,283 @@ current_fixup(struct archive_write_disk *a, const char *pathname)
 	return (a->current_fixup);
 }
 
-/* TODO: Make this work. */
-/*
- * TODO: The deep-directory support bypasses this; disable deep directory
- * support if we're doing symlink checks.
- */
+/* Error helper for new *_fsobj functions */
+static void
+fsobj_error(int *a_eno, struct archive_string *a_estr,
+    int err, const char *errstr, const char *path)
+{
+	if (a_eno)
+		*a_eno = err;
+	if (a_estr)
+		archive_string_sprintf(a_estr, errstr, path);
+}
+
 /*
  * TODO: Someday, integrate this with the deep dir support; they both
  * scan the path and both can be optimized by comparing against other
  * recent paths.
  */
 /* TODO: Extend this to support symlinks on Windows Vista and later. */
+
+/*
+ * Checks the given path to see if any elements along it are symlinks.  Returns
+ * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
+ */
 static int
-check_symlinks(struct archive_write_disk *a)
+check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
+    int flags)
 {
 #if !defined(HAVE_LSTAT)
 	/* Platform doesn't have lstat, so we can't look for symlinks. */
-	(void)a; /* UNUSED */
+	(void)path; /* UNUSED */
+	(void)error_number; /* UNUSED */
+	(void)error_string; /* UNUSED */
+	(void)flags; /* UNUSED */
 	return (ARCHIVE_OK);
 #else
-	char *pn;
+	int res = ARCHIVE_OK;
+	char *tail;
+	char *head;
+	int last;
 	char c;
 	int r;
 	struct stat st;
+	int restore_pwd;
+
+	/* Nothing to do here if name is empty */
+	if(path[0] == '\0')
+	    return (ARCHIVE_OK);
 
 	/*
 	 * Guard against symlink tricks.  Reject any archive entry whose
 	 * destination would be altered by a symlink.
+	 *
+	 * Walk the filename in chunks separated by '/'.  For each segment:
+	 *  - if it doesn't exist, continue
+	 *  - if it's symlink, abort or remove it
+	 *  - if it's a directory and it's not the last chunk, cd into it
+	 * As we go:
+	 *  head points to the current (relative) path
+	 *  tail points to the temporary \0 terminating the segment we're
+	 *      currently examining
+	 *  c holds what used to be in *tail
+	 *  last is 1 if this is the last tail
 	 */
-	/* Whatever we checked last time doesn't need to be re-checked. */
-	pn = a->name;
-	if (archive_strlen(&(a->path_safe)) > 0) {
-		char *p = a->path_safe.s;
-		while ((*pn != '\0') && (*p == *pn))
-			++p, ++pn;
-	}
+	restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
+	__archive_ensure_cloexec_flag(restore_pwd);
+	if (restore_pwd < 0)
+		return (ARCHIVE_FATAL);
+	head = path;
+	tail = path;
+	last = 0;
+	/* TODO: reintroduce a safe cache here? */
 	/* Skip the root directory if the path is absolute. */
-	if(pn == a->name && pn[0] == '/')
-		++pn;
-	c = pn[0];
-	/* Keep going until we've checked the entire name. */
-	while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
+	if(tail == path && tail[0] == '/')
+		++tail;
+	/* Keep going until we've checked the entire name.
+	 * head, tail, path all alias the same string, which is
+	 * temporarily zeroed at tail, so be careful restoring the
+	 * stashed (c=tail[0]) for error messages.
+	 * Exiting the loop with break is okay; continue is not.
+	 */
+	while (!last) {
+		/*
+		 * Skip the separator we just consumed, plus any adjacent ones
+		 */
+		while (*tail == '/')
+		    ++tail;
 		/* Skip the next path element. */
-		while (*pn != '\0' && *pn != '/')
-			++pn;
-		c = pn[0];
-		pn[0] = '\0';
+		while (*tail != '\0' && *tail != '/')
+			++tail;
+		/* is this the last path component? */
+		last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0');
+		/* temporarily truncate the string here */
+		c = tail[0];
+		tail[0] = '\0';
 		/* Check that we haven't hit a symlink. */
-		r = lstat(a->name, &st);
+		r = lstat(head, &st);
 		if (r != 0) {
+			tail[0] = c;
 			/* We've hit a dir that doesn't exist; stop now. */
-			if (errno == ENOENT)
+			if (errno == ENOENT) {
+				break;
+			} else {
+				/*
+				 * Treat any other error as fatal - best to be
+				 * paranoid here.
+				 * Note: This effectively disables deep
+				 * directory support when security checks are
+				 * enabled. Otherwise, very long pathnames that
+				 * trigger an error here could evade the
+				 * sandbox.
+				 * TODO: We could do better, but it would
+				 * probably require merging the symlink checks
+				 * with the deep-directory editing.
+				 */
+				fsobj_error(a_eno, a_estr, errno,
+				    "Could not stat %s", path);
+				res = ARCHIVE_FAILED;
 				break;
+			}
+		} else if (S_ISDIR(st.st_mode)) {
+			if (!last) {
+				if (chdir(head) != 0) {
+					tail[0] = c;
+					fsobj_error(a_eno, a_estr, errno,
+					    "Could not chdir %s", path);
+					res = (ARCHIVE_FATAL);
+					break;
+				}
+				/* Our view is now from inside this dir: */
+				head = tail + 1;
+			}
 		} else if (S_ISLNK(st.st_mode)) {
-			if (c == '\0') {
+			if (last) {
 				/*
 				 * Last element is symlink; remove it
 				 * so we can overwrite it with the
 				 * item being extracted.
 				 */
-				if (unlink(a->name)) {
-					archive_set_error(&a->archive, errno,
+				if (unlink(head)) {
+					tail[0] = c;
+					fsobj_error(a_eno, a_estr, errno,
 					    "Could not remove symlink %s",
-					    a->name);
-					pn[0] = c;
-					return (ARCHIVE_FAILED);
+					    path);
+					res = ARCHIVE_FAILED;
+					break;
 				}
-				a->pst = NULL;
 				/*
 				 * Even if we did remove it, a warning
 				 * is in order.  The warning is silly,
 				 * though, if we're just replacing one
 				 * symlink with another symlink.
 				 */
-				if (!S_ISLNK(a->mode)) {
-					archive_set_error(&a->archive, 0,
-					    "Removing symlink %s",
-					    a->name);
+				tail[0] = c;
+				/*
+				 * FIXME:  not sure how important this is to
+				 * restore
+				 */
+				/*
+				if (!S_ISLNK(path)) {
+					fsobj_error(a_eno, a_estr, 0,
+					    "Removing symlink %s", path);
 				}
+				*/
 				/* Symlink gone.  No more problem! */
-				pn[0] = c;
-				return (0);
-			} else if (a->flags & ARCHIVE_EXTRACT_UNLINK) {
+				res = ARCHIVE_OK;
+				break;
+			} else if (flags & ARCHIVE_EXTRACT_UNLINK) {
 				/* User asked us to remove problems. */
-				if (unlink(a->name) != 0) {
-					archive_set_error(&a->archive, 0,
-					    "Cannot remove intervening symlink %s",
-					    a->name);
-					pn[0] = c;
-					return (ARCHIVE_FAILED);
+				if (unlink(head) != 0) {
+					tail[0] = c;
+					fsobj_error(a_eno, a_estr, 0,
+					    "Cannot remove intervening "
+					    "symlink %s", path);
+					res = ARCHIVE_FAILED;
+					break;
+				}
+				tail[0] = c;
+			} else if ((flags &
+			    ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
+				/*
+				 * We are not the last element and we want to
+				 * follow symlinks if they are a directory.
+				 * 
+				 * This is needed to extract hardlinks over
+				 * symlinks.
+				 */
+				r = stat(head, &st);
+				if (r != 0) {
+					tail[0] = c;
+					if (errno == ENOENT) {
+						break;
+					} else {
+						fsobj_error(a_eno, a_estr,
+						    errno,
+						    "Could not stat %s", path);
+						res = (ARCHIVE_FAILED);
+						break;
+					}
+				} else if (S_ISDIR(st.st_mode)) {
+					if (chdir(head) != 0) {
+						tail[0] = c;
+						fsobj_error(a_eno, a_estr,
+						    errno,
+						    "Could not chdir %s", path);
+						res = (ARCHIVE_FATAL);
+						break;
+					}
+					/*
+					 * Our view is now from inside
+					 * this dir:
+					 */
+					head = tail + 1;
+				} else {
+					tail[0] = c;
+					fsobj_error(a_eno, a_estr, 0,
+					    "Cannot extract through "
+					    "symlink %s", path);
+					res = ARCHIVE_FAILED;
+					break;
 				}
-				a->pst = NULL;
 			} else {
-				archive_set_error(&a->archive, 0,
-				    "Cannot extract through symlink %s",
-				    a->name);
-				pn[0] = c;
-				return (ARCHIVE_FAILED);
+				tail[0] = c;
+				fsobj_error(a_eno, a_estr, 0,
+				    "Cannot extract through symlink %s", path);
+				res = ARCHIVE_FAILED;
+				break;
 			}
 		}
-		pn[0] = c;
-		if (pn[0] != '\0')
-			pn++; /* Advance to the next segment. */
+		/* be sure to always maintain this */
+		tail[0] = c;
+		if (tail[0] != '\0')
+			tail++; /* Advance to the next segment. */
+	}
+	/* Catches loop exits via break */
+	tail[0] = c;
+#ifdef HAVE_FCHDIR
+	/* If we changed directory above, restore it here. */
+	if (restore_pwd >= 0) {
+		r = fchdir(restore_pwd);
+		if (r != 0) {
+			fsobj_error(a_eno, a_estr, errno,
+			    "chdir() failure", "");
+		}
+		close(restore_pwd);
+		restore_pwd = -1;
+		if (r != 0) {
+			res = (ARCHIVE_FATAL);
+		}
 	}
-	pn[0] = c;
-	/* We've checked and/or cleaned the whole path, so remember it. */
-	archive_strcpy(&a->path_safe, a->name);
-	return (ARCHIVE_OK);
 #endif
+	/* TODO: reintroduce a safe cache here? */
+	return res;
+#endif
+}
+
+/*
+ * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise
+ * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED}
+ */
+static int
+check_symlinks(struct archive_write_disk *a)
+{
+	struct archive_string error_string;
+	int error_number;
+	int rc;
+	archive_string_init(&error_string);
+	rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
+	    a->flags);
+	if (rc != ARCHIVE_OK) {
+		archive_set_error(&a->archive, error_number, "%s",
+		    error_string.s);
+	}
+	archive_string_free(&error_string);
+	a->pst = NULL;	/* to be safe */
+	return rc;
 }
 
+
 #if defined(__CYGWIN__)
 /*
  * 1. Convert a path separator from '\' to '/' .
@@ -2471,7 +2746,7 @@ check_symlinks(struct archive_write_disk *a)
  * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
  */
 static void
-cleanup_pathname_win(struct archive_write_disk *a)
+cleanup_pathname_win(char *path)
 {
 	wchar_t wc;
 	char *p;
@@ -2482,7 +2757,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
 	mb = 0;
 	complete = 1;
 	utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0;
-	for (p = a->name; *p != '\0'; p++) {
+	for (p = path; *p != '\0'; p++) {
 		++alen;
 		if (*p == '\\') {
 			/* If previous byte is smaller than 128,
@@ -2507,7 +2782,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
 	/*
 	 * Convert path separator in wide-character.
 	 */
-	p = a->name;
+	p = path;
 	while (*p != '\0' && alen) {
 		l = mbtowc(&wc, p, alen);
 		if (l == (size_t)-1) {
@@ -2534,26 +2809,27 @@ cleanup_pathname_win(struct archive_write_disk *a)
  * is set) if the path is absolute.
  */
 static int
-cleanup_pathname(struct archive_write_disk *a)
+cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
+    int flags)
 {
 	char *dest, *src;
 	char separator = '\0';
 
-	dest = src = a->name;
+	dest = src = path;
 	if (*src == '\0') {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Invalid empty pathname");
+		fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
+		    "Invalid empty ", "pathname");
 		return (ARCHIVE_FAILED);
 	}
 
 #if defined(__CYGWIN__)
-	cleanup_pathname_win(a);
+	cleanup_pathname_win(path);
 #endif
 	/* Skip leading '/'. */
 	if (*src == '/') {
-		if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-			                  "Path is absolute");
+		if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
+			fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
+			    "Path is ", "absolute");
 			return (ARCHIVE_FAILED);
 		}
 
@@ -2580,10 +2856,11 @@ cleanup_pathname(struct archive_write_disk *a)
 			} else if (src[1] == '.') {
 				if (src[2] == '/' || src[2] == '\0') {
 					/* Conditionally warn about '..' */
-					if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
-						archive_set_error(&a->archive,
+					if (flags
+					    & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
+						fsobj_error(a_eno, a_estr,
 						    ARCHIVE_ERRNO_MISC,
-						    "Path contains '..'");
+						    "Path contains ", "'..'");
 						return (ARCHIVE_FAILED);
 					}
 				}
@@ -2614,7 +2891,7 @@ cleanup_pathname(struct archive_write_disk *a)
 	 * We've just copied zero or more path elements, not including the
 	 * final '/'.
 	 */
-	if (dest == a->name) {
+	if (dest == path) {
 		/*
 		 * Nothing got copied.  The path must have been something
 		 * like '.' or '/' or './' or '/././././/./'.
@@ -2629,6 +2906,23 @@ cleanup_pathname(struct archive_write_disk *a)
 	return (ARCHIVE_OK);
 }
 
+static int
+cleanup_pathname(struct archive_write_disk *a)
+{
+	struct archive_string error_string;
+	int error_number;
+	int rc;
+	archive_string_init(&error_string);
+	rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string,
+	    a->flags);
+	if (rc != ARCHIVE_OK) {
+		archive_set_error(&a->archive, error_number, "%s",
+		    error_string.s);
+	}
+	archive_string_free(&error_string);
+	return rc;
+}
+
 /*
  * Create the parent directory of the specified path, assuming path
  * is already in mutable storage.
@@ -2707,7 +3001,8 @@ create_dir(struct archive_write_disk *a, char *path)
 		}
 	} else if (errno != ENOENT && errno != ENOTDIR) {
 		/* Stat failed? */
-		archive_set_error(&a->archive, errno, "Can't test directory '%s'", path);
+		archive_set_error(&a->archive, errno,
+		    "Can't test directory '%s'", path);
 		return (ARCHIVE_FAILED);
 	} else if (slash != NULL) {
 		*slash = '\0';
@@ -3172,12 +3467,19 @@ set_fflags(struct archive_write_disk *a)
 #ifdef UF_APPEND
 	critical_flags |= UF_APPEND;
 #endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+	critical_flags |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
 	critical_flags |= EXT2_APPEND_FL;
 #endif
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+	critical_flags |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
 	critical_flags |= EXT2_IMMUTABLE_FL;
 #endif
+#ifdef FS_JOURNAL_DATA_FL
+	critical_flags |= FS_JOURNAL_DATA_FL;
+#endif
 
 	if (a->todo & TODO_FFLAGS) {
 		archive_entry_fflags(a->entry, &set, &clear);
@@ -3232,7 +3534,8 @@ clear_nochange_fflags(struct archive_write_disk *a)
 	nochange_flags |= EXT2_IMMUTABLE_FL;
 #endif
 
-	return (set_fflags_platform(a, a->fd, a->name, mode, 0, nochange_flags));
+	return (set_fflags_platform(a, a->fd, a->name, mode, 0,
+	    nochange_flags));
 }
 
 
@@ -3288,7 +3591,10 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
 	return (ARCHIVE_WARN);
 }
 
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \
+       defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+      (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \
+       defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
 /*
  * Linux uses ioctl() to read and write file flags.
  */
@@ -3301,7 +3607,7 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
 	int newflags, oldflags;
 	int sf_mask = 0;
 
-	if (set == 0  && clear == 0)
+	if (set == 0 && clear == 0)
 		return (ARCHIVE_OK);
 	/* Only regular files and dirs can have flags. */
 	if (!S_ISREG(mode) && !S_ISDIR(mode))
@@ -3322,12 +3628,19 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
 	 * defines. (?)  The code below degrades reasonably gracefully
 	 * if sf_mask is incomplete.
 	 */
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+	sf_mask |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
 	sf_mask |= EXT2_IMMUTABLE_FL;
 #endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+	sf_mask |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
 	sf_mask |= EXT2_APPEND_FL;
 #endif
+#if defined(FS_JOURNAL_DATA_FL)
+	sf_mask |= FS_JOURNAL_DATA_FL;
+#endif
 	/*
 	 * XXX As above, this would be way simpler if we didn't have
 	 * to read the current flags from disk. XXX
@@ -3335,12 +3648,24 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
 	ret = ARCHIVE_OK;
 
 	/* Read the current file flags. */
-	if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0)
+	if (ioctl(myfd,
+#ifdef FS_IOC_GETFLAGS
+	    FS_IOC_GETFLAGS,
+#else
+	    EXT2_IOC_GETFLAGS,
+#endif
+	    &oldflags) < 0)
 		goto fail;
 
 	/* Try setting the flags as given. */
 	newflags = (oldflags & ~clear) | set;
-	if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+	if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+	    FS_IOC_SETFLAGS,
+#else
+	    EXT2_IOC_SETFLAGS,
+#endif
+	    &newflags) >= 0)
 		goto cleanup;
 	if (errno != EPERM)
 		goto fail;
@@ -3349,7 +3674,13 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
 	newflags &= ~sf_mask;
 	oldflags &= sf_mask;
 	newflags |= oldflags;
-	if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+	if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+	    FS_IOC_SETFLAGS,
+#else
+	    EXT2_IOC_SETFLAGS,
+#endif
+	    &newflags) >= 0)
 		goto cleanup;
 
 	/* We couldn't set the flags, so report the failure. */
@@ -3487,6 +3818,9 @@ exit_xattr:
 static int
 copy_acls(struct archive_write_disk *a, int tmpfd, int dffd)
 {
+#ifndef HAVE_SYS_ACL_H
+	return 0;
+#else
 	acl_t acl, dfacl = NULL;
 	int acl_r, ret = ARCHIVE_OK;
 
@@ -3514,6 +3848,7 @@ exit_acl:
 	if (dfacl)
 		acl_free(dfacl);
 	return (ret);
+#endif
 }
 
 static int
@@ -3753,7 +4088,8 @@ set_xattrs(struct archive_write_disk *a)
 				if (errno == ENOTSUP || errno == ENOSYS) {
 					if (!warning_done) {
 						warning_done = 1;
-						archive_set_error(&a->archive, errno,
+						archive_set_error(&a->archive,
+						    errno,
 						    "Cannot restore extended "
 						    "attributes on this file "
 						    "system");
@@ -3764,7 +4100,8 @@ set_xattrs(struct archive_write_disk *a)
 				ret = ARCHIVE_WARN;
 			}
 		} else {
-			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+			archive_set_error(&a->archive,
+			    ARCHIVE_ERRNO_FILE_FORMAT,
 			    "Invalid extended attribute encountered");
 			ret = ARCHIVE_WARN;
 		}
@@ -3808,19 +4145,22 @@ set_xattrs(struct archive_write_disk *a)
 			errno = 0;
 #if HAVE_EXTATTR_SET_FD
 			if (a->fd >= 0)
-				e = extattr_set_fd(a->fd, namespace, name, value, size);
+				e = extattr_set_fd(a->fd, namespace, name,
+				    value, size);
 			else
 #endif
 			/* TODO: should we use extattr_set_link() instead? */
 			{
-				e = extattr_set_file(archive_entry_pathname(entry),
-				    namespace, name, value, size);
+				e = extattr_set_file(
+				    archive_entry_pathname(entry), namespace,
+				    name, value, size);
 			}
 			if (e != (int)size) {
 				if (errno == ENOTSUP || errno == ENOSYS) {
 					if (!warning_done) {
 						warning_done = 1;
-						archive_set_error(&a->archive, errno,
+						archive_set_error(&a->archive,
+						    errno,
 						    "Cannot restore extended "
 						    "attributes on this file "
 						    "system");
@@ -3866,10 +4206,10 @@ older(struct stat *st, struct archive_entry *entry)
 {
 	/* First, test the seconds and return if we have a definite answer. */
 	/* Definitely older. */
-	if (st->st_mtime < archive_entry_mtime(entry))
+	if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry)))
 		return (1);
 	/* Definitely younger. */
-	if (st->st_mtime > archive_entry_mtime(entry))
+	if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry)))
 		return (0);
 	/* If this platform supports fractional seconds, try those. */
 #if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c
index 3b868fb..5c766d7 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c
@@ -84,15 +84,13 @@ static void	cleanup(void *);
 int
 archive_write_disk_set_standard_lookup(struct archive *a)
 {
-	struct bucket *ucache = malloc(cache_size * sizeof(struct bucket));
-	struct bucket *gcache = malloc(cache_size * sizeof(struct bucket));
+	struct bucket *ucache = calloc(cache_size, sizeof(struct bucket));
+	struct bucket *gcache = calloc(cache_size, sizeof(struct bucket));
 	if (ucache == NULL || gcache == NULL) {
 		free(ucache);
 		free(gcache);
 		return (ARCHIVE_FATAL);
 	}
-	memset(ucache, 0, cache_size * sizeof(struct bucket));
-	memset(gcache, 0, cache_size * sizeof(struct bucket));
 	archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup);
 	archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup);
 	return (ARCHIVE_OK);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
index da76c54..94b016e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
@@ -192,7 +192,7 @@ struct archive_write_disk {
 
 /*
  * Default mode for dirs created automatically (will be modified by umask).
- * Note that POSIX specifies 0777 for implicity-created dirs, "modified
+ * Note that POSIX specifies 0777 for implicitly-created dirs, "modified
  * by the process' file creation mask."
  */
 #define	DEFAULT_DIR_MODE 0777
@@ -396,7 +396,7 @@ permissive_name_w(struct archive_write_disk *a)
 	}
 
 	/*
-	 * A full-pathname pointig a network drive
+	 * A full-pathname pointing to a network drive
 	 * like "\\<server-name>\<share-name>\file". 
 	 */
 	if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
@@ -1221,10 +1221,9 @@ archive_write_disk_new(void)
 {
 	struct archive_write_disk *a;
 
-	a = (struct archive_write_disk *)malloc(sizeof(*a));
+	a = (struct archive_write_disk *)calloc(1, sizeof(*a));
 	if (a == NULL)
 		return (NULL);
-	memset(a, 0, sizeof(*a));
 	a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
 	/* We're ready to write a header immediately. */
 	a->archive.state = ARCHIVE_STATE_HEADER;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open.3 b/Utilities/cmlibarchive/libarchive/archive_write_open.3
index a52959b..457873e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open.3
@@ -66,6 +66,7 @@ Freeze the settings, open the archive, and prepare for writing entries.
 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_open_fd
 A convenience form of
 .Fn archive_write_open
@@ -123,12 +124,21 @@ is currently in use.
 You should be careful to ensure that this variable
 remains allocated until after the archive is
 closed.
+This function will disable padding unless you
+have specifically set the block size.
 .El
 More information about the
 .Va struct archive
 object and the overall design of the library can be found in the
 .Xr libarchive 3
 overview.
+.Pp
+Note that the convenience forms above vary in how
+they block the output.
+See
+.Xr archive_write_blocksize 3
+if you need to control the block size used for writes
+or the end-of-file padding behavior.
 .\"
 .Sh CLIENT CALLBACKS
 To use this library, you will need to define and register
@@ -226,6 +236,7 @@ functions.
 .Xr tar 1 ,
 .Xr libarchive 3 ,
 .Xr archive_write 3 ,
+.Xr archive_write_blocksize 3 ,
 .Xr archive_write_filter 3 ,
 .Xr archive_write_format 3 ,
 .Xr archive_write_new 3 ,
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c b/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c
index 4f8d679..ea6ae0a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c
@@ -53,12 +53,11 @@ archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t
 {
 	struct write_memory_data *mine;
 
-	mine = (struct write_memory_data *)malloc(sizeof(*mine));
+	mine = (struct write_memory_data *)calloc(1, sizeof(*mine));
 	if (mine == NULL) {
 		archive_set_error(a, ENOMEM, "No memory");
 		return (ARCHIVE_FATAL);
 	}
-	memset(mine, 0, sizeof(*mine));
 	mine->buff = buff;
 	mine->size = buffSize;
 	mine->client_size = used;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
index 8718d25..3fc5a07 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
@@ -205,7 +205,7 @@ struct _7zip {
 	/*
 	 * The list of the file entries which has its contents is used to
 	 * manage struct file objects.
-	 * We use 'next' a menber of struct file to chain.
+	 * We use 'next' (a member of struct file) to chain.
 	 */
 	struct {
 		struct file	*first;
@@ -1358,7 +1358,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
 	if (r < 0)
 		return (r);
 
-	/* Write Nume size. */
+	/* Write Name size. */
 	r = enc_uint64(a, zip->total_bytes_entry_name+1);
 	if (r < 0)
 		return (r);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
index 9f17564..c9771d8 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
@@ -126,12 +126,11 @@ archive_write_set_format_ar(struct archive_write *a)
 	if (a->format_free != NULL)
 		(a->format_free)(a);
 
-	ar = (struct ar_w *)malloc(sizeof(*ar));
+	ar = (struct ar_w *)calloc(1, sizeof(*ar));
 	if (ar == NULL) {
 		archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data");
 		return (ARCHIVE_FATAL);
 	}
-	memset(ar, 0, sizeof(*ar));
 	a->format_data = ar;
 
 	a->format_name = "ar";
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
index 3526493..a4c9d1e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
@@ -289,7 +289,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
 	sconv = get_sconv(a);
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pahtname, hardlink and symlink
+	/* Make sure the path separators in pathname, hardlink and symlink
 	 * are all slash '/', not the Windows path separator '\'. */
 	entry_main = __la_win_entry_in_posix_pathseparator(entry);
 	if (entry_main == NULL) {
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 a9bfa80..957f1a3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
@@ -116,12 +116,11 @@ archive_write_set_format_cpio_newc(struct archive *_a)
 	if (a->format_free != NULL)
 		(a->format_free)(a);
 
-	cpio = (struct cpio *)malloc(sizeof(*cpio));
+	cpio = (struct cpio *)calloc(1, sizeof(*cpio));
 	if (cpio == NULL) {
 		archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
 		return (ARCHIVE_FATAL);
 	}
-	memset(cpio, 0, sizeof(*cpio));
 	a->format_data = cpio;
 	a->format_name = "cpio";
 	a->format_options = archive_write_newc_options;
@@ -232,7 +231,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
 	sconv = get_sconv(a);
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pahtname, hardlink and symlink
+	/* Make sure the path separators in pathname, hardlink and symlink
 	 * are all slash '/', not the Windows path separator '\'. */
 	entry_main = __la_win_entry_in_posix_pathseparator(entry);
 	if (entry_main == NULL) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
index 1d635d2..2d858c9 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
@@ -119,9 +119,9 @@ static const char template_header[] = {
 	'0','0','0','0','0','0', '0','\0',
 	/* gid, null termination: 8 bytes */
 	'0','0','0','0','0','0', '0','\0',
-	/* size, space termation: 12 bytes */
+	/* size, space termination: 12 bytes */
 	'0','0','0','0','0','0','0','0','0','0','0', '\0',
-	/* mtime, space termation: 12 bytes */
+	/* mtime, space termination: 12 bytes */
 	'0','0','0','0','0','0','0','0','0','0','0', '\0',
 	/* Initial checksum value: 8 spaces */
 	' ',' ',' ',' ',' ',' ',' ',' ',
@@ -368,7 +368,7 @@ archive_write_gnutar_header(struct archive_write *a,
 	}
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pahtname, hardlink and symlink
+	/* Make sure the path separators in pathname, hardlink and symlink
 	 * are all slash '/', not the Windows path separator '\'. */
 	entry_main = __la_win_entry_in_posix_pathseparator(entry);
 	if (entry_main == NULL) {
@@ -478,15 +478,15 @@ archive_write_gnutar_header(struct archive_write *a,
 		archive_entry_set_pathname(temp, "././@LongLink");
 		archive_entry_set_size(temp, length);
 		ret = archive_format_gnutar_header(a, buff, temp, 'K');
+		archive_entry_free(temp);
 		if (ret < ARCHIVE_WARN)
 			goto exit_write_header;
 		ret = __archive_write_output(a, buff, 512);
-		if(ret < ARCHIVE_WARN)
+		if (ret < ARCHIVE_WARN)
 			goto exit_write_header;
-		archive_entry_free(temp);
 		/* Write name and trailing null byte. */
 		ret = __archive_write_output(a, gnutar->linkname, length);
-		if(ret < ARCHIVE_WARN)
+		if (ret < ARCHIVE_WARN)
 			goto exit_write_header;
 		/* Pad to 512 bytes */
 		ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length));
@@ -508,12 +508,12 @@ archive_write_gnutar_header(struct archive_write *a,
 		archive_entry_set_pathname(temp, "././@LongLink");
 		archive_entry_set_size(temp, length);
 		ret = archive_format_gnutar_header(a, buff, temp, 'L');
+		archive_entry_free(temp);
 		if (ret < ARCHIVE_WARN)
 			goto exit_write_header;
 		ret = __archive_write_output(a, buff, 512);
 		if(ret < ARCHIVE_WARN)
 			goto exit_write_header;
-		archive_entry_free(temp);
 		/* Write pathname + trailing null byte. */
 		ret = __archive_write_output(a, pathname, length);
 		if(ret < ARCHIVE_WARN)
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
index 879a776..4adf68e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
@@ -161,7 +161,7 @@ struct isofile {
 	/* Used for managing struct isofile list. */
 	struct isofile		*allnext;
 	struct isofile		*datanext;
-	/* Used for managing a hardlined struct isofile list. */
+	/* Used for managing a hardlinked struct isofile list. */
 	struct isofile		*hlnext;
 	struct isofile		*hardlink_target;
 
@@ -436,7 +436,7 @@ struct iso_option {
 	 * Type   : string
 	 * Default: Auto detect
 	 *        : We check a size of boot image;
-	 *        : If ths size is just 1.22M/1.44M/2.88M,
+	 *        : If the size is just 1.22M/1.44M/2.88M,
 	 *        : we assume boot_type is 'fd';
 	 *        : otherwise boot_type is 'no-emulation'.
 	 * COMPAT :
@@ -528,7 +528,7 @@ struct iso_option {
 	 *   - allow more then 8 depths of directory trees;
 	 *   - disable a version number to a File Name;
 	 *   - disable a forced period to the tail of a File Name;
-	 *   - the maxinum length of files and directories is raised to 193.
+	 *   - the maximum length of files and directories is raised to 193.
 	 *     if rockridge option is disabled, raised to 207.
 	 */
 	unsigned int	 iso_level:3;
@@ -626,7 +626,7 @@ struct iso_option {
 	 *        :    NOTE  Our rockridge=useful option does not set a zero
 	 *        :          to uid and gid, you should use application
 	 *        :          option such as --gid,--gname,--uid and --uname
-	 *        :          badtar options instead.
+	 *        :          bsdtar options instead.
 	 * Type   : boolean/string
 	 * Default: Enabled as rockridge=useful
 	 * COMPAT : mkisofs -r / -R
@@ -660,7 +660,7 @@ struct iso_option {
 	 *        :    for making zisofs.
 	 *        :    When the file size is less than one Logical Block
 	 *        :    size, that file will not zisofs'ed since it does
-	 *        :    reduece an ISO-image size.
+	 *        :    reduce an ISO-image size.
 	 *        :
 	 *        :    When you specify option 'boot=<boot-image>', that
 	 *        :    'boot-image' file won't be converted to zisofs file.
@@ -680,7 +680,7 @@ struct iso9660 {
 	/* The creation time of ISO image. */
 	time_t			 birth_time;
 	/* A file stream of a temporary file, which file contents
-	 * save to until ISO iamge can be created. */
+	 * save to until ISO image can be created. */
 	int			 temp_fd;
 
 	struct isofile		*cur_file;
@@ -703,7 +703,7 @@ struct iso9660 {
 	}			 all_file_list;
 
 	/* A list of struct isofile entries which have its
-	 * contents and are not a directory, a hardlined file
+	 * contents and are not a directory, a hardlinked file
 	 * and a symlink file. */
 	struct {
 		struct isofile	*first;
@@ -1907,9 +1907,9 @@ iso9660_close(struct archive_write *a)
 		    iso9660->primary.rootent);
 		if (ret < 0)
 			return (ret);
-		/* Make sure we have UTF-16BE convertors.
-		 * if there is no file entry, convertors are still
-		 * uninitilized. */
+		/* Make sure we have UTF-16BE converters.
+		 * if there is no file entry, converters are still
+		 * uninitialized. */
 		if (iso9660->sconv_to_utf16be == NULL) {
 			iso9660->sconv_to_utf16be =
 			    archive_string_conversion_to_charset(
@@ -1995,7 +1995,7 @@ iso9660_close(struct archive_write *a)
 	 * Write an ISO 9660 image.
 	 */
 
-	/* Switc to start using wbuff as file buffer. */
+	/* Switch to start using wbuff as file buffer. */
 	iso9660->wbuff_remaining = wb_buffmax();
 	iso9660->wbuff_type = WB_TO_STREAM;
 	iso9660->wbuff_offset = 0;
@@ -2524,7 +2524,8 @@ get_tmfromtime(struct tm *tm, time_t *t)
 	tzset();
 	localtime_r(t, tm);
 #elif HAVE__LOCALTIME64_S
-	_localtime64_s(tm, t);
+	__time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits
+	_localtime64_s(tm, &tmp_t);
 #else
 	memcpy(tm, localtime(t), sizeof(*tm));
 #endif
@@ -2553,7 +2554,7 @@ set_date_time(unsigned char *p, time_t t)
 static void
 set_date_time_null(unsigned char *p)
 {
-	memset(p, '0', 16);
+	memset(p, (int)'0', 16);
 	p[16] = 0;
 }
 
@@ -2959,7 +2960,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
 			gid = archive_entry_gid(file->entry);
 			if (iso9660->opt.rr == OPT_RR_USEFUL) {
 				/*
-				 * This action is simular mkisofs -r option
+				 * This action is similar to mkisofs -r option
 				 * but our rockridge=useful option does not
 				 * set a zero to uid and gid.
 				 */
@@ -3024,8 +3025,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
 		 *    +----+----+----+----+----+
 		 *   10   11   12   13   14   15
 		 *
-	 	 *    - cflg : flag of componet
-		 *    - clen : length of componet
+		 *    - cflg : flag of component
+		 *    - clen : length of component
 		 */
 		const char *sl;
 		char sl_last;
@@ -3108,7 +3109,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
 					/*
 					 *     flg  len
 					 *    +----+----+
-					 *    | 02 | 00 | CURREENT component.
+					 *    | 02 | 00 | CURRENT component.
 					 *    +----+----+ (".")
 					 */
 					if (nc != NULL) {
@@ -3947,7 +3948,7 @@ write_VD(struct archive_write *a, struct vdd *vdd)
 	    "Abstract File", 0, D_CHAR);
 	if (r != ARCHIVE_OK)
 		return (r);
-	/* Bibliongraphic File Identifier */
+	/* Bibliographic File Identifier */
 	r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
 	    &(iso9660->bibliographic_file_identifier),
 	    "Bibliongraphic File", 0, D_CHAR);
@@ -4073,7 +4074,10 @@ write_information_block(struct archive_write *a)
 	memset(info.s, 0, info_size);
 	opt = 0;
 #if defined(HAVE__CTIME64_S)
-	_ctime64_s(buf, sizeof(buf), &(iso9660->birth_time));
+	{
+		__time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
+		_ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
+	}
 #elif defined(HAVE_CTIME_R)
 	ctime_r(&(iso9660->birth_time), buf);
 #else
@@ -4558,7 +4562,7 @@ write_file_descriptors(struct archive_write *a)
 		file->cur_content = &(file->content);
 		do {
 			blocks += file->cur_content->blocks;
-			/* Next fragument */
+			/* Next fragment */
 			file->cur_content = file->cur_content->next;
 		} while (file->cur_content != NULL);
 	}
@@ -4748,7 +4752,7 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
 		}
 
 		/*
-		 * Converte a filename to UTF-16BE.
+		 * Convert a filename to UTF-16BE.
 		 */
 		if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
 		    iso9660->sconv_to_utf16be)) {
@@ -5512,7 +5516,7 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location)
 			file->cur_content->location = location;
 			location += file->cur_content->blocks;
 			total_block += file->cur_content->blocks;
-			/* Next fragument */
+			/* Next fragment */
 			file->cur_content = file->cur_content->next;
 		} while (file->cur_content != NULL);
 	}
@@ -6135,7 +6139,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
 					off = ffmax - extlen;
 					if (off == 0) {
 						/* A dot('.')  character
-						 * does't place to the first
+						 * doesn't place to the first
 						 * byte of identifier. */
 						off ++;
 						extlen --;
@@ -6164,7 +6168,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
 		np->id_len = l = ext_off + np->ext_len;
 
 		/* Make an offset of the number which is used to be set
-		 * hexadecimal number to avoid duplicate identififier. */
+		 * hexadecimal number to avoid duplicate identifier. */
 		if (iso9660->opt.iso_level == 1) {
 			if (ext_off >= 5)
 				noff = 5;
@@ -6742,7 +6746,7 @@ isoent_rr_move(struct archive_write *a)
 	int r;
 
 	pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
-	/* Theare aren't level 8 directories reaching a deepr level. */
+	/* There aren't level 8 directories reaching a deeper level. */
 	if (pt->cnt == 0)
 		return (ARCHIVE_OK);
 
@@ -6813,7 +6817,7 @@ _compare_path_table(const void *v1, const void *v2)
 	if (cmp != 0)
 		return (cmp);
 
-	/* Compare indetifier */
+	/* Compare identifier */
 	s1 = p1->identifier;
 	s2 = p2->identifier;
 	l = p1->ext_off;
@@ -6855,7 +6859,7 @@ _compare_path_table_joliet(const void *v1, const void *v2)
 	if (cmp != 0)
 		return (cmp);
 
-	/* Compare indetifier */
+	/* Compare identifier */
 	s1 = (const unsigned char *)p1->identifier;
 	s2 = (const unsigned char *)p2->identifier;
 	l = p1->ext_off;
@@ -7149,7 +7153,7 @@ isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
 
 	iso9660->el_torito.catalog = isoent;
 	/*
-	 * Get a boot medai type.
+	 * Get a boot media type.
 	 */
 	switch (iso9660->opt.boot_type) {
 	default:
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
index b686303..493d473 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
@@ -1840,9 +1840,9 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
 	len = strlen(p);
 
 	/*
-	 * Add "./" prefiex.
+	 * Add "./" prefix.
 	 * NOTE: If the pathname does not have a path separator, we have
-	 * to add "./" to the head of the pathename because mtree reader
+	 * to add "./" to the head of the pathname because mtree reader
 	 * will suppose that it is v1(a.k.a classic) mtree format and
 	 * change the directory unexpectedly and so it will make a wrong
 	 * path.
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
index 6f7fe78..6a301ac 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2003-2007 Tim Kientzle
  * Copyright (c) 2010-2012 Michihiro NAKAJIMA
+ * Copyright (c) 2016 Martin Matuska
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -61,15 +62,24 @@ struct pax {
 	struct sparse_block	*sparse_tail;
 	struct archive_string_conv *sconv_utf8;
 	int			 opt_binary;
+
+	unsigned flags;
+#define WRITE_SCHILY_XATTR       (1 << 0)
+#define WRITE_LIBARCHIVE_XATTR   (1 << 1)
 };
 
 static void		 add_pax_attr(struct archive_string *, const char *key,
 			     const char *value);
+static void		 add_pax_attr_binary(struct archive_string *,
+			     const char *key,
+			     const char *value, size_t value_len);
 static void		 add_pax_attr_int(struct archive_string *,
 			     const char *key, int64_t value);
 static void		 add_pax_attr_time(struct archive_string *,
 			     const char *key, int64_t sec,
 			     unsigned long nanos);
+static int		 add_pax_acl(struct archive_write *,
+			    struct archive_entry *, struct pax *, int);
 static ssize_t		 archive_write_pax_data(struct archive_write *,
 			     const void *, size_t);
 static int		 archive_write_pax_close(struct archive_write *);
@@ -127,13 +137,14 @@ archive_write_set_format_pax(struct archive *_a)
 	if (a->format_free != NULL)
 		(a->format_free)(a);
 
-	pax = (struct pax *)malloc(sizeof(*pax));
+	pax = (struct pax *)calloc(1, sizeof(*pax));
 	if (pax == NULL) {
 		archive_set_error(&a->archive, ENOMEM,
 		    "Can't allocate pax data");
 		return (ARCHIVE_FATAL);
 	}
-	memset(pax, 0, sizeof(*pax));
+	pax->flags = WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR;
+
 	a->format_data = pax;
 	a->format_name = "pax";
 	a->format_options = archive_write_pax_options;
@@ -273,6 +284,17 @@ add_pax_attr_int(struct archive_string *as, const char *key, int64_t value)
 static void
 add_pax_attr(struct archive_string *as, const char *key, const char *value)
 {
+	add_pax_attr_binary(as, key, value, strlen(value));
+}
+
+/*
+ * Add a key/value attribute to the pax header.  This function handles
+ * binary values.
+ */
+static void
+add_pax_attr_binary(struct archive_string *as, const char *key,
+		    const char *value, size_t value_len)
+{
 	int digits, i, len, next_ten;
 	char tmp[1 + 3 * sizeof(int)];	/* < 3 base-10 digits per byte */
 
@@ -280,7 +302,7 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value)
 	 * PAX attributes have the following layout:
 	 *     <len> <space> <key> <=> <value> <nl>
 	 */
-	len = 1 + (int)strlen(key) + 1 + (int)strlen(value) + 1;
+	len = 1 + (int)strlen(key) + 1 + (int)value_len + 1;
 
 	/*
 	 * The <len> field includes the length of the <len> field, so
@@ -311,21 +333,47 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value)
 	archive_strappend_char(as, ' ');
 	archive_strcat(as, key);
 	archive_strappend_char(as, '=');
-	archive_strcat(as, value);
+	archive_array_append(as, value, value_len);
 	archive_strappend_char(as, '\n');
 }
 
+static void
+archive_write_pax_header_xattr(struct pax *pax, const char *encoded_name,
+    const void *value, size_t value_len)
+{
+	struct archive_string s;
+	char *encoded_value;
+
+	if (pax->flags & WRITE_LIBARCHIVE_XATTR) {
+		encoded_value = base64_encode((const char *)value, value_len);
+
+		if (encoded_name != NULL && encoded_value != NULL) {
+			archive_string_init(&s);
+			archive_strcpy(&s, "LIBARCHIVE.xattr.");
+			archive_strcat(&s, encoded_name);
+			add_pax_attr(&(pax->pax_header), s.s, encoded_value);
+			archive_string_free(&s);
+		}
+		free(encoded_value);
+	}
+	if (pax->flags & WRITE_SCHILY_XATTR) {
+		archive_string_init(&s);
+		archive_strcpy(&s, "SCHILY.xattr.");
+		archive_strcat(&s, encoded_name);
+		add_pax_attr_binary(&(pax->pax_header), s.s, value, value_len);
+		archive_string_free(&s);
+	}
+}
+
 static int
 archive_write_pax_header_xattrs(struct archive_write *a,
     struct pax *pax, struct archive_entry *entry)
 {
-	struct archive_string s;
 	int i = archive_entry_xattr_reset(entry);
 
 	while (i--) {
 		const char *name;
 		const void *value;
-		char *encoded_value;
 		char *url_encoded_name = NULL, *encoded_name = NULL;
 		size_t size;
 		int r;
@@ -346,16 +394,9 @@ archive_write_pax_header_xattrs(struct archive_write *a,
 			}
 		}
 
-		encoded_value = base64_encode((const char *)value, size);
+		archive_write_pax_header_xattr(pax, encoded_name,
+		    value, size);
 
-		if (encoded_name != NULL && encoded_value != NULL) {
-			archive_string_init(&s);
-			archive_strcpy(&s, "LIBARCHIVE.xattr.");
-			archive_strcat(&s, encoded_name);
-			add_pax_attr(&(pax->pax_header), s.s, encoded_value);
-			archive_string_free(&s);
-		}
-		free(encoded_value);
 	}
 	return (ARCHIVE_OK);
 }
@@ -450,6 +491,45 @@ get_entry_symlink(struct archive_write *a, struct archive_entry *entry,
 	return (ARCHIVE_OK);
 }
 
+/* Add ACL to pax header */
+static int
+add_pax_acl(struct archive_write *a,
+    struct archive_entry *entry, struct pax *pax, int flags)
+{
+	char *p;
+	const char *attr;
+	int acl_types;
+
+	acl_types = archive_entry_acl_types(entry);
+
+	if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
+		attr = "SCHILY.acl.ace";
+	else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
+		attr = "SCHILY.acl.access";
+	else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
+		attr = "SCHILY.acl.default";
+	else
+		return (ARCHIVE_FATAL);
+
+	p = archive_entry_acl_to_text_l(entry, NULL, flags, pax->sconv_utf8);
+	if (p == NULL) {
+		if (errno == ENOMEM) {
+			archive_set_error(&a->archive, ENOMEM, "%s %s",
+			    "Can't allocate memory for ", attr);
+			return (ARCHIVE_FATAL);
+		}
+		archive_set_error(&a->archive,
+		    ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s",
+		    "Can't translate ", attr, " to UTF-8");
+		return(ARCHIVE_WARN);
+	} else if (*p != '\0') {
+		add_pax_attr(&(pax->pax_header),
+		    attr, p);
+		free(p);
+	}
+	return(ARCHIVE_OK);
+}
+
 /*
  * TODO: Consider adding 'comment' and 'charset' fields to
  * archive_entry so that clients can specify them.  Also, consider
@@ -466,6 +546,7 @@ archive_write_pax_header(struct archive_write *a,
 	const char *p;
 	const char *suffix;
 	int need_extension, r, ret;
+	int acl_types;
 	int sparse_count;
 	uint64_t sparse_total, real_size;
 	struct pax *pax;
@@ -709,7 +790,7 @@ archive_write_pax_header(struct archive_write *a,
 
 	/* Copy entry so we can modify it as needed. */
 #if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pahtname, hardlink and symlink
+	/* Make sure the path separators in pathname, hardlink and symlink
 	 * are all slash '/', not the Windows path separator '\'. */
 	entry_main = __la_win_entry_in_posix_pathseparator(entry_original);
 	if (entry_main == entry_original)
@@ -1017,16 +1098,6 @@ archive_write_pax_header(struct archive_write *a,
 	if (!need_extension && p != NULL  &&  *p != '\0')
 		need_extension = 1;
 
-	/* If there are non-trivial ACL entries, we need an extension. */
-	if (!need_extension && archive_entry_acl_count(entry_original,
-		ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0)
-		need_extension = 1;
-
-	/* If there are non-trivial ACL entries, we need an extension. */
-	if (!need_extension && archive_entry_acl_count(entry_original,
-		ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) > 0)
-		need_extension = 1;
-
 	/* If there are extended attributes, we need an extension */
 	if (!need_extension && archive_entry_xattr_count(entry_original) > 0)
 		need_extension = 1;
@@ -1035,6 +1106,12 @@ archive_write_pax_header(struct archive_write *a,
 	if (!need_extension && sparse_count > 0)
 		need_extension = 1;
 
+	acl_types = archive_entry_acl_types(entry_original);
+
+	/* If there are any ACL entries, we need an extension */
+	if (!need_extension && acl_types != 0)
+		need_extension = 1;
+
 	/*
 	 * Libarchive used to include these in extended headers for
 	 * restricted pax format, but that confused people who
@@ -1086,43 +1163,29 @@ archive_write_pax_header(struct archive_write *a,
 			add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p);
 
 		/* I use star-compatible ACL attributes. */
-		r = archive_entry_acl_text_l(entry_original,
-		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
-		    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
-		    &p, NULL, pax->sconv_utf8);
-		if (r != 0) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for "
-				    "ACL.access");
+		if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
+			ret = add_pax_acl(a, entry_original, pax,
+			    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
+			    ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA |
+			    ARCHIVE_ENTRY_ACL_STYLE_COMPACT);
+			if (ret == ARCHIVE_FATAL)
 				return (ARCHIVE_FATAL);
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Can't translate ACL.access to UTF-8");
-			ret = ARCHIVE_WARN;
-		} else if (p != NULL && *p != '\0') {
-			add_pax_attr(&(pax->pax_header),
-			    "SCHILY.acl.access", p);
 		}
-		r = archive_entry_acl_text_l(entry_original,
-		    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
-		    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
-		    &p, NULL, pax->sconv_utf8);
-		if (r != 0) {
-			if (errno == ENOMEM) {
-				archive_set_error(&a->archive, ENOMEM,
-				    "Can't allocate memory for "
-				    "ACL.default");
+		if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
+			ret = add_pax_acl(a, entry_original, pax,
+			    ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
+			    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
+			    ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
+			if (ret == ARCHIVE_FATAL)
+				return (ARCHIVE_FATAL);
+		}
+		if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) {
+			ret = add_pax_acl(a, entry_original, pax,
+			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
+			    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
+			    ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
+			if (ret == ARCHIVE_FATAL)
 				return (ARCHIVE_FATAL);
-			}
-			archive_set_error(&a->archive,
-			    ARCHIVE_ERRNO_FILE_FORMAT,
-			    "Can't translate ACL.default to UTF-8");
-			ret = ARCHIVE_WARN;
-		} else if (p != NULL && *p != '\0') {
-			add_pax_attr(&(pax->pax_header),
-			    "SCHILY.acl.default", p);
 		}
 
 		/* We use GNU-tar-compatible sparse attributes. */
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c
index c033fb3..5be310a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_shar.c
@@ -113,12 +113,11 @@ archive_write_set_format_shar(struct archive *_a)
 	if (a->format_free != NULL)
 		(a->format_free)(a);
 
-	shar = (struct shar *)malloc(sizeof(*shar));
+	shar = (struct shar *)calloc(1, sizeof(*shar));
 	if (shar == NULL) {
 		archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data");
 		return (ARCHIVE_FATAL);
 	}
-	memset(shar, 0, sizeof(*shar));
 	archive_string_init(&shar->work);
 	archive_string_init(&shar->quoted_name);
 	a->format_data = shar;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c
index 484ab34..c54aeab 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c
@@ -114,9 +114,9 @@ static const char template_header[] = {
 	'0','0','0','0','0','0', ' ','\0',
 	/* gid, space-null termination: 8 bytes */
 	'0','0','0','0','0','0', ' ','\0',
-	/* size, space termation: 12 bytes */
+	/* size, space termination: 12 bytes */
 	'0','0','0','0','0','0','0','0','0','0','0', ' ',
-	/* mtime, space termation: 12 bytes */
+	/* mtime, space termination: 12 bytes */
 	'0','0','0','0','0','0','0','0','0','0','0', ' ',
 	/* Initial checksum value: 8 spaces */
 	' ',' ',' ',' ',' ',' ',' ',' ',
@@ -184,13 +184,12 @@ archive_write_set_format_ustar(struct archive *_a)
 		return (ARCHIVE_FATAL);
 	}
 
-	ustar = (struct ustar *)malloc(sizeof(*ustar));
+	ustar = (struct ustar *)calloc(1, sizeof(*ustar));
 	if (ustar == NULL) {
 		archive_set_error(&a->archive, ENOMEM,
 		    "Can't allocate ustar data");
 		return (ARCHIVE_FATAL);
 	}
-	memset(ustar, 0, sizeof(*ustar));
 	a->format_data = ustar;
 	a->format_name = "ustar";
 	a->format_options = archive_write_ustar_options;
@@ -307,7 +306,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
 		 * case getting WCS failed. On POSIX, this is a
 		 * normal operation.
 		 */
-		if (p != NULL && p[strlen(p) - 1] != '/') {
+		if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
 			struct archive_string as;
 
 			archive_string_init(&as);
@@ -336,7 +335,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
 	}
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pahtname, hardlink and symlink
+	/* Make sure the path separators in pathname, hardlink and symlink
 	 * are all slash '/', not the Windows path separator '\'. */
 	entry_main = __la_win_entry_in_posix_pathseparator(entry);
 	if (entry_main == NULL) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c
index 17efbaf..62b1522 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c
@@ -98,9 +98,9 @@ static const char template_header[] = {
 	'0','0','0','0','0','0', ' ','\0',
 	/* gid, space-null termination: 8 bytes */
 	'0','0','0','0','0','0', ' ','\0',
-	/* size, space termation: 12 bytes */
+	/* size, space termination: 12 bytes */
 	'0','0','0','0','0','0','0','0','0','0','0', ' ',
-	/* mtime, space termation: 12 bytes */
+	/* mtime, space termination: 12 bytes */
 	'0','0','0','0','0','0','0','0','0','0','0', ' ',
 	/* Initial checksum value: 8 spaces */
 	' ',' ',' ',' ',' ',' ',' ',' ',
@@ -161,13 +161,12 @@ archive_write_set_format_v7tar(struct archive *_a)
 		return (ARCHIVE_FATAL);
 	}
 
-	v7tar = (struct v7tar *)malloc(sizeof(*v7tar));
+	v7tar = (struct v7tar *)calloc(1, sizeof(*v7tar));
 	if (v7tar == NULL) {
 		archive_set_error(&a->archive, ENOMEM,
 		    "Can't allocate v7tar data");
 		return (ARCHIVE_FATAL);
 	}
-	memset(v7tar, 0, sizeof(*v7tar));
 	a->format_data = v7tar;
 	a->format_name = "tar (non-POSIX)";
 	a->format_options = archive_write_v7tar_options;
@@ -314,7 +313,7 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry)
 	}
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pahtname, hardlink and symlink
+	/* Make sure the path separators in pathname, hardlink and symlink
 	 * are all slash '/', not the Windows path separator '\'. */
 	entry_main = __la_win_entry_in_posix_pathseparator(entry);
 	if (entry_main == NULL) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c
index ea66929..8b6daf9 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c
@@ -79,7 +79,7 @@ typedef enum {
 	WT_RVIS,
 	/* conversion, unsupported */
 	WT_CONV,
-	/* continutation, unsupported at the moment */
+	/* continuation, unsupported at the moment */
 	WT_CONT,
 	/* invalid type */
 	LAST_WT
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
index 58ad9e0..3c617ec 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
@@ -63,7 +63,7 @@ __FBSDID("$FreeBSD$");
  * - When writing an XML element <link type="<file-type>">, <file-type>
  *   which is a file type a symbolic link is referencing is always marked
  *   as "broken". Xar utility uses stat(2) to get the file type, but, in
- *   libarcive format writer, we should not use it; if it is needed, we
+ *   libarchive format writer, we should not use it; if it is needed, we
  *   should get about it at archive_read_disk.c.
  * - It is possible to appear both <flags> and <ext2> elements.
  *   Xar utility generates <flags> on BSD platform and <ext2> on Linux
@@ -192,7 +192,7 @@ struct file {
 	struct file		*parent;	/* parent directory entry */
 	/*
 	 * To manage sub directory files.
-	 * We use 'chnext' a menber of struct file to chain.
+	 * We use 'chnext' (a member of struct file) to chain.
 	 */
 	struct {
 		struct file	*first;
@@ -258,7 +258,7 @@ struct xar {
 	/*
 	 * The list of all file entries is used to manage struct file
 	 * objects.
-	 * We use 'next' a menber of struct file to chain.
+	 * We use 'next' (a member of struct file) to chain.
 	 */
 	struct {
 		struct file	*first;
@@ -266,7 +266,7 @@ struct xar {
 	}			 file_list;
 	/*
 	 * The list of hard-linked file entries.
-	 * We use 'hlnext' a menber of struct file to chain.
+	 * We use 'hlnext' (a member of struct file) to chain.
 	 */
 	struct archive_rb_tree	 hardlink_rbtree;
 };
@@ -1227,7 +1227,7 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 	case AE_IFLNK:
 		/*
 		 * xar utility has checked a file type, which
-		 * a symblic-link file has referenced.
+		 * a symbolic-link file has referenced.
 		 * For example:
 		 *   <link type="directory">../ref/</link>
 		 *   The symlink target file is "../ref/" and its
@@ -1237,8 +1237,8 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		 *   The symlink target file is "../f" and its
 		 *   file type is a regular file.
 		 *
-		 * But our implemention cannot do it, and then we
-		 * always record that a attribute "type" is "borken",
+		 * But our implementation cannot do it, and then we
+		 * always record that a attribute "type" is "broken",
 		 * for example:
 		 *   <link type="broken">foo/bar</link>
 		 *   It means "foo/bar" is not reachable.
@@ -1544,7 +1544,7 @@ make_toc(struct archive_write *a)
 	}
 
 	/*
-	 * Start recoding TOC
+	 * Start recording TOC
 	 */
 	r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
 	if (r < 0) {
@@ -1961,6 +1961,7 @@ file_free(struct file *file)
 	archive_string_free(&(file->basename));
 	archive_string_free(&(file->symlink));
 	archive_string_free(&(file->script));
+	archive_entry_free(file->entry);
 	free(file);
 }
 
@@ -2484,7 +2485,7 @@ file_connect_hardlink_files(struct xar *xar)
 		archive_entry_set_nlink(target->entry, hl->nlink);
 		if (hl->nlink > 1)
 			/* It means this file is a hardlink
-			 * targe itself. */
+			 * target itself. */
 			target->hardlink_target = target;
 		for (nf = target->hlnext;
 		    nf != NULL; nf = nf->hlnext) {
@@ -2913,7 +2914,7 @@ compression_init_encoder_xz(struct archive *a,
 	*strm = lzma_init_data;
 #ifdef HAVE_LZMA_STREAM_ENCODER_MT
 	if (threads > 1) {
-		bzero(&mt_options, sizeof(mt_options));
+		memset(&mt_options, 0, sizeof(mt_options));
 		mt_options.threads = threads;
 		mt_options.timeout = 300;
 		mt_options.filters = lzmafilters;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
index 0b2c69b..a4ae229 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
@@ -592,7 +592,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
 
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
-	/* Make sure the path separators in pahtname, hardlink and symlink
+	/* Make sure the path separators in pathname, hardlink and symlink
 	 * are all slash '/', not the Windows path separator '\'. */
 	zip->entry = __la_win_entry_in_posix_pathseparator(entry);
 	if (zip->entry == entry)
@@ -878,7 +878,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
 	        || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) {
 
 		memcpy(e, "\001\231\007\000\001\000AE", 8);
-		/* AES vendoer version AE-2 does not store a CRC.
+		/* AES vendor version AE-2 does not store a CRC.
 		 * WinZip 11 uses AE-1, which does store the CRC,
 		 * but it does not store the CRC when the file size
 		 * is less than 20 bytes. So we simulate what
@@ -1013,7 +1013,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
 	if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) {
 		switch (zip->entry_encryption) {
 		case ENCRYPTION_TRADITIONAL:
-			/* Initialize traditoinal PKWARE encryption context. */
+			/* Initialize traditional PKWARE encryption context. */
 			if (!zip->tctx_valid) {
 				ret = init_traditional_pkware_encryption(a);
 				if (ret != ARCHIVE_OK)
@@ -1499,7 +1499,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
 }
 
 static uint8_t
-trad_enc_decypt_byte(struct trad_enc_ctx *ctx)
+trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
 {
 	unsigned temp = ctx->keys[2] | 2;
 	return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
@@ -1515,7 +1515,7 @@ trad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
 
 	for (i = 0; i < max; i++) {
 		uint8_t t = in[i];
-		out[i] = t ^ trad_enc_decypt_byte(ctx);
+		out[i] = t ^ trad_enc_decrypt_byte(ctx);
 		trad_enc_update_keys(ctx, t);
 	}
 	return i;
@@ -1626,7 +1626,7 @@ init_winzip_aes_encryption(struct archive_write *a)
 		return (ARCHIVE_FAILED);
         }
 
-	/* Set a passowrd verification value after the 'salt'. */
+	/* Set a password verification value after the 'salt'. */
 	salt[salt_len] = derived_key[key_len * 2];
 	salt[salt_len + 1] = derived_key[key_len * 2 + 1];
 
diff --git a/Utilities/cmlibarchive/libarchive/config_freebsd.h b/Utilities/cmlibarchive/libarchive/config_freebsd.h
index 2073431..215e886 100644
--- a/Utilities/cmlibarchive/libarchive/config_freebsd.h
+++ b/Utilities/cmlibarchive/libarchive/config_freebsd.h
@@ -28,6 +28,7 @@
 /* FreeBSD 5.0 and later have ACL and extattr support. */
 #if __FreeBSD__ > 4
 #define	HAVE_ACL_CREATE_ENTRY 1
+#define	HAVE_ACL_GET_FD_NP 1
 #define	HAVE_ACL_GET_LINK_NP 1
 #define	HAVE_ACL_GET_PERM_NP 1
 #define	HAVE_ACL_INIT 1
@@ -39,6 +40,7 @@
 #define	HAVE_EXTATTR_LIST_FILE 1
 #define	HAVE_EXTATTR_SET_FD 1
 #define	HAVE_EXTATTR_SET_FILE 1
+#define	HAVE_STRUCT_XVFSCONF 1
 #define	HAVE_SYS_ACL_H 1
 #define	HAVE_SYS_EXTATTR_H 1
 #endif
diff --git a/Utilities/cmlibarchive/libarchive/libarchive-formats.5 b/Utilities/cmlibarchive/libarchive/libarchive-formats.5
index 9cec760..62359dd 100644
--- a/Utilities/cmlibarchive/libarchive/libarchive-formats.5
+++ b/Utilities/cmlibarchive/libarchive/libarchive-formats.5
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 18, 2012
+.Dd December 27, 2016
 .Dt LIBARCHIVE-FORMATS 5
 .Os
 .Sh NAME
@@ -191,8 +191,6 @@ and device numbers.
 .It Solaris extensions
 Libarchive recognizes ACL and extended attribute records written
 by Solaris tar.
-Currently, libarchive only has support for old-style ACLs; the
-newer NFSv4 ACLs are recognized but discarded.
 .El
 .Pp
 The first tar program appeared in Seventh Edition Unix in 1979.
diff --git a/Utilities/cmlibarchive/libarchive/tar.5 b/Utilities/cmlibarchive/libarchive/tar.5
index 6e6f0c0..30b837d 100644
--- a/Utilities/cmlibarchive/libarchive/tar.5
+++ b/Utilities/cmlibarchive/libarchive/tar.5
@@ -1,4 +1,5 @@
 .\" Copyright (c) 2003-2009 Tim Kientzle
+.\" Copyright (c) 2016 Martin Matuska
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 23, 2011
+.Dd December 27, 2016
 .Dt TAR 5
 .Os
 .Sh NAME
@@ -440,11 +441,11 @@ archives to store files much larger than the historic 8GB limit.
 Vendor-specific attributes used by Joerg Schilling's
 .Nm star
 implementation.
-.It Cm SCHILY.acl.access , Cm SCHILY.acl.default
-Stores the access and default ACLs as textual strings in a format
+.It Cm SCHILY.acl.access , Cm SCHILY.acl.default, Cm SCHILY.acl.ace
+Stores the access, default and NFSv4 ACLs as textual strings in a format
 that is an extension of the format specified by POSIX.1e draft 17.
-In particular, each user or group access specification can include a fourth
-colon-separated field with the numeric UID or GID.
+In particular, each user or group access specification can include
+an additional colon-separated field with the numeric UID or GID.
 This allows ACLs to be restored on systems that may not have complete
 user or group information available (such as when NIS/YP or LDAP services
 are temporarily unavailable).
diff --git a/Utilities/cmlibarchive/libarchive/xxhash.c b/Utilities/cmlibarchive/libarchive/xxhash.c
index 262fecb..6f5ba52 100644
--- a/Utilities/cmlibarchive/libarchive/xxhash.c
+++ b/Utilities/cmlibarchive/libarchive/xxhash.c
@@ -29,13 +29,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 You can contact the author at :
 - xxHash source repository : http://code.google.com/p/xxhash/
 */
-
 #include "archive_platform.h"
-#include "archive_xxhash.h"
 
 #include <stdlib.h>
 #include <string.h>
 
+#include "archive_xxhash.h"
+
 #ifdef HAVE_LIBLZ4
 
 /***************************************
@@ -61,7 +61,7 @@ You can contact the author at :
 ** By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
 ** Results are therefore identical for little-endian and big-endian CPU.
 ** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
-** Should endian-independance be of no importance for your application, you may set the #define below to 1.
+** Should endian-independence be of no importance for your application, you may set the #define below to 1.
 ** It will improve speed for Big-endian CPU.
 ** This option has no impact on Little_Endian CPU.
 */
diff --git a/Utilities/cmliblzma/CMakeLists.txt b/Utilities/cmliblzma/CMakeLists.txt
index e806680..bb3b8a7 100644
--- a/Utilities/cmliblzma/CMakeLists.txt
+++ b/Utilities/cmliblzma/CMakeLists.txt
@@ -15,11 +15,11 @@ CHECK_C_SOURCE_COMPILES(
   HAVE___RESTRICT)
 
 CHECK_C_SOURCE_COMPILES(
-  "inline int test (void) {return 0;}\nint main (void) {return test();}"
+  "static inline int test (void) {return 0;}\nint main (void) {return test();}"
   HAVE_INLINE)
 
 CHECK_C_SOURCE_COMPILES (
-  "__inline int test (void) {return 0;}\nint main (void) {return test();}"
+  "static __inline int test (void) {return 0;}\nint main (void) {return test();}"
   HAVE___INLINE)
 
 CHECK_INCLUDE_FILE(byteswap.h HAVE_BYTESWAP_H)
diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt
index a8e25ba..4c8e228 100644
--- a/Utilities/cmlibuv/CMakeLists.txt
+++ b/Utilities/cmlibuv/CMakeLists.txt
@@ -133,6 +133,27 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
     )
 endif()
 
+if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN")
+  list(APPEND uv_libraries
+    )
+  list(APPEND uv_headers
+    include/uv-posix.h
+    )
+  list(APPEND uv_defines
+    )
+  list(APPEND uv_sources
+    src/unix/cygwin.c
+    src/unix/bsd-ifaddrs.c
+    src/unix/no-fsevents.c
+    src/unix/no-proctitle.c
+    src/unix/posix-hrtime.c
+    src/unix/posix-poll.c
+    src/unix/procfs-exepath.c
+    src/unix/sysinfo-loadavg.c
+    src/unix/sysinfo-memory.c
+    )
+endif()
+
 if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
   list(APPEND uv_headers
     include/uv-darwin.h
@@ -143,6 +164,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
     _DARWIN_UNLIMITED_SELECT=1
     )
   list(APPEND uv_sources
+    src/unix/bsd-ifaddrs.c
     src/unix/darwin.c
     src/unix/darwin-proctitle.c
     src/unix/fsevents.c
@@ -163,7 +185,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
     src/unix/linux-inotify.c
     src/unix/linux-syscalls.c
     src/unix/linux-syscalls.h
+    src/unix/procfs-exepath.c
     src/unix/proctitle.c
+    src/unix/sysinfo-loadavg.c
+    src/unix/sysinfo-memory.c
     )
 endif()
 
@@ -175,8 +200,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
     include/uv-bsd.h
     )
   list(APPEND uv_sources
+    src/unix/bsd-ifaddrs.c
     src/unix/freebsd.c
     src/unix/kqueue.c
+    src/unix/posix-hrtime.c
     )
 endif()
 
@@ -188,8 +215,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
     include/uv-bsd.h
     )
   list(APPEND uv_sources
+    src/unix/bsd-ifaddrs.c
     src/unix/netbsd.c
     src/unix/kqueue.c
+    src/unix/posix-hrtime.c
     )
 endif()
 
@@ -201,8 +230,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
     include/uv-bsd.h
     )
   list(APPEND uv_sources
+    src/unix/bsd-ifaddrs.c
     src/unix/openbsd.c
     src/unix/kqueue.c
+    src/unix/posix-hrtime.c
     )
 endif()
 
@@ -212,6 +243,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
     nsl
     sendfile
     socket
+    rt
     )
   list(APPEND uv_headers
     include/uv-sunos.h
@@ -220,15 +252,28 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
     __EXTENSIONS__
     )
   if(CMAKE_SYSTEM_VERSION STREQUAL "5.10")
+    set(CMAKE_C_STANDARD 90)
+    if(CMAKE_VERSION VERSION_LESS 3.8.20170504 AND CMAKE_C_COMPILER_ID STREQUAL "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.14)
+      # The running version of CMake does not know how to add this flag.
+      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c90")
+    endif()
     list(APPEND uv_defines
       _XOPEN_SOURCE=500
       )
   else()
+    if(NOT CMAKE_C_STANDARD OR CMAKE_C_STANDARD EQUAL 90)
+      set(CMAKE_C_STANDARD 11)
+    endif()
+    if(CMAKE_VERSION VERSION_LESS 3.8.20170505 AND CMAKE_C_COMPILER_ID STREQUAL "SunPro" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5.14)
+      # The running version of CMake does not know how to add this flag.
+      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -xc99")
+    endif()
     list(APPEND uv_defines
       _XOPEN_SOURCE=600
       )
   endif()
   list(APPEND uv_sources
+    src/unix/no-proctitle.c
     src/unix/sunos.c
     )
 endif()
diff --git a/Utilities/cmlibuv/include/pthread-barrier.h b/Utilities/cmlibuv/include/pthread-barrier.h
index 3e01705..900ebed 100644
--- a/Utilities/cmlibuv/include/pthread-barrier.h
+++ b/Utilities/cmlibuv/include/pthread-barrier.h
@@ -18,7 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define _UV_PTHREAD_BARRIER_
 #include <errno.h>
 #include <pthread.h>
+#if !defined(__MVS__)
 #include <semaphore.h> /* sem_t */
+#endif
 
 #define PTHREAD_BARRIER_SERIAL_THREAD  0x12345
 
diff --git a/Utilities/cmlibuv/include/uv-os390.h b/Utilities/cmlibuv/include/uv-os390.h
index b0b068f..58f9261 100644
--- a/Utilities/cmlibuv/include/uv-os390.h
+++ b/Utilities/cmlibuv/include/uv-os390.h
@@ -24,4 +24,7 @@
 
 #define UV_PLATFORM_SEM_T int
 
+#define UV_PLATFORM_LOOP_FIELDS                                               \
+  void* ep;                                                                   \
+
 #endif /* UV_MVS_H */
diff --git a/Utilities/cmlibuv/include/uv-posix.h b/Utilities/cmlibuv/include/uv-posix.h
new file mode 100644
index 0000000..9a96634
--- /dev/null
+++ b/Utilities/cmlibuv/include/uv-posix.h
@@ -0,0 +1,31 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef UV_POSIX_H
+#define UV_POSIX_H
+
+#define UV_PLATFORM_LOOP_FIELDS                                               \
+  struct pollfd* poll_fds;                                                    \
+  size_t poll_fds_used;                                                       \
+  size_t poll_fds_size;                                                       \
+  unsigned char poll_fds_iterating;                                           \
+
+#endif /* UV_POSIX_H */
diff --git a/Utilities/cmlibuv/include/uv-unix.h b/Utilities/cmlibuv/include/uv-unix.h
index bca2714..d775450 100644
--- a/Utilities/cmlibuv/include/uv-unix.h
+++ b/Utilities/cmlibuv/include/uv-unix.h
@@ -36,7 +36,9 @@
 #include <termios.h>
 #include <pwd.h>
 
+#if !defined(__MVS__)
 #include <semaphore.h>
+#endif
 #include <pthread.h>
 #include <signal.h>
 
@@ -44,6 +46,8 @@
 
 #if defined(__linux__)
 # include "uv-linux.h"
+#elif defined (__MVS__)
+# include "uv-os390.h"
 #elif defined(_AIX)
 # include "uv-aix.h"
 #elif defined(__sun)
@@ -56,6 +60,8 @@
       defined(__OpenBSD__)         || \
       defined(__NetBSD__)
 # include "uv-bsd.h"
+#elif defined(__CYGWIN__) || defined(__MSYS__)
+# include "uv-posix.h"
 #endif
 
 #ifndef PTHREAD_BARRIER_SERIAL_THREAD
@@ -75,7 +81,6 @@
 #endif
 
 struct uv__io_s;
-struct uv__async;
 struct uv_loop_s;
 
 typedef void (*uv__io_cb)(struct uv_loop_s* loop,
@@ -93,16 +98,6 @@ struct uv__io_s {
   UV_IO_PRIVATE_PLATFORM_FIELDS
 };
 
-typedef void (*uv__async_cb)(struct uv_loop_s* loop,
-                             struct uv__async* w,
-                             unsigned int nevents);
-
-struct uv__async {
-  uv__async_cb cb;
-  uv__io_t io_watcher;
-  int wfd;
-};
-
 #ifndef UV_PLATFORM_SEM_T
 # define UV_PLATFORM_SEM_T sem_t
 #endif
@@ -212,7 +207,9 @@ typedef struct {
   void* check_handles[2];                                                     \
   void* idle_handles[2];                                                      \
   void* async_handles[2];                                                     \
-  struct uv__async async_watcher;                                             \
+  void (*async_unused)(void);  /* TODO(bnoordhuis) Remove in libuv v2. */     \
+  uv__io_t async_io_watcher;                                                  \
+  int async_wfd;                                                              \
   struct {                                                                    \
     void* min;                                                                \
     unsigned int nelts;                                                       \
diff --git a/Utilities/cmlibuv/include/uv-version.h b/Utilities/cmlibuv/include/uv-version.h
index 3cb9b5f..e165809 100644
--- a/Utilities/cmlibuv/include/uv-version.h
+++ b/Utilities/cmlibuv/include/uv-version.h
@@ -31,8 +31,8 @@
  */
 
 #define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 9
-#define UV_VERSION_PATCH 2
+#define UV_VERSION_MINOR 11
+#define UV_VERSION_PATCH 1
 #define UV_VERSION_IS_RELEASE 0
 #define UV_VERSION_SUFFIX "dev"
 
diff --git a/Utilities/cmlibuv/include/uv-win.h b/Utilities/cmlibuv/include/uv-win.h
index 89ee09a..d3e32a5 100644
--- a/Utilities/cmlibuv/include/uv-win.h
+++ b/Utilities/cmlibuv/include/uv-win.h
@@ -49,6 +49,7 @@ typedef struct pollfd {
 
 #include <process.h>
 #include <signal.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 
 #if defined(_MSC_VER) && _MSC_VER < 1600
diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h
index e3e20dc..38f5676 100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@ -278,6 +278,7 @@ UV_EXTERN void uv_loop_delete(uv_loop_t*);
 UV_EXTERN size_t uv_loop_size(void);
 UV_EXTERN int uv_loop_alive(const uv_loop_t* loop);
 UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...);
+UV_EXTERN int uv_loop_fork(uv_loop_t* loop);
 
 UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);
 UV_EXTERN void uv_stop(uv_loop_t*);
@@ -367,6 +368,8 @@ typedef enum {
 } uv_membership;
 
 
+UV_EXTERN int uv_translate_sys_error(int sys_errno);
+
 UV_EXTERN const char* uv_strerror(int err);
 UV_EXTERN const char* uv_err_name(int err);
 
@@ -1075,6 +1078,12 @@ UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
 UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
                                            int count);
 
+UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
+UV_EXTERN int uv_os_setenv(const char* name, const char* value);
+UV_EXTERN int uv_os_unsetenv(const char* name);
+
+UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
+
 
 typedef enum {
   UV_FS_UNKNOWN = -1,
@@ -1326,6 +1335,9 @@ UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle);
 UV_EXTERN int uv_signal_start(uv_signal_t* handle,
                               uv_signal_cb signal_cb,
                               int signum);
+UV_EXTERN int uv_signal_start_oneshot(uv_signal_t* handle,
+                                      uv_signal_cb signal_cb,
+                                      int signum);
 UV_EXTERN int uv_signal_stop(uv_signal_t* handle);
 
 UV_EXTERN void uv_loadavg(double avg[3]);
diff --git a/Utilities/cmlibuv/src/threadpool.c b/Utilities/cmlibuv/src/threadpool.c
index 2c5152b..1089341 100644
--- a/Utilities/cmlibuv/src/threadpool.c
+++ b/Utilities/cmlibuv/src/threadpool.c
@@ -23,18 +23,6 @@
 
 #if !defined(_WIN32)
 # include "unix/internal.h"
-#else
-# include "win/req-inl.h"
-/* TODO(saghul): unify internal req functions */
-static void uv__req_init(uv_loop_t* loop,
-                         uv_req_t* req,
-                         uv_req_type type) {
-  uv_req_init(loop, req);
-  req->type = type;
-  uv__req_register(loop, req);
-}
-# define uv__req_init(loop, req, type) \
-    uv__req_init((loop), (uv_req_t*)(req), (type))
 #endif
 
 #include <stdlib.h>
@@ -139,7 +127,7 @@ UV_DESTRUCTOR(static void cleanup(void)) {
 #endif
 
 
-static void init_once(void) {
+static void init_threads(void) {
   unsigned int i;
   const char* val;
 
@@ -177,6 +165,27 @@ static void init_once(void) {
 }
 
 
+#ifndef _WIN32
+static void reset_once(void) {
+  uv_once_t child_once = UV_ONCE_INIT;
+  memcpy(&once, &child_once, sizeof(child_once));
+}
+#endif
+
+
+static void init_once(void) {
+#ifndef _WIN32
+  /* Re-initialize the threadpool after fork.
+   * Note that this discards the global mutex and condition as well
+   * as the work queue.
+   */
+  if (pthread_atfork(NULL, NULL, &reset_once))
+    abort();
+#endif
+  init_threads();
+}
+
+
 void uv__work_submit(uv_loop_t* loop,
                      struct uv__work* w,
                      void (*work)(struct uv__work* w),
diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c
index 652cd98..388c9cc 100644
--- a/Utilities/cmlibuv/src/unix/aix.c
+++ b/Utilities/cmlibuv/src/unix/aix.c
@@ -64,6 +64,11 @@
 #define RDWR_BUF_SIZE   4096
 #define EQ(a,b)         (strcmp(a,b) == 0)
 
+static void* args_mem = NULL;
+static char** process_argv = NULL;
+static int process_argc = 0;
+static char* process_title_ptr = NULL;
+
 int uv__platform_loop_init(uv_loop_t* loop) {
   loop->fs_fd = -1;
 
@@ -91,6 +96,13 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
 }
 
 
+int uv__io_fork(uv_loop_t* loop) {
+  uv__platform_loop_delete(loop);
+
+  return uv__platform_loop_init(loop);
+}
+
+
 int uv__io_check_fd(uv_loop_t* loop, int fd) {
   struct poll_ctl pc;
 
@@ -753,6 +765,13 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int
 
   assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file");
 
+  /* In file / directory move cases, AIX Event infrastructure
+   * produces a second event with no data.
+   * Ignore it and return gracefully.
+   */
+  if(bytes == 0)
+    return;
+
   /* Parse the data */
   if(bytes > 0)
     rc = uv__parse_data(result_data, &events, handle);
@@ -881,24 +900,94 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
 
 
 char** uv_setup_args(int argc, char** argv) {
-  return argv;
+  char** new_argv;
+  size_t size;
+  char* s;
+  int i;
+
+  if (argc <= 0)
+    return argv;
+
+  /* Save the original pointer to argv.
+   * AIX uses argv to read the process name.
+   * (Not the memory pointed to by argv[0..n] as on Linux.)
+   */
+  process_argv = argv;
+  process_argc = argc;
+
+  /* Calculate how much memory we need for the argv strings. */
+  size = 0;
+  for (i = 0; i < argc; i++)
+    size += strlen(argv[i]) + 1;
+
+  /* Add space for the argv pointers. */
+  size += (argc + 1) * sizeof(char*);
+
+  new_argv = uv__malloc(size);
+  if (new_argv == NULL)
+    return argv;
+  args_mem = new_argv;
+
+  /* Copy over the strings and set up the pointer table. */
+  s = (char*) &new_argv[argc + 1];
+  for (i = 0; i < argc; i++) {
+    size = strlen(argv[i]) + 1;
+    memcpy(s, argv[i], size);
+    new_argv[i] = s;
+    s += size;
+  }
+  new_argv[i] = NULL;
+
+  return new_argv;
 }
 
 
 int uv_set_process_title(const char* title) {
+  char* new_title;
+
+  /* We cannot free this pointer when libuv shuts down,
+   * the process may still be using it.
+   */
+  new_title = uv__strdup(title);
+  if (new_title == NULL)
+    return -ENOMEM;
+
+  /* If this is the first time this is set,
+   * don't free and set argv[1] to NULL.
+   */
+  if (process_title_ptr != NULL)
+    uv__free(process_title_ptr);
+
+  process_title_ptr = new_title;
+
+  process_argv[0] = process_title_ptr;
+  if (process_argc > 1)
+     process_argv[1] = NULL;
+
   return 0;
 }
 
 
 int uv_get_process_title(char* buffer, size_t size) {
+  size_t len;
+  len = strlen(process_argv[0]);
   if (buffer == NULL || size == 0)
     return -EINVAL;
+  else if (size <= len)
+    return -ENOBUFS;
+
+  memcpy(buffer, process_argv[0], len + 1);
 
-  buffer[0] = '\0';
   return 0;
 }
 
 
+UV_DESTRUCTOR(static void free_args_mem(void)) {
+  uv__free(args_mem);  /* Keep valgrind happy. */
+  args_mem = NULL;
+}
+
+
 int uv_resident_set_memory(size_t* rss) {
   char pp[64];
   psinfo_t psinfo;
diff --git a/Utilities/cmlibuv/src/unix/async.c b/Utilities/cmlibuv/src/unix/async.c
index 393cdeb..45c088e 100644
--- a/Utilities/cmlibuv/src/unix/async.c
+++ b/Utilities/cmlibuv/src/unix/async.c
@@ -33,16 +33,15 @@
 #include <string.h>
 #include <unistd.h>
 
-static void uv__async_event(uv_loop_t* loop,
-                            struct uv__async* w,
-                            unsigned int nevents);
+static void uv__async_send(uv_loop_t* loop);
+static int uv__async_start(uv_loop_t* loop);
 static int uv__async_eventfd(void);
 
 
 int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
   int err;
 
-  err = uv__async_start(loop, &loop->async_watcher, uv__async_event);
+  err = uv__async_start(loop);
   if (err)
     return err;
 
@@ -63,7 +62,7 @@ int uv_async_send(uv_async_t* handle) {
     return 0;
 
   if (cmpxchgi(&handle->pending, 0, 1) == 0)
-    uv__async_send(&handle->loop->async_watcher);
+    uv__async_send(handle->loop);
 
   return 0;
 }
@@ -75,44 +74,18 @@ void uv__async_close(uv_async_t* handle) {
 }
 
 
-static void uv__async_event(uv_loop_t* loop,
-                            struct uv__async* w,
-                            unsigned int nevents) {
+static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+  char buf[1024];
+  ssize_t r;
   QUEUE queue;
   QUEUE* q;
   uv_async_t* h;
 
-  QUEUE_MOVE(&loop->async_handles, &queue);
-  while (!QUEUE_EMPTY(&queue)) {
-    q = QUEUE_HEAD(&queue);
-    h = QUEUE_DATA(q, uv_async_t, queue);
-
-    QUEUE_REMOVE(q);
-    QUEUE_INSERT_TAIL(&loop->async_handles, q);
-
-    if (cmpxchgi(&h->pending, 1, 0) == 0)
-      continue;
-
-    if (h->async_cb == NULL)
-      continue;
-    h->async_cb(h);
-  }
-}
-
+  assert(w == &loop->async_io_watcher);
 
-static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
-  struct uv__async* wa;
-  char buf[1024];
-  unsigned n;
-  ssize_t r;
-
-  n = 0;
   for (;;) {
     r = read(w->fd, buf, sizeof(buf));
 
-    if (r > 0)
-      n += r;
-
     if (r == sizeof(buf))
       continue;
 
@@ -128,23 +101,26 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
     abort();
   }
 
-  wa = container_of(w, struct uv__async, io_watcher);
+  QUEUE_MOVE(&loop->async_handles, &queue);
+  while (!QUEUE_EMPTY(&queue)) {
+    q = QUEUE_HEAD(&queue);
+    h = QUEUE_DATA(q, uv_async_t, queue);
+
+    QUEUE_REMOVE(q);
+    QUEUE_INSERT_TAIL(&loop->async_handles, q);
 
-#if defined(__linux__)
-  if (wa->wfd == -1) {
-    uint64_t val;
-    assert(n == sizeof(val));
-    memcpy(&val, buf, sizeof(val));  /* Avoid alignment issues. */
-    wa->cb(loop, wa, val);
-    return;
-  }
-#endif
+    if (cmpxchgi(&h->pending, 1, 0) == 0)
+      continue;
+
+    if (h->async_cb == NULL)
+      continue;
 
-  wa->cb(loop, wa, n);
+    h->async_cb(h);
+  }
 }
 
 
-void uv__async_send(struct uv__async* wa) {
+static void uv__async_send(uv_loop_t* loop) {
   const void* buf;
   ssize_t len;
   int fd;
@@ -152,14 +128,14 @@ void uv__async_send(struct uv__async* wa) {
 
   buf = "";
   len = 1;
-  fd = wa->wfd;
+  fd = loop->async_wfd;
 
 #if defined(__linux__)
   if (fd == -1) {
     static const uint64_t val = 1;
     buf = &val;
     len = sizeof(val);
-    fd = wa->io_watcher.fd;  /* eventfd */
+    fd = loop->async_io_watcher.fd;  /* eventfd */
   }
 #endif
 
@@ -178,17 +154,11 @@ void uv__async_send(struct uv__async* wa) {
 }
 
 
-void uv__async_init(struct uv__async* wa) {
-  wa->io_watcher.fd = -1;
-  wa->wfd = -1;
-}
-
-
-int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) {
+static int uv__async_start(uv_loop_t* loop) {
   int pipefd[2];
   int err;
 
-  if (wa->io_watcher.fd != -1)
+  if (loop->async_io_watcher.fd != -1)
     return 0;
 
   err = uv__async_eventfd();
@@ -222,32 +192,41 @@ int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) {
   if (err < 0)
     return err;
 
-  uv__io_init(&wa->io_watcher, uv__async_io, pipefd[0]);
-  uv__io_start(loop, &wa->io_watcher, POLLIN);
-  wa->wfd = pipefd[1];
-  wa->cb = cb;
+  uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]);
+  uv__io_start(loop, &loop->async_io_watcher, POLLIN);
+  loop->async_wfd = pipefd[1];
 
   return 0;
 }
 
 
-void uv__async_stop(uv_loop_t* loop, struct uv__async* wa) {
-  if (wa->io_watcher.fd == -1)
+int uv__async_fork(uv_loop_t* loop) {
+  if (loop->async_io_watcher.fd == -1) /* never started */
+    return 0;
+
+  uv__async_stop(loop);
+
+  return uv__async_start(loop);
+}
+
+
+void uv__async_stop(uv_loop_t* loop) {
+  if (loop->async_io_watcher.fd == -1)
     return;
 
-  if (wa->wfd != -1) {
-    if (wa->wfd != wa->io_watcher.fd)
-      uv__close(wa->wfd);
-    wa->wfd = -1;
+  if (loop->async_wfd != -1) {
+    if (loop->async_wfd != loop->async_io_watcher.fd)
+      uv__close(loop->async_wfd);
+    loop->async_wfd = -1;
   }
 
-  uv__io_stop(loop, &wa->io_watcher, POLLIN);
-  uv__close(wa->io_watcher.fd);
-  wa->io_watcher.fd = -1;
+  uv__io_stop(loop, &loop->async_io_watcher, POLLIN);
+  uv__close(loop->async_io_watcher.fd);
+  loop->async_io_watcher.fd = -1;
 }
 
 
-static int uv__async_eventfd() {
+static int uv__async_eventfd(void) {
 #if defined(__linux__)
   static int no_eventfd2;
   static int no_eventfd;
diff --git a/Utilities/cmlibuv/src/unix/atomic-ops.h b/Utilities/cmlibuv/src/unix/atomic-ops.h
index 815e355..9dac255 100644
--- a/Utilities/cmlibuv/src/unix/atomic-ops.h
+++ b/Utilities/cmlibuv/src/unix/atomic-ops.h
@@ -43,8 +43,12 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
   __compare_and_swap(ptr, &oldval, newval);
   return out;
 #elif defined(__MVS__)
-  return __plo_CS(ptr, (unsigned int*) ptr,
-                  oldval, (unsigned int*) &newval);
+  unsigned int op4;
+  if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
+                (unsigned int*) ptr, *ptr, &op4))
+    return oldval;
+  else
+    return op4;
 #else
   return __sync_val_compare_and_swap(ptr, oldval, newval);
 #endif
@@ -67,13 +71,18 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
 # endif /* if defined(__64BIT__) */
   return out;
 #elif defined (__MVS__)
-# ifdef _LP64
-  return __plo_CSGR(ptr, (unsigned long long*) ptr,
-                    oldval, (unsigned long long*) &newval);
-# else
-  return __plo_CS(ptr, (unsigned int*) ptr,
-                  oldval, (unsigned int*) &newval);
-# endif
+#ifdef _LP64
+  unsigned long long op4;
+  if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval,
+                  (unsigned long long*) ptr, *ptr, &op4))
+#else
+  unsigned long op4;
+  if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
+                (unsigned int*) ptr, *ptr, &op4))
+#endif
+    return oldval;
+  else
+    return op4;
 #else
   return __sync_val_compare_and_swap(ptr, oldval, newval);
 #endif
diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
new file mode 100644
index 0000000..4147894
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
@@ -0,0 +1,139 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <errno.h>
+#include <stddef.h>
+
+#include <ifaddrs.h>
+#include <net/if.h>
+#if !defined(__CYGWIN__) && !defined(__MSYS__)
+#include <net/if_dl.h>
+#endif
+
+static int uv__ifaddr_exclude(struct ifaddrs *ent) {
+  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
+    return 1;
+  if (ent->ifa_addr == NULL)
+    return 1;
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
+  /*
+   * On BSD getifaddrs returns information related to the raw underlying
+   * devices.  We're not interested in this information.
+   */
+  if (ent->ifa_addr->sa_family == AF_LINK)
+    return 1;
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+  if (ent->ifa_addr->sa_family != PF_INET)
+    return 1;
+#endif
+  return 0;
+}
+
+int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
+  struct ifaddrs* addrs;
+  struct ifaddrs* ent;
+  uv_interface_address_t* address;
+  int i;
+
+  if (getifaddrs(&addrs) != 0)
+    return -errno;
+
+  *count = 0;
+
+  /* Count the number of interfaces */
+  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
+    if (uv__ifaddr_exclude(ent))
+      continue;
+    (*count)++;
+  }
+
+  *addresses = uv__malloc(*count * sizeof(**addresses));
+
+  if (*addresses == NULL) {
+    freeifaddrs(addrs);
+    return -ENOMEM;
+  }
+
+  address = *addresses;
+
+  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
+    if (uv__ifaddr_exclude(ent))
+      continue;
+
+    address->name = uv__strdup(ent->ifa_name);
+
+    if (ent->ifa_addr->sa_family == AF_INET6) {
+      address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
+    } else {
+      address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
+    }
+
+    if (ent->ifa_netmask->sa_family == AF_INET6) {
+      address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
+    } else {
+      address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
+    }
+
+    address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
+
+    address++;
+  }
+
+  /* Fill in physical addresses for each interface */
+  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
+    if (uv__ifaddr_exclude(ent))
+      continue;
+
+    address = *addresses;
+
+    for (i = 0; i < *count; i++) {
+      if (strcmp(address->name, ent->ifa_name) == 0) {
+#if defined(__CYGWIN__) || defined(__MSYS__)
+        memset(address->phys_addr, 0, sizeof(address->phys_addr));
+#else
+        struct sockaddr_dl* sa_addr;
+        sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
+        memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
+#endif
+      }
+      address++;
+    }
+  }
+
+  freeifaddrs(addrs);
+
+  return 0;
+}
+
+
+void uv_free_interface_addresses(uv_interface_address_t* addresses,
+                                 int count) {
+  int i;
+
+  for (i = 0; i < count; i++) {
+    uv__free(addresses[i].name);
+  }
+
+  uv__free(addresses);
+}
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index d88fc1d..30cdaef 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <assert.h>
 #include <unistd.h>
+#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -42,6 +43,7 @@
 #include <pwd.h>
 
 #ifdef __sun
+# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
 # include <sys/filio.h>
 # include <sys/types.h>
 # include <sys/wait.h>
@@ -80,6 +82,11 @@
 #include <sys/ioctl.h>
 #endif
 
+/* Fallback for the maximum hostname length */
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 256
+#endif
+
 static int uv__run_pending(uv_loop_t* loop);
 
 /* Verify that uv_buf_t is ABI-compatible with struct iovec. */
@@ -98,7 +105,7 @@ uint64_t uv_hrtime(void) {
 
 
 void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
-  assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+  assert(!uv__is_closing(handle));
 
   handle->flags |= UV_CLOSING;
   handle->close_cb = close_cb;
@@ -517,6 +524,9 @@ int uv__close_nocheckstdio(int fd) {
 
 int uv__close(int fd) {
   assert(fd > STDERR_FILENO);  /* Catch stdio close bugs. */
+#if defined(__MVS__)
+  epoll_file_close(fd);
+#endif
   return uv__close_nocheckstdio(fd);
 }
 
@@ -535,6 +545,7 @@ int uv__nonblock_ioctl(int fd, int set) {
 }
 
 
+#if !defined(__CYGWIN__) && !defined(__MSYS__)
 int uv__cloexec_ioctl(int fd, int set) {
   int r;
 
@@ -547,6 +558,7 @@ int uv__cloexec_ioctl(int fd, int set) {
 
   return 0;
 }
+#endif
 
 
 int uv__nonblock_fcntl(int fd, int set) {
@@ -836,13 +848,8 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
    * every tick of the event loop but the other backends allow us to
    * short-circuit here if the event mask is unchanged.
    */
-  if (w->events == w->pevents) {
-    if (w->events == 0 && !QUEUE_EMPTY(&w->watcher_queue)) {
-      QUEUE_REMOVE(&w->watcher_queue);
-      QUEUE_INIT(&w->watcher_queue);
-    }
+  if (w->events == w->pevents)
     return;
-  }
 #endif
 
   if (QUEUE_EMPTY(&w->watcher_queue))
@@ -1236,3 +1243,84 @@ void uv_os_free_passwd(uv_passwd_t* pwd) {
 int uv_os_get_passwd(uv_passwd_t* pwd) {
   return uv__getpwuid_r(pwd);
 }
+
+
+int uv_translate_sys_error(int sys_errno) {
+  /* If < 0 then it's already a libuv error. */
+  return sys_errno <= 0 ? sys_errno : -sys_errno;
+}
+
+
+int uv_os_getenv(const char* name, char* buffer, size_t* size) {
+  char* var;
+  size_t len;
+
+  if (name == NULL || buffer == NULL || size == NULL || *size == 0)
+    return -EINVAL;
+
+  var = getenv(name);
+
+  if (var == NULL)
+    return -ENOENT;
+
+  len = strlen(var);
+
+  if (len >= *size) {
+    *size = len + 1;
+    return -ENOBUFS;
+  }
+
+  memcpy(buffer, var, len + 1);
+  *size = len;
+
+  return 0;
+}
+
+
+int uv_os_setenv(const char* name, const char* value) {
+  if (name == NULL || value == NULL)
+    return -EINVAL;
+
+  if (setenv(name, value, 1) != 0)
+    return -errno;
+
+  return 0;
+}
+
+
+int uv_os_unsetenv(const char* name) {
+  if (unsetenv(name) != 0)
+    return -errno;
+
+  return 0;
+}
+
+
+int uv_os_gethostname(char* buffer, size_t* size) {
+  /*
+    On some platforms, if the input buffer is not large enough, gethostname()
+    succeeds, but truncates the result. libuv can detect this and return ENOBUFS
+    instead by creating a large enough buffer and comparing the hostname length
+    to the size input.
+  */
+  char buf[MAXHOSTNAMELEN + 1];
+  size_t len;
+
+  if (buffer == NULL || size == NULL || *size == 0)
+    return -EINVAL;
+
+  if (gethostname(buf, sizeof(buf)) != 0)
+    return -errno;
+
+  buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
+  len = strlen(buf);
+
+  if (len >= *size) {
+    *size = len + 1;
+    return -ENOBUFS;
+  }
+
+  memcpy(buffer, buf, len + 1);
+  *size = len;
+  return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/cygwin.c b/Utilities/cmlibuv/src/unix/cygwin.c
new file mode 100644
index 0000000..5a887dd
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/cygwin.c
@@ -0,0 +1,54 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <sys/sysinfo.h>
+#include <unistd.h>
+
+int uv_uptime(double* uptime) {
+  struct sysinfo info;
+
+  if (sysinfo(&info) < 0)
+    return -errno;
+
+  *uptime = info.uptime;
+  return 0;
+}
+
+int uv_resident_set_memory(size_t* rss) {
+  /* FIXME: read /proc/meminfo? */
+  *rss = 0;
+  return UV_ENOSYS;
+}
+
+int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
+  /* FIXME: read /proc/stat? */
+  *cpu_infos = NULL;
+  *count = 0;
+  return UV_ENOSYS;
+}
+
+void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
+  (void)cpu_infos;
+  (void)count;
+}
diff --git a/Utilities/cmlibuv/src/unix/darwin.c b/Utilities/cmlibuv/src/unix/darwin.c
index cf95da2..df6dd1c 100644
--- a/Utilities/cmlibuv/src/unix/darwin.c
+++ b/Utilities/cmlibuv/src/unix/darwin.c
@@ -25,10 +25,6 @@
 #include <stdint.h>
 #include <errno.h>
 
-#include <ifaddrs.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-
 #include <mach/mach.h>
 #include <mach/mach_time.h>
 #include <mach-o/dyld.h> /* _NSGetExecutablePath */
@@ -233,103 +229,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
 
   uv__free(cpu_infos);
 }
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
-  struct ifaddrs *addrs, *ent;
-  uv_interface_address_t* address;
-  int i;
-  struct sockaddr_dl *sa_addr;
-
-  if (getifaddrs(&addrs))
-    return -errno;
-
-  *count = 0;
-
-  /* Count the number of interfaces */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family == AF_LINK)) {
-      continue;
-    }
-
-    (*count)++;
-  }
-
-  *addresses = uv__malloc(*count * sizeof(**addresses));
-  if (!(*addresses)) {
-    freeifaddrs(addrs);
-    return -ENOMEM;
-  }
-
-  address = *addresses;
-
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
-      continue;
-
-    if (ent->ifa_addr == NULL)
-      continue;
-
-    /*
-     * On Mac OS X getifaddrs returns information related to Mac Addresses for
-     * various devices, such as firewire, etc. These are not relevant here.
-     */
-    if (ent->ifa_addr->sa_family == AF_LINK)
-      continue;
-
-    address->name = uv__strdup(ent->ifa_name);
-
-    if (ent->ifa_addr->sa_family == AF_INET6) {
-      address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
-    } else {
-      address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
-    }
-
-    if (ent->ifa_netmask->sa_family == AF_INET6) {
-      address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
-    } else {
-      address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
-    }
-
-    address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
-    address++;
-  }
-
-  /* Fill in physical addresses for each interface */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family != AF_LINK)) {
-      continue;
-    }
-
-    address = *addresses;
-
-    for (i = 0; i < (*count); i++) {
-      if (strcmp(address->name, ent->ifa_name) == 0) {
-        sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
-        memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
-      }
-      address++;
-    }
-  }
-
-  freeifaddrs(addrs);
-
-  return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
-  int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(addresses[i].name);
-  }
-
-  uv__free(addresses);
-}
diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c
index cba44a3..e52ae99 100644
--- a/Utilities/cmlibuv/src/unix/freebsd.c
+++ b/Utilities/cmlibuv/src/unix/freebsd.c
@@ -25,10 +25,6 @@
 #include <string.h>
 #include <errno.h>
 
-#include <ifaddrs.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-
 #include <kvm.h>
 #include <paths.h>
 #include <sys/user.h>
@@ -41,9 +37,6 @@
 #include <unistd.h> /* sysconf */
 #include <fcntl.h>
 
-#undef NANOSEC
-#define NANOSEC ((uint64_t) 1e9)
-
 #ifndef CPUSTATES
 # define CPUSTATES 5U
 #endif
@@ -67,13 +60,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
 }
 
 
-uint64_t uv__hrtime(uv_clocktype_t type) {
-  struct timespec ts;
-  clock_gettime(CLOCK_MONOTONIC, &ts);
-  return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
-}
-
-
 #ifdef __DragonFly__
 int uv_exepath(char* buffer, size_t* size) {
   char abspath[PATH_MAX * 2 + 1];
@@ -358,103 +344,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
 
   uv__free(cpu_infos);
 }
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
-  struct ifaddrs *addrs, *ent;
-  uv_interface_address_t* address;
-  int i;
-  struct sockaddr_dl *sa_addr;
-
-  if (getifaddrs(&addrs))
-    return -errno;
-
-   *count = 0;
-
-  /* Count the number of interfaces */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family == AF_LINK)) {
-      continue;
-    }
-
-    (*count)++;
-  }
-
-  *addresses = uv__malloc(*count * sizeof(**addresses));
-  if (!(*addresses)) {
-    freeifaddrs(addrs);
-    return -ENOMEM;
-  }
-
-  address = *addresses;
-
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
-      continue;
-
-    if (ent->ifa_addr == NULL)
-      continue;
-
-    /*
-     * On FreeBSD getifaddrs returns information related to the raw underlying
-     * devices. We're not interested in this information yet.
-     */
-    if (ent->ifa_addr->sa_family == AF_LINK)
-      continue;
-
-    address->name = uv__strdup(ent->ifa_name);
-
-    if (ent->ifa_addr->sa_family == AF_INET6) {
-      address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
-    } else {
-      address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
-    }
-
-    if (ent->ifa_netmask->sa_family == AF_INET6) {
-      address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
-    } else {
-      address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
-    }
-
-    address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
-    address++;
-  }
-
-  /* Fill in physical addresses for each interface */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family != AF_LINK)) {
-      continue;
-    }
-
-    address = *addresses;
-
-    for (i = 0; i < (*count); i++) {
-      if (strcmp(address->name, ent->ifa_name) == 0) {
-        sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
-        memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
-      }
-      address++;
-    }
-  }
-
-  freeifaddrs(addrs);
-
-  return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
-  int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(addresses[i].name);
-  }
-
-  uv__free(addresses);
-}
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 3d478b7..8a4ba7a 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -129,8 +129,23 @@
 static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
 #if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
   return fdatasync(req->file);
-#elif defined(__APPLE__) && defined(SYS_fdatasync)
-  return syscall(SYS_fdatasync, req->file);
+#elif defined(__APPLE__)
+  /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
+   * to the drive platters. This is in contrast to Linux's fdatasync and fsync
+   * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
+   * for flushing buffered data to permanent storage.
+   */
+  return fcntl(req->file, F_FULLFSYNC);
+#else
+  return fsync(req->file);
+#endif
+}
+
+
+static ssize_t uv__fs_fsync(uv_fs_t* req) {
+#if defined(__APPLE__)
+  /* See the comment in uv__fs_fdatasync. */
+  return fcntl(req->file, F_FULLFSYNC);
 #else
   return fsync(req->file);
 #endif
@@ -229,9 +244,19 @@ skip:
 #endif
 }
 
+#if defined(__sun) && _XOPEN_SOURCE < 600
+static char* uv__mkdtemp(char *template)
+{
+  if (!mktemp(template) || mkdir(template, 0700))
+    return NULL;
+  return template;
+}
+#else
+#define uv__mkdtemp mkdtemp
+#endif
 
 static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
-  return mkdtemp((char*) req->path) ? 0 : -1;
+  return uv__mkdtemp((char*) req->path) ? 0 : -1;
 }
 
 
@@ -365,7 +390,6 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
 
 static ssize_t uv__fs_scandir(uv_fs_t* req) {
   uv__dirent_t **dents;
-  int saved_errno;
   int n;
 
   dents = NULL;
@@ -374,28 +398,17 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) {
   /* NOTE: We will use nbufs as an index field */
   req->nbufs = 0;
 
-  if (n == 0)
-    goto out; /* osx still needs to deallocate some memory */
-  else if (n == -1)
-    return n;
-
-  req->ptr = dents;
-
-  return n;
-
-out:
-  saved_errno = errno;
-  if (dents != NULL) {
-    int i;
-
-    /* Memory was allocated using the system allocator, so use free() here. */
-    for (i = 0; i < n; i++)
-      free(dents[i]);
+  if (n == 0) {
+    /* OS X still needs to deallocate some memory.
+     * Memory was allocated using the system allocator, so use free() here.
+     */
     free(dents);
+    dents = NULL;
+  } else if (n == -1) {
+    return n;
   }
-  errno = saved_errno;
 
-  req->ptr = NULL;
+  req->ptr = dents;
 
   return n;
 }
@@ -798,6 +811,10 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
   dst->st_flags = 0;
   dst->st_gen = 0;
 #elif !defined(_AIX) && (       \
+    defined(__DragonFly__)   || \
+    defined(__FreeBSD__)     || \
+    defined(__OpenBSD__)     || \
+    defined(__NetBSD__)      || \
     defined(_GNU_SOURCE)     || \
     defined(_BSD_SOURCE)     || \
     defined(_SVID_SOURCE)    || \
@@ -809,9 +826,7 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
   dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
   dst->st_ctim.tv_sec = src->st_ctim.tv_sec;
   dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
-# if defined(__DragonFly__)  || \
-     defined(__FreeBSD__)    || \
-     defined(__OpenBSD__)    || \
+# if defined(__FreeBSD__)    || \
      defined(__NetBSD__)
   dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec;
   dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec;
@@ -945,7 +960,7 @@ static void uv__fs_work(struct uv__work* w) {
     X(FCHOWN, fchown(req->file, req->uid, req->gid));
     X(FDATASYNC, uv__fs_fdatasync(req));
     X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
-    X(FSYNC, fsync(req->file));
+    X(FSYNC, uv__fs_fsync(req));
     X(FTRUNCATE, ftruncate(req->file, req->off));
     X(FUTIME, uv__fs_futime(req));
     X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c
index d331a13..643e233 100644
--- a/Utilities/cmlibuv/src/unix/fsevents.c
+++ b/Utilities/cmlibuv/src/unix/fsevents.c
@@ -378,9 +378,6 @@ static void uv__fsevents_destroy_stream(uv_loop_t* loop) {
   if (state->fsevent_stream == NULL)
     return;
 
-  /* Flush all accumulated events */
-  pFSEventStreamFlushSync(state->fsevent_stream);
-
   /* Stop emitting events */
   pFSEventStreamStop(state->fsevent_stream);
 
diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h
index 2570026..2e3afa6 100644
--- a/Utilities/cmlibuv/src/unix/internal.h
+++ b/Utilities/cmlibuv/src/unix/internal.h
@@ -38,6 +38,10 @@
 # include "linux-syscalls.h"
 #endif /* __linux__ */
 
+#if defined(__MVS__)
+# include "os390-syscalls.h"
+#endif /* __MVS__ */
+
 #if defined(__sun)
 # include <sys/port.h>
 # include <port.h>
@@ -51,6 +55,10 @@
 # include <poll.h>
 #endif /* _AIX */
 
+#if defined(__APPLE__) && !TARGET_OS_IPHONE
+# include <AvailabilityMacros.h>
+#endif
+
 #if defined(__ANDROID__)
 int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
 # ifdef pthread_sigmask
@@ -154,7 +162,8 @@ struct uv__stream_queued_fds_s {
     defined(__DragonFly__) || \
     defined(__FreeBSD__) || \
     defined(__FreeBSD_kernel__) || \
-    defined(__linux__)
+    defined(__linux__) || \
+    defined(__OpenBSD__)
 #define uv__cloexec uv__cloexec_ioctl
 #define uv__nonblock uv__nonblock_ioctl
 #else
@@ -183,12 +192,12 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* w);
 int uv__io_active(const uv__io_t* w, unsigned int events);
 int uv__io_check_fd(uv_loop_t* loop, int fd);
 void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
+int uv__io_fork(uv_loop_t* loop);
 
 /* async */
-void uv__async_send(struct uv__async* wa);
-void uv__async_init(struct uv__async* wa);
-int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb);
-void uv__async_stop(uv_loop_t* loop, struct uv__async* wa);
+void uv__async_stop(uv_loop_t* loop);
+int uv__async_fork(uv_loop_t* loop);
+
 
 /* loop */
 void uv__run_idle(uv_loop_t* loop);
@@ -224,6 +233,7 @@ int uv__next_timeout(const uv_loop_t* loop);
 void uv__signal_close(uv_signal_t* handle);
 void uv__signal_global_once_init(void);
 void uv__signal_loop_cleanup(uv_loop_t* loop);
+int uv__signal_loop_fork(uv_loop_t* loop);
 
 /* platform specific */
 uint64_t uv__hrtime(uv_clocktype_t type);
@@ -268,7 +278,6 @@ int uv__make_socketpair(int fds[2], int flags);
 int uv__make_pipe(int fds[2], int flags);
 
 #if defined(__APPLE__)
-#include <AvailabilityMacros.h>
 
 int uv__fsevents_init(uv_fs_event_t* handle);
 int uv__fsevents_close(uv_fs_event_t* handle);
@@ -294,15 +303,6 @@ static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000;
 
 #endif /* defined(__APPLE__) */
 
-UV_UNUSED(static void uv__req_init(uv_loop_t* loop,
-                                   uv_req_t* req,
-                                   uv_req_type type)) {
-  req->type = type;
-  uv__req_register(loop, req);
-}
-#define uv__req_init(loop, req, type) \
-  uv__req_init((loop), (uv_req_t*)(req), (type))
-
 UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) {
   /* Use a fast time source if available.  We only need millisecond precision.
    */
@@ -319,4 +319,8 @@ UV_UNUSED(static char* uv__basename_r(const char* path)) {
   return s + 1;
 }
 
+#if defined(__linux__)
+int uv__inotify_fork(uv_loop_t* loop, void* old_watchers);
+#endif
+
 #endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c
index fffd462..6bc60bb 100644
--- a/Utilities/cmlibuv/src/unix/kqueue.c
+++ b/Utilities/cmlibuv/src/unix/kqueue.c
@@ -48,6 +48,37 @@ int uv__kqueue_init(uv_loop_t* loop) {
 }
 
 
+static int uv__has_forked_with_cfrunloop;
+
+int uv__io_fork(uv_loop_t* loop) {
+  int err;
+  uv__close(loop->backend_fd);
+  loop->backend_fd = -1;
+  err = uv__kqueue_init(loop);
+  if (err)
+    return err;
+
+#if defined(__APPLE__)
+  if (loop->cf_state != NULL) {
+    /* We cannot start another CFRunloop and/or thread in the child
+       process; CF aborts if you try or if you try to touch the thread
+       at all to kill it. So the best we can do is ignore it from now
+       on. This means we can't watch directories in the same way
+       anymore (like other BSDs). It also means we cannot properly
+       clean up the allocated resources; calling
+       uv__fsevents_loop_delete from uv_loop_close will crash the
+       process. So we sidestep the issue by pretending like we never
+       started it in the first place.
+    */
+    uv__has_forked_with_cfrunloop = 1;
+    uv__free(loop->cf_state);
+    loop->cf_state = NULL;
+  }
+#endif
+  return err;
+}
+
+
 int uv__io_check_fd(uv_loop_t* loop, int fd) {
   struct kevent ev;
   int rc;
@@ -404,6 +435,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
   handle->cb = cb;
 
 #if defined(__APPLE__)
+  if (uv__has_forked_with_cfrunloop)
+    goto fallback;
+
   /* Nullify field to perform checks later */
   handle->cf_cb = NULL;
   handle->realpath = NULL;
@@ -438,7 +472,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
   uv__handle_stop(handle);
 
 #if defined(__APPLE__)
-  if (uv__fsevents_close(handle))
+  if (uv__has_forked_with_cfrunloop || uv__fsevents_close(handle))
 #endif /* defined(__APPLE__) */
   {
     uv__io_close(handle->loop, &handle->event_watcher);
diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c
index 58dd813..2866e93 100644
--- a/Utilities/cmlibuv/src/unix/linux-core.c
+++ b/Utilities/cmlibuv/src/unix/linux-core.c
@@ -107,6 +107,24 @@ int uv__platform_loop_init(uv_loop_t* loop) {
 }
 
 
+int uv__io_fork(uv_loop_t* loop) {
+  int err;
+  void* old_watchers;
+
+  old_watchers = loop->inotify_watchers;
+
+  uv__close(loop->backend_fd);
+  loop->backend_fd = -1;
+  uv__platform_loop_delete(loop);
+
+  err = uv__platform_loop_init(loop);
+  if (err)
+    return err;
+
+  return uv__inotify_fork(loop, old_watchers);
+}
+
+
 void uv__platform_loop_delete(uv_loop_t* loop) {
   if (loop->inotify_fd == -1) return;
   uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN);
@@ -454,55 +472,6 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
 }
 
 
-void uv_loadavg(double avg[3]) {
-  struct sysinfo info;
-
-  if (sysinfo(&info) < 0) return;
-
-  avg[0] = (double) info.loads[0] / 65536.0;
-  avg[1] = (double) info.loads[1] / 65536.0;
-  avg[2] = (double) info.loads[2] / 65536.0;
-}
-
-
-int uv_exepath(char* buffer, size_t* size) {
-  ssize_t n;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return -EINVAL;
-
-  n = *size - 1;
-  if (n > 0)
-    n = readlink("/proc/self/exe", buffer, n);
-
-  if (n == -1)
-    return -errno;
-
-  buffer[n] = '\0';
-  *size = n;
-
-  return 0;
-}
-
-
-uint64_t uv_get_free_memory(void) {
-  struct sysinfo info;
-
-  if (sysinfo(&info) == 0)
-    return (uint64_t) info.freeram * info.mem_unit;
-  return 0;
-}
-
-
-uint64_t uv_get_total_memory(void) {
-  struct sysinfo info;
-
-  if (sysinfo(&info) == 0)
-    return (uint64_t) info.totalram * info.mem_unit;
-  return 0;
-}
-
-
 int uv_resident_set_memory(size_t* rss) {
   char buf[1024];
   const char* s;
@@ -868,6 +837,19 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
   uv__free(cpu_infos);
 }
 
+static int uv__ifaddr_exclude(struct ifaddrs *ent) {
+  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
+    return 1;
+  if (ent->ifa_addr == NULL)
+    return 1;
+  /*
+   * On Linux getifaddrs returns information related to the raw underlying
+   * devices. We're not interested in this information yet.
+   */
+  if (ent->ifa_addr->sa_family == PF_PACKET)
+    return 1;
+  return 0;
+}
 
 int uv_interface_addresses(uv_interface_address_t** addresses,
   int* count) {
@@ -887,11 +869,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
 
   /* Count the number of interfaces */
   for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family == PF_PACKET)) {
+    if (uv__ifaddr_exclude(ent))
       continue;
-    }
 
     (*count)++;
   }
@@ -908,17 +887,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
   address = *addresses;
 
   for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
-      continue;
-
-    if (ent->ifa_addr == NULL)
-      continue;
-
-    /*
-     * On Linux getifaddrs returns information related to the raw underlying
-     * devices. We're not interested in this information yet.
-     */
-    if (ent->ifa_addr->sa_family == PF_PACKET)
+    if (uv__ifaddr_exclude(ent))
       continue;
 
     address->name = uv__strdup(ent->ifa_name);
@@ -942,11 +911,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
 
   /* Fill in physical addresses for each interface */
   for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family != PF_PACKET)) {
+    if (uv__ifaddr_exclude(ent))
       continue;
-    }
 
     address = *addresses;
 
diff --git a/Utilities/cmlibuv/src/unix/linux-inotify.c b/Utilities/cmlibuv/src/unix/linux-inotify.c
index 4708c05..5934c5d 100644
--- a/Utilities/cmlibuv/src/unix/linux-inotify.c
+++ b/Utilities/cmlibuv/src/unix/linux-inotify.c
@@ -61,6 +61,8 @@ static void uv__inotify_read(uv_loop_t* loop,
                              uv__io_t* w,
                              unsigned int revents);
 
+static void maybe_free_watcher_list(struct watcher_list* w,
+                                    uv_loop_t* loop);
 
 static int new_inotify_fd(void) {
   int err;
@@ -108,6 +110,71 @@ static int init_inotify(uv_loop_t* loop) {
 }
 
 
+int uv__inotify_fork(uv_loop_t* loop, void* old_watchers) {
+  /* Open the inotify_fd, and re-arm all the inotify watchers. */
+  int err;
+  struct watcher_list* tmp_watcher_list_iter;
+  struct watcher_list* watcher_list;
+  struct watcher_list tmp_watcher_list;
+  QUEUE queue;
+  QUEUE* q;
+  uv_fs_event_t* handle;
+  char* tmp_path;
+
+  if (old_watchers != NULL) {
+    /* We must restore the old watcher list to be able to close items
+     * out of it.
+     */
+    loop->inotify_watchers = old_watchers;
+
+    QUEUE_INIT(&tmp_watcher_list.watchers);
+    /* Note that the queue we use is shared with the start and stop()
+     * functions, making QUEUE_FOREACH unsafe to use. So we use the
+     * QUEUE_MOVE trick to safely iterate. Also don't free the watcher
+     * list until we're done iterating. c.f. uv__inotify_read.
+     */
+    RB_FOREACH_SAFE(watcher_list, watcher_root,
+                    CAST(&old_watchers), tmp_watcher_list_iter) {
+      watcher_list->iterating = 1;
+      QUEUE_MOVE(&watcher_list->watchers, &queue);
+      while (!QUEUE_EMPTY(&queue)) {
+        q = QUEUE_HEAD(&queue);
+        handle = QUEUE_DATA(q, uv_fs_event_t, watchers);
+        /* It's critical to keep a copy of path here, because it
+         * will be set to NULL by stop() and then deallocated by
+         * maybe_free_watcher_list
+         */
+        tmp_path = uv__strdup(handle->path);
+        assert(tmp_path != NULL);
+        QUEUE_REMOVE(q);
+        QUEUE_INSERT_TAIL(&watcher_list->watchers, q);
+        uv_fs_event_stop(handle);
+
+        QUEUE_INSERT_TAIL(&tmp_watcher_list.watchers, &handle->watchers);
+        handle->path = tmp_path;
+      }
+      watcher_list->iterating = 0;
+      maybe_free_watcher_list(watcher_list, loop);
+    }
+
+    QUEUE_MOVE(&tmp_watcher_list.watchers, &queue);
+    while (!QUEUE_EMPTY(&queue)) {
+        q = QUEUE_HEAD(&queue);
+        QUEUE_REMOVE(q);
+        handle = QUEUE_DATA(q, uv_fs_event_t, watchers);
+        tmp_path = handle->path;
+        handle->path = NULL;
+        err = uv_fs_event_start(handle, handle->cb, tmp_path, 0);
+        uv__free(tmp_path);
+        if (err)
+          return err;
+    }
+  }
+
+  return 0;
+}
+
+
 static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) {
   struct watcher_list w;
   w.wd = wd;
diff --git a/Utilities/cmlibuv/src/unix/loop.c b/Utilities/cmlibuv/src/unix/loop.c
index bd63c2f..bcd4924 100644
--- a/Utilities/cmlibuv/src/unix/loop.c
+++ b/Utilities/cmlibuv/src/unix/loop.c
@@ -54,7 +54,8 @@ int uv_loop_init(uv_loop_t* loop) {
 
   loop->closing_handles = NULL;
   uv__update_time(loop);
-  uv__async_init(&loop->async_watcher);
+  loop->async_io_watcher.fd = -1;
+  loop->async_wfd = -1;
   loop->signal_pipefd[0] = -1;
   loop->signal_pipefd[1] = -1;
   loop->backend_fd = -1;
@@ -108,10 +109,43 @@ fail_signal_init:
 }
 
 
+int uv_loop_fork(uv_loop_t* loop) {
+  int err;
+  unsigned int i;
+  uv__io_t* w;
+
+  err = uv__io_fork(loop);
+  if (err)
+    return err;
+
+  err = uv__async_fork(loop);
+  if (err)
+    return err;
+
+  err = uv__signal_loop_fork(loop);
+  if (err)
+    return err;
+
+  /* Rearm all the watchers that aren't re-queued by the above. */
+  for (i = 0; i < loop->nwatchers; i++) {
+    w = loop->watchers[i];
+    if (w == NULL)
+      continue;
+
+    if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) {
+      w->events = 0; /* Force re-registration in uv__io_poll. */
+      QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
+    }
+  }
+
+  return 0;
+}
+
+
 void uv__loop_close(uv_loop_t* loop) {
   uv__signal_loop_cleanup(loop);
   uv__platform_loop_delete(loop);
-  uv__async_stop(loop, &loop->async_watcher);
+  uv__async_stop(loop);
 
   if (loop->emfile_fd != -1) {
     uv__close(loop->emfile_fd);
diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c
index 4a9e6cb..9b5546b 100644
--- a/Utilities/cmlibuv/src/unix/netbsd.c
+++ b/Utilities/cmlibuv/src/unix/netbsd.c
@@ -27,14 +27,11 @@
 
 #include <kvm.h>
 #include <paths.h>
-#include <ifaddrs.h>
 #include <unistd.h>
 #include <time.h>
 #include <stdlib.h>
 #include <fcntl.h>
 
-#include <net/if.h>
-#include <net/if_dl.h>
 #include <sys/resource.h>
 #include <sys/types.h>
 #include <sys/sysctl.h>
@@ -43,9 +40,6 @@
 #include <unistd.h>
 #include <time.h>
 
-#undef NANOSEC
-#define NANOSEC ((uint64_t) 1e9)
-
 static char *process_title;
 
 
@@ -58,13 +52,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
 }
 
 
-uint64_t uv__hrtime(uv_clocktype_t type) {
-  struct timespec ts;
-  clock_gettime(CLOCK_MONOTONIC, &ts);
-  return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
-}
-
-
 void uv_loadavg(double avg[3]) {
   struct loadavg info;
   size_t size = sizeof(info);
@@ -283,98 +270,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
 
   uv__free(cpu_infos);
 }
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
-  struct ifaddrs *addrs, *ent;
-  uv_interface_address_t* address;
-  int i;
-  struct sockaddr_dl *sa_addr;
-
-  if (getifaddrs(&addrs))
-    return -errno;
-
-  *count = 0;
-
-  /* Count the number of interfaces */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family != PF_INET)) {
-      continue;
-    }
-    (*count)++;
-  }
-
-  *addresses = uv__malloc(*count * sizeof(**addresses));
-
-  if (!(*addresses)) {
-    freeifaddrs(addrs);
-    return -ENOMEM;
-  }
-
-  address = *addresses;
-
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
-      continue;
-
-    if (ent->ifa_addr == NULL)
-      continue;
-
-    if (ent->ifa_addr->sa_family != PF_INET)
-      continue;
-
-    address->name = uv__strdup(ent->ifa_name);
-
-    if (ent->ifa_addr->sa_family == AF_INET6) {
-      address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
-    } else {
-      address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
-    }
-
-    if (ent->ifa_netmask->sa_family == AF_INET6) {
-      address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
-    } else {
-      address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
-    }
-
-    address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
-    address++;
-  }
-
-  /* Fill in physical addresses for each interface */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family != AF_LINK)) {
-      continue;
-    }
-
-    address = *addresses;
-
-    for (i = 0; i < (*count); i++) {
-      if (strcmp(address->name, ent->ifa_name) == 0) {
-        sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
-        memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
-      }
-      address++;
-    }
-  }
-
-  freeifaddrs(addrs);
-
-  return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(addresses[i].name);
-  }
-
-  uv__free(addresses);
-}
diff --git a/Utilities/cmlibuv/src/unix/no-fsevents.c b/Utilities/cmlibuv/src/unix/no-fsevents.c
new file mode 100644
index 0000000..38fb6ab
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/no-fsevents.c
@@ -0,0 +1,42 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <errno.h>
+
+int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
+  return -ENOSYS;
+}
+
+int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
+                      const char* filename, unsigned int flags) {
+  return -ENOSYS;
+}
+
+int uv_fs_event_stop(uv_fs_event_t* handle) {
+  return -ENOSYS;
+}
+
+void uv__fs_event_close(uv_fs_event_t* handle) {
+  UNREACHABLE();
+}
diff --git a/Utilities/cmlibuv/src/unix/no-proctitle.c b/Utilities/cmlibuv/src/unix/no-proctitle.c
new file mode 100644
index 0000000..a5c19fb
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/no-proctitle.c
@@ -0,0 +1,42 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <errno.h>
+#include <stddef.h>
+
+char** uv_setup_args(int argc, char** argv) {
+  return argv;
+}
+
+int uv_set_process_title(const char* title) {
+  return 0;
+}
+
+int uv_get_process_title(char* buffer, size_t size) {
+  if (buffer == NULL || size == 0)
+    return -EINVAL;
+
+  buffer[0] = '\0';
+  return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c
index 909288c..56f0af1 100644
--- a/Utilities/cmlibuv/src/unix/openbsd.c
+++ b/Utilities/cmlibuv/src/unix/openbsd.c
@@ -28,21 +28,13 @@
 #include <sys/time.h>
 #include <sys/sysctl.h>
 
-#include <ifaddrs.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-
 #include <errno.h>
 #include <fcntl.h>
-#include <kvm.h>
 #include <paths.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#undef NANOSEC
-#define NANOSEC ((uint64_t) 1e9)
-
 
 static char *process_title;
 
@@ -56,13 +48,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
 }
 
 
-uint64_t uv__hrtime(uv_clocktype_t type) {
-  struct timespec ts;
-  clock_gettime(CLOCK_MONOTONIC, &ts);
-  return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
-}
-
-
 void uv_loadavg(double avg[3]) {
   struct loadavg info;
   size_t size = sizeof(info);
@@ -163,7 +148,7 @@ char** uv_setup_args(int argc, char** argv) {
 int uv_set_process_title(const char* title) {
   uv__free(process_title);
   process_title = uv__strdup(title);
-  setproctitle(title);
+  setproctitle("%s", title);
   return 0;
 }
 
@@ -297,100 +282,3 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
 
   uv__free(cpu_infos);
 }
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses,
-  int* count) {
-  struct ifaddrs *addrs, *ent;
-  uv_interface_address_t* address;
-  int i;
-  struct sockaddr_dl *sa_addr;
-
-  if (getifaddrs(&addrs) != 0)
-    return -errno;
-
-   *count = 0;
-
-  /* Count the number of interfaces */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family != PF_INET)) {
-      continue;
-    }
-    (*count)++;
-  }
-
-  *addresses = uv__malloc(*count * sizeof(**addresses));
-
-  if (!(*addresses)) {
-    freeifaddrs(addrs);
-    return -ENOMEM;
-  }
-
-  address = *addresses;
-
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
-      continue;
-
-    if (ent->ifa_addr == NULL)
-      continue;
-
-    if (ent->ifa_addr->sa_family != PF_INET)
-      continue;
-
-    address->name = uv__strdup(ent->ifa_name);
-
-    if (ent->ifa_addr->sa_family == AF_INET6) {
-      address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
-    } else {
-      address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
-    }
-
-    if (ent->ifa_netmask->sa_family == AF_INET6) {
-      address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
-    } else {
-      address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
-    }
-
-    address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
-    address++;
-  }
-
-  /* Fill in physical addresses for each interface */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family != AF_LINK)) {
-      continue;
-    }
-
-    address = *addresses;
-
-    for (i = 0; i < (*count); i++) {
-      if (strcmp(address->name, ent->ifa_name) == 0) {
-        sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
-        memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
-      }
-      address++;
-    }
-  }
-
-  freeifaddrs(addrs);
-
-  return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
-  int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(addresses[i].name);
-  }
-
-  uv__free(addresses);
-}
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c
new file mode 100644
index 0000000..7edf235
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c
@@ -0,0 +1,334 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+
+#include "os390-syscalls.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <search.h>
+
+#define CW_CONDVAR 32
+
+#pragma linkage(BPX4CTW, OS)
+#pragma linkage(BPX1CTW, OS)
+
+static int number_of_epolls;
+static QUEUE global_epoll_queue;
+static uv_mutex_t global_epoll_lock;
+static uv_once_t once = UV_ONCE_INIT;
+
+int scandir(const char* maindir, struct dirent*** namelist,
+            int (*filter)(const struct dirent*),
+            int (*compar)(const struct dirent**,
+            const struct dirent **)) {
+  struct dirent** nl;
+  struct dirent* dirent;
+  unsigned count;
+  size_t allocated;
+  DIR* mdir;
+
+  nl = NULL;
+  count = 0;
+  allocated = 0;
+  mdir = opendir(maindir);
+  if (!mdir)
+    return -1;
+
+  while (1) {
+    dirent = readdir(mdir);
+    if (!dirent)
+      break;
+    if (!filter || filter(dirent)) {
+      struct dirent* copy;
+      copy = uv__malloc(sizeof(*copy));
+      if (!copy) {
+        while (count) {
+          dirent = nl[--count];
+          uv__free(dirent);
+        }
+        uv__free(nl);
+        closedir(mdir);
+        errno = ENOMEM;
+        return -1;
+      }
+      memcpy(copy, dirent, sizeof(*copy));
+
+      nl = uv__realloc(nl, sizeof(*copy) * (count + 1));
+      nl[count++] = copy;
+    }
+  }
+
+  qsort(nl, count, sizeof(struct dirent *),
+       (int (*)(const void *, const void *)) compar);
+
+  closedir(mdir);
+
+  *namelist = nl;
+  return count;
+}
+
+
+static unsigned int next_power_of_two(unsigned int val) {
+  val -= 1;
+  val |= val >> 1;
+  val |= val >> 2;
+  val |= val >> 4;
+  val |= val >> 8;
+  val |= val >> 16;
+  val += 1;
+  return val;
+}
+
+
+static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
+  unsigned int newsize;
+  unsigned int i;
+  struct pollfd* newlst;
+
+  if (len <= lst->size)
+    return;
+
+  newsize = next_power_of_two(len);
+  newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0]));
+
+  if (newlst == NULL)
+    abort();
+  for (i = lst->size; i < newsize; ++i)
+    newlst[i].fd = -1;
+
+  lst->items = newlst;
+  lst->size = newsize;
+}
+
+
+static void epoll_init(void) {
+  QUEUE_INIT(&global_epoll_queue);
+  if (uv_mutex_init(&global_epoll_lock))
+    abort();
+}
+
+
+uv__os390_epoll* epoll_create1(int flags) {
+  uv__os390_epoll* lst;
+
+  uv_once(&once, epoll_init);
+  uv_mutex_lock(&global_epoll_lock);
+  lst = uv__malloc(sizeof(*lst));
+  if (lst == -1)
+    return NULL;
+  QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
+  uv_mutex_unlock(&global_epoll_lock);
+
+  /* initialize list */
+  lst->size = 0;
+  lst->items = NULL;
+  return lst;
+}
+
+
+int epoll_ctl(uv__os390_epoll* lst,
+              int op,
+              int fd,
+              struct epoll_event *event) {
+  if(op == EPOLL_CTL_DEL) {
+    if (fd >= lst->size || lst->items[fd].fd == -1) {
+      errno = ENOENT;
+      return -1;
+    }
+    lst->items[fd].fd = -1;
+  } else if(op == EPOLL_CTL_ADD) {
+    maybe_resize(lst, fd + 1);
+    if (lst->items[fd].fd != -1) {
+      errno = EEXIST;
+      return -1;
+    }
+    lst->items[fd].fd = fd;
+    lst->items[fd].events = event->events;
+  } else if(op == EPOLL_CTL_MOD) {
+    if (fd >= lst->size || lst->items[fd].fd == -1) {
+      errno = ENOENT;
+      return -1;
+    }
+    lst->items[fd].events = event->events;
+  } else
+    abort();
+
+  return 0;
+}
+
+
+int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
+               int maxevents, int timeout) {
+  size_t size;
+  struct pollfd* pfds;
+  int pollret;
+  int reventcount;
+
+  uv_mutex_lock(&global_epoll_lock);
+  uv_mutex_unlock(&global_epoll_lock);
+  size = lst->size;
+  pfds = lst->items;
+  pollret = poll(pfds, size, timeout);
+  if(pollret == -1)
+    return pollret;
+
+  reventcount = 0;
+  for (int i = 0; i < lst->size && i < maxevents; ++i) {
+    struct epoll_event ev;
+
+    ev.events = 0;
+    ev.fd = pfds[i].fd;
+    if(!pfds[i].revents)
+      continue;
+
+    if(pfds[i].revents & POLLRDNORM)
+      ev.events = ev.events | POLLIN;
+
+    if(pfds[i].revents & POLLWRNORM)
+      ev.events = ev.events | POLLOUT;
+
+    if(pfds[i].revents & POLLHUP)
+      ev.events = ev.events | POLLHUP;
+
+    pfds[i].revents = 0;
+    events[reventcount++] = ev;
+  }
+
+  return reventcount;
+}
+
+
+int epoll_file_close(int fd) {
+  QUEUE* q;
+
+  uv_once(&once, epoll_init);
+  uv_mutex_lock(&global_epoll_lock);
+  QUEUE_FOREACH(q, &global_epoll_queue) {
+    uv__os390_epoll* lst;
+
+    lst = QUEUE_DATA(q, uv__os390_epoll, member);
+    if (fd < lst->size && lst->items != NULL && lst->items[fd].fd != -1)
+      lst->items[fd].fd = -1;
+  }
+
+  uv_mutex_unlock(&global_epoll_lock);
+  return 0;
+}
+
+void epoll_queue_close(uv__os390_epoll* lst) {
+  uv_mutex_lock(&global_epoll_lock);
+  QUEUE_REMOVE(&lst->member);
+  uv_mutex_unlock(&global_epoll_lock);
+  uv__free(lst->items);
+  lst->items = NULL;
+}
+
+
+int nanosleep(const struct timespec* req, struct timespec* rem) {
+  unsigned nano;
+  unsigned seconds;
+  unsigned events;
+  unsigned secrem;
+  unsigned nanorem;
+  int rv;
+  int rc;
+  int rsn;
+
+  nano = (int)req->tv_nsec;
+  seconds = req->tv_sec;
+  events = CW_CONDVAR;
+
+#if defined(_LP64)
+  BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
+#else
+  BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
+#endif
+
+  assert(rv == -1 && errno == EAGAIN);
+
+  if(rem != NULL) {
+    rem->tv_nsec = nanorem;
+    rem->tv_sec = secrem;
+  }
+
+  return 0;
+}
+
+
+char* mkdtemp(char* path) {
+  static const char* tempchars =
+    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+  static const size_t num_chars = 62;
+  static const size_t num_x = 6;
+  char *ep, *cp;
+  unsigned int tries, i;
+  size_t len;
+  uint64_t v;
+  int fd;
+  int retval;
+  int saved_errno;
+
+  len = strlen(path);
+  ep = path + len;
+  if (len < num_x || strncmp(ep - num_x, "XXXXXX", num_x)) {
+    errno = EINVAL;
+    return NULL;
+  }
+
+  fd = open("/dev/urandom", O_RDONLY);
+  if (fd == -1)
+    return NULL;
+
+  tries = TMP_MAX;
+  retval = -1;
+  do {
+    if (read(fd, &v, sizeof(v)) != sizeof(v))
+      break;
+
+    cp = ep - num_x;
+    for (i = 0; i < num_x; i++) {
+      *cp++ = tempchars[v % num_chars];
+      v /= num_chars;
+    }
+
+    if (mkdir(path, S_IRWXU) == 0) {
+      retval = 0;
+      break;
+    }
+    else if (errno != EEXIST)
+      break;
+  } while (--tries);
+
+  saved_errno = errno;
+  uv__close(fd);
+  if (tries == 0) {
+    errno = EEXIST;
+    return NULL;
+  }
+
+  if (retval == -1) {
+    errno = saved_errno;
+    return NULL;
+  }
+
+  return path;
+}
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.h b/Utilities/cmlibuv/src/unix/os390-syscalls.h
new file mode 100644
index 0000000..61a7cee
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.h
@@ -0,0 +1,69 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+
+#ifndef UV_OS390_SYSCALL_H_
+#define UV_OS390_SYSCALL_H_
+
+#include "uv.h"
+#include "internal.h"
+#include <dirent.h>
+#include <poll.h>
+#include <pthread.h>
+
+#define EPOLL_CTL_ADD             1
+#define EPOLL_CTL_DEL             2
+#define EPOLL_CTL_MOD             3
+#define MAX_EPOLL_INSTANCES       256
+#define MAX_ITEMS_PER_EPOLL       1024
+
+#define UV__O_CLOEXEC             0x80000
+#define UV__EPOLL_CLOEXEC         UV__O_CLOEXEC
+#define UV__EPOLL_CTL_ADD         EPOLL_CTL_ADD
+#define UV__EPOLL_CTL_DEL         EPOLL_CTL_DEL
+#define UV__EPOLL_CTL_MOD         EPOLL_CTL_MOD
+
+struct epoll_event {
+  int events;
+  int fd;
+};
+
+typedef struct {
+  QUEUE member;
+  struct pollfd* items;
+  unsigned long size;
+} uv__os390_epoll;
+
+/* epoll api */
+uv__os390_epoll* epoll_create1(int flags);
+int epoll_ctl(uv__os390_epoll* ep, int op, int fd, struct epoll_event *event);
+int epoll_wait(uv__os390_epoll* ep, struct epoll_event *events, int maxevents, int timeout);
+int epoll_file_close(int fd);
+
+/* utility functions */
+int nanosleep(const struct timespec* req, struct timespec* rem);
+int scandir(const char* maindir, struct dirent*** namelist,
+            int (*filter)(const struct dirent *),
+            int (*compar)(const struct dirent **,
+            const struct dirent **));
+char *mkdtemp(char* path);
+
+#endif /* UV_OS390_SYSCALL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c
index bcdbc4b..2ba5abf 100644
--- a/Utilities/cmlibuv/src/unix/os390.c
+++ b/Utilities/cmlibuv/src/unix/os390.c
@@ -20,6 +20,628 @@
  */
 
 #include "internal.h"
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <utmpx.h>
+#include <unistd.h>
+#include <sys/ps.h>
+#if defined(__clang__)
+#include "csrsic.h"
+#else
+#include "//'SYS1.SAMPLIB(CSRSIC)'"
+#endif
+
+#define CVT_PTR           0x10
+#define CSD_OFFSET        0x294
+
+/*
+    Long-term average CPU service used by this logical partition,
+    in millions of service units per hour. If this value is above
+    the partition's defined capacity, the partition will be capped.
+    It is calculated using the physical CPU adjustment factor
+    (RCTPCPUA) so it may not match other measures of service which
+    are based on the logical CPU adjustment factor. It is available
+    if the hardware supports LPAR cluster.
+*/
+#define RCTLACS_OFFSET    0xC4
+
+/* 32-bit count of alive CPUs. This includes both CPs and IFAs */
+#define CSD_NUMBER_ONLINE_CPUS        0xD4
+
+/* Address of system resources manager (SRM) control table */
+#define CVTOPCTP_OFFSET   0x25C
+
+/* Address of the RCT table */
+#define RMCTRCT_OFFSET    0xE4
+
+/* Address of the rsm control and enumeration area. */
+#define CVTRCEP_OFFSET    0x490
+
+/*
+    Number of frames currently available to system.
+    Excluded are frames backing perm storage, frames offline, and bad frames.
+*/
+#define RCEPOOL_OFFSET    0x004
+
+/* Total number of frames currently on all available frame queues. */
+#define RCEAFC_OFFSET     0x088
+
+/* CPC model length from the CSRSI Service. */
+#define CPCMODEL_LENGTH   16
+
+/* Thread Entry constants */
+#define PGTH_CURRENT  1
+#define PGTH_LEN      26
+#define PGTHAPATH     0x20
+#pragma linkage(BPX4GTH, OS)
+#pragma linkage(BPX1GTH, OS)
+
+typedef unsigned data_area_ptr_assign_type;
+
+typedef union {
+  struct {
+#if defined(_LP64)
+    data_area_ptr_assign_type lower;
+#endif
+    data_area_ptr_assign_type assign;
+  };
+  char* deref;
+} data_area_ptr;
+
+
+void uv_loadavg(double avg[3]) {
+  /* TODO: implement the following */
+  avg[0] = 0;
+  avg[1] = 0;
+  avg[2] = 0;
+}
+
+
+int uv__platform_loop_init(uv_loop_t* loop) {
+  uv__os390_epoll* ep;
+
+  ep = epoll_create1(UV__EPOLL_CLOEXEC);
+  loop->ep = ep;
+  if (ep == NULL)
+    return -errno;
+
+  return 0;
+}
+
+
+void uv__platform_loop_delete(uv_loop_t* loop) {
+  if (loop->ep != NULL) {
+    epoll_queue_close(loop->ep);
+    loop->ep = NULL;
+  }
+}
+
+
+uint64_t uv__hrtime(uv_clocktype_t type) {
+  struct timeval time;
+  gettimeofday(&time, NULL);
+  return (uint64_t) time.tv_sec * 1e9 + time.tv_usec * 1e3;
+}
+
+
+/*
+    Get the exe path using the thread entry information
+    in the address space.
+*/
+static int getexe(const int pid, char* buf, size_t len) {
+  struct {
+    int pid;
+    int thid[2];
+    char accesspid;
+    char accessthid;
+    char asid[2];
+    char loginname[8];
+    char flag;
+    char len;
+  } Input_data;
+
+  union {
+    struct {
+      char gthb[4];
+      int pid;
+      int thid[2];
+      char accesspid;
+      char accessthid[3];
+      int lenused;
+      int offsetProcess;
+      int offsetConTTY;
+      int offsetPath;
+      int offsetCommand;
+      int offsetFileData;
+      int offsetThread;
+    } Output_data;
+    char buf[2048];
+  } Output_buf;
+
+  struct Output_path_type {
+    char gthe[4];
+    short int len;
+    char path[1024];
+  };
+
+  int Input_length;
+  int Output_length;
+  void* Input_address;
+  void* Output_address;
+  struct Output_path_type* Output_path;
+  int rv;
+  int rc;
+  int rsn;
+
+  Input_length = PGTH_LEN;
+  Output_length = sizeof(Output_buf);
+  Output_address = &Output_buf;
+  Input_address = &Input_data;
+  memset(&Input_data, 0, sizeof Input_data);
+  Input_data.flag |= PGTHAPATH;
+  Input_data.pid = pid;
+  Input_data.accesspid = PGTH_CURRENT;
+
+#ifdef _LP64
+  BPX4GTH(&Input_length,
+          &Input_address,
+          &Output_length,
+          &Output_address,
+          &rv,
+          &rc,
+          &rsn);
+#else
+  BPX1GTH(&Input_length,
+          &Input_address,
+          &Output_length,
+          &Output_address,
+          &rv,
+          &rc,
+          &rsn);
+#endif
+
+  if (rv == -1) {
+    errno = rc;
+    return -1;
+  }
+
+  /* Check highest byte to ensure data availability */
+  assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A');
+
+  /* Get the offset from the lowest 3 bytes */
+  Output_path = (char*)(&Output_buf) +
+                (Output_buf.Output_data.offsetPath & 0x00FFFFFF);
+
+  if (Output_path->len >= len) {
+    errno = ENOBUFS;
+    return -1;
+  }
+
+  strncpy(buf, Output_path->path, len);
+
+  return 0;
+}
+
+
+/*
+ * We could use a static buffer for the path manipulations that we need outside
+ * of the function, but this function could be called by multiple consumers and
+ * we don't want to potentially create a race condition in the use of snprintf.
+ * There is no direct way of getting the exe path in zOS - either through /procfs
+ * or through some libc APIs. The below approach is to parse the argv[0]'s pattern
+ * and use it in conjunction with PATH environment variable to craft one.
+ */
+int uv_exepath(char* buffer, size_t* size) {
+  int res;
+  char args[PATH_MAX];
+  char abspath[PATH_MAX];
+  size_t abspath_size;
+  int pid;
+
+  if (buffer == NULL || size == NULL || *size == 0)
+    return -EINVAL;
+
+  pid = getpid();
+  res = getexe(pid, args, sizeof(args));
+  if (res < 0)
+    return -EINVAL;
+
+  /*
+   * Possibilities for args:
+   * i) an absolute path such as: /home/user/myprojects/nodejs/node
+   * ii) a relative path such as: ./node or ../myprojects/nodejs/node
+   * iii) a bare filename such as "node", after exporting PATH variable
+   *     to its location.
+   */
+
+  /* Case i) and ii) absolute or relative paths */
+  if (strchr(args, '/') != NULL) {
+    if (realpath(args, abspath) != abspath)
+      return -errno;
+
+    abspath_size = strlen(abspath);
+
+    *size -= 1;
+    if (*size > abspath_size)
+      *size = abspath_size;
+
+    memcpy(buffer, abspath, *size);
+    buffer[*size] = '\0';
+
+    return 0;
+  } else {
+    /* Case iii). Search PATH environment variable */
+    char trypath[PATH_MAX];
+    char* clonedpath = NULL;
+    char* token = NULL;
+    char* path = getenv("PATH");
+
+    if (path == NULL)
+      return -EINVAL;
+
+    clonedpath = uv__strdup(path);
+    if (clonedpath == NULL)
+      return -ENOMEM;
+
+    token = strtok(clonedpath, ":");
+    while (token != NULL) {
+      snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
+      if (realpath(trypath, abspath) == abspath) {
+        /* Check the match is executable */
+        if (access(abspath, X_OK) == 0) {
+          abspath_size = strlen(abspath);
+
+          *size -= 1;
+          if (*size > abspath_size)
+            *size = abspath_size;
+
+          memcpy(buffer, abspath, *size);
+          buffer[*size] = '\0';
+
+          uv__free(clonedpath);
+          return 0;
+        }
+      }
+      token = strtok(NULL, ":");
+    }
+    uv__free(clonedpath);
+
+    /* Out of tokens (path entries), and no match found */
+    return -EINVAL;
+  }
+}
+
+
+uint64_t uv_get_free_memory(void) {
+  uint64_t freeram;
+
+  data_area_ptr cvt = {0};
+  data_area_ptr rcep = {0};
+  cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
+  rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET);
+  freeram = *((uint64_t*)(rcep.deref + RCEAFC_OFFSET)) * 4;
+  return freeram;
+}
+
+
+uint64_t uv_get_total_memory(void) {
+  uint64_t totalram;
+
+  data_area_ptr cvt = {0};
+  data_area_ptr rcep = {0};
+  cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
+  rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET);
+  totalram = *((uint64_t*)(rcep.deref + RCEPOOL_OFFSET)) * 4;
+  return totalram;
+}
+
+
+int uv_resident_set_memory(size_t* rss) {
+  W_PSPROC buf;
+
+  memset(&buf, 0, sizeof(buf));
+  if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1)
+    return -EINVAL;
+
+  *rss = buf.ps_size;
+  return 0;
+}
+
+
+int uv_uptime(double* uptime) {
+  struct utmpx u ;
+  struct utmpx *v;
+  time64_t t;
+
+  u.ut_type = BOOT_TIME;
+  v = getutxid(&u);
+  if (v == NULL)
+    return -1;
+  *uptime = difftime64(time64(&t), v->ut_tv.tv_sec);
+  return 0;
+}
+
+
+int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
+  uv_cpu_info_t* cpu_info;
+  int result;
+  int idx;
+  siv1v2 info;
+  data_area_ptr cvt = {0};
+  data_area_ptr csd = {0};
+  data_area_ptr rmctrct = {0};
+  data_area_ptr cvtopctp = {0};
+  int cpu_usage_avg;
+
+  cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
+
+  csd.assign = *((data_area_ptr_assign_type *) (cvt.deref + CSD_OFFSET));
+  cvtopctp.assign = *((data_area_ptr_assign_type *) (cvt.deref + CVTOPCTP_OFFSET));
+  rmctrct.assign = *((data_area_ptr_assign_type *) (cvtopctp.deref + RMCTRCT_OFFSET));
+
+  *count = *((int*) (csd.deref + CSD_NUMBER_ONLINE_CPUS));
+  cpu_usage_avg = *((unsigned short int*) (rmctrct.deref + RCTLACS_OFFSET));
+
+  *cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t));
+  if (!*cpu_infos)
+    return -ENOMEM;
+
+  cpu_info = *cpu_infos;
+  idx = 0;
+  while (idx < *count) {
+    cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability);
+    cpu_info->model = uv__malloc(CPCMODEL_LENGTH + 1);
+    memset(cpu_info->model, '\0', CPCMODEL_LENGTH + 1);
+    memcpy(cpu_info->model, info.siv1v2si11v1.si11v1cpcmodel, CPCMODEL_LENGTH);
+    cpu_info->cpu_times.user = cpu_usage_avg;
+    /* TODO: implement the following */
+    cpu_info->cpu_times.sys = 0;
+    cpu_info->cpu_times.idle = 0;
+    cpu_info->cpu_times.irq = 0;
+    cpu_info->cpu_times.nice = 0;
+    ++cpu_info;
+    ++idx;
+  }
+
+  return 0;
+}
+
+
+void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
+  for (int i = 0; i < count; ++i)
+    uv__free(cpu_infos[i].model);
+  uv__free(cpu_infos);
+}
+
+
+static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
+                                      int* count) {
+  uv_interface_address_t* address;
+  int sockfd;
+  int maxsize;
+  __net_ifconf6header_t ifc;
+  __net_ifconf6entry_t* ifr;
+  __net_ifconf6entry_t* p;
+  __net_ifconf6entry_t flg;
+
+  *count = 0;
+  /* Assume maximum buffer size allowable */
+  maxsize = 16384;
+
+  if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
+    return -errno;
+
+  ifc.__nif6h_version = 1;
+  ifc.__nif6h_buflen = maxsize;
+  ifc.__nif6h_buffer = uv__calloc(1, maxsize);;
+
+  if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
+    uv__close(sockfd);
+    return -errno;
+  }
+
+
+  *count = 0;
+  ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
+  while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
+    p = ifr;
+    ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
+
+    if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
+          p->__nif6e_addr.sin6_family == AF_INET))
+      continue;
+
+    if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
+      continue;
+
+    ++(*count);
+  }
+
+  /* Alloc the return interface structs */
+  *addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
+  if (!(*addresses)) {
+    uv__close(sockfd);
+    return -ENOMEM;
+  }
+  address = *addresses;
+
+  ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
+  while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
+    p = ifr;
+    ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
+
+    if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
+          p->__nif6e_addr.sin6_family == AF_INET))
+      continue;
+
+    if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
+      continue;
+
+    /* All conditions above must match count loop */
+
+    address->name = uv__strdup(p->__nif6e_name);
+
+    if (p->__nif6e_addr.sin6_family == AF_INET6)
+      address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr);
+    else
+      address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr);
+
+    /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
+
+    address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
+
+    address++;
+  }
+
+  uv__close(sockfd);
+  return 0;
+}
+
+
+int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
+  uv_interface_address_t* address;
+  int sockfd;
+  int maxsize;
+  struct ifconf ifc;
+  struct ifreq flg;
+  struct ifreq* ifr;
+  struct ifreq* p;
+  int count_v6;
+
+  /* get the ipv6 addresses first */
+  uv_interface_address_t* addresses_v6;
+  uv__interface_addresses_v6(&addresses_v6, &count_v6);
+
+  /* now get the ipv4 addresses */
+  *count = 0;
+
+  /* Assume maximum buffer size allowable */
+  maxsize = 16384;
+
+  sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+  if (0 > sockfd)
+    return -errno;
+
+  ifc.ifc_req = uv__calloc(1, maxsize);
+  ifc.ifc_len = maxsize;
+  if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
+    uv__close(sockfd);
+    return -errno;
+  }
+
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
+
+  /* Count all up and running ipv4/ipv6 addresses */
+  ifr = ifc.ifc_req;
+  while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
+    p = ifr;
+    ifr = (struct ifreq*)
+      ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
+
+    if (!(p->ifr_addr.sa_family == AF_INET6 ||
+          p->ifr_addr.sa_family == AF_INET))
+      continue;
+
+    memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
+    if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
+      uv__close(sockfd);
+      return -errno;
+    }
+
+    if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
+      continue;
+
+    (*count)++;
+  }
+
+  /* Alloc the return interface structs */
+  *addresses = uv__malloc((*count + count_v6) *
+                          sizeof(uv_interface_address_t));
+
+  if (!(*addresses)) {
+    uv__close(sockfd);
+    return -ENOMEM;
+  }
+  address = *addresses;
+
+  /* copy over the ipv6 addresses */
+  memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t));
+  address += count_v6;
+  *count += count_v6;
+  uv__free(addresses_v6);
+
+  ifr = ifc.ifc_req;
+  while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
+    p = ifr;
+    ifr = (struct ifreq*)
+      ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
+
+    if (!(p->ifr_addr.sa_family == AF_INET6 ||
+          p->ifr_addr.sa_family == AF_INET))
+      continue;
+
+    memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
+    if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
+      uv__close(sockfd);
+      return -ENOSYS;
+    }
+
+    if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
+      continue;
+
+    /* All conditions above must match count loop */
+
+    address->name = uv__strdup(p->ifr_name);
+
+    if (p->ifr_addr.sa_family == AF_INET6) {
+      address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
+    } else {
+      address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
+    }
+
+    address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
+    address++;
+  }
+
+#undef ADDR_SIZE
+#undef MAX
+
+  uv__close(sockfd);
+  return 0;
+}
+
+
+void uv_free_interface_addresses(uv_interface_address_t* addresses,
+                                 int count) {
+  int i;
+  for (i = 0; i < count; ++i)
+    uv__free(addresses[i].name);
+  uv__free(addresses);
+}
+
+
+void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
+  struct epoll_event* events;
+  struct epoll_event dummy;
+  uintptr_t i;
+  uintptr_t nfds;
+
+  assert(loop->watchers != NULL);
+
+  events = (struct epoll_event*) loop->watchers[loop->nwatchers];
+  nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
+  if (events != NULL)
+    /* Invalidate events with same file descriptor */
+    for (i = 0; i < nfds; i++)
+      if ((int) events[i].fd == fd)
+        events[i].fd = -1;
+
+  /* Remove the file descriptor from the epoll. */
+  if (loop->ep != NULL)
+    epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy);
+}
+
 
 int uv__io_check_fd(uv_loop_t* loop, int fd) {
   struct pollfd p[1];
@@ -40,3 +662,188 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
 
   return 0;
 }
+
+void uv__io_poll(uv_loop_t* loop, int timeout) {
+  static const int max_safe_timeout = 1789569;
+  struct epoll_event events[1024];
+  struct epoll_event* pe;
+  struct epoll_event e;
+  int real_timeout;
+  QUEUE* q;
+  uv__io_t* w;
+  uint64_t base;
+  int count;
+  int nfds;
+  int fd;
+  int op;
+  int i;
+
+  if (loop->nfds == 0) {
+    assert(QUEUE_EMPTY(&loop->watcher_queue));
+    return;
+  }
+
+  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
+    uv_stream_t* stream;
+
+    q = QUEUE_HEAD(&loop->watcher_queue);
+    QUEUE_REMOVE(q);
+    QUEUE_INIT(q);
+    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
+
+    assert(w->pevents != 0);
+    assert(w->fd >= 0);
+
+    stream= container_of(w, uv_stream_t, io_watcher);
+
+    assert(w->fd < (int) loop->nwatchers);
+
+    e.events = w->pevents;
+    e.fd = w->fd;
+
+    if (w->events == 0)
+      op = UV__EPOLL_CTL_ADD;
+    else
+      op = UV__EPOLL_CTL_MOD;
+
+    /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
+     * events, skip the syscall and squelch the events after epoll_wait().
+     */
+    if (epoll_ctl(loop->ep, op, w->fd, &e)) {
+      if (errno != EEXIST)
+        abort();
+
+      assert(op == UV__EPOLL_CTL_ADD);
+
+      /* We've reactivated a file descriptor that's been watched before. */
+      if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e))
+        abort();
+    }
+
+    w->events = w->pevents;
+  }
+
+  assert(timeout >= -1);
+  base = loop->time;
+  count = 48; /* Benchmarks suggest this gives the best throughput. */
+  real_timeout = timeout;
+  int nevents = 0;
+
+  nfds = 0;
+  for (;;) {
+    if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
+      timeout = max_safe_timeout;
+
+    nfds = epoll_wait(loop->ep, events,
+                      ARRAY_SIZE(events), timeout);
+
+    /* Update loop->time unconditionally. It's tempting to skip the update when
+     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
+     * operating system didn't reschedule our process while in the syscall.
+     */
+    base = loop->time;
+    SAVE_ERRNO(uv__update_time(loop));
+    if (nfds == 0) {
+      assert(timeout != -1);
+      timeout = real_timeout - timeout;
+      if (timeout > 0)
+        continue;
+
+      return;
+    }
+
+    if (nfds == -1) {
+
+      if (errno != EINTR)
+        abort();
+
+      if (timeout == -1)
+        continue;
+
+      if (timeout == 0)
+        return;
+
+      /* Interrupted by a signal. Update timeout and poll again. */
+      goto update_timeout;
+    }
+
+
+    assert(loop->watchers != NULL);
+    loop->watchers[loop->nwatchers] = (void*) events;
+    loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
+    for (i = 0; i < nfds; i++) {
+      pe = events + i;
+      fd = pe->fd;
+
+      /* Skip invalidated events, see uv__platform_invalidate_fd */
+      if (fd == -1)
+        continue;
+
+      assert(fd >= 0);
+      assert((unsigned) fd < loop->nwatchers);
+
+      w = loop->watchers[fd];
+
+      if (w == NULL) {
+        /* File descriptor that we've stopped watching, disarm it.
+         *
+         * Ignore all errors because we may be racing with another thread
+         * when the file descriptor is closed.
+         */
+        epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe);
+        continue;
+      }
+
+      /* Give users only events they're interested in. Prevents spurious
+       * callbacks when previous callback invocation in this loop has stopped
+       * the current watcher. Also, filters out events that users has not
+       * requested us to watch.
+       */
+      pe->events &= w->pevents | POLLERR | POLLHUP;
+
+      if (pe->events == POLLERR || pe->events == POLLHUP)
+        pe->events |= w->pevents & (POLLIN | POLLOUT);
+
+      if (pe->events != 0) {
+        w->cb(loop, w, pe->events);
+        nevents++;
+      }
+    }
+    loop->watchers[loop->nwatchers] = NULL;
+    loop->watchers[loop->nwatchers + 1] = NULL;
+
+    if (nevents != 0) {
+      if (nfds == ARRAY_SIZE(events) && --count != 0) {
+        /* Poll for more events but don't block this time. */
+        timeout = 0;
+        continue;
+      }
+      return;
+    }
+
+    if (timeout == 0)
+      return;
+
+    if (timeout == -1)
+      continue;
+
+update_timeout:
+    assert(timeout > 0);
+
+    real_timeout -= (loop->time - base);
+    if (real_timeout <= 0)
+      return;
+
+    timeout = real_timeout;
+  }
+}
+
+void uv__set_process_title(const char* title) {
+  /* do nothing */
+}
+
+int uv__io_fork(uv_loop_t* loop) {
+  uv__platform_loop_delete(loop);
+
+  return uv__platform_loop_init(loop);
+}
diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c
index 80f5e6f..7ba1bf8 100644
--- a/Utilities/cmlibuv/src/unix/pipe.c
+++ b/Utilities/cmlibuv/src/unix/pipe.c
@@ -73,7 +73,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
     /* Convert ENOENT to EACCES for compatibility with Windows. */
     if (err == -ENOENT)
       err = -EACCES;
-    goto err_bind;
+
+    uv__close(sockfd);
+    goto err_socket;
   }
 
   /* Success. */
@@ -82,9 +84,6 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
   handle->io_watcher.fd = sockfd;
   return 0;
 
-err_bind:
-  uv__close(sockfd);
-
 err_socket:
   uv__free((void*)pipe_fname);
   return err;
@@ -180,6 +179,14 @@ void uv_pipe_connect(uv_connect_t* req,
 
   if (r == -1 && errno != EINPROGRESS) {
     err = -errno;
+#if defined(__CYGWIN__) || defined(__MSYS__)
+    /* EBADF is supposed to mean that the socket fd is bad, but
+       Cygwin reports EBADF instead of ENOTSOCK when the file is
+       not a socket.  We do not expect to see a bad fd here
+       (e.g. due to new_sock), so translate the error.  */
+    if (err == -EBADF)
+      err = -ENOTSOCK;
+#endif
     goto out;
   }
 
diff --git a/Utilities/cmlibuv/src/unix/poll.c b/Utilities/cmlibuv/src/unix/poll.c
index 4c0d478..370994b 100644
--- a/Utilities/cmlibuv/src/unix/poll.c
+++ b/Utilities/cmlibuv/src/unix/poll.c
@@ -92,7 +92,7 @@ static void uv__poll_stop(uv_poll_t* handle) {
 
 
 int uv_poll_stop(uv_poll_t* handle) {
-  assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+  assert(!uv__is_closing(handle));
   uv__poll_stop(handle);
   return 0;
 }
@@ -102,7 +102,7 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
   int events;
 
   assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
-  assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+  assert(!uv__is_closing(handle));
 
   uv__poll_stop(handle);
 
diff --git a/Utilities/cmlibuv/src/unix/posix-hrtime.c b/Utilities/cmlibuv/src/unix/posix-hrtime.c
new file mode 100644
index 0000000..323dfc2
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/posix-hrtime.c
@@ -0,0 +1,35 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stdint.h>
+#include <time.h>
+
+#undef NANOSEC
+#define NANOSEC ((uint64_t) 1e9)
+
+uint64_t uv__hrtime(uv_clocktype_t type) {
+  struct timespec ts;
+  clock_gettime(CLOCK_MONOTONIC, &ts);
+  return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
+}
diff --git a/Utilities/cmlibuv/src/unix/posix-poll.c b/Utilities/cmlibuv/src/unix/posix-poll.c
new file mode 100644
index 0000000..3fba96e
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/posix-poll.c
@@ -0,0 +1,324 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+/* POSIX defines poll() as a portable way to wait on file descriptors.
+ * Here we maintain a dynamically sized array of file descriptors and
+ * events to pass as the first argument to poll().
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+
+int uv__platform_loop_init(uv_loop_t* loop) {
+  loop->poll_fds = NULL;
+  loop->poll_fds_used = 0;
+  loop->poll_fds_size = 0;
+  loop->poll_fds_iterating = 0;
+  return 0;
+}
+
+void uv__platform_loop_delete(uv_loop_t* loop) {
+  uv__free(loop->poll_fds);
+  loop->poll_fds = NULL;
+}
+
+int uv__io_fork(uv_loop_t* loop) {
+  uv__platform_loop_delete(loop);
+  return uv__platform_loop_init(loop);
+}
+
+/* Allocate or dynamically resize our poll fds array.  */
+static void uv__pollfds_maybe_resize(uv_loop_t* loop) {
+  size_t i;
+  size_t n;
+  struct pollfd* p;
+
+  if (loop->poll_fds_used < loop->poll_fds_size)
+    return;
+
+  n = loop->poll_fds_size ? loop->poll_fds_size * 2 : 64;
+  p = uv__realloc(loop->poll_fds, n * sizeof(*loop->poll_fds));
+  if (p == NULL)
+    abort();
+
+  loop->poll_fds = p;
+  for (i = loop->poll_fds_size; i < n; i++) {
+    loop->poll_fds[i].fd = -1;
+    loop->poll_fds[i].events = 0;
+    loop->poll_fds[i].revents = 0;
+  }
+  loop->poll_fds_size = n;
+}
+
+/* Primitive swap operation on poll fds array elements.  */
+static void uv__pollfds_swap(uv_loop_t* loop, size_t l, size_t r) {
+  struct pollfd pfd;
+  pfd = loop->poll_fds[l];
+  loop->poll_fds[l] = loop->poll_fds[r];
+  loop->poll_fds[r] = pfd;
+}
+
+/* Add a watcher's fd to our poll fds array with its pending events.  */
+static void uv__pollfds_add(uv_loop_t* loop, uv__io_t* w) {
+  size_t i;
+  struct pollfd* pe;
+
+  /* If the fd is already in the set just update its events.  */
+  assert(!loop->poll_fds_iterating);
+  for (i = 0; i < loop->poll_fds_used; ++i) {
+    if (loop->poll_fds[i].fd == w->fd) {
+      loop->poll_fds[i].events = w->pevents;
+      return;
+    }
+  }
+
+  /* Otherwise, allocate a new slot in the set for the fd.  */
+  uv__pollfds_maybe_resize(loop);
+  pe = &loop->poll_fds[loop->poll_fds_used++];
+  pe->fd = w->fd;
+  pe->events = w->pevents;
+}
+
+/* Remove a watcher's fd from our poll fds array.  */
+static void uv__pollfds_del(uv_loop_t* loop, int fd) {
+  size_t i;
+  assert(!loop->poll_fds_iterating);
+  for (i = 0; i < loop->poll_fds_used; ++i) {
+    if (loop->poll_fds[i].fd == fd) {
+      /* swap to last position and remove */
+      --loop->poll_fds_used;
+      uv__pollfds_swap(loop, i, loop->poll_fds_used);
+      loop->poll_fds[loop->poll_fds_used].fd = -1;
+      loop->poll_fds[loop->poll_fds_used].events = 0;
+      loop->poll_fds[loop->poll_fds_used].revents = 0;
+      return;
+    }
+  }
+}
+
+
+void uv__io_poll(uv_loop_t* loop, int timeout) {
+  sigset_t* pset;
+  sigset_t set;
+  uint64_t time_base;
+  uint64_t time_diff;
+  QUEUE* q;
+  uv__io_t* w;
+  size_t i;
+  unsigned int nevents;
+  int nfds;
+  int have_signals;
+  struct pollfd* pe;
+  int fd;
+
+  if (loop->nfds == 0) {
+    assert(QUEUE_EMPTY(&loop->watcher_queue));
+    return;
+  }
+
+  /* Take queued watchers and add their fds to our poll fds array.  */
+  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
+    q = QUEUE_HEAD(&loop->watcher_queue);
+    QUEUE_REMOVE(q);
+    QUEUE_INIT(q);
+
+    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
+    assert(w->pevents != 0);
+    assert(w->fd >= 0);
+    assert(w->fd < (int) loop->nwatchers);
+
+    uv__pollfds_add(loop, w);
+
+    w->events = w->pevents;
+  }
+
+  /* Prepare a set of signals to block around poll(), if any.  */
+  pset = NULL;
+  if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
+    pset = &set;
+    sigemptyset(pset);
+    sigaddset(pset, SIGPROF);
+  }
+
+  assert(timeout >= -1);
+  time_base = loop->time;
+
+  /* Loop calls to poll() and processing of results.  If we get some
+   * results from poll() but they turn out not to be interesting to
+   * our caller then we need to loop around and poll() again.
+   */
+  for (;;) {
+    if (pset != NULL)
+      if (pthread_sigmask(SIG_BLOCK, pset, NULL))
+        abort();
+    nfds = poll(loop->poll_fds, (nfds_t)loop->poll_fds_used, timeout);
+    if (pset != NULL)
+      if (pthread_sigmask(SIG_UNBLOCK, pset, NULL))
+        abort();
+
+    /* Update loop->time unconditionally. It's tempting to skip the update when
+     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
+     * operating system didn't reschedule our process while in the syscall.
+     */
+    SAVE_ERRNO(uv__update_time(loop));
+
+    if (nfds == 0) {
+      assert(timeout != -1);
+      return;
+    }
+
+    if (nfds == -1) {
+      if (errno != EINTR)
+        abort();
+
+      if (timeout == -1)
+        continue;
+
+      if (timeout == 0)
+        return;
+
+      /* Interrupted by a signal. Update timeout and poll again. */
+      goto update_timeout;
+    }
+
+    /* Tell uv__platform_invalidate_fd not to manipulate our array
+     * while we are iterating over it.
+     */
+    loop->poll_fds_iterating = 1;
+
+    /* Initialize a count of events that we care about.  */
+    nevents = 0;
+    have_signals = 0;
+
+    /* Loop over the entire poll fds array looking for returned events.  */
+    for (i = 0; i < loop->poll_fds_used; i++) {
+      pe = loop->poll_fds + i;
+      fd = pe->fd;
+
+      /* Skip invalidated events, see uv__platform_invalidate_fd.  */
+      if (fd == -1)
+        continue;
+
+      assert(fd >= 0);
+      assert((unsigned) fd < loop->nwatchers);
+
+      w = loop->watchers[fd];
+
+      if (w == NULL) {
+        /* File descriptor that we've stopped watching, ignore.  */
+        uv__platform_invalidate_fd(loop, fd);
+        continue;
+      }
+
+      /* Filter out events that user has not requested us to watch
+       * (e.g. POLLNVAL).
+       */
+      pe->revents &= w->pevents | POLLERR | POLLHUP;
+
+      if (pe->revents != 0) {
+        /* Run signal watchers last.  */
+        if (w == &loop->signal_io_watcher) {
+          have_signals = 1;
+        } else {
+          w->cb(loop, w, pe->revents);
+        }
+
+        nevents++;
+      }
+    }
+
+    if (have_signals != 0)
+      loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
+
+    loop->poll_fds_iterating = 0;
+
+    /* Purge invalidated fds from our poll fds array.  */
+    uv__pollfds_del(loop, -1);
+
+    if (have_signals != 0)
+      return;  /* Event loop should cycle now so don't poll again. */
+
+    if (nevents != 0)
+      return;
+
+    if (timeout == 0)
+      return;
+
+    if (timeout == -1)
+      continue;
+
+update_timeout:
+    assert(timeout > 0);
+
+    time_diff = loop->time - time_base;
+    if (time_diff >= (uint64_t) timeout)
+      return;
+
+    timeout -= time_diff;
+  }
+}
+
+/* Remove the given fd from our poll fds array because no one
+ * is interested in its events anymore.
+ */
+void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
+  size_t i;
+
+  if (loop->poll_fds_iterating) {
+    /* uv__io_poll is currently iterating.  Just invalidate fd.  */
+    for (i = 0; i < loop->poll_fds_used; i++)
+      if (loop->poll_fds[i].fd == fd) {
+        loop->poll_fds[i].fd = -1;
+        loop->poll_fds[i].events = 0;
+        loop->poll_fds[i].revents = 0;
+      }
+  } else {
+    /* uv__io_poll is not iterating.  Delete fd from the set.  */
+    uv__pollfds_del(loop, fd);
+  }
+}
+
+/* Check whether the given fd is supported by poll().  */
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+  struct pollfd p[1];
+  int rv;
+
+  p[0].fd = fd;
+  p[0].events = POLLIN;
+
+  do
+    rv = poll(p, 1, 0);
+  while (rv == -1 && (errno == EINTR || errno == EAGAIN));
+
+  if (rv == -1)
+    return -errno;
+
+  if (p[0].revents & POLLNVAL)
+    return -EINVAL;
+
+  return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index 45f5b45..f2fe305 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -323,7 +323,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
     }
 
     if (fd == use_fd)
-      uv__cloexec(use_fd, 0);
+      uv__cloexec_fcntl(use_fd, 0);
     else
       fd = dup2(use_fd, fd);
 
@@ -333,7 +333,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
     }
 
     if (fd <= 2)
-      uv__nonblock(fd, 0);
+      uv__nonblock_fcntl(fd, 0);
 
     if (close_fd >= stdio_count)
       uv__close(close_fd);
diff --git a/Utilities/cmlibuv/src/unix/procfs-exepath.c b/Utilities/cmlibuv/src/unix/procfs-exepath.c
new file mode 100644
index 0000000..5fdb611
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/procfs-exepath.c
@@ -0,0 +1,45 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stddef.h>
+#include <unistd.h>
+
+int uv_exepath(char* buffer, size_t* size) {
+  ssize_t n;
+
+  if (buffer == NULL || size == NULL || *size == 0)
+    return -EINVAL;
+
+  n = *size - 1;
+  if (n > 0)
+    n = readlink("/proc/self/exe", buffer, n);
+
+  if (n == -1)
+    return -errno;
+
+  buffer[n] = '\0';
+  *size = n;
+
+  return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/proctitle.c b/Utilities/cmlibuv/src/unix/proctitle.c
index 08d875f..9160f7e 100644
--- a/Utilities/cmlibuv/src/unix/proctitle.c
+++ b/Utilities/cmlibuv/src/unix/proctitle.c
@@ -48,9 +48,15 @@ char** uv_setup_args(int argc, char** argv) {
   for (i = 0; i < argc; i++)
     size += strlen(argv[i]) + 1;
 
+#if defined(__MVS__)
+  /* argv is not adjacent. So just use argv[0] */
+  process_title.str = argv[0];
+  process_title.len = strlen(argv[0]);
+#else
   process_title.str = argv[0];
   process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0];
   assert(process_title.len + 1 == size);  /* argv memory should be adjacent. */
+#endif
 
   /* Add space for the argv pointers. */
   size += (argc + 1) * sizeof(char*);
diff --git a/Utilities/cmlibuv/src/unix/pthread-barrier.c b/Utilities/cmlibuv/src/unix/pthread-barrier.c
index f57bf25..b6e604d 100644
--- a/Utilities/cmlibuv/src/unix/pthread-barrier.c
+++ b/Utilities/cmlibuv/src/unix/pthread-barrier.c
@@ -73,7 +73,8 @@ int pthread_barrier_wait(pthread_barrier_t* barrier) {
   if (++b->in == b->threshold) {
     b->in = 0;
     b->out = b->threshold - 1;
-    assert(pthread_cond_signal(&b->cond) == 0);
+    rc = pthread_cond_signal(&b->cond);
+    assert(rc == 0);
 
     pthread_mutex_unlock(&b->mutex);
     return PTHREAD_BARRIER_SERIAL_THREAD;
diff --git a/Utilities/cmlibuv/src/unix/signal.c b/Utilities/cmlibuv/src/unix/signal.c
index d82b9b7..cb09ead 100644
--- a/Utilities/cmlibuv/src/unix/signal.c
+++ b/Utilities/cmlibuv/src/unix/signal.c
@@ -38,12 +38,17 @@ RB_HEAD(uv__signal_tree_s, uv_signal_s);
 
 
 static int uv__signal_unlock(void);
+static int uv__signal_start(uv_signal_t* handle,
+                            uv_signal_cb signal_cb,
+                            int signum,
+                            int oneshot);
 static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events);
 static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
 static void uv__signal_stop(uv_signal_t* handle);
+static void uv__signal_unregister_handler(int signum);
 
 
-static pthread_once_t uv__signal_global_init_guard = PTHREAD_ONCE_INIT;
+static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
 static struct uv__signal_tree_s uv__signal_tree =
     RB_INITIALIZER(uv__signal_tree);
 static int uv__signal_lock_pipefd[2];
@@ -53,8 +58,19 @@ RB_GENERATE_STATIC(uv__signal_tree_s,
                    uv_signal_s, tree_entry,
                    uv__signal_compare)
 
+static void uv__signal_global_reinit(void);
 
 static void uv__signal_global_init(void) {
+  if (!uv__signal_lock_pipefd[0])
+    /* pthread_atfork can register before and after handlers, one
+     * for each child. This only registers one for the child. That
+     * state is both persistent and cumulative, so if we keep doing
+     * it the handler functions will be called multiple times. Thus
+     * we only want to do it once.
+     */
+    if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit))
+      abort();
+
   if (uv__make_pipe(uv__signal_lock_pipefd, 0))
     abort();
 
@@ -63,8 +79,24 @@ static void uv__signal_global_init(void) {
 }
 
 
+static void uv__signal_global_reinit(void) {
+  /* We can only use signal-safe functions here.
+   * That includes read/write and close, fortunately.
+   * We do all of this directly here instead of resetting
+   * uv__signal_global_init_guard because
+   * uv__signal_global_once_init is only called from uv_loop_init
+   * and this needs to function in existing loops.
+   */
+  uv__close(uv__signal_lock_pipefd[0]);
+  uv__signal_lock_pipefd[0] = -1;
+  uv__close(uv__signal_lock_pipefd[1]);
+  uv__signal_lock_pipefd[1] = -1;
+  uv__signal_global_init();
+}
+
+
 void uv__signal_global_once_init(void) {
-  pthread_once(&uv__signal_global_init_guard, uv__signal_global_init);
+  uv_once(&uv__signal_global_init_guard, uv__signal_global_init);
 }
 
 
@@ -122,6 +154,7 @@ static uv_signal_t* uv__signal_first_handle(int signum) {
   uv_signal_t* handle;
 
   lookup.signum = signum;
+  lookup.flags = 0;
   lookup.loop = NULL;
 
   handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup);
@@ -174,7 +207,7 @@ static void uv__signal_handler(int signum) {
 }
 
 
-static int uv__signal_register_handler(int signum) {
+static int uv__signal_register_handler(int signum, int oneshot) {
   /* When this function is called, the signal lock must be held. */
   struct sigaction sa;
 
@@ -183,6 +216,7 @@ static int uv__signal_register_handler(int signum) {
   if (sigfillset(&sa.sa_mask))
     abort();
   sa.sa_handler = uv__signal_handler;
+  sa.sa_flags = oneshot ? SA_RESETHAND : 0;
 
   /* XXX save old action so we can restore it later on? */
   if (sigaction(signum, &sa, NULL))
@@ -228,6 +262,16 @@ static int uv__signal_loop_once_init(uv_loop_t* loop) {
 }
 
 
+int uv__signal_loop_fork(uv_loop_t* loop) {
+  uv__io_stop(loop, &loop->signal_io_watcher, POLLIN);
+  uv__close(loop->signal_pipefd[0]);
+  uv__close(loop->signal_pipefd[1]);
+  loop->signal_pipefd[0] = -1;
+  loop->signal_pipefd[1] = -1;
+  return uv__signal_loop_once_init(loop);
+}
+
+
 void uv__signal_loop_cleanup(uv_loop_t* loop) {
   QUEUE* q;
 
@@ -287,10 +331,26 @@ void uv__signal_close(uv_signal_t* handle) {
 
 
 int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
+  return uv__signal_start(handle, signal_cb, signum, 0);
+}
+
+
+int uv_signal_start_oneshot(uv_signal_t* handle,
+                            uv_signal_cb signal_cb,
+                            int signum) {
+  return uv__signal_start(handle, signal_cb, signum, 1);
+}
+
+
+static int uv__signal_start(uv_signal_t* handle,
+                            uv_signal_cb signal_cb,
+                            int signum,
+                            int oneshot) {
   sigset_t saved_sigmask;
   int err;
+  uv_signal_t* first_handle;
 
-  assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+  assert(!uv__is_closing(handle));
 
   /* If the user supplies signum == 0, then return an error already. If the
    * signum is otherwise invalid then uv__signal_register will find out
@@ -318,9 +378,12 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
 
   /* If at this point there are no active signal watchers for this signum (in
    * any of the loops), it's time to try and register a handler for it here.
+   * Also in case there's only one-shot handlers and a regular handler comes in.
    */
-  if (uv__signal_first_handle(signum) == NULL) {
-    err = uv__signal_register_handler(signum);
+  first_handle = uv__signal_first_handle(signum);
+  if (first_handle == NULL ||
+      (!oneshot && (first_handle->flags & UV__SIGNAL_ONE_SHOT))) {
+    err = uv__signal_register_handler(signum, oneshot);
     if (err) {
       /* Registering the signal handler failed. Must be an invalid signal. */
       uv__signal_unlock_and_unblock(&saved_sigmask);
@@ -329,6 +392,9 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
   }
 
   handle->signum = signum;
+  if (oneshot)
+    handle->flags |= UV__SIGNAL_ONE_SHOT;
+
   RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
 
   uv__signal_unlock_and_unblock(&saved_sigmask);
@@ -390,6 +456,9 @@ static void uv__signal_event(uv_loop_t* loop,
 
       handle->dispatched_signals++;
 
+      if (handle->flags & UV__SIGNAL_ONE_SHOT)
+        uv__signal_stop(handle);
+
       /* If uv_close was called while there were caught signals that were not
        * yet dispatched, the uv__finish_close was deferred. Make close pending
        * now if this has happened.
@@ -414,12 +483,22 @@ static void uv__signal_event(uv_loop_t* loop,
 
 
 static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
+  int f1;
+  int f2;
   /* Compare signums first so all watchers with the same signnum end up
    * adjacent.
    */
   if (w1->signum < w2->signum) return -1;
   if (w1->signum > w2->signum) return 1;
 
+  /* Handlers without UV__SIGNAL_ONE_SHOT set will come first, so if the first
+   * handler returned is a one-shot handler, the rest will be too.
+   */
+  f1 = w1->flags & UV__SIGNAL_ONE_SHOT;
+  f2 = w2->flags & UV__SIGNAL_ONE_SHOT;
+  if (f1 < f2) return -1;
+  if (f1 > f2) return 1;
+
   /* Sort by loop pointer, so we can easily look up the first item after
    * { .signum = x, .loop = NULL }.
    */
@@ -434,7 +513,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
 
 
 int uv_signal_stop(uv_signal_t* handle) {
-  assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
+  assert(!uv__is_closing(handle));
   uv__signal_stop(handle);
   return 0;
 }
@@ -443,6 +522,10 @@ int uv_signal_stop(uv_signal_t* handle) {
 static void uv__signal_stop(uv_signal_t* handle) {
   uv_signal_t* removed_handle;
   sigset_t saved_sigmask;
+  uv_signal_t* first_handle;
+  int rem_oneshot;
+  int first_oneshot;
+  int ret;
 
   /* If the watcher wasn't started, this is a no-op. */
   if (handle->signum == 0)
@@ -457,8 +540,17 @@ static void uv__signal_stop(uv_signal_t* handle) {
   /* Check if there are other active signal watchers observing this signal. If
    * not, unregister the signal handler.
    */
-  if (uv__signal_first_handle(handle->signum) == NULL)
+  first_handle = uv__signal_first_handle(handle->signum);
+  if (first_handle == NULL) {
     uv__signal_unregister_handler(handle->signum);
+  } else {
+    rem_oneshot = handle->flags & UV__SIGNAL_ONE_SHOT;
+    first_oneshot = first_handle->flags & UV__SIGNAL_ONE_SHOT;
+    if (first_oneshot && !rem_oneshot) {
+      ret = uv__signal_register_handler(handle->signum, 1);
+      assert(ret == 0);
+    }
+  }
 
   uv__signal_unlock_and_unblock(&saved_sigmask);
 
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index d20d0bc..7b23d16 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -785,7 +785,12 @@ start:
     struct msghdr msg;
     struct cmsghdr *cmsg;
     int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
-    char scratch[64] = {0};
+    union {
+      char data[64];
+      struct cmsghdr alias;
+    } scratch;
+
+    memset(&scratch, 0, sizeof(scratch));
 
     assert(fd_to_send >= 0);
 
@@ -795,7 +800,7 @@ start:
     msg.msg_iovlen = iovcnt;
     msg.msg_flags = 0;
 
-    msg.msg_control = (void*) scratch;
+    msg.msg_control = &scratch.alias;
     msg.msg_controllen = CMSG_SPACE(sizeof(fd_to_send));
 
     cmsg = CMSG_FIRSTHDR(&msg);
@@ -1168,6 +1173,11 @@ static void uv__read(uv_stream_t* stream) {
           uv__stream_osx_interrupt_select(stream);
         }
         stream->read_cb(stream, 0, &buf);
+#if defined(__CYGWIN__) || defined(__MSYS__)
+      } else if (errno == ECONNRESET && stream->type == UV_NAMED_PIPE) {
+        uv__stream_eof(stream, &buf);
+        return;
+#endif
       } else {
         /* Error. User should call uv_close(). */
         stream->read_cb(stream, -errno, &buf);
@@ -1194,6 +1204,30 @@ static void uv__read(uv_stream_t* stream) {
           return;
         }
       }
+
+#if defined(__MVS__)
+      if (is_ipc && msg.msg_controllen > 0) {
+        uv_buf_t blankbuf;
+        int nread;
+        struct iovec *old;
+
+        blankbuf.base = 0;
+        blankbuf.len = 0;
+        old = msg.msg_iov;
+        msg.msg_iov = (struct iovec*) &blankbuf;
+        nread = 0;
+        do {
+          nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0);
+          err = uv__stream_recv_cmsg(stream, &msg);
+          if (err != 0) {
+            stream->read_cb(stream, err, &buf);
+            msg.msg_iov = old;
+            return;
+          }
+        } while (nread == 0 && msg.msg_controllen > 0);
+        msg.msg_iov = old;
+      }
+#endif
       stream->read_cb(stream, nread, &buf);
 
       /* Return if we didn't fill the buffer, there is no more data to read. */
@@ -1221,8 +1255,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
   if (!(stream->flags & UV_STREAM_WRITABLE) ||
       stream->flags & UV_STREAM_SHUT ||
       stream->flags & UV_STREAM_SHUTTING ||
-      stream->flags & UV_CLOSED ||
-      stream->flags & UV_CLOSING) {
+      uv__is_closing(stream)) {
     return -ENOTCONN;
   }
 
@@ -1377,6 +1410,12 @@ int uv_write2(uv_write_t* req,
      */
     if (uv__handle_fd((uv_handle_t*) send_handle) < 0)
       return -EBADF;
+
+#if defined(__CYGWIN__) || defined(__MSYS__)
+    /* Cygwin recvmsg always sets msg_controllen to zero, so we cannot send it.
+       See https://github.com/mirror/newlib-cygwin/blob/86fc4bf0/winsup/cygwin/fhandler_socket.cc#L1736-L1743 */
+    return -ENOSYS;
+#endif
   }
 
   /* It's legal for write_queue_size > 0 even when the write_queue is empty;
diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c
index 3e7a759..041f3f3 100644
--- a/Utilities/cmlibuv/src/unix/sunos.c
+++ b/Utilities/cmlibuv/src/unix/sunos.c
@@ -28,6 +28,10 @@
 #include <assert.h>
 #include <errno.h>
 
+#if !defined(SUNOS_NO_IFADDRS) && _XOPEN_SOURCE < 600
+#define SUNOS_NO_IFADDRS
+#endif
+
 #ifndef SUNOS_NO_IFADDRS
 # include <ifaddrs.h>
 #endif
@@ -99,6 +103,18 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
 }
 
 
+int uv__io_fork(uv_loop_t* loop) {
+#if defined(PORT_SOURCE_FILE)
+  if (loop->fs_fd != -1) {
+    /* stop the watcher before we blow away its fileno */
+    uv__io_stop(loop, &loop->fs_event_watcher, POLLIN);
+  }
+#endif
+  uv__platform_loop_delete(loop);
+  return uv__platform_loop_init(loop);
+}
+
+
 void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
   struct port_event* events;
   uintptr_t i;
@@ -469,8 +485,10 @@ int uv_fs_event_start(uv_fs_event_t* handle,
   memset(&handle->fo, 0, sizeof handle->fo);
   handle->fo.fo_name = handle->path;
   err = uv__fs_event_rearm(handle);
-  if (err != 0)
+  if (err != 0) {
+    uv_fs_event_stop(handle);
     return err;
+  }
 
   if (first_run) {
     uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd);
@@ -531,25 +549,6 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
 #endif /* defined(PORT_SOURCE_FILE) */
 
 
-char** uv_setup_args(int argc, char** argv) {
-  return argv;
-}
-
-
-int uv_set_process_title(const char* title) {
-  return 0;
-}
-
-
-int uv_get_process_title(char* buffer, size_t size) {
-  if (buffer == NULL || size == 0)
-    return -EINVAL;
-
-  buffer[0] = '\0';
-  return 0;
-}
-
-
 int uv_resident_set_memory(size_t* rss) {
   psinfo_t psinfo;
   int err;
@@ -695,6 +694,11 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
   uv__free(cpu_infos);
 }
 
+#ifdef SUNOS_NO_IFADDRS
+int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
+  return -ENOSYS;
+}
+#else  /* SUNOS_NO_IFADDRS */
 /*
  * Inspired By:
  * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris
@@ -741,10 +745,18 @@ static int uv__set_phys_addr(uv_interface_address_t* address,
   return 0;
 }
 
+
+static int uv__ifaddr_exclude(struct ifaddrs *ent) {
+  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
+    return 1;
+  if (ent->ifa_addr == NULL)
+    return 1;
+  if (ent->ifa_addr->sa_family == PF_PACKET)
+    return 1;
+  return 0;
+}
+
 int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
-#ifdef SUNOS_NO_IFADDRS
-  return -ENOSYS;
-#else
   uv_interface_address_t* address;
   struct ifaddrs* addrs;
   struct ifaddrs* ent;
@@ -757,12 +769,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
 
   /* Count the number of interfaces */
   for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) ||
-        (ent->ifa_addr == NULL) ||
-        (ent->ifa_addr->sa_family == PF_PACKET)) {
+    if (uv__ifaddr_exclude(ent))
       continue;
-    }
-
     (*count)++;
   }
 
@@ -775,10 +783,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
   address = *addresses;
 
   for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
-      continue;
-
-    if (ent->ifa_addr == NULL)
+    if (uv__ifaddr_exclude(ent))
       continue;
 
     address->name = uv__strdup(ent->ifa_name);
@@ -805,9 +810,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
   freeifaddrs(addrs);
 
   return 0;
-#endif  /* SUNOS_NO_IFADDRS */
 }
-
+#endif  /* SUNOS_NO_IFADDRS */
 
 void uv_free_interface_addresses(uv_interface_address_t* addresses,
   int count) {
diff --git a/Utilities/cmlibuv/src/unix/sysinfo-loadavg.c b/Utilities/cmlibuv/src/unix/sysinfo-loadavg.c
new file mode 100644
index 0000000..ebad0e8
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/sysinfo-loadavg.c
@@ -0,0 +1,36 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stdint.h>
+#include <sys/sysinfo.h>
+
+void uv_loadavg(double avg[3]) {
+  struct sysinfo info;
+
+  if (sysinfo(&info) < 0) return;
+
+  avg[0] = (double) info.loads[0] / 65536.0;
+  avg[1] = (double) info.loads[1] / 65536.0;
+  avg[2] = (double) info.loads[2] / 65536.0;
+}
diff --git a/Utilities/cmlibuv/src/unix/sysinfo-memory.c b/Utilities/cmlibuv/src/unix/sysinfo-memory.c
new file mode 100644
index 0000000..23b4fc6
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/sysinfo-memory.c
@@ -0,0 +1,42 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stdint.h>
+#include <sys/sysinfo.h>
+
+uint64_t uv_get_free_memory(void) {
+  struct sysinfo info;
+
+  if (sysinfo(&info) == 0)
+    return (uint64_t) info.freeram * info.mem_unit;
+  return 0;
+}
+
+uint64_t uv_get_total_memory(void) {
+  struct sysinfo info;
+
+  if (sysinfo(&info) == 0)
+    return (uint64_t) info.totalram * info.mem_unit;
+  return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c
index 52989f7..a9b5e4c 100644
--- a/Utilities/cmlibuv/src/unix/thread.c
+++ b/Utilities/cmlibuv/src/unix/thread.c
@@ -40,28 +40,8 @@
 #undef NANOSEC
 #define NANOSEC ((uint64_t) 1e9)
 
-struct thread_ctx {
-  void (*entry)(void* arg);
-  void* arg;
-};
-
-
-static void* uv__thread_start(void *arg)
-{
-  struct thread_ctx *ctx_p;
-  struct thread_ctx ctx;
-
-  ctx_p = arg;
-  ctx = *ctx_p;
-  uv__free(ctx_p);
-  ctx.entry(ctx.arg);
-
-  return 0;
-}
-
 
 int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
-  struct thread_ctx* ctx;
   int err;
   pthread_attr_t* attr;
 #if defined(__APPLE__)
@@ -69,13 +49,6 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
   struct rlimit lim;
 #endif
 
-  ctx = uv__malloc(sizeof(*ctx));
-  if (ctx == NULL)
-    return UV_ENOMEM;
-
-  ctx->entry = entry;
-  ctx->arg = arg;
-
   /* On OSX threads other than the main thread are created with a reduced stack
    * size by default, adjust it to RLIMIT_STACK.
    */
@@ -99,14 +72,11 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
   attr = NULL;
 #endif
 
-  err = pthread_create(tid, attr, uv__thread_start, ctx);
+  err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg);
 
   if (attr != NULL)
     pthread_attr_destroy(attr);
 
-  if (err)
-    uv__free(ctx);
-
   return -err;
 }
 
diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c
index 1cd4925..c556325 100644
--- a/Utilities/cmlibuv/src/unix/udp.c
+++ b/Utilities/cmlibuv/src/unix/udp.c
@@ -307,7 +307,7 @@ int uv__udp_bind(uv_udp_t* handle,
   if (flags & UV_UDP_REUSEADDR) {
     err = uv__set_reuse(fd);
     if (err)
-      goto out;
+      return err;
   }
 
   if (flags & UV_UDP_IPV6ONLY) {
@@ -315,11 +315,11 @@ int uv__udp_bind(uv_udp_t* handle,
     yes = 1;
     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) {
       err = -errno;
-      goto out;
+      return err;
     }
 #else
     err = -ENOTSUP;
-    goto out;
+    return err;
 #endif
   }
 
@@ -329,27 +329,25 @@ int uv__udp_bind(uv_udp_t* handle,
       /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
        * socket created with AF_INET to an AF_INET6 address or vice versa. */
       err = -EINVAL;
-    goto out;
+    return err;
   }
 
   if (addr->sa_family == AF_INET6)
     handle->flags |= UV_HANDLE_IPV6;
 
   handle->flags |= UV_HANDLE_BOUND;
-
   return 0;
-
-out:
-  uv__close(handle->io_watcher.fd);
-  handle->io_watcher.fd = -1;
-  return err;
 }
 
 
 static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
                                        int domain,
                                        unsigned int flags) {
-  unsigned char taddr[sizeof(struct sockaddr_in6)];
+  union {
+    struct sockaddr_in6 in6;
+    struct sockaddr_in in;
+    struct sockaddr addr;
+  } taddr;
   socklen_t addrlen;
 
   if (handle->io_watcher.fd != -1)
@@ -358,7 +356,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
   switch (domain) {
   case AF_INET:
   {
-    struct sockaddr_in* addr = (void*)&taddr;
+    struct sockaddr_in* addr = &taddr.in;
     memset(addr, 0, sizeof *addr);
     addr->sin_family = AF_INET;
     addr->sin_addr.s_addr = INADDR_ANY;
@@ -367,7 +365,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
   }
   case AF_INET6:
   {
-    struct sockaddr_in6* addr = (void*)&taddr;
+    struct sockaddr_in6* addr = &taddr.in6;
     memset(addr, 0, sizeof *addr);
     addr->sin6_family = AF_INET6;
     addr->sin6_addr = in6addr_any;
@@ -379,7 +377,7 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
     abort();
   }
 
-  return uv__udp_bind(handle, (const struct sockaddr*) &taddr, addrlen, flags);
+  return uv__udp_bind(handle, &taddr.addr, addrlen, flags);
 }
 
 
@@ -429,6 +427,13 @@ int uv__udp_send(uv_udp_send_t* req,
 
   if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) {
     uv__udp_sendmsg(handle);
+
+    /* `uv__udp_sendmsg` may not be able to do non-blocking write straight
+     * away. In such cases the `io_watcher` has to be queued for asynchronous
+     * write.
+     */
+    if (!QUEUE_EMPTY(&handle->write_queue))
+      uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
   } else {
     uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
   }
diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c
index 46d9546..bc7d137 100644
--- a/Utilities/cmlibuv/src/uv-common.c
+++ b/Utilities/cmlibuv/src/uv-common.c
@@ -512,8 +512,18 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) {
 int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
   uv__dirent_t** dents;
   uv__dirent_t* dent;
+  unsigned int* nbufs;
 
-  unsigned int* nbufs = uv__get_nbufs(req);
+  /* Check to see if req passed */
+  if (req->result < 0)
+    return req->result;
+
+  /* Ptr will be null if req was canceled or no files found */
+  if (!req->ptr)
+    return UV_EOF;
+
+  nbufs = uv__get_nbufs(req);
+  assert(nbufs);
 
   dents = req->ptr;
 
diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h
index 27902fd..781a855 100644
--- a/Utilities/cmlibuv/src/uv-common.h
+++ b/Utilities/cmlibuv/src/uv-common.h
@@ -55,16 +55,19 @@ extern int snprintf(char*, size_t, const char*, ...);
 
 #ifndef _WIN32
 enum {
+  UV__SIGNAL_ONE_SHOT = 0x80000,  /* On signal reception remove sighandler */
   UV__HANDLE_INTERNAL = 0x8000,
   UV__HANDLE_ACTIVE   = 0x4000,
   UV__HANDLE_REF      = 0x2000,
   UV__HANDLE_CLOSING  = 0 /* no-op on unix */
 };
 #else
-# define UV__HANDLE_INTERNAL  0x80
-# define UV__HANDLE_ACTIVE    0x40
-# define UV__HANDLE_REF       0x20
-# define UV__HANDLE_CLOSING   0x01
+# define UV__SIGNAL_ONE_SHOT_DISPATCHED   0x200
+# define UV__SIGNAL_ONE_SHOT              0x100
+# define UV__HANDLE_INTERNAL              0x80
+# define UV__HANDLE_ACTIVE                0x40
+# define UV__HANDLE_REF                   0x20
+# define UV__HANDLE_CLOSING               0x01
 #endif
 
 int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
@@ -215,6 +218,30 @@ void uv__fs_scandir_cleanup(uv_fs_t* req);
   }                                                                           \
   while (0)
 
+/* Note: uses an open-coded version of SET_REQ_SUCCESS() because of
+ * a circular dependency between src/uv-common.h and src/win/internal.h.
+ */
+#if defined(_WIN32)
+# define UV_REQ_INIT(req, typ)                                                \
+  do {                                                                        \
+    (req)->type = (typ);                                                      \
+    (req)->u.io.overlapped.Internal = 0;  /* SET_REQ_SUCCESS() */             \
+  }                                                                           \
+  while (0)
+#else
+# define UV_REQ_INIT(req, typ)                                                \
+  do {                                                                        \
+    (req)->type = (typ);                                                      \
+  }                                                                           \
+  while (0)
+#endif
+
+#define uv__req_init(loop, req, typ)                                          \
+  do {                                                                        \
+    UV_REQ_INIT(req, typ);                                                    \
+    uv__req_register(loop, req);                                              \
+  }                                                                           \
+  while (0)
 
 /* Allocator prototypes */
 void *uv__calloc(size_t count, size_t size);
diff --git a/Utilities/cmlibuv/src/win/async.c b/Utilities/cmlibuv/src/win/async.c
index ad240ab..0b636ed 100644
--- a/Utilities/cmlibuv/src/win/async.c
+++ b/Utilities/cmlibuv/src/win/async.c
@@ -45,8 +45,7 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
   handle->async_cb = async_cb;
 
   req = &handle->async_req;
-  uv_req_init(loop, req);
-  req->type = UV_WAKEUP;
+  UV_REQ_INIT(req, UV_WAKEUP);
   req->data = handle;
 
   uv__handle_start(handle);
diff --git a/Utilities/cmlibuv/src/win/atomicops-inl.h b/Utilities/cmlibuv/src/win/atomicops-inl.h
index 61e0060..6d8126f 100644
--- a/Utilities/cmlibuv/src/win/atomicops-inl.h
+++ b/Utilities/cmlibuv/src/win/atomicops-inl.h
@@ -23,6 +23,7 @@
 #define UV_WIN_ATOMICOPS_INL_H_
 
 #include "uv.h"
+#include "internal.h"
 
 
 /* Atomic set operation on char */
@@ -34,7 +35,7 @@
 /* target to be aligned. */
 #pragma intrinsic(_InterlockedOr8)
 
-static char __declspec(inline) uv__atomic_exchange_set(char volatile* target) {
+static char INLINE uv__atomic_exchange_set(char volatile* target) {
   return _InterlockedOr8(target, 1);
 }
 
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c
index 9d00afc..9ed4e82 100644
--- a/Utilities/cmlibuv/src/win/core.c
+++ b/Utilities/cmlibuv/src/win/core.c
@@ -35,10 +35,6 @@
 #include "handle-inl.h"
 #include "req-inl.h"
 
-
-static uv_loop_t default_loop_struct;
-static uv_loop_t* default_loop_ptr;
-
 /* uv_once initialization guards */
 static uv_once_t uv_init_guard_ = UV_ONCE_INIT;
 
@@ -87,13 +83,8 @@ static int uv__loops_capacity;
 #define UV__LOOPS_CHUNK_SIZE 8
 static uv_mutex_t uv__loops_lock;
 
-static void uv__loops_init() {
+static void uv__loops_init(void) {
   uv_mutex_init(&uv__loops_lock);
-  uv__loops = uv__calloc(UV__LOOPS_CHUNK_SIZE, sizeof(uv_loop_t*));
-  if (!uv__loops)
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  uv__loops_size = 0;
-  uv__loops_capacity = UV__LOOPS_CHUNK_SIZE;
 }
 
 static int uv__loops_add(uv_loop_t* loop) {
@@ -142,6 +133,13 @@ static void uv__loops_remove(uv_loop_t* loop) {
   uv__loops[uv__loops_size - 1] = NULL;
   --uv__loops_size;
 
+  if (uv__loops_size == 0) {
+    uv__loops_capacity = 0;
+    uv__free(uv__loops);
+    uv__loops = NULL;
+    goto loop_removed;
+  }
+
   /* If we didn't grow to big skip downsizing */
   if (uv__loops_capacity < 4 * UV__LOOPS_CHUNK_SIZE)
     goto loop_removed;
@@ -160,7 +158,7 @@ loop_removed:
   uv_mutex_unlock(&uv__loops_lock);
 }
 
-void uv__wake_all_loops() {
+void uv__wake_all_loops(void) {
   int i;
   uv_loop_t* loop;
 
@@ -336,6 +334,11 @@ int uv_backend_fd(const uv_loop_t* loop) {
 }
 
 
+int uv_loop_fork(uv_loop_t* loop) {
+  return UV_ENOSYS;
+}
+
+
 int uv_backend_timeout(const uv_loop_t* loop) {
   if (loop->stop_flag != 0)
     return 0;
diff --git a/Utilities/cmlibuv/src/win/detect-wakeup.c b/Utilities/cmlibuv/src/win/detect-wakeup.c
index a12179f..72dfb7a 100644
--- a/Utilities/cmlibuv/src/win/detect-wakeup.c
+++ b/Utilities/cmlibuv/src/win/detect-wakeup.c
@@ -2,9 +2,9 @@
 #include "internal.h"
 #include "winapi.h"
 
-static void uv__register_system_resume_callback();
+static void uv__register_system_resume_callback(void);
 
-void uv__init_detect_system_wakeup() {
+void uv__init_detect_system_wakeup(void) {
   /* Try registering system power event callback. This is the cleanest
    * method, but it will only work on Win8 and above.
    */
@@ -20,7 +20,7 @@ static ULONG CALLBACK uv__system_resume_callback(PVOID Context,
   return 0;
 }
 
-static void uv__register_system_resume_callback() {
+static void uv__register_system_resume_callback(void) {
   _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS recipient;
   _HPOWERNOTIFY registration_handle;
 
diff --git a/Utilities/cmlibuv/src/win/error.c b/Utilities/cmlibuv/src/win/error.c
index c512f35..642d111 100644
--- a/Utilities/cmlibuv/src/win/error.c
+++ b/Utilities/cmlibuv/src/win/error.c
@@ -71,6 +71,7 @@ int uv_translate_sys_error(int sys_errno) {
   switch (sys_errno) {
     case ERROR_NOACCESS:                    return UV_EACCES;
     case WSAEACCES:                         return UV_EACCES;
+    case ERROR_ELEVATION_REQUIRED:          return UV_EACCES;
     case ERROR_ADDRESS_ALREADY_ASSOCIATED:  return UV_EADDRINUSE;
     case WSAEADDRINUSE:                     return UV_EADDRINUSE;
     case WSAEADDRNOTAVAIL:                  return UV_EADDRNOTAVAIL;
diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c
index 03e4adc..95f843a 100644
--- a/Utilities/cmlibuv/src/win/fs-event.c
+++ b/Utilities/cmlibuv/src/win/fs-event.c
@@ -81,8 +81,17 @@ static void uv_relative_path(const WCHAR* filename,
 
 static int uv_split_path(const WCHAR* filename, WCHAR** dir,
     WCHAR** file) {
-  int len = wcslen(filename);
-  int i = len;
+  size_t len, i;
+ 
+  if (filename == NULL) {
+    if (dir != NULL)
+      *dir = NULL;
+    *file = NULL;
+    return 0;
+  }
+
+  len = wcslen(filename);
+  i = len;
   while (i > 0 && filename[--i] != '\\' && filename[i] != '/');
 
   if (i == 0) {
@@ -131,8 +140,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
   handle->short_filew = NULL;
   handle->dirw = NULL;
 
-  uv_req_init(loop, (uv_req_t*)&handle->req);
-  handle->req.type = UV_FS_EVENT_REQ;
+  UV_REQ_INIT(&handle->req, UV_FS_EVENT_REQ);
   handle->req.data = handle;
 
   return 0;
@@ -146,7 +154,8 @@ int uv_fs_event_start(uv_fs_event_t* handle,
   int name_size, is_path_dir;
   DWORD attr, last_error;
   WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
-  WCHAR short_path[MAX_PATH];
+  WCHAR short_path_buffer[MAX_PATH];
+  WCHAR* short_path;
 
   if (uv__is_active(handle))
     return UV_EINVAL;
@@ -188,7 +197,6 @@ int uv_fs_event_start(uv_fs_event_t* handle,
 
   if (is_path_dir) {
      /* path is a directory, so that's the directory that we will watch. */
-    handle->dirw = pathw;
     dir_to_watch = pathw;
   } else {
     /*
@@ -197,9 +205,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
      */
 
     /* Convert to short path. */
+    short_path = short_path_buffer;
     if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) {
-      last_error = GetLastError();
-      goto error;
+      short_path = NULL;
     }
 
     if (uv_split_path(pathw, &dir, &handle->filew) != 0) {
@@ -274,6 +282,8 @@ int uv_fs_event_start(uv_fs_event_t* handle,
     goto error;
   }
 
+  assert(is_path_dir ? pathw != NULL : pathw == NULL);
+  handle->dirw = pathw;
   handle->req_pending = 1;
   return 0;
 
@@ -305,6 +315,9 @@ error:
     handle->buffer = NULL;
   }
 
+  if (uv__is_active(handle))
+    uv__handle_stop(handle);
+
   return uv_translate_sys_error(last_error);
 }
 
@@ -344,8 +357,11 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
 }
 
 
-static int file_info_cmp(WCHAR* str, WCHAR* file_name, int file_name_len) {
-  int str_len;
+static int file_info_cmp(WCHAR* str, WCHAR* file_name, size_t file_name_len) {
+  size_t str_len;
+
+  if (str == NULL)
+    return -1;
 
   str_len = wcslen(str);
 
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index f1711ac..2d72cdc 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -114,7 +114,7 @@ const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
 const WCHAR UNC_PATH_PREFIX_LEN = 8;
 
 
-void uv_fs_init() {
+void uv_fs_init(void) {
   _fmode = _O_BINARY;
 }
 
@@ -123,7 +123,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
     const char* new_path, const int copy_path) {
   char* buf;
   char* pos;
-  ssize_t buf_sz = 0, path_len, pathw_len = 0, new_pathw_len = 0;
+  ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0;
 
   /* new_path can only be set if path is also set. */
   assert(new_path == NULL || path != NULL);
@@ -220,9 +220,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
 
 INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
     uv_fs_type fs_type, const uv_fs_cb cb) {
-  uv_req_init(loop, (uv_req_t*) req);
-
-  req->type = UV_FS;
+  UV_REQ_INIT(req, UV_FS);
   req->loop = loop;
   req->flags = 0;
   req->fs_type = fs_type;
@@ -403,7 +401,6 @@ void fs__open(uv_fs_t* req) {
   switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
   case _O_RDONLY:
     access = FILE_GENERIC_READ;
-    attributes |= FILE_FLAG_BACKUP_SEMANTICS;
     break;
   case _O_WRONLY:
     access = FILE_GENERIC_WRITE;
@@ -418,7 +415,6 @@ void fs__open(uv_fs_t* req) {
   if (flags & _O_APPEND) {
     access &= ~FILE_WRITE_DATA;
     access |= FILE_APPEND_DATA;
-    attributes &= ~FILE_FLAG_BACKUP_SEMANTICS;
   }
 
   /*
@@ -1375,7 +1371,7 @@ static void fs__access(uv_fs_t* req) {
    * - or it's a directory.
    * (Directories cannot be read-only on Windows.)
    */
-  if (!(req->flags & W_OK) ||
+  if (!(req->fs.info.mode & W_OK) ||
       !(attr & FILE_ATTRIBUTE_READONLY) ||
       (attr & FILE_ATTRIBUTE_DIRECTORY)) {
     SET_REQ_RESULT(req, 0);
@@ -2402,7 +2398,7 @@ int uv_fs_access(uv_loop_t* loop,
   if (err)
     return uv_translate_sys_error(err);
 
-  req->flags = flags;
+  req->fs.info.mode = flags;
 
   if (cb) {
     QUEUE_FS_TP_JOB(loop, req);
diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c
index 744f8e0..baab838 100644
--- a/Utilities/cmlibuv/src/win/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/win/getaddrinfo.c
@@ -262,15 +262,12 @@ int uv_getaddrinfo(uv_loop_t* loop,
   int err;
 
   if (req == NULL || (node == NULL && service == NULL)) {
-    err = WSAEINVAL;
-    goto error;
+    return UV_EINVAL;
   }
 
-  uv_req_init(loop, (uv_req_t*)req);
-
+  UV_REQ_INIT(req, UV_GETADDRINFO);
   req->getaddrinfo_cb = getaddrinfo_cb;
   req->addrinfo = NULL;
-  req->type = UV_GETADDRINFO;
   req->loop = loop;
   req->retcode = 0;
 
diff --git a/Utilities/cmlibuv/src/win/getnameinfo.c b/Utilities/cmlibuv/src/win/getnameinfo.c
index 66b64b8..9f10cd2 100644
--- a/Utilities/cmlibuv/src/win/getnameinfo.c
+++ b/Utilities/cmlibuv/src/win/getnameinfo.c
@@ -127,12 +127,11 @@ int uv_getnameinfo(uv_loop_t* loop,
     return UV_EINVAL;
   }
 
-  uv_req_init(loop, (uv_req_t*)req);
+  UV_REQ_INIT(req, UV_GETNAMEINFO);
   uv__req_register(loop, req);
 
   req->getnameinfo_cb = getnameinfo_cb;
   req->flags = flags;
-  req->type = UV_GETNAMEINFO;
   req->loop = loop;
   req->retcode = 0;
 
diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h
index 8a17e94..83601d5 100644
--- a/Utilities/cmlibuv/src/win/internal.h
+++ b/Utilities/cmlibuv/src/win/internal.h
@@ -210,7 +210,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);
 /*
  * TTY
  */
-void uv_console_init();
+void uv_console_init(void);
 
 int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
     uv_read_cb read_cb);
@@ -263,7 +263,7 @@ void uv_prepare_invoke(uv_loop_t* loop);
 void uv_check_invoke(uv_loop_t* loop);
 void uv_idle_invoke(uv_loop_t* loop);
 
-void uv__once_init();
+void uv__once_init(void);
 
 
 /*
@@ -279,7 +279,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
 /*
  * Signal watcher
  */
-void uv_signals_init();
+void uv_signals_init(void);
 int uv__signal_dispatch(int signum);
 
 void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle);
@@ -306,7 +306,7 @@ int uv_translate_sys_error(int sys_errno);
 /*
  * FS
  */
-void uv_fs_init();
+void uv_fs_init(void);
 
 
 /*
@@ -327,14 +327,15 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
 /*
  * Utilities.
  */
-void uv__util_init();
+void uv__util_init(void);
 
 uint64_t uv__hrtime(double scale);
-int uv_parent_pid();
-int uv_current_pid();
+int uv_parent_pid(void);
+int uv_current_pid(void);
 __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
 int uv__getpwuid_r(uv_passwd_t* pwd);
 int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
+int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
 
 
 /*
@@ -353,13 +354,13 @@ HANDLE uv__stdio_handle(BYTE* buffer, int fd);
 /*
  * Winapi and ntapi utility functions
  */
-void uv_winapi_init();
+void uv_winapi_init(void);
 
 
 /*
  * Winsock utility functions
  */
-void uv_winsock_init();
+void uv_winsock_init(void);
 
 int uv_ntstatus_to_winsock_error(NTSTATUS status);
 
@@ -388,11 +389,11 @@ extern struct sockaddr_in6 uv_addr_ip6_any_;
 /*
  * Wake all loops with fake message
  */
-void uv__wake_all_loops();
+void uv__wake_all_loops(void);
 
 /*
  * Init system wake-up detection
  */
-void uv__init_detect_system_wakeup();
+void uv__init_detect_system_wakeup(void);
 
 #endif /* UV_WIN_INTERNAL_H_ */
diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c
index 2442be7..edf3002 100644
--- a/Utilities/cmlibuv/src/win/pipe.c
+++ b/Utilities/cmlibuv/src/win/pipe.c
@@ -103,7 +103,7 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
   handle->pipe.conn.non_overlapped_writes_tail = NULL;
   handle->pipe.conn.readfile_thread = NULL;
 
-  uv_req_init(loop, (uv_req_t*) &handle->pipe.conn.ipc_header_write_req);
+  UV_REQ_INIT(&handle->pipe.conn.ipc_header_write_req, UV_UNKNOWN_REQ);
 
   return 0;
 }
@@ -505,8 +505,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
 
   for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
     req = &handle->pipe.serv.accept_reqs[i];
-    uv_req_init(loop, (uv_req_t*) req);
-    req->type = UV_ACCEPT;
+    UV_REQ_INIT(req, UV_ACCEPT);
     req->data = handle;
     req->pipeHandle = INVALID_HANDLE_VALUE;
     req->next_pending = NULL;
@@ -626,8 +625,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
   HANDLE pipeHandle = INVALID_HANDLE_VALUE;
   DWORD duplex_flags;
 
-  uv_req_init(loop, (uv_req_t*) req);
-  req->type = UV_CONNECT;
+  UV_REQ_INIT(req, UV_CONNECT);
   req->handle = (uv_stream_t*) handle;
   req->cb = cb;
 
@@ -962,7 +960,7 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) {
     uv_mutex_lock(m); /* mutex controls *setting* of readfile_thread */
     if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
                         GetCurrentProcess(), &hThread,
-                        0, TRUE, DUPLICATE_SAME_ACCESS)) {
+                        0, FALSE, DUPLICATE_SAME_ACCESS)) {
       handle->pipe.conn.readfile_thread = hThread;
     } else {
       hThread = NULL;
@@ -1239,8 +1237,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
 
   assert(handle->handle != INVALID_HANDLE_VALUE);
 
-  uv_req_init(loop, (uv_req_t*) req);
-  req->type = UV_WRITE;
+  UV_REQ_INIT(req, UV_WRITE);
   req->handle = (uv_stream_t*) handle;
   req->cb = cb;
   req->ipc_header = 0;
@@ -1301,8 +1298,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
         }
       }
 
-      uv_req_init(loop, (uv_req_t*) ipc_header_req);
-      ipc_header_req->type = UV_WRITE;
+      UV_REQ_INIT(ipc_header_req, UV_WRITE);
       ipc_header_req->handle = (uv_stream_t*) handle;
       ipc_header_req->cb = NULL;
       ipc_header_req->ipc_header = 1;
@@ -2076,7 +2072,6 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
   buffer[addrlen] = '\0';
 
   err = 0;
-  goto cleanup;
 
 error:
   uv__free(name_info);
diff --git a/Utilities/cmlibuv/src/win/poll.c b/Utilities/cmlibuv/src/win/poll.c
index d479e52..a648ba7 100644
--- a/Utilities/cmlibuv/src/win/poll.c
+++ b/Utilities/cmlibuv/src/win/poll.c
@@ -61,13 +61,13 @@ static void uv__init_overlapped_dummy(void) {
 }
 
 
-static OVERLAPPED* uv__get_overlapped_dummy() {
+static OVERLAPPED* uv__get_overlapped_dummy(void) {
   uv_once(&overlapped_dummy_init_guard_, uv__init_overlapped_dummy);
   return &overlapped_dummy_;
 }
 
 
-static AFD_POLL_INFO* uv__get_afd_poll_info_dummy() {
+static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) {
   return &afd_poll_info_dummy_;
 }
 
@@ -572,13 +572,11 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
 
   /* Initialize 2 poll reqs. */
   handle->submitted_events_1 = 0;
-  uv_req_init(loop, (uv_req_t*) &(handle->poll_req_1));
-  handle->poll_req_1.type = UV_POLL_REQ;
+  UV_REQ_INIT(&handle->poll_req_1, UV_POLL_REQ);
   handle->poll_req_1.data = handle;
 
   handle->submitted_events_2 = 0;
-  uv_req_init(loop, (uv_req_t*) &(handle->poll_req_2));
-  handle->poll_req_2.type = UV_POLL_REQ;
+  UV_REQ_INIT(&handle->poll_req_2, UV_POLL_REQ);
   handle->poll_req_2.data = handle;
 
   return 0;
diff --git a/Utilities/cmlibuv/src/win/process-stdio.c b/Utilities/cmlibuv/src/win/process-stdio.c
index e3c06f5..032e309 100644
--- a/Utilities/cmlibuv/src/win/process-stdio.c
+++ b/Utilities/cmlibuv/src/win/process-stdio.c
@@ -372,6 +372,7 @@ int uv__stdio_create(uv_loop_t* loop,
 
           case FILE_TYPE_PIPE:
             CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
+            break;
 
           case FILE_TYPE_CHAR:
           case FILE_TYPE_REMOTE:
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index 855c374..d141601 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -148,8 +148,7 @@ static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
   handle->child_stdio_buffer = NULL;
   handle->exit_cb_pending = 0;
 
-  uv_req_init(loop, (uv_req_t*)&handle->exit_req);
-  handle->exit_req.type = UV_PROCESS_EXIT;
+  UV_REQ_INIT(&handle->exit_req, UV_PROCESS_EXIT);
   handle->exit_req.data = handle;
 }
 
@@ -492,7 +491,7 @@ WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) {
    *   input : hello\\"world
    *   output: "hello\\\\\"world"
    *   input : hello world\
-   *   output: "hello world\"
+   *   output: "hello world\\"
    */
 
   *(target++) = L'"';
diff --git a/Utilities/cmlibuv/src/win/req-inl.h b/Utilities/cmlibuv/src/win/req-inl.h
index b5e502e..f2513b7 100644
--- a/Utilities/cmlibuv/src/win/req-inl.h
+++ b/Utilities/cmlibuv/src/win/req-inl.h
@@ -34,6 +34,9 @@
 #define SET_REQ_ERROR(req, error)                                       \
   SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error)))
 
+/* Note: used open-coded in UV_REQ_INIT() because of a circular dependency
+ * between src/uv-common.h and src/win/internal.h.
+ */
 #define SET_REQ_SUCCESS(req)                                            \
   SET_REQ_STATUS((req), STATUS_SUCCESS)
 
@@ -79,12 +82,6 @@
   }
 
 
-INLINE static void uv_req_init(uv_loop_t* loop, uv_req_t* req) {
-  req->type = UV_UNKNOWN_REQ;
-  SET_REQ_SUCCESS(req);
-}
-
-
 INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) {
   return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped);
 }
diff --git a/Utilities/cmlibuv/src/win/signal.c b/Utilities/cmlibuv/src/win/signal.c
index 2c64a55..7b42dd9 100644
--- a/Utilities/cmlibuv/src/win/signal.c
+++ b/Utilities/cmlibuv/src/win/signal.c
@@ -30,12 +30,19 @@
 RB_HEAD(uv_signal_tree_s, uv_signal_s);
 
 static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree);
-static ssize_t volatile uv__signal_control_handler_refs = 0;
 static CRITICAL_SECTION uv__signal_lock;
 
+static BOOL WINAPI uv__signal_control_handler(DWORD type);
 
-void uv_signals_init() {
+int uv__signal_start(uv_signal_t* handle,
+                     uv_signal_cb signal_cb,
+                     int signum,
+                     int oneshot);
+
+void uv_signals_init(void) {
   InitializeCriticalSection(&uv__signal_lock);
+  if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
+    abort();
 }
 
 
@@ -68,7 +75,9 @@ RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare
 int uv__signal_dispatch(int signum) {
   uv_signal_t lookup;
   uv_signal_t* handle;
-  int dispatched = 0;
+  int dispatched;
+
+  dispatched = 0;
 
   EnterCriticalSection(&uv__signal_lock);
 
@@ -81,11 +90,16 @@ int uv__signal_dispatch(int signum) {
     unsigned long previous = InterlockedExchange(
             (volatile LONG*) &handle->pending_signum, signum);
 
+    if (handle->flags & UV__SIGNAL_ONE_SHOT_DISPATCHED)
+      continue;
+
     if (!previous) {
       POST_COMPLETION_FOR_REQ(handle->loop, &handle->signal_req);
     }
 
     dispatched = 1;
+    if (handle->flags & UV__SIGNAL_ONE_SHOT)
+      handle->flags |= UV__SIGNAL_ONE_SHOT_DISPATCHED;
   }
 
   LeaveCriticalSection(&uv__signal_lock);
@@ -125,114 +139,14 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
 }
 
 
-static int uv__signal_register_control_handler() {
-  /* When this function is called, the uv__signal_lock must be held. */
-
-  /* If the console control handler has already been hooked, just add a */
-  /* reference. */
-  if (uv__signal_control_handler_refs > 0) {
-    uv__signal_control_handler_refs++;
-    return 0;
-  }
-
-  if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
-    return GetLastError();
-
-  uv__signal_control_handler_refs++;
-
-  return 0;
-}
-
-
-static void uv__signal_unregister_control_handler() {
-  /* When this function is called, the uv__signal_lock must be held. */
-  BOOL r;
-
-  /* Don't unregister if the number of console control handlers exceeds one. */
-  /* Just remove a reference in that case. */
-  if (uv__signal_control_handler_refs > 1) {
-    uv__signal_control_handler_refs--;
-    return;
-  }
-
-  assert(uv__signal_control_handler_refs == 1);
-
-  r = SetConsoleCtrlHandler(uv__signal_control_handler, FALSE);
-  /* This should never fail; if it does it is probably a bug in libuv. */
-  assert(r);
-
-  uv__signal_control_handler_refs--;
-}
-
-
-static int uv__signal_register(int signum) {
-  switch (signum) {
-    case SIGINT:
-    case SIGBREAK:
-    case SIGHUP:
-      return uv__signal_register_control_handler();
-
-    case SIGWINCH:
-      /* SIGWINCH is generated in tty.c. No need to register anything. */
-      return 0;
-
-    case SIGILL:
-    case SIGABRT_COMPAT:
-    case SIGFPE:
-    case SIGSEGV:
-    case SIGTERM:
-    case SIGABRT:
-      /* Signal is never raised. */
-      return 0;
-
-    default:
-      /* Invalid signal. */
-      return ERROR_INVALID_PARAMETER;
-  }
-}
-
-
-static void uv__signal_unregister(int signum) {
-  switch (signum) {
-    case SIGINT:
-    case SIGBREAK:
-    case SIGHUP:
-      uv__signal_unregister_control_handler();
-      return;
-
-    case SIGWINCH:
-      /* SIGWINCH is generated in tty.c. No need to unregister anything. */
-      return;
-
-    case SIGILL:
-    case SIGABRT_COMPAT:
-    case SIGFPE:
-    case SIGSEGV:
-    case SIGTERM:
-    case SIGABRT:
-      /* Nothing is registered for this signal. */
-      return;
-
-    default:
-      /* Libuv bug. */
-      assert(0 && "Invalid signum");
-      return;
-  }
-}
-
-
 int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
-  uv_req_t* req;
-
   uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);
   handle->pending_signum = 0;
   handle->signum = 0;
   handle->signal_cb = NULL;
 
-  req = &handle->signal_req;
-  uv_req_init(loop, req);
-  req->type = UV_SIGNAL_REQ;
-  req->data = handle;
+  UV_REQ_INIT(&handle->signal_req, UV_SIGNAL_REQ);
+  handle->signal_req.data = handle;
 
   return 0;
 }
@@ -247,8 +161,6 @@ int uv_signal_stop(uv_signal_t* handle) {
 
   EnterCriticalSection(&uv__signal_lock);
 
-  uv__signal_unregister(handle->signum);
-
   removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle);
   assert(removed_handle == handle);
 
@@ -262,14 +174,24 @@ int uv_signal_stop(uv_signal_t* handle) {
 
 
 int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
-  int err;
+  return uv__signal_start(handle, signal_cb, signum, 0);
+}
+
+
+int uv_signal_start_oneshot(uv_signal_t* handle,
+                            uv_signal_cb signal_cb,
+                            int signum) {
+  return uv__signal_start(handle, signal_cb, signum, 1);
+}
 
-  /* If the user supplies signum == 0, then return an error already. If the */
-  /* signum is otherwise invalid then uv__signal_register will find out */
-  /* eventually. */
-  if (signum == 0) {
+
+int uv__signal_start(uv_signal_t* handle,
+                            uv_signal_cb signal_cb,
+                            int signum,
+                            int oneshot) {
+  /* Test for invalid signal values. */
+  if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG))
     return UV_EINVAL;
-  }
 
   /* Short circuit: if the signal watcher is already watching {signum} don't */
   /* go through the process of deregistering and registering the handler. */
@@ -289,14 +211,10 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
 
   EnterCriticalSection(&uv__signal_lock);
 
-  err = uv__signal_register(signum);
-  if (err) {
-    /* Uh-oh, didn't work. */
-    LeaveCriticalSection(&uv__signal_lock);
-    return uv_translate_sys_error(err);
-  }
-
   handle->signum = signum;
+  if (oneshot)
+    handle->flags |= UV__SIGNAL_ONE_SHOT;
+
   RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
 
   LeaveCriticalSection(&uv__signal_lock);
@@ -325,6 +243,9 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
   if (dispatched_signum == handle->signum)
     handle->signal_cb(handle, dispatched_signum);
 
+  if (handle->flags & UV__SIGNAL_ONE_SHOT)
+    uv_signal_stop(handle);
+
   if (handle->flags & UV__HANDLE_CLOSING) {
     /* When it is closing, it must be stopped at this point. */
     assert(handle->signum == 0);
diff --git a/Utilities/cmlibuv/src/win/stream-inl.h b/Utilities/cmlibuv/src/win/stream-inl.h
index b7a3c11..bf12148 100644
--- a/Utilities/cmlibuv/src/win/stream-inl.h
+++ b/Utilities/cmlibuv/src/win/stream-inl.h
@@ -43,10 +43,9 @@ INLINE static void uv_connection_init(uv_stream_t* handle) {
   handle->flags |= UV_HANDLE_CONNECTION;
   handle->stream.conn.write_reqs_pending = 0;
 
-  uv_req_init(handle->loop, (uv_req_t*) &(handle->read_req));
+  UV_REQ_INIT(&handle->read_req, UV_READ);
   handle->read_req.event_handle = NULL;
   handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
-  handle->read_req.type = UV_READ;
   handle->read_req.data = handle;
 
   handle->stream.conn.shutdown_req = NULL;
diff --git a/Utilities/cmlibuv/src/win/stream.c b/Utilities/cmlibuv/src/win/stream.c
index a2466e5..13cbfdc 100644
--- a/Utilities/cmlibuv/src/win/stream.c
+++ b/Utilities/cmlibuv/src/win/stream.c
@@ -210,8 +210,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
     return UV_EPIPE;
   }
 
-  uv_req_init(loop, (uv_req_t*) req);
-  req->type = UV_SHUTDOWN;
+  UV_REQ_INIT(req, UV_SHUTDOWN);
   req->handle = handle;
   req->cb = cb;
 
diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c
index 0709696..972539f 100644
--- a/Utilities/cmlibuv/src/win/tcp.c
+++ b/Utilities/cmlibuv/src/win/tcp.c
@@ -555,7 +555,6 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
 
 
 int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
-  uv_loop_t* loop = handle->loop;
   unsigned int i, simultaneous_accepts;
   uv_tcp_accept_t* req;
   int err;
@@ -612,8 +611,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
 
     for (i = 0; i < simultaneous_accepts; i++) {
       req = &handle->tcp.serv.accept_reqs[i];
-      uv_req_init(loop, (uv_req_t*)req);
-      req->type = UV_ACCEPT;
+      UV_REQ_INIT(req, UV_ACCEPT);
       req->accept_socket = INVALID_SOCKET;
       req->data = handle;
 
@@ -635,8 +633,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
     /* try to clean up {uv_simultaneous_server_accepts} requests. */
     for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {
       req = &handle->tcp.serv.accept_reqs[i];
-      uv_req_init(loop, (uv_req_t*) req);
-      req->type = UV_ACCEPT;
+      UV_REQ_INIT(req, UV_ACCEPT);
       req->accept_socket = INVALID_SOCKET;
       req->data = handle;
       req->wait_handle = INVALID_HANDLE_VALUE;
@@ -779,8 +776,7 @@ static int uv_tcp_try_connect(uv_connect_t* req,
     }
   }
 
-  uv_req_init(loop, (uv_req_t*) req);
-  req->type = UV_CONNECT;
+  UV_REQ_INIT(req, UV_CONNECT);
   req->handle = (uv_stream_t*) handle;
   req->cb = cb;
   memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
@@ -863,8 +859,7 @@ int uv_tcp_write(uv_loop_t* loop,
   int result;
   DWORD bytes;
 
-  uv_req_init(loop, (uv_req_t*) req);
-  req->type = UV_WRITE;
+  UV_REQ_INIT(req, UV_WRITE);
   req->handle = (uv_stream_t*) handle;
   req->cb = cb;
 
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index 18d68d0..a6f5839 100644
--- a/Utilities/cmlibuv/src/win/tty.c
+++ b/Utilities/cmlibuv/src/win/tty.c
@@ -56,6 +56,7 @@
 #define ANSI_BACKSLASH_SEEN   0x80
 
 #define MAX_INPUT_BUFFER_LENGTH 8192
+#define MAX_CONSOLE_CHAR 8192
 
 #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
 #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
@@ -137,7 +138,7 @@ typedef enum {
 static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED;
 static void uv__determine_vterm_state(HANDLE handle);
 
-void uv_console_init() {
+void uv_console_init(void) {
   if (uv_sem_init(&uv_tty_output_lock, 1))
     abort();
 }
@@ -1003,6 +1004,9 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
   if (handle->tty.rd.last_key_len > 0) {
     SET_REQ_SUCCESS(&handle->read_req);
     uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
+    /* Make sure no attempt is made to insert it again until it's handled. */
+    handle->flags |= UV_HANDLE_READ_PENDING;
+    handle->reqs_pending++;
     return 0;
   }
 
@@ -1616,17 +1620,29 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
                              DWORD* error) {
   /* We can only write 8k characters at a time. Windows can't handle */
   /* much more characters in a single console write anyway. */
-  WCHAR utf16_buf[8192];
+  WCHAR utf16_buf[MAX_CONSOLE_CHAR];
+  WCHAR* utf16_buffer;
   DWORD utf16_buf_used = 0;
-  unsigned int i;
-
-#define FLUSH_TEXT()                                                \
-  do {                                                              \
-    if (utf16_buf_used > 0) {                                       \
-      uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error);   \
-      utf16_buf_used = 0;                                           \
-    }                                                               \
-  } while (0)
+  unsigned int i, len, max_len, pos;
+  int allocate = 0;
+
+#define FLUSH_TEXT()                                                 \
+  do {                                                               \
+    pos = 0;                                                         \
+    do {                                                             \
+      len = utf16_buf_used - pos;                                    \
+      if (len > MAX_CONSOLE_CHAR)                                    \
+        len = MAX_CONSOLE_CHAR;                                      \
+      uv_tty_emit_text(handle, &utf16_buffer[pos], len, error);      \
+      pos += len;                                                    \
+    } while (pos < utf16_buf_used);                                  \
+    if (allocate) {                                                  \
+      uv__free(utf16_buffer);                                        \
+      allocate = 0;                                                  \
+      utf16_buffer = utf16_buf;                                      \
+    }                                                                \
+    utf16_buf_used = 0;                                              \
+ } while (0)
 
 #define ENSURE_BUFFER_SPACE(wchars_needed)                          \
   if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) {     \
@@ -1644,38 +1660,47 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
   /* state. */
   *error = ERROR_SUCCESS;
 
+  utf16_buffer = utf16_buf;
+
   uv_sem_wait(&uv_tty_output_lock);
 
   for (i = 0; i < nbufs; i++) {
     uv_buf_t buf = bufs[i];
     unsigned int j;
 
-  if (uv__vterm_state == UV_SUPPORTED) {
-    utf16_buf_used = MultiByteToWideChar(CP_UTF8,
-                                         0,
-                                         buf.base,
-                                         buf.len,
-                                         NULL,
-                                         0);
+    if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) {
+      utf16_buf_used = MultiByteToWideChar(CP_UTF8,
+                                           0,
+                                           buf.base,
+                                           buf.len,
+                                           NULL,
+                                           0);
+
+      if (utf16_buf_used == 0) {
+        *error = GetLastError();
+        break;
+      }
 
-    if (utf16_buf_used == 0) {
-      *error = GetLastError();
-      break;
-    }
+      max_len = (utf16_buf_used + 1) * sizeof(WCHAR);
+      allocate = max_len > MAX_CONSOLE_CHAR;
+      if (allocate)
+        utf16_buffer = uv__malloc(max_len);
+      if (!MultiByteToWideChar(CP_UTF8,
+                               0,
+                               buf.base,
+                               buf.len,
+                               utf16_buffer,
+                               utf16_buf_used)) {
+        if (allocate)
+          uv__free(utf16_buffer);
+        *error = GetLastError();
+        break;
+      }
 
-    if (!MultiByteToWideChar(CP_UTF8,
-                             0,
-                             buf.base,
-                             buf.len,
-                             utf16_buf,
-                             utf16_buf_used)) {
-      *error = GetLastError();
-      break;
-    }
+      FLUSH_TEXT();
 
-    FLUSH_TEXT();
-    continue;
-  }
+      continue;
+    }
 
     for (j = 0; j < buf.len; j++) {
       unsigned char c = buf.base[j];
@@ -2101,8 +2126,7 @@ int uv_tty_write(uv_loop_t* loop,
                  uv_write_cb cb) {
   DWORD error;
 
-  uv_req_init(loop, (uv_req_t*) req);
-  req->type = UV_WRITE;
+  UV_REQ_INIT(req, UV_WRITE);
   req->handle = (uv_stream_t*) handle;
   req->cb = cb;
 
diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c
index 9bf1453..2fd15cf 100644
--- a/Utilities/cmlibuv/src/win/udp.c
+++ b/Utilities/cmlibuv/src/win/udp.c
@@ -142,8 +142,7 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
   handle->func_wsarecvfrom = WSARecvFrom;
   handle->send_queue_size = 0;
   handle->send_queue_count = 0;
-  uv_req_init(loop, (uv_req_t*) &(handle->recv_req));
-  handle->recv_req.type = UV_UDP_RECV;
+  UV_REQ_INIT(&handle->recv_req, UV_UDP_RECV);
   handle->recv_req.data = handle;
 
   /* If anything fails beyond this point we need to remove the handle from
@@ -417,8 +416,7 @@ static int uv__send(uv_udp_send_t* req,
   uv_loop_t* loop = handle->loop;
   DWORD result, bytes;
 
-  uv_req_init(loop, (uv_req_t*) req);
-  req->type = UV_UDP_SEND;
+  UV_REQ_INIT(req, UV_UDP_SEND);
   req->handle = handle;
   req->cb = cb;
   memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c
index 050058a..d2e7f77 100644
--- a/Utilities/cmlibuv/src/win/util.c
+++ b/Utilities/cmlibuv/src/win/util.c
@@ -59,6 +59,17 @@
 # define UNLEN 256
 #endif
 
+/*
+  Max hostname length. The Windows gethostname() documentation states that 256
+  bytes will always be large enough to hold the null-terminated hostname.
+*/
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 256
+#endif
+
+/* Maximum environment variable size, including the terminating null */
+#define MAX_ENV_VAR_LENGTH 32767
+
 /* Cached copy of the process title, plus a mutex guarding it. */
 static char *process_title;
 static CRITICAL_SECTION process_title_lock;
@@ -74,7 +85,7 @@ static double hrtime_interval_ = 0;
 /*
  * One-time initialization code for functionality defined in util.c.
  */
-void uv__util_init() {
+void uv__util_init(void) {
   LARGE_INTEGER perf_frequency;
 
   /* Initialize process title access mutex. */
@@ -320,7 +331,7 @@ uint64_t uv_get_total_memory(void) {
 }
 
 
-int uv_parent_pid() {
+int uv_parent_pid(void) {
   int parent_pid = -1;
   HANDLE handle;
   PROCESSENTRY32 pe;
@@ -343,7 +354,7 @@ int uv_parent_pid() {
 }
 
 
-int uv_current_pid() {
+int uv_current_pid(void) {
   if (current_pid == 0) {
     current_pid = GetCurrentProcessId();
   }
@@ -405,7 +416,7 @@ done:
 }
 
 
-static int uv__get_process_title() {
+static int uv__get_process_title(void) {
   WCHAR title_w[MAX_TITLE_LENGTH];
 
   if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {
@@ -1322,6 +1333,47 @@ int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) {
 }
 
 
+/*
+ * Converts a UTF-8 string into a UTF-16 one. The resulting string is
+ * null-terminated.
+ *
+ * If utf8 is null terminated, utf8len can be set to -1, otherwise it must
+ * be specified.
+ */
+int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) {
+  int bufsize;
+
+  if (utf8 == NULL)
+    return UV_EINVAL;
+
+  /* Check how much space we need */
+  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, NULL, 0);
+
+  if (bufsize == 0)
+    return uv_translate_sys_error(GetLastError());
+
+  /* Allocate the destination buffer adding an extra byte for the terminating
+   * NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so
+   * we do it ourselves always, just in case. */
+  *utf16 = uv__malloc(sizeof(WCHAR) * (bufsize + 1));
+
+  if (*utf16 == NULL)
+    return UV_ENOMEM;
+
+  /* Convert to UTF-16 */
+  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
+
+  if (bufsize == 0) {
+    uv__free(*utf16);
+    *utf16 = NULL;
+    return uv_translate_sys_error(GetLastError());
+  }
+
+  (*utf16)[bufsize] = '\0';
+  return 0;
+}
+
+
 int uv__getpwuid_r(uv_passwd_t* pwd) {
   HANDLE token;
   wchar_t username[UNLEN + 1];
@@ -1387,3 +1439,138 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
 int uv_os_get_passwd(uv_passwd_t* pwd) {
   return uv__getpwuid_r(pwd);
 }
+
+
+int uv_os_getenv(const char* name, char* buffer, size_t* size) {
+  wchar_t var[MAX_ENV_VAR_LENGTH];
+  wchar_t* name_w;
+  DWORD bufsize;
+  size_t len;
+  int r;
+
+  if (name == NULL || buffer == NULL || size == NULL || *size == 0)
+    return UV_EINVAL;
+
+  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
+
+  if (r != 0)
+    return r;
+
+  len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH);
+  uv__free(name_w);
+  assert(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */
+
+  if (len == 0) {
+    r = GetLastError();
+
+    if (r == ERROR_ENVVAR_NOT_FOUND)
+      return UV_ENOENT;
+
+    return uv_translate_sys_error(r);
+  }
+
+  /* Check how much space we need */
+  bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);
+
+  if (bufsize == 0) {
+    return uv_translate_sys_error(GetLastError());
+  } else if (bufsize > *size) {
+    *size = bufsize;
+    return UV_ENOBUFS;
+  }
+
+  /* Convert to UTF-8 */
+  bufsize = WideCharToMultiByte(CP_UTF8,
+                                0,
+                                var,
+                                -1,
+                                buffer,
+                                *size,
+                                NULL,
+                                NULL);
+
+  if (bufsize == 0)
+    return uv_translate_sys_error(GetLastError());
+
+  *size = bufsize - 1;
+  return 0;
+}
+
+
+int uv_os_setenv(const char* name, const char* value) {
+  wchar_t* name_w;
+  wchar_t* value_w;
+  int r;
+
+  if (name == NULL || value == NULL)
+    return UV_EINVAL;
+
+  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
+
+  if (r != 0)
+    return r;
+
+  r = uv__convert_utf8_to_utf16(value, -1, &value_w);
+
+  if (r != 0) {
+    uv__free(name_w);
+    return r;
+  }
+
+  r = SetEnvironmentVariableW(name_w, value_w);
+  uv__free(name_w);
+  uv__free(value_w);
+
+  if (r == 0)
+    return uv_translate_sys_error(GetLastError());
+
+  return 0;
+}
+
+
+int uv_os_unsetenv(const char* name) {
+  wchar_t* name_w;
+  int r;
+
+  if (name == NULL)
+    return UV_EINVAL;
+
+  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
+
+  if (r != 0)
+    return r;
+
+  r = SetEnvironmentVariableW(name_w, NULL);
+  uv__free(name_w);
+
+  if (r == 0)
+    return uv_translate_sys_error(GetLastError());
+
+  return 0;
+}
+
+
+int uv_os_gethostname(char* buffer, size_t* size) {
+  char buf[MAXHOSTNAMELEN + 1];
+  size_t len;
+
+  if (buffer == NULL || size == NULL || *size == 0)
+    return UV_EINVAL;
+
+  uv__once_init(); /* Initialize winsock */
+
+  if (gethostname(buf, sizeof(buf)) != 0)
+    return uv_translate_sys_error(WSAGetLastError());
+
+  buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
+  len = strlen(buf);
+
+  if (len >= *size) {
+    *size = len + 1;
+    return UV_ENOBUFS;
+  }
+
+  memcpy(buffer, buf, len + 1);
+  *size = len;
+  return 0;
+}
diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c
index 1fa179b..aa5d719 100644
--- a/Utilities/cmlibuv/src/win/winapi.c
+++ b/Utilities/cmlibuv/src/win/winapi.c
@@ -53,7 +53,7 @@ sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
 sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
 
 
-void uv_winapi_init() {
+void uv_winapi_init(void) {
   HMODULE ntdll_module;
   HMODULE kernel32_module;
   HMODULE powrprof_module;
diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h
index 597a93d..4b0eeca 100644
--- a/Utilities/cmlibuv/src/win/winapi.h
+++ b/Utilities/cmlibuv/src/win/winapi.h
@@ -4615,6 +4615,10 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
 #endif
 
 /* from winerror.h */
+#ifndef ERROR_ELEVATION_REQUIRED
+# define ERROR_ELEVATION_REQUIRED 740
+#endif
+
 #ifndef ERROR_SYMLINK_NOT_SUPPORTED
 # define ERROR_SYMLINK_NOT_SUPPORTED 1464
 #endif
diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c
index d2e667e..e86d76b 100644
--- a/Utilities/cmlibuv/src/win/winsock.c
+++ b/Utilities/cmlibuv/src/win/winsock.c
@@ -80,7 +80,7 @@ static int error_means_no_support(DWORD error) {
 }
 
 
-void uv_winsock_init() {
+void uv_winsock_init(void) {
   WSADATA wsa_data;
   int errorno;
   SOCKET dummy;
diff --git a/bootstrap b/bootstrap
index 8063edb..84df54a 100755
--- a/bootstrap
+++ b/bootstrap
@@ -6,6 +6,17 @@ die() {
   echo "$@" 1>&2 ; exit 1
 }
 
+# Compile flag extraction function.
+cmake_extract_standard_flags()
+{
+  cd "${cmake_source_dir}/Modules/Compiler/"
+  for file in ${1:-*}-${2}.cmake; do
+    cat "${file}" \
+      | sed -n "s/ *set *( *CMAKE_${2}${3}_EXTENSION_COMPILE_OPTION *\"\{0,1\}\([^\")]*\).*/\1/p" \
+      | tr ';' ' '
+  done
+}
+
 # Version number extraction function.
 cmake_version_component()
 {
@@ -255,8 +266,6 @@ CMAKE_CXX_SOURCES="\
   cmCPackPropertiesGenerator \
   cmCacheManager \
   cmCommand \
-  cmCommandArgumentLexer \
-  cmCommandArgumentParser \
   cmCommandArgumentParserHelper \
   cmCommandArgumentsHelper \
   cmCommands \
@@ -276,6 +285,7 @@ CMAKE_CXX_SOURCES="\
   cmDefinitions \
   cmDepends \
   cmDependsC \
+  cmDisallowedCommand \
   cmDocumentationFormatter \
   cmEnableLanguageCommand \
   cmEnableTestingCommand \
@@ -288,8 +298,6 @@ CMAKE_CXX_SOURCES="\
   cmExportSet \
   cmExportSetMap \
   cmExportTryCompileFileGenerator \
-  cmExprLexer \
-  cmExprParser \
   cmExprParserHelper \
   cmExternalMakefileProjectGenerator \
   cmFileCommand \
@@ -404,6 +412,7 @@ CMAKE_CXX_SOURCES="\
   cmUnsetCommand \
   cmVersion \
   cmWhileCommand \
+  cmWorkingDirectory \
   cmake  \
   cmakemain \
   cmcmd  \
@@ -415,9 +424,16 @@ if ${cmake_system_mingw}; then
     cmGlobalMinGWMakefileGenerator"
 fi
 
-CMAKE_C_SOURCES="\
+LexerParser_CXX_SOURCES="\
+  cmCommandArgumentLexer \
+  cmCommandArgumentParser \
+  cmExprLexer \
+  cmExprParser \
+"
+
+LexerParser_C_SOURCES="\
   cmListFileLexer \
-  "
+"
 
 if ${cmake_system_mingw}; then
   KWSYS_C_SOURCES="\
@@ -855,7 +871,7 @@ cmake_toolchains=''
 case "${cmake_system}" in
   *AIX*)   cmake_toolchains='XL GNU' ;;
   *CYGWIN*) cmake_toolchains='GNU' ;;
-  *Darwin*) cmake_toolchains='GNU Clang' ;;
+  *Darwin*) cmake_toolchains='Clang GNU' ;;
   *Linux*) cmake_toolchains='GNU Clang XL PGI PathScale' ;;
   *MINGW*) cmake_toolchains='GNU' ;;
 esac
@@ -949,6 +965,17 @@ for a in ${cmake_c_compilers}; do
     cmake_c_compiler="${a}"
   fi
 done
+for std in 11 99 90; do
+  try_flags="`cmake_extract_standard_flags \"${cmake_toolchain}\" C \"${std}\"`"
+  for flag in $try_flags; do
+    echo "Checking whether ${cmake_c_compiler} supports ${flag}" >> cmake_bootstrap.log 2>&1
+    if cmake_try_run "${cmake_c_compiler}" "${cmake_c_flags} ${flag}" \
+      "${TMPFILE}.c" >> cmake_bootstrap.log 2>&1; then
+      cmake_c_flags="${cmake_c_flags} ${flag}"
+      break 2
+    fi
+  done
+done
 rm -f "${TMPFILE}.c"
 
 if [ -z "${cmake_c_compiler}" ]; then
@@ -983,6 +1010,10 @@ echo '
 # include <iostream.h>
 #endif
 
+#if __cplusplus >= 201103L && defined(__SUNPRO_CC) && __SUNPRO_CC < 0x5140
+#error "SunPro <= 5.13 C++ 11 mode not supported due to bug in move semantics."
+#endif
+
 class NeedCXX
 {
 public:
@@ -1010,6 +1041,17 @@ for a in ${cmake_cxx_compilers}; do
     fi
   done
 done
+for std in 14 11 98; do
+  try_flags="`cmake_extract_standard_flags \"${cmake_toolchain}\" CXX \"${std}\"`"
+  for flag in $try_flags; do
+    echo "Checking for wheter ${cmake_cxx_flags} supports ${flag}" >> cmake_bootstrap.log 2>&1
+    if cmake_try_run "${cmake_cxx_compiler}" "${cmake_cxx_flags} ${flag} -DTEST1" \
+      "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then
+      cmake_cxx_flags="${cmake_cxx_flags} ${flag} "
+      break 2
+    fi
+  done
+done
 rm -f "${TMPFILE}.cxx"
 
 if [ -z "${cmake_cxx_compiler}" ]; then
@@ -1106,84 +1148,6 @@ rm -f "${TMPFILE}.cxx"
 if [ "x${cmake_cxx_compiler_is_gnu}" != "x1" ]; then
   # Check for non-GNU compiler flags
 
-  # If we are on IRIX, check for -LANG:std
-  cmake_test_flags="-LANG:std"
-  if [ "x${cmake_system}" = "xIRIX64" ]; then
-    TMPFILE=`cmake_tmp_file`
-    echo '
-    #include <iostream>
-    int main() { std::cout << "No need for '"${cmake_test_flags}"'" << std::endl; return 0;}
-' > ${TMPFILE}.cxx
-    cmake_need_lang_std=0
-    if cmake_try_run "${cmake_cxx_compiler}" \
-      "${cmake_cxx_flags}" "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then
-      :
-    else
-      if cmake_try_run "${cmake_cxx_compiler}" \
-        "${cmake_cxx_flags} ${cmake_test_flags}" "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then
-        cmake_need_lang_std=1
-      fi
-    fi
-    if [ "x${cmake_need_lang_std}" = "x1" ]; then
-      cmake_cxx_flags="${cmake_cxx_flags} ${cmake_test_flags}"
-      echo "${cmake_cxx_compiler} needs ${cmake_test_flags}"
-    else
-      echo "${cmake_cxx_compiler} does not need ${cmake_test_flags}"
-    fi
-    rm -f "${TMPFILE}.cxx"
-  fi
-  cmake_test_flags=
-
-  # If we are on OSF, check for -timplicit_local -no_implicit_include
-  cmake_test_flags="-timplicit_local -no_implicit_include"
-  if [ "x${cmake_system}" = "xOSF1" ]; then
-    TMPFILE=`cmake_tmp_file`
-    echo '
-    #include <iostream>
-    int main() { std::cout << "We need '"${cmake_test_flags}"'" << std::endl; return 0;}
-' > ${TMPFILE}.cxx
-    cmake_need_flags=1
-    if cmake_try_run "${cmake_cxx_compiler}" \
-      "${cmake_cxx_flags} ${cmake_test_flags}" "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then
-      :
-    else
-      cmake_need_flags=0
-    fi
-    if [ "x${cmake_need_flags}" = "x1" ]; then
-      cmake_cxx_flags="${cmake_cxx_flags} ${cmake_test_flags}"
-      echo "${cmake_cxx_compiler} needs ${cmake_test_flags}"
-    else
-      echo "${cmake_cxx_compiler} does not need ${cmake_test_flags}"
-    fi
-    rm -f "${TMPFILE}.cxx"
-  fi
-  cmake_test_flags=
-
-  # If we are on OSF, check for -std strict_ansi -nopure_cname
-  cmake_test_flags="-std strict_ansi -nopure_cname"
-  if [ "x${cmake_system}" = "xOSF1" ]; then
-    TMPFILE=`cmake_tmp_file`
-    echo '
-    #include <iostream>
-    int main() { std::cout << "We need '"${cmake_test_flags}"'" << std::endl; return 0;}
-' > ${TMPFILE}.cxx
-    cmake_need_flags=1
-    if cmake_try_run "${cmake_cxx_compiler}" \
-      "${cmake_cxx_flags} ${cmake_test_flags}" "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then
-      :
-    else
-      cmake_need_flags=0
-    fi
-    if [ "x${cmake_need_flags}" = "x1" ]; then
-      cmake_cxx_flags="${cmake_cxx_flags} ${cmake_test_flags}"
-      echo "${cmake_cxx_compiler} needs ${cmake_test_flags}"
-    else
-      echo "${cmake_cxx_compiler} does not need ${cmake_test_flags}"
-    fi
-    rm -f "${TMPFILE}.cxx"
-  fi
-  cmake_test_flags=
-
   # If we are on HP-UX, check for -Ae for the C compiler.
   if [ "x${cmake_system}" = "xHP-UX" ]; then
     cmake_test_flags="-Ae"
@@ -1235,34 +1199,6 @@ if [ "x${cmake_cxx_compiler_is_gnu}" != "x1" ]; then
 fi
 
 
-if [ "x${cmake_cxx_compiler_is_gnu}" != "x1" ]; then
-  # Are we SolarisStudio?
-
-  TMPFILE=`cmake_tmp_file`
-  echo '
-  #if defined(__SUNPRO_CC)
-  #include <iostream>
-  int main() { std::cout << "This is SolarisStudio" << std::endl; return 0;}
-  #endif
-  ' > ${TMPFILE}.cxx
-  cmake_cxx_compiler_is_solarisstudio=0
-  if cmake_try_run "${cmake_cxx_compiler}" \
-    "${cmake_cxx_flags} " "${TMPFILE}.cxx" >> cmake_bootstrap.log 2>&1; then
-    cmake_cxx_compiler_is_solarisstudio=1
-  fi
-  if [ "x${cmake_cxx_compiler_is_solarisstudio}" = "x1" ]; then
-    echo "${cmake_cxx_compiler} is SolarisStudio compiler"
-  else
-    echo "${cmake_cxx_compiler} is not SolarisStudio compiler"
-  fi
-  rm -f "${TMPFILE}.cxx"
-
-  if [ "x${cmake_cxx_compiler_is_solarisstudio}" = "x1" ]; then
-    cmake_cxx_flags="${cmake_cxx_flags} -library=stlport4"
-  fi
-fi
-
-
 # Test for kwsys features
 KWSYS_NAME_IS_KWSYS=0
 KWSYS_BUILD_SHARED=0
@@ -1341,6 +1277,8 @@ cmake_compiler_settings_comment="/*
  *
  * Sources:
  * ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES}
+ * LexerParser Sources:
+ * ${LexerParser_CXX_SOURCES} ${LexerParser_C_SOURCES}
  * kwSys Sources:
  * ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES}
  */
@@ -1368,8 +1306,11 @@ cmake_report cmConfigure.h${_tmp} "#define CMAKE_BOOTSTRAP_BINARY_DIR \"${CMAKE_
 cmake_report cmConfigure.h${_tmp} "#define CMAKE_BIN_DIR \"/bootstrap-not-insalled\""
 cmake_report cmConfigure.h${_tmp} "#define CMAKE_DATA_DIR \"/bootstrap-not-insalled\""
 cmake_report cmConfigure.h${_tmp} "#define CMAKE_BOOTSTRAP"
+cmake_report cmConfigure.h${_tmp} "#define CM_EQ_DELETE"
+cmake_report cmConfigure.h${_tmp} "#define CM_FALLTHROUGH"
 cmake_report cmConfigure.h${_tmp} "#define CM_NULLPTR 0"
 cmake_report cmConfigure.h${_tmp} "#define CM_OVERRIDE"
+cmake_report cmConfigure.h${_tmp} "#define CM_DISABLE_COPY(Class)"
 
 # Regenerate configured headers
 for h in Configure VersionConfig; do
@@ -1400,7 +1341,7 @@ cmake_generate_file "${cmake_bootstrap_dir}/cmThirdParty.h" ""
 # Generate Makefile
 dep="cmConfigure.h cmsys/*.hxx cmsys/*.h `cmake_escape \"${cmake_source_dir}\"`/Source/*.h"
 objs=""
-for a in ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES}; do
+for a in ${CMAKE_CXX_SOURCES} ${CMAKE_C_SOURCES} ${LexerParser_CXX_SOURCES} ${LexerParser_C_SOURCES} ${KWSYS_CXX_SOURCES} ${KWSYS_C_SOURCES}; do
   objs="${objs} ${a}.o"
 done
 
@@ -1419,6 +1360,7 @@ fi
 cmake_c_flags_String="-DKWSYS_STRING_C"
 if ${cmake_system_mingw}; then
   cmake_c_flags_EncodingC="-DKWSYS_ENCODING_DEFAULT_CODEPAGE=CP_ACP"
+  cmake_cxx_flags_EncodingCXX="${cmake_c_flags_EncodingC}"
   cmake_cxx_flags_cmProcessOutput="${cmake_c_flags_EncodingC}"
 fi
 cmake_cxx_flags_SystemTools="
@@ -1428,9 +1370,15 @@ cmake_cxx_flags_SystemTools="
   -DKWSYS_CXX_HAS_UTIMENSAT=${KWSYS_CXX_HAS_UTIMENSAT}
   -DKWSYS_CXX_HAS_UTIMES=${KWSYS_CXX_HAS_UTIMES}
 "
-cmake_c_flags="${cmake_c_flags}-I`cmake_escape \"${cmake_bootstrap_dir}\"` -I`cmake_escape \"${cmake_source_dir}/Source\"` \
+cmake_c_flags="${cmake_c_flags} \
+  -I`cmake_escape \"${cmake_bootstrap_dir}\"` \
+  -I`cmake_escape \"${cmake_source_dir}/Source\"` \
+  -I`cmake_escape \"${cmake_source_dir}/Source/LexerParser\"` \
   -I`cmake_escape \"${cmake_source_dir}/Utilities\"`"
-cmake_cxx_flags="${cmake_cxx_flags} -I`cmake_escape \"${cmake_bootstrap_dir}\"` -I`cmake_escape \"${cmake_source_dir}/Source\"` \
+cmake_cxx_flags="${cmake_cxx_flags} \
+  -I`cmake_escape \"${cmake_bootstrap_dir}\"` \
+  -I`cmake_escape \"${cmake_source_dir}/Source\"` \
+  -I`cmake_escape \"${cmake_source_dir}/Source/LexerParser\"` \
   -I`cmake_escape \"${cmake_source_dir}/Utilities\"`"
 echo "cmake: ${objs}" > "${cmake_bootstrap_dir}/Makefile"
 echo "	${cmake_cxx_compiler} ${cmake_ld_flags} ${cmake_cxx_flags} ${objs} -o cmake" >> "${cmake_bootstrap_dir}/Makefile"
@@ -1440,13 +1388,22 @@ for a in ${CMAKE_CXX_SOURCES}; do
   echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile"
   echo "	${cmake_cxx_compiler} ${cmake_cxx_flags} ${src_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile"
 done
-echo "cmBootstrapCommands1.o : $cmBootstrapCommands1Deps" >> "${cmake_bootstrap_dir}/Makefile"
-echo "cmBootstrapCommands2.o : $cmBootstrapCommands2Deps" >> "${cmake_bootstrap_dir}/Makefile"
 for a in ${CMAKE_C_SOURCES}; do
   src=`cmake_escape "${cmake_source_dir}/Source/${a}.c"`
   echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile"
   echo "	${cmake_c_compiler} ${cmake_c_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile"
 done
+for a in ${LexerParser_CXX_SOURCES}; do
+  src=`cmake_escape "${cmake_source_dir}/Source/LexerParser/${a}.cxx"`
+  src_flags=`eval echo \\${cmake_cxx_flags_\${a}}`
+  echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile"
+  echo "	${cmake_cxx_compiler} ${cmake_cxx_flags} ${src_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile"
+done
+for a in ${LexerParser_C_SOURCES}; do
+  src=`cmake_escape "${cmake_source_dir}/Source/LexerParser/${a}.c"`
+  echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile"
+  echo "	${cmake_c_compiler} ${cmake_c_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile"
+done
 for a in ${KWSYS_C_SOURCES}; do
   src=`cmake_escape "${cmake_source_dir}/Source/kwsys/${a}.c"`
   src_flags=`eval echo \\${cmake_c_flags_\${a}}`

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-cmake/cmake.git



More information about the Pkg-cmake-commits mailing list