Removed CALL_LARGE_STACK support.
[wine.git] / dlls / ntdll / debugtools.c
blob9cc73b7c7bb0d34d10e9efa415f8255c95efc477
1 /*
2 * Debugging functions
3 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <ctype.h>
11 #include "debugtools.h"
12 #include "thread.h"
13 #include "winbase.h"
14 #include "winnt.h"
15 #include "wtypes.h"
17 /* ---------------------------------------------------------------------- */
19 struct debug_info
21 char *str_pos; /* current position in strings buffer */
22 char *out_pos; /* current position in output buffer */
23 char strings[504]; /* buffer for temporary strings */
24 char output[504]; /* current output line */
27 static struct debug_info tmp;
29 /* get the debug info pointer for the current thread */
30 static inline struct debug_info *get_info(void)
32 struct debug_info *info = NtCurrentTeb()->debug_info;
33 if (!info)
35 if (!tmp.str_pos)
37 tmp.str_pos = tmp.strings;
38 tmp.out_pos = tmp.output;
40 if (!GetProcessHeap()) return &tmp;
41 /* setup the temp structure in case HeapAlloc wants to print something */
42 NtCurrentTeb()->debug_info = &tmp;
43 info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
44 info->str_pos = info->strings;
45 info->out_pos = info->output;
46 NtCurrentTeb()->debug_info = info;
48 return info;
51 /* allocate some tmp space for a string */
52 static void *gimme1(int n)
54 struct debug_info *info = get_info();
55 char *res = info->str_pos;
57 if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
58 info->str_pos = res + n;
59 return res;
62 /* release extra space that we requested in gimme1() */
63 static inline void release( void *ptr )
65 struct debug_info *info = NtCurrentTeb()->debug_info;
66 info->str_pos = ptr;
69 /***********************************************************************
70 * wine_dbgstr_an
72 const char *wine_dbgstr_an( const char *src, int n )
74 char *dst, *res;
76 if (!HIWORD(src))
78 if (!src) return "(null)";
79 res = gimme1(6);
80 sprintf(res, "#%04x", LOWORD(src) );
81 return res;
83 if (n < 0) n = 0;
84 dst = res = gimme1 (n * 4 + 6);
85 *dst++ = '"';
86 while (n-- > 0 && *src)
88 unsigned char c = *src++;
89 switch (c)
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
101 *dst++ = '\\';
102 *dst++ = '0' + ((c >> 6) & 7);
103 *dst++ = '0' + ((c >> 3) & 7);
104 *dst++ = '0' + ((c >> 0) & 7);
108 *dst++ = '"';
109 if (*src)
111 *dst++ = '.';
112 *dst++ = '.';
113 *dst++ = '.';
115 *dst++ = '\0';
116 release( dst );
117 return res;
120 /***********************************************************************
121 * wine_dbgstr_wn
123 const char *wine_dbgstr_wn( const WCHAR *src, int n )
125 char *dst, *res;
127 if (!HIWORD(src))
129 if (!src) return "(null)";
130 res = gimme1(6);
131 sprintf(res, "#%04x", LOWORD(src) );
132 return res;
134 if (n < 0) n = 0;
135 dst = res = gimme1 (n * 5 + 7);
136 *dst++ = 'L';
137 *dst++ = '"';
138 while (n-- > 0 && *src)
140 WCHAR c = *src++;
141 switch (c)
143 case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
144 case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
145 case '\t': *dst++ = '\\'; *dst++ = 't'; break;
146 case '"': *dst++ = '\\'; *dst++ = '"'; break;
147 case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
148 default:
149 if (c >= ' ' && c <= 126)
150 *dst++ = c;
151 else
153 *dst++ = '\\';
154 sprintf(dst,"%04x",c);
155 dst+=4;
159 *dst++ = '"';
160 if (*src)
162 *dst++ = '.';
163 *dst++ = '.';
164 *dst++ = '.';
166 *dst++ = '\0';
167 release( dst );
168 return res;
171 /***********************************************************************
172 * wine_dbgstr_guid
174 const char *wine_dbgstr_guid( const GUID *id )
176 char *str;
178 if (!id) return "(null)";
179 if (!HIWORD(id))
181 str = gimme1(12);
182 sprintf( str, "<guid-0x%04x>", LOWORD(id) );
184 else
186 str = gimme1(40);
187 sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
188 id->Data1, id->Data2, id->Data3,
189 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
190 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
192 return str;
195 /***********************************************************************
196 * wine_dbg_vprintf
198 int wine_dbg_vprintf( const char *format, va_list args )
200 struct debug_info *info = get_info();
202 int ret = vsprintf( info->out_pos, format, args );
203 char *p = strrchr( info->out_pos, '\n' );
204 if (!p) info->out_pos += ret;
205 else
207 char *pos = info->output;
208 p++;
209 write( 2, pos, p - pos );
210 /* move beginning of next line to start of buffer */
211 while ((*pos = *p++)) pos++;
212 info->out_pos = pos;
214 return ret;
217 /***********************************************************************
218 * wine_dbg_printf
220 int wine_dbg_printf(const char *format, ...)
222 int ret;
223 va_list valist;
225 va_start(valist, format);
226 ret = wine_dbg_vprintf( format, valist );
227 va_end(valist);
228 return ret;
231 /***********************************************************************
232 * wine_dbg_log
234 int wine_dbg_log(enum __DEBUG_CLASS cls, const char *channel,
235 const char *function, const char *format, ... )
237 static const char *classes[__DBCL_COUNT] = { "fixme", "err", "warn", "trace" };
238 va_list valist;
239 int ret = 0;
241 va_start(valist, format);
242 if (cls < __DBCL_COUNT)
243 ret = wine_dbg_printf( "%s:%s:%s ", classes[cls], channel + 1, function );
244 if (format)
245 ret += wine_dbg_vprintf( format, valist );
246 va_end(valist);
247 return ret;