Mostly minor updates to the source tree for portcls.
[reactos.git] / reactos / lib / 3rdparty / libwine / debug.c
1 /*
2 * Management of the debugging channels
3 *
4 * Copyright 2000 Alexandre Julliard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <windows.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <tchar.h>
25
26 #include <wine/config.h>
27 #include <wine/port.h>
28 #include <wine/debug.h>
29
30 /* ---------------------------------------------------------------------- */
31
32 static CRITICAL_SECTION WineDebugCS;
33 static CRITICAL_SECTION_DEBUG critsect_debug =
34 {
35 0, 0, &WineDebugCS,
36 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
37 0, 0, { 0, 0 }
38 };
39 static CRITICAL_SECTION WineDebugCS = { &critsect_debug, -1, 0, 0, 0, 0 };
40 static DWORD WineDebugTlsIndex = TLS_OUT_OF_INDEXES;
41
42 /* ---------------------------------------------------------------------- */
43
44 struct debug_info
45 {
46 char *str_pos; /* current position in strings buffer */
47 char *out_pos; /* current position in output buffer */
48 char strings[1024]; /* buffer for temporary strings */
49 char output[1024]; /* current output line */
50 };
51
52 static struct debug_info tmp = { tmp.strings, tmp.output };
53
54 /* get the debug info pointer for the current thread */
55 static inline struct debug_info *get_info(void)
56 {
57 struct debug_info *info;
58
59 if (WineDebugTlsIndex == TLS_OUT_OF_INDEXES)
60 {
61 EnterCriticalSection(&WineDebugCS);
62 if (WineDebugTlsIndex == TLS_OUT_OF_INDEXES)
63 {
64 DWORD NewTlsIndex = TlsAlloc();
65 if (NewTlsIndex == TLS_OUT_OF_INDEXES)
66 {
67 LeaveCriticalSection(&WineDebugCS);
68 return &tmp;
69 }
70 info = HeapAlloc(GetProcessHeap(), 0, sizeof(*info));
71 if (!info)
72 {
73 LeaveCriticalSection(&WineDebugCS);
74 TlsFree(NewTlsIndex);
75 return &tmp;
76 }
77 info->str_pos = info->strings;
78 info->out_pos = info->output;
79 TlsSetValue(NewTlsIndex, info);
80 WineDebugTlsIndex = NewTlsIndex;
81 }
82 LeaveCriticalSection(&WineDebugCS);
83 }
84
85 return TlsGetValue(WineDebugTlsIndex);
86 }
87
88 /* allocate some tmp space for a string */
89 static void *gimme1(int n)
90 {
91 struct debug_info *info = get_info();
92 char *res = info->str_pos;
93
94 if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
95 info->str_pos = res + n;
96 return res;
97 }
98
99 /* release extra space that we requested in gimme1() */
100 static inline void release(void *ptr)
101 {
102 struct debug_info *info;
103 if (WineDebugTlsIndex == TLS_OUT_OF_INDEXES)
104 info = &tmp;
105 else
106 info = TlsGetValue(WineDebugTlsIndex);
107 info->str_pos = ptr;
108 }
109
110 /***********************************************************************
111 * wine_dbgstr_an
112 */
113 const char *wine_dbgstr_an(const char *src, int n)
114 {
115 char *dst, *res;
116
117 if (!HIWORD(src))
118 {
119 if (!src) return "(null)";
120 res = gimme1(6);
121 sprintf(res, "#%04x", (WORD)(DWORD)(src) );
122 return res;
123 }
124 if (n < 0) n = 0;
125 else if (n > 200) n = 200;
126 dst = res = gimme1 (n * 4 + 6);
127 *dst++ = '"';
128 while (n-- > 0 && *src)
129 {
130 unsigned char c = *src++;
131 switch (c)
132 {
133 case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
134 case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
135 case '\t': *dst++ = '\\'; *dst++ = 't'; break;
136 case '"': *dst++ = '\\'; *dst++ = '"'; break;
137 case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
138 default:
139 if (c >= ' ' && c <= 126)
140 *dst++ = c;
141 else
142 {
143 *dst++ = '\\';
144 *dst++ = '0' + ((c >> 6) & 7);
145 *dst++ = '0' + ((c >> 3) & 7);
146 *dst++ = '0' + ((c >> 0) & 7);
147 }
148 }
149 }
150 *dst++ = '"';
151 if (*src)
152 {
153 *dst++ = '.';
154 *dst++ = '.';
155 *dst++ = '.';
156 }
157 *dst++ = '\0';
158 release( dst );
159 return res;
160 }
161
162 /***********************************************************************
163 * wine_dbgstr_wn
164 */
165 const char *wine_dbgstr_wn(const WCHAR *src, int n)
166 {
167 char *dst, *res;
168
169 if (!HIWORD(src))
170 {
171 if (!src) return "(null)";
172 res = gimme1(6);
173 sprintf(res, "#%04x", (WORD)(DWORD)(src) );
174 return res;
175 }
176 if (n < 0) n = 0;
177 else if (n > 200) n = 200;
178 dst = res = gimme1(n * 5 + 7);
179 *dst++ = 'L';
180 *dst++ = '"';
181 while (n-- > 0 && *src)
182 {
183 WCHAR c = *src++;
184 switch (c)
185 {
186 case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
187 case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
188 case '\t': *dst++ = '\\'; *dst++ = 't'; break;
189 case '"': *dst++ = '\\'; *dst++ = '"'; break;
190 case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
191 default:
192 if (c >= ' ' && c <= 126)
193 *dst++ = c;
194 else
195 {
196 *dst++ = '\\';
197 sprintf(dst,"%04x",c);
198 dst+=4;
199 }
200 }
201 }
202 *dst++ = '"';
203 if (*src)
204 {
205 *dst++ = '.';
206 *dst++ = '.';
207 *dst++ = '.';
208 }
209 *dst++ = '\0';
210 release(dst);
211 return res;
212 }
213
214 /***********************************************************************
215 * wine_dbgstr_guid
216 */
217 const char *wine_dbgstr_guid(const GUID *id)
218 {
219 char *str;
220
221 if (!id) return "(null)";
222 if (!HIWORD(id)) {
223 str = gimme1(12);
224 sprintf(str, "<guid-0x%04x>", (WORD)(DWORD)(id));
225 } else {
226 str = gimme1(40);
227 sprintf(str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
228 id->Data1, id->Data2, id->Data3,
229 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
230 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7]);
231 }
232 return str;
233 }
234
235 const char *wine_dbgstr_longlong( unsigned long long ll )
236 {
237 if (ll >> 32) return wine_dbg_sprintf( "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll );
238 else return wine_dbg_sprintf( "%lx", (unsigned long)ll );
239 }
240
241 /* varargs wrapper for __wine_dbg_vsprintf */
242 const char *wine_dbg_sprintf( const char *format, ... )
243 {
244 char* buffer = gimme1(1024);
245 va_list ap;
246
247 va_start(ap, format);
248 release(buffer+vsnprintf(buffer, 1024, format, ap));
249 va_end(ap);
250
251 return buffer;
252 }
253
254 const char *wine_dbgstr_w( const WCHAR *s )
255 {
256 return wine_dbgstr_wn( s, -1 );
257 }