Index: /trunk/src/kmk/Makefile.am
===================================================================
--- /trunk/src/kmk/Makefile.am	(revision 2262)
+++ /trunk/src/kmk/Makefile.am	(revision 2263)
@@ -69,4 +69,5 @@
 		kmkbuiltin/install.c \
 		kmkbuiltin/kDepIDB.c \
+		kmkbuiltin/kDepObj.c \
 		kmkbuiltin/ln.c \
 		kmkbuiltin/md5sum.c \
Index: /trunk/src/kmk/Makefile.kmk
===================================================================
--- /trunk/src/kmk/Makefile.kmk	(revision 2262)
+++ /trunk/src/kmk/Makefile.kmk	(revision 2263)
@@ -240,4 +240,5 @@
 	kmkbuiltin/install.c \
 	kmkbuiltin/kDepIDB.c \
+	kmkbuiltin/kDepObj.c \
 	kmkbuiltin/md5sum.c \
 	kmkbuiltin/mkdir.c \
@@ -281,4 +282,5 @@
 	kmk_test \
 	kDepIDB \
+	kDepObj \
 
 kmk_append_TEMPLATE = BIN-KMK
@@ -383,4 +385,11 @@
 kDepIDB_SOURCES = \
 	kmkbuiltin/kDepIDB.c
+
+kDepObj_TEMPLATE = BIN-KMK
+kDepObj_DEFS = kmk_builtin_kDepObj=main
+kDepObj_INCS = .
+kDepObj_LIBS = $(LIB_KDEP)
+kDepObj_SOURCES = \
+	kmkbuiltin/kDepObj.c
 
 
Index: /trunk/src/kmk/kmkbuiltin.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin.c	(revision 2262)
+++ /trunk/src/kmk/kmkbuiltin.c	(revision 2263)
@@ -211,4 +211,6 @@
         rc = kmk_builtin_test(argc, argv, environ, ppapszArgvToSpawn);
     /* rarely used commands: */
+    else if (!strcmp(pszCmd, "kDepObj"))
+        rc = kmk_builtin_kDepObj(argc, argv, environ);
     else if (!strcmp(pszCmd, "chmod"))
         rc = kmk_builtin_chmod(argc, argv, environ);
Index: /trunk/src/kmk/kmkbuiltin.h
===================================================================
--- /trunk/src/kmk/kmkbuiltin.h	(revision 2262)
+++ /trunk/src/kmk/kmkbuiltin.h	(revision 2263)
@@ -53,4 +53,5 @@
 extern int kmk_builtin_test(int argc, char **argv, char **envp, char ***ppapszArgvSpawn);
 extern int kmk_builtin_kDepIDB(int argc, char **argv, char **envp);
+extern int kmk_builtin_kDepObj(int argc, char **argv, char **envp);
 
 extern char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname);
Index: /trunk/src/kmk/kmkbuiltin/kDepIDB.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/kDepIDB.c	(revision 2262)
+++ /trunk/src/kmk/kmkbuiltin/kDepIDB.c	(revision 2263)
@@ -38,24 +38,21 @@
 #endif
 #if !defined(_MSC_VER)
-# include <stdint.h>
 # include <unistd.h>
 #else
-# define USE_WIN_MMAP
 # include <io.h>
-# include <Windows.h>
- typedef unsigned char  uint8_t;
- typedef unsigned short uint16_t;
- typedef unsigned int   uint32_t;
 #endif
-/*#include "kDep.h"*/
+#include "../../lib/k/kDefs.h"
+#include "../../lib/k/kTypes.h"
 #include "../../lib/kDep.h"
 #include "kmkbuiltin.h"
 
-#define OFFSETOF(type, member)  ( (int)(size_t)(void *)&( ((type *)(void *)0)->member) )
-
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
 /*#define DEBUG*/
 #ifdef DEBUG
 # define dprintf(a)             printf a
-# define dump(pb, cb, offBase)  hexdump(pb,cb,offBase)
+# define dump(pb, cb, offBase)  depHexDump(pb,cb,offBase)
 #else
 # define dprintf(a)             do {} while (0)
@@ -70,36 +67,4 @@
 static const char *argv0 = "";
 
-#ifdef DEBUG
-/**
- * Performs a hexdump.
- */
-static void hexdump(const uint8_t *pb, size_t cb, size_t offBase)
-{
-    static const char   szHex[16] = "0123456789abcdef";
-
-    const unsigned      cchWidth = 16;
-    size_t              off = 0;
-    while (off < cb)
-    {
-        unsigned i;
-        printf("%s%0*x %04x:", off ? "\n" : "", sizeof(pb) * 2, offBase + off, off);
-        for (i = 0; i < cchWidth && off + i < cb ; i++)
-            printf(off + i < cb ? !(i & 7) && i ? "-%02x" : " %02x" : "   ", pb[i]);
-
-        while (i++ < cchWidth)
-                printf("   ");
-        printf(" ");
-
-        for (i = 0; i < cchWidth && off + i < cb; i++)
-        {
-            const uint8_t u8 = pb[i];
-            printf("%c", u8 < 127 && u8 >= 32 ? u8 : '.', 1);
-        }
-        off += cchWidth;
-        pb  += cchWidth;
-    }
-    printf("\n");
-}
-#endif
 
 /**
@@ -113,7 +78,7 @@
  * @param   cchPrefix       The size of the prefix.
  */
