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