diff options
| author | Florian Hahn <flo@fhahn.com> | 2013-10-01 23:53:56 +0200 |
|---|---|---|
| committer | Florian Hahn <flo@fhahn.com> | 2013-10-05 12:09:30 +0200 |
| commit | b7b4f7a5e2982c8412fe71a9534f6f62435f9bc3 (patch) | |
| tree | c02274d0eda2a0010a816762da896fba51d33fc8 /src/libstd | |
| parent | 5dd1145c9b5e4ee12d6ef6d5d87bcbe0941b174b (diff) | |
| download | rust-b7b4f7a5e2982c8412fe71a9534f6f62435f9bc3.tar.gz rust-b7b4f7a5e2982c8412fe71a9534f6f62435f9bc3.zip | |
Add code for older crate map versions, bumped crate map version number
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/rt/crate_map.rs | 209 |
1 files changed, 171 insertions, 38 deletions
diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index 3120d69d5df..ef1bfb1e5e9 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -8,12 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[cfg(not(stage0))] use cast::transmute; +//#[cfg(not(stage0))] use cast::transmute; use container::MutableSet; use hashmap::HashSet; use option::{Some, None}; use vec::ImmutableVector; +/// Imports for old crate map versions +use cast::transmute; +use libc::c_char; +use ptr; +use str::raw::from_c_str; +use vec; + // 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 // the crate_map properly. @@ -28,14 +35,27 @@ extern { static CRATE_MAP: CrateMap<'static>; } -pub struct ModEntry<'self> { - name: &'self str, +/// structs for old crate map versions +pub struct ModEntryV0 { + name: *c_char, log_level: *mut u32 } +pub struct CrateMapV0 { + entries: *ModEntryV0, + children: [*CrateMapV0, ..1] +} -pub struct CrateMapV0<'self> { - entries: &'self [ModEntry<'self>], - children: &'self [&'self CrateMap<'self>] +pub struct CrateMapV1 { + version: i32, + entries: *ModEntryV0, + /// a dynamically sized struct, where all pointers to children are listed adjacent + /// to the struct, terminated with NULL + children: [*CrateMapV1, ..1] +} + +pub struct ModEntry<'self> { + name: &'self str, + log_level: *mut u32 } pub struct CrateMap<'self> { @@ -46,6 +66,8 @@ pub struct CrateMap<'self> { children: &'self [&'self CrateMap<'self>] } + + #[cfg(not(windows))] pub fn get_crate_map() -> &'static CrateMap<'static> { &'static CRATE_MAP @@ -71,51 +93,60 @@ pub fn get_crate_map() -> &'static CrateMap<'static> { fn version(crate_map: &CrateMap) -> i32 { match crate_map.version { + 2 => return 2, 1 => return 1, _ => return 0 } } -#[cfg(not(stage0))] -fn get_entries_and_children<'a>(crate_map: &'a CrateMap<'a>) -> - (&'a [ModEntry<'a>], &'a [&'a CrateMap<'a>]) { - match version(crate_map) { - 0 => { - unsafe { - let v0: &'a CrateMapV0<'a> = transmute(crate_map); - return (v0.entries, v0.children); - } - } - 1 => return (*crate_map).entries, - _ => fail2!("Unknown crate map version!") - } -} - -#[cfg(not(stage0))] fn iter_module_map(mod_entries: &[ModEntry], f: &fn(&ModEntry)) { for entry in mod_entries.iter() { f(entry); } } -#[cfg(not(stage0))] +unsafe fn iter_module_map_v0(entries: *ModEntryV0, f: &fn(&ModEntry)) { + let mut curr = entries; + while !(*curr).name.is_null() { + let mod_entry = ModEntry { name: from_c_str((*curr).name), log_level: (*curr).log_level }; + f(&mod_entry); + curr = curr.offset(1); + } +} + 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) { - let (entries, children) = get_entries_and_children(crate_map); - iter_module_map(entries, |x| f(x)); - for child in children.iter() { - do_iter_crate_map(*child, |x| f(x), visited); + 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") } } } -#[cfg(stage0)] -/// Iterates recursively over `crate_map` and all child crate maps -pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) { -} - -#[cfg(not(stage0))] /// Iterates recursively over `crate_map` and all child crate maps 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 @@ -137,13 +168,13 @@ mod tests { ]; let child_crate = CrateMap { - version: 1, + version: 2, entries: entries, children: [] }; let root_crate = CrateMap { - version: 1, + version: 2, entries: [], children: [&child_crate, &child_crate] }; @@ -163,7 +194,7 @@ mod tests { let mut level2: u32 = 2; let mut level3: u32 = 3; let child_crate2 = CrateMap { - version: 1, + version: 2, entries: [ ModEntry { name: "c::m1", log_level: &mut level2}, ModEntry { name: "c::m2", log_level: &mut level3}, @@ -172,7 +203,7 @@ mod tests { }; let child_crate1 = CrateMap { - version: 1, + version: 2, entries: [ ModEntry { name: "t::f1", log_level: &mut 1}, ], @@ -180,7 +211,7 @@ mod tests { }; let root_crate = CrateMap { - version: 1, + version: 2, entries: [ ModEntry { name: "t::f2", log_level: &mut 0}, ], @@ -196,4 +227,106 @@ mod tests { 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: *ModEntryV0, + children: [*CrateMapV1, ..3] + } + + unsafe { + let mod_name1 = "c::m1".to_c_str(); + let mut level3: u32 = 3; + + 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 = CrateMapV1 { + version: 1, + entries: vec::raw::to_ptr(entries), + children: [ptr::null()] + }; + + let root_crate = CrateMapT3 { + version: 1, + 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; + do iter_crate_map(transmute(&root_crate)) |entry| { + assert!(*(*entry).log_level == 3); + cnt += 1; + } + assert!(cnt == 1); + } + } + + #[test] + 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: *ModEntryV0, + children: [*CrateMapV1, ..2] + } + + unsafe { + let mod_name1 = "c::m1".to_c_str(); + let mod_name2 = "c::m2".to_c_str(); + let mut level2: u32 = 2; + let mut level3: u32 = 3; + let child_crate2 = CrateMapV1 { + version: 1, + entries: vec::raw::to_ptr([ + 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()] + }; + + let child_crate1 = CrateMapT2 { + version: 1, + entries: vec::raw::to_ptr([ + 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 *CrateMapV1, ptr::null()] + }; + + let child_crate1_ptr: *CrateMapV1 = transmute(&child_crate1); + let root_crate = CrateMapT2 { + version: 1, + entries: vec::raw::to_ptr([ + 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()] + }; + + let mut cnt = 0; + do iter_crate_map(transmute(&root_crate)) |entry| { + assert!(*(*entry).log_level == cnt); + cnt += 1; + } + assert!(cnt == 4); + } + } } |
