[Pkg-virtualbox-commits] [kbuild] 07/10: New upstream version 0.1.9998svn3098+dfsg

Gianfranco Costamagna locutusofborg at moszumanska.debian.org
Thu Oct 19 15:44:40 UTC 2017


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

locutusofborg pushed a commit to branch experimental
in repository kbuild.

commit fb9427207780db27824338c43a7f8c9c959c935b
Author: Gianfranco Costamagna <locutusofborg at debian.org>
Date:   Thu Oct 19 17:29:23 2017 +0200

    New upstream version 0.1.9998svn3098+dfsg
---
 Config.kmk                                  | 185 +++---
 SlickEdit/kdev.e                            |  48 +-
 bootstrap.gmk                               |   4 +-
 kBuild/env.sh                               |  51 +-
 kBuild/header.kmk                           | 106 ++-
 kBuild/tools/GCC32.kmk                      |   4 +-
 kBuild/tools/GCC64.kmk                      |   4 +-
 kBuild/tools/GXX32.kmk                      |   4 +-
 kBuild/tools/GXX64.kmk                      |   4 +-
 kBuild/tools/VAC308.kmk                     |  20 +-
 kBuild/tools/VCC120.kmk                     | 432 +++++++++++++
 kBuild/tools/VCC120AMD64.kmk                | 465 +++++++++++++
 kBuild/tools/VCC120X86.kmk                  | 465 +++++++++++++
 src/kDepPre/kDepPre.c                       |  12 +-
 src/kObjCache/kObjCache.c                   |  27 +-
 src/kWorker/Makefile.kmk                    |  21 +-
 src/kWorker/kWorker.c                       | 616 +++++++++++++++++-
 src/kWorker/kWorkerTlsXxxK.c                | 110 ++++
 src/kash/Makefile.kmk                       |  21 +-
 src/kash/eval.c                             |   6 +-
 src/kash/exec.c                             |  50 +-
 src/kash/input.c                            |   6 +
 src/kash/mystring.h                         |   2 +-
 src/kash/parser.c                           |  27 +-
 src/kash/shell.h                            |   2 +
 src/kmk/Makefile.am                         |  16 +-
 src/kmk/Makefile.kmk                        |  21 +-
 src/kmk/config.h.netbsd                     | 459 +++++++++++++
 src/kmk/dir.c                               |  10 +-
 src/kmk/expreval.c                          |   6 +-
 src/kmk/glob/glob.h                         |   1 +
 src/kmk/job.c                               |  50 +-
 src/kmk/kbuild-object.c                     |  10 +-
 src/kmk/kbuild.c                            |  40 +-
 src/kmk/kmkbuiltin.c                        | 210 +++---
 src/kmk/kmkbuiltin.h                        |   7 +-
 src/kmk/kmkbuiltin/cmp.c                    |   4 +-
 src/kmk/kmkbuiltin/cmp_util.c               |   6 +-
 src/kmk/kmkbuiltin/common-env-and-cwd-opt.c | 200 ++++--
 src/kmk/kmkbuiltin/echo.c                   |  20 +-
 src/kmk/kmkbuiltin/err.c                    |  22 +-
 src/kmk/kmkbuiltin/install.c                |   4 +
 src/kmk/kmkbuiltin/kDepObj.c                |  24 +-
 src/kmk/kmkbuiltin/kSubmit.c                |  54 +-
 src/kmk/kmkbuiltin/mscfakes.c               |  76 ++-
 src/kmk/kmkbuiltin/mscfakes.h               |  26 +-
 src/kmk/kmkbuiltin/redirect.c               | 212 +++---
 src/kmk/kmkbuiltin/rm.c                     |   4 +
 src/kmk/kmkbuiltin/test.c                   |   4 +-
 src/kmk/kmkbuiltin/touch.c                  | 967 ++++++++++++++++++++++++++++
 src/kmk/main.c                              |  24 +-
 src/kmk/misc.c                              |   4 +-
 src/kmk/strcache.c                          |   2 +-
 src/kmk/strcache2.c                         |  63 +-
 src/kmk/variable.c                          |   2 +-
 src/kmk/variable.h                          |   8 +-
 src/kmk/w32/pathstuff.c                     |   1 -
 src/kmk/w32/subproc/sub_proc.c              |  19 +
 src/lib/Makefile.kmk                        |   3 +-
 src/lib/kDep.c                              |   4 +-
 src/lib/kStuff/include/k/kDefs.h            |  60 +-
 src/lib/kStuff/include/k/kHlpAssert.h       | 125 +++-
 src/lib/kStuff/kLdr/kLdrModLX.c             |  16 +-
 src/lib/kStuff/kLdr/kLdrModMachO.c          |  50 +-
 src/lib/maybe_con_write.c                   |   4 +-
 src/lib/md5.c                               |   2 +-
 src/lib/nt/kFsCache.c                       |  37 +-
 src/lib/nt/nthlp.h                          |  19 +-
 src/lib/nt/nttypes.h                        |  12 +-
 src/lib/nt/ntunlink.c                       |   8 +-
 src/lib/nt/ntunlink.h                       |   3 +-
 src/lib/nt/ntutimes.c                       |  99 +++
 src/lib/nt/{nttypes.h => ntutimes.h}        |  28 +-
 src/sed/Makefile.kmk                        |   6 +-
 src/sed/config.h.netbsd                     | 471 ++++++++++++++
 75 files changed, 5552 insertions(+), 663 deletions(-)

diff --git a/Config.kmk b/Config.kmk
index 176a1b6..816f948 100644
--- a/Config.kmk
+++ b/Config.kmk
@@ -1,4 +1,4 @@
-# $Id: Config.kmk 2870 2016-09-04 13:52:39Z bird $
+# $Id: Config.kmk 3087 2017-10-03 13:31:19Z bird $
 ## @file
 # Build Configuration.
 #
@@ -223,61 +223,13 @@ endif
 
 
 ifeq ($(KBUILD_TARGET),os2)
-TEMPLATE_BIN_TOOL               = GCC3OMF
-TEMPLATE_BIN_CFLAGS             = -g
-TEMPLATE_BIN_CFLAGS.profile     = -pg
-TEMPLATE_BIN_CFLAGS.release     = -O3
-TEMPLATE_BIN_LDFLAGS            = -Zhigh-mem -Zstack=1024 -g
-endif
-
-ifeq ($(KBUILD_TARGET),darwin)
- ifndef KBUILD_MACOSX_VERSION
-  export KBUILD_MACOSX_VERSION := $(expr $(firstword $(subst ., ,$(shell uname -r))) - 4)
- endif
- #ifndef KBUILD_XCODE_VERSION
- # export KBUILD_XCODE_VERSION := $(shell xcodebuild -version | kmk_sed -e '/Xcode/!d' -e 's/Xcode *//')
- #endif
- ifndef KBUILD_MACOSX_TARGET_VERSION
-  if $(KBUILD_TARGET_ARCH) == amd64
-    KBUILD_MACOSX_TARGET_VERSION = 6
-  else
-    KBUILD_MACOSX_TARGET_VERSION = 4
-  endif
- endif
- ifndef KBUILD_MACOSX_WHATEVER_MODE
-  if $(KBUILD_MACOSX_TARGET_VERSION) == 4
-   TOOL_GCC4MACHO_SUFFIX	        = -4.0
-   TOOL_GXX4MACHO_SUFFIX		= -4.0
-  else if $(KBUILD_MACOSX_TARGET_VERSION) >= 5
-   TOOL_GCC4MACHO_SUFFIX	        = -4.2
-   TOOL_GXX4MACHO_SUFFIX		= -4.2
-  endif
-  ifndef KBUILD_MACOSX_SDK
-   KBUILD_MACOSX_SDK            := /Developer/SDKs/MacOSX10.$(KBUILD_MACOSX_TARGET_VERSION)$(if-expr $(KBUILD_MACOSX_TARGET_VERSION)==4,u,).sdk
-   ifeq ($(wildcard $(KBUILD_MACOSX_SDK)),)
-    KBUILD_MACOSX_SDK           := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform$(KBUILD_MACOSX_SDK)
-   endif
-  endif
-  ifeq ($(wildcard $(KBUILD_MACOSX_SDK)),)
-   $(error SDK not found ($(KBUILD_MACOSX_SDK)), please adjust KBUILD_MACOSX_TARGET_VERSION or/and KBUILD_MACOSX_SDK in LocalConfig.kmk or simply use KBUILD_MACOSX_WHATEVER_MODE=1.)
-  endif
- endif # !KBUILD_MACOSX_WHATEVER_MODE
- TEMPLATE_BIN_TOOL              = GCC4MACHO
- TEMPLATE_BIN_CFLAGS            = -g -mmacosx-version-min=10.$(KBUILD_MACOSX_TARGET_VERSION) $(if $(KBUILD_MACOSX_WHATEVER_MODE),,-isysroot $(KBUILD_MACOSX_SDK))
- ifeq ($(USER),bird)
-  TEMPLATE_BIN_CFLAGS          += -Wall $(GCC_Wextra) -pedantic -Wno-unused-parameter -Wno-long-long -Wshadow
-  TEMPLATE_BIN_DEFS            += NO_ENUM_BITFIELDS
- endif
- TEMPLATE_BIN_CFLAGS.profile    = -O3 -pg
+ TEMPLATE_BIN_TOOL              = GCC3OMF
+ TEMPLATE_BIN_CFLAGS            = -g
+ TEMPLATE_BIN_CFLAGS.profile    = -pg
  TEMPLATE_BIN_CFLAGS.release    = -O3
- TEMPLATE_BIN_LDFLAGS           = -g -mmacosx-version-min=10.$(KBUILD_MACOSX_TARGET_VERSION) $(if $(KBUILD_MACOSX_WHATEVER_MODE),,-Wl,-syslibroot,$(KBUILD_MACOSX_SDK))
- if $(KBUILD_MACOSX_TARGET_VERSION) == 4 && $(KBUILD_MACOSX_VERSION) >= 5
-  TEMPLATE_BIN_LDFLAGS         += -classic_ld
- endif
- TEMPLATE_BIN_LDFLAGS.profile   = -pg
-endif
+ TEMPLATE_BIN_LDFLAGS           = -Zhigh-mem -Zstack=1024 -g
 
-ifeq ($(filter-out win nt,$(KBUILD_TARGET)),)
+else if1of ($(KBUILD_TARGET), win nt)
  TEMPLATE_BIN_TOOL              = VCC100
  TEMPLATE_BIN_TOOL.x86          = VCC100X86
  TEMPLATE_BIN_TOOL.amd64        = VCC100AMD64
@@ -319,49 +271,104 @@ ifeq ($(filter-out win nt,$(KBUILD_TARGET)),)
    	$(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/msvcrt.lib
   endif
  endif
-endif
 
-ifndef TEMPLATE_BIN_TOOL
- # Use GCC3 when we're certain that the system is using GNU ld and ar.
- ifeq ($(filter-out linux freebsd openbsd netbsd,$(KBUILD_TARGET)),)
-  TEMPLATE_BIN_TOOL              = GCC3
- else
-  TEMPLATE_BIN_TOOL              = GCC3PLAIN
- endif
- TEMPLATE_BIN_CFLAGS            = -g
- ifeq ($(USER),bird)
-  TEMPLATE_BIN_CFLAGS          += -Wall $(GCC_Wextra) -pedantic -Wno-unused-parameter -Wshadow
-  TEMPLATE_BIN_DEFS            += NO_ENUM_BITFIELDS
- endif
- TEMPLATE_BIN_LDFLAGS           = -g
- TEMPLATE_BIN_LDFLAGS.profile   = -pg -p
- TEMPLATE_BIN_CFLAGS.release    = -O3
- TEMPLATE_BIN_CFLAGS.profile    = -O3 -pg -p
- ifeq ($(KBUILD_TARGET),freebsd)
-  TEMPLATE_BIN_INCS            += $(PATH_GNUMAKE_SRC)/glob /usr/local/include
- endif
- ifeq ($(KBUILD_TARGET),linux)
-  TEMPLATE_BIN_LIBS            += rt
+else # !os2, !win, !nt
+
+ ifeq ($(KBUILD_TARGET),darwin)
+  ifndef KBUILD_MACOSX_VERSION
+   export KBUILD_MACOSX_VERSION := $(expr $(firstword $(subst ., ,$(shell uname -r))) - 4)
+  endif
+  #ifndef KBUILD_XCODE_VERSION
+  # export KBUILD_XCODE_VERSION := $(shell xcodebuild -version | kmk_sed -e '/Xcode/!d' -e 's/Xcode *//')
+  #endif
+  ifndef KBUILD_MACOSX_TARGET_VERSION
+   if $(KBUILD_TARGET_ARCH) == amd64
+     KBUILD_MACOSX_TARGET_VERSION = 6
+   else
+     KBUILD_MACOSX_TARGET_VERSION = 5
+   endif
+  endif
+  ifndef KBUILD_MACOSX_WHATEVER_MODE
+   if $(KBUILD_MACOSX_TARGET_VERSION) == 4
+    TOOL_GCC4MACHO_SUFFIX	        = -4.0
+    TOOL_GXX4MACHO_SUFFIX		= -4.0
+   else if $(KBUILD_MACOSX_TARGET_VERSION) >= 5
+    TOOL_GCC4MACHO_SUFFIX	        = -4.2
+    TOOL_GXX4MACHO_SUFFIX		= -4.2
+   endif
+   ifndef KBUILD_MACOSX_SDK
+    KBUILD_MACOSX_SDK            := /Developer/SDKs/MacOSX10.$(KBUILD_MACOSX_TARGET_VERSION)$(if-expr $(KBUILD_MACOSX_TARGET_VERSION)==4,u,).sdk
+    ifeq ($(wildcard $(KBUILD_MACOSX_SDK)),)
+     KBUILD_MACOSX_SDK           := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform$(KBUILD_MACOSX_SDK)
+    endif
+   endif
+   ifeq ($(wildcard $(KBUILD_MACOSX_SDK)),)
+    $(error SDK not found ($(KBUILD_MACOSX_SDK)), please adjust KBUILD_MACOSX_TARGET_VERSION or/and KBUILD_MACOSX_SDK in LocalConfig.kmk or simply use KBUILD_MACOSX_WHATEVER_MODE=1.)
+   endif
+  endif # !KBUILD_MACOSX_WHATEVER_MODE
+  TEMPLATE_BIN_TOOL              = GCC4MACHO
+  TEMPLATE_BIN_CFLAGS            = -g -mmacosx-version-min=10.$(KBUILD_MACOSX_TARGET_VERSION) $(if $(KBUILD_MACOSX_WHATEVER_MODE),,-isysroot $(KBUILD_MACOSX_SDK))
+  ifeq ($(USER),bird)
+   TEMPLATE_BIN_CFLAGS          += -Wall $(GCC_Wextra) -pedantic -Wno-unused-parameter -Wno-long-long -Wshadow
+   TEMPLATE_BIN_DEFS            += NO_ENUM_BITFIELDS
+  endif
+  TEMPLATE_BIN_CFLAGS.profile    = -O3 -pg
+  TEMPLATE_BIN_CFLAGS.release    = -O3
+  TEMPLATE_BIN_LDFLAGS           = -g -mmacosx-version-min=10.$(KBUILD_MACOSX_TARGET_VERSION) $(if $(KBUILD_MACOSX_WHATEVER_MODE),,-Wl,-syslibroot,$(KBUILD_MACOSX_SDK))
+  if $(KBUILD_MACOSX_TARGET_VERSION) == 4 && $(KBUILD_MACOSX_VERSION) >= 5
+   TEMPLATE_BIN_LDFLAGS         += -classic_ld
+  endif
+  TEMPLATE_BIN_LDFLAGS.profile   = -pg
+
+ else # !darwin
+  # Use GCC3 when we're certain that the system is using GNU ld and ar.
+  ifeq ($(filter-out linux freebsd openbsd netbsd,$(KBUILD_TARGET)),)
+   TEMPLATE_BIN_TOOL              = GCC3
+  else
+   TEMPLATE_BIN_TOOL              = GCC3PLAIN
+  endif
+  TEMPLATE_BIN_CFLAGS            = -g
+  ifeq ($(USER),bird)
+   TEMPLATE_BIN_CFLAGS          += -Wall $(GCC_Wextra) -pedantic -Wno-unused-parameter -Wshadow
+   TEMPLATE_BIN_DEFS            += NO_ENUM_BITFIELDS
+  endif
+  TEMPLATE_BIN_LDFLAGS           = -g
+  TEMPLATE_BIN_LDFLAGS.profile   = -pg -p
+  TEMPLATE_BIN_CFLAGS.release    = -O3
+  TEMPLATE_BIN_CFLAGS.profile    = -O3 -pg -p
+  ifeq ($(KBUILD_TARGET),freebsd)
+   TEMPLATE_BIN_INCS            += $(PATH_GNUMAKE_SRC)/glob /usr/local/include
+  endif
+  ifeq ($(KBUILD_TARGET),linux)
+   TEMPLATE_BIN_LIBS            += rt
+  endif
  endif
-  TEMPLATE_BIN_CFLAGS.x86      += -m32
-  TEMPLATE_BIN_CFLAGS.sparc32  += -m32
-  TEMPLATE_BIN_CFLAGS.amd64    += -m64
-  TEMPLATE_BIN_CFLAGS.sparc64  += -m64
-  TEMPLATE_BIN_CXXFLAGS.x86    += -m32
-  TEMPLATE_BIN_CXXFLAGS.sparc32+= -m32
-  TEMPLATE_BIN_CXXFLAGS.amd64  += -m64
-  TEMPLATE_BIN_CXXFLAGS.sparc64+= -m64
-  TEMPLATE_BIN_LDFLAGS.x86     += -m32
-  TEMPLATE_BIN_LDFLAGS.sparc32 += -m32
-  TEMPLATE_BIN_LDFLAGS.amd64   += -m64
-  TEMPLATE_BIN_LDFLAGS.sparc64 += -m64
+
+ # Make sure we get the right bit count in the output.
+ TEMPLATE_BIN_CFLAGS.x86       += -m32
+ TEMPLATE_BIN_CFLAGS.sparc32   += -m32
+ TEMPLATE_BIN_CFLAGS.amd64     += -m64
+ TEMPLATE_BIN_CFLAGS.sparc64   += -m64
+ TEMPLATE_BIN_CXXFLAGS.x86     += -m32
+ TEMPLATE_BIN_CXXFLAGS.sparc32 += -m32
+ TEMPLATE_BIN_CXXFLAGS.amd64   += -m64
+ TEMPLATE_BIN_CXXFLAGS.sparc64 += -m64
+ TEMPLATE_BIN_LDFLAGS.x86      += -m32
+ TEMPLATE_BIN_LDFLAGS.sparc32  += -m32
+ TEMPLATE_BIN_LDFLAGS.amd64    += -m64
+ TEMPLATE_BIN_LDFLAGS.sparc64  += -m64
  ifeq ($(KBUILD_TARGET),solaris)
   TEMPLATE_BIN_LIBS            += rt dl
   TEMPLATE_BIN_LDFLAGS         += -Wl,-i
   TEMPLATE_BIN_DEFS.x86        += _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE
   TEMPLATE_BIN_DEFS.sparc32    += _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE
  endif
+ ifeq ($(KBUILD_TARGET),netbsd)
+  TEMPLATE_BIN_LIBS            += util
+ endif
 endif
+
+# On systems where it's possible, do split out the debug info from the binaries.
 if1of ($(KBUILD_TARGET), darwin win)
  TEMPLATE_BIN_LD_DEBUG = split
 endif
@@ -372,7 +379,7 @@ endif
 TEMPLATE_BIN-THREADED = Threaded command line binary
 TEMPLATE_BIN-THREADED_EXTENDS = BIN
 TEMPLATE_BIN-THREADED_EXTENDS_BY = appending
-if1of ($(KBUILD_TARGET), dragonfly freebsd linux openbsd)
+if1of ($(KBUILD_TARGET), dragonfly freebsd gnukfbsd gnuknbsd linux netbsd openbsd)
  TEMPLATE_BIN-THREADED_LIBS = pthread
 endif
 
diff --git a/SlickEdit/kdev.e b/SlickEdit/kdev.e
index 46d7940..476d437 100644
--- a/SlickEdit/kdev.e
+++ b/SlickEdit/kdev.e
@@ -1,4 +1,4 @@
-/* $Id: kdev.e 3018 2017-01-07 00:06:39Z bird $  -*- tab-width: 4 c-indent-level: 4 -*- */
+/* $Id: kdev.e 3069 2017-10-02 06:28:54Z bird $  -*- tab-width: 4 c-indent-level: 4 -*- */
 /** @file
  * Visual SlickEdit Documentation Macros.
  */
@@ -66,6 +66,7 @@ def  'C-S-G' = k_box_globals
 def  'C-S-H' = k_box_headers
 def  'C-S-I' = k_box_intfuncs
 def  'C-S-K' = k_box_consts
+def  'C-S-N' = k_noref
 def  'C-S-M' = k_javadoc_moduleheader
 def  'C-S-O' = k_oneliner
 def  'C-S-P' = k_mark_modified_line
@@ -1561,8 +1562,6 @@ void k_box_exported()
     k_box_end();
 }
 
-
-
 /** oneliner comment */
 void k_oneliner()
 {
@@ -1600,7 +1599,6 @@ void k_mark_modified_line()
     down();
 }
 
-
 /**
  * Inserts a signature. Form: "//Initials ISO-date:"
  * @remark    defeventtab
@@ -1616,6 +1614,48 @@ void k_signature()
     k_insert_comment(sSig, KIC_CURSOR_AT_END);
 }
 
+/* Insert a list of NOREF() macro invocations. */
+void k_noref()
+{
+    typeless org_pos;
+    _save_pos2(org_pos);
+
+    _str sNoRefs = '';
+    boolean fFoundFn = !k_func_goto_nearest_function();
+    if (fFoundFn)
+    {
+        _str sArgs = k_func_getparams();
+        int  cArgs = k_func_countparams(sArgs);
+        int  i;
+        int  offLine = 4;
+        for (i = 0; i < cArgs; i++)
+        {
+            _str sName, sType, sDefault;
+            if (!k_func_enumparams(sArgs, i, sType, sName, sDefault))
+            {
+                sThis = 'NOREF(' sName ');';
+                if (length(sNoRefs) == 0)
+                {
+                    sNoRefs = sThis;
+                    offLine += length(sThis);
+                }
+                else if (offLine + length(sThis) < 130)
+                {
+                    sNoRefs = sNoRefs ' ' sThis;
+                    offLine += 1 + length(sThis);
+                }
+                else
+                {
+                    sNoRefs = sNoRefs "\n    " sThis;
+                    offLine = 4 + length(sThis);
+                }
+            }
+        }
+    }
+
+    _restore_pos2(org_pos);
+    _insert_text(sNoRefs);
+}
 
 /*******************************************************************************
 *   kLIB Logging                                                               *
diff --git a/bootstrap.gmk b/bootstrap.gmk
index 8cbb233..7f4b1cb 100644
--- a/bootstrap.gmk
+++ b/bootstrap.gmk
@@ -1,4 +1,4 @@
-# $Id: bootstrap.gmk 2421 2010-10-17 21:27:53Z bird $
+# $Id: bootstrap.gmk 3028 2017-04-13 13:31:34Z bird $
 ## @file
 # GNU Make Compatible bootstrap Makefile.
 #
@@ -36,7 +36,7 @@
 #   - echo done > some-file works.
 #   - Recent GNU make that implements CURDIR, $(error) and ifdef.
 #
-# Tip: kBuild/env.sh --full (g(nu))make -f bootstrap.kmk
+# Tip: kBuild/env.sh --full (g(nu))make -f bootstrap.gmk
 #
 # Note to self on bootstrapping solaris.sparc64:
 #   SED_MAKE_DEFS="SED=gsed" AUTOPOINT=true ACLOCAL=aclocal-1.10 AUTOMAKE=automake-1.10 nice ./kBuild/env.sh --full gmake -f bootstrap.gmk
diff --git a/kBuild/env.sh b/kBuild/env.sh
index b832cf2..7be6315 100755
--- a/kBuild/env.sh
+++ b/kBuild/env.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: env.sh 2546 2011-10-01 19:49:54Z bird $
+# $Id: env.sh 3062 2017-09-30 11:26:21Z bird $
 ## @file
 # Environment setup script.
 #
@@ -329,22 +329,28 @@ if test -z "$KBUILD_HOST_ARCH"; then
         x86|i86pc|ia32|i[3456789]86|BePC)
             KBUILD_HOST_ARCH='x86'
             ;;
-        sparc32|sparc|sparcv8|sparcv7|sparcv8e)
-            KBUILD_HOST_ARCH='sparc32'
+        alpha)
+            KBUILD_HOST_ARCH='alpha'
             ;;
-        sparc64|sparcv9)
-            KBUILD_HOST_ARCH='sparc64'
+        aarch32|arm|arm1|arm2|arm3|arm6|armv1|armv2|armv3*|armv4*|armv5*|armv6*|armv7*)
+            KBUILD_HOST_ARCH='arm32'
             ;;
-        s390)
-            KBUILD_HOST_ARCH='s390'
+        aarch64*)
+            KBUILD_HOST_ARCH='arm64'
             ;;
-        s390x)
-            KBUILD_HOST_ARCH='s390x'
+        hppa32|parisc32|parisc)
+            KBUILD_HOST_ARCH='hppa32'
+            ;;
+        hppa64|parisc64)
+            KBUILD_HOST_ARCH='hppa64'
+            ;;
+        ia64)
+            KBUILD_HOST_ARCH='ia64'
             ;;
         ppc32|ppc|powerpc)
             KBUILD_HOST_ARCH='ppc32'
             ;;
-        ppc64|powerpc64)
+        ppc64|ppc64le|powerpc64|powerpc64le)
             KBUILD_HOST_ARCH='ppc64'
             ;;
         mips32|mips)
@@ -353,20 +359,23 @@ if test -z "$KBUILD_HOST_ARCH"; then
         mips64)
             KBUILD_HOST_ARCH='mips64'
             ;;
-        ia64)
-            KBUILD_HOST_ARCH='ia64'
-            ;;
-        hppa32|parisc32|parisc)
-            KBUILD_HOST_ARCH='hppa32'
+        s390)
+            KBUILD_HOST_ARCH='s390'
             ;;
-        hppa64|parisc64)
-            KBUILD_HOST_ARCH='hppa64'
+        s390x)
+            KBUILD_HOST_ARCH='s390x'
             ;;
-        arm|armv4l|armv5tel|armv5tejl)
-            KBUILD_HOST_ARCH='arm'
+	sh|sh2|sh2a|sh3|sh3|sh4|sh4a|sh4al|sh4al-dsp|shmedia)
+	    KBUILD_HOST_ARCH='sh32'
+	    ;;
+        sh64)
+	    KBUILD_HOST_ARCH='sh64'
+	    ;;
+        sparc32|sparc|sparcv8|sparcv7|sparcv8e)
+            KBUILD_HOST_ARCH='sparc32'
             ;;
-        alpha)
-            KBUILD_HOST_ARCH='alpha'
+        sparc64|sparcv9)
+            KBUILD_HOST_ARCH='sparc64'
             ;;
 
         *)  echo "$0: unknown cpu/arch - $KBUILD_HOST_ARCH" 1>&${ERR_REDIR}
diff --git a/kBuild/header.kmk b/kBuild/header.kmk
index 21a0e3d..648a03f 100644
--- a/kBuild/header.kmk
+++ b/kBuild/header.kmk
@@ -1,4 +1,4 @@
-# $Id: header.kmk 2971 2016-09-27 11:25:09Z bird $
+# $Id: header.kmk 3093 2017-10-13 13:07:39Z bird $
 ## @file
 # kBuild - File included at top of a makefile.
 #
@@ -79,7 +79,7 @@ endif
 # The revision in which this file was last modified.
 # This can be useful when using development versions of kBuild.
 #
-KMK_REVISION := $(patsubst %:,,  $Rev: 2971 $  )
+KMK_REVISION := $(patsubst %:,,  $Rev: 3093 $  )
 
 
 #
@@ -170,6 +170,14 @@ SQUOTE := '
 # Double quote character.
 DQUOTE := "
 
+##
+# Opening parenthesis.
+OPENPAR := (
+
+##
+# Closing parenthesis.
+CLOSEPAR := )
+
 
 #
 # The list of standard build types in kBuild.
@@ -188,10 +196,11 @@ KBUILD_BLD_TYPES := release profile debug
 # this keyword namespace is shared between OSes, architectures, cpus and
 # build types. (PORTME)
 #
-KBUILD_OSES      := darwin dos dragonfly freebsd haiku l4 linux netbsd nt openbsd os2 solaris win os-agnostic
-KBUILD_ARCHES    := x86 amd64 sparc32 sparc64 s390 s390x ppc32 ppc64 mips32 mips64 ia64 hppa32 hppa64 arm alpha noarch
-KBUILD_ARCHES_64 := amd64 sparc64 s390x ppc64 mips64 ia64 hppa64 alpha
-KBUILD_ARCHES_32 := x86 sparc32 s390 ppc32 mips32 hppa32 arm
+KBUILD_OSES      := darwin dos dragonfly freebsd gnukfbsd gnuknbsd haiku l4 linux netbsd nt openbsd os2 solaris win os-agnostic
+KBUILD_ARCHES    := x86 amd64 noarch alpha arm32 arm64 hppa32 hppa64 ia64 mips32 mips64 ppc32 ppc64 s390 s390x sh32 sh64 sparc32 sparc64
+KBUILD_ARCHES_64 := amd64 alpha arm64 hppa64 ia64 mips64 ppc64 s390x sh64 sparc64
+KBUILD_ARCHES_32 := x86 arm32 hppa32 mips32 ppc32 s390 sh32 sparc32
+
 
 
 #
@@ -585,21 +594,25 @@ if1of ($(KBUILD_HOST), win nt)
 # Win, Win32, Win64, NT.
 EXEC_X86_WIN32      :=
 HOSTSUFF_EXE        := .exe
+HOST_PATH_SEP       := $(SEMICOLON)
 
 # OS/2.
 else ifeq ($(KBUILD_HOST),os2)
 EXEC_X86_WIN32      := innopec.exe
 HOSTSUFF_EXE        := .exe
+HOST_PATH_SEP       := $(SEMICOLON)
 
-else if1of ($(KBUILD_HOST), freebsd dragonfly linux openbsd netbsd)
+else if1of ($(KBUILD_HOST), dragonfly freebsd gnukfbsd gnuknbsd linux openbsd netbsd)
 # Unix (like) systems with wine.
 EXEC_X86_WIN32      := wine
 HOSTSUFF_EXE        :=
+HOST_PATH_SEP       := $(COLON)
 
 else
 # Unix (like) systems without wine.
 EXEC_X86_WIN32      := false
 HOSTSUFF_EXE        :=
+HOST_PATH_SEP       := $(COLON)
 endif
 
 
@@ -635,7 +648,7 @@ SUFF_OBJ    := .o
 SUFF_LIB    := .a
 SUFF_DLL    := .so
 SUFF_EXE    :=
- if1of ($(KBUILD_TARGET), dragonfly freebsd linux netbsd openbsd) ## @todo check netbsd and openbsd.
+ if1of ($(KBUILD_TARGET), dragonfly freebsd gnukfbsd gnuknbsd linux netbsd openbsd) ## @todo check netbsd, gnuknbsd and openbsd.
 SUFF_SYS    := .ko
  else
 SUFF_SYS    :=
@@ -757,6 +770,14 @@ TIME_EXT    := $(KBUILD_BIN_PATH)/kmk_time$(HOSTSUFF_EXE)
 TIME_INT    := $(TIME_EXT)
 TIME        := $(TIME_INT)
 
+TOUCH_EXT   := $(KBUILD_BIN_PATH)/kmk_touch$(HOSTSUFF_EXE)
+if $(KBUILD_KMK_REVISION) >= 3060
+TOUCH_INT   := kmk_builtin_touch
+else
+TOUCH_INT   := $(TOUCH_EXT)
+endif
+TOUCH       := $(TOUCH_INT)
+
 # Our default shell is the Almquist shell from *BSD.
 ASH         := $(KBUILD_BIN_PATH)/kmk_ash$(HOSTSUFF_EXE)
 MAKESHELL   := $(ASH)
@@ -946,6 +967,50 @@ endif
 
 
 #
+# Somewhat simple solution for automatic command dependencies.
+#
+
+##
+# Advanced version of KB_FN_AUTO_CMD_DEPS_COMMANDS_EX where you set
+# the dependency file name yourself.
+#
+# After or before the recipe do $(call KB_FN_AUTO_CMD_DEPS_EX,<recipe-target>,<dep-file>).
+#
+# @param 1    dep file.
+define KB_FN_AUTO_CMD_DEPS_COMMANDS_EX
+	%$(QUIET2)$(RM) -f -- "$1"
+       %$(QUIET2)$(APPEND) "$1" 'define AUTO_CMD_DEP_$(translate $@,:,_)_PREV_CMDS'
+       %$(QUIET2)$(APPEND) -c "$1"  '$@'
+       %$(QUIET2)$(APPEND) "$1" 'endef'
+endef
+
+##
+# Advanced version of KB_FN_AUTO_CMD_DEPS
+#
+# @param 1     recipe name
+# @param 2     dep file.
+KB_FN_AUTO_CMD_DEPS_EX = $(eval includedep $2)$(eval _DEPFILES_INCLUDED += $2)$1: .MUST_MAKE = $$(comp-cmds-ex $$(AUTO_CMD_DEP_$(translate $1,:,_)_PREV_CMDS),$$(commands $1),FORCE)
+
+##
+# $(call KB_FN_AUTO_CMD_DEPS_COMMANDS) as the first command in a recipe to
+# automatically generate command dependencies.
+# After or before the recipe do $(call KB_FN_AUTO_CMD_DEPS,<recipe-target>).
+define KB_FN_AUTO_CMD_DEPS_COMMANDS
+	%$(QUIET2)$(RM) -f -- "$@.auto-dep"
+       %$(QUIET2)$(APPEND) "$@.auto-dep" 'define AUTO_CMD_DEP_$(translate $@,:,_)_PREV_CMDS'
+       %$(QUIET2)$(APPEND) -c "$@.auto-dep"  '$@'
+       %$(QUIET2)$(APPEND) "$@.auto-dep" 'endef'
+endef
+
+##
+# Call before or after defining a recipe that you want automatic command
+# dependencies on. The recipe must start off by $(call KB_FN_AUTO_CMD_DEPS_COMMANDS).
+#
+# @param 1     recipe name
+KB_FN_AUTO_CMD_DEPS = $(call KB_FN_AUTO_CMD_DEPS_EX,$1,$1.auto-dep)
+
+
+#
 # Initialize some of the globals which the Config.kmk and
 # others can add stuff to if they like for processing in the footer.
 #
@@ -1317,14 +1382,22 @@ ifeq ($(KBUILD_TARGET),darwin)
 	/Developer/usr/
  KBUILD_LIB_SEARCH_SUBS  := lib/
 
-else if1of ($(KBUILD_TARGET), freebsd netbsd openbsd dragonfly)
+else if1of ($(KBUILD_TARGET), freebsd openbsd dragonfly)
+ KBUILD_LIB_SEARCH_ROOTS := \
+	/ \
+	/usr/ \
+	/usr/local/
+ KBUILD_LIB_SEARCH_SUBS := lib/
+
+else ifeq ($(KBUILD_TARGET),netbsd)
  KBUILD_LIB_SEARCH_ROOTS := \
 	/ \
 	/usr/ \
+	/usr/pkg/ \
 	/usr/local/
  KBUILD_LIB_SEARCH_SUBS := lib/
 
-else ifeq ($(KBUILD_TARGET),linux)
+else if1of ($(KBUILD_TARGET), gnukfbsd gnuknbsd linux)
  ifeq ($(realpath /bin),/usr/bin)
   KBUILD_LIB_SEARCH_ROOTS := \
   	/usr/ \
@@ -1601,9 +1674,11 @@ else
 endif
 
 
+##
+# An internal define used by subheader.kmk, subfooter.kmk, and
+# KB_FN_PASS_0_ON_TARGET.
 #
-# An internal define used by subheader.kmk and subfooter.kmk.
-# We keep them here to avoid redefining them for each sub-makefile.
+# @param target    The target to process.
 #
 define def_subfooter_header_target_pass
  ifndef $(target)_PATH
@@ -1623,6 +1698,13 @@ define def_subfooter_header_target_pass
  endif
 endef
 
+##
+# Function to call to set _0_OUTDIR, _DEFPATH, and _MAKEFILE earlier than subfooter.
+# Can be used to avoid exploiting double expansion.
+#
+# @param 1     The target name.
+KB_FN_DO_PASS0_ON_TARGET = $(foreach target,$1,$(if-expr defined($(target)_0_OUTDIR),,$(evalval def_subfooter_header_target_pass)))
+
 
 #
 # Validate any KBUILD_BLD_TYPES additions and finally the KBUILD_TYPE.
diff --git a/kBuild/tools/GCC32.kmk b/kBuild/tools/GCC32.kmk
index 595e78a..88fb941 100644
--- a/kBuild/tools/GCC32.kmk
+++ b/kBuild/tools/GCC32.kmk
@@ -1,4 +1,4 @@
-# $Id: GCC32.kmk 2775 2015-02-03 20:00:15Z bird $
+# $Id: GCC32.kmk 3062 2017-09-30 11:26:21Z bird $
 ## @file
 # kBuild Tool Config - Generic 32-bit GCC v3.2.x or later Using The System GCC.
 #
@@ -46,7 +46,7 @@ TOOL_GCC32_LDFLAGS.dll ?= -shared
 else
 TOOL_GCC32_LDFLAGS.dll ?= $(TOOL_GCC32_LDFLAGS.$(KBUILD_TARGET))
 endif
-TOOL_GCC32_LDFLAGS.sysmod ?= -r -m elf_i386$(if-expr "$(KBUILD_TARGET)" == "freebsd",_fbsd,)
+TOOL_GCC32_LDFLAGS.sysmod ?= -r -m elf_i386$(if-expr "$(KBUILD_TARGET)" == "freebsd" || "$(KBUILD_TARGET)" == "gnukfbsd",_fbsd,)
 TOOL_GCC32_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
 ifeq ($(KBUILD_TARGET),os2)
 TOOL_GCC32_LD_MAP ?= -Zmap=$(1)
diff --git a/kBuild/tools/GCC64.kmk b/kBuild/tools/GCC64.kmk
index 586f737..154f7d8 100644
--- a/kBuild/tools/GCC64.kmk
+++ b/kBuild/tools/GCC64.kmk
@@ -1,4 +1,4 @@
-# $Id: GCC64.kmk 2774 2015-02-03 19:56:24Z bird $
+# $Id: GCC64.kmk 3062 2017-09-30 11:26:21Z bird $
 ## @file
 # kBuild Tool Config - Generic 64-bit GCC v3.2.x or later Using The System GCC.
 #
@@ -46,7 +46,7 @@ TOOL_GCC64_LDFLAGS.dll ?= -shared
 else
 TOOL_GCC64_LDFLAGS.dll ?= $(TOOL_GCC64_LDFLAGS.$(KBUILD_TARGET))
 endif
-TOOL_GCC64_LDFLAGS.sysmod ?= -r -m elf_x86_64$(if-expr "$(KBUILD_TARGET)" == "freebsd",_fbsd,)
+TOOL_GCC64_LDFLAGS.sysmod ?= -r -m elf_x86_64$(if-expr "$(KBUILD_TARGET)" == "freebsd" || "$(KBUILD_TARGET)" == "gnukfbsd",_fbsd,)
 TOOL_GCC64_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
 ifeq ($(KBUILD_TARGET),os2)
 TOOL_GCC64_LD_MAP ?= -Zmap=$(1)
diff --git a/kBuild/tools/GXX32.kmk b/kBuild/tools/GXX32.kmk
index 49463d2..cda007f 100644
--- a/kBuild/tools/GXX32.kmk
+++ b/kBuild/tools/GXX32.kmk
@@ -1,4 +1,4 @@
-# $Id: GXX32.kmk 2775 2015-02-03 20:00:15Z bird $
+# $Id: GXX32.kmk 3062 2017-09-30 11:26:21Z bird $
 ## @file
 # kBuild Tool Config - Generic 32-bit GCC v3.2.x or later using the system GCC, for building C++ code.
 #
@@ -46,7 +46,7 @@ TOOL_GXX32_LDFLAGS.dll ?= -shared
 else
 TOOL_GXX32_LDFLAGS.dll ?= $(TOOL_GXX32_LDFLAGS.$(KBUILD_TARGET))
 endif
-TOOL_GXX32_LDFLAGS.sysmod ?= -r -m elf_i386$(if-expr "$(KBUILD_TARGET)" == "freebsd",_fbsd,)
+TOOL_GXX32_LDFLAGS.sysmod ?= -r -m elf_i386$(if-expr "$(KBUILD_TARGET)" == "freebsd" || "$(KBUILD_TARGET)" == "gnukfbsd",_fbsd,)
 TOOL_GXX32_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
 ifeq ($(KBUILD_TARGET),os2)
 TOOL_GXX32_LD_MAP ?= -Zmap=$(1)
diff --git a/kBuild/tools/GXX64.kmk b/kBuild/tools/GXX64.kmk
index 03973fc..0c319ea 100644
--- a/kBuild/tools/GXX64.kmk
+++ b/kBuild/tools/GXX64.kmk
@@ -1,4 +1,4 @@
-# $Id: GXX64.kmk 2774 2015-02-03 19:56:24Z bird $
+# $Id: GXX64.kmk 3062 2017-09-30 11:26:21Z bird $
 ## @file
 # kBuild Tool Config - Generic 64-bit GCC v3.2.x or later using the system GCC, for building C++ code.
 #
@@ -46,7 +46,7 @@ TOOL_GXX64_LDFLAGS.dll ?= -shared
 else
 TOOL_GXX64_LDFLAGS.dll ?= $(TOOL_GXX64_LDFLAGS.$(KBUILD_TARGET))
 endif
-TOOL_GXX64_LDFLAGS.sysmod ?= -r -m elf_x86_64$(if-expr "$(KBUILD_TARGET)" == "freebsd",_fbsd,)
+TOOL_GXX64_LDFLAGS.sysmod ?= -r -m elf_x86_64$(if-expr "$(KBUILD_TARGET)" == "freebsd" || "$(KBUILD_TARGET)" == "gnukfbsd",_fbsd,)
 TOOL_GXX64_LD_SONAME ?= -Wl,-soname=$(firstword $($(1)_SONAME.$(KBUILD_TARGET).$(KBUILD_TYPE)) $($(1)_SONAME.$(KBUILD_TARGET)) $($(1)_SONAME.$(KBUILD_TYPE)) $($(1)_SONAME) $(notdir $(2)))
 ifeq ($(KBUILD_TARGET),os2)
 TOOL_GXX64_LD_MAP ?= -Zmap=$(1)
diff --git a/kBuild/tools/VAC308.kmk b/kBuild/tools/VAC308.kmk
index 8899f19..7b9e78f 100644
--- a/kBuild/tools/VAC308.kmk
+++ b/kBuild/tools/VAC308.kmk
@@ -1,4 +1,4 @@
-# $Id: VAC308.kmk 3023 2017-01-07 17:24:57Z bird $
+# $Id: VAC308.kmk 3055 2017-08-31 15:34:33Z bird $
 ## @file
 # kBuild Tool Config - VisualAge for C++ v3.08.
 #
@@ -68,6 +68,7 @@ ifneq ($(PATH_TOOL_VAC308),)
 	-E 'DPATH=$(PATH_TOOL_VAC308_LOCALE);$(PATH_TOOL_VAC308_HELP);$(DPATH)' \
 	-E 'LIB=$1' \
 	-E 'INCLUDE=' \
+	$2 \
 	--
  TOOL_VAC308_CC  ?= $(PATH_TOOL_VAC308_BIN)/icc$(HOSTSUFF_EXE)
  TOOL_VAC308_CXX ?= $(PATH_TOOL_VAC308_BIN)/icc$(HOSTSUFF_EXE)
@@ -81,6 +82,7 @@ else
  TOOL_VAC308_ENV_SETUP ?= $(REDIRECT) \
 	-E 'LIB=$1' \
 	-E 'INCLUDE=' \
+	$2 \
 	--
  TOOL_VAC308_CC  ?= icc$(HOSTSUFF_EXE)
  TOOL_VAC308_CXX ?= icc$(HOSTSUFF_EXE)
@@ -125,30 +127,30 @@ TOOL_VAC308_LDFLAGS.debug    ?= -Ti+
 
 TOOL_VAC308_COMPILE_C_DEPEND =
 TOOL_VAC308_COMPILE_C_DEPORD =
-TOOL_VAC308_COMPILE_C_OUTPUT =
+TOOL_VAC308_COMPILE_C_OUTPUT = $(obj).ii
 define TOOL_VAC308_COMPILE_C_CMDS
 	$(QUIET) $(call TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CC) -c\
 		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
 		-Fo$(obj)\
 		$(abspath $(source))
-	$(QUIET) $(call TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CC) -P+ -Pd+ \
+	$(QUIET) $(call TOOL_VAC308_ENV_SETUP,,-wo $(obj).ii) $(TOOL_VAC308_CC) -P+ -Pd+ \
 		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
-		$(abspath $(source)) \
-		| $(DEP_PRE) -f -s -o $(dep) -t $(obj) -
+		$(abspath $(source)) 
+	$(QUIET)$(DEP_PRE) -f -s -o $(dep) -t $(obj) $(obj).ii
 endef
 
 TOOL_VAC308_COMPILE_CXX_DEPEND =
 TOOL_VAC308_COMPILE_CXX_DEPORD =
-TOOL_VAC308_COMPILE_CXX_OUTPUT =
+TOOL_VAC308_COMPILE_CXX_OUTPUT = $(obj).ii
 define TOOL_VAC308_COMPILE_CXX_CMDS
 	$(QUIET) $(call TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CXX) -c\
 		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
 		-Fo$(obj)\
 		$(abspath $(source))
-	$(QUIET) $(call TOOL_VAC308_ENV_SETUP) $(TOOL_VAC308_CXX) -P+ -Pd+ \
+	$(QUIET) $(call TOOL_VAC308_ENV_SETUP,,-wo $(obj).ii) $(TOOL_VAC308_CXX) -P+ -Pd+ \
 		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
-		$(abspath $(source)) \
-		| $(DEP_PRE) -f -s -o $(dep) -t $(obj) -
+		$(abspath $(source))
+	$(QUIET)$(DEP_PRE) -f -s -o $(dep) -t $(obj) $(obj).ii
 endef
 
 TOOL_VAC308_COMPILE_RC_OUTPUT =
diff --git a/kBuild/tools/VCC120.kmk b/kBuild/tools/VCC120.kmk
new file mode 100644
index 0000000..eb67a1b
--- /dev/null
+++ b/kBuild/tools/VCC120.kmk
@@ -0,0 +1,432 @@
+# $Id: VCC120.kmk 3037 2017-05-10 09:24:06Z bird $
+## @file
+# kBuild Tool Config - Visual C++ 12.0 (aka Visual 2013 and MSC v18), targeting $(KBUILD_TARGET).
+#
+
+#
+# Copyright (c) 2004-2017 knut st. osmundsen <bird-kBuild-spam-xiv at anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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 of the License, or
+# (at your option) any later version.
+#
+# kBuild is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_VCC120 := Visual C++ 12.0 (aka Visual 2013 and MSC v18), targeting $(KBUILD_TARGET).
+
+# Tool Specific Properties
+ifndef PATH_TOOL_VCC120
+ PATH_TOOL_VCC120 := $(wildcard $(KBUILD_DEVTOOLS_TRG)/vcc/v12*)
+ ifeq ($(PATH_TOOL_VCC120),)
+  PATH_TOOL_VCC120 := $(wildcard $(KBUILD_DEVTOOLS)/win.x86/vcc/v12*)
+ endif
+ ifeq ($(PATH_TOOL_VCC120),)
+  PATH_TOOL_VCC120 := $(wildcard $(KBUILD_DEVTOOLS)/x86.win32/vcc/v12*)
+ endif
+ ifeq ($(PATH_TOOL_VCC120),)
+  PATH_TOOL_VCC120 := $(wildcard $(KBUILD_DEVTOOLS)/win.amd64/vcc/v12*)
+ endif
+ ifeq ($(PATH_TOOL_VCC120),)
+  PATH_TOOL_VCC120 := $(lastword $(sort $(PATH_TOOL_VCC120)))
+ endif
+ # if not found, we'll enter 'pathless' mode.
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_VCC120 := $(PATH_TOOL_VCC120)
+endif
+ifneq ($(PATH_TOOL_VCC120),)
+ if "$(KBUILD_HOST).$(KBUILD_HOST_ARCH)" == "win.amd64" && exists("$(PATH_TOOL_VCC120AMD64)/bin/amd64") # Missing in express edition.
+ PATH_TOOL_VCC120_BIN.amd64 ?= $(PATH_TOOL_VCC120)/bin/amd64
+ else
+ PATH_TOOL_VCC120_BIN.amd64 ?= $(PATH_TOOL_VCC120)/bin/x86_amd64
+ endif
+ PATH_TOOL_VCC120_BIN.x86   ?= $(PATH_TOOL_VCC120)/bin
+ PATH_TOOL_VCC120_BIN       ?= $(PATH_TOOL_VCC120_BIN.$(KBUILD_TARGET_ARCH))
+ PATH_TOOL_VCC120_LIB.amd64 ?= $(PATH_TOOL_VCC120)/lib/amd64
+ PATH_TOOL_VCC120_LIB.x86   ?= $(PATH_TOOL_VCC120)/lib
+ PATH_TOOL_VCC120_LIB       ?= $(PATH_TOOL_VCC120_LIB.$(KBUILD_TARGET_ARCH))
+ PATH_TOOL_VCC120_INC       ?= $(PATH_TOOL_VCC120)/include
+ PATH_TOOL_VCC120_ATLMFC    ?= $(PATH_TOOL_VCC120X86)/atlmfc
+ PATH_TOOL_VCC120_ATLMFC_INC       ?= $(PATH_TOOL_VCC120_ATLMFC)/include
+ PATH_TOOL_VCC120_ATLMFC_LIB.amd64 ?= $(PATH_TOOL_VCC120_ATLMFC)/lib
+ PATH_TOOL_VCC120_ATLMFC_LIB.x86   ?= $(PATH_TOOL_VCC120_ATLMFC)/lib/amd64
+ PATH_TOOL_VCC120_ATLMFC_LIB       ?= $(PATH_TOOL_VCC120_ATLMFC_LIB.$(KBUILD_TARGET_ARCH))
+ TOOL_VCC120_CC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120_BIN)/cl.exe
+ TOOL_VCC120_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120_BIN)/cl.exe
+ TOOL_VCC120_AS  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120_BIN)/ml64.exe
+ TOOL_VCC120_AR  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120_BIN)/lib.exe
+ TOOL_VCC120_LD  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120_BIN)/link.exe
+ TOOL_VCC120_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120_BIN)/dumpbin.exe
+ TOOL_VCC120_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120_BIN)/editbin.exe
+else
+ # Pathless, relies on the environment.
+ TOOL_VCC120_CC  ?= $(EXEC_X86_WIN32) cl.exe
+ TOOL_VCC120_CXX ?= $(EXEC_X86_WIN32) cl.exe
+ TOOL_VCC120_AS  ?= $(EXEC_X86_WIN32) ml64.exe
+ TOOL_VCC120_AR  ?= $(EXEC_X86_WIN32) lib.exe
+ TOOL_VCC120_LD  ?= $(EXEC_X86_WIN32) link.exe
+ TOOL_VCC120_DUMPBIN ?= $(EXEC_X86_WIN32) dumpbin.exe
+ TOOL_VCC120_EDITBIN ?= $(EXEC_X86_WIN32) editbin.exe
+endif
+TOOL_VCC120_RC   ?= $(EXEC_X86_WIN32) $(call TOOL_VCC120_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC120_RC_CACHED)
+TOOL_VCC120_MT   ?= $(EXEC_X86_WIN32) $(call TOOL_VCC120_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC120_MT_CACHED)
+
+# The following in duplicated in VCC120.kmk and VCC120X86.kmk.
+TOOL_VCC120_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword  \
+       $(if-expr defined(PATH_SDK_WINPSDK71_BIN), $(wildcard $(PATH_SDK_WINPSDK71_BIN)/$2)) \
+       $(if-expr defined(PATH_SDK_WINPSDK_BIN)  , $(wildcard $(PATH_SDK_WINPSDK_BIN)/$2)) \
+	$(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/sdk/*/[Bb][Ii][Nn]/$2)) \
+	$(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/sdk/*/[Bb][Ii][Nn]/$2)) \
+	$1))
+TOOL_VCC120_FN_FIND_SDK_TOOL = $(if-expr !defined($3),$(TOOL_VCC120_FN_FIND_SDK_TOOL_SUB),)$($3)
+
+## Disabled fast DEP_IDB based dependencies.
+#VCC120_OLD_DEPS = 1
+
+## Constructs the correct .pdb name (the name is lowercased).
+# @param    $(1)        Base name, no extention.
+# @param    $(2)        The extension.
+TOOL_VCC120_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2)
+
+
+# General Properties used by kBuild
+TOOL_VCC120_COBJSUFF         ?= .obj
+TOOL_VCC120_CFLAGS           ?= -TC -nologo -Zi
+TOOL_VCC120_CFLAGS.debug     ?=
+TOOL_VCC120_CFLAGS.dbgopt    ?= -O2
+TOOL_VCC120_CFLAGS.release   ?= -O2
+TOOL_VCC120_CFLAGS.profile   ?= -O2
+TOOL_VCC120_CINCS            ?= $(PATH_TOOL_VCC120_INC)
+TOOL_VCC120_CDEFS            ?=
+
+TOOL_VCC120_CXXOBJSUFF       ?= .obj
+TOOL_VCC120_CXXFLAGS         ?= -TP -nologo -Zi
+TOOL_VCC120_CXXFLAGS.debug   ?=
+TOOL_VCC120_CXXFLAGS.dbgopt  ?= -O2
+TOOL_VCC120_CXXFLAGS.release ?= -O2
+TOOL_VCC120_CXXFLAGS.profile ?= -O2
+TOOL_VCC120_CXXINCS          ?= $(PATH_TOOL_VCC120_INC) $(PATH_TOOL_VCC120_ATLMFC_INC)
+TOOL_VCC120_CXXDEFS          ?=
+
+TOOL_VCC120_ASOBJSUFF        ?= .obj
+
+TOOL_VCC120_RCOBJSUFF        ?= .res
+TOOL_VCC120_RCINCS           ?= $(PATH_TOOL_VCC120_INC) $(PATH_TOOL_VCC120_ATLMFC_INC)
+
+TOOL_VCC120_ARFLAGS.amd64    ?= -machine:amd64
+TOOL_VCC120_ARFLAGS.x86      ?= -machine:x86
+TOOL_VCC120_ARFLAGS          ?= -nologo
+TOOL_VCC120_ARLIBSUFF        ?= .lib
+
+TOOL_VCC120_LDFLAGS.amd64    ?= -machine:amd64
+TOOL_VCC120_LDFLAGS.x86      ?= -machine:x86
+TOOL_VCC120_LDFLAGS          ?= -nologo
+TOOL_VCC120_LDFLAGS.debug    ?= -debug
+TOOL_VCC120_LDFLAGS.dbgopt   ?= -debug
+TOOL_VCC120_LDFLAGS.profile  ?= -debug
+TOOL_VCC120_LDFLAGS.release  ?=
+TOOL_VCC120_LIBPATH.amd64    ?= $(PATH_TOOL_VCC120_LIB.amd64) $(PATH_TOOL_VCC120_ATLMFC_LIB.amd64)
+TOOL_VCC120_LIBPATH.x86      ?= $(PATH_TOOL_VCC120_LIB.x86) $(PATH_TOOL_VCC120_ATLMFC_LIB.x86)
+
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC120_COMPILE_C_DEPEND =
+TOOL_VCC120_COMPILE_C_DEPORD =
+TOOL_VCC120_COMPILE_C_OUTPUT =
+TOOL_VCC120_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC120_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC120_PDB, $(outbase)-obj,idb)
+define TOOL_VCC120_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_VCC120_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_OBJ) -f -s -q -o $(dep) -t $(obj) $(obj)
+endef
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC120_COMPILE_CXX_DEPEND = $($(target)_1_VCC_PCH_FILE)
+TOOL_VCC120_COMPILE_CXX_DEPORD =
+TOOL_VCC120_COMPILE_CXX_OUTPUT =
+TOOL_VCC120_COMPILE_CXX_OUTPUT_MAYBE = $(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB)\
+	,,$(call TOOL_VCC120_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC120_PDB, $(outbase)-obj,idb))
+define TOOL_VCC120_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC120_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		$(if-expr defined($(target)_PCH_HDR)\
+		,-FI$($(target)_PCH_HDR) -Yu$($(target)_PCH_HDR) -Fp$($(target)_1_VCC_PCH_FILE) -FS,)\
+		-Fd$(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB),$($(target)_1_VCC_COMMON_OBJ_PDB),$(outbase)-obj.pdb) \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_OBJ) -f -s -q -o $(dep) -t $(obj) $(obj)
+endef
+
+
+#
+# Helper tool for creating the precompiled C++ header.
+#
+# It only have the C++ compile bits and it's purpose is to skip bits
+# related _1_VCC_PCH_FILE and add -Yc.
+#
+TOOL_VCC120-PCH                         := Helper for creating precompiled header using CXX handling.
+TOOL_VCC120-PCH_EXTENDS                 := VCC120
+TOOL_VCC120-PCH_CXXOBJSUFF              := .obj
+TOOL_VCC120-PCH_CXXINCS                  = $(TOOL_VCC120_CXXINCS)
+TOOL_VCC120-PCH_CXXFLAGS                 = $(TOOL_VCC120_CXXFLAGS) -FS
+TOOL_VCC120-PCH_CXXFLAGS.debug           = $(TOOL_VCC120_CXXFLAGS.debug)
+TOOL_VCC120-PCH_CXXFLAGS.dbgopt          = $(TOOL_VCC120_CXXFLAGS.dbgopt)
+TOOL_VCC120-PCH_CXXFLAGS.release         = $(TOOL_VCC120_CXXFLAGS.release)
+TOOL_VCC120-PCH_CXXFLAGS.profile         = $(TOOL_VCC120_CXXFLAGS.profile)
+TOOL_VCC120-PCH_COMPILE_CXX_DEPEND       = $(NO_SUCH_VARIABLE)
+TOOL_VCC120-PCH_COMPILE_CXX_DEPORD       = $(NO_SUCH_VARIABLE)
+TOOL_VCC120-PCH_COMPILE_CXX_OUTPUT       = $($(target)_1_VCC_PCH_FILE) $($(target)_1_VCC_COMMON_OBJ_PDB)
+TOOL_VCC120-PCH_COMPILE_CXX_OUTPUT_MAYBE = $(NO_SUCH_VARIABLE)
+ifdef TOOL_VCC120_KSUBMIT
+ define TOOL_VCC120-PCH_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC120_KSUBMIT) --no-pch-caching -P $(DEP_OBJ_INT) -f -s -q -e .pch -o $(dep) -t $(obj) $(obj)\
+		-- $(TOOL_VCC120_CXX) -c -Yc\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+               -Fp$($(target)_1_VCC_PCH_FILE) \
+		-Fd$($(target)_1_VCC_COMMON_OBJ_PDB) \
+		-Fo$(obj)\
+               -TP \
+		$(subst /,\\,$(abspath $(source)))
+ endef
+else
+ define TOOL_VCC120-PCH_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC120_CXX) -c -Yc\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+               -Fp$($(target)_1_VCC_PCH_FILE) \
+		-Fd$($(target)_1_VCC_COMMON_OBJ_PDB) \
+		-Fo$(obj)\
+               -TP \
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_OBJ) -f -s -q  -e .pch -o $(dep) -t $(obj) $(obj)
+
+ endef
+endif # !TOOL_VCC120_KSUBMIT
+
+
+## @todo configure the assembler template.
+
+## Compile resource source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC120_COMPILE_RC_OUTPUT =
+TOOL_VCC120_COMPILE_RC_DEPEND =
+TOOL_VCC120_COMPILE_RC_DEPORD =
+define TOOL_VCC120_COMPILE_RC_CMDS
+	$(QUIET)$(TOOL_VCC120_RC) \
+		$(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\
+		/fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_VCC120_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_VCC120_LINK_LIBRARY_DEPORD =
+TOOL_VCC120_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_VCC120_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb
+define TOOL_VCC120_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+			$(subst /,\\,$(objs) \
+			$(filter-out %.def,$(othersrc))) \
+			$(addprefix /DEF:,$(filter %.def,$(othersrc))) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120_AR) $(flags) /OUT:$(out) @$(outbase).rsp
+endef
+
+
+## Link program
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          Program name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)      Output basename (full). Use this for list files and such.
+#
+TOOL_VCC120_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC120_LINK_PROGRAM_DEPORD =
+TOOL_VCC120_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_VCC120_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest
+TOOL_VCC120_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb
+TOOL_VCC120_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb
+define TOOL_VCC120_LINK_PROGRAM_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+		    $(subst /,\\,$(objs)) \
+		    $(subst /,\\,$(libs)) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		@$(outbase).rsp
+ifndef TOOL_VCC120_NO_AUTO_MANIFEST
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC120_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out))
+endif
+endef
+
+
+## Link DLL.
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      DLL name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC120_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC120_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB))
+TOOL_VCC120_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp
+TOOL_VCC120_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(out).manifest $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp
+TOOL_VCC120_LINK_DLL_OUTPUT_MAYBE_PRECIOUS = $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib
+TOOL_VCC120_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb
+TOOL_VCC120_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb
+define TOOL_VCC120_LINK_DLL_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+		    $(subst /,\\,$(objs)) \
+		    $(subst /,\\,$(libs)) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120_LD) $(flags) \
+		/OUT:$(out) \
+		/IMPLIB:$(outbase).lib \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		/DLL \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		@$(outbase).rsp
+ifndef TOOL_VCC120_NO_AUTO_MANIFEST
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC120_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+endif
+	$(QUIET)$(TEST) -f $(outbase).lib -- $(KLIBTWEAKER_EXT) --clear-timestamps $(outbase).lib
+	$(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/
+$(eval _DIRS += $(PATH_STAGE_LIB))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          System module name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC120_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC120_LINK_SYSMOD_DEPORD =
+TOOL_VCC120_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_VCC120_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest
+TOOL_VCC120_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb
+TOOL_VCC120_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb
+define TOOL_VCC120_LINK_SYSMOD_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+		    $(subst /,\\,$(objs)) \
+		    $(subst /,\\,$(libs)) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		@$(outbase).rsp
+ifndef TOOL_VCC120_NO_AUTO_MANIFEST
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC120_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+endif
+endef
+
diff --git a/kBuild/tools/VCC120AMD64.kmk b/kBuild/tools/VCC120AMD64.kmk
new file mode 100644
index 0000000..225b358
--- /dev/null
+++ b/kBuild/tools/VCC120AMD64.kmk
@@ -0,0 +1,465 @@
+# $Id: VCC120AMD64.kmk 3044 2017-05-11 13:29:49Z bird $
+## @file
+# kBuild Tool Config - Visual C++ 12.0 (aka Visual 2013 and MSC v18), targeting AMD64.
+#
+
+#
+# Copyright (c) 2004-2017 knut st. osmundsen <bird-kBuild-spam-xiv at anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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 of the License, or
+# (at your option) any later version.
+#
+# kBuild is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_VCC120AMD64 := Visual C++ 12.0 (aka Visual 2013 and MSC v18), targeting AMD64
+
+# Tool Specific Properties
+ifndef PATH_TOOL_VCC120AMD64
+ PATH_TOOL_VCC120AMD64 := $(wildcard $(KBUILD_DEVTOOLS)/win.x86/vcc/v12*)
+ ifeq ($(PATH_TOOL_VCC120AMD64),)
+  PATH_TOOL_VCC120AMD64 := $(PATH_TOOL_VCC120)
+ endif
+ ifeq ($(PATH_TOOL_VCC120AMD64),)
+  PATH_TOOL_VCC120AMD64 := $(PATH_TOOL_VCC120X86)
+ endif
+ ifeq ($(PATH_TOOL_VCC120AMD64),)
+  PATH_TOOL_VCC120AMD64 := $(wildcard $(KBUILD_DEVTOOLS)/win.x86/vcc/v12*)
+ endif
+ ifneq ($(PATH_TOOL_VCC120AMD64),)
+  PATH_TOOL_VCC120AMD64 := $(lastword $(sort $(PATH_TOOL_VCC120AMD64)))
+ else
+  $(warning kBuild: PATH_TOOL_VCC120AMD64 cannot be determined!)
+  PATH_TOOL_VCC120AMD64 := $(KBUILD_DEVTOOLS)/win.x86/vcc/v12
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_VCC120AMD64 := $(PATH_TOOL_VCC120AMD64)
+endif
+if "$(KBUILD_HOST).$(KBUILD_HOST_ARCH)" == "win.amd64" && exists("$(PATH_TOOL_VCC120AMD64)/bin/amd64") # Missing in express edition.
+PATH_TOOL_VCC120AMD64_BIN ?= $(PATH_TOOL_VCC120AMD64)/bin/amd64
+#$(error works now: $(PATH_TOOL_VCC120AMD64)/bin/amd64)
+else
+#$(error no joy: $(PATH_TOOL_VCC120AMD64)/bin/amd64)
+PATH_TOOL_VCC120AMD64_BIN_DLL ?= $(PATH_TOOL_VCC120AMD64)/bin
+PATH_TOOL_VCC120AMD64_BIN ?= $(PATH_TOOL_VCC120AMD64)/bin/x86_amd64
+endif
+PATH_TOOL_VCC120AMD64_LIB ?= $(PATH_TOOL_VCC120AMD64)/lib/amd64
+PATH_TOOL_VCC120AMD64_INC ?= $(PATH_TOOL_VCC120AMD64)/include
+PATH_TOOL_VCC120AMD64_ATLMFC ?= $(PATH_TOOL_VCC120AMD64)/atlmfc
+PATH_TOOL_VCC120AMD64_ATLMFC_INC ?= $(PATH_TOOL_VCC120AMD64_ATLMFC)/include
+PATH_TOOL_VCC120AMD64_ATLMFC_LIB ?= $(PATH_TOOL_VCC120AMD64_ATLMFC)/lib/amd64
+TOOL_VCC120AMD64_CC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120AMD64_BIN)/cl.exe
+TOOL_VCC120AMD64_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120AMD64_BIN)/cl.exe
+TOOL_VCC120AMD64_AS  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120AMD64_BIN)/ml64.exe
+#TOOL_VCC120AMD64_AR  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120AMD64_BIN)/lib.exe - just an exec wrapper for the below
+TOOL_VCC120AMD64_AR  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120AMD64_BIN)/link.exe /LIB
+TOOL_VCC120AMD64_LD  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120AMD64_BIN)/link.exe
+TOOL_VCC120AMD64_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120AMD64_BIN)/dumpbin.exe
+TOOL_VCC120AMD64_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120AMD64_BIN)/editbin.exe
+TOOL_VCC120AMD64_RC  ?= $(EXEC_X86_WIN32) $(call TOOL_VCC120_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC120_RC_CACHED)
+TOOL_VCC120AMD64_MT  ?= $(EXEC_X86_WIN32) $(call TOOL_VCC120_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC120_MT_CACHED)
+ifdef TOOL_VCC120AMD64_USE_KSUBMIT
+ ifeq ($(KBUILD_HOST),win)
+  ifneq ($(substr $(PATH_TOOL_VCC120AMD64_BIN),-9),x86_amd64)
+   TOOL_VCC120AMD64_KSUBMIT ?= kmk_builtin_kSubmit --64-bit
+   ifdef PATH_TOOL_VCC120AMD64_BIN_DLL
+    TOOL_VCC120AMD64_KSUBMIT += --prepend 'PATH=$(PATH_TOOL_VCC120AMD64_BIN_DLL)$(HOST_PATH_SEP)'
+   endif
+   TOOL_VCC120AMD64_KSUBMIT_DD = $(TOOL_VCC120AMD64_KSUBMIT) --
+  else
+   # "fatal error C1902: Program database manager mismatch; please check your installation" when mixing with the 32-bit compiler.
+   #TOOL_VCC120AMD64_KSUBMIT ?= kmk_builtin_kSubmit --32-bit
+   #TOOL_VCC120AMD64_KSUBMIT_DD = $(TOOL_VCC120AMD64_KSUBMIT) --
+  endif
+ endif
+else ifdef PATH_TOOL_VCC120AMD64_BIN_DLL
+ TOOL_VCC120AMD64_KSUBMIT_DD  = $(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120AMD64_BIN_DLL)$(HOST_PATH_SEP)' --
+endif
+
+# The following in duplicated in VCC120.kmk and VCC120X86.kmk.
+TOOL_VCC120_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword  \
+       $(if-expr defined(PATH_SDK_WINPSDK71_BIN), $(wildcard $(PATH_SDK_WINPSDK71_BIN)/$2)) \
+       $(if-expr defined(PATH_SDK_WINPSDK_BIN)  , $(wildcard $(PATH_SDK_WINPSDK_BIN)/$2)) \
+	$(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/sdk/*/[Bb][Ii][Nn]/$2)) \
+	$(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/sdk/*/[Bb][Ii][Nn]/$2)) \
+	$1))
+TOOL_VCC120_FN_FIND_SDK_TOOL = $(if-expr !defined($3),$(TOOL_VCC120_FN_FIND_SDK_TOOL_SUB),)$($3)
+
+## Disabled fast DEP_IDB based dependencies.
+#VCC120AMD64_OLD_DEPS = 1
+
+## Constructs the correct .pdb name (the name is lowercased).
+# @param    $(1)        Base name, no extention.
+# @param    $(2)        The extension.
+TOOL_VCC120AMD64_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2)
+
+
+# General Properties used by kBuild
+TOOL_VCC120AMD64_COBJSUFF         ?= .obj
+TOOL_VCC120AMD64_CFLAGS           ?= -TC -nologo -Zi
+TOOL_VCC120AMD64_CFLAGS.debug     ?=
+TOOL_VCC120AMD64_CFLAGS.dbgopt    ?= -O2
+TOOL_VCC120AMD64_CFLAGS.release   ?= -O2
+TOOL_VCC120AMD64_CFLAGS.profile   ?= -O2
+TOOL_VCC120AMD64_CINCS            ?= $(PATH_TOOL_VCC120AMD64_INC)
+TOOL_VCC120AMD64_CDEFS            ?=
+
+TOOL_VCC120AMD64_CXXOBJSUFF       ?= .obj
+TOOL_VCC120AMD64_CXXFLAGS         ?= -TP -nologo -Zi
+TOOL_VCC120AMD64_CXXFLAGS.debug   ?=
+TOOL_VCC120AMD64_CXXFLAGS.dbgopt  ?= -O2
+TOOL_VCC120AMD64_CXXFLAGS.release ?= -O2
+TOOL_VCC120AMD64_CXXFLAGS.profile ?= -O2
+TOOL_VCC120AMD64_CXXINCS          ?= $(PATH_TOOL_VCC120AMD64_INC) $(PATH_TOOL_VCC120AMD64_ATLMFC_INC)
+TOOL_VCC120AMD64_CXXDEFS          ?=
+
+TOOL_VCC120AMD64_ASOBJSUFF        ?= .obj
+
+TOOL_VCC120AMD64_RCOBJSUFF        ?= .res
+TOOL_VCC120AMD64_RCINCS           ?= $(PATH_TOOL_VCC120AMD64_INC) $(PATH_TOOL_VCC120AMD64_ATLMFC_INC)
+
+TOOL_VCC120AMD64_ARFLAGS          ?= -nologo -machine:amd64
+TOOL_VCC120AMD64_ARLIBSUFF        ?= .lib
+
+TOOL_VCC120AMD64_LDFLAGS          ?= -nologo -machine:amd64
+TOOL_VCC120AMD64_LDFLAGS.debug    ?= -debug
+TOOL_VCC120AMD64_LDFLAGS.dbgopt   ?= -debug
+TOOL_VCC120AMD64_LDFLAGS.profile  ?= -debug
+TOOL_VCC120AMD64_LDFLAGS.release  ?=
+
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC120AMD64_COMPILE_C_DEPEND =
+TOOL_VCC120AMD64_COMPILE_C_DEPORD =
+TOOL_VCC120AMD64_COMPILE_C_OUTPUT =
+TOOL_VCC120AMD64_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC120AMD64_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC120AMD64_PDB, $(outbase)-obj,idb)
+ifdef TOOL_VCC120AMD64_KSUBMIT
+ TOOL_VCC120AMD64_COMPILE_C_DONT_PURGE_OUTPUT := 1 # speed
+ define TOOL_VCC120AMD64_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_VCC120AMD64_KSUBMIT) -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\
+		-- $(TOOL_VCC120AMD64_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+ endef
+else
+ define TOOL_VCC120AMD64_COMPILE_C_CMDS
+	$(QUIET)$(if-expr defined(PATH_TOOL_VCC120AMD64_BIN_DLL)\
+		,$(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120AMD64_BIN_DLL)$(HOST_PATH_SEP)' -- ,)$(TOOL_VCC120AMD64_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_OBJ) -f -s -q -o $(dep) -t $(obj) $(obj)
+ endef
+endif # !TOOL_VCC120AMD64_KSUBMIT
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC120AMD64_COMPILE_CXX_DEPEND = $($(target)_1_VCC_PCH_FILE)
+TOOL_VCC120AMD64_COMPILE_CXX_DEPORD =
+TOOL_VCC120AMD64_COMPILE_CXX_OUTPUT =
+TOOL_VCC120AMD64_COMPILE_CXX_OUTPUT_MAYBE = $(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB)\
+	,,$(call TOOL_VCC120AMD64_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC120AMD64_PDB, $(outbase)-obj,idb))
+ifdef TOOL_VCC120AMD64_KSUBMIT
+ TOOL_VCC120AMD64_COMPILE_CXX_DONT_PURGE_OUTPUT := 1 # speed
+ define TOOL_VCC120AMD64_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC120AMD64_KSUBMIT) -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\
+		-- $(TOOL_VCC120AMD64_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		$(if-expr defined($(target)_PCH_HDR)\
+		,-FI$($(target)_PCH_HDR) -Yu$($(target)_PCH_HDR) -Fp$($(target)_1_VCC_PCH_FILE) -FS,)\
+		-Fd$(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB),$($(target)_1_VCC_COMMON_OBJ_PDB),$(outbase)-obj.pdb) \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+ endef
+else
+ define TOOL_VCC120AMD64_COMPILE_CXX_CMDS
+	$(QUIET)$(if-expr defined(PATH_TOOL_VCC120AMD64_BIN_DLL)\
+		,$(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120AMD64_BIN_DLL)$(HOST_PATH_SEP)' -- ,)$(TOOL_VCC120AMD64_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		$(if-expr defined($(target)_PCH_HDR)\
+		,-FI$($(target)_PCH_HDR) -Yu$($(target)_PCH_HDR) -Fp$($(target)_1_VCC_PCH_FILE) -FS,)\
+		-Fd$(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB),$($(target)_1_VCC_COMMON_OBJ_PDB),$(outbase)-obj.pdb) \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_OBJ) -f -s -q -o $(dep) -t $(obj) $(obj)
+ endef
+endif # !TOOL_VCC120AMD64_KSUBMIT
+
+
+#
+# Helper tool for creating the precompiled C++ header.
+#
+# It only have the C++ compile bits and it's purpose is to skip bits
+# related _1_VCC_PCH_FILE and add -Yc.
+#
+TOOL_VCC120AMD64-PCH                         := Helper for creating precompiled header using CXX handling.
+TOOL_VCC120AMD64-PCH_EXTENDS                 := VCC120AMD64
+TOOL_VCC120AMD64-PCH_CXXOBJSUFF              := .obj
+TOOL_VCC120AMD64-PCH_CXXINCS                  = $(TOOL_VCC120AMD64_CXXINCS)
+TOOL_VCC120AMD64-PCH_CXXFLAGS                 = $(TOOL_VCC120AMD64_CXXFLAGS) -FS
+TOOL_VCC120AMD64-PCH_CXXFLAGS.debug           = $(TOOL_VCC120AMD64_CXXFLAGS.debug)
+TOOL_VCC120AMD64-PCH_CXXFLAGS.dbgopt          = $(TOOL_VCC120AMD64_CXXFLAGS.dbgopt)
+TOOL_VCC120AMD64-PCH_CXXFLAGS.release         = $(TOOL_VCC120AMD64_CXXFLAGS.release)
+TOOL_VCC120AMD64-PCH_CXXFLAGS.profile         = $(TOOL_VCC120AMD64_CXXFLAGS.profile)
+TOOL_VCC120AMD64-PCH_COMPILE_CXX_DEPEND       = $(NO_SUCH_VARIABLE)
+TOOL_VCC120AMD64-PCH_COMPILE_CXX_DEPORD       = $(NO_SUCH_VARIABLE)
+TOOL_VCC120AMD64-PCH_COMPILE_CXX_OUTPUT       = $($(target)_1_VCC_PCH_FILE) $($(target)_1_VCC_COMMON_OBJ_PDB)
+TOOL_VCC120AMD64-PCH_COMPILE_CXX_OUTPUT_MAYBE = $(NO_SUCH_VARIABLE)
+ifdef TOOL_VCC120AMD64_KSUBMIT
+ define TOOL_VCC120AMD64-PCH_COMPILE_CXX_CMDS
+	$(QUIET)$(RM) -f -- $($(target)_1_VCC_PCH_FILE) $($(target)_1_VCC_COMMON_OBJ_PDB)
+	$(QUIET)$(TOOL_VCC120AMD64_KSUBMIT) --no-pch-caching -P $(DEP_OBJ_INT) -f -s -q -e .pch -o $(dep) -t $(obj) $(obj)\
+		-- $(TOOL_VCC120AMD64_CXX) -c -Yc\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+               -Fp$($(target)_1_VCC_PCH_FILE) \
+		-Fd$($(target)_1_VCC_COMMON_OBJ_PDB) \
+		-Fo$(obj)\
+               -TP \
+		$(subst /,\\,$(abspath $(source)))
+ endef
+else
+ define TOOL_VCC120AMD64-PCH_COMPILE_CXX_CMDS
+	$(QUIET)$(RM) -f -- $($(target)_1_VCC_PCH_FILE) $($(target)_1_VCC_COMMON_OBJ_PDB)
+	$(QUIET)$(if-expr defined(PATH_TOOL_VCC120AMD64_BIN_DLL)\
+		,$(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120AMD64_BIN_DLL)$(HOST_PATH_SEP)' -- ,)$(TOOL_VCC120AMD64_CXX) -c -Yc\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+               -Fp$($(target)_1_VCC_PCH_FILE) \
+		-Fd$($(target)_1_VCC_COMMON_OBJ_PDB) \
+		-Fo$(obj)\
+               -TP \
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_OBJ) -f -s -q  -e .pch -o $(dep) -t $(obj) $(obj)
+
+ endef
+endif # !TOOL_VCC120AMD64_KSUBMIT
+
+
+## @todo configure the assembler template.
+
+## Compile resource source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC120AMD64_COMPILE_RC_DEPEND =
+TOOL_VCC120AMD64_COMPILE_RC_DEPORD =
+TOOL_VCC120AMD64_COMPILE_RC_OUTPUT =
+## @todo Fix kmk_redirect so we can use it for setting PATH without spawning a shell or two
+define TOOL_VCC120AMD64_COMPILE_RC_CMDS
+	$(QUIET)$(if-expr defined(PATH_TOOL_VCC120AMD64_BIN_DLL)\
+		,$(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120AMD64_BIN_DLL)$(HOST_PATH_SEP)' -- ,)$(TOOL_VCC120AMD64_RC) \
+		$(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\
+		/fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_VCC120AMD64_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_VCC120AMD64_LINK_LIBRARY_DEPORD =
+TOOL_VCC120AMD64_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_VCC120AMD64_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb
+define TOOL_VCC120AMD64_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+			$(subst /,\\,$(objs) \
+			$(filter-out %.def,$(othersrc))) \
+			$(addprefix /DEF:,$(filter %.def,$(othersrc))) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120AMD64_KSUBMIT_DD) $(TOOL_VCC120AMD64_AR) $(flags) /OUT:$(out) @$(outbase).rsp
+endef
+
+
+## Link program
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          Program name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)      Output basename (full). Use this for list files and such.
+#
+TOOL_VCC120AMD64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC120AMD64_LINK_PROGRAM_DEPORD =
+TOOL_VCC120AMD64_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_VCC120AMD64_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest
+TOOL_VCC120AMD64_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb
+TOOL_VCC120AMD64_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb
+define TOOL_VCC120AMD64_LINK_PROGRAM_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+		    $(subst /,\\,$(objs)) \
+		    $(subst /,\\,$(libs)) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120AMD64_KSUBMIT_DD) $(TOOL_VCC120AMD64_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		@$(outbase).rsp
+ifndef TOOL_VCC120AMD64_NO_AUTO_MANIFEST
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC120AMD64_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out))
+endif
+endef
+
+
+## Link DLL.
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      DLL name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC120AMD64_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC120AMD64_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB))
+TOOL_VCC120AMD64_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp
+TOOL_VCC120AMD64_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(out).manifest $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp
+TOOL_VCC120AMD64_LINK_DLL_OUTPUT_MAYBE_PRECIOUS = $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib
+TOOL_VCC120AMD64_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb
+TOOL_VCC120AMD64_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb
+define TOOL_VCC120AMD64_LINK_DLL_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+		    $(subst /,\\,$(objs)) \
+		    $(subst /,\\,$(libs)) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120AMD64_KSUBMIT_DD) $(TOOL_VCC120AMD64_LD) $(flags) \
+		/OUT:$(out) \
+		/IMPLIB:$(outbase).lib \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		/DLL \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		@$(outbase).rsp
+ifndef TOOL_VCC120AMD64_NO_AUTO_MANIFEST
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC120AMD64_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+endif
+	$(QUIET)$(TEST) -f $(outbase).lib -- $(KLIBTWEAKER_EXT) --clear-timestamps $(outbase).lib
+	$(QUIET)$(CP) --changed -v --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/
+$(eval _DIRS += $(PATH_STAGE_LIB))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          System module name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC120AMD64_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC120AMD64_LINK_SYSMOD_DEPORD =
+TOOL_VCC120AMD64_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_VCC120AMD64_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest
+TOOL_VCC120AMD64_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb
+TOOL_VCC120AMD64_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb
+define TOOL_VCC120AMD64_LINK_SYSMOD_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+		    $(subst /,\\,$(objs)) \
+		    $(subst /,\\,$(libs)) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120AMD64_KSUBMIT_DD) $(TOOL_VCC120AMD64_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		@$(outbase).rsp
+ifndef TOOL_VCC120AMD64_NO_AUTO_MANIFEST
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC120AMD64_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+endif
+endef
+
diff --git a/kBuild/tools/VCC120X86.kmk b/kBuild/tools/VCC120X86.kmk
new file mode 100644
index 0000000..7092f5c
--- /dev/null
+++ b/kBuild/tools/VCC120X86.kmk
@@ -0,0 +1,465 @@
+# $Id: VCC120X86.kmk 3048 2017-05-19 11:55:36Z bird $
+## @file
+# kBuild Tool Config - Visual C++ 12.0 (aka Visual 2013 and MSC v18), targeting x86.
+#
+
+#
+# Copyright (c) 2004-2017 knut st. osmundsen <bird-kBuild-spam-xiv at anduin.net>
+#
+# This file is part of kBuild.
+#
+# kBuild 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 of the License, or
+# (at your option) any later version.
+#
+# kBuild is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with kBuild; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+# As a special exception you are granted permission to include this file, via
+# the kmk include directive, as you wish without this in itself causing the
+# resulting makefile, program or whatever to be covered by the GPL license.
+# This exception does not however invalidate any other reasons why the makefile,
+# program, whatever should not be covered the GPL.
+#
+#
+
+TOOL_VCC120X86 := Visual C++ 12.0 (aka Visual 2013 and MSC v18), targeting x86.
+
+# Tool Specific Properties
+ifndef PATH_TOOL_VCC120X86
+ PATH_TOOL_VCC120X86 := $(wildcard $(KBUILD_DEVTOOLS)/win.x86/vcc/v12*)
+ ifeq ($(PATH_TOOL_VCC120X86),)
+  PATH_TOOL_VCC120X86 := $(PATH_TOOL_VCC120)
+ endif
+ ifeq ($(PATH_TOOL_VCC120X86),)
+  PATH_TOOL_VCC120X86 := $(PATH_TOOL_VCC120AMD64)
+ endif
+ ifeq ($(PATH_TOOL_VCC120X86),)
+  PATH_TOOL_VCC120X86 := $(wildcard $(KBUILD_DEVTOOLS)/x86.win32/vcc/v12*)
+ endif
+ ifeq ($(PATH_TOOL_VCC120X86),)
+  PATH_TOOL_VCC120X86 := $(wildcard $(KBUILD_DEVTOOLS)/win.amd64/vcc/v12*)
+ endif
+ ifneq ($(PATH_TOOL_VCC120X86),)
+  PATH_TOOL_VCC120X86 := $(lastword $(sort $(PATH_TOOL_VCC120X86)))
+ else
+  $(warning kBuild: PATH_TOOL_VCC120X86 cannot be determined!)
+  PATH_TOOL_VCC120X86 := $(KBUILD_DEVTOOLS)/x86.win/vcc/v12
+ endif
+else
+ # Resolve any fancy stuff once and for all.
+ PATH_TOOL_VCC120X86 := $(PATH_TOOL_VCC120X86)
+endif
+
+if "$(KBUILD_HOST).$(KBUILD_HOST_ARCH)" == "win.amd64" && exists("$(PATH_TOOL_VCC120AMD64)/bin/amd64_x86") # Missing in express edition.
+ PATH_TOOL_VCC120X86_BIN_DLL ?= $(PATH_TOOL_VCC120X86)/bin/amd64
+ PATH_TOOL_VCC120X86_BIN     ?= $(PATH_TOOL_VCC120X86)/bin/amd64_x86
+else
+ PATH_TOOL_VCC120X86_BIN_DLL ?=
+ PATH_TOOL_VCC120X86_BIN   ?= $(PATH_TOOL_VCC120X86)/bin
+endif
+PATH_TOOL_VCC120X86_BIN    ?= $(PATH_TOOL_VCC120X86)/bin
+PATH_TOOL_VCC120X86_LIB    ?= $(PATH_TOOL_VCC120X86)/lib
+PATH_TOOL_VCC120X86_INC    ?= $(PATH_TOOL_VCC120X86)/include
+PATH_TOOL_VCC120X86_ATLMFC ?= $(PATH_TOOL_VCC120X86)/atlmfc
+PATH_TOOL_VCC120X86_ATLMFC_INC ?= $(PATH_TOOL_VCC120X86_ATLMFC)/include
+PATH_TOOL_VCC120X86_ATLMFC_LIB ?= $(PATH_TOOL_VCC120X86_ATLMFC)/lib
+TOOL_VCC120X86_CC  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120X86_BIN)/cl.exe
+TOOL_VCC120X86_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120X86_BIN)/cl.exe
+TOOL_VCC120X86_AS  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120X86_BIN)/ml.exe
+#TOOL_VCC120X86_AR  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120X86_BIN)/lib.exe - just an exec wrapper for the below
+TOOL_VCC120X86_AR  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120X86_BIN)/link.exe /LIB
+TOOL_VCC120X86_LD  ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120X86_BIN)/link.exe
+TOOL_VCC120X86_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120X86_BIN)/dumpbin.exe
+TOOL_VCC120X86_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC120X86_BIN)/editbin.exe
+TOOL_VCC120X86_RC  ?= $(EXEC_X86_WIN32) $(call TOOL_VCC120_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC120_RC_CACHED)
+TOOL_VCC120X86_MT  ?= $(EXEC_X86_WIN32) $(call TOOL_VCC120_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC120_MT_CACHED)
+ifdef TOOL_VCC120X86_USE_KSUBMIT
+ ifeq ($(KBUILD_HOST),win)
+  if  "$(substr $(PATH_TOOL_VCC120X86_BIN),-10)" == "/amd64_x86"
+   TOOL_VCC120X86_KSUBMIT ?= kmk_builtin_kSubmit --64-bit
+  else
+   TOOL_VCC120X86_KSUBMIT ?= kmk_builtin_kSubmit --32-bit
+  endif
+  ifdef PATH_TOOL_VCC120X86_BIN_DLL
+   TOOL_VCC120X86_KSUBMIT += --prepend 'PATH=$(PATH_TOOL_VCC120X86_BIN_DLL)$(HOST_PATH_SEP)'
+  endif
+  TOOL_VCC120X86_KSUBMIT_DD = $(TOOL_VCC120X86_KSUBMIT) --
+ endif
+else ifdef PATH_TOOL_VCC120X86_BIN_DLL
+ TOOL_VCC120X86_KSUBMIT_DD  = $(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120X86_BIN_DLL)$(HOST_PATH_SEP)' --
+endif
+
+# The following in duplicated in VCC120.kmk and VCC120X86.kmk.
+TOOL_VCC120_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword  \
+       $(if-expr defined(PATH_SDK_WINPSDK71_BIN), $(wildcard $(PATH_SDK_WINPSDK71_BIN)/$2)) \
+       $(if-expr defined(PATH_SDK_WINPSDK_BIN)  , $(wildcard $(PATH_SDK_WINPSDK_BIN)/$2)) \
+	$(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/sdk/*/[Bb][Ii][Nn]/$2)) \
+	$(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/sdk/*/[Bb][Ii][Nn]/$2)) \
+	$1))
+TOOL_VCC120_FN_FIND_SDK_TOOL = $(if-expr !defined($3),$(TOOL_VCC120_FN_FIND_SDK_TOOL_SUB),)$($3)
+
+## Disabled fast DEP_IDB based dependencies.
+#VCC120X86_OLD_DEPS = 1
+
+## Constructs the correct .pdb name (the name is lowercased).
+# @param    $(1)        Base name, no extention.
+# @param    $(2)        The extension.
+TOOL_VCC120X86_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2)
+
+
+# General Properties used by kBuild
+TOOL_VCC120X86_COBJSUFF         ?= .obj
+TOOL_VCC120X86_CFLAGS           ?= -TC -nologo -Zi
+TOOL_VCC120X86_CFLAGS.debug     ?=
+TOOL_VCC120X86_CFLAGS.dbgopt    ?= -O2
+TOOL_VCC120X86_CFLAGS.release   ?= -O2
+TOOL_VCC120X86_CFLAGS.profile   ?= -O2
+TOOL_VCC120X86_CINCS            ?= $(PATH_TOOL_VCC120X86_INC)
+TOOL_VCC120X86_CDEFS            ?=
+
+TOOL_VCC120X86_CXXOBJSUFF       ?= .obj
+TOOL_VCC120X86_CXXFLAGS         ?= -TP -nologo -Zi
+TOOL_VCC120X86_CXXFLAGS.debug   ?=
+TOOL_VCC120X86_CXXFLAGS.dbgopt  ?= -O2
+TOOL_VCC120X86_CXXFLAGS.release ?= -O2
+TOOL_VCC120X86_CXXFLAGS.profile ?= -O2
+TOOL_VCC120X86_CXXINCS          ?= $(PATH_TOOL_VCC120X86_INC) $(PATH_TOOL_VCC120X86_ATLMFC_INC)
+TOOL_VCC120X86_CXXDEFS          ?=
+
+TOOL_VCC120X86_ASOBJSUFF        ?= .obj
+
+TOOL_VCC120X86_RCOBJSUFF        ?= .res
+TOOL_VCC120X86_RCINCS           ?= $(PATH_TOOL_VCC120X86_INC) $(PATH_TOOL_VCC120X86_ATLMFC_INC)
+
+TOOL_VCC120X86_ARFLAGS          ?= -nologo -machine:x86
+TOOL_VCC120X86_ARLIBSUFF        ?= .lib
+
+TOOL_VCC120X86_LDFLAGS          ?= -nologo -machine:x86
+TOOL_VCC120X86_LDFLAGS.debug    ?= -debug
+TOOL_VCC120X86_LDFLAGS.dbgopt   ?= -debug
+TOOL_VCC120X86_LDFLAGS.profile  ?= -debug
+TOOL_VCC120X86_LDFLAGS.release  ?=
+
+
+
+## Compile C source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC120X86_COMPILE_C_DEPEND =
+TOOL_VCC120X86_COMPILE_C_DEPORD =
+TOOL_VCC120X86_COMPILE_C_OUTPUT =
+TOOL_VCC120X86_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC120X86_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC120X86_PDB, $(outbase)-obj,idb)
+ifdef TOOL_VCC120X86_KSUBMIT
+ TOOL_VCC120X86_COMPILE_C_DONT_PURGE_OUTPUT = 1 # speed
+ define TOOL_VCC120X86_COMPILE_C_CMDS
+	$(QUIET)$(TOOL_VCC120X86_KSUBMIT) -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\
+		-- $(TOOL_VCC120X86_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+ endef
+else
+ define TOOL_VCC120X86_COMPILE_C_CMDS
+	$(QUIET)$(if-expr defined(PATH_TOOL_VCC120X86_BIN_DLL)\
+		,$(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120X86_BIN_DLL)$(HOST_PATH_SEP)' -- ,)$(TOOL_VCC120X86_CC) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		-Fd$(outbase)-obj.pdb \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_OBJ) -f -s -q -o $(dep) -t $(obj) $(obj)
+ endef
+endif # !TOOL_VCC120X86_KSUBMIT
+
+
+## Compile C++ source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC120X86_COMPILE_CXX_DEPEND = $($(target)_1_VCC_PCH_FILE)
+TOOL_VCC120X86_COMPILE_CXX_DEPORD =
+TOOL_VCC120X86_COMPILE_CXX_OUTPUT =
+TOOL_VCC120X86_COMPILE_CXX_OUTPUT_MAYBE = $(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB)\
+	,,$(call TOOL_VCC120X86_PDB, $(outbase)-obj,pdb) $(call TOOL_VCC120X86_PDB, $(outbase)-obj,idb))
+ifdef TOOL_VCC120X86_KSUBMIT
+ TOOL_VCC120X86_COMPILE_CXX_DONT_PURGE_OUTPUT = 1 # speed
+ define TOOL_VCC120X86_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC120X86_KSUBMIT) -P $(DEP_OBJ_INT) -f -s -q -o $(dep) -t $(obj) $(obj)\
+		-- $(TOOL_VCC120X86_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		$(if-expr defined($(target)_PCH_HDR)\
+		,-FI$($(target)_PCH_HDR) -Yu$($(target)_PCH_HDR) -Fp$($(target)_1_VCC_PCH_FILE) -FS,)\
+		-Fd$(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB),$($(target)_1_VCC_COMMON_OBJ_PDB),$(outbase)-obj.pdb) \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+ endef
+else
+ define TOOL_VCC120X86_COMPILE_CXX_CMDS
+	$(QUIET)$(if-expr defined(PATH_TOOL_VCC120X86_BIN_DLL)\
+		,$(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120X86_BIN_DLL)$(HOST_PATH_SEP)' -- ,)$(TOOL_VCC120X86_CXX) -c\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+		$(if-expr defined($(target)_PCH_HDR)\
+		,-FI$($(target)_PCH_HDR) -Yu$($(target)_PCH_HDR) -Fp$($(target)_1_VCC_PCH_FILE) -FS,)\
+		-Fd$(if-expr defined($(target)_1_VCC_COMMON_OBJ_PDB),$($(target)_1_VCC_COMMON_OBJ_PDB),$(outbase)-obj.pdb) \
+		-Fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_OBJ) -f -s -q -o $(dep) -t $(obj) $(obj)
+ endef
+endif # !TOOL_VCC120X86_KSUBMIT
+
+
+#
+# Helper tool for creating the precompiled C++ header.
+#
+# It only have the C++ compile bits and it's purpose is to skip bits
+# related _1_VCC_PCH_FILE and add -Yc.
+#
+TOOL_VCC120X86-PCH                         := Helper for creating precompiled header using CXX handling.
+TOOL_VCC120X86-PCH_EXTENDS                 := VCC120X86
+TOOL_VCC120X86-PCH_CXXOBJSUFF              := .obj
+TOOL_VCC120X86-PCH_CXXINCS                  = $(TOOL_VCC120X86_CXXINCS)
+TOOL_VCC120X86-PCH_CXXFLAGS                 = $(TOOL_VCC120X86_CXXFLAGS) -FS
+TOOL_VCC120X86-PCH_CXXFLAGS.debug           = $(TOOL_VCC120X86_CXXFLAGS.debug)
+TOOL_VCC120X86-PCH_CXXFLAGS.dbgopt          = $(TOOL_VCC120X86_CXXFLAGS.dbgopt)
+TOOL_VCC120X86-PCH_CXXFLAGS.release         = $(TOOL_VCC120X86_CXXFLAGS.release)
+TOOL_VCC120X86-PCH_CXXFLAGS.profile         = $(TOOL_VCC120X86_CXXFLAGS.profile)
+TOOL_VCC120X86-PCH_COMPILE_CXX_DEPEND       = $(NO_SUCH_VARIABLE)
+TOOL_VCC120X86-PCH_COMPILE_CXX_DEPORD       = $(NO_SUCH_VARIABLE)
+TOOL_VCC120X86-PCH_COMPILE_CXX_OUTPUT       = $($(target)_1_VCC_PCH_FILE) $($(target)_1_VCC_COMMON_OBJ_PDB)
+TOOL_VCC120X86-PCH_COMPILE_CXX_OUTPUT_MAYBE = $(NO_SUCH_VARIABLE)
+ifdef TOOL_VCC120X86_KSUBMIT
+ define TOOL_VCC120X86-PCH_COMPILE_CXX_CMDS
+	$(QUIET)$(TOOL_VCC120X86_KSUBMIT) --no-pch-caching -P $(DEP_OBJ_INT) -f -s -q -e .pch -o $(dep) -t $(obj) $(obj)\
+		-- $(TOOL_VCC120X86_CXX) -c -Yc\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+               -Fp$($(target)_1_VCC_PCH_FILE) \
+		-Fd$($(target)_1_VCC_COMMON_OBJ_PDB) \
+		-Fo$(obj)\
+               -TP \
+		$(subst /,\\,$(abspath $(source)))
+ endef
+else
+ define TOOL_VCC120X86-PCH_COMPILE_CXX_CMDS
+	$(QUIET)$(if-expr defined(PATH_TOOL_VCC120X86_BIN_DLL)\
+		,$(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120X86_BIN_DLL)$(HOST_PATH_SEP)' -- ,)$(TOOL_VCC120X86_CXX) -c -Yc\
+		$(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\
+               -Fp$($(target)_1_VCC_PCH_FILE) \
+		-Fd$($(target)_1_VCC_COMMON_OBJ_PDB) \
+		-Fo$(obj)\
+               -TP \
+		$(subst /,\\,$(abspath $(source)))
+	$(QUIET)$(DEP_OBJ) -f -s -q  -e .pch -o $(dep) -t $(obj) $(obj)
+
+ endef
+endif # !TOOL_VCC120X86_KSUBMIT
+
+
+## @todo configure the assembler template.
+
+## Compile resource source.
+# @param    $(target)   Normalized main target name.
+# @param    $(source)   Source filename (relative).
+# @param    $(obj)      Object file name. This shall be (re)created by the compilation.
+# @param    $(dep)      Dependcy file. This shall be (re)created by the compilation.
+# @param    $(flags)    Flags.
+# @param    $(defs)     Definitions. No -D or something.
+# @param    $(incs)     Includes. No -I or something.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+# @param    $(objsuff)  Object suffix.
+TOOL_VCC120X86_COMPILE_RC_DEPEND =
+TOOL_VCC120X86_COMPILE_RC_DEPORD =
+TOOL_VCC120X86_COMPILE_RC_OUTPUT =
+## @todo Fix kmk_redirect so we can use it for setting PATH without spawning a shell or two
+define TOOL_VCC120X86_COMPILE_RC_CMDS
+	$(QUIET)$(if-expr defined(PATH_TOOL_VCC120X86_BIN_DLL)\
+		,$(REDIRECT) --prepend 'PATH=$(PATH_TOOL_VCC120X86_BIN_DLL)$(HOST_PATH_SEP)' -- ,) $(TOOL_VCC120X86_RC) \
+		$(flags) $(addprefix /i, $(subst /,\\,$(incs))) $(addprefix /d, $(defs))\
+		/fo$(obj)\
+		$(subst /,\\,$(abspath $(source)))
+endef
+
+
+## Link library
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      Library name.
+# @param    $(objs)     Object files to put in the library.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc) Unhandled sources.
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+#
+TOOL_VCC120X86_LINK_LIBRARY_DEPEND = $(othersrc)
+TOOL_VCC120X86_LINK_LIBRARY_DEPORD =
+TOOL_VCC120X86_LINK_LIBRARY_OUTPUT = $(outbase).rsp
+TOOL_VCC120X86_LINK_LIBRARY_OUTPUT_MAYBE = $(outbase).lst $(outbase).exp $(outbase).pdb
+define TOOL_VCC120X86_LINK_LIBRARY_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+			$(subst /,\\,$(objs) \
+			$(filter-out %.def,$(othersrc))) \
+			$(addprefix /DEF:,$(filter %.def,$(othersrc))) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120X86_KSUBMIT_DD) $(TOOL_VCC120X86_AR) $(flags) /OUT:$(out) @$(outbase).rsp
+endef
+
+
+## Link program
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          Program name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+# @param    $(outbase)      Output basename (full). Use this for list files and such.
+#
+TOOL_VCC120X86_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC120X86_LINK_PROGRAM_DEPORD =
+TOOL_VCC120X86_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_VCC120X86_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest
+TOOL_VCC120X86_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb
+TOOL_VCC120X86_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb
+define TOOL_VCC120X86_LINK_PROGRAM_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+		    $(subst /,\\,$(objs)) \
+		    $(subst /,\\,$(libs)) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120X86_KSUBMIT_DD) $(TOOL_VCC120X86_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		@$(outbase).rsp
+ifndef TOOL_VCC120X86_NO_AUTO_MANIFEST
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC120X86_MT) -manifest $(subst /,\\,$(out)).manifest -outputresource:$(subst /,\\,$(out))
+endif
+endef
+
+
+## Link DLL.
+# @param    $(target)   Normalized main target name.
+# @param    $(out)      DLL name.
+# @param    $(objs)     Object files to link together.
+# @param    $(libs)     Libraries to search.
+# @param    $(libpath)  Library search paths.
+# @param    $(flags)    Flags.
+# @param    $(dirdep)   Directory creation dependency.
+# @param    $(deps)     Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC120X86_LINK_DLL_DEPEND = $(objs) $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC120X86_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB))
+TOOL_VCC120X86_LINK_DLL_OUTPUT = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).rsp
+TOOL_VCC120X86_LINK_DLL_OUTPUT_MAYBE = $(outbase).ilk $(out).manifest $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp
+TOOL_VCC120X86_LINK_DLL_OUTPUT_MAYBE_PRECIOUS = $(PATH_STAGE_LIB)/$(notdir $(outbase)).lib
+TOOL_VCC120X86_LINK_DLL_OUTPUT_DEBUG = $(outbase).pdb
+TOOL_VCC120X86_LINK_DLL_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb
+define TOOL_VCC120X86_LINK_DLL_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+		    $(subst /,\\,$(objs)) \
+		    $(subst /,\\,$(libs)) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120X86_KSUBMIT_DD) $(TOOL_VCC120X86_LD) $(flags) \
+		/OUT:$(out) \
+		/IMPLIB:$(outbase).lib \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		/DLL \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		@$(outbase).rsp
+ifndef TOOL_VCC120X86_NO_AUTO_MANIFEST
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC120X86_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+endif
+	$(QUIET)$(TEST) -f $(outbase).lib -- $(KLIBTWEAKER_EXT) --clear-timestamps $(outbase).lib
+	$(QUIET)$(CP) --changed --ignore-non-existing $(outbase).exp $(outbase).lib $(PATH_STAGE_LIB)/
+$(eval _DIRS += $(PATH_STAGE_LIB))
+endef
+
+
+## Link system module (windows aka driver, linux aka kernel module)
+# @param    $(target)       Normalized main target name.
+# @param    $(out)          System module name.
+# @param    $(objs)         Object files to link together.
+# @param    $(libs)         Libraries to search.
+# @param    $(libpath)      Library search paths.
+# @param    $(flags)        Flags.
+# @param    $(dirdep)       Directory creation dependency.
+# @param    $(deps)         Other dependencies.
+# @param    $(othersrc)     Unhandled sources.
+# @param    $(custom_pre)   Custom step invoked before linking.
+# @param    $(custom_post)  Custom step invoked after linking.
+#
+# @param    $(outbase)  Output basename (full). Use this for list files and such.
+TOOL_VCC120X86_LINK_SYSMOD_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc)
+TOOL_VCC120X86_LINK_SYSMOD_DEPORD =
+TOOL_VCC120X86_LINK_SYSMOD_OUTPUT = $(outbase).map $(outbase).rsp
+TOOL_VCC120X86_LINK_SYSMOD_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest
+TOOL_VCC120X86_LINK_SYSMOD_OUTPUT_DEBUG = $(outbase).pdb
+TOOL_VCC120X86_LINK_SYSMOD_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb
+define TOOL_VCC120X86_LINK_SYSMOD_CMDS
+	$(QUIET)$(APPEND) -tn $(outbase).rsp \
+		$(foreach arg,\
+		    $(subst /,\\,$(objs)) \
+		    $(subst /,\\,$(libs)) \
+			,\"$(arg)\")
+	$(QUIET)$(TOOL_VCC120X86_KSUBMIT_DD) $(TOOL_VCC120X86_LD) $(flags) \
+		/OUT:$(out) \
+		/MAPINFO:EXPORTS /INCREMENTAL:NO \
+		/MAP:$(outbase).map \
+		$(foreach def,$(filter %.def,$(othersrc)), /DEF:$(def)) \
+		$(subst /,\\,$(filter %.exp %.res,$(othersrc))) \
+		$(foreach p,$(libpath), /LIBPATH:$(p)) \
+		@$(outbase).rsp
+ifndef TOOL_VCC120X86_NO_AUTO_MANIFEST
+	$(QUIET)$(TEST) -f $(out).manifest -- \
+		$(TOOL_VCC120X86_MT) -manifest $(subst /,\\,$(out)).manifest '-outputresource:$(subst /,\\,$(out));#2'
+endif
+endef
+
diff --git a/src/kDepPre/kDepPre.c b/src/kDepPre/kDepPre.c
index e677b5b..1243ca1 100644
--- a/src/kDepPre/kDepPre.c
+++ b/src/kDepPre/kDepPre.c
@@ -1,4 +1,4 @@
-/* $Id: kDepPre.c 2955 2016-09-21 19:05:53Z bird $ */
+/* $Id: kDepPre.c 3065 2017-09-30 12:52:35Z bird $ */
 /** @file
  * kDepPre - Dependency Generator using Precompiler output.
  */
@@ -293,14 +293,14 @@ int main(int argc, char *argv[])
                  */
                 case 'l':
                 {
-                    const char *psz = &argv[i][2];
-                    if (*psz == '=')
-                        psz++;
-                    if (!strcmp(psz, "c"))
+                    const char *pszValue = &argv[i][2];
+                    if (*pszValue == '=')
+                        pszValue++;
+                    if (!strcmp(pszValue, "c"))
                         ;
                     else
                     {
-                        fprintf(stderr, "%s: error: The '%s' language is not supported.\n", argv[0], psz);
+                        fprintf(stderr, "%s: error: The '%s' language is not supported.\n", argv[0], pszValue);
                         return 1;
                     }
                     break;
diff --git a/src/kObjCache/kObjCache.c b/src/kObjCache/kObjCache.c
index fdb0697..e3d590c 100644
--- a/src/kObjCache/kObjCache.c
+++ b/src/kObjCache/kObjCache.c
@@ -1,4 +1,4 @@
-/* $Id: kObjCache.c 2955 2016-09-21 19:05:53Z bird $ */
+/* $Id: kObjCache.c 3065 2017-09-30 12:52:35Z bird $ */
 /** @file
  * kObjCache - Object Cache.
  */
@@ -69,6 +69,9 @@
 # ifndef O_BINARY
 #  define O_BINARY 0
 # endif
+# ifndef __sun__
+#  include <sys/file.h> /* flock */
+# endif
 #endif
 #if defined(__WIN__)
 # include <Windows.h>
@@ -1070,6 +1073,10 @@ kOCDepConsumer(PKOCDEP pDepState, const char *pszInput, size_t cchInput)
                     off++;
                 }
             }
+
+            case kOCDepState_Invalid:
+                assert(0);
+                break;
         }
 
         /* next newline */
@@ -2354,10 +2361,10 @@ static void kOCEntryRead(PKOCENTRY pEntry)
                 else if (!strncmp(g_szLine, "cc-argv-#", sizeof("cc-argv-#") - 1))
                 {
                     char *pszNext;
-                    unsigned i = strtoul(&g_szLine[sizeof("cc-argv-#") - 1], &pszNext, 0);
-                    if ((fBad = i >= pEntry->Old.cArgvCompile || pEntry->Old.papszArgvCompile[i] || (pszNext && *pszNext)))
+                    unsigned iArg = strtoul(&g_szLine[sizeof("cc-argv-#") - 1], &pszNext, 0);
+                    if ((fBad = iArg >= pEntry->Old.cArgvCompile || pEntry->Old.papszArgvCompile[iArg] || (pszNext && *pszNext)))
                         break;
-                    pEntry->Old.papszArgvCompile[i] = xstrdup(pszVal);
+                    pEntry->Old.papszArgvCompile[iArg] = xstrdup(pszVal);
                 }
                 else if (!strcmp(g_szLine, "cc-argv-sum"))
                 {
@@ -2490,13 +2497,13 @@ static void kOCEntryWrite(PKOCENTRY pEntry)
         do { int cch = expr; if (cch >= KOBJCACHE_MAX_LINE_LEN) FatalDie("Line too long: %d (max %d)\nexpr: %s\n", cch, KOBJCACHE_MAX_LINE_LEN, #expr); } while (0)
 
     fprintf(pFile, "magic=kObjCacheEntry-v0.1.1\n");
-    CHECK_LEN(fprintf(pFile, "target=%s\n", pEntry->New.pszTarget ? pEntry->New.pszTarget : pEntry->Old.pszTarget));
-    CHECK_LEN(fprintf(pFile, "key=%lu\n", (unsigned long)pEntry->uKey));
+    CHECK_LEN(fprintf(pFile, "target=%s\n",     pEntry->New.pszTarget ? pEntry->New.pszTarget : pEntry->Old.pszTarget));
+    CHECK_LEN(fprintf(pFile, "key=%lu\n",       (unsigned long)pEntry->uKey));
     CHECK_LEN(fprintf(pFile, "obj=%s\n",        pEntry->New.pszObjName ? pEntry->New.pszObjName : pEntry->Old.pszObjName));
     CHECK_LEN(fprintf(pFile, "cpp=%s\n",        pEntry->New.pszCppName ? pEntry->New.pszCppName : pEntry->Old.pszCppName));
-    CHECK_LEN(fprintf(pFile, "cpp-size=%lu\n",  pEntry->New.pszCppName ? pEntry->New.cbCpp      : pEntry->Old.cbCpp));
-    CHECK_LEN(fprintf(pFile, "cpp-ms=%lu\n",    pEntry->New.pszCppName ? pEntry->New.cMsCpp     : pEntry->Old.cMsCpp));
-    CHECK_LEN(fprintf(pFile, "cc-ms=%lu\n",     pEntry->New.pszCppName ? pEntry->New.cMsCompile : pEntry->Old.cMsCompile));
+    CHECK_LEN(fprintf(pFile, "cpp-size=%lu\n",  (unsigned long)(pEntry->New.pszCppName ? pEntry->New.cbCpp      : pEntry->Old.cbCpp)));
+    CHECK_LEN(fprintf(pFile, "cpp-ms=%lu\n",    (unsigned long)(pEntry->New.pszCppName ? pEntry->New.cMsCpp     : pEntry->Old.cMsCpp)));
+    CHECK_LEN(fprintf(pFile, "cc-ms=%lu\n",     (unsigned long)(pEntry->New.pszCppName ? pEntry->New.cMsCompile : pEntry->Old.cMsCompile)));
 
     if (!kOCSumIsEmpty(&pEntry->New.SumCompArgv))
     {
@@ -5087,7 +5094,7 @@ int main(int argc, char **argv)
         }
         else if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version"))
         {
-            printf("kObjCache - kBuild version %d.%d.%d ($Revision: 2955 $)\n"
+            printf("kObjCache - kBuild version %d.%d.%d ($Revision: 3065 $)\n"
                    "Copyright (c) 2007-2012 knut st. osmundsen\n",
                    KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH);
             return 0;
diff --git a/src/kWorker/Makefile.kmk b/src/kWorker/Makefile.kmk
index 2f0331b..c2647f2 100644
--- a/src/kWorker/Makefile.kmk
+++ b/src/kWorker/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2968 2016-09-26 18:14:50Z bird $
+# $Id: Makefile.kmk 3042 2017-05-11 10:23:12Z bird $
 ## @file
 # Sub-makefile for kWorker.
 #
@@ -152,6 +152,25 @@ kStuff_SOURCES.darwin += \
 	kStuff/kHlp/Bare/kHlpSys-darwin.c
 
 
+#
+# A couple of dummy DLLs we use for grabbing LDR TLS entries.
+#
+DLLS += kWorkerTls1K kWorkerTls64K kWorkerTls512K
+kWorkerTls1K_TEMPLATE   = BIN-STATIC-THREADED
+kWorkerTls1K_DEFS       = KWORKER_BASE=0x10000 TLS_SIZE=1024
+kWorkerTls1K_SOURCES    = kWorkerTlsXxxK.c
+kWorkerTls1K_LDFLAGS    = /Entry:DummyDllEntry
+
+kWorkerTls64K_TEMPLATE  = BIN-STATIC-THREADED
+kWorkerTls64K_DEFS      = KWORKER_BASE=0x10000 TLS_SIZE=65536
+kWorkerTls64K_SOURCES   = kWorkerTlsXxxK.c
+kWorkerTls64K_LDFLAGS   = /Entry:DummyDllEntry
+
+kWorkerTls512K_TEMPLATE = BIN-STATIC-THREADED
+kWorkerTls512K_DEFS     = KWORKER_BASE=0x10000 TLS_SIZE=524288
+kWorkerTls512K_SOURCES  = kWorkerTlsXxxK.c
+kWorkerTls512K_LDFLAGS  = /Entry:DummyDllEntry
+
 
 include $(KBUILD_PATH)/subfooter.kmk
 
diff --git a/src/kWorker/kWorker.c b/src/kWorker/kWorker.c
index 13e7d94..05ba245 100644
--- a/src/kWorker/kWorker.c
+++ b/src/kWorker/kWorker.c
@@ -1,4 +1,4 @@
-/* $Id: kWorker.c 2987 2016-11-01 18:27:39Z bird $ */
+/* $Id: kWorker.c 3089 2017-10-04 13:10:41Z bird $ */
 /** @file
  * kWorker - experimental process reuse worker for Windows.
  *
@@ -292,6 +292,20 @@ typedef struct KWMODULE
                 /** How much to zero. */
                 KSIZE           cbToZero;
             } aQuickZeroChunks[3];
+
+            /** TLS index if one was allocated, otherwise KU32_MAX. */
+            KU32                idxTls;
+            /** Offset (RVA) of the TLS initialization data. */
+            KU32                offTlsInitData;
+            /** Number of bytes of TLS initialization data. */
+            KU32                cbTlsInitData;
+            /** Number of allocated bytes for TLS. */
+            KU32                cbTlsAlloc;
+            /** Number of TLS callbacks. */
+            KU32                cTlsCallbacks;
+            /** Offset (RVA) of the TLS callback table. */
+            KU32                offTlsCallbacks;
+
             /** Number of imported modules. */
             KSIZE               cImpMods;
             /** Import array (variable size). */
@@ -892,6 +906,9 @@ static KWGETMODULEHANDLECACHE g_aGetModuleHandleCache[] =
     { MOD_CACHE_STRINGS("mscoree.dll"),     NULL },
 };
 
+/** Module pending TLS allocation. See kwLdrModuleCreateNonNativeSetupTls. */
+static PKWMODULE    g_pModPendingTlsAlloc = NULL;
+
 
 /** The file system cache. */
 static PKFSCACHE    g_pFsCache;
@@ -1017,11 +1034,13 @@ static KSIZE    g_cbWriteFileToInMemTemp;
 *   Internal Functions                                                                                                           *
 *********************************************************************************************************************************/
 static FNKLDRMODGETIMPORT kwLdrModuleGetImportCallback;
-static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod);
+static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter,
+                                       const char *pszSearchPath, PKWMODULE *ppMod);
 static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle, HANDLE hHandle);
 #ifdef WITH_CONSOLE_OUTPUT_BUFFERING
 static void kwSandboxConsoleWriteA(PKWSANDBOX pSandbox, PKWOUTPUTSTREAMBUF pLineBuf, const char *pchBuffer, KU32 cchToWrite);
 #endif
+static PPEB kwSandboxGetProcessEnvironmentBlock(void);
 
 
 
@@ -2001,6 +2020,178 @@ static void kwLdrModuleCreateNonNativeSetupQuickZeroAndCopy(PKWMODULE pMod)
 
 
 /**
+ * Called from TLS allocation DLL during DLL_PROCESS_ATTACH.
+ *
+ * @param   hDll            The DLL handle.
+ * @param   idxTls          The allocated TLS index.
+ * @param   ppfnTlsCallback Pointer to the TLS callback table entry.
+ */
+__declspec(dllexport) void kwLdrTlsAllocationHook(void *hDll, ULONG idxTls, PIMAGE_TLS_CALLBACK *ppfnTlsCallback)
+{
+    /*
+     * Do the module initialization thing first.
+     */
+    PKWMODULE pMod = g_pModPendingTlsAlloc;
+    if (pMod)
+    {
+        PPEB        pPeb = kwSandboxGetProcessEnvironmentBlock();
+        LIST_ENTRY *pHead;
+        LIST_ENTRY *pCur;
+
+        pMod->u.Manual.idxTls = idxTls;
+        KWLDR_LOG(("kwLdrTlsAllocationHook: idxTls=%d (%#x) for %s\n", idxTls, idxTls, pMod->pszPath));
+
+        /*
+         * Try sabotage the DLL name so we can load this module again.
+         */
+        pHead = &pPeb->Ldr->InMemoryOrderModuleList;
+        for (pCur = pHead->Blink; pCur != pHead; pCur = pCur->Blink)
+        {
+            LDR_DATA_TABLE_ENTRY *pMte;
+            pMte = (LDR_DATA_TABLE_ENTRY *)((KUPTR)pCur - K_OFFSETOF(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks));
+            if (((KUPTR)pMte->DllBase & ~(KUPTR)31) == ((KUPTR)hDll & ~(KUPTR)31))
+            {
+                PUNICODE_STRING pStr = &pMte->FullDllName;
+                KSIZE off = pStr->Length / sizeof(pStr->Buffer[0]);
+                pStr->Buffer[--off]++;
+                pStr->Buffer[--off]++;
+                pStr->Buffer[--off]++;
+                KWLDR_LOG(("kwLdrTlsAllocationHook: patched the MTE (%p) for %p\n", pMte, hDll));
+                break;
+            }
+        }
+    }
+}
+
+
+/**
+ * Allocates and initializes TLS variables.
+ *
+ * @returns 0 on success, non-zero failure.
+ * @param   pMod                The module.
+ */
+static int kwLdrModuleCreateNonNativeSetupTls(PKWMODULE pMod)
+{
+    KU8                        *pbImg = (KU8 *)pMod->u.Manual.pbCopy;
+    IMAGE_NT_HEADERS const     *pNtHdrs;
+    IMAGE_DATA_DIRECTORY const *pTlsDir;
+
+    if (((PIMAGE_DOS_HEADER)pbImg)->e_magic == IMAGE_DOS_SIGNATURE)
+        pNtHdrs = (PIMAGE_NT_HEADERS)&pbImg[((PIMAGE_DOS_HEADER)pbImg)->e_lfanew];
+    else
+        pNtHdrs = (PIMAGE_NT_HEADERS)pbImg;
+    kHlpAssert(pNtHdrs->Signature == IMAGE_NT_SIGNATURE);
+
+    pTlsDir = &pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
+    if (pTlsDir->Size >= sizeof(IMAGE_TLS_DIRECTORY))
+    {
+        PIMAGE_TLS_DIRECTORY const  paEntries = (PIMAGE_TLS_DIRECTORY)&pbImg[pTlsDir->VirtualAddress];
+        KU32 const                  cEntries  = pTlsDir->Size / sizeof(IMAGE_TLS_DIRECTORY);
+        KU32                        iEntry;
+        KUPTR                       offIndex;
+        KUPTR                       offCallbacks;
+        KUPTR const                *puCallbacks;
+        KSIZE                       cbData;
+        const wchar_t              *pwszTlsDll;
+        HMODULE                     hmodTlsDll;
+
+        /*
+         * Check and log.
+         */
+        for (iEntry = 0; iEntry < cEntries; iEntry++)
+        {
+            KUPTR        offIndex     = (KUPTR)paEntries[iEntry].AddressOfIndex     - (KUPTR)pMod->u.Manual.pbLoad;
+            KUPTR        offCallbacks = (KUPTR)paEntries[iEntry].AddressOfCallBacks - (KUPTR)pMod->u.Manual.pbLoad;
+            KUPTR const *puCallbacks  = (KUPTR const *)&pbImg[offCallbacks];
+            KWLDR_LOG(("TLS DIR #%u: %#x-%#x idx=@%#x (%#x) callbacks=@%#x (%#x) cbZero=%#x flags=%#x\n",
+                       iEntry, paEntries[iEntry].StartAddressOfRawData, paEntries[iEntry].EndAddressOfRawData,
+                       paEntries[iEntry].AddressOfIndex, offIndex, paEntries[iEntry].AddressOfCallBacks, offCallbacks,
+                       paEntries[iEntry].SizeOfZeroFill, paEntries[iEntry].Characteristics));
+
+            if (offIndex >= pMod->cbImage)
+            {
+                kwErrPrintf("TLS entry #%u in %s has an invalid index address: %p, RVA %p, image size %#x\n",
+                            iEntry, pMod->pszPath, paEntries[iEntry].AddressOfIndex, offIndex, pMod->cbImage);
+                return -1;
+            }
+            if (offCallbacks >= pMod->cbImage)
+            {
+                kwErrPrintf("TLS entry #%u in %s has an invalid callbacks address: %p, RVA %p, image size %#x\n",
+                            iEntry, pMod->pszPath, paEntries[iEntry].AddressOfCallBacks, offCallbacks, pMod->cbImage);
+                return -1;
+            }
+            while (*puCallbacks != 0)
+            {
+                KWLDR_LOG(("TLS DIR #%u:   callback %p, RVA %#x\n",
+                            iEntry, *puCallbacks, *puCallbacks - (KUPTR)pMod->u.Manual.pbLoad));
+                puCallbacks++;
+            }
+            if (paEntries[iEntry].Characteristics > IMAGE_SCN_ALIGN_16BYTES)
+            {
+                kwErrPrintf("TLS entry #%u in %s has an unsupported alignment restriction: %#x\n",
+                            iEntry, pMod->pszPath, paEntries[iEntry].Characteristics);
+                return -1;
+            }
+        }
+
+        if (cEntries > 1)
+        {
+            kwErrPrintf("More than one TLS directory entry in %s: %u\n", pMod->pszPath, cEntries);
+            return -1;
+        }
+
+        /*
+         * Make the allocation by loading a new instance of one of the TLS dlls.
+         * The DLL will make a call to
+         */
+        offIndex     = (KUPTR)paEntries[0].AddressOfIndex     - (KUPTR)pMod->u.Manual.pbLoad;
+        offCallbacks = (KUPTR)paEntries[0].AddressOfCallBacks - (KUPTR)pMod->u.Manual.pbLoad;
+        puCallbacks  = (KUPTR const *)&pbImg[offCallbacks];
+        cbData = paEntries[0].SizeOfZeroFill + (paEntries[0].EndAddressOfRawData - paEntries[0].StartAddressOfRawData);
+        if (cbData <= 1024)
+            pwszTlsDll = L"kWorkerTls1K.dll";
+        else if (cbData <= 65536)
+            pwszTlsDll = L"kWorkerTls64K.dll";
+        else if (cbData <= 524288)
+            pwszTlsDll = L"kWorkerTls512K.dll";
+        else
+        {
+            kwErrPrintf("TLS data size in %s is too big: %u (%#p), max 512KB\n", pMod->pszPath, (unsigned)cbData, cbData);
+            return -1;
+        }
+
+        pMod->u.Manual.idxTls         = KU32_MAX;
+        pMod->u.Manual.offTlsInitData = (KU32)((KUPTR)paEntries[0].StartAddressOfRawData - (KUPTR)pMod->u.Manual.pbLoad);
+        pMod->u.Manual.cbTlsInitData  = (KU32)(paEntries[0].EndAddressOfRawData - paEntries[0].StartAddressOfRawData);
+        pMod->u.Manual.cbTlsAlloc     = (KU32)cbData;
+        pMod->u.Manual.cTlsCallbacks  = 0;
+        while (puCallbacks[pMod->u.Manual.cTlsCallbacks] != 0)
+            pMod->u.Manual.cTlsCallbacks++;
+        pMod->u.Manual.offTlsCallbacks = pMod->u.Manual.cTlsCallbacks ? (KU32)offCallbacks : KU32_MAX;
+
+        g_pModPendingTlsAlloc = pMod;
+        hmodTlsDll = LoadLibraryExW(pwszTlsDll, NULL /*hFile*/, 0);
+        g_pModPendingTlsAlloc = NULL;
+        if (hmodTlsDll == NULL)
+        {
+            kwErrPrintf("TLS allocation failed for '%s': LoadLibraryExW(%ls) -> %u\n", pMod->pszPath, pwszTlsDll, GetLastError());
+            return -1;
+        }
+        if (pMod->u.Manual.idxTls == KU32_MAX)
+        {
+            kwErrPrintf("TLS allocation failed for '%s': idxTls = KU32_MAX\n", pMod->pszPath, GetLastError());
+            return -1;
+        }
+
+        *(KU32 *)&pMod->u.Manual.pbCopy[offIndex] = pMod->u.Manual.idxTls;
+        KWLDR_LOG(("kwLdrModuleCreateNonNativeSetupTls: idxTls=%d hmodTlsDll=%p (%ls) cbData=%#x\n",
+                   pMod->u.Manual.idxTls, hmodTlsDll, pwszTlsDll, cbData));
+    }
+    return 0;
+}
+
+
+/**
  * Creates a module using the our own loader.
  *
  * @returns Module w/ 1 reference on success, NULL on failure.
@@ -2011,8 +2202,10 @@ static void kwLdrModuleCreateNonNativeSetupQuickZeroAndCopy(PKWMODULE pMod)
  *                              into the global module table.
  * @param   pExeMod             The executable module of the process (for
  *                              resolving imports).  NULL if fExe is set.
+ * @param   pszSearchPath       The PATH to search for imports.  Can be NULL.
  */
-static PKWMODULE kwLdrModuleCreateNonNative(const char *pszPath, KU32 uHashPath, KBOOL fExe, PKWMODULE pExeMod)
+static PKWMODULE kwLdrModuleCreateNonNative(const char *pszPath, KU32 uHashPath, KBOOL fExe,
+                                            PKWMODULE pExeMod, const char *pszSearchPath)
 {
     /*
      * Open the module and check the type.
@@ -2068,10 +2261,16 @@ static PKWMODULE kwLdrModuleCreateNonNative(const char *pszPath, KU32 uHashPath,
 #if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64)
                     pMod->u.Manual.fRegisteredFunctionTable = K_FALSE;
 #endif
-                    pMod->u.Manual.fUseLdBuf = K_FALSE;
-                    pMod->u.Manual.fCanDoQuick = K_FALSE;
+                    pMod->u.Manual.fUseLdBuf        = K_FALSE;
+                    pMod->u.Manual.fCanDoQuick      = K_FALSE;
                     pMod->u.Manual.cQuickZeroChunks = 0;
                     pMod->u.Manual.cQuickCopyChunks = 0;
+                    pMod->u.Manual.idxTls           = KU32_MAX;
+                    pMod->u.Manual.offTlsInitData   = KU32_MAX;
+                    pMod->u.Manual.cbTlsInitData    = 0;
+                    pMod->u.Manual.cbTlsAlloc       = 0;
+                    pMod->u.Manual.cTlsCallbacks    = 0;
+                    pMod->u.Manual.offTlsCallbacks  = 0;
                     pMod->pszPath       = (char *)kHlpMemCopy(&pMod->u.Manual.apImpMods[cImports + 1], pszPath, cbPath);
                     pMod->pwszPath      = (wchar_t *)(pMod->pszPath + cbPath + (cbPath & 1));
                     kwStrToUtf16(pMod->pszPath, (wchar_t *)pMod->pwszPath, cbPath * 2);
@@ -2105,6 +2304,7 @@ static PKWMODULE kwLdrModuleCreateNonNative(const char *pszPath, KU32 uHashPath,
                                 kwLdrModuleLink(pMod);
                             KW_LOG(("New module: %p LB %#010x %s (kLdr)\n",
                                     pMod->u.Manual.pbLoad, pMod->cbImage, pMod->pszPath));
+                            KW_LOG(("TODO: .reload /f %s=%p\n", pMod->pszPath, pMod->u.Manual.pbLoad));
                             kwDebuggerPrintf("TODO: .reload /f %s=%p\n", pMod->pszPath, pMod->u.Manual.pbLoad);
 
                             for (iImp = 0; iImp < cImports; iImp++)
@@ -2113,7 +2313,8 @@ static PKWMODULE kwLdrModuleCreateNonNative(const char *pszPath, KU32 uHashPath,
                                 rc = kLdrModGetImport(pMod->pLdrMod, NULL /*pvBits*/, iImp, szName, sizeof(szName));
                                 if (rc == 0)
                                 {
-                                    rc = kwLdrModuleResolveAndLookup(szName, pExeMod, pMod, &pMod->u.Manual.apImpMods[iImp]);
+                                    rc = kwLdrModuleResolveAndLookup(szName, pExeMod, pMod, pszSearchPath,
+                                                                     &pMod->u.Manual.apImpMods[iImp]);
                                     if (rc == 0)
                                         continue;
                                 }
@@ -2156,15 +2357,21 @@ static PKWMODULE kwLdrModuleCreateNonNative(const char *pszPath, KU32 uHashPath,
 
                                     kwLdrModuleCreateNonNativeSetupQuickZeroAndCopy(pMod);
 
-                                    /*
-                                     * Final finish.
-                                     */
-                                    pMod->u.Manual.pvBits = pMod->u.Manual.pbCopy;
-                                    pMod->u.Manual.enmState = KWMODSTATE_NEEDS_BITS;
-                                    g_cModules++;
-                                    g_cNonNativeModules++;
-                                    return pMod;
+                                    rc = kwLdrModuleCreateNonNativeSetupTls(pMod);
+                                    if (rc == 0)
+                                    {
+                                        /*
+                                         * Final finish.
+                                         */
+                                        pMod->u.Manual.pvBits = pMod->u.Manual.pbCopy;
+                                        pMod->u.Manual.enmState = KWMODSTATE_NEEDS_BITS;
+                                        g_cModules++;
+                                        g_cNonNativeModules++;
+                                        return pMod;
+                                    }
                                 }
+                                else
+                                    kwErrPrintf("kLdrModGetBits failed for %s: %#x (%d)\n", pszPath, rc, rc);
                             }
 
                             kwLdrModuleRelease(pMod);
@@ -2231,6 +2438,7 @@ static int kwLdrModuleGetImportCallback(PKLDRMOD pMod, KU32 iImport, KU32 iSymbo
     }
 
     //printf("iImport=%u (%s) %*.*s rc=%d\n", iImport, &pImpMod->pszPath[pImpMod->offFilename], cchSymbol, cchSymbol, pchSymbol, rc);
+    KW_LOG(("iImport=%u (%s) %*.*s rc=%d\n", iImport, &pImpMod->pszPath[pImpMod->offFilename], cchSymbol, cchSymbol, pchSymbol, rc));
     return rc;
 
 }
@@ -2401,8 +2609,9 @@ static KBOOL kwLdrModuleIsRegularFile(const char *pszPath)
  *                              the heuristics for determining if we can use the
  *                              native loader or need to sandbox the DLL.
  * @param   pExe                The executable (optional).
+ * @param   pszSearchPath       The PATH to search (optional).
  */
-static PKWMODULE kwLdrModuleTryLoadDll(const char *pszPath, KWLOCATION enmLocation, PKWMODULE pExeMod)
+static PKWMODULE kwLdrModuleTryLoadDll(const char *pszPath, KWLOCATION enmLocation, PKWMODULE pExeMod, const char *pszSearchPath)
 {
     /*
      * Does the file exists and is it a regular file?
@@ -2439,7 +2648,7 @@ static PKWMODULE kwLdrModuleTryLoadDll(const char *pszPath, KWLOCATION enmLocati
                 pMod = kwLdrModuleCreateNative(szNormPath, uHashPath,
                                                kwLdrModuleShouldDoNativeReplacements(pszName, enmLocation));
             else
-                pMod = kwLdrModuleCreateNonNative(szNormPath, uHashPath, K_FALSE /*fExe*/, pExeMod);
+                pMod = kwLdrModuleCreateNonNative(szNormPath, uHashPath, K_FALSE /*fExe*/, pExeMod, pszSearchPath);
             if (pMod)
                 return pMod;
             return (PKWMODULE)~(KUPTR)0;
@@ -2461,9 +2670,11 @@ static PKWMODULE kwLdrModuleTryLoadDll(const char *pszPath, KWLOCATION enmLocati
  * @param   pszName             The name of the import module.
  * @param   pExe                The executable (optional).
  * @param   pImporter           The module doing the importing (optional).
+ * @param   pszSearchPath       The PATH to search (optional).
  * @param   ppMod               Where to return the module pointer w/ reference.
  */
-static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod)
+static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter,
+                                       const char *pszSearchPath, PKWMODULE *ppMod)
 {
     KSIZE const cchName = kHlpStrLen(pszName);
     char        szPath[1024];
@@ -2482,7 +2693,7 @@ static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWM
         psz = (char *)kHlpMemPCopy(kHlpMemPCopy(szPath, pImporter->pszPath, pImporter->offFilename), pszName, cchName + 1);
         if (fNeedSuffix)
             kHlpMemCopy(psz - 1, ".dll", sizeof(".dll"));
-        pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_IMPORTER_DIR, pExe);
+        pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_IMPORTER_DIR, pExe, pszSearchPath);
     }
 
     /* Application directory first. */
@@ -2493,7 +2704,7 @@ static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWM
         psz = (char *)kHlpMemPCopy(kHlpMemPCopy(szPath, pExe->pszPath, pExe->offFilename), pszName, cchName + 1);
         if (fNeedSuffix)
             kHlpMemCopy(psz - 1, ".dll", sizeof(".dll"));
-        pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_EXE_DIR, pExe);
+        pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_EXE_DIR, pExe, pszSearchPath);
     }
 
     /* The windows directory. */
@@ -2507,7 +2718,44 @@ static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWM
         psz = (char *)kHlpMemPCopy(&szPath[cchDir], pszName, cchName + 1);
         if (fNeedSuffix)
             kHlpMemCopy(psz - 1, ".dll", sizeof(".dll"));
-        pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_SYSTEM32, pExe);
+        pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_SYSTEM32, pExe, pszSearchPath);
+    }
+
+    /* The path. */
+    if (   pMod == NULL
+        && pszSearchPath)
+    {
+        const char *pszCur = pszSearchPath;
+        while (*pszCur != '\0')
+        {
+            /* Find the end of the component */
+            KSIZE cch = 0;
+            while (pszCur[cch] != ';' && pszCur[cch] != '\0')
+                cch++;
+
+            if (   cch > 0 /* wrong, but whatever */
+                && cch + 1 + cchName + cchSuffix < sizeof(szPath))
+            {
+                char *pszDst = kHlpMemPCopy(szPath, pszCur, cch);
+                if (   szPath[cch - 1] != ':'
+                    && szPath[cch - 1] != '/'
+                    && szPath[cch - 1] != '\\')
+                    *pszDst++ = '\\';
+                pszDst = kHlpMemPCopy(pszDst, pszName, cchName);
+                if (fNeedSuffix)
+                    pszDst = kHlpMemPCopy(pszDst, ".dll", 4);
+                *pszDst = '\0';
+
+                pMod = kwLdrModuleTryLoadDll(szPath, KWLOCATION_SYSTEM32, pExe, pszSearchPath);
+                if (pMod)
+                    break;
+            }
+
+            /* Advance */
+            pszCur += cch;
+            while (*pszCur == ';')
+                pszCur++;
+        }
     }
 
     /* Return. */
@@ -2522,6 +2770,50 @@ static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWM
 
 
 /**
+ * Does the TLS memory initialization for a module on the current thread.
+ *
+ * @returns 0 on success, error on failure.
+ * @param   pMod                The module.
+ */
+static int kwLdrCallTlsAllocateAndInit(PKWMODULE pMod)
+{
+    if (pMod->u.Manual.idxTls != KU32_MAX)
+    {
+        PTEB pTeb = NtCurrentTeb();
+        void **ppvTls = *(void ***)( (KUPTR)pTeb + (sizeof(void *) == 4 ? 0x2c : 0x58) );
+        KU8   *pbData = (KU8 *)ppvTls[pMod->u.Manual.idxTls];
+        KWLDR_LOG(("%s: TLS: Initializing %#x (%#x), idxTls=%d\n",
+                   pMod->pszPath, pbData, pMod->u.Manual.cbTlsAlloc, pMod->u.Manual.cbTlsInitData, pMod->u.Manual.idxTls));
+        if (pMod->u.Manual.cbTlsInitData < pMod->u.Manual.cbTlsAlloc)
+            kHlpMemSet(&pbData[pMod->u.Manual.cbTlsInitData], 0, pMod->u.Manual.cbTlsAlloc);
+        if (pMod->u.Manual.cbTlsInitData)
+            kHlpMemCopy(pbData, &pMod->u.Manual.pbCopy[pMod->u.Manual.offTlsInitData], pMod->u.Manual.cbTlsInitData);
+    }
+    return 0;
+}
+
+
+/**
+ * Does the TLS callbacks for a module.
+ *
+ * @param   pMod                The module.
+ * @param   dwReason            The callback reason.
+ */
+static void kwLdrCallTlsCallbacks(PKWMODULE pMod, DWORD dwReason)
+{
+    if (pMod->u.Manual.cTlsCallbacks)
+    {
+        PIMAGE_TLS_CALLBACK *pCallback = (PIMAGE_TLS_CALLBACK *)&pMod->u.Manual.pbLoad[pMod->u.Manual.offTlsCallbacks];
+        do
+        {
+            KWLDR_LOG(("%s: Calling TLS callback %p(%p,%#x,0)\n", pMod->pszPath, *pCallback, pMod->hOurMod, dwReason));
+            (*pCallback)(pMod->hOurMod, dwReason, 0);
+        } while (*++pCallback);
+    }
+}
+
+
+/**
  * Does module initialization starting at @a pMod.
  *
  * This is initially used on the executable.  Later it is used by the
@@ -2535,6 +2827,9 @@ static int kwLdrModuleInitTree(PKWMODULE pMod)
     int rc = 0;
     if (!pMod->fNative)
     {
+        KWLDR_LOG(("kwLdrModuleInitTree: enmState=%#x idxTls=%u %s\n",
+                   pMod->u.Manual.enmState, pMod->u.Manual.idxTls, pMod->pszPath));
+
         /*
          * Need to copy bits?
          */
@@ -2606,6 +2901,7 @@ static int kwLdrModuleInitTree(PKWMODULE pMod)
         }
 #endif
 
+
         if (pMod->u.Manual.enmState == KWMODSTATE_NEEDS_INIT)
         {
             /*
@@ -2622,6 +2918,14 @@ static int kwLdrModuleInitTree(PKWMODULE pMod)
                     return rc;
             }
 
+            /* Do TLS allocations for module init? */
+            rc = kwLdrCallTlsAllocateAndInit(pMod);
+            if (rc != 0)
+                return rc;
+            if (pMod->u.Manual.cTlsCallbacks > 0)
+                kwLdrCallTlsCallbacks(pMod, DLL_PROCESS_ATTACH);
+
+            /* Finally call the entry point. */
             rc = kLdrModCallInit(pMod->pLdrMod, pMod->u.Manual.pbLoad, (KUPTR)pMod->hOurMod);
             if (rc == 0)
                 pMod->u.Manual.enmState = KWMODSTATE_READY;
@@ -2828,8 +3132,9 @@ static int kwToolAddModuleAndImports(PKWTOOL pTool, PKWMODULE pMod)
  *
  *                              A reference is donated by the caller and must be
  *                              released.
+ * @param   pszSearchPath       The PATH environment variable value, or NULL.
  */
-static PKWTOOL kwToolEntryCreate(PKFSOBJ pToolFsObj)
+static PKWTOOL kwToolEntryCreate(PKFSOBJ pToolFsObj, const char *pszSearchPath)
 {
     KSIZE   cwcPath = pToolFsObj->cwcParent + pToolFsObj->cwcName + 1;
     KSIZE   cbPath  = pToolFsObj->cchParent + pToolFsObj->cchName + 1;
@@ -2847,7 +3152,8 @@ static PKWTOOL kwToolEntryCreate(PKFSOBJ pToolFsObj)
         kHlpAssert(fRc);
 
         pTool->enmType = KWTOOLTYPE_SANDBOXED;
-        pTool->u.Sandboxed.pExe = kwLdrModuleCreateNonNative(pTool->pszPath, kwStrHash(pTool->pszPath), K_TRUE /*fExe*/, NULL);
+        pTool->u.Sandboxed.pExe = kwLdrModuleCreateNonNative(pTool->pszPath, kwStrHash(pTool->pszPath), K_TRUE /*fExe*/,
+                                                             NULL /*pEexeMod*/, pszSearchPath);
         if (pTool->u.Sandboxed.pExe)
         {
             int rc = kwLdrModuleQueryMainEntrypoint(pTool->u.Sandboxed.pExe, &pTool->u.Sandboxed.uMainAddr);
@@ -2884,20 +3190,32 @@ static PKWTOOL kwToolEntryCreate(PKFSOBJ pToolFsObj)
 /**
  * Looks up the given tool, creating a new tool table entry if necessary.
  *
- * @returns Pointer to the tool entry.  NULL on failure.
+ * @returns Pointer to the tool entry.  NULL on failure (fully bitched).
  * @param   pszExe              The executable for the tool (not normalized).
+ * @param   cEnvVars            Number of environment varibles.
+ * @param   papszEnvVars        Environment variables.  For getting the PATH.
  */
-static PKWTOOL kwToolLookup(const char *pszExe)
+static PKWTOOL kwToolLookup(const char *pszExe, KU32 cEnvVars, const char **papszEnvVars)
 {
     /*
      * We associate the tools instances with the file system objects.
+     *
+     * We'd like to do the lookup without invaliding the volatile parts of the
+     * cache, thus the double lookup here.  The cache gets invalidate later on.
      */
     KFSLOOKUPERROR  enmError;
     PKFSOBJ         pToolFsObj = kFsCacheLookupA(g_pFsCache, pszExe, &enmError);
+    if (   !pToolFsObj
+        || pToolFsObj->bObjType != KFSOBJ_TYPE_FILE)
+    {
+        kFsCacheInvalidateCustomBoth(g_pFsCache);
+        pToolFsObj = kFsCacheLookupA(g_pFsCache, pszExe, &enmError);
+    }
     if (pToolFsObj)
     {
         if (pToolFsObj->bObjType == KFSOBJ_TYPE_FILE)
         {
+            const char *pszSearchPath;
             PKWTOOL pTool = (PKWTOOL)kFsCacheObjGetUserData(g_pFsCache, pToolFsObj, KW_DATA_KEY_TOOL);
             if (pTool)
             {
@@ -2908,10 +3226,30 @@ static PKWTOOL kwToolLookup(const char *pszExe)
             /*
              * Need to create a new tool.
              */
-            return kwToolEntryCreate(pToolFsObj);
+            pszSearchPath = NULL;
+            while (cEnvVars-- > 0)
+                if (_strnicmp(papszEnvVars[cEnvVars], "PATH=", 5) == 0)
+                {
+                    pszSearchPath = &papszEnvVars[cEnvVars][5];
+                    break;
+                }
+
+            pTool = kwToolEntryCreate(pToolFsObj, pszSearchPath);
+            if (pTool)
+                return pTool;
+
+            kwErrPrintf("kwToolLookup(%s) -> NULL: kwToolEntryCreate failed\n", pszExe);
+        }
+        else
+        {
+            kFsCacheObjRelease(g_pFsCache, pToolFsObj);
+            kwErrPrintf("kwToolLookup(%s) -> NULL: not file (bObjType=%d fFlags=%#x uCacheGen=%u auGenerationsMissing=[%u,%u])\n",
+                        pszExe, pToolFsObj->bObjType, pToolFsObj->fFlags, pToolFsObj->uCacheGen,
+                        g_pFsCache->auGenerationsMissing[0], g_pFsCache->auGenerationsMissing[1]);
         }
-        kFsCacheObjRelease(g_pFsCache, pToolFsObj);
     }
+    else
+        kwErrPrintf("kwToolLookup(%s) -> NULL: enmError=%d\n", pszExe, enmError);
     return NULL;
 }
 
@@ -3473,6 +3811,42 @@ static uintptr_t __cdecl kwSandbox_msvcrt__beginthread(void (__cdecl *pfnThreadP
 }
 
 
+/** _beginthreadex - create a new thread, msvcr120.dll hack for c2.dll. */
+static uintptr_t __cdecl kwSandbox_msvcr120__beginthreadex(void *pvSecAttr, unsigned cbStack,
+                                                           unsigned (__stdcall *pfnThreadProc)(void *), void *pvUser,
+                                                           unsigned fCreate, unsigned *pidThread)
+{
+    /*
+     * The VC++ 12 (VS 2013) compiler pass two is now threaded.  Let it do
+     * whatever it needs to.
+     */
+    KW_LOG(("kwSandbox_msvcr120__beginthreadex: pvSecAttr=%p (inh=%d) cbStack=%#x pfnThreadProc=%p pvUser=%p fCreate=%#x pidThread=%p\n",
+            pvSecAttr, pvSecAttr ? ((LPSECURITY_ATTRIBUTES)pvSecAttr)->bInheritHandle : 0, cbStack,
+            pfnThreadProc, pvUser, fCreate, pidThread));
+    if (g_Sandbox.pTool->u.Sandboxed.enmHint == KWTOOLHINT_VISUAL_CPP_CL)
+    {
+        uintptr_t rcRet;
+        static uintptr_t (__cdecl *s_pfnReal)(void *, unsigned , unsigned (__stdcall *)(void *), void *, unsigned , unsigned *);
+        if (!s_pfnReal)
+        {
+            *(FARPROC *)&s_pfnReal = GetProcAddress(GetModuleHandleA("msvcr120.dll"), "_beginthreadex");
+            if (!s_pfnReal)
+            {
+                kwErrPrintf("kwSandbox_msvcr120__beginthreadex: Failed to resolve _beginthreadex in msvcr120.dll!\n");
+                __debugbreak();
+            }
+        }
+        rcRet = s_pfnReal(pvSecAttr, cbStack, pfnThreadProc, pvUser, fCreate, pidThread);
+        KW_LOG(("kwSandbox_msvcr120__beginthreadex: returns %p *pidThread=%#x\n", rcRet, pidThread ? *pidThread : -1));
+        return rcRet;
+    }
+
+    kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
+    KWFS_TODO();
+    return 0;
+}
+
+
 /** _beginthreadex - create a new thread. */
 static uintptr_t __cdecl kwSandbox_msvcrt__beginthreadex(void *pvSecAttr, unsigned cbStack,
                                                          unsigned (__stdcall *pfnThreadProc)(void *), void *pvUser,
@@ -4331,6 +4705,7 @@ static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA_VirtualApiModule(PKWDYNL
 static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA(LPCSTR pszFilename, HANDLE hFile, DWORD fFlags)
 {
     KSIZE       cchFilename = kHlpStrLen(pszFilename);
+    const char *pszSearchPath;
     PKWDYNLOAD  pDynLoad;
     PKWMODULE   pMod;
     int         rc;
@@ -4339,7 +4714,8 @@ static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA(LPCSTR pszFilename, HAND
     /*
      * Deal with a couple of extremely unlikely special cases right away.
      */
-    if (   !(fFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
+    if (   (   !(fFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)
+            || (fFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE))
         && (hFile == NULL || hFile == INVALID_HANDLE_VALUE) )
     { /* likely */ }
     else
@@ -4389,6 +4765,7 @@ static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA(LPCSTR pszFilename, HAND
      */
     if (fFlags & (  DONT_RESOLVE_DLL_REFERENCES
                   | LOAD_LIBRARY_AS_DATAFILE
+                  | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE
                   | LOAD_LIBRARY_AS_IMAGE_RESOURCE) )
         return kwSandbox_Kernel32_LoadLibraryExA_Resource(pDynLoad, fFlags);
 
@@ -4403,15 +4780,16 @@ static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA(LPCSTR pszFilename, HAND
      * Normal library loading.
      * We start by being very lazy and reusing the code for resolving imports.
      */
+    pszSearchPath = kwSandboxDoGetEnvA(&g_Sandbox, "PATH", 4);
     if (!kHlpIsFilenameOnly(pszFilename))
-        pMod = kwLdrModuleTryLoadDll(pszFilename, KWLOCATION_UNKNOWN, g_Sandbox.pTool->u.Sandboxed.pExe);
+        pMod = kwLdrModuleTryLoadDll(pszFilename, KWLOCATION_UNKNOWN, g_Sandbox.pTool->u.Sandboxed.pExe, pszSearchPath);
     else
     {
-        rc = kwLdrModuleResolveAndLookup(pszFilename, g_Sandbox.pTool->u.Sandboxed.pExe, NULL /*pImporter*/, &pMod);
+        rc = kwLdrModuleResolveAndLookup(pszFilename, g_Sandbox.pTool->u.Sandboxed.pExe, NULL /*pImporter*/, pszSearchPath, &pMod);
         if (rc != 0)
             pMod = NULL;
     }
-    if (pMod)
+    if (pMod && pMod != (PKWMODULE)~(KUPTR)0)
     {
         /* Enter it into the tool module table and dynamic link request cache. */
         kwToolAddModuleAndImports(g_Sandbox.pTool, pMod);
@@ -4439,12 +4817,81 @@ static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExA(LPCSTR pszFilename, HAND
     {
         KWFS_TODO();
         kHlpFree(pDynLoad);
-        SetLastError(ERROR_MOD_NOT_FOUND);
+        SetLastError(pMod ? ERROR_BAD_EXE_FORMAT : ERROR_MOD_NOT_FOUND);
     }
     return NULL;
 }
 
 
+/** Kernel32 - LoadLibraryExA() for native overloads */
+static HMODULE WINAPI kwSandbox_Kernel32_Native_LoadLibraryExA(LPCSTR pszFilename, HANDLE hFile, DWORD fFlags)
+{
+    char szPath[1024];
+    KWLDR_LOG(("kwSandbox_Kernel32_Native_LoadLibraryExA(%s, %p, %#x)\n", pszFilename, hFile, fFlags));
+
+    /*
+     * We may have to help resolved unqualified DLLs living in the executable directory.
+     */
+    if (kHlpIsFilenameOnly(pszFilename))
+    {
+        KSIZE cchFilename = kHlpStrLen(pszFilename);
+        KSIZE cchExePath  = g_Sandbox.pTool->u.Sandboxed.pExe->offFilename;
+        if (cchExePath + cchFilename + 1 <= sizeof(szPath))
+        {
+            kHlpMemCopy(szPath, g_Sandbox.pTool->u.Sandboxed.pExe->pszPath, cchExePath);
+            kHlpMemCopy(&szPath[cchExePath], pszFilename, cchFilename + 1);
+            if (kwFsPathExists(szPath))
+            {
+                KWLDR_LOG(("kwSandbox_Kernel32_Native_LoadLibraryExA: %s -> %s\n", pszFilename, szPath));
+                pszFilename = szPath;
+            }
+        }
+
+        if (pszFilename != szPath)
+        {
+            KSIZE cchSuffix = 0;
+            KBOOL fNeedSuffix = K_FALSE;
+            const char *pszCur = kwSandboxDoGetEnvA(&g_Sandbox, "PATH", 4);
+            while (*pszCur != '\0')
+            {
+                /* Find the end of the component */
+                KSIZE cch = 0;
+                while (pszCur[cch] != ';' && pszCur[cch] != '\0')
+                    cch++;
+
+                if (   cch > 0 /* wrong, but whatever */
+                    && cch + 1 + cchFilename + cchSuffix < sizeof(szPath))
+                {
+                    char *pszDst = kHlpMemPCopy(szPath, pszCur, cch);
+                    if (   szPath[cch - 1] != ':'
+                        && szPath[cch - 1] != '/'
+                        && szPath[cch - 1] != '\\')
+                        *pszDst++ = '\\';
+                    pszDst = kHlpMemPCopy(pszDst, pszFilename, cchFilename);
+                    if (fNeedSuffix)
+                        pszDst = kHlpMemPCopy(pszDst, ".dll", 4);
+                    *pszDst = '\0';
+
+                    if (kwFsPathExists(szPath))
+                    {
+                        KWLDR_LOG(("kwSandbox_Kernel32_Native_LoadLibraryExA: %s -> %s\n", pszFilename, szPath));
+                        pszFilename = szPath;
+                        break;
+                    }
+                }
+
+                /* Advance */
+                pszCur += cch;
+                while (*pszCur == ';')
+                    pszCur++;
+            }
+        }
+    }
+
+    return LoadLibraryExA(pszFilename, hFile, fFlags);
+}
+
+
 /** Kernel32 - LoadLibraryExW()   */
 static HMODULE WINAPI kwSandbox_Kernel32_LoadLibraryExW(LPCWSTR pwszFilename, HANDLE hFile, DWORD fFlags)
 {
@@ -4492,6 +4939,7 @@ static HMODULE WINAPI kwSandbox_Kernel32_GetModuleHandleA(LPCSTR pszModule)
 {
     KSIZE i;
     KSIZE cchModule;
+    PKWDYNLOAD pDynLoad;
     kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
 
     /*
@@ -4513,7 +4961,27 @@ static HMODULE WINAPI kwSandbox_Kernel32_GetModuleHandleA(LPCSTR pszModule)
             return g_aGetModuleHandleCache[i].hmod = GetModuleHandleA(pszModule);
         }
 
+    /*
+     * Modules we've dynamically loaded.
+     */
+    for (pDynLoad = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead; pDynLoad; pDynLoad = pDynLoad->pNext)
+        if (   pDynLoad->pMod
+            && (   stricmp(pDynLoad->pMod->pszPath, pszModule) == 0
+                || stricmp(&pDynLoad->pMod->pszPath[pDynLoad->pMod->offFilename], pszModule) == 0) )
+        {
+            if (   pDynLoad->pMod->fNative
+                || pDynLoad->pMod->u.Manual.enmState == KWMODSTATE_READY)
+            {
+                KW_LOG(("kwSandbox_Kernel32_GetModuleHandleA(%s,,) -> %p [dynload]\n", pszModule, pDynLoad->hmod));
+                return pDynLoad->hmod;
+            }
+            SetLastError(ERROR_MOD_NOT_FOUND);
+            return NULL;
+        }
+
+    kwErrPrintf("pszModule=%s\n", pszModule);
     KWFS_TODO();
+    SetLastError(ERROR_MOD_NOT_FOUND);
     return NULL;
 }
 
@@ -4523,6 +4991,7 @@ static HMODULE WINAPI kwSandbox_Kernel32_GetModuleHandleW(LPCWSTR pwszModule)
 {
     KSIZE i;
     KSIZE cwcModule;
+    PKWDYNLOAD pDynLoad;
     kHlpAssert(GetCurrentThreadId() == g_Sandbox.idMainThread);
 
     /*
@@ -4544,7 +5013,27 @@ static HMODULE WINAPI kwSandbox_Kernel32_GetModuleHandleW(LPCWSTR pwszModule)
             return g_aGetModuleHandleCache[i].hmod = GetModuleHandleW(pwszModule);
         }
 
+    /*
+     * Modules we've dynamically loaded.
+     */
+    for (pDynLoad = g_Sandbox.pTool->u.Sandboxed.pDynLoadHead; pDynLoad; pDynLoad = pDynLoad->pNext)
+        if (   pDynLoad->pMod
+            && (   _wcsicmp(pDynLoad->pMod->pwszPath, pwszModule) == 0
+                || _wcsicmp(&pDynLoad->pMod->pwszPath[pDynLoad->pMod->offFilename], pwszModule) == 0) ) /** @todo wrong offset */
+        {
+            if (   pDynLoad->pMod->fNative
+                || pDynLoad->pMod->u.Manual.enmState == KWMODSTATE_READY)
+            {
+                KW_LOG(("kwSandbox_Kernel32_GetModuleHandleW(%ls,,) -> %p [dynload]\n", pwszModule, pDynLoad->hmod));
+                return pDynLoad->hmod;
+            }
+            SetLastError(ERROR_MOD_NOT_FOUND);
+            return NULL;
+        }
+
+    kwErrPrintf("pwszModule=%ls\n", pwszModule);
     KWFS_TODO();
+    SetLastError(ERROR_MOD_NOT_FOUND);
     return NULL;
 }
 
@@ -8759,6 +9248,17 @@ static void * __cdecl kwSandbox_msvcrt_memcpy(void *pvDst, void const *pvSrc, si
     return pvDst;
 }
 
+
+/** CRT - memset   */
+static void * __cdecl kwSandbox_msvcrt_memset(void *pvDst, int bFiller, size_t cb)
+{
+    KU8       *pbDst = (KU8 *)pvDst;
+    KSIZE      cbLeft = cb;
+    while (cbLeft-- > 0)
+        *pbDst++ = bFiller;
+    return pvDst;
+}
+
 #endif /* NDEBUG */
 
 
@@ -8881,6 +9381,7 @@ KWREPLACEMENTFUNCTION const g_aSandboxReplacements[] =
 
     { TUPLE("_beginthread"),                NULL,       (KUPTR)kwSandbox_msvcrt__beginthread },
     { TUPLE("_beginthreadex"),              NULL,       (KUPTR)kwSandbox_msvcrt__beginthreadex },
+    { TUPLE("_beginthreadex"),          "msvcr120.dll", (KUPTR)kwSandbox_msvcr120__beginthreadex }, /* higher priority last */
 
     { TUPLE("__argc"),                      NULL,       (KUPTR)&g_Sandbox.cArgs },
     { TUPLE("__argv"),                      NULL,       (KUPTR)&g_Sandbox.papszArgs },
@@ -8920,6 +9421,7 @@ KWREPLACEMENTFUNCTION const g_aSandboxReplacements[] =
 
 #ifndef NDEBUG
     { TUPLE("memcpy"),                      NULL,       (KUPTR)kwSandbox_msvcrt_memcpy },
+    { TUPLE("memset"),                      NULL,       (KUPTR)kwSandbox_msvcrt_memset },
 #endif
 };
 /** Number of entries in g_aReplacements. */
@@ -8969,6 +9471,7 @@ KWREPLACEMENTFUNCTION const g_aSandboxNativeReplacements[] =
     { TUPLE("DeleteFileW"),                 NULL,       (KUPTR)kwSandbox_Kernel32_DeleteFileW },
 #endif
     { TUPLE("SetConsoleCtrlHandler"),       NULL,       (KUPTR)kwSandbox_Kernel32_SetConsoleCtrlHandler },
+    { TUPLE("LoadLibraryExA"),              NULL,       (KUPTR)kwSandbox_Kernel32_Native_LoadLibraryExA },
 
     { TUPLE("WriteConsoleA"),               NULL,       (KUPTR)kwSandbox_Kernel32_WriteConsoleA },
     { TUPLE("WriteConsoleW"),               NULL,       (KUPTR)kwSandbox_Kernel32_WriteConsoleW },
@@ -9280,8 +9783,9 @@ static int kwSandboxInit(PKWSANDBOX pSandbox, PKWTOOL pTool,
         {
             const char *pszVar   = papszEnvVars[i];
             KSIZE       cchVar   = kHlpStrLen(pszVar);
+            const char *pszEqual;
             if (   cchVar > 0
-                && kHlpMemChr(pszVar, '=', cchVar) != NULL)
+                && (pszEqual = kHlpMemChr(pszVar, '=', cchVar)) != NULL)
             {
                 char       *pszCopy  = kHlpDup(pszVar, cchVar + 1);
                 wchar_t    *pwszCopy = kwStrToUtf16AllocN(pszVar, cchVar + 1);
@@ -9291,6 +9795,16 @@ static int kwSandboxInit(PKWSANDBOX pSandbox, PKWTOOL pTool,
                     pSandbox->environ[iDst]       = pszCopy;
                     pSandbox->papwszEnvVars[iDst] = pwszCopy;
                     pSandbox->wenviron[iDst]      = pwszCopy;
+
+                    /* When we see the path, we must tell the system or native exec and module loading won't work . */
+                    if (   (pszEqual - pszVar) == 4
+                        && (  pszCopy[0] == 'P' || pszCopy[0] == 'p')
+                        && (  pszCopy[1] == 'A' || pszCopy[1] == 'a')
+                        && (  pszCopy[2] == 'T' || pszCopy[2] == 't')
+                        && (  pszCopy[3] == 'H' || pszCopy[3] == 'h'))
+                        if (!SetEnvironmentVariableW(L"Path", &pwszCopy[5]))
+                            kwErrPrintf("kwSandboxInit: SetEnvironmentVariableW(Path,) failed: %u\n", GetLastError());
+
                     iDst++;
                 }
                 else
@@ -9311,7 +9825,6 @@ static int kwSandboxInit(PKWSANDBOX pSandbox, PKWTOOL pTool,
     else
         return kwErrPrintfRc(KERR_NO_MEMORY, "Error setting up environment variables: kwSandboxGrowEnv failed\n");
 
-
     /*
      * Invalidate the volatile parts of cache (kBuild output directory,
      * temporary directory, whatever).
@@ -9821,7 +10334,7 @@ static int kSubmitHandleJobUnpacked(const char *pszExecutable, const char *pszCw
     /*
      * Lookup the tool.
      */
-    pTool = kwToolLookup(pszExecutable);
+    pTool = kwToolLookup(pszExecutable, cEnvVars, papszEnvVars);
     if (pTool)
     {
         /*
@@ -10620,11 +11133,44 @@ int main(int argc, char **argv)
         }
         else if (strcmp(argv[i], "--test") == 0)
             return kwTestRun(argc - i - 1, &argv[i + 1]);
+        else if (strcmp(argv[i], "--priority") == 0)
+        {
+            i++;
+            if (i < argc)
+            {
+                char *pszEnd = NULL;
+                unsigned long uValue = strtoul(argv[i], &pszEnd, 16);
+                if (   *argv[i]
+                    && pszEnd != NULL
+                    && *pszEnd == '\0'
+                    && uValue >= 1
+                    && uValue <= 5)
+                {
+                    DWORD dwClass, dwPriority;
+                    switch (uValue)
+                    {
+                        case 1: dwClass = IDLE_PRIORITY_CLASS;         dwPriority = THREAD_PRIORITY_IDLE; break;
+                        case 2: dwClass = BELOW_NORMAL_PRIORITY_CLASS; dwPriority = THREAD_PRIORITY_BELOW_NORMAL; break;
+                        case 3: dwClass = NORMAL_PRIORITY_CLASS;       dwPriority = THREAD_PRIORITY_NORMAL; break;
+                        case 4: dwClass = HIGH_PRIORITY_CLASS;         dwPriority = 0xffffffff; break;
+                        case 5: dwClass = REALTIME_PRIORITY_CLASS;     dwPriority = 0xffffffff; break;
+                    }
+                    SetPriorityClass(GetCurrentProcess(), dwClass);
+                    if (dwPriority != 0xffffffff)
+                        SetThreadPriority(GetCurrentThread(), dwPriority);
+                }
+                else
+                    return kwErrPrintfRc(2, "Invalid --priority argument: %s\n", argv[i]);
+            }
+            else
+                return kwErrPrintfRc(2, "--priority takes an argument!\n");
+
+        }
         else if (   strcmp(argv[i], "--help") == 0
                  || strcmp(argv[i], "-h") == 0
                  || strcmp(argv[i], "-?") == 0)
         {
-            printf("usage: kWorker [--volatile dir] --pipe <pipe-handle>\n"
+            printf("usage: kWorker [--volatile dir] [--priority <1-5>] --pipe <pipe-handle>\n"
                    "usage: kWorker <--help|-h>\n"
                    "usage: kWorker <--version|-V>\n"
                    "usage: kWorker [--volatile dir] --test [<times> [--chdir <dir>] [--breakpoint] -- args\n"
diff --git a/src/kWorker/kWorkerTlsXxxK.c b/src/kWorker/kWorkerTlsXxxK.c
new file mode 100644
index 0000000..6bd9e47
--- /dev/null
+++ b/src/kWorker/kWorkerTlsXxxK.c
@@ -0,0 +1,110 @@
+/* $Id: kWorkerTlsXxxK.c 3042 2017-05-11 10:23:12Z bird $ */
+/** @file
+ * kWorkerTlsXxxK - Loader TLS allocation hack DLL.
+ */
+
+/*
+ * Copyright (c) 2017 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kBuild.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <windows.h>
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+typedef void KWLDRTLSALLOCATIONHOOK(void *hDll, ULONG idxTls, PIMAGE_TLS_CALLBACK *ppfnTlsCallback);
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+__declspec(dllexport) void __stdcall DummyTlsCallback(void *hDll, DWORD dwReason, void *pvContext);
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+/** The TLS pointer array. The 2nd entry is NULL and serve to terminate the array.
+ * The first entry can be used by kWorker if it needs to. */
+__declspec(dllexport) PIMAGE_TLS_CALLBACK g_apfnTlsCallbacks[2] = { DummyTlsCallback, NULL };
+
+/**
+ * The TLS index.
+ */
+__declspec(dllexport) ULONG               g_idxTls              = ~(ULONG)0;
+
+/**
+ * Initialization data.
+ */
+static char const g_abDummy[TLS_SIZE] = {0x42};
+
+/**
+ * The TLS directory entry.  Not possible to get more than one from the linker
+ * and probably also the loader doesn't want more than one anyway.
+ */
+#pragma section(".rdata$T", long, read)
+__declspec(allocate(".rdata$T")) const IMAGE_TLS_DIRECTORY _tls_used =
+{
+    (ULONG_PTR)&g_abDummy,
+    (ULONG_PTR)&g_abDummy + sizeof(g_abDummy),
+    (ULONG_PTR)&g_idxTls,
+    (ULONG_PTR)&g_apfnTlsCallbacks,
+    0, /* This SizeOfZeroFill bugger doesn't work on w10/amd64 from what I can tell! */
+    IMAGE_SCN_ALIGN_32BYTES
+};
+
+
+/*
+ * This is just a dummy TLS callback function.
+ * We'll be replacing g_apfnTlsCallbacks[0] from kWorker.c after loading it.
+ *
+ * Note! W10 doesn't seem to want to process the TLS directory if the DLL
+ *       doesn't have any imports (to snap).
+ */
+__declspec(dllexport) void __stdcall DummyTlsCallback(void *hDll, DWORD dwReason, void *pvContext)
+{
+    (void)hDll; (void)dwReason; (void)pvContext;
+    if (dwReason == DLL_PROCESS_ATTACH)
+    {
+        HMODULE hModExe = (HMODULE)(ULONG_PTR)KWORKER_BASE;
+        KWLDRTLSALLOCATIONHOOK *pfnHook = (KWLDRTLSALLOCATIONHOOK *)GetProcAddress(hModExe, "kwLdrTlsAllocationHook");
+        if (pfnHook)
+        {
+            pfnHook(hDll, g_idxTls, &g_apfnTlsCallbacks[0]);
+            return;
+        }
+        __debugbreak();
+    }
+}
+
+
+/*
+ * Dummy DLL entry point to avoid dragging in unnecessary CRT stuff. kWorkerTls1K!_tls_index
+ */
+BOOL __stdcall DummyDllEntry(void *hDll, DWORD dwReason, void *pvContext)
+{
+    (void)hDll; (void)dwReason; (void)pvContext;
+    return TRUE;
+}
+
diff --git a/src/kash/Makefile.kmk b/src/kash/Makefile.kmk
index f378c8e..63f068b 100644
--- a/src/kash/Makefile.kmk
+++ b/src/kash/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2652 2012-09-09 17:21:48Z bird $
+# $Id: Makefile.kmk 3073 2017-10-02 08:45:19Z bird $
 ## @file
 # Sub-makefile for kash.
 #
@@ -52,6 +52,9 @@ kash_DEFS.dragonfly = \
 	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
 kash_DEFS.freebsd = \
 	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
+kash_DEFS.gnukfbsd = HAVE_SYSCTL_H
+kash_DEFS.netbsd = \
+	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
 kash_DEFS.openbsd = \
 	HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME
 kash_INCS = $(kash_0_OUTDIR) . # (the last is because of error.h)
@@ -99,6 +102,12 @@ kash_SOURCES = \
 	shheap.c \
 	shthread.c \
 	shfile.c
+kash_SOURCES.gnukfbsd = \
+	sys_signame.c \
+	strlcpy.c
+kash_SOURCES.gnuknbsd = \
+	sys_signame.c \
+	strlcpy.c
 kash_SOURCES.haiku = \
 	sys_signame.c \
 	strlcpy.c
@@ -107,7 +116,7 @@ kash_SOURCES.linux = \
 	strlcpy.c
 kash_SOURCES.solaris = \
 	sys_signame.c \
-        strlcpy.c
+	strlcpy.c
 kash_SOURCES.win = \
 	sys_signame.c \
 	strlcpy.c \
@@ -135,6 +144,10 @@ kash_main.c_DEFS = KBUILD_SVN_REV=$(KBUILD_SVN_REV)
 
 
 if1of ($(KBUILD_TARGET), win os2)
+ KASH_USE_PREGENERATED_CODE = 1
+endif
+
+ifdef KASH_USE_PREGENERATED_CODE
 
 #
 # Use the pregenerated code.
@@ -154,7 +167,7 @@ endef
 $(foreach src, arith.h arith.c arith_lex.c builtins.h builtins.c nodes.h nodes.c token.h init.c,\
 $(eval $(def_copy_generated)))
 
-else
+else # !KASH_USE_PREGENERATED_CODE
 
 #
 # Generate the code on the fly.
@@ -208,7 +221,7 @@ $$(kash_0_OUTDIR)/init.c: \
 	$(BOOTSTRAP_SHELL) $+
 	$(MV) init.c $@
 
-endif
+endif # !KASH_USE_PREGENERATED_CODE
 
 #
 # For debugging file handle inheritance on Windows.
diff --git a/src/kash/eval.c b/src/kash/eval.c
index d96c2a3..78ae637 100644
--- a/src/kash/eval.c
+++ b/src/kash/eval.c
@@ -678,7 +678,7 @@ evalcommand(shinstance *psh, union node *cmd, int flags, struct backcmd *backcmd
 	char **envp;
 	int numvars;
 	struct strlist *sp;
-	int mode;
+	int mode = 0;
 	int pip[2];
 	struct cmdentry cmdentry;
 	struct job *jp;
@@ -692,11 +692,13 @@ evalcommand(shinstance *psh, union node *cmd, int flags, struct backcmd *backcmd
 	const char *path = pathval(psh);
 	volatile int temp_path;
 #if __GNUC__
-	/* Avoid longjmp clobbering */
+	/* Try avoid longjmp clobbering */
 	(void) &argv;
 	(void) &argc;
 	(void) &lastarg;
 	(void) &flags;
+	(void) &path;
+	(void) &mode;
 #endif
 
 	psh->vforked = 0;
diff --git a/src/kash/exec.c b/src/kash/exec.c
index d76bf2a..9fa8b32 100644
--- a/src/kash/exec.c
+++ b/src/kash/exec.c
@@ -121,32 +121,48 @@ shellexec(shinstance *psh, char **argv, char **envp, const char *path, int idx,
 {
 	char *cmdname;
 	int e;
+	const char *argv0 = argv[0];
+	int argv0len = (int)strlen(argv0);
+	char kmkcmd[48];
 #ifdef PC_EXE_EXTS
-        int has_ext = (int)strlen(argv[0]) - 4;
+        int has_ext = argv0len - 4;
         has_ext = has_ext > 0
-            && argv[0][has_ext] == '.'
+            && argv0[has_ext] == '.'
             /* use strstr and upper/lower permuated extensions to avoid multiple strcasecmp calls. */
             && strstr("exe;" "Exe;" "EXe;" "EXE;" "ExE;" "eXe;" "eXE;" "exE;"
                       "cmd;" "Cmd;" "CMd;" "CMD;" "CmD;" "cMd;" "cMD;" "cmD;"
                       "com;" "Com;" "COm;" "COM;" "CoM;" "cOm;" "cOM;" "coM;"
                       "bat;" "Bat;" "BAt;" "BAT;" "BaT;" "bAt;" "bAT;" "baT;"
                       "btm;" "Btm;" "BTm;" "BTM;" "BtM;" "bTm;" "bTM;" "btM;",
-                      argv[0] + has_ext + 1)
+		      argv0 + has_ext + 1)
                != NULL;
 #else
 	const int has_ext = 1;
 #endif
-	TRACE((psh, "shellexec: argv[0]=%s idx=%d\n", argv[0], idx));
-	if (strchr(argv[0], '/') != NULL) {
-		cmdname = stalloc(psh, strlen(argv[0]) + 5);
-		strcpy(cmdname, argv[0]);
+	TRACE((psh, "shellexec: argv[0]=%s idx=%d\n", argv0, idx));
+	if (strchr(argv0, '/') != NULL) {
+		cmdname = stalloc(psh, argv0len + 5);
+		strcpy(cmdname, argv0);
 		tryexec(psh, cmdname, argv, envp, vforked, has_ext);
 		TRACE((psh, "shellexec: cmdname=%s\n", cmdname));
 		stunalloc(psh, cmdname);
 		e = errno;
 	} else {
+		/* Before we search the PATH, transform kmk_builtin_% to kmk_% so we don't
+		   need to be too careful mixing internal and external kmk command. */
+		if (   argv0len > 12
+		    && argv0len < 42
+		    && strncmp(argv0, "kmk_builtin_", 12) == 0
+		    && strpbrk(argv0 + 12, "./\\-:;<>") == NULL) {
+			memcpy(kmkcmd, "kmk_", 4);
+			memcpy(&kmkcmd[4], argv0 + 12, argv0len + 1 - 8);
+			TRACE((psh, "shellexec: dropped '_builtin' from %s to %s\n", argv0, kmkcmd));
+			argv0len -= 8;
+			argv0 = kmkcmd;
+		}
+
 		e = ENOENT;
-		while ((cmdname = padvance(psh, &path, argv[0])) != NULL) {
+		while ((cmdname = padvance(psh, &path, argv0)) != NULL) {
 			if (--idx < 0 && psh->pathopt == NULL) {
 				tryexec(psh, cmdname, argv, envp, vforked, has_ext);
 				if (errno != ENOENT && errno != ENOTDIR)
@@ -552,9 +568,10 @@ find_command(shinstance *psh, char *name, struct cmdentry *entry, int act, const
 	struct stat statb;
 	int e;
 	int (*bltin)(shinstance*,int,char **);
-
+	int argv0len = (int)strlen(name);
+	char kmkcmd[48];
 #ifdef PC_EXE_EXTS
-        int has_ext = (int)(strlen(name) - 4);
+        int has_ext = argv0len - 4;
         has_ext = has_ext > 0
             && name[has_ext] == '.'
             /* use strstr and upper/lower permuated extensions to avoid multiple strcasecmp calls. */
@@ -639,6 +656,19 @@ find_command(shinstance *psh, char *name, struct cmdentry *entry, int act, const
 			prev = cmdp->param.index;
 	}
 
+	/* Before we search the PATH, transform kmk_builtin_% to kmk_% so we don't
+	   need to be too careful mixing internal and external kmk command. */
+	if (   argv0len > 12
+	    && argv0len < (int)sizeof(kmkcmd)
+	    && strncmp(name, "kmk_builtin_", 12) == 0
+	    && strpbrk(name + 12, "./\\-:;<>") == NULL) {
+	        memcpy(kmkcmd, "kmk_", 4);
+		memcpy(&kmkcmd[4], name + 12, argv0len + 1 - 8);
+		TRACE((psh, "find_command: dropped '_builtin' from %s to %s\n", name, kmkcmd));
+		argv0len -= 8;
+		name = kmkcmd;
+	}
+
 	e = ENOENT;
 	idx = -1;
 loop:
diff --git a/src/kash/input.c b/src/kash/input.c
index c3036fa..35ba917 100644
--- a/src/kash/input.c
+++ b/src/kash/input.c
@@ -280,7 +280,9 @@ preadbuffer(shinstance *psh)
 {
 	char *p, *q;
 	int more;
+#ifndef SMALL
 	int something;
+#endif
 	char savec;
 
 	if (psh->parsefile->strpush) {
@@ -304,7 +306,9 @@ again:
 	q = p = psh->parsenextc;
 
 	/* delete nul characters */
+#ifndef SMALL
 	something = 0;
+#endif
 	for (more = 1; more;) {
 		switch (*p) {
 		case '\0':
@@ -321,7 +325,9 @@ again:
 			break;
 
 		default:
+#ifndef SMALL
 			something = 1;
+#endif
 			break;
 		}
 
diff --git a/src/kash/mystring.h b/src/kash/mystring.h
index 78a0cfb..cc9662d 100644
--- a/src/kash/mystring.h
+++ b/src/kash/mystring.h
@@ -44,7 +44,7 @@ void scopyn(const char *, char *, ssize_t);
 int prefix(const char *, const char *);
 int number(struct shinstance *, const char *);
 int is_number(const char *);
-#ifdef _MSC_VER
+#if !defined(RT_OS_FREEBSD) && !defined(RT_OS_NETBSD) && !defined(RT_OS_OPENBSD) && !defined(RT_OS_OS2)
 size_t strlcpy(char *dst, const char *src, size_t siz);
 #endif
 
diff --git a/src/kash/parser.c b/src/kash/parser.c
index b0dbad7..2eea32e 100644
--- a/src/kash/parser.c
+++ b/src/kash/parser.c
@@ -913,7 +913,7 @@ readtoken1(shinstance *psh, int firstc, char const *syntax, char *eofmark, int s
 	int len;
 	char line[EOFMARKLEN + 1];
 	struct nodelist *bqlist;
-	int quotef;
+	int quotef = 0;
 	int *dblquotep = NULL;
 	size_t maxnest = 32;
 	int dblquote;
@@ -922,8 +922,20 @@ readtoken1(shinstance *psh, int firstc, char const *syntax, char *eofmark, int s
 	int parenlevel;	/* levels of parens in arithmetic */
 	int oldstyle;
 	char const *prevsyntax;	/* syntax before arithmetic */
+
+	psh->startlinno = psh->plinno;
+	dblquote = 0;
+	varnest = 0;
+	if (syntax == DQSYNTAX) {
+		SETDBLQUOTE();
+	}
+	quotef = 0;
+	bqlist = NULL;
+	arinest = 0;
+	parenlevel = 0;
+
 #if __GNUC__
-	/* Avoid longjmp clobbering */
+	/* Try avoid longjmp clobbering */
 	(void) &maxnest;
 	(void) &dblquotep;
 	(void) &out;
@@ -937,17 +949,6 @@ readtoken1(shinstance *psh, int firstc, char const *syntax, char *eofmark, int s
 	(void) &syntax;
 #endif
 
-	psh->startlinno = psh->plinno;
-	dblquote = 0;
-	varnest = 0;
-	if (syntax == DQSYNTAX) {
-		SETDBLQUOTE();
-	}
-	quotef = 0;
-	bqlist = NULL;
-	arinest = 0;
-	parenlevel = 0;
-
 	STARTSTACKSTR(psh, out);
 	loop: {	/* for each line, until end of word */
 #if ATTY
diff --git a/src/kash/shell.h b/src/kash/shell.h
index 9294204..53c652b 100644
--- a/src/kash/shell.h
+++ b/src/kash/shell.h
@@ -61,11 +61,13 @@
 # define BSD 1
 #endif
 
+#if 0
 #ifndef DO_SHAREDVFORK
 # if __NetBSD_Version__ >= 104000000
 #  define DO_SHAREDVFORK
 # endif
 #endif
+#endif
 
 typedef void *pointer;
 #ifndef NULL
diff --git a/src/kmk/Makefile.am b/src/kmk/Makefile.am
index 99a9a6a..bad8c4a 100644
--- a/src/kmk/Makefile.am
+++ b/src/kmk/Makefile.am
@@ -56,6 +56,8 @@ kmk_SOURCES =	ar.c arscan.c commands.c default.c dir.c expand.c file.c \
 		electric.c \
 		../lib/md5.c \
 		../lib/kDep.c \
+		../lib/kbuild_version.c \
+		../lib/maybe_con_fwrite.c \
 		\
 		kmkbuiltin.c \
 		kmkbuiltin/append.c \
@@ -75,10 +77,13 @@ kmk_SOURCES =	ar.c arscan.c commands.c default.c dir.c expand.c file.c \
 		kmkbuiltin/mkdir.c \
 		kmkbuiltin/mv.c \
 		kmkbuiltin/printf.c \
+		kmkbuiltin/redirect.c \
 		kmkbuiltin/rm.c \
 		kmkbuiltin/rmdir.c \
 		kmkbuiltin/sleep.c \
 		kmkbuiltin/test.c \
+		kmkbuiltin/touch.c \
+               \
 		kmkbuiltin/err.c \
 		kmkbuiltin/fts.c \
 		kmkbuiltin/setmode.c \
@@ -86,9 +91,14 @@ kmk_SOURCES =	ar.c arscan.c commands.c default.c dir.c expand.c file.c \
 		kmkbuiltin/strlcpy.c \
 		kmkbuiltin/osdep.c \
 		kmkbuiltin/kbuild_protection.c \
-		kmkbuiltin/kbuild_version.c
+		kmkbuiltin/common-env-and-cwd-opt.c
+
+kmk_redirect_SOURCES = kmkbuiltin/redirect.c \
+		kmkbuiltin/common-env-and-cwd-opt.c \
+		kmkbuiltin/err.c \
+		../lib/kbuild_version.c
+kmk_redirect_CFLAGS = -UKMK
 
-kmk_redirect_SOURCES = kmkbuiltin/redirect.c
 
 EXTRA_kmk_SOURCES = vmsjobs.c remote-stub.c remote-cstms.c
 
@@ -171,7 +181,7 @@ DEFS = \
 	-DCONFIG_WITH_KMK_BUILTIN \
     @DEFS@
 
-AM_CPPFLAGS =	$(GLOBINC) -I$(srcdir)/../lib
+AM_CPPFLAGS =	$(GLOBINC) -I$(srcdir)/../lib -I$(srcdir)/../lib/kStuff/include
 # Only process if target is MS-Windows
 if WINDOWSENV
     AM_CPPFLAGS +=	$(W32INC)
diff --git a/src/kmk/Makefile.kmk b/src/kmk/Makefile.kmk
index 25a9da6..a86e8fc 100644
--- a/src/kmk/Makefile.kmk
+++ b/src/kmk/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2994 2016-11-01 22:41:41Z bird $
+# $Id: Makefile.kmk 3062 2017-09-30 11:26:21Z bird $
 ## @file
 # Sub-makefile for kmk / GNU Make.
 #
@@ -107,6 +107,12 @@ kmkmissing_SOURCES.dragonfly = \
 kmkmissing_SOURCES.freebsd = \
 	glob/fnmatch.c
 
+kmkmissing_SOURCES.gnukfbsd += \
+	kmkbuiltin/strlcpy.c
+
+kmkmissing_SOURCES.gnuknbsd += \
+	kmkbuiltin/strlcpy.c
+
 kmkmissing_SOURCES.haiku = \
 	kmkbuiltin/haikufakes.c \
 	glob/fnmatch.c
@@ -114,6 +120,10 @@ kmkmissing_SOURCES.haiku = \
 kmkmissing_SOURCES.linux += \
 	kmkbuiltin/strlcpy.c
 
+kmkmissing_SOURCES.netbsd = \
+	glob/glob.c \
+	glob/fnmatch.c
+
 kmkmissing_SOURCES.openbsd = \
 	kmkbuiltin/openbsd.c
 
@@ -285,7 +295,8 @@ kmk_SOURCES += \
 	kmkbuiltin/rmdir.c \
 	$(if-expr $(KBUILD_TARGET) == win,kmkbuiltin/kSubmit.c) \
 	kmkbuiltin/sleep.c \
-	kmkbuiltin/test.c
+	kmkbuiltin/test.c \
+	kmkbuiltin/touch.c
 
 ## @todo kmkbuiltin/redirect.c
 
@@ -317,6 +328,7 @@ PROGRAMS += \
 	kmk_rmdir \
 	kmk_sleep \
 	kmk_test \
+	kmk_touch \
 	kDepIDB \
 	kDepObj \
 
@@ -416,6 +428,11 @@ kmk_test_DEFS = kmk_builtin_test=main
 kmk_test_SOURCES = \
 	kmkbuiltin/test.c
 
+kmk_touch_TEMPLATE = BIN-KMK
+kmk_touch_DEFS = kmk_builtin_touch=main
+kmk_touch_SOURCES = \
+	kmkbuiltin/touch.c
+
 kDepIDB_TEMPLATE = BIN-KMK
 kDepIDB_DEFS = kmk_builtin_kDepIDB=main
 kDepIDB_INCS = .
diff --git a/src/kmk/config.h.netbsd b/src/kmk/config.h.netbsd
new file mode 100755
index 0000000..77c43d1
--- /dev/null
+++ b/src/kmk/config.h.netbsd
@@ -0,0 +1,459 @@
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if using `getloadavg.c'. */
+/* #undef C_GETLOADAVG */
+
+/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */
+/* #undef DGUX */
+
+/* Use high resolution file timestamps if nonzero. */
+#define FILE_TIMESTAMP_HI_RES 0
+
+/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid.
+   */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define to 1 if your compiler conforms to the ANSI C standard. */
+#define HAVE_ANSI_COMPILER 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Use case insensitive file names */
+/* #undef HAVE_CASE_INSENSITIVE_FS */
+
+/* Define to 1 if you have the clock_gettime function. */
+/* #undef HAVE_CLOCK_GETTIME */
+
+/* Define to 1 if you have the declaration of `bsd_signal', and to 0 if you
+   don't. */
+#define HAVE_DECL_BSD_SIGNAL 0
+
+/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL_SYS_SIGLIST 1
+
+/* Define to 1 if you have the declaration of `_sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL__SYS_SIGLIST 0
+
+/* Define to 1 if you have the declaration of `__sys_siglist', and to 0 if you
+   don't. */
+#define HAVE_DECL___SYS_SIGLIST 0
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Use platform specific coding */
+/* #undef HAVE_DOS_PATHS */
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdopen' function. */
+#define HAVE_FDOPEN 1
+
+/* Define to 1 if you have the `fileno' function. */
+#define HAVE_FILENO 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getgroups' function. */
+#define HAVE_GETGROUPS 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+/* #undef HAVE_GETHOSTBYNAME */
+
+/* Define to 1 if you have the `gethostname' function. */
+/* #undef HAVE_GETHOSTNAME */
+
+/* Define to 1 if you have the `getloadavg' function. */
+#define HAVE_GETLOADAVG 1
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have a standard gettimeofday function */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `dgc' library (-ldgc). */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `mktemp' function. */
+#define HAVE_MKTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nlist.h> header file. */
+/* #undef HAVE_NLIST_H */
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define to 1 if <signal.h> defines the SA_RESTART constant. */
+#define HAVE_SA_RESTART 1
+
+/* Define to 1 if you have the `setegid' function. */
+#define HAVE_SETEGID 1
+
+/* Define to 1 if you have the `seteuid' function. */
+#define HAVE_SETEUID 1
+
+/* Define to 1 if you have the `setlinebuf' function. */
+#define HAVE_SETLINEBUF 1
+
+/* Define to 1 if you have the `setlocale' function. */
+/* #undef HAVE_SETLOCALE */
+
+/* Define to 1 if you have the `setregid' function. */
+#define HAVE_SETREGID 1
+
+/* Define to 1 if you have the `setreuid' function. */
+#define HAVE_SETREUID 1
+
+/* Define to 1 if you have the `setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the `setvbuf' function. */
+#define HAVE_SETVBUF 1
+
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the `sigsetmask' function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define to 1 if you have the `socket' function. */
+/* #undef HAVE_SOCKET */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strcmpi' function. */
+/* #undef HAVE_STRCMPI */
+
+/* Define to 1 if you have the `strcoll' function and it is properly defined.
+   */
+#define HAVE_STRCOLL 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `stricmp' function. */
+/* #undef HAVE_STRICMP */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strncmpi' function. */
+/* #undef HAVE_STRNCMPI */
+
+/* Define to 1 if you have the `strndup' function. */
+#define HAVE_STRNDUP 1
+
+/* Define to 1 if you have the `strnicmp' function. */
+/* #undef HAVE_STRNICMP */
+
+/* Define to 1 if you have the `strsignal' function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define to 1 if `n_un.n_name' is a member of `struct nlist'. */
+/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the \`union wait' type in <sys/wait.h>. */
+/* #undef HAVE_UNION_WAIT */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <varargs.h> header file. */
+/* #undef HAVE_VARARGS_H */
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the `wait3' function. */
+#define HAVE_WAIT3 1
+
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Build host information. (not used by kmk) */
+#define MAKE_HOST "i386-unknown-netbsdelf5.1."
+
+/* Define to 1 to enable job server support in GNU make. */
+#define MAKE_JOBSERVER 1
+
+/* Define to 1 to enable symbolic link timestamp checking. */
+#define MAKE_SYMLINKS 1
+
+/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend
+   on `HAVE_STRUCT_NLIST_N_UN_N_NAME */
+/* #undef NLIST_NAME_UNION */
+
+/* Define to 1 if struct nlist.n_name is a pointer rather than an array. */
+/* #undef NLIST_STRUCT */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "make"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-make at gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GNU make"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GNU make 3.82"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "make"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "http://www.gnu.org/software/make/"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.82"
+
+/* Define to the character that separates directories in PATH. */
+#define PATH_SEPARATOR_CHAR ':'
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to the name of the SCCS 'get' command. */
+#define SCCS_GET "get"
+
+/* Define to 1 if the SCCS 'get' command understands the '-G<file>' option. */
+/* #undef SCCS_GET_MINUS_G */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if struct stat contains a nanoseconds field */
+/* #undef ST_MTIM_NSEC */
+
+/* Define to 1 on System V Release 4. */
+/* #undef SVR4 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 for Encore UMAX. */
+/* #undef UMAX */
+
+/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of
+   <sys/cpustats.h>. */
+/* #undef UMAX4_3 */
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+
+/* Version number of package */
+#define VERSION "3.82"
+
+/* Use platform specific coding */
+/* #undef WINDOWS32 */
+
+/* Define if using the dmalloc debugging malloc package */
+/* #undef WITH_DMALLOC */
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define uintmax_t if not defined in <stdint.h> or <inttypes.h>. */
+/* #undef uintmax_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
+
+#include "inlined_memchr.h"
diff --git a/src/kmk/dir.c b/src/kmk/dir.c
index c9b1b37..0e44824 100644
--- a/src/kmk/dir.c
+++ b/src/kmk/dir.c
@@ -710,7 +710,7 @@ static int
 dir_contents_file_exists_p (struct directory_contents *dir,
                             const char *filename)
 {
-  unsigned int hash;
+  /*unsigned int hash;*/
   struct dirfile *df;
   struct dirent *d;
 #ifdef WINDOWS32
@@ -744,7 +744,7 @@ dir_contents_file_exists_p (struct directory_contents *dir,
   filename = vmsify (filename,0);
 #endif
 
-  hash = 0;
+  /*hash = 0;*/
   if (filename != 0)
     {
       struct dirfile dirfile_key;
@@ -1340,11 +1340,7 @@ void print_dir_stats (void)
 

 /* Hooks for globbing.  */
 
-#if defined(KMK) && !defined(__OS2__)
-# include "glob/glob.h"
-#else
 #include <glob.h>
-#endif
 
 /* Structure describing state of iterating through a directory hash table.  */
 
@@ -1479,7 +1475,7 @@ dir_setup_glob (glob_t *gl)
 #ifdef __EMX__ /* The FreeBSD implementation actually uses gl_lstat!! */
   gl->gl_lstat = local_stat;
 #endif
-#if defined(KMK) && !defined(__OS2__)
+#ifdef GLOB_WITH_EXTENDED_KMK_MEMBERS
   gl->gl_exists = file_exists_p;
   gl->gl_isdir = dir_exists_p;
 #endif
diff --git a/src/kmk/expreval.c b/src/kmk/expreval.c
index 4d9cb5f..f887a7c 100644
--- a/src/kmk/expreval.c
+++ b/src/kmk/expreval.c
@@ -1,5 +1,5 @@
 #ifdef CONFIG_WITH_IF_CONDITIONALS
-/* $Id: expreval.c 2573 2012-05-13 19:39:47Z bird $ */
+/* $Id: expreval.c 3065 2017-09-30 12:52:35Z bird $ */
 /** @file
  * expreval - Expressions evaluator, C / BSD make / nmake style.
  */
@@ -390,7 +390,7 @@ static EXPRRET expr_string_to_num(PEXPR pThis, EXPRINT64 *piDst, const char *psz
                 i = -i;
             *piDst = i;
             if (!fQuiet)
-                expr_error(pThis, "Invalid a number \"%.80s\"", pszSrc);
+                expr_error(pThis, "Invalid number \"%.80s\"", pszSrc);
             return kExprRet_Error;
         }
 
@@ -1396,7 +1396,7 @@ static EXPRRET expr_op_equal(PEXPR pThis)
     }
 
     expr_pop_and_delete_var(pThis);
-    return kExprRet_Ok;
+    return rc;
 }
 
 
diff --git a/src/kmk/glob/glob.h b/src/kmk/glob/glob.h
index f987d03..ef004c0 100644
--- a/src/kmk/glob/glob.h
+++ b/src/kmk/glob/glob.h
@@ -137,6 +137,7 @@ typedef struct
     int (*gl_stat) __PMT ((__const char *, struct stat *));
 #endif
 #ifdef KMK
+# define GLOB_WITH_EXTENDED_KMK_MEMBERS
     int (*gl_exists) __PMT ((__const char *));
     int (*gl_isdir) __PMT ((__const char *));
 #endif
diff --git a/src/kmk/job.c b/src/kmk/job.c
index 06efde3..8cd910e 100644
--- a/src/kmk/job.c
+++ b/src/kmk/job.c
@@ -464,9 +464,30 @@ child_error (const char *target_name,
 #else
   if (exit_sig == 0)
 # if defined(KMK) && defined(KBUILD_OS_WINDOWS)
-    error (NILF, ignored ? _("[%s] Error %d (%#x) (ignored)") :
-           _("*** [%s] Error %d (%#x)"),
-           target_name, exit_code, exit_code);
+    {
+      const char *name = NULL;
+      switch ((unsigned)exit_code)
+        {
+        case 0xc0000005U: name = "STATUS_ACCESS_VIOLATION"; break;
+        case 0xc000013aU: name = "STATUS_CONTROL_C_EXIT"; break;
+        case 0xc0000374U: name = "STATUS_HEAP_CORRUPTION"; break;
+        case 0xc0000409U: name = "STATUS_STACK_BUFFER_OVERRUN"; break;
+        case 0xc0000417U: name = "STATUS_INVALID_CRUNTIME_PARAMETER"; break;
+        case 0x80000003U: name = "STATUS_BREAKPOINT"; break;
+        case 0x40000015U: name = "STATUS_FATAL_APP_EXIT"; break;
+        case 0x40010004U: name = "DBG_TERMINATE_PROCESS"; break;
+        case 0x40010005U: name = "DBG_CONTROL_C"; break;
+        case 0x40010008U: name = "DBG_CONTROL_BREAK"; break;
+        }
+      if (name)
+        error(NILF, ignored ? _("[%s] Error %d (%s) (ignored)") :
+               _("*** [%s] Error %d (%s)"),
+               target_name, exit_code, name);
+      else
+        error(NILF, ignored ? _("[%s] Error %d (%#x) (ignored)") :
+               _("*** [%s] Error %d (%#x)"),
+               target_name, exit_code, exit_code);
+    }
 # else
     error (NILF, ignored ? _("[%s] Error %d (ignored)") :
 	   _("*** [%s] Error %d"),
@@ -840,9 +861,13 @@ reap_children (int block, int err)
 #ifdef KMK
             {
               child_error (c->file->name, exit_code, exit_sig, coredump, 0);
-              if ((  c->file->cmds->lines_flags[c->command_line - 1]
-                   & (COMMANDS_SILENT | COMMANDS_RECURSE))
-                  == COMMANDS_SILENT)
+              if (   (  c->file->cmds->lines_flags[c->command_line - 1]
+                      & (COMMANDS_SILENT | COMMANDS_RECURSE))
+                     == COMMANDS_SILENT
+# ifdef KBUILD_OS_WINDOWS /* show commands for NT statuses */
+                  || (exit_code & 0xc0000000)
+# endif
+                  || exit_sig != 0)
                 message (0, "The failing command:\n%s", c->file->cmds->command_lines[c->command_line - 1]);
             }
 #else  /* !KMK */
@@ -2680,7 +2705,9 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
   int i;
   char *p;
   char *ap;
+#ifndef NDEBUG
   char *end;
+#endif
   int instring, word_has_equals, seen_nonequals, last_argument_was_empty;
   char **new_argv = 0;
   char *argstr = 0;
@@ -2768,6 +2795,11 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
        * shell after this function returns.  */
       default_shell = xstrdup (shell);
     }
+#  ifdef KMK
+  if (is_kmk_shell)
+  { /* done above already */ }
+  else
+#   endif
   if (unixy_shell)
     {
       sh_chars = sh_chars_sh;
@@ -2809,7 +2841,9 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
 
   /* All the args can fit in a buffer as big as LINE is.   */
   ap = new_argv[0] = argstr = xmalloc (i);
+#ifndef NDEBUG
   end = ap + i;
+#endif
 
   /* I is how many complete arguments have been found.  */
   i = 0;
@@ -3119,7 +3153,9 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
     unsigned int shell_len = strlen (shell);
     unsigned int line_len = strlen (line);
     unsigned int sflags_len = strlen (shellflags);
+# ifdef WINDOWS32
     char *command_ptr = NULL; /* used for batch_mode_shell mode */
+# endif
     char *new_line;
 
 # ifdef __EMX__ /* is this necessary? */
@@ -3200,7 +3236,9 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
     memcpy (ap, shellflags, sflags_len);
     ap += sflags_len;
     *(ap++) = ' ';
+#ifdef WINDOWS32
     command_ptr = ap;
+#endif
     for (p = line; *p != '\0'; ++p)
       {
 	if (restp != NULL && *p == '\n')
diff --git a/src/kmk/kbuild-object.c b/src/kmk/kbuild-object.c
index 07c4b9f..51977f4 100644
--- a/src/kmk/kbuild-object.c
+++ b/src/kmk/kbuild-object.c
@@ -1,4 +1,4 @@
-/* $Id: kbuild-object.c 2720 2014-01-01 22:59:50Z bird $ */
+/* $Id: kbuild-object.c 3065 2017-09-30 12:52:35Z bird $ */
 /** @file
  * kBuild objects.
  */
@@ -276,6 +276,7 @@ eval_kbuild_type_from_string(const char *pchWord, size_t cchWord)
 
 
 
+#if 0 /* unused */
 /**
  * Helper function for caching variable name strings.
  *
@@ -292,6 +293,7 @@ kbuild_variable_name(const char *pszName, const char **ppszCache)
         *ppszCache = pszRet = strcache2_add(&variable_strcache, pszName, strlen(pszName));
     return pszRet;
 }
+#endif
 
 static struct kbuild_object *
 lookup_kbuild_object(enum kBuildType enmType, const char *pchName, size_t cchName)
@@ -558,7 +560,7 @@ try_define_kbuild_object_variable_via_accessor(const char *pchName, size_t cchNa
     {
         assert(pObj != NULL);
         if (!is_valid_kbuild_object_variable_name(pchVarNm, cchVarNm))
-            fatal(pFileLoc, _("Invalid kBuild object variable name: '%.*s' ('%s')"),
+            fatal(pFileLoc, _("Invalid kBuild object variable name: '%.*s' ('%.*s')"),
                   (int)cchVarNm, pchVarNm, (int)cchName, pchName);
         return define_kbuild_object_variable_cached(pObj, strcache2_add(&variable_strcache, pchVarNm, cchVarNm),
                                                     pszValue, cchValue, fDuplicateValue, enmOrigin, fRecursive,
@@ -1321,8 +1323,8 @@ parse_kbuild_object_variable_accessor(const char *pchExpr, size_t cchExpr,
 struct variable *
 lookup_kbuild_object_variable_accessor(const char *pchName, size_t cchName)
 {
-    const char * const     pchOrgName = pchName;
-    size_t       const     cchOrgName = cchName;
+    /*const char * const     pchOrgName = pchName;*/
+    /*size_t       const     cchOrgName = cchName;*/
     const char *           pchVarNm;
     size_t                 cchVarNm;
     struct kbuild_object  *pObj;
diff --git a/src/kmk/kbuild.c b/src/kmk/kbuild.c
index 1a2399f..f57e198 100644
--- a/src/kmk/kbuild.c
+++ b/src/kmk/kbuild.c
@@ -1,4 +1,4 @@
-/* $Id: kbuild.c 2861 2016-09-01 22:42:55Z bird $ */
+/* $Id: kbuild.c 3068 2017-10-01 13:10:47Z bird $ */
 /** @file
  * kBuild specific make functionality.
  */
@@ -47,6 +47,7 @@
 #endif
 
 #include "kbuild.h"
+#include "k/kDefs.h"
 
 #include <assert.h>
 
@@ -65,14 +66,14 @@
         else \
             switch (len) \
             { \
-                case 8: dst[7] = src[7]; \
-                case 7: dst[6] = src[6]; \
-                case 6: dst[5] = src[5]; \
-                case 5: dst[4] = src[4]; \
-                case 4: dst[3] = src[3]; \
-                case 3: dst[2] = src[2]; \
-                case 2: dst[1] = src[1]; \
-                case 1: dst[0] = src[0]; \
+                case 8: dst[7] = src[7]; /* fall thru */ \
+                case 7: dst[6] = src[6]; /* fall thru */ \
+                case 6: dst[5] = src[5]; /* fall thru */ \
+                case 5: dst[4] = src[4]; /* fall thru */ \
+                case 4: dst[3] = src[3]; /* fall thru */ \
+                case 3: dst[2] = src[2]; /* fall thru */ \
+                case 2: dst[1] = src[1]; /* fall thru */ \
+                case 1: dst[0] = src[0]; /* fall thru */ \
                 case 0: break; \
             } \
     } while (0)
@@ -612,8 +613,14 @@ kbuild_lookup_variable_n(const char *pszName, size_t cchName)
         MY_ASSERT_MSG(strlen(pVar->value) == pVar->value_length,
                       ("%u != %u %.*s\n", pVar->value_length, (unsigned int)strlen(pVar->value), (int)cchName, pVar->name));
 
-        /* Make sure the variable is simple, convert it if necessary. */
-        if (pVar->recursive)
+        /* Make sure the variable is simple, convert it if necessary.
+           Note! Must NOT do this for the dynamic INCS of sdks/ReorderCompilerIncs.kmk */
+        if (!pVar->recursive)
+        { /* likely */ }
+        else if (   cchName < sizeof("SDK_ReorderCompilerIncs_INCS.") - 1U
+                 || pszName[0] != 'S'
+                 || pszName[4] != 'R'
+                 || memcmp(pszName, "SDK_ReorderCompilerIncs_INCS.", sizeof("SDK_ReorderCompilerIncs_INCS.") - 1U) == 0)
             kbuild_simplify_variable(pVar);
     }
     return pVar;
@@ -1994,7 +2001,10 @@ func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
     struct variable *pTool      = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
     struct variable *pOutBase   = kbuild_get_object_base(pTarget, pSource, "outbase");
     struct variable *pObjSuff   = kbuild_get_object_suffix(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch, "objsuff");
-    struct variable *pDefs, *pIncs, *pFlags, *pDeps, *pOrderDeps, *pDirDep, *pDep, *pVar, *pOutput, *pOutputMaybe;
+    struct variable *pDeps, *pOrderDeps, *pDirDep, *pDep, *pVar, *pOutput, *pOutputMaybe;
+#if 0 /* not used */
+    struct variable *pDefs, *pIncs, *pFlags;
+#endif
     struct variable *pObj       = kbuild_set_object_name_and_dep_and_dirdep_and_PATH_target_source(pTarget, pSource, pOutBase, pObjSuff, "obj", &pDep, &pDirDep);
     int fInstallOldVars = 0;
     char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
@@ -2047,11 +2057,11 @@ func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
         pDefPath = NULL;
 
 
-    pDefs      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
+    /*pDefs  =*/ kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
                                             ST("DEFS"),  ST("defs"), 1/* left-to-right */);
-    pIncs      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
+    /*pIncs  =*/ kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
                                             ST("INCS"),  ST("incs"), -1/* right-to-left */);
-    pFlags     = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
+    /*pFlags =*/ kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
                                             ST("FLAGS"), ST("flags"), 1/* left-to-right */);
     pDeps      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
                                             ST("DEPS"),  ST("deps"), 1/* left-to-right */);
diff --git a/src/kmk/kmkbuiltin.c b/src/kmk/kmkbuiltin.c
index 3cca960..af7bdf1 100644
--- a/src/kmk/kmkbuiltin.c
+++ b/src/kmk/kmkbuiltin.c
@@ -1,4 +1,4 @@
-/* $Id: kmkbuiltin.c 2912 2016-09-14 13:36:15Z bird $ */
+/* $Id: kmkbuiltin.c 3059 2017-09-21 13:34:15Z bird $ */
 /** @file
  * kMk Builtin command execution.
  */
@@ -42,126 +42,182 @@
 extern char **environ;
 #endif
 
+
 int kmk_builtin_command(const char *pszCmd, struct child *pChild, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
 {
     int         argc;
     char      **argv;
     int         rc;
+    char       *pszzCmd;
+    char       *pszDst;
+    int         fOldStyle = 0;
 
     /*
      * Check and skip the prefix.
      */
     if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
     {
-        printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
+        fprintf(stderr, "kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
         return 1;
     }
 
     /*
      * Parse arguments.
      */
-    argc = 0;
-    argv = NULL;
-    while (*pszCmd)
+    rc      = 0;
+    argc    = 0;
+    argv    = NULL;
+    pszzCmd = pszDst = (char *)strdup(pszCmd);
+    if (!pszDst)
     {
-        const char *pszEnd;
-        const char *pszNext;
-        int         fEscaped = 0;
-        size_t      cch;
-
-        /*
-         * Find start and end of the current command.
-         */
-        if (*pszCmd == '"' || *pszCmd == '\'')
-        {
-            pszEnd = pszCmd;
-            for (;;)
-            {
-                pszEnd = strchr(pszEnd + 1, *pszCmd);
-                if (!pszEnd)
-                {
-                    printf("kmk_builtin: Unbalanced quote in argument %d: %s\n", argc + 1, pszCmd);
-                    while (argc--)
-                        free(argv[argc]);
-                    free(argv);
-                    return 1;
-                }
-                /* two quotes -> escaped quote. */
-                if (pszEnd[0] != pszEnd[1])
-                    break;
-                fEscaped = 1;
-            }
-            pszNext = pszEnd + 1;
-            pszCmd++;
-        }
-        else
-        {
-            pszEnd = pszCmd;
-            while (!isspace(*pszEnd) && *pszEnd)
-                pszEnd++;
-            pszNext = pszEnd;
-        }
+        fprintf(stderr, "kmk_builtin: out of memory. argc=%d\n", argc);
+        return 1;
+    }
+    do
+    {
+        const char * const pszSrcStart = pszCmd;
+        char ch;
+        char chQuote;
 
         /*
-         * Make argument.
+         * Start new argument.
          */
         if (!(argc % 16))
         {
             void *pv = realloc(argv, sizeof(char *) * (argc + 17));
             if (!pv)
             {
-                printf("kmk_builtin: out of memory. argc=%d\n", argc);
+                fprintf(stderr, "kmk_builtin: out of memory. argc=%d\n", argc);
+                rc = 1;
                 break;
             }
             argv = (char **)pv;
         }
-        cch = pszEnd - pszCmd;
-        argv[argc] = malloc(cch + 1);
-        if (!argv[argc])
+        argv[argc++] = pszDst;
+        argv[argc]   = NULL;
+
+        if (!fOldStyle)
         {
-            printf("kmk_builtin: out of memory. argc=%d len=%d\n", argc, (int)(pszEnd - pszCmd + 1));
-            break;
+            /*
+             * Process the next argument, bourne style.
+             */
+            chQuote = 0;
+            ch = *pszCmd++;
+            do
+            {
+                /* Unquoted mode? */
+                if (chQuote == 0)
+                {
+                    if (ch != '\'' && ch != '"')
+                    {
+                        if (!isspace(ch))
+                        {
+                            if (ch != '\\')
+                                *pszDst++ = ch;
+                            else
+                            {
+                                ch = *pszCmd++;
+                                if (ch)
+                                    *pszDst++ = ch;
+                                else
+                                {
+                                    fprintf(stderr, "kmk_builtin: Incomplete escape sequence in argument %d: %s\n",
+                                            argc, pszSrcStart);
+                                    rc = 1;
+                                    break;
+                                }
+                            }
+                        }
+                        else
+                            break;
+                    }
+                    else
+                        chQuote = ch;
+                }
+                /* Quoted mode */
+                else if (ch != chQuote)
+                {
+                    if (   ch != '\\'
+                        || chQuote == '\'')
+                        *pszDst++ = ch;
+                    else
+                    {
+                        ch = *pszCmd++;
+                        if (ch)
+                        {
+                            if (   ch != '\\'
+                                && ch != '"'
+                                && ch != '`'
+                                && ch != '$'
+                                && ch != '\n')
+                                *pszDst++ = '\\';
+                            *pszDst++ = ch;
+                        }
+                        else
+                        {
+                            fprintf(stderr, "kmk_builtin: Unbalanced quote in argument %d: %s\n", argc, pszSrcStart);
+                            rc = 1;
+                            break;
+                        }
+                    }
+                }
+                else
+                    chQuote = 0;
+            } while ((ch = *pszCmd++) != '\0');
         }
-        memcpy(argv[argc], pszCmd, cch);
-        argv[argc][cch] = '\0';
-
-        /* unescape quotes? */
-        if (fEscaped)
+        else
         {
-            char ch = pszCmd[-1];
-            char *pszW = argv[argc];
-            char *pszR = argv[argc];
-            while (*pszR)
+            /*
+             * Old style in case we ever need it.
+             */
+            ch = *pszCmd++;
+            if (ch != '"' && ch != '\'')
+            {
+                do
+                    *pszDst++ = ch;
+                while ((ch = *pszCmd++) != '\0' && !isspace(ch));
+            }
+            else
             {
-                if (*pszR == ch)
-                    pszR++;
-                *pszW++ = *pszR++;
+                chQuote = ch;
+                for (;;)
+                {
+                    char *pszEnd = strchr(pszCmd, chQuote);
+                    if (pszEnd)
+                    {
+                        fprintf(stderr, "kmk_builtin: Unbalanced quote in argument %d: %s\n", argc, pszSrcStart);
+                        rc = 1;
+                        break;
+                    }
+                    memcpy(pszDst, pszCmd, pszEnd - pszCmd);
+                    pszDst += pszEnd - pszCmd;
+                    if (pszEnd[1] != chQuote)
+                        break;
+                    *pszDst++ = chQuote;
+                }
             }
-            *pszW = '\0';
         }
-        /* commit it */
-        argv[++argc] = NULL;
+        *pszDst++ = '\0';
 
         /*
-         * Next
+         * Skip argument separators (IFS=space() for now).  Check for EOS.
          */
-        pszCmd = pszNext;
-        if (isspace(*pszCmd) && *pszCmd)
-            pszCmd++;
-    }
+        if (ch != 0)
+            while ((ch = *pszCmd) && isspace(ch))
+                pszCmd++;
+        if (ch == 0)
+            break;
+    } while (rc == 0);
 
     /*
      * Execute the command if parsing was successful.
      */
-    if (!*pszCmd)
+    if (rc == 0)
         rc = kmk_builtin_command_parsed(argc, argv, pChild, ppapszArgvToSpawn, pPidSpawned);
-    else
-        rc = 1;
 
     /* clean up and return. */
-    while (argc--)
-        free(argv[argc]);
     free(argv);
+    free(pszzCmd);
     return rc;
 }
 
@@ -177,7 +233,7 @@ int kmk_builtin_command_parsed(int argc, char **argv, struct child *pChild, char
      */
     if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
     {
-        printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
+        fprintf(stderr, "kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
         return 1;
     }
     pszCmd += sizeof("kmk_builtin_") - 1;
@@ -230,6 +286,8 @@ int kmk_builtin_command_parsed(int argc, char **argv, struct child *pChild, char
         rc = kmk_builtin_cmp(argc, argv, environ);
     else if (!strcmp(pszCmd, "cat"))
         rc = kmk_builtin_cat(argc, argv, environ);
+    else if (!strcmp(pszCmd, "touch"))
+        rc = kmk_builtin_touch(argc, argv, environ);
     else if (!strcmp(pszCmd, "sleep"))
         rc = kmk_builtin_sleep(argc, argv, environ);
     else if (!strcmp(pszCmd, "dircache"))
@@ -240,7 +298,7 @@ int kmk_builtin_command_parsed(int argc, char **argv, struct child *pChild, char
 #endif
     else
     {
-        printf("kmk_builtin: Unknown command '%s'!\n", pszCmd);
+        fprintf(stderr, "kmk_builtin: Unknown command '%s'!\n", pszCmd);
         return 1;
     }
 
diff --git a/src/kmk/kmkbuiltin.h b/src/kmk/kmkbuiltin.h
index 03d0a98..077b51a 100644
--- a/src/kmk/kmkbuiltin.h
+++ b/src/kmk/kmkbuiltin.h
@@ -1,4 +1,4 @@
-/* $Id: kmkbuiltin.h 2912 2016-09-14 13:36:15Z bird $ */
+/* $Id: kmkbuiltin.h 3059 2017-09-21 13:34:15Z bird $ */
 /** @file
  * kMk Builtin command handling.
  */
@@ -63,6 +63,7 @@ extern int kmk_builtin_test(int argc, char **argv, char **envp
                             , char ***ppapszArgvSpawn
 #endif
                             );
+extern int kmk_builtin_touch(int argc, char **argv, char **envp);
 #ifdef KBUILD_OS_WINDOWS
 extern int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild, pid_t *pPidSpawned);
 extern int kSubmitSubProcGetResult(intptr_t pvUser, int *prcExit, int *piSigNo);
@@ -77,6 +78,10 @@ extern char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname)
 /* common-env-and-cwd-opt.c: */
 extern int kBuiltinOptEnvSet(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
                              int cVerbosity, const char *pszValue);
+extern int kBuiltinOptEnvAppend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
+                                int cVerbosity, const char *pszValue);
+extern int kBuiltinOptEnvPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
+                                 int cVerbosity, const char *pszValue);
 extern int kBuiltinOptEnvUnset(char **papszEnv, unsigned *pcEnvVars, int cVerbosity, const char *pszVarToRemove);
 extern int kBuiltinOptChDir(char *pszCwd, size_t cbCwdBuf, const char *pszValue);
 
diff --git a/src/kmk/kmkbuiltin/cmp.c b/src/kmk/kmkbuiltin/cmp.c
index e24ca17..2c098bb 100644
--- a/src/kmk/kmkbuiltin/cmp.c
+++ b/src/kmk/kmkbuiltin/cmp.c
@@ -34,6 +34,9 @@
 static char sccsid[] = "@(#)cmp.c	8.3 (Berkeley) 4/2/94";
 __RCSID("$NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $"); */
 
+#ifdef _MSC_VER
+# define MSC_DO_64_BIT_IO /* for correct off_t */
+#endif
 #include "config.h"
 #include <sys/types.h>
 #include "err.h"
@@ -45,7 +48,6 @@ __RCSID("$NetBSD: cmp.c,v 1.15 2006/01/19 20:44:57 garbled Exp $"); */
 #ifndef _MSC_VER
 # include <unistd.h>
 #else
-# define MSC_DO_64_BIT_IO /* for correct off_t */
 # include "mscfakes.h"
 #endif
 #include "getopt.h"
diff --git a/src/kmk/kmkbuiltin/cmp_util.c b/src/kmk/kmkbuiltin/cmp_util.c
index 905ac13..c79c001 100644
--- a/src/kmk/kmkbuiltin/cmp_util.c
+++ b/src/kmk/kmkbuiltin/cmp_util.c
@@ -35,6 +35,9 @@
 /*__COPYRIGHT("@(#) Copyright (c) 1987, 1990, 1993, 1994\n\
 	The Regents of the University of California.  All rights reserved.\n");*/
 
+#ifdef _MSC_VER
+# define MSC_DO_64_BIT_IO
+#endif
 #include "config.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -54,7 +57,6 @@
 #  define O_BINARY 0
 # endif
 #else
-# define MSC_DO_64_BIT_IO
 # include "mscfakes.h"
 #endif
 #include "err.h"
@@ -359,7 +361,7 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
     for (blk_sz = CMP_BUF_SIZE; length != 0; length -= blk_sz)
     {
         if ((off_t)blk_sz > length)
-            blk_sz = length;
+            blk_sz = (size_t)length;
 
         bytes_read = read(fd1, b1, blk_sz);
         if (bytes_read != (off_t)blk_sz)
diff --git a/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c b/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c
index 21b76d5..88c649a 100644
--- a/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c
+++ b/src/kmk/kmkbuiltin/common-env-and-cwd-opt.c
@@ -1,4 +1,4 @@
-/* $Id: common-env-and-cwd-opt.c 2912 2016-09-14 13:36:15Z bird $ */
+/* $Id: common-env-and-cwd-opt.c 3039 2017-05-10 10:55:51Z bird $ */
 /** @file
  * kMk Builtin command - Commmon environment and CWD option handling code.
  */
@@ -45,10 +45,80 @@
 
 
 /**
- * Handles the --set var=value option.
+ * Common worker for kBuiltinOptEnvSet and kBuiltinOptEnvAppendPrepend that adds
+ * a new variable to the environment.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   papszEnv            The environment vector.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
+ *                              environment vector.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ */
+static int kBuiltinOptEnvAddVar(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
+                                int cVerbosity, const char *pszValue)
+{
+    /* Append new variable. We probably need to resize the vector. */
+    char   **papszEnv = *ppapszEnv;
+    unsigned cEnvVars = *pcEnvVars;
+    if ((cEnvVars + 2) > *pcAllocatedEnvVars)
+    {
+        *pcAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf;
+        papszEnv = (char **)realloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0]));
+        if (!papszEnv)
+            return errx(1, "out of memory!");
+        *ppapszEnv = papszEnv;
+    }
+    papszEnv[cEnvVars] = strdup(pszValue);
+    if (!papszEnv[cEnvVars])
+        return errx(1, "out of memory!");
+    papszEnv[++cEnvVars]   = NULL;
+    *pcEnvVars = cEnvVars;
+    if (cVerbosity > 0)
+        warnx("added '%s'", papszEnv[cEnvVars - 1]);
+    return 0;
+}
+
+
+/**
+ * Common worker for kBuiltinOptEnvSet and kBuiltinOptEnvAppendPrepend that
+ * remove duplicates.
  *
  * @returns 0 on success, non-zero exit code on error.
  * @param   papszEnv            The environment vector.
+ * @param   cEnvVars            Number of environment variables.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ * @param   cchVar              The length of the variable part of @a pszValue.
+ * @param   iEnvVar             Where to start searching after.
+ */
+static int kBuiltinOptEnvRemoveDuplicates(char **papszEnv, unsigned cEnvVars, int cVerbosity,
+                                          const char *pszValue, size_t cchVar, unsigned iEnvVar)
+{
+    for (iEnvVar++; iEnvVar < cEnvVars; iEnvVar++)
+        if (   KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszValue, cchVar) == 0
+            && papszEnv[iEnvVar][cchVar] == '=')
+        {
+            if (cVerbosity > 0)
+                warnx("removing duplicate '%s'", papszEnv[iEnvVar]);
+            free(papszEnv[iEnvVar]);
+            cEnvVars--;
+            if (iEnvVar != cEnvVars)
+                papszEnv[iEnvVar] = papszEnv[cEnvVars];
+            papszEnv[cEnvVars] = NULL;
+            iEnvVar--;
+        }
+    return 0;
+}
+
+
+/**
+ * Handles the --set var=value option.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   ppapszEnv           The environment vector pointer.
  * @param   pcEnvVars           Pointer to the variable holding the number of
  *                              environment variables held by @a papszEnv.
  * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
@@ -77,50 +147,108 @@ int kBuiltinOptEnvSet(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAlloca
                 papszEnv[iEnvVar] = strdup(pszValue);
                 if (!papszEnv[iEnvVar])
                     return errx(1, "out of memory!");
-                break;
+
+                return kBuiltinOptEnvRemoveDuplicates(papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);
             }
         }
-        if (iEnvVar == cEnvVars)
+        return kBuiltinOptEnvAddVar(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue);
+    }
+    return errx(1, "Missing '=': -E %s", pszValue);
+}
+
+
+/**
+ * Common worker for kBuiltinOptEnvAppend and kBuiltinOptEnvPrepend.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   ppapszEnv           The environment vector pointer.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
+ *                              environment vector.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ */
+static int kBuiltinOptEnvAppendPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars,
+                                       int cVerbosity, const char *pszValue, int fAppend)
+{
+    const char *pszEqual = strchr(pszValue, '=');
+    if (pszEqual)
+    {
+        char   **papszEnv = *ppapszEnv;
+        unsigned iEnvVar;
+        unsigned cEnvVars = *pcEnvVars;
+        size_t const cchVar = pszEqual - pszValue;
+        for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++)
         {
-            /* Append new variable. We probably need to resize the vector. */
-            if ((cEnvVars + 2) > *pcAllocatedEnvVars)
+            char *pszCur = papszEnv[iEnvVar];
+            if (   KSUBMIT_ENV_NCMP(pszCur, pszValue, cchVar) == 0
+                && pszCur[cchVar] == '=')
             {
-                *pcAllocatedEnvVars = (cEnvVars + 2 + 0xf) & ~(unsigned)0xf;
-                papszEnv = (char **)realloc(papszEnv, *pcAllocatedEnvVars * sizeof(papszEnv[0]));
-                if (!papszEnv)
+                size_t cchOldValue = strlen(papszEnv[iEnvVar]) - cchVar - 1;
+                size_t cchNewValue = strlen(pszValue)          - cchVar - 1;
+                char *pszNew = malloc(cchVar + 1 + cchOldValue + cchNewValue);
+                if (!papszEnv[iEnvVar])
                     return errx(1, "out of memory!");
-                *ppapszEnv = papszEnv;
-            }
-            papszEnv[cEnvVars] = strdup(pszValue);
-            if (!papszEnv[cEnvVars])
-                return errx(1, "out of memory!");
-            papszEnv[++cEnvVars]   = NULL;
-            *pcEnvVars = cEnvVars;
-            if (cVerbosity > 0)
-                warnx("added '%s'", papszEnv[iEnvVar]);
-        }
-        else
-        {
-            /* Check for duplicates. */
-            for (iEnvVar++; iEnvVar < cEnvVars; iEnvVar++)
-                if (   KSUBMIT_ENV_NCMP(papszEnv[iEnvVar], pszValue, cchVar) == 0
-                    && papszEnv[iEnvVar][cchVar] == '=')
+                if (fAppend)
+                {
+                    memcpy(pszNew, papszEnv[iEnvVar], cchVar + 1 + cchOldValue);
+                    memcpy(&pszNew[cchVar + 1 + cchOldValue], &pszValue[cchVar + 1], cchNewValue + 1);
+                }
+                else
                 {
-                    if (cVerbosity > 0)
-                        warnx("removing duplicate '%s'", papszEnv[iEnvVar]);
-                    free(papszEnv[iEnvVar]);
-                    cEnvVars--;
-                    if (iEnvVar != cEnvVars)
-                        papszEnv[iEnvVar] = papszEnv[cEnvVars];
-                    papszEnv[cEnvVars] = NULL;
-                    iEnvVar--;
+                    memcpy(pszNew, papszEnv[iEnvVar], cchVar + 1); /* preserve variable name case  */
+                    memcpy(&pszNew[cchVar + 1], &pszValue[cchVar + 1], cchNewValue);
+                    memcpy(&pszNew[cchVar + 1 + cchNewValue], &papszEnv[iEnvVar][cchVar + 1], cchOldValue + 1);
                 }
+
+                if (cVerbosity > 0)
+                    warnx("replacing '%s' with '%s'", papszEnv[iEnvVar], pszNew);
+                free(papszEnv[iEnvVar]);
+                papszEnv[iEnvVar] = pszNew;
+
+                return kBuiltinOptEnvRemoveDuplicates(papszEnv, cEnvVars, cVerbosity, pszValue, cchVar, iEnvVar);
+            }
         }
+        return kBuiltinOptEnvAddVar(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue);
     }
-    else
-        return errx(1, "Missing '=': -E %s", pszValue);
+    return errx(1, "Missing '=': -E %s", pszValue);
+}
 
-    return 0;
+
+/**
+ * Handles the --append var=value option.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   ppapszEnv           The environment vector pointer.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
+ *                              environment vector.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ */
+int kBuiltinOptEnvAppend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue)
+{
+    return kBuiltinOptEnvAppendPrepend(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 1 /*fAppend*/);
+}
+
+
+/**
+ * Handles the --prepend var=value option.
+ *
+ * @returns 0 on success, non-zero exit code on error.
+ * @param   ppapszEnv           The environment vector pointer.
+ * @param   pcEnvVars           Pointer to the variable holding the number of
+ *                              environment variables held by @a papszEnv.
+ * @param   pcAllocatedEnvVars  Pointer to the variable holding max size of the
+ *                              environment vector.
+ * @param   cVerbosity          The verbosity level.
+ * @param   pszValue            The var=value string to apply.
+ */
+int kBuiltinOptEnvPrepend(char ***ppapszEnv, unsigned *pcEnvVars, unsigned *pcAllocatedEnvVars, int cVerbosity, const char *pszValue)
+{
+    return kBuiltinOptEnvAppendPrepend(ppapszEnv, pcEnvVars, pcAllocatedEnvVars, cVerbosity, pszValue, 0 /*fAppend*/);
 }
 
 
diff --git a/src/kmk/kmkbuiltin/echo.c b/src/kmk/kmkbuiltin/echo.c
index dff8cb2..a0153ef 100644
--- a/src/kmk/kmkbuiltin/echo.c
+++ b/src/kmk/kmkbuiltin/echo.c
@@ -72,20 +72,22 @@ static void
 errexit(const char *prog, const char *reason)
 {
 	char *errstr = strerror(errno);
+	ssize_t cchIgn = 0; /* this is to shut up irrelevant warnings on linux. */
 #ifdef _MSC_VER
 	int doserrno = _doserrno;
-       char szDosErr[48];
-       sprintf(szDosErr, " (doserrno=%d)", doserrno);
+	char szDosErr[48];
+	sprintf(szDosErr, " (doserrno=%d)", doserrno);
 #endif
-	write(STDERR_FILENO, prog, strlen(prog));
-	write(STDERR_FILENO, ": ", 2);
-	write(STDERR_FILENO, reason, strlen(reason));
-	write(STDERR_FILENO, ": ", 2);
-	write(STDERR_FILENO, errstr, strlen(errstr));
+	cchIgn += write(STDERR_FILENO, prog, strlen(prog));
+	cchIgn += write(STDERR_FILENO, ": ", 2);
+	cchIgn += write(STDERR_FILENO, reason, strlen(reason));
+	cchIgn += write(STDERR_FILENO, ": ", 2);
+	cchIgn += write(STDERR_FILENO, errstr, strlen(errstr));
 #ifdef _MSC_VER
-	write(STDERR_FILENO, szDosErr, strlen(szDosErr));
+	cchIgn += write(STDERR_FILENO, szDosErr, strlen(szDosErr));
 #endif
-	write(STDERR_FILENO, "\n", 1);
+	cchIgn += write(STDERR_FILENO, "\n", 1);
+	(void)cchIgn;
 }
 
 int
diff --git a/src/kmk/kmkbuiltin/err.c b/src/kmk/kmkbuiltin/err.c
index 90d99e4..da0a27f 100644
--- a/src/kmk/kmkbuiltin/err.c
+++ b/src/kmk/kmkbuiltin/err.c
@@ -1,4 +1,4 @@
-/* $Id: err.c 2911 2016-09-10 11:16:59Z bird $ */
+/* $Id: err.c 3065 2017-09-30 12:52:35Z bird $ */
 /** @file
  * Override err.h so we get the program name right.
  */
@@ -54,18 +54,18 @@ int err(int eval, const char *fmt, ...)
        one go so it won't be split by other output. */
     char szMsg[4096];
     int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname);
-    if (cchMsg < sizeof(szMsg) - 1 && cchMsg > 0)
+    if (cchMsg < (int)sizeof(szMsg) - 1 && cchMsg > 0)
     {
         int cchMsg2;
         va_start(args, fmt);
         cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
         va_end(args);
 
-        if (   cchMsg < sizeof(szMsg) - 1
+        if (   cchMsg < (int)sizeof(szMsg) - 1
             && cchMsg2 >= 0)
         {
             cchMsg += cchMsg2 = snprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, ": %s\n", strerror(error));
-            if (   cchMsg < sizeof(szMsg) - 1
+            if (   cchMsg < (int)sizeof(szMsg) - 1
                 && cchMsg2 >= 0)
             {
                 fwrite(szMsg, cchMsg, 1, stderr);
@@ -95,14 +95,14 @@ int errx(int eval, const char *fmt, ...)
        one go so it won't be split by other output. */
     char szMsg[4096];
     int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname);
-    if (cchMsg < sizeof(szMsg) - 1 && cchMsg > 0)
+    if (cchMsg < (int)sizeof(szMsg) - 1 && cchMsg > 0)
     {
         int cchMsg2;
         va_start(args, fmt);
         cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
         va_end(args);
 
-        if (   cchMsg < sizeof(szMsg) - 1
+        if (   cchMsg < (int)sizeof(szMsg) - 1
             && cchMsg2 >= 0)
         {
             szMsg[cchMsg++] = '\n';
@@ -131,18 +131,18 @@ void warn(const char *fmt, ...)
        one go so it won't be split by other output. */
     char szMsg[4096];
     int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname);
-    if (cchMsg < sizeof(szMsg) - 1 && cchMsg > 0)
+    if (cchMsg < (int)sizeof(szMsg) - 1 && cchMsg > 0)
     {
         int cchMsg2;
         va_start(args, fmt);
         cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
         va_end(args);
 
-        if (   cchMsg < sizeof(szMsg) - 1
+        if (   cchMsg < (int)sizeof(szMsg) - 1
             && cchMsg2 >= 0)
         {
             cchMsg += cchMsg2 = snprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, ": %s\n", strerror(error));
-            if (   cchMsg < sizeof(szMsg) - 1
+            if (   cchMsg < (int)sizeof(szMsg) - 1
                 && cchMsg2 >= 0)
             {
                 fwrite(szMsg, cchMsg, 1, stderr);
@@ -168,14 +168,14 @@ void warnx(const char *fmt, ...)
        one go so it won't be split by other output. */
     char szMsg[4096];
     int cchMsg = snprintf(szMsg, sizeof(szMsg), "%s: ", g_progname);
-    if (cchMsg < sizeof(szMsg) - 1 && cchMsg > 0)
+    if (cchMsg < (int)sizeof(szMsg) - 1 && cchMsg > 0)
     {
         int cchMsg2;
         va_start(args, fmt);
         cchMsg += cchMsg2 = vsnprintf(&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
         va_end(args);
 
-        if (   cchMsg < sizeof(szMsg) - 1
+        if (   cchMsg < (int)sizeof(szMsg) - 1
             && cchMsg2 >= 0)
         {
             szMsg[cchMsg++] = '\n';
diff --git a/src/kmk/kmkbuiltin/install.c b/src/kmk/kmkbuiltin/install.c
index 13bec72..afccab1 100644
--- a/src/kmk/kmkbuiltin/install.c
+++ b/src/kmk/kmkbuiltin/install.c
@@ -73,6 +73,10 @@ __FBSDID("$FreeBSD: src/usr.bin/xinstall/xinstall.c,v 1.66 2005/01/25 14:34:57 s
 #ifndef __HAIKU__
 # include <sysexits.h>
 #endif
+#ifdef __NetBSD__
+# include <util.h>
+# define strtofflags(a, b, c)	string_to_flags(a, b, c)
+#endif
 #include <unistd.h>
 #if defined(__EMX__) || defined(_MSC_VER)
 # include <process.h>
diff --git a/src/kmk/kmkbuiltin/kDepObj.c b/src/kmk/kmkbuiltin/kDepObj.c
index 5cb090a..3445798 100644
--- a/src/kmk/kmkbuiltin/kDepObj.c
+++ b/src/kmk/kmkbuiltin/kDepObj.c
@@ -1,4 +1,4 @@
-/* $Id: kDepObj.c 2955 2016-09-21 19:05:53Z bird $ */
+/* $Id: kDepObj.c 3064 2017-09-30 11:38:48Z bird $ */
 /** @file
  * kDepObj - Extract dependency information from an object file.
  */
@@ -52,9 +52,11 @@
 #if 0
 # define dprintf(a)             printf a
 # define dump(pb, cb, offBase)  depHexDump(pb,cb,offBase)
+# define WITH_DPRINTF
 #else
 # define dprintf(a)             do {} while (0)
 # define dump(pb, cb, offBase)  do {} while (0)
+# undef  WITH_DPRINTF
 #endif
 
 /** @name OMF defines
@@ -386,13 +388,16 @@ int kDepObjOMFParse(const KU8 *pbFile, KSIZE cbFile)
                     KU16 uSeg = kDepObjOMFGetIndex(&uData, &cbRecLeft);
                     if (uSeg == KU16_MAX)
                         return kDepErr(1, "%#07lx - Bad LINNUM32 record\n", (long)((const KU8 *)pHdr - pbFile));
+                    K_NOREF(uGrp);
 
                     if (uLinNumType == KU8_MAX)
                     {
+#ifdef WITH_DPRINTF
                         static const char * const s_apsz[5] =
                         {
                             "source file", "listing file", "source & listing file", "file names table", "path table"
                         };
+#endif
                         KU16 uLine;
                         KU8  uReserved;
                         KU16 uSeg2;
@@ -403,16 +408,17 @@ int kDepObjOMFParse(const KU8 *pbFile, KSIZE cbFile)
                         cbRecLeft  -= 2+1+1+2+2+4;
                         uLine       = *uData.pu16++;
                         uLinNumType = *uData.pu8++;
-                        uReserved   = *uData.pu8++;
-                        cLinNums    = *uData.pu16++;
-                        uSeg2       = *uData.pu16++;
-                        cbLinNames  = *uData.pu32++;
+                        uReserved   = *uData.pu8++;  K_NOREF(uReserved);
+                        cLinNums    = *uData.pu16++; K_NOREF(cLinNums);
+                        uSeg2       = *uData.pu16++; K_NOREF(uSeg2);
+                        cbLinNames  = *uData.pu32++; K_NOREF(cbLinNames);
 
                         dprintf(("LINNUM32: uGrp=%#x uSeg=%#x uSeg2=%#x uLine=%#x (MBZ) uReserved=%#x\n",
                                  uGrp, uSeg, uSeg2, uLine, uReserved));
                         dprintf(("LINNUM32: cLinNums=%#x (%u) cbLinNames=%#x (%u) uLinNumType=%#x (%s)\n",
                                  cLinNums, cLinNums, cbLinNames, cbLinNames, uLinNumType,
                                  uLinNumType < K_ELEMENTS(s_apsz) ? s_apsz[uLinNumType] : "??"));
+
                         if (uLine != 0)
                             return kDepErr(1, "%#07lx - Bad LINNUM32 record, line %#x (MBZ)\n", (long)((const KU8 *)pHdr - pbFile), uLine);
                         cLinFiles = iLinFile = KU32_MAX;
@@ -478,8 +484,8 @@ int kDepObjOMFParse(const KU8 *pbFile, KSIZE cbFile)
                                 return kDepErr(1, "%#07lx - Bad LINNUM32 record, incomplete file/path table header\n", (long)((const KU8 *)pHdr - pbFile));
                             cbRecLeft -= 4+4+4;
 
-                            iFirstCol = *uData.pu32++;
-                            cCols     = *uData.pu32++;
+                            iFirstCol = *uData.pu32++;  K_NOREF(iFirstCol);
+                            cCols     = *uData.pu32++;  K_NOREF(cCols);
                             cLinFiles = *uData.pu32++;
                             dprintf(("%s table header: cLinFiles=%#" KX32_PRI " (%" KU32_PRI ") iFirstCol=%" KU32_PRI " cCols=%" KU32_PRI"\n",
                                      uLinNumType == 3 ? "file names" : "path", cLinFiles, cLinFiles, iFirstCol, cCols));
@@ -1046,7 +1052,7 @@ int kmk_builtin_kDepObj(int argc, char *argv[], char **envp)
                         pszValue = argv[i];
                     else
                     {
-                        fprintf(stderr, "%s: syntax error: The '-%c' option takes a value.\n", chOpt);
+                        fprintf(stderr, "%s: syntax error: The '-%c' option takes a value.\n", argv[0], chOpt);
                         return 2;
                     }
                     break;
@@ -1130,7 +1136,7 @@ int kmk_builtin_kDepObj(int argc, char *argv[], char **envp)
                 {
                     if (pszIgnoreExt)
                     {
-                        fprintf(stderr, "%s: syntax error: The '-e' option can only be used once!\n");
+                        fprintf(stderr, "%s: syntax error: The '-e' option can only be used once!\n", argv[0]);
                         return 2;
                     }
                     pszIgnoreExt = pszValue;
diff --git a/src/kmk/kmkbuiltin/kSubmit.c b/src/kmk/kmkbuiltin/kSubmit.c
index b3132a4..50d8ca5 100644
--- a/src/kmk/kmkbuiltin/kSubmit.c
+++ b/src/kmk/kmkbuiltin/kSubmit.c
@@ -1,4 +1,4 @@
-/* $Id: kSubmit.c 2959 2016-09-21 20:53:32Z bird $ */
+/* $Id: kSubmit.c 3051 2017-07-24 10:59:59Z bird $ */
 /** @file
  * kMk Builtin command - submit job to a kWorker.
  */
@@ -382,13 +382,26 @@ static int kSubmitSpawnWorker(PWORKERINSTANCE pWorker, int cVerbosity)
                 if (pWorker->OverlappedRead.hEvent != NULL)
                 {
                     char        szHandleArg[32];
-                    const char *apszArgs[6] =
-                    {
-                        szExecutable, "--pipe", szHandleArg,
-                        pVarVolatile ? "--volatile" : NULL, pVarVolatile ? pVarVolatile->value : NULL,
-                        NULL
-                    };
+                    extern int process_priority; /* main.c */
+                    char        szPriorityArg[32];
+                    const char *apszArgs[10];
+                    int         cArgs = 0;
+                    apszArgs[cArgs++] = szExecutable;
+                    apszArgs[cArgs++] = "--pipe";
                     _snprintf(szHandleArg, sizeof(szHandleArg), "%p", hWorkerPipe);
+                    apszArgs[cArgs++] = szHandleArg;
+                    if (pVarVolatile)
+                    {
+                        apszArgs[cArgs++] = "--volatile";
+                        apszArgs[cArgs++] = pVarVolatile->value;
+                    }
+                    if (process_priority != 0)
+                    {
+                        apszArgs[cArgs++] = "--priority";
+                        _snprintf(szPriorityArg, sizeof(szPriorityArg), "%u", process_priority);
+                        apszArgs[cArgs++] = szPriorityArg;
+                    }
+                    apszArgs[cArgs] = NULL;
 
                     /*
                      * Create the worker process.
@@ -1168,6 +1181,7 @@ static int usage(FILE *pOut,  const char *argv0)
 {
     fprintf(pOut,
             "usage: %s [-Z|--zap-env] [-E|--set <var=val>] [-U|--unset <var=val>]\n"
+            "           [-A|--append <var=val>] [-D|--prepend <var=val>]\n"
             "           [-C|--chdir <dir>] [--wcc-brain-damage] [--no-pch-caching]\n"
             "           [-3|--32-bit] [-6|--64-bit] [-v]\n"
             "           [-P|--post-cmd <cmd> [args]] -- <program> [args]\n"
@@ -1181,6 +1195,10 @@ static int usage(FILE *pOut,  const char *argv0)
             "    Sets an enviornment variable putenv fashion. Position dependent.\n"
             "  -U, --unset <var>\n"
             "    Removes an environment variable. Position dependent.\n"
+            "  -A, --append <var>=<value>\n"
+            "    Appends the given value to the environment variable.\n"
+            "  -D,--prepend <var>=<value>\n"
+            "    Prepends the given value to the environment variable.\n"
             "  -C, --chdir <dir>\n"
             "    Specifies the current directory for the program.  Relative paths\n"
             "    are relative to the previous -C option.  Default is getcwd value.\n"
@@ -1295,6 +1313,10 @@ int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild
                     chOpt = 'V';
                 else if (strcmp(pszArg, "set") == 0)
                     chOpt = 'E';
+                else if (strcmp(pszArg, "append") == 0)
+                    chOpt = 'A';
+                else if (strcmp(pszArg, "prepend") == 0)
+                    chOpt = 'D';
                 else if (strcmp(pszArg, "unset") == 0)
                     chOpt = 'U';
                 else if (   strcmp(pszArg, "zap-env") == 0
@@ -1326,9 +1348,11 @@ int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild
                 const char *pszValue = NULL;
                 switch (chOpt)
                 {
+                    case 'A':
+                    case 'C':
                     case 'E':
                     case 'U':
-                    case 'C':
+                    case 'D':
                     case 'e':
                         if (*pszArg != '\0')
                             pszValue = pszArg + (*pszArg == ':' || *pszArg == '=');
@@ -1359,6 +1383,20 @@ int kmk_builtin_kSubmit(int argc, char **argv, char **envp, struct child *pChild
                             break;
                         return rcExit;
 
+                    case 'A':
+                        rcExit = kBuiltinOptEnvAppend(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                        pChild->environment = papszEnv;
+                        if (rcExit == 0)
+                            break;
+                        return rcExit;
+
+                    case 'D':
+                        rcExit = kBuiltinOptEnvPrepend(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                        pChild->environment = papszEnv;
+                        if (rcExit == 0)
+                            break;
+                        return rcExit;
+
                     case 'U':
                         rcExit = kBuiltinOptEnvUnset(papszEnv, &cEnvVars, cVerbosity, pszValue);
                         if (rcExit == 0)
diff --git a/src/kmk/kmkbuiltin/mscfakes.c b/src/kmk/kmkbuiltin/mscfakes.c
index b820dd8..26d475c 100644
--- a/src/kmk/kmkbuiltin/mscfakes.c
+++ b/src/kmk/kmkbuiltin/mscfakes.c
@@ -1,4 +1,4 @@
-/* $Id: mscfakes.c 2901 2016-09-09 15:10:24Z bird $ */
+/* $Id: mscfakes.c 3094 2017-10-14 03:32:50Z bird $ */
 /** @file
  * Fake Unix stuff for MSC.
  */
@@ -36,13 +36,19 @@
 #include <io.h>
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <sys/timeb.h>
 #include "err.h"
 #include "mscfakes.h"
 
+#include "nt/ntutimes.h"
+#undef utimes
+#undef lutimes
+
 #define timeval windows_timeval
 #include <Windows.h>
 #undef timeval
 
+
 /*******************************************************************************
 *   Internal Functions                                                         *
 *******************************************************************************/
@@ -459,13 +465,6 @@ int snprintf(char *buf, size_t size, const char *fmt, ...)
 #endif
 
 
-int utimes(const char *pszPath, const struct timeval *paTimes)
-{
-    /** @todo implement me! */
-    return 0;
-}
-
-
 /* We override the libc write function (in our modules only, unfortunately) so
    we can kludge our way around a ENOSPC problem observed on build servers
    capturing STDOUT and STDERR via pipes.  Apparently this may happen when the
@@ -650,6 +649,67 @@ int vasprintf(char **strp, const char *fmt, va_list va)
 }
 
 
+int utimes(const char *pszPath, const struct timeval *paTimes)
+{
+    if (paTimes)
+    {
+        BirdTimeVal_T aTimes[2];
+        aTimes[0].tv_sec  = paTimes[0].tv_sec;
+        aTimes[0].tv_usec = paTimes[0].tv_usec;
+        aTimes[1].tv_sec  = paTimes[1].tv_sec;
+        aTimes[1].tv_usec = paTimes[1].tv_usec;
+        return birdUtimes(pszPath, aTimes);
+    }
+    return birdUtimes(pszPath, NULL);
+}
+
+
+int lutimes(const char *pszPath, const struct timeval *paTimes)
+{
+    if (paTimes)
+    {
+        BirdTimeVal_T aTimes[2];
+        aTimes[0].tv_sec  = paTimes[0].tv_sec;
+        aTimes[0].tv_usec = paTimes[0].tv_usec;
+        aTimes[1].tv_sec  = paTimes[1].tv_sec;
+        aTimes[1].tv_usec = paTimes[1].tv_usec;
+        return birdUtimes(pszPath, aTimes);
+    }
+    return birdUtimes(pszPath, NULL);
+}
+
+
+int gettimeofday(struct timeval *pNow, void *pvIgnored)
+{
+    struct __timeb64 Now;
+    int rc = _ftime64_s(&Now);
+    if (rc == 0)
+    {
+        pNow->tv_sec  = Now.time;
+        pNow->tv_usec = Now.millitm * 1000;
+        return 0;
+    }
+    errno = rc;
+    return -1;
+}
+
+
+struct tm *localtime_r(const __time64_t *pNow, struct tm *pResult)
+{
+    int rc = _localtime64_s(pResult, pNow);
+    if (rc == 0)
+        return pResult;
+    errno = rc;
+    return NULL;
+}
+
+
+__time64_t timegm(struct tm *pNow)
+{
+    return _mkgmtime64(pNow);
+}
+
+
 /**
  * Checks if the given file descriptor is a pipe or not.
  *
diff --git a/src/kmk/kmkbuiltin/mscfakes.h b/src/kmk/kmkbuiltin/mscfakes.h
index 379875a..904f098 100644
--- a/src/kmk/kmkbuiltin/mscfakes.h
+++ b/src/kmk/kmkbuiltin/mscfakes.h
@@ -1,4 +1,4 @@
-/* $Id: mscfakes.h 2766 2015-01-30 03:32:38Z bird $ */
+/* $Id: mscfakes.h 3092 2017-10-11 17:55:09Z bird $ */
 /** @file
  * Unix fakes for MSC.
  */
@@ -27,6 +27,8 @@
 #define ___mscfakes_h
 #ifdef _MSC_VER
 
+#define timeval windows_timeval
+
 /* Include the config file (kmk's) so we don't need to duplicate stuff from it here. */
 #include "config.h"
 
@@ -45,11 +47,15 @@
 #include <direct.h>
 #include "nt/ntstat.h"
 #include "nt/ntunlink.h"
-#if defined(MSC_DO_64_BIT_IO) && _MSC_VER >= 1400 /* We want 64-bit file lengths here when possible. */
-# define off_t __int64
-# define lseek _lseeki64
+#ifdef MSC_DO_64_BIT_IO
+# if _MSC_VER >= 1400 /* We want 64-bit file lengths here when possible. */
+#  define off_t __int64
+#  define lseek _lseeki64
+# endif
 #endif
 
+#undef timeval
+
 #undef  PATH_MAX
 #define PATH_MAX   _MAX_PATH
 #undef  MAXPATHLEN
@@ -103,13 +109,11 @@ typedef signed short   int16_t;
 typedef signed int     int32_t;
 #endif
 
-#if !defined(timerisset) && defined(MSCFAKES_NO_WINDOWS_H)
 struct timeval
 {
-    long tv_sec;
+    __time64_t tv_sec;
     long tv_usec;
 };
-#endif
 
 struct iovec
 {
@@ -133,7 +137,6 @@ int lchmod(const char *path, mode_t mode);
 int msc_chmod(const char *path, mode_t mode);
 #define chmod msc_chmod
 #define lchown(path, uid, gid) chown(path, uid, gid)
-#define lutimes(path, tvs) utimes(path, tvs)
 int link(const char *pszDst, const char *pszLink);
 int mkdir_msc(const char *path, mode_t mode);
 #define mkdir(path, mode) mkdir_msc(path, mode)
@@ -157,8 +160,15 @@ int snprintf(char *buf, size_t size, const char *fmt, ...);
 #endif
 int symlink(const char *pszDst, const char *pszLink);
 int utimes(const char *pszPath, const struct timeval *paTimes);
+int lutimes(const char *pszPath, const struct timeval *paTimes);
 ssize_t writev(int fd, const struct iovec *vector, int count);
 
+int gettimeofday(struct timeval *pNow, void *pvIgnored);
+struct tm *localtime_r(const __time64_t *pNow, struct tm *pResult);
+__time64_t timegm(struct tm *pNow);
+#undef mktime
+#define mktime _mktime64
+
 /* bird write ENOSPC hacks. */
 #undef write
 #define write msc_write
diff --git a/src/kmk/kmkbuiltin/redirect.c b/src/kmk/kmkbuiltin/redirect.c
index 5f5a558..699c3db 100644
--- a/src/kmk/kmkbuiltin/redirect.c
+++ b/src/kmk/kmkbuiltin/redirect.c
@@ -1,4 +1,4 @@
-/* $Id: redirect.c 2916 2016-09-15 11:41:42Z bird $ */
+/* $Id: redirect.c 3085 2017-10-03 11:01:54Z bird $ */
 /** @file
  * kmk_redirect - Do simple program <-> file redirection (++).
  */
@@ -26,8 +26,8 @@
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
-#ifdef __APPLE__
-# define _POSIX_C_SOURCE 1 /* 10.4 sdk and unsetenv */
+#if defined(__APPLE__)
+/*# define _POSIX_C_SOURCE 1  / *  10.4 sdk and unsetenv  * / - breaks O_CLOEXEC on 10.8 */
 #endif
 #include "make.h"
 #include <assert.h>
@@ -44,8 +44,18 @@
 # include <io.h>
 # include "quote_argv.h"
 #else
+# ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+#  if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
+#   define USE_POSIX_SPAWN
+#  endif
+# elif !defined(KBUILD_OS_WINDOWS) && !defined(KBUILD_OS_OS2)
+#  define USE_POSIX_SPAWN
+# endif
 # include <unistd.h>
-# include <spawn.h>
+# ifdef USE_POSIX_SPAWN
+#  include <spawn.h>
+# endif
+# include <sys/wait.h>
 #endif
 
 #include <k/kDefs.h>
@@ -70,10 +80,6 @@
 # endif
 #endif
 
-#if !defined(KBUILD_OS_WINDOWS) && !defined(KBUILD_OS_OS2)
-# define USE_POSIX_SPAWN
-#endif
-
 
 /* String + strlen tuple. */
 #define TUPLE(a_sz)     a_sz, sizeof(a_sz) - 1
@@ -89,7 +95,7 @@ static void __cdecl ignore_invalid_parameter(const wchar_t *a, const wchar_t *b,
 
 #endif /* _MSC_VER */
 
-
+#if 0 /* unused */
 /**
  * Safely works around MS CRT's pedantic close() function.
  *
@@ -106,6 +112,7 @@ static void safeCloseFd(int fd)
     close(fd);
 #endif
 }
+#endif /* unused */
 
 
 static const char *name(const char *pszName)
@@ -175,7 +182,7 @@ typedef struct REDIRECTORDERS
         kRedirectOrder_Invalid = 0,
         kRedirectOrder_Close,
         kRedirectOrder_Open,
-        kRedirectOrder_Dup,
+        kRedirectOrder_Dup
     }           enmOrder;
     /** The target file handle. */
     int         fdTarget;
@@ -382,10 +389,11 @@ static int kRedirectOpenWithoutConflict(const char *pszFilename, int fOpen, mode
 #elif defined(O_CLOEXEC)
     int const   fNoInherit = O_CLOEXEC;
 #else
-# error "port me"
+    int const   fNoInherit = 0;
+# define USE_FD_CLOEXEC
 #endif
     int         aFdTries[32];
-    int         cTries;
+    unsigned    cTries;
     int         fdOpened;
 
 #ifdef KBUILD_OS_WINDOWS
@@ -404,7 +412,9 @@ static int kRedirectOpenWithoutConflict(const char *pszFilename, int fOpen, mode
         if (fdOpened != fdTarget)
             return fdOpened;
 #ifndef _MSC_VER /* Stupid, stupid MSVCRT!  No friggin way of making a handle inheritable (or not). */
-        if (fcntl(fdOpened, F_SETFD, FD_CLOEXEC) != -1)
+# ifndef USE_FD_CLOEXEC
+        if (fcntl(fdOpened, F_SETFD, 0) != -1)
+# endif
             return fdOpened;
 #endif
     }
@@ -426,8 +436,13 @@ static int kRedirectOpenWithoutConflict(const char *pszFilename, int fOpen, mode
                 )
             {
 #ifndef _MSC_VER
-                if (   fdOpened != fdTarget
+# ifdef USE_FD_CLOEXEC
+                if (   fdOpened == fdTarget
                     || fcntl(fdOpened, F_SETFD, FD_CLOEXEC) != -1)
+# else
+                if (   fdOpened != fdTarget
+                    || fcntl(fdOpened, F_SETFD, 0) != -1)
+# endif
 #endif
                 {
                     while (cTries-- > 0)
@@ -456,6 +471,35 @@ static int kRedirectOpenWithoutConflict(const char *pszFilename, int fOpen, mode
     return -1;
 }
 
+
+/**
+ * Cleans up the file operation orders.
+ *
+ * This does not restore stuff, just closes handles we've opened for the child.
+ *
+ * @param   cOrders         Number of file operation orders.
+ * @param   paOrders        The file operation orders.
+ * @param   fFailed         Set if it's a failure.
+ */
+static void kRedirectCleanupFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders, KBOOL fFailure)
+{
+    unsigned i = cOrders;
+    while (i-- > 0)
+    {
+        if (   paOrders[i].enmOrder == kRedirectOrder_Open
+            && paOrders[i].fdSource != -1)
+        {
+            close(paOrders[i].fdSource);
+            paOrders[i].fdSource = -1;
+            if (   fFailure
+                && paOrders[i].fRemoveOnFailure
+                && paOrders[i].pszFilename)
+                remove(paOrders[i].pszFilename);
+        }
+    }
+}
+
+
 #ifndef USE_POSIX_SPAWN
 
 /**
@@ -573,34 +617,6 @@ static int kRedirectSaveHandle(REDIRECTORDERS *pToSave, unsigned cOrders, REDIRE
 
 
 /**
- * Cleans up the file operation orders.
- *
- * This does not restore stuff, just closes handles we've opened for the guest.
- *
- * @param   cOrders         Number of file operation orders.
- * @param   paOrders        The file operation orders.
- * @param   fFailed         Set if it's a failure.
- */
-static void kRedirectCleanupFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders, KBOOL fFailure)
-{
-    unsigned i = cOrders;
-    while (i-- > 0)
-    {
-        if (   paOrders[i].enmOrder == kRedirectOrder_Open
-            && paOrders[i].fdSource != -1)
-        {
-            close(paOrders[i].fdSource);
-            paOrders[i].fdSource = -1;
-            if (   fFailure
-                && paOrders[i].fRemoveOnFailure
-                && paOrders[i].pszFilename)
-                remove(paOrders[i].pszFilename);
-        }
-    }
-}
-
-
-/**
  * Restores the target file descriptors affected by the file operation orders.
  *
  * @param   cOrders         Number of file operation orders.
@@ -637,7 +653,7 @@ static void kRedirectRestoreFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders,
             }
 #ifndef KBUILD_OS_WINDOWS
             else
-                fprintf(*ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s",
+                fprintf(*ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s\n",
                         g_progname, paOrders[i].fdSaved, paOrders[i].fdTarget, strerror(errno));
 #endif
         }
@@ -645,10 +661,10 @@ static void kRedirectRestoreFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders,
 #ifndef KBUILD_OS_WINDOWS
         if (paOrders[i].fSaved != -1)
         {
-            if (fcntl(paOrders[i].fdTarget, F_SETFD, paOrders[i].fSaved & FD_CLOEXEC) == -1)
+            if (fcntl(paOrders[i].fdTarget, F_SETFD, paOrders[i].fSaved & FD_CLOEXEC) != -1)
                 paOrders[i].fSaved = -1;
             else
-                fprintf(*ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,%s) failed: %s",
+                fprintf(*ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,%s) failed: %s\n",
                         g_progname, paOrders[i].fdTarget, paOrders[i].fSaved & FD_CLOEXEC ? "FD_CLOEXEC" : "0", strerror(errno));
         }
 #endif
@@ -700,13 +716,13 @@ static int kRedirectExecFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders, FIL
                                  || errno == EBADF)
                             rcExit = 0;
                         else
-                            fprintf(*ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,FD_CLOEXEC) failed: %s",
+                            fprintf(*ppWorkingStdErr, "%s: fcntl(%d,F_SETFD,FD_CLOEXEC) failed: %s\n",
                                     g_progname, fdTarget, strerror(errno));
                     }
                     else if (errno == EBADF)
                         rcExit = 0;
                     else
-                        fprintf(*ppWorkingStdErr, "%s: fcntl(%d,F_GETFD,0) failed: %s", g_progname, fdTarget, strerror(errno));
+                        fprintf(*ppWorkingStdErr, "%s: fcntl(%d,F_GETFD,0) failed: %s\n", g_progname, fdTarget, strerror(errno));
                 }
 # endif
                 else
@@ -724,10 +740,10 @@ static int kRedirectExecFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders, FIL
                     else
                     {
                         if (paOrders[i].enmOrder == kRedirectOrder_Open)
-                            fprintf(*ppWorkingStdErr, "%s: dup2(%d [%s],%d) failed: %s", g_progname, paOrders[i].fdSource,
+                            fprintf(*ppWorkingStdErr, "%s: dup2(%d [%s],%d) failed: %s\n", g_progname, paOrders[i].fdSource,
                                     paOrders[i].pszFilename, paOrders[i].fdTarget, strerror(errno));
                         else
-                            fprintf(*ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s",
+                            fprintf(*ppWorkingStdErr, "%s: dup2(%d,%d) failed: %s\n",
                                     g_progname, paOrders[i].fdSource, paOrders[i].fdTarget, strerror(errno));
                         rcExit = 10;
                     }
@@ -762,7 +778,7 @@ static int kRedirectExecFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders, FIL
  * @param   papszArgs           The child argument vector.
  * @param   fWatcomBrainDamage  Whether MSC need to do quoting according to
  *                              weird Watcom WCC rules.
- * @param   papszEnv            The child environment vector.
+ * @param   papszEnvVars        The child environment vector.
  * @param   pszCwd              The current working directory of the child.
  * @param   pszSavedCwd         The saved current working directory.  This is
  *                              NULL if the CWD doesn't need changing.
@@ -776,7 +792,7 @@ static int kRedirectExecFdOrders(unsigned cOrders, REDIRECTORDERS *paOrders, FIL
  * @param   pfIsChildExitCode   Where to indicate whether the return exit code
  *                              is from the child or from our setup efforts.
  */
-static int kRedirectDoSpawn(const char *pszExecutable, int cArgs, char **papszArgs, int fWatcomBrainDamage, char **papszEnv,
+static int kRedirectDoSpawn(const char *pszExecutable, int cArgs, char **papszArgs, int fWatcomBrainDamage, char **papszEnvVars,
                             const char *pszCwd, const char *pszSavedCwd, unsigned cOrders, REDIRECTORDERS *paOrders,
 #ifdef USE_POSIX_SPAWN
                             posix_spawn_file_actions_t *pFileActions,
@@ -787,7 +803,7 @@ static int kRedirectDoSpawn(const char *pszExecutable, int cArgs, char **papszAr
 #endif
                             KBOOL *pfIsChildExitCode)
 {
-    int     rcExit;
+    int     rcExit = 0;
     int     i;
 #ifdef _MSC_VER
     char  **papszArgsOriginal = papszArgs;
@@ -862,7 +878,7 @@ static int kRedirectDoSpawn(const char *pszExecutable, int cArgs, char **papszAr
                  */
 #if defined(KBUILD_OS_WINDOWS)
                 /* Windows is slightly complicated due to handles and sub_proc.c. */
-                HANDLE  hProcess = (HANDLE)_spawnvpe(_P_NOWAIT, pszExecutable, papszArgs, papszEnv);
+                HANDLE  hProcess = (HANDLE)_spawnvpe(_P_NOWAIT, pszExecutable, papszArgs, papszEnvVars);
                 kRedirectRestoreFdOrders(cOrders, paOrders, &pWorkingStdErr);
                 if ((intptr_t)hProcess != -1)
                 {
@@ -897,7 +913,7 @@ static int kRedirectDoSpawn(const char *pszExecutable, int cArgs, char **papszAr
                     rcExit = err(10, "_spawnvpe(%s) failed", pszExecutable);
 
 # elif defined(KBUILD_OS_OS2)
-                *pPidSpawned = _spawnve(_P_NOWAIT, pszExecutable, papszArgs, papszEnv);
+                *pPidSpawned = _spawnvpe(P_NOWAIT, pszExecutable, papszArgs, papszEnvVars);
                 kRedirectRestoreFdOrders(cOrders, paOrders, &pWorkingStdErr);
                 if (*pPidSpawned != -1)
                 {
@@ -929,7 +945,11 @@ static int kRedirectDoSpawn(const char *pszExecutable, int cArgs, char **papszAr
                  */
 # if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2)
                 errno  = 0;
-                rcExit = (int)_spawnvpe(_P_WAIT, pszExecutable, papszArgs, papszEnv);
+#  if defined(KBUILD_OS_WINDOWS)
+                rcExit = (int)_spawnvpe(_P_WAIT, pszExecutable, papszArgs, papszEnvVars);
+#  else
+                rcExit = (int)_spawnvpe(P_WAIT, pszExecutable, papszArgs, papszEnvVars);
+#  endif
                 kRedirectRestoreFdOrders(cOrders, paOrders, &pWorkingStdErr);
                 if (rcExit != -1 || errno == 0)
                 {
@@ -1022,7 +1042,7 @@ int main(int argc, char **argv, char **envp)
 
     int             iArg;
     const char     *pszExecutable      = NULL;
-    char          **papszEnv           = NULL;
+    char          **papszEnvVars       = NULL;
     unsigned        cAllocatedEnvVars;
     unsigned        iEnvVar;
     unsigned        cEnvVars;
@@ -1056,11 +1076,11 @@ int main(int argc, char **argv, char **envp)
 
 #if defined(KMK)
     /* We get it from kmk and just count it:  */
-    papszEnv = pChild->environment;
-    if (!papszEnv)
-        pChild->environment = papszEnv = target_environment(pChild->file);
+    papszEnvVars = pChild->environment;
+    if (!papszEnvVars)
+        pChild->environment = papszEnvVars = target_environment(pChild->file);
     cEnvVars = 0;
-    while (papszEnv[cEnvVars] != NULL)
+    while (papszEnvVars[cEnvVars] != NULL)
         cEnvVars++;
     cAllocatedEnvVars = cEnvVars;
 #else
@@ -1070,20 +1090,20 @@ int main(int argc, char **argv, char **envp)
         cEnvVars++;
 
     cAllocatedEnvVars = cEnvVars + 4;
-    papszEnv = malloc((cAllocatedEnvVars + 1) * sizeof(papszEnv));
-    if (!papszEnv)
+    papszEnvVars = malloc((cAllocatedEnvVars + 1) * sizeof(papszEnvVars));
+    if (!papszEnvVars)
         return errx(9, "out of memory!");
 
     iEnvVar = cEnvVars;
-    papszEnv[iEnvVar] = NULL;
+    papszEnvVars[iEnvVar] = NULL;
     while (iEnvVar-- > 0)
     {
-        papszEnv[iEnvVar] = strdup(envp[iEnvVar]);
-        if (!papszEnv[iEnvVar])
+        papszEnvVars[iEnvVar] = strdup(envp[iEnvVar]);
+        if (!papszEnvVars[iEnvVar])
         {
             while (iEnvVar-- > 0)
-                free(papszEnv[iEnvVar]);
-            free(papszEnv);
+                free(papszEnvVars[iEnvVar]);
+            free(papszEnvVars);
             return errx(9, "out of memory!");
         }
     }
@@ -1114,11 +1134,16 @@ int main(int argc, char **argv, char **envp)
             pszArg++;
             if (chOpt == '-')
             {
-                /* '--' indicates where the bits to execute start. */
+                /* '--' indicates where the bits to execute start.  Check if we're
+                   relaunching ourselves here and just continue parsing if we are. */
                 if (*pszArg == '\0')
                 {
                     iArg++;
-                    break;
+                    if (    iArg >= argc
+                        || (   strcmp(argv[iArg], "kmk_builtin_redirect") != 0
+                            && strcmp(argv[iArg], argv[0]) != 0))
+                        break;
+                    continue;
                 }
 
                 if (   strcmp(pszArg, "wcc-brain-damage") == 0
@@ -1136,6 +1161,10 @@ int main(int argc, char **argv, char **envp)
                 else if (   strcmp(pszArg, "set") == 0
                          || strcmp(pszArg, "env") == 0)
                     chOpt = 'E';
+                else if (strcmp(pszArg, "append") == 0)
+                    chOpt = 'A';
+                else if (strcmp(pszArg, "prepend") == 0)
+                    chOpt = 'D';
                 else if (strcmp(pszArg, "unset") == 0)
                     chOpt = 'U';
                 else if (   strcmp(pszArg, "zap-env") == 0
@@ -1176,6 +1205,8 @@ int main(int argc, char **argv, char **envp)
              * Get option value first, if the option takes one.
              */
             if (   chOpt == 'E'
+                || chOpt == 'A'
+                || chOpt == 'D'
                 || chOpt == 'U'
                 || chOpt == 'C'
                 || chOpt == 'c'
@@ -1214,7 +1245,7 @@ int main(int argc, char **argv, char **envp)
                     if (apszSavedLibPaths[ulVar] == NULL)
                     {
                         /* The max length is supposed to be 1024 bytes. */
-                        apszSavedLibPaths[ulVar] = calloc(1024 * 2);
+                        apszSavedLibPaths[ulVar] = calloc(1024, 2);
                         if (apszSavedLibPaths[ulVar])
                         {
                             rc = DosQueryExtLIBPATH(apszSavedLibPaths[ulVar], ulVar);
@@ -1244,9 +1275,9 @@ int main(int argc, char **argv, char **envp)
                 {
                     if (pchEqual[1] != '\0')
                     {
-                        rcExit = kBuiltinOptEnvSet(&papszEnv, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                        rcExit = kBuiltinOptEnvSet(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
 #ifdef KMK
-                        pChild->environment = papszEnv;
+                        pChild->environment = papszEnvVars;
 #endif
                     }
                     else
@@ -1255,7 +1286,7 @@ int main(int argc, char **argv, char **envp)
                         if (pszCopy)
                         {
                             pszCopy[pchEqual - pszValue] = '\0';
-                            rcExit = kBuiltinOptEnvUnset(papszEnv, &cEnvVars, cVerbosity, pszCopy);
+                            rcExit = kBuiltinOptEnvUnset(papszEnvVars, &cEnvVars, cVerbosity, pszCopy);
                             free(pszCopy);
                         }
                         else
@@ -1268,6 +1299,25 @@ int main(int argc, char **argv, char **envp)
             }
 
             /*
+             * Append or prepend value to and environment variable.
+             */
+            if (chOpt == 'A' || chOpt == 'D')
+            {
+#ifdef KBUILD_OS_OS2
+                if (   strcmp(pszValue, "BEGINLIBPATH") == 0
+                    || strcmp(pszValue, "ENDLIBPATH") == 0
+                    || strcmp(pszValue, "LIBPATHSTRICT") == 0)
+                    rcExit = errx(2, "error: '%s' cannot currently be appended or prepended to. Please use -E/--set for now.", pszValue);
+                else
+#endif
+                if (chOpt == 'A')
+                    rcExit = kBuiltinOptEnvAppend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                else
+                    rcExit = kBuiltinOptEnvPrepend(&papszEnvVars, &cEnvVars, &cAllocatedEnvVars, cVerbosity, pszValue);
+                continue;
+            }
+
+            /*
              * Unset environment variable.
              */
             if (chOpt == 'U')
@@ -1279,7 +1329,7 @@ int main(int argc, char **argv, char **envp)
                     rcExit = errx(2, "error: '%s' cannot be unset, only set to an empty value using -E/--set.", pszValue);
                 else
 #endif
-                    rcExit = kBuiltinOptEnvUnset(papszEnv, &cEnvVars, cVerbosity, pszValue);
+                    rcExit = kBuiltinOptEnvUnset(papszEnvVars, &cEnvVars, cVerbosity, pszValue);
                 continue;
             }
 
@@ -1290,8 +1340,8 @@ int main(int argc, char **argv, char **envp)
                 || chOpt == 'i' /* GNU env compatibility. */ )
             {
                 for (iEnvVar = 0; iEnvVar < cEnvVars; iEnvVar++)
-                    free(papszEnv[iEnvVar]);
-                papszEnv[0] = NULL;
+                    free(papszEnvVars[iEnvVar]);
+                papszEnvVars[0] = NULL;
                 cEnvVars = 0;
                 continue;
             }
@@ -1576,7 +1626,7 @@ int main(int argc, char **argv, char **envp)
                     cOrders++;
 
 #ifdef USE_POSIX_SPAWN
-                    if (fdOpened != fdSource)
+                    if (fdOpened != fd)
                     {
                         rcExit = posix_spawn_file_actions_adddup2(&FileActions, fdOpened, fd);
                         if (rcExit != 0)
@@ -1606,7 +1656,7 @@ int main(int argc, char **argv, char **envp)
         /*
          * Do the spawning in a separate function (main is far to large as it is by now).
          */
-        rcExit = kRedirectDoSpawn(pszExecutable, argc - iArg, &argv[iArg], fWatcomBrainDamage, papszEnv, szCwd, pszSavedCwd,
+        rcExit = kRedirectDoSpawn(pszExecutable, argc - iArg, &argv[iArg], fWatcomBrainDamage, papszEnvVars, szCwd, pszSavedCwd,
 #ifdef USE_POSIX_SPAWN
                                   cOrders, aOrders, &FileActions, cVerbosity,
 #else
@@ -1638,8 +1688,8 @@ int main(int argc, char **argv, char **envp)
 #ifndef KMK
     iEnvVar = cEnvVars;
     while (iEnvVar-- > 0)
-        free(papszEnv[iEnvVar]);
-    free(papszEnv);
+        free(papszEnvVars[iEnvVar]);
+    free(papszEnvVars);
 #endif
 #ifdef KBUILD_OS_OS2
     for (ulLibPath = 0; ulLibPath < K_ELEMENTS(apszSavedLibPaths); ulLibPath++)
@@ -1649,7 +1699,7 @@ int main(int argc, char **argv, char **envp)
             if (rc != 0)
                 warnx("DosSetExtLIBPATH('%s',%u) failed with %u when restoring the original values!",
                       apszSavedLibPaths[ulLibPath], ulLibPath, rc);
-            free(apszSavedLibPaths[ulLibPath])
+            free(apszSavedLibPaths[ulLibPath]);
         }
 #endif
 
diff --git a/src/kmk/kmkbuiltin/rm.c b/src/kmk/kmkbuiltin/rm.c
index 986f991..afa57e1 100644
--- a/src/kmk/kmkbuiltin/rm.c
+++ b/src/kmk/kmkbuiltin/rm.c
@@ -66,6 +66,10 @@ static char sccsid[] = "@(#)rm.c	8.5 (Berkeley) 4/18/94";
 #ifdef __HAIKU__
 # include "haikufakes.h"
 #endif
+#ifdef __NetBSD__
+# include <util.h>
+# define fflagstostr(flags)    	flags_to_string(flags, "")
+#endif
 #ifdef KBUILD_OS_WINDOWS
 # ifdef _MSC_VER
 #  include "mscfakes.h"
diff --git a/src/kmk/kmkbuiltin/test.c b/src/kmk/kmkbuiltin/test.c
index 69dc2db..74e6d69 100644
--- a/src/kmk/kmkbuiltin/test.c
+++ b/src/kmk/kmkbuiltin/test.c
@@ -277,7 +277,7 @@ int kmk_builtin_test(int argc, char **argv, char **envp
 # endif
 #else /* in kmk */
 			/* let job.c spawn the process, make a job.c style argv_spawn copy. */
-			char *buf, *cur, **argv_new;
+			char *cur, **argv_new;
 			size_t sz = 0;
 			int argc_new = 0;
 			while (argv_spawn[argc_new]) {
@@ -287,7 +287,7 @@ int kmk_builtin_test(int argc, char **argv, char **envp
 			}
 
 			argv_new = xmalloc((argc_new + 1) * sizeof(char *));
-			buf = cur = xmalloc(sz);
+			cur = xmalloc(sz);
 			for (i = 0; i < argc_new; i++) {
 				size_t len = strlen(argv_spawn[i]) + 1;
 				argv_new[i] = memcpy(cur, argv_spawn[i], len);
diff --git a/src/kmk/kmkbuiltin/touch.c b/src/kmk/kmkbuiltin/touch.c
new file mode 100644
index 0000000..2f4adcd
--- /dev/null
+++ b/src/kmk/kmkbuiltin/touch.c
@@ -0,0 +1,967 @@
+/* $Id: touch.c 3074 2017-10-02 09:09:57Z bird $ */
+/** @file
+ * kmk_touch - Simple touch implementation.
+ */
+
+/*
+ * Copyright (c) 2017 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kBuild.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "make.h"
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#if defined(_MSC_VER)
+# include <ctype.h>
+# include <io.h>
+# include <sys/timeb.h>
+#else
+# include <unistd.h>
+#endif
+
+#include <k/kDefs.h>
+#include <k/kTypes.h>
+#include "err.h"
+#include "kbuild_version.h"
+#include "kmkbuiltin.h"
+
+#ifdef _MSC_VER
+# include "nt/ntstat.h"
+# undef FILE_TIMESTAMP_HI_RES
+# define FILE_TIMESTAMP_HI_RES 1
+#endif
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+/** The program name to use in message. */
+#ifdef KMK
+# define TOUCH_NAME  "kmk_builtin_touch"
+#else
+# define TOUCH_NAME  "kmk_touch"
+#endif
+/** Converts a two digit decimal field to a number. */
+#define TWO_CHARS_TO_INT(chHigh, chLow)  ( ((unsigned)(chHigh) - (unsigned)'0') * 10 + ((unsigned)(chLow) - (unsigned)'0') )
+/** Checks an alleged digit. */
+#define IS_DIGIT(chDigit, uMax)          ( ((unsigned)(chDigit) - (unsigned)'0') <= (unsigned)(uMax) )
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+typedef enum KMKTOUCHTARGET
+{
+    kTouchAccessAndModify,
+    kTouchAccessOnly,
+    kTouchModifyOnly
+} KMKTOUCHTARGET;
+
+typedef enum KMKTOUCHACTION
+{
+    kTouchActionCurrent,
+    kTouchActionSet,
+    kTouchActionAdjust
+} KMKTOUCHACTION;
+
+
+typedef struct KMKTOUCHOPTS
+{
+    /** What timestamps to modify on the files. */
+    KMKTOUCHTARGET  enmWhatToTouch;
+    /** How to update the time. */
+    KMKTOUCHACTION  enmAction;
+    /** Whether to create files (K_TRUE) or ignore missing (K_FALSE). */
+    KBOOL           fCreate;
+    /** Whether to dereference files. */
+    KBOOL           fDereference;
+    /** The new access time value. */
+    struct timeval  NewATime;
+    /** The new modified time value. */
+    struct timeval  NewMTime;
+
+    /** Number of files. */
+    int             cFiles;
+    /** The specified files.   */
+    char          **papszFiles;
+} KMKTOUCHOPTS;
+typedef KMKTOUCHOPTS *PKMKTOUCHOPTS;
+
+
+
+static int touch_error(const char *pszMsg, ...)
+{
+    va_list va;
+    fputs(TOUCH_NAME ": error: ", stderr);
+    va_start(va, pszMsg);
+    vfprintf(stderr, pszMsg, va);
+    va_end(va);
+    fputc('\n', stderr);
+    return 1;
+}
+
+static int touch_syntax(const char *pszMsg, ...)
+{
+    va_list va;
+    fputs(TOUCH_NAME ": syntax error: ", stderr);
+    va_start(va, pszMsg);
+    vfprintf(stderr, pszMsg, va);
+    va_end(va);
+    fputc('\n', stderr);
+    return 2;
+}
+
+static int touch_usage(void)
+{
+    fputs("Usage: " TOUCH_NAME " [options] [MMDDhhmm[YY]] <file1> [.. [fileN]]\n"
+          "\n"
+          "Options:\n"
+          "  -A [-][[hh]mm]SS, --adjust=[-][[hh]mm]SS\n"
+          "    Adjust timestamps by given delta.\n"
+          "  -a, --time=atime, --time=access\n"
+          "    Only change the accessed timestamp.\n"
+          "  -c, --no-create\n"
+          "    Ignore missing files and don't create them. (default create empty file)\n"
+          "  -d YYYY-MM-DDThh:mm:SS[.frac][tz], --date=YYYY-MM-DDThh:mm:SS[.frac][tz]\n"
+          "    Set the timestamps to the given one.\n"
+          "  -f\n"
+          "    Ignored for compatbility reasons.\n"
+          "  -h, --no-dereference\n"
+          "    Don't follow links, touch links. (Not applicable to -r.)\n"
+          "  -m, --time=mtime, --time=modify\n"
+          "    Only changed the modified timestamp.\n"
+          "  -r <file>, --reference=<file>\n"
+          "    Take the timestamps from <file>.\n"
+          "  -t [[CC]YY]MMDDhhmm[.SS]\n"
+          "    Set the timestamps to the given one.\n"
+          "\n"
+          "Note. For compatibility reasons the first file can be taken to be a 8 or 10\n"
+          "      character long timestamp if it matches the given pattern and none of\n"
+          "      the -A, -d, --date, -r, --reference, or -t options are given.  So, use\n"
+          "      absolute or relative paths when specifying more than one file.\n"
+          , stdout);
+    return 0;
+}
+
+
+#if K_OS == K_OS_SOLARIS
+/**
+ * Solaris doesn't have lutimes because System V doesn't believe in stuff like file modes on symbolic links.
+ */
+static int lutimes(const char *pszFile, struct timeval aTimes[2])
+{
+    struct stat Stat;
+    if (stat(pszFile, &Stat) != -1)
+    {
+        if (!S_ISLNK(Stat.st_mode))
+            return utimes(pszFile, aTimes);
+        return 0;
+    }
+    return -1;
+}
+#endif 
+
+
+/**
+ * Parses adjustment value: [-][[hh]mm]SS
+ */
+static int touch_parse_adjust(const char *pszValue, int *piAdjustValue)
+{
+    const char * const  pszInValue = pszValue;
+    size_t              cchValue  = strlen(pszValue);
+    KBOOL               fNegative = K_FALSE;
+
+    /* Deal with negativity */
+    if (pszValue[0] == '-')
+    {
+        fNegative = K_TRUE;
+        pszValue++;
+        cchValue--;
+    }
+
+    /* Validate and convert. */
+    *piAdjustValue = 0;
+    switch (cchValue)
+    {
+        case 6:
+            if (   !IS_DIGIT(pszValue[0], 9)
+                || !IS_DIGIT(pszValue[0], 9))
+                return touch_syntax("Malformed hour part of -A value: %s", pszInValue);
+            *piAdjustValue = TWO_CHARS_TO_INT(pszValue[0], pszValue[1]) * 60 * 60;
+            /* fall thru */
+        case 4:
+            if (   !IS_DIGIT(pszValue[cchValue - 4], 9) /* don't bother limit to 60 minutes */
+                || !IS_DIGIT(pszValue[cchValue - 3], 9))
+                return touch_syntax("Malformed minute part of -A value: %s", pszInValue);
+            *piAdjustValue += TWO_CHARS_TO_INT(pszValue[cchValue - 4], pszValue[cchValue - 3]) * 60;
+            /* fall thru */
+        case 2:
+            if (   !IS_DIGIT(pszValue[cchValue - 2], 9) /* don't bother limit to 60 seconds */
+                || !IS_DIGIT(pszValue[cchValue - 1], 9))
+                return touch_syntax("Malformed second part of -A value: %s", pszInValue);
+            *piAdjustValue += TWO_CHARS_TO_INT(pszValue[cchValue - 2], pszValue[cchValue - 1]);
+            break;
+
+        default:
+            return touch_syntax("Invalid -A value (length): %s", pszInValue);
+    }
+
+    /* Apply negativity. */
+    if (fNegative)
+        *piAdjustValue = -*piAdjustValue;
+
+    return 0;
+}
+
+
+/**
+ * Parse -d timestamp: YYYY-MM-DDThh:mm:SS[.frac][tz]
+ */
+static int touch_parse_d_ts(const char *pszTs, struct timeval *pDst)
+{
+    const char * const  pszTsIn = pszTs;
+    struct tm           ExpTime;
+
+    /*
+     * Validate and parse the timestamp into the tm structure.
+     */
+    memset(&ExpTime, 0, sizeof(ExpTime));
+
+    /* year */
+    if (   !IS_DIGIT(pszTs[0], 9)
+        || !IS_DIGIT(pszTs[1], 9)
+        || !IS_DIGIT(pszTs[2], 9)
+        || !IS_DIGIT(pszTs[3], 9)
+        || pszTs[4] != '-')
+        return touch_error("Malformed timestamp '%s' given to -d: expected to start with 4 digit year followed by a dash",
+                           pszTsIn);
+    ExpTime.tm_year = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) * 100
+                    + TWO_CHARS_TO_INT(pszTs[2], pszTs[3])
+                    - 1900;
+    pszTs += 5;
+
+    /* month */
+    if (   !IS_DIGIT(pszTs[0], 1)
+        || !IS_DIGIT(pszTs[1], 9)
+        || pszTs[2] != '-')
+        return touch_error("Malformed timestamp '%s' given to -d: expected to two digit month at position 6 followed by a dash",
+                           pszTsIn);
+    ExpTime.tm_mon = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) - 1;
+    pszTs += 3;
+
+    /* day */
+    if (   !IS_DIGIT(pszTs[0], 3)
+        || !IS_DIGIT(pszTs[1], 9)
+        || (pszTs[2] != 'T' && pszTs[2] != 't' && pszTs[2] != ' ') )
+        return touch_error("Malformed timestamp '%s' given to -d: expected to two digit day of month at position 9 followed by 'T' or space",
+                           pszTsIn);
+    ExpTime.tm_mday = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]);
+    pszTs += 3;
+
+    /* hour */
+    if (   !IS_DIGIT(pszTs[0], 2)
+        || !IS_DIGIT(pszTs[1], 9)
+        || pszTs[2] != ':')
+        return touch_error("Malformed timestamp '%s' given to -d: expected to two digit hour at position 12 followed by colon",
+                           pszTsIn);
+    ExpTime.tm_hour = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]);
+    pszTs += 3;
+
+    /* minute */
+    if (   !IS_DIGIT(pszTs[0], 5)
+        || !IS_DIGIT(pszTs[1], 9)
+        || pszTs[2] != ':')
+        return touch_error("Malformed timestamp '%s' given to -d: expected to two digit minute at position 15 followed by colon",
+                           pszTsIn);
+    ExpTime.tm_min = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]);
+    pszTs += 3;
+
+    /* seconds */
+    if (   !IS_DIGIT(pszTs[0], 5)
+        || !IS_DIGIT(pszTs[1], 9))
+        return touch_error("Malformed timestamp '%s' given to -d: expected to two digit seconds at position 12", pszTsIn);
+    ExpTime.tm_sec = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]);
+    pszTs += 2;
+
+    /* fraction */
+    pDst->tv_usec = 0;
+    if (*pszTs == '.' || *pszTs == ',')
+    {
+        int iFactor;
+
+        pszTs++;
+        if (!IS_DIGIT(*pszTs, 9))
+            return touch_error("Malformed timestamp '%s' given to -d: empty fraction", pszTsIn);
+
+        iFactor = 100000;
+        do
+        {
+            pDst->tv_usec += ((unsigned)*pszTs - (unsigned)'0') * iFactor;
+            iFactor /= 10;
+            pszTs++;
+        } while (IS_DIGIT(*pszTs, 9));
+    }
+
+    /* zulu time indicator */
+    ExpTime.tm_isdst = -1;
+    if (*pszTs == 'Z' || *pszTs == 'z')
+    {
+        ExpTime.tm_isdst = 0;
+        pszTs++;
+        if (*pszTs != '\0')
+            return touch_error("Malformed timestamp '%s' given to -d: Unexpected character(s) after zulu time indicator at end of timestamp",
+                               pszTsIn);
+    }
+    else if (*pszTs != '\0')
+        return touch_error("Malformed timestamp '%s' given to -d: expected to 'Z' (zulu) or nothing at end of timestamp", pszTsIn);
+
+    /*
+     * Convert to UTC seconds using either timegm or mktime.
+     */
+    ExpTime.tm_yday  = -1;
+    ExpTime.tm_wday  = -1;
+    if (ExpTime.tm_isdst == 0)
+    {
+#if K_OS == K_OS_SOLARIS || K_OS == K_OS_OS2
+        pDst->tv_sec = mktime(&ExpTime) - timezone; /* best we can do for now */
+#else
+        pDst->tv_sec = timegm(&ExpTime);
+#endif
+        if (pDst->tv_sec == -1)
+            return touch_error("timegm failed on '%s': %s", pszTs, strerror(errno));
+    }
+    else
+    {
+        pDst->tv_sec = mktime(&ExpTime);
+        if (pDst->tv_sec == -1)
+            return touch_error("mktime failed on '%s': %s", pszTs, strerror(errno));
+    }
+    return 0;
+}
+
+
+/**
+ * Parse -t timestamp: [[CC]YY]MMDDhhmm[.SS]
+ */
+static int touch_parse_ts(const char *pszTs, struct timeval *pDst)
+{
+    size_t const    cchTs = strlen(pszTs);
+    size_t          cchTsNoSec;
+    struct tm       ExpTime;
+    struct tm      *pExpTime;
+    struct timeval  Now;
+    int rc;
+
+    /*
+     * Do some input validations first.
+     */
+    if ((cchTs & 1) && pszTs[cchTs - 3] != '.')
+        return touch_error("Invalid timestamp given to -t: %s", pszTs);
+    switch (cchTs)
+    {
+        case 8:             /*     MMDDhhmm */
+        case 8 + 2:         /*   YYMMDDhhmm */
+        case 8 + 2 + 2:     /* CCYYMMDDhhmm */
+            cchTsNoSec = cchTs;
+            break;
+        case 8 + 3:         /*     MMDDhhmm.SS */
+        case 8 + 3 + 2:     /*   YYMMDDhhmm.SS */
+        case 8 + 3 + 2 + 2: /* CCYYMMDDhhmm.SS */
+            if (pszTs[cchTs - 3] != '.')
+                return touch_error("Invalid timestamp (-t) '%s': missing dot for seconds part", pszTs);
+            if (   !IS_DIGIT(pszTs[cchTs - 2], 5)
+                || !IS_DIGIT(pszTs[cchTs - 1], 9))
+                return touch_error("Invalid timestamp (-t) '%s': malformed seconds part", pszTs);
+            cchTsNoSec = cchTs - 3;
+            break;
+        default:
+            return touch_error("Invalid timestamp (-t) '%s': wrong length (%d)", pszTs, (int)cchTs);
+    }
+
+    switch (cchTsNoSec)
+    {
+        case 8 + 2 + 2:     /* CCYYMMDDhhmm */
+            if (   !IS_DIGIT(pszTs[cchTsNoSec - 12], 9)
+                || !IS_DIGIT(pszTs[cchTsNoSec - 11], 9))
+                return touch_error("Invalid timestamp (-t) '%s': malformed CC part", pszTs);
+            /* fall thru */
+        case 8 + 2:         /*   YYMMDDhhmm */
+            if (   !IS_DIGIT(pszTs[cchTsNoSec - 10], 9)
+                || !IS_DIGIT(pszTs[cchTsNoSec -  9], 9))
+                return touch_error("Invalid timestamp (-t) '%s': malformed YY part", pszTs);
+            /* fall thru */
+        case 8:             /*     MMDDhhmm */
+            if (   !IS_DIGIT(pszTs[cchTsNoSec - 8], 1)
+                || !IS_DIGIT(pszTs[cchTsNoSec - 7], 9) )
+                return touch_error("Invalid timestamp (-t) '%s': malformed month part", pszTs);
+            if (   !IS_DIGIT(pszTs[cchTsNoSec - 6], 3)
+                || !IS_DIGIT(pszTs[cchTsNoSec - 5], 9) )
+                return touch_error("Invalid timestamp (-t) '%s': malformed day part", pszTs);
+            if (   !IS_DIGIT(pszTs[cchTsNoSec - 4], 2)
+                || !IS_DIGIT(pszTs[cchTsNoSec - 3], 9) )
+                return touch_error("Invalid timestamp (-t) '%s': malformed hour part", pszTs);
+            if (   !IS_DIGIT(pszTs[cchTsNoSec - 2], 5)
+                || !IS_DIGIT(pszTs[cchTsNoSec - 1], 9) )
+                return touch_error("Invalid timestamp (-t) '%s': malformed minute part", pszTs);
+            break;
+    }
+
+    /*
+     * Get the current time and explode it.
+     */
+    rc = gettimeofday(&Now, NULL);
+    if (rc != 0)
+        return touch_error("gettimeofday failed: %s", strerror(errno));
+
+    pExpTime = localtime_r(&Now.tv_sec, &ExpTime);
+    if (pExpTime == NULL)
+        return touch_error("localtime_r failed: %s", strerror(errno));
+
+    /*
+     * Do the decoding.
+     */
+    if (cchTs & 1)
+        pExpTime->tm_sec = TWO_CHARS_TO_INT(pszTs[cchTs - 2], pszTs[cchTs - 1]);
+    else
+        pExpTime->tm_sec = 0;
+
+    if (cchTsNoSec == 8 + 2 + 2) /* CCYY */
+        pExpTime->tm_year = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]) * 100
+                          + TWO_CHARS_TO_INT(pszTs[2], pszTs[3])
+                          - 1900;
+    else  if (cchTsNoSec == 8 + 2) /* YY */
+    {
+        pExpTime->tm_year = TWO_CHARS_TO_INT(pszTs[0], pszTs[1]);
+        if (pExpTime->tm_year < 69)
+            pExpTime->tm_year += 100;
+    }
+
+    pExpTime->tm_mon  = TWO_CHARS_TO_INT(pszTs[cchTsNoSec - 8], pszTs[cchTsNoSec - 7]) - 1;
+    pExpTime->tm_mday = TWO_CHARS_TO_INT(pszTs[cchTsNoSec - 6], pszTs[cchTsNoSec - 5]);
+    pExpTime->tm_hour = TWO_CHARS_TO_INT(pszTs[cchTsNoSec - 4], pszTs[cchTsNoSec - 3]);
+    pExpTime->tm_min  = TWO_CHARS_TO_INT(pszTs[cchTsNoSec - 2], pszTs[cchTsNoSec - 1]);
+
+    /*
+     * Use mktime to convert to UTC seconds.
+     */
+    pExpTime->tm_isdst = -1;
+    pExpTime->tm_yday  = -1;
+    pExpTime->tm_wday  = -1;
+    pDst->tv_usec = 0;
+    pDst->tv_sec  = mktime(pExpTime);
+    if (pDst->tv_sec != -1)
+        return 0;
+    return touch_error("mktime failed on '%s': %s", pszTs, strerror(errno));
+}
+
+
+/**
+ * Check for old timestamp: MMDDhhmm[YY]
+ */
+static int touch_parse_old_ts(const char *pszOldTs, time_t Now, struct timeval *pDst)
+{
+    /*
+     * Check if this is a valid timestamp.
+     */
+    size_t const cchOldTs = strlen(pszOldTs);
+    if (   (   cchOldTs == 8
+            || cchOldTs == 10)
+        && IS_DIGIT(pszOldTs[0], 1)
+        && IS_DIGIT(pszOldTs[1], 9)
+        && IS_DIGIT(pszOldTs[2], 3)
+        && IS_DIGIT(pszOldTs[3], 9)
+        && IS_DIGIT(pszOldTs[4], 2)
+        && IS_DIGIT(pszOldTs[5], 9)
+        && IS_DIGIT(pszOldTs[6], 5)
+        && IS_DIGIT(pszOldTs[7], 9)
+        && (   cchOldTs == 8
+            || (   IS_DIGIT(pszOldTs[8], 9)
+                && IS_DIGIT(pszOldTs[9], 9) )) )
+    {
+        /*
+         * Explode the current time as local.
+         */
+        struct tm   ExpTime;
+        struct tm  *pExpTime;
+        pExpTime = localtime_r(&Now, &ExpTime);
+        if (pExpTime == NULL)
+            return touch_error("localtime_r failed: %s", strerror(errno));
+
+        /*
+         * Decode the bits we've got.
+         */
+        pExpTime->tm_mon  = TWO_CHARS_TO_INT(pszOldTs[0], pszOldTs[1]) - 1;
+        pExpTime->tm_mday = TWO_CHARS_TO_INT(pszOldTs[2], pszOldTs[3]);
+        pExpTime->tm_hour = TWO_CHARS_TO_INT(pszOldTs[4], pszOldTs[5]);
+        pExpTime->tm_min  = TWO_CHARS_TO_INT(pszOldTs[6], pszOldTs[7]);
+        if (cchOldTs == 10)
+        {
+            pExpTime->tm_year = TWO_CHARS_TO_INT(pszOldTs[8], pszOldTs[9]);
+            if (pExpTime->tm_year <= 38)  /* up to 2038, 32-bit time_t style logic. */
+                pExpTime->tm_year += 100;
+        }
+
+        /*
+         * Use mktime to convert to UTC seconds.
+         */
+        pExpTime->tm_isdst = -1;
+        pExpTime->tm_yday  = -1;
+        pExpTime->tm_wday  = -1;
+        pDst->tv_usec = 0;
+        pDst->tv_sec  = mktime(pExpTime);
+        if (pDst->tv_sec != -1)
+            return 0;
+        return touch_error("mktime failed on '%s': %s", pszOldTs, strerror(errno));
+    }
+
+    /* No valid timestamp present. */
+    return -1;
+}
+
+
+/**
+ * Parses the arguments into pOpts.
+ *
+ * @returns exit code.
+ * @param   pOpts               Options structure to return the parsed info in.
+ *                              Caller initalizes this with defaults.
+ * @param   cArgs               The number of arguments.
+ * @param   papszArgs           The arguments.
+ * @param   pfExit              Indicates whether to exit or to start processing
+ *                              files.
+ */
+static int touch_parse_args(PKMKTOUCHOPTS pOpts, int cArgs, char **papszArgs, KBOOL *pfExit)
+{
+    int iAdjustValue = 0;
+    int iArg;
+    int rc;
+
+    *pfExit = K_TRUE;
+    /*
+     * Parse arguments, skipping all files (GNU style).
+     */
+    for (iArg = 1; iArg < cArgs; iArg++)
+    {
+        const char *pszArg = papszArgs[iArg];
+        if (*pszArg == '-')
+        {
+            const char *pszLongValue = NULL;
+            char ch = *++pszArg;
+            pszArg++;
+
+            /*
+             * Deal with long options first, preferably translating them into short ones.
+             */
+            if (ch == '-')
+            {
+                const char *pszLong = pszArg;
+                ch = *pszArg++;
+                if (!ch)
+                {
+                    while (++iArg < cArgs)
+                        pOpts->papszFiles[pOpts->cFiles++] = papszArgs[iArg];
+                    break; /* '--' */
+                }
+
+                /* Translate long options. */
+                pszArg = "";
+                if (strcmp(pszLong, "adjust") == 0)
+                    ch = 'A';
+                else if (strncmp(pszLong, "adjust=", sizeof("adjust=") - 1) == 0)
+                {
+                    ch = 'A';
+                    pszLongValue = pszArg = pszLong + sizeof("adjust=") - 1;
+                }
+                else if (strcmp(pszLong, "no-create") == 0)
+                    ch = 'c';
+                else if (strcmp(pszLong, "date") == 0)
+                    ch = 'd';
+                else if (strncmp(pszLong, "date=", sizeof("date=") - 1) == 0)
+                {
+                    ch = 'd';
+                    pszLongValue = pszArg = pszLong + sizeof("date=") - 1;
+                }
+                else if (strcmp(pszLong, "no-dereference") == 0)
+                    ch = 'h';
+                else if (strcmp(pszLong, "reference") == 0)
+                    ch = 'r';
+                else if (strncmp(pszLong, "reference=", sizeof("reference=") - 1) == 0)
+                {
+                    ch = 'r';
+                    pszLongValue = pszArg = pszLong + sizeof("reference=") - 1;
+                }
+                else if (strcmp(pszLong, "time") == 0)
+                    ch = 'T';
+                else if (strncmp(pszLong, "time=", sizeof("time=") - 1) == 0)
+                {
+                    ch = 'T';
+                    pszLongValue = pszArg = pszLong + sizeof("time=") - 1;
+                }
+                else if (strcmp(pszLong, "help") == 0)
+                    return touch_usage();
+                else if (strcmp(pszLong, "version") == 0)
+                    return kbuild_version(papszArgs[0]);
+                else
+                    return touch_syntax("Unknown option: --%s", pszLong);
+            }
+
+            /*
+             * Process short options.
+             */
+            do
+            {
+                /* Some options takes a value. */
+                const char *pszValue;
+                switch (ch)
+                {
+                    case 'A':
+                    case 'd':
+                    case 'r':
+                    case 't':
+                    case 'T':
+                        if (*pszArg || pszLongValue)
+                        {
+                            pszValue = pszArg;
+                            pszArg = "";
+                        }
+                        else if (iArg + 1 < cArgs)
+                            pszValue = papszArgs[++iArg];
+                        else
+                            return touch_syntax("Option -%c requires a value", ch);
+                        break;
+
+                    default:
+                        pszValue = NULL;
+                        break;
+                }
+
+                switch (ch)
+                {
+                    /* -A [-][[HH]MM]SS */
+                    case 'A':
+                        rc = touch_parse_adjust(pszValue, &iAdjustValue);
+                        if (rc != 0)
+                            return rc;
+                        if (pOpts->enmAction != kTouchActionSet)
+                        {
+                            pOpts->enmAction = kTouchActionAdjust;
+                            pOpts->NewATime.tv_sec  = iAdjustValue;
+                            pOpts->NewATime.tv_usec = 0;
+                            pOpts->NewMTime = pOpts->NewATime;
+                        }
+                        /* else: applied after parsing everything. */
+                        break;
+
+                    case 'a':
+                        pOpts->enmWhatToTouch = kTouchAccessOnly;
+                        break;
+
+                    case 'c':
+                        pOpts->fCreate = K_FALSE;
+                        break;
+
+                    case 'd':
+                        rc = touch_parse_d_ts(pszValue, &pOpts->NewATime);
+                        if (rc != 0)
+                            return rc;
+                        pOpts->enmAction = kTouchActionSet;
+                        pOpts->NewMTime  = pOpts->NewATime;
+                        break;
+
+                    case 'f':
+                        /* some historical thing, ignored. */
+                        break;
+
+                    case 'h':
+                        pOpts->fDereference = K_FALSE;
+                        break;
+
+                    case 'm':
+                        pOpts->enmWhatToTouch = kTouchModifyOnly;
+                        break;
+
+                    case 'r':
+                    {
+                        struct stat St;
+                        if (stat(pszValue, &St) != 0)
+                            return touch_error("Failed to stat '%s' (-r option): %s", pszValue, strerror(errno));
+
+                        pOpts->enmAction = kTouchActionSet;
+                        pOpts->NewATime.tv_sec  = St.st_atime;
+                        pOpts->NewMTime.tv_sec  = St.st_mtime;
+#if FILE_TIMESTAMP_HI_RES
+                        pOpts->NewATime.tv_usec = St.st_atim.tv_nsec / 1000;
+                        pOpts->NewMTime.tv_usec = St.st_mtim.tv_nsec / 1000;
+#else
+                        pOpts->NewATime.tv_usec = 0;
+                        pOpts->NewMTime.tv_usec = 0;
+#endif
+                        break;
+                    }
+
+                    case 't':
+                        rc = touch_parse_ts(pszValue, &pOpts->NewATime);
+                        if (rc != 0)
+                            return rc;
+                        pOpts->enmAction = kTouchActionSet;
+                        pOpts->NewMTime  = pOpts->NewATime;
+                        break;
+
+                    case 'T':
+                        if (   strcmp(pszValue, "atime") == 0
+                            || strcmp(pszValue, "access") == 0)
+                            pOpts->enmWhatToTouch = kTouchAccessOnly;
+                        else if (   strcmp(pszValue, "mtime") == 0
+                                 || strcmp(pszValue, "modify") == 0)
+                            pOpts->enmWhatToTouch = kTouchModifyOnly;
+                        else
+                            return touch_syntax("Unknown --time value: %s", pszValue);
+                        break;
+
+                    case 'V':
+                        return kbuild_version(papszArgs[0]);
+
+                    default:
+                        return touch_syntax("Unknown option: -%c (%c%s)", ch, ch, pszArg);
+                }
+
+            } while ((ch = *pszArg++) != '\0');
+        }
+        else
+            pOpts->papszFiles[pOpts->cFiles++] = papszArgs[iArg];
+    }
+
+    /*
+     * Allow adjusting specified timestamps too like BSD does.
+     */
+    if (   pOpts->enmAction == kTouchActionSet
+        && iAdjustValue != 0)
+    {
+        if (   pOpts->enmWhatToTouch == kTouchAccessAndModify
+            || pOpts->enmWhatToTouch == kTouchAccessOnly)
+            pOpts->NewATime.tv_sec += iAdjustValue;
+        if (   pOpts->enmWhatToTouch == kTouchAccessAndModify
+            || pOpts->enmWhatToTouch == kTouchModifyOnly)
+            pOpts->NewMTime.tv_sec += iAdjustValue;
+    }
+
+    /*
+     * Check for old timestamp: MMDDhhmm[YY]
+     */
+    if (   pOpts->enmAction == kTouchActionCurrent
+        && pOpts->cFiles >= 2)
+    {
+        struct timeval OldTs;
+        rc = touch_parse_old_ts(pOpts->papszFiles[0], pOpts->NewATime.tv_sec, &OldTs);
+        if (rc == 0)
+        {
+            int iFile;
+
+            pOpts->NewATime = OldTs;
+            pOpts->NewMTime = OldTs;
+            pOpts->enmAction = kTouchActionSet;
+
+            for (iFile = 1; iFile < pOpts->cFiles; iFile++)
+                pOpts->papszFiles[iFile - 1] = pOpts->papszFiles[iFile];
+            pOpts->cFiles--;
+        }
+        else if (rc > 0)
+            return rc;
+    }
+
+    /*
+     * Check that we've found at least one file argument.
+     */
+    if (pOpts->cFiles > 0)
+    {
+        *pfExit = K_FALSE;
+        return 0;
+    }
+    return touch_syntax("No file specified");
+}
+
+
+/**
+ * Touches one file.
+ *
+ * @returns exit code.
+ * @param   pOpts               The options.
+ * @param   pszFile             The file to touch.
+ */
+static int touch_process_file(PKMKTOUCHOPTS pOpts, const char *pszFile)
+{
+    int             fd;
+    int             rc;
+    struct stat     St;
+    struct timeval  aTimes[2];
+
+    /*
+     * Create the file if it doesn't exists.  If the --no-create/-c option is
+     * in effect, we silently skip the file if it doesn't already exist.
+     */
+    if (pOpts->fDereference)
+        rc = stat(pszFile, &St);
+    else
+        rc = lstat(pszFile, &St);
+    if (rc != 0)
+    {
+        if (errno != ENOENT)
+            return touch_error("Failed to stat '%s': %s", pszFile, strerror(errno));
+
+        if (!pOpts->fCreate)
+            return 0;
+        fd = open(pszFile, O_WRONLY | O_CREAT, 0666);
+        if (fd == -1)
+            return touch_error("Failed to create '%s': %s", pszFile, strerror(errno));
+
+        /* If we're not setting the current time, we may need value stat info
+           on the file, so get it thru the file descriptor before closing it. */
+        if (pOpts->enmAction == kTouchActionCurrent)
+            rc = 0;
+        else
+            rc = fstat(fd, &St);
+        if (close(fd) != 0)
+            return touch_error("Failed to close '%s' after creation: %s", pszFile, strerror(errno));
+        if (rc != 0)
+            return touch_error("Failed to fstat '%s' after creation: %s", pszFile, strerror(errno));
+
+        /* We're done now if we're setting the current time. */
+        if (pOpts->enmAction == kTouchActionCurrent)
+            return 0;
+    }
+
+    /*
+     * Create aTimes and call utimes/lutimes.
+     */
+    aTimes[0].tv_sec  = St.st_atime;
+    aTimes[1].tv_sec  = St.st_mtime;
+#if FILE_TIMESTAMP_HI_RES
+    aTimes[0].tv_usec = St.st_atim.tv_nsec / 1000;
+    aTimes[1].tv_usec = St.st_mtim.tv_nsec / 1000;
+#else
+    aTimes[0].tv_usec = 0;
+    aTimes[1].tv_usec = 0;
+#endif
+    if (   pOpts->enmWhatToTouch == kTouchAccessAndModify
+        || pOpts->enmWhatToTouch == kTouchAccessOnly)
+    {
+        if (   pOpts->enmAction == kTouchActionCurrent
+            || pOpts->enmAction == kTouchActionSet)
+            aTimes[0] = pOpts->NewATime;
+        else
+            aTimes[0].tv_sec += pOpts->NewATime.tv_sec;
+    }
+    if (   pOpts->enmWhatToTouch == kTouchAccessAndModify
+        || pOpts->enmWhatToTouch == kTouchModifyOnly)
+    {
+        if (   pOpts->enmAction == kTouchActionCurrent
+            || pOpts->enmAction == kTouchActionSet)
+            aTimes[1] = pOpts->NewMTime;
+        else
+            aTimes[1].tv_sec += pOpts->NewMTime.tv_sec;
+    }
+
+    /*
+     * Try set the times.  If we're setting current time, fall back on calling
+     * [l]utimes with a NULL timeval vector since that has slightly different
+     * permissions checks.  (Note that we don't do that by default because it
+     * may do more than what we want (st_ctime).)
+     */
+    if (pOpts->fDereference)
+        rc = utimes(pszFile, aTimes);
+    else
+        rc = lutimes(pszFile, aTimes);
+    if (rc != 0)
+    {
+        if (pOpts->enmAction == kTouchActionCurrent)
+        {
+            if (pOpts->fDereference)
+                rc = utimes(pszFile, NULL);
+            else
+                rc = lutimes(pszFile, NULL);
+        }
+        if (rc != 0)
+            rc = touch_error("%stimes failed on '%s': %s", pOpts->fDereference ? "" : "l", pszFile, strerror(errno));
+    }
+
+    return rc;
+}
+
+
+/**
+ * The function that does almost everything here... ugly.
+ */
+#ifdef KMK
+int kmk_builtin_touch(int argc, char **argv, char **envp)
+#else
+int main(int argc, char **argv, char **envp)
+#endif
+{
+    int             rc;
+    KMKTOUCHOPTS    Opts;
+    K_NOREF(envp);
+
+    /*
+     * Initialize options with defaults and parse them.
+     */
+    Opts.enmWhatToTouch = kTouchAccessAndModify;
+    Opts.enmAction      = kTouchActionCurrent;
+    Opts.fCreate        = K_TRUE;
+    Opts.fDereference   = K_TRUE;
+    Opts.cFiles         = 0;
+    Opts.papszFiles     = (char **)calloc(argc, sizeof(char *));
+    if (Opts.papszFiles)
+    {
+        rc = gettimeofday(&Opts.NewATime, NULL);
+        if (rc == 0)
+        {
+            KBOOL fExit;
+            Opts.NewMTime = Opts.NewATime;
+
+            rc = touch_parse_args(&Opts, argc, argv, &fExit);
+            if (rc == 0 && !fExit)
+            {
+                /*
+                 * Process the files.
+                 */
+                int iFile;
+                for (iFile = 0; iFile < Opts.cFiles; iFile++)
+                {
+                    int rc2 = touch_process_file(&Opts, Opts.papszFiles[iFile]);
+                    if (rc2 != 0 && rc == 0)
+                        rc = rc2;
+                }
+            }
+        }
+        else
+            rc = touch_error("gettimeofday failed: %s", strerror(errno));
+        free(Opts.papszFiles);
+    }
+    else
+        rc = touch_error("calloc failed");
+    return rc;
+}
+
diff --git a/src/kmk/main.c b/src/kmk/main.c
index 7bb2437..2db8638 100644
--- a/src/kmk/main.c
+++ b/src/kmk/main.c
@@ -461,6 +461,8 @@ static const char *const usage[] =
                                 3 = normal / nice 0;\n\
                                 4 = high / nice -10;\n\
                                 5 = realtime / nice -19;\n"),
+    N_("\
+  --nice                      Alias for --priority=1\n"),
 #endif /* KMK */
 #ifdef CONFIG_PRETTY_COMMAND_PRINTING
     N_("\
@@ -534,6 +536,7 @@ static const struct command_switch switches[] =
       (char *) &process_priority, (char *) &process_priority, "priority" },
     { CHAR_MAX+15, positive_int, (char *) &process_affinity, 1, 1, 0,
       (char *) &process_affinity, (char *) &process_affinity, "affinity" },
+    { CHAR_MAX+17, flag, (char *) &process_priority, 1, 1, 0, 0, 0, "nice" },
 #endif
     { 'q', flag, &question_flag, 1, 1, 1, 0, 0, "question" },
     { 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, "no-builtin-rules" },
@@ -855,24 +858,29 @@ static void
 set_make_priority_and_affinity (void)
 {
 # ifdef WINDOWS32
-  DWORD dwPriority;
+  DWORD dwClass, dwPriority;
+
   if (process_affinity)
     if (!SetProcessAffinityMask (GetCurrentProcess (), process_affinity))
-      fprintf (stderr, "warning: SetPriorityClass (,%#x) failed with last error %d\n",
+      fprintf (stderr, "warning: SetProcessAffinityMask (,%#x) failed with last error %d\n",
                process_affinity, GetLastError ());
 
   switch (process_priority)
     {
       case 0:     return;
-      case 1:     dwPriority = IDLE_PRIORITY_CLASS; break;
-      case 2:     dwPriority = BELOW_NORMAL_PRIORITY_CLASS; break;
-      case 3:     dwPriority = NORMAL_PRIORITY_CLASS; break;
-      case 4:     dwPriority = HIGH_PRIORITY_CLASS; break;
-      case 5:     dwPriority = REALTIME_PRIORITY_CLASS; break;
+      case 1:     dwClass = IDLE_PRIORITY_CLASS;         dwPriority = THREAD_PRIORITY_IDLE; break;
+      case 2:     dwClass = BELOW_NORMAL_PRIORITY_CLASS; dwPriority = THREAD_PRIORITY_BELOW_NORMAL; break;
+      case 3:     dwClass = NORMAL_PRIORITY_CLASS;       dwPriority = THREAD_PRIORITY_NORMAL; break;
+      case 4:     dwClass = HIGH_PRIORITY_CLASS;         dwPriority = 0xffffffff; break;
+      case 5:     dwClass = REALTIME_PRIORITY_CLASS;     dwPriority = 0xffffffff; break;
       default:    fatal (NILF, _("invalid priority %d\n"), process_priority);
     }
-  if (!SetPriorityClass (GetCurrentProcess (), dwPriority))
+  if (!SetPriorityClass (GetCurrentProcess (), dwClass))
     fprintf (stderr, "warning: SetPriorityClass (,%#x) failed with last error %d\n",
+             dwClass, GetLastError ());
+  if (dwPriority != 0xffffffff
+      && !SetThreadPriority (GetCurrentThread (), dwPriority))
+    fprintf (stderr, "warning: SetThreadPriority (,%#x) failed with last error %d\n",
              dwPriority, GetLastError ());
 
 #elif defined(__HAIKU__)
diff --git a/src/kmk/misc.c b/src/kmk/misc.c
index a22759b..63782d4 100644
--- a/src/kmk/misc.c
+++ b/src/kmk/misc.c
@@ -368,7 +368,7 @@ error (flocp, fmt, va_alist)
   VA_START (args, fmt);
   cchMsg += cchUser = vsnprintf (&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
   VA_END (args);
-  if (   cchMsg < sizeof(szMsg)
+  if (   cchMsg < (int)sizeof(szMsg)
       && cchUser >= 0)
     {
       extern size_t maybe_con_fwrite(void const *, size_t, size_t, FILE *);
@@ -433,7 +433,7 @@ fatal (flocp, fmt, va_alist)
   VA_START (args, fmt);
   cchMsg += cchUser = vsnprintf (&szMsg[cchMsg], sizeof(szMsg) - cchMsg, fmt, args);
   VA_END (args);
-  if (   cchMsg + cchStop <= sizeof(szMsg)
+  if (   cchMsg + cchStop <= (int)sizeof(szMsg)
       && cchUser >= 0)
     {
       extern size_t maybe_con_fwrite(void const *, size_t, size_t, FILE *);
diff --git a/src/kmk/strcache.c b/src/kmk/strcache.c
index 90dceb6..fb6a767 100644
--- a/src/kmk/strcache.c
+++ b/src/kmk/strcache.c
@@ -259,7 +259,7 @@ void strcache_init (void)
 {
   strcache2_init(&file_strcache,
                  "file",        /* name */
-                 65536,         /* hash size */
+                 131072,        /* hash size */
                  0,             /* default segment size*/
 #ifdef HAVE_CASE_INSENSITIVE_FS
                  1,             /* case insensitive */
diff --git a/src/kmk/strcache2.c b/src/kmk/strcache2.c
index 2f943c8..9da2185 100644
--- a/src/kmk/strcache2.c
+++ b/src/kmk/strcache2.c
@@ -1,4 +1,4 @@
-/* $Id: strcache2.c 2799 2015-09-19 20:36:31Z bird $ */
+/* $Id: strcache2.c 3091 2017-10-04 14:31:04Z bird $ */
 /** @file
  * strcache2 - New string cache.
  */
@@ -92,6 +92,7 @@ typedef signed int     int32_t;
 static struct strcache2 *strcache_head;
 
 
+#ifndef STRCACHE2_USE_MASK
 /** Finds the closest primary number for power of two value (or something else
  *  useful if not support).   */
 MY_INLINE unsigned int strcache2_find_prime(unsigned int shift)
@@ -123,6 +124,7 @@ MY_INLINE unsigned int strcache2_find_prime(unsigned int shift)
           return (1 << shift) - 1;
     }
 }
+#endif
 
 /* The following is a bit experiment. It produces longer chains, i.e. worse
    distribution of the strings in the table, however the actual make
@@ -410,6 +412,7 @@ strcache2_case_insensitive_hash (const char *str, unsigned int len)
   return hash;
 }
 
+#if 0
 MY_INLINE int
 strcache2_memcmp_inline_short (const char *xs, const char *ys, unsigned int length)
 {
@@ -484,6 +487,7 @@ strcache2_memcmp_inline_short (const char *xs, const char *ys, unsigned int leng
   /* memcmp for longer strings */
   return memcmp (xs, ys, length);
 }
+#endif
 
 MY_INLINE int
 strcache2_memcmp_inlined (const char *xs, const char *ys, unsigned int length)
@@ -493,9 +497,11 @@ strcache2_memcmp_inlined (const char *xs, const char *ys, unsigned int length)
 #endif
   if (!((size_t)xs & 3))
     {
-      int result;
       /* aligned */
-      while (length >= 8)
+      int result;
+      unsigned reminder = length & 7;
+      length >>= 3;
+      while (length-- > 0)
         {
           result  = *(int32_t*)xs - *(int32_t*)ys;
           result |= *(int32_t*)(xs + 4) - *(int32_t*)(ys + 4);
@@ -503,9 +509,8 @@ strcache2_memcmp_inlined (const char *xs, const char *ys, unsigned int length)
             return result;
           xs += 8;
           ys += 8;
-          length -= 8;
         }
-      switch (length)
+      switch (reminder)
         {
           case 7:
               result  = *(int32_t*)xs - *(int32_t*)ys;
@@ -544,7 +549,9 @@ strcache2_memcmp_inlined (const char *xs, const char *ys, unsigned int length)
     {
       /* unaligned */
       int result;
-      while (length >= 8)
+      unsigned reminder = length & 7;
+      length >>= 3;
+      while (length-- > 0)
         {
 #if defined(__i386__) || defined(__x86_64__)
           result  = (  ((int32_t)xs[3] << 24)
@@ -571,18 +578,18 @@ strcache2_memcmp_inlined (const char *xs, const char *ys, unsigned int length)
             return result;
           xs += 8;
           ys += 8;
-          length -= 8;
         }
+
       result = 0;
-      switch (length)
+      switch (reminder)
         {
-          case 7: result |= xs[6] - ys[6];
-          case 6: result |= xs[5] - ys[5];
-          case 5: result |= xs[4] - ys[4];
-          case 4: result |= xs[3] - ys[3];
-          case 3: result |= xs[2] - ys[2];
-          case 2: result |= xs[1] - ys[1];
-          case 1: result |= xs[0] - ys[0];
+          case 7: result |= xs[6] - ys[6]; /* fall thru */
+          case 6: result |= xs[5] - ys[5]; /* fall thru */
+          case 5: result |= xs[4] - ys[4]; /* fall thru */
+          case 4: result |= xs[3] - ys[3]; /* fall thru */
+          case 3: result |= xs[2] - ys[2]; /* fall thru */
+          case 2: result |= xs[1] - ys[1]; /* fall thru */
+          case 1: result |= xs[0] - ys[0]; /* fall thru */
               return result;
           default:
           case 0:
@@ -611,6 +618,7 @@ strcache2_is_equal (struct strcache2 *cache, struct strcache2_entry const *entry
 #endif
 }
 
+#if defined(HAVE_CASE_INSENSITIVE_FS)
 MY_INLINE int
 strcache2_is_iequal (struct strcache2 *cache, struct strcache2_entry const *entry,
                      const char *str, unsigned int length, unsigned int hash)
@@ -622,12 +630,13 @@ strcache2_is_iequal (struct strcache2 *cache, struct strcache2_entry const *entr
       || entry->length != length)
       return 0;
 
-#if defined(_MSC_VER) || defined(__OS2__)
+# if defined(_MSC_VER) || defined(__OS2__)
   return _memicmp (entry + 1, str, length) == 0;
-#else
+# else
   return strncasecmp ((const char *)(entry + 1), str, length) == 0;
-#endif
+# endif
 }
+#endif /* HAVE_CASE_INSENSITIVE_FS */
 
 static void
 strcache2_rehash (struct strcache2 *cache)
@@ -914,14 +923,14 @@ strcache2_iadd (struct strcache2 *cache, const char *str, unsigned int length)
   entry = cache->hash_tab[idx];
   if (!entry)
     return strcache2_enter_string (cache, idx, str, length, hash);
-  if (strcache2_is_equal (cache, entry, str, length, hash))
+  if (strcache2_is_iequal (cache, entry, str, length, hash))
     return (const char *)(entry + 1);
   MAKE_STATS (cache->collision_1st_count++);
 
   entry = entry->next;
   if (!entry)
     return strcache2_enter_string (cache, idx, str, length, hash);
-  if (strcache2_is_equal (cache, entry, str, length, hash))
+  if (strcache2_is_iequal (cache, entry, str, length, hash))
     return (const char *)(entry + 1);
   MAKE_STATS (cache->collision_2nd_count++);
 
@@ -931,7 +940,7 @@ strcache2_iadd (struct strcache2 *cache, const char *str, unsigned int length)
       entry = entry->next;
       if (!entry)
         return strcache2_enter_string (cache, idx, str, length, hash);
-      if (strcache2_is_equal (cache, entry, str, length, hash))
+      if (strcache2_is_iequal (cache, entry, str, length, hash))
         return (const char *)(entry + 1);
       MAKE_STATS (cache->collision_3rd_count++);
     }
@@ -963,14 +972,14 @@ strcache2_iadd_hashed (struct strcache2 *cache, const char *str,
   entry = cache->hash_tab[idx];
   if (!entry)
     return strcache2_enter_string (cache, idx, str, length, hash);
-  if (strcache2_is_equal (cache, entry, str, length, hash))
+  if (strcache2_is_iequal (cache, entry, str, length, hash))
     return (const char *)(entry + 1);
   MAKE_STATS (cache->collision_1st_count++);
 
   entry = entry->next;
   if (!entry)
     return strcache2_enter_string (cache, idx, str, length, hash);
-  if (strcache2_is_equal (cache, entry, str, length, hash))
+  if (strcache2_is_iequal (cache, entry, str, length, hash))
     return (const char *)(entry + 1);
   MAKE_STATS (cache->collision_2nd_count++);
 
@@ -980,7 +989,7 @@ strcache2_iadd_hashed (struct strcache2 *cache, const char *str,
       entry = entry->next;
       if (!entry)
         return strcache2_enter_string (cache, idx, str, length, hash);
-      if (strcache2_is_equal (cache, entry, str, length, hash))
+      if (strcache2_is_iequal (cache, entry, str, length, hash))
         return (const char *)(entry + 1);
       MAKE_STATS (cache->collision_3rd_count++);
     }
@@ -1006,14 +1015,14 @@ strcache2_ilookup (struct strcache2 *cache, const char *str, unsigned int length
   entry = cache->hash_tab[idx];
   if (!entry)
     return NULL;
-  if (strcache2_is_equal (cache, entry, str, length, hash))
+  if (strcache2_is_iequal (cache, entry, str, length, hash))
     return (const char *)(entry + 1);
   MAKE_STATS (cache->collision_1st_count++);
 
   entry = entry->next;
   if (!entry)
     return NULL;
-  if (strcache2_is_equal (cache, entry, str, length, hash))
+  if (strcache2_is_iequal (cache, entry, str, length, hash))
     return (const char *)(entry + 1);
   MAKE_STATS (cache->collision_2nd_count++);
 
@@ -1023,7 +1032,7 @@ strcache2_ilookup (struct strcache2 *cache, const char *str, unsigned int length
       entry = entry->next;
       if (!entry)
         return NULL;
-      if (strcache2_is_equal (cache, entry, str, length, hash))
+      if (strcache2_is_iequal (cache, entry, str, length, hash))
         return (const char *)(entry + 1);
       MAKE_STATS (cache->collision_3rd_count++);
     }
diff --git a/src/kmk/variable.c b/src/kmk/variable.c
index 5e85e83..eb32468 100644
--- a/src/kmk/variable.c
+++ b/src/kmk/variable.c
@@ -246,7 +246,7 @@ init_hash_global_variable_set (void)
   hash_init (&global_variable_set.table, VARIABLE_BUCKETS,
 	     variable_hash_1, variable_hash_2, variable_hash_cmp);
 #else  /* CONFIG_WITH_STRCACHE2 */
-  strcache2_init (&variable_strcache, "variable", 65536, 0, 0, 0);
+  strcache2_init (&variable_strcache, "variable", 262144, 0, 0, 0);
   hash_init_strcached (&global_variable_set.table, VARIABLE_BUCKETS,
                        &variable_strcache, offsetof (struct variable, name));
 #endif /* CONFIG_WITH_STRCACHE2 */
diff --git a/src/kmk/variable.h b/src/kmk/variable.h
index 3238108..5f3ea89 100644
--- a/src/kmk/variable.h
+++ b/src/kmk/variable.h
@@ -223,10 +223,10 @@ variable_buffer_output (char *ptr, const char *string, unsigned int length)
 # ifndef _MSC_VER
   switch (length)
     {
-      case 4: ptr[3] = string[3];
-      case 3: ptr[2] = string[2];
-      case 2: ptr[1] = string[1];
-      case 1: ptr[0] = string[0];
+      case 4: ptr[3] = string[3]; /* fall thru */
+      case 3: ptr[2] = string[2]; /* fall thru */
+      case 2: ptr[1] = string[1]; /* fall thru */
+      case 1: ptr[0] = string[0]; /* fall thru */
       case 0:
           break;
       default:
diff --git a/src/kmk/w32/pathstuff.c b/src/kmk/w32/pathstuff.c
index 1a5c7e0..80dd97b 100644
--- a/src/kmk/w32/pathstuff.c
+++ b/src/kmk/w32/pathstuff.c
@@ -15,7 +15,6 @@ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 You should have received a copy of the GNU General Public License along with
 this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#include <Windows.h> /* bird */
 #include "make.h"
 #include <string.h>
 #include <stdlib.h>
diff --git a/src/kmk/w32/subproc/sub_proc.c b/src/kmk/w32/subproc/sub_proc.c
index f2e9b49..ff5c8e1 100644
--- a/src/kmk/w32/subproc/sub_proc.c
+++ b/src/kmk/w32/subproc/sub_proc.c
@@ -547,6 +547,7 @@ process_begin(
 	char *envblk=NULL;
 #ifdef KMK
         size_t exec_path_len;
+	extern int process_priority;
 
 	assert (pproc->enmType == kRegular);
 #endif
@@ -715,6 +716,14 @@ process_begin(
 			kmk_cache_exec_image(exec_path);
 		else if (argv[0])
 			kmk_cache_exec_image(argv[0]);
+
+		switch (process_priority) {
+		case 1: flags |= CREATE_SUSPENDED | IDLE_PRIORITY_CLASS; break;
+		case 2: flags |= CREATE_SUSPENDED | BELOW_NORMAL_PRIORITY_CLASS; break;
+		case 3: flags |= CREATE_SUSPENDED | NORMAL_PRIORITY_CLASS; break;
+		case 4: flags |= CREATE_SUSPENDED | HIGH_PRIORITY_CLASS; break;
+		case 5: flags |= CREATE_SUSPENDED | REALTIME_PRIORITY_CLASS; break;
+		}
 #endif
 		if (CreateProcess(
 			exec_path,
@@ -740,6 +749,16 @@ process_begin(
 			free( command_line );
 			return(-1);
 		}
+#ifdef KMK
+		switch (process_priority) {
+		case 1: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_IDLE); break;
+		case 2: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_BELOW_NORMAL); break;
+		case 3: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_NORMAL); break;
+		case 4: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_HIGHEST); break;
+		case 5: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_TIME_CRITICAL); break;
+		}
+		ResumeThread(procInfo.hThread);
+#endif
 	}
 
 	pproc->pid = (pid_t)procInfo.hProcess;
diff --git a/src/lib/Makefile.kmk b/src/lib/Makefile.kmk
index 0cd8307..b3f5a67 100644
--- a/src/lib/Makefile.kmk
+++ b/src/lib/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2994 2016-11-01 22:41:41Z bird $
+# $Id: Makefile.kmk 3060 2017-09-21 15:11:07Z bird $
 ## @file
 # Sub-makefile for various libraries and stuff.
 #
@@ -52,6 +52,7 @@ kUtil_SOURCES.win = \
        nt/ntdir.c \
        nt/ntstat.c \
        nt/ntunlink.c \
+       nt/ntutimes.c \
        nt/fts-nt.c \
        nt/kFsCache.c \
        kStuff/kHlp/CRT/kHlpCRTString.cpp \
diff --git a/src/lib/kDep.c b/src/lib/kDep.c
index 186c20c..caa63bd 100644
--- a/src/lib/kDep.c
+++ b/src/lib/kDep.c
@@ -1,4 +1,4 @@
-/* $Id: kDep.c 2955 2016-09-21 19:05:53Z bird $ */
+/* $Id: kDep.c 3063 2017-09-30 11:34:07Z bird $ */
 /** @file
  * kDep - Common Dependency Managemnt Code.
  */
@@ -129,7 +129,7 @@ static void fixcase(char *pszFilename)
          * Find the next slash (or end of string) and terminate the string there.
          */
         while (*psz != '/' && *psz)
-            *psz++;
+            psz++;
         chSlash = *psz;
         *psz = '\0';
 
diff --git a/src/lib/kStuff/include/k/kDefs.h b/src/lib/kStuff/include/k/kDefs.h
index f805cc3..9730fbc 100644
--- a/src/lib/kStuff/include/k/kDefs.h
+++ b/src/lib/kStuff/include/k/kDefs.h
@@ -1,10 +1,10 @@
-/* $Id: kDefs.h 84 2016-09-04 13:54:11Z bird $ */
+/* $Id: kDefs.h 100 2017-10-01 13:08:49Z bird $ */
 /** @file
  * kTypes - Defines and Macros.
  */
 
 /*
- * Copyright (c) 2006-2008 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
+ * Copyright (c) 2006-2017 Knut St. Osmundsen <bird-kStuff-spamix at anduin.net>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -46,22 +46,26 @@
 #define K_OS_DRAGONFLY  2
 /** FreeBSD. */
 #define K_OS_FREEBSD    3
+/** GNU/kFreeBSD. */
+#define K_OS_GNU_KFBSD  4
+/** GNU/kNetBSD or GNU/NetBSD or whatever the decide to call it. */
+#define K_OS_GNU_KNBSD  5
 /** Linux. */
-#define K_OS_LINUX      4
+#define K_OS_LINUX      6
 /** NetBSD. */
-#define K_OS_NETBSD     5
+#define K_OS_NETBSD     7
 /** NT (native). */
-#define K_OS_NT         6
+#define K_OS_NT         8
 /** OpenBSD*/
-#define K_OS_OPENBSD    7
+#define K_OS_OPENBSD    9
 /** OS/2 */
-#define K_OS_OS2        8
+#define K_OS_OS2        10
 /** Solaris */
-#define K_OS_SOLARIS    9
+#define K_OS_SOLARIS    11
 /** Windows. */
-#define K_OS_WINDOWS    10
+#define K_OS_WINDOWS    12
 /** The max K_OS_* value (exclusive). */
-#define K_OS_MAX        11
+#define K_OS_MAX        13
 /** @} */
 
 /** @def K_OS
@@ -80,12 +84,16 @@
 #  define K_OS      K_OS_DARWIN
 # elif defined(__DragonFly__)
 #  define K_OS      K_OS_DRAGONFLY
-# elif defined(__FreeBSD__) /*??*/
+# elif defined(__FreeBSD__)
 #  define K_OS      K_OS_FREEBSD
+# elif defined(__FreeBSD_kernel__)
+#  define K_OS      K_OS_GNU_KFBSD
 # elif defined(__gnu_linux__)
 #  define K_OS      K_OS_LINUX
 # elif defined(__NetBSD__) /*??*/
 #  define K_OS      K_OS_NETBSD
+# elif defined(__NetBSD_kernel__)
+#  define K_OS      K_OS_GNU_KNBSD
 # elif defined(__OpenBSD__) /*??*/
 #  define K_OS      K_OS_OPENBSD
 # elif defined(__OS2__)
@@ -162,12 +170,16 @@
 #define K_ARCH_S390_32          (15 | K_ARCH_BIT_32 | K_ARCH_END_BIG)
 /** 64-bit S390. */
 #define K_ARCH_S390_64          (16 | K_ARCH_BIT_64 | K_ARCH_END_BIG)
+/** 32-bit SuperH. */
+#define K_ARCH_SH_32            (17 | K_ARCH_BIT_32 | K_ARCH_END_BI)
+/** 64-bit SuperH. */
+#define K_ARCH_SH_64            (17 | K_ARCH_BIT_64 | K_ARCH_END_BI)
 /** 32-bit SPARC. */
-#define K_ARCH_SPARC_32         (17 | K_ARCH_BIT_32 | K_ARCH_END_BIG)
+#define K_ARCH_SPARC_32         (18 | K_ARCH_BIT_32 | K_ARCH_END_BIG)
 /** 64-bit SPARC. */
-#define K_ARCH_SPARC_64         (18 | K_ARCH_BIT_64 | K_ARCH_END_BI)
+#define K_ARCH_SPARC_64         (19 | K_ARCH_BIT_64 | K_ARCH_END_BI)
 /** The end of the valid architecture values (exclusive). */
-#define K_ARCH_MAX              (19)
+#define K_ARCH_MAX              (20)
 /** @} */
 
 
@@ -186,6 +198,8 @@
 #  define K_ARCH    K_ARCH_ALPHA
 # elif defined(__arm__) || defined(__arm32__)
 #  define K_ARCH    K_ARCH_ARM_32
+# elif defined(__aarch64__) || defined(__arm64__)
+#  define K_ARCH    K_ARCH_ARM_64
 # elif defined(__hppa__) && defined(__LP64__)
 #  define K_ARCH    K_ARCH_PARISC_64
 # elif defined(__hppa__)
@@ -206,6 +220,16 @@
 #  define K_ARCH    K_ARCH_S390_64
 # elif defined(__s390__)
 #  define K_ARCH    K_ARCH_S390_32
+# elif defined(__sh__)
+#  if !defined(__SH5__)
+#   define K_ARCH    K_ARCH_SH_32
+#  else
+#   if __SH5__ == 64
+#    define K_ARCH   K_ARCH_SH_64
+#   else
+#    define K_ARCH   K_ARCH_SH_32
+#   endif
+#  endif
 # else
 #  error "Port Me"
 # endif
@@ -300,6 +324,14 @@
   /* use K_ARCH if possible. */
 # if K_ARCH_ENDIAN != K_ENDIAN_BI
 #  define K_ENDIAN K_ARCH_ENDIAN
+# elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__)
+#  if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  define K_ENDIAN K_ARCH_LITTLE
+#  elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  define K_ENDIAN K_ARCH_BIG
+#  else
+#   error "Port Me or define K_ENDIAN."
+#  endif
 # else
 #  error "Port Me or define K_ENDIAN."
 # endif
diff --git a/src/lib/kStuff/include/k/kHlpAssert.h b/src/lib/kStuff/include/k/kHlpAssert.h
index aac38be..061f425 100644
--- a/src/lib/kStuff/include/k/kHlpAssert.h
+++ b/src/lib/kStuff/include/k/kHlpAssert.h
@@ -1,4 +1,4 @@
-/* $Id: kHlpAssert.h 93 2016-09-15 11:53:59Z bird $ */
+/* $Id: kHlpAssert.h 101 2017-10-02 10:37:39Z bird $ */
 /** @file
  * kHlpAssert - Assertion Macros.
  */
@@ -196,7 +196,103 @@ extern "C" {
         } \
     } while (0)
 
+/* Same as above, only no expression. */
+
+# define kHlpAssertFailed() \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertBreakpoint(); \
+    } while (0)
+
+# define kHlpAssertFailedStmt(stmt) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertBreakpoint(); \
+        stmt; \
+    } while (0)
+
+# define kHlpAssertFailedReturn(rcRet) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertBreakpoint(); \
+        return (rcRet); \
+    } while (0)
+
+# define kHlpAssertFailedStmtReturn(stmt, rcRet) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertBreakpoint(); \
+        stmt; \
+        return (rcRet); \
+    } while (0)
+
+# define kHlpAssertFailedReturnVoid() \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertBreakpoint(); \
+        return; \
+    } while (0)
+
+# define kHlpAssertFailedStmtReturnVoid(stmt) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertBreakpoint(); \
+        stmt; \
+        return; \
+    } while (0)
+
+# define kHlpAssertMsgFailed(msg) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertMsg2 msg; \
+        kHlpAssertBreakpoint(); \
+    } while (0)
+
+# define kHlpAssertMsgFailedStmt(msg, stmt) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertMsg2 msg; \
+        kHlpAssertBreakpoint(); \
+        stmt; \
+    } while (0)
+
+# define kHlpAssertMsgFailedReturn(msg, rcRet) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertMsg2 msg; \
+        kHlpAssertBreakpoint(); \
+        return (rcRet); \
+    } while (0)
+
+# define kHlpAssertMsgFailedStmtReturn(msg, stmt, rcRet) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertMsg2 msg; \
+        kHlpAssertBreakpoint(); \
+        stmt; \
+        return (rcRet); \
+    } while (0)
+
+# define kHlpAssertMsgFailedReturnVoid(msg) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertMsg2 msg; \
+        kHlpAssertBreakpoint(); \
+        return; \
+    } while (0)
+
+# define kHlpAssertMsgFailedStmtReturnVoid(msg, stmt) \
+    do { \
+        kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \
+        kHlpAssertMsg2 msg; \
+        kHlpAssertBreakpoint(); \
+        stmt; \
+        return; \
+    } while (0)
+
+
 #else   /* !K_STRICT */
+
 # define kHlpAssert(expr)                                   do { } while (0)
 # define kHlpAssertStmt(expr, stmt)                         do { if (!(expr)) { stmt; }  } while (0)
 # define kHlpAssertReturn(expr, rcRet)                      do { if (!(expr)) return (rcRet); } while (0)
@@ -209,6 +305,20 @@ extern "C" {
 # define kHlpAssertMsgStmtReturn(expr, msg, stmt, rcRet)    do { if (!(expr)) { stmt; return (rcRet); } } while (0)
 # define kHlpAssertMsgReturnVoid(expr, msg)                 do { if (!(expr)) return; } while (0)
 # define kHlpAssertMsgStmtReturnVoid(expr, msg, stmt)       do { if (!(expr)) { stmt; return; } } while (0)
+/* Same as above, only no expression: */
+# define kHlpAssertFailed()                                 do { } while (0)
+# define kHlpAssertFailedStmt(stmt)                         do { stmt; } while (0)
+# define kHlpAssertFailedReturn(rcRet)                      do { return (rcRet); } while (0)
+# define kHlpAssertFailedStmtReturn(stmt, rcRet)            do { stmt; return (rcRet);  } while (0)
+# define kHlpAssertFailedReturnVoid()                       do { return; } while (0)
+# define kHlpAssertFailedStmtReturnVoid(stmt)               do { stmt; return; }  while (0)
+# define kHlpAssertMsgFailed(msg)                           do { } while (0)
+# define kHlpAssertMsgFailedStmt(msg, stmt)                 do { stmt; } while (0)
+# define kHlpAssertMsgFailedReturn(msg, rcRet)              do { return (rcRet); } while (0)
+# define kHlpAssertMsgFailedStmtReturn(msg, stmt, rcRet)    do { { stmt; return (rcRet); } } while (0)
+# define kHlpAssertMsgFailedReturnVoid(msg)                 do { return; } while (0)
+# define kHlpAssertMsgFailedStmtReturnVoid(msg, stmt)       do { stmt; return; } while (0)
+
 #endif  /* !K_STRICT */
 
 #define kHlpAssertPtr(ptr)                      kHlpAssertMsg(K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr)))
@@ -221,18 +331,7 @@ extern "C" {
 #define kHlpAssertRC(rc)                        kHlpAssertMsg((rc) == 0, ("%s = %d\n", #rc, (rc)))
 #define kHlpAssertRCReturn(rc, rcRet)           kHlpAssertMsgReturn((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)), (rcRet))
 #define kHlpAssertRCReturnVoid(rc)              kHlpAssertMsgReturnVoid((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)))
-#define kHlpAssertFailed()                              kHlpAssert(0)
-#define kHlpAssertFailedStmt(stmt)                      kHlpAssertStmt(0, stmt)
-#define kHlpAssertFailedReturn(rcRet)                   kHlpAssertReturn(0, (rcRet))
-#define kHlpAssertFailedStmtReturn(stmt, rcRet)         kHlpAssertStmtReturn(0, stmt, (rcRet))
-#define kHlpAssertFailedReturnVoid()                    kHlpAssertReturnVoid(0)
-#define kHlpAssertFailedStmtReturnVoid(stmt)            kHlpAssertStmtReturnVoid(0, stmt)
-#define kHlpAssertMsgFailed(msg)                        kHlpAssertMsg(0, msg)
-#define kHlpAssertMsgFailedStmt(msg, stmt)              kHlpAssertMsgStmt(0, msg, stmt)
-#define kHlpAssertMsgFailedReturn(msg, rcRet)           kHlpAssertMsgReturn(0, msg, (rcRet))
-#define kHlpAssertMsgFailedStmtReturn(msg, stmt, rcRet) kHlpAssertMsgStmtReturn(0, msg, stmt, (rcRet))
-#define kHlpAssertMsgFailedReturnVoid(msg)              kHlpAssertMsgReturnVoid(0, msg)
-#define kHlpAssertMsgFailedStmtReturnVoid(msg, stmt)    kHlpAssertMsgStmtReturnVoid(0, msg, stmt)
+
 
 /**
  * Helper function that displays the first part of the assertion message.
diff --git a/src/lib/kStuff/kLdr/kLdrModLX.c b/src/lib/kStuff/kLdr/kLdrModLX.c
index 8af1421..f7d11c8 100644
--- a/src/lib/kStuff/kLdr/kLdrModLX.c
+++ b/src/lib/kStuff/kLdr/kLdrModLX.c
@@ -1,4 +1,4 @@
-/* $Id: kLdrModLX.c 87 2016-09-07 13:09:12Z bird $ */
+/* $Id: kLdrModLX.c 102 2017-10-02 10:45:31Z bird $ */
 /** @file
  * kLdr - The Module Interpreter for the Linear eXecutable (LX) Format.
  */
@@ -1486,6 +1486,7 @@ static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits)
 
                 case RANGE:
                     KLDRMODLX_ASSERT(!"RANGE");
+                    /* Falls through. */
                 default:
                     rc = KLDR_ERR_LX_BAD_PAGE_MAP;
                     break;
@@ -1522,7 +1523,7 @@ static int kldrModLXDoIterDataUnpacking(KU8 *pbDst, const KU8 *pbSrc, int cbSrc)
     int                     cbDst = OBJPAGELEN;
 
     /* Validate size of data. */
-    if (cbSrc >= OBJPAGELEN - 2)
+    if (cbSrc >= (int)OBJPAGELEN - 2)
         return KLDR_ERR_LX_BAD_ITERDATA;
 
     /*
@@ -2443,6 +2444,7 @@ static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAd
 
                     case NRRENT:
                         KLDRMODLX_ASSERT(!"NRRENT");
+                        /* Falls through. */
                     default:
                         iSelector = -1;
                         break;
@@ -2474,11 +2476,11 @@ static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAd
                     /* common / simple */
                     if (    (u.prlc->nr_stype & NRSRCMASK) == NROFF32
                         &&  off >= 0
-                        &&  off <= OBJPAGELEN - 4)
+                        &&  off <= (int)OBJPAGELEN - 4)
                         *(KU32 *)&pbPage[off] = (KU32)uValue;
                     else if (    (u.prlc->nr_stype & NRSRCMASK) == NRSOFF32
                             &&  off >= 0
-                            &&  off <= OBJPAGELEN - 4)
+                            &&  off <= (int)OBJPAGELEN - 4)
                         *(KU32 *)&pbPage[off] = (KU32)(uValue - (PageAddress + off + 4));
                     else
                     {
@@ -2499,7 +2501,7 @@ static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAd
                         while (c-- > 0)
                         {
                             int off = *poffSrc++;
-                            if (off >= 0 && off <= OBJPAGELEN - 4)
+                            if (off >= 0 && off <= (int)OBJPAGELEN - 4)
                                 *(KU32 *)&pbPage[off] = (KU32)uValue;
                             else
                             {
@@ -2514,7 +2516,7 @@ static int kldrModLXRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAd
                         while (c-- > 0)
                         {
                             int off = *poffSrc++;
-                            if (off >= 0 && off <= OBJPAGELEN - 4)
+                            if (off >= 0 && off <= (int)OBJPAGELEN - 4)
                                 *(KU32 *)&pbPage[off] = (KU32)(uValue - (PageAddress + off + 4));
                             else
                             {
@@ -2647,7 +2649,7 @@ static int kldrModLXDoReloc(KU8 *pbPage, int off, KLDRADDR PageAddress, const st
     pbDst = pbPage + off;
     while (cb-- > 0)
     {
-        if (off > OBJPAGELEN)
+        if (off > (int)OBJPAGELEN)
             break;
         if (off >= 0)
             *pbDst = *pbSrc;
diff --git a/src/lib/kStuff/kLdr/kLdrModMachO.c b/src/lib/kStuff/kLdr/kLdrModMachO.c
index 6a11d30..48f2a9f 100644
--- a/src/lib/kStuff/kLdr/kLdrModMachO.c
+++ b/src/lib/kStuff/kLdr/kLdrModMachO.c
@@ -1,4 +1,4 @@
-/* $Id: kLdrModMachO.c 91 2016-09-07 14:29:58Z bird $ */
+/* $Id: kLdrModMachO.c 102 2017-10-02 10:45:31Z bird $ */
 /** @file
  * kLdr - The Module Interpreter for the MACH-O format.
  */
@@ -749,6 +749,7 @@ static int  kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea
                                 /** @todo this requires a query API or flag... (e.g. C++ constructors) */ \
                                 KLDRMODMACHO_CHECK_RETURN(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO, \
                                                           KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION); \
+                                /* Falls through. */ \
                             case S_MOD_TERM_FUNC_POINTERS: \
                                 /** @todo this requires a query API or flag... (e.g. C++ destructors) */ \
                                 KLDRMODMACHO_CHECK_RETURN(fOpenFlags & KLDRMOD_OPEN_FLAGS_FOR_INFO, \
@@ -852,7 +853,7 @@ static int  kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_hea
                                     if (cSegments == 1) /* The link address is set by the first segment. */  \
                                         *pLinkAddress = pSect->addr; \
                                 } \
-                                /* fall thru */ \
+                                /* Falls through. */ \
                             case MH_EXECUTE: \
                             case MH_DYLIB: \
                             case MH_BUNDLE: \
@@ -1854,7 +1855,7 @@ static int kldrModMachODoQuerySymbol32Bit(PKLDRMODMACHO pModMachO, const macho_n
         case MACHO_N_INDR:
             /** @todo implement indirect and prebound symbols. */
         default:
-            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+            KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
     }
 
     return 0;
@@ -1982,7 +1983,7 @@ static int kldrModMachODoQuerySymbol64Bit(PKLDRMODMACHO pModMachO, const macho_n
         case MACHO_N_INDR:
             /** @todo implement indirect and prebound symbols. */
         default:
-            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+            KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
     }
 
     return 0;
@@ -2029,7 +2030,7 @@ static int kldrModMachOEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR B
         }
     }
     else
-        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+        KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
 
     return rc;
 }
@@ -2133,7 +2134,7 @@ static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_n
             case MACHO_N_INDR:
                 /** @todo implement indirect and prebound symbols. */
             default:
-                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
         }
 
         /*
@@ -2245,7 +2246,7 @@ static int kldrModMachODoEnumSymbols64Bit(PKLDRMODMACHO pModMachO, const macho_n
             case MACHO_N_INDR:
                 /** @todo implement indirect and prebound symbols. */
             default:
-                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
         }
 
         /*
@@ -2774,7 +2775,7 @@ static int  kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KL
                                                    (macho_nlist_64_t *)pModMachO->pvaSymbols,
                                                    pModMachO->cSymbols, NewBaseAddress);
             else
-                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
             if (rc)
                 break;
         }
@@ -2887,9 +2888,9 @@ static int  kldrModMachOFixupSectionGeneric32Bit(PKLDRMODMACHO pModMachO, KU8 *p
 
                     case MACHO_N_INDR:
                     case MACHO_N_PBUD:
-                        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                        KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
                     default:
-                        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                        KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_SYMBOL);
                 }
             }
             else if (Fixup.r.r_symbolnum != R_ABS)
@@ -3053,7 +3054,7 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
             case 2: SymAddr = *uFixVirgin.pi32; break;
             case 3: SymAddr = *uFixVirgin.pi64; break;
             default:
-                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_BAD_FIXUP);
         }
 
         /* Add symbol / section address. */
@@ -3079,9 +3080,9 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
                             break;
                         case MACHO_N_INDR:
                         case MACHO_N_PBUD:
-                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                            KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
                         default:
-                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                            KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_SYMBOL);
                     }
                     SymAddr = sizeof(KU64) * Fixup.r.r_symbolnum + pModMachO->GotRVA + NewBaseAddress;
                     KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_length == 2, KLDR_ERR_BAD_FIXUP);
@@ -3095,6 +3096,7 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
                 case X86_64_RELOC_SIGNED_2:
                 case X86_64_RELOC_SIGNED_4:
                     KLDRMODMACHO_CHECK_RETURN(Fixup.r.r_pcrel, KLDR_ERR_BAD_FIXUP);
+                    /* Falls through. */
                 default:
                 {
                     /* Adjust with fixup specific addend and vierfy unsigned/r_pcrel. */
@@ -3114,7 +3116,7 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
                             SymAddr -= 4;
                             break;
                         default:
-                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+                            KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_BAD_FIXUP);
                     }
 
                     switch (pSym->n_type & MACHO_N_TYPE)
@@ -3146,9 +3148,9 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
 
                         case MACHO_N_INDR:
                         case MACHO_N_PBUD:
-                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                            KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
                         default:
-                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                            KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_SYMBOL);
                     }
                     break;
                 }
@@ -3179,9 +3181,9 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
 
                         case MACHO_N_INDR:
                         case MACHO_N_PBUD:
-                            KLDRMODMACHO_CHECK_RETURN(0,KLDR_ERR_TODO);
+                            KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
                         default:
-                            KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                            KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_SYMBOL);
                     }
 
                     /* Load the 2nd fixup, check sanity. */
@@ -3220,9 +3222,9 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
 
                             case MACHO_N_INDR:
                             case MACHO_N_PBUD:
-                                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
                             default:
-                                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_MACHO_BAD_SYMBOL);
+                                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_SYMBOL);
                         }
                     }
                     else if (Fixup2.r_symbolnum != R_ABS)
@@ -3233,7 +3235,7 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
                         SymAddr += pSymSect->RVA + NewBaseAddress;
                     }
                     else
-                        KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+                        KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_BAD_FIXUP);
                 }
                 break;
             }
@@ -3260,7 +3262,7 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
                 /*case X86_64_RELOC_GOT: */
                 /*case X86_64_RELOC_SUBTRACTOR: - must be r_extern=1 says as. */
                 default:
-                    KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_BAD_FIXUP);
             }
             if (Fixup.r.r_symbolnum != R_ABS)
             {
@@ -3293,7 +3295,7 @@ static int  kldrModMachOFixupSectionAMD64(PKLDRMODMACHO pModMachO, KU8 *pbSectBi
                 *uFix.pu32 = (KU32)SymAddr;
                 break;
             default:
-                KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_BAD_FIXUP);
+                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_BAD_FIXUP);
         }
     }
 
@@ -3671,7 +3673,7 @@ static int kldrModMachOMakeGOT(PKLDRMODMACHO pModMachO, void *pvBits, KLDRADDR N
                 }
 
                 default:
-                    KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO);
+                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_TODO);
             }
         }
     }
diff --git a/src/lib/maybe_con_write.c b/src/lib/maybe_con_write.c
index 0b28a42..0ddea09 100644
--- a/src/lib/maybe_con_write.c
+++ b/src/lib/maybe_con_write.c
@@ -1,4 +1,4 @@
-/* $Id: maybe_con_write.c 2900 2016-09-09 14:42:06Z bird $ */
+/* $Id: maybe_con_write.c 3065 2017-09-30 12:52:35Z bird $ */
 /** @file
  * maybe_con_write - Optimized console output on windows.
  */
@@ -97,7 +97,7 @@ ssize_t maybe_con_write(int fd, void *pvBuf, size_t cbToWrite)
      * Semi regular write handling.
      */
     cbWritten = write(fd, pvBuf, (to_write_t)cbToWrite);
-    if (cbWritten == cbToWrite)
+    if (cbWritten == (ssize_t)cbToWrite)
     { /* likely */ }
     else if (cbWritten >= 0 || errno == EINTR)
     {
diff --git a/src/lib/md5.c b/src/lib/md5.c
index e9d9474..3f17d3a 100644
--- a/src/lib/md5.c
+++ b/src/lib/md5.c
@@ -144,7 +144,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
     MD5Transform(ctx->buf, (uint32 *) ctx->in);
     byteReverse((unsigned char *) ctx->buf, 4);
     memcpy(digest, ctx->buf, 16);
-    memset(ctx, 0, sizeof(ctx));        /* In case it's sensitive */
+    memset(ctx, 0, sizeof(*ctx));       /* In case it's sensitive */
 }
 
 
diff --git a/src/lib/nt/kFsCache.c b/src/lib/nt/kFsCache.c
index 59fa467..763a383 100644
--- a/src/lib/nt/kFsCache.c
+++ b/src/lib/nt/kFsCache.c
@@ -1,4 +1,4 @@
-/* $Id: kFsCache.c 3007 2016-11-06 16:46:43Z bird $ */
+/* $Id: kFsCache.c 3082 2017-10-02 19:23:17Z bird $ */
 /** @file
  * ntdircache.c - NT directory content cache.
  */
@@ -2747,8 +2747,8 @@ static PKFSOBJ kFsCacheLookupUncShareW(PKFSCACHE pCache, const wchar_t *pwszPath
  * @param   penmError           Where to return details as to why the lookup
  *                              failed.
  * @param   ppLastAncestor      Where to return the last parent element found
- *                              (referenced) in case of error an path/file not
- *                              found problem.  Optional.
+ *                              (referenced) in case of error like an path/file
+ *                              not found problem.  Optional.
  */
 PKFSOBJ kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const char *pszPath, KU32 cchPath, KU32 fFlags,
                                      KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
@@ -2794,7 +2794,11 @@ PKFSOBJ kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const ch
                  || kFsCachePopuplateOrRefreshDir(pCache, pParent, penmError))
         { /* likely */ }
         else
+        {
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
+        }
 
         /*
          * Search the current node for the name.
@@ -2835,7 +2839,11 @@ PKFSOBJ kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const ch
                 || kFsCacheRefreshMissing(pCache, pChild, penmError) )
             { /* likely */ }
             else
+            {
+                if (ppLastAncestor)
+                    *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
                 return NULL;
+            }
             return kFsCacheObjRetainInternal(pChild);
         }
 
@@ -2871,8 +2879,8 @@ PKFSOBJ kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const ch
         }
     }
 
+    /* not reached */
     return NULL;
-
 }
 
 
@@ -2893,8 +2901,8 @@ PKFSOBJ kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const ch
  * @param   penmError           Where to return details as to why the lookup
  *                              failed.
  * @param   ppLastAncestor      Where to return the last parent element found
- *                              (referenced) in case of error an path/file not
- *                              found problem.  Optional.
+ *                              (referenced) in case of error like an path/file
+ *                              not found problem.  Optional.
  */
 PKFSOBJ kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwszPath, KU32 cwcPath, KU32 fFlags,
                                      KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
@@ -2940,7 +2948,11 @@ PKFSOBJ kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wc
                  || kFsCachePopuplateOrRefreshDir(pCache, pParent, penmError))
         { /* likely */ }
         else
+        {
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
+        }
 
         /*
          * Search the current node for the name.
@@ -2981,7 +2993,11 @@ PKFSOBJ kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wc
                 || kFsCacheRefreshMissing(pCache, pChild, penmError) )
             { /* likely */ }
             else
+            {
+                if (ppLastAncestor)
+                    *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
                 return NULL;
+            }
             return kFsCacheObjRetainInternal(pChild);
         }
 
@@ -3019,7 +3035,6 @@ PKFSOBJ kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wc
     }
 
     return NULL;
-
 }
 
 /**
@@ -3096,6 +3111,8 @@ static PKFSOBJ kFsCacheLookupAbsoluteA(PKFSCACHE pCache, const char *pszPath, KU
             || (fFlags & KFSCACHE_LOOKUP_F_NO_REFRESH)
             || kFsCacheRefreshObj(pCache, pRoot, penmError))
             return kFsCacheObjRetainInternal(pRoot);
+        if (ppLastAncestor)
+            *ppLastAncestor = kFsCacheObjRetainInternal(pRoot);
         return NULL;
     }
 
@@ -3195,6 +3212,8 @@ static PKFSOBJ kFsCacheLookupAbsoluteW(PKFSCACHE pCache, const wchar_t *pwszPath
             || (fFlags & KFSCACHE_LOOKUP_F_NO_REFRESH)
             || kFsCacheRefreshObj(pCache, pRoot, penmError))
             return kFsCacheObjRetainInternal(pRoot);
+        if (ppLastAncestor)
+            *ppLastAncestor = kFsCacheObjRetainInternal(pRoot);
         return NULL;
     }
 
@@ -3513,7 +3532,7 @@ static PKFSOBJ kFsCacheLookupHashedA(PKFSCACHE pCache, const char *pchPath, KU32
                 && *penmError != KFSLOOKUPERROR_PATH_TOO_LONG)
             || *penmError == KFSLOOKUPERROR_UNSUPPORTED )
             kFsCacheCreatePathHashTabEntryA(pCache, pFsObj, pchPath, cchPath, uHashPath, idxHashTab, fAbsolute,
-                                            pLastAncestor ? pLastAncestor->bObjType & KFSOBJ_F_USE_CUSTOM_GEN : 0, *penmError);
+                                            pLastAncestor ? pLastAncestor->fFlags & KFSOBJ_F_USE_CUSTOM_GEN : 0, *penmError);
         if (pLastAncestor)
             kFsCacheObjRelease(pCache, pLastAncestor);
 
@@ -3621,7 +3640,7 @@ static PKFSOBJ kFsCacheLookupHashedW(PKFSCACHE pCache, const wchar_t *pwcPath, K
                 && *penmError != KFSLOOKUPERROR_PATH_TOO_LONG)
             || *penmError == KFSLOOKUPERROR_UNSUPPORTED )
             kFsCacheCreatePathHashTabEntryW(pCache, pFsObj, pwcPath, cwcPath, uHashPath, idxHashTab, fAbsolute,
-                                            pLastAncestor ? pLastAncestor->bObjType & KFSOBJ_F_USE_CUSTOM_GEN : 0, *penmError);
+                                            pLastAncestor ? pLastAncestor->fFlags & KFSOBJ_F_USE_CUSTOM_GEN : 0, *penmError);
         if (pLastAncestor)
             kFsCacheObjRelease(pCache, pLastAncestor);
 
diff --git a/src/lib/nt/nthlp.h b/src/lib/nt/nthlp.h
index 18125e4..29b1b72 100644
--- a/src/lib/nt/nthlp.h
+++ b/src/lib/nt/nthlp.h
@@ -1,4 +1,4 @@
-/* $Id: nthlp.h 3009 2016-11-07 02:21:59Z bird $ */
+/* $Id: nthlp.h 3060 2017-09-21 15:11:07Z bird $ */
 /** @file
  * MSC + NT helper functions.
  */
@@ -88,5 +88,22 @@ static __inline void birdNtTimeToTimeSpec(__int64 iNtTime, BirdTimeSpec_T *pTime
 }
 
 
+static __inline void birdNtTimeToTimeVal(__int64 iNtTime, BirdTimeVal_T *pTimeVal)
+{
+    iNtTime -= BIRD_NT_EPOCH_OFFSET_UNIX_100NS;
+    pTimeVal->tv_sec  = iNtTime / 10000000;
+    pTimeVal->tv_usec = (iNtTime % 10000000) / 10;
+}
+
+
+static __inline __int64 birdNtTimeFromTimeVal(BirdTimeVal_T const *pTimeVal)
+{
+    __int64 iNtTime = pTimeVal->tv_sec * 10000000;
+    iNtTime += pTimeVal->tv_usec * 10;
+    iNtTime += BIRD_NT_EPOCH_OFFSET_UNIX_100NS;
+    return iNtTime;
+}
+
+
 #endif
 
diff --git a/src/lib/nt/nttypes.h b/src/lib/nt/nttypes.h
index 8e714c4..fe669c8 100644
--- a/src/lib/nt/nttypes.h
+++ b/src/lib/nt/nttypes.h
@@ -1,10 +1,10 @@
-/* $Id: nttypes.h 2702 2013-11-21 00:11:08Z bird $ */
+/* $Id: nttypes.h 3060 2017-09-21 15:11:07Z bird $ */
 /** @file
  * MSC + NT basic & common types, various definitions.
  */
 
 /*
- * Copyright (c) 2005-2013 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2005-2017 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,6 +33,13 @@
 
 #include <sys/types.h>
 
+typedef struct BirdTimeVal
+{
+    __int64       tv_sec;
+    __int32       tv_usec;
+    __int32       tv_padding0;
+} BirdTimeVal_T;
+
 typedef struct BirdTimeSpec
 {
     __int64       tv_sec;
@@ -46,4 +53,3 @@ typedef struct BirdTimeSpec
 
 #endif
 
-
diff --git a/src/lib/nt/ntunlink.c b/src/lib/nt/ntunlink.c
index 50921bd..fc0d82e 100644
--- a/src/lib/nt/ntunlink.c
+++ b/src/lib/nt/ntunlink.c
@@ -1,10 +1,10 @@
-/* $Id: ntunlink.c 3009 2016-11-07 02:21:59Z bird $ */
+/* $Id: ntunlink.c 3060 2017-09-21 15:11:07Z bird $ */
 /** @file
  * MSC + NT unlink and variations.
  */
 
 /*
- * Copyright (c) 2005-2013 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2005-2017 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -32,9 +32,7 @@
 /*******************************************************************************
 *   Header Files                                                               *
 *******************************************************************************/
-#include <stdio.h>
-#include <errno.h>
-#include <malloc.h>
+#include "ntunlink.h"
 
 #include "ntstuff.h"
 #include "nthlp.h"
diff --git a/src/lib/nt/ntunlink.h b/src/lib/nt/ntunlink.h
index 035a028..e7934be 100644
--- a/src/lib/nt/ntunlink.h
+++ b/src/lib/nt/ntunlink.h
@@ -1,4 +1,4 @@
-/* $Id: ntunlink.h 3009 2016-11-07 02:21:59Z bird $ */
+/* $Id: ntunlink.h 3060 2017-09-21 15:11:07Z bird $ */
 /** @file
  * MSC + NT unlink and variations.
  */
@@ -32,6 +32,7 @@
 #define ___nt_ntunlink_h
 
 #include "nttypes.h"
+#include <wchar.h>
 
 int birdUnlink(const char *pszFile);
 int birdUnlinkW(const wchar_t *pwszFile);
diff --git a/src/lib/nt/ntutimes.c b/src/lib/nt/ntutimes.c
new file mode 100644
index 0000000..554e6e6
--- /dev/null
+++ b/src/lib/nt/ntutimes.c
@@ -0,0 +1,99 @@
+/* $Id: ntutimes.c 3097 2017-10-14 03:52:44Z bird $ */
+/** @file
+ * MSC + NT utimes and lutimes
+ */
+
+/*
+ * Copyright (c) 2005-2017 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ *
+ * 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.
+ *
+ * Alternatively, the content of this file may be used under the terms of the
+ * GPL version 2 or later, or LGPL version 2.1 or later.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "ntutimes.h"
+
+#include "ntstuff.h"
+#include "nthlp.h"
+
+
+
+static int birdUtimesInternal(const char *pszPath, BirdTimeVal_T paTimes[2], int fFollowLink)
+{
+    HANDLE hFile = birdOpenFileEx(NULL,
+                                  pszPath,
+                                  FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
+                                  FILE_ATTRIBUTE_NORMAL,
+                                  FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                  FILE_OPEN,
+                                  FILE_OPEN_FOR_BACKUP_INTENT | (fFollowLink ? 0 : FILE_OPEN_REPARSE_POINT),
+                                  OBJ_CASE_INSENSITIVE);
+    if (hFile != INVALID_HANDLE_VALUE)
+    {
+        MY_FILE_BASIC_INFORMATION   Info;
+        MY_IO_STATUS_BLOCK          Ios;
+        MY_NTSTATUS                 rcNt;
+
+        memset(&Info, 0, sizeof(Info));
+        if (paTimes)
+        {
+            Info.LastAccessTime.QuadPart = birdNtTimeFromTimeVal(&paTimes[0]);
+            Info.LastWriteTime.QuadPart  = birdNtTimeFromTimeVal(&paTimes[1]);
+        }
+        else
+        {
+            /** @todo replace this with something from ntdll  */
+            FILETIME Now;
+            GetSystemTimeAsFileTime(&Now);
+            Info.LastAccessTime.HighPart  = Now.dwHighDateTime;
+            Info.LastAccessTime.LowPart   = Now.dwLowDateTime;
+            Info.LastWriteTime.HighPart   = Now.dwHighDateTime;
+            Info.LastWriteTime.LowPart    = Now.dwLowDateTime;
+        }
+
+        Ios.Information = -1;
+        Ios.u.Status    = -1;
+
+        rcNt = g_pfnNtSetInformationFile(hFile, &Ios, &Info, sizeof(Info), MyFileBasicInformation);
+
+        birdCloseFile(hFile);
+
+        if (MY_NT_SUCCESS(rcNt))
+            return 0;
+        birdSetErrnoFromNt(rcNt);
+    }
+    return -1;
+}
+
+
+int birdUtimes(const char *pszFile, BirdTimeVal_T paTimes[2])
+{
+    return birdUtimesInternal(pszFile, paTimes, 1 /*fFollowLink*/);
+}
+
+int birdLUtimes(const char *pszFile, BirdTimeVal_T paTimes[2])
+{
+    return birdUtimesInternal(pszFile, paTimes, 0 /*fFollowLink*/);
+}
+
diff --git a/src/lib/nt/nttypes.h b/src/lib/nt/ntutimes.h
similarity index 70%
copy from src/lib/nt/nttypes.h
copy to src/lib/nt/ntutimes.h
index 8e714c4..42589ff 100644
--- a/src/lib/nt/nttypes.h
+++ b/src/lib/nt/ntutimes.h
@@ -1,10 +1,10 @@
-/* $Id: nttypes.h 2702 2013-11-21 00:11:08Z bird $ */
+/* $Id: ntutimes.h 3060 2017-09-21 15:11:07Z bird $ */
 /** @file
- * MSC + NT basic & common types, various definitions.
+ * MSC + NT utimes and lutimes.
  */
 
 /*
- * Copyright (c) 2005-2013 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
+ * Copyright (c) 2005-2017 knut st. osmundsen <bird-kBuild-spamx at anduin.net>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -28,22 +28,18 @@
  * GPL version 2 or later, or LGPL version 2.1 or later.
  */
 
-#ifndef ___nt_nttypes_h
-#define ___nt_nttypes_h
+#ifndef ___nt_ntutimes_h
+#define ___nt_ntutimes_h
 
-#include <sys/types.h>
+#include "nttypes.h"
 
-typedef struct BirdTimeSpec
-{
-    __int64       tv_sec;
-    __int32       tv_nsec;
-    __int32       tv_padding0;
-} BirdTimeSpec_T;
+int birdUtimes(const char *pszFile, BirdTimeVal_T paTimes[2]);
+int birdLUtimes(const char *pszFile, BirdTimeVal_T paTimes[2]);
 
-/** The distance between the NT and unix epochs given in NT time (units of 100
- *  ns). */
-#define BIRD_NT_EPOCH_OFFSET_UNIX_100NS 116444736000000000LL
+#undef  utimes
+#define utimes(a_pszPath, a_paTimes)    birdUtimes(a_pszPath, a_paTimes)
+#undef  lutimes
+#define lutimes(a_pszPath, a_paTimes)   birdLUtimes(a_pszPath, a_paTimes)
 
 #endif
 
-
diff --git a/src/sed/Makefile.kmk b/src/sed/Makefile.kmk
index 1fec22c..f34b3e8 100644
--- a/src/sed/Makefile.kmk
+++ b/src/sed/Makefile.kmk
@@ -1,4 +1,4 @@
-# $Id: Makefile.kmk 2909 2016-09-09 22:54:17Z bird $
+# $Id: Makefile.kmk 3062 2017-09-30 11:26:21Z bird $
 ## @file
 # Sub-Makefile for kmk_sed.
 #
@@ -73,6 +73,10 @@ kmk_sed_SOURCES.freebsd = \
 kmk_sed_SOURCES.haiku = \
 	lib/strverscmp.c \
 	lib/obstack.c
+kmk_sed_SOURCES.netbsd = \
+	lib/strverscmp.c \
+	lib/obstack.c \
+	lib/getline.c
 kmk_sed_SOURCES.openbsd = \
 	lib/strverscmp.c \
 	lib/obstack.c \
diff --git a/src/sed/config.h.netbsd b/src/sed/config.h.netbsd
new file mode 100755
index 0000000..568e886
--- /dev/null
+++ b/src/sed/config.h.netbsd
@@ -0,0 +1,471 @@
+/* config.h.  Generated from config_h.in by configure.  */
+/* config_h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c' support on those systems.
+   */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define to 1 if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define to 1 if you have the `asprintf' function. */
+#define HAVE_ASPRINTF 1
+
+/* Define to 1 if you have the `bcopy' function. */
+#define HAVE_BCOPY 1
+
+/* Define to 1 if you have the `btowc' function. */
+#define HAVE_BTOWC 1
+
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO 1
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you
+   don't. */
+#define HAVE_DECL_FEOF_UNLOCKED 0
+
+/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if
+   you don't. */
+#define HAVE_DECL_FGETS_UNLOCKED 0
+
+/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you
+   don't. */
+#define HAVE_DECL_GETC_UNLOCKED 1
+
+/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you
+   don't. */
+#define HAVE_DECL__SNPRINTF 0
+
+/* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you
+   don't. */
+#define HAVE_DECL__SNWPRINTF 0
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `fchmod' function. */
+#define HAVE_FCHMOD 1
+
+/* Define to 1 if you have the `fchown' function. */
+#define HAVE_FCHOWN 1
+
+/* Define to 1 if you have the `fwprintf' function. */
+#define HAVE_FWPRINTF 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getegid' function. */
+#define HAVE_GETEGID 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the iconv() function. */
+#define HAVE_ICONV 1
+
+/* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */
+#define HAVE_INTMAX_T 1
+
+/* Define if <inttypes.h> exists and doesn't clash with <sys/types.h>. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and
+   declares uintmax_t. */
+#define HAVE_INTTYPES_H_WITH_UINTMAX 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the `isatty' function. */
+#define HAVE_ISATTY 1
+
+/* Define to 1 if you have the `isblank' function. */
+#define HAVE_ISBLANK 1
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if you have the `regex' library (-lregex). */
+/* #undef HAVE_LIBREGEX */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the 'long double' type. */
+#define HAVE_LONG_DOUBLE 1
+
+/* Define to 1 if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define if you have the 'long long' type. */
+#define HAVE_LONG_LONG 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+#define HAVE_MBRTOWC 1
+
+/* Define to 1 if <wchar.h> declares mbstate_t. */
+#define HAVE_MBSTATE_T 1
+
+/* Define to 1 if you have the <mcheck.h> header file. */
+/* #undef HAVE_MCHECK_H */
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mempcpy' function. */
+/* #undef HAVE_MEMPCPY */
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the `munmap' function. */
+#define HAVE_MUNMAP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define to 1 if libc includes obstacks. */
+/* #undef HAVE_OBSTACK */
+
+/* Define to 1 if you have the `pathconf' function. */
+#define HAVE_PATHCONF 1
+
+/* Define to 1 if you have the `popen' function. */
+#define HAVE_POPEN 1
+
+/* Define if your printf() function supports format strings with positions. */
+#define HAVE_POSIX_PRINTF 1
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+/* #undef HAVE_REGEX_H */
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares
+   uintmax_t. */
+#define HAVE_STDINT_H_WITH_UINTMAX 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `stpcpy' function. */
+/* #undef HAVE_STPCPY */
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the `strverscmp' function. */
+/* #undef HAVE_STRVERSCMP */
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `tsearch' function. */
+#define HAVE_TSEARCH 1
+
+/* Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>. */
+#define HAVE_UINTMAX_T 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the 'unsigned long long' type. */
+#define HAVE_UNSIGNED_LONG_LONG 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define if you have the 'wchar_t' type. */
+#define HAVE_WCHAR_T 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+#define HAVE_WCRTOMB 1
+
+/* Define to 1 if you have the `wcscoll' function. */
+#define HAVE_WCSCOLL 1
+
+/* Define to 1 if you have the `wcslen' function. */
+#define HAVE_WCSLEN 1
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define if you have the 'wint_t' type. */
+#define HAVE_WINT_T 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Define to 1 if you have the `__argz_count' function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define to 1 if you have the `__argz_next' function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define to 1 if you have the `__fsetlocking' function. */
+/* #undef HAVE___FSETLOCKING */
+
+/* Define as const if the declaration of iconv() needs const. */
+#define ICONV_CONST const
+
+/* Define if integer division by zero raises signal SIGFPE. */
+#define INTDIV0_RAISES_SIGFPE 1
+
+/* Name of package */
+#define PACKAGE "sed"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bonzini at gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "sed"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "sed 4.1.5"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "sed"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.1.5"
+
+/* Define if <inttypes.h> exists and defines unusable PRI* macros. */
+/* #undef PRI_MACROS_BROKEN */
+
+/* Define to the version of GNU sed whose features are supported by this sed.
+   */
+#define SED_FEATURE_VERSION "4.1"
+
+/* Define as the maximum value of type 'size_t', if the system doesn't define
+   it. */
+/* #undef SIZE_MAX */
+
+/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+
+/* Version number of package */
+#define VERSION "4.1.5"
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Include BSD functions in regex, used by the testsuite */
+#define _REGEX_RE_COMP 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to a type if <wchar.h> does not define. */
+/* #undef mbstate_t */
+
+/* Define to `long int' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define as the type of the result of subtracting two pointers, if the system
+   doesn't define it. */
+/* #undef ptrdiff_t */
+
+/* Define to empty if the C compiler doesn't support this keyword. */
+/* #undef signed */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
+
+/* Define to unsigned long or unsigned long long if <stdint.h> and
+   <inttypes.h> don't define. */
+/* #undef uintmax_t */

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



More information about the Pkg-virtualbox-commits mailing list