-static int ScanStream(uint8_t *pbStream, size_t cbStream, const char *pszPrefix, size_t cchPrefix)
-{
-    const uint8_t  *pbCur = pbStream;
+static int ScanStream(KU8 *pbStream, size_t cbStream, const char *pszPrefix, size_t cchPrefix)
+{
+    const KU8      *pbCur = pbStream;
     size_t          cbLeft = cbStream;
     register char   chFirst = *pszPrefix;
@@ -140,96 +105,4 @@
 
     return 0;
-}
-
-
-#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 FreeFileMemory().
- */
-void *ReadFileIntoMemory(FILE *pInput, size_t *pcbFile)
-{
-    void       *pvFile;
-    long        cbFile;
-
-    /*
-     * 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);
-        return NULL;
-    }
-    if (pcbFile)
-        *pcbFile = cbFile;
-
-    /*
-     * 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.
-     */
-    pvFile = malloc(cbFile + 1);
-    if (pvFile)
-    {
-        if (fread(pvFile, cbFile, 1, pInput))
-        {
-            ((uint8_t *)pvFile)[cbFile] = '\0';
-            return pvFile;
-        }
-        fprintf(stderr, "%s: error: Failed to read %ld bytes.\n", argv0, cbFile);
-        free(pvFile);
-    }
-    else
-        fprintf(stderr, "%s: error: Failed to allocate %ld bytes (file mapping).\n", argv0, cbFile);
-    return NULL;
-}
-
-
-static void FreeFileMemory(void *pvFile)
-{
-#if defined(USE_WIN_MMAP)
-    if (g_hMapObj)
-    {
-        UnmapViewOfFile(pvFile);
-        CloseHandle(g_hMapObj);
-        return;
-    }
-#endif
-    free(pvFile);
 }
 
@@ -244,5 +117,5 @@
 
 /** A PDB 7.0 Page number. */
-typedef uint32_t PDB70PAGE;
+typedef KU32 PDB70PAGE;
 /** Pointer to a PDB 7.0 Page number. */
 typedef PDB70PAGE *PPDB70PAGE;
@@ -254,5 +127,5 @@
 {
     /** The size of the stream. */
-    uint32_t    cbStream;
+    KU32        cbStream;
 } PDB70STREAM, *PPDB70STREAM;
 
@@ -266,7 +139,7 @@
 {
     /** The signature string. */
-    uint8_t     szSignature[sizeof(PDB_SIGNATURE_700)];
+    KU8         szSignature[sizeof(PDB_SIGNATURE_700)];
     /** The page size. */
-    uint32_t    cbPage;
+    KU32        cbPage;
     /** The start page. */
     PDB70PAGE   iStartPage;
@@ -274,7 +147,7 @@
     PDB70PAGE   cPages;
     /** The root stream directory. */
-    uint32_t    cbRoot;
+    KU32        cbRoot;
     /** Unknown function, always 0. */
-    uint32_t    u32Reserved;
+    KU32        u32Reserved;
     /** The page index of the root page table. */
     PDB70PAGE   iRootPages;
@@ -287,8 +160,8 @@
 {
     /** The number of streams */
-    uint32_t    cStreams;
+    KU32        cStreams;
     /** Array of streams. */
     PDB70STREAM aStreams[1];
-    /* uint32_t aiPages[] */
+    /* KU32 aiPages[] */
 } PDB70ROOT, *PPDB70ROOT;
 
@@ -299,13 +172,13 @@
 {
     /** The structure version. */
-    uint32_t        Version;
+    KU32            Version;
     /** Timestamp.  */
-    uint32_t        TimeStamp;
+    KU32            TimeStamp;
     /** Unknown. */
-    uint32_t        Unknown1;
+    KU32            Unknown1;
     /** GUID. */
-    uint32_t        u32Guid[4];
+    KU32            u32Guid[4];
     /** The size of the following name table. */
-    uint32_t        cbNames;
+    KU32            cbNames;
     /** The name table. */
     char            szzNames[1];
@@ -341,5 +214,5 @@
 static size_t Pdb70Align(PPDB70HDR pHdr, size_t cb)
 {
-    if (cb == ~(uint32_t)0 || !cb)
+    if (cb == ~(KU32)0 || !cb)
         return 0;
     return ((cb + pHdr->cbPage - 1) / pHdr->cbPage) * pHdr->cbPage;
@@ -349,5 +222,5 @@
 static size_t Pdb70Pages(PPDB70HDR pHdr, size_t cb)
 {
-    if (cb == ~(uint32_t)0 || !cb)
+    if (cb == ~(KU32)0 || !cb)
         return 0;
     return (cb + pHdr->cbPage - 1) / pHdr->cbPage;
@@ -358,5 +231,5 @@
     const size_t    cbPage = pHdr->cbPage;
     size_t          cPages = Pdb70Pages(pHdr, cb);
-    uint8_t *pbBuf = malloc(cPages * cbPage + 1);
+    KU8            *pbBuf = malloc(cPages * cbPage + 1);
     if (pbBuf)
     {
@@ -368,5 +241,5 @@
             {
                 off *= cbPage;
-                memcpy(pbBuf + iPage * cbPage, (uint8_t *)pHdr + off, cbPage);
+                memcpy(pbBuf + iPage * cbPage, (KU8 *)pHdr + off, cbPage);
                 dump(pbBuf + iPage * cbPage, iPage + 1 < cPages ? cbPage : cb % cbPage, off);
             }
@@ -393,5 +266,5 @@
      * (Todo: Check if we can just use the stream #0 size..)
      */
-    PPDB70PAGE piPageMap = (uint32_t *)((uint8_t *)pHdr + pHdr->iRootPages * pHdr->cbPage);
+    PPDB70PAGE piPageMap = (KU32 *)((KU8 *)pHdr + pHdr->iRootPages * pHdr->cbPage);
     PPDB70ROOT pRoot = Pdb70AllocAndRead(pHdr, pHdr->cbRoot, piPageMap);
     if (pRoot)
@@ -400,5 +273,5 @@
         /* This stuff is probably unnecessary: */
         /* size = stream header + array of stream. */
-        size_t cb = OFFSETOF(PDB70ROOT, aStreams[pRoot->cStreams]);
+        size_t cb = K_OFFSETOF(PDB70ROOT, aStreams[pRoot->cStreams]);
         free(pRoot);
         pRoot = Pdb70AllocAndRead(pHdr, cb, piPageMap);
@@ -408,5 +281,5 @@
             unsigned iStream = pRoot->cStreams;
             while (iStream-- > 0)
-                if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
+                if (pRoot->aStreams[iStream].cbStream != ~(KU32)0)
                     cb += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB70PAGE);
             free(pRoot);
@@ -431,5 +304,5 @@
     PPDB70PAGE      paiPageMap;
     if (    iStream >= pRoot->cStreams
-        ||  cbStream == ~(uint32_t)0)
+        ||  cbStream == ~(KU32)0)
     {
         fprintf(stderr, "%s: error: Invalid stream %d\n", argv0, iStream);
@@ -439,5 +312,5 @@
     paiPageMap = (PPDB70PAGE)&pRoot->aStreams[pRoot->cStreams];
     while (iStream-- > 0)
-        if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
+        if (pRoot->aStreams[iStream].cbStream != ~(KU32)0)
             paiPageMap += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream);
 
@@ -447,5 +320,5 @@
 }
 
-static int Pdb70Process(uint8_t *pbFile, size_t cbFile)
+static int Pdb70Process(KU8 *pbFile, size_t cbFile)
 {
     PPDB70HDR   pHdr = (PPDB70HDR)pbFile;
@@ -477,5 +350,5 @@
         if (    pNames->Version == PDB70NAMES_VERSION
             &&  pNames->cbNames > 32
-            &&  pNames->cbNames + offsetof(PDB70NAMES, szzNames) <= pRoot->aStreams[1].cbStream)
+            &&  pNames->cbNames + K_OFFSETOF(PDB70NAMES, szzNames) <= pRoot->aStreams[1].cbStream)
         {
             /*
@@ -529,11 +402,11 @@
         for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++)
         {
-            uint8_t *pbStream;
-            if (    pRoot->aStreams[iStream].cbStream == ~(uint32_t)0
+            KU8 *pbStream;
+            if (    pRoot->aStreams[iStream].cbStream == ~(KU32)0
                 ||  !pRoot->aStreams[iStream].cbStream)
                 continue;
             dprintf(("Stream #%d: %#x bytes (%#x aligned)\n", iStream, pRoot->aStreams[iStream].cbStream,
                      Pdb70Align(pHdr, pRoot->aStreams[iStream].cbStream)));
-            pbStream = (uint8_t *)Pdb70AllocAndReadStream(pHdr, pRoot, iStream, &cbStream);
+            pbStream = (KU8 *)Pdb70AllocAndReadStream(pHdr, pRoot, iStream, &cbStream);
             if (pbStream)
             {
@@ -562,5 +435,5 @@
 
 /** A PDB 2.0 Page number. */
-typedef uint16_t PDB20PAGE;
+typedef KU16 PDB20PAGE;
 /** Pointer to a PDB 2.0 Page number. */
 typedef PDB20PAGE *PPDB20PAGE;
@@ -572,7 +445,7 @@
 {
     /** The size of the stream. */
-    uint32_t    cbStream;
+    KU32        cbStream;
     /** Some unknown value. */
-    uint32_t    u32Unknown;
+    KU32        u32Unknown;
 } PDB20STREAM, *PPDB20STREAM;
 
@@ -585,7 +458,7 @@
 {
     /** The signature string. */
-    uint8_t     szSignature[sizeof(PDB_SIGNATURE_200)];
+    KU8         szSignature[sizeof(PDB_SIGNATURE_200)];
     /** The page size. */
-    uint32_t    cbPage;
+    KU32        cbPage;
     /** The start page - whatever that is... */
     PDB20PAGE   iStartPage;
@@ -604,7 +477,7 @@
 {
     /** The number of streams */
-    uint16_t    cStreams;
+    KU16        cStreams;
     /** Reserved or high part of cStreams. */
-    uint16_t    u16Reserved;
+    KU16        u16Reserved;
     /** Array of streams. */
     PDB20STREAM aStreams[1];
@@ -629,5 +502,5 @@
 static size_t Pdb20Pages(PPDB20HDR pHdr, size_t cb)
 {
-    if (cb == ~(uint32_t)0 || !cb)
+    if (cb == ~(KU32)0 || !cb)
         return 0;
     return (cb + pHdr->cbPage - 1) / pHdr->cbPage;
@@ -637,5 +510,5 @@
 {
     size_t cPages = Pdb20Pages(pHdr, cb);
-    uint8_t *pbBuf = malloc(cPages * pHdr->cbPage + 1);
+    KU8   *pbBuf = malloc(cPages * pHdr->cbPage + 1);
     if (pbBuf)
     {
@@ -645,5 +518,5 @@
             size_t off = paiPageMap[iPage];
             off *= pHdr->cbPage;
-            memcpy(pbBuf + iPage * pHdr->cbPage, (uint8_t *)pHdr + off, pHdr->cbPage);
+            memcpy(pbBuf + iPage * pHdr->cbPage, (KU8 *)pHdr + off, pHdr->cbPage);
             iPage++;
         }
@@ -665,5 +538,5 @@
     {
         /* size = stream header + array of stream. */
-        size_t cb = OFFSETOF(PDB20ROOT, aStreams[pRoot->cStreams]);
+        size_t cb = K_OFFSETOF(PDB20ROOT, aStreams[pRoot->cStreams]);
         free(pRoot);
         pRoot = Pdb20AllocAndRead(pHdr, cb, &pHdr->aiRootPageMap[0]);
@@ -673,5 +546,5 @@
             unsigned iStream = pRoot->cStreams;
             while (iStream-- > 0)
-                if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
+                if (pRoot->aStreams[iStream].cbStream != ~(KU32)0)
                     cb += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB20PAGE);
             free(pRoot);
@@ -693,5 +566,5 @@
     PPDB20PAGE  paiPageMap;
     if (    iStream >= pRoot->cStreams
-        ||  cbStream == ~(uint32_t)0)
+        ||  cbStream == ~(KU32)0)
     {
         fprintf(stderr, "%s: error: Invalid stream %d\n", argv0, iStream);
@@ -701,5 +574,5 @@
     paiPageMap = (PPDB20PAGE)&pRoot->aStreams[pRoot->cStreams];
     while (iStream-- > 0)
-        if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
+        if (pRoot->aStreams[iStream].cbStream != ~(KU32)0)
             paiPageMap += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream);
 
@@ -709,5 +582,5 @@
 }
 
-static int Pdb20Process(uint8_t *pbFile, size_t cbFile)
+static int Pdb20Process(KU8 *pbFile, size_t cbFile)
 {
     PPDB20HDR   pHdr = (PPDB20HDR)pbFile;
@@ -732,8 +605,8 @@
     for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++)
     {
-        uint8_t *pbStream;
-        if (pRoot->aStreams[iStream].cbStream == ~(uint32_t)0)
+        KU8 *pbStream;
+        if (pRoot->aStreams[iStream].cbStream == ~(KU32)0)
             continue;
-        pbStream = (uint8_t *)Pdb20AllocAndReadStream(pHdr, pRoot, iStream, NULL);
+        pbStream = (KU8 *)Pdb20AllocAndReadStream(pHdr, pRoot, iStream, NULL);
         if (pbStream)
         {
@@ -756,5 +629,6 @@
 {
     size_t      cbFile;
-    uint8_t    *pbFile;
+    KU8        *pbFile;
+    void       *pvOpaque;
     int         rc = 0;
 
@@ -762,5 +636,5 @@
      * Read the file into memory.
      */
-    pbFile = (uint8_t *)ReadFileIntoMemory(pInput, &cbFile);
+    pbFile = (KU8 *)depReadFileIntoMemory(pInput, &cbFile, &pvOpaque);
     if (!pbFile)
         return 1;
@@ -779,5 +653,5 @@
     }
 
-    FreeFileMemory(pbFile);
+    depFreeFileMemory(pbFile, pvOpaque);
     return rc;
 }
Index: /trunk/src/kmk/kmkbuiltin/kDepObj.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/kDepObj.c	(revision 2263)
+++ /trunk/src/kmk/kmkbuiltin/kDepObj.c	(revision 2263)
@@ -0,0 +1,524 @@
+/* $Id$ */
+/** @file
+ * kDepObj - Extract dependency information from an object file.
+ */
+
+/*
+ * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@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 "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+#if !defined(_MSC_VER)
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
+#include "../../lib/k/kDefs.h"
+#include "../../lib/k/kTypes.h"
+#include "../../lib/kDep.h"
+#include "kmkbuiltin.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/*#define DEBUG*/
+#define DEBUG
+#ifdef DEBUG
+# define dprintf(a)             printf a
+# define dump(pb, cb, offBase)  depHexDump(pb,cb,offBase)
+#else
+# define dprintf(a)             do {} while (0)
+# define dump(pb, cb, offBase)  do {} while (0)
+#endif
+
+/** @name OMF defines
+ * @{ */
+#define KDEPOMF_THEADR          0x80
+#define KDEPOMF_LHEADR          0x82
+#define KDEPOMF_COMMENT         0x88
+#define KDEPOMF_CMTCLS_DEPENDENCY  0xe9
+/** @} */
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/** @name OMF structure
+ * @{ */
+#pragma pack(1)
+/** OMF record header. */
+typedef struct KDEPOMFHDR
+{
+    /** The record type. */
+    KU8     bType;
+    /** The size of the record, excluding this header. */
+    KU16    cbRec;
+} KDEPOMFHDR;
+typedef KDEPOMFHDR *PKDEPOMFHDR;
+typedef const KDEPOMFHDR *PCKDEPOMFHDR;
+
+/** OMF string. */
+typedef struct KDEPOMFSTR
+{
+    KU8     cch;
+    char    ach[1];
+} KDEPOMFSTR;
+typedef KDEPOMFSTR *PKDEPOMFSTR;
+typedef const KDEPOMFSTR *PCKDEPOMFSTR;
+
+/** THEADR/LHEADR. */
+typedef struct KDEPOMFTHEADR
+{
+    KDEPOMFHDR  Hdr;
+    KDEPOMFSTR  Name;
+} KDEPOMFTHEADR;
+typedef KDEPOMFTHEADR *PKDEPOMFTHEADR;
+typedef const KDEPOMFTHEADR *PCKDEPOMFTHEADR;
+
+/** Dependency File. */
+typedef struct KDEPOMFDEPFILE
+{
+    KDEPOMFHDR  Hdr;
+    KU8         fType;
+    KU8         bClass;
+    KU16        wDosTime;
+    KU16        wDosDate;
+    KDEPOMFSTR  Name;
+} KDEPOMFDEPFILE;
+typedef KDEPOMFDEPFILE *PKDEPOMFDEPFILE;
+typedef const KDEPOMFDEPFILE *PCKDEPOMFDEPFILE;
+
+#pragma pack()
+/** @} */
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** the executable name. */
+static const char *argv0 = "";
+
+
+/**
+ * Parses the OMF file.
+ *
+ * @returns 0 on success, 1 on failure.
+ * @param   pbFile      The start of the file.
+ * @param   cbFile      The file size.
+ */
+int kDepObjOMFParse(const KU8 *pbFile, KSIZE cbFile)
+{
+    PCKDEPOMFHDR    pHdr = (PCKDEPOMFHDR)pbFile;
+    KSIZE           cbLeft = cbFile;
+
+
+    /*
+     * Iterate thru the records until we hit the end or an invalid one.
+     */
+    while (   cbLeft >= sizeof(*pHdr)
+           && cbLeft >= pHdr->cbRec + sizeof(*pHdr))
+    {
+        /* process selected record types. */
+        dprintf(("%#07x: %#04x %#05x\n", (const KU8*)pHdr - pbFile, pHdr->bType, pHdr->cbRec));
+        switch (pHdr->bType)
+        {
+            /*
+             * The T/L Header contains the source name. When emitting CodeView 4
+             * and earlier (like masm and watcom does), all includes used by the
+             * line number tables have their own THEADR record.
+             */
+            case KDEPOMF_THEADR:
+            case KDEPOMF_LHEADR:
+            {
+                PCKDEPOMFTHEADR pTHeadr = (PCKDEPOMFTHEADR)pHdr;
+                if (1 + pTHeadr->Name.cch + 1 != pHdr->cbRec)
+                {
+                    fprintf(stderr, "%s: error: %#07x - Bad %cHEADR record, length mismatch.\n",
+                            argv0, (const KU8*)pHdr - pbFile, pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L');
+                    return 1;
+                }
+                depAdd(pTHeadr->Name.ach, pTHeadr->Name.cch);
+                break;
+            }
+
+            case KDEPOMF_COMMENT:
+                if (pHdr->cbRec < 2)
+                {
+                    fprintf(stderr, "%s: error: %#07x - Bad COMMENT record, too small.\n",
+                            argv0, (const KU8*)pHdr - pbFile);
+                    return 1;
+                }
+                if (((const KU8 *)(pHdr+1))[0] & 0x3f)
+                {
+                    fprintf(stderr, "%s: error: %#07x - Bad COMMENT record, reserved flags set.\n",
+                            argv0, (const KU8*)pHdr - pbFile);
+                    return 1;
+                }
+                switch (((const KU8 *)(pHdr+1))[1])
+                {
+                    /*
+                     * Borland dependency file comment (famously used by wmake and Watcom).
+                     */
+                    case KDEPOMF_CMTCLS_DEPENDENCY:
+                    {
+                        PCKDEPOMFDEPFILE pDep = (PCKDEPOMFDEPFILE)pHdr;
+                        if (K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1 != pHdr->cbRec + sizeof(*pHdr))
+                        {
+                            /* Empty record indicates the end of the dependency files,
+                               no need to go on. */
+                            if (pHdr->cbRec == 2 + 1)
+                                return 0;
+
+                            fprintf(stderr, "%s: error: %#07x - Bad DEPENDENCY FILE record, length mismatch. (%d/%d)\n",
+                                    argv0, (const KU8*)pHdr - pbFile,
+                                    K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1,
+                                    pHdr->cbRec + sizeof(*pHdr));
+                            return 1;
+
+                        }
+                        depAdd(pDep->Name.ach, pDep->Name.cch);
+                        break;
+                    }
+
+                    /** @todo Check for class A1 and pick up the debug info type (HL/CV(/DX)). */
+                }
+                break;
+            /** @todo add support for HLL line number segments and stuff. */
+        }
+
+        /* advance */
+        cbLeft -= pHdr->cbRec + sizeof(*pHdr);
+        pHdr = (PCKDEPOMFHDR)((const KU8 *)(pHdr + 1) + pHdr->cbRec);
+    }
+
+    if (cbLeft)
+    {
+        fprintf(stderr, "%s: error: %#07x - Unexpected EOF. cbLeft=%#x\n",
+                argv0, (const KU8*)pHdr - pbFile, cbLeft);
+        return 1;
+    }
+    return 0;
+}
+
+
+/**
+ * Checks if this file is an OMF file or not.
+ *
+ * @returns K_TRUE if it's OMF, K_FALSE otherwise.
+ *
+ * @param   pb      The start of the file.
+ * @param   cb      The file size.
+ */
+KBOOL kDepObjOMFTest(const KU8 *pbFile, KSIZE cbFile)
+{
+    PCKDEPOMFTHEADR pHdr = (PCKDEPOMFTHEADR)pbFile;
+
+    if (cbFile < sizeof(*pHdr))
+        return K_FALSE;
+    if (    pHdr->Hdr.bType != KDEPOMF_THEADR
+        &&  pHdr->Hdr.bType != KDEPOMF_LHEADR)
+        return K_FALSE;
+    if (pHdr->Hdr.cbRec + sizeof(pHdr->Hdr) >= cbFile)
+        return K_FALSE;
+    if (pHdr->Hdr.cbRec != 1 + pHdr->Name.cch + 1)
+        return K_FALSE;
+
+    return K_TRUE;
+}
+
+
+/**
+ * Read the file into memory and parse it.
+ */
+static int kDepObjProcessFile(FILE *pInput)
+{
+    size_t      cbFile;
+    KU8        *pbFile;
+    void       *pvOpaque;
+    int         rc = 0;
+
+    /*
+     * Read the file into memory.
+     */
+    pbFile = (KU8 *)depReadFileIntoMemory(pInput, &cbFile, &pvOpaque);
+    if (!pbFile)
+        return 1;
+
+    /*
+     * See if it's an OMF file, then process it.
+     */
+    if (kDepObjOMFTest(pbFile, cbFile))
+        rc = kDepObjOMFParse(pbFile, cbFile);
+    else
+    {
+        fprintf(stderr, "%s: error: Doesn't recognize the header of the OMF file.\n", argv0);
+        rc = 1;
+    }
+
+    depFreeFileMemory(pbFile, pvOpaque);
+    return rc;
+}
+
+
+static void usage(const char *a_argv0)
+{
+    printf("usage: %s -o <output> -t <target> [-fqs] <OMF-file>\n"
+           "   or: %s --help\n"
+           "   or: %s --version\n",
+           a_argv0, a_argv0, a_argv0);
+}
+
+
+int kmk_builtin_kDepObj(int argc, char *argv[], char **envp)
+{
+    int         i;
+
+    /* Arguments. */
+    FILE       *pOutput = NULL;
+    const char *pszOutput = NULL;
+    FILE       *pInput = NULL;
+    const char *pszTarget = NULL;
+    int         fStubs = 0;
+    int         fFixCase = 0;
+    /* Argument parsing. */
+    int         fInput = 0;             /* set when we've found input argument. */
+    int         fQuiet = 0;
+
+    argv0 = argv[0];
+
+    /*
+     * Parse arguments.
+     */
+    if (argc <= 1)
+    {
+        usage(argv[0]);
+        return 1;
+    }
+    for (i = 1; i < argc; i++)
+    {
+        if (argv[i][0] == '-')
+        {
+            const char *psz = &argv[i][1];
+            if (*psz == '-')
+            {
+                if (!strcmp(psz, "-quiet"))
+                    psz = "q";
+                else if (!strcmp(psz, "-help"))
+                    psz = "?";
+                else if (!strcmp(psz, "-version"))
+                    psz = "V";
+            }
+
+            switch (*psz)
+            {
+                /*
+                 * Output file.
+                 */
+                case 'o':
+                {
+                    pszOutput = &argv[i][2];
+                    if (pOutput)
+                    {
+                        fprintf(stderr, "%s: syntax error: only one output file!\n", argv[0]);
+                        return 1;
+                    }
+                    if (!*pszOutput)
+                    {
+                        if (++i >= argc)
+                        {
+                            fprintf(stderr, "%s: syntax error: The '-o' argument is missing the filename.\n", argv[0]);
+                            return 1;
+                        }
+                        pszOutput = argv[i];
+                    }
+                    if (pszOutput[0] == '-' && !pszOutput[1])
+                        pOutput = stdout;
+                    else
+                        pOutput = fopen(pszOutput, "w");
+                    if (!pOutput)
+                    {
+                        fprintf(stderr, "%s: error: Failed to create output file '%s'.\n", argv[0], pszOutput);
+                        return 1;
+                    }
+                    break;
+                }
+
+                /*
+                 * Target name.
+                 */
+                case 't':
+                {
+                    if (pszTarget)
+                    {
+                        fprintf(stderr, "%s: syntax error: only one target!\n", argv[0]);
+                        return 1;
+                    }
+                    pszTarget = &argv[i][2];
+                    if (!*pszTarget)
+                    {
+                        if (++i >= argc)
+                        {
+                            fprintf(stderr, "%s: syntax error: The '-t' argument is missing the target name.\n", argv[0]);
+                            return 1;
+                        }
+                        pszTarget = argv[i];
+                    }
+                    break;
+                }
+
+                /*
+                 * Fix case.
+                 */
+                case 'f':
+                {
+                    fFixCase = 1;
+                    break;
+                }
+
+                /*
+                 * Quiet.
+                 */
+                case 'q':
+                {
+                    fQuiet = 1;
+                    break;
+                }
+
+                /*
+                 * Generate stubs.
+                 */
+                case 's':
+                {
+                    fStubs = 1;
+                    break;
+                }
+
+                /*
+                 * The mandatory version & help.
+                 */
+                case '?':
+                    usage(argv[0]);
+                    return 0;
+                case 'V':
+                case 'v':
+                    return kbuild_version(argv[0]);
+
+                /*
+                 * Invalid argument.
+                 */
+                default:
+                    fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", argv[0], argv[i]);
+                    usage(argv[0]);
+                    return 1;
+            }
+        }
+        else
+        {
+            pInput = fopen(argv[i], "rb");
+            if (!pInput)
+            {
+                fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", argv[0], argv[i]);
+                return 1;
+            }
+            fInput = 1;
+        }
+
+        /*
+         * End of the line?
+         */
+        if (fInput)
+        {
+            if (++i < argc)
+            {
+                fprintf(stderr, "%s: syntax error: No arguments shall follow the input spec.\n", argv[0]);
+                return 1;
+            }
+            break;
+        }
+    }
+
+    /*
+     * Got all we require?
+     */
+    if (!pInput)
+    {
+        fprintf(stderr, "%s: syntax error: No input!\n", argv[0]);
+        return 1;
+    }
+    if (!pOutput)
+    {
+        fprintf(stderr, "%s: syntax error: No output!\n", argv[0]);
+        return 1;
+    }
+    if (!pszTarget)
+    {
+        fprintf(stderr, "%s: syntax error: No target!\n", argv[0]);
+        return 1;
+    }
+
+    /*
+     * Do the parsing.
+     */
+    i = kDepObjProcessFile(pInput);
+    fclose(pInput);
+
+    /*
+     * Write the dependecy file.
+     */
+    if (!i)
+    {
+        depOptimize(fFixCase, fQuiet);
+        fprintf(pOutput, "%s:", pszTarget);
+        depPrint(pOutput);
+        if (fStubs)
+            depPrintStubs(pOutput);
+    }
+
+    /*
+     * Close the output, delete output on failure.
+     */
+    if (!i && ferror(pOutput))
+    {
+        i = 1;
+        fprintf(stderr, "%s: error: Error writing to '%s'.\n", argv[0], pszOutput);
+    }
+    fclose(pOutput);
+    if (i)
+    {
+        if (unlink(pszOutput))
+            fprintf(stderr, "%s: warning: failed to remove output file '%s' on failure.\n", argv[0], pszOutput);
+    }
+
+    depCleanup();
+    return i;
+}
+
Index: /trunk/src/lib/kDep.c
===================================================================
--- /trunk/src/lib/kDep.c	(revision 2262)
+++ /trunk/src/lib/kDep.c	(revision 2263)
@@ -35,6 +35,9 @@
 #include <sys/stat.h>
 #include "k/kDefs.h"
+#include "k/kTypes.h"
 #if K_OS == K_OS_WINDOWS
-# include <windows.h>
+# define USE_WIN_MMAP
+# include <io.h>
+# include <Windows.h>
  extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull); /* nt_fullpath.c */
 #else
@@ -294,10 +297,10 @@
    this is one of the algorithms used in berkeley db (see sleepycat) and
    elsewhere. */
-static unsigned sdbm(const char *str)
+static unsigned sdbm(const char *str, size_t size)
 {
     unsigned hash = 0;
     int c;
 
-    while ((c = *(unsigned const char *)str++))
+    while (size-- > 0 && (c = *(unsigned const char *)str++))
         hash = c + (hash << 6) + (hash << 16) - hash;
 
@@ -310,12 +313,12 @@
  *
  * @returns Pointer to the allocated dependency.
- * @param   pszFilename     The filename.
+ * @param   pszFilename     The filename. Does not need to be terminated.
  * @param   cchFilename     The length of the filename.
  */
 PDEP depAdd(const char *pszFilename, size_t cchFilename)
 {
-    unsigned uHash = sdbm(pszFilename);
-    PDEP    pDep;
-    PDEP    pDepPrev;
+    unsigned    uHash = sdbm(pszFilename, cchFilename);
+    PDEP        pDep;
+    PDEP        pDepPrev;
 
     /*
@@ -341,5 +344,6 @@
 
     pDep->cchFilename = cchFilename;
-    memcpy(pDep->szFilename, pszFilename, cchFilename + 1);
+    memcpy(pDep->szFilename, pszFilename, cchFilename);
+    pDep->szFilename[cchFilename] = '\0';
     pDep->uHash = uHash;
 
@@ -373,2 +377,130 @@
 }
 
+
+/**
+ * Performs a hexdump.
+ */
+void depHexDump(const KU8 *pb, size_t cb, size_t offBase)
+{
+    const unsigned      cchWidth = 16;
+    size_t              off = 0;
+    while (off < cb)
+    {
+        unsigned i;
+        printf("%s%0*x %04x:", off ? "\n" : "", sizeof(pb) * 2, offBase + off, off);
+        for (i = 0; i < cchWidth && off + i < cb ; i++)
+            printf(off + i < cb ? !(i & 7) && i ? "-%02x" : " %02x" : "   ", pb[i]);
+
+        while (i++ < cchWidth)
+                printf("   ");
+        printf(" ");
+
+        for (i = 0; i < cchWidth && off + i < cb; i++)
+        {
+            const KU8 u8 = pb[i];
+            printf("%c", u8 < 127 && u8 >= 32 ? u8 : '.', 1);
+        }
+        off += cchWidth;
+        pb  += cchWidth;
+    }
+    printf("\n");
+}
+
+
+/**
+ * Reads the file specified by the pInput file stream into memory.
+ *
+ * @returns The address of the memory mapping on success. This must be
+ *          freed by calling depFreeFileMemory.
+ *
+ * @param   pInput      The file stream to load or map into memory.
+ * @param   pcbFile     Where to return the mapping (file) size.
+ * @param   ppvOpaque   Opaque data when mapping, otherwise NULL.
+ */
+void *depReadFileIntoMemory(FILE *pInput, size_t *pcbFile, void **ppvOpaque)
+{
+    void       *pvFile;
+    long        cbFile;
+
+    /*
+     * 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, "kDep: error: Failed to determin file size.\n");
+        return NULL;
+    }
+    if (pcbFile)
+        *pcbFile = cbFile;
+
+    /*
+     * 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)
+            {
+                *ppvOpaque = hMapObj;
+                return pvFile;
+            }
+            fprintf(stderr, "kDep: warning: MapViewOfFile failed, %d.\n", GetLastError());
+            CloseHandle(hMapObj);
+        }
+        else
+            fprintf(stderr, "kDep: warning: CreateFileMapping failed, %d.\n", GetLastError());
+    }
+
+#endif
+
+    /*
+     * Allocate memory and read the file.
+     */
+    pvFile = malloc(cbFile + 1);
+    if (pvFile)
+    {
+        if (fread(pvFile, cbFile, 1, pInput))
+        {
+            ((KU8 *)pvFile)[cbFile] = '\0';
+            *ppvOpaque = NULL;
+            return pvFile;
+        }
+        fprintf(stderr, "kDep: error: Failed to read %ld bytes.\n", cbFile);
+        free(pvFile);
+    }
+    else
+        fprintf(stderr, "kDep: error: Failed to allocate %ld bytes (file mapping).\n", cbFile);
+    return NULL;
+}
+
+
+/**
+ * Free resources allocated by depReadFileIntoMemory.
+ *
+ * @param   pvFile      The address of the memory mapping.
+ * @param   pvOpaque    The opaque value returned together with the mapping.
+ */
+void depFreeFileMemory(void *pvFile, void *pvOpaque)
+{
+#if defined(USE_WIN_MMAP)
+    if (pvOpaque)
+    {
+        UnmapViewOfFile(pvFile);
+        CloseHandle(pvOpaque);
+        return;
+    }
+#endif
+    free(pvFile);
+}
+
Index: /trunk/src/lib/kDep.h
===================================================================
--- /trunk/src/lib/kDep.h	(revision 2262)
+++ /trunk/src/lib/kDep.h	(revision 2263)
@@ -46,4 +46,9 @@
 extern void depPrintStubs(FILE *pOutput);
 extern void depCleanup(void);
+extern void *depReadFileIntoMemory(FILE *pInput, size_t *pcbFile, void **ppvOpaque);
+extern void depFreeFileMemory(void *pvFile, void *pvOpaque);
+#ifdef ___k_kTypes_h___
+extern void depHexDump(const KU8 *pb, size_t cb, size_t offBase);
+#endif
 
 #endif
