Index: /trunk/src/kmk/Makefile.kmk
===================================================================
--- /trunk/src/kmk/Makefile.kmk	(revision 1164)
+++ /trunk/src/kmk/Makefile.kmk	(revision 1165)
@@ -32,5 +32,5 @@
 TEMPLATE_BIN-KMK_INCS.freebsd = glob
 TEMPLATE_BIN-KMK_INCS.solaris = glob
-TEMPLATE_BIN-KMK_LIBS = $(TEMPLATE_BIN_LIBS) $(TARGET_kmkmissing)
+TEMPLATE_BIN-KMK_LIBS = $(TEMPLATE_BIN_LIBS) $(TARGET_kmkmissing) $(LIB_KUTIL)
 ifdef ELECTRIC_HEAP # for electric heap (see electric.c) - windows only.
 TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN_CFLAGS) /FI$(PATH_CURRENT)/electric.h -DELECTRIC_HEAP=1
Index: /trunk/src/kmk/kmkbuiltin/kDepIDB.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/kDepIDB.c	(revision 1164)
+++ /trunk/src/kmk/kmkbuiltin/kDepIDB.c	(revision 1165)
@@ -38,4 +38,7 @@
 # include <stdint.h>
 #else
+# define USE_WIN_MMAP
+# include <io.h>
+# include <Windows.h>
  typedef unsigned char  uint8_t;
  typedef unsigned short uint16_t;
@@ -137,9 +140,14 @@
 
 
+#ifdef USE_WIN_MMAP
+/** Handle to the current file mapping object. */
+static HANDLE g_hMapObj = NULL;
+#endif
+
 
 /**
  * Reads the file specified by the pInput file stream into memory.
  * The size of the file is returned in *pcbFile if specified.
- * The returned pointer should be freed by free().
+ * The returned pointer should be freed by FreeFileMemory().
  */
 void *ReadFileIntoMemory(FILE *pInput, size_t *pcbFile)
@@ -152,7 +160,12 @@
      * Figure out file size.
      */
+#if defined(_MSC_VER)
+    cbFile = _filelength(fileno(pInput));
+    if (cbFile < 0)
+#else
     if (    fseek(pInput, 0, SEEK_END) < 0
         ||  (cbFile = ftell(pInput)) < 0
         ||  fseek(pInput, 0, SEEK_SET))
+#endif
     {
         fprintf(stderr, "%s: error: Failed to determin file size.\n", argv0);
@@ -163,4 +176,28 @@
 
     /*
+     * Try mmap first.
+     */
+#ifdef USE_WIN_MMAP
+    {
+        HANDLE hMapObj = CreateFileMapping((HANDLE)_get_osfhandle(fileno(pInput)),
+                                           NULL, PAGE_READONLY, 0, cbFile, NULL);
+        if (hMapObj != NULL)
+        {
+            pvFile = MapViewOfFile(hMapObj, FILE_MAP_READ, 0, 0, cbFile);
+            if (pvFile)
+            {
+                g_hMapObj = hMapObj;
+                return pvFile;
+            }
+            fprintf(stderr, "%s: warning: MapViewOfFile failed, %d.\n", argv0, GetLastError());
+            CloseHandle(hMapObj);
+        }
+        else
+            fprintf(stderr, "%s: warning: CreateFileMapping failed, %d.\n", argv0, GetLastError());
+    }
+
+#endif
+
+    /*
      * Allocate memory and read the file.
      */
@@ -168,5 +205,10 @@
     if (pvFile)
     {
+#if 1
+        long cbRead = (long)read(fileno(pInput), pvFile, cbFile);
+        if (cbRead == cbFile)
+#else
         if (fread(pvFile, cbFile, 1, pInput))
+#endif
         {
             ((uint8_t *)pvFile)[cbFile] = '\0';
@@ -181,4 +223,17 @@
 }
 
+
+static void FreeFileMemory(void *pvFile)
+{
+#if defined(USE_WIN_MMAP)
+    if (g_hMapObj)
+    {
+        UnmapViewOfFile(pvFile);
+        CloseHandle(g_hMapObj);
+        return;
+    }
+#endif
+    free(pvFile);
+}
 
 
@@ -726,5 +781,5 @@
     }
 
-    free(pbFile);
+    FreeFileMemory(pbFile);
     return rc;
 }
@@ -925,4 +980,5 @@
     }
 
+    depCleanup();
     return i;
 }
Index: /trunk/src/kmk/w32/pathstuff.c
===================================================================
--- /trunk/src/kmk/w32/pathstuff.c	(revision 1164)
+++ /trunk/src/kmk/w32/pathstuff.c	(revision 1165)
@@ -83,350 +83,6 @@
 
 #if 1 /* bird */
