[前][次][番号順一覧][スレッド一覧]

ruby-changes:72101

From: Koichi <ko1@a...>
Date: Thu, 9 Jun 2022 01:51:30 +0900 (JST)
Subject: [ruby-changes:72101] 5a4f997b2e (master): func: and file: prefix for `RUBY_DEBUG_LOG_FILTER`

https://git.ruby-lang.org/ruby.git/commit/?id=5a4f997b2e

From 5a4f997b2e8e819ed40731cd769826112072a9d4 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Wed, 8 Jun 2022 16:14:20 +0900
Subject: func: and file: prefix for `RUBY_DEBUG_LOG_FILTER`

`RUBY_DEBUG_LOG_FILTER` specified only function names but this
patch also check file names for each log events.
If you specify `file:` or `func:` prefix, it's only filter
file names or func names (otherwize check both).

  foo
  # show log when file or func names are mached with foo

  func:foo
  # show log when func name matches foo

  file:foo
  # show log when file name matches foo

  -file:foo,func:bar
  # show log when file name does not contains foo
  #           and func name matches bar
---
 debug.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 121 insertions(+), 45 deletions(-)

diff --git a/debug.c b/debug.c
index 6c9d6563db..b9df026af8 100644
--- a/debug.c
+++ b/debug.c
@@ -273,10 +273,26 @@ ruby_set_debug_option(const char *str) https://github.com/ruby/ruby/blob/trunk/debug.c#L273
 
 enum ruby_debug_log_mode ruby_debug_log_mode;
 
+struct debug_log_filter {
+    enum debug_log_filter_type {
+        dlf_all,
+        dlf_file, // "file:..."
+        dlf_func, // "func:..."
+    } type;
+    bool negative;
+    char str[MAX_DEBUG_LOG_FILTER_LEN];
+};
+
+static const char *dlf_type_names[] = {
+    "all",
+    "file",
+    "func",
+};
+
 static struct {
     char *mem;
     unsigned int cnt;
-    char filters[MAX_DEBUG_LOG_FILTER_NUM][MAX_DEBUG_LOG_FILTER_LEN];
+    struct debug_log_filter filters[MAX_DEBUG_LOG_FILTER_NUM];
     unsigned int filters_num;
     rb_nativethread_lock_t lock;
     FILE *output;
@@ -288,6 +304,23 @@ RUBY_DEBUG_LOG_MEM_ENTRY(unsigned int index) https://github.com/ruby/ruby/blob/trunk/debug.c#L304
     return &debug_log.mem[MAX_DEBUG_LOG_MESSAGE_LEN * index];
 }
 
