ReactOS 0.4.17-dev-934-g091855f
debug.c
Go to the documentation of this file.
1/*
2 * Copyright 2016 Józef Kucia for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#ifdef _WIN32
20# define _WIN32_WINNT 0x0600 /* For InitOnceExecuteOnce(). */
21#endif
22
23#include "vkd3d_common.h"
24
25#include <ctype.h>
26#include <errno.h>
27#include <inttypes.h>
28#include <limits.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <stdbool.h>
32#include <string.h>
33#include <unistd.h>
34#ifdef HAVE_PTHREAD_H
35#include <pthread.h>
36#endif
37
38#include "vkd3d_memory.h"
39
40#define VKD3D_DEBUG_BUFFER_COUNT 64
41#define VKD3D_DEBUG_BUFFER_SIZE 512
42
43extern const char *const vkd3d_dbg_env_name;
44
45static const char *const debug_level_names[] =
46{
47 [VKD3D_DBG_LEVEL_NONE ] = "none",
48 [VKD3D_DBG_LEVEL_MESSAGE] = "message",
49 [VKD3D_DBG_LEVEL_ERR ] = "err",
50 [VKD3D_DBG_LEVEL_FIXME] = "fixme",
51 [VKD3D_DBG_LEVEL_WARN ] = "warn",
52 [VKD3D_DBG_LEVEL_TRACE] = "trace",
53};
54
56{
57 static unsigned int level = ~0u;
58 const char *vkd3d_debug;
59 unsigned int i;
60
61 if (level != ~0u)
62 return level;
63
64 if (!(vkd3d_debug = getenv(vkd3d_dbg_env_name)))
65 vkd3d_debug = "";
66
67 for (i = 0; i < ARRAY_SIZE(debug_level_names); ++i)
68 {
69 if (!strcmp(debug_level_names[i], vkd3d_debug))
70 {
71 level = i;
72 return level;
73 }
74 }
75
76 /* Default debug level. */
78 return level;
79}
80
82
83static void vkd3d_dbg_voutput(const char *fmt, va_list args)
84{
85 if (log_callback)
87 else
89}
90
91static void vkd3d_dbg_output(const char *fmt, ...)
92{
94
97 va_end(args);
98}
99
100void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function, const char *fmt, ...)
101{
103
105 return;
106
107#ifdef _WIN32
108 vkd3d_dbg_output("vkd3d:%04lx:%s:%s ", GetCurrentThreadId(), debug_level_names[level], function);
109#elif HAVE_GETTID
110 vkd3d_dbg_output("vkd3d:%u:%s:%s ", gettid(), debug_level_names[level], function);
111#else
112 vkd3d_dbg_output("vkd3d:%s:%s ", debug_level_names[level], function);
113#endif
114 va_start(args, fmt);
116 va_end(args);
117}
118
120{
122}
123
124static char *get_buffer(void)
125{
127 static unsigned int buffer_index;
128 unsigned int current_index;
129
130 current_index = vkd3d_atomic_increment_u32(&buffer_index) % ARRAY_SIZE(buffers);
131 return buffers[current_index];
132}
133
134const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args)
135{
136 char *buffer;
137
138 buffer = get_buffer();
141 return buffer;
142}
143
144const char *vkd3d_dbg_sprintf(const char *fmt, ...)
145{
146 const char *buffer;
148
149 va_start(args, fmt);
151 va_end(args);
152 return buffer;
153}
154
155static int get_escape_char(int c)
156{
157 switch (c)
158 {
159 case '"':
160 case '\\':
161 return c;
162 case '\t':
163 return 't';
164 case '\n':
165 return 'n';
166 case '\r':
167 return 'r';
168 default:
169 return 0;
170 }
171}
172
173const char *debugstr_an(const char *str, size_t n)
174{
175 char *buffer, *ptr;
176 int escape_char;
177 char c;
178
179 if (!str)
180 return "(null)";
181 if (n == SIZE_MAX)
182 n = strlen(str);
183
184 ptr = buffer = get_buffer();
185
186 *ptr++ = '"';
187 while (n-- && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 8)
188 {
189 c = *str++;
190
191 if ((escape_char = get_escape_char(c)))
192 {
193 *ptr++ = '\\';
194 *ptr++ = escape_char;
195 continue;
196 }
197
198 if (isprint(c))
199 {
200 *ptr++ = c;
201 }
202 else
203 {
204 *ptr++ = '\\';
205 sprintf(ptr, "%02x", c);
206 ptr += 2;
207 }
208 }
209 *ptr++ = '"';
210
211 if (++n)
212 {
213 *ptr++ = '.';
214 *ptr++ = '.';
215 *ptr++ = '.';
216 }
217 *ptr = '\0';
218
219 return buffer;
220}
221
222const char *debugstr_a(const char *str)
223{
224 return debugstr_an(str, SIZE_MAX);
225}
226
227static const char *debugstr_w16(const uint16_t *wstr)
228{
229 char *buffer, *ptr;
230 uint16_t c;
231
232 if (!wstr)
233 return "(null)";
234
235 ptr = buffer = get_buffer();
236
237 *ptr++ = '"';
238 while ((c = *wstr++) && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 10)
239 {
240 int escape_char = get_escape_char(c);
241
242 if (escape_char)
243 {
244 *ptr++ = '\\';
245 *ptr++ = escape_char;
246 continue;
247 }
248
249 if (isprint(c))
250 {
251 *ptr++ = c;
252 }
253 else
254 {
255 *ptr++ = '\\';
256 sprintf(ptr, "%04x", c);
257 ptr += 4;
258 }
259 }
260 *ptr++ = '"';
261
262 if (c)
263 {
264 *ptr++ = '.';
265 *ptr++ = '.';
266 *ptr++ = '.';
267 }
268 *ptr = '\0';
269
270 return buffer;
271}
272
273static const char *debugstr_w32(const uint32_t *wstr)
274{
275 char *buffer, *ptr;
276 uint32_t c;
277
278 if (!wstr)
279 return "(null)";
280
281 ptr = buffer = get_buffer();
282
283 *ptr++ = '"';
284 while ((c = *wstr++) && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 10)
285 {
286 int escape_char = get_escape_char(c);
287
288 if (escape_char)
289 {
290 *ptr++ = '\\';
291 *ptr++ = escape_char;
292 continue;
293 }
294
295 if (isprint(c))
296 {
297 *ptr++ = c;
298 }
299 else
300 {
301 *ptr++ = '\\';
302 sprintf(ptr, "%04x", c);
303 ptr += 4;
304 }
305 }
306 *ptr++ = '"';
307
308 if (c)
309 {
310 *ptr++ = '.';
311 *ptr++ = '.';
312 *ptr++ = '.';
313 }
314 *ptr = '\0';
315
316 return buffer;
317}
318
319const char *debugstr_w(const WCHAR *wstr, size_t wchar_size)
320{
321 if (wchar_size == 2)
322 return debugstr_w16((const uint16_t *)wstr);
323 return debugstr_w32((const uint32_t *)wstr);
324}
325
326unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value)
327{
328 const char *value = getenv(name);
329 unsigned long r;
330 char *end_ptr;
331
332 if (value)
333 {
334 errno = 0;
335 r = strtoul(value, &end_ptr, 0);
336 if (!errno && end_ptr != value)
337 return min(r, UINT_MAX);
338 }
339
340 return default_value;
341}
342
343static bool is_option_separator(char c)
344{
345 return c == ',' || c == ';' || c == '\0';
346}
347
348bool vkd3d_debug_list_has_member(const char *string, const char *member)
349{
350 char prev_char, next_char;
351 const char *p;
352
353 p = string;
354 while (p)
355 {
356 if ((p = strstr(p, member)))
357 {
358 prev_char = p > string ? p[-1] : 0;
359 p += strlen(member);
360 next_char = *p;
361
362 if (is_option_separator(prev_char) && is_option_separator(next_char))
363 return true;
364 }
365 }
366
367 return false;
368}
369
371 const struct vkd3d_debug_option *options, unsigned int option_count)
372{
373 uint64_t flags = 0;
374 unsigned int i;
375
376 for (i = 0; i < option_count; ++i)
377 {
378 const struct vkd3d_debug_option *opt = &options[i];
379
380 if (vkd3d_debug_list_has_member(string, opt->name))
381 flags |= opt->flag;
382 }
383
384 return flags;
385}
386
387#ifdef _WIN32
388
389static HRESULT (WINAPI *pfn_SetThreadDescription)(HANDLE, const WCHAR *);
390static BOOL WINAPI resolve_SetThreadDescription(INIT_ONCE *once, void *param, void **context)
391{
392 HMODULE kernelbase;
393
394 if (!(kernelbase = LoadLibraryA("kernelbase.dll")))
395 return TRUE;
396
397 if (!(pfn_SetThreadDescription = (void *)GetProcAddress(kernelbase, "SetThreadDescription")))
398 FreeLibrary(kernelbase);
399
400 return TRUE;
401}
402
403#endif
404
406{
407#ifdef _WIN32
409 WCHAR *wname;
410 int ret;
411
412 InitOnceExecuteOnce(&init_once, resolve_SetThreadDescription, NULL, NULL);
413 if (!pfn_SetThreadDescription)
414 return;
415
416 if ((ret = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0)) <= 0)
417 return;
418
419 if (!(wname = vkd3d_malloc(ret * sizeof(*wname))))
420 return;
421
422 if ((ret = MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, ret)) > 0)
423 pfn_SetThreadDescription(GetCurrentThread(), wname);
424
425 vkd3d_free(wname);
426#elif defined(HAVE_PTHREAD_SETNAME_NP_2)
427 pthread_setname_np(pthread_self(), name);
428#elif defined(HAVE_PTHREAD_SETNAME_NP_1)
429 pthread_setname_np(name);
430#endif
431}
#define isprint(c)
Definition: acclib.h:73
#define vsnprintf
Definition: acwin.h:108
#define ARRAY_SIZE(A)
Definition: main.h:20
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
#define MultiByteToWideChar
Definition: compat.h:110
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
BOOL WINAPI InitOnceExecuteOnce(_Inout_ PINIT_ONCE InitOnce, _In_ __callback PINIT_ONCE_FN InitFn, _Inout_opt_ PVOID Parameter, _Outptr_opt_result_maybenull_ LPVOID *Context)
Definition: InitOnce.c:12
char *CDECL getenv(const char *name)
Definition: environ.c:227
int CDECL vfprintf(FILE *file, const char *format, va_list valist)
Definition: file.c:5349
#define stderr
#define errno
Definition: errno.h:120
#define SIZE_MAX
Definition: limits.h:49
#define UINT_MAX
Definition: limits.h:27
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
unsigned short uint16_t
Definition: stdint.h:35
_ACRTIMP __msvcrt_ulong __cdecl strtoul(const char *, char **, int)
Definition: string.c:1864
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1597
_ACRTIMP char *__cdecl strstr(const char *, const char *)
Definition: string.c:3420
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3324
char * va_list
Definition: vadefs.h:50
return ret
Definition: mutex.c:147
unsigned int BOOL
Definition: ntddk_ex.h:94
GLint level
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat param
Definition: glext.h:5796
const GLuint * buffers
Definition: glext.h:5916
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define c
Definition: ke_i.h:80
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
char string[160]
Definition: util.h:11
static PVOID ptr
Definition: dispmode.c:27
#define sprintf
Definition: sprintf.c:45
static IPrintDialogCallback callback
Definition: printdlg.c:325
pid_t gettid(void)
#define min(a, b)
Definition: monoChain.cc:55
short WCHAR
Definition: pedump.c:58
const WCHAR * str
#define CP_UTF8
Definition: nls.h:20
static const char *const debug_level_names[]
Definition: debug.c:45
#define VKD3D_DEBUG_BUFFER_SIZE
Definition: debug.c:41
#define VKD3D_DEBUG_BUFFER_COUNT
Definition: debug.c:40
enum vkd3d_dbg_level vkd3d_dbg_get_level(void)
Definition: debug.c:55
static char * get_buffer(void)
Definition: debug.c:124
static bool is_option_separator(char c)
Definition: debug.c:343
void vkd3d_set_thread_name(const char *name)
Definition: debug.c:405
uint64_t vkd3d_parse_debug_options(const char *string, const struct vkd3d_debug_option *options, unsigned int option_count)
Definition: debug.c:370
static int get_escape_char(int c)
Definition: debug.c:155
static void vkd3d_dbg_output(const char *fmt,...)
Definition: debug.c:91
static const char * debugstr_w32(const uint32_t *wstr)
Definition: debug.c:273
static void vkd3d_dbg_voutput(const char *fmt, va_list args)
Definition: debug.c:83
const char *const vkd3d_dbg_env_name
const char * vkd3d_dbg_vsprintf(const char *fmt, va_list args)
Definition: debug.c:134
const char * debugstr_an(const char *str, size_t n)
Definition: debug.c:173
bool vkd3d_debug_list_has_member(const char *string, const char *member)
Definition: debug.c:348
const char * vkd3d_dbg_sprintf(const char *fmt,...)
Definition: debug.c:144
void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function, const char *fmt,...)
Definition: debug.c:100
void vkd3d_dbg_set_log_callback(PFN_vkd3d_log callback)
Definition: debug.c:119
unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value)
Definition: debug.c:326
static PFN_vkd3d_log log_callback
Definition: debug.c:81
static const char * debugstr_w16(const uint16_t *wstr)
Definition: debug.c:227
#define args
Definition: format.c:66
Definition: match.c:390
Definition: http.c:7252
Definition: dsound.c:943
Definition: name.c:39
const char * name
Definition: vkd3d_common.h:271
PVOID HANDLE
Definition: typedefs.h:73
Definition: pdh_main.c:64
static INIT_ONCE init_once
Definition: vfwcapture.c:981
vkd3d_dbg_level
Definition: vkd3d_common.h:143
@ VKD3D_DBG_LEVEL_WARN
Definition: vkd3d_common.h:148
@ VKD3D_DBG_LEVEL_NONE
Definition: vkd3d_common.h:144
@ VKD3D_DBG_LEVEL_TRACE
Definition: vkd3d_common.h:149
@ VKD3D_DBG_LEVEL_MESSAGE
Definition: vkd3d_common.h:145
@ VKD3D_DBG_LEVEL_ERR
Definition: vkd3d_common.h:146
@ VKD3D_DBG_LEVEL_FIXME
Definition: vkd3d_common.h:147
static uint32_t vkd3d_atomic_increment_u32(uint32_t volatile *x)
Definition: vkd3d_common.h:482
static void vkd3d_free(void *ptr)
Definition: vkd3d_memory.h:52
static void * vkd3d_malloc(size_t size)
Definition: vkd3d_memory.h:28
void(* PFN_vkd3d_log)(const char *format, va_list args)
Definition: vkd3d_types.h:66
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1195
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
RTL_RUN_ONCE INIT_ONCE
Definition: winbase.h:3654
#define INIT_ONCE_STATIC_INIT
Definition: winbase.h:591
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6