Index: trunk/src/emx/Makefile
===================================================================
--- trunk/src/emx/Makefile	(revision 1156)
+++ trunk/src/emx/Makefile	(revision 1157)
@@ -105,10 +105,12 @@
 CFLAGS.omf  = -Zomf
 CFLAGS.prof = -pg
+CFLAGS.log  = -DDEBUG_LOGGING
 # The object files are put in subdirectory objectformat-targetkind,
 # we decompose object file name back and pick appropiate $CFLAGS
 CFLAGS.KIND = $(foreach x,$(subst -, ,$(firstword $(subst /, ,$(subst $.,,$@)))),$(CFLAGS.$x))
 # How to compile a .c file
-DO.COMPILE.c = $(CC) $(strip $(CFLAGS) $1) -o $@ $(srcdir)/$< -I$(dir $<)
-DO.COMPILE.s = $(call DO.COMPILE.c,-x assembler-with-cpp $1)
+DO.COMPILE.c = $(CC) -std=gnu99 $(strip $(CFLAGS) $1) -o $@ $(srcdir)/$< -I$(dir $<)
+# '-std=gnu99' doesn't work with '-x assembler-with-cpp', therefor no $(call DO.COMPILE.c).
+DO.COMPILE.s = $(CC) -x assembler-with-cpp $(strip $(CFLAGS) $1) -o $@ $(srcdir)/$< -I$(dir $<)
 
 # The linker
Index: trunk/src/emx/common.smak
===================================================================
--- trunk/src/emx/common.smak	(revision 1156)
+++ trunk/src/emx/common.smak	(revision 1157)
@@ -26,4 +26,7 @@
 .tmp += prof
 endif # neq ($(findstring prof,$(.TKIND)),)
+ifneq ($(findstring log,$(.TKIND)),)
+.tmp += log
+endif # neq ($(findstring log,$(.TKIND)),)
 .TKIND := $(.tmp)
 ifdef .TKVAR
Index: trunk/src/emx/include/emx/libclog.h
===================================================================
--- trunk/src/emx/include/emx/libclog.h	(revision 1157)
+++ trunk/src/emx/include/emx/libclog.h	(revision 1157)
@@ -0,0 +1,84 @@
+/* $Id$ */
+/** @file
+ *
+ * Debug Logging Features - internal libc use only.
+ *
+ * InnoTek Systemberatung GmbH confidential
+ *
+ * Copyright (c) 2004 InnoTek Systemberatung GmbH
+ * Author: knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ * All Rights Reserved
+ *
+ */
+
+#ifndef __LIBCLOG_H__
+#define __LIBCLOG_H__
+
+
+#ifdef DEBUG_LOGGING
+/*
+ * Logging is enabled.
+ */
+/**
+ * Output an enter function log message.
+ * An enter message is considered to be one line and is appended a newline if
+ * none was given.
+ *
+ * @returns Current timestamp.
+ * @param   pszFunction     Name of the function which was entered.
+ * @param   pszFormat       Format string to display arguments.
+ * @param   ...             Arguments to the format string.
+ */
+extern unsigned __libc_LogEnter(const char *pszFunction, const char *pszFormat, ...);
+/**
+ * Output a leave function log message.
+ * A leave message is considered to be one line and is appended a newline if
+ * none was given.
+ *
+ * @param   uEnterTS        The timestamp returned by LogEnter.
+ * @param   pszFunction     Name of the function which was entered.
+ * @param   pszFormat       Format string to display the result.
+ * @param   ...             Arguments to the format string.
+ */
+extern void     __libc_LogLeave(unsigned uEnterTS, const char *pszFunction, const char *pszFormat, ...);
+
+/**
+ * Output a log message.
+ * A log message is considered to be one line and is appended a newline if
+ * none was given.
+ *
+ * @param   uEnterTS        The timestamp returned by LogEnter.
+ * @param   pszFunction     Name of the function which was entered.
+ * @param   pszFormat       Format string for the message to log.
+ * @param   ...             Arguments to the format string.
+ */
+extern void     __libc_LogMsg(unsigned uEnterTS, const char *pszFunction, const char *pszFormat, ...);
+
+/** Macro to log a function entry. */
+#define LIBCLOG_ENTER(...) \
+    unsigned __libclog_uEnterTS__ = __libc_LogEnter(__PRETTY_FUNCTION__, __VA_ARGS__)
+#define LIBCLOG_LEAVE(...) \
+    __libc_LogLeave(__libclog_uEnterTS__, __PRETTY_FUNCTION__, __VA_ARGS__)
+#define LIBCLOG_MSG(...) \
+    __libc_LogLeave(__libclog_uEnterTS__, __PRETTY_FUNCTION__, __VA_ARGS__)
+
+#else
+/*
+ * Logging is disabled.
+ */
+#define LIBCLOG_ENTER(...) //hmm
+#define LIBCLOG_LEAVE(...)  do {} while (0)
+#define LIBCLOG_MSG(...)    do {} while (0)
+
+#endif
+
+/* helpers */
+#define LIBCLOG_RETURN_VOID()    do { LIBCLOG_LEAVE("ret void\n");                      return;      } while (0)
+#define LIBCLOG_RETURN_INT(rc)   do { LIBCLOG_LEAVE("ret %d (%#x)\n", (rc), (rc));      return (rc); } while (0)
+#define LIBCLOG_RETURN_UINT(rc)  do { LIBCLOG_LEAVE("ret %u (%#x)\n", (rc), (rc));      return (rc); } while (0)
+#define LIBCLOG_RETURN_LONG(rc)  do { LIBCLOG_LEAVE("ret %ld (%#lx)\n", (rc), (rc));    return (rc); } while (0)
+#define LIBCLOG_RETURN_ULONG(rc) do { LIBCLOG_LEAVE("ret %lu (%#lx)\n", (rc), (rc));    return (rc); } while (0)
+#define LIBCLOG_RETURN_P(rc)     do { LIBCLOG_LEAVE("ret %p\n", (rc));                  return (rc); } while (0)
+
+#endif
Index: trunk/src/emx/src/lib/app/app.smak
===================================================================
--- trunk/src/emx/src/lib/app/app.smak	(revision 1156)
+++ trunk/src/emx/src/lib/app/app.smak	(revision 1157)
@@ -19,4 +19,8 @@
 LIBC.DLL.OBJS += $(.OBJS)
 