-/*
- * Corrects the case of a path.
- * Expects a fullpath!
- * Added by bird for the $(abspath ) function and w32ify
- */
-void
-w32_fixcase(char *pszPath)
-{
-    static char     s_szLast[260];
-    unsigned        cchLast;
-
-#ifndef NDEBUG
-# define my_assert(expr) \
-    do { \
-        if (!(expr)) { \
-            printf("my_assert: %s, file %s, line %d\npszPath=%s\npsz=%s\n", \
-                   #expr, __FILE__, __LINE__, pszPath, psz); \
-            __debugbreak(); \
-            exit(1); \
-        } \
-    } while (0)
-#else
-# define my_assert(expr) do {} while (0)
-#endif
-
-    char *psz = pszPath;
-    if (*psz == '/' || *psz == '\\')
-    {
-        if (psz[1] == '/' || psz[1] == '\\')
-        {
-            /* UNC */
-            my_assert(psz[1] == '/' || psz[1] == '\\');
-            my_assert(psz[2] != '/' && psz[2] != '\\');
-
-            /* skip server name */
-            psz += 2;
-            while (*psz != '\\' && *psz != '/')
-            {
-                if (!*psz)
-                    return;
-                *psz++ = toupper(*psz);
-            }
-
-            /* skip the share name */
-            psz++;
-            my_assert(*psz != '/' && *psz != '\\');
-            while (*psz != '\\' && *psz != '/')
-            {
-                if (!*psz)
-                    return;
-                *psz++ = toupper(*psz);
-            }
-            my_assert(*psz == '/' || *psz == '\\');
-            psz++;
-        }
-        else
-        {
-            /* Unix spec */
-            psz++;
-        }
-    }
-    else
-    {
-        /* Drive letter */
-        my_assert(psz[1] == ':');
-        *psz = toupper(*psz);
-        my_assert(psz[0] >= 'A' && psz[0] <= 'Z');
-        my_assert(psz[2] == '/' || psz[2] == '\\');
-        psz += 3;
-    }
-
-    /*
-     * Try make use of the result from the previous call.
-     * This is ignorant to slashes and similar, but may help even so.
-     */
-    if (    s_szLast[0] == pszPath[0]
-        &&  (psz - pszPath == 1 || s_szLast[1] == pszPath[1])
-        &&  (psz - pszPath <= 2 || s_szLast[2] == pszPath[2])
-       )
-    {
-        char *pszLast = &s_szLast[psz - pszPath];
-        char *pszCur = psz;
-        for (;;)
-        {
-            const char ch1 = *pszCur;
-            const char ch2 = *pszLast;
-            if (    ch1 != ch2
-                &&  (ch1 != '\\' || ch2 != '/')
-                &&  (ch1 != '/'  || ch2 != '\\'))
-            {
-                if (    tolower(ch1) != tolower(ch2)
-                    &&  toupper(ch1) != toupper(ch2))
-                    break;
-                /* optimistic, component mismatch will be corrected in the next loop. */
-                *pszCur = ch2;
-            }
-            if (ch1 == '/' || ch1 == '\\')
-                psz = pszCur + 1;
-            else if (ch1 == '\0')
-            {
-                psz = pszCur;
-                break;
-            }
-            pszCur++;
-            pszLast++;
-        }
-    }
-
-    /*
-     * Pointing to the first char after the unc or drive specifier,
-     * or in case of a cache hit, the first non-matching char (following a slash of course).
-     */
-    while (*psz)
-    {
-        WIN32_FIND_DATA FindFileData;
-        HANDLE hDir;
-        char chSaved0;
-        char chSaved1;
-        char *pszEnd;
-        int iLongNameDiff;
-
-
-        /* find the end of the component. */
-        pszEnd = psz;
-        while (*pszEnd && *pszEnd != '/' && *pszEnd != '\\')
-            pszEnd++;
-
-        /* replace the end with "?\0" */
-        chSaved0 = pszEnd[0];
-        chSaved1 = pszEnd[1];
-        pszEnd[0] = '?';
-        pszEnd[1] = '\0';
-
-        /* find the right filename. */
-        hDir = FindFirstFile(pszPath, &FindFileData);
-        pszEnd[1] = chSaved1;
-        if (!hDir)
-        {
-            cchLast = psz - pszPath;
-            memcpy(s_szLast, pszPath, cchLast + 1);
-            pszEnd[0] = chSaved0;
-            return;
-        }
-        pszEnd[0] = '\0';
-        while (   (iLongNameDiff = stricmp(FindFileData.cFileName, psz))
-               && stricmp(FindFileData.cAlternateFileName, psz))
-        {
-            if (!FindNextFile(hDir, &FindFileData))
-            {
-                cchLast = psz - pszPath;
-                memcpy(s_szLast, pszPath, cchLast + 1);
-                pszEnd[0] = chSaved0;
-                return;
-            }
-        }
-        strcpy(psz, !iLongNameDiff ? FindFileData.cFileName : FindFileData.cAlternateFileName);
-        pszEnd[0] = chSaved0;
-        FindClose(hDir);
-
-        /* advance to the next component */
-        if (!chSaved0)
-        {
-            psz = pszEnd;
-            break;
-        }
-        psz = pszEnd + 1;
-        my_assert(*psz != '/' && *psz != '\\');
-    }
-
-    /* *psz == '\0', the end. */
-    cchLast = psz - pszPath;
-    memcpy(s_szLast, pszPath, cchLast + 1);
-#undef my_assert
-}
-
-#define MY_FileNameInformation 9
-
-typedef struct _MY_FILE_NAME_INFORMATION
-{
-    ULONG FileNameLength;
-    WCHAR FileName[1];
-} MY_FILE_NAME_INFORMATION, *PMY_FILE_NAME_INFORMATION;
-
-typedef struct _IO_STATUS_BLOCK 
-{
-    union
-    {
-        LONG Status;
-        PVOID Pointer;
-    };
-    ULONG_PTR Information;
-} MY_IO_STATUS_BLOCK, *PMY_IO_STATUS_BLOCK;
-
-static BOOL g_fInitialized = FALSE;
-static LONG (NTAPI *g_pfnNtQueryInformationFile)(HANDLE FileHandle, 
-    PMY_IO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation,  
-    ULONG Length, ULONG FileInformationClass);
-
-
-int
-nt_get_filename_info(const char *pszPath, char *pszFull, size_t cchFull)
-{
-    static char                 abBuf[8192];
-    PMY_FILE_NAME_INFORMATION   pFileNameInfo = (PMY_FILE_NAME_INFORMATION)abBuf;
-    MY_IO_STATUS_BLOCK          Ios;
-    LONG                        rcNt;
-    HANDLE                      hFile;
-
-    /*
-     * Check for NtQueryInformationFile the first time around.
-     */
-    if (!g_fInitialized)
-    {
-        g_fInitialized = TRUE;
-        if (!getenv("KMK_DONT_USE_NT_QUERY_INFORMATION_FILE"))
-            *(FARPROC *)&g_pfnNtQueryInformationFile = 
-                GetProcAddress(LoadLibrary("ntdll.dll"), "NtQueryInformationFile");
-    }
-    if (!g_pfnNtQueryInformationFile)
-        return -1;
-
-    /*
-     * Try open the path and query its file name information.
-     */
-    hFile = CreateFile(pszPath, 
-                       GENERIC_READ,
-                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                       NULL,
-                       OPEN_EXISTING,
-                       FILE_FLAG_BACKUP_SEMANTICS,
-                       NULL);
-    if (hFile)
-    {
-        memset(&Ios, 0, sizeof(Ios));
-        rcNt = g_pfnNtQueryInformationFile(hFile, &Ios, abBuf, sizeof(abBuf), MY_FileNameInformation);
-        CloseHandle(hFile);
-        if (rcNt >= 0)
-        {
-            /*
-             * The FileNameInformation we get is relative to where the volume is mounted,
-             * so we have to extract the driveletter prefix ourselves.
-             *
-             * FIXME: This will probably not work for volumes mounted in NTFS sub-directories.
-             */
-            int cchOut;
-            int fUnc = 0;
-            char *psz = pszFull;
-            if (pszPath[0] == '\\' || pszPath[0] == '/')
-            {
-                /* unc or root of volume */
-                if (    (pszPath[1] == '\\' || pszPath[1] == '/')
-                    &&  (pszPath[2] != '\\' || pszPath[2] == '/'))
-                {
-                    /* unc - we get the server + name back */
-                    *psz++ = '\\';
-                    fUnc = 1;
-                }
-                else
-                {
-                    /* root slash */
-                    *psz++ = _getdrive() + 'A' - 1;
-                    *psz++ = ':';
-                }
-            }
-            else if (pszPath[1] == ':' && isalpha(pszPath[0]))
-            {
-                /* drive letter */
-                *psz++ = toupper(pszPath[0]);
-                *psz++ = ':';
-            }
-            else
-            {
-                /* relative */
-                *psz++ = _getdrive() + 'A' - 1;
-                *psz++ = ':';
-            }
-
-            cchOut = WideCharToMultiByte(CP_ACP, 0, 
-                                         pFileNameInfo->FileName, pFileNameInfo->FileNameLength / sizeof(WCHAR), 
-                                         psz, cchFull - (psz - pszFull) - 2, NULL, NULL);
-            if (cchOut > 0)
-            {
-                const char *pszEnd;
-
-                /* upper case the server and share */
-                if (fUnc)
-                {
-                    for (psz++; *psz != '/' && *psz != '\\'; psz++)
-                        *psz = toupper(*psz);
-                    for (psz++; *psz != '/' && *psz != '\\'; psz++)
-                        *psz = toupper(*psz);
-                }
-
-                /* add trailing slash on directories if input has it. */
-                pszEnd = strchr(pszPath, '\0');
-                if (    (pszEnd[-1] == '/' || pszEnd[-1] == '\\')
-                    &&  psz[cchOut - 1] != '\\' 
-                    &&  psz[cchOut - 1] != '//')
-                    psz[cchOut++] = '\\';
-
-                /* make sure it's terminated */
-                psz[cchOut] = '\0';
-                return 0;
-            }
-            return -3;
-        }
-    }
-    return -2;
-}
-
-void 
-nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull)
-{
-#if 0
-    static int s_cHits = 0;
-    static int s_cFallbacks = 0;
-#endif
-
-    /*
-     * The simple case, the file / dir / whatever exists and can be 
-     * queried without problems.
-     */
-    if (nt_get_filename_info(pszPath, pszFull, cchFull) == 0)
-    {
-#if 0
-        fprintf(stderr, "nt #%d - %s\n", ++s_cHits, pszFull);
-#endif
-        return;
-    }
-    if (g_pfnNtQueryInformationFile)
-    {
-        /* do _fullpath and drop off path elements until we get a hit... - later */
-    }
-    
-    /*
-     * For now, simply fall back on the old method. 
-     */
-    _fullpath(pszFull, pszPath, cchFull);
-    w32_fixcase(pszFull);
-#if 0
-    fprintf(stderr, "fb #%d - %s\n", ++s_cFallbacks, pszFull);
-#endif
-}
-
-#endif /* bird */
-
+extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull);
+#endif
 
 /*
@@ -441,10 +97,5 @@
     if (resolve) {
 #if 1 /* bird */
