• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2008 VMware, Inc.
4  * Copyright (c) 2008 VMware, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27  **************************************************************************/
28 
29 
30 #include "util/u_debug.h"
31 #include "util/u_string.h"
32 #include "util/u_math.h"
33 #include <inttypes.h>
34 
35 #include <stdio.h>
36 #include <limits.h> /* CHAR_BIT */
37 #include <ctype.h> /* isalnum */
38 
39 #ifdef _WIN32
40 #include <windows.h>
41 #include <stdlib.h>
42 #endif
43 
44 
45 void
_debug_vprintf(const char * format,va_list ap)46 _debug_vprintf(const char *format, va_list ap)
47 {
48    static char buf[4096] = {'\0'};
49 #if DETECT_OS_WINDOWS || defined(EMBEDDED_DEVICE)
50    /* We buffer until we find a newline. */
51    size_t len = strlen(buf);
52    int ret = vsnprintf(buf + len, sizeof(buf) - len, format, ap);
53    if (ret > (int)(sizeof(buf) - len - 1) || strchr(buf + len, '\n')) {
54       os_log_message(buf);
55       buf[0] = '\0';
56    }
57 #else
58    vsnprintf(buf, sizeof(buf), format, ap);
59    os_log_message(buf);
60 #endif
61 }
62 
63 
64 void
_util_debug_message(struct util_debug_callback * cb,unsigned * id,enum util_debug_type type,const char * fmt,...)65 _util_debug_message(struct util_debug_callback *cb,
66                     unsigned *id,
67                     enum util_debug_type type,
68                     const char *fmt, ...)
69 {
70    va_list args;
71    va_start(args, fmt);
72    if (cb && cb->debug_message)
73       cb->debug_message(cb->data, id, type, fmt, args);
74    va_end(args);
75 }
76 
77 
78 #ifdef _WIN32
79 void
debug_disable_win32_error_dialogs(void)80 debug_disable_win32_error_dialogs(void)
81 {
82    /* When Windows' error message boxes are disabled for this process (as is
83     * typically the case when running tests in an automated fashion) we disable
84     * CRT message boxes too.
85     */
86    UINT uMode = SetErrorMode(0);
87    SetErrorMode(uMode);
88    if (uMode & SEM_FAILCRITICALERRORS) {
89       /* Disable assertion failure message box.
90        * http://msdn.microsoft.com/en-us/library/sas1dkb2.aspx
91        */
92       _set_error_mode(_OUT_TO_STDERR);
93 #ifdef _MSC_VER
94       /* Disable abort message box.
95        * http://msdn.microsoft.com/en-us/library/e631wekh.aspx
96        */
97       _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
98 #endif
99    }
100 }
101 #endif /* _WIN32 */
102 
103 
104 #ifdef DEBUG
105 void
debug_print_blob(const char * name,const void * blob,unsigned size)106 debug_print_blob(const char *name, const void *blob, unsigned size)
107 {
108    const unsigned *ublob = (const unsigned *)blob;
109    unsigned i;
110 
111    debug_printf("%s (%d dwords%s)\n", name, size/4,
112                 size%4 ? "... plus a few bytes" : "");
113 
114    for (i = 0; i < size/4; i++) {
115       debug_printf("%d:\t%08x\n", i, ublob[i]);
116    }
117 }
118 #endif
119 
120 
121 static bool
debug_get_option_should_print(void)122 debug_get_option_should_print(void)
123 {
124    static bool initialized = false;
125    static bool value = false;
126 
127    if (initialized)
128       return value;
129 
130    /* Oh hey this will call into this function,
131     * but its cool since we set first to false
132     */
133    initialized = true;
134    value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", false);
135    /* XXX should we print this option? Currently it wont */
136    return value;
137 }
138 
139 
140 const char *
debug_get_option(const char * name,const char * dfault)141 debug_get_option(const char *name, const char *dfault)
142 {
143    const char *result;
144 
145    result = os_get_option(name);
146    if (!result)
147       result = dfault;
148 
149    if (debug_get_option_should_print())
150       debug_printf("%s: %s = %s\n", __FUNCTION__, name,
151                    result ? result : "(null)");
152 
153    return result;
154 }
155 
156 
157 bool
debug_get_bool_option(const char * name,bool dfault)158 debug_get_bool_option(const char *name, bool dfault)
159 {
160    const char *str = os_get_option(name);
161    bool result;
162 
163    if (str == NULL)
164       result = dfault;
165    else if (!strcmp(str, "n"))
166       result = false;
167    else if (!strcmp(str, "no"))
168       result = false;
169    else if (!strcmp(str, "0"))
170       result = false;
171    else if (!strcmp(str, "f"))
172       result = false;
173    else if (!strcmp(str, "F"))
174       result = false;
175    else if (!strcmp(str, "false"))
176       result = false;
177    else if (!strcmp(str, "FALSE"))
178       result = false;
179    else
180       result = true;
181 
182    if (debug_get_option_should_print())
183       debug_printf("%s: %s = %s\n", __FUNCTION__, name,
184                    result ? "TRUE" : "FALSE");
185 
186    return result;
187 }
188 
189 
190 long
debug_get_num_option(const char * name,long dfault)191 debug_get_num_option(const char *name, long dfault)
192 {
193    long result;
194    const char *str;
195 
196    str = os_get_option(name);
197    if (!str) {
198       result = dfault;
199    } else {
200       char *endptr;
201 
202       result = strtol(str, &endptr, 0);
203       if (str == endptr) {
204          /* Restore the default value when no digits were found. */
205          result = dfault;
206       }
207    }
208 
209    if (debug_get_option_should_print())
210       debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
211 
212    return result;
213 }
214 
215 void
debug_get_version_option(const char * name,unsigned * major,unsigned * minor)216 debug_get_version_option(const char *name, unsigned *major, unsigned *minor)
217 {
218    const char *str;
219 
220    str = os_get_option(name);
221    if (str) {
222       unsigned v_maj, v_min;
223       int n;
224 
225       n = sscanf(str, "%u.%u", &v_maj, &v_min);
226       if (n != 2) {
227          debug_printf("Illegal version specified for %s : %s\n", name, str);
228          return;
229       }
230       *major = v_maj;
231       *minor = v_min;
232    }
233 
234    if (debug_get_option_should_print())
235       debug_printf("%s: %s = %u.%u\n", __FUNCTION__, name, *major, *minor);
236 
237    return;
238 }
239 
240 static bool
str_has_option(const char * str,const char * name)241 str_has_option(const char *str, const char *name)
242 {
243    /* Empty string. */
244    if (!*str) {
245       return false;
246    }
247 
248    /* OPTION=all */
249    if (!strcmp(str, "all")) {
250       return true;
251    }
252 
253    /* Find 'name' in 'str' surrounded by non-alphanumeric characters. */
254    {
255       const char *start = str;
256       unsigned name_len = strlen(name);
257 
258       /* 'start' is the beginning of the currently-parsed word,
259        * we increment 'str' each iteration.
260        * if we find either the end of string or a non-alphanumeric character,
261        * we compare 'start' up to 'str-1' with 'name'. */
262 
263       while (1) {
264          if (!*str || !(isalnum(*str) || *str == '_')) {
265             if (str-start == name_len &&
266                 !memcmp(start, name, name_len)) {
267                return true;
268             }
269 
270             if (!*str) {
271                return false;
272             }
273 
274             start = str+1;
275          }
276 
277          str++;
278       }
279    }
280 
281    return false;
282 }
283 
284 
285 uint64_t
debug_get_flags_option(const char * name,const struct debug_named_value * flags,uint64_t dfault)286 debug_get_flags_option(const char *name,
287                        const struct debug_named_value *flags,
288                        uint64_t dfault)
289 {
290    uint64_t result;
291    const char *str;
292    const struct debug_named_value *orig = flags;
293    unsigned namealign = 0;
294 
295    str = os_get_option(name);
296    if (!str)
297       result = dfault;
298    else if (!strcmp(str, "help")) {
299       result = dfault;
300       _debug_printf("%s: help for %s:\n", __FUNCTION__, name);
301       for (; flags->name; ++flags)
302          namealign = MAX2(namealign, strlen(flags->name));
303       for (flags = orig; flags->name; ++flags)
304          _debug_printf("| %*s [0x%0*"PRIx64"]%s%s\n", namealign, flags->name,
305                       (int)sizeof(uint64_t)*CHAR_BIT/4, flags->value,
306                       flags->desc ? " " : "", flags->desc ? flags->desc : "");
307    }
308    else {
309       result = 0;
310       while (flags->name) {
311 	 if (str_has_option(str, flags->name))
312 	    result |= flags->value;
313 	 ++flags;
314       }
315    }
316 
317    if (debug_get_option_should_print()) {
318       if (str) {
319          debug_printf("%s: %s = 0x%"PRIx64" (%s)\n",
320                       __FUNCTION__, name, result, str);
321       } else {
322          debug_printf("%s: %s = 0x%"PRIx64"\n", __FUNCTION__, name, result);
323       }
324    }
325 
326    return result;
327 }
328 
329 
330 const char *
debug_dump_enum(const struct debug_named_value * names,unsigned long value)331 debug_dump_enum(const struct debug_named_value *names,
332                 unsigned long value)
333 {
334    static char rest[64];
335 
336    while (names->name) {
337       if (names->value == value)
338 	 return names->name;
339       ++names;
340    }
341 
342    snprintf(rest, sizeof(rest), "0x%08lx", value);
343    return rest;
344 }
345 
346 
347 const char *
debug_dump_enum_noprefix(const struct debug_named_value * names,const char * prefix,unsigned long value)348 debug_dump_enum_noprefix(const struct debug_named_value *names,
349                          const char *prefix,
350                          unsigned long value)
351 {
352    static char rest[64];
353 
354    while (names->name) {
355       if (names->value == value) {
356          const char *name = names->name;
357          while (*name == *prefix) {
358             name++;
359             prefix++;
360          }
361          return name;
362       }
363       ++names;
364    }
365 
366    snprintf(rest, sizeof(rest), "0x%08lx", value);
367    return rest;
368 }
369 
370 
371 const char *
debug_dump_flags(const struct debug_named_value * names,unsigned long value)372 debug_dump_flags(const struct debug_named_value *names, unsigned long value)
373 {
374    static char output[4096];
375    static char rest[256];
376    int first = 1;
377 
378    output[0] = '\0';
379 
380    while (names->name) {
381       if ((names->value & value) == names->value) {
382 	 if (!first)
383 	    strncat(output, "|", sizeof(output) - strlen(output) - 1);
384 	 else
385 	    first = 0;
386 	 strncat(output, names->name, sizeof(output) - strlen(output) - 1);
387 	 output[sizeof(output) - 1] = '\0';
388 	 value &= ~names->value;
389       }
390       ++names;
391    }
392 
393    if (value) {
394       if (!first)
395 	 strncat(output, "|", sizeof(output) - strlen(output) - 1);
396       else
397 	 first = 0;
398 
399       snprintf(rest, sizeof(rest), "0x%08lx", value);
400       strncat(output, rest, sizeof(output) - strlen(output) - 1);
401       output[sizeof(output) - 1] = '\0';
402    }
403 
404    if (first)
405       return "0";
406 
407    return output;
408 }
409 
410 
411 
412 #ifdef DEBUG
413 int fl_indent = 0;
414 const char* fl_function[1024];
415 
416 int
debug_funclog_enter(const char * f,UNUSED const int line,UNUSED const char * file)417 debug_funclog_enter(const char* f, UNUSED const int line,
418                     UNUSED const char* file)
419 {
420    int i;
421 
422    for (i = 0; i < fl_indent; i++)
423       debug_printf("  ");
424    debug_printf("%s\n", f);
425 
426    assert(fl_indent < 1023);
427    fl_function[fl_indent++] = f;
428 
429    return 0;
430 }
431 
432 void
debug_funclog_exit(const char * f,UNUSED const int line,UNUSED const char * file)433 debug_funclog_exit(const char* f, UNUSED const int line,
434                    UNUSED const char* file)
435 {
436    --fl_indent;
437    assert(fl_indent >= 0);
438    assert(fl_function[fl_indent] == f);
439 }
440 
441 void
debug_funclog_enter_exit(const char * f,UNUSED const int line,UNUSED const char * file)442 debug_funclog_enter_exit(const char* f, UNUSED const int line,
443                          UNUSED const char* file)
444 {
445    int i;
446    for (i = 0; i < fl_indent; i++)
447       debug_printf("  ");
448    debug_printf("%s\n", f);
449 }
450 #endif
451