Use a per-thread buffer and write(2) for debug traces.
Removed debug_dumpstr.

diff --git a/if1632/relay.c b/if1632/relay.c
index c161d4f..ede3cd8 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -15,11 +15,10 @@
 #include "builtin16.h"
 #include "task.h"
 #include "syslevel.h"
-#include "debugstr.h"
 #include "debugtools.h"
 #include "main.h"
 
-DEFAULT_DEBUG_CHANNEL(relay)
+DEFAULT_DEBUG_CHANNEL(relay);
 
 /***********************************************************************
  *           RELAY_Init
@@ -143,20 +142,14 @@
                 DPRINTF( "0x%08x", *(int *)args16 );
                 args16 += 4;
                 break;
-            case 't':
-                DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
-                if (HIWORD(*(SEGPTR *)args16))
-                    debug_dumpstr( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 ));
-                args16 += 4;
-                break;
             case 'p':
                 DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
                 args16 += 4;
                 break;
+            case 't':
             case 'T':
-                DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
-                if (HIWORD( *(SEGPTR *)args16 ))
-                    debug_dumpstr( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 ));
+                DPRINTF( "%04x:%04x %s", *(WORD *)(args16+2), *(WORD *)args16,
+                         debugres_a( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 )) );
                 args16 += 4;
                 break;
             }
@@ -199,9 +192,8 @@
                 break;
             case 't':
                 args16 -= 4;
-                DPRINTF( "0x%08x", *(int *)args16 );
-                if (HIWORD(*(SEGPTR *)args16))
-                    debug_dumpstr( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 ));
+                DPRINTF( "0x%08x %s", *(int *)args16,
+                         debugres_a( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 )));
                 break;
             case 'p':
                 args16 -= 4;
@@ -209,9 +201,8 @@
                 break;
             case 'T':
                 args16 -= 4;
-                DPRINTF( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
-                if (HIWORD( *(SEGPTR *)args16 ))
-                    debug_dumpstr( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 ));
+                DPRINTF( "%04x:%04x %s", *(WORD *)(args16+2), *(WORD *)args16,
+                         debugres_a( (LPSTR)PTR_SEG_TO_LIN(*(SEGPTR *)args16 )));
                 break;
             }
             args++;
diff --git a/include/debugtools.h b/include/debugtools.h
index 2abc0f7..3071ec2 100644
--- a/include/debugtools.h
+++ b/include/debugtools.h
@@ -4,12 +4,15 @@
 
 #ifdef __WINE__  /* Debugging interface is internal to Wine */
 
+#include <stdarg.h>
 #include <stdio.h>
 #include "config.h"
-#include "debugstr.h"
+#include "windef.h"
 
 #define DEBUG_RUNTIME
 
+struct _GUID;
+
 /* Internal definitions (do not use these directly) */
 
 enum __DEBUG_CLASS { __DBCL_FIXME, __DBCL_ERR, __DBCL_WARN, __DBCL_TRACE, __DBCL_COUNT };
@@ -36,6 +39,25 @@
 
 /* Exported definitions and macros */
 
+/* These function return a printable version of a string, including
+   quotes.  The string will be valid for some time, but not indefinitely
+   as strings are re-used.  */
+extern LPSTR debugstr_an (LPCSTR s, int n);
+extern LPSTR debugstr_a (LPCSTR s);
+extern LPSTR debugstr_wn (LPCWSTR s, int n);
+extern LPSTR debugstr_w (LPCWSTR s);
+extern LPSTR debugres_a (LPCSTR res);
+extern LPSTR debugres_w (LPCWSTR res);
+extern LPSTR debugstr_guid( const struct _GUID *id );
+extern LPSTR debugstr_hex_dump (const void *ptr, int len);
+extern int dbg_vprintf( const char *format, va_list args );
+
+#ifdef __GNUC__
+extern int dbg_printf(const char *format, ...) __attribute__((format (printf,1,2)));
+#else
+extern int dbg_printf(const char *format, ...);
+#endif
+
 /* use configure to allow user to compile out debugging messages */
 #ifndef NO_TRACE_MSGS
 #define TRACE        __DPRINTF(__DBCL_TRACE,*DBCH_DEFAULT)
diff --git a/include/thread.h b/include/thread.h
index a08dc18..e1813b4 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -94,10 +94,11 @@
     int          socket;         /* --3 204 Socket for server communication */
     void        *buffer;         /* --3 208 Buffer shared with server */
     int          buffer_size;    /* --3 20c Size of server buffer */