+.TKIND	:= aout log
+.TARGET	:= libc_app_l.a
+include mklib.smak
+				
 .TKIND	:= aout prof
 .TARGET	:= libc_app_p.a
Index: trunk/src/emx/src/lib/startup/exit.c
===================================================================
--- trunk/src/emx/src/lib/startup/exit.c	(revision 1156)
+++ trunk/src/emx/src/lib/startup/exit.c	(revision 1157)
@@ -4,4 +4,5 @@
 #include <stdlib.h>
 #include <emx/startup.h>
+#include <emx/libclog.h>
 
 void (*_atexit_v[64])(void);
@@ -10,9 +11,14 @@
 void _STD(exit) (int ret)
 {
+  LIBCLOG_ENTER("ret=%d\n", ret);
   int i;
 
   for (i = _atexit_n-1; i >= 0; --i)
-    _atexit_v[i]();
+    {
+      LIBCLOG_MSG("calling _atexit[%d] %p\n", i, _atexit_v[i]);
+      _atexit_v[i]();
+    }
   _CRT_term ();
+  LIBCLOG_MSG("calling _exit\n");
   _exit (ret);
 }
Index: trunk/src/emx/src/lib/startup/startup.c
===================================================================
--- trunk/src/emx/src/lib/startup/startup.c	(revision 1156)
+++ trunk/src/emx/src/lib/startup/startup.c	(revision 1157)
@@ -9,4 +9,5 @@
 #include <emx/syscalls.h>
 #include <emx/startup.h>
+#include <emx/libclog.h>
 
 extern int __crtinit1__;
@@ -18,4 +19,5 @@
 int _CRT_init (void)
 {
+  LIBCLOG_ENTER("\n");
   static int startup_flag;
 
@@ -23,5 +25,5 @@
      _DLL_InitTerm() and by the application program's startup code). */
   if (startup_flag)
-    return 0;
+    LIBCLOG_RETURN_INT(0);
   startup_flag = 1;
 
@@ -36,5 +38,5 @@
   errno = 0;
 
-  return 0;
+  LIBCLOG_RETURN_INT(0);
 }
 
