auto merge of #9593 : fhahn/rust/logging-unsafe-removal, r=alexcrichton
This pull request changes to memory layout of the `CrateMap` struct to use static slices instead of raw pointers. Most of the discussion took place [here](63b5975efa (L1R92)
) .
The memory layout of CrateMap changed, without bumping the version number in the struct. Another, more backward compatible, solution would be to keep the old code and increase the version number in the new struct. On the other hand, the `annihilate_fn` pointer was removed without bumping the version number recently.
At the moment, the stage0 compiler does not use the new memory layout, which would lead the segfaults during stage0 compilation, so I've added a dummy `iter_crate_map` function for stage0, which does nothing. Again, this could be avoided if we'd bump the version number in the struct and keep the old code.
I'd like to use a normal `for` loop [here](https://github.com/fhahn/rust/compare/logging-unsafe-removal?expand=1#L1R109),
for child in children.iter() {
do_iter_crate_map(child, |x| f(x), visited);
}
but for some reason this only yields `error: unresolved enum variant, struct or const 'Some'` and I have no idea why.
This commit is contained in:
commit
c05fbc5a2c
3 changed files with 342 additions and 223 deletions
|
@ -54,7 +54,7 @@ use middle::trans::glue;
|
|||
use middle::trans::inline;
|
||||
use middle::trans::llrepr::LlvmRepr;
|
||||
use middle::trans::machine;
|
||||
use middle::trans::machine::{llalign_of_min, llsize_of};
|
||||
use middle::trans::machine::{llalign_of_min, llsize_of, llsize_of_alloc};
|
||||
use middle::trans::meth;
|
||||
use middle::trans::monomorphize;
|
||||
use middle::trans::tvec;
|
||||
|
@ -2911,9 +2911,10 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef {
|
||||
let elttype = Type::struct_([ccx.int_type, ccx.int_type], false);
|
||||
let maptype = Type::array(&elttype, (ccx.module_data.len() + 1) as u64);
|
||||
pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint, uint) {
|
||||
let str_slice_type = Type::struct_([Type::i8p(), ccx.int_type], false);
|
||||
let elttype = Type::struct_([str_slice_type, ccx.int_type], false);
|
||||
let maptype = Type::array(&elttype, ccx.module_data.len() as u64);
|
||||
let map = do "_rust_mod_map".with_c_str |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
|
||||
|
@ -2932,18 +2933,17 @@ pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef {
|
|||
|
||||
for key in keys.iter() {
|
||||
let val = *ccx.module_data.find_equiv(key).unwrap();
|
||||
let s_const = C_cstr(ccx, *key);
|
||||
let s_ptr = p2i(ccx, s_const);
|
||||
let v_ptr = p2i(ccx, val);
|
||||
let elt = C_struct([s_ptr, v_ptr]);
|
||||
let elt = C_struct([
|
||||
C_estr_slice(ccx, *key),
|
||||
v_ptr
|
||||
]);
|
||||
elts.push(elt);
|
||||
}
|
||||
let term = C_struct([C_int(ccx, 0), C_int(ccx, 0)]);
|
||||
elts.push(term);
|
||||
unsafe {
|
||||
llvm::LLVMSetInitializer(map, C_array(elttype, elts));
|
||||
}
|
||||
return map;
|
||||
return (map, keys.len(), llsize_of_alloc(ccx, elttype));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2959,9 +2959,10 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
|
|||
} else {
|
||||
~"toplevel"
|
||||
};
|
||||
|
||||
let sym_name = ~"_rust_crate_map_" + mapname;
|
||||
let arrtype = Type::array(&int_type, n_subcrates as u64);
|
||||
let maptype = Type::struct_([Type::i32(), int_type, arrtype], false);
|
||||
let slicetype = Type::struct_([int_type, int_type], false);
|
||||
let maptype = Type::struct_([Type::i32(), slicetype, slicetype], false);
|
||||
let map = do sym_name.with_c_str |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
|
||||
|
@ -2996,14 +2997,29 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
|
|||
subcrates.push(p2i(ccx, cr));
|
||||
i += 1;
|
||||
}
|
||||
subcrates.push(C_int(ccx, 0));
|
||||
|
||||
unsafe {
|
||||
let mod_map = create_module_map(ccx);
|
||||
let maptype = Type::array(&ccx.int_type, subcrates.len() as u64);
|
||||
let vec_elements = do "_crate_map_child_vectors".with_c_str |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
|
||||
};
|
||||
lib::llvm::SetLinkage(vec_elements, lib::llvm::InternalLinkage);
|
||||
|
||||
llvm::LLVMSetInitializer(vec_elements, C_array(ccx.int_type, subcrates));
|
||||
let (mod_map, mod_count, mod_struct_size) = create_module_map(ccx);
|
||||
|
||||
llvm::LLVMSetInitializer(map, C_struct(
|
||||
[C_i32(1),
|
||||
[C_i32(2),
|
||||
C_struct([
|
||||
p2i(ccx, mod_map),
|
||||
C_array(ccx.int_type, subcrates)]));
|
||||
// byte size of the module map array, an entry consists of two integers
|
||||
C_int(ccx, ((mod_count * mod_struct_size) as int))
|
||||
]),
|
||||
C_struct([
|
||||
p2i(ccx, vec_elements),
|
||||
// byte size of the subcrates array, an entry consists of an integer
|
||||
C_int(ccx, (subcrates.len() * llsize_of_alloc(ccx, ccx.int_type)) as int)
|
||||
])
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,17 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use container::MutableSet;
|
||||
use hashmap::HashSet;
|
||||
use option::{Some, None, Option};
|
||||
use vec::ImmutableVector;
|
||||
|
||||
/// Imports for old crate map versions
|
||||
use cast::transmute;
|
||||
use libc::c_char;
|
||||
use ptr;
|
||||
use ptr::RawPtr;
|
||||
use str::raw::from_c_str;
|
||||
use vec;
|
||||
use hashmap::HashSet;
|
||||
use container::MutableSet;
|
||||
|
||||
// Need to tell the linker on OS X to not barf on undefined symbols
|
||||
// and instead look them up at runtime, which we need to resolve
|
||||
|
@ -27,35 +31,52 @@ extern {}
|
|||
extern {
|
||||
#[weak_linkage]
|
||||
#[link_name = "_rust_crate_map_toplevel"]
|
||||
static CRATE_MAP: CrateMap;
|
||||
static CRATE_MAP: CrateMap<'static>;
|
||||
}
|
||||
|
||||
pub struct ModEntry {
|
||||
/// structs for old crate map versions
|
||||
pub struct ModEntryV0 {
|
||||
name: *c_char,
|
||||
log_level: *mut u32
|
||||
}
|
||||
struct CrateMapV0 {
|
||||
entries: *ModEntry,
|
||||
children: [*CrateMap, ..1]
|
||||
pub struct CrateMapV0 {
|
||||
entries: *ModEntryV0,
|
||||
children: [*CrateMapV0, ..1]
|
||||
}
|
||||
|
||||
struct CrateMap {
|
||||
pub struct CrateMapV1 {
|
||||
version: i32,
|
||||
entries: *ModEntry,
|
||||
entries: *ModEntryV0,
|
||||
/// a dynamically sized struct, where all pointers to children are listed adjacent
|
||||
/// to the struct, terminated with NULL
|
||||
children: [*CrateMap, ..1]
|
||||
children: [*CrateMapV1, ..1]
|
||||
}
|
||||
|
||||
pub struct ModEntry<'self> {
|
||||
name: &'self str,
|
||||
log_level: *mut u32
|
||||
}
|
||||
|
||||
pub struct CrateMap<'self> {
|
||||
version: i32,
|
||||
entries: &'self [ModEntry<'self>],
|
||||
children: &'self [&'self CrateMap<'self>]
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn get_crate_map() -> *CrateMap {
|
||||
&'static CRATE_MAP as *CrateMap
|
||||
pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
|
||||
let ptr: (*CrateMap) = &'static CRATE_MAP;
|
||||
if ptr.is_null() {
|
||||
return None;
|
||||
} else {
|
||||
return Some(&'static CRATE_MAP);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[fixed_stack_segment]
|
||||
#[inline(never)]
|
||||
pub fn get_crate_map() -> *CrateMap {
|
||||
pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
|
||||
use c_str::ToCStr;
|
||||
use unstable::dynamic_lib::dl;
|
||||
|
||||
|
@ -67,87 +88,178 @@ pub fn get_crate_map() -> *CrateMap {
|
|||
dl::close(module);
|
||||
sym
|
||||
};
|
||||
|
||||
sym as *CrateMap
|
||||
let ptr: (*CrateMap) = sym as *CrateMap;
|
||||
if ptr.is_null() {
|
||||
return None;
|
||||
} else {
|
||||
unsafe {
|
||||
return Some(transmute(sym));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn version(crate_map: *CrateMap) -> i32 {
|
||||
match (*crate_map).version {
|
||||
fn version(crate_map: &CrateMap) -> i32 {
|
||||
match crate_map.version {
|
||||
2 => return 2,
|
||||
1 => return 1,
|
||||
_ => return 0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn entries(crate_map: *CrateMap) -> *ModEntry {
|
||||
match version(crate_map) {
|
||||
0 => {
|
||||
let v0 = crate_map as (*CrateMapV0);
|
||||
return (*v0).entries;
|
||||
}
|
||||
1 => return (*crate_map).entries,
|
||||
_ => fail2!("Unknown crate map version!")
|
||||
fn iter_module_map(mod_entries: &[ModEntry], f: &fn(&ModEntry)) {
|
||||
for entry in mod_entries.iter() {
|
||||
f(entry);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn iterator(crate_map: *CrateMap) -> **CrateMap {
|
||||
match version(crate_map) {
|
||||
0 => {
|
||||
let v0 = crate_map as (*CrateMapV0);
|
||||
return vec::raw::to_ptr((*v0).children);
|
||||
}
|
||||
1 => return vec::raw::to_ptr((*crate_map).children),
|
||||
_ => fail2!("Unknown crate map version!")
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn iter_module_map(mod_entries: *ModEntry, f: &fn(*mut ModEntry)) {
|
||||
let mut curr = mod_entries;
|
||||
|
||||
unsafe fn iter_module_map_v0(entries: *ModEntryV0, f: &fn(&ModEntry)) {
|
||||
let mut curr = entries;
|
||||
while !(*curr).name.is_null() {
|
||||
f(curr as *mut ModEntry);
|
||||
let mod_entry = ModEntry { name: from_c_str((*curr).name), log_level: (*curr).log_level };
|
||||
f(&mod_entry);
|
||||
curr = curr.offset(1);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn do_iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry),
|
||||
visited: &mut HashSet<*CrateMap>) {
|
||||
if visited.insert(crate_map) {
|
||||
iter_module_map(entries(crate_map), |x| f(x));
|
||||
let child_crates = iterator(crate_map);
|
||||
do ptr::array_each(child_crates) |child| {
|
||||
do_iter_crate_map(child, |x| f(x), visited);
|
||||
fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry),
|
||||
visited: &mut HashSet<*CrateMap<'a>>) {
|
||||
if visited.insert(crate_map as *CrateMap) {
|
||||
match version(crate_map) {
|
||||
2 => {
|
||||
let (entries, children) = (crate_map.entries, crate_map.children);
|
||||
iter_module_map(entries, |x| f(x));
|
||||
for child in children.iter() {
|
||||
do_iter_crate_map(*child, |x| f(x), visited);
|
||||
}
|
||||
},
|
||||
// code for old crate map versions
|
||||
1 => unsafe {
|
||||
let v1: *CrateMapV1 = transmute(crate_map);
|
||||
iter_module_map_v0((*v1).entries, |x| f(x));
|
||||
let children = vec::raw::to_ptr((*v1).children);
|
||||
do ptr::array_each(children) |child| {
|
||||
do_iter_crate_map(transmute(child), |x| f(x), visited);
|
||||
}
|
||||
},
|
||||
0 => unsafe {
|
||||
let v0: *CrateMapV0 = transmute(crate_map);
|
||||
iter_module_map_v0((*v0).entries, |x| f(x));
|
||||
let children = vec::raw::to_ptr((*v0).children);
|
||||
do ptr::array_each(children) |child| {
|
||||
do_iter_crate_map(transmute(child), |x| f(x), visited);
|
||||
}
|
||||
},
|
||||
_ => fail2!("invalid crate map version")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterates recursively over `crate_map` and all child crate maps
|
||||
pub unsafe fn iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry)) {
|
||||
pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) {
|
||||
// XXX: use random numbers as keys from the OS-level RNG when there is a nice
|
||||
// way to do this
|
||||
let mut v: HashSet<*CrateMap> = HashSet::with_capacity_and_keys(0, 0, 32);
|
||||
let mut v: HashSet<*CrateMap<'a>> = HashSet::with_capacity_and_keys(0, 0, 32);
|
||||
do_iter_crate_map(crate_map, f, &mut v);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rt::crate_map::{CrateMap, ModEntry, iter_crate_map};
|
||||
|
||||
#[test]
|
||||
fn iter_crate_map_duplicates() {
|
||||
let mut level3: u32 = 3;
|
||||
|
||||
let entries = [
|
||||
ModEntry { name: "c::m1", log_level: &mut level3},
|
||||
];
|
||||
|
||||
let child_crate = CrateMap {
|
||||
version: 2,
|
||||
entries: entries,
|
||||
children: []
|
||||
};
|
||||
|
||||
let root_crate = CrateMap {
|
||||
version: 2,
|
||||
entries: [],
|
||||
children: [&child_crate, &child_crate]
|
||||
};
|
||||
|
||||
let mut cnt = 0;
|
||||
unsafe {
|
||||
do iter_crate_map(&root_crate) |entry| {
|
||||
assert!(*entry.log_level == 3);
|
||||
cnt += 1;
|
||||
}
|
||||
assert!(cnt == 1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter_crate_map_follow_children() {
|
||||
let mut level2: u32 = 2;
|
||||
let mut level3: u32 = 3;
|
||||
let child_crate2 = CrateMap {
|
||||
version: 2,
|
||||
entries: [
|
||||
ModEntry { name: "c::m1", log_level: &mut level2},
|
||||
ModEntry { name: "c::m2", log_level: &mut level3},
|
||||
],
|
||||
children: []
|
||||
};
|
||||
|
||||
let child_crate1 = CrateMap {
|
||||
version: 2,
|
||||
entries: [
|
||||
ModEntry { name: "t::f1", log_level: &mut 1},
|
||||
],
|
||||
children: [&child_crate2]
|
||||
};
|
||||
|
||||
let root_crate = CrateMap {
|
||||
version: 2,
|
||||
entries: [
|
||||
ModEntry { name: "t::f2", log_level: &mut 0},
|
||||
],
|
||||
children: [&child_crate1]
|
||||
};
|
||||
|
||||
let mut cnt = 0;
|
||||
unsafe {
|
||||
do iter_crate_map(&root_crate) |entry| {
|
||||
assert!(*entry.log_level == cnt);
|
||||
cnt += 1;
|
||||
}
|
||||
assert!(cnt == 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Tests for old crate map versions
|
||||
#[test]
|
||||
fn iter_crate_map_duplicates_v1() {
|
||||
use c_str::ToCStr;
|
||||
use cast::transmute;
|
||||
use ptr;
|
||||
use rt::crate_map::{CrateMapV1, ModEntryV0, iter_crate_map};
|
||||
use vec;
|
||||
|
||||
struct CrateMapT3 {
|
||||
version: i32,
|
||||
entries: *ModEntry,
|
||||
children: [*CrateMap, ..3]
|
||||
entries: *ModEntryV0,
|
||||
children: [*CrateMapV1, ..3]
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mod_name1 = "c::m1".to_c_str();
|
||||
let mut level3: u32 = 3;
|
||||
|
||||
let entries: ~[ModEntry] = ~[
|
||||
ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3},
|
||||
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
||||
let entries: ~[ModEntryV0] = ~[
|
||||
ModEntryV0 { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3},
|
||||
ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
|
||||
];
|
||||
let child_crate = CrateMap {
|
||||
let child_crate = CrateMapV1 {
|
||||
version: 1,
|
||||
entries: vec::raw::to_ptr(entries),
|
||||
children: [ptr::null()]
|
||||
|
@ -155,8 +267,10 @@ fn iter_crate_map_duplicates() {
|
|||
|
||||
let root_crate = CrateMapT3 {
|
||||
version: 1,
|
||||
entries: vec::raw::to_ptr([ModEntry { name: ptr::null(), log_level: ptr::mut_null()}]),
|
||||
children: [&child_crate as *CrateMap, &child_crate as *CrateMap, ptr::null()]
|
||||
entries: vec::raw::to_ptr([
|
||||
ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
|
||||
]),
|
||||
children: [&child_crate as *CrateMapV1, &child_crate as *CrateMapV1, ptr::null()]
|
||||
};
|
||||
|
||||
let mut cnt = 0;
|
||||
|
@ -169,14 +283,17 @@ fn iter_crate_map_duplicates() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn iter_crate_map_follow_children() {
|
||||
fn iter_crate_map_follow_children_v1() {
|
||||
use c_str::ToCStr;
|
||||
use cast::transmute;
|
||||
use ptr;
|
||||
use rt::crate_map::{CrateMapV1, ModEntryV0, iter_crate_map};
|
||||
use vec;
|
||||
|
||||
struct CrateMapT2 {
|
||||
version: i32,
|
||||
entries: *ModEntry,
|
||||
children: [*CrateMap, ..2]
|
||||
entries: *ModEntryV0,
|
||||
children: [*CrateMapV1, ..2]
|
||||
}
|
||||
|
||||
unsafe {
|
||||
|
@ -184,12 +301,12 @@ fn iter_crate_map_follow_children() {
|
|||
let mod_name2 = "c::m2".to_c_str();
|
||||
let mut level2: u32 = 2;
|
||||
let mut level3: u32 = 3;
|
||||
let child_crate2 = CrateMap {
|
||||
let child_crate2 = CrateMapV1 {
|
||||
version: 1,
|
||||
entries: vec::raw::to_ptr([
|
||||
ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2},
|
||||
ModEntry { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3},
|
||||
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
||||
ModEntryV0 { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2},
|
||||
ModEntryV0 { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3},
|
||||
ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
|
||||
]),
|
||||
children: [ptr::null()]
|
||||
};
|
||||
|
@ -197,18 +314,18 @@ fn iter_crate_map_follow_children() {
|
|||
let child_crate1 = CrateMapT2 {
|
||||
version: 1,
|
||||
entries: vec::raw::to_ptr([
|
||||
ModEntry { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 1},
|
||||
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
||||
ModEntryV0 { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 1},
|
||||
ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
|
||||
]),
|
||||
children: [&child_crate2 as *CrateMap, ptr::null()]
|
||||
children: [&child_crate2 as *CrateMapV1, ptr::null()]
|
||||
};
|
||||
|
||||
let child_crate1_ptr: *CrateMap = transmute(&child_crate1);
|
||||
let child_crate1_ptr: *CrateMapV1 = transmute(&child_crate1);
|
||||
let root_crate = CrateMapT2 {
|
||||
version: 1,
|
||||
entries: vec::raw::to_ptr([
|
||||
ModEntry { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 0},
|
||||
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
||||
ModEntryV0 { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 0},
|
||||
ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
|
||||
]),
|
||||
children: [child_crate1_ptr, ptr::null()]
|
||||
};
|
||||
|
@ -221,3 +338,4 @@ fn iter_crate_map_follow_children() {
|
|||
assert!(cnt == 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,11 @@ use libc::{uintptr_t, exit};
|
|||
use option::{Some, None, Option};
|
||||
use rt;
|
||||
use rt::util::dumb_println;
|
||||
use rt::crate_map::{ModEntry, iter_crate_map};
|
||||
use rt::crate_map::get_crate_map;
|
||||
use rt::crate_map::{ModEntry, CrateMap, iter_crate_map, get_crate_map};
|
||||
use str::StrSlice;
|
||||
use str::raw::from_c_str;
|
||||
use u32;
|
||||
use vec::ImmutableVector;
|
||||
use cast::transmute;
|
||||
#[cfg(test)] use cast::transmute;
|
||||
|
||||
struct LogDirective {
|
||||
name: Option<~str>,
|
||||
|
@ -110,10 +108,9 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
|
|||
|
||||
/// Set the log level of an entry in the crate map depending on the vector
|
||||
/// of log directives
|
||||
fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 {
|
||||
fn update_entry(dirs: &[LogDirective], entry: &ModEntry) -> u32 {
|
||||
let mut new_lvl: u32 = DEFAULT_LOG_LEVEL;
|
||||
let mut longest_match = -1i;
|
||||
unsafe {
|
||||
for dir in dirs.iter() {
|
||||
match dir.name {
|
||||
None => {
|
||||
|
@ -123,7 +120,7 @@ fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 {
|
|||
}
|
||||
}
|
||||
Some(ref dir_name) => {
|
||||
let name = from_c_str((*entry).name);
|
||||
let name = entry.name;
|
||||
let len = dir_name.len() as int;
|
||||
if name.starts_with(*dir_name) &&
|
||||
len >= longest_match {
|
||||
|
@ -133,36 +130,31 @@ fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 {
|
|||
}
|
||||
};
|
||||
}
|
||||
*(*entry).log_level = new_lvl;
|
||||
}
|
||||
unsafe { *entry.log_level = new_lvl; }
|
||||
if longest_match >= 0 { return 1; } else { return 0; }
|
||||
}
|
||||
|
||||
#[fixed_stack_segment] #[inline(never)]
|
||||
/// Set log level for every entry in crate_map according to the sepecification
|
||||
/// in settings
|
||||
fn update_log_settings(crate_map: *u8, settings: ~str) {
|
||||
fn update_log_settings(crate_map: &CrateMap, settings: ~str) {
|
||||
let mut dirs = ~[];
|
||||
if settings.len() > 0 {
|
||||
if settings == ~"::help" || settings == ~"?" {
|
||||
dumb_println("\nCrate log map:\n");
|
||||
unsafe {
|
||||
do iter_crate_map(transmute(crate_map)) |entry: *mut ModEntry| {
|
||||
dumb_println(" "+from_c_str((*entry).name));
|
||||
}
|
||||
exit(1);
|
||||
do iter_crate_map(crate_map) |entry| {
|
||||
dumb_println(" "+entry.name);
|
||||
}
|
||||
unsafe { exit(1); }
|
||||
}
|
||||
dirs = parse_logging_spec(settings);
|
||||
}
|
||||
|
||||
let mut n_matches: u32 = 0;
|
||||
unsafe {
|
||||
do iter_crate_map(transmute(crate_map)) |entry: *mut ModEntry| {
|
||||
do iter_crate_map(crate_map) |entry| {
|
||||
let m = update_entry(dirs, entry);
|
||||
n_matches += m;
|
||||
}
|
||||
}
|
||||
|
||||
if n_matches < (dirs.len() as u32) {
|
||||
dumb_println(format!("warning: got {} RUST_LOG specs but only matched\n\
|
||||
|
@ -207,9 +199,9 @@ impl rt::io::Writer for StdErrLogger {
|
|||
pub fn init() {
|
||||
use os;
|
||||
|
||||
let crate_map = get_crate_map() as *u8;
|
||||
|
||||
let log_spec = os::getenv("RUST_LOG");
|
||||
match get_crate_map() {
|
||||
Some(crate_map) => {
|
||||
match log_spec {
|
||||
Some(spec) => {
|
||||
update_log_settings(crate_map, spec);
|
||||
|
@ -218,6 +210,16 @@ pub fn init() {
|
|||
update_log_settings(crate_map, ~"");
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
match log_spec {
|
||||
Some(_) => {
|
||||
dumb_println("warning: RUST_LOG set, but no crate map found.");
|
||||
},
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[fixed_stack_segment] #[inline(never)]
|
||||
|
@ -291,88 +293,71 @@ fn parse_logging_spec_global() {
|
|||
// Tests for update_entry
|
||||
#[test]
|
||||
fn update_entry_match_full_path() {
|
||||
use c_str::ToCStr;
|
||||
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
|
||||
LogDirective {name: Some(~"crate2"), level: 3}];
|
||||
let level = &mut 0;
|
||||
unsafe {
|
||||
do "crate1::mod1".with_c_str |ptr| {
|
||||
let entry= &ModEntry {name: ptr, log_level: level};
|
||||
let entry= &ModEntry {name:"crate1::mod1", log_level: level};
|
||||
let m = update_entry(dirs, transmute(entry));
|
||||
assert!(*entry.log_level == 2);
|
||||
assert!(m == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_entry_no_match() {
|
||||
use c_str::ToCStr;
|
||||
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
|
||||
LogDirective {name: Some(~"crate2"), level: 3}];
|
||||
let level = &mut 0;
|
||||
unsafe {
|
||||
do "crate3::mod1".with_c_str |ptr| {
|
||||
let entry= &ModEntry {name: ptr, log_level: level};
|
||||
let entry= &ModEntry {name: "crate3::mod1", log_level: level};
|
||||
let m = update_entry(dirs, transmute(entry));
|
||||
assert!(*entry.log_level == DEFAULT_LOG_LEVEL);
|
||||
assert!(m == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_entry_match_beginning() {
|
||||
use c_str::ToCStr;
|
||||
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
|
||||
LogDirective {name: Some(~"crate2"), level: 3}];
|
||||
let level = &mut 0;
|
||||
unsafe {
|
||||
do "crate2::mod1".with_c_str |ptr| {
|
||||
let entry= &ModEntry {name: ptr, log_level: level};
|
||||
let entry= &ModEntry {name: "crate2::mod1", log_level: level};
|
||||
let m = update_entry(dirs, transmute(entry));
|
||||
assert!(*entry.log_level == 3);
|
||||
assert!(m == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_entry_match_beginning_longest_match() {
|
||||
use c_str::ToCStr;
|
||||
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
|
||||
LogDirective {name: Some(~"crate2"), level: 3},
|
||||
LogDirective {name: Some(~"crate2::mod"), level: 4}];
|
||||
let level = &mut 0;
|
||||
unsafe {
|
||||
do "crate2::mod1".with_c_str |ptr| {
|
||||
let entry = &ModEntry {name: ptr, log_level: level};
|
||||
let entry = &ModEntry {name: "crate2::mod1", log_level: level};
|
||||
let m = update_entry(dirs, transmute(entry));
|
||||
assert!(*entry.log_level == 4);
|
||||
assert!(m == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_entry_match_default() {
|
||||
use c_str::ToCStr;
|
||||
let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
|
||||
LogDirective {name: None, level: 3}
|
||||
];
|
||||
let level = &mut 0;
|
||||
unsafe {
|
||||
do "crate1::mod1".with_c_str |ptr| {
|
||||
let entry= &ModEntry {name: ptr, log_level: level};
|
||||
let entry= &ModEntry {name: "crate1::mod1", log_level: level};
|
||||
let m = update_entry(dirs, transmute(entry));
|
||||
assert!(*entry.log_level == 2);
|
||||
assert!(m == 1);
|
||||
}
|
||||
do "crate2::mod2".with_c_str |ptr| {
|
||||
let entry= &ModEntry {name: ptr, log_level: level};
|
||||
let entry= &ModEntry {name: "crate2::mod2", log_level: level};
|
||||
let m = update_entry(dirs, transmute(entry));
|
||||
assert!(*entry.log_level == 3);
|
||||
assert!(m == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue