2 * Management of the debugging channels
4 * Copyright 2000 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * @brief Management of the debugging channels
39 extern STARTUP_OPTION startup_option;
40 static char logfile[256] = { 0, };
41 static char debugchfile[256] = {0, };
42 static inline int interlocked_xchg_add( int *dest, int incr )
45 __asm__ __volatile__( "lock; xaddl %0,(%1)"
46 : "=r" (ret) : "r" (dest), "0" (incr) : "memory" );
50 static const char * const debug_classes[] = {"fixme", "err", "warn", "trace", "info"};
52 #define MAX_DEBUG_OPTIONS 256
54 //static unsigned char default_flags = (1 << __DBCL_ERR) | (1 << __DBCL_FIXME) | (1 << __DBCL_INFO);
55 static unsigned char default_flags = (1 << __DBCL_ERR) | (1 << __DBCL_INFO);
56 static int nb_debug_options = -1;
57 static struct _debug_channel debug_options[MAX_DEBUG_OPTIONS];
59 static void debug_init(void);
61 static int cmp_name( const void *p1, const void *p2 )
63 const char *name = p1;
64 const struct _debug_channel *chan = p2;
65 return strcmp( name, chan->name );
68 /* get the flags to use for a given channel, possibly setting them too in case of lazy init */
69 unsigned char _dbg_get_channel_flags( struct _debug_channel *channel )
71 if (nb_debug_options == -1)
75 struct _debug_channel *opt;
77 /* first check for multi channel */
78 opt = bsearch( channel->multiname,
81 sizeof(debug_options[0]), cmp_name );
85 opt = bsearch( channel->name,
88 sizeof(debug_options[0]), cmp_name );
94 /* no option for this channel */
95 if (channel->flags & (1 << __DBCL_INIT))
96 channel->flags = default_flags;
101 /* set the flags to use for a given channel; return 0 if the channel is not available to set */
102 int _dbg_set_channel_flags( struct _debug_channel *channel,
103 unsigned char set, unsigned char clear )
105 if (nb_debug_options == -1)
108 if (nb_debug_options){
109 struct _debug_channel *opt;
111 /* first set for multi channel */
112 opt = bsearch( channel->multiname,
115 sizeof(debug_options[0]), cmp_name );
117 opt->flags = (opt->flags & ~clear) | set;
121 opt = bsearch( channel->name,
124 sizeof(debug_options[0]), cmp_name );
126 opt->flags = (opt->flags & ~clear) | set;
133 /* add a new debug option at the end of the option list */
134 static void add_option( const char *name, unsigned char set, unsigned char clear )
136 int min = 0, max = nb_debug_options - 1, pos, res;
138 if (!name[0]) /* "all" option */
140 default_flags = (default_flags & ~clear) | set;
144 if (strlen(name) >= sizeof(debug_options[0].name))
149 pos = (min + max) / 2;
150 res = strcmp( name, debug_options[pos].name );
153 debug_options[pos].flags = (debug_options[pos].flags & ~clear) | set;
161 if (nb_debug_options >= MAX_DEBUG_OPTIONS)
165 if (pos < nb_debug_options) {
166 memmove( &debug_options[pos + 1],
168 (nb_debug_options - pos) * sizeof(debug_options[0]) );
171 strcpy( debug_options[pos].name, name );
172 debug_options[pos].flags = (default_flags & ~clear) | set;
176 /* parse a set of debugging option specifications and add them to the option list */
177 static void parse_options( const char *str )
179 char *opt, *next, *options;
182 if (!(options = strdup(str)))
184 for (opt = options; opt; opt = next)
187 unsigned char set = 0, clear = 0;
189 if ((next = strchr( opt, ',' )))
192 p = opt + strcspn( opt, "+-" );
194 p = opt; /* assume it's a debug channel name */
198 for (i = 0; i < sizeof(debug_classes)/sizeof(debug_classes[0]); i++)
200 int len = strlen(debug_classes[i]);
201 if (len != (p - opt))
203 if (!memcmp( opt, debug_classes[i], len )) /* found it */
212 if (i == sizeof(debug_classes)/sizeof(debug_classes[0])) /* bad class name, skip it */
222 if (*p == '+' || *p == '-')
227 if (!strcmp( p, "all" ))
228 default_flags = (default_flags & ~clear) | set;
230 add_option( p, set, clear );
235 /* print the usage message */
236 static void debug_usage(void)
238 static const char usage[] =
239 "Syntax of the DEBUGCH variable:\n"
240 " DEBUGCH=[class]+xxx,[class]-yyy,...\n\n"
241 "Example: DEBUGCH=+all,warn-heap\n"
242 " turns on all messages except warning heap messages\n"
243 "Available message classes: err, warn, fixme, trace\n";
244 const int ret = write( 2, usage, sizeof(usage) - 1 );
249 /* initialize all options at startup */
250 static void debug_init(void)
255 char *tizen_vms_path = NULL;
257 if (nb_debug_options != -1)
258 return; /* already initialized */
260 nb_debug_options = 0;
261 strcpy(debugchfile, get_etc_path());
262 strcat(debugchfile, "/DEBUGCH");
264 fp= fopen(debugchfile, "r");
266 debug = getenv("DEBUGCH");
268 if ((tmp= (char *)malloc(1024 + 1)) == NULL){
273 fseek(fp, 0, SEEK_SET);
274 const char* str = fgets(tmp, 1024, fp);
276 tmp[strlen(tmp)-1] = 0;
284 if (!strcmp( debug, "help" ))
286 parse_options( debug );
293 //to make logfile, create tizen_vms dir
294 tizen_vms_path = (char*)get_tizen_vms_path();
295 if(access(tizen_vms_path, R_OK) != 0){
296 g_mkdir_with_parents(tizen_vms_path, 0755);
298 strcpy(logfile, tizen_vms_path);
299 strcat(logfile, EMULMGR_LOGFILE);
301 free(tizen_vms_path);
303 if(access(logfile, F_OK | R_OK) == 0)
307 /* allocate some tmp string space */
308 /* FIXME: this is not 100% thread-safe */
309 char *get_dbg_temp_buffer( size_t size )
311 static char *list[32];
316 idx = interlocked_xchg_add( &pos, 1 ) % (sizeof(list)/sizeof(list[0]));
318 if ((ret = realloc( list[idx], size )))
324 /* release unused part of the buffer */
325 void release_dbg_temp_buffer( char *buffer, size_t size )
327 /* don't bother doing anything */
332 static int dbg_vprintf( const char *format, va_list args )
334 char tmp[MSGSIZE_MAX] = { 0, };
335 char txt[MSGSIZE_MAX] = { 0, };
340 int ret = vsnprintf( tmp, MSGSIZE_MAX, format, args );
342 tmp[MSGSIZE_MAX - 2] = '\n';
343 tmp[MSGSIZE_MAX - 1] = 0;
345 sprintf(txt, "%s", tmp);
348 if ((fp = fopen(logfile, "a+")) == NULL) {
349 fprintf(stdout, "Emulator manager can't open.\n"
351 "this binary file is running on the right path.\n");
361 int dbg_printf( const char *format, ... )
366 va_start(valist, format);
367 ret = dbg_vprintf( format, valist );
373 int dbg_printf_nonewline( const char *format, ... )
378 va_start(valist, format);
379 ret = dbg_vprintf( format, valist );
385 /* printf with temp buffer allocation */
386 const char *dbg_sprintf( const char *format, ... )
388 static const int max_size = 200;
393 va_start(valist, format);
394 ret = get_dbg_temp_buffer( max_size );
395 len = vsnprintf( ret, max_size, format, valist );
396 if (len == -1 || len >= max_size)
399 release_dbg_temp_buffer( ret, len + 1 );
404 /* default implementation of dbg_vlog */
405 static int dbg_vlog( enum _debug_class cls, struct _debug_channel *channel,
406 const char *format, va_list args )
410 if (cls < sizeof(debug_classes)/sizeof(debug_classes[0])) {
412 /* to print debug class, channel */
413 ret += dbg_printf_nonewline("[%s:%s"
414 , debug_classes[cls] , channel->name);
416 if (*channel->multiname)
417 ret += dbg_printf_nonewline(":%s] ", channel->multiname);
419 ret += dbg_printf_nonewline("] ");
422 ret += dbg_vprintf( format, args );
427 int dbg_log( enum _debug_class cls, struct _debug_channel *channel,
428 const char *format, ... )
433 if (!(_dbg_get_channel_flags( channel ) & (1 << cls)))
436 va_start(valist, format);
437 ret = dbg_vlog( cls, channel, format, valist );
445 void assert_fail(char *exp, const char *file, int line)
447 fprintf(stderr, "[%s][%d] Assert(%s) failed \n"
449 fprintf(stdout, "[%s][%d] Assert(%s) failed \n"
454 /* end of debug_ch.c */