1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 #[cfg(stage0)] use libc::c_void;
18 use container::MutableSet;
20 // Need to tell the linker on OS X to not barf on undefined symbols
21 // and instead look them up at runtime, which we need to resolve
22 // the crate_map properly.
23 #[cfg(target_os = "macos")]
24 #[link_args = "-undefined dynamic_lookup"]
30 #[link_name = "_rust_crate_map_toplevel"]
31 static CRATE_MAP: CrateMap;
40 children: [*CrateMap, ..1]
46 annihilate_fn: *c_void,
48 /// a dynamically sized struct, where all pointers to children are listed adjacent
49 /// to the struct, terminated with NULL
50 children: [*CrateMap, ..1]
57 /// a dynamically sized struct, where all pointers to children are listed adjacent
58 /// to the struct, terminated with NULL
59 children: [*CrateMap, ..1]
63 pub fn get_crate_map() -> *CrateMap {
64 &'static CRATE_MAP as *CrateMap
68 #[fixed_stack_segment]
70 pub fn get_crate_map() -> *CrateMap {
72 use unstable::dynamic_lib::dl;
75 let module = dl::open_internal();
76 let sym = do "__rust_crate_map_toplevel".with_c_str |buf| {
77 dl::symbol(module, buf)
86 unsafe fn version(crate_map: *CrateMap) -> i32 {
87 match (*crate_map).version {
93 unsafe fn entries(crate_map: *CrateMap) -> *ModEntry {
94 match version(crate_map) {
96 let v0 = crate_map as (*CrateMapV0);
99 1 => return (*crate_map).entries,
100 _ => fail!("Unknown crate map version!")
104 unsafe fn iterator(crate_map: *CrateMap) -> **CrateMap {
105 match version(crate_map) {
107 let v0 = crate_map as (*CrateMapV0);
108 return vec::raw::to_ptr((*v0).children);
110 1 => return vec::raw::to_ptr((*crate_map).children),
111 _ => fail!("Unknown crate map version!")
115 unsafe fn iter_module_map(mod_entries: *ModEntry, f: &fn(*mut ModEntry)) {
116 let mut curr = mod_entries;
118 while !(*curr).name.is_null() {
119 f(curr as *mut ModEntry);
120 curr = curr.offset(1);
124 unsafe fn do_iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry),
125 visited: &mut HashSet<*CrateMap>) {
126 if visited.insert(crate_map) {
127 iter_module_map(entries(crate_map), |x| f(x));
128 let child_crates = iterator(crate_map);
129 do ptr::array_each(child_crates) |child| {
130 do_iter_crate_map(child, |x| f(x), visited);
135 /// Iterates recursively over `crate_map` and all child crate maps
136 pub unsafe fn iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry)) {
137 // XXX: use random numbers as keys from the OS-level RNG when there is a nice
139 let mut v: HashSet<*CrateMap> = HashSet::with_capacity_and_keys(0, 0, 32);
140 do_iter_crate_map(crate_map, f, &mut v);
144 fn iter_crate_map_duplicates() {
151 children: [*CrateMap, ..3]
155 let mod_name1 = "c::m1".to_c_str();
156 let mut level3: u32 = 3;
158 let entries: ~[ModEntry] = ~[
159 ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3},
160 ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
162 let child_crate = CrateMap {
164 entries: vec::raw::to_ptr(entries),
165 children: [ptr::null()]
168 let root_crate = CrateMapT3 {
170 entries: vec::raw::to_ptr([ModEntry { name: ptr::null(), log_level: ptr::mut_null()}]),
171 children: [&child_crate as *CrateMap, &child_crate as *CrateMap, ptr::null()]
175 do iter_crate_map(transmute(&root_crate)) |entry| {
176 assert!(*(*entry).log_level == 3);
184 fn iter_crate_map_follow_children() {
191 children: [*CrateMap, ..2]
195 let mod_name1 = "c::m1".to_c_str();
196 let mod_name2 = "c::m2".to_c_str();
197 let mut level2: u32 = 2;
198 let mut level3: u32 = 3;
199 let child_crate2 = CrateMap {
201 entries: vec::raw::to_ptr([
202 ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2},
203 ModEntry { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3},
204 ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
206 children: [ptr::null()]
209 let child_crate1 = CrateMapT2 {
211 entries: vec::raw::to_ptr([
212 ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 1},
213 ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
215 children: [&child_crate2 as *CrateMap, ptr::null()]
218 let child_crate1_ptr: *CrateMap = transmute(&child_crate1);
219 let root_crate = CrateMapT2 {
221 entries: vec::raw::to_ptr([
222 ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 0},
223 ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
225 children: [child_crate1_ptr, ptr::null()]
229 do iter_crate_map(transmute(&root_crate)) |entry| {
230 assert!(*(*entry).log_level == cnt);