Merge branch 'release'
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 @@
 
 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/CMakeLists.txt b/CMakeLists.txt
index bec81a3..ed5de10 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -421,14 +421,15 @@
       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 +450,14 @@
     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")
@@ -507,12 +509,6 @@
     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)
@@ -810,6 +806,7 @@
     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..434f0f4 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,13 +24,18 @@
 To contribute patches:
 
 #. Fork the upstream `CMake Repository`_ into a personal account.
+#. Run `Utilities/SetupForDevelopment.sh`_ for local configuration.
 #. 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
+.. _`Utilities/SetupForDevelopment.sh`: Utilities/SetupForDevelopment.sh
+.. _`CMake Review Process`: Help/dev/review.rst
 
 Code Style
 ==========
diff --git a/Help/command/find_library.rst b/Help/command/find_library.rst
index 1eb50f7..f774f17 100644
--- a/Help/command/find_library.rst
+++ b/Help/command/find_library.rst
@@ -49,6 +49,14 @@
 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 +64,13 @@
 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/dev/README.rst b/Help/dev/README.rst
new file mode 100644
index 0000000..0dc512a
--- /dev/null
+++ b/Help/dev/README.rst
@@ -0,0 +1,31 @@
+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
diff --git a/Help/dev/review.rst b/Help/dev/review.rst
new file mode 100644
index 0000000..3004a14
--- /dev/null
+++ b/Help/dev/review.rst
@@ -0,0 +1,337 @@
+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!
+
+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@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``, or ``vs<year>``
+
+.. _`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.
+
+* 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@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/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 @@
 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/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-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,10 +7,64 @@
 
    .. contents::
 
-Normal Commands
-===============
+Scripting Commands
+==================
 
-These commands may be used freely in CMake projects.
+These commands are always available.
+
+.. toctree::
+   :maxdepth: 1
+
+   /command/break
+   /command/cmake_host_system_information
+   /command/cmake_minimum_required
+   /command/cmake_parse_arguments
+   /command/cmake_policy
+   /command/configure_file
+   /command/continue
+   /command/elseif
+   /command/else
+   /command/endforeach
+   /command/endfunction
+   /command/endif
+   /command/endmacro
+   /command/endwhile
+   /command/execute_process
+   /command/file
+   /command/find_file
+   /command/find_library
+   /command/find_package
+   /command/find_path
+   /command/find_program
+   /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
@@ -25,73 +79,31 @@
    /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/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 @@
    /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 @@
    /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-modules.7.rst b/Help/manual/cmake-modules.7.rst
index c478a1b..1e8342c 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -27,6 +27,7 @@
    /module/CheckFortranFunctionExists
    /module/CheckFortranSourceCompiles
    /module/CheckFunctionExists
+   /module/CheckIPOSupported
    /module/CheckIncludeFileCXX
    /module/CheckIncludeFile
    /module/CheckIncludeFiles
@@ -229,6 +230,7 @@
    /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..0c9ee2d 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,14 @@
 to determine whether to report an error on use of deprecated macros or
 functions.
 
+Policies Introduced by CMake 3.9
+================================
+
+.. toctree::
+   :maxdepth: 1
+
+   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..072d7c5 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -16,8 +16,11 @@
    :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,6 +29,7 @@
    /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/GLOBAL_DEPENDS_DEBUG_MODE
    /prop_gbl/GLOBAL_DEPENDS_NO_CYCLES
@@ -115,14 +119,17 @@
    /prop_tgt/ARCHIVE_OUTPUT_NAME_CONFIG
    /prop_tgt/ARCHIVE_OUTPUT_NAME
    /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
@@ -318,6 +325,7 @@
    /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..3b95b05 100644
--- a/Help/manual/cmake-qt.7.rst
+++ b/Help/manual/cmake-qt.7.rst
@@ -63,26 +63,33 @@
 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
+``<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.)
+
+Not included ``moc_<basename>.cpp`` files will be generated in custom
+folders to avoid name collisions and included in a separate
+``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/moc_compilation.cpp``
+file which is compiled into the target.
 
 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,7 +104,9 @@
 
 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
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 38444d1..9d8d596 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -13,9 +13,9 @@
 .. 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
@@ -40,6 +40,8 @@
    /variable/CMAKE_FIND_PACKAGE_NAME
    /variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION
    /variable/CMAKE_FIND_PACKAGE_SORT_ORDER
+   /variable/CMAKE_GCC_AR
+   /variable/CMAKE_GCC_RANLIB
    /variable/CMAKE_GENERATOR
    /variable/CMAKE_GENERATOR_PLATFORM
    /variable/CMAKE_GENERATOR_TOOLSET
@@ -82,18 +84,20 @@
    /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_NAME
    /variable/PROJECT_SOURCE_DIR
    /variable/PROJECT_VERSION
    /variable/PROJECT_VERSION_MAJOR
@@ -127,9 +131,9 @@
    /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 +147,9 @@
    /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 +167,7 @@
    /variable/CMAKE_STAGING_PREFIX
    /variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS
    /variable/CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE
+   /variable/CMAKE_SYSROOT
    /variable/CMAKE_SYSTEM_APPBUNDLE_PATH
    /variable/CMAKE_SYSTEM_FRAMEWORK_PATH
    /variable/CMAKE_SYSTEM_IGNORE_PATH
@@ -187,23 +192,24 @@
    /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 +220,6 @@
    /variable/MSVC80
    /variable/MSVC90
    /variable/MSVC_IDE
-   /variable/MSVC
    /variable/MSVC_VERSION
    /variable/UNIX
    /variable/WIN32
@@ -256,31 +261,35 @@
    /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_IOS_INSTALL_COMBINED
    /variable/CMAKE_LANG_CLANG_TIDY
    /variable/CMAKE_LANG_COMPILER_LAUNCHER
@@ -299,9 +308,9 @@
    /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 +323,15 @@
    /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 +340,8 @@
    /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 +355,6 @@
    /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 +363,10 @@
    /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 +377,27 @@
    /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 +408,8 @@
    /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 063aea1..a11e2f9 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -315,6 +315,9 @@
 ``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/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/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 @@
 :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 @@
 :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_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 @@
 :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/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst
index b42643f..7e10fde 100644
--- a/Help/prop_tgt/AUTOMOC.rst
+++ b/Help/prop_tgt/AUTOMOC.rst
@@ -8,31 +8,41 @@
 :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
+* 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
+  ``<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.
+  included ``moc_<basename>.cpp`` file regardless of the location the
+  original source.
 
-* 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 "<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 the generated
+  ``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/moc_compilation.cpp`` file,
+  which is compiled as part of the target. The custom directories help to
+  avoid name collisions for moc files with the same ``<basename>``.
+
+* 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 +57,12 @@
 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 @@
 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..91d95e5 100644
--- a/Help/prop_tgt/AUTOUIC.rst
+++ b/Help/prop_tgt/AUTOUIC.rst
@@ -10,8 +10,13 @@
 
 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
+``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/include``,
+which is added to the target's :prop_tgt:`INCLUDE_DIRECTORIES` automatically.
+
 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/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 @@
 
 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/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 @@
 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 @@
 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/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst
new file mode 100644
index 0000000..e4cc01e
--- /dev/null
+++ b/Help/release/dev/0-sample-topic.rst
@@ -0,0 +1,7 @@
+0-sample-topic
+--------------
+
+* This is a sample release note for the change in a topic.
+  Developers should add similar notes for each topic branch
+  making a noteworthy change.  Each document should be named
+  and titled to match the topic name to avoid merge conflicts.
diff --git a/Help/release/dev/Autogen_depends.rst b/Help/release/dev/Autogen_depends.rst
new file mode 100644
index 0000000..c774386
--- /dev/null
+++ b/Help/release/dev/Autogen_depends.rst
@@ -0,0 +1,10 @@
+AutoGen depends
+---------------
+
+* Variable :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` was introduced to
+  allow :variable:`CMAKE_AUTOMOC` to extract additional dependency file names
+  for ``moc`` from the contents of source files.
+
+* The new target property :prop_tgt:`AUTOMOC_DEPEND_FILTERS` was introduced to
+  allow :prop_tgt:`AUTOMOC` to extract additional dependency file names
+  for ``moc`` from the contents of source files.
diff --git a/Help/release/dev/Autogen_json.rst b/Help/release/dev/Autogen_json.rst
new file mode 100644
index 0000000..73bbdf1
--- /dev/null
+++ b/Help/release/dev/Autogen_json.rst
@@ -0,0 +1,10 @@
+AutoGen json
+------------
+
+* When using :prop_tgt:`AUTOMOC`, CMake 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 respective header file is searched
+  for in the :prop_tgt:`INCLUDE_DIRECTORIES` of the target as well.
diff --git a/Help/release/dev/Autogen_source_group.rst b/Help/release/dev/Autogen_source_group.rst
new file mode 100644
index 0000000..60faa8c
--- /dev/null
+++ b/Help/release/dev/Autogen_source_group.rst
@@ -0,0 +1,8 @@
+AutoGen source group
+--------------------
+
+* 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`.
diff --git a/Help/release/dev/Autogen_uic_paths.rst b/Help/release/dev/Autogen_uic_paths.rst
new file mode 100644
index 0000000..0893194
--- /dev/null
+++ b/Help/release/dev/Autogen_uic_paths.rst
@@ -0,0 +1,10 @@
+AutoGen uic paths
+-----------------
+
+* Variable :variable:`CMAKE_AUTOUIC_SEARCH_PATHS` was introduced to
+  allow :variable:`CMAKE_AUTOUIC` to search for ``foo.ui`` in more
+  places than the vicinity of the ``ui_foo.h`` including file.
+
+* The new target property :prop_tgt:`AUTOUIC_SEARCH_PATHS` was introduced to
+  allow :prop_tgt:`AUTOUIC` to search for ``foo.ui`` in more
+  places than the vicinity of the ``ui_foo.h`` including file.
diff --git a/Help/release/dev/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst b/Help/release/dev/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst
new file mode 100644
index 0000000..fc4f733
--- /dev/null
+++ b/Help/release/dev/CMAKE_INTERPROCEDURAL_OPTIMIZATION.rst
@@ -0,0 +1,6 @@
+CMAKE_INTERPROCEDURAL_OPTIMIZATION
+----------------------------------
+
+* A :variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable was added to
+  initialize the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` property on all
+  targets.
diff --git a/Help/release/dev/CheckIPOSupported.rst b/Help/release/dev/CheckIPOSupported.rst
new file mode 100644
index 0000000..dbc84e6
--- /dev/null
+++ b/Help/release/dev/CheckIPOSupported.rst
@@ -0,0 +1,6 @@
+CheckIPOSupported
+-----------------
+
+* A :module:`CheckIPOSupported` module was added to help projects
+  check whether interprocedural optimization (IPO) is supported by
+  the current toolchain and CMake version.
diff --git a/Help/release/dev/ExtractGTestMacro.rst b/Help/release/dev/ExtractGTestMacro.rst
new file mode 100644
index 0000000..574982c
--- /dev/null
+++ b/Help/release/dev/ExtractGTestMacro.rst
@@ -0,0 +1,5 @@
+ExtractGTestMacro
+-----------------
+
+* A new :module:`GoogleTest` module was added to provide the
+  ``gtest_add_tests`` macro independently of the :module:`FindGTest` module.
diff --git a/Help/release/dev/FeatureSummary_description.rst b/Help/release/dev/FeatureSummary_description.rst
new file mode 100644
index 0000000..c56e4ce
--- /dev/null
+++ b/Help/release/dev/FeatureSummary_description.rst
@@ -0,0 +1,11 @@
+FeatureSummary_description
+--------------------------
+
+* The :command:`feature_summary` command in the :module:`FeatureSummary` module
+  accepts the new ``DEFAULT_DESCRIPTION`` option that will print the default
+  title for the selected package type.
+
+* 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 by the
+  :module:`FeatureSummary` module.
diff --git a/Help/release/dev/FindProtobuf-static-libs.rst b/Help/release/dev/FindProtobuf-static-libs.rst
new file mode 100644
index 0000000..fcc0678
--- /dev/null
+++ b/Help/release/dev/FindProtobuf-static-libs.rst
@@ -0,0 +1,5 @@
+FindProtobuf-static-libs
+------------------------
+
+* The :module:`FindProtobuf` module now supports usage of static libraries
+  for Unix via a new ``Protobuf_USE_STATIC_LIBS`` input variable.
diff --git a/Help/release/dev/cmake-xcode-schemes.rst b/Help/release/dev/cmake-xcode-schemes.rst
new file mode 100644
index 0000000..81068ae
--- /dev/null
+++ b/Help/release/dev/cmake-xcode-schemes.rst
@@ -0,0 +1,6 @@
+cmake-xcode-schemes
+-------------------
+
+* The :generator:`Xcode` generator got the ability to create schema files.
+  This is still an experimental feature and can be activated by setting the
+  :variable:`CMAKE_XCODE_GENERATE_SCHEME` variable to a ``TRUE`` value.
diff --git a/Help/release/dev/cpack-rpm-debuginfo-honor-package-filename.rst b/Help/release/dev/cpack-rpm-debuginfo-honor-package-filename.rst
new file mode 100644
index 0000000..1c6eb2b
--- /dev/null
+++ b/Help/release/dev/cpack-rpm-debuginfo-honor-package-filename.rst
@@ -0,0 +1,5 @@
+cpack-rpm-debuginfo-honor-package-filename
+------------------------------------------
+
+* The :module:`CPackRPM` module learned to modify debuginfo package name.
+  See :variable:`CPACK_RPM_DEBUGINFO_FILE_NAME` variable.
diff --git a/Help/release/dev/cpack-sign-uninstaller.rst b/Help/release/dev/cpack-sign-uninstaller.rst
new file mode 100644
index 0000000..ff2b402
--- /dev/null
+++ b/Help/release/dev/cpack-sign-uninstaller.rst
@@ -0,0 +1,5 @@
+cpack-sign_uninstaller
+----------------------
+
+* The :module:`CPackNSIS` module learned to sign the uninstaller
+  when using :variable:`CPACK_NSIS_SIGN_UNINSTALLER` variable.
diff --git a/Help/release/dev/ctest-disable-tests.rst b/Help/release/dev/ctest-disable-tests.rst
new file mode 100644
index 0000000..9208f0c
--- /dev/null
+++ b/Help/release/dev/ctest-disable-tests.rst
@@ -0,0 +1,5 @@
+ctest-disable-tests
+-------------------
+
+* A :prop_test:`DISABLED` test property was added to mark tests that
+  are configured but explicitly disabled so they do not run.
diff --git a/Help/release/dev/cuda-vs.rst b/Help/release/dev/cuda-vs.rst
new file mode 100644
index 0000000..9170537
--- /dev/null
+++ b/Help/release/dev/cuda-vs.rst
@@ -0,0 +1,5 @@
+cuda-vs
+-------
+
+* ``CUDA`` is now supported by the :ref:`Visual Studio Generators`
+  for VS 2010 and above.
diff --git a/Help/release/dev/find_library-custom-lib-suffix.rst b/Help/release/dev/find_library-custom-lib-suffix.rst
new file mode 100644
index 0000000..824b27e
--- /dev/null
+++ b/Help/release/dev/find_library-custom-lib-suffix.rst
@@ -0,0 +1,6 @@
+find_library-custom-lib-suffix
+------------------------------
+
+* 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.
diff --git a/Help/release/dev/gcc_archiving_tools.rst b/Help/release/dev/gcc_archiving_tools.rst
new file mode 100644
index 0000000..b3cc7d6
--- /dev/null
+++ b/Help/release/dev/gcc_archiving_tools.rst
@@ -0,0 +1,8 @@
+gcc_archiving_tools
+-------------------
+
+* The :variable:`CMAKE_GCC_AR` variable with the path to GCC wrapper of ``ar``
+  utility was added.
+
+* The :variable:`CMAKE_GCC_RANLIB` variable with the path to GCC wrapper of
+  ``ranlib`` utility was added.
diff --git a/Help/release/dev/install_name_policy.rst b/Help/release/dev/install_name_policy.rst
new file mode 100644
index 0000000..7fe9a86
--- /dev/null
+++ b/Help/release/dev/install_name_policy.rst
@@ -0,0 +1,11 @@
+install_name_policy
+-------------------
+
+* 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``.
+
+* On macOS, ``RPATH`` settings such as :prop_tgt:`BUILD_WITH_INSTALL_RPATH`
+  no longer affect the ``install_name`` field.  See policy :policy:`CMP0068`.
diff --git a/Help/release/dev/module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS.rst b/Help/release/dev/module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS.rst
new file mode 100644
index 0000000..dfa9ef1
--- /dev/null
+++ b/Help/release/dev/module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS.rst
@@ -0,0 +1,8 @@
+module-def-and-WINDOWS_EXPORT_ALL_SYMBOLS
+-----------------------------------------
+
+* 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``).
diff --git a/Help/release/dev/productbuild_component_plist.rst b/Help/release/dev/productbuild_component_plist.rst
new file mode 100644
index 0000000..78d305c
--- /dev/null
+++ b/Help/release/dev/productbuild_component_plist.rst
@@ -0,0 +1,7 @@
+productbuild_component_plist
+----------------------------
+
+* 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.
diff --git a/Help/release/dev/productbuild_resources.rst b/Help/release/dev/productbuild_resources.rst
new file mode 100644
index 0000000..f381e63
--- /dev/null
+++ b/Help/release/dev/productbuild_resources.rst
@@ -0,0 +1,7 @@
+productbuild_resources
+----------------------
+
+* The :module:`CPackProductBuild` module gained a new
+  :variable:`CPACK_PRODUCTBUILD_RESOURCES_DIR` variable to
+  specify resources to be copied into the ``Resources``
+  directory.
diff --git a/Help/release/dev/update-curl.rst b/Help/release/dev/update-curl.rst
new file mode 100644
index 0000000..852ad5a
--- /dev/null
+++ b/Help/release/dev/update-curl.rst
@@ -0,0 +1,6 @@
+update-curl
+-----------
+
+* 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.
diff --git a/Help/release/dev/vs-nasm.rst b/Help/release/dev/vs-nasm.rst
new file mode 100644
index 0000000..bb082a4
--- /dev/null
+++ b/Help/release/dev/vs-nasm.rst
@@ -0,0 +1,5 @@
+vs-nasm
+-------
+
+* :ref:`Visual Studio Generators` for VS 2010 and above learned to support
+  the ``ASM_NASM`` language when ``nasm`` is installed.
diff --git a/Help/release/dev/wix-custom-root-id.rst b/Help/release/dev/wix-custom-root-id.rst
new file mode 100644
index 0000000..3e10fdd
--- /dev/null
+++ b/Help/release/dev/wix-custom-root-id.rst
@@ -0,0 +1,7 @@
+wix-custom-root-id
+------------------
+
+* 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``.
diff --git a/Help/release/dev/x32-abi.rst b/Help/release/dev/x32-abi.rst
new file mode 100644
index 0000000..7571fac
--- /dev/null
+++ b/Help/release/dev/x32-abi.rst
@@ -0,0 +1,6 @@
+x32-abi
+-------
+
+* 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.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 8f0f252..292c9a8 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -5,6 +5,8 @@
   This file should include the adjacent "dev.txt" file
   in development versions but not in release versions.
 
+.. include:: dev.txt
+
 Releases
 ========
 
diff --git a/Help/variable/CMAKE_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_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_GCC_AR.rst b/Help/variable/CMAKE_GCC_AR.rst
new file mode 100644
index 0000000..ac90b46
--- /dev/null
+++ b/Help/variable/CMAKE_GCC_AR.rst
@@ -0,0 +1,7 @@
+CMAKE_GCC_AR
+------------
+
+A wrapper around ``ar`` adding the appropriate ``--plugin`` option for the
+GCC compiler. For other compilers variable is not defined.
+
+See also :variable:`CMAKE_AR`.
diff --git a/Help/variable/CMAKE_GCC_RANLIB.rst b/Help/variable/CMAKE_GCC_RANLIB.rst
new file mode 100644
index 0000000..3d42aba
--- /dev/null
+++ b/Help/variable/CMAKE_GCC_RANLIB.rst
@@ -0,0 +1,7 @@
+CMAKE_GCC_RANLIB
+----------------
+
+A wrapper around ``ranlib`` adding the appropriate ``--plugin`` option for the
+GCC compiler. For other compilers variable is not defined.
+
+See also :variable:`CMAKE_RANLIB`.
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 @@
 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_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_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 @@
 
 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 @@
 ``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_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/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 3fafaff..fcecb6c 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -1,25 +1,33 @@
-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@")
+# Target names
+set(AM_TARGET_NAME @_autogen_target_name@)
+set(AM_ORIGIN_TARGET_NAME @_origin_target_name@)
+# 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_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@)
+# 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 @@
     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 @@
       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..ad65698 100644
--- a/Modules/CMakeASMCompiler.cmake.in
+++ b/Modules/CMakeASMCompiler.cmake.in
@@ -1,7 +1,9 @@
 set(CMAKE_ASM@ASM_DIALECT@_COMPILER "@_CMAKE_ASM_COMPILER@")
 set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ARG1 "@_CMAKE_ASM_COMPILER_ARG1@")
 set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_GCC_AR "@CMAKE_GCC_AR@")
 set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_GCC_RANLIB "@CMAKE_GCC_RANLIB@")
 set(CMAKE_LINKER "@CMAKE_LINKER@")
 set(CMAKE_ASM@ASM_DIALECT@_COMPILER_LOADED 1)
 set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ID "@_CMAKE_ASM_COMPILER_ID@")
diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in
index 50b12f2..ab068a2 100644
--- a/Modules/CMakeCCompiler.cmake.in
+++ b/Modules/CMakeCCompiler.cmake.in
@@ -14,7 +14,9 @@
 set(CMAKE_C_SIMULATE_VERSION "@CMAKE_C_SIMULATE_VERSION@")
 @SET_MSVC_C_ARCHITECTURE_ID@
 set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_GCC_AR "@CMAKE_GCC_AR@")
 set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_GCC_RANLIB "@CMAKE_GCC_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/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index 6d56488..27c8881 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -15,7 +15,9 @@
 set(CMAKE_CXX_SIMULATE_VERSION "@CMAKE_CXX_SIMULATE_VERSION@")
 @SET_MSVC_CXX_ARCHITECTURE_ID@
 set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_GCC_AR "@CMAKE_GCC_AR@")
 set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_GCC_RANLIB "@CMAKE_GCC_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/CMakeCompilerABI.h b/Modules/CMakeCompilerABI.h
index f2714b4..ad481d6 100644
--- a/Modules/CMakeCompilerABI.h
+++ b/Modules/CMakeCompilerABI.h
@@ -25,6 +25,10 @@
 #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/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake
index 4162726..7d5e2b2 100644
--- a/Modules/CMakeDetermineASMCompiler.cmake
+++ b/Modules/CMakeDetermineASMCompiler.cmake
@@ -92,9 +92,17 @@
   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)
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..5d9850d 100644
--- a/Modules/CMakeDetermineCCompiler.cmake
+++ b/Modules/CMakeDetermineCCompiler.cmake
@@ -166,6 +166,10 @@
 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})")
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index 7b6d17b..55a6f0c 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -5,36 +5,40 @@
 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|[7-9][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)
+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")
+      # 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()
-      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()
+
+    # 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 @@
     "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..4d85150 100644
--- a/Modules/CMakeDetermineCXXCompiler.cmake
+++ b/Modules/CMakeDetermineCXXCompiler.cmake
@@ -161,6 +161,10 @@
 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})")
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index c41a986..1abbc01 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -24,16 +24,21 @@
 
   # 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 @@
 
   # 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 @@
   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()
@@ -127,7 +136,7 @@
 #-----------------------------------------------------------------------------
 # 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 +146,7 @@
   # 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 +235,26 @@
     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")
@@ -333,7 +362,7 @@
     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 +650,7 @@
 #   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 +668,7 @@
     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 +696,7 @@
   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 +706,7 @@
   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..9e9770a 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -255,6 +255,9 @@
 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 @@
       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 @@
   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/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in
index 69800d7..c49621b 100644
--- a/Modules/CMakeFortranCompiler.cmake.in
+++ b/Modules/CMakeFortranCompiler.cmake.in
@@ -8,7 +8,9 @@
 set(CMAKE_Fortran_SIMULATE_VERSION "@CMAKE_Fortran_SIMULATE_VERSION@")
 @SET_MSVC_Fortran_ARCHITECTURE_ID@
 set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_GCC_AR "@CMAKE_GCC_AR@")
 set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_GCC_RANLIB "@CMAKE_GCC_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/CPackComponent.cmake b/Modules/CPackComponent.cmake
index 188dde3..2adc9b9 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,38 +303,6 @@
 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
@@ -388,9 +360,10 @@
 # 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 @@
   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 @@
 # 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 @@
 # 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 @@
 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/CPackNSIS.cmake b/Modules/CPackNSIS.cmake
index 18d1871..37fedf3 100644
--- a/Modules/CPackNSIS.cmake
+++ b/Modules/CPackNSIS.cmake
@@ -133,6 +133,10 @@
 #       "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake.html"
 #       "CMake Help" "https://cmake.org" "CMake Web Site")
 #
+# .. variable:: CPACK_NSIS_SIGN_UNINSTALLER
+#
+#  Specify a command to use for signing the uninstaller.  The command will
+#  be invoked a path to the uninstaller as its only argument.
 
 #FIXME we should put NSIS specific code here
 #FIXME but I'm not doing it because I'm not able to test it...
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..cc54032 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)
 # ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 #
@@ -950,10 +974,20 @@
   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 +1070,7 @@
   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 +2156,11 @@
       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 +2664,27 @@
     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..5a36e4c 100644
--- a/Modules/CPackWIX.cmake
+++ b/Modules/CPackWIX.cmake
@@ -268,6 +268,17 @@
 #     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``.
+#
 
 if(NOT CPACK_WIX_ROOT)
   file(TO_CMAKE_PATH "$ENV{WIX}" CPACK_WIX_ROOT)
diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake
new file mode 100644
index 0000000..6f7bc82
--- /dev/null
+++ b/Modules/CheckIPOSupported.cmake
@@ -0,0 +1,215 @@
+# 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.
+
+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}/_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)
+
+  if(is_c)
+    set(copy_sources foo.c main.c)
+  elseif(is_cxx)
+    set(copy_sources foo.cpp main.cpp)
+  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)
+  # TODO: IPO policy
+
+  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()
+
+  list(FIND languages "Fortran" result)
+  if(NOT result EQUAL -1)
+    _ipo_not_supported("Fortran is not supported")
+    return()
+  endif()
+
+  if(NOT _CMAKE_IPO_SUPPORTED_BY_CMAKE)
+    _ipo_not_supported("CMake doesn't support IPO for current compiler")
+    return()
+  endif()
+
+  if(NOT _CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER)
+    _ipo_not_supported("compiler doesn't support IPO")
+    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..d20f31f
--- /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)
+
+# TODO: IPO policy
+
+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..4b55c70
--- /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)
+
+# TODO: IPO policy
+
+add_library(foo foo.cpp)
+add_executable(boo main.cpp)
+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/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/CheckLanguage.cmake b/Modules/CheckLanguage.cmake
index 6b4a9e4..1ea91d2 100644
--- a/Modules/CheckLanguage.cmake
+++ b/Modules/CheckLanguage.cmake
@@ -46,6 +46,8 @@
     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/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake
index c007c98..2499d2f 100644
--- a/Modules/Compiler/GNU-CXX.cmake
+++ b/Modules/Compiler/GNU-CXX.cmake
@@ -11,8 +11,7 @@
   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()
diff --git a/Modules/Compiler/GNU-FindBinUtils.cmake b/Modules/Compiler/GNU-FindBinUtils.cmake
new file mode 100644
index 0000000..466d4cf
--- /dev/null
+++ b/Modules/Compiler/GNU-FindBinUtils.cmake
@@ -0,0 +1,25 @@
+if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "")
+  message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
+endif()
+
+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_GCC_AR NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar"
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ar-${__version_x_y}"
+    HINTS ${__gcc_hints}
+    DOC "A wrapper around 'ar' adding the appropriate '--plugin' option for the GCC compiler"
+)
+
+# http://manpages.ubuntu.com/manpages/wily/en/man1/gcc-ranlib.1.html
+find_program(CMAKE_GCC_RANLIB NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib"
+    "${_CMAKE_TOOLCHAIN_PREFIX}gcc-ranlib-${__version_x_y}"
+    HINTS ${__gcc_hints}
+    DOC "A wrapper around 'ranlib' adding the appropriate '--plugin' option for the GCC compiler"
+)
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_@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/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 00781d6..97438e6 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -1987,11 +1987,10 @@
         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 @@
 
 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 @@
                      [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 @@
   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 @@
 
 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 @@
     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 @@
                                "${_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 @@
       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/FindDevIL.cmake b/Modules/FindDevIL.cmake
index 45fab82..4b868a2 100644
--- a/Modules/FindDevIL.cmake
+++ b/Modules/FindDevIL.cmake
@@ -45,7 +45,7 @@
 
 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(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(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."
 )
 
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/FindGTK2.cmake b/Modules/FindGTK2.cmake
index fd179a8..b87b9f3 100644
--- a/Modules/FindGTK2.cmake
+++ b/Modules/FindGTK2.cmake
@@ -292,8 +292,10 @@
     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)
+# See :module:`GoogleTest` for information on the :command:`gtest_add_tests`
+# command.
 
-#
-# Thanks to Daniel Blezek <blezek@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})
-
-          # 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..1e2ea69 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``.
 
@@ -400,15 +410,23 @@
       ${_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 +438,7 @@
             #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 +446,29 @@
               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 +513,6 @@
       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 +602,6 @@
           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 +704,8 @@
             ${_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 +847,23 @@
 )
 
 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 @@
   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/FindKDE3.cmake b/Modules/FindKDE3.cmake
index 62e2a50..03216a5 100644
--- a/Modules/FindKDE3.cmake
+++ b/Modules/FindKDE3.cmake
@@ -221,6 +221,8 @@
 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/FindOpenAL.cmake b/Modules/FindOpenAL.cmake
index 8622b4c..c3d202e 100644
--- a/Modules/FindOpenAL.cmake
+++ b/Modules/FindOpenAL.cmake
@@ -79,7 +79,7 @@
   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/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index 2ee9439..f399836 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -48,6 +48,7 @@
     #GNU
     "-fopenmp"
     #Clang
+    "-fopenmp=libiomp5"
     "-fopenmp=libomp"
     #Microsoft Visual Studio
     "/openmp"
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index 6259ce1..117811c 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -160,6 +160,7 @@
         libcrypto
         libeay32${_OPENSSL_MSVC_RT_MODE}
         libeay32
+        crypto
       NAMES_PER_DIR
       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
       PATH_SUFFIXES
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index 1958f4b..54572f0 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -312,6 +312,10 @@
           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,39 +364,26 @@
         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()
-
-      if (_pkg_check_modules_pkg_op STREQUAL "<=")
-        list(APPEND _pkg_check_modules_exist_query --max-version)
-      endif()
-
-      # create the final query which is of the format:
-      # * --atleast-version <version> <pkg-name>
-      # * --exact-version <version> <pkg-name>
-      # * --max-version <version> <pkg-name>
-      # * --exists <pkg-name>
-      if (_pkg_check_modules_pkg_op)
-        list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}")
-      else()
-        list(APPEND _pkg_check_modules_exist_query --exists)
-      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}")
 
+      # create the final query which is of the format:
+      # * <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_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()
+
       # execute the query
       execute_process(
         COMMAND ${PKG_CONFIG_EXECUTABLE} ${_pkg_check_modules_exist_query}
diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake
index 3ffd5a7..102ed42 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:
 #
@@ -218,6 +221,14 @@
   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 +256,17 @@
   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
@@ -399,6 +421,11 @@
     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/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake
index 6d1b4ed..4573c2e 100644
--- a/Modules/GenerateExportHeader.cmake
+++ b/Modules/GenerateExportHeader.cmake
@@ -215,9 +215,6 @@
     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 @@
     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 @@
   _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..a3b97ab 100644
--- a/Modules/GetPrerequisites.cmake
+++ b/Modules/GetPrerequisites.cmake
@@ -399,6 +399,11 @@
     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 @@
     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()
diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake
new file mode 100644
index 0000000..91a3a25
--- /dev/null
+++ b/Modules/GoogleTest.cmake
@@ -0,0 +1,73 @@
+# 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(<exe> <args> <files>...)
+
+  ``<exe>``
+    The path to the test executable.
+  ``<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.
+
+Example
+^^^^^^^
+
+.. code-block:: cmake
+
+  include(GoogleTest)
+  set(FooTestArgs --foo 1 --bar 2)
+  add_executable(FooTest FooUnitTest.cc)
+  gtest_add_tests(FooTest "${FooTestArgs}" AUTO)
+
+#]=======================================================================]
+
+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})
+
+      # 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()
diff --git a/Modules/NSIS.template.in b/Modules/NSIS.template.in
index 9001888..4f6aa75 100644
--- a/Modules/NSIS.template.in
+++ b/Modules/NSIS.template.in
@@ -29,6 +29,34 @@
 
 ;--------------------------------
 ;General
+!ifdef INNER
+  OutFile "${TEMPINSTALLER}.exe"
+  SetCompress off                           ; for speed
+!else
+  ; Call makensis again, defining INNER.  This writes an installer for us which, when
+  ; it is invoked, will just write the uninstaller to some location, and then exit.
+  ; Be sure to substitute the name of this script here.
+  !tempfile TEMPINSTALLER
+  !tempfile TEMPUNINSTALLER
+  !system "$\"${NSISDIR}\makensis$\" /DTEMPINSTALLER=$\"${TEMPINSTALLER}$\" /DTEMPUNINSTALLER=$\"${TEMPUNINSTALLER}$\" /DINNER $\"@CPACK_TEMPORARY_DIRECTORY@/../project.nsi$\"" = 0
+
+  ; So now run that installer we just created as %TEMP%\tempinstaller.exe.  Since it
+  ; calls quit the return value isn't zero.
+
+  !system "$\"${TEMPINSTALLER}.exe$\"" = 2
+
+  ; That will have written an uninstaller binary for us.  Now we sign it with your
+  ; favourite code signing tool.
+
+  !tempfile INCEXIST
+  !system 'if exist "@CPACK_NSIS_SIGN_UNINSTALLER@" echo !define HAVE_SIGN_UNINST > "${INCEXIST}"'
+  !include "${INCEXIST}"
+  !delfile "${INCEXIST}"
+  !ifdef HAVE_SIGN_UNINST
+  !system '"@CPACK_NSIS_SIGN_UNINSTALLER@" "${TEMPUNINSTALLER}.exe"' = 0
+  !endif
+
+  ; Good.  Now we can carry on writing the real installer.
 
   ;Name and file
   Name "@CPACK_NSIS_PACKAGE_NAME@"
@@ -36,6 +64,7 @@
 
   ;Set compression
   SetCompressor @CPACK_NSIS_COMPRESSOR@
+!endif
 
   ;Require administrator access
   RequestExecutionLevel admin
@@ -559,8 +588,10 @@
   !insertmacro MUI_PAGE_INSTFILES
   !insertmacro MUI_PAGE_FINISH
 
+!ifdef INNER
   !insertmacro MUI_UNPAGE_CONFIRM
   !insertmacro MUI_UNPAGE_INSTFILES
+!endif
 
 ;--------------------------------
 ;Languages
@@ -642,7 +673,10 @@
   WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR
 
   ;Create uninstaller
-  WriteUninstaller "$INSTDIR\Uninstall.exe"
+!ifndef INNER
+  ; this packages the signed uninstaller
+  File "/oname=Uninstall.exe" "${TEMPUNINSTALLER}.exe"
+!endif
   Push "DisplayName"
   Push "@CPACK_NSIS_DISPLAY_NAME@"
   Call ConditionalAddToRegisty
@@ -801,6 +835,7 @@
 ;--------------------------------
 ;Uninstaller Section
 
+!ifdef INNER
 Section "Uninstall"
   ReadRegStr $START_MENU SHCTX \
    "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu"
@@ -886,6 +921,7 @@
     Call un.RemoveFromPath
   doNotRemoveFromPath:
 SectionEnd
+!endif
 
 ;--------------------------------
 ; determine admin versus local install
@@ -898,6 +934,14 @@
 ; "Program Files" for AllUsers, "My Documents" for JustMe...
 
 Function .onInit
+!ifdef INNER
+  ; If INNER is defined, then we aren't supposed to do anything except write out
+  ; the installer.  This is better than processing a command line option as it means
+  ; this entire code path is not present in the final (real) installer.
+
+  WriteUninstaller "${TEMPUNINSTALLER}.exe"
+  Quit  ; just bail out quickly when running the "inner" installer
+!endif
   StrCmp "@CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL@" "ON" 0 inst
 
   ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString"
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_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/Linux-Intel.cmake b/Modules/Platform/Linux-Intel.cmake
index 85a0772..45dc36f 100644
--- a/Modules/Platform/Linux-Intel.cmake
+++ b/Modules/Platform/Linux-Intel.cmake
@@ -30,12 +30,17 @@
   # executables that use dlopen but do not set ENABLE_EXPORTS.
   set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
 
+  set(_CMAKE_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_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+  else()
+    set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
   endif()
 
   if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 12.0)
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 @@
 
 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 @@
   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 @@
 # 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/TestBigEndian.cmake b/Modules/TestBigEndian.cmake
index 085be22..cc627d0 100644
--- a/Modules/TestBigEndian.cmake
+++ b/Modules/TestBigEndian.cmake
@@ -19,21 +19,29 @@
     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 @@
 
     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/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake
index 0b16aa4..362099e 100644
--- a/Modules/WriteCompilerDetectionHeader.cmake
+++ b/Modules/WriteCompilerDetectionHeader.cmake
@@ -503,10 +503,19 @@
       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/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 2835ee6..59920f8 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -344,6 +344,8 @@
   cmPropertyDefinitionMap.h
   cmPropertyMap.cxx
   cmPropertyMap.h
+  cmQtAutoGeneratorCommon.cxx
+  cmQtAutoGeneratorCommon.h
   cmQtAutoGeneratorInitializer.cxx
   cmQtAutoGeneratorInitializer.h
   cmQtAutoGenerators.cxx
@@ -381,6 +383,8 @@
   cmVariableWatch.h
   cmVersion.cxx
   cmVersion.h
+  cmWorkingDirectory.cxx
+  cmWorkingDirectory.h
   cmXMLParser.cxx
   cmXMLParser.h
   cmXMLSafe.cxx
@@ -440,6 +444,8 @@
   cmCreateTestSourceList.h
   cmDefinePropertyCommand.cxx
   cmDefinePropertyCommand.h
+  cmDisallowedCommand.cxx
+  cmDisallowedCommand.h
   cmEnableLanguageCommand.cxx
   cmEnableLanguageCommand.h
   cmEnableTestingCommand.cxx
@@ -637,6 +643,7 @@
   set(SRCS ${SRCS}
     cmXCodeObject.cxx
     cmXCode21Object.cxx
+    cmXCodeScheme.cxx
     cmGlobalXCodeGenerator.cxx
     cmGlobalXCodeGenerator.h
     cmLocalXCodeGenerator.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 58497b3..e88a12b 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_PATCH 0)
-set(CMake_VERSION_RC 4)
+set(CMake_VERSION_PATCH 20170330)
+#set(CMake_VERSION_RC 1)
diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx
index b159e64..aeabde9 100644
--- a/Source/CPack/OSXScriptLauncher.cxx
+++ b/Source/CPack/OSXScriptLauncher.cxx
@@ -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;
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 2bccf2e..39586de 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -437,8 +437,8 @@
   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 @@
   return this->Patch->CheckForUnappliedFragments();
 }
 
-std::string cmCPackWIXGenerator::GetProgramFilesFolderId() const
+std::string cmCPackWIXGenerator::GetRootFolderId() const
 {
   if (cmSystemTools::IsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) {
     return "";
   }
-  if (GetArchitecture() == "x86") {
-    return "ProgramFilesFolder";
-  } else {
-    return "ProgramFiles64Folder";
+
+  std::string result = "ProgramFiles<64>Folder";
+
+  const char* rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID");
+  if (rootFolderId) {
+    result = rootFolderId;
   }
+
+  if (GetArchitecture() == "x86") {
+    cmSystemTools::ReplaceString(result, "<64>", "");
+  } else {
+    cmSystemTools::ReplaceString(result, "<64>", "64");
+  }
+
+  return result;
 }
 
 bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate()
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index fc0994c..36647d8 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -65,7 +65,7 @@
 
   bool CreateWiXSourceFiles();
 
-  std::string GetProgramFilesFolderId() const;
+  std::string GetRootFolderId() const;
 
   bool GenerateMainSourceFileFromTemplate();
 
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
index a471d26..3158343 100644
--- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
@@ -9,9 +9,7 @@
 #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,
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 9d9cd66..cc01b0c 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>
@@ -37,9 +38,8 @@
   // 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 +64,6 @@
       return 0;
     }
   }
-  // Go back to previous dir
-  cmSystemTools::ChangeDirectory(dir);
   return 1;
 }
 
@@ -227,8 +225,7 @@
   // 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 +238,6 @@
       return 0;
     }
   }
-  cmSystemTools::ChangeDirectory(dir);
   // The destructor of cmArchiveWrite will close and finish the write
   return 1;
 }
diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h
index f955daf..510adc2 100644
--- a/Source/CPack/cmCPackComponentGroup.h
+++ b/Source/CPack/cmCPackComponentGroup.h
@@ -78,6 +78,10 @@
   /// 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/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
index 92475d9..bd22cec 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
@@ -15,7 +15,7 @@
 // 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..ed87238 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -8,6 +8,7 @@
 #include "cmCPackLog.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
+#include "cm_sys_stat.h"
 
 #include <cmsys/Glob.hxx>
 #include <limits.h>
@@ -16,7 +17,6 @@
 #include <set>
 #include <stdio.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <utility>
 
 // NOTE:
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index fd67df9..ec5fc88 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -390,6 +390,8 @@
   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 @@
 
       return 0;
     }
+    temp_image_format = "UDRW";
   }
 
   // Create a temporary read-write disk image ...
@@ -413,7 +416,7 @@
   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 @@
       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 @@
     }
     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 @@
     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 @@
                                                            << std::endl);
       return 0;
     }
-
-    temp_image = temp_udco;
   }
 
   // Create the final compressed read-only disk image ...
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 21eda79..f6ea8cf 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -16,6 +16,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmStateSnapshot.h"
+#include "cmWorkingDirectory.h"
 #include "cmXMLSafe.h"
 #include "cm_auto_ptr.hxx"
 #include "cmake.h"
@@ -383,7 +384,7 @@
         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 @@
         }
         cmCPackLogger(cmCPackLog::LOG_DEBUG, "Going back to: " << curDir
                                                                << std::endl);
-        cmSystemTools::ChangeDirectory(curDir);
       }
     }
   }
@@ -1396,6 +1396,11 @@
       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..39fd2cc 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -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 @@
   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/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/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 @@
     }
   }
 
-  // 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 @@
                                   : " --keychain \"" + keychainPath + "\"")
          << " \"" << packageFile << "\"";
 
+  if (component && !component->Plist.empty()) {
+    pkgCmd << " --component-plist \"" << component->Plist << "\"";
+  }
+
   // Run ProductBuild
   return RunProductBuild(pkgCmd.str());
 }
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index 682394e..2765e2a 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -8,13 +8,10 @@
 #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/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx
index b42953b..6769ee5 100644
--- a/Source/CTest/cmCTestBZR.cxx
+++ b/Source/CTest/cmCTestBZR.cxx
@@ -151,22 +151,24 @@
   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 @@
   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 @@
     // 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 @@
     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 @@
   }
 };
 
-void cmCTestBZR::LoadModifications()
+bool cmCTestBZR::LoadModifications()
 {
   // Run "bzr status" which reports local modifications.
   const char* bzr = this->CommandLineTool.c_str();
@@ -468,4 +471,5 @@
   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..0b62582 100644
--- a/Source/CTest/cmCTestBZR.h
+++ b/Source/CTest/cmCTestBZR.h
@@ -26,16 +26,16 @@
 
 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/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 6780a0e..6f81429 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -6,6 +6,7 @@
 #include "cmCTestTestHandler.h"
 #include "cmGlobalGenerator.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 #include "cmake.h"
 
 #include <cmsys/Process.h>
@@ -42,7 +43,7 @@
 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 @@
   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 @@
     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 {
@@ -199,13 +196,12 @@
   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 @@
     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 @@
     } 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..af082a3 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.h
+++ b/Source/CTest/cmCTestBuildAndTestHandler.h
@@ -46,7 +46,7 @@
   ///! 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/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 989c096..120c5d9 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -12,6 +12,7 @@
 #include "cmParseJacocoCoverage.h"
 #include "cmParsePHPCoverage.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 #include "cmXMLWriter.h"
 #include "cmake.h"
 
@@ -969,9 +970,8 @@
 
   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;
 
@@ -1294,7 +1294,6 @@
     }
   }
 
-  cmSystemTools::ChangeDirectory(currentDirectory);
   return file_count;
 }
 
@@ -1340,7 +1339,6 @@
     return 0;
   }
   std::string testingDir = this->CTest->GetBinaryDir();
-  std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
 
   std::set<std::string> missingFiles;
 
@@ -1362,7 +1360,7 @@
     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,
@@ -1552,7 +1550,6 @@
     }
   }
 
-  cmSystemTools::ChangeDirectory(currentDirectory);
   return file_count;
 }
 
@@ -1591,13 +1588,8 @@
   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 +1597,9 @@
     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 +1636,7 @@
 
   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 +1723,6 @@
     }
     ++file_count;
   }
-  cmSystemTools::ChangeDirectory(currentDirectory);
   return file_count;
 }
 
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index d30f6b3..9c53aa1 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -67,19 +67,21 @@
   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()
@@ -607,7 +609,7 @@
 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 @@
   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 @@
        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..d5a1ee3 100644
--- a/Source/CTest/cmCTestGIT.h
+++ b/Source/CTest/cmCTestGIT.h
@@ -28,8 +28,8 @@
   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 @@
   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/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 @@
 
 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 @@
     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..9fa5f21 100644
--- a/Source/CTest/cmCTestGlobalVC.h
+++ b/Source/CTest/cmCTestGlobalVC.h
@@ -64,8 +64,8 @@
   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..68ebd37 100644
--- a/Source/CTest/cmCTestHG.cxx
+++ b/Source/CTest/cmCTestHG.cxx
@@ -104,19 +104,21 @@
   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 @@
   }
 };
 
-void cmCTestHG::LoadRevisions()
+bool cmCTestHG::LoadRevisions()
 {
   // Use 'hg log' to get revisions in a xml format.
   //
@@ -293,9 +295,10 @@
   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 @@
   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..63baba2 100644
--- a/Source/CTest/cmCTestHG.h
+++ b/Source/CTest/cmCTestHG.h
@@ -26,12 +26,12 @@
 
 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 @@
     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 @@
       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 @@
     this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                   returnString);
   }
-  cmSystemTools::ChangeDirectory(current_dir);
   return true;
 }
 
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index c1724ab..2d4726c 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -7,6 +7,7 @@
 #include "cmCTestScriptHandler.h"
 #include "cmCTestTestHandler.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 
 #include <algorithm>
 #include <cmsys/FStream.hxx>
@@ -138,8 +139,7 @@
     }
   }
 
-  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 @@
     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)
@@ -683,9 +684,7 @@
     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);
@@ -724,8 +723,6 @@
     cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet);
     cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, p.Name << std::endl,
                        this->Quiet);
-    // pop working dir
-    cmSystemTools::ChangeDirectory(current_dir);
   }
 
   cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl
diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx
index 41b45a8..4f78876 100644
--- a/Source/CTest/cmCTestP4.cxx
+++ b/Source/CTest/cmCTestP4.cxx
@@ -369,24 +369,26 @@
   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 @@
   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 @@
   this->RunChild(&p4_changes[0], &out, &err);
 
   if (ChangeLists.empty()) {
-    return;
+    return true;
   }
 
   // p4 describe -s ...@1111111,2222222
@@ -435,9 +437,10 @@
     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 @@
   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..2c04dc6 100644
--- a/Source/CTest/cmCTestP4.h
+++ b/Source/CTest/cmCTestP4.h
@@ -51,13 +51,13 @@
   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/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index ac1644f..94aa4bd 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -7,6 +7,7 @@
 #include "cmCTestTestHandler.h"
 #include "cmProcess.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 
 #include <cmConfigure.h>
 #include <cm_curl.h>
@@ -214,6 +215,9 @@
     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 ");
     } else if ((success && !this->TestProperties->WillFail) ||
                (!success && this->TestProperties->WillFail)) {
@@ -252,6 +256,8 @@
         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 +276,11 @@
     *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
@@ -356,11 +359,8 @@
   }
   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 +418,24 @@
                << 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 +460,7 @@
     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 +480,7 @@
     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 +500,7 @@
                  "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 +516,7 @@
                "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;
   }
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index 410e0d4..ce395cd 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -97,9 +97,11 @@
   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();
@@ -116,11 +118,14 @@
   // 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();
@@ -153,6 +158,7 @@
 
   // 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 @@
   }
 };
 
-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();
   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 @@
   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 @@
   }
 };
 
-void cmCTestSVN::LoadModifications()
+bool cmCTestSVN::LoadModifications()
 {
   // Run "svn status" which reports local modifications.
   std::vector<const char*> svn_status;
@@ -476,6 +484,7 @@
   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 @@
   }
 };
 
-void cmCTestSVN::LoadRepositories()
+bool cmCTestSVN::LoadRepositories()
 {
   if (!this->Repositories.empty()) {
-    return;
+    return true;
   }
 
   // Info for root repository
@@ -536,7 +545,7 @@
   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..e5fe5b7 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -30,8 +30,8 @@
 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,
@@ -77,10 +77,10 @@
   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/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 5e5119d..88193b0 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -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_sys_stat.h"
 #include <cm_xmlrpc.h>
-#include <sys/stat.h>
 #endif
 
 #define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120
@@ -1519,7 +1520,6 @@
 #endif
   } else if (dropMethod == "scp") {
     std::string url;
-    std::string oldWorkingDirectory;
     if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) {
       url += this->CTest->GetCTestConfiguration("DropSiteUser") + "@";
     }
@@ -1528,19 +1528,16 @@
 
     // 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 +1547,18 @@
 
     // 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/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 6175e50..814b310 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -27,6 +27,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"
@@ -86,22 +87,24 @@
       // 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 +112,6 @@
       return false;
     }
   }
-  cmSystemTools::ChangeDirectory(cwd);
   return true;
 }
 
@@ -149,9 +151,7 @@
     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 +159,23 @@
     // 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;
@@ -487,6 +487,19 @@
       }
     }
 
+    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 (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 +518,33 @@
                        "\nTotal Test time (real) = " << realBuf << "\n",
                        this->Quiet);
 
+    if (!disabledTests.empty()) {
+      cmGeneratedFileStream ofs;
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
+                   << "The following tests are disabled and did not run:"
+                   << std::endl);
+      this->StartLogFile("TestsDisabled", ofs);
+
+      for (std::vector<cmCTestTestHandler::cmCTestTestResult>::iterator dtit =
+             disabledTests.begin();
+           dtit != disabledTests.end(); ++dtit) {
+        ofs << dtit->TestCount << ":" << dtit->Name << std::endl;
+        cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t"
+                     << std::setw(3) << dtit->TestCount << " - " << dtit->Name
+                     << 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 &&
+            ftit->CompletionStatus != "Disabled") {
           ofs << ftit->TestCount << ":" << ftit->Name << std::endl;
           cmCTestLog(
             this->CTest, HANDLER_OUTPUT, "\t"
@@ -841,6 +866,11 @@
   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
@@ -1200,6 +1230,7 @@
     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 +1239,7 @@
         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 +1254,7 @@
       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 +1263,14 @@
         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");
@@ -2000,6 +2033,9 @@
           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);
           }
@@ -2178,6 +2214,7 @@
 
   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..a95f088 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -114,6 +114,7 @@
     std::map<std::string, std::string> Measurements;
     bool IsInBasedOnREOptions;
     bool WillFail;
+    bool Disabled;
     float Cost;
     int PreviousRuns;
     bool RunSerial;
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index 0998d59..2b5683a 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -198,7 +198,7 @@
   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 @@
   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/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx
index 444c43d..26c9bb5 100644
--- a/Source/CTest/cmCTestVC.cxx
+++ b/Source/CTest/cmCTestVC.cxx
@@ -147,23 +147,25 @@
   // 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..a1c1673 100644
--- a/Source/CTest/cmCTestVC.h
+++ b/Source/CTest/cmCTestVC.h
@@ -67,9 +67,9 @@
 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/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index 5e03c39..b2f0b2d 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -184,9 +184,9 @@
 }
 
 #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/bindexplib.cxx b/Source/bindexplib.cxx
index eded883..47c7565 100644
--- a/Source/bindexplib.cxx
+++ b/Source/bindexplib.cxx
@@ -64,7 +64,7 @@
 #include "bindexplib.h"
 
 #include <cmsys/Encoding.hxx>
-#include <fstream>
+#include <cmsys/FStream.hxx>
 #include <iostream>
 #include <windows.h>
 
@@ -308,7 +308,8 @@
                   this->DataSymbols.insert(symbol);
                } else {
                   if ( pSymbolTable->Type  ||
-                       !(SectChar & IMAGE_SCN_MEM_READ)) {
+                       !(SectChar & IMAGE_SCN_MEM_READ) ||
+                       (SectChar & IMAGE_SCN_MEM_EXECUTE)) {
                      this->Symbols.insert(symbol);
                   } else {
                      // printf(" strange symbol: %s \n",symbol.c_str());
@@ -425,24 +426,46 @@
 
 bool bindexplib::AddObjectFile(const char* filename)
 {
-  if(!DumpFile(filename, this->Symbols, this->DataSymbols))
-    {
-    return false;
-    }
-  return true;
+  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)
-    {
+  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..7f0615f 100644
--- a/Source/bindexplib.h
+++ b/Source/bindexplib.h
@@ -13,6 +13,7 @@
 {
 public:
   bindexplib() {}
+  bool AddDefinitionFile(const char* filename);
   bool AddObjectFile(const char* filename);
   void WriteFile(FILE* file);
 private:
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index 7c683ad..f5469e5 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -101,6 +101,12 @@
   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>
diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx
index 1e1cd21..93e5ca2 100644
--- a/Source/cmBuildNameCommand.cxx
+++ b/Source/cmBuildNameCommand.cxx
@@ -6,7 +6,6 @@
 #include <cmsys/RegularExpression.hxx>
 
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 
@@ -16,11 +15,6 @@
 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/cmCTest.cxx b/Source/cmCTest.cxx
index 559275e..e6e50e9 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -1122,7 +1122,6 @@
     if (log) {
       *log << "* Run internal CTest" << std::endl;
     }
-    std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
 
     CM_AUTO_PTR<cmSystemTools::SaveRestoreEnvironment> saveEnv;
     if (modifyEnv) {
@@ -1137,7 +1136,6 @@
     if (log && output) {
       *log << *output;
     }
-    cmSystemTools::ChangeDirectory(oldpath);
     if (output) {
       cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
                  "Internal cmCTest object used to run test." << std::endl
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 4d33458..be736da 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -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 @@
   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/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 @@
 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..9107d85 100644
--- a/Source/cmCommand.h
+++ b/Source/cmCommand.h
@@ -7,9 +7,6 @@
 #include <string>
 #include <vector>
 
-#include "cmCommandArgumentsHelper.h"
-#include "cmPolicies.h"
-
 class cmExecutionStatus;
 class cmMakefile;
 struct cmListFileArgument;
@@ -105,12 +102,12 @@
    */
   void SetError(const std::string& e);
 
-  /** Check if the command is disallowed by a policy.  */
-  bool Disallowed(cmPolicies::PolicyID pol, const char* e);
+private:
+  cmCommand(cmCommand const&);            // = delete;
+  cmCommand& operator=(cmCommand const&); // = delete;
 
 protected:
   cmMakefile* Makefile;
-  cmCommandArgumentsHelper Helper;
 
 private:
   std::string Error;
diff --git a/Source/cmCommandArgumentParser.cxx b/Source/cmCommandArgumentParser.cxx
index e384f21..4a7acfc 100644
--- a/Source/cmCommandArgumentParser.cxx
+++ b/Source/cmCommandArgumentParser.cxx
@@ -1,16 +1,13 @@
-/* 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.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
-/* Skeleton implementation for Bison's Yacc-like parsers in C
+/* Bison implementation for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
 
-   This program is free software; you can redistribute it and/or modify
+   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.
+   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
@@ -18,9 +15,7 @@
    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.  */
+   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
@@ -49,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.3"
+#define YYBISON_VERSION "3.0.4"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -57,58 +52,23 @@
 /* Pure parsers.  */
 #define YYPURE 1
 
-/* Using locations.  */
-#define YYLSP_NEEDED 0
+/* 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 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
-
-
+#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"
+#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.  */
@@ -121,19 +81,14 @@
   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
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
 
 */
 
-#include "cmStandardIncludes.h"
+#include <cmConfigure.h> // IWYU pragma: keep
 
-/* 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)
+#include <string.h>
+
 #define yyGetParser (cmCommandArgument_yyget_extra(yyscanner))
 
 /* Make sure malloc and free are available on QNX.  */
@@ -156,10 +111,9 @@
 /* Forward declare the lexer entry point.  */
 YY_DECL;
 
-/* Internal utility functions.  */
-static void cmCommandArgumentError(yyscan_t yyscanner, const char* message);
+/* Helper function to forward error callback from parser.  */
+static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
 
-#define YYDEBUG 1
 /* Configure the parser to support large input.  */
 #define YYMAXDEPTH 100000
 #define YYINITDEPTH 10000
@@ -173,39 +127,80 @@
 # pragma warning (disable: 4702) /* unreachable code */
 #endif
 
+#line 131 "cmCommandArgumentParser.cxx" /* yacc.c:339  */
 
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
+# 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 0
+# define YYERROR_VERBOSE 1
 #endif
 
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
+/* 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
 
-#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
+/* 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 216 of yacc.c.  */
-#line 227 "cmCommandArgumentParser.cxx"
+#line 204 "cmCommandArgumentParser.cxx" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -219,11 +214,8 @@
 
 #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;
+typedef signed char yytype_int8;
 #endif
 
 #ifdef YYTYPE_UINT16
@@ -243,8 +235,7 @@
 #  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)
+# elif ! defined YYSIZE_T
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
@@ -258,38 +249,67 @@
 # if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
 #  endif
 # endif
 # ifndef YY_
-#  define YY_(msgid) msgid
+#  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))
+# define YYUSE(E) ((void) (E))
 #else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
 #endif
 
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
+#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
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
+# define YY_INITIAL_VALUE(Value) Value
 #endif
-{
-  return i;
-}
+#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
 
@@ -308,11 +328,11 @@
 #    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)
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
 #     endif
 #    endif
 #   endif
@@ -320,8 +340,8 @@
 # endif
 
 # ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+   /* 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
@@ -335,25 +355,23 @@
 #  ifndef YYSTACK_ALLOC_MAXIMUM
 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 #  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
        && ! ((defined YYMALLOC || defined malloc) \
              && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
 #   endif
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   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 _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined free && ! defined EXIT_SUCCESS
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
@@ -368,9 +386,9 @@
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
+  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)
@@ -381,42 +399,46 @@
      ((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
+# 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)                                        \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
     do                                                                  \
       {                                                                 \
         YYSIZE_T yynewbytes;                                            \
-        YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-        Stack = &yyptr->Stack;                                          \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
         yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
         yyptr += yynewbytes / sizeof (*yyptr);                          \
       }                                                                 \
-    while (YYID (0))
+    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.  */
@@ -428,17 +450,19 @@
 #define YYNNTS  10
 /* YYNRULES -- Number of rules.  */
 #define YYNRULES  24
-/* YYNRULES -- Number of states.  */
+/* YYNSTATES -- Number of states.  */
 #define YYNSTATES  33
 
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+/* 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[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+/* 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,
@@ -471,36 +495,16 @@
 };
 
 #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.  */
+  /* 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
+       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 || YYTOKEN_TABLE
+#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[] =
@@ -509,13 +513,13 @@
   "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"",
   "cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start",
   "GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable",
-  "EnvVarName", "MultipleIds", "ID", 0
+  "EnvVarName", "MultipleIds", "ID", YY_NULLPTR
 };
 #endif
 
 # ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
+/* 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,
@@ -523,42 +527,18 @@
 };
 # 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
+
+#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,
@@ -567,17 +547,32 @@
       -3,    -3,    -3
 };
 
-/* YYPGOTO[NTERM-NUM].  */
+  /* 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
 };
 
-/* 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
+  /* 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,
@@ -596,8 +591,8 @@
       14
 };
 
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
+  /* 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,
@@ -606,6 +601,23 @@
       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)
@@ -616,85 +628,30 @@
 #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)                          \
+  if (yychar == YYEMPTY)                                        \
     {                                                           \
       yychar = (Token);                                         \
       yylval = (Value);                                         \
-      yytoken = YYTRANSLATE (yychar);                           \
-      YYPOPSTACK (1);                                           \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
       goto yybackup;                                            \
     }                                                           \
   else                                                          \
     {                                                           \
-      yyerror (YY_("syntax error: cannot back up")); \
+      yyerror (yyscanner, YY_("syntax error: cannot back up")); \
       YYERROR;                                                  \
     }                                                           \
-while (YYID (0))
+while (0)
 
-
+/* Error token number */
 #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
@@ -708,7 +665,13 @@
 do {                                            \
   if (yydebug)                                  \
     YYFPRINTF Args;                             \
-} while (YYID (0))
+} 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 {                                                                      \
@@ -716,42 +679,29 @@
     {                                                                     \
       YYFPRINTF (stderr, "%s ", Title);                                   \
       yy_symbol_print (stderr,                                            \
-                  Type, Value); \
+                  Type, Value, yyscanner); \
       YYFPRINTF (stderr, "\n");                                           \
     }                                                                     \
-} while (YYID (0))
+} while (0)
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+/*----------------------------------------.
+| Print this symbol's value 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
+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);
-# else
-  YYUSE (yyoutput);
 # endif
-  switch (yytype)
-    {
-      default:
-        break;
-    }
+  YYUSE (yytype);
 }
 
 
@@ -759,24 +709,13 @@
 | 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
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
 {
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
   YYFPRINTF (yyoutput, ")");
 }
 
@@ -785,20 +724,15 @@
 | 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
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
 {
   YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
   YYFPRINTF (stderr, "\n");
 }
 
@@ -806,45 +740,38 @@
 do {                                                            \
   if (yydebug)                                                  \
     yy_stack_print ((Bottom), (Top));                           \
-} while (YYID (0))
+} while (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
+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;
-  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],
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
                        &(yyvsp[(yyi + 1) - (yynrhs)])
-                                       );
-      fprintf (stderr, "\n");
+                                              , yyscanner);
+      YYFPRINTF (stderr, "\n");
     }
 }
 
 # define YY_REDUCE_PRINT(Rule)          \
 do {                                    \
   if (yydebug)                          \
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
+    yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \
+} while (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
@@ -873,7 +800,6 @@
 # define YYMAXDEPTH 10000
 #endif
 
-
 
 #if YYERROR_VERBOSE
 
@@ -882,15 +808,8 @@
 #   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++)
@@ -906,16 +825,8 @@
 #  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;
@@ -976,165 +887,159 @@
 }
 # 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)
+/* 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)
 {
-  int yyn = yypact[yystate];
+  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;
 
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
+  /* 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 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)
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
         {
-          /* 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)
+          /* 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];
                 {
-                  yyp += yytnamerr (yyp, yyarg[yyi++]);
-                  yyf += 2;
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
                 }
-              else
-                {
-                  yyp++;
-                  yyf++;
-                }
-            }
+              }
         }
-      return yysize;
     }
+
+  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.  |
 `-----------------------------------------------*/
 
-/*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
+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);
 
-  switch (yytype)
-    {
-
-      default:
-        break;
-    }
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 }
-
-
-/* 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 */
-
-
 
 
 
@@ -1143,44 +1048,53 @@
 | 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
+yyparse (yyscan_t yyscanner)
 {
-  /* The look-ahead symbol.  */
+/* The lookahead symbol.  */
 int yychar;
 
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
 
-/* Number of syntax errors so far.  */
-int yynerrs;
+/* 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);
 
-  int yystate;
+    /* 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;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
+  /* 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];
@@ -1188,54 +1102,22 @@
   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;
 
+  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.  */
-
-  /* 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;
-
+  yychar = YYEMPTY; /* Cause a token to be read.  */
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -1262,7 +1144,6 @@
         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
@@ -1270,7 +1151,6 @@
         yyoverflow (YY_("memory exhausted"),
                     &yyss1, yysize * sizeof (*yyssp),
                     &yyvs1, yysize * sizeof (*yyvsp),
-
                     &yystacksize);
 
         yyss = yyss1;
@@ -1293,9 +1173,8 @@
           (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
         if (! yyptr)
           goto yyexhaustedlab;
-        YYSTACK_RELOCATE (yyss);
-        YYSTACK_RELOCATE (yyvs);
-
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
         if (yyss1 != yyssa)
           YYSTACK_FREE (yyss1);
@@ -1306,7 +1185,6 @@
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
-
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
                   (unsigned long int) yystacksize));
 
@@ -1316,6 +1194,9 @@
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
   goto yybackup;
 
 /*-----------.
@@ -1324,20 +1205,20 @@
 yybackup:
 
   /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
+     lookahead token if we need one and don't already have one.  */
 
-  /* First try to decide what to do without reference to look-ahead token.  */
+  /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
+  if (yypact_value_is_default (yyn))
     goto yydefault;
 
-  /* Not known => get a look-ahead token if don't already have one.  */
+  /* Not known => get a lookahead token if don't already have one.  */
 
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
+      yychar = yylex (&yylval, yyscanner);
     }
 
   if (yychar <= YYEOF)
@@ -1359,29 +1240,27 @@
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
+      if (yytable_value_is_error (yyn))
         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.  */
+  /* Shift the lookahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
 
   yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
   goto yynewstate;
 
@@ -1404,7 +1283,7 @@
   yylen = yyr2[yyn];
 
   /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
+     '$$ = $1'.
 
      Otherwise, the following line sets YYVAL to garbage.
      This behavior is undocumented and Bison
@@ -1418,175 +1297,205 @@
   switch (yyn)
     {
         case 2:
-#line 117 "cmCommandArgumentParser.y"
+#line 96 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = 0;
-  yyGetParser->SetResult((yyvsp[(1) - (1)].str));
-}
+    (yyval.str) = 0;
+    yyGetParser->SetResult((yyvsp[0].str));
+  }
+#line 1306 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 3:
-#line 124 "cmCommandArgumentParser.y"
+#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 4:
-#line 129 "cmCommandArgumentParser.y"
+#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
-}
+    (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
+  }
+#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 5:
-#line 134 "cmCommandArgumentParser.y"
+#line 110 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = 0;
-}
+    (yyval.str) = 0;
+  }
+#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 139 "cmCommandArgumentParser.y"
+#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
-}
+    (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
+  }
+#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 145 "cmCommandArgumentParser.y"
+#line 118 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 150 "cmCommandArgumentParser.y"
+#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 156 "cmCommandArgumentParser.y"
+#line 126 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 161 "cmCommandArgumentParser.y"
+#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 166 "cmCommandArgumentParser.y"
+#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 171 "cmCommandArgumentParser.y"
+#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 176 "cmCommandArgumentParser.y"
+#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 181 "cmCommandArgumentParser.y"
+#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 187 "cmCommandArgumentParser.y"
+#line 146 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str));
-  //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
+    (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
+  }
+#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 193 "cmCommandArgumentParser.y"
+#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str));
-  //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
+    (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
+  }
+#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 199 "cmCommandArgumentParser.y"
+#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = yyGetParser->ExpandVariable((yyvsp[(2) - (3)].str));
-  //std::cerr << __LINE__ << " here: [" << $<str>1 << "] [" << $<str>2 << "] [" << $<str>3 << "]" << std::endl;
-}
+    (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str));
+  }
+#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 205 "cmCommandArgumentParser.y"
+#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[(1) - (1)].str));
-}
+    (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str));
+  }
+#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 211 "cmCommandArgumentParser.y"
+#line 160 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 216 "cmCommandArgumentParser.y"
+#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (2)].str);
-}
+    (yyval.str) = (yyvsp[-1].str);
+  }
+#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 221 "cmCommandArgumentParser.y"
+#line 168 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = 0;
-}
+    (yyval.str) = 0;
+  }
+#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 226 "cmCommandArgumentParser.y"
+#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
-}
+    (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
+  }
+#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 232 "cmCommandArgumentParser.y"
+#line 176 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 237 "cmCommandArgumentParser.y"
+#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646  */
     {
-  (yyval.str) = (yyvsp[(1) - (1)].str);
-}
+    (yyval.str) = (yyvsp[0].str);
+  }
+#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1646  */
     break;
 
 
-/* Line 1267 of yacc.c.  */
-#line 1606 "cmCommandArgumentParser.cxx"
+#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);
@@ -1595,8 +1504,7 @@
 
   *++yyvsp = yyval;
 
-
-  /* Now `shift' the result of the reduction.  Determine what state
+  /* 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.  */
 
@@ -1611,48 +1519,51 @@
   goto yynewstate;
 
 
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| 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 (YY_("syntax error"));
+      yyerror (yyscanner, YY_("syntax error"));
 #else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
       {
-        YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-        if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+        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)
           {
-            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 = (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;
               }
           }
-
-        if (0 < yysize && yysize <= yymsg_alloc)
-          {
-            (void) yysyntax_error (yymsg, yystate, yychar);
-            yyerror (yymsg);
-          }
-        else
-          {
-            yyerror (YY_("syntax error"));
-            if (yysize != 0)
-              goto yyexhaustedlab;
-          }
+        yyerror (yyscanner, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
       }
+# undef YYSYNTAX_ERROR
 #endif
     }
 
@@ -1660,7 +1571,7 @@
 
   if (yyerrstatus == 3)
     {
-      /* If just tried and failed to reuse look-ahead token after an
+      /* If just tried and failed to reuse lookahead token after an
          error, discard it.  */
 
       if (yychar <= YYEOF)
@@ -1672,12 +1583,13 @@
       else
         {
           yydestruct ("Error: discarding",
-                      yytoken, &yylval);
+                      yytoken, &yylval, yyscanner);
           yychar = YYEMPTY;
         }
     }
 
-  /* Else will try to reuse look-ahead token after shifting the error
+#if 0
+  /* Else will try to reuse lookahead token after shifting the error
      token.  */
   goto yyerrlab1;
 
@@ -1693,7 +1605,7 @@
   if (/*CONSTCOND*/ 0)
      goto yyerrorlab;
 
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
   yylen = 0;
@@ -1706,12 +1618,13 @@
 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
 `-------------------------------------------------------------*/
 yyerrlab1:
+#endif
   yyerrstatus = 3;      /* Each real token shifted decrements this.  */
 
   for (;;)
     {
       yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
+      if (!yypact_value_is_default (yyn))
         {
           yyn += YYTERROR;
           if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -1728,16 +1641,15 @@
 
 
       yydestruct ("Error: popping",
-                  yystos[yystate], yyvsp);
+                  yystos[yystate], yyvsp, yyscanner);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
 
   /* Shift the error token.  */
@@ -1761,28 +1673,33 @@
   yyresult = 1;
   goto yyreturn;
 
-#ifndef yyoverflow
+#if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
 yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
+  yyerror (yyscanner, 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
+  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);
+                  yystos[*yyssp], yyvsp, yyscanner);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -1793,19 +1710,14 @@
   if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);
 #endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
+  return yyresult;
 }
-
-
-#line 242 "cmCommandArgumentParser.y"
+#line 184 "cmCommandArgumentParser.y" /* yacc.c:1906  */
 
 /* End of grammar */
 
 /*--------------------------------------------------------------------------*/
-void cmCommandArgumentError(yyscan_t yyscanner, const char* message)
+void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message)
 {
   yyGetParser->Error(message);
 }
-
-
diff --git a/Source/cmCommandArgumentParser.y b/Source/cmCommandArgumentParser.y
index b2f4b1b..d71b605 100644
--- a/Source/cmCommandArgumentParser.y
+++ b/Source/cmCommandArgumentParser.y
@@ -10,20 +10,14 @@
   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
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
 
 */
 
-#include "cmStandardIncludes.h"
+#include <cmConfigure.h> // IWYU pragma: keep
 
-/* 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)
+#include <string.h>
+
 #define yyGetParser (cmCommandArgument_yyget_extra(yyscanner))
 
 /* Make sure malloc and free are available on QNX.  */
@@ -46,10 +40,9 @@
 /* Forward declare the lexer entry point.  */
 YY_DECL;
 
-/* Internal utility functions.  */
-static void cmCommandArgumentError(yyscan_t yyscanner, const char* message);
+/* Helper function to forward error callback from parser.  */
+static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
 
-#define YYDEBUG 1
 /* Configure the parser to support large input.  */
 #define YYMAXDEPTH 100000
 #define YYINITDEPTH 10000
@@ -65,7 +58,13 @@
 %}
 
 /* Generate a reentrant parser object.  */
-%pure_parser
+%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 {
@@ -94,137 +93,99 @@
 
 
 Start:
-GoalWithOptionalBackSlash
-{
-  $<str>$ = 0;
-  yyGetParser->SetResult($<str>1);
-}
+  GoalWithOptionalBackSlash {
+    $<str>$ = 0;
+    yyGetParser->SetResult($<str>1);
+  }
 
 GoalWithOptionalBackSlash:
-Goal
-{
-  $<str>$ = $<str>1;
-}
-|
-Goal cal_BSLASH
-{
-  $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
-}
+  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);
-}
+  {
+    $<str>$ = 0;
+  }
+| String Goal {
+    $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
+  }
 
 String:
-OuterText
-{
-  $<str>$ = $<str>1;
-}
-|
-Variable
-{
-  $<str>$ = $<str>1;
-}
+  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;
-}
+  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);
-}
+  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>$ = $<str>1;
+  }
+| cal_SYMBOL EnvVarName {
+    $<str>$ = $<str>1;
+  }
 
 MultipleIds:
-{
-  $<str>$ = 0;
-}
-|
-ID MultipleIds
-{
-  $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
-}
+  {
+    $<str>$ = 0;
+  }
+| ID MultipleIds {
+    $<str>$ = yyGetParser->CombineUnions($<str>1, $<str>2);
+  }
 
 ID:
-cal_NAME
-{
-  $<str>$ = $<str>1;
-}
-|
-Variable
-{
-  $<str>$ = $<str>1;
-}
-
+  cal_NAME {
+    $<str>$ = $<str>1;
+  }
+| Variable {
+    $<str>$ = $<str>1;
+  }
+;
 
 %%
 /* End of grammar */
 
 /*--------------------------------------------------------------------------*/
-void cmCommandArgumentError(yyscan_t yyscanner, const char* message)
+void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message)
 {
   yyGetParser->Error(message);
 }
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 2d66344..1222d5a 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -2,8 +2,6 @@
    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"
diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h
index 95bf0ad..5bfb236 100644
--- a/Source/cmCommandArgumentParserHelper.h
+++ b/Source/cmCommandArgumentParserHelper.h
@@ -8,27 +8,15 @@
 #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
 {
 public:
-  typedef struct
+  struct ParserType
   {
     char* str;
-  } ParserType;
+  };
 
   cmCommandArgumentParserHelper();
   ~cmCommandArgumentParserHelper();
@@ -100,4 +88,10 @@
   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
index d162b82..3172182 100644
--- a/Source/cmCommandArgumentParserTokens.h
+++ b/Source/cmCommandArgumentParserTokens.h
@@ -1,16 +1,13 @@
-/* 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.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
 
-   This program is free software; you can redistribute it and/or modify
+   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.
+   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
@@ -18,9 +15,7 @@
    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.  */
+   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
@@ -35,25 +30,34 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
-/* Tokens.  */
+#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
-   /* 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
-   };
+  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
@@ -69,15 +73,10 @@
 #define cal_ERROR 268
 #define cal_ATNAME 269
 
+/* Value type.  */
 
 
 
-#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
+int cmCommandArgument_yyparse (yyscan_t yyscanner);
 
-
-
+#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED  */
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 4c5b093..1576722 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"
@@ -77,6 +79,7 @@
 #include "cmAuxSourceDirectoryCommand.h"
 #include "cmBuildNameCommand.h"
 #include "cmCMakeHostSystemInformationCommand.h"
+#include "cmDisallowedCommand.h"
 #include "cmExportCommand.h"
 #include "cmExportLibraryDependenciesCommand.h"
 #include "cmFLTKWrapUICommand.h"
@@ -104,138 +107,162 @@
 #include "cmWriteFileCommand.h"
 #endif
 
-std::vector<cmCommand*> GetPredefinedCommands()
+void GetScriptingCommands(cmState* state)
 {
-  std::vector<cmCommand*> commands;
+  state->AddCommand(new cmBreakCommand);
+  state->AddCommand(new cmCMakeMinimumRequired);
+  state->AddCommand(new cmCMakePolicyCommand);
+  state->AddCommand(new cmConfigureFileCommand);
+  state->AddCommand(new cmContinueCommand);
+  state->AddCommand(new cmExecProgramCommand);
+  state->AddCommand(new cmExecuteProcessCommand);
+  state->AddCommand(new cmFileCommand);
+  state->AddCommand(new cmFindFileCommand);
+  state->AddCommand(new cmFindLibraryCommand);
+  state->AddCommand(new cmFindPackageCommand);
+  state->AddCommand(new cmFindPathCommand);
+  state->AddCommand(new cmFindProgramCommand);
+  state->AddCommand(new cmForEachCommand);
+  state->AddCommand(new cmFunctionCommand);
+  state->AddCommand(new cmGetCMakePropertyCommand);
+  state->AddCommand(new cmGetDirectoryPropertyCommand);
+  state->AddCommand(new cmGetFilenameComponentCommand);
+  state->AddCommand(new cmGetPropertyCommand);
+  state->AddCommand(new cmIfCommand);
+  state->AddCommand(new cmIncludeCommand);
+  state->AddCommand(new cmListCommand);
+  state->AddCommand(new cmMacroCommand);
+  state->AddCommand(new cmMakeDirectoryCommand);
+  state->AddCommand(new cmMarkAsAdvancedCommand);
+  state->AddCommand(new cmMathCommand);
+  state->AddCommand(new cmMessageCommand);
+  state->AddCommand(new cmOptionCommand);
+  state->AddCommand(new cmParseArgumentsCommand);
+  state->AddCommand(new cmReturnCommand);
+  state->AddCommand(new cmSeparateArgumentsCommand);
+  state->AddCommand(new cmSetCommand);
+  state->AddCommand(new cmSetDirectoryPropertiesCommand);
+  state->AddCommand(new cmSetPropertyCommand);
+  state->AddCommand(new cmSiteNameCommand);
+  state->AddCommand(new cmStringCommand);
+  state->AddCommand(new cmUnsetCommand);
+  state->AddCommand(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->AddCommand(new cmUnexpectedCommand(
     "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(
+  state->AddCommand(new cmUnexpectedCommand(
     "elseif", "An ELSEIF command was found outside of a proper "
               "IF ENDIF structure."));
-  commands.push_back(new cmUnexpectedCommand(
+  state->AddCommand(new cmUnexpectedCommand(
     "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(
+  state->AddCommand(new cmUnexpectedCommand(
     "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(
+  state->AddCommand(new cmUnexpectedCommand(
     "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(
+  state->AddCommand(new cmUnexpectedCommand(
     "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(
+  state->AddCommand(new cmUnexpectedCommand(
     "endwhile", "An ENDWHILE command was found outside of a proper "
                 "WHILE ENDWHILE structure. Or its arguments did not "
                 "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);
-#endif
+  state->AddCommand(new cmCMakeHostSystemInformationCommand);
+  state->AddCommand(new cmRemoveCommand);
+  state->AddCommand(new cmVariableWatchCommand);
+  state->AddCommand(new cmWriteFileCommand);
 
-  return commands;
+  state->AddCommand(new cmDisallowedCommand(
+    new cmBuildNameCommand, cmPolicies::CMP0036,
+    "The build_name command should not be called; see CMP0036."));
+  state->AddCommand(new cmDisallowedCommand(
+    new cmUseMangledMesaCommand, cmPolicies::CMP0030,
+    "The use_mangled_mesa command should not be called; see CMP0030."));
+
+#endif
+}
+
+void GetProjectCommands(cmState* state)
+{
+  state->AddCommand(new cmAddCustomCommandCommand);
+  state->AddCommand(new cmAddCustomTargetCommand);
+  state->AddCommand(new cmAddDefinitionsCommand);
+  state->AddCommand(new cmAddDependenciesCommand);
+  state->AddCommand(new cmAddExecutableCommand);
+  state->AddCommand(new cmAddLibraryCommand);
+  state->AddCommand(new cmAddSubDirectoryCommand);
+  state->AddCommand(new cmAddTestCommand);
+  state->AddCommand(new cmBuildCommand);
+  state->AddCommand(new cmCreateTestSourceList);
+  state->AddCommand(new cmDefinePropertyCommand);
+  state->AddCommand(new cmEnableLanguageCommand);
+  state->AddCommand(new cmEnableTestingCommand);
+  state->AddCommand(new cmGetSourceFilePropertyCommand);
+  state->AddCommand(new cmGetTargetPropertyCommand);
+  state->AddCommand(new cmGetTestPropertyCommand);
+  state->AddCommand(new cmIncludeDirectoryCommand);
+  state->AddCommand(new cmIncludeRegularExpressionCommand);
+  state->AddCommand(new cmInstallCommand);
+  state->AddCommand(new cmInstallFilesCommand);
+  state->AddCommand(new cmInstallTargetsCommand);
+  state->AddCommand(new cmLinkDirectoriesCommand);
+  state->AddCommand(new cmProjectCommand);
+  state->AddCommand(new cmSetSourceFilesPropertiesCommand);
+  state->AddCommand(new cmSetTargetPropertiesCommand);
+  state->AddCommand(new cmSetTestsPropertiesCommand);
+  state->AddCommand(new cmSubdirCommand);
+  state->AddCommand(new cmTargetLinkLibrariesCommand);
+  state->AddCommand(new cmTryCompileCommand);
+  state->AddCommand(new cmTryRunCommand);
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  state->AddCommand(new cmAddCompileOptionsCommand);
+  state->AddCommand(new cmAuxSourceDirectoryCommand);
+  state->AddCommand(new cmExportCommand);
+  state->AddCommand(new cmFLTKWrapUICommand);
+  state->AddCommand(new cmIncludeExternalMSProjectCommand);
+  state->AddCommand(new cmInstallProgramsCommand);
+  state->AddCommand(new cmLinkLibrariesCommand);
+  state->AddCommand(new cmLoadCacheCommand);
+  state->AddCommand(new cmQTWrapCPPCommand);
+  state->AddCommand(new cmQTWrapUICommand);
+  state->AddCommand(new cmRemoveDefinitionsCommand);
+  state->AddCommand(new cmSourceGroupCommand);
+  state->AddCommand(new cmTargetCompileDefinitionsCommand);
+  state->AddCommand(new cmTargetCompileFeaturesCommand);
+  state->AddCommand(new cmTargetCompileOptionsCommand);
+  state->AddCommand(new cmTargetIncludeDirectoriesCommand);
+  state->AddCommand(new cmTargetSourcesCommand);
+
+  state->AddCommand(new cmDisallowedCommand(
+    new cmExportLibraryDependenciesCommand, cmPolicies::CMP0033,
+    "The export_library_dependencies command should not be called; "
+    "see CMP0033."));
+  state->AddCommand(new cmDisallowedCommand(
+    new cmLoadCommandCommand, cmPolicies::CMP0031,
+    "The load_command command should not be called; see CMP0031."));
+  state->AddCommand(new cmDisallowedCommand(
+    new cmOutputRequiredFilesCommand, cmPolicies::CMP0032,
+    "The output_required_files command should not be called; "
+    "see CMP0032."));
+  state->AddCommand(new cmDisallowedCommand(
+    new cmSubdirDependsCommand, cmPolicies::CMP0029,
+    "The subdir_depends command should not be called; see CMP0029."));
+  state->AddCommand(new cmDisallowedCommand(
+    new cmUtilitySourceCommand, cmPolicies::CMP0034,
+    "The utility_source command should not be called; see CMP0034."));
+  state->AddCommand(new cmDisallowedCommand(
+    new cmVariableRequiresCommand, cmPolicies::CMP0035,
+    "The variable_requires command should not be called; see CMP0035."));
+#endif
 }
diff --git a/Source/cmCommands.h b/Source/cmCommands.h
index 649dea6..7895ece 100644
--- a/Source/cmCommands.h
+++ b/Source/cmCommands.h
@@ -3,16 +3,14 @@
 #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);
 
 #endif
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 239582f..fd1ad36 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -26,7 +26,6 @@
   , GlobalGenerator(static_cast<cmGlobalCommonGenerator*>(
       gt->LocalGenerator->GetGlobalGenerator()))
   , ConfigName(LocalGenerator->GetConfigName())
-  , ModuleDefinitionFile(GeneratorTarget->GetModuleDefinitionFile(ConfigName))
 {
 }
 
@@ -63,14 +62,9 @@
 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 +79,7 @@
   // 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..8d68123 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -44,9 +44,6 @@
   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/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 26f1df2..5f89ba1 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)
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index ff9ffc0..fd9d04b 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -8,6 +8,7 @@
 #include <sstream>
 #include <stdio.h>
 #include <string.h>
+#include <utility>
 
 #include "cmAlgorithms.h"
 #include "cmExportTryCompileFileGenerator.h"
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index c189419..b8c76b9 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -7,6 +7,7 @@
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
+#include "cmWorkingDirectory.h"
 
 #include <cmsys/FStream.hxx>
 #include <sstream>
@@ -75,13 +76,7 @@
                       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 @@
     okay = false;
   }
 
-  // Restore working directory.
-  if (oldcwd != ".") {
-    cmSystemTools::ChangeDirectory(oldcwd);
-  }
-
   return okay;
 }
 
diff --git a/Source/cmDependsJavaParser.cxx b/Source/cmDependsJavaParser.cxx
index b99d631..b09bd0c 100644
--- a/Source/cmDependsJavaParser.cxx
+++ b/Source/cmDependsJavaParser.cxx
@@ -1,12 +1,13 @@
-/* A Bison parser, made by GNU Bison 1.875d.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
-/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984,
-   1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Bison implementation for Yacc-like parsers in C
 
-   This program is free software; you can redistribute it and/or modify
+   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 2, or (at your option)
-   any later version.
+   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
@@ -14,17 +15,23 @@
    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.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-/* 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.  */
+/* 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.
 
-/* Written by Richard Stallman by simplifying the original so called
-   ``semantic'' parser.  */
+   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
@@ -33,145 +40,223 @@
    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
 
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.4"
+
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 
 /* Pure parsers.  */
 #define YYPURE 1
 
-/* Using locations.  */
-#define YYLSP_NEEDED 0
+/* Push parsers.  */
+#define YYPUSH 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
+/* Pull parsers.  */
+#define YYPULL 1
 
 
-/* Tokens.  */
+/* 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
-   /* 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
-   };
+  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
@@ -276,141 +361,205 @@
 #define jp_TIMESEQUALS 359
 #define jp_ERROR 360
 
+/* Value type.  */
 
 
 
-/* Copy the first part of user declarations.  */
-#line 1 "cmDependsJavaParser.y"
+int cmDependsJava_yyparse (yyscan_t yyscanner);
 
-/* 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
-
-
+#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED  */
 
 /* Copy the second part of user declarations.  */
 
+#line 375 "cmDependsJavaParser.cxx" /* yacc.c:358  */
 
-/* Line 214 of yacc.c.  */
-#line 372 "cmDependsJavaParser.cxx"
+#ifdef short
+# undef short
+#endif
 
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
 
-# ifndef YYFREE
-#  define YYFREE free
+#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
-# ifndef YYMALLOC
-#  define YYMALLOC malloc
+#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
-#   define YYSTACK_ALLOC alloca
-#  endif
-# else
-#  if defined (alloca) || defined (_ALLOCA_H)
-#   define YYSTACK_ALLOC alloca
-#  else
 #   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. */
+   /* 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
+#  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 */
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
 
 
-#if (! defined (yyoverflow) \
-     && (! defined (__cplusplus) \
-   || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+#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;
-  };
+  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)
@@ -418,74 +567,74 @@
 /* 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))      \
+     ((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 (0)
-#  endif
-# endif
+# 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)          \
-    do                  \
-      {                  \
-  YYSIZE_T yynewbytes;            \
-  YYCOPY (&yyptr->Stack, Stack, yysize);        \
-  Stack = &yyptr->Stack;            \
-  yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-  yyptr += yynewbytes / sizeof (*yyptr);        \
-      }                  \
+# 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 (__STDC__) || defined (__cplusplus)
-   typedef signed char yysigned_char;
-#else
-   typedef short int yysigned_char;
-#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. */
+/* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  23
 /* YYLAST -- Last index in YYTABLE.  */
 #define YYLAST   2215
 
-/* YYNTOKENS -- Number of terminals. */
+/* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  106
-/* YYNNTS -- Number of nonterminals. */
+/* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  158
-/* YYNRULES -- Number of rules. */
+/* YYNRULES -- Number of rules.  */
 #define YYNRULES  351
-/* YYNRULES -- Number of states. */
+/* YYNSTATES -- Number of states.  */
 #define YYNSTATES  575
 
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+/* 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)             \
+#define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const unsigned char yytranslate[] =
+/* 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,
@@ -527,201 +676,51 @@
 };
 
 #if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const unsigned short int yyprhs[] =
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
 {
-       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
+       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
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+#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",
@@ -798,14 +797,14 @@
   "ConditionalAndExpression", "ConditionalOrExpression",
   "ConditionalExpression", "AssignmentExpression", "Assignment",
   "LeftHandSide", "AssignmentOperator", "Expression", "ConstantExpression",
-  "New", 0
+  "New", YY_NULLPTR
 };
 #endif
 
 # ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const unsigned short int yytoknum[] =
+/* 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,
@@ -821,178 +820,19 @@
 };
 # 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[] =
+
+#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,
@@ -1054,8 +894,73 @@
     1699,   432,  -503,  1699,  -503
 };
 
-/* YYPGOTO[NTERM-NUM].  */
-static const short int yypgoto[] =
+  /* 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,
@@ -1075,12 +980,31 @@
       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[] =
+  /* 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,
@@ -1306,7 +1230,7 @@
        0,     0,     0,     0,     0,   305
 };
 
-static const short int yycheck[] =
+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,
@@ -1532,9 +1456,9 @@
       -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[] =
+  /* 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,
@@ -1596,78 +1520,123 @@
       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
+  /* 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
+};
 
-#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
+  /* 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
+};
 
 
-/* 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 yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
 
-#define YYFAIL    goto yyerrlab
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
 
 #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;              \
-    }                \
+#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)
 
-#define YYTERROR  1
-#define YYERRCODE  256
+/* Error token number */
+#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
@@ -1677,54 +1646,85 @@
 #  define YYFPRINTF fprintf
 # endif
 
-# define YYDPRINTF(Args)      \
-do {            \
-  if (yydebug)          \
-    YYFPRINTF Args;        \
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
 } while (0)
 
-# define YYDSYMPRINT(Args)      \
-do {            \
-  if (yydebug)          \
-    yysymprint Args;        \
+/* 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)
 
-# define YYDSYMPRINTF(Title, Token, Value, Location)    \
-do {                \
-  if (yydebug)              \
-    {                \
-      YYFPRINTF (stderr, "%s ", Title);        \
-      yysymprint (stderr,           \
-                  Token, Value);  \
-      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).                                                   |
 `------------------------------------------------------------------*/
 
-#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
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
 {
   YYFPRINTF (stderr, "Stack now");
-  for (/* Nothing. */; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
+  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));        \
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
 } while (0)
 
 
@@ -1732,29 +1732,30 @@
 | 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
+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;
-  unsigned int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
              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]]);
+  /* 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 (Rule);    \
+# 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
@@ -1762,15 +1763,14 @@
 int yydebug;
 #else /* !YYDEBUG */
 # define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, Value, Location)
+# 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
+#ifndef YYINITDEPTH
 # define YYINITDEPTH 200
 #endif
 
@@ -1778,58 +1778,40 @@
    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)
+   YYSTACK_ALLOC_MAXIMUM < 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)
+#  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')
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
     continue;
-
-  return yys - yystr - 1;
+  return yylen;
 }
 #  endif
 # endif
 
 # ifndef yystpcpy
-#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#  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;
@@ -1842,91 +1824,207 @@
 #  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
+# 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)
 {
-  /* Pacify ``unused variable'' warnings.  */
-  (void) yyvaluep;
-
-  if (yytype < YYNTOKENS)
+  if (*yystr == '"')
     {
-      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
-      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
-    }
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
 
-  switch (yytype)
-    {
-      default:
-        break;
+      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: ;
     }
-  YYFPRINTF (yyoutput, ")");
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
 }
+# endif
 
-#endif /* ! YYDEBUG */
+/* 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.  |
 `-----------------------------------------------*/
 
-#if defined (__STDC__) || defined (__cplusplus)
 static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yytype, yyvaluep)
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner)
 {
-  /* Pacify ``unused variable'' warnings.  */
-  (void) yyvaluep;
+  YYUSE (yyvaluep);
+  YYUSE (yyscanner);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
-  switch (yytype)
-    {
-
-      default:
-        break;
-    }
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 }
-
-
-/* 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 */
-
-
 
 
 
@@ -1935,90 +2033,76 @@
 | 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
+yyparse (yyscan_t yyscanner)
 {
-  /* The lookahead symbol.  */
+/* The lookahead symbol.  */
 int yychar;
 
+
 /* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
+/* 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;
+    /* Number of syntax errors so far.  */
+    int yynerrs;
 
-  int yystate;
+    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;
-  /* 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;
 
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
 
-  /* When reducing, the number of symbols on the RHS of the reduced
-     rule.  */
-  int yylen;
+#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.  */
-
-  /* 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;
-
-
+  yychar = YYEMPTY; /* Cause a token to be read.  */
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -2026,8 +2110,7 @@
 `------------------------------------------------------------*/
  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.
-     */
+     have just been pushed.  So pushing a state here evens the stacks.  */
   yyssp++;
 
  yysetstate:
@@ -2040,49 +2123,46 @@
 
 #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;
+        /* 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);
 
-  /* 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;
+        yyss = yyss1;
+        yyvs = yyvs1;
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
-      goto yyoverflowlab;
+      goto yyexhaustedlab;
 # else
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-  goto yyoverflowlab;
+        goto yyexhaustedlab;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
-  yystacksize = YYMAXDEPTH;
+        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);
-
+        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);
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
       }
 # endif
 #endif /* no yyoverflow */
@@ -2090,16 +2170,18 @@
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
-
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-      (unsigned long int) yystacksize));
+                  (unsigned long int) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
-  YYABORT;
+        YYABORT;
     }
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
   goto yybackup;
 
 /*-----------.
@@ -2107,14 +2189,12 @@
 `-----------*/
 yybackup:
 
-/* Do appropriate processing given the current state.  */
-/* Read a lookahead token if we need one and don't already have one.  */
-/* yyresume: */
+  /* 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 (yyn == YYPACT_NINF)
+  if (yypact_value_is_default (yyn))
     goto yydefault;
 
   /* Not known => get a lookahead token if don't already have one.  */
@@ -2123,7 +2203,7 @@
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
+      yychar = yylex (&yylval, yyscanner);
     }
 
   if (yychar <= YYEOF)
@@ -2134,7 +2214,7 @@
   else
     {
       yytoken = YYTRANSLATE (yychar);
-      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
     }
 
   /* If the proper action on seeing token YYTOKEN is to reduce or to
@@ -2145,31 +2225,28 @@
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-  goto yyerrlab;
+      if (yytable_value_is_error (yyn))
+        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--;
 
+  /* 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;
 
 
@@ -2191,7 +2268,7 @@
   yylen = yyr2[yyn];
 
   /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
+     '$$ = $1'.
 
      Otherwise, the following line sets YYVAL to garbage.
      This behavior is undocumented and Bison
@@ -2205,3581 +2282,3927 @@
   switch (yyn)
     {
         case 2:
-#line 192 "cmDependsJavaParser.y"
+#line 180 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2293 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 3:
-#line 201 "cmDependsJavaParser.y"
+#line 189 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2304 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 4:
-#line 209 "cmDependsJavaParser.y"
+#line 197 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2315 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 5:
-#line 217 "cmDependsJavaParser.y"
+#line 205 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2326 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 225 "cmDependsJavaParser.y"
+#line 213 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2337 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 233 "cmDependsJavaParser.y"
+#line 221 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2348 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 241 "cmDependsJavaParser.y"
+#line 229 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2359 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 250 "cmDependsJavaParser.y"
+#line 238 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2370 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 258 "cmDependsJavaParser.y"
+#line 246 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2381 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 267 "cmDependsJavaParser.y"
+#line 255 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2392 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 275 "cmDependsJavaParser.y"
+#line 263 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2403 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 284 "cmDependsJavaParser.y"
+#line 272 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
 }
+#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 289 "cmDependsJavaParser.y"
+#line 277 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
 }
+#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 294 "cmDependsJavaParser.y"
+#line 282 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
 }
+#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 299 "cmDependsJavaParser.y"
+#line 287 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
 }
+#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 304 "cmDependsJavaParser.y"
+#line 292 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
 }
+#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 309 "cmDependsJavaParser.y"
+#line 297 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
 }
+#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 314 "cmDependsJavaParser.y"
+#line 302 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
 }
+#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 319 "cmDependsJavaParser.y"
+#line 307 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
 }
+#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 325 "cmDependsJavaParser.y"
+#line 313 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2478 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 333 "cmDependsJavaParser.y"
+#line 321 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2489 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 342 "cmDependsJavaParser.y"
+#line 330 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  jpStoreClass(yyvsp[0].str);
+  jpStoreClass((yyvsp[0].str));
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2501 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 352 "cmDependsJavaParser.y"
+#line 340 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2512 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 361 "cmDependsJavaParser.y"
+#line 349 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2523 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 26:
-#line 370 "cmDependsJavaParser.y"
+#line 358 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2534 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 27:
-#line 378 "cmDependsJavaParser.y"
+#line 366 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
-  jpStoreClass(yyvsp[-1].str);
+  jpStoreClass((yyvsp[-1].str));
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2546 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 28:
-#line 388 "cmDependsJavaParser.y"
+#line 376 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyval.str = yyvsp[0].str;
+  (yyval.str) = (yyvsp[0].str);
 }
+#line 2555 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 29:
-#line 394 "cmDependsJavaParser.y"
+#line 382 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyval.str = yyvsp[0].str;
+  (yyval.str) = (yyvsp[0].str);
 }
+#line 2564 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 30:
-#line 401 "cmDependsJavaParser.y"
+#line 389 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyval.str = yyvsp[0].str;
+  (yyval.str) = (yyvsp[0].str);
 }
+#line 2573 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 408 "cmDependsJavaParser.y"
+#line 396 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyval.str = yyvsp[0].str;
+  (yyval.str) = (yyvsp[0].str);
 }
+#line 2582 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 414 "cmDependsJavaParser.y"
+#line 402 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
-  yyval.str = yyvsp[0].str;
+  (yyval.str) = (yyvsp[0].str);
 }
+#line 2591 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 421 "cmDependsJavaParser.y"
+#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());
+  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 430 "cmDependsJavaParser.y"
+#line 418 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  jpStoreClass(yyvsp[-2].str);
+  jpStoreClass((yyvsp[-2].str));
   jpCheckEmpty(3);
   yyGetParser->SetCurrentCombine("");
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2616 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 440 "cmDependsJavaParser.y"
+#line 428 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  jpStoreClass(yyvsp[-2].str);
+  jpStoreClass((yyvsp[-2].str));
   yyGetParser->SetCurrentCombine("");
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2629 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 450 "cmDependsJavaParser.y"
+#line 438 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2640 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 459 "cmDependsJavaParser.y"
+#line 447 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2651 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 467 "cmDependsJavaParser.y"
+#line 455 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2662 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 476 "cmDependsJavaParser.y"
+#line 464 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2673 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 484 "cmDependsJavaParser.y"
+#line 472 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2683 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 491 "cmDependsJavaParser.y"
+#line 479 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2694 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 42:
-#line 499 "cmDependsJavaParser.y"
+#line 487 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2704 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 506 "cmDependsJavaParser.y"
+#line 494 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2715 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 514 "cmDependsJavaParser.y"
+#line 502 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2725 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 521 "cmDependsJavaParser.y"
+#line 509 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2736 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 530 "cmDependsJavaParser.y"
+#line 518 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  yyGetParser->SetCurrentPackage(yyvsp[-1].str);
-  yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
+  yyGetParser->SetCurrentPackage((yyvsp[-1].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
   yyGetParser->SetCurrentCombine("");
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2750 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 542 "cmDependsJavaParser.y"
+#line 530 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2761 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 550 "cmDependsJavaParser.y"
+#line 538 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2772 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 49:
-#line 559 "cmDependsJavaParser.y"
+#line 547 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  yyGetParser->AddPackagesImport(yyvsp[-1].str);
-  yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
+  yyGetParser->AddPackagesImport((yyvsp[-1].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
   yyGetParser->SetCurrentCombine("");
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2786 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 50:
-#line 571 "cmDependsJavaParser.y"
+#line 559 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
-  std::string str = yyvsp[-3].str;
+  std::string str = (yyvsp[-3].str);
   str += ".*";
   yyGetParser->AddPackagesImport(str.c_str());
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
   yyGetParser->SetCurrentCombine("");
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2801 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 51:
-#line 584 "cmDependsJavaParser.y"
+#line 572 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2812 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 52:
-#line 592 "cmDependsJavaParser.y"
+#line 580 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2823 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 53:
-#line 600 "cmDependsJavaParser.y"
+#line 588 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2834 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 54:
-#line 609 "cmDependsJavaParser.y"
+#line 597 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2845 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 55:
-#line 617 "cmDependsJavaParser.y"
+#line 605 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2856 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 67:
-#line 632 "cmDependsJavaParser.y"
+#line 620 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
-  yyGetParser->StartClass(yyvsp[0].str);
+  yyGetParser->StartClass((yyvsp[0].str));
   jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(3);
 }
+#line 2867 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 68:
-#line 642 "cmDependsJavaParser.y"
+#line 630 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
+#line 2879 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 69:
-#line 651 "cmDependsJavaParser.y"
+#line 639 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
+#line 2891 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 70:
-#line 660 "cmDependsJavaParser.y"
+#line 648 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
+#line 2903 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 71:
-#line 669 "cmDependsJavaParser.y"
+#line 657 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
+#line 2915 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 72:
-#line 678 "cmDependsJavaParser.y"
+#line 666 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2925 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 73:
-#line 685 "cmDependsJavaParser.y"
+#line 673 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2936 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 74:
-#line 694 "cmDependsJavaParser.y"
+#line 682 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2947 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 75:
-#line 703 "cmDependsJavaParser.y"
+#line 691 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2958 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 76:
-#line 712 "cmDependsJavaParser.y"
+#line 700 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2969 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 77:
-#line 720 "cmDependsJavaParser.y"
+#line 708 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2980 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 78:
-#line 729 "cmDependsJavaParser.y"
+#line 717 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 2991 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 79:
-#line 737 "cmDependsJavaParser.y"
+#line 725 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3001 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 80:
-#line 744 "cmDependsJavaParser.y"
+#line 732 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3012 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 81:
-#line 753 "cmDependsJavaParser.y"
+#line 741 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3023 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 82:
-#line 761 "cmDependsJavaParser.y"
+#line 749 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3034 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 83:
-#line 769 "cmDependsJavaParser.y"
+#line 757 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3045 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 84:
-#line 777 "cmDependsJavaParser.y"
+#line 765 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3056 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 85:
-#line 786 "cmDependsJavaParser.y"
+#line 774 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3067 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 86:
-#line 794 "cmDependsJavaParser.y"
+#line 782 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3078 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 87:
-#line 803 "cmDependsJavaParser.y"
+#line 791 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
 }
+#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 88:
-#line 809 "cmDependsJavaParser.y"
+#line 797 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3097 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 89:
-#line 817 "cmDependsJavaParser.y"
+#line 805 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3108 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 90:
-#line 826 "cmDependsJavaParser.y"
+#line 814 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3119 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 91:
-#line 834 "cmDependsJavaParser.y"
+#line 822 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3130 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 92:
-#line 843 "cmDependsJavaParser.y"
+#line 831 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3142 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 93:
-#line 852 "cmDependsJavaParser.y"
+#line 840 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3153 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 94:
-#line 861 "cmDependsJavaParser.y"
+#line 849 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3164 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 95:
-#line 869 "cmDependsJavaParser.y"
+#line 857 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3175 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 96:
-#line 878 "cmDependsJavaParser.y"
+#line 866 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3186 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 97:
-#line 886 "cmDependsJavaParser.y"
+#line 874 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3197 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 98:
-#line 894 "cmDependsJavaParser.y"
+#line 882 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3208 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 99:
-#line 903 "cmDependsJavaParser.y"
+#line 891 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3220 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 100:
-#line 912 "cmDependsJavaParser.y"
+#line 900 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3232 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 101:
-#line 921 "cmDependsJavaParser.y"
+#line 909 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3243 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 102:
-#line 929 "cmDependsJavaParser.y"
+#line 917 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3255 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 103:
-#line 939 "cmDependsJavaParser.y"
+#line 927 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3268 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 104:
-#line 949 "cmDependsJavaParser.y"
+#line 937 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
 
 }
+#line 3277 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 105:
-#line 955 "cmDependsJavaParser.y"
+#line 943 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3288 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 107:
-#line 966 "cmDependsJavaParser.y"
+#line 954 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
 
 }
+#line 3297 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 108:
-#line 972 "cmDependsJavaParser.y"
+#line 960 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3309 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 109:
-#line 982 "cmDependsJavaParser.y"
+#line 970 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3321 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 110:
-#line 992 "cmDependsJavaParser.y"
+#line 980 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3333 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 111:
-#line 1002 "cmDependsJavaParser.y"
+#line 990 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
 
 }
+#line 3342 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 112:
-#line 1008 "cmDependsJavaParser.y"
+#line 996 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3354 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 113:
-#line 1018 "cmDependsJavaParser.y"
+#line 1006 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3366 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 114:
-#line 1028 "cmDependsJavaParser.y"
+#line 1016 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3378 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 115:
-#line 1038 "cmDependsJavaParser.y"
+#line 1026 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3390 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 116:
-#line 1047 "cmDependsJavaParser.y"
+#line 1035 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3402 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 117:
-#line 1057 "cmDependsJavaParser.y"
+#line 1045 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3415 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 118:
-#line 1068 "cmDependsJavaParser.y"
+#line 1056 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3427 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 119:
-#line 1077 "cmDependsJavaParser.y"
+#line 1065 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3438 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 120:
-#line 1085 "cmDependsJavaParser.y"
+#line 1073 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3450 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 121:
-#line 1095 "cmDependsJavaParser.y"
+#line 1083 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3462 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 122:
-#line 1104 "cmDependsJavaParser.y"
+#line 1092 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3474 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 123:
-#line 1114 "cmDependsJavaParser.y"
+#line 1102 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
-  yyGetParser->StartClass(yyvsp[0].str);
+  yyGetParser->StartClass((yyvsp[0].str));
   jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(3);
 }
+#line 3485 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 124:
-#line 1123 "cmDependsJavaParser.y"
+#line 1111 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
   yyGetParser->EndClass();
 }
+#line 3497 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 125:
-#line 1132 "cmDependsJavaParser.y"
+#line 1120 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 }
+#line 3507 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 126:
-#line 1139 "cmDependsJavaParser.y"
+#line 1127 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3519 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 127:
-#line 1149 "cmDependsJavaParser.y"
+#line 1137 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3531 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 128:
-#line 1158 "cmDependsJavaParser.y"
+#line 1146 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3543 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 129:
-#line 1168 "cmDependsJavaParser.y"
+#line 1156 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3555 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 130:
-#line 1177 "cmDependsJavaParser.y"
+#line 1165 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3566 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 131:
-#line 1185 "cmDependsJavaParser.y"
+#line 1173 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3577 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 132:
-#line 1194 "cmDependsJavaParser.y"
+#line 1182 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3589 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 133:
-#line 1203 "cmDependsJavaParser.y"
+#line 1191 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3601 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 134:
-#line 1212 "cmDependsJavaParser.y"
+#line 1200 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3613 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 135:
-#line 1221 "cmDependsJavaParser.y"
+#line 1209 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3624 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 136:
-#line 1229 "cmDependsJavaParser.y"
+#line 1217 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3636 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 137:
-#line 1238 "cmDependsJavaParser.y"
+#line 1226 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3647 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 138:
-#line 1247 "cmDependsJavaParser.y"
+#line 1235 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3659 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 139:
-#line 1257 "cmDependsJavaParser.y"
+#line 1245 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3671 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 140:
-#line 1267 "cmDependsJavaParser.y"
+#line 1255 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3683 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 141:
-#line 1276 "cmDependsJavaParser.y"
+#line 1264 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3695 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 142:
-#line 1286 "cmDependsJavaParser.y"
+#line 1274 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3707 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 143:
-#line 1295 "cmDependsJavaParser.y"
+#line 1283 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3718 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 144:
-#line 1303 "cmDependsJavaParser.y"
+#line 1291 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3730 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 145:
-#line 1312 "cmDependsJavaParser.y"
+#line 1300 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3742 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 146:
-#line 1322 "cmDependsJavaParser.y"
+#line 1310 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3754 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 147:
-#line 1331 "cmDependsJavaParser.y"
+#line 1319 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3766 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 148:
-#line 1341 "cmDependsJavaParser.y"
+#line 1329 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3777 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 149:
-#line 1349 "cmDependsJavaParser.y"
+#line 1337 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3788 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 150:
-#line 1357 "cmDependsJavaParser.y"
+#line 1345 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3800 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 151:
-#line 1367 "cmDependsJavaParser.y"
+#line 1355 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3812 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 152:
-#line 1376 "cmDependsJavaParser.y"
+#line 1364 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3824 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 153:
-#line 1386 "cmDependsJavaParser.y"
+#line 1374 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3836 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 154:
-#line 1395 "cmDependsJavaParser.y"
+#line 1383 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3848 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 155:
-#line 1404 "cmDependsJavaParser.y"
+#line 1392 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3860 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 156:
-#line 1414 "cmDependsJavaParser.y"
+#line 1402 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3872 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 157:
-#line 1424 "cmDependsJavaParser.y"
+#line 1412 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3884 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 158:
-#line 1433 "cmDependsJavaParser.y"
+#line 1421 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3896 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 159:
-#line 1443 "cmDependsJavaParser.y"
+#line 1431 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3908 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 160:
-#line 1452 "cmDependsJavaParser.y"
+#line 1440 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3920 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 161:
-#line 1461 "cmDependsJavaParser.y"
+#line 1449 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3932 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 162:
-#line 1470 "cmDependsJavaParser.y"
+#line 1458 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3944 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 163:
-#line 1479 "cmDependsJavaParser.y"
+#line 1467 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3956 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 164:
-#line 1488 "cmDependsJavaParser.y"
+#line 1476 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3968 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 165:
-#line 1498 "cmDependsJavaParser.y"
+#line 1486 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3980 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 166:
-#line 1507 "cmDependsJavaParser.y"
+#line 1495 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 3992 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 167:
-#line 1516 "cmDependsJavaParser.y"
+#line 1504 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4004 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 168:
-#line 1525 "cmDependsJavaParser.y"
+#line 1513 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4016 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 169:
-#line 1534 "cmDependsJavaParser.y"
+#line 1522 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4028 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 170:
-#line 1544 "cmDependsJavaParser.y"
+#line 1532 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4040 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 171:
-#line 1553 "cmDependsJavaParser.y"
+#line 1541 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4052 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 172:
-#line 1562 "cmDependsJavaParser.y"
+#line 1550 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4064 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 173:
-#line 1571 "cmDependsJavaParser.y"
+#line 1559 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4076 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 174:
-#line 1580 "cmDependsJavaParser.y"
+#line 1568 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4088 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 175:
-#line 1589 "cmDependsJavaParser.y"
+#line 1577 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4100 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 176:
-#line 1598 "cmDependsJavaParser.y"
+#line 1586 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4112 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 177:
-#line 1607 "cmDependsJavaParser.y"
+#line 1595 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4124 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 178:
-#line 1616 "cmDependsJavaParser.y"
+#line 1604 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4136 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 179:
-#line 1625 "cmDependsJavaParser.y"
+#line 1613 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4148 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 180:
-#line 1634 "cmDependsJavaParser.y"
+#line 1622 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4160 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 181:
-#line 1643 "cmDependsJavaParser.y"
+#line 1631 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4172 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 182:
-#line 1653 "cmDependsJavaParser.y"
+#line 1641 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4184 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 183:
-#line 1663 "cmDependsJavaParser.y"
+#line 1651 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[-2].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4197 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 184:
-#line 1674 "cmDependsJavaParser.y"
+#line 1662 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4209 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 185:
-#line 1684 "cmDependsJavaParser.y"
+#line 1672 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4221 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 186:
-#line 1694 "cmDependsJavaParser.y"
+#line 1682 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4233 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 187:
-#line 1703 "cmDependsJavaParser.y"
+#line 1691 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4245 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 188:
-#line 1712 "cmDependsJavaParser.y"
+#line 1700 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4257 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 189:
-#line 1721 "cmDependsJavaParser.y"
+#line 1709 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4269 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 190:
-#line 1730 "cmDependsJavaParser.y"
+#line 1718 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4281 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 191:
-#line 1739 "cmDependsJavaParser.y"
+#line 1727 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4293 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 192:
-#line 1748 "cmDependsJavaParser.y"
+#line 1736 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4305 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 193:
-#line 1758 "cmDependsJavaParser.y"
+#line 1746 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4317 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 194:
-#line 1768 "cmDependsJavaParser.y"
+#line 1756 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(7);
   jpCheckEmpty(7);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4329 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 195:
-#line 1778 "cmDependsJavaParser.y"
+#line 1766 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(7);
   jpCheckEmpty(7);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4341 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 196:
-#line 1788 "cmDependsJavaParser.y"
+#line 1776 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
 
 }
+#line 4350 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 197:
-#line 1795 "cmDependsJavaParser.y"
+#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
 
 }
+#line 4359 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 198:
-#line 1801 "cmDependsJavaParser.y"
+#line 1789 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4370 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 199:
-#line 1809 "cmDependsJavaParser.y"
+#line 1797 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4382 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 200:
-#line 1818 "cmDependsJavaParser.y"
+#line 1806 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4393 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 201:
-#line 1826 "cmDependsJavaParser.y"
+#line 1814 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4405 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 202:
-#line 1836 "cmDependsJavaParser.y"
+#line 1824 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4417 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 203:
-#line 1846 "cmDependsJavaParser.y"
+#line 1834 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4429 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 204:
-#line 1855 "cmDependsJavaParser.y"
+#line 1843 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4441 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 205:
-#line 1865 "cmDependsJavaParser.y"
+#line 1853 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4453 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 206:
-#line 1874 "cmDependsJavaParser.y"
+#line 1862 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4465 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 207:
-#line 1884 "cmDependsJavaParser.y"
+#line 1872 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
 
 }
+#line 4474 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 208:
-#line 1891 "cmDependsJavaParser.y"
+#line 1879 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
 
 }
+#line 4483 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 209:
-#line 1898 "cmDependsJavaParser.y"
+#line 1886 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(7);
 
 }
+#line 4492 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 210:
-#line 1906 "cmDependsJavaParser.y"
+#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(9);
 
 }
+#line 4501 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 211:
-#line 1912 "cmDependsJavaParser.y"
+#line 1900 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4512 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 212:
-#line 1920 "cmDependsJavaParser.y"
+#line 1908 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4524 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 213:
-#line 1929 "cmDependsJavaParser.y"
+#line 1917 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4535 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 214:
-#line 1937 "cmDependsJavaParser.y"
+#line 1925 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4547 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 215:
-#line 1948 "cmDependsJavaParser.y"
+#line 1936 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(9);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4558 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 216:
-#line 1956 "cmDependsJavaParser.y"
+#line 1944 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4569 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 217:
-#line 1964 "cmDependsJavaParser.y"
+#line 1952 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4581 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 218:
-#line 1974 "cmDependsJavaParser.y"
+#line 1962 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4593 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 219:
-#line 1983 "cmDependsJavaParser.y"
+#line 1971 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4605 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 220:
-#line 1993 "cmDependsJavaParser.y"
+#line 1981 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4617 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 221:
-#line 2003 "cmDependsJavaParser.y"
+#line 1991 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4629 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 222:
-#line 2012 "cmDependsJavaParser.y"
+#line 2000 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4641 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 223:
-#line 2022 "cmDependsJavaParser.y"
+#line 2010 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4653 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 224:
-#line 2031 "cmDependsJavaParser.y"
+#line 2019 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4665 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 225:
-#line 2041 "cmDependsJavaParser.y"
+#line 2029 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4678 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 226:
-#line 2051 "cmDependsJavaParser.y"
+#line 2039 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4689 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 227:
-#line 2059 "cmDependsJavaParser.y"
+#line 2047 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
 
 }
+#line 4698 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 228:
-#line 2066 "cmDependsJavaParser.y"
+#line 2054 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[-1].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4711 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 229:
-#line 2077 "cmDependsJavaParser.y"
+#line 2065 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4723 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 230:
-#line 2087 "cmDependsJavaParser.y"
+#line 2075 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4735 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 231:
-#line 2097 "cmDependsJavaParser.y"
+#line 2085 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4747 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 232:
-#line 2107 "cmDependsJavaParser.y"
+#line 2095 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4759 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 233:
-#line 2116 "cmDependsJavaParser.y"
+#line 2104 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4771 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 234:
-#line 2125 "cmDependsJavaParser.y"
+#line 2113 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4782 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 235:
-#line 2133 "cmDependsJavaParser.y"
+#line 2121 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4794 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 236:
-#line 2143 "cmDependsJavaParser.y"
+#line 2131 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4806 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 237:
-#line 2152 "cmDependsJavaParser.y"
+#line 2140 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4818 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 238:
-#line 2162 "cmDependsJavaParser.y"
+#line 2150 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
 
 }
+#line 4827 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 239:
-#line 2169 "cmDependsJavaParser.y"
+#line 2157 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4839 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 240:
-#line 2179 "cmDependsJavaParser.y"
+#line 2167 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4851 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 241:
-#line 2188 "cmDependsJavaParser.y"
+#line 2176 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4863 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 242:
-#line 2198 "cmDependsJavaParser.y"
+#line 2186 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4875 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 243:
-#line 2207 "cmDependsJavaParser.y"
+#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
 
 }
+#line 4884 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 244:
-#line 2213 "cmDependsJavaParser.y"
+#line 2201 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4896 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 245:
-#line 2222 "cmDependsJavaParser.y"
+#line 2210 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4908 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 246:
-#line 2231 "cmDependsJavaParser.y"
+#line 2219 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4920 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 247:
-#line 2240 "cmDependsJavaParser.y"
+#line 2228 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4932 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 248:
-#line 2249 "cmDependsJavaParser.y"
+#line 2237 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4944 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 249:
-#line 2259 "cmDependsJavaParser.y"
+#line 2247 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(6);
   jpCheckEmpty(6);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4956 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 250:
-#line 2268 "cmDependsJavaParser.y"
+#line 2256 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4967 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 251:
-#line 2276 "cmDependsJavaParser.y"
+#line 2264 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4979 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 252:
-#line 2285 "cmDependsJavaParser.y"
+#line 2273 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 4990 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 253:
-#line 2293 "cmDependsJavaParser.y"
+#line 2281 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5002 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 254:
-#line 2303 "cmDependsJavaParser.y"
+#line 2291 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5014 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 255:
-#line 2312 "cmDependsJavaParser.y"
+#line 2300 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5026 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 256:
-#line 2322 "cmDependsJavaParser.y"
+#line 2310 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5038 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 257:
-#line 2331 "cmDependsJavaParser.y"
+#line 2319 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5050 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 258:
-#line 2340 "cmDependsJavaParser.y"
+#line 2328 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5062 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 259:
-#line 2349 "cmDependsJavaParser.y"
+#line 2337 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5074 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 260:
-#line 2358 "cmDependsJavaParser.y"
+#line 2346 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(0);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5085 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 261:
-#line 2366 "cmDependsJavaParser.y"
+#line 2354 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5097 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 262:
-#line 2376 "cmDependsJavaParser.y"
+#line 2364 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5109 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 263:
-#line 2385 "cmDependsJavaParser.y"
+#line 2373 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5121 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 264:
-#line 2395 "cmDependsJavaParser.y"
+#line 2383 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5133 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 265:
-#line 2405 "cmDependsJavaParser.y"
+#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
 
 }
+#line 5142 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 266:
-#line 2411 "cmDependsJavaParser.y"
+#line 2399 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
 
 }
+#line 5151 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 267:
-#line 2418 "cmDependsJavaParser.y"
+#line 2406 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5164 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 268:
-#line 2428 "cmDependsJavaParser.y"
+#line 2416 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5177 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 269:
-#line 2438 "cmDependsJavaParser.y"
+#line 2426 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5190 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 270:
-#line 2448 "cmDependsJavaParser.y"
+#line 2436 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5203 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 271:
-#line 2459 "cmDependsJavaParser.y"
+#line 2447 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5216 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 272:
-#line 2469 "cmDependsJavaParser.y"
+#line 2457 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(6);
-  yyGetParser->DeallocateParserType(&(yyvsp[-5].str));
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-5].str)));
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
   jpCheckEmpty(6);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5230 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 273:
-#line 2480 "cmDependsJavaParser.y"
+#line 2468 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(6);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
   jpCheckEmpty(6);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5243 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 274:
-#line 2490 "cmDependsJavaParser.y"
+#line 2478 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(6);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
   jpCheckEmpty(6);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5256 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 275:
-#line 2501 "cmDependsJavaParser.y"
+#line 2489 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
-  yyGetParser->DeallocateParserType(&(yyvsp[-3].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5269 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 276:
-#line 2511 "cmDependsJavaParser.y"
+#line 2499 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5281 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 277:
-#line 2521 "cmDependsJavaParser.y"
+#line 2509 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5293 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 278:
-#line 2530 "cmDependsJavaParser.y"
+#line 2518 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
-  yyval.str = 0;
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5305 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 279:
-#line 2539 "cmDependsJavaParser.y"
+#line 2527 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5317 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 280:
-#line 2548 "cmDependsJavaParser.y"
+#line 2536 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5329 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 281:
-#line 2557 "cmDependsJavaParser.y"
+#line 2545 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5341 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 282:
-#line 2567 "cmDependsJavaParser.y"
+#line 2555 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5353 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 283:
-#line 2577 "cmDependsJavaParser.y"
+#line 2565 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5365 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 284:
-#line 2587 "cmDependsJavaParser.y"
+#line 2575 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5377 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 285:
-#line 2596 "cmDependsJavaParser.y"
+#line 2584 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5389 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 286:
-#line 2605 "cmDependsJavaParser.y"
+#line 2593 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5401 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 287:
-#line 2614 "cmDependsJavaParser.y"
+#line 2602 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5413 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 288:
-#line 2623 "cmDependsJavaParser.y"
+#line 2611 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5425 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 289:
-#line 2633 "cmDependsJavaParser.y"
+#line 2621 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5437 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 290:
-#line 2643 "cmDependsJavaParser.y"
+#line 2631 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5449 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 291:
-#line 2653 "cmDependsJavaParser.y"
+#line 2641 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5461 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 292:
-#line 2662 "cmDependsJavaParser.y"
+#line 2650 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5473 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 293:
-#line 2671 "cmDependsJavaParser.y"
+#line 2659 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(2);
   jpCheckEmpty(2);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5485 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 294:
-#line 2680 "cmDependsJavaParser.y"
+#line 2668 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5497 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 295:
-#line 2690 "cmDependsJavaParser.y"
+#line 2678 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5509 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 296:
-#line 2699 "cmDependsJavaParser.y"
+#line 2687 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(4);
   jpCheckEmpty(4);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5521 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 297:
-#line 2708 "cmDependsJavaParser.y"
+#line 2696 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
 
 }
+#line 5530 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 298:
-#line 2715 "cmDependsJavaParser.y"
+#line 2703 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5542 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 299:
-#line 2724 "cmDependsJavaParser.y"
+#line 2712 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5554 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 300:
-#line 2733 "cmDependsJavaParser.y"
+#line 2721 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5566 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 301:
-#line 2742 "cmDependsJavaParser.y"
+#line 2730 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5578 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 302:
-#line 2752 "cmDependsJavaParser.y"
+#line 2740 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5590 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 303:
-#line 2761 "cmDependsJavaParser.y"
+#line 2749 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5602 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 304:
-#line 2770 "cmDependsJavaParser.y"
+#line 2758 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5614 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 305:
-#line 2780 "cmDependsJavaParser.y"
+#line 2768 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5626 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 306:
-#line 2789 "cmDependsJavaParser.y"
+#line 2777 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5638 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 307:
-#line 2798 "cmDependsJavaParser.y"
+#line 2786 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5650 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 308:
-#line 2807 "cmDependsJavaParser.y"
+#line 2795 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5662 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 309:
-#line 2817 "cmDependsJavaParser.y"
+#line 2805 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5674 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 310:
-#line 2826 "cmDependsJavaParser.y"
+#line 2814 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5686 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 311:
-#line 2835 "cmDependsJavaParser.y"
+#line 2823 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5698 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 312:
-#line 2844 "cmDependsJavaParser.y"
+#line 2832 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5710 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 313:
-#line 2853 "cmDependsJavaParser.y"
+#line 2841 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5722 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 314:
-#line 2862 "cmDependsJavaParser.y"
+#line 2850 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5734 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 315:
-#line 2872 "cmDependsJavaParser.y"
+#line 2860 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5746 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 316:
-#line 2881 "cmDependsJavaParser.y"
+#line 2869 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5758 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 317:
-#line 2890 "cmDependsJavaParser.y"
+#line 2878 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5770 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 318:
-#line 2900 "cmDependsJavaParser.y"
+#line 2888 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5782 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 319:
-#line 2909 "cmDependsJavaParser.y"
+#line 2897 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5794 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 320:
-#line 2919 "cmDependsJavaParser.y"
+#line 2907 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5806 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 321:
-#line 2928 "cmDependsJavaParser.y"
+#line 2916 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5818 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 322:
-#line 2938 "cmDependsJavaParser.y"
+#line 2926 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5830 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 323:
-#line 2947 "cmDependsJavaParser.y"
+#line 2935 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5842 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 324:
-#line 2957 "cmDependsJavaParser.y"
+#line 2945 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5854 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 325:
-#line 2966 "cmDependsJavaParser.y"
+#line 2954 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5866 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 326:
-#line 2976 "cmDependsJavaParser.y"
+#line 2964 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5878 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 327:
-#line 2985 "cmDependsJavaParser.y"
+#line 2973 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5890 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 328:
-#line 2995 "cmDependsJavaParser.y"
+#line 2983 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5902 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 329:
-#line 3004 "cmDependsJavaParser.y"
+#line 2992 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(5);
   jpCheckEmpty(5);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5914 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 330:
-#line 3014 "cmDependsJavaParser.y"
+#line 3002 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5926 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 331:
-#line 3023 "cmDependsJavaParser.y"
+#line 3011 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5938 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 332:
-#line 3033 "cmDependsJavaParser.y"
+#line 3021 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5950 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 333:
-#line 3043 "cmDependsJavaParser.y"
+#line 3031 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
-  yyGetParser->DeallocateParserType(&(yyvsp[0].str));
+  yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5963 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 334:
-#line 3053 "cmDependsJavaParser.y"
+#line 3041 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5975 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 335:
-#line 3062 "cmDependsJavaParser.y"
+#line 3050 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5987 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 336:
-#line 3072 "cmDependsJavaParser.y"
+#line 3060 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 5999 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 337:
-#line 3081 "cmDependsJavaParser.y"
+#line 3069 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6011 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 338:
-#line 3090 "cmDependsJavaParser.y"
+#line 3078 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6023 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 339:
-#line 3099 "cmDependsJavaParser.y"
+#line 3087 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6035 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 340:
-#line 3108 "cmDependsJavaParser.y"
+#line 3096 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6047 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 341:
-#line 3117 "cmDependsJavaParser.y"
+#line 3105 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6059 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 342:
-#line 3126 "cmDependsJavaParser.y"
+#line 3114 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6071 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 343:
-#line 3135 "cmDependsJavaParser.y"
+#line 3123 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6083 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 344:
-#line 3144 "cmDependsJavaParser.y"
+#line 3132 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6095 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 345:
-#line 3153 "cmDependsJavaParser.y"
+#line 3141 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6107 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 346:
-#line 3162 "cmDependsJavaParser.y"
+#line 3150 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6119 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 347:
-#line 3171 "cmDependsJavaParser.y"
+#line 3159 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6131 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 348:
-#line 3181 "cmDependsJavaParser.y"
+#line 3169 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6143 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 349:
-#line 3191 "cmDependsJavaParser.y"
+#line 3179 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6155 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 350:
-#line 3201 "cmDependsJavaParser.y"
+#line 3189 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(1);
   jpCheckEmpty(1);
-  yyval.str = 0;
+  (yyval.str) = 0;
   yyGetParser->SetCurrentCombine("");
 
 }
+#line 6167 "cmDependsJavaParser.cxx" /* yacc.c:1646  */
     break;
 
   case 351:
-#line 3210 "cmDependsJavaParser.y"
+#line 3198 "cmDependsJavaParser.y" /* yacc.c:1646  */
     {
   jpElementStart(3);
-  jpStoreClass(yyvsp[-2].str);
+  jpStoreClass((yyvsp[-2].str));
   jpCheckEmpty(3);
-  yyval.str = 0;
+  (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);
 
-/* Line 1010 of yacc.c.  */
-#line 5780 "cmDependsJavaParser.cxx"
-
-  yyvsp -= yylen;
-  yyssp -= yylen;
-
-
+  YYPOPSTACK (yylen);
+  yylen = 0;
   YY_STACK_PRINT (yyss, yyssp);
 
   *++yyvsp = yyval;
 
-
-  /* Now `shift' the result of the reduction.  Determine what state
+  /* 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.  */
 
@@ -5794,74 +6217,52 @@
   goto yynewstate;
 
 
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| 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
-      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)
+#if ! YYERROR_VERBOSE
+      yyerror (yyscanner, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
       {
-        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)
+        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)
           {
-      yyp = yystpcpy (yyp, yyprefix);
-      yyp = yystpcpy (yyp, yytname[yyx]);
-      yyprefix = " or ";
+            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 (yymsg);
-        YYSTACK_FREE (yymsg);
+        yyerror (yyscanner, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
       }
-    else
-      yyerror ("syntax error; also virtual memory exhausted");
-  }
-      else
-#endif /* YYERROR_VERBOSE */
-  yyerror ("syntax error");
+# undef YYSYNTAX_ERROR
+#endif
     }
 
 
@@ -5869,31 +6270,23 @@
   if (yyerrstatus == 3)
     {
       /* If just tried and failed to reuse lookahead token after an
-   error, discard it.  */
+         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);
-         }
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
         }
       else
-  {
-    YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
-    yydestruct (yytoken, &yylval);
-    yychar = YYEMPTY;
-
-  }
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, yyscanner);
+          yychar = YYEMPTY;
+        }
     }
 
+#if 0
   /* Else will try to reuse lookahead token after shifting the error
      token.  */
   goto yyerrlab1;
@@ -5904,15 +6297,17 @@
 `---------------------------------------------------*/
 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)
+  /* 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;
-#endif
 
-  yyvsp -= yylen;
-  yyssp -= yylen;
+  /* 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;
 
@@ -5921,41 +6316,43 @@
 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
 `-------------------------------------------------------------*/
 yyerrlab1:
-  yyerrstatus = 3;  /* Each real token shifted decrements this.  */
+#endif
+  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;
-      }
-  }
+      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;
+        YYABORT;
 
-      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-      yydestruct (yystos[yystate], yyvsp);
-      YYPOPSTACK;
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, yyscanner);
+      YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  YYDPRINTF ((stderr, "Shifting error token, "));
-
+  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;
 
@@ -5974,33 +6371,51 @@
   yyresult = 1;
   goto yyreturn;
 
-#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here.  |
-`----------------------------------------------*/
-yyoverflowlab:
-  yyerror ("parser stack overflow");
+#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 3219 "cmDependsJavaParser.y"
+#line 3207 "cmDependsJavaParser.y" /* yacc.c:1906  */
 
 /* End of grammar */
 
 /*--------------------------------------------------------------------------*/
-void cmDependsJavaError(yyscan_t yyscanner, const char* message)
+void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message)
 {
   yyGetParser->Error(message);
 }
-
-
diff --git a/Source/cmDependsJavaParser.y b/Source/cmDependsJavaParser.y
index 91ee7c8..150ac92 100644
--- a/Source/cmDependsJavaParser.y
+++ b/Source/cmDependsJavaParser.y
@@ -10,18 +10,16 @@
   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
+  - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
 
 */
 
-/* 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)
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
 #define yyGetParser (cmDependsJava_yyget_extra(yyscanner))
 
 /*-------------------------------------------------------------------------*/
@@ -32,10 +30,9 @@
 /* Forward declare the lexer entry point.  */
 YY_DECL;
 
-/* Internal utility functions.  */
-static void cmDependsJavaError(yyscan_t yyscanner, const char* message);
+/* Helper function to forward error callback from parser.  */
+static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
 
-#define YYDEBUG 1
 #define YYMAXDEPTH 1000000
 
 
@@ -50,7 +47,13 @@
 %}
 
 /* Generate a reentrant parser object.  */
-%pure_parser
+%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 {
@@ -3205,7 +3208,7 @@
 /* End of grammar */
 
 /*--------------------------------------------------------------------------*/
-void cmDependsJavaError(yyscan_t yyscanner, const char* message)
+void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message)
 {
   yyGetParser->Error(message);
 }
diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h
index 71b939c..5f28f70 100644
--- a/Source/cmDependsJavaParserHelper.h
+++ b/Source/cmDependsJavaParserHelper.h
@@ -8,26 +8,18 @@
 #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 @@
   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
index c7a414f..7f18f1d 100644
--- a/Source/cmDependsJavaParserTokens.h
+++ b/Source/cmDependsJavaParserTokens.h
@@ -1,12 +1,13 @@
-/* A Bison parser, made by GNU Bison 1.875d.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
-/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984,
-   1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Bison interface for Yacc-like parsers in C
 
-   This program is free software; you can redistribute it and/or modify
+   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 2, or (at your option)
-   any later version.
+   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
@@ -14,126 +15,142 @@
    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.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-/* 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.  */
+/* 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.
 
-/* Tokens.  */
+   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
-   /* 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
-   };
+  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
@@ -238,17 +255,10 @@
 #define jp_TIMESEQUALS 359
 #define jp_ERROR 360
 
+/* Value type.  */
 
 
 
-#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
+int cmDependsJava_yyparse (yyscan_t yyscanner);
 
-
-
-
-
+#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED  */
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..00b0183
--- /dev/null
+++ b/Source/cmDisallowedCommand.h
@@ -0,0 +1,57 @@
+/* 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();
+  }
+
+  bool IsScriptable() const CM_OVERRIDE
+  {
+    return this->Command->IsScriptable();
+  }
+
+  std::string GetName() const CM_OVERRIDE { return this->Command->GetName(); }
+
+private:
+  cmCommand* Command;
+  cmPolicies::PolicyID Policy;
+  const char* Message;
+};
+
+#endif
diff --git a/Source/cmDynamicLoader.cxx b/Source/cmDynamicLoader.cxx
index a30b642..39a59fc 100644
--- a/Source/cmDynamicLoader.cxx
+++ b/Source/cmDynamicLoader.cxx
@@ -4,7 +4,6 @@
 
 #include <cmConfigure.h>
 
-#include <cmsys/DynamicLoader.hxx>
 #include <map>
 #include <string>
 #include <utility>
diff --git a/Source/cmDynamicLoader.h b/Source/cmDynamicLoader.h
index d14f81e..5d69400 100644
--- a/Source/cmDynamicLoader.h
+++ b/Source/cmDynamicLoader.h
@@ -10,7 +10,7 @@
 
 #include <cmConfigure.h> // IWYU pragma: keep
 
-#include <cmsys/DynamicLoader.hxx>
+#include "cmsys/DynamicLoader.hxx" // IWYU pragma: export
 
 class cmDynamicLoader
 {
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 8102276..09c01e9 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -279,7 +279,6 @@
 #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..a0224d0 100644
--- a/Source/cmExportCommand.h
+++ b/Source/cmExportCommand.h
@@ -41,6 +41,7 @@
   std::string GetName() const CM_OVERRIDE { return "export"; }
 
 private:
+  cmCommandArgumentsHelper Helper;
   cmCommandArgumentGroup ArgumentGroup;
   cmCAStringVector Targets;
   cmCAEnabler Append;
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 64ea3c8..3b76a87 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -195,8 +195,10 @@
        << " \"${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 <<
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index ac4f040..deecad8 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -9,7 +9,6 @@
 #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 @@
 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/cmExprParser.cxx b/Source/cmExprParser.cxx
index d11d0b6..a9088a6 100644
--- a/Source/cmExprParser.cxx
+++ b/Source/cmExprParser.cxx
@@ -85,14 +85,17 @@
 
 */
 
+#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.  */
 
-#include <math.h>
-
 /* Forward declare the lexer entry point.  */
 YY_DECL;
 
@@ -105,7 +108,7 @@
 # pragma warning (disable: 4065) /* Switch statement contains default but no case. */
 #endif
 
-#line 109 "cmExprParser.cxx" /* yacc.c:339  */
+#line 112 "cmExprParser.cxx" /* yacc.c:339  */
 
 # ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
@@ -182,7 +185,7 @@
 
 /* Copy the second part of user declarations.  */
 
-#line 186 "cmExprParser.cxx" /* yacc.c:358  */
+#line 189 "cmExprParser.cxx" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -481,9 +484,9 @@
   /* 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
+       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
 
@@ -1278,183 +1281,183 @@
   switch (yyn)
     {
         case 2:
-#line 70 "cmExprParser.y" /* yacc.c:1646  */
+#line 73 "cmExprParser.y" /* yacc.c:1646  */
     {
     cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
   }
-#line 1286 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1289 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 3:
-#line 75 "cmExprParser.y" /* yacc.c:1646  */
+#line 78 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1294 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1297 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 4:
-#line 78 "cmExprParser.y" /* yacc.c:1646  */
+#line 81 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
   }
-#line 1302 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1305 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 5:
-#line 83 "cmExprParser.y" /* yacc.c:1646  */
+#line 86 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1310 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1313 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 86 "cmExprParser.y" /* yacc.c:1646  */
+#line 89 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
   }
-#line 1318 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1321 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 91 "cmExprParser.y" /* yacc.c:1646  */
+#line 94 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1326 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1329 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 94 "cmExprParser.y" /* yacc.c:1646  */
+#line 97 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
   }
-#line 1334 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1337 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 99 "cmExprParser.y" /* yacc.c:1646  */
+#line 102 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1342 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1345 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 102 "cmExprParser.y" /* yacc.c:1646  */
+#line 105 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
   }
-#line 1350 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1353 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 105 "cmExprParser.y" /* yacc.c:1646  */
+#line 108 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
   }
-#line 1358 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1361 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 110 "cmExprParser.y" /* yacc.c:1646  */
+#line 113 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1366 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1369 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 113 "cmExprParser.y" /* yacc.c:1646  */
+#line 116 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
   }
-#line 1374 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1377 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 116 "cmExprParser.y" /* yacc.c:1646  */
+#line 119 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
   }
-#line 1382 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1385 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 121 "cmExprParser.y" /* yacc.c:1646  */
+#line 124 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1390 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1393 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 124 "cmExprParser.y" /* yacc.c:1646  */
+#line 127 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
   }
-#line 1398 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1401 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 127 "cmExprParser.y" /* yacc.c:1646  */
+#line 130 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
   }
-#line 1406 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1409 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 130 "cmExprParser.y" /* yacc.c:1646  */
+#line 133 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
   }
-#line 1414 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1417 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 135 "cmExprParser.y" /* yacc.c:1646  */
+#line 138 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1422 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1425 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 138 "cmExprParser.y" /* yacc.c:1646  */
+#line 141 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = + (yyvsp[0].Number);
   }
-#line 1430 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1433 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 141 "cmExprParser.y" /* yacc.c:1646  */
+#line 144 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = - (yyvsp[0].Number);
   }
-#line 1438 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1441 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 146 "cmExprParser.y" /* yacc.c:1646  */
+#line 149 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1446 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1449 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 149 "cmExprParser.y" /* yacc.c:1646  */
+#line 152 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-1].Number);
   }
-#line 1454 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1457 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
 
-#line 1458 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1461 "cmExprParser.cxx" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1684,7 +1687,7 @@
 #endif
   return yyresult;
 }
-#line 154 "cmExprParser.y" /* yacc.c:1906  */
+#line 157 "cmExprParser.y" /* yacc.c:1906  */
 
 /* End of grammar */
 
diff --git a/Source/cmExprParser.y b/Source/cmExprParser.y
index c7c4a7b..0429663 100644
--- a/Source/cmExprParser.y
+++ b/Source/cmExprParser.y
@@ -14,14 +14,17 @@
 
 */
 
+#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.  */
 
-#include <math.h>
-
 /* Forward declare the lexer entry point.  */
 YY_DECL;
 
diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h
index 8f00f1d..df365fc 100644
--- a/Source/cmExprParserHelper.h
+++ b/Source/cmExprParserHelper.h
@@ -8,23 +8,13 @@
 #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 @@
   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/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 91cecb3..63012a5 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -16,10 +16,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <sys/types.h>
-// include sys/stat.h after sys/types.h
-#include <sys/stat.h>
-
 #include "cmAlgorithms.h"
 #include "cmCommandArgumentsHelper.h"
 #include "cmCryptoHash.h"
@@ -35,11 +31,17 @@
 #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
 
 class cmSystemToolsFileTime;
@@ -166,6 +168,9 @@
   if (subCommand == "RPATH_REMOVE") {
     return this->HandleRPathRemoveCommand(args);
   }
+  if (subCommand == "READ_ELF") {
+    return this->HandleReadElfCommand(args);
+  }
   if (subCommand == "RELATIVE_PATH") {
     return this->HandleRelativePathCommand(args);
   }
@@ -1024,8 +1029,6 @@
     {
     }
   };
-  struct MatchRule;
-  friend struct MatchRule;
   struct MatchRule
   {
     cmsys::RegularExpression Regex;
@@ -1482,6 +1485,9 @@
     // 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;
@@ -2177,6 +2183,68 @@
   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);
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 319864c..2d82a23 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -53,6 +53,7 @@
   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/cmFileMonitor.h b/Source/cmFileMonitor.h
index 48169b8..2957328 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> // IWYU pragma: keep
+
 #include <functional>
 #include <string>
 #include <vector>
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 @@
   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::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..59ca34c 100644
--- a/Source/cmFilePathChecksum.h
+++ b/Source/cmFilePathChecksum.h
@@ -47,13 +47,13 @@
   /* @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..ef4337b 100644
--- a/Source/cmFileTimeComparison.cxx
+++ b/Source/cmFileTimeComparison.cxx
@@ -10,7 +10,7 @@
 
 // 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>
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index c86f9c1..e92d672 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -43,20 +43,29 @@
     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();
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 60de74f..fe4cc54 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -92,6 +92,7 @@
   this->DebugMode = false;
   this->UseLib32Paths = false;
   this->UseLib64Paths = false;
+  this->UseLibx32Paths = false;
   this->PolicyScope = true;
   this->VersionMajor = 0;
   this->VersionMinor = 0;
@@ -173,6 +174,13 @@
     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;
@@ -1165,7 +1173,6 @@
 
 #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
@@ -2002,6 +2009,9 @@
   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..61a8dd6 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -169,6 +169,7 @@
   bool DebugMode;
   bool UseLib32Paths;
   bool UseLib64Paths;
+  bool UseLibx32Paths;
   bool PolicyScope;
   std::string LibraryArchitecture;
   std::vector<std::string> Names;
diff --git a/Source/cmFortranParser.cxx b/Source/cmFortranParser.cxx
index 896e589..c67227f 100644
--- a/Source/cmFortranParser.cxx
+++ b/Source/cmFortranParser.cxx
@@ -97,13 +97,17 @@
   - "#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.  */
 
-#include <cmsys/String.h>
-
 /* Forward declare the lexer entry point.  */
 YY_DECL;
 
@@ -124,7 +128,7 @@
 # pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
 #endif
 
-#line 137 "cmFortranParser.cxx" /* yacc.c:339  */
+#line 132 "cmFortranParser.cxx" /* yacc.c:339  */
 
 # ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
@@ -244,11 +248,11 @@
 
 union YYSTYPE
 {
-#line 75 "cmFortranParser.y" /* yacc.c:355  */
+#line 70 "cmFortranParser.y" /* yacc.c:355  */
 
   char* string;
 
-#line 261 "cmFortranParser.cxx" /* yacc.c:355  */
+#line 256 "cmFortranParser.cxx" /* yacc.c:355  */
 };
 
 typedef union YYSTYPE YYSTYPE;
@@ -264,7 +268,7 @@
 
 /* Copy the second part of user declarations.  */
 
-#line 277 "cmFortranParser.cxx" /* yacc.c:358  */
+#line 272 "cmFortranParser.cxx" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -565,13 +569,13 @@
   /* 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
+       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
 
@@ -1523,26 +1527,26 @@
   switch (yyn)
     {
         case 4:
-#line 106 "cmFortranParser.y" /* yacc.c:1646  */
+#line 101 "cmFortranParser.y" /* yacc.c:1646  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_SetInInterface(parser, true);
   }
-#line 1541 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1536 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 5:
-#line 110 "cmFortranParser.y" /* yacc.c:1646  */
+#line 105 "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  */
+#line 1546 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 115 "cmFortranParser.y" /* yacc.c:1646  */
+#line 110 "cmFortranParser.y" /* yacc.c:1646  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
@@ -1552,22 +1556,22 @@
     }
     free((yyvsp[-2].string));
   }
-#line 1565 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1560 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 124 "cmFortranParser.y" /* yacc.c:1646  */
+#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 1576 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1571 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 130 "cmFortranParser.y" /* yacc.c:1646  */
+#line 125 "cmFortranParser.y" /* yacc.c:1646  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleUse(parser, (yyvsp[-6].string));
@@ -1575,40 +1579,40 @@
     free((yyvsp[-4].string));
     free((yyvsp[-2].string));
   }
-#line 1588 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1583 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 137 "cmFortranParser.y" /* yacc.c:1646  */
+#line 132 "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  */
+#line 1593 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 142 "cmFortranParser.y" /* yacc.c:1646  */
+#line 137 "cmFortranParser.y" /* yacc.c:1646  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_SetInInterface(parser, false);
   }
-#line 1607 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1602 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 146 "cmFortranParser.y" /* yacc.c:1646  */
+#line 141 "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  */
+#line 1612 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 151 "cmFortranParser.y" /* yacc.c:1646  */
+#line 146 "cmFortranParser.y" /* yacc.c:1646  */
     {
     if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
       cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
@@ -1617,139 +1621,139 @@
     free((yyvsp[-4].string));
     free((yyvsp[-2].string));
   }
-#line 1630 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1625 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 159 "cmFortranParser.y" /* yacc.c:1646  */
+#line 154 "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  */
+#line 1635 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 164 "cmFortranParser.y" /* yacc.c:1646  */
+#line 159 "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  */
+#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 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  */
+#line 1665 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 179 "cmFortranParser.y" /* yacc.c:1646  */
+#line 174 "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  */
+#line 1675 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 184 "cmFortranParser.y" /* yacc.c:1646  */
+#line 179 "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  */
+#line 1685 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 189 "cmFortranParser.y" /* yacc.c:1646  */
+#line 184 "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  */
+#line 1695 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 194 "cmFortranParser.y" /* yacc.c:1646  */
+#line 189 "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  */
+#line 1705 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 199 "cmFortranParser.y" /* yacc.c:1646  */
+#line 194 "cmFortranParser.y" /* yacc.c:1646  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleIf(parser);
   }
-#line 1719 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1714 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 203 "cmFortranParser.y" /* yacc.c:1646  */
+#line 198 "cmFortranParser.y" /* yacc.c:1646  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleElif(parser);
   }
-#line 1728 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1723 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 207 "cmFortranParser.y" /* yacc.c:1646  */
+#line 202 "cmFortranParser.y" /* yacc.c:1646  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleElse(parser);
   }
-#line 1737 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1732 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 211 "cmFortranParser.y" /* yacc.c:1646  */
+#line 206 "cmFortranParser.y" /* yacc.c:1646  */
     {
     cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
     cmFortranParser_RuleEndif(parser);
   }
-#line 1746 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1741 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 233 "cmFortranParser.y" /* yacc.c:1646  */
+#line 228 "cmFortranParser.y" /* yacc.c:1646  */
     { free ((yyvsp[0].string)); }
-#line 1752 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1747 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
   case 55:
-#line 240 "cmFortranParser.y" /* yacc.c:1646  */
+#line 235 "cmFortranParser.y" /* yacc.c:1646  */
     { free ((yyvsp[0].string)); }
-#line 1758 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1753 "cmFortranParser.cxx" /* yacc.c:1646  */
     break;
 
 
-#line 1762 "cmFortranParser.cxx" /* yacc.c:1646  */
+#line 1757 "cmFortranParser.cxx" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1979,6 +1983,6 @@
 #endif
   return yyresult;
 }
-#line 251 "cmFortranParser.y" /* yacc.c:1906  */
+#line 246 "cmFortranParser.y" /* yacc.c:1906  */
 
 /* End of grammar */
diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h
index 06985d2..024b00a 100644
--- a/Source/cmFortranParser.h
+++ b/Source/cmFortranParser.h
@@ -6,7 +6,9 @@
 #if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx)
 #include <cmConfigure.h>
 
-#include "cmStandardIncludes.h"
+#include <set>
+#include <string>
+#include <vector>
 #endif
 
 #include <stddef.h> /* size_t */
@@ -52,8 +54,7 @@
 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
index 7eb5ef5..3d68134 100644
--- a/Source/cmFortranParser.y
+++ b/Source/cmFortranParser.y
@@ -26,13 +26,17 @@
   - "#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.  */
 
-#include <cmsys/String.h>
-
 /* Forward declare the lexer entry point.  */
 YY_DECL;
 
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx
index 1a5e6c5..1abe673 100644
--- a/Source/cmFortranParserImpl.cxx
+++ b/Source/cmFortranParserImpl.cxx
@@ -1,7 +1,6 @@
 /* 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 <assert.h>
diff --git a/Source/cmFortranParserTokens.h b/Source/cmFortranParserTokens.h
index 18b9e0a..8d6a5fe 100644
--- a/Source/cmFortranParserTokens.h
+++ b/Source/cmFortranParserTokens.h
@@ -130,7 +130,7 @@
 
 union YYSTYPE
 {
-#line 75 "cmFortranParser.y" /* yacc.c:1909  */
+#line 70 "cmFortranParser.y" /* yacc.c:1909  */
 
   char* string;
 
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
index 26135df..1223ffd 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.h
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -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/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 3fe5c83..f78a933 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -112,7 +112,7 @@
 struct ResxTag
 {
 };
-struct ModuleDefinitionFileTag
+struct ModuleDefinitionSourcesTag
 {
 };
 struct AppManifestTag
@@ -236,8 +236,8 @@
     } 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);
+      DoAccept<IsSameTag<Tag, ModuleDefinitionSourcesTag>::Result>::Do(
+        this->Data, sf);
       if (this->IsObjLib) {
         this->BadObjLibFiles.push_back(sf);
       }
@@ -681,6 +681,12 @@
   return it != this->ExplicitObjectName.end();
 }
 
+void cmGeneratorTarget::GetModuleDefinitionSources(
+  std::vector<cmSourceFile const*>& data, const std::string& config) const
+{
+  IMPLEMENT_VISIT(ModuleDefinitionSources);
+}
+
 void cmGeneratorTarget::GetIDLSources(std::vector<cmSourceFile const*>& data,
                                       const std::string& config) const
 {
@@ -711,12 +717,18 @@
   IMPLEMENT_VISIT(ExternalObjects);
 }
 
-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;
+  HeadersCacheType::const_iterator it = this->ResxHeadersCache.find(config);
+  if (it == this->ResxHeadersCache.end()) {
+    ResxData data;
+    IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
+    it = this->ResxHeadersCache
+           .insert(std::make_pair(config, data.ExpectedResxHeaders))
+           .first;
+  }
+  headers = it->second;
 }
 
 void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& srcs,
@@ -748,9 +760,15 @@
 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;
+  HeadersCacheType::const_iterator it = this->XamlHeadersCache.find(config);
+  if (it == this->XamlHeadersCache.end()) {
+    XamlData data;
+    IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
+    it = this->XamlHeadersCache
+           .insert(std::make_pair(config, data.ExpectedXamlHeaders))
+           .first;
+  }
+  headers = it->second;
 }
 
 void cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
@@ -1321,8 +1339,7 @@
       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 +1412,53 @@
   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()) {
@@ -1503,24 +1567,25 @@
 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();
     }
-    dir += "/";
-    return dir;
+
+    // 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;
+    }
   }
   return "";
 }
@@ -1531,8 +1596,7 @@
     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 += "/";
@@ -1880,17 +1944,46 @@
   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;
+}
+
+void cmGeneratorTarget::ComputeModuleDefinitionInfo(
+  std::string const& config, ModuleDefinitionInfo& info) const
+{
+  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();
+  }
 }
 
 bool cmGeneratorTarget::IsDLLPlatform() const
@@ -3222,8 +3315,18 @@
     // 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 +3380,7 @@
       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;
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index f568699..d60ad24 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -77,6 +77,8 @@
   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*>&,
@@ -233,7 +235,15 @@
   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;
@@ -412,7 +422,9 @@
     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
   {
@@ -525,6 +537,16 @@
   /** 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;
@@ -711,6 +733,12 @@
   typedef std::map<std::string, OutputInfo> OutputInfoMapType;
   mutable OutputInfoMapType OutputInfoMap;
 
+  typedef std::map<std::string, ModuleDefinitionInfo>
+    ModuleDefinitionInfoMapType;
+  mutable ModuleDefinitionInfoMapType ModuleDefinitionInfoMap;
+  void ComputeModuleDefinitionInfo(std::string const& config,
+                                   ModuleDefinitionInfo& info) const;
+
   typedef std::pair<std::string, bool> OutputNameKey;
   typedef std::map<OutputNameKey, std::string> OutputNameMapType;
   mutable OutputNameMapType OutputNameMap;
@@ -729,6 +757,10 @@
   bool ComputePDBOutputDir(const std::string& kind, const std::string& config,
                            std::string& out) const;
 
+  typedef std::map<std::string, std::set<std::string> > HeadersCacheType;
+  mutable HeadersCacheType ResxHeadersCache;
+  mutable HeadersCacheType XamlHeadersCache;
+
 public:
   const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
     const std::string& config) const;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index f118250..851290a 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1,12 +1,5 @@
 /* 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 <algorithm>
@@ -19,6 +12,10 @@
 #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,6 +39,7 @@
 #include "cmStateDirectory.h"
 #include "cmStateTypes.h"
 #include "cmVersion.h"
+#include "cmWorkingDirectory.h"
 #include "cmake.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -50,6 +48,10 @@
 #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 =
   "CMAKE_PLATFORM_INFO_INITIALIZED";
 
@@ -1194,6 +1196,11 @@
   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 +1242,8 @@
 
   // 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()) {
@@ -1366,6 +1375,24 @@
     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);
 }
 
@@ -1738,8 +1765,7 @@
   /**
    * 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 +1805,6 @@
       output += *outputPtr;
       output += "\nGenerator: execution of make clean failed.\n";
 
-      // return to the original directory
-      cmSystemTools::ChangeDirectory(cwd);
       return 1;
     }
     output += *outputPtr;
@@ -1803,8 +1827,6 @@
     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 +1839,6 @@
     retVal = 1;
   }
 
-  cmSystemTools::ChangeDirectory(cwd);
   return retVal;
 }
 
@@ -2466,6 +2487,11 @@
   return ruleFile;
 }
 
+bool cmGlobalGenerator::ShouldStripResourcePath(cmMakefile* mf) const
+{
+  return mf->PlatformIsAppleIos();
+}
+
 std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage(
   std::string const& l) const
 {
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 18e3730..2558fee 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -337,6 +337,10 @@
       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 +361,7 @@
   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;
 
@@ -562,6 +567,8 @@
 
   // 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/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index e27615a..ca98e6c 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 @@
     "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,7 +124,10 @@
   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;
 }
@@ -153,6 +168,13 @@
   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 +190,119 @@
   if (!this->ParseGeneratorToolset(ts, mf)) {
     return false;
   }
+
+  if (!this->FindVCTargetsPath(mf)) {
+    return false;
+  }
+
+  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;
   }
 
-  this->GeneratorToolset = ts;
+  // 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;
+    }
+  }
+
   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 +459,16 @@
 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 +503,20 @@
   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 +571,208 @@
   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 +987,17 @@
   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 +1005,8 @@
 
   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..20f992a 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -23,7 +23,6 @@
   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 @@
                               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,10 @@
   /** 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 the CMAKE_SYSTEM_NAME.  */
   std::string const& GetSystemName() const { return this->SystemName; }
 
@@ -95,7 +100,10 @@
   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 +113,9 @@
   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 +126,7 @@
 
   std::string GeneratorToolset;
   std::string GeneratorToolsetHostArchitecture;
+  std::string GeneratorToolsetCuda;
   std::string DefaultPlatformToolset;
   std::string WindowsTargetPlatformVersion;
   std::string SystemName;
@@ -124,7 +136,10 @@
   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 +169,13 @@
   virtual std::string FindDevEnvCommand();
   virtual std::string GetVSMakeProgram() { return this->GetMSBuildCommand(); }
 
+  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/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index 2656dcc..de62ff0 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -109,19 +109,15 @@
   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..3453628 100644
--- a/Source/cmGlobalVisualStudio12Generator.h
+++ b/Source/cmGlobalVisualStudio12Generator.h
@@ -31,8 +31,8 @@
   // 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..d2ac36b 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -238,8 +238,7 @@
 
   // 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/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 602666e..e7fb203 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"
@@ -14,6 +12,7 @@
 #include <cmsys/Encoding.hxx>
 
 #include <assert.h>
+#include <windows.h>
 
 static cmVS7FlagTable cmVS7ExtraFlagTable[] = {
   // Precompiled header and related options.  Note that the
@@ -47,6 +46,7 @@
   this->IntelProjectVersion = 0;
   this->DevEnvCommandInitialized = false;
   this->MasmEnabled = false;
+  this->NasmEnabled = false;
 
   if (platformName.empty()) {
     this->DefaultPlatformName = "Win32";
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 62194c3..1f96cc6 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -95,6 +95,7 @@
 
   /** 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();
@@ -163,6 +164,7 @@
   std::string GeneratorPlatform;
   std::string DefaultPlatformName;
   bool MasmEnabled;
+  bool NasmEnabled;
 
 private:
   char* IntelProjectVersion;
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index ced0c26..32579aa 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -5,6 +5,7 @@
 
 #include <cmsys/Encoding.hxx>
 #include <iostream>
+#include <windows.h>
 
 #include "cmAlgorithms.h"
 #include "cmCallVisualStudioMacro.h"
@@ -441,8 +442,6 @@
   return this->GetAllTargetName();
 }
 
-#include <windows.h>
-
 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
                                         const std::string& regKeyBase,
                                         std::string& nextAvailableSubKeyName)
@@ -814,10 +813,14 @@
   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 +838,59 @@
   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());
+    }
+
+    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";
+      }
     }
   }
+
+  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/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index dd771b1..42dd997 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -28,6 +28,7 @@
 #include "cmTarget.h"
 #include "cmXCode21Object.h"
 #include "cmXCodeObject.h"
+#include "cmXCodeScheme.h"
 #include "cm_auto_ptr.hxx"
 #include "cmake.h"
 
@@ -423,14 +424,12 @@
   // 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 +474,12 @@
       // 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 +487,8 @@
         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 &&
@@ -1155,8 +1154,12 @@
           // 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 +1177,45 @@
       }
     }
 
+    // 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()) {
@@ -3133,10 +3175,7 @@
     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();
@@ -3187,29 +3226,9 @@
     "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 +3247,7 @@
       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 +3257,7 @@
       }
 
       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 +3275,15 @@
           }
         }
 
+        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 +3294,28 @@
           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 +3343,14 @@
       }
     }
   }
+
+  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(
@@ -3331,6 +3385,15 @@
     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 (root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME") &&
+      this->XcodeVersion >= 70) {
+    this->OutputXCodeSharedSchemes(xcodeDir);
+    this->OutputXCodeWorkspaceSettings(xcodeDir);
+  }
+
   this->ClearXCodeObjects();
 
   // Since this call may have created new cache entries, save the cache:
@@ -3339,6 +3402,54 @@
     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*>&)
@@ -3593,6 +3704,12 @@
   return cmSystemTools::IsOn(epnValue);
 }
 
+bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const
+{
+  // Xcode determines Resource location itself
+  return true;
+}
+
 void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 1aaf9c7..172e414 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -88,6 +88,8 @@
 
   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 +167,9 @@
                           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,
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 @@
                                     // 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..bda6b75 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -125,6 +125,8 @@
     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 @@
   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..11f8aba 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -31,6 +31,7 @@
   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 @@
       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..421c3dd 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -57,8 +57,19 @@
         // 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 @@
         } 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 {
diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h
index 56eef30..f81db67 100644
--- a/Source/cmIfCommand.h
+++ b/Source/cmIfCommand.h
@@ -21,6 +21,7 @@
   cmIfFunctionBlocker()
   {
     this->HasRun = false;
+    this->ElseSeen = false;
     this->ScopeDepth = 0;
   }
   ~cmIfFunctionBlocker() CM_OVERRIDE {}
@@ -32,6 +33,7 @@
   std::vector<cmListFileFunction> Functions;
   bool IsBlocking;
   bool HasRun;
+  bool ElseSeen;
   unsigned int ScopeDepth;
 };
 
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 6a700ff..6789555 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -2,10 +2,18 @@
    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 "cmStateDirectory.h"
+#include "cmStateTypes.h"
+
+class cmOutputConverter;
 
 cmLinkLineDeviceComputer::cmLinkLineDeviceComputer(
   cmOutputConverter* outputConverter, cmStateDirectory stateDir)
diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h
index f4bb3eb..f275a0d 100644
--- a/Source/cmLinkLineDeviceComputer.h
+++ b/Source/cmLinkLineDeviceComputer.h
@@ -4,8 +4,17 @@
 #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
 {
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index b1cd889..23b666e 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -80,6 +80,13 @@
     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);
diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c
index 56559f6..44d0894 100644
--- a/Source/cmListFileLexer.c
+++ b/Source/cmListFileLexer.c
@@ -2559,11 +2559,15 @@
       if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) {
         return cmListFileLexer_BOM_UTF32LE;
       }
-      fsetpos(f, &p);
+      if (fsetpos(f, &p) != 0) {
+        return cmListFileLexer_BOM_Broken;
+      }
       return cmListFileLexer_BOM_UTF16LE;
     }
   }
-  rewind(f);
+  if (fseek(f, 0, SEEK_SET) != 0) {
+    return cmListFileLexer_BOM_Broken;
+  }
   return cmListFileLexer_BOM_None;
 }
 
diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h
index c9fb6da..f243010a 100644
--- a/Source/cmListFileLexer.h
+++ b/Source/cmListFileLexer.h
@@ -32,6 +32,7 @@
 enum cmListFileLexer_BOM_e
 {
   cmListFileLexer_BOM_None,
+  cmListFileLexer_BOM_Broken,
   cmListFileLexer_BOM_UTF8,
   cmListFileLexer_BOM_UTF16BE,
   cmListFileLexer_BOM_UTF16LE,
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index b6743f1..5cf1853 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 "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>
 
+#include "cmCPluginAPI.cxx"
+#include "cmCPluginAPI.h"
+#include "cmDynamicLoader.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmSystemTools.h"
+
+class cmExecutionStatus;
+
 #ifdef __QNX__
 #include <malloc.h> /* for malloc/free on QNX */
 #endif
@@ -174,11 +173,6 @@
 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;
   }
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 7077bbb..82bf0b9 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"
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 41a4caf..4388e75 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1864,10 +1864,7 @@
     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/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 38dda04..3117ef3 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -16,6 +16,7 @@
 #include "cmGeneratedFileStream.h"
 
 #include <ctype.h> // for isspace
+#include <windows.h>
 
 static bool cmLVS7G_IsFAT(const char* dir);
 
@@ -745,11 +746,13 @@
 
   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 +790,6 @@
          << 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);
@@ -997,19 +999,14 @@
   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;
@@ -1090,7 +1087,6 @@
       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) "
@@ -1176,7 +1172,6 @@
       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) "
@@ -1365,7 +1360,6 @@
   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;
@@ -1377,9 +1371,6 @@
     }
     // Add the file to the list of sources.
     std::string source = (*i)->GetFullPath();
-    if (cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF") {
-      this->ModuleDefinitionFile = (*i)->GetFullPath();
-    }
     cmSourceGroup* sourceGroup =
       this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
     sourceGroup->AssignSource(*i);
@@ -1675,7 +1666,6 @@
             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 +1819,15 @@
   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());
@@ -2130,7 +2118,6 @@
   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..ae6e2ed 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -128,7 +128,6 @@
 
   friend class EventWriter;
 
-  std::string ModuleDefinitionFile;
   bool FortranProject;
   bool WindowsCEProject;
   cmLocalVisualStudio7GeneratorInternals* Internal;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 1e995fb..f7d822a 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -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
@@ -281,7 +283,8 @@
       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) {
@@ -653,21 +656,12 @@
   // 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 +686,8 @@
   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 +727,8 @@
     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 "
@@ -2155,6 +2151,12 @@
 
 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 +2171,17 @@
   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;
@@ -3153,8 +3166,7 @@
 
   // 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
@@ -3168,8 +3180,6 @@
                          this->GetGlobalGenerator()->GetName() +
                          "' could not be created.");
     cmSystemTools::SetFatalErrorOccured();
-    // return to the original directory
-    cmSystemTools::ChangeDirectory(cwd);
     this->IsSourceFileTryCompile = false;
     return 1;
   }
@@ -3233,8 +3243,6 @@
     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 +3251,6 @@
     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 +3259,6 @@
   int ret = this->GetGlobalGenerator()->TryCompile(
     srcdir, bindir, projectName, targetName, fast, output, this);
 
-  cmSystemTools::ChangeDirectory(cwd);
   this->IsSourceFileTryCompile = false;
   return ret;
 }
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 9d9e90a..4e48c88 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -119,6 +119,13 @@
    */
   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 +133,8 @@
     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,
@@ -428,6 +436,8 @@
 
   /** 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;
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index b76ddeb..493f474 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>
@@ -555,10 +556,7 @@
     }
 
     // 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..598ac3d 100644
--- a/Source/cmMakefileExecutableTargetGenerator.h
+++ b/Source/cmMakefileExecutableTargetGenerator.h
@@ -5,6 +5,8 @@
 
 #include <cmConfigure.h>
 
+#include <string>
+
 #include "cmMakefileTargetGenerator.h"
 
 class cmGeneratorTarget;
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index ff8b604..e5fae13 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>
 
@@ -751,10 +750,7 @@
     }
 
     // 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();
 
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 54b3f36..ed38024 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1414,8 +1414,14 @@
   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.
@@ -1718,31 +1724,32 @@
 }
 
 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 +1761,11 @@
          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..07b8005 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -166,8 +166,7 @@
                          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/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index b1374c2..560eb4f 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -260,12 +260,9 @@
       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 +385,9 @@
       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");
@@ -869,19 +863,6 @@
     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) {
@@ -998,35 +979,39 @@
   }
 
   // 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
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index d57b8f7..2b16e19 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -212,9 +212,14 @@
   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.
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index 7a17f2c..3db0fec 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -10,7 +10,6 @@
 #include "cmAlgorithms.h"
 #include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -495,11 +494,6 @@
 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/cmPolicies.h b/Source/cmPolicies.h
index 62e67c7..ecf06b3 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -200,7 +200,10 @@
          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)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
@@ -221,7 +224,8 @@
   F(CMP0052)                                                                  \
   F(CMP0060)                                                                  \
   F(CMP0063)                                                                  \
-  F(CMP0065)
+  F(CMP0065)                                                                  \
+  F(CMP0068)
 
 /** \class cmPolicies
  * \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmQtAutoGeneratorCommon.cxx b/Source/cmQtAutoGeneratorCommon.cxx
new file mode 100644
index 0000000..2498fe8
--- /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 != line.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..b004005
--- /dev/null
+++ b/Source/cmQtAutoGeneratorCommon.h
@@ -0,0 +1,38 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#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..d69794c 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -1,20 +1,21 @@
 /* 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"
 #include "cmFilePathChecksum.h"
 #include "cmGeneratorTarget.h"
-#include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #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__)
@@ -22,16 +23,11 @@
 #endif
 
 #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 +41,16 @@
   }
 }
 
-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)
@@ -98,21 +96,106 @@
   return qtMajorVersion;
 }
 
-static void SetupSourceFiles(cmGeneratorTarget const* target,
+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 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 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 +206,24 @@
         !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
       continue;
     }
-    if (cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
-      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 +239,89 @@
   }
 }
 
-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,
+  const std::string& qtMajorVersion,
+  std::vector<std::string> const& mocSkipList,
   std::map<std::string, std::string>& configIncludes,
   std::map<std::string, std::string>& configDefines)
 {
   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");
+  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"));
 
-  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;
-      }
+  // Moc includes and compile definitions
+  {
+    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);
+      AddDefinitionEscaped(makefile, "_moc_incs", _moc_incs);
+      AddDefinitionEscaped(makefile, "_moc_compile_defs", _moc_compile_defs);
     }
-    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;
+    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;
+        }
+      }
+      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;
+        }
       }
     }
   }
 
-  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 +334,140 @@
 }
 
 static void UicSetupAutoTarget(
-  cmGeneratorTarget const* target, std::vector<std::string> const& skipUic,
+  cmGeneratorTarget const* target, const std::string& qtMajorVersion,
+  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());
+  // 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);
   }
-  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 target options
+  {
+    std::string _uic_opts;
+    std::vector<std::string> configs;
+    UicGetOpts(target, makefile->GetConfigurations(configs), _uic_opts);
+
+    AddDefinitionEscaped(makefile, "_uic_target_options", _uic_opts);
+
+    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 files options
+  {
+    std::vector<std::string> uiFileFiles;
+    std::vector<std::string> uiFileOptions;
+    {
+      std::set<std::string> skipped;
+      skipped.insert(uicSkipList.begin(), uicSkipList.end());
 
-  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;
+      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 +477,104 @@
   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;
+      const char* optName = fit->c_str();
+      if (*optName == '-') {
+        ++optName;
+        if (isQt5 && *optName == '-') {
+          ++optName;
+        }
       }
-      if (isQt5 && *o == '-') {
-        ++o;
-      }
-      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();
+  const bool qtMajorVersion5 = (qtMajorVersion == "5");
+  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, rccOptionsTarget);
+  }
 
   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;
-  if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) {
-    cmSystemTools::ExpandListArgument(opts, rccOptions);
-  }
-
   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;
+          rccFileFiles.push_back(absFile);
+          rccFileOptions.push_back(
+            cmJoin(rccOptions, cmQtAutoGeneratorCommon::listSep));
         }
-        const char* listSep = "";
-        for (std::vector<std::string>::const_iterator it = rccOptions.begin();
-             it != rccOptions.end(); ++it) {
-          rccFileOptions += listSep;
-          rccFileOptions += *it;
-          listSep = "@list_sep@";
-        }
-        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 +582,14 @@
 {
   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");
+    std::string mocCppFile = GetAutogenTargetBuildDir(target);
+    mocCppFile += "moc_compilation.cpp";
+    {
+      cmSourceFile* gFile = makefile->GetOrCreateSource(mocCppFile, true);
+      gFile->SetProperty("SKIP_AUTOGEN", "On");
+    }
     target->AddSource(mocCppFile);
+    AddToSourceGroup(makefile, mocCppFile, cmQtAutoGeneratorCommon::MOC);
   }
 }
 
@@ -667,12 +599,17 @@
   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 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;
+  const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
+  std::vector<std::string> autogenDepends;
+  std::vector<std::string> autogenProvides;
 
   // Remove old settings on cleanup
   {
@@ -682,32 +619,6 @@
                              false);
   }
 
-  // Create autogen target build directory and add it to the clean files
-  cmSystemTools::MakeDirectory(autogenBuildDir);
-  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);
-  }
-
   // Compose command lines
   cmCustomCommandLines commandLines;
   {
@@ -724,13 +635,13 @@
   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,6 +657,24 @@
     autogenComment = "Automatic " + tools + " for target " + target->GetName();
   }
 
+  // Create autogen target build directory and add it to the clean files
+  cmSystemTools::MakeDirectory(autogenBuildDir);
+  makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
+                           autogenBuildDir.c_str(), false);
+
+  // Create autogen target includes directory and
+  // add it to the origin target INCLUDE_DIRECTORIES
+  if (mocEnabled || uicEnabled) {
+    const std::string incsDir = autogenBuildDir + "include";
+    cmSystemTools::MakeDirectory(incsDir);
+    target->AddIncludeDirectory(incsDir, true);
+  }
+
+  // Register moc compilation file as generated
+  if (mocEnabled) {
+    autogenProvides.push_back(autogenBuildDir + "moc_compilation.cpp");
+  }
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
   bool usePRE_BUILD = false;
   cmGlobalGenerator* gg = lg->GetGlobalGenerator();
@@ -757,65 +686,103 @@
     // 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;
-        }
-      }
-    }
   }
 #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")) {
+        const std::string 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);
+          // Compose rcc output file name
+          {
+            std::string rccOut = autogenBuildDir;
+            rccOut += fpathCheckSum.getPart(absFile);
+            rccOut += "/qrc_";
+            rccOut +=
+              cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
+            rccOut += ".cpp";
 
-          std::string rccOutputFile = autogenBuildDir;
-          rccOutputFile += fpathCheckSum.getPart(absFile);
-          rccOutputFile += "/qrc_";
-          rccOutputFile +=
-            cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
-          rccOutputFile += ".cpp";
+            // Register rcc output file as generated
+            autogenProvides.push_back(rccOut);
 
-          // 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);
-#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;
-#endif
+            // Add rcc output file to origin target sources
+            {
+              cmSourceFile* gFile = makefile->GetOrCreateSource(rccOut, true);
+              gFile->SetProperty("SKIP_AUTOGEN", "On");
+            }
+            target->AddSource(rccOut);
+            AddToSourceGroup(makefile, rccOut, cmQtAutoGeneratorCommon::RCC);
           }
+
+          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;
+#endif
         }
       }
     }
@@ -823,12 +790,21 @@
 
 #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 +815,7 @@
   {
     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,47 +848,41 @@
   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);
-
-  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;
   std::map<std::string, std::string> configMocIncludes;
   std::map<std::string, std::string> configMocDefines;
   std::map<std::string, std::string> configUicOptions;
+  {
+    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);
 
-  if (target->GetPropertyAsBool("AUTOMOC") ||
-      target->GetPropertyAsBool("AUTOUIC") ||
-      target->GetPropertyAsBool("AUTORCC")) {
-    SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic);
-  }
-  makefile->AddDefinition(
-    "_moc_uic_sources",
-    cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str());
-  makefile->AddDefinition(
-    "_moc_uic_headers",
-    cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str());
+    std::vector<std::string> _sources;
+    std::vector<std::string> _headers;
 
-  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);
+    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,
+                           mocSkipList, configMocIncludes, configMocDefines);
+      }
+      if (uicEnabled) {
+        UicSetupAutoTarget(target, qtMajorVersion, uicSkipList,
+                           configUicOptions);
+      }
+      if (rccEnabled) {
+        RccSetupAutoTarget(target, qtMajorVersion);
+      }
+    }
+
+    AddDefinitionEscaped(makefile, "_autogen_target_name", autogenTargetName);
+    AddDefinitionEscaped(makefile, "_origin_target_name", target->GetName());
+    AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion);
+    AddDefinitionEscaped(makefile, "_sources", _sources);
+    AddDefinitionEscaped(makefile, "_headers", _headers);
   }
 
   // Generate config file
@@ -924,7 +894,7 @@
   makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true,
                           false);
 
-  // Append custom definitions to config file
+  // Append custom config definitions to info file
   if (!configMocDefines.empty() || !configMocIncludes.empty() ||
       !configUicOptions.empty()) {
 
@@ -946,33 +916,34 @@
       error += outputFile;
       error += " for writing.";
       cmSystemTools::Error(error.c_str());
-      return;
-    }
-    if (!configMocDefines.empty()) {
-      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";
+    } else {
+      infoFile << "# Configuration specific options\n";
+      if (!configMocDefines.empty()) {
+        for (std::map<std::string, std::string>::iterator
+               it = configMocDefines.begin(),
+               end = configMocDefines.end();
+             it != end; ++it) {
+          infoFile << "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";
+      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";
+        }
       }
-    }
-    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";
+      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";
+        }
       }
     }
   }
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 1d6972b..246dd8d 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -1,19 +1,21 @@
 /* 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 <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 "cmFilePathChecksum.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
@@ -29,29 +31,52 @@
 
 // -- 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_OLD_SETTINGS";
+static const char* SettingsKeyUic = "AM_UIC_OLD_SETTINGS";
+static const char* SettingsKeyRcc = "AM_RCC_OLD_SETTINGS";
 
 // -- 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 makefile->GetSafeDefinition(key);
+  return cmQtAutoGeneratorCommon::Quoted(text);
 }
 
-static std::string OldSettingsFile(const std::string& targetDirectory)
+static void InfoGet(cmMakefile* makefile, const char* key, std::string& value)
+{
+  value = makefile->GetSafeDefinition(key);
+}
+
+static void InfoGet(cmMakefile* makefile, const char* key, bool& value)
+{
+  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 InfoGet(cmMakefile* makefile, const char* key,
+                    const std::string& config, std::vector<std::string>& list)
+{
+  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);
+  }
+  cmSystemTools::ExpandListArgument(valueConf, list);
+}
+
+static std::string SettingsFile(const std::string& targetDirectory)
 {
   std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
   cmSystemTools::ConvertToUnixSlashes(filename);
@@ -59,40 +84,28 @@
   return filename;
 }
 
-static std::string FindMatchingHeader(
-  const std::string& absPath, const std::string& mocSubDir,
-  const std::string& basename,
-  const std::vector<std::string>& headerExtensions)
+inline static bool SettingsMatch(cmMakefile* makefile, const char* key,
+                                 const std::string& 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;
-      }
-    }
-  }
-
-  return header;
+  return (value == makefile->GetSafeDefinition(key));
 }
 
-static std::string ExtractSubDir(const std::string& absPath,
-                                 const std::string& currentMoc)
+static void SettingWrite(std::ostream& ostr, const char* key,
+                         const std::string& value)
 {
-  std::string subDir;
-  if (currentMoc.find_first_of('/') != std::string::npos) {
-    subDir = absPath + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/';
+  if (!value.empty()) {
+    ostr << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
+         << ")\n";
   }
-  return subDir;
+}
+
+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 +125,19 @@
   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 +159,19 @@
   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 += "===";
@@ -214,9 +239,9 @@
   , RunMocFailed(false)
   , RunUicFailed(false)
   , RunRccFailed(false)
-  , GenerateMocAll(false)
-  , GenerateUicAll(false)
-  , GenerateRccAll(false)
+  , GenerateAllMoc(false)
+  , GenerateAllUic(false)
+  , GenerateAllRcc(false)
 {
 
   std::string colorEnv;
@@ -229,9 +254,12 @@
     }
   }
 
+  this->MacroFilters[0].first = "Q_OBJECT";
+  this->MacroFilters[0].second.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
+  this->MacroFilters[1].first = "Q_GADGET";
+  this->MacroFilters[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(
     "[\n][ \t]*#[ \t]*include[ \t]+"
     "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
@@ -255,23 +283,46 @@
   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(), targetDirectory);
+    // Init and run
+    this->Init(mf.get());
+    if (this->RunAutogen()) {
+      // Write current settings
+      if (this->SettingsFileWrite(targetDirectory)) {
+        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 +334,373 @@
   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");
+  InfoGet(makefile, "AM_TARGET_NAME", this->AutogenTargetName);
+  InfoGet(makefile, "AM_ORIGIN_TARGET_NAME", this->OriginTargetName);
 
-  // - 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");
+  // - 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_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);
   }
-  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);
+  InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable);
+  InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable);
+  InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable);
+  // Check Qt version
+  if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
+    this->LogError("AutoGen: Error: Unsupported Qt version: " +
+                   Quoted(this->QtMajorVersion));
+    return false;
+  }
 
   // - 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");
+  if (this->MocEnabled()) {
+    InfoGet(makefile, "AM_MOC_SKIP", this->MocSkipList);
+    InfoGet(makefile, "AM_MOC_DEFINITIONS", config, this->MocDefinitions);
+    InfoGet(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;
+      }
+    }
+  }
 
   // - 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;
-    }
-    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;
+  if (this->UicEnabled()) {
+    InfoGet(makefile, "AM_UIC_SKIP", this->UicSkipList);
+    InfoGet(makefile, "AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
+    InfoGet(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;
+      }
     }
   }
 
   // - 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;
+  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 = rccFilesVec.begin(),
-                                            optionIt = rccOptionsVec.begin();
-         fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) {
-      cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";");
-      this->RccOptions[*fileIt] = *optionIt;
+    // 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;
+      }
     }
   }
-  {
-    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;
-    }
-    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;
-    }
-  }
-
-  // - 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()
+void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile,
+                                          const std::string& targetDirectory)
 {
-  std::string res;
-  res += this->MocCompileDefinitionsStr;
-  res += " ~~~ ";
-  res += this->MocIncludesStr;
-  res += " ~~~ ";
-  res += this->MocOptionsStr;
-  res += " ~~~ ";
-  res += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE";
-  res += " ~~~ ";
-  return res;
-}
+  // Compose current settings strings
+  if (this->MocEnabled()) {
+    std::string& str = this->SettingsStringMoc;
+    str += JoinOptionsList(this->MocDefinitions);
+    str += " ~~~ ";
+    str += JoinOptionsList(this->MocIncludePaths);
+    str += " ~~~ ";
+    str += JoinOptionsList(this->MocOptions);
+    str += " ~~~ ";
+    str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE";
+    str += " ~~~ ";
+  }
+  if (this->UicEnabled()) {
+    std::string& str = this->SettingsStringUic;
+    str += JoinOptionsList(this->UicTargetOptions);
+    str += " ~~~ ";
+    str += JoinOptionsMap(this->UicOptions);
+    str += " ~~~ ";
+  }
+  if (this->RccEnabled()) {
+    std::string& str = this->SettingsStringRcc;
+    str += JoinOptionsMap(this->RccOptions);
+    str += " ~~~ ";
+  }
 
-std::string cmQtAutoGenerators::UicSettingsStringCompose()
-{
-  std::string res;
-  res += cmJoin(this->UicTargetOptions, "@osep@");
-  res += " ~~~ ";
-  res += JoinOptions(this->UicOptions);
-  res += " ~~~ ";
-  return res;
-}
-
-std::string cmQtAutoGenerators::RccSettingsStringCompose()
-{
-  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();
-
-    // 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
+  const std::string filename = SettingsFile(targetDirectory);
+  if (makefile->ReadListFile(filename.c_str())) {
+    if (!SettingsMatch(makefile, SettingsKeyMoc, this->SettingsStringMoc)) {
+      this->GenerateAllMoc = true;
     }
+    if (!SettingsMatch(makefile, SettingsKeyUic, this->SettingsStringUic)) {
+      this->GenerateAllUic = true;
+    }
+    if (!SettingsMatch(makefile, SettingsKeyRcc, this->SettingsStringRcc)) {
+      this->GenerateAllRcc = 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->GenerateAllAny()) {
+      cmSystemTools::RemoveFile(filename);
+    }
+  } else {
+    // If the file could not be read re-generate everythiung.
+    this->GenerateAllMoc = true;
+    this->GenerateAllUic = true;
+    this->GenerateAllRcc = true;
   }
 }
 
-bool cmQtAutoGenerators::OldSettingsWriteFile(
-  const std::string& targetDirectory)
+bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory)
 {
   bool success = true;
   // Only write if any setting changed
-  if (this->GenerateMocAll || this->GenerateUicAll || this->GenerateRccAll) {
-    const std::string filename = OldSettingsFile(targetDirectory);
+  if (this->GenerateAllAny()) {
+    const std::string filename = SettingsFile(targetDirectory);
+    if (this->Verbose) {
+      this->LogInfo("AutoGen: Writing settings file " + filename);
+    }
     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";
-      }
+      SettingWrite(outfile, SettingsKeyMoc, this->SettingsStringMoc);
+      SettingWrite(outfile, SettingsKeyUic, this->SettingsStringUic);
+      SettingWrite(outfile, SettingsKeyRcc, this->SettingsStringRcc);
       success = outfile.good();
       outfile.close();
     } else {
       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());
-      }
+      this->LogError("AutoGen: Error: Writing old settings file failed: " +
+                     filename);
     }
   }
   return success;
 }
 
-void cmQtAutoGenerators::Init()
+void cmQtAutoGenerators::Init(cmMakefile* makefile)
 {
   this->AutogenBuildSubDir = this->AutogenTargetName;
   this->AutogenBuildSubDir += "/";
 
-  this->OutMocCppFilenameRel = this->AutogenBuildSubDir;
-  this->OutMocCppFilenameRel += "moc_compilation.cpp";
+  this->MocCppFilenameRel = this->AutogenBuildSubDir;
+  this->MocCppFilenameRel += "moc_compilation.cpp";
 
-  this->OutMocCppFilenameAbs =
-    this->CurrentBinaryDir + this->OutMocCppFilenameRel;
+  this->MocCppFilenameAbs = this->CurrentBinaryDir + this->MocCppFilenameRel;
 
   // Init file path checksum generator
   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));
-  }
+  // Acquire header extensions
+  this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
 
-  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);
-  }
-
+  // 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.
+  // is included anywhere a moc_<filename>.cpp file is created and included
+  // in the moc_compilation.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 +711,73 @@
  * @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;
-    }
-  }
-  if (strstr(text.c_str(), "Q_GADGET") != CM_NULLPTR) {
-    if (this->RegExpQGadget.find(text)) {
-      macroName = "Q_GADGET";
-      return true;
+  for (unsigned int ii = 0; ii != cmArraySize(this->MacroFilters); ++ii) {
+    MacroFilter& filter = this->MacroFilters[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;
+      }
     }
   }
   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();
+      }
+    }
+  }
+}
+
 /**
  * @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 +787,11 @@
 /**
  * @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,52 +803,49 @@
  */
 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());
+  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 {
-    // 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::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));
+      uisIncluded[absFilename].push_back(this->RegExpUicInclude.match(1));
       contentChars += this->RegExpUicInclude.end();
     }
   }
@@ -791,79 +854,67 @@
 /**
  * @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);
+      const std::string incString = this->RegExpMocInclude.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;
+          // 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: " << 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,71 +922,81 @@
         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());
+              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 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());
+                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: Error: " << 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
@@ -943,36 +1004,40 @@
     }
   }
 
-  // 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,144 +1045,145 @@
   return true;
 }
 
-void cmQtAutoGenerators::SearchHeadersForSourceFile(
-  const std::string& absFilename,
-  const std::vector<std::string>& headerExtensions,
-  std::set<std::string>& absHeadersMoc, std::set<std::string>& absHeadersUic)
+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)
 {
-  // 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;
-    }
+  // Log
+  if (this->Verbose) {
+    this->LogInfo("AutoMoc: Checking " + absFilename);
   }
-  // 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())) {
+  if (this->MocRequired(contentText)) {
+    // Register moc job
+    mocsNotIncluded[absFilename] =
+      this->ChecksumedPath(absFilename, "moc_", ".cpp");
+    this->MocFindDepends(absFilename, contentText, mocDepends);
+  }
+}
+
+void cmQtAutoGenerators::SearchHeadersForSourceFile(
+  const std::string& absFilename, std::set<std::string>& mocHeaderFiles,
+  std::set<std::string>& uicHeaderFiles) const
+{
+  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";
+  }
+
+  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;
   }
 
+  bool mocCompFileGenerated = false;
+  bool mocCompChanged = false;
+
   // 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.
+  // Generate moc files that are included by source files.
   {
-    const std::string subDirPrefix = "include/";
+    const std::string subDir = "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)) {
+           mocsIncluded.begin();
+         it != mocsIncluded.end(); ++it) {
+      if (!this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) {
         if (this->RunMocFailed) {
           return false;
         }
       }
     }
   }
-
-  // generate moc files that are _not_ included by source files.
-  bool automocCppChanged = false;
+  // Generate moc files that are _not_ included by source files.
   {
-    const std::string subDirPrefix;
+    const std::string subDir;
     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;
+           mocsNotIncluded.begin();
+         it != mocsNotIncluded.end(); ++it) {
+      if (this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) {
+        mocCompFileGenerated = true;
       } else {
         if (this->RunMocFailed) {
           return false;
@@ -1129,183 +1195,238 @@
   // Compose moc_compilation.cpp 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();
+    automocSource = ost.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;
-    }
-  }
-
-  // Actually write moc_compilation.cpp
+  // Check if the content of moc_compilation.cpp changed
   {
-    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());
+    std::string oldContents;
+    if (ReadAll(oldContents, this->MocCppFilenameAbs)) {
+      mocCompChanged = (oldContents != automocSource);
     } 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());
-      }
+      mocCompChanged = true;
     }
   }
+
+  bool success = true;
+  if (mocCompChanged) {
+    // Actually write moc_compilation.cpp
+    this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel);
+
+    // Make sure the parent directory exists
+    success = this->MakeParentDirectory(this->MocCppFilenameAbs);
+    if (success) {
+      cmsys::ofstream outfile;
+      outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc);
+      if (!outfile) {
+        success = false;
+        this->LogError("AutoMoc: Error opening " + this->MocCppFilenameAbs);
+      } else {
+        outfile << automocSource;
+        // Check for write errors
+        if (!outfile.good()) {
+          success = false;
+          this->LogError("AutoMoc: Error writing " + this->MocCppFilenameAbs);
+        }
+      }
+    }
+  } else if (mocCompFileGenerated) {
+    // Only touch moc_compilation.cpp
+    if (this->Verbose) {
+      this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel);
+    }
+    cmSystemTools::Touch(this->MocCppFilenameAbs, false);
+  }
+
   return success;
 }
 
 /**
  * @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::string& subDir,
+  const std::map<std::string, std::set<std::string> >& mocDepends)
 {
+  bool mocGenerated = false;
+  bool generateMoc = this->GenerateAllMoc;
+
   const std::string mocFileRel =
-    this->AutogenBuildSubDir + subDirPrefix + mocFileName;
+    this->AutogenBuildSubDir + subDir + mocFileName;
   const std::string mocFileAbs = this->CurrentBinaryDir + 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);
-    }
-
-    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());
+    if (this->MakeParentDirectory(mocFileAbs)) {
+      // Compose moc command
+      std::vector<std::string> cmd;
+      cmd.push_back(this->MocExecutable);
+      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));
       }
-      cmSystemTools::RemoveFile(mocFileAbs);
+      cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end());
+#ifdef _WIN32
+      cmd.push_back("-DWIN32");
+#endif
+      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" << cmJoin(cmd, " ") << "\n";
+          ost << "AutoMoc: Command output:\n" << output << "\n";
+          this->LogError(ost.str());
+        }
+        cmSystemTools::RemoveFile(mocFileAbs);
+        this->RunMocFailed = true;
+      }
+    } else {
+      // Parent directory creation failed
       this->RunMocFailed = true;
-      return false;
     }
-    return true;
   }
-  return false;
+  return mocGenerated;
+}
+
+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;
+      }
+    }
+  }
+  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) {
@@ -1327,13 +1448,15 @@
                                          const std::string& uiInputFile,
                                          const std::string& uiOutputFile)
 {
+  bool uicGenerated = false;
+  bool generateUic = this->GenerateAllUic;
+
   const std::string uicFileRel =
     this->AutogenBuildSubDir + "include/" + uiOutputFile;
   const std::string uicFileAbs = this->CurrentBinaryDir + 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,55 +1464,54 @@
     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(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);
+      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" << cmJoin(cmd, " ") << "\n";
+          ost << "AutoUic: Command output:\n" << output << "\n";
+          this->LogError(ost.str());
+        }
+        cmSystemTools::RemoveFile(uicFileAbs);
+        this->RunUicFailed = true;
+      }
+    } else {
+      // Parent directory creation failed
       this->RunUicFailed = true;
-      return false;
     }
-    return true;
   }
-  return false;
+  return uicGenerated;
 }
 
-bool cmQtAutoGenerators::QrcGenerateAll()
+bool cmQtAutoGenerators::RccGenerateAll()
 {
-  if (this->RccExecutable.empty()) {
+  if (!this->RccEnabled()) {
     return true;
   }
 
@@ -1399,9 +1521,8 @@
        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";
+      qrcGenMap[*si] =
+        this->AutogenBuildSubDir + this->ChecksumedPath(*si, "qrc_", ".cpp");
     }
   }
 
@@ -1409,12 +1530,11 @@
   {
     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,7 +1544,7 @@
          qrcGenMap.begin();
        si != qrcGenMap.end(); ++si) {
     bool unique = FileNameIsUnique(si->first, qrcGenMap);
-    if (!this->QrcGenerateFile(si->first, si->second, unique)) {
+    if (!this->RccGenerateFile(si->first, si->second, unique)) {
       if (this->RunRccFailed) {
         return false;
       }
@@ -1436,155 +1556,194 @@
 /**
  * @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(), '-', '_');
+  bool rccGenerated = false;
+  bool generateRcc = this->GenerateAllRcc;
 
-  const std::string qrcBuildFile = this->CurrentBinaryDir + qrcOutputFile;
+  const std::string rccBuildFile = this->CurrentBinaryDir + rccOutputFile;
 
-  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;
+  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->RunRccFailed = 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(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);
+      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" << cmJoin(cmd, " ") << "\n";
+          ost << "AutoRcc: Command output:\n" << output << "\n";
+          this->LogError(ost.str());
+        }
+        cmSystemTools::RemoveFile(rccBuildFile);
+        this->RunRccFailed = true;
+      }
+    } else {
+      // Parent directory creation failed
       this->RunRccFailed = true;
-      return false;
     }
-    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();
-}
-
-void cmQtAutoGenerators::LogError(const std::string& message)
-{
-  std::ostringstream ostr;
-  ostr << message << "\n\n";
-  std::cerr << ostr.str();
-}
-
-void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command)
-{
-  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;
+    cmSystemTools::Stdout(msg.c_str(), msg.size());
   }
-  if (!sbuf.str().empty()) {
-    sbuf << std::endl;
-    this->LogInfo(sbuf.str());
+}
+
+void cmQtAutoGenerators::LogWarning(const std::string& message) const
+{
+  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::LogError(const std::string& message) const
+{
+  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::Stderr(msg.c_str(), msg.size());
+  }
+}
+
+void cmQtAutoGenerators::LogCommand(
+  const std::vector<std::string>& command) const
+{
+  std::vector<std::string> cmdEscaped;
+  typedef std::vector<std::string>::const_iterator Iter;
+  for (Iter cit = command.begin(); cit != command.end(); ++cit) {
+    const std::string cesc = Quoted(*cit);
+    if ((cesc.size() > (cit->size() + 2)) ||
+        (cesc.find(' ') != std::string::npos)) {
+      cmdEscaped.push_back(cesc);
+    } else {
+      cmdEscaped.push_back(*cit);
+    }
+  }
+  this->LogInfo(cmJoin(cmdEscaped, " "));
+}
+
 /**
  * @brief Collects name collisions as output/input pairs
  * @return True if there were collisions
  */
 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 +1768,126 @@
 }
 
 /**
+ * @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 char* basePrefix,
+                                               const char* 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 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());
+      this->LogError("AutoGen: Error: Directory creation failed: " + dirName);
+    }
+  }
+  return success;
+}
+
+/**
+ * @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) const
+{
+  // Log command
+  if (this->Verbose) {
+    this->LogCommand(command);
+  }
+  // Execute command
+  int retVal = 0;
+  bool res =
+    cmSystemTools::RunSingleCommand(command, &output, &output, &retVal);
+  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..ee046de 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -7,10 +7,10 @@
 #include <cmFilePathChecksum.h>
 #include <cmsys/RegularExpression.hxx>
 
-#include <list>
 #include <map>
 #include <set>
 #include <string>
+#include <utility>
 #include <vector>
 
 class cmMakefile;
@@ -22,91 +22,135 @@
   bool Run(const std::string& targetDirectory, const std::string& config);
 
 private:
+  // - 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> MacroFilter;
+
   // - 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,
+                        const std::string& targetDirectory);
+  bool SettingsFileWrite(const std::string& targetDirectory);
+
+  bool GenerateAllAny() const
+  {
+    return (this->GenerateAllMoc || this->GenerateAllRcc ||
+            this->GenerateAllUic);
+  }
 
   // - Init and run
-  void Init();
-  bool RunAutogen(cmMakefile* makefile);
+  void Init(cmMakefile* makefile);
+  bool RunAutogen();
 
   // - Content analysis
-  bool MocRequired(const std::string& text, std::string& macroName);
-  bool MocSkipTest(const std::string& absFilename);
-  bool UicSkipTest(const std::string& absFilename);
+  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);
+
+  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 SearchHeadersForSourceFile(const std::string& absFilename,
+                                  std::set<std::string>& mocHeaderFiles,
+                                  std::set<std::string>& uicHeaderFiles) const;
 
-  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,
+  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);
+
+  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);
 
   // - 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);
+    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::string& subDir,
+    const std::map<std::string, std::set<std::string> >& mocDepends);
 
   // - 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
   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);
+    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);
-  bool MakeParentDirectory(const std::string& filename);
+  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 char* basePrefix,
+                             const char* baseSuffix) const;
+  bool MakeParentDirectory(const std::string& filename) const;
+  bool RunCommand(const std::vector<std::string>& command,
+                  std::string& output) 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;
 
   // - Target names
   std::string OriginTargetName;
@@ -125,31 +169,32 @@
   // - File lists
   std::vector<std::string> Sources;
   std::vector<std::string> Headers;
+  // - Settings
+  std::string SettingsStringMoc;
+  std::string SettingsStringUic;
+  std::string SettingsStringRcc;
   // - 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::string MocCppFilenameRel;
+  std::string MocCppFilenameAbs;
+  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;
+  std::vector<MocDependFilter> MocDependFilters;
   // - Uic
-  std::vector<std::string> SkipUic;
+  std::vector<std::string> UicSkipList;
   std::vector<std::string> UicTargetOptions;
   std::map<std::string, std::string> UicOptions;
-  std::string UicSettingsString;
+  std::vector<std::string> UicSearchPaths;
   // - Rcc
   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;
+  std::vector<std::string> HeaderExtensions;
+  MacroFilter MacroFilters[2];
   cmsys::RegularExpression RegExpMocInclude;
   cmsys::RegularExpression RegExpUicInclude;
   // - Flags
@@ -159,9 +204,9 @@
   bool RunMocFailed;
   bool RunUicFailed;
   bool RunRccFailed;
-  bool GenerateMocAll;
-  bool GenerateUicAll;
-  bool GenerateRccAll;
+  bool GenerateAllMoc;
+  bool GenerateAllUic;
+  bool GenerateAllRcc;
   bool MocRelaxedMode;
 };
 
diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h
index 3efe28d..9357831 100644
--- a/Source/cmServerConnection.h
+++ b/Source/cmServerConnection.h
@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #pragma once
 
+#include <cmConfigure.h> // IWYU pragma: keep
+
 #include <string>
 #include <vector>
 
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index 5555199..631f2a6 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"
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/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index c6288a5..d2c9d73 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
@@ -298,9 +302,15 @@
 #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/cmStateTypes.h b/Source/cmStateTypes.h
index 2c974c1..da14cdb 100644
--- a/Source/cmStateTypes.h
+++ b/Source/cmStateTypes.h
@@ -27,6 +27,9 @@
   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,
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/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 9efc13b..ee751f2 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -4,6 +4,7 @@
 
 #include "cmAlgorithms.h"
 #include "cmProcessOutput.h"
+#include "cm_sys_stat.h"
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmArchiveWrite.h"
@@ -33,7 +34,6 @@
 #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>
@@ -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>
@@ -1978,6 +1978,7 @@
     // ???
   }
 #endif
+  exe_dir = cmSystemTools::GetActualCaseForPath(exe_dir);
   cmSystemToolsCMakeCommand = exe_dir;
   cmSystemToolsCMakeCommand += "/cmake";
   cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension();
@@ -2015,8 +2016,7 @@
   // 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;
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 10e8280..e93eaae 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -5,19 +5,13 @@
 
 #include <cmConfigure.h> // IWYU pragma: keep
 
+#include "cmsys/SystemTools.hxx" // IWYU pragma: export
 #include <cmProcessOutput.h>
 #include <cmsys/Process.h>
-#include <cmsys/SystemTools.hxx>
 #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
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index fe3472d..e3c7b63 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -230,6 +230,7 @@
     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 +246,17 @@
     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);
diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx
index 3e72d75..8ef0958 100644
--- a/Source/cmUseMangledMesaCommand.cxx
+++ b/Source/cmUseMangledMesaCommand.cxx
@@ -5,7 +5,6 @@
 #include <cmsys/FStream.hxx>
 #include <cmsys/RegularExpression.hxx>
 
-#include "cmPolicies.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -13,11 +12,6 @@
 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/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx
index 3b78abe..37d8bfb 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 @@
 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;
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/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/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx
index 1eb1f20..10b0a88 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,11 +12,6 @@
 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;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 902fe03..9c9296e 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -10,6 +10,7 @@
 #include "cmLocalVisualStudio7Generator.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
+#include "cmSystemTools.h"
 #include "cmVisualStudioGeneratorOptions.h"
 #include "windows.h"
 
@@ -111,6 +112,10 @@
        i != this->LinkOptions.end(); ++i) {
     delete i->second;
   }
+  for (OptionsMap::iterator i = this->CudaOptions.begin();
+       i != this->CudaOptions.end(); ++i) {
+    delete i->second;
+  }
   if (!this->BuildFileStream) {
     return;
   }
@@ -205,9 +210,15 @@
     if (!this->ComputeRcOptions()) {
       return;
     }
+    if (!this->ComputeCudaOptions()) {
+      return;
+    }
     if (!this->ComputeMasmOptions()) {
       return;
     }
+    if (!this->ComputeNasmOptions()) {
+      return;
+    }
     if (!this->ComputeLinkOptions()) {
       return;
     }
@@ -450,11 +461,34 @@
     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 +539,26 @@
   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 =
@@ -1668,8 +1717,10 @@
   //
   // 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())) {
@@ -1740,10 +1791,14 @@
       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";
     }
 
     if (!tool.empty()) {
@@ -1813,10 +1868,9 @@
     (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\" />\n";
   }
 
-  if (cmSourceFile const* defsrc =
-        this->GeneratorTarget->GetModuleDefinitionFile("")) {
-    this->WriteSource("None", defsrc);
-  }
+  std::vector<cmSourceFile const*> defSources;
+  this->GeneratorTarget->GetModuleDefinitionSources(defSources, "");
+  this->WriteSources("None", defSources);
 
   if (this->IsMissingFiles) {
     this->WriteMissingFiles();
@@ -1932,7 +1986,7 @@
       }
       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);
@@ -2180,8 +2234,10 @@
   if (linkLanguage == "CXX") {
     clOptions.AddFlag("CompileAs", "CompileAsCpp");
   }
-  this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
-                                          linkLanguage, configName.c_str());
+  if (linkLanguage != "CUDA") {
+    this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
+                                            linkLanguage, configName.c_str());
+  }
 
   // Get preprocessor definitions for this directory.
   std::string defineFlags =
@@ -2265,7 +2321,7 @@
     return;
   }
   this->WriteString("<ClCompile>\n", 2);
-  clOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
+  clOptions.PrependInheritedString("AdditionalOptions");
   clOptions.AppendFlag("AdditionalIncludeDirectories", includes);
   clOptions.AppendFlag("AdditionalIncludeDirectories",
                        "%(AdditionalIncludeDirectories)");
@@ -2369,12 +2425,105 @@
   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));
+
+  // 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");
+  }
+
+  // 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 these before nvcc!  Just drop whatever
+  // did not parse and hope it works.
+  cudaOptions.RemoveFlag("AdditionalCompilerOptions");
+
+  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::ComputeMasmOptions()
 {
   if (!this->GlobalGenerator->IsMasmEnabled()) {
@@ -2427,12 +2576,77 @@
   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 +2665,7 @@
       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 +2862,10 @@
     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 +2906,6 @@
     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 +2915,30 @@
       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
@@ -2836,24 +3053,15 @@
   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() >=
@@ -2940,7 +3148,7 @@
   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 +3271,9 @@
       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);
@@ -3090,18 +3300,15 @@
   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",
@@ -3990,3 +4197,14 @@
   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..52d5550 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -51,7 +51,7 @@
   };
 
   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();
@@ -98,10 +98,19 @@
   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 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 +154,9 @@
   typedef std::map<std::string, Options*> OptionsMap;
   OptionsMap ClOptions;
   OptionsMap RcOptions;
+  OptionsMap CudaOptions;
   OptionsMap MasmOptions;
+  OptionsMap NasmOptions;
   OptionsMap LinkOptions;
   std::string PathToProjectFile;
   std::string ProjectFileExtension;
@@ -177,6 +188,7 @@
 
   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..0f15ec4 100644
--- a/Source/cmVisualStudio10ToolsetOptions.cxx
+++ b/Source/cmVisualStudio10ToolsetOptions.cxx
@@ -11,6 +11,7 @@
 #include "cmVS10LibFlagTable.h"
 #include "cmVS10LinkFlagTable.h"
 #include "cmVS10MASMFlagTable.h"
+#include "cmVS10NASMFlagTable.h"
 #include "cmVS10RCFlagTable.h"
 #include "cmVS11CLFlagTable.h"
 #include "cmVS11CSharpFlagTable.h"
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index da6f9a7..abc4924 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -44,6 +44,8 @@
   this->FortranRuntimeDebug = false;
   this->FortranRuntimeDLL = false;
   this->FortranRuntimeMT = false;
+
+  this->UnknownFlagField = "AdditionalOptions";
 }
 
 cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
@@ -68,6 +70,8 @@
   this->FortranRuntimeDebug = false;
   this->FortranRuntimeDLL = false;
   this->FortranRuntimeMT = false;
+
+  this->UnknownFlagField = "AdditionalOptions";
 }
 
 void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table)
@@ -82,6 +86,13 @@
   }
 }
 
+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
@@ -177,6 +188,78 @@
   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 +293,44 @@
     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 +356,22 @@
   }
 
   // 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 +386,22 @@
   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 +430,7 @@
     sep = ";";
   }
   if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
-    fout << ";%(PreprocessorDefinitions)</PreprocessorDefinitions>" << suffix;
+    fout << ";%(" << tag << ")</" << tag << ">" << suffix;
   } else {
     fout << "\"" << suffix;
   }
@@ -335,26 +471,3 @@
     }
   }
 }
-
-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..52689e0 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -26,7 +26,9 @@
   {
     Compiler,
     ResourceCompiler,
+    CudaCompiler,
     MasmCompiler,
+    NasmCompiler,
     Linker,
     FortranCompiler,
     CSharpCompiler
@@ -42,10 +44,19 @@
   // 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 @@
   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 @@
                                      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 @@
   bool FortranRuntimeDLL;
   bool FortranRuntimeMT;
 
+  std::string UnknownFlagField;
+
   virtual void StoreUnknownFlag(const char* flag);
+
+  FlagValue TakeFlag(std::string const& key);
 };
 
 #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..af0fd44
--- /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..ce2de57 100644
--- a/Source/cmWriteFileCommand.cxx
+++ b/Source/cmWriteFileCommand.cxx
@@ -4,12 +4,9 @@
 
 #include <cmsys/FStream.hxx>
 
-#include <sys/types.h>
-// include sys/stat.h after sys/types.h
-#include <sys/stat.h>
-
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
+#include "cm_sys_stat.h"
 
 class cmExecutionStatus;
 
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..0a8e737
--- /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/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx
index 2f50fe9..541cb3d 100644
--- a/Source/cmXMLWriter.cxx
+++ b/Source/cmXMLWriter.cxx
@@ -7,6 +7,7 @@
 
 cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
   : Output(output)
+  , IndentationElement(1, '\t')
   , Level(level)
   , ElementOpen(false)
   , BreakAttrib(false)
@@ -100,10 +101,18 @@
   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..6d1e6b4 100644
--- a/Source/cmXMLWriter.h
+++ b/Source/cmXMLWriter.h
@@ -60,6 +60,8 @@
 
   void FragmentFile(const char* fname);
 
+  void SetIndentationElement(std::string const& element);
+
 private:
   cmXMLWriter(const cmXMLWriter&);
   cmXMLWriter& operator=(const cmXMLWriter&);
@@ -107,6 +109,7 @@
 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_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/cmake.cxx b/Source/cmake.cxx
index 6141f50..4363c12 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -23,7 +23,9 @@
 #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>
@@ -105,10 +107,6 @@
 #include <sys/time.h>
 #endif
 
-#include <sys/types.h>
-// include sys/stat.h after sys/types.h
-#include <sys/stat.h> // struct stat
-
 #include <algorithm>
 #include <cmsys/FStream.hxx>
 #include <cmsys/Glob.hxx>
@@ -120,8 +118,6 @@
 #include <string.h>
 #include <utility>
 
-class cmCommand;
-
 namespace {
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -179,7 +175,8 @@
 
   this->AddDefaultGenerators();
   this->AddDefaultExtraGenerators();
-  this->AddDefaultCommands();
+  this->AddScriptingCommands();
+  this->AddProjectCommands();
 
   // Make sure we can capture the build tool output.
   cmSystemTools::EnableVSConsoleOutput();
@@ -1654,13 +1651,14 @@
   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()
@@ -2199,24 +2197,23 @@
     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");
diff --git a/Source/cmake.h b/Source/cmake.h
index 5347745..abb13ac 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -425,7 +425,8 @@
   typedef std::vector<cmExternalMakefileProjectGeneratorFactory*>
     RegisteredExtraGeneratorsVector;
   RegisteredExtraGeneratorsVector ExtraGenerators;
-  void AddDefaultCommands();
+  void AddScriptingCommands();
+  void AddProjectCommands();
   void AddDefaultGenerators();
   void AddDefaultExtraGenerators();
 
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index b8e227f..805a9f7 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,7 +12,11 @@
 #include "cmake.h"
 #include "cmcmd.h"
 
-#include <cmConfigure.h>
+#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>
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 823b38f..9e08b9c 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -258,11 +258,18 @@
                   << "\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);
diff --git a/Source/kwsys/.gitattributes b/Source/kwsys/.gitattributes
index a121ad1..3583f39 100644
--- a/Source/kwsys/.gitattributes
+++ b/Source/kwsys/.gitattributes
@@ -1,12 +1,15 @@
 .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              our-c-style
+*.c.in           our-c-style
+*.cxx            our-c-style
+*.h              our-c-style
+*.h.in           our-c-style
+*.hxx            our-c-style
+*.hxx.in         our-c-style
 
+*.cmake          whitespace=tab-in-indent
 *.rst            whitespace=tab-in-indent conflict-marker-size=79
+*.txt            whitespace=tab-in-indent
+
+* -format.clang-format
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index d4fe8a7..de68118 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -946,7 +946,7 @@
         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
diff --git a/Source/kwsys/ConsoleBuf.hxx.in b/Source/kwsys/ConsoleBuf.hxx.in
index cb58865..32e680c 100644
--- a/Source/kwsys/ConsoleBuf.hxx.in
+++ b/Source/kwsys/ConsoleBuf.hxx.in
@@ -25,8 +25,7 @@
 #if defined(_WIN32)
 
 template <class CharT, class Traits = std::char_traits<CharT> >
-class @KWSYS_NAMESPACE@_EXPORT BasicConsoleBuf
-  : public std::basic_streambuf<CharT, Traits>
+class BasicConsoleBuf : public std::basic_streambuf<CharT, Traits>
 {
 public:
   typedef typename Traits::int_type int_type;
diff --git a/Source/kwsys/Encoding.hxx.in b/Source/kwsys/Encoding.hxx.in
index 6639efd..bf93f50 100644
--- a/Source/kwsys/Encoding.hxx.in
+++ b/Source/kwsys/Encoding.hxx.in
@@ -13,7 +13,7 @@
 {
 public:
   // Container class for argc/argv.
-  class CommandLineArguments
+  class @KWSYS_NAMESPACE@_EXPORT CommandLineArguments
   {
   public:
     // On Windows, get the program command line arguments
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
index 736214f..d4bc6c9 100644
--- a/Source/kwsys/FStream.hxx.in
+++ b/Source/kwsys/FStream.hxx.in
@@ -170,8 +170,6 @@
 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 @@
 
   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@_FStream_NOEXCEPT { close(); }
@@ -269,7 +269,7 @@
 // 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);
+@KWSYS_NAMESPACE@_EXPORT BOM ReadBOM(std::istream& in);
 }
 }
 
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index e01dcd7..93312e9 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 @@
     bool SupportsMP;
     bool HasMMXPlus;
     bool HasSSEMMX;
-    bool SupportsHyperthreading;
     unsigned int LogicalProcessorsPerPhysical;
     int APIC_ID;
     CPUPowerManagement PowerManagement;
@@ -463,10 +467,9 @@
   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 @@
   std::string OSRelease;
   std::string OSVersion;
   std::string OSPlatform;
+  bool OSIs64Bit;
 };
 
 SystemInformation::SystemInformation()
@@ -1496,6 +1500,7 @@
   this->OSRelease = "";
   this->OSVersion = "";
   this->OSPlatform = "";
+  this->OSIs64Bit = (sizeof(void*) == 8);
 }
 
 SystemInformationImplementation::~SystemInformationImplementation()
@@ -1542,7 +1547,7 @@
     RetrieveProcessorSerialNumber();
   }
 
-  this->CPUCount();
+  this->CPUCountWindows();
 
 #elif defined(__APPLE__)
   this->ParseSysCtl();
@@ -2090,16 +2095,10 @@
 
   // 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;
+    bool SupportsSMT =
+      ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: SMT --> Bit 28
 
-    if ((this->Features.ExtendedFeatures.SupportsHyperthreading) &&
-        (this->Features.HasAPIC)) {
+    if ((SupportsSMT) && (this->Features.HasAPIC)) {
       // Retrieve APIC information if there is one present.
       this->Features.ExtendedFeatures.APIC_ID =
         ((cpuinfo[1] & 0xFF000000) >> 24);
@@ -3401,7 +3400,7 @@
   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) {
     this->NumberOfLogicalCPU++;
@@ -3409,30 +3408,25 @@
   }
 
 #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) {
     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 +3441,7 @@
   if (this->NumberOfPhysicalCPU <= 0) {
     this->NumberOfPhysicalCPU = 1;
   }
-  // LogicalProcessorsPerPhysical>1 => hyperthreading.
+  // LogicalProcessorsPerPhysical>1 => SMT.
   this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
     this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU;
 
@@ -4322,68 +4316,10 @@
   (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 +4328,7 @@
   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 +4338,46 @@
 }
 
 /** 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;
-
+  std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> ProcInfo;
   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;
-
-            if (LOG_ID != 0) {
-              HT_Enabled = 1;
-            }
-          }
-        }
-        dwAffinityMask = dwAffinityMask << 1;
-      }
-      // Reset the processor affinity
-      SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity);
-
-      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;
-        }
-      }
-    }
-  } else {
-    // Processors do not have Hyper-Threading technology
-    StatusFlag = HT_NOT_CAPABLE;
-    this->NumberOfLogicalCPU = 1;
+  {
+    DWORD Length = 0;
+    DWORD rc = GetLogicalProcessorInformation(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 = GetLogicalProcessorInformation(&ProcInfo[0], &Length);
+    assert(rc != FALSE);
+    (void)rc; // Silence unused variable warning in Borland C++ 5.81
   }
-  return StatusFlag;
+
+  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;
+    }
+
+    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;
+    }
+    this->NumberOfPhysicalCPU++;
+    this->NumberOfLogicalCPU += (unsigned int)count;
+    this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = count;
+  }
+  this->NumberOfPhysicalCPU = std::max(1u, this->NumberOfPhysicalCPU);
+  this->NumberOfLogicalCPU = std::max(1u, this->NumberOfLogicalCPU);
 #else
-  return 0;
 #endif
 }
 
@@ -4559,8 +4439,14 @@
   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);
@@ -5436,10 +5322,20 @@
   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 +5346,12 @@
     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 +5405,6 @@
 /** 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..54e7fc1 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -65,9 +65,10 @@
   // 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..65b7b26 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -3067,6 +3067,28 @@
 #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 +3331,7 @@
   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.
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index f3d06fe..7a5256b 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -654,6 +654,11 @@
   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/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 @@
   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 @@
   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/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-&gt;'%(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.UndefinePreprocessorDefinitions)" ErrorReportingFormat="%(NASM.ErrorReportingFormat)" TreatWarningsAsErrors="%(NASM.TreatWarningsAsErrors)" floatunderflow="%(NASM.floatunderflow)" macrodefaults="%(NASM.macrodefaults)" user="%(NASM.user)" floatoverflow="%(NASM.floatoverflow)" floatdenorm="%(NASM.floatdenorm)" numberoverflow="%(NASM.numberoverflow)" macroselfref="%(NASM.macroselfref)" floattoolong="%(NASM.floattoolong)" orphanlabels="%(NASM.orphanlabels)" CommandLineTemplate="%(NASM.CommandLineTemplate)" AdditionalOptions="%(NASM.AdditionalOptions)"/>
+  </Target>
+  <Target Name="ComputeNASMOutput" Condition="'@(NASM)' != ''">
+    <ItemGroup>
+      <Link Include="@(NASM-&gt;Metadata('OutputFormat')-&gt;Distinct()-&gt;ClearMetadata())" Condition="'%(NASM.ExcludedFromBuild)' != 'true'"/>
+      <Lib Include="@(NASM-&gt;Metadata('OutputFormat')-&gt;Distinct()-&gt;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 &quot;[value]&quot;"/>
+    <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 &quot;[value]&quot;"/>
+    <StringListProperty Name="IncludePaths" Category="General" DisplayName="Include Paths" Description="Sets path for include file.     (-I[path])" HelpUrl="http://www.nasm.us/doc/" Switch="-I&quot;[value]&quot;"/>
+    <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/Tests/CMakeLib/testEncoding.cxx b/Tests/CMakeLib/testEncoding.cxx
index 88743b0..403c896 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>
 
+#ifdef _WIN32
 #include <cmsys/ConsoleBuf.hxx>
+#endif
 
 #ifdef _WIN32
 void setEncoding(cmsys::ConsoleBuf::Manager& buf, UINT codepage)
@@ -37,7 +39,7 @@
     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/CMakeLists.txt b/Tests/CMakeLists.txt
index 4945b31..910ff39 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -2043,7 +2043,8 @@
     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 +2135,10 @@
     endif()
   endif()
 
+  if(CMAKE_GENERATOR MATCHES "Visual Studio ([^789]|[789][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}
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 @@
 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 @@
 
 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 @@
   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 @@
   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/CMakeOnly/find_library/lib/A/libXYZ/libtest2.a b/Tests/CMakeOnly/find_library/lib/A/libXYZ/libtest2.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/lib/A/libXYZ/libtest2.a
diff --git a/Tests/CMakeOnly/find_library/lib/A/libx32/libtest3.a b/Tests/CMakeOnly/find_library/lib/A/libx32/libtest3.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/lib/A/libx32/libtest3.a
diff --git a/Tests/CMakeOnly/find_library/lib/XYZ/libtest1.a b/Tests/CMakeOnly/find_library/lib/XYZ/libtest1.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/lib/XYZ/libtest1.a
diff --git a/Tests/CMakeOnly/find_library/lib/x32/libtest2.a b/Tests/CMakeOnly/find_library/lib/x32/libtest2.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/lib/x32/libtest2.a
diff --git a/Tests/CMakeOnly/find_library/libXYZ/A/lib/libtest4.a b/Tests/CMakeOnly/find_library/libXYZ/A/lib/libtest4.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/libXYZ/A/lib/libtest4.a
diff --git a/Tests/CMakeOnly/find_library/libXYZ/A/libXYZ/libtest5.a b/Tests/CMakeOnly/find_library/libXYZ/A/libXYZ/libtest5.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/libXYZ/A/libXYZ/libtest5.a
diff --git a/Tests/CMakeOnly/find_library/libXYZ/A/libtest6.a b/Tests/CMakeOnly/find_library/libXYZ/A/libtest6.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/libXYZ/A/libtest6.a
diff --git a/Tests/CMakeOnly/find_library/libXYZ/libtest7.a b/Tests/CMakeOnly/find_library/libXYZ/libtest7.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/libXYZ/libtest7.a
diff --git a/Tests/CMakeOnly/find_library/libx32/A/lib/libtest2.a b/Tests/CMakeOnly/find_library/libx32/A/lib/libtest2.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/libx32/A/lib/libtest2.a
diff --git a/Tests/CMakeOnly/find_library/libx32/A/libtest1.a b/Tests/CMakeOnly/find_library/libx32/A/libtest1.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/libx32/A/libtest1.a
diff --git a/Tests/CMakeOnly/find_library/libx32/A/libx32/libtest1.a b/Tests/CMakeOnly/find_library/libx32/A/libx32/libtest1.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/libx32/A/libx32/libtest1.a
diff --git a/Tests/CMakeOnly/find_library/libx32/libtest1.a b/Tests/CMakeOnly/find_library/libx32/libtest1.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/CMakeOnly/find_library/libx32/libtest1.a
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 @@
 
 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_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 @@
 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/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_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 @@
   )
 
 # 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/CheckFortran.cmake b/Tests/CheckFortran.cmake
index 93990ad..b1652ba 100644
--- a/Tests/CheckFortran.cmake
+++ b/Tests/CheckFortran.cmake
@@ -18,6 +18,8 @@
   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/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 @@
 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..f677868 100644
--- a/Tests/Cuda/Complex/dynamic.cu
+++ b/Tests/Cuda/Complex/dynamic.cu
@@ -20,11 +20,50 @@
 {
 }
 
+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 >= 4) {
+      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;
-  file3_kernel<<<1, 1>>>(r, x);
-  cudaError_t err = cudaGetLastError();
-  if (err == cudaSuccess) {
-    std::cerr << cudaGetErrorString(err) << std::endl;
+  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;
   }
-  return r.sum;
+
+  file3_kernel<<<1, 1>>>(r, x);
+  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 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 @@
 
 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 @@
 {
   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_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 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/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
index d134b96..420d7a9 100644
--- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
+++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
@@ -12,22 +12,22 @@
 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)
 
 #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( CUDASerarateLibA
-                       CUDASerarateLibB
+set_target_properties( CUDASeparateLibA
+                       CUDASeparateLibB
                        PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
 
-set_target_properties( CUDASerarateLibA
-                       CUDASerarateLibB
+set_target_properties( CUDASeparateLibA
+                       CUDASeparateLibB
                        PROPERTIES POSITION_INDEPENDENT_CODE ON)
diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt
index 2646d29..38f2a44 100644
--- a/Tests/CudaOnly/WithDefs/CMakeLists.txt
+++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt
@@ -16,8 +16,15 @@
 #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
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/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 @@
 )
 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/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 @@
 # 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 @@
 # 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 @@
 #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/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt
index 4b90ad8..101b396 100644
--- a/Tests/QtAutogen/CMakeLists.txt
+++ b/Tests/QtAutogen/CMakeLists.txt
@@ -46,26 +46,26 @@
 
 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 @@
 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 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 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 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}" NO_DEFAULT_PATH)
+  find_library(plBFile "PlugB" PATHS "${mocPlugBinDir}" NO_DEFAULT_PATH)
+  find_library(plCFile "PlugC" PATHS "${mocPlugBinDir}" NO_DEFAULT_PATH)
+  find_library(plDFile "PlugD" PATHS "${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/mocDepends/CMakeLists.txt b/Tests/QtAutogen/mocDepends/CMakeLists.txt
new file mode 100644
index 0000000..8bd72eb
--- /dev/null
+++ b/Tests/QtAutogen/mocDepends/CMakeLists.txt
@@ -0,0 +1,45 @@
+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)
+
+# -- 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)
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..4843c21
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.8)
+
+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..69ea8d7
--- /dev/null
+++ b/Tests/QtAutogen/mocRerun/CMakeLists.txt
@@ -0,0 +1,34 @@
+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
+  )
+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/autorcc_depends/res1.qrc.in b/Tests/QtAutogen/rccDepends/res1a.qrc.in
similarity index 66%
rename from Tests/QtAutogen/autorcc_depends/res1.qrc.in
rename to Tests/QtAutogen/rccDepends/res1a.qrc.in
index 2a5417b..d111ffb 100644
--- a/Tests/QtAutogen/autorcc_depends/res1.qrc.in
+++ b/Tests/QtAutogen/rccDepends/res1a.qrc.in
@@ -1,5 +1,5 @@
 <RCC>
-    <qresource prefix="/">
+    <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 @@
 )
 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/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 @@
   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 @@
 // test regular C
 int bar();
 int objlib();
+void justnop();
 }
 
 // test c++ functions
@@ -42,5 +43,8 @@
   bar();
   objlib();
   printf("\n");
+#ifdef HAS_JUSTNOP
+  justnop();
+#endif
   return 0;
 }
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/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index a16efb3..e2dc128 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -104,6 +104,9 @@
 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()
 
 # The test for Policy 65 requires the use of the
 # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
@@ -199,6 +202,7 @@
 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_upload)
 add_RunCMake_test(ctest_fixtures)
 add_RunCMake_test(file)
@@ -290,7 +294,8 @@
 
 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)
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index 65399db..8ca7126 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -21,6 +21,7 @@
 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(USER_FILELIST "RPM" false "MONOLITHIC")
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(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 @@
 
 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@-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/CheckIPOSupported/CMakeLists.txt b/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt
new file mode 100644
index 0000000..a0effc9
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/CMakeLists.txt
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.0)
+project(${RunCMake_TEST} NONE)
+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..e304c61
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/RunCMakeTest.cmake
@@ -0,0 +1,9 @@
+include(RunCMake)
+
+run_cmake(unparsed-arguments)
+run_cmake(user-lang-unknown)
+run_cmake(user-lang-fortran)
+run_cmake(default-lang-none)
+run_cmake(not-supported-by-cmake)
+run_cmake(not-supported-by-compiler)
+run_cmake(save-to-result)
diff --git a/Tests/RunCMake/CheckIPOSupported/default-lang-none-result.txt b/Tests/RunCMake/CheckIPOSupported/default-lang-none-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/default-lang-none-result.txt
@@ -0,0 +1 @@
+1
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/CheckIPOSupported/not-supported-by-cmake-result.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-result.txt
@@ -0,0 +1 @@
+1
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..f63f30f
--- /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 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..6f61f7e
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake
@@ -0,0 +1,3 @@
+project(${RunCMake_TEST} LANGUAGES C)
+set(_CMAKE_IPO_SUPPORTED_BY_CMAKE NO)
+check_ipo_supported()
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-result.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-result.txt
@@ -0,0 +1 @@
+1
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..73e2f26
--- /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 \(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..652cfd5
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake
@@ -0,0 +1,4 @@
+project(${RunCMake_TEST} LANGUAGES C)
+set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES)
+set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+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/CheckIPOSupported/unparsed-arguments-result.txt b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/unparsed-arguments-result.txt
@@ -0,0 +1 @@
+1
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/CheckIPOSupported/user-lang-fortran-result.txt b/Tests/RunCMake/CheckIPOSupported/user-lang-fortran-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/user-lang-fortran-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CheckIPOSupported/user-lang-fortran-stderr.txt b/Tests/RunCMake/CheckIPOSupported/user-lang-fortran-stderr.txt
new file mode 100644
index 0000000..2cb595d
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/user-lang-fortran-stderr.txt
@@ -0,0 +1,6 @@
+^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
+  IPO is not supported \(Fortran is not supported\)\.
+Call Stack \(most recent call first\):
+  .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\)
+  user-lang-fortran\.cmake:[0-9]+ \(check_ipo_supported\)
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CheckIPOSupported/user-lang-fortran.cmake b/Tests/RunCMake/CheckIPOSupported/user-lang-fortran.cmake
new file mode 100644
index 0000000..275dbd9
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/user-lang-fortran.cmake
@@ -0,0 +1 @@
+check_ipo_supported(LANGUAGES "Fortran")
diff --git a/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-result.txt b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CheckIPOSupported/user-lang-unknown-result.txt
@@ -0,0 +1 @@
+1
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/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 0c4f71c..b213ee2 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})
@@ -301,3 +303,14 @@
     )
 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/CommandLine/reject_fifo-result.txt b/Tests/RunCMake/CommandLine/reject_fifo-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/reject_fifo-result.txt
@@ -0,0 +1 @@
+1
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/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(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/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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
   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/FindPkgConfig/pc-bar/libx32/pkgconfig/.placeholder b/Tests/RunCMake/FindPkgConfig/pc-bar/libx32/pkgconfig/.placeholder
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FindPkgConfig/pc-bar/libx32/pkgconfig/.placeholder
diff --git a/Tests/RunCMake/FindPkgConfig/pc-foo/libx32/pkgconfig/.placeholder b/Tests/RunCMake/FindPkgConfig/pc-foo/libx32/pkgconfig/.placeholder
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/FindPkgConfig/pc-foo/libx32/pkgconfig/.placeholder
diff --git a/Tests/RunCMake/Framework/FrameworkLayout.cmake b/Tests/RunCMake/Framework/FrameworkLayout.cmake
index ae32134..dcfbd2d 100644
--- a/Tests/RunCMake/Framework/FrameworkLayout.cmake
+++ b/Tests/RunCMake/Framework/FrameworkLayout.cmake
@@ -4,11 +4,17 @@
 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>)
diff --git a/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake b/Tests/RunCMake/Framework/OSXFrameworkLayout-build-check.cmake
index da1ccb4..1a543d8 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")
 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 @@
   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/deepresource.txt b/Tests/RunCMake/Framework/deepresource.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/Framework/deepresource.txt
diff --git a/Tests/RunCMake/Framework/flatresource.txt b/Tests/RunCMake/Framework/flatresource.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/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..e068a3a 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")
 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 @@
   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/Framework/some.txt b/Tests/RunCMake/Framework/some.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/Framework/some.txt
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 @@
   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/GeneratorToolset/BadToolsetFormat-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt
@@ -0,0 +1 @@
+1
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 @@
 
     .*
 
-  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/GeneratorToolset/BadToolsetHostArchTwice-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt
@@ -0,0 +1 @@
+1
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/GeneratorToolset/BadToolsetHostArchXcode-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt
new file mode 100644
index 0000000..5737e95
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+  Generator
+
+    .*
+
+  does not recognize the toolset
+
+    Test Toolset,host=x6[45]
+
+  that was specified\.$
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..f6449f2 100644
--- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
@@ -3,9 +3,15 @@
 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 @@
     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" AND NOT XCODE_BELOW_3)
+  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)
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/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/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
index 42973f8..e932693 100644
--- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
@@ -16,3 +16,28 @@
 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/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..9e2fe7a 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -101,7 +101,7 @@
   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/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 57047fb..78657ef 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -20,6 +20,7 @@
    \* CMP0060
    \* CMP0063
    \* CMP0065
+   \* CMP0068
 
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
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 @@
   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/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)
+@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..ee0dc51
--- /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 are disabled and did not run:
+.*2 \- CleanupTest
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..e2c9f92
--- /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 are disabled and did not run:
+.*3 \- DisabledFailingTest
++
+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..d8bf966
--- /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 are disabled and did not run:
+.*2 \- DisabledTest
++
+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..886efb8
--- /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 are disabled and did not run:
+.*2 \- DisabledTest
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..dc27950
--- /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 are disabled and did not run:
+.*2 \- DisabledTest
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..d8bf966
--- /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 are disabled and did not run:
+.*2 \- DisabledTest
++
+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@-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/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/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/file/READ_ELF-result.txt b/Tests/RunCMake/file/READ_ELF-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/READ_ELF-result.txt
@@ -0,0 +1 @@
+1
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..63cbdd9 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -25,6 +25,7 @@
 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 +36,5 @@
 
 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/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 @@
 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/if/duplicate-deep-else-result.txt b/Tests/RunCMake/if/duplicate-deep-else-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/if/duplicate-deep-else-result.txt
@@ -0,0 +1 @@
+1
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/if/duplicate-else-after-elseif-result.txt b/Tests/RunCMake/if/duplicate-else-after-elseif-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/if/duplicate-else-after-elseif-result.txt
@@ -0,0 +1 @@
+1
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/if/duplicate-else-result.txt b/Tests/RunCMake/if/duplicate-else-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/if/duplicate-else-result.txt
@@ -0,0 +1 @@
+1
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/if/misplaced-elseif-result.txt b/Tests/RunCMake/if/misplaced-elseif-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/if/misplaced-elseif-result.txt
@@ -0,0 +1 @@
+1
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/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/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(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/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/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@cmake.org:stage/cmake.git
+	url = https://gitlab.kitware.com/utils/gitsetup.git
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 @@
   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 @@
 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/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 22d1d8a..9cff7ca 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@
 readonly ownership="Curl Upstream <curl-library@cool.haxx.se>"
 readonly subtree="Utilities/cmcurl"
 readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_51_0"
+readonly tag="curl-7_52_1"
 readonly shortlog=false
 readonly paths="
   CMake/*
diff --git a/Utilities/Scripts/update-kwsys.bash b/Utilities/Scripts/update-kwsys.bash
index 83da8a4..d5485aa 100755
--- a/Utilities/Scripts/update-kwsys.bash
+++ b/Utilities/Scripts/update-kwsys.bash
@@ -15,6 +15,7 @@
 
 extract_source () {
     git_archive
+    disable_custom_gitattributes
 }
 
 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 ownership="LibArchive Upstream <libarchive-discuss@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 @@
         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 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/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 @@
 
 primary_domain = 'cmake'
 
-exclude_patterns = []
+exclude_patterns = [
+    'dev', # ignore developer-only documentation
+    ]
 
 extensions = ['cmake']
 templates_path = ['@conf_path@/templates']
@@ -52,6 +54,26 @@
 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/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 @@
 
 
 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/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 262554d..6a34e8d 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -316,7 +316,7 @@
 
 # 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)
 
@@ -801,7 +801,11 @@
 
 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)
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index aa1034b..daca8d1 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -143,7 +143,7 @@
   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 */
@@ -270,7 +270,7 @@
   unsigned int flags;
 
   /* used internally */
-  char * b_data;
+  char *b_data;
   size_t b_size;
   size_t b_used;
 };
@@ -640,6 +640,7 @@
                            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 +1207,8 @@
   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
@@ -1704,6 +1706,70 @@
    * 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),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
@@ -1805,6 +1871,7 @@
   CURL_SSLVERSION_TLSv1_0,
   CURL_SSLVERSION_TLSv1_1,
   CURL_SSLVERSION_TLSv1_2,
+  CURL_SSLVERSION_TLSv1_3,
 
   CURL_SSLVERSION_LAST /* never use, keep last */
 };
@@ -1839,7 +1906,10 @@
 
 
 /* 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);
 
@@ -2209,9 +2279,12 @@
   CURLINFO_ACTIVESOCKET     = CURLINFO_SOCKET + 44,
   CURLINFO_TLS_SSL_PTR      = CURLINFO_SLIST  + 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
@@ -2372,6 +2445,7 @@
 #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/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 2415d1a..3967ad2 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -30,13 +30,13 @@
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.51.0"
+#define LIBCURL_VERSION "7.52.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 52
+#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,7 +57,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
 */
-#define LIBCURL_VERSION_NUM 0x073300
+#define LIBCURL_VERSION_NUM 0x073401
 
 /*
  * This is the date and time when the full source package was created. The
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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -58,7 +58,7 @@
  * 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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,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/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 6ec8bcf..4eb896e 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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -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 @@
 /* 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 *))                                        \
@@ -151,7 +151,7 @@
   "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 +182,25 @@
               "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")
 
 /* groups of curl_easy_setops options that take the same type of argument */
 
@@ -363,7 +364,7 @@
 
 /* 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 */
@@ -455,12 +456,12 @@
    _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)                                               \
@@ -473,14 +474,14 @@
    _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_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*);
+                                       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*);
+                                       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)                                         \
@@ -490,10 +491,10 @@
    _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)                                       \
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 @@
   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 @@
   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..c038c2a 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -169,7 +169,7 @@
   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 @@
 /*
  * 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);
 
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 7cce01a..26a15b1 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -155,8 +155,8 @@
   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_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 @@
 /* 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 @@
  * 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 @@
 /*
  * 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 @@
 /*
  * 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 @@
  *
  * 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 @@
   }
   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;
 
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index 01b1b44..d8ef9a5 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -132,8 +132,10 @@
 {
   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
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index 3df34d9..524d885 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -179,12 +179,12 @@
  *
  * @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 @@
   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 @@
 {
   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 @@
       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 @@
 {
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_OK;
-  long allow;
+  time_t allow;
   int error = 0;
   struct timeval now;
   int rc;
@@ -843,7 +845,7 @@
   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 +855,10 @@
         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
@@ -1153,7 +1157,7 @@
   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 */
@@ -1243,24 +1247,6 @@
       /* 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 +1255,33 @@
 }
 
 /*
+ * 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!
@@ -1391,3 +1404,16 @@
                                    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..5653cb4 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -35,9 +35,9 @@
 
 /* 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 @@
 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.
@@ -137,4 +142,6 @@
 #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..5385058 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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -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 @@
 {
   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;
 }
@@ -327,14 +327,14 @@
    * 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 +371,15 @@
   {
     /* 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..092a226 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -146,12 +146,12 @@
  * 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 */
@@ -798,8 +798,8 @@
   /* 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);
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 35eb2dd..61cdadd 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -146,7 +146,8 @@
     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 +164,8 @@
     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 +173,8 @@
     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 +289,24 @@
     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 +331,7 @@
 
     /* 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 */
 
@@ -475,8 +481,9 @@
 /**
  * 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, int *longpath)
 {
   Curl_addrinfo *ai;
   struct sockaddr_un *sa_un;
@@ -485,8 +492,10 @@
   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);
+    *longpath = FALSE;
     return NULL;
   }
   /* sun_path must be able to store the NUL-terminated path */
@@ -494,6 +503,7 @@
   if(path_len >= sizeof(sa_un->sun_path)) {
     free(ai->ai_addr);
     free(ai);
+    *longpath = TRUE;
     return NULL;
   }
 
@@ -576,7 +586,7 @@
   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..4f24730 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.h
+++ b/Utilities/cmcurl/lib/curl_addrinfo.h
@@ -80,7 +80,7 @@
 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, int *longpath);
 #endif
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c
index 76deca6..c2d21de 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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -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,7 +56,7 @@
  *
  * 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);
@@ -77,7 +77,7 @@
  * Returns the integer.
  */
 #if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_le(unsigned char *buf)
+unsigned long long Curl_read64_le(const unsigned char *buf)
 {
   return ((unsigned long long)buf[0]) |
          ((unsigned long long)buf[1] << 8) |
@@ -89,7 +89,7 @@
          ((unsigned long long)buf[7] << 56);
 }
 #else
-unsigned __int64 Curl_read64_le(unsigned char *buf)
+unsigned __int64 Curl_read64_le(const unsigned char *buf)
 {
   return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) |
          ((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) |
@@ -113,7 +113,7 @@
  *
  * 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]));
@@ -132,7 +132,7 @@
  *
  * Returns the integer.
  */
-unsigned int Curl_read32_be(unsigned char *buf)
+unsigned int Curl_read32_be(const unsigned char *buf)
 {
   return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) |
          ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]);
@@ -153,7 +153,7 @@
  * Returns the integer.
  */
 #if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_be(unsigned char *buf)
+unsigned long long Curl_read64_be(const unsigned char *buf)
 {
   return ((unsigned long long)buf[0] << 56) |
          ((unsigned long long)buf[1] << 48) |
@@ -165,7 +165,7 @@
          ((unsigned long long)buf[7]);
 }
 #else
-unsigned __int64 Curl_read64_be(unsigned char *buf)
+unsigned __int64 Curl_read64_be(const unsigned char *buf)
 {
   return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) |
          ((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) |
diff --git a/Utilities/cmcurl/lib/curl_endian.h b/Utilities/cmcurl/lib/curl_endian.h
index df8398c..8a2b07a 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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,32 +23,32 @@
  ***************************************************************************/
 
 /* 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);
+unsigned int Curl_read32_le(const 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);
+unsigned long long Curl_read64_le(const unsigned char *buf);
 #else
-unsigned __int64 Curl_read64_le(unsigned char *buf);
+unsigned __int64 Curl_read64_le(const unsigned char *buf);
 #endif
 #endif
 
 /* Converts a 16-bit integer from big endian */
-unsigned short Curl_read16_be(unsigned char *buf);
+unsigned short Curl_read16_be(const unsigned char *buf);
 
 /* Converts a 32-bit integer from big endian */
-unsigned int Curl_read32_be(unsigned char *buf);
+unsigned int Curl_read32_be(const 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);
+unsigned long long Curl_read64_be(const unsigned char *buf);
 #else
-unsigned __int64 Curl_read64_be(unsigned char *buf);
+unsigned __int64 Curl_read64_be(const unsigned char *buf);
 #endif
 #endif
 
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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -48,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 @@
 
 #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 @@
     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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,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 @@
 /* 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_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index 812a073..73d983c 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -566,7 +566,7 @@
     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_MBEDTLS)
     mbedtls_md4(pw, 2 * len, ntbuffer);
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index afdea16..6a90e62 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.c
@@ -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 @@
   }
   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 @@
       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 @@
 
   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_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 6b86962..807f5de 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -262,10 +262,13 @@
   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 @@
 
       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,6 +411,9 @@
   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;
@@ -542,8 +548,8 @@
     /* 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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,8 +30,8 @@
   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 @@
 #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..c861e97 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -482,8 +482,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      "/"
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 @@
   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 @@
 
 #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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -50,7 +50,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/easy.c b/Utilities/cmcurl/lib/easy.c
index eee1061..1242369 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -927,6 +927,8 @@
 
   Curl_convert_setup(outcurl);
 
+  Curl_initinfo(outcurl);
+
   outcurl->magic = CURLEASY_MAGIC_NUMBER;
 
   /* we reach this point and thus we are OK */
diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c
index 6657007..9c811b8 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,11 +110,9 @@
       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;
         }
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index 272289e..3dbc0f2 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -313,7 +313,7 @@
   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
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index 785f1a6..abd2da0 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -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"
@@ -80,7 +81,7 @@
             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,
@@ -315,7 +316,7 @@
         break;
     }
 
-    switch (option) {
+    switch(option) {
     case CURLFORM_ARRAY:
       if(array_state)
         /* we don't support an array from within an array */
@@ -547,9 +548,9 @@
       {
         /* 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;
@@ -761,8 +762,8 @@
  * 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 +792,8 @@
  *  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 +949,8 @@
     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 +1031,8 @@
     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
@@ -1166,7 +1167,7 @@
   curl_off_t size = 0; /* support potentially ENORMOUS formposts */
   char *boundary;
   char *fileboundary = NULL;
-  struct curl_slist* curList;
+  struct curl_slist *curList;
 
   *finalform = NULL; /* default form is empty */
 
@@ -1373,8 +1374,8 @@
       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)
@@ -1426,13 +1427,14 @@
    *
    */
 # 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:
@@ -1569,8 +1571,12 @@
 {
   /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
      combinations */
-  return aprintf("------------------------%08x%08x",
-                 Curl_rand(data), Curl_rand(data));
+  unsigned int rnd[2];
+  CURLcode result = Curl_rand(data, &rnd[0], 2);
+  if(result)
+    return NULL;
+
+  return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
 }
 
 #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 @@
                          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..89c7e40 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -384,10 +384,10 @@
  * 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 @@
   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 @@
   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 @@
   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 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;
@@ -687,8 +687,8 @@
    * 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 +740,8 @@
        * 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);
@@ -1035,7 +1035,8 @@
     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 +1044,35 @@
       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
@@ -1850,84 +1856,6 @@
   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 +1863,7 @@
      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 +1987,9 @@
      * 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,8 +1999,7 @@
       (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);
+      failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
       return CURLE_FTP_CANT_GET_HOST;
     }
   }
@@ -2115,6 +2040,10 @@
     /* this just dumps information about this second connection */
     ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
 
+  Curl_safefree(conn->secondaryhostname);
+  conn->secondaryhostname = strdup(ftpc->newhost);
+  conn->secondary_port = ftpc->newport;
+
   Curl_resolv_unlock(data, addr); /* we're done using this address */
   conn->bits.do_more = TRUE;
   state(conn, FTP_STOP); /* this phase is completed */
@@ -2763,7 +2692,10 @@
       }
 #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 @@
         /* 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 @@
     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 */
@@ -3250,7 +3182,7 @@
   ssize_t nread;
   int ftpcode;
   CURLcode result = CURLE_OK;
-  char *path;
+  char *path = NULL;
   const char *path_to_use = data->state.path;
 
   if(!ftp)
@@ -3666,10 +3598,6 @@
     /* 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 @@
     }
   }
 
+  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 */
@@ -3940,7 +3880,7 @@
   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)
@@ -4247,8 +4187,8 @@
   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;
@@ -4568,7 +4508,7 @@
     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 @@
   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..f94b31b 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -396,9 +396,9 @@
       }
     }
 
-    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:
@@ -447,7 +447,7 @@
         }
         break;
       case PL_UNIX_FILETYPE:
-        switch (c) {
+        switch(c) {
         case '-':
           finfo->filetype = CURLFILETYPE_FILE;
           break;
@@ -967,7 +967,7 @@
         }
         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;
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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -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 @@
   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 @@
 }
 
 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 @@
   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 @@
   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 @@
     *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 @@
       break;
     }
     break;
+  case CURLINFO_PROTOCOL:
+    *param_longp = data->info.conn_protocol;
+    break;
 
   default:
     return CURLE_UNKNOWN_OPTION;
@@ -379,7 +394,7 @@
   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 @@
   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/hash.c b/Utilities/cmcurl/lib/hash.c
index 937381b..0655042 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -135,7 +135,7 @@
 {
   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;
@@ -291,9 +291,9 @@
   }
 }
 
-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;
 
diff --git a/Utilities/cmcurl/lib/hash.h b/Utilities/cmcurl/lib/hash.h
index 57a17f0..a5a6cac 100644
--- a/Utilities/cmcurl/lib/hash.h
+++ b/Utilities/cmcurl/lib/hash.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -29,16 +29,16 @@
 #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 *);
@@ -76,7 +76,7 @@
 
 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 +84,9 @@
 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 @@
 
 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 @@
 }
 
 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_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..cbd0893 100644
--- a/Utilities/cmcurl/lib/hostcheck.c
+++ b/Utilities/cmcurl/lib/hostcheck.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -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
@@ -144,4 +147,4 @@
   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..fa4bad9 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -172,7 +172,7 @@
   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;
@@ -568,7 +568,7 @@
                         const char *hostname,
                         int port,
                         struct Curl_dns_entry **entry,
-                        long timeoutms)
+                        time_t timeoutms)
 {
 #ifdef USE_ALARM_TIMEOUT
 #ifdef HAVE_SIGACTION
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index 9098ee3..1dc4079 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -87,7 +87,7 @@
                 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
 /*
@@ -131,7 +131,7 @@
 void Curl_hostcache_prune(struct Curl_easy *data);
 
 /* Return # of adresses in a Curl_addrinfo struct */
-int Curl_num_addresses (const Curl_addrinfo *addr);
+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 @@
 #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 @@
      * 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..4c1c07f 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -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"
@@ -287,8 +288,8 @@
 
   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;
@@ -544,8 +545,8 @@
     }
   }
   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,7 +642,7 @@
   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;
   }
@@ -839,9 +840,11 @@
                   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,7 +1101,9 @@
     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
@@ -1255,14 +1260,13 @@
 
     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,10 +1354,13 @@
   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(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;
@@ -1396,50 +1403,16 @@
 
   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
@@ -2092,7 +2065,7 @@
         /* 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':
@@ -2328,7 +2301,7 @@
    * 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) {
+  switch(data->state.authproxy.picked) {
   case CURLAUTH_NEGOTIATE:
   case CURLAUTH_NTLM:
   case CURLAUTH_NTLM_WB:
@@ -2782,7 +2755,7 @@
   /* 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 +2793,7 @@
   /* 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)) {
@@ -2872,8 +2845,8 @@
       /* 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 +2854,7 @@
     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;
@@ -3122,8 +3095,8 @@
        * 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;
       }
 
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index cfdb327..4cc17ba 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -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.
@@ -223,7 +229,8 @@
 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 */
@@ -841,10 +848,9 @@
             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;
       }
@@ -966,7 +972,7 @@
  */
 static nghttp2_settings_entry settings[] = {
   { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
-  { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
+  { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, HTTP2_HUGE_WINDOW_SIZE },
 };
 
 #define H2_BUFSIZE 32768
@@ -1572,6 +1578,72 @@
 #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 +1659,7 @@
   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 +1797,6 @@
   i = 3;
   while(i < nheader) {
     size_t hlen;
-    int skip = 0;
 
     hdbuf = line_end + 2;
 
@@ -1743,12 +1814,7 @@
       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 +1827,28 @@
     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 */
@@ -1961,7 +2039,8 @@
   else {
     /* 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, settings,
+                                 sizeof(settings) / sizeof(settings[0]));
     if(rv != 0) {
       failf(data, "nghttp2_submit_settings() failed: %s(%d)",
             nghttp2_strerror(rv), rv);
@@ -1969,6 +2048,16 @@
     }
   }
 
+#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 +2073,8 @@
                     " 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 +2114,82 @@
   return CURLE_OK;
 }
 
+void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
+                          bool exclusive)
+{
+  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_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 @@
 #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 @@
 
       /* 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 @@
         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 @@
 
 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 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 @@
   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 @@
      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 @@
   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 @@
   }
 
   /* 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..21c77cd 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -136,8 +136,8 @@
 
   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..e0213f3 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -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 */
@@ -68,15 +104,20 @@
     memset(&http_proxy, 0, sizeof(http_proxy));
     conn->data->req.protop = &http_proxy;
     connkeep(conn, "HTTP proxy CONNECT");
-    if(conn->bits.conn_to_host)
+    if(sockindex == SECONDARYSOCKET)
+      hostname = conn->secondaryhostname;
+    else if(conn->bits.conn_to_host)
       hostname = conn->conn_to_host.name;
     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,
+    result = Curl_proxyCONNECT(conn, sockindex, hostname,
                                remote_port, FALSE);
     conn->data->req.protop = prot_save;
     if(CURLE_OK != result)
@@ -113,7 +154,7 @@
   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
@@ -161,7 +202,7 @@
         char *host=(char *)"";
         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;
@@ -244,7 +285,7 @@
     }
 
     if(!blocking) {
-      if(0 == SOCKET_READABLE(tunnelsocket, 0))
+      if(!Curl_conn_data_pending(conn, sockindex))
         /* return so we'll be called again polling-style */
         return CURLE_OK;
       else {
@@ -263,13 +304,22 @@
       char *ptr;
       char *line_start;
 
-      ptr=data->state.buffer;
+      ptr = data->state.buffer;
       line_start = ptr;
 
-      nread=0;
-      perline=0;
+      nread = 0;
+      perline = 0;
 
-      while((nread<BUFSIZE) && (keepon && !error)) {
+      while(nread < BUFSIZE && keepon && !error) {
+        int writetype;
+
+        if(Curl_pgrsUpdate(conn))
+          return CURLE_ABORTED_BY_CALLBACK;
+
+        if(ptr >= &data->state.buffer[BUFSIZE]) {
+          failf(data, "CONNECT response too large!");
+          return CURLE_RECV_ERROR;
+        }
 
         check = Curl_timeleft(data, NULL, TRUE);
         if(check <= 0) {
@@ -278,253 +328,233 @@
           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;
+        }
+        else 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 = 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--;
+            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;
+            /* 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;
 
-            nread += gotbytes;
+            /* 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;
+        }
 
-            if(keepon > TRUE) {
-              /* This means we are currently ignoring a response-body */
+        perline++; /* amount of bytes in this line so far */
 
-              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;
-                }
+        /* 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);
+
+        /* 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);
+            }
+            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 server MUST NOT send any Transfer-Encoding or
+               Content-Length header fields in a 2xx (Successful)
+               response to CONNECT. (RFC 7231 section 4.3.6) */
+            failf(data, "Content-Length: in %03d response",
+                  k->httpcode);
+            return CURLE_RECV_ERROR;
+          }
+
+          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")) {
+          if(k->httpcode/100 == 2) {
+            /* A server MUST NOT send any Transfer-Encoding or
+               Content-Length header fields in a 2xx (Successful)
+               response to CONNECT. (RFC 7231 section 4.3.6) */
+            failf(data, "Transfer-Encoding: in %03d response", k->httpcode);
+            return CURLE_RECV_ERROR;
+          }
+          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 = data->state.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 +568,7 @@
         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;
       }
 
@@ -600,7 +629,7 @@
 
   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  */
diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h
index fd04330..d1f5a7c 100644
--- a/Utilities/cmcurl/lib/http_proxy.h
+++ b/Utilities/cmcurl/lib/http_proxy.h
@@ -32,11 +32,11 @@
 /* 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_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..d876615 100644
--- a/Utilities/cmcurl/lib/if2ip.c
+++ b/Utilities/cmcurl/lib/if2ip.c
@@ -68,7 +68,7 @@
 #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) {
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index 4aa7dcc..78dc6fa 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -107,7 +107,7 @@
                                           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.
@@ -390,10 +390,10 @@
  *
  * 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++)
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 @@
  */
 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 @@
 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 @@
   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 @@
   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..067b0a5 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -121,7 +121,7 @@
   /* 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,
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 7dbc1b0..979ce7d 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -109,9 +109,9 @@
 #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 @@
 
 #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
@@ -271,7 +271,7 @@
     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 +279,11 @@
       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 +321,10 @@
       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;
@@ -655,7 +655,7 @@
 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);
@@ -682,7 +682,7 @@
 }
 
 #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 +694,9 @@
   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 +705,7 @@
 /*
  * 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 +799,7 @@
     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 +864,7 @@
       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 +917,7 @@
 
       goto quit;
     }
-    LDAP_TRACE (("scope %d\n", ludp->lud_scope));
+    LDAP_TRACE(("scope %d\n", ludp->lud_scope));
   }
 
   p = q;
@@ -934,7 +934,7 @@
     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 +1009,7 @@
     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/md4.c b/Utilities/cmcurl/lib/md4.c
index 60f73a2..1bdc9f3 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -213,7 +213,8 @@
   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;
 
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index f818d32..f2dc16c 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -45,7 +45,7 @@
 }
 
 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_Update(MD5_CTX * ctx,
-                       const unsigned char * input,
+                       const unsigned char *input,
                        unsigned int inputLen)
 {
   gcry_md_write(*ctx, input, inputLen);
@@ -402,7 +402,8 @@
   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..15e8661 100644
--- a/Utilities/cmcurl/lib/memdebug.c
+++ b/Utilities/cmcurl/lib/memdebug.c
@@ -90,7 +90,7 @@
   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 :-( */
diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c
index 3cdd41a..4baa1cc 100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@ -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 @@
           flags |= FLAGS_ALT;
           break;
         case '.':
-          flags |= FLAGS_PREC;
           if('*' == *fmt) {
             /* The precision is picked from a specified parameter */
 
@@ -498,7 +498,7 @@
         (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;
@@ -688,7 +688,7 @@
 
     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 @@
         *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,9 @@
         /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
            output characters */
         (sprintf)(work, formatbuf, p->data.dnum);
-
+#ifdef CURLDEBUG
+        assert(strlen(work) <= sizeof(work));
+#endif
         for(fptr=work; *fptr; fptr++)
           OUTCHAR(*fptr);
       }
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 2432b15..950b600 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -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"
@@ -812,6 +813,11 @@
   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];
@@ -1300,7 +1306,7 @@
   CURLMcode rc;
   CURLcode result = CURLE_OK;
   struct SingleRequest *k;
-  long timeout_ms;
+  time_t timeout_ms;
   int control;
 
   if(!GOOD_EASY_HANDLE(data))
@@ -1548,7 +1554,9 @@
         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 +1569,14 @@
       /* 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:
@@ -2486,7 +2502,7 @@
      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 = curlx_tvdiff(*(struct timeval *)e->ptr, now);
     if(diff <= 0)
       /* remove outdated entry */
       Curl_llist_remove(list, e, NULL);
@@ -2764,7 +2780,7 @@
 
     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
@@ -2871,7 +2887,7 @@
     /* 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);
+      time_t diff = curlx_tvdiff(*checktime, *timedup);
       if(diff > 0)
         break;
       prev = e;
@@ -2898,7 +2914,7 @@
  * 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.
  */
-void Curl_expire(struct Curl_easy *data, long milli)
+void Curl_expire(struct Curl_easy *data, time_t milli)
 {
   struct Curl_multi *multi = data->multi;
   struct timeval *nowp = &data->state.expiretime;
@@ -2911,7 +2927,7 @@
     return;
 
   set = Curl_tvnow();
-  set.tv_sec += milli/1000;
+  set.tv_sec += (long)(milli/1000);
   set.tv_usec += (milli%1000)*1000;
 
   if(set.tv_usec >= 1000000) {
@@ -2923,7 +2939,7 @@
     /* 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);
     if(diff > 0) {
       /* the new expire time was later so just add it to the queue
          and get out */
@@ -2961,14 +2977,14 @@
  * time-out period to expire.
  *
  */
-void Curl_expire_latest(struct Curl_easy *data, long milli)
+void Curl_expire_latest(struct Curl_easy *data, time_t milli)
 {
   struct timeval *expire = &data->state.expiretime;
 
   struct timeval set;
 
   set = Curl_tvnow();
-  set.tv_sec += milli / 1000;
+  set.tv_sec += (long)(milli / 1000);
   set.tv_usec += (milli % 1000) * 1000;
 
   if(set.tv_usec >= 1000000) {
@@ -2980,7 +2996,7 @@
     /* 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);
+    time_t diff = curlx_tvdiff(set, *expire);
     if(diff > 0)
       /* the new expire time was later than the top time, so just skip this */
       return;
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index c56b6ae..0b78de9 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -38,7 +38,9 @@
   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 */
diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index eaff496..e5de1fc 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -25,9 +25,9 @@
 /*
  * 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);
 void Curl_expire_clear(struct Curl_easy *data);
-void Curl_expire_latest(struct Curl_easy *data, long milli);
+void Curl_expire_latest(struct Curl_easy *data, time_t milli);
 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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -117,7 +117,7 @@
     /* 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/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 @@
      */
     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 @@
           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 @@
 /* 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 @@
 #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 @@
 }
 
 /* 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..7a99357 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.c
@@ -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 @@
   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 @@
   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))
diff --git a/Utilities/cmcurl/lib/pingpong.h b/Utilities/cmcurl/lib/pingpong.h
index 2f649d5..500100a 100644
--- a/Utilities/cmcurl/lib/pingpong.h
+++ b/Utilities/cmcurl/lib/pingpong.h
@@ -88,7 +88,7 @@
 
 /* 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);
 
 
 /***********************************************************************
diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 8486519..9bb691c 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -104,7 +104,7 @@
 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.
@@ -290,10 +290,10 @@
  *
  * 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++)
@@ -1572,7 +1572,7 @@
       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..60627b2 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -249,24 +249,26 @@
                             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);
+  else
+    return 0;
 }
 
 void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
@@ -359,9 +361,7 @@
   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 @@
      (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 @@
 
     /* 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
diff --git a/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c
new file mode 100644
index 0000000..a51951c
--- /dev/null
+++ b/Utilities/cmcurl/lib/rand.c
@@ -0,0 +1,130 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * 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"
+
+#include <fcntl.h>
+
+#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) {
+      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++;
+    *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 funtion 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 int *rndptr,
+                   unsigned int num)
+{
+  CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+  unsigned int i;
+
+  assert(num > 0);
+
+  for(i = 0; i < num; i++) {
+    result = randit(data, rndptr++);
+    if(result)
+      return result;
+  }
+  return result;
+}
diff --git a/Utilities/cmcurl/lib/rand.h b/Utilities/cmcurl/lib/rand.h
new file mode 100644
index 0000000..0f89861
--- /dev/null
+++ b/Utilities/cmcurl/lib/rand.h
@@ -0,0 +1,43 @@
+#ifndef HEADER_CURL_RAND_H
+#define HEADER_CURL_RAND_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * 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 integers 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 int *rnd,
+                   unsigned int num);
+
+#endif /* HEADER_CURL_RAND_H */
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index d1bad19..65c6c3b 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -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 @@
  * 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 @@
     /* 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;
@@ -488,7 +486,7 @@
    * 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 @@
 
   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;
@@ -736,7 +734,7 @@
   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 +742,12 @@
   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;
   }
 
diff --git a/Utilities/cmcurl/lib/security.c b/Utilities/cmcurl/lib/security.c
index ff26066..4a8f444 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 @@
 
 /* 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 @@
   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 @@
 {
   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 @@
       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 */
 
@@ -411,7 +412,7 @@
 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..6bb0ab1 100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@ -145,7 +145,7 @@
 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];
diff --git a/Utilities/cmcurl/lib/select.h b/Utilities/cmcurl/lib/select.h
index 1d26f49..e247bd9 100644
--- a/Utilities/cmcurl/lib/select.h
+++ b/Utilities/cmcurl/lib/select.h
@@ -73,7 +73,7 @@
 
 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..7601697 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -122,6 +122,13 @@
 #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];
@@ -201,6 +208,12 @@
 }
 #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 */
@@ -488,7 +501,7 @@
  */
 CURLcode Curl_client_chop_write(struct connectdata *conn,
                                 int type,
-                                char * ptr,
+                                char *ptr,
                                 size_t len)
 {
   struct Curl_easy *data = conn->data;
@@ -571,7 +584,7 @@
         return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
 
       if(wrote != chunklen) {
-        failf (data, "Failed writing header");
+        failf(data, "Failed writing header");
         return CURLE_WRITE_ERROR;
       }
     }
@@ -692,7 +705,7 @@
     }
     /* 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, BUFSIZE * sizeof(char));
     buffertofill = conn->master_buffer;
   }
   else {
@@ -796,7 +809,7 @@
     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_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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -41,18 +41,18 @@
 #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_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_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 @@
 #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 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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -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;
+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;
-    }
+  /* 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);
+  unix_path = decc$translate_vms(path);
 
-    if((int)unix_path <= 0) {
-      /* We can not translate it, so return the original string */
-      return (char *)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 @@
 #   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;
-    }
-
-    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 */
-
+  /* first use the DECC getenv() function */
+  result = decc$getenv(envvar);
+  if(result == NULL) {
     return result;
+  }
+
+  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 */
+
+  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;
-    }
+  my_passwd = decc_getpwuid(uid);
+  if(my_passwd == NULL) {
+    return my_passwd;
+  }
 
-    unix_path = vms_translate_path(my_passwd->pw_dir);
+  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((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;
-    }
+  /* 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;
+  /* 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;
+  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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -54,8 +54,8 @@
   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..f197fe1 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -308,8 +308,8 @@
   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 +320,7 @@
     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;
     }
@@ -781,9 +781,9 @@
       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 +812,7 @@
       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..ff8e80d 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -103,7 +103,7 @@
 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.
@@ -278,10 +278,10 @@
  *
  * 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++)
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index 742d411..774fb20 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.c
@@ -57,7 +57,7 @@
   ssize_t nread;
   ssize_t allread = 0;
   int result;
-  long timeleft;
+  time_t timeleft;
   *n = 0;
   for(;;) {
     timeleft = Curl_timeleft(conn->data, NULL, TRUE);
@@ -109,9 +109,10 @@
                      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 @@
     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 @@
       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 @@
     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 @@
       /* 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 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 "
@@ -605,9 +615,9 @@
         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 @@
         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);
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 @@
                      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 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 @@
                                     &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 @@
                                     &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 @@
   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 @@
 
   /* 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 @@
   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 @@
   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 @@
       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..bc15d97 100644
--- a/Utilities/cmcurl/lib/speedcheck.c
+++ b/Utilities/cmcurl/lib/speedcheck.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -40,8 +40,8 @@
      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;
+    time_t howlong = Curl_tvdiff(now, data->state.keeps_speed);
+    time_t nextcheck = (data->set.low_speed_time * 1000) - howlong;
 
     /* We are now below the "low speed limit". If we are below it
        for "low speed time" seconds we consider that enough reason
diff --git a/Utilities/cmcurl/lib/ssh.c b/Utilities/cmcurl/lib/ssh.c
index 43c8283..5ed036a 100644
--- a/Utilities/cmcurl/lib/ssh.c
+++ b/Utilities/cmcurl/lib/ssh.c
@@ -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"
@@ -239,7 +239,7 @@
 
 static CURLcode sftp_libssh2_error_to_CURLE(int err)
 {
-  switch (err) {
+  switch(err) {
     case LIBSSH2_FX_OK:
       return CURLE_OK;
 
@@ -271,7 +271,7 @@
 
 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 +676,7 @@
    * 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. "
@@ -782,14 +782,14 @@
           state(conn, SSH_AUTH_DONE);
           break;
         }
-        else if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
-           LIBSSH2_ERROR_EAGAIN) {
-          rc = LIBSSH2_ERROR_EAGAIN;
-          break;
-        }
         else {
-          state(conn, SSH_SESSION_FREE);
-          sshc->actualcode = libssh2_session_error_to_CURLE(err);
+          err = libssh2_session_last_errno(sshc->ssh_session);
+          if(err == LIBSSH2_ERROR_EAGAIN)
+            rc = LIBSSH2_ERROR_EAGAIN;
+          else {
+            state(conn, SSH_SESSION_FREE);
+            sshc->actualcode = libssh2_session_error_to_CURLE(err);
+          }
           break;
         }
       }
@@ -874,7 +874,7 @@
           break;
         }
 
-        sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
+        sshc->passphrase = data->set.ssl.key_passwd;
         if(!sshc->passphrase)
           sshc->passphrase = "";
 
@@ -1987,12 +1987,14 @@
           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 +2114,10 @@
 
       /* 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);
@@ -2651,7 +2654,7 @@
         else 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
@@ -2788,13 +2791,16 @@
 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;
@@ -2860,8 +2866,8 @@
       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
 
@@ -3383,7 +3389,7 @@
 
 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..a750f7b 100644
--- a/Utilities/cmcurl/lib/strcase.c
+++ b/Utilities/cmcurl/lib/strcase.c
@@ -34,7 +34,7 @@
   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 @@
   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);
+  else
+    /* 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 @@
 
   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 @@
 curl_easy_strerror(CURLcode error)
 {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (error) {
+  switch(error) {
   case CURLE_OK:
     return "No error";
 
@@ -348,7 +348,7 @@
 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 @@
 curl_share_strerror(CURLSHcode error)
 {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (error) {
+  switch(error) {
   case CURLSHE_OK:
     return "No error";
 
@@ -435,7 +435,7 @@
   const char *p;
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (err) {
+  switch(err) {
   case WSAEINTR:
     p = "Call interrupted";
     break;
@@ -609,7 +609,7 @@
   else
     p = "error";
 #endif
-  strncpy (buf, p, len);
+  strncpy(buf, p, len);
   buf [len-1] = '\0';
   return buf;
 }
@@ -715,10 +715,12 @@
   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 @@
 
   old_errno = ERRNO;
 
-  switch (err) {
+  switch(err) {
     case SEC_E_OK:
       txt = "No error";
       break;
@@ -1035,10 +1037,12 @@
     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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -165,7 +165,7 @@
     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/telnet.c b/Utilities/cmcurl/lib/telnet.c
index c37242d..551af60 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -91,7 +91,7 @@
 
 #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
@@ -935,7 +935,7 @@
   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,12 +1004,12 @@
   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);
@@ -1020,8 +1020,8 @@
     /* 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 @@
   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 @@
     case CURL_TS_IAC:
     process_iac:
       DEBUGASSERT(startwrite < 0);
-      switch (c) {
+      switch(c) {
       case CURL_WILL:
         tn->telrcv_state = CURL_TS_WILL;
         break;
@@ -1241,7 +1241,7 @@
       struct pollfd pfd[1];
       pfd[0].fd = conn->sock[FIRSTSOCKET];
       pfd[0].events = POLLOUT;
-      switch (Curl_poll(pfd, 1, -1)) {
+      switch(Curl_poll(pfd, 1, -1)) {
         case -1:                    /* error, abort writing */
         case 0:                     /* timeout (will never happen) */
           result = CURLE_SEND_ERROR;
@@ -1489,7 +1489,8 @@
 
       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;
@@ -1576,7 +1577,7 @@
   }
 
   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;
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index deee394..f2f8347 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -199,7 +199,7 @@
 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 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;
 }
 
@@ -1356,7 +1356,7 @@
 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 +1372,7 @@
     *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..f3b207a 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -116,7 +116,7 @@
  * 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 @@
     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;
 }
 
 /*
@@ -144,7 +144,7 @@
 }
 
 /* return the number of seconds in the given input timeval struct */
-long Curl_tvlong(struct timeval t1)
+time_t Curl_tvlong(struct timeval t1)
 {
   return t1.tv_sec;
 }
diff --git a/Utilities/cmcurl/lib/timeval.h b/Utilities/cmcurl/lib/timeval.h
index 50c31a2..09f8b3a 100644
--- a/Utilities/cmcurl/lib/timeval.h
+++ b/Utilities/cmcurl/lib/timeval.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
  *
  * 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,7 +46,7 @@
  */
 double curlx_tvdiff_secs(struct timeval t1, struct timeval t2);
 
-long Curl_tvlong(struct timeval t1);
+time_t Curl_tvlong(struct timeval t1);
 
 /* These two defines below exist to provide the older API for library
    internals only. */
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index 6245ee4..750fb04 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -741,8 +741,8 @@
              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 +775,9 @@
             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;
           }
@@ -1137,7 +1137,7 @@
 
       */
 
-      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;
@@ -1296,7 +1296,7 @@
   /* 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;
 
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index b997f41..7944d7b 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -92,6 +92,7 @@
 #include "warnless.h"
 #include "non-ascii.h"
 #include "inet_pton.h"
+#include "getinfo.h"
 
 /* And now for the protocols */
 #include "ftp.h"
@@ -463,6 +464,7 @@
   /* 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 +527,9 @@
   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 +541,16 @@
    * 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->general_ssl.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,14 +573,17 @@
 
   /* 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;
 #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],
+                     (char *) CURL_CA_PATH);
 #endif
 
   set->wildcardmatch  = FALSE;
@@ -646,6 +653,8 @@
 
     Curl_convert_init(data);
 
+    Curl_initinfo(data);
+
     /* most recent connection is not yet defined */
     data->state.lastconnect = NULL;
 
@@ -694,7 +703,12 @@
     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 +914,18 @@
      * implementations are lame.
      */
 #ifdef USE_SSL
-    data->set.ssl.version = va_arg(param, long);
+    data->set.ssl.primary.version = va_arg(param, long);
+#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
+    data->set.proxy_ssl.primary.version = va_arg(param, long);
 #else
     result = CURLE_UNKNOWN_OPTION;
 #endif
@@ -1007,7 +1032,7 @@
           (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 +1459,30 @@
 
   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 +1494,7 @@
     /*
      * 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 +1947,70 @@
     /*
      * 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:
@@ -2001,7 +2073,15 @@
     /*
      * 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 +2099,25 @@
       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 +2128,8 @@
       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 +2175,19 @@
      * 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 +2197,15 @@
     /*
      * 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 +2215,16 @@
      * 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 *));
+    break;
+  case CURLOPT_PROXY_CAPATH:
+    /*
+     * 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 +2235,15 @@
      * 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 +2251,7 @@
      * 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:
@@ -2196,7 +2332,7 @@
       }
 #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 +2367,14 @@
 
   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 +2470,8 @@
     break;
 
   case CURLOPT_SSL_SESSIONID_CACHE:
-    data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.general_ssl.sessionid = (0 != va_arg(param, long)) ?
+                                      TRUE : FALSE;
     break;
 
 #ifdef USE_LIBSSH2
@@ -2595,23 +2738,43 @@
     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_TLSAUTH_PASSWORD:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
+  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] && !data->set.ssl.authtype)
+    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_ORIG],
+                       va_arg(param, char *));
+    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")))
       data->set.ssl.authtype = CURL_TLSAUTH_SRP;
     else
       data->set.ssl.authtype = CURL_TLSAUTH_NONE;
     break;
+  case CURLOPT_PROXY_TLSAUTH_TYPE:
+    if(strncasecompare((char *)va_arg(param, char *), "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 *));
@@ -2678,9 +2841,11 @@
     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
@@ -2718,10 +2883,10 @@
 #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);
   }
 }
 
@@ -2768,8 +2933,10 @@
   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,7 +2950,9 @@
   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);
 
   conn_reset_all_postponed_data(conn);
@@ -2795,7 +2964,12 @@
   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 */
 }
@@ -2856,6 +3030,8 @@
   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);
 
@@ -3014,8 +3190,8 @@
   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;
@@ -3052,6 +3228,21 @@
   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) &&
+     Curl_safe_strcasecompare(data->user, needle->user) &&
+     Curl_safe_strcasecompare(data->passwd, needle->passwd))
+    return TRUE;
+
+  return FALSE;
+}
+
+
 /*
  * This function finds the connection in the connection
  * bundle that has been unused for the longest time.
@@ -3064,8 +3255,8 @@
                                       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;
@@ -3147,7 +3338,7 @@
 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,
@@ -3326,6 +3517,17 @@
         }
       }
 
+#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;
+      }
+      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 +3536,12 @@
           /* 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,6 +3554,33 @@
          * connections that don't use this feature */
         continue;
 
+      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(!canPipeline && check->inuse)
         /* this request can't be pipelined but the checked connection is
            already in use so we skip it */
@@ -3382,9 +3600,8 @@
         */
         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 +3616,11 @@
       }
 
       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)) &&
@@ -3463,12 +3681,13 @@
 
         /* 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) {
@@ -3572,51 +3791,48 @@
    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);
+    const char * const host = conn->bits.conn_to_host ?
+                              conn->conn_to_host.name :
+                              conn->bits.httpproxy ?
+                              conn->http_proxy.host.name :
+                              sockindex == SECONDARYSOCKET ?
+                              conn->secondaryhostname : conn->host.name;
+    const int port = conn->bits.conn_to_port ? conn->conn_to_port :
+                     conn->bits.httpproxy ?
+                     (int)conn->http_proxy.port :
+                     sockindex == SECONDARYSOCKET ?
+                      conn->secondary_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:
-    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_SOCKS4:
+    case CURLPROXY_SOCKS4A:
+      result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
+                           conn);
+      break;
 
-  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);
-
+    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 +3843,9 @@
 {
   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->host.dispname,
           conn->ip_addr_str, conn->port, conn->connection_id);
 }
 #endif
@@ -3717,10 +3935,14 @@
 
   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
@@ -3750,7 +3972,7 @@
  */
 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)
@@ -3879,12 +4101,14 @@
   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 +4119,20 @@
   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 +4141,10 @@
   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.verifypeer = data->set.ssl.primary.verifypeer;
+  conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
+  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,7 +4159,7 @@
   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(BUFSIZE, sizeof(char));
     if(!conn->master_buffer)
       goto error;
   }
@@ -4065,33 +4300,38 @@
      * 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
-
-           RFC1738 (section 3.1, page 5) says:
-
-           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.
-
-           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.
-        */
-
-        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++;
-
-        /* This cannot be made with strcpy, as the memory chunks overlap! */
-        memmove(path, ptr, strlen(ptr)+1);
+      /* 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, "Valid host name with slash missing in URL");
+        return CURLE_URL_MALFORMAT;
       }
+      ptr = &path[9]; /* now points to the slash after the host */
+
+      /* there was a host name and slash present
+
+         RFC1738 (section 3.1, page 5) says:
+
+         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.
+
+         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.
+      */
+
+      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);
     }
 
     protop = "file"; /* protocol string */
@@ -4473,7 +4713,7 @@
 * 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 +4722,7 @@
    */
   size_t tok_start;
   size_t tok_end;
-  const char* separator = ", ";
+  const char *separator = ", ";
   size_t no_proxy_len;
   size_t namelen;
   char *endptr;
@@ -4636,7 +4876,8 @@
  * 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 +4886,10 @@
   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 +4899,16 @@
   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 +4920,28 @@
   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 +4978,7 @@
   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 +5012,59 @@
     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);
+
+      if(!proxyinfo->user)
+        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("");
+
+      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 +5090,11 @@
     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;
 }
 #endif /* CURL_DISABLE_PROXY */
@@ -5180,11 +5446,16 @@
       *portptr = '\0'; /* cut off the name there */
       conn->remote_port = curlx_ultous(port);
     }
-    else
+    else {
+      if(rest[0]) {
+        failf(data, "Illegal port number");
+        return CURLE_URL_MALFORMAT;
+      }
       /* 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
@@ -5404,6 +5675,9 @@
   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,9 +5740,9 @@
 {
   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)
@@ -5487,7 +5761,7 @@
     else {
       /* no "connect to host" */
       conn->bits.conn_to_host = FALSE;
-      free(host);
+      Curl_safefree(host);
     }
 
     if(port >= 0) {
@@ -5498,6 +5772,7 @@
     else {
       /* no "connect to port" */
       conn->bits.conn_to_port = FALSE;
+      port = -1;
     }
 
     conn_to_host = conn_to_host->next;
@@ -5514,7 +5789,7 @@
                                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 +5806,36 @@
     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;
+        int longpath=0;
+        hostaddr->addr = Curl_unix2addr(path, &longpath);
+        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;
@@ -5588,8 +5867,11 @@
     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 +5881,7 @@
         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 +5901,18 @@
 static void reuse_conn(struct connectdata *old_conn,
                        struct connectdata *conn)
 {
+  free_fixed_hostname(&old_conn->http_proxy.host);
+  free_fixed_hostname(&old_conn->socks_proxy.host);
   free_fixed_hostname(&old_conn->proxy);
+
+  free(old_conn->http_proxy.host.rawalloc);
+  free(old_conn->socks_proxy.host.rawalloc);
   free(old_conn->proxy.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 +5932,18 @@
   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
@@ -5675,8 +5969,10 @@
 
   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);
@@ -5686,6 +5982,10 @@
   old_conn->recv_pipe = NULL;
 
   Curl_safefree(old_conn->master_buffer);
+
+#ifdef USE_UNIX_SOCKETS
+  Curl_safefree(old_conn->unix_domain_socket);
+#endif
 }
 
 /**
@@ -5717,6 +6017,7 @@
   char *options = NULL;
   bool reuse;
   char *proxy = NULL;
+  char *socksproxy = NULL;
   bool prot_missing = FALSE;
   bool connections_available = TRUE;
   bool force_reuse = FALSE;
@@ -5883,18 +6184,35 @@
     }
   }
 
+  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;
+    }
+  }
+
   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;
+    Curl_safefree(proxy);
+    Curl_safefree(socksproxy);
   }
-  else if(!proxy)
+  else if(!proxy && !socksproxy)
     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;
+  if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+    if(proxy) {
+      free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
+      proxy = NULL;
+    }
+    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;
+    }
   }
 #endif
 
@@ -5903,23 +6221,36 @@
                      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) {
-    result = parse_proxy(data, conn, proxy);
+  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;
+    }
 
-    free(proxy); /* parse_proxy copies the proxy string */
-    proxy = NULL;
+    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(result)
-      goto out;
-
-    if((conn->proxytype == CURLPROXY_HTTP) ||
-       (conn->proxytype == CURLPROXY_HTTP_1_0)) {
+    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;
@@ -5938,12 +6269,34 @@
       conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
       conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
     }
-    conn->bits.proxy = TRUE;
+
+    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;
   }
@@ -6079,20 +6432,51 @@
      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;
   }
@@ -6149,7 +6533,9 @@
     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
@@ -6280,6 +6666,7 @@
   free(options);
   free(passwd);
   free(user);
+  free(socksproxy);
   free(proxy);
   return result;
 }
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_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 @@
 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..0271d26 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -316,6 +316,8 @@
 #elif defined(USE_GSKIT)
   gsk_handle handle;
   int iocport;
+  int localfd;
+  int remotefd;
 #elif defined(USE_AXTLS)
   SSL_CTX* ssl_ctx;
   SSL*     ssl;
@@ -341,28 +343,38 @@
 #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 */
-
   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 */
+};
+
+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 +382,11 @@
 #endif
 };
 
+struct ssl_general_config {
+  bool sessionid; /* cache session IDs or not */
+  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 +397,7 @@
   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 */
@@ -451,7 +468,7 @@
 #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 +514,7 @@
                         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 +549,7 @@
   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 +566,9 @@
   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 {
@@ -732,7 +754,7 @@
  */
 
 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 *);
@@ -849,6 +871,14 @@
 };
 #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.
@@ -898,14 +928,20 @@
   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 +966,6 @@
 
   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 +983,9 @@
   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 +996,8 @@
   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 */
@@ -1020,7 +1054,7 @@
                                    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;
+  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 +1075,8 @@
   /* 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 +1112,6 @@
   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 +1130,17 @@
   struct connectbundle *bundle; /* The bundle we are member of */
 
   int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
+
+#ifdef USE_UNIX_SOCKETS
+  char *unix_domain_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 +1174,9 @@
   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 +1184,8 @@
 
 
 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 */
@@ -1242,6 +1280,11 @@
                    be RFC compliant */
 };
 
+struct Curl_http2_dep {
+  struct Curl_http2_dep *next;
+  struct Curl_easy *data;
+};
+
 struct UrlState {
 
   /* Points to the connection cache */
@@ -1402,8 +1445,10 @@
 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 +1458,35 @@
   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 +1514,10 @@
   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 +1581,10 @@
   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,7 +1635,10 @@
   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 */
+  curl_proxytype socks_proxytype; /* what kind of socks proxy that is in use */
   long dns_cache_timeout; /* DNS cache timeout */
   long buffer_size;      /* size of receive buffer to use */
   void *private_data; /* application-private data */
@@ -1642,9 +1702,6 @@
   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) */
@@ -1695,6 +1752,8 @@
   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;
 };
 
 struct Names {
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 @@
   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 @@
   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..7d9200a 100644
--- a/Utilities/cmcurl/lib/vauth/digest.c
+++ b/Utilities/cmcurl/lib/vauth/digest.c
@@ -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; \
@@ -387,10 +388,9 @@
     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);
+  result = Curl_rand(data, &entropy[0], 4);
+  if(result)
+    return result;
 
   /* Convert the random data into a 32 byte hex string */
   snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
@@ -684,9 +684,12 @@
     digest->nc = 1;
 
   if(!digest->cnonce) {
+    unsigned int rnd[4];
+    result = Curl_rand(data, &rnd[0], 4);
+    if(result)
+      return result;
     snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
-             Curl_rand(data), Curl_rand(data),
-             Curl_rand(data), Curl_rand(data));
+             rnd[0], rnd[1], rnd[2], rnd[3]);
 
     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..b9ceb12 100644
--- a/Utilities/cmcurl/lib/vauth/digest_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/digest_sspi.c
@@ -414,7 +414,7 @@
       return CURLE_OUT_OF_MEMORY;
 
     /* Populate our identity domain */
-    if(Curl_override_sspi_http_realm((const char*) digest->input_token,
+    if(Curl_override_sspi_http_realm((const char *) digest->input_token,
                                      &identity))
       return CURLE_OUT_OF_MEMORY;
 
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index b484a01..b4d345d 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -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
@@ -558,8 +558,9 @@
     unsigned int entropy[2];
     unsigned char ntlmv2hash[0x18];
 
-    entropy[0] = Curl_rand(data);
-    entropy[1] = Curl_rand(data);
+    result = Curl_rand(data, &entropy[0], 2);
+    if(result)
+      return result;
 
     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
     if(result)
@@ -598,8 +599,9 @@
     unsigned int entropy[2];
 
     /* Need to create 8 bytes random data */
-    entropy[0] = Curl_rand(data);
-    entropy[1] = Curl_rand(data);
+    result = Curl_rand(data, &entropy[0], 2);
+    if(result)
+      return result;
 
     /* 8 bytes random data as challenge in lmresp */
     memcpy(lmresp, entropy, 8);
diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index 672b43f..5fa95e2 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -264,7 +264,7 @@
 
   /* 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 @@
 #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..ff4634e 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.c
+++ b/Utilities/cmcurl/lib/vtls/axtls.c
@@ -65,7 +65,7 @@
 
 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 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) {
@@ -158,7 +158,7 @@
 
   /* 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 +183,17 @@
   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 +205,15 @@
    */
 
   /* 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 +221,7 @@
     /* 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 +229,15 @@
   /* 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 +245,7 @@
     /* 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,15 +256,16 @@
    * 2) setting up callbacks.  these seem gnutls specific
    */
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.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);
     }
@@ -291,13 +292,17 @@
   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 +333,8 @@
     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 +342,21 @@
 
   /* 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 +365,17 @@
         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 +386,13 @@
   conn->send[sockindex] = axtls_send;
 
   /* Put our freshly minted SSL session in cache */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     const uint8_t *ssl_sessionid = ssl_get_session_id_size(ssl);
     size_t ssl_idsize = ssl_get_session_id(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 +440,7 @@
         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 +506,7 @@
     /* 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) {
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c
index 5d6dbfb..fc4dde4 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -149,7 +149,7 @@
     return CURLE_OK;
 
   /* 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 +174,15 @@
     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 +208,7 @@
     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 */
@@ -228,18 +231,18 @@
 
 #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 +259,25 @@
     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 +290,8 @@
    * 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 +300,15 @@
 #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 +337,7 @@
     }
   }
 #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 +383,11 @@
 #endif /* HAVE_ALPN */
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.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 +397,7 @@
         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 +420,20 @@
   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 +457,31 @@
     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 +500,7 @@
     }
   }
 
-  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+  if(pinnedpubkey) {
 #ifdef KEEP_PEER_CERT
     X509 *x509;
     const char *x509_der;
@@ -509,7 +522,8 @@
     }
 
     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 +532,7 @@
     }
 
     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) {
@@ -583,7 +597,7 @@
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     bool incache;
     SSL_SESSION *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -591,7 +605,8 @@
     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 +617,7 @@
 
     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 +669,11 @@
 
   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;
   }
 }
@@ -740,7 +755,7 @@
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
   if(connssl->handle) {
-    SSL_free (connssl->handle);
+    SSL_free(connssl->handle);
     connssl->handle = NULL;
   }
   return retval;
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c
index 66e74f1..a43e391 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.c
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.c
@@ -197,7 +197,7 @@
 
   do {
     length = write(sock,
-                   (char*)dataPtr + bytesSent,
+                   (char *)dataPtr + bytesSent,
                    dataLen - bytesSent);
   } while((length > 0) &&
            ( (bytesSent += length) < dataLen) );
@@ -219,8 +219,9 @@
   return ortn;
 }
 
-CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
-  switch (cipher) {
+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 +365,8 @@
   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:
@@ -883,14 +885,18 @@
                                       SecIdentityRef *out_cert_and_key)
 {
   OSStatus status = errSecItemNotFound;
+  CFArrayRef keys_list;
+  CFIndex keys_list_count;
+  CFIndex i;
+  CFStringRef common_name;
 
 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
   /* 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 +906,53 @@
     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;
+      for(i=0; i<keys_list_count; i++) {
+        OSStatus err = noErr;
+        SecCertificateRef cert = NULL;
+        *out_cert_and_key =
+          (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
+        err = SecIdentityCopyCertificate(*out_cert_and_key, &cert);
+        if(err == noErr) {
+          SecCertificateCopyCommonName(cert, &common_name);
+          if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
+            CFRelease(cert);
+            CFRelease(common_name);
+            status = noErr;
+            break;
+          }
+          CFRelease(common_name);
+        }
+        *out_cert_and_key = NULL;
+        status = 1;
+        CFRelease(cert);
+      }
+    }
+
     CFRelease(query_dict);
+    CFRelease(label_cf);
   }
   else {
 #if CURL_SUPPORT_MAC_10_6
@@ -1002,6 +1040,12 @@
   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 +1096,46 @@
   /* 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);
-        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);
+    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:
+      (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_TLSv1_3:
+      failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
+      return CURLE_SSL_CONNECT_ERROR;
+    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,82 +1143,37 @@
     (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:
+      (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:
-      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:
-      err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                         kSSLProtocol2,
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kTLSProtocol11,
                                          true);
-      if(err != noErr) {
-        failf(data, "Your version of the OS does not support SSLv2");
-        return CURLE_SSL_CONNECT_ERROR;
-      }
       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;
     case CURL_SSLVERSION_SSLv3:
       err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                          kSSLProtocol3,
@@ -1178,36 +1183,91 @@
         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;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+#endif  /* CURL_SUPPORT_MAC_10_8 */
+  }
+#else
+  (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) {
       SecCertificateRef cert = NULL;
@@ -1246,27 +1306,27 @@
     }
     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 +1357,7 @@
 #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 +1369,7 @@
   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,22 +1378,21 @@
   }
 #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) {
+    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) {
+    if(!verifypeer) {
       failf(data, "SSL: CA certificate set, but certificate verification "
             "is disabled");
       return CURLE_SSL_CONNECT_ERROR;
@@ -1344,22 +1402,22 @@
   /* 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");
     }
   }
 
@@ -1382,7 +1440,7 @@
         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 +1532,22 @@
   /* 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(data->set.general_ssl.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 +1563,8 @@
     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 +1574,8 @@
         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 +1879,7 @@
     return sslerr_to_curlerr(data, ret);
   }
 
-  switch (trust_eval) {
+  switch(trust_eval) {
     case kSecTrustResultUnspecified:
     case kSecTrustResultProceed:
       return CURLE_OK;
@@ -1842,6 +1901,8 @@
   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 +1912,7 @@
   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 +1921,8 @@
       /* 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)) {
+          int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
                                 connssl->ssl_ctx);
           if(res != CURLE_OK)
             return res;
@@ -1930,7 +1991,7 @@
         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;
     }
   }
@@ -1941,7 +2002,7 @@
     /* 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));
@@ -2390,7 +2451,8 @@
   (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
 }
 
-bool Curl_darwinssl_false_start(void) {
+bool Curl_darwinssl_false_start(void)
+{
 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
   if(SSLSetSessionOption != NULL)
     return TRUE;
@@ -2427,7 +2489,7 @@
   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 +2509,7 @@
     /* 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 +2538,7 @@
   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/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 3b0cfd5..a0d462b 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -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 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 @@
                              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 @@
   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 @@
 {
   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 @@
 {
   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 @@
 {
   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 @@
 {
   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_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;
@@ -340,7 +345,7 @@
       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 @@
   /* 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 @@
   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 void close_one(struct ssl_connect_data *conn,
-                      struct Curl_easy *data)
+static int
+inetsocketpair(int sv[2])
 {
-  if(conn->handle) {
-    gskit_status(data, gsk_secure_soc_close(&conn->handle),
-              "gsk_secure_soc_close()", 0);
-    conn->handle = (gsk_handle) NULL;
+  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;
   }
-  if(conn->iocport >= 0)
-    close_async_handshake(conn);
+
+  /* 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 *connssl,
+                      struct connectdata *conn, int sockindex)
+{
+  if(connssl->handle) {
+    gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
+              "gsk_secure_soc_close()", 0);
+    /* 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(connssl->iocport >= 0)
+    close_async_handshake(connssl);
 }
 
 
@@ -518,13 +701,18 @@
                            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,15 +727,23 @@
   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;
 }
@@ -560,18 +756,26 @@
   gsk_handle envir;
   CURLcode result;
   int rc;
-  char *keyringfile;
-  char *keyringpwd;
-  char *keyringlabel;
-  char *sni;
+  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;
   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 +790,6 @@
    *  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,19 +814,36 @@
   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;
@@ -639,6 +857,12 @@
   case CURL_SSLVERSION_TLSv1_2:
     protoflags = CURL_GSKPROTO_TLSV12_MASK;
     break;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "GSKit: TLS 1.3 is not yet supported");
+    return CURLE_SSL_CONNECT_ERROR;
+  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 +885,12 @@
                            (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 +933,7 @@
   }
   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 +957,10 @@
     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 +973,7 @@
   }
 
   /* Error: rollback. */
-  close_one(connssl, data);
+  close_one(connssl, conn, sockindex);
   return result;
 }
 
@@ -765,7 +996,7 @@
       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 +1053,7 @@
     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 +1096,14 @@
   }
 
   /* 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 +1144,11 @@
       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 +1163,17 @@
       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 +1217,8 @@
 
 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 +1237,7 @@
   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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -41,6 +41,9 @@
 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 @@
 #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..0e308cb 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -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 */
@@ -171,6 +171,16 @@
   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
@@ -225,14 +235,15 @@
   infof(data, "%s\n", data->state.buffer);
 }
 
-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 +262,8 @@
   return loaded_file;
 }
 
-static void unload_file(gnutls_datum_t data) {
+static void unload_file(gnutls_datum_t data)
+{
   free(data.data);
 }
 
@@ -371,6 +383,9 @@
   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
@@ -397,10 +412,13 @@
    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 +427,11 @@
   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 +442,8 @@
   }
 
 #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 +455,8 @@
 
     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,64 +465,64 @@
   }
 #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 */
@@ -518,13 +535,13 @@
   /* 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 +562,13 @@
   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;
@@ -569,12 +586,16 @@
       break;
     case CURL_SSLVERSION_TLSv1_2:
       protocol_priority[0] = GNUTLS_TLS1_2;
-    break;
-      case CURL_SSLVERSION_SSLv2:
-    default:
+      break;
+    case CURL_SSLVERSION_TLSv1_3:
+      failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+      return CURLE_SSL_CONNECT_ERROR;
+    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 +607,7 @@
   /* 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;
@@ -607,11 +628,15 @@
       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
                      "+VERS-TLS1.2:" GNUTLS_SRP;
       break;
+    case CURL_SSLVERSION_TLSv1_3:
+      failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+      return CURLE_SSL_CONNECT_ERROR;
     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 +686,8 @@
   }
 #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 +696,11 @@
         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 +714,14 @@
 #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 +729,7 @@
 
 #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 +748,30 @@
     }
   }
 
-  /* 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 +782,17 @@
 
   /* 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(data->set.general_ssl.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);
   }
@@ -847,8 +882,9 @@
   gnutls_datum_t proto;
 #endif
   CURLcode result = CURLE_OK;
-
   gnutls_protocol_t version = gnutls_protocol_get_version(session);
+  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 +902,13 @@
 
   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 +941,7 @@
     }
   }
 
-  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 +957,11 @@
 
     /* 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 +974,7 @@
     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 +1086,21 @@
        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 +1119,7 @@
      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 +1135,10 @@
     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 +1163,18 @@
   }
 #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 +1183,7 @@
   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 +1193,7 @@
   }
   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 +1208,7 @@
   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 +1218,7 @@
   }
   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 +1230,8 @@
       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) {
@@ -1270,7 +1311,7 @@
   conn->recv[sockindex] = gtls_recv;
   conn->send[sockindex] = gtls_send;
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.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 +1330,8 @@
       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 +1339,8 @@
       }
 
       /* 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 +1375,7 @@
 
   /* 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 +1422,20 @@
   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 +1455,29 @@
   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 +1543,8 @@
   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
 
@@ -1597,7 +1654,7 @@
   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 +1673,7 @@
   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..6531201 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.h
+++ b/Utilities/cmcurl/lib/vtls/gtls.h
@@ -34,6 +34,8 @@
 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);
@@ -55,6 +57,9 @@
 
 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 @@
 #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..8bcaddd 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -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>
@@ -159,13 +163,20 @@
 {
   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;
   }
@@ -201,34 +212,32 @@
   /* 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 +245,15 @@
   /* 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 +262,9 @@
   /* 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 +273,7 @@
       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 +282,21 @@
   /* 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 +318,7 @@
   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,
@@ -347,8 +353,11 @@
                                  MBEDTLS_SSL_MINOR_VERSION_3);
     infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
     break;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "mbedTLS: TLS 1.3 is not yet supported");
+    return CURLE_SSL_CONNECT_ERROR;
   default:
-    failf(data, "mbedTLS: Unsupported SSL protocol version");
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
@@ -365,11 +374,11 @@
                                 mbedtls_ssl_list_ciphersuites());
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.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 +394,11 @@
                             &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. */
@@ -443,9 +452,12 @@
   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 +491,7 @@
 
   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 +526,7 @@
     free(buffer);
   }
 
-  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+  if(pinnedpubkey) {
     int size;
     CURLcode result;
     mbedtls_x509_crt *p;
@@ -553,7 +565,7 @@
 
     /* 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 +618,7 @@
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     int ret;
     mbedtls_ssl_session *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -625,10 +637,10 @@
 
     /* 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);
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index dff1575..ba8d582 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -200,14 +200,14 @@
 #endif
 };
 
-static const char* pem_library = "libnsspem.so";
-static SECMODModule* mod = NULL;
+static const char *pem_library = "libnsspem.so";
+static SECMODModule *mod = 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 +254,8 @@
     while((*cipher) && (ISSPACE(*cipher)))
       ++cipher;
 
-    if((cipher_list = strchr(cipher, ','))) {
+    cipher_list = strchr(cipher, ',');
+    if(cipher_list) {
       *cipher_list++ = '\0';
     }
 
@@ -337,9 +338,8 @@
  * 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))
@@ -514,7 +514,7 @@
   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 +540,7 @@
     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");
@@ -585,6 +585,7 @@
   SECStatus status;
   CURLcode result;
   struct ssl_connect_data *ssl = conn->ssl;
+  struct Curl_easy *data = conn->data;
 
   (void)sockindex; /* unused */
 
@@ -602,8 +603,7 @@
   SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
   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 +664,7 @@
   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 +682,7 @@
   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 +708,7 @@
   }
 #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 +734,11 @@
   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 +933,12 @@
   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;
 
@@ -1367,38 +1375,57 @@
   return -1;  /* connection status unknown */
 }
 
-/*
- * This function is called when an SSL connection is closed.
- */
-void Curl_nss_close(struct connectdata *conn, int sockindex)
+static void nss_close(struct ssl_connect_data *connssl)
 {
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  /* 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_list = NULL;
+  connssl->obj_clicert = NULL;
 
   if(connssl->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))
+    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);
 
-    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;
-
     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 || 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->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;
+
+  nss_close(connssl);
+  nss_close(connssl_proxy);
+}
+
 /* return true if NSS can provide error code (and possibly msg) for the
    error */
 static bool is_nss_error(CURLcode err)
@@ -1437,8 +1464,8 @@
                                          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);
 
   if(cafile) {
     CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
@@ -1486,13 +1513,22 @@
 }
 
 static CURLcode nss_init_sslver(SSLVersionRange *sslver,
-                                struct Curl_easy *data)
+                                struct Curl_easy *data,
+                                struct connectdata *conn)
 {
-  switch(data->set.ssl.version) {
-  default:
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_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;
+    return CURLE_OK;
+
   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;
 #elif defined SSL_LIBRARY_VERSION_TLS_1_1
@@ -1532,6 +1568,18 @@
     return CURLE_OK;
 #endif
     break;
+
+  case CURL_SSLVERSION_TLSv1_3:
+#ifdef SSL_LIBRARY_VERSION_TLS_1_3
+    sslver->min = SSL_LIBRARY_VERSION_TLS_1_3;
+    sslver->max = SSL_LIBRARY_VERSION_TLS_1_3;
+    return CURLE_OK;
+#endif
+    break;
+
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
   failf(data, "TLS minor version cannot be set");
@@ -1589,6 +1637,7 @@
   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 */
@@ -1647,18 +1696,18 @@
     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 = (data->set.general_ssl.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 +1719,14 @@
     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,14 +1734,19 @@
   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) {
+  if(SSL_CONN_CONFIG(verifypeer)) {
     const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
     if(rv) {
       result = rv;
@@ -1700,24 +1754,24 @@
     }
   }
 
-  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 +1791,24 @@
     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 +1817,8 @@
 
   /* 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 +1826,8 @@
   /* 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 +1835,12 @@
   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 +1900,14 @@
     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,6 +1925,12 @@
   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);
@@ -1872,9 +1946,9 @@
     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 +1957,11 @@
   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 +1976,7 @@
     }
   }
 
-  result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
+  result = cmp_peer_pubkey(connssl, pinnedpubkey);
   if(result)
     /* status already printed */
     goto error;
@@ -2112,7 +2186,8 @@
 #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..fd94003 100644
--- a/Utilities/cmcurl/lib/vtls/nssg.h
+++ b/Utilities/cmcurl/lib/vtls/nssg.h
@@ -65,6 +65,9 @@
 
 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..d92e713 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -176,39 +176,34 @@
 }
 
 /*
- * 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)
 {
+  /* we have the "SSL is seeded" boolean static to prevent multiple
+     time-consuming seedings in vain */
+  static bool ssl_seeded = FALSE;
   char *buf = data->state.buffer; /* point to the big buffer */
   int nread=0;
 
-  /* 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 +212,7 @@
                              data->set.str[STRING_SSL_RANDOM_FILE]:
                              RANDOM_FILE),
                             RAND_LOAD_LENGTH);
-    if(seed_enough(nread))
+    if(rand_enough())
       return nread;
   }
 
@@ -237,7 +232,7 @@
                        data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
     if(-1 != ret) {
       nread += ret;
-      if(seed_enough(nread))
+      if(rand_enough())
         return nread;
     }
   }
@@ -248,9 +243,10 @@
   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 */
@@ -258,25 +254,12 @@
   if(buf[0]) {
     /* we got a file name to try */
     nread += RAND_load_file(buf, RAND_LOAD_LENGTH);
-    if(seed_enough(nread))
+    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 +295,7 @@
   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,7 +331,8 @@
                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;
 
@@ -359,10 +343,9 @@
     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);
     }
@@ -473,7 +456,7 @@
 
       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
@@ -571,7 +554,7 @@
         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 +568,7 @@
           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");
@@ -916,24 +899,28 @@
 }
 
 
+static void ossl_close(struct ssl_connect_data *connssl)
+{
+  if(connssl->handle) {
+    (void)SSL_shutdown(connssl->handle);
+    SSL_set_connect_state(connssl->handle);
+
+    SSL_free(connssl->handle);
+    connssl->handle = NULL;
+  }
+  if(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)
 {
-  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);
-    connssl->handle = NULL;
-  }
-  if(connssl->ctx) {
-    SSL_CTX_free (connssl->ctx);
-    connssl->ctx = NULL;
-  }
+  ossl_close(&conn->ssl[sockindex]);
+  ossl_close(&conn->proxy_ssl[sockindex]);
 }
 
 /*
@@ -1031,7 +1018,7 @@
 #endif
     }
 
-    SSL_free (connssl->handle);
+    SSL_free(connssl->handle);
     connssl->handle = NULL;
   }
   return retval;
@@ -1107,16 +1094,20 @@
   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 +1156,11 @@
           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 +1171,7 @@
             ipmatched = TRUE;
             infof(data,
                   " subjectAltName: host \"%s\" matched cert's IP address!\n",
-                  conn->host.dispname);
+                  dispname);
           }
           break;
         }
@@ -1196,9 +1187,9 @@
     /* 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 +1263,9 @@
             "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 {
@@ -1425,7 +1416,7 @@
 {
 #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 +1440,7 @@
   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 +1540,11 @@
     verstr = "TLSv1.2";
     break;
 #endif
+#ifdef TLS1_3_VERSION
+  case TLS1_3_VERSION:
+    verstr = "TLSv1.3";
+    break;
+#endif
   case 0:
     break;
   default:
@@ -1571,7 +1567,7 @@
     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",
@@ -1677,6 +1673,10 @@
     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";
@@ -1711,23 +1711,39 @@
   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);
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   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 +1759,7 @@
     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 +1772,16 @@
     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)
@@ -1841,14 +1860,14 @@
 #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 +1876,9 @@
 #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;
 
@@ -1872,38 +1894,75 @@
 #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;
 
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
   case CURL_SSLVERSION_TLSv1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     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;
+#ifdef TLS1_3_VERSION
+    ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
     break;
+#else
+    failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
+    return CURLE_NOT_BUILT_IN;
+#endif
 
   case CURL_SSLVERSION_TLSv1_2:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     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;
+#ifdef TLS1_3_VERSION
+    ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
     break;
+#else
+    failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
+    return CURLE_NOT_BUILT_IN;
 #endif
 
-#ifndef OPENSSL_NO_SSL2
+  case CURL_SSLVERSION_TLSv1_3:
+#ifdef TLS1_3_VERSION
+    SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
+    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;
+    ctx_options |= SSL_OP_NO_TLSv1_2;
+    break;
+#else
+    failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+    return CURLE_NOT_BUILT_IN;
+#endif
+
   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 +2001,16 @@
   }
 #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 +2020,20 @@
   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,20 +2043,17 @@
     }
   }
 #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 {
@@ -2015,29 +2070,25 @@
     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 {
@@ -2046,9 +2097,7 @@
       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");
+    infof(data, "  CRLfile: %s\n", ssl_crlfile);
   }
 
   /* Try building a chain using issuers in the trusted store first to avoid
@@ -2059,7 +2108,7 @@
   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 +2119,7 @@
    * 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,31 +2142,30 @@
 
 #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(data->set.general_ssl.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);
@@ -2127,13 +2174,21 @@
         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));
     return CURLE_SSL_CONNECT_ERROR;
@@ -2149,9 +2204,11 @@
   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();
 
@@ -2198,7 +2255,7 @@
 
         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 +2277,11 @@
        * the SO_ERROR is also lost.
        */
       if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
+        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, "Unknown SSL protocol error in connection to %s:%ld ",
-              conn->host.name, conn->remote_port);
+              hostname, port);
         return result;
       }
 
@@ -2245,7 +2305,7 @@
      * 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 +2336,8 @@
 {
   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);
@@ -2698,6 +2759,8 @@
   FILE *fp;
   char *buffer = data->state.buffer;
   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)
@@ -2713,7 +2776,7 @@
     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);
@@ -2731,7 +2794,7 @@
 
   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);
@@ -2754,12 +2817,12 @@
        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 +2832,7 @@
       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 +2844,7 @@
       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 +2852,14 @@
       }
 
       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 +2878,7 @@
 
 #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 +2892,8 @@
     /* 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 +2915,7 @@
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     bool incache;
     SSL_SESSION *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -2864,7 +2927,8 @@
         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 +2939,7 @@
 
     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 +2963,8 @@
    * 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 +2984,7 @@
   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 */
@@ -3048,7 +3112,10 @@
 {
   if(conn->ssl[connindex].handle)
     /* SSL is in use */
-    return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
+    return (0 != SSL_pending(conn->ssl[connindex].handle) ||
+           (conn->proxy_ssl[connindex].handle &&
+            0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ?
+           TRUE : FALSE;
   else
     return FALSE;
 }
@@ -3093,8 +3160,18 @@
       /*  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;
     }
@@ -3178,7 +3255,7 @@
         sub[0] = 'z';
       }
       else {
-        sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1);
+        sub[0] = (char) (minor_ver + 'a' - 1);
       }
     }
     else
@@ -3199,7 +3276,12 @@
                      size_t length)
 {
   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 1; /* couldn't seed for some reason */
+  }
+  else {
+    if(!rand_enough())
+      return 1;
   }
   RAND_bytes(entropy, curlx_uztosi(length));
   return 0; /* 0 as in no problem */
diff --git a/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h
index ee18e71..cff1e90 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.h
+++ b/Utilities/cmcurl/lib/vtls/openssl.h
@@ -79,6 +79,9 @@
 
 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..4bba3e3 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.c
+++ b/Utilities/cmcurl/lib/vtls/polarssl.c
@@ -147,12 +147,16 @@
 {
   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 +184,29 @@
   /* 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 +214,25 @@
   /* 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 +244,7 @@
     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 +253,27 @@
   /* 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,
@@ -306,6 +307,12 @@
                         SSL_MINOR_VERSION_3);
     infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
     break;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "PolarSSL: TLS 1.3 is not yet supported");
+    return CURLE_SSL_CONNECT_ERROR;
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
   ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
@@ -320,11 +327,11 @@
   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(data->set.general_ssl.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 +346,12 @@
   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 +361,7 @@
 
 #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 +397,10 @@
   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 +434,7 @@
 
   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 +462,7 @@
   }
 
   /* adapted from mbedtls.c */
-  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+  if(pinnedpubkey) {
     int size;
     CURLcode result;
     x509_crt *p;
@@ -493,7 +504,7 @@
 
     /* 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 +555,7 @@
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     int ret;
     ssl_session *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -563,10 +574,10 @@
 
     /* 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);
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index f731eeb..ac8b705 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -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"
@@ -123,9 +124,11 @@
 #endif
   TCHAR *host_name;
   CURLcode result;
+  const 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);
 
 #ifdef HAS_ALPN
   /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
@@ -142,9 +145,9 @@
   connssl->cred = NULL;
 
   /* check for an existing re-usable credential handle */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.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 +164,7 @@
     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 +173,14 @@
         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 +193,14 @@
       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");
     }
 
-    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 |
@@ -213,12 +216,18 @@
     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;
     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 +262,9 @@
   }
 
   /* 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 +274,17 @@
   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 +342,7 @@
   }
   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;
 
@@ -406,11 +415,13 @@
   TCHAR *host_name;
   CURLcode result;
   bool doread;
+  const 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;
@@ -506,7 +517,7 @@
     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;
 
@@ -623,7 +634,7 @@
 #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 +649,8 @@
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   SECURITY_STATUS sspi_status = SEC_E_OK;
   CERT_CONTEXT *ccert_context = NULL;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 #ifdef HAS_ALPN
   SecPkgContext_ApplicationProtocol alpn_result;
 #endif
@@ -645,7 +658,7 @@
   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 +714,13 @@
 #endif
 
   /* save the current session data for possible re-use */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.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 +731,8 @@
     }
     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 +784,7 @@
   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 +972,7 @@
     /* send entire message or fail */
     while(len > (size_t)written) {
       ssize_t this_write;
-      long timeleft;
+      time_t timeleft;
       int what;
 
       this_write = 0;
@@ -1376,9 +1391,11 @@
    */
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  const 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 +1417,7 @@
       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;
 
@@ -1525,6 +1542,9 @@
   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 +1566,7 @@
                                 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 +1602,10 @@
   }
 
   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 +1616,50 @@
       */
       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/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index 56a8823..b808e1c 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -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,49 @@
                                  (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->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;
 
-  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);
   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 +133,6 @@
   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 +173,41 @@
 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)) {
+  if((data->set.ssl.primary.version < 0)
+     || (data->set.ssl.primary.version >= CURL_SSLVERSION_LAST)) {
     failf(data, "Unrecognized parameter value passed via CURLOPT_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 +228,11 @@
                              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 +275,8 @@
  */
 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 +284,18 @@
   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(data->set.general_ssl.sessionid);
 
-  if(!conn->ssl_config.sessionid)
+  if(!data->set.general_ssl.sessionid)
     /* session ID re-use is disabled */
     return TRUE;
 
@@ -385,21 +305,21 @@
   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 +348,7 @@
     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 +363,7 @@
   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 +381,8 @@
  */
 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 +392,14 @@
   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(data->set.general_ssl.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 +430,14 @@
   }
 
   /* 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
@@ -528,10 +453,11 @@
   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 +473,7 @@
   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 +484,43 @@
   curlssl_close_all(data);
 }
 
+#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
+    defined(USE_DARWINSSL) || defined(USE_NSS)
+/* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only. */
+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);
+  }
+  else 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_SSLEAY || 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 +578,7 @@
     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 +654,9 @@
                                     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,11 +699,16 @@
   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);
+  int rc = curlssl_random(data, entropy, length);
+  if(rc) {
+    failf(data, "PRNG seeding failed");
+    return CURLE_FAILED_INIT; /* possibly weird return code */
+  }
+  return CURLE_OK;
 }
 
 /*
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);
+/* 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 */
 
-unsigned int Curl_rand(struct Curl_easy *);
+#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 @@
 /* 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 @@
  */
 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 @@
  */
 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_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/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c
index 74a511b..c4bc7c1 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 @@
  */
 
 
-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 @@
      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 @@
     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 @@
       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 @@
   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 @@
   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 @@
   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 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 @@
      string length. */
 
   *to = (char *) NULL;
-  switch (type) {
+  switch(type) {
   case CURL_ASN1_BMP_STRING:
     size = 2;
     break;
@@ -282,6 +287,8 @@
 
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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,7 +460,7 @@
 
   /* Get seconds digits. */
   sec1 = '0';
-  switch (fracp - beg - 12) {
+  switch(fracp - beg - 12) {
   case 0:
     sec2 = '0';
     break;
@@ -499,11 +506,11 @@
                        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 +519,7 @@
     ;
   /* Get the seconds. */
   sec = beg + 10;
-  switch (tzp - sec) {
+  switch(tzp - sec) {
   case 0:
     sec = "00";
   case 2:
@@ -538,7 +545,7 @@
                        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 +556,7 @@
   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 +588,17 @@
   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 +654,9 @@
   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 +676,12 @@
  * 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 +693,8 @@
   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 +757,10 @@
   }
   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 +777,8 @@
   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 +793,10 @@
   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 +810,14 @@
   }
 }
 
-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 +874,18 @@
 #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 +898,8 @@
   /* 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 +1039,12 @@
 
 #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 +1063,26 @@
   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 +1092,19 @@
   /* 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 +1122,12 @@
       /* 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 +1142,15 @@
     }
   }
 
-  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 +1182,14 @@
     }
     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@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -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 @@
  * 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/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 @@
 #
 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 @@
 
 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(CheckIncludeFile)
 INCLUDE(CheckIncludeFiles)
 INCLUDE(CheckLibraryExists)
-INCLUDE(CheckStructMember)
+INCLUDE(CheckStructHasMember)
 INCLUDE(CheckSymbolExists)
 INCLUDE(CheckTypeExists)
 INCLUDE(CheckTypeSize)
@@ -285,21 +287,20 @@
 # 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 @@
   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)
+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)
+  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("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 @@
 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 @@
 
 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 @@
   "#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 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 @@
   # 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 @@
   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@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 @@
 /* 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 @@
 /* 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 @@
 /* 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 @@
 /* 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 @@
 /* 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 @@
   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 @@
 /*
  * 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 @@
  *   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 @@
  * 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_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 @@
 #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 @@
 
 /*
  * 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 @@
 		    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 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 @@
 		acl->acl_text = NULL;
 	}
 	acl->acl_p = NULL;
+	acl->acl_types = 0;
 	acl->acl_state = 0; /* Not counting. */
 }
 
@@ -279,23 +333,31 @@
 		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 @@
 }
 
 /*
+ * 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 @@
  * 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 @@
 }
 
 /*
- * 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 want_type;
+
+	/* 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);
+	}
+
+	/* 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;
+	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 */
+			/* ID digit count */
+			idlen = 1;
+			tmp = ap->id;
+			while (tmp > 9) {
+				tmp = tmp / 10;
+				idlen++;
+			}
+			length += idlen;
+		}
+		length ++; /* entry separator */
+	}
+
+	/* 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;
-	size_t length;
+	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;
-	wchar_t *wp;
+	int id, r, want_type;
+	wchar_t *wp, *ws;
 
-	if (acl->acl_text_w != NULL) {
-		free (acl->acl_text_w);
-		acl->acl_text_w = NULL;
-	}
+	want_type = archive_acl_text_want_type(acl, flags);
 
-	separator = L',';
-	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 */
-			length += 3; /* rwx */
-			length += 1; /* colon */
-			length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1;
-			length ++; /* newline */
-		}
-		ap = ap->next;
-	}
-
-	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 (count == 0)
+	/* 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 (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 @@
 }
 
 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 @@
 	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 @@
 	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 @@
 		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);
-		*wp += wcslen(*wp);
-	} else if (tag == ARCHIVE_ENTRY_ACL_USER
-	    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
-		append_id_w(wp, id);
-		id = -1;
+	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':';
 	}
-	*(*wp)++ = L':';
-	*(*wp)++ = (perm & 0444) ? L'r' : L'-';
-	*(*wp)++ = (perm & 0222) ? L'w' : L'-';
-	*(*wp)++ = (perm & 0111) ? L'x' : 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);
+	}
 	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 @@
 }
 
 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 @@
 	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 @@
 	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 @@
 		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);
-		*p += strlen(*p);
-	} else if (tag == ARCHIVE_ENTRY_ACL_USER
-	    || tag == ARCHIVE_ENTRY_ACL_GROUP) {
-		append_id(p, id);
-		id = -1;
+	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)++ = ':';
 	}
-	*(*p)++ = ':';
-	*(*p)++ = (perm & 0444) ? 'r' : '-';
-	*(*p)++ = (perm & 0222) ? 'w' : '-';
-	*(*p)++ = (perm & 0111) ? 'x' : '-';
+	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);
+	}
 	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;
 
-	int fields, n;
-	int type, tag, permset, id;
+	const wchar_t *s, *st;
+
+	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 @@
 		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 @@
 		} 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. */
+		if (field[0].start != NULL && *(field[0].start) == L'#') {
+			/* Comment, skip entry */
+			continue;
+		}
+
+		n = 0;
+		sol = 0;
 		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;
-
+		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;
+
+		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
+				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_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;
-				name = field[1];
-			} 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 @@
 	*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 @@
 }
 
 /*
- * 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 @@
 		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 @@
 		} 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. */
+		if (field[0].start != NULL && *(field[0].start) == '#') {
+			/* Comment, skip entry */
+			continue;
+		}
+
+		n = 0;
+		sol = 0;
 		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;
-
+		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;
+
+		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
+				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_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;
-				name = field[1];
-			} 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 @@
 			return (r);
 		if (r != ARCHIVE_OK)
 			ret = ARCHIVE_WARN;
+		types |= type;
 	}
+
+	/* Reset ACL */
+	archive_acl_reset(acl, types);
+
 	return (ret);
 }
 
@@ -1220,6 +1927,112 @@
 }
 
 /*
+ * 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 @@
 	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 @@
 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_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 @@
 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 @@
 {
 	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 @@
 }
 
 /*
+ * 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 @@
 }
 
 /*
- * 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 @@
 	{ "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 @@
 	{ "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 @@
 #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 @@
 #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 @@
 # 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 @@
 # 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 @@
 /*
  * 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 @@
 	    | 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 @@
  * 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 @@
 .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 @@
 .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 @@
 .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 @@
 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 @@
 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 @@
 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 @@
 .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 @@
     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 @@
 		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 @@
 
 #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 @@
 }
 
 /*
- * 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 @@
 		}
 	}
 
-	/* 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 @@
 #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 @@
 			&(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 @@
 			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 @@
 		}
 	}
 
-	/* 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 @@
 			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 @@
 	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 @@
 #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 @@
 
 	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 @@
 		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 @@
 
 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 @@
 	{
 		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 @@
 			/* 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 @@
 		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 @@
  * 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 @@
 	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 @@
 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 @@
 	/* 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 @@
 __archive_read_reset_passphrase(struct archive_read *a)
 {
 
-	a->passphrases.candiate = -1;
+	a->passphrases.candidate = -1;
 }
 
 /*
@@ -137,31 +137,31 @@
 	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 @@
 			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 @@
     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 @@
   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 @@
 .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 @@
 #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 @@
 #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 @@
     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 @@
 #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 @@
 		}
 		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 @@
 	}
 #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 @@
 	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 @@
 }
 #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 @@
 		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;
-	}
-#endif
 	if (acl != NULL) {
-		translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
-		acl_free(acl);
-		return (ARCHIVE_OK);
-	}
+#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) {
+		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+		acl_free(acl);
+		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 @@
 #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 @@
 		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 @@
 		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 @@
 			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);
+			}
+#endif	/* HAVE_ACL_TYPE_NFS4 */
+
+			/*
+			 * 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 */
 
-		/*
-		 * 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
-
-		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 @@
 					    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 @@
 	(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 @@
 
 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 @@
 	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 @@
 		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 @@
  */
 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 @@
 	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 @@
 		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 @@
 #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 @@
  */
 
 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 @@
 		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 @@
 		} 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 @@
     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 @@
 	}
 
 	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 @@
 		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 @@
 		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 @@
 			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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 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_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 @@
 				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 @@
 	} 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 @@
 		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 @@
 	}
 	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 @@
 	 * 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 @@
 			    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 @@
 
 	/* 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 @@
 		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 @@
 		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 @@
 	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 @@
 
 	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 @@
 	}
 
 	/*
-	 * 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 @@
 			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 @@
 	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 @@
 #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 @@
 	else
 		t->current_filesystem->name_max = nm;
 #endif
-#endif /* HAVE_READDIR_R */
+#endif /* USE_READDIR_R */
 	return (ARCHIVE_OK);
 }
 
@@ -1643,7 +1646,7 @@
 		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 @@
 #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 @@
 #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 @@
 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 @@
 	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 @@
 	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 @@
 	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 @@
 {
 	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 @@
 {
 	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 @@
 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 @@
 	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 @@
 			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 @@
 			}
 			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 @@
 	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 @@
 	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 @@
 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 @@
 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 @@
 	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 @@
 {
 	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 @@
 	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_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 @@
 		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 @@
 	}
 	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 @@
 
 	/* 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 @@
 		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 @@
 		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 @@
 	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 @@
 
 	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 @@
 	}
 
 	/*
-	 * 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 @@
 			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 @@
 	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 @@
 {
 	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 @@
 {
 	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 @@
 	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 @@
 __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 @@
 	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 @@
 #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 @@
 		else
 			archive_set_error(a, errno, "Can't stat '%s'",
 			    filename);
-		return (ARCHIVE_FATAL);
+		goto fail;
 	}
 
 	/*
@@ -356,11 +356,9 @@
 		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 @@
 		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 @@
 {
 	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 {
 		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_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 @@
 			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 @@
 	/* 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 @@
 #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 @@
 
 	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 @@
 	/* 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 @@
 	}
 
 	/*
-	 * 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 @@
 	    &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 @@
 	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 @@
 	avail -= len;
 
 	if (l == 6) {
+		/* "begin " */
 		if (!uuchar[*b])
 			return (0);
 		/* Get a length of decoded bytes. */
@@ -319,30 +320,14 @@
 		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 @@
 		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 @@
 		}
 		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 @@
 				    "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 @@
 #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 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 @@
 	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 @@
 	/* 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 @@
 		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 @@
 
 #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 @@
 	return (r);
 }
 
-#endif /* HAVE_LZMADEC_H */
-
-
 static int
 xz_bidder_init(struct archive_read_filter *self)
 {
@@ -984,5 +793,4 @@
 	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 @@
 	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 @@
 	/*
 	 * 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 @@
 	/*
 	 * 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 @@
 			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 @@
 #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 @@
 		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 @@
 		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 @@
 
 		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 @@
 					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 @@
 					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 @@
 			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 @@
 			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 @@
 		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 @@
 				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 @@
 	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_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 @@
 		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 @@
 		 * 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 @@
 
 		/* 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 @@
 	/* 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 = (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 @@
 
 		/* 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 @@
 	/*
 	 * 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 @@
 	}
 
 	/*
-	 * 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 @@
 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 @@
 
 	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 @@
     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 @@
 			    "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 @@
 	 * 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 @@
  * 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 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 @@
 	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_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 @@
 		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 @@
 			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 @@
 				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 @@
 				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 @@
 				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 @@
 				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 @@
 				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 @@
 					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 @@
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    "Invalid Rockridge CL");
-				return (NULL);
+				goto fail;
 			}
 		}
 	}
@@ -2088,6 +2086,10 @@
 #endif
 	register_file(iso9660, file);
 	return (file);
+fail:
+	archive_string_free(&file->name);
+	free(file);
+	return (NULL);
 }
 
 static int
@@ -2407,7 +2409,7 @@
 				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 @@
 		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 @@
 	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 @@
 			/* 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 @@
 	/* 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 @@
 	 */
 	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 @@
 #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 @@
 	char *name;
 	char full;
 	char used;
+	unsigned int name_hash;
+	struct mtree_entry *hashtable_next;
 };
 
 struct mtree {
@@ -98,6 +102,7 @@
 	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 @@
 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_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 @@
 	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 @@
 		*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 @@
 				}
 			} 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 @@
     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 @@
 	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 @@
 	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 @@
 		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 @@
 		 * 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 @@
 			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 @@
 		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_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 @@
                             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 @@
 	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 @@
 		    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 @@
 	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 @@
 		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 @@
 
 	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->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 @@
 {
 	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 @@
 	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 @@
 			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 @@
 	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 @@
 		 * 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 @@
 	 * 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 @@
  */
 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 @@
 		}
 		*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 @@
 	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 @@
  */
 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 @@
 				 * 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 @@
 	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 @@
 		} 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 @@
 {
 	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 @@
 	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 @@
 	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 @@
 	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 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_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 @@
 
 	/* 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 @@
 			&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 @@
 	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 @@
 		}
 		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 @@
 
 	/* 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 @@
 		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 @@
 }
 
 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;
+	const char *c;
+	unsigned int ver = 0U;
+	unsigned int end = 0U;
 
-	(void)bsz; /* UNUSED */
-
-	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 @@
 _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;
 	}
-	/* 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 WT_NONE;
+	}
 
-	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;
+	/* overread whitespace */
+	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 @@
 _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 @@
 		return res;
 	}
 	/* overread whitespace */
-	for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++);
-
-	/* overread URL designators */
-	if ((uri = xmemmem(val, eob - val, "://", 3U)) == NULL) {
-		/* not touching that! */
-		return res;
-	} else if ((eol = memchr(uri, '\n', eob - uri)) == NULL) {
-		/* no end of line? :O */
+	val += sizeof(_key) - 1U;
+	if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
+		/* no end of line */
 		return res;
 	}
 
-	/* massage uri to point to after :// */
+	while (val < eol && (*val == ' ' || *val == '\t'))
+		++val;
+
+	/* overread URL designators */
+	if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) {
+		/* not touching that! */
+		return res;
+	}
+
+	/* 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 @@
 _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 @@
 		/* no bother */
 		return -1;
 	}
-
-	/* strtol kindly overreads whitespace for us, so use that */
 	val += sizeof(_key) - 1U;
-	len = strtol(val, &on, 10);
-	if (on == NULL || !isspace(*on)) {
-		/* hm, can we trust that number?  Best not. */
+	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 != eol) {
+		/* line must end here */
+		return -1;
+	}
+
 	return (size_t)len;
 }
 
@@ -738,7 +751,7 @@
 _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 @@
 		/* 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 @@
 _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 @@
 		/* 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 @@
 	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 @@
 #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 @@
 #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 @@
 		    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 @@
 	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 @@
 	}
 	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 @@
 		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 @@
 	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 @@
 		*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 @@
 }
 
 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 @@
 	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 @@
 		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 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 @@
 }
 
 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 @@
 	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 @@
  *	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 @@
 			/* 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 @@
 			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 @@
 		}
 		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 @@
 		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 @@
 				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 @@
 				archive_strcat(&s, cp);
 				archive_strappend_char(&s, '/');
 				archive_entry_set_pathname(entry, s.s);
+				archive_string_free(&s);
 			}
 		}
 	}
@@ -1140,11 +1168,18 @@
 			|| (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 @@
 	    && 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->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 @@
 	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 @@
 	__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 @@
 		}
 
 		/*
-		 * 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 @@
 			    "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 @@
 	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 @@
 			}
 			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 @@
 	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 @@
 		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 @@
 		/*
 		 * 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 @@
  * 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 @@
 	 * 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 @@
     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 @@
 	 * 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 @@
 #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 @@
 
 /*
  * 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 @@
 
 	/*
 	 * 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 @@
 		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 @@
 		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 @@
 	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 @@
 /*
  * 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 @@
 
 	/*
 	 * 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 @@
 /*
  * 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 @@
 		}
 
 		/*
-		 * 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 @@
 
 /*
  * 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 @@
 		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 @@
 
 /*
  * 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 @@
 	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 @@
 
 /*
  * 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 @@
 
 /*
  * 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 @@
 
 #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_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 @@
 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 @@
 
 
 /* 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 @@
 	(((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 @@
 __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 @@
 			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 @@
 		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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 		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 @@
 		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 @@
 		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 @@
 	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 @@
 #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 @@
 #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 @@
 	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 @@
 	{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,23 +254,166 @@
 	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@.
+		 * 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:
-			acl_set_tag_type(acl_entry, ACL_USER);
 			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
-			acl_set_qualifier(acl_entry, &ae_uid);
+			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:
-			acl_set_tag_type(acl_entry, ACL_GROUP);
 			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
-			acl_set_qualifier(acl_entry, &ae_gid);
+			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:
+			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:
+			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;
 		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
@@ -179,85 +425,230 @@
 		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:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
+			if (ace != NULL)
+				ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+			else
+				r = -1;
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
+			if (ace != NULL)
+				ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
+			else
+				r = -1;
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
+			if (ace != NULL)
+				ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
+			else
+				r = -1;
 			break;
 		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
-			acl_set_entry_type_np(acl_entry, ACL_ENTRY_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:
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
+			break;
+		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+			r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
+			break;
+		case ARCHIVE_ENTRY_ACL_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;
 		}
+
+		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 */
 
-		acl_get_permset(acl_entry, &acl_permset);
-		acl_clear_perms(acl_permset);
-
+#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 @@
 #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 @@
 #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 @@
 #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 @@
 #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 @@
 
 #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 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 @@
 		/*
 		 * 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 @@
 	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 @@
 		}
 		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 @@
 				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 @@
 		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 @@
 		    (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 @@
 		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 @@
 		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 @@
 	 * 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 @@
 {
 	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 @@
 	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 @@
 		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 @@
 
 	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 @@
 	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 @@
 #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 @@
 			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 @@
 		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 @@
 	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;
 				}
-				a->pst = NULL;
+				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;
+				}
 			} 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. */
 	}
-	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);
+	/* 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);
+		}
+	}
+#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 @@
  * 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 @@
 	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 @@
 	/*
 	 * 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 @@
  * 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 @@
 			} 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 @@
 	 * 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 @@
 	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 @@
 		}
 	} 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 @@
 #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 @@
 	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 @@
 	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 @@
 	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 @@
 	 * 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 @@
 	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 @@
 	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 @@
 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 @@
 	if (dfacl)
 		acl_free(dfacl);
 	return (ret);
+#endif
 }
 
 static int
@@ -3753,7 +4088,8 @@
 				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 @@
 				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 @@
 			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 @@
 {
 	/* 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 @@
 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 @@
 
 /*
  * 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 @@
 	}
 
 	/*
-	 * 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 @@
 {
 	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 @@
 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 @@
 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 @@
 .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 @@
 {
 	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 @@
 	/*
 	 * 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	'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 @@
 	}
 
 #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_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_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 @@
 	/* 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 @@
 	 * 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 @@
 	 *   - 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 @@
 	 *        :    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 @@
 	 *        :    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 @@
 	/* 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 @@
 	}			 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->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 @@
 	 * 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 @@
 	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 @@
 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 @@
 			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 @@
 		 *    +----+----+----+----+----+
 		 *   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 @@
 					/*
 					 *     flg  len
 					 *    +----+----+
-					 *    | 02 | 00 | CURREENT component.
+					 *    | 02 | 00 | CURRENT component.
 					 *    +----+----+ (".")
 					 */
 					if (nc != NULL) {
@@ -3947,7 +3948,7 @@
 	    "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 @@
 	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 @@
 		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 @@
 		}
 
 		/*
-		 * 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 @@
 			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 @@
 					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 @@
 		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 @@
 	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 @@
 	if (cmp != 0)
 		return (cmp);
 
-	/* Compare indetifier */
+	/* Compare identifier */
 	s1 = p1->identifier;
 	s2 = p2->identifier;
 	l = p1->ext_off;
@@ -6855,7 +6859,7 @@
 	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 @@
 
 	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 @@
 	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 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 @@
 	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 @@
 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 @@
 	 * 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 @@
 	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 @@
 			}
 		}
 
-		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 @@
 	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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 	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 @@
 			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);
-			}
-			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);
+		}
+		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);
 		}
 
 		/* 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 @@
 	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 @@
 	'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 @@
 		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 @@
 		 * 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 @@
 	}
 
 #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 @@
 	'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 @@
 		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 @@
 	}
 
 #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 @@
 	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 @@
  * - 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		*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 @@
 	/*
 	 * 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 @@
 	}			 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 @@
 	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 @@
 		 *   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 @@
 	}
 
 	/*
-	 * Start recoding TOC
+	 * Start recording TOC
 	 */
 	r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
 	if (r < 0) {
@@ -1961,6 +1961,7 @@
 	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 @@
 		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 @@
 	*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 @@
 
 
 #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 @@
 	        || 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 @@
 	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 @@
 }
 
 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 @@
 
 	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 @@
 		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 @@
 .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 @@
 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 @@
 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 @@
 ** 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/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt
index a8e25ba..6632a1e 100644
--- a/Utilities/cmlibuv/CMakeLists.txt
+++ b/Utilities/cmlibuv/CMakeLists.txt
@@ -212,6 +212,7 @@
     nsl
     sendfile
     socket
+    rt
     )
   list(APPEND uv_headers
     include/uv-sunos.h
@@ -223,6 +224,9 @@
     list(APPEND uv_defines
       _XOPEN_SOURCE=500
       )
+    if(CMAKE_C_STANDARD)
+      set(CMAKE_C_STANDARD 90)
+    endif()
   else()
     list(APPEND uv_defines
       _XOPEN_SOURCE=600
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 @@
 #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-unix.h b/Utilities/cmlibuv/include/uv-unix.h
index bca2714..3030f71 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)
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 @@
 
 #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..5879764 100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@ -367,6 +367,8 @@
 } 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);
 
diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c
index 652cd98..1d2cd4a 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;
 
@@ -753,6 +758,13 @@
 
   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 +893,94 @@
 
 
 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;
 
-  buffer[0] = '\0';
+  memcpy(buffer, process_argv[0], len + 1);
+
   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/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 @@
   __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 @@
 # 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/core.c b/Utilities/cmlibuv/src/unix/core.c
index d88fc1d..9ef7134 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -98,7 +98,7 @@
 
 
 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 +517,9 @@
 
 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);
 }
 
@@ -836,13 +839,8 @@
    * 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 +1234,9 @@
 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;
+}
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 @@
 #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 ssize_t uv__fs_scandir(uv_fs_t* req) {
   uv__dirent_t **dents;
-  int saved_errno;
   int n;
 
   dents = NULL;
@@ -374,30 +398,19 @@
   /* 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)
+  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;
+  }
 
   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]);
-    free(dents);
-  }
-  errno = saved_errno;
-
-  req->ptr = NULL;
-
-  return n;
 }
 
 
@@ -798,6 +811,10 @@
   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 @@
   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 @@
     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/internal.h b/Utilities/cmlibuv/src/unix/internal.h
index 2570026..b48f8fa 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 @@
     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
@@ -268,7 +277,6 @@
 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);
diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c
index 909288c..ac28b69 100644
--- a/Utilities/cmlibuv/src/unix/openbsd.c
+++ b/Utilities/cmlibuv/src/unix/openbsd.c
@@ -163,7 +163,7 @@
 int uv_set_process_title(const char* title) {
   uv__free(process_title);
   process_title = uv__strdup(title);
-  setproctitle(title);
+  setproctitle("%s", title);
   return 0;
 }
 
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c
new file mode 100644
index 0000000..2bf3b73
--- /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() {
+  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..be325a9 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,204 @@
 
   return 0;
 }
+
+
+void uv__fs_event_close(uv_fs_event_t* handle) {
+  UNREACHABLE();
+}
+
+
+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__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 */
+}
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 @@
 
 
 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 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/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 @@
     }
 
     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 @@
     }
 
     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/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 @@
   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 @@
   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..dbd8f86 100644
--- a/Utilities/cmlibuv/src/unix/signal.c
+++ b/Utilities/cmlibuv/src/unix/signal.c
@@ -43,7 +43,7 @@
 static void uv__signal_stop(uv_signal_t* handle);
 
 
-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];
@@ -64,7 +64,7 @@
 
 
 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);
 }
 
 
@@ -290,7 +290,7 @@
   sigset_t saved_sigmask;
   int err;
 
-  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
@@ -434,7 +434,7 @@
 
 
 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;
 }
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index d20d0bc..7059df1 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -390,7 +390,7 @@
 
 
 int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
-#if defined(__APPLE__)
+#if defined(__APPLE__) || defined(__MVS__)
   int enable;
 #endif
 
@@ -409,7 +409,7 @@
       return -errno;
   }
 
-#if defined(__APPLE__)
+#if defined(__APPLE__) || defined(__MVS__)
   enable = 1;
   if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
       errno != ENOTSOCK &&
@@ -1194,6 +1194,30 @@
           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 +1245,7 @@
   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;
   }
 
diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c
index 3e7a759..14c58af 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
@@ -695,6 +699,11 @@
   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
@@ -742,9 +751,6 @@
 }
 
 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;
@@ -805,9 +811,8 @@
   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/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 @@
   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 @@
   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/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 @@
 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/win/core.c b/Utilities/cmlibuv/src/win/core.c
index 9d00afc..e84186d 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;
 
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 @@
   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..05fc1d0 100644
--- a/Utilities/cmlibuv/src/win/fs-event.c
+++ b/Utilities/cmlibuv/src/win/fs-event.c
@@ -188,7 +188,6 @@
 
   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 {
     /*
@@ -274,6 +273,8 @@
     goto error;
   }
 
+  assert(is_path_dir ? pathw != NULL : pathw == NULL);
+  handle->dirw = pathw;
   handle->req_pending = 1;
   return 0;
 
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index f1711ac..6902d4f 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -123,7 +123,7 @@
     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);
@@ -403,7 +403,6 @@
   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 +417,6 @@
   if (flags & _O_APPEND) {
     access &= ~FILE_WRITE_DATA;
     access |= FILE_APPEND_DATA;
-    attributes &= ~FILE_FLAG_BACKUP_SEMANTICS;
   }
 
   /*
diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c
index 744f8e0..c13bfec 100644
--- a/Utilities/cmlibuv/src/win/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/win/getaddrinfo.c
@@ -262,8 +262,7 @@
   int err;
 
   if (req == NULL || (node == NULL && service == NULL)) {
-    err = WSAEINVAL;
-    goto error;
+    return UV_EINVAL;
   }
 
   uv_req_init(loop, (uv_req_t*)req);
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 @@
 
           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..bdf88d2 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -492,7 +492,7 @@
    *   input : hello\\"world
    *   output: "hello\\\\\"world"
    *   input : hello world\
-   *   output: "hello world\"
+   *   output: "hello world\\"
    */
 
   *(target++) = L'"';
diff --git a/Utilities/cmlibuv/src/win/signal.c b/Utilities/cmlibuv/src/win/signal.c
index 2c64a55..af7974c 100644
--- a/Utilities/cmlibuv/src/win/signal.c
+++ b/Utilities/cmlibuv/src/win/signal.c
@@ -30,12 +30,14 @@
 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() {
   InitializeCriticalSection(&uv__signal_lock);
+  if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
+    abort();
 }
 
 
@@ -125,102 +127,6 @@
 }
 
 
-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;
 
@@ -247,8 +153,6 @@
 
   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 +166,9 @@
 
 
 int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
-  int err;
-
-  /* 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) {
+  /* 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,13 +188,6 @@
 
   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;
   RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
 
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index 18d68d0..1b7adf6 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
@@ -1003,6 +1004,9 @@
   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 @@
                              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;
+  unsigned int i, len, max_len, pos;
+  int allocate = 0;
 
-#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)
+#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,39 +1660,48 @@
   /* 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;
+      }
+
+      FLUSH_TEXT();
+
+      continue;
     }
 
-    if (!MultiByteToWideChar(CP_UTF8,
-                             0,
-                             buf.base,
-                             buf.len,
-                             utf16_buf,
-                             utf16_buf_used)) {
-      *error = GetLastError();
-      break;
-    }
-
-    FLUSH_TEXT();
-    continue;
-  }
-
     for (j = 0; j < buf.len; j++) {
       unsigned char c = buf.base[j];
 
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 @@
 #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/bootstrap b/bootstrap
index 8063edb..4f58365 100755
--- a/bootstrap
+++ b/bootstrap
@@ -404,6 +404,7 @@
   cmUnsetCommand \
   cmVersion \
   cmWhileCommand \
+  cmWorkingDirectory \
   cmake  \
   cmakemain \
   cmcmd  \