+static enum debug_log_filter_type
+filter_type(const char *str, int *skiplen)
+{
+    if (strncmp(str, "file:", 5) == 0) {
+        *skiplen = 5;
+        return dlf_file;
+    }
+    else if(strncmp(str, "func:", 5) == 0) {
+        *skiplen = 5;
+        return dlf_func;
+    }
+    else {
+        *skiplen = 0;
+        return dlf_all;
+    }
+}
+
 static void
 setup_debug_log(void)
 {
@@ -323,30 +356,75 @@ setup_debug_log(void) https://github.com/ruby/ruby/blob/trunk/debug.c#L356
     const char *filter_config = getenv("RUBY_DEBUG_LOG_FILTER");
     if (filter_config && strlen(filter_config) > 0) {
         unsigned int i;
-        for (i=0; i<MAX_DEBUG_LOG_FILTER_NUM; i++) {
+        for (i=0; i<MAX_DEBUG_LOG_FILTER_NUM && filter_config; i++) {
+            size_t len;
+            const char *str = filter_config;
             const char *p;
-            if ((p = strchr(filter_config, ',')) == NULL) {
-                if (strlen(filter_config) >= MAX_DEBUG_LOG_FILTER_LEN) {
-                    fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER_LEN);
-                    exit(1);
-                }
-                strncpy(debug_log.filters[i], filter_config, MAX_DEBUG_LOG_FILTER_LEN - 1);
-                i++;
-                break;
+
+            if ((p = strchr(str, ',')) == NULL) {
+                len = strlen(str);
+                filter_config = NULL;
             }
             else {
-                size_t n = p - filter_config;
-                if (n >= MAX_DEBUG_LOG_FILTER_LEN) {
-                    fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER_LEN);
-                    exit(1);
-                }
-                strncpy(debug_log.filters[i], filter_config, n);
-                filter_config = p+1;
+                len = p - str - 1; // 1 is ','
+                filter_config = p + 1;
+            }
+
+            // positive/negative
+            if (*str == '-') {
+                debug_log.filters[i].negative = true;
+                str++;
+            } else if (*str == '+') {
+                // negative is false on default.
+                str++;
+            }
+
+            // type
+            int skiplen;
+            debug_log.filters[i].type = filter_type(str, &skiplen);
+            len -= skiplen;
+
+            if (len >= MAX_DEBUG_LOG_FILTER_LEN) {
+                fprintf(stderr, "too long: %s (max:%d)\n", str, MAX_DEBUG_LOG_FILTER_LEN - 1);
+                exit(1);
             }
+
+            // body
+            strncpy(debug_log.filters[i].str, str + skiplen, len);
+            debug_log.filters[i].str[len] = 0;
         }
         debug_log.filters_num = i;
+
         for (i=0; i<debug_log.filters_num; i++) {
-            fprintf(stderr, "RUBY_DEBUG_LOG_FILTER[%d]=%s\n", i, debug_log.filters[i]);
+            fprintf(stderr, "RUBY_DEBUG_LOG_FILTER[%d]=%s (%s%s)\n", i,
+                    debug_log.filters[i].str,
+                    debug_log.filters[i].negative ? "-" : "",
+                    dlf_type_names[debug_log.filters[i].type]);
+        }
+    }
+}
+
+static bool
+check_filter(const char *str, const struct debug_log_filter *filter, bool *state)
+{
+    if (filter->negative) {
+        if (strstr(str, filter->str) == NULL) {
+            *state = true;
+            return false;
+        }
+        else {
+            *state = false;
+            return true;
+        }
+    }
+    else {
+        if (strstr(str, filter->str) != NULL) {
+            *state = true;
+            return true;
+        }
+        else {
+            *state = false;
+            return false;
         }
     }
 }
@@ -354,47 +432,45 @@ setup_debug_log(void) https://github.com/ruby/ruby/blob/trunk/debug.c#L432
 //
 // RUBY_DEBUG_LOG_FILTER=-foo,-bar,baz,boo
 // returns true if
-//   func_name doesn't contain foo
+//   (func_name or file_name) doesn't contain foo
 // and
-//   func_name doesn't contain bar
+//   (func_name or file_name) doesn't contain bar
 // and
-//   func_name contains baz or boo
+//   (func_name or file_name) contains baz or boo
 //
 // RUBY_DEBUG_LOG_FILTER=foo,bar,-baz,-boo
 // retunrs true if
-//   func_name contains foo or bar
+//   (func_name or file_name) contains foo or bar
 // or
-//   func_name doesn't contain baz and
-//   func_name doesn't contain boo and
+//   (func_name or file_name) doesn't contain baz and
+//   (func_name or file_name) doesn't contain boo and
+//
+// You can specify "file:" (ex file:foo) or "func:" (ex  func:foo)
+// prefixes to specify the filter for.
 //
 bool
-ruby_debug_log_filter(const char *func_name)
+ruby_debug_log_filter(const char *func_name, const char *file_name)
 {
     if (debug_log.filters_num > 0) {
-        bool status = false;
+        bool state = false;
 
         for (unsigned int i = 0; i<debug_log.filters_num; i++) {
-            const char *filter = debug_log.filters[i];
-
-            if (*filter == '-') {
-                if (strstr(func_name, &filter[1]) == NULL) {
-                    status = true;
-                }
-                else {
-                    return false;
-                }
-            }
-            else {
-                if (strstr(func_name, filter) != NULL) {
-                    return true;
-                }
-                else {
-                    status = false;
-                }
+            const struct debug_log_filter *filter = &debug_log.filters[i];
+
+            switch (filter->type) {
+              case dlf_all:
+                if (check_filter(func_name, filter, &state)) return state;
+                if (check_filter(file_name, filter, &state)) return state;
+                break;
+              case dlf_func:
+                if (check_filter(func_name, filter, &state)) return state;
+                break;
+              case dlf_file:
+                if (check_filter(file_name, filter, &state)) return state;
+                break;
             }
         }
-
-        return status;
+        return state;
     }
     else {
         return true;
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]