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