Index: trunk/src/emx/src/lib/sys/libclog.c
===================================================================
--- trunk/src/emx/src/lib/sys/libclog.c	(revision 1157)
+++ trunk/src/emx/src/lib/sys/libclog.c	(revision 1157)
@@ -0,0 +1,249 @@
+/* $Id$ */
+/** @file
+ *
+ * Debug Logging Facility - internal libc use only.
+ *
+ * InnoTek Systemberatung GmbH confidential
+ *
+ * Copyright (c) 2004 InnoTek Systemberatung GmbH
+ * Author: knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ * All Rights Reserved
+ *
+ */
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+#define CCHTMPMSGBUFFER 512
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <process.h>
+#undef DEBUG_LOGGING
+#define DEBUG_LOGGING                   /* need prototypes. */
+#include <emx/libclog.h>
+
+#define INCL_BASE
+#include <os2.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Logfile. */
+static HFILE    hLog = -1;
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static int openLog(void);
+static unsigned getTimestamp(void);
+static unsigned getTid(void);
+
+
+/**
+ * Opens the log file.
+ * @returns 0 on success.
+ * @returns -1 on failure.
+ */
+static int openLog(void)
+{
+    char        szFilename[256];
+    ULONG       ulAction;
+    int         rc;
+    char       *pszMsg;
+
+    if ((int)hLog >= 0)
+        return 0;
+
+    sprintf(szFilename, "libc_%04x.log", getpid());
+    rc = DosOpen(szFilename, &hLog, &ulAction, 0, FILE_NORMAL,
+                 OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
+                 OPEN_FLAGS_SEQUENTIAL | OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYWRITE | OPEN_ACCESS_WRITEONLY,
+                 NULL);
+    if (rc)
+        return -1;
+
+    /* write a log header */
+    pszMsg = alloca(CCHTMPMSGBUFFER);
+    if (pszMsg)
+    {
+        PTIB        pTib;
+        PPIB        pPib;
+        DATETIME    dt;
+        const char *psz;
+        ULONG       cb;
+        int         cch;
+
+        DosGetInfoBlocks(&pTib, &pPib);
+        DosGetDateTime(&dt);
+        if (DosQueryModuleName(pPib->pib_hmte, sizeof(szFilename), &szFilename[0]))
+            szFilename[0] = '\0';
+
+        cch = snprintf(pszMsg, CCHTMPMSGBUFFER,
+                       "Opened log at %04d-%02d-%02d %02d:%02d:%02d.%02d\n"
+                       "Process ID: %#x (%d) Parent PID: %#x (%d)\n",
+                       dt.year, dt.month, dt.day, dt.hours, dt.minutes, dt.seconds, dt.hundredths,
+                       (int)pPib->pib_ulpid, (unsigned)pPib->pib_ulpid, (int)pPib->pib_ulppid, (unsigned)pPib->pib_ulppid);
+        DosWrite(hLog, pszMsg, cch, &cb);
+
+        cch = snprintf(pszMsg, CCHTMPMSGBUFFER,
+                       "Exe hmte  : %#x (%s)\n",
+                       (unsigned)pPib->pib_hmte, szFilename);
+        DosWrite(hLog, pszMsg, cch, &cb);
+
+        cch = snprintf(pszMsg, CCHTMPMSGBUFFER,
+                       "First arg : %s\n"
+                       "Second arg: ",
+                       pPib->pib_pchcmd);
+        DosWrite(hLog, pszMsg, cch, &cb);
+
+        psz = pPib->pib_pchcmd + strlen(pPib->pib_pchcmd) + 1;
+        cch = strlen(psz);
+        DosWrite(hLog, psz, cch, &cb);
+        DosWrite(hLog, "\n", 1, &cb);
+    }
+    return 0;
+}
+
+
+/**
+ * Get ts. (milliseconds preferably)
+ */
+inline static unsigned getTimestamp(void)
+{
+    unsigned long ulTs = 0;
+    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &ulTs, sizeof(ulTs));
+    return (unsigned)ulTs;
+}
+
+
+/**
+ * Gets the current thread id.
+ */
+inline static unsigned getTid(void)
+{
+    PTIB    pTib;
+    PPIB    pPib;
+    DosGetInfoBlocks(&pTib, &pPib);
+    return pTib->tib_ptib2->tib2_ultid;
+}
+
+
+/**
+ * Output an enter function log message.
+ * An enter message is considered to be one line and is appended a newline if
+ * none was given.
+ *
+ * @returns Current timestamp.
+ * @param   pszFunction     Name of the function which was entered.
+ * @param   pszFormat       Format string to display arguments.
+ * @param   ...             Arguments to the format string.
+ */
+unsigned __libc_LogEnter(const char *pszFunction, const char *pszFormat, ...)
+{
+    unsigned    uTS = getTimestamp();
+    char       *pszMsg;
+    int         cch;
+    va_list     args;
+    ULONG       cb;
+
+    if ((int)hLog < 0 && openLog())
+        return 0;
+
+    pszMsg = alloca(CCHTMPMSGBUFFER);
+    if (!pszMsg)
+        return uTS;
+
+    cch = snprintf(pszMsg, CCHTMPMSGBUFFER, "%08x %02x Entr %s: ", uTS, getTid(), pszFunction);
+    va_start(args, pszFormat);
+    cch += vsnprintf(pszMsg + cch, CCHTMPMSGBUFFER - cch, pszFormat, args);
+    va_end(args);
+    if (cch >= CCHTMPMSGBUFFER)
+        memcpy(pszMsg + CCHTMPMSGBUFFER - 5, "...\n", 5);
+    else if (pszMsg[cch - 1] != '\n')
+        memcpy(&pszMsg[cch++], "\n", 2);
+
+    DosWrite(hLog, pszMsg, cch, &cb);
+    return uTS;
+}
+
+/**
+ * Output a leave function log message.
+ * A leave message is considered to be one line and is appended a newline if
+ * none was given.
+ *
+ * @param   uEnterTS        The timestamp returned by LogEnter.
+ * @param   pszFunction     Name of the function which was entered.
+ * @param   pszFormat       Format string to display the result.
+ * @param   ...             Arguments to the format string.
+ */
+void     __libc_LogLeave(unsigned uEnterTS, const char *pszFunction, const char *pszFormat, ...)
+{
+    unsigned    uTS = getTimestamp();
+    char       *pszMsg;
+    int         cch;
+    va_list     args;
+    ULONG       cb;
+
+    if ((int)hLog < 0 && openLog())
+        return;
+
+    pszMsg = alloca(CCHTMPMSGBUFFER);
+    if (!pszMsg)
+        return;
+
+    cch = snprintf(pszMsg, CCHTMPMSGBUFFER, "%08x %02x Leav %s (%2d ms): ", uTS, getTid(), pszFunction, uTS - uEnterTS);
+    va_start(args, pszFormat);
+    cch += vsnprintf(pszMsg + cch, CCHTMPMSGBUFFER - cch, pszFormat, args);
+    va_end(args);
+    if (cch >= CCHTMPMSGBUFFER)
+        memcpy(pszMsg + CCHTMPMSGBUFFER - 5, "...\n", 5);
+    else if (pszMsg[cch - 1] != '\n')
+        memcpy(&pszMsg[cch++], "\n", 2);
+    DosWrite(hLog, pszMsg, cch, &cb);
+}
+
+/**
+ * Output a log message.
+ * A log message is considered to be one line and is appended a newline if
+ * none was given.
+ *
+ * @param   uEnterTS        The timestamp returned by LogEnter.
+ * @param   pszFunction     Name of the function which was entered.
+ * @param   pszFormat       Format string for the message to log.
+ * @param   ...             Arguments to the format string.
+ */
+void     __libc_LogMsg(unsigned uEnterTS, const char *pszFunction, const char *pszFormat, ...)
+{
+    unsigned    uTS = getTimestamp();
+    char       *pszMsg;
+    int         cch;
+    ULONG       cb;
+    va_list     args;
+
+    if ((int)hLog < 0 && openLog())
+        return;
+
+    pszMsg = alloca(CCHTMPMSGBUFFER);
+    if (!pszMsg)
+        return;
+
+    cch = snprintf(pszMsg, CCHTMPMSGBUFFER, "%08x %02x Msg  %s (%2d ms): ", uTS, getTid(), pszFunction, uTS - uEnterTS);
+    va_start(args, pszFormat);
+    cch += vsnprintf(pszMsg + cch, CCHTMPMSGBUFFER - cch, pszFormat, args);
+    va_end(args);
+    if (cch >= CCHTMPMSGBUFFER)
+        memcpy(pszMsg + CCHTMPMSGBUFFER - 5, "...\n", 5);
+    else if (pszMsg[cch - 1] != '\n')
+        memcpy(&pszMsg[cch++], "\n", 2);
+    DosWrite(hLog, pszMsg, cch, &cb);
+}
+
