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