1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/**
29bf215546Sopenharmony_ci * @file
30bf215546Sopenharmony_ci * Cross-platform debugging helpers.
31bf215546Sopenharmony_ci *
32bf215546Sopenharmony_ci * For now it just has assert and printf replacements, but it might be extended
33bf215546Sopenharmony_ci * with stack trace reports and more advanced logging in the near future.
34bf215546Sopenharmony_ci *
35bf215546Sopenharmony_ci * @author Jose Fonseca <jfonseca@vmware.com>
36bf215546Sopenharmony_ci */
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#ifndef U_DEBUG_H_
39bf215546Sopenharmony_ci#define U_DEBUG_H_
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#include <stdarg.h>
42bf215546Sopenharmony_ci#include <string.h>
43bf215546Sopenharmony_ci#if !defined(_WIN32)
44bf215546Sopenharmony_ci#include <sys/types.h>
45bf215546Sopenharmony_ci#include <unistd.h>
46bf215546Sopenharmony_ci#endif
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci#include "util/os_misc.h"
49bf215546Sopenharmony_ci#include "util/detect_os.h"
50bf215546Sopenharmony_ci#include "util/macros.h"
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci#if DETECT_OS_HAIKU
53bf215546Sopenharmony_ci/* Haiku provides debug_printf in libroot with OS.h */
54bf215546Sopenharmony_ci#include <OS.h>
55bf215546Sopenharmony_ci#endif
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci#ifdef __cplusplus
58bf215546Sopenharmony_ciextern "C" {
59bf215546Sopenharmony_ci#endif
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_cienum util_debug_type
62bf215546Sopenharmony_ci{
63bf215546Sopenharmony_ci   UTIL_DEBUG_TYPE_OUT_OF_MEMORY = 1,
64bf215546Sopenharmony_ci   UTIL_DEBUG_TYPE_ERROR,
65bf215546Sopenharmony_ci   UTIL_DEBUG_TYPE_SHADER_INFO,
66bf215546Sopenharmony_ci   UTIL_DEBUG_TYPE_PERF_INFO,
67bf215546Sopenharmony_ci   UTIL_DEBUG_TYPE_INFO,
68bf215546Sopenharmony_ci   UTIL_DEBUG_TYPE_FALLBACK,
69bf215546Sopenharmony_ci   UTIL_DEBUG_TYPE_CONFORMANCE,
70bf215546Sopenharmony_ci};
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci/**
73bf215546Sopenharmony_ci * Structure that contains a callback for debug messages from the driver back
74bf215546Sopenharmony_ci * to the gallium frontend.
75bf215546Sopenharmony_ci */
76bf215546Sopenharmony_cistruct util_debug_callback
77bf215546Sopenharmony_ci{
78bf215546Sopenharmony_ci   /**
79bf215546Sopenharmony_ci    * When set to \c true, the callback may be called asynchronously from a
80bf215546Sopenharmony_ci    * driver-created thread.
81bf215546Sopenharmony_ci    */
82bf215546Sopenharmony_ci   bool async;
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   /**
85bf215546Sopenharmony_ci    * Callback for the driver to report debug/performance/etc information back
86bf215546Sopenharmony_ci    * to the gallium frontend.
87bf215546Sopenharmony_ci    *
88bf215546Sopenharmony_ci    * \param data       user-supplied data pointer
89bf215546Sopenharmony_ci    * \param id         message type identifier, if pointed value is 0, then a
90bf215546Sopenharmony_ci    *                   new id is assigned
91bf215546Sopenharmony_ci    * \param type       UTIL_DEBUG_TYPE_*
92bf215546Sopenharmony_ci    * \param format     printf-style format string
93bf215546Sopenharmony_ci    * \param args       args for format string
94bf215546Sopenharmony_ci    */
95bf215546Sopenharmony_ci   void (*debug_message)(void *data,
96bf215546Sopenharmony_ci                         unsigned *id,
97bf215546Sopenharmony_ci                         enum util_debug_type type,
98bf215546Sopenharmony_ci                         const char *fmt,
99bf215546Sopenharmony_ci                         va_list args);
100bf215546Sopenharmony_ci   void *data;
101bf215546Sopenharmony_ci};
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci#define _util_printf_format(fmt, list) PRINTFLIKE(fmt, list)
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_civoid _debug_vprintf(const char *format, va_list ap);
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_cistatic inline void
109bf215546Sopenharmony_ci_debug_printf(const char *format, ...)
110bf215546Sopenharmony_ci{
111bf215546Sopenharmony_ci   va_list ap;
112bf215546Sopenharmony_ci   va_start(ap, format);
113bf215546Sopenharmony_ci   _debug_vprintf(format, ap);
114bf215546Sopenharmony_ci   va_end(ap);
115bf215546Sopenharmony_ci}
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci/**
119bf215546Sopenharmony_ci * Print debug messages.
120bf215546Sopenharmony_ci *
121bf215546Sopenharmony_ci * The actual channel used to output debug message is platform specific. To
122bf215546Sopenharmony_ci * avoid misformating or truncation, follow these rules of thumb:
123bf215546Sopenharmony_ci * - output whole lines
124bf215546Sopenharmony_ci * - avoid outputing large strings (512 bytes is the current maximum length
125bf215546Sopenharmony_ci * that is guaranteed to be printed in all platforms)
126bf215546Sopenharmony_ci */
127bf215546Sopenharmony_ci#if !DETECT_OS_HAIKU
128bf215546Sopenharmony_cistatic inline void
129bf215546Sopenharmony_cidebug_printf(const char *format, ...) _util_printf_format(1,2);
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_cistatic inline void
132bf215546Sopenharmony_cidebug_printf(const char *format, ...)
133bf215546Sopenharmony_ci{
134bf215546Sopenharmony_ci#ifdef DEBUG
135bf215546Sopenharmony_ci   va_list ap;
136bf215546Sopenharmony_ci   va_start(ap, format);
137bf215546Sopenharmony_ci   _debug_vprintf(format, ap);
138bf215546Sopenharmony_ci   va_end(ap);
139bf215546Sopenharmony_ci#else
140bf215546Sopenharmony_ci   (void) format; /* silence warning */
141bf215546Sopenharmony_ci#endif
142bf215546Sopenharmony_ci}
143bf215546Sopenharmony_ci#endif
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci/*
147bf215546Sopenharmony_ci * ... isn't portable so we need to pass arguments in parentheses.
148bf215546Sopenharmony_ci *
149bf215546Sopenharmony_ci * usage:
150bf215546Sopenharmony_ci *    debug_printf_once(("answer: %i\n", 42));
151bf215546Sopenharmony_ci */
152bf215546Sopenharmony_ci#define debug_printf_once(args) \
153bf215546Sopenharmony_ci   do { \
154bf215546Sopenharmony_ci      static bool once = true; \
155bf215546Sopenharmony_ci      if (once) { \
156bf215546Sopenharmony_ci         once = false; \
157bf215546Sopenharmony_ci         debug_printf args; \
158bf215546Sopenharmony_ci      } \
159bf215546Sopenharmony_ci   } while (0)
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci#ifdef DEBUG
163bf215546Sopenharmony_ci#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
164bf215546Sopenharmony_ci#else
165bf215546Sopenharmony_ci#define debug_vprintf(_format, _ap) ((void)0)
166bf215546Sopenharmony_ci#endif
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci#ifdef DEBUG
170bf215546Sopenharmony_ci/**
171bf215546Sopenharmony_ci * Dump a blob in hex to the same place that debug_printf sends its
172bf215546Sopenharmony_ci * messages.
173bf215546Sopenharmony_ci */
174bf215546Sopenharmony_civoid debug_print_blob( const char *name, const void *blob, unsigned size );
175bf215546Sopenharmony_ci#else
176bf215546Sopenharmony_ci#define debug_print_blob(_name, _blob, _size) ((void)0)
177bf215546Sopenharmony_ci#endif
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci#ifdef _WIN32
181bf215546Sopenharmony_ci/**
182bf215546Sopenharmony_ci * Disable Win32 interactive error message boxes.
183bf215546Sopenharmony_ci *
184bf215546Sopenharmony_ci * Should be called as soon as possible for effectiveness.
185bf215546Sopenharmony_ci */
186bf215546Sopenharmony_civoid
187bf215546Sopenharmony_cidebug_disable_win32_error_dialogs(void);
188bf215546Sopenharmony_ci#endif
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci/**
192bf215546Sopenharmony_ci * Hard-coded breakpoint.
193bf215546Sopenharmony_ci */
194bf215546Sopenharmony_ci#ifdef DEBUG
195bf215546Sopenharmony_ci#define debug_break() os_break()
196bf215546Sopenharmony_ci#else /* !DEBUG */
197bf215546Sopenharmony_ci#define debug_break() ((void)0)
198bf215546Sopenharmony_ci#endif /* !DEBUG */
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_cilong
202bf215546Sopenharmony_cidebug_get_num_option(const char *name, long dfault);
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_civoid
205bf215546Sopenharmony_cidebug_get_version_option(const char *name, unsigned *major, unsigned *minor);
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci/**
209bf215546Sopenharmony_ci * Output the current function name.
210bf215546Sopenharmony_ci */
211bf215546Sopenharmony_ci#ifdef DEBUG
212bf215546Sopenharmony_ci#define debug_checkpoint() \
213bf215546Sopenharmony_ci   _debug_printf("%s\n", __FUNCTION__)
214bf215546Sopenharmony_ci#else
215bf215546Sopenharmony_ci#define debug_checkpoint() \
216bf215546Sopenharmony_ci   ((void)0)
217bf215546Sopenharmony_ci#endif
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci/**
221bf215546Sopenharmony_ci * Output the full source code position.
222bf215546Sopenharmony_ci */
223bf215546Sopenharmony_ci#ifdef DEBUG
224bf215546Sopenharmony_ci#define debug_checkpoint_full() \
225bf215546Sopenharmony_ci   _debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__)
226bf215546Sopenharmony_ci#else
227bf215546Sopenharmony_ci#define debug_checkpoint_full() \
228bf215546Sopenharmony_ci   ((void)0)
229bf215546Sopenharmony_ci#endif
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci/**
233bf215546Sopenharmony_ci * Output a warning message. Muted on release version.
234bf215546Sopenharmony_ci */
235bf215546Sopenharmony_ci#ifdef DEBUG
236bf215546Sopenharmony_ci#define debug_warning(__msg) \
237bf215546Sopenharmony_ci   _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
238bf215546Sopenharmony_ci#else
239bf215546Sopenharmony_ci#define debug_warning(__msg) \
240bf215546Sopenharmony_ci   ((void)0)
241bf215546Sopenharmony_ci#endif
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci/**
245bf215546Sopenharmony_ci * Emit a warning message, but only once.
246bf215546Sopenharmony_ci */
247bf215546Sopenharmony_ci#ifdef DEBUG
248bf215546Sopenharmony_ci#define debug_warn_once(__msg) \
249bf215546Sopenharmony_ci   do { \
250bf215546Sopenharmony_ci      static bool warned = false; \
251bf215546Sopenharmony_ci      if (!warned) { \
252bf215546Sopenharmony_ci         _debug_printf("%s:%u:%s: one time warning: %s\n", \
253bf215546Sopenharmony_ci                       __FILE__, __LINE__, __FUNCTION__, __msg); \
254bf215546Sopenharmony_ci         warned = true; \
255bf215546Sopenharmony_ci      } \
256bf215546Sopenharmony_ci   } while (0)
257bf215546Sopenharmony_ci#else
258bf215546Sopenharmony_ci#define debug_warn_once(__msg) \
259bf215546Sopenharmony_ci   ((void)0)
260bf215546Sopenharmony_ci#endif
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci/**
264bf215546Sopenharmony_ci * Output an error message. Not muted on release version.
265bf215546Sopenharmony_ci */
266bf215546Sopenharmony_ci#ifdef DEBUG
267bf215546Sopenharmony_ci#define debug_error(__msg) \
268bf215546Sopenharmony_ci   _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
269bf215546Sopenharmony_ci#else
270bf215546Sopenharmony_ci#define debug_error(__msg) \
271bf215546Sopenharmony_ci   _debug_printf("error: %s\n", __msg)
272bf215546Sopenharmony_ci#endif
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci/**
275bf215546Sopenharmony_ci * Output a debug log message to the debug info callback.
276bf215546Sopenharmony_ci */
277bf215546Sopenharmony_ci#define util_debug_message(cb, type, fmt, ...) do { \
278bf215546Sopenharmony_ci   static unsigned id = 0; \
279bf215546Sopenharmony_ci   if ((cb) && (cb)->debug_message) { \
280bf215546Sopenharmony_ci      _util_debug_message(cb, &id, \
281bf215546Sopenharmony_ci                          UTIL_DEBUG_TYPE_ ## type, \
282bf215546Sopenharmony_ci                          fmt, ##__VA_ARGS__); \
283bf215546Sopenharmony_ci   } \
284bf215546Sopenharmony_ci} while (0)
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_civoid
287bf215546Sopenharmony_ci_util_debug_message(
288bf215546Sopenharmony_ci   struct util_debug_callback *cb,
289bf215546Sopenharmony_ci   unsigned *id,
290bf215546Sopenharmony_ci   enum util_debug_type type,
291bf215546Sopenharmony_ci   const char *fmt, ...) _util_printf_format(4, 5);
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci/**
295bf215546Sopenharmony_ci * Used by debug_dump_enum and debug_dump_flags to describe symbols.
296bf215546Sopenharmony_ci */
297bf215546Sopenharmony_cistruct debug_named_value
298bf215546Sopenharmony_ci{
299bf215546Sopenharmony_ci   const char *name;
300bf215546Sopenharmony_ci   uint64_t value;
301bf215546Sopenharmony_ci   const char *desc;
302bf215546Sopenharmony_ci};
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci/**
306bf215546Sopenharmony_ci * Some C pre-processor magic to simplify creating named values.
307bf215546Sopenharmony_ci *
308bf215546Sopenharmony_ci * Example:
309bf215546Sopenharmony_ci * @code
310bf215546Sopenharmony_ci * static const debug_named_value my_names[] = {
311bf215546Sopenharmony_ci *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
312bf215546Sopenharmony_ci *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
313bf215546Sopenharmony_ci *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
314bf215546Sopenharmony_ci *    DEBUG_NAMED_VALUE_END
315bf215546Sopenharmony_ci * };
316bf215546Sopenharmony_ci *
317bf215546Sopenharmony_ci *    ...
318bf215546Sopenharmony_ci *    debug_printf("%s = %s\n",
319bf215546Sopenharmony_ci *                 name,
320bf215546Sopenharmony_ci *                 debug_dump_enum(my_names, my_value));
321bf215546Sopenharmony_ci *    ...
322bf215546Sopenharmony_ci * @endcode
323bf215546Sopenharmony_ci */
324bf215546Sopenharmony_ci#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol, NULL}
325bf215546Sopenharmony_ci#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
326bf215546Sopenharmony_ci#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci/**
330bf215546Sopenharmony_ci * Convert a enum value to a string.
331bf215546Sopenharmony_ci */
332bf215546Sopenharmony_ciconst char *
333bf215546Sopenharmony_cidebug_dump_enum(const struct debug_named_value *names,
334bf215546Sopenharmony_ci                unsigned long value);
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ciconst char *
337bf215546Sopenharmony_cidebug_dump_enum_noprefix(const struct debug_named_value *names,
338bf215546Sopenharmony_ci                         const char *prefix,
339bf215546Sopenharmony_ci                         unsigned long value);
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci/**
343bf215546Sopenharmony_ci * Convert binary flags value to a string.
344bf215546Sopenharmony_ci */
345bf215546Sopenharmony_ciconst char *
346bf215546Sopenharmony_cidebug_dump_flags(const struct debug_named_value *names,
347bf215546Sopenharmony_ci                 unsigned long value);
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci/**
351bf215546Sopenharmony_ci * Function enter exit loggers
352bf215546Sopenharmony_ci */
353bf215546Sopenharmony_ci#ifdef DEBUG
354bf215546Sopenharmony_ciint debug_funclog_enter(const char* f, const int line, const char* file);
355bf215546Sopenharmony_civoid debug_funclog_exit(const char* f, const int line, const char* file);
356bf215546Sopenharmony_civoid debug_funclog_enter_exit(const char* f, const int line, const char* file);
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci#define DEBUG_FUNCLOG_ENTER() \
359bf215546Sopenharmony_ci   int __debug_decleration_work_around = \
360bf215546Sopenharmony_ci      debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
361bf215546Sopenharmony_ci#define DEBUG_FUNCLOG_EXIT() \
362bf215546Sopenharmony_ci   do { \
363bf215546Sopenharmony_ci      (void)__debug_decleration_work_around; \
364bf215546Sopenharmony_ci      debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
365bf215546Sopenharmony_ci      return; \
366bf215546Sopenharmony_ci   } while(0)
367bf215546Sopenharmony_ci#define DEBUG_FUNCLOG_EXIT_RET(ret) \
368bf215546Sopenharmony_ci   do { \
369bf215546Sopenharmony_ci      (void)__debug_decleration_work_around; \
370bf215546Sopenharmony_ci      debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
371bf215546Sopenharmony_ci      return ret; \
372bf215546Sopenharmony_ci   } while(0)
373bf215546Sopenharmony_ci#define DEBUG_FUNCLOG_ENTER_EXIT() \
374bf215546Sopenharmony_ci   debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci#else
377bf215546Sopenharmony_ci#define DEBUG_FUNCLOG_ENTER() \
378bf215546Sopenharmony_ci   int __debug_decleration_work_around
379bf215546Sopenharmony_ci#define DEBUG_FUNCLOG_EXIT() \
380bf215546Sopenharmony_ci   do { (void)__debug_decleration_work_around; return; } while(0)
381bf215546Sopenharmony_ci#define DEBUG_FUNCLOG_EXIT_RET(ret) \
382bf215546Sopenharmony_ci   do { (void)__debug_decleration_work_around; return ret; } while(0)
383bf215546Sopenharmony_ci#define DEBUG_FUNCLOG_ENTER_EXIT()
384bf215546Sopenharmony_ci#endif
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci/**
388bf215546Sopenharmony_ci * Get option.
389bf215546Sopenharmony_ci *
390bf215546Sopenharmony_ci * It is an alias for getenv on Linux.
391bf215546Sopenharmony_ci *
392bf215546Sopenharmony_ci * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
393bf215546Sopenharmony_ci * endings with one option per line as
394bf215546Sopenharmony_ci *
395bf215546Sopenharmony_ci *   NAME=value
396bf215546Sopenharmony_ci *
397bf215546Sopenharmony_ci * This file must be terminated with an extra empty line.
398bf215546Sopenharmony_ci */
399bf215546Sopenharmony_ciconst char *
400bf215546Sopenharmony_cidebug_get_option(const char *name, const char *dfault);
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_cibool
403bf215546Sopenharmony_cidebug_get_bool_option(const char *name, bool dfault);
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_cilong
406bf215546Sopenharmony_cidebug_get_num_option(const char *name, long dfault);
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ciuint64_t
409bf215546Sopenharmony_cidebug_get_flags_option(const char *name,
410bf215546Sopenharmony_ci                       const struct debug_named_value *flags,
411bf215546Sopenharmony_ci                       uint64_t dfault);
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci#define DEBUG_GET_ONCE_OPTION(suffix, name, dfault) \
414bf215546Sopenharmony_cistatic const char * \
415bf215546Sopenharmony_cidebug_get_option_ ## suffix (void) \
416bf215546Sopenharmony_ci{ \
417bf215546Sopenharmony_ci   static bool initialized = false; \
418bf215546Sopenharmony_ci   static const char * value; \
419bf215546Sopenharmony_ci   if (!initialized) { \
420bf215546Sopenharmony_ci      initialized = true; \
421bf215546Sopenharmony_ci      value = debug_get_option(name, dfault); \
422bf215546Sopenharmony_ci   } \
423bf215546Sopenharmony_ci   return value; \
424bf215546Sopenharmony_ci}
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_cistatic inline bool
427bf215546Sopenharmony_ci__check_suid(void)
428bf215546Sopenharmony_ci{
429bf215546Sopenharmony_ci#if !defined(_WIN32)
430bf215546Sopenharmony_ci   if (geteuid() != getuid())
431bf215546Sopenharmony_ci      return true;
432bf215546Sopenharmony_ci#endif
433bf215546Sopenharmony_ci   return false;
434bf215546Sopenharmony_ci}
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci/**
437bf215546Sopenharmony_ci * Define a getter for a debug option which specifies a 'FILE *'
438bf215546Sopenharmony_ci * to open, with additional checks for suid executables.  Note
439bf215546Sopenharmony_ci * that if the return is not NULL, the caller owns the 'FILE *'
440bf215546Sopenharmony_ci * reference.
441bf215546Sopenharmony_ci */
442bf215546Sopenharmony_ci#define DEBUG_GET_ONCE_FILE_OPTION(suffix, name, dfault, mode) \
443bf215546Sopenharmony_cistatic FILE * \
444bf215546Sopenharmony_cidebug_get_option_ ## suffix (void) \
445bf215546Sopenharmony_ci{ \
446bf215546Sopenharmony_ci   static bool initialized = false; \
447bf215546Sopenharmony_ci   static const char * value; \
448bf215546Sopenharmony_ci   if (__check_suid()) \
449bf215546Sopenharmony_ci      return NULL; \
450bf215546Sopenharmony_ci   if (!initialized) { \
451bf215546Sopenharmony_ci      initialized = true; \
452bf215546Sopenharmony_ci      value = debug_get_option(name, dfault); \
453bf215546Sopenharmony_ci   } \
454bf215546Sopenharmony_ci   if (!value) \
455bf215546Sopenharmony_ci      return NULL; \
456bf215546Sopenharmony_ci   return fopen(value, mode); \
457bf215546Sopenharmony_ci}
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \
460bf215546Sopenharmony_cistatic bool \
461bf215546Sopenharmony_cidebug_get_option_ ## sufix (void) \
462bf215546Sopenharmony_ci{ \
463bf215546Sopenharmony_ci   static bool initialized = false; \
464bf215546Sopenharmony_ci   static bool value; \
465bf215546Sopenharmony_ci   if (!initialized) { \
466bf215546Sopenharmony_ci      initialized = true; \
467bf215546Sopenharmony_ci      value = debug_get_bool_option(name, dfault); \
468bf215546Sopenharmony_ci   } \
469bf215546Sopenharmony_ci   return value; \
470bf215546Sopenharmony_ci}
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ci#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \
473bf215546Sopenharmony_cistatic long \
474bf215546Sopenharmony_cidebug_get_option_ ## sufix (void) \
475bf215546Sopenharmony_ci{ \
476bf215546Sopenharmony_ci   static bool initialized = false; \
477bf215546Sopenharmony_ci   static long value; \
478bf215546Sopenharmony_ci   if (!initialized) { \
479bf215546Sopenharmony_ci      initialized = true; \
480bf215546Sopenharmony_ci      value = debug_get_num_option(name, dfault); \
481bf215546Sopenharmony_ci   } \
482bf215546Sopenharmony_ci   return value; \
483bf215546Sopenharmony_ci}
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \
486bf215546Sopenharmony_cistatic unsigned long \
487bf215546Sopenharmony_cidebug_get_option_ ## sufix (void) \
488bf215546Sopenharmony_ci{ \
489bf215546Sopenharmony_ci   static bool initialized = false; \
490bf215546Sopenharmony_ci   static unsigned long value; \
491bf215546Sopenharmony_ci   if (!initialized) { \
492bf215546Sopenharmony_ci      initialized = true; \
493bf215546Sopenharmony_ci      value = debug_get_flags_option(name, flags, dfault); \
494bf215546Sopenharmony_ci   } \
495bf215546Sopenharmony_ci   return value; \
496bf215546Sopenharmony_ci}
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci#ifdef __cplusplus
500bf215546Sopenharmony_ci}
501bf215546Sopenharmony_ci#endif
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ci#endif /* U_DEBUG_H_ */
504