diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2011-04-18 16:18:55 +0200 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2011-04-18 16:21:49 +0200 |
| commit | f6be25a8705b40c2c5127b52479485d904d38b64 (patch) | |
| tree | dc569bf01f47e01e70c8820a7a6341ac229154dd /src/rt/rust_log.cpp | |
| parent | f12998e5d7a4409d2bf748a671c345a79085213e (diff) | |
| download | rust-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.cpp | 83 |
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); +} |