+    void        *debug_info;     /* --3 210 Info for debugstr functions */
     /* here is plenty space for wine specific fields (don't forget to change pad6!!) */
 
     /* the following are nt specific fields */
-    DWORD        pad6[634];                  /* --n 210 */
+    DWORD        pad6[633];                  /* --n 214 */
     UNICODE_STRING StaticUnicodeString;      /* -2- bf8 used by advapi32 */
     USHORT       StaticUnicodeBuffer[261];   /* -2- c00 used by advapi32 */
     DWORD        pad7;                       /* --n e0c */
diff --git a/misc/debugstr.c b/misc/debugstr.c
index c505e6c..9c5fd30 100644
--- a/misc/debugstr.c
+++ b/misc/debugstr.c
@@ -1,30 +1,46 @@
-#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <ctype.h>
 
-#include "debugstr.h"
 #include "debugtools.h"
 #include "wtypes.h"
-#include "xmalloc.h"
+#include "thread.h"
 
 /* ---------------------------------------------------------------------- */
 
-#define SAVE_STRING_COUNT 50
-static void *strings[SAVE_STRING_COUNT];
-static int nextstring;
+struct debug_info
+{
+    char *str_pos;       /* current position in strings buffer */
+    char *out_pos;       /* current position in output buffer */
+    char  strings[500];  /* buffer for temporary strings */
+    char  output[500];   /* current output line */
+};
+
+static inline struct debug_info *get_info(void)
+{
+    struct debug_info *info = NtCurrentTeb()->debug_info;
+    if (!info)
+    {
+        NtCurrentTeb()->debug_info = info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
+        info->str_pos = info->strings;
+        info->out_pos = info->output;
+    }
+    return info;
+}
 
 /* ---------------------------------------------------------------------- */
 
 static void *
 gimme1 (int n)
 {
-  void *res;
-  if (strings[nextstring]) free (strings[nextstring]);
-  res = strings[nextstring] = xmalloc (n);
-  if (++nextstring == SAVE_STRING_COUNT) nextstring = 0;
-  return res;
+    struct debug_info *info = get_info();
+    char *res = info->str_pos;
+
+    if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
+    info->str_pos = res + n;
+    return res;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -176,39 +192,23 @@
 
 /* ---------------------------------------------------------------------- */
 
-void debug_dumpstr (LPCSTR s)
+int dbg_vprintf( const char *format, va_list args )
 {
-  fputc ('"', stderr);
-  while (*s)
+    struct debug_info *info = get_info();
+
+    int ret = vsprintf( info->out_pos, format, args );
+    char *p = strrchr( info->out_pos, '\n' );
+    if (!p) info->out_pos += ret;
+    else
     {
-      switch (*s)
-	{
-	case '\\':
-	case '"':
-	  fputc ('\\', stderr);
-	  fputc (*s, stderr);
-	  break;
-	case '\n':
-	  fputc ('\\', stderr);
-	  fputc ('n', stderr);
-	  break;
-	case '\r':
-	  fputc ('\\', stderr);
-	  fputc ('r', stderr);
-	  break;
-	case '\t':
-	  fputc ('\\', stderr);
-	  fputc ('t', stderr);
-	  break;
-	default:
-	  if (*s<' ')
-	    fprintf (stderr, "\\0x%02x", *s);
-	  else
-	    fputc (*s, stderr);
-	}
-      s++;
+        char *pos = info->output;
+        p++;
+        write( 2, pos, p - pos );
+        /* move beginning of next line to start of buffer */
+        while ((*pos = *p++)) pos++;
+        info->out_pos = pos;
     }
-  fputc ('"', stderr);
+    return ret;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -219,7 +219,7 @@
     va_list valist;
 
     va_start(valist, format);
-    ret = vfprintf(stderr, format, valist);
+    ret = dbg_vprintf( format, valist);
     va_end(valist);
     return ret;
 }
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 247d4b5..f36ccc1 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -165,6 +165,7 @@
     SELECTOR_FreeBlock( teb->teb_sel, 1 );
     close( teb->socket );
     if (teb->buffer) munmap( teb->buffer, teb->buffer_size );
+    if (teb->debug_info) HeapFree( GetProcessHeap(), 0, teb->debug_info );
     VirtualFree( teb->stack_base, 0, MEM_RELEASE );
     VirtualFree( teb, 0, MEM_FREE );
 }