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