about summary refs log tree commit diff
path: root/src/rt/rust_log.cpp
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-04-18 16:18:55 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-04-18 16:21:49 +0200
commitf6be25a8705b40c2c5127b52479485d904d38b64 (patch)
treedc569bf01f47e01e70c8820a7a6341ac229154dd /src/rt/rust_log.cpp
parentf12998e5d7a4409d2bf748a671c345a79085213e (diff)
downloadrust-f6be25a8705b40c2c5127b52479485d904d38b64.tar.gz
rust-f6be25a8705b40c2c5127b52479485d904d38b64.zip
Update foregoing patches to leave rust_crate alone.
Apparently it can't live in the main binary, since on non-Linux
platforms, dynamics libs won't find symbols in the binary. This
removes the crate_map pointer from rust_crate again, and instead
passes it as an extra argument to rust_start. Rustboot doesn't pass
this argument, but supposedly that's okay as long as we don't actually
use it on that platform.
Diffstat (limited to 'src/rt/rust_log.cpp')
-rw-r--r--src/rt/rust_log.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/rt/rust_log.cpp b/src/rt/rust_log.cpp
index 076c4b0ae7a..8f074cdf3cb 100644
--- a/src/rt/rust_log.cpp
+++ b/src/rt/rust_log.cpp
@@ -218,3 +218,86 @@ void
 rust_log::reset_indent(uint32_t indent) {
     _indent = indent;
 }
+
+struct mod_entry {
+    const char* name;
+    int* state;
+};
+
+struct cratemap {
+    mod_entry* entries;
+    cratemap* children[1];
+};
+
+struct log_directive {
+    char* name;
+    size_t level;
+};
+
+const size_t max_log_directives = 255;
+
+// This is a rather ugly parser for strings in the form
+// "crate1,crate2.mod3,crate3.x=2". Log levels range 0=err, 1=warn, 2=info,
+// 3=debug. Default is 1. Words without an '=X' part set the log level for
+// that module (and submodules) to 3.
+size_t parse_logging_spec(char* spec, log_directive* dirs) {
+    size_t dir = 0;
+    while (dir < max_log_directives && *spec) {
+        char* start = spec;
+        char cur;
+        while (true) {
+            cur = *spec;
+            if (cur == ',' || cur == '=' || cur == '\0') {
+                if (start == spec) {spec++; break;}
+                *spec = '\0';
+                spec++;
+                size_t level = 3;
+                if (cur == '=') {
+                    level = *spec - '0';
+                    if (level > 3) level = 1;
+                    if (*spec) ++spec;
+                }
+                dirs[dir].name = start;
+                dirs[dir++].level = level;
+                break;
+            }
+            spec++;
+        }
+    }
+    return dir;
+}
+
+void update_crate_map(cratemap* map, log_directive* dirs, size_t n_dirs) {
+    // First update log levels for this crate
+    for (mod_entry* cur = map->entries; cur->name; cur++) {
+        size_t level = 1, longest_match = 0;
+        for (size_t d = 0; d < n_dirs; d++) {
+            if (strstr(cur->name, dirs[d].name) == cur->name &&
+                strlen(dirs[d].name) > longest_match) {
+                longest_match = strlen(dirs[d].name);
+                level = dirs[d].level;
+            }
+        }
+        *cur->state = level;
+    }
+
+    // Then recurse on linked crates
+    for (size_t i = 0; map->children[i]; i++) {
+        update_crate_map(map->children[i], dirs, n_dirs);
+    }
+}
+
+void update_log_settings(void* crate_map, char* settings) {
+    char* buffer = NULL;
+    log_directive dirs[256];
+    size_t dir = 0;
+    if (settings) {
+        buffer = (char*)malloc(strlen(settings));
+        strcpy(buffer, settings);
+        dir = parse_logging_spec(buffer, &dirs[0]);
+    }
+
+    update_crate_map((cratemap*)crate_map, &dirs[0], dir);
+
+    free(buffer);
+}