about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2013-10-01 23:53:56 +0200
committerFlorian Hahn <flo@fhahn.com>2013-10-05 12:09:30 +0200
commitb7b4f7a5e2982c8412fe71a9534f6f62435f9bc3 (patch)
treec02274d0eda2a0010a816762da896fba51d33fc8 /src/libstd
parent5dd1145c9b5e4ee12d6ef6d5d87bcbe0941b174b (diff)
downloadrust-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.rs209
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);
+        }
+    }
 }