Index: /trunk/kLdr/testcase/Makefile.kmk
===================================================================
--- /trunk/kLdr/testcase/Makefile.kmk	(revision 2841)
+++ /trunk/kLdr/testcase/Makefile.kmk	(revision 2841)
@@ -0,0 +1,154 @@
+# $Id: Makefile.kmk 2836 2006-10-26 03:58:53Z bird $# $Id: Makefile.kmk 2836 2006-10-26 03:58:53Z bird $
+## @file
+#
+# kBuild Makefile for the kLdr.
+#
+# Copyright (c) 2006 knut st. osmundsen <bird@anduin.net>
+#
+#
+# This file is part of kLdr.
+#
+# kLdr 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.
+#
+# kLdr 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 kLdr; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+#
+
+# generate rules.
+DEPTH = ../..
+include $(PATH_KBUILD)/header.kmk
+
+
+#
+# Template for testcases.
+#
+TEMPLATE_TST = Testcase template
+ifneq ($(filter win nt win32 win64,$(BUILD_TARGET)),)
+ TEMPLATE_TST_TOOL = VCC70
+ TEMPLATE_TST_CFLAGS = -W3 -Zi -Zl -MD
+ TEMPLATE_TST_CFLAGS.release = -O2
+ TEMPLATE_TST_CXXFLAGS = -W3 -Zi -Zl -MD
+ TEMPLATE_TST_CXXFLAGS.release = -O2
+ TEMPLATE_TST_ASFLAGS = -f win
+ TEMPLATE_TST_DEFS = __WIN__
+ TEMPLATE_TST_SDKS = WIN32SDK
+ #kLdr_SDKS.x86 = WIN32SDK
+ #kLdr_SDKS.amd64 = WIN64SDK
+
+## @todo this is a kBuild bug!
+ TEMPLATE_TST_LIBS = \
+   	$$(PATH_TOOL_VCC70_LIB)/msvcrt.lib
+else
+ ifneq ($(filter os2,$(BUILD_TARGET)),)
+  TEMPLATE_TST_TOOL = GCC3OMF
+  TEMPLATE_TST_ASFLAGS = -f obj
+  TEMPLATE_TST_LIBS = os2 gcc end
+ else
+  TEMPLATE_TST_TOOL = GCC3
+  TEMPLATE_TST_ASFLAGS = -f elf
+  TEMPLATE_TST_LIBS = gcc
+ endif
+ TEMPLATE_TST_CFLAGS = -Wall -pedantic -g
+ TEMPLATE_TST_CFLAGS.release = -O2
+ TEMPLATE_TST_LDFLAGS =
+endif
+TEMPLATE_TST_INCS = .
+
+
+TEMPLATE_TSTPROG = Testcase program template
+TEMPLATE_TSTPROG_EXTENDS = TST
+ifneq ($(filter win nt win32 win64,$(BUILD_TARGET)),)
+else
+endif
+
+
+TEMPLATE_TSTDLL = Testcase dll template
+TEMPLATE_TSTDLL_EXTENDS = TST
+ifneq ($(filter win nt win32 win64,$(BUILD_TARGET)),)
+else
+endif
+
+
+#
+# tst-1: four dlls, three of which depends on the 4th and the testcase depends on those three again.
+#
+PROGRAMS += tst-1
+DLLS += tst-1-a tst-1-b tst-1-c tst-1-d
+
+tst-1-a_TEMPLATE = TSTDLL
+tst-1-a_SOURCES  = tst-1-a.c tstDllMain.c
+
+tst-1-b_TEMPLATE = TSTDLL
+tst-1-b_SOURCES  = tst-1-b.c tstDllMain.c
+
+tst-1-c_TEMPLATE = TSTDLL
+tst-1-c_SOURCES  = tst-1-c.c tstDllMain.c
+
+tst-1-d_TEMPLATE = TSTDLL
+tst-1-d_SOURCES  = tst-1-d.c tstDllMain.c
+
+tst-1_TEMPLATE   = TSTPROG
+tst-1_SOURCES    = tst-1.c
+
+ifeq ($(filter-out nt win win32 win64,$(BUILD_TARGET)),)
+tst-1-a_LIBS     = $(PATH_TARGET)/tst-1-d/tst-1-d.lib
+tst-1-b_LIBS     = $(PATH_TARGET)/tst-1-d/tst-1-d.lib
+tst-1-c_LIBS     = $(PATH_TARGET)/tst-1-d/tst-1-d.lib
+tst-1_LIBS       = $(TARGET_tst-1-a:.dll=.lib) $(TARGET_tst-1-b:.dll=.lib) $(TARGET_tst-1-c:.dll=.lib)
+else
+tst-1-a_LIBS     = $(TARGET_tst-1-a:-a=-d)
+tst-1-b_LIBS     = $(TARGET_tst-1-b:-b=-d)
+tst-1-c_LIBS     = $(TARGET_tst-1-c:-c=-d)
+tst-1_LIBS       = $(TARGET_tst-1-a) $(TARGET_tst-1-b) $(TARGET_tst-1-c)
+endif
+
+
+#
+# tst-2: four dlls, three of which depends on the 1st, and the testcase depends on those all of them.
+#
+PROGRAMS += tst-2
+DLLS += tst-2-a tst-2-b tst-2-c tst-2-d
+
+tst-2-a_TEMPLATE = TSTDLL
+tst-2-a_SOURCES  = tst-2-a.c tstDllMain.c
+
+tst-2-b_TEMPLATE = TSTDLL
+tst-2-b_SOURCES  = tst-2-b.c tstDllMain.c
+
+tst-2-c_TEMPLATE = TSTDLL
+tst-2-c_SOURCES  = tst-2-c.c tstDllMain.c
+
+tst-2-d_TEMPLATE = TSTDLL
+tst-2-d_SOURCES  = tst-2-d.c tstDllMain.c
+
+tst-2_TEMPLATE   = TSTPROG
+tst-2_SOURCES    = tst-2.c
+
+ifeq ($(filter-out nt win win32 win64,$(BUILD_TARGET)),)
+tst-2-b_LIBS     = $(PATH_TARGET)/tst-2-a/tst-2-a.lib
+tst-2-c_LIBS     = $(PATH_TARGET)/tst-2-a/tst-2-a.lib
+tst-2-d_LIBS     = $(PATH_TARGET)/tst-2-a/tst-2-a.lib
+tst-2_LIBS       = $(TARGET_tst-2-b:.dll=.lib) $(TARGET_tst-2-c:.dll=.lib) $(TARGET_tst-2-d:.dll=.lib) $(TARGET_tst-2-a:.dll=.lib)
+else
+tst-2-b_LIBS     = $(TARGET_tst-2-b:-b=-a)
+tst-2-c_LIBS     = $(TARGET_tst-2-c:-c=-a)
+tst-2-d_LIBS     = $(TARGET_tst-2-d:-d=-a)
+tst-2_LIBS       = $(TARGET_tst-2-a) $(TARGET_tst-2-b) $(TARGET_tst-2-c) $(TARGET_tst-2-d)
+endif
+
+
+
+# generate rules.
+include $(PATH_KBUILD)/footer.kmk
+
+#$(error tst-2-a_LIBS=$(tst-2-a_LIBS))
Index: /trunk/kLdr/testcase/tst-1-a.c
===================================================================
--- /trunk/kLdr/testcase/tst-1-a.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-1-a.c	(revision 2841)
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "a";
+
+MY_IMPORT(int) FuncD(void);
+
+MY_EXPORT(int) FuncA(void)
+{
+    return FuncD();
+}
+
Index: /trunk/kLdr/testcase/tst-1-b.c
===================================================================
--- /trunk/kLdr/testcase/tst-1-b.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-1-b.c	(revision 2841)
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "b";
+
+MY_IMPORT(int) FuncD(void);
+
+MY_EXPORT(int) FuncB(void)
+{
+    return FuncD();
+}
+
Index: /trunk/kLdr/testcase/tst-1-c.c
===================================================================
--- /trunk/kLdr/testcase/tst-1-c.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-1-c.c	(revision 2841)
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "c";
+
+MY_IMPORT(int) FuncD(void);
+
+MY_EXPORT(int) FuncC(void)
+{
+    return FuncD();
+}
+
Index: /trunk/kLdr/testcase/tst-1-d.c
===================================================================
--- /trunk/kLdr/testcase/tst-1-d.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-1-d.c	(revision 2841)
@@ -0,0 +1,8 @@
+#include "tst.h"
+const char *g_pszName = "d";
+
+MY_EXPORT(int) FuncD(void)
+{
+    return 0;
+}
+
Index: /trunk/kLdr/testcase/tst-1.c
===================================================================
--- /trunk/kLdr/testcase/tst-1.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-1.c	(revision 2841)
@@ -0,0 +1,15 @@
+#include "tst.h"
+#include <stdio.h>
+
+MY_IMPORT(int) FuncA(void);
+MY_IMPORT(int) FuncB(void);
+MY_IMPORT(int) FuncC(void);
+
+int main()
+{
+    printf("graph:\n"
+           "  tst-1 -> a -> d\n"
+           "           b -> d\n"
+           "           c -> d\n");
+    return FuncA() + FuncB() + FuncC();
+}
Index: /trunk/kLdr/testcase/tst-2-a.c
===================================================================
--- /trunk/kLdr/testcase/tst-2-a.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-2-a.c	(revision 2841)
@@ -0,0 +1,8 @@
+#include "tst.h"
+const char *g_pszName = "a";
+
+MY_EXPORT(int) FuncA(void)
+{
+    return 0;
+}
+
Index: /trunk/kLdr/testcase/tst-2-b.c
===================================================================
--- /trunk/kLdr/testcase/tst-2-b.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-2-b.c	(revision 2841)
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "b";
+
+MY_IMPORT(int) FuncA(void);
+
+MY_EXPORT(int) FuncB(void)
+{
+    return FuncA();
+}
+
Index: /trunk/kLdr/testcase/tst-2-c.c
===================================================================
--- /trunk/kLdr/testcase/tst-2-c.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-2-c.c	(revision 2841)
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "c";
+
+MY_IMPORT(int) FuncA(void);
+
+MY_EXPORT(int) FuncC(void)
+{
+    return FuncA();
+}
+
Index: /trunk/kLdr/testcase/tst-2-d.c
===================================================================
--- /trunk/kLdr/testcase/tst-2-d.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-2-d.c	(revision 2841)
@@ -0,0 +1,10 @@
+#include "tst.h"
+const char *g_pszName = "d";
+
+MY_IMPORT(int) FuncA(void);
+
+MY_EXPORT(int) FuncD(void)
+{
+    return FuncA();
+}
+
Index: /trunk/kLdr/testcase/tst-2.c
===================================================================
--- /trunk/kLdr/testcase/tst-2.c	(revision 2841)
+++ /trunk/kLdr/testcase/tst-2.c	(revision 2841)
@@ -0,0 +1,16 @@
+#include "tst.h"
+
+MY_IMPORT(int) FuncA(void);
+MY_IMPORT(int) FuncB(void);
+MY_IMPORT(int) FuncC(void);
+MY_IMPORT(int) FuncD(void);
+
+int main()
+{
+    printf("graph:\n"
+           "  tst-2 -> b -> a\n"
+           "           c -> a\n"
+           "           d -> a\n"
+           "           a\n");
+    return FuncA() + FuncB() + FuncC() + FuncD();
+}
Index: /trunk/kLdr/testcase/tst.h
===================================================================
--- /trunk/kLdr/testcase/tst.h	(revision 2841)
+++ /trunk/kLdr/testcase/tst.h	(revision 2841)
@@ -0,0 +1,48 @@
+/* $Id: $ */
+/** @file
+ *
+ * kLdr testcase.
+ *
+ * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
+ *
+ *
+ * This file is part of kLdr.
+ *
+ * kLdr 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.
+ *
+ * kLdr 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 kLdr; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef __tst_h__
+#define __tst_h__
+
+#include "../kLdr.h"
+#include "../kLdrHlp.h"
+
+
+#if defined(__OS2__) || defined(__WIN__)
+# define MY_EXPORT(type) __declspec(dllexport) type
+//# define MY_IMPORT(type) extern __declspec(dllimport) type
+# define MY_IMPORT(type) extern type
+#else
+# define MY_EXPORT(type) type
+# define MY_IMPORT(type) extern type
+#endif
+
+
+extern const char *g_pszName;
+
+#endif
+
Index: /trunk/kLdr/testcase/tstDllMain.c
===================================================================
--- /trunk/kLdr/testcase/tstDllMain.c	(revision 2841)
+++ /trunk/kLdr/testcase/tstDllMain.c	(revision 2841)
@@ -0,0 +1,178 @@
+/* $Id: $ */
+/** @file
+ *
+ * kLdr testcase.
+ *
+ * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
+ *
+ *
+ * This file is part of kLdr.
+ *
+ * kLdr 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.
+ *
+ * kLdr 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 kLdr; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "tst.h"
+
+#ifdef __OS2__
+# define INCL_BASE
+# include <os2.h>
+# include <string.h>
+
+#elif defined(__WIN__)
+# include <windows.h>
+# include <string.h>
+
+#else
+# error "port me"
+#endif
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static void tstWrite(const char *psz);
+
+
+
+#ifdef __OS2__
+/**
+ * OS/2 DLL 'main'
+ */
+ULONG _System _DLL_InitTerm(HMODULE hmod, ULONG fFlag)
+{
+    switch (fFlags)
+    {
+        case 0:
+            tstWrite("init: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        case 1:
+            tstWrite("term: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        default:
+            tstWrite("!invalid!: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return FALSE;
+    }
+}
+
+#elif defined(__WIN__)
+
+/**
+ * OS/2 DLL 'main'
+ */
+BOOL __stdcall DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
+{
+    switch (dwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            tstWrite("init: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        case DLL_PROCESS_DETACH:
+            tstWrite("term: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        case DLL_THREAD_ATTACH:
+            tstWrite("thread init: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        case DLL_THREAD_DETACH:
+            tstWrite("thread term: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return TRUE;
+
+        default:
+            tstWrite("!invalid!: ");
+            tstWrite(g_pszName);
+            tstWrite("\n");
+            return FALSE;
+    }
+}
+
+#else
+# error "port me"
+#endif
+
+
+/**
+ * Writes a string with unix lineendings.
+ *
+ * @param   pszMsg  The string.
+ */
+static void tstWrite(const char *pszMsg)
+{
+#if defined(__OS2__) || defined(__WIN__)
+    /*
+     * Line by line.
+     */
+    ULONG       cbWritten;
+    const char *pszNl = strchr(pszMsg, '\n');
+
+    while (pszNl)
+    {
+        cbWritten = pszNl - pszMsg;
+
+#ifdef __OS2__
+        if (cbWritten)
+            DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
+        DosWrite((HFILE)2, "\r\n", 2, &cbWritten);
+#else /* __WIN32__ */
+        if (cbWritten)
+            WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
+        WriteFile((HANDLE)STD_ERROR_HANDLE, "\r\n", 2, &cbWritten, NULL);
+#endif
+
+        /* next */
+        pszMsg = pszNl + 1;
+        pszNl = strchr(pszMsg, '\n');
+    }
+
+    /*
+     * Remaining incomplete line.
+     */
+    if (*pszMsg)
+    {
+        cbWritten = strlen(pszMsg);
+#ifdef __OS2__
+        DosWrite((HFILE)2, pszMsg, cbWritten, &cbWritten);
+#else /* __WIN32__ */
+        WriteFile((HANDLE)STD_ERROR_HANDLE, pszMsg, cbWritten, &cbWritten, NULL);
+#endif
+    }
+
+#else
+# error "port me"
+#endif
+}
+
+
