@@ -273,10 +273,26 @@ ruby_set_debug_option(const char *str)
273273
274274enum ruby_debug_log_mode ruby_debug_log_mode ;
275275
276+ struct debug_log_filter {
277+ enum debug_log_filter_type {
278+ dlf_all ,
279+ dlf_file , // "file:..."
280+ dlf_func , // "func:..."
281+ } type ;
282+ bool negative ;
283+ char str [MAX_DEBUG_LOG_FILTER_LEN ];
284+ };
285+
286+ static const char * dlf_type_names [] = {
287+ "all" ,
288+ "file" ,
289+ "func" ,
290+ };
291+
276292static struct {
277293 char * mem ;
278294 unsigned int cnt ;
279- char filters [MAX_DEBUG_LOG_FILTER_NUM ][ MAX_DEBUG_LOG_FILTER_LEN ];
295+ struct debug_log_filter filters [MAX_DEBUG_LOG_FILTER_NUM ];
280296 unsigned int filters_num ;
281297 rb_nativethread_lock_t lock ;
282298 FILE * output ;
@@ -288,6 +304,23 @@ RUBY_DEBUG_LOG_MEM_ENTRY(unsigned int index)
288304 return & debug_log .mem [MAX_DEBUG_LOG_MESSAGE_LEN * index ];
289305}
290306
307+ static enum debug_log_filter_type
308+ filter_type (const char * str , int * skiplen )
309+ {
310+ if (strncmp (str , "file:" , 5 ) == 0 ) {
311+ * skiplen = 5 ;
312+ return dlf_file ;
313+ }
314+ else if (strncmp (str , "func:" , 5 ) == 0 ) {
315+ * skiplen = 5 ;
316+ return dlf_func ;
317+ }
318+ else {
319+ * skiplen = 0 ;
320+ return dlf_all ;
321+ }
322+ }
323+
291324static void
292325setup_debug_log (void )
293326{
@@ -323,78 +356,121 @@ setup_debug_log(void)
323356 const char * filter_config = getenv ("RUBY_DEBUG_LOG_FILTER" );
324357 if (filter_config && strlen (filter_config ) > 0 ) {
325358 unsigned int i ;
326- for (i = 0 ; i < MAX_DEBUG_LOG_FILTER_NUM ; i ++ ) {
359+ for (i = 0 ; i < MAX_DEBUG_LOG_FILTER_NUM && filter_config ; i ++ ) {
360+ size_t len ;
361+ const char * str = filter_config ;
327362 const char * p ;
328- if ((p = strchr (filter_config , ',' )) == NULL ) {
329- if (strlen (filter_config ) >= MAX_DEBUG_LOG_FILTER_LEN ) {
330- fprintf (stderr , "too long: %s (max:%d)\n" , filter_config , MAX_DEBUG_LOG_FILTER_LEN );
331- exit (1 );
332- }
333- strncpy (debug_log .filters [i ], filter_config , MAX_DEBUG_LOG_FILTER_LEN - 1 );
334- i ++ ;
335- break ;
363+
364+ if ((p = strchr (str , ',' )) == NULL ) {
365+ len = strlen (str );
366+ filter_config = NULL ;
336367 }
337368 else {
338- size_t n = p - filter_config ;
339- if (n >= MAX_DEBUG_LOG_FILTER_LEN ) {
340- fprintf (stderr , "too long: %s (max:%d)\n" , filter_config , MAX_DEBUG_LOG_FILTER_LEN );
341- exit (1 );
342- }
343- strncpy (debug_log .filters [i ], filter_config , n );
344- filter_config = p + 1 ;
369+ len = p - str - 1 ; // 1 is ','
370+ filter_config = p + 1 ;
371+ }
372+
373+ // positive/negative
374+ if (* str == '-' ) {
375+ debug_log .filters [i ].negative = true;
376+ str ++ ;
377+ } else if (* str == '+' ) {
378+ // negative is false on default.
379+ str ++ ;
380+ }
381+
382+ // type
383+ int skiplen ;
384+ debug_log .filters [i ].type = filter_type (str , & skiplen );
385+ len -= skiplen ;
386+
387+ if (len >= MAX_DEBUG_LOG_FILTER_LEN ) {
388+ fprintf (stderr , "too long: %s (max:%d)\n" , str , MAX_DEBUG_LOG_FILTER_LEN - 1 );
389+ exit (1 );
345390 }
391+
392+ // body
393+ strncpy (debug_log .filters [i ].str , str + skiplen , len );
394+ debug_log .filters [i ].str [len ] = 0 ;
346395 }
347396 debug_log .filters_num = i ;
397+
348398 for (i = 0 ; i < debug_log .filters_num ; i ++ ) {
349- fprintf (stderr , "RUBY_DEBUG_LOG_FILTER[%d]=%s\n" , i , debug_log .filters [i ]);
399+ fprintf (stderr , "RUBY_DEBUG_LOG_FILTER[%d]=%s (%s%s)\n" , i ,
400+ debug_log .filters [i ].str ,
401+ debug_log .filters [i ].negative ? "-" : "" ,
402+ dlf_type_names [debug_log .filters [i ].type ]);
403+ }
404+ }
405+ }
406+
407+ static bool
408+ check_filter (const char * str , const struct debug_log_filter * filter , bool * state )
409+ {
410+ if (filter -> negative ) {
411+ if (strstr (str , filter -> str ) == NULL ) {
412+ * state = true;
413+ return false;
414+ }
415+ else {
416+ * state = false;
417+ return true;
418+ }
419+ }
420+ else {
421+ if (strstr (str , filter -> str ) != NULL ) {
422+ * state = true;
423+ return true;
424+ }
425+ else {
426+ * state = false;
427+ return false;
350428 }
351429 }
352430}
353431
354432//
355433// RUBY_DEBUG_LOG_FILTER=-foo,-bar,baz,boo
356434// returns true if
357- // func_name doesn't contain foo
435+ // ( func_name or file_name) doesn't contain foo
358436// and
359- // func_name doesn't contain bar
437+ // ( func_name or file_name) doesn't contain bar
360438// and
361- // func_name contains baz or boo
439+ // ( func_name or file_name) contains baz or boo
362440//
363441// RUBY_DEBUG_LOG_FILTER=foo,bar,-baz,-boo
364442// retunrs true if
365- // func_name contains foo or bar
443+ // ( func_name or file_name) contains foo or bar
366444// or
367- // func_name doesn't contain baz and
368- // func_name doesn't contain boo and
445+ // (func_name or file_name) doesn't contain baz and
446+ // (func_name or file_name) doesn't contain boo and
447+ //
448+ // You can specify "file:" (ex file:foo) or "func:" (ex func:foo)
449+ // prefixes to specify the filter for.
369450//
370451bool
371- ruby_debug_log_filter (const char * func_name )
452+ ruby_debug_log_filter (const char * func_name , const char * file_name )
372453{
373454 if (debug_log .filters_num > 0 ) {
374- bool status = false;
455+ bool state = false;
375456
376457 for (unsigned int i = 0 ; i < debug_log .filters_num ; i ++ ) {
377- const char * filter = debug_log .filters [i ];
378-
379- if (* filter == '-' ) {
380- if (strstr (func_name , & filter [1 ]) == NULL ) {
381- status = true;
382- }
383- else {
384- return false;
385- }
386- }
387- else {
388- if (strstr (func_name , filter ) != NULL ) {
389- return true;
390- }
391- else {
392- status = false;
393- }
458+ const struct debug_log_filter * filter = & debug_log .filters [i ];
459+
460+ switch (filter -> type ) {
461+ case dlf_all :
462+ if (check_filter (func_name , filter , & state )) return state ;
463+ if (check_filter (file_name , filter , & state )) return state ;
464+ break ;
465+ case dlf_func :
466+ if (check_filter (func_name , filter , & state )) return state ;
467+ break ;
468+ case dlf_file :
469+ if (check_filter (file_name , filter , & state )) return state ;
470+ break ;
394471 }
395472 }
396-
397- return status ;
473+ return state ;
398474 }
399475 else {
400476 return true;
0 commit comments