]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/crate_map.rs
Remove the annihilate function from the crate map. Fixes #8431
[rust.git] / src / libstd / rt / crate_map.rs
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.
4 //
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.
10
11
12 use libc::c_char;
13 #[cfg(stage0)] use libc::c_void;
14 use ptr;
15 use ptr::RawPtr;
16 use vec;
17 use hashmap::HashSet;
18 use container::MutableSet;
19
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"]
25 extern {}
26
27 #[cfg(not(windows))]
28 extern {
29     #[weak_linkage]
30     #[link_name = "_rust_crate_map_toplevel"]
31     static CRATE_MAP: CrateMap;
32 }
33
34 pub struct ModEntry {
35     name: *c_char,
36     log_level: *mut u32
37 }
38 struct CrateMapV0 {
39     entries: *ModEntry,
40     children: [*CrateMap, ..1]
41 }
42
43 #[cfg(stage0)]
44 struct CrateMap {
45     version: i32,
46     annihilate_fn: *c_void,
47     entries: *ModEntry,
48     /// a dynamically sized struct, where all pointers to children are listed adjacent
49     /// to the struct, terminated with NULL
50     children: [*CrateMap, ..1]
51 }
52
53 #[cfg(not(stage0))]
54 struct CrateMap {
55     version: i32,
56     entries: *ModEntry,
57     /// a dynamically sized struct, where all pointers to children are listed adjacent
58     /// to the struct, terminated with NULL
59     children: [*CrateMap, ..1]
60 }
61
62 #[cfg(not(windows))]
63 pub fn get_crate_map() -> *CrateMap {
64     &'static CRATE_MAP as *CrateMap
65 }
66
67 #[cfg(windows)]
68 #[fixed_stack_segment]
69 #[inline(never)]
70 pub fn get_crate_map() -> *CrateMap {
71     use c_str::ToCStr;
72     use unstable::dynamic_lib::dl;
73
74     let sym = unsafe {
75         let module = dl::open_internal();
76         let sym = do "__rust_crate_map_toplevel".with_c_str |buf| {
77             dl::symbol(module, buf)
78         };
79         dl::close(module);
80         sym
81     };
82
83     sym as *CrateMap
84 }
85
86 unsafe fn version(crate_map: *CrateMap) -> i32 {
87     match (*crate_map).version {
88         1 => return 1,
89         _ => return 0
90     }
91 }
92
93 unsafe fn entries(crate_map: *CrateMap) -> *ModEntry {
94     match version(crate_map) {
95         0 => {
96             let v0 = crate_map as (*CrateMapV0);
97             return (*v0).entries;
98         }
99         1 => return (*crate_map).entries,
100         _ => fail!("Unknown crate map version!")
101     }
102 }
103
104 unsafe fn iterator(crate_map: *CrateMap) -> **CrateMap {
105     match version(crate_map) {
106         0 => {
107             let v0 = crate_map as (*CrateMapV0);
108             return vec::raw::to_ptr((*v0).children);
109         }
110         1 => return vec::raw::to_ptr((*crate_map).children),
111         _ => fail!("Unknown crate map version!")
112     }
113 }
114
115 unsafe fn iter_module_map(mod_entries: *ModEntry, f: &fn(*mut ModEntry)) {
116     let mut curr = mod_entries;
117
118     while !(*curr).name.is_null() {
119         f(curr as *mut ModEntry);
120         curr = curr.offset(1);
121     }
122 }
123
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);
131         }
132     }
133 }
134
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
138     //        way to do this
139     let mut v: HashSet<*CrateMap> = HashSet::with_capacity_and_keys(0, 0, 32);
140     do_iter_crate_map(crate_map, f, &mut v);
141 }
142
143 #[test]
144 fn iter_crate_map_duplicates() {
145     use c_str::ToCStr;
146     use cast::transmute;
147
148     struct CrateMapT3 {
149         version: i32,
150         entries: *ModEntry,
151         children: [*CrateMap, ..3]
152     }
153
154     unsafe {
155         let mod_name1 = "c::m1".to_c_str();
156         let mut level3: u32 = 3;
157
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()}
161         ];
162         let child_crate = CrateMap {
163             version: 1,
164             entries: vec::raw::to_ptr(entries),
165             children: [ptr::null()]
166         };
167
168         let root_crate = CrateMapT3 {
169             version: 1,
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()]
172         };
173
174         let mut cnt = 0;
175         do iter_crate_map(transmute(&root_crate)) |entry| {
176             assert!(*(*entry).log_level == 3);
177             cnt += 1;
178         }
179         assert!(cnt == 1);
180     }
181 }
182
183 #[test]
184 fn iter_crate_map_follow_children() {
185     use c_str::ToCStr;
186     use cast::transmute;
187
188     struct CrateMapT2 {
189         version: i32,
190         entries: *ModEntry,
191         children: [*CrateMap, ..2]
192     }
193
194     unsafe {
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 {
200             version: 1,
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()}
205             ]),
206             children: [ptr::null()]
207         };
208
209         let child_crate1 = CrateMapT2 {
210             version: 1,
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()}
214             ]),
215             children: [&child_crate2 as *CrateMap, ptr::null()]
216         };
217
218         let child_crate1_ptr: *CrateMap = transmute(&child_crate1);
219         let root_crate = CrateMapT2 {
220             version: 1,
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()}
224             ]),
225             children: [child_crate1_ptr, ptr::null()]
226         };
227
228         let mut cnt = 0;
229         do iter_crate_map(transmute(&root_crate)) |entry| {
230             assert!(*(*entry).log_level == cnt);
231             cnt += 1;
232         }
233         assert!(cnt == 4);
234     }
235 }