branch update for HEAD-2003050101
[reactos.git] / lib / winedbgc / winedbgc.c
1 /*
2  * Debugging channels functions for WINE support on ROS.
3  */
4 #include <windows.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include "porting.h"
8 #include "trace.h"
9
10 //#include <ntddk.h>
11 #include <wine/debugtools.h>
12
13 DECLARE_DEBUG_CHANNEL(winedbgc);
14
15
16 /* ---------------------------------------------------------------------- */
17
18 struct debug_info
19 {
20     char *str_pos;       /* current position in strings buffer */
21     char *out_pos;       /* current position in output buffer */
22     char  strings[1024]; /* buffer for temporary strings */
23     char  output[1024];  /* current output line */
24 };
25
26 static struct debug_info tmp;
27
28 /* get the debug info pointer for the current thread */
29 static inline struct debug_info *get_info(void)
30 {
31     struct debug_info *info = NtCurrentTeb()->WineDebugInfo;
32     if (!info)
33     {
34         if (!tmp.str_pos)
35         {
36             tmp.str_pos = tmp.strings;
37             tmp.out_pos = tmp.output;
38         }
39         if (!RtlGetProcessHeap()) return &tmp;
40         /* setup the temp structure in case HeapAlloc wants to print something */
41         NtCurrentTeb()->WineDebugInfo = &tmp;
42         info = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*info));
43         info->str_pos = info->strings;
44         info->out_pos = info->output;
45         NtCurrentTeb()->WineDebugInfo = info;
46     }
47     return info;
48 }
49
50 /* allocate some tmp space for a string */
51 static void *gimme1(int n)
52 {
53     struct debug_info *info = get_info();
54     char *res = info->str_pos;
55
56     if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
57     info->str_pos = res + n;
58     return res;
59 }
60
61 /* release extra space that we requested in gimme1() */
62 static inline void release(void *ptr)
63 {
64     struct debug_info *info = NtCurrentTeb()->WineDebugInfo;
65     info->str_pos = ptr;
66 }
67
68 /***********************************************************************
69  *              wine_dbgstr_an (NTDLL.@)
70  */
71 const char *wine_dbgstr_an(const char *src, int n)
72 {
73     char *dst, *res;
74
75     if (!((WORD)(DWORD)(src) >> 16))
76     {
77         if (!src) return "(null)";
78         res = gimme1(6);
79         sprintf(res, "#%04x", (WORD)(DWORD)(src) );
80         return res;
81     }
82     if (n < 0) n = 0;
83     else if (n > 200) n = 200;
84     dst = res = gimme1 (n * 4 + 6);
85     *dst++ = '"';
86     while (n-- > 0 && *src)
87     {
88         unsigned char c = *src++;
89         switch (c)
90         {
91         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
92         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
93         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
94         case '"': *dst++ = '\\'; *dst++ = '"'; break;
95         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
96         default:
97             if (c >= ' ' && c <= 126)
98                 *dst++ = c;
99             else
100             {
101                 *dst++ = '\\';
102                 *dst++ = '0' + ((c >> 6) & 7);
103                 *dst++ = '0' + ((c >> 3) & 7);
104                 *dst++ = '0' + ((c >> 0) & 7);
105             }
106         }
107     }
108     *dst++ = '"';
109     if (*src)
110     {
111         *dst++ = '.';
112         *dst++ = '.';
113         *dst++ = '.';
114     }
115     *dst++ = '\0';
116     release( dst );
117     return res;
118 }
119
120 /***********************************************************************
121  *              wine_dbgstr_wn (NTDLL.@)
122  */
123 const char *wine_dbgstr_wn(const WCHAR *src, int n)
124 {
125     char *dst, *res;
126
127     if (!((WORD)(DWORD)(src) >> 16))
128     {
129         if (!src) return "(null)";
130         res = gimme1(6);
131         sprintf(res, "#%04x", (WORD)(DWORD)(src) );
132         return res;
133     }
134     if (n < 0) n = 0;
135     else if (n > 200) n = 200;
136     dst = res = gimme1(n * 5 + 7);
137     *dst++ = 'L';
138     *dst++ = '"';
139     while (n-- > 0 && *src)
140     {
141         WCHAR c = *src++;
142         switch (c)
143         {
144         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
145         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
146         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
147         case '"': *dst++ = '\\'; *dst++ = '"'; break;
148         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
149         default:
150             if (c >= ' ' && c <= 126)
151                 *dst++ = c;
152             else
153             {
154                 *dst++ = '\\';
155                 sprintf(dst,"%04x",c);
156                 dst+=4;
157             }
158         }
159     }
160     *dst++ = '"';
161     if (*src)
162     {
163         *dst++ = '.';
164         *dst++ = '.';
165         *dst++ = '.';
166     }
167     *dst++ = '\0';
168     release(dst);
169     return res;
170 }
171
172 /***********************************************************************
173  *              wine_dbgstr_guid (NTDLL.@)
174  */
175 const char *wine_dbgstr_guid(const GUID *id)
176 {
177     char *str;
178
179     if (!id) return "(null)";
180     if (!((WORD)(DWORD)(id) >> 16)) {
181         str = gimme1(12);
182         sprintf(str, "<guid-0x%04x>", (WORD)(DWORD)(id));
183     } else {
184         str = gimme1(40);
185         sprintf(str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
186                 id->Data1, id->Data2, id->Data3,
187                 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
188                 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7]);
189     }
190     return str;
191 }
192
193 /***********************************************************************
194  *              wine_dbg_vprintf (NTDLL.@)
195  */
196 int wine_dbg_vprintf(const char *format, va_list args)
197 {
198     struct debug_info *info = get_info();
199     char *p;
200
201     int ret = _vsnprintf(info->out_pos, sizeof(info->output) - (info->out_pos - info->output),
202                          format, args);
203
204     p = strrchr(info->out_pos, '\n');
205     if (!p) {
206         info->out_pos += ret;
207     } else {
208         char *pos = info->output;
209         char saved_ch;
210         p++;
211         saved_ch = *p;
212         *p = 0;
213         DbgPrint(pos);
214         *p = saved_ch;
215         /* move beginning of next line to start of buffer */
216         while ((*pos = *p++)) pos++;
217         info->out_pos = pos;
218     }
219     return ret;
220 }
221
222 /***********************************************************************
223  *              wine_dbg_printf (NTDLL.@)
224  */
225 int wine_dbg_printf(const char *format, ...)
226 {
227     int ret;
228     va_list valist;
229
230     va_start(valist, format);
231 //
232     Trace(format, valist);
233 //
234     ret = wine_dbg_vprintf(format, valist);
235     va_end(valist);
236     return ret;
237 }
238
239 /***********************************************************************
240  *              wine_dbg_log (NTDLL.@)
241  */
242 int wine_dbg_log(enum __DEBUG_CLASS cls, const char *channel,
243                  const char *function, const char *format, ...)
244 {
245     static const char *classes[__DBCL_COUNT] = { "fixme", "err", "warn", "trace" };
246     va_list valist;
247     int ret = 0;
248
249     va_start(valist, format);
250     if (TRACE_ON(winedbgc))
251         ret = wine_dbg_printf("%08lx:", NtCurrentTeb()->Cid.UniqueThread);
252     if (cls < __DBCL_COUNT)
253         ret += wine_dbg_printf("%s:%s:%s ", classes[cls], channel + 1, function);
254     if (format)
255         ret += wine_dbg_vprintf(format, valist);
256     va_end(valist);
257     return ret;
258 }