-# if 1
         nt_fullpath(filename, w32_path, sizeof(w32_path));
-# else
-        _fullpath(w32_path, filename, sizeof(w32_path));
-        w32_fixcase(w32_path);
-# endif
 #else   /* !bird */
         _fullpath(w32_path, filename, sizeof (w32_path));
Index: /trunk/src/kmk/w32/subproc/sub_proc.c
===================================================================
--- /trunk/src/kmk/w32/subproc/sub_proc.c	(revision 1164)
+++ /trunk/src/kmk/w32/subproc/sub_proc.c	(revision 1165)
@@ -737,4 +737,5 @@
 
 	while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
+long tick;
 		wait_count = 0;
 		if (!stdin_eof) {
@@ -751,8 +752,10 @@
 		}
 
+tick = GetTickCount();
 		wait_return = WaitForMultipleObjects(wait_count, wait_list,
 			 FALSE, /* don't wait for all: one ready will do */
 			 child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
 			 	one second to collect all remaining output */
+printf("waitformultipleobjects: %d ms rc=%d\n", GetTickCount() - tick, wait_return);
 
 		if (wait_return == WAIT_FAILED) {
@@ -1075,5 +1078,5 @@
 #ifdef KMK /* for the space before the final " in case we need it. */
 	bytes_required++;
-#endif 
+#endif
 
 	command_line = (char*) malloc(bytes_required);
@@ -1125,5 +1128,5 @@
 					 */
 					backslash_count++;
-	
+
 					while(backslash_count) {
 						*(command_line_i++) = '\\';
Index: /trunk/src/lib/Makefile.kmk
===================================================================
--- /trunk/src/lib/Makefile.kmk	(revision 1164)
+++ /trunk/src/lib/Makefile.kmk	(revision 1165)
@@ -32,4 +32,5 @@
 kDep_DEFS.win += NEED_ISBLANK=1 __WIN32__=1
 kDep_SOURCES = kDep.c
+kDep_SOURCES.win = nt_fullpath.c
 kDep_NOINST = 1
 
@@ -38,4 +39,5 @@
 kUtil_DEFS.win = __WIN__
 kUtil_SOURCES = crc32.c md5.c
+kUtil_SOURCES.win = nt_fullpath.c
 kUtil_NOINST = 1
 
Index: /trunk/src/lib/kDep.c
===================================================================
--- /trunk/src/lib/kDep.c	(revision 1164)
+++ /trunk/src/lib/kDep.c	(revision 1165)
@@ -49,4 +49,5 @@
  typedef unsigned short uint16_t;
  typedef unsigned int   uint32_t;
+ extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull); /* nt_fullpath.c */
 #endif
 
@@ -82,153 +83,5 @@
 
 
-#ifdef __WIN32__
-/**
- * Corrects the case of a path and changes any path components containing
- * spaces with the short name (which can be longer).
- *
- * Expects a _fullpath!
- *
- * @param   pszPath     Pointer to the path, both input and output.
- *                      The buffer must be at least MAX_PATH in length.
- */
-static void fixcase(char *pszPath)
-{
-#define my_assert(expr) \
-    do { \
-        if (!(expr)) { \
-            printf("my_assert: %s, file %s, line %d\npszPath=%s\npsz=%s\n", \
-                   #expr, __FILE__, __LINE__, pszPath, psz); \
-            __debugbreak(); \
-            exit(1); \
-        } \
-    } while (0)
-
-    char *psz = pszPath;
-    if (*psz == '/' || *psz == '\\')
-    {
-        if (psz[1] == '/' || psz[1] == '\\')
-        {
-            /* UNC */
-            my_assert(psz[1] == '/' || psz[1] == '\\');
-            my_assert(psz[2] != '/' && psz[2] != '\\');
-
-            /* skip server name */
-            psz += 2;
-            while (*psz != '\\' && *psz != '/')
-            {
-                if (!*psz)
-                    return;
-                *psz++ = toupper(*psz);
-            }
-
-            /* skip the share name */
-            psz++;
-            my_assert(*psz != '/' && *psz != '\\');
-            while (*psz != '\\' && *psz != '/')
-            {
-                if (!*psz)
-                    return;
-                *psz++ = toupper(*psz);
-            }
-            my_assert(*psz == '/' || *psz == '\\');
-            psz++;
-        }
-        else
-        {
-            /* Unix spec */
-            psz++;
-        }
-    }
-    else
-    {
-        /* Drive letter */
-        my_assert(psz[1] == ':');
-        *psz = toupper(*psz);
-        my_assert(psz[0] >= 'A' && psz[0] <= 'Z');
-        my_assert(psz[2] == '/' || psz[2] == '\\');
-        psz += 3;
-    }
-
-    /*
-     * Pointing to the first char after the unc or drive specifier.
-     */
-    while (*psz)
-    {
-        WIN32_FIND_DATA FindFileData;
-        HANDLE hDir;
-        char chSaved0;
-        char chSaved1;
-        char *pszEnd;
-        size_t cch;
-        int iLongNameDiff;
-
-
-        /* find the end of the component. */
-        pszEnd = psz;
-        while (*pszEnd && *pszEnd != '/' && *pszEnd != '\\')
-            pszEnd++;
-        cch = pszEnd - psz;
-
-        /* replace the end with "?\0" */
-        chSaved0 = pszEnd[0];
-        chSaved1 = pszEnd[1];
-        pszEnd[0] = '?';
-        pszEnd[1] = '\0';
-
-        /* find the right filename. */
-        hDir = FindFirstFile(pszPath, &FindFileData);
-        pszEnd[1] = chSaved1;
-        if (!hDir)
-        {
-            pszEnd[0] = chSaved0;
-            return;
-        }
-        pszEnd[0] = '\0';
-        while (   (iLongNameDiff = _stricmp(FindFileData.cFileName, psz))
-               && _stricmp(FindFileData.cAlternateFileName, psz))
-        {
-            if (!FindNextFile(hDir, &FindFileData))
-            {
-                pszEnd[0] = chSaved0;
-                return;
-            }
-        }
-        pszEnd[0] = chSaved0;
-        if (iLongNameDiff || !FindFileData.cAlternateFileName[0] || !memchr(psz, ' ', cch))
-            memcpy(psz, !iLongNameDiff ? FindFileData.cFileName : FindFileData.cAlternateFileName, cch);
-        else
-        {
-            /* replace spacy name with the short name. */
-            const size_t cchAlt = strlen(FindFileData.cAlternateFileName);
-            const size_t cchDelta = cch - cchAlt;
-            my_assert(cchAlt > 0);
-            if (!cchDelta)
-                memcpy(psz, FindFileData.cAlternateFileName, cch);
-            else
-            {
-                size_t cbLeft = strlen(pszEnd) + 1;
-                if ((psz - pszPath) + cbLeft + cchAlt <= _MAX_PATH)
-                {
-                    memmove(psz + cchAlt, pszEnd, cbLeft);
-                    pszEnd -= cchDelta;
-                    memcpy(psz, FindFileData.cAlternateFileName, cchAlt);
-                }
-                else
-                    fprintf(stderr, "kDep: case & space fixed filename is growing too long (%d bytes)! '%s'\n",
-                            (psz - pszPath) + cbLeft + cchAlt, pszPath);
-            }
-        }
-        my_assert(pszEnd[0] == chSaved0);
-
-        /* advance to the next component */
-        if (!chSaved0)
-            return;
-        psz = pszEnd + 1;
-        my_assert(*psz != '/' && *psz != '\\');
-    }
-#undef my_assert
-}
-
-#elif defined(__OS2__)
+#if defined(__OS2__)
 
 /**
@@ -243,5 +96,5 @@
 }
 
-#else
+#elif !defined(__WIN32__) && !defined(__WIN64__)
 
 /**
@@ -372,12 +225,10 @@
         if (fFixCase)
         {
-#ifdef __WIN32__
-            if (_fullpath(szFilename, pszFilename, sizeof(szFilename)))
-                ;
-            else
-#endif
-                strcpy(szFilename, pszFilename);
+#if defined(__WIN32__) || defined(__WIN64__)
+            nt_fullpath(pszFilename, szFilename, sizeof(szFilename));
+#else
             fixslash(szFilename);
             fixcase(szFilename);
+#endif
             pszFilename = szFilename;
         }
@@ -398,5 +249,4 @@
     }
 
-#if 0 /* waste of time */
     /*
      * Free the old ones.
@@ -408,5 +258,4 @@
         free(pDep);
     }
-#endif
 }
 
@@ -510,2 +359,19 @@
     return pDep;
 }
+
+
+/**
+ * Frees the current dependency chain.
+ */
+void depCleanup(void)
+{
+    PDEP pDep = g_pDeps;
+    g_pDeps = NULL;
+    while (pDep)
+    {
+        PDEP pFree = pDep;
+        pDep = pDep->pNext;
+        free(pFree);
+    }
+}
+
Index: /trunk/src/lib/kDep.h
===================================================================
--- /trunk/src/lib/kDep.h	(revision 1164)
+++ /trunk/src/lib/kDep.h	(revision 1165)
@@ -47,4 +47,5 @@
 extern void depPrint(FILE *pOutput);
 extern void depPrintStubs(FILE *pOutput);
+extern void depCleanup(void);
 
 #endif
Index: /trunk/src/lib/nt_fullpath.c
===================================================================
--- /trunk/src/lib/nt_fullpath.c	(revision 1165)
+++ /trunk/src/lib/nt_fullpath.c	(revision 1165)
@@ -0,0 +1,380 @@
+/* $Id$ */
+/** @file
+ * fixcase - fixes the case of paths, windows specific.
+ */
+
+/*
+ * Copyright (c) 2004-2007 knut st. osmundsen <bird-src-spam@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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <Windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <direct.h>
+
+/*
+ * Corrects the case of a path.
+ * Expects a fullpath!
+ * Added by bird for the $(abspath ) function and w32ify
+ */
+static void w32_fixcase(char *pszPath)
+{
+    static char     s_szLast[260];
+    size_t          cchLast;
+
+#ifndef NDEBUG
+# define my_assert(expr) \
+    do { \
+        if (!(expr)) { \
+            printf("my_assert: %s, file %s, line %d\npszPath=%s\npsz=%s\n", \
+                   #expr, __FILE__, __LINE__, pszPath, psz); \
+            __debugbreak(); \
+            exit(1); \
+        } \
+    } while (0)
+#else
+# define my_assert(expr) do {} while (0)
+#endif
+
+    char *psz = pszPath;
+    if (*psz == '/' || *psz == '\\')
+    {
+        if (psz[1] == '/' || psz[1] == '\\')
+        {
+            /* UNC */
+            my_assert(psz[1] == '/' || psz[1] == '\\');
+            my_assert(psz[2] != '/' && psz[2] != '\\');
+
+            /* skip server name */
+            psz += 2;
+            while (*psz != '\\' && *psz != '/')
+            {
+                if (!*psz)
+                    return;
+                *psz++ = toupper(*psz);
+            }
+
+            /* skip the share name */
+            psz++;
+            my_assert(*psz != '/' && *psz != '\\');
+            while (*psz != '\\' && *psz != '/')
+            {
+                if (!*psz)
+                    return;
+                *psz++ = toupper(*psz);
+            }
+            my_assert(*psz == '/' || *psz == '\\');
+            psz++;
+        }
+        else
+        {
+            /* Unix spec */
+            psz++;
+        }
+    }
+    else
+    {
+        /* Drive letter */
+        my_assert(psz[1] == ':');
+        *psz = toupper(*psz);
+        my_assert(psz[0] >= 'A' && psz[0] <= 'Z');
+        my_assert(psz[2] == '/' || psz[2] == '\\');
+        psz += 3;
+    }
+
+    /*
+     * Try make use of the result from the previous call.
+     * This is ignorant to slashes and similar, but may help even so.
+     */
+    if (    s_szLast[0] == pszPath[0]
+        &&  (psz - pszPath == 1 || s_szLast[1] == pszPath[1])
+        &&  (psz - pszPath <= 2 || s_szLast[2] == pszPath[2])
+       )
+    {
+        char *pszLast = &s_szLast[psz - pszPath];
+        char *pszCur = psz;
+        for (;;)
+        {
+            const char ch1 = *pszCur;
+            const char ch2 = *pszLast;
+            if (    ch1 != ch2
+                &&  (ch1 != '\\' || ch2 != '/')
+                &&  (ch1 != '/'  || ch2 != '\\'))
+            {
+                if (    tolower(ch1) != tolower(ch2)
+                    &&  toupper(ch1) != toupper(ch2))
+                    break;
+                /* optimistic, component mismatch will be corrected in the next loop. */
+                *pszCur = ch2;
+            }
+            if (ch1 == '/' || ch1 == '\\')
+                psz = pszCur + 1;
+            else if (ch1 == '\0')
+            {
+                psz = pszCur;
+                break;
+            }
+            pszCur++;
+            pszLast++;
+        }
+    }
+
+    /*
+     * Pointing to the first char after the unc or drive specifier,
+     * or in case of a cache hit, the first non-matching char (following a slash of course).
+     */
+    while (*psz)
+    {
+        WIN32_FIND_DATA FindFileData;
+        HANDLE hDir;
+        char chSaved0;
+        char chSaved1;
+        char *pszEnd;
+        int iLongNameDiff;
+
+
+        /* find the end of the component. */
+        pszEnd = psz;
+        while (*pszEnd && *pszEnd != '/' && *pszEnd != '\\')
+            pszEnd++;
+
+        /* replace the end with "?\0" */
+        chSaved0 = pszEnd[0];
+        chSaved1 = pszEnd[1];
+        pszEnd[0] = '?';
+        pszEnd[1] = '\0';
+
+        /* find the right filename. */
+        hDir = FindFirstFile(pszPath, &FindFileData);
+        pszEnd[1] = chSaved1;
+        if (!hDir)
+        {
+            cchLast = psz - pszPath;
+            memcpy(s_szLast, pszPath, cchLast + 1);
+            pszEnd[0] = chSaved0;
+            return;
+        }
+        pszEnd[0] = '\0';
+        while (   (iLongNameDiff = stricmp(FindFileData.cFileName, psz))
+               && stricmp(FindFileData.cAlternateFileName, psz))
+        {
+            if (!FindNextFile(hDir, &FindFileData))
+            {
+                cchLast = psz - pszPath;
+                memcpy(s_szLast, pszPath, cchLast + 1);
+                pszEnd[0] = chSaved0;
+                return;
+            }
+        }
+        strcpy(psz, !iLongNameDiff ? FindFileData.cFileName : FindFileData.cAlternateFileName);
+        pszEnd[0] = chSaved0;
+        FindClose(hDir);
+
+        /* advance to the next component */
+        if (!chSaved0)
+        {
+            psz = pszEnd;
+            break;
+        }
+        psz = pszEnd + 1;
+        my_assert(*psz != '/' && *psz != '\\');
+    }
+
+    /* *psz == '\0', the end. */
+    cchLast = psz - pszPath;
+    memcpy(s_szLast, pszPath, cchLast + 1);
+#undef my_assert
+}
+
+#define MY_FileNameInformation 9
+
+typedef struct _MY_FILE_NAME_INFORMATION
+{
+    ULONG FileNameLength;
+    WCHAR FileName[1];
+} MY_FILE_NAME_INFORMATION, *PMY_FILE_NAME_INFORMATION;
+
+typedef struct _IO_STATUS_BLOCK
+{
+    union
+    {
+        LONG Status;
+        PVOID Pointer;
+    };
+    ULONG_PTR Information;
+} MY_IO_STATUS_BLOCK, *PMY_IO_STATUS_BLOCK;
+
+static BOOL g_fInitialized = FALSE;
+static LONG (NTAPI *g_pfnNtQueryInformationFile)(HANDLE FileHandle,
+    PMY_IO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation,
+    ULONG Length, ULONG FileInformationClass);
+
+
+int
+nt_get_filename_info(const char *pszPath, char *pszFull, size_t cchFull)
+{
+    static char                 abBuf[8192];
+    PMY_FILE_NAME_INFORMATION   pFileNameInfo = (PMY_FILE_NAME_INFORMATION)abBuf;
+    MY_IO_STATUS_BLOCK          Ios;
+    LONG                        rcNt;
+    HANDLE                      hFile;
+
+    /*
+     * Check for NtQueryInformationFile the first time around.
+     */
+    if (!g_fInitialized)
+    {
+        g_fInitialized = TRUE;
+        if (!getenv("KMK_DONT_USE_NT_QUERY_INFORMATION_FILE"))
+            *(FARPROC *)&g_pfnNtQueryInformationFile =
+                GetProcAddress(LoadLibrary("ntdll.dll"), "NtQueryInformationFile");
+    }
+    if (!g_pfnNtQueryInformationFile)
+        return -1;
+
+    /*
+     * Try open the path and query its file name information.
+     */
+    hFile = CreateFile(pszPath,
+                       GENERIC_READ,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                       NULL,
+                       OPEN_EXISTING,
+                       FILE_FLAG_BACKUP_SEMANTICS,
+                       NULL);
+    if (hFile)
+    {
+        memset(&Ios, 0, sizeof(Ios));
+        rcNt = g_pfnNtQueryInformationFile(hFile, &Ios, abBuf, sizeof(abBuf), MY_FileNameInformation);
+        CloseHandle(hFile);
+        if (rcNt >= 0)
+        {
+            /*
+             * The FileNameInformation we get is relative to where the volume is mounted,
+             * so we have to extract the driveletter prefix ourselves.
+             *
+             * FIXME: This will probably not work for volumes mounted in NTFS sub-directories.
+             */
+            int cchOut;
+            int fUnc = 0;
+            char *psz = pszFull;
+            if (pszPath[0] == '\\' || pszPath[0] == '/')
+            {
+                /* unc or root of volume */
+                if (    (pszPath[1] == '\\' || pszPath[1] == '/')
+                    &&  (pszPath[2] != '\\' || pszPath[2] == '/'))
+                {
+                    /* unc - we get the server + name back */
+                    *psz++ = '\\';
+                    fUnc = 1;
+                }
+                else
+                {
+                    /* root slash */
+                    *psz++ = _getdrive() + 'A' - 1;
+                    *psz++ = ':';
+                }
+            }
+            else if (pszPath[1] == ':' && isalpha(pszPath[0]))
+            {
+                /* drive letter */
+                *psz++ = toupper(pszPath[0]);
+                *psz++ = ':';
+            }
+            else
+            {
+                /* relative */
+                *psz++ = _getdrive() + 'A' - 1;
+                *psz++ = ':';
+            }
+
+            cchOut = WideCharToMultiByte(CP_ACP, 0,
+                                         pFileNameInfo->FileName, pFileNameInfo->FileNameLength / sizeof(WCHAR),
+                                         psz, (int)(cchFull - (psz - pszFull) - 2), NULL, NULL);
+            if (cchOut > 0)
+            {
+                const char *pszEnd;
+
+                /* upper case the server and share */
+                if (fUnc)
+                {
+                    for (psz++; *psz != '/' && *psz != '\\'; psz++)
+                        *psz = toupper(*psz);
+                    for (psz++; *psz != '/' && *psz != '\\'; psz++)
+                        *psz = toupper(*psz);
+                }
+
+                /* add trailing slash on directories if input has it. */
+                pszEnd = strchr(pszPath, '\0');
+                if (    (pszEnd[-1] == '/' || pszEnd[-1] == '\\')
+                    &&  psz[cchOut - 1] != '\\'
+                    &&  psz[cchOut - 1] != '//')
+                    psz[cchOut++] = '\\';
+
+                /* make sure it's terminated */
+                psz[cchOut] = '\0';
+                return 0;
+            }
+            return -3;
+        }
+    }
+    return -2;
+}
+
+/**
+ * Somewhat similar to fullpath, except that it will fix
+ * the case of existing path components.
+ */
+void
+nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull)
+{
+#if 0
+    static int s_cHits = 0;
+    static int s_cFallbacks = 0;
+#endif
+
+    /*
+     * The simple case, the file / dir / whatever exists and can be
+     * queried without problems.
+     */
+    if (nt_get_filename_info(pszPath, pszFull, cchFull) == 0)
+    {
+#if 0
+        fprintf(stderr, "nt #%d - %s\n", ++s_cHits, pszFull);
+#endif
+        return;
+    }
+    if (g_pfnNtQueryInformationFile)
+    {
+        /* do _fullpath and drop off path elements until we get a hit... - later */
+    }
+
+    /*
+     * For now, simply fall back on the old method.
+     */
+    _fullpath(pszFull, pszPath, cchFull);
+    w32_fixcase(pszFull);
+#if 0
+    fprintf(stderr, "fb #%d - %s\n", ++s_cFallbacks, pszFull);
+#endif
+}
+
