101e04c3fSmrg/************************************************************************** 201e04c3fSmrg * 301e04c3fSmrg * Copyright 2008 VMware, Inc. 401e04c3fSmrg * Copyright (c) 2008 VMware, Inc. 501e04c3fSmrg * All Rights Reserved. 601e04c3fSmrg * 701e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 801e04c3fSmrg * copy of this software and associated documentation files (the 901e04c3fSmrg * "Software"), to deal in the Software without restriction, including 1001e04c3fSmrg * without limitation the rights to use, copy, modify, merge, publish, 1101e04c3fSmrg * distribute, sub license, and/or sell copies of the Software, and to 1201e04c3fSmrg * permit persons to whom the Software is furnished to do so, subject to 1301e04c3fSmrg * the following conditions: 1401e04c3fSmrg * 1501e04c3fSmrg * The above copyright notice and this permission notice (including the 1601e04c3fSmrg * next paragraph) shall be included in all copies or substantial portions 1701e04c3fSmrg * of the Software. 1801e04c3fSmrg * 1901e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2001e04c3fSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2101e04c3fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2201e04c3fSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 2301e04c3fSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2401e04c3fSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2501e04c3fSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2601e04c3fSmrg * 2701e04c3fSmrg **************************************************************************/ 2801e04c3fSmrg 2901e04c3fSmrg 3001e04c3fSmrg#include "pipe/p_config.h" 3101e04c3fSmrg 3201e04c3fSmrg#include "util/u_debug.h" 3301e04c3fSmrg#include "pipe/p_format.h" 3401e04c3fSmrg#include "pipe/p_state.h" 3501e04c3fSmrg#include "util/u_string.h" 3601e04c3fSmrg#include "util/u_math.h" 3701e04c3fSmrg#include <inttypes.h> 3801e04c3fSmrg 3901e04c3fSmrg#include <stdio.h> 4001e04c3fSmrg#include <limits.h> /* CHAR_BIT */ 4101e04c3fSmrg#include <ctype.h> /* isalnum */ 4201e04c3fSmrg 4301e04c3fSmrg#ifdef _WIN32 4401e04c3fSmrg#include <windows.h> 4501e04c3fSmrg#include <stdlib.h> 4601e04c3fSmrg#endif 4701e04c3fSmrg 4801e04c3fSmrg 4901e04c3fSmrgvoid 5001e04c3fSmrg_debug_vprintf(const char *format, va_list ap) 5101e04c3fSmrg{ 5201e04c3fSmrg static char buf[4096] = {'\0'}; 537ec681f3Smrg#if DETECT_OS_WINDOWS || defined(EMBEDDED_DEVICE) 5401e04c3fSmrg /* We buffer until we find a newline. */ 5501e04c3fSmrg size_t len = strlen(buf); 567ec681f3Smrg int ret = vsnprintf(buf + len, sizeof(buf) - len, format, ap); 577ec681f3Smrg if (ret > (int)(sizeof(buf) - len - 1) || strchr(buf + len, '\n')) { 5801e04c3fSmrg os_log_message(buf); 5901e04c3fSmrg buf[0] = '\0'; 6001e04c3fSmrg } 6101e04c3fSmrg#else 627ec681f3Smrg vsnprintf(buf, sizeof(buf), format, ap); 6301e04c3fSmrg os_log_message(buf); 6401e04c3fSmrg#endif 6501e04c3fSmrg} 6601e04c3fSmrg 6701e04c3fSmrg 6801e04c3fSmrgvoid 6901e04c3fSmrg_pipe_debug_message(struct pipe_debug_callback *cb, 7001e04c3fSmrg unsigned *id, 7101e04c3fSmrg enum pipe_debug_type type, 7201e04c3fSmrg const char *fmt, ...) 7301e04c3fSmrg{ 7401e04c3fSmrg va_list args; 7501e04c3fSmrg va_start(args, fmt); 7601e04c3fSmrg if (cb && cb->debug_message) 7701e04c3fSmrg cb->debug_message(cb->data, id, type, fmt, args); 7801e04c3fSmrg va_end(args); 7901e04c3fSmrg} 8001e04c3fSmrg 8101e04c3fSmrg 8201e04c3fSmrgvoid 8301e04c3fSmrgdebug_disable_error_message_boxes(void) 8401e04c3fSmrg{ 8501e04c3fSmrg#ifdef _WIN32 8601e04c3fSmrg /* When Windows' error message boxes are disabled for this process (as is 8701e04c3fSmrg * typically the case when running tests in an automated fashion) we disable 8801e04c3fSmrg * CRT message boxes too. 8901e04c3fSmrg */ 9001e04c3fSmrg UINT uMode = SetErrorMode(0); 9101e04c3fSmrg SetErrorMode(uMode); 9201e04c3fSmrg if (uMode & SEM_FAILCRITICALERRORS) { 9301e04c3fSmrg /* Disable assertion failure message box. 9401e04c3fSmrg * http://msdn.microsoft.com/en-us/library/sas1dkb2.aspx 9501e04c3fSmrg */ 9601e04c3fSmrg _set_error_mode(_OUT_TO_STDERR); 9701e04c3fSmrg#ifdef _MSC_VER 9801e04c3fSmrg /* Disable abort message box. 9901e04c3fSmrg * http://msdn.microsoft.com/en-us/library/e631wekh.aspx 10001e04c3fSmrg */ 10101e04c3fSmrg _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); 10201e04c3fSmrg#endif 10301e04c3fSmrg } 10401e04c3fSmrg#endif /* _WIN32 */ 10501e04c3fSmrg} 10601e04c3fSmrg 10701e04c3fSmrg 10801e04c3fSmrg#ifdef DEBUG 10901e04c3fSmrgvoid 11001e04c3fSmrgdebug_print_blob(const char *name, const void *blob, unsigned size) 11101e04c3fSmrg{ 11201e04c3fSmrg const unsigned *ublob = (const unsigned *)blob; 11301e04c3fSmrg unsigned i; 11401e04c3fSmrg 11501e04c3fSmrg debug_printf("%s (%d dwords%s)\n", name, size/4, 11601e04c3fSmrg size%4 ? "... plus a few bytes" : ""); 11701e04c3fSmrg 11801e04c3fSmrg for (i = 0; i < size/4; i++) { 11901e04c3fSmrg debug_printf("%d:\t%08x\n", i, ublob[i]); 12001e04c3fSmrg } 12101e04c3fSmrg} 12201e04c3fSmrg#endif 12301e04c3fSmrg 12401e04c3fSmrg 1257ec681f3Smrgstatic bool 12601e04c3fSmrgdebug_get_option_should_print(void) 12701e04c3fSmrg{ 1287ec681f3Smrg static bool first = true; 1297ec681f3Smrg static bool value = false; 13001e04c3fSmrg 13101e04c3fSmrg if (!first) 13201e04c3fSmrg return value; 13301e04c3fSmrg 13401e04c3fSmrg /* Oh hey this will call into this function, 13501e04c3fSmrg * but its cool since we set first to false 13601e04c3fSmrg */ 1377ec681f3Smrg first = false; 1387ec681f3Smrg value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", false); 13901e04c3fSmrg /* XXX should we print this option? Currently it wont */ 14001e04c3fSmrg return value; 14101e04c3fSmrg} 14201e04c3fSmrg 14301e04c3fSmrg 14401e04c3fSmrgconst char * 14501e04c3fSmrgdebug_get_option(const char *name, const char *dfault) 14601e04c3fSmrg{ 14701e04c3fSmrg const char *result; 14801e04c3fSmrg 14901e04c3fSmrg result = os_get_option(name); 15001e04c3fSmrg if (!result) 15101e04c3fSmrg result = dfault; 15201e04c3fSmrg 15301e04c3fSmrg if (debug_get_option_should_print()) 15401e04c3fSmrg debug_printf("%s: %s = %s\n", __FUNCTION__, name, 15501e04c3fSmrg result ? result : "(null)"); 15601e04c3fSmrg 15701e04c3fSmrg return result; 15801e04c3fSmrg} 15901e04c3fSmrg 16001e04c3fSmrg 1617ec681f3Smrgbool 1627ec681f3Smrgdebug_get_bool_option(const char *name, bool dfault) 16301e04c3fSmrg{ 16401e04c3fSmrg const char *str = os_get_option(name); 1657ec681f3Smrg bool result; 16601e04c3fSmrg 16701e04c3fSmrg if (str == NULL) 16801e04c3fSmrg result = dfault; 1697ec681f3Smrg else if (!strcmp(str, "n")) 1707ec681f3Smrg result = false; 1717ec681f3Smrg else if (!strcmp(str, "no")) 1727ec681f3Smrg result = false; 1737ec681f3Smrg else if (!strcmp(str, "0")) 1747ec681f3Smrg result = false; 1757ec681f3Smrg else if (!strcmp(str, "f")) 1767ec681f3Smrg result = false; 1777ec681f3Smrg else if (!strcmp(str, "F")) 1787ec681f3Smrg result = false; 1797ec681f3Smrg else if (!strcmp(str, "false")) 1807ec681f3Smrg result = false; 1817ec681f3Smrg else if (!strcmp(str, "FALSE")) 1827ec681f3Smrg result = false; 18301e04c3fSmrg else 1847ec681f3Smrg result = true; 18501e04c3fSmrg 18601e04c3fSmrg if (debug_get_option_should_print()) 18701e04c3fSmrg debug_printf("%s: %s = %s\n", __FUNCTION__, name, 18801e04c3fSmrg result ? "TRUE" : "FALSE"); 18901e04c3fSmrg 19001e04c3fSmrg return result; 19101e04c3fSmrg} 19201e04c3fSmrg 19301e04c3fSmrg 19401e04c3fSmrglong 19501e04c3fSmrgdebug_get_num_option(const char *name, long dfault) 19601e04c3fSmrg{ 19701e04c3fSmrg long result; 19801e04c3fSmrg const char *str; 19901e04c3fSmrg 20001e04c3fSmrg str = os_get_option(name); 20101e04c3fSmrg if (!str) { 20201e04c3fSmrg result = dfault; 20301e04c3fSmrg } else { 20401e04c3fSmrg char *endptr; 20501e04c3fSmrg 20601e04c3fSmrg result = strtol(str, &endptr, 0); 20701e04c3fSmrg if (str == endptr) { 20801e04c3fSmrg /* Restore the default value when no digits were found. */ 20901e04c3fSmrg result = dfault; 21001e04c3fSmrg } 21101e04c3fSmrg } 21201e04c3fSmrg 21301e04c3fSmrg if (debug_get_option_should_print()) 21401e04c3fSmrg debug_printf("%s: %s = %li\n", __FUNCTION__, name, result); 21501e04c3fSmrg 21601e04c3fSmrg return result; 21701e04c3fSmrg} 21801e04c3fSmrg 2197ec681f3Smrgvoid 2207ec681f3Smrgdebug_get_version_option(const char *name, unsigned *major, unsigned *minor) 2217ec681f3Smrg{ 2227ec681f3Smrg const char *str; 2237ec681f3Smrg 2247ec681f3Smrg str = os_get_option(name); 2257ec681f3Smrg if (str) { 2267ec681f3Smrg unsigned v_maj, v_min; 2277ec681f3Smrg int n; 2287ec681f3Smrg 2297ec681f3Smrg n = sscanf(str, "%u.%u", &v_maj, &v_min); 2307ec681f3Smrg if (n != 2) { 2317ec681f3Smrg debug_printf("Illegal version specified for %s : %s\n", name, str); 2327ec681f3Smrg return; 2337ec681f3Smrg } 2347ec681f3Smrg *major = v_maj; 2357ec681f3Smrg *minor = v_min; 2367ec681f3Smrg } 2377ec681f3Smrg 2387ec681f3Smrg if (debug_get_option_should_print()) 2397ec681f3Smrg debug_printf("%s: %s = %u.%u\n", __FUNCTION__, name, *major, *minor); 2407ec681f3Smrg 2417ec681f3Smrg return; 2427ec681f3Smrg} 24301e04c3fSmrg 2447ec681f3Smrgstatic bool 24501e04c3fSmrgstr_has_option(const char *str, const char *name) 24601e04c3fSmrg{ 24701e04c3fSmrg /* Empty string. */ 24801e04c3fSmrg if (!*str) { 2497ec681f3Smrg return false; 25001e04c3fSmrg } 25101e04c3fSmrg 25201e04c3fSmrg /* OPTION=all */ 2537ec681f3Smrg if (!strcmp(str, "all")) { 2547ec681f3Smrg return true; 25501e04c3fSmrg } 25601e04c3fSmrg 25701e04c3fSmrg /* Find 'name' in 'str' surrounded by non-alphanumeric characters. */ 25801e04c3fSmrg { 25901e04c3fSmrg const char *start = str; 26001e04c3fSmrg unsigned name_len = strlen(name); 26101e04c3fSmrg 26201e04c3fSmrg /* 'start' is the beginning of the currently-parsed word, 26301e04c3fSmrg * we increment 'str' each iteration. 26401e04c3fSmrg * if we find either the end of string or a non-alphanumeric character, 26501e04c3fSmrg * we compare 'start' up to 'str-1' with 'name'. */ 26601e04c3fSmrg 26701e04c3fSmrg while (1) { 26801e04c3fSmrg if (!*str || !(isalnum(*str) || *str == '_')) { 26901e04c3fSmrg if (str-start == name_len && 27001e04c3fSmrg !memcmp(start, name, name_len)) { 2717ec681f3Smrg return true; 27201e04c3fSmrg } 27301e04c3fSmrg 27401e04c3fSmrg if (!*str) { 2757ec681f3Smrg return false; 27601e04c3fSmrg } 27701e04c3fSmrg 27801e04c3fSmrg start = str+1; 27901e04c3fSmrg } 28001e04c3fSmrg 28101e04c3fSmrg str++; 28201e04c3fSmrg } 28301e04c3fSmrg } 28401e04c3fSmrg 2857ec681f3Smrg return false; 28601e04c3fSmrg} 28701e04c3fSmrg 28801e04c3fSmrg 28901e04c3fSmrguint64_t 29001e04c3fSmrgdebug_get_flags_option(const char *name, 29101e04c3fSmrg const struct debug_named_value *flags, 29201e04c3fSmrg uint64_t dfault) 29301e04c3fSmrg{ 29401e04c3fSmrg uint64_t result; 29501e04c3fSmrg const char *str; 29601e04c3fSmrg const struct debug_named_value *orig = flags; 29701e04c3fSmrg unsigned namealign = 0; 29801e04c3fSmrg 29901e04c3fSmrg str = os_get_option(name); 30001e04c3fSmrg if (!str) 30101e04c3fSmrg result = dfault; 3027ec681f3Smrg else if (!strcmp(str, "help")) { 30301e04c3fSmrg result = dfault; 30401e04c3fSmrg _debug_printf("%s: help for %s:\n", __FUNCTION__, name); 30501e04c3fSmrg for (; flags->name; ++flags) 30601e04c3fSmrg namealign = MAX2(namealign, strlen(flags->name)); 30701e04c3fSmrg for (flags = orig; flags->name; ++flags) 30801e04c3fSmrg _debug_printf("| %*s [0x%0*"PRIx64"]%s%s\n", namealign, flags->name, 30901e04c3fSmrg (int)sizeof(uint64_t)*CHAR_BIT/4, flags->value, 31001e04c3fSmrg flags->desc ? " " : "", flags->desc ? flags->desc : ""); 31101e04c3fSmrg } 31201e04c3fSmrg else { 31301e04c3fSmrg result = 0; 31401e04c3fSmrg while (flags->name) { 31501e04c3fSmrg if (str_has_option(str, flags->name)) 31601e04c3fSmrg result |= flags->value; 31701e04c3fSmrg ++flags; 31801e04c3fSmrg } 31901e04c3fSmrg } 32001e04c3fSmrg 32101e04c3fSmrg if (debug_get_option_should_print()) { 32201e04c3fSmrg if (str) { 32301e04c3fSmrg debug_printf("%s: %s = 0x%"PRIx64" (%s)\n", 32401e04c3fSmrg __FUNCTION__, name, result, str); 32501e04c3fSmrg } else { 32601e04c3fSmrg debug_printf("%s: %s = 0x%"PRIx64"\n", __FUNCTION__, name, result); 32701e04c3fSmrg } 32801e04c3fSmrg } 32901e04c3fSmrg 33001e04c3fSmrg return result; 33101e04c3fSmrg} 33201e04c3fSmrg 33301e04c3fSmrg 33401e04c3fSmrgvoid 33501e04c3fSmrg_debug_assert_fail(const char *expr, const char *file, unsigned line, 33601e04c3fSmrg const char *function) 33701e04c3fSmrg{ 33801e04c3fSmrg _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", 33901e04c3fSmrg file, line, function, expr); 34001e04c3fSmrg os_abort(); 34101e04c3fSmrg} 34201e04c3fSmrg 34301e04c3fSmrg 34401e04c3fSmrgconst char * 34501e04c3fSmrgdebug_dump_enum(const struct debug_named_value *names, 34601e04c3fSmrg unsigned long value) 34701e04c3fSmrg{ 34801e04c3fSmrg static char rest[64]; 34901e04c3fSmrg 35001e04c3fSmrg while (names->name) { 35101e04c3fSmrg if (names->value == value) 35201e04c3fSmrg return names->name; 35301e04c3fSmrg ++names; 35401e04c3fSmrg } 35501e04c3fSmrg 3567ec681f3Smrg snprintf(rest, sizeof(rest), "0x%08lx", value); 35701e04c3fSmrg return rest; 35801e04c3fSmrg} 35901e04c3fSmrg 36001e04c3fSmrg 36101e04c3fSmrgconst char * 36201e04c3fSmrgdebug_dump_enum_noprefix(const struct debug_named_value *names, 36301e04c3fSmrg const char *prefix, 36401e04c3fSmrg unsigned long value) 36501e04c3fSmrg{ 36601e04c3fSmrg static char rest[64]; 36701e04c3fSmrg 36801e04c3fSmrg while (names->name) { 36901e04c3fSmrg if (names->value == value) { 37001e04c3fSmrg const char *name = names->name; 37101e04c3fSmrg while (*name == *prefix) { 37201e04c3fSmrg name++; 37301e04c3fSmrg prefix++; 37401e04c3fSmrg } 37501e04c3fSmrg return name; 37601e04c3fSmrg } 37701e04c3fSmrg ++names; 37801e04c3fSmrg } 37901e04c3fSmrg 3807ec681f3Smrg snprintf(rest, sizeof(rest), "0x%08lx", value); 38101e04c3fSmrg return rest; 38201e04c3fSmrg} 38301e04c3fSmrg 38401e04c3fSmrg 38501e04c3fSmrgconst char * 38601e04c3fSmrgdebug_dump_flags(const struct debug_named_value *names, unsigned long value) 38701e04c3fSmrg{ 38801e04c3fSmrg static char output[4096]; 38901e04c3fSmrg static char rest[256]; 39001e04c3fSmrg int first = 1; 39101e04c3fSmrg 39201e04c3fSmrg output[0] = '\0'; 39301e04c3fSmrg 39401e04c3fSmrg while (names->name) { 39501e04c3fSmrg if ((names->value & value) == names->value) { 39601e04c3fSmrg if (!first) 3977ec681f3Smrg strncat(output, "|", sizeof(output) - strlen(output) - 1); 39801e04c3fSmrg else 39901e04c3fSmrg first = 0; 4007ec681f3Smrg strncat(output, names->name, sizeof(output) - strlen(output) - 1); 40101e04c3fSmrg output[sizeof(output) - 1] = '\0'; 40201e04c3fSmrg value &= ~names->value; 40301e04c3fSmrg } 40401e04c3fSmrg ++names; 40501e04c3fSmrg } 40601e04c3fSmrg 40701e04c3fSmrg if (value) { 40801e04c3fSmrg if (!first) 4097ec681f3Smrg strncat(output, "|", sizeof(output) - strlen(output) - 1); 41001e04c3fSmrg else 41101e04c3fSmrg first = 0; 41201e04c3fSmrg 4137ec681f3Smrg snprintf(rest, sizeof(rest), "0x%08lx", value); 4147ec681f3Smrg strncat(output, rest, sizeof(output) - strlen(output) - 1); 41501e04c3fSmrg output[sizeof(output) - 1] = '\0'; 41601e04c3fSmrg } 41701e04c3fSmrg 41801e04c3fSmrg if (first) 41901e04c3fSmrg return "0"; 42001e04c3fSmrg 42101e04c3fSmrg return output; 42201e04c3fSmrg} 42301e04c3fSmrg 42401e04c3fSmrg 42501e04c3fSmrg 42601e04c3fSmrg#ifdef DEBUG 42701e04c3fSmrgint fl_indent = 0; 42801e04c3fSmrgconst char* fl_function[1024]; 42901e04c3fSmrg 43001e04c3fSmrgint 43101e04c3fSmrgdebug_funclog_enter(const char* f, UNUSED const int line, 43201e04c3fSmrg UNUSED const char* file) 43301e04c3fSmrg{ 43401e04c3fSmrg int i; 43501e04c3fSmrg 43601e04c3fSmrg for (i = 0; i < fl_indent; i++) 43701e04c3fSmrg debug_printf(" "); 43801e04c3fSmrg debug_printf("%s\n", f); 43901e04c3fSmrg 44001e04c3fSmrg assert(fl_indent < 1023); 44101e04c3fSmrg fl_function[fl_indent++] = f; 44201e04c3fSmrg 44301e04c3fSmrg return 0; 44401e04c3fSmrg} 44501e04c3fSmrg 44601e04c3fSmrgvoid 44701e04c3fSmrgdebug_funclog_exit(const char* f, UNUSED const int line, 44801e04c3fSmrg UNUSED const char* file) 44901e04c3fSmrg{ 45001e04c3fSmrg --fl_indent; 45101e04c3fSmrg assert(fl_indent >= 0); 45201e04c3fSmrg assert(fl_function[fl_indent] == f); 45301e04c3fSmrg} 45401e04c3fSmrg 45501e04c3fSmrgvoid 45601e04c3fSmrgdebug_funclog_enter_exit(const char* f, UNUSED const int line, 45701e04c3fSmrg UNUSED const char* file) 45801e04c3fSmrg{ 45901e04c3fSmrg int i; 46001e04c3fSmrg for (i = 0; i < fl_indent; i++) 46101e04c3fSmrg debug_printf(" "); 46201e04c3fSmrg debug_printf("%s\n", f); 46301e04c3fSmrg} 46401e04c3fSmrg#endif 465