(index<- ) ./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 use container::MutableSet;
12 use hashmap::HashSet;
13 use option::{Some, None, Option};
14 use vec::ImmutableVector;
15
16 // Need to tell the linker on OS X to not barf on undefined symbols
17 // and instead look them up at runtime, which we need to resolve
18 // the crate_map properly.
19 #[cfg(target_os = "macos")]
20 #[link_args = "-undefined dynamic_lookup"]
21 extern {}
22
23 pub struct ModEntry<'self> {
24 name: &'self str,
25 log_level: *mut u32
26 }
27
28 pub struct CrateMap<'self> {
29 version: i32,
30 entries: &'self [ModEntry<'self>],
31 children: &'self [&'self CrateMap<'self>]
32 }
33
34 #[cfg(not(windows))]
35 pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
36 extern {
37 #[weak_linkage]
38 #[link_name = "_rust_crate_map_toplevel"]
39 static CRATE_MAP: CrateMap<'static>;
40 }
41
42 let ptr: (*CrateMap) = &'static CRATE_MAP;
43 if ptr.is_null() {
44 return None;
45 } else {
46 return Some(&'static CRATE_MAP);
47 }
48 }
49
50 #[cfg(windows)]
51 #[fixed_stack_segment]
52 #[inline(never)]
53 pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
54 use cast::transmute;
55 use c_str::ToCStr;
56 use unstable::dynamic_lib::dl;
57
58 let sym = unsafe {
59 let module = dl::open_internal();
60 let sym = do "__rust_crate_map_toplevel".with_c_str |buf| {
61 dl::symbol(module, buf)
62 };
63 dl::close(module);
64 sym
65 };
66 let ptr: (*CrateMap) = sym as *CrateMap;
67 if ptr.is_null() {
68 return None;
69 } else {
70 unsafe {
71 return Some(transmute(sym));
72 }
73 }
74 }
75
76 fn version(crate_map: &CrateMap) -> i32 {
77 match crate_map.version {
78 2 => return 2,
79 _ => return 0
80 }
81 }
82
83 fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry),
84 visited: &mut HashSet<*CrateMap<'a>>) {
85 if visited.insert(crate_map as *CrateMap) {
86 match version(crate_map) {
87 2 => {
88 let (entries, children) = (crate_map.entries, crate_map.children);
89 for entry in entries.iter() {
90 f(entry);
91 }
92 for child in children.iter() {
93 do_iter_crate_map(*child, |x| f(x), visited);
94 }
95 },
96 _ => fail2!("invalid crate map version")
97 }
98 }
99 }
100
101 /// Iterates recursively over `crate_map` and all child crate maps
102 pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) {
103 // XXX: use random numbers as keys from the OS-level RNG when there is a nice
104 // way to do this
105 let mut v: HashSet<*CrateMap<'a>> = HashSet::with_capacity_and_keys(0, 0, 32);
106 do_iter_crate_map(crate_map, f, &mut v);
107 }
108
109 #[cfg(test)]
110 mod tests {
111 use rt::crate_map::{CrateMap, ModEntry, iter_crate_map};
112
113 #[test]
114 fn iter_crate_map_duplicates() {
115 let mut level3: u32 = 3;
116
117 let entries = [
118 ModEntry { name: "c::m1", log_level: &mut level3},
119 ];
120
121 let child_crate = CrateMap {
122 version: 2,
123 entries: entries,
124 children: []
125 };
126
127 let root_crate = CrateMap {
128 version: 2,
129 entries: [],
130 children: [&child_crate, &child_crate]
131 };
132
133 let mut cnt = 0;
134 unsafe {
135 do iter_crate_map(&root_crate) |entry| {
136 assert!(*entry.log_level == 3);
137 cnt += 1;
138 }
139 assert!(cnt == 1);
140 }
141 }
142
143 #[test]
144 fn iter_crate_map_follow_children() {
145 let mut level2: u32 = 2;
146 let mut level3: u32 = 3;
147 let child_crate2 = CrateMap {
148 version: 2,
149 entries: [
150 ModEntry { name: "c::m1", log_level: &mut level2},
151 ModEntry { name: "c::m2", log_level: &mut level3},
152 ],
153 children: []
154 };
155
156 let child_crate1 = CrateMap {
157 version: 2,
158 entries: [
159 ModEntry { name: "t::f1", log_level: &mut 1},
160 ],
161 children: [&child_crate2]
162 };
163
164 let root_crate = CrateMap {
165 version: 2,
166 entries: [
167 ModEntry { name: "t::f2", log_level: &mut 0},
168 ],
169 children: [&child_crate1]
170 };
171
172 let mut cnt = 0;
173 unsafe {
174 do iter_crate_map(&root_crate) |entry| {
175 assert!(*entry.log_level == cnt);
176 cnt += 1;
177 }
178 assert!(cnt == 4);
179 }
180 }
181 }
libstd/rt/crate_map.rs:82:1-82:1 -fn- definition:
fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry),
references:-106: do_iter_crate_map(crate_map, f, &mut v);
93: do_iter_crate_map(*child, |x| f(x), visited);
libstd/rt/crate_map.rs:27:1-27:1 -struct- definition:
pub struct CrateMap<'self> {
references:-76: fn version(crate_map: &CrateMap) -> i32 {
84: visited: &mut HashSet<*CrateMap<'a>>) {
85: if visited.insert(crate_map as *CrateMap) {
35: pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
102: pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) {
31: children: &'self [&'self CrateMap<'self>]
105: let mut v: HashSet<*CrateMap<'a>> = HashSet::with_capacity_and_keys(0, 0, 32);
42: let ptr: (*CrateMap) = &'static CRATE_MAP;
39: static CRATE_MAP: CrateMap<'static>;
83: fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry),
libstd/rt/logging.rs:
138: fn update_log_settings(crate_map: &CrateMap, settings: ~str) {
libstd/rt/crate_map.rs:34:21-34:21 -fn- definition:
#[cfg(not(windows))]
pub fn get_crate_map() -> Option<&'static CrateMap<'static>> {
references:-libstd/rt/logging.rs:
186: match get_crate_map() {
libstd/rt/crate_map.rs:75:1-75:1 -fn- definition:
fn version(crate_map: &CrateMap) -> i32 {
references:-86: match version(crate_map) {
libstd/rt/crate_map.rs:22:1-22:1 -struct- definition:
pub struct ModEntry<'self> {
references:-102: pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) {
83: fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry),
30: entries: &'self [ModEntry<'self>],
libstd/rt/logging.rs:
109: fn update_entry(dirs: &[LogDirective], entry: &ModEntry) -> u32 {
libstd/rt/crate_map.rs:101:67-101:67 -fn- definition:
/// Iterates recursively over `crate_map` and all child crate maps
pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) {
references:-libstd/rt/logging.rs:
152: do iter_crate_map(crate_map) |entry| {
143: do iter_crate_map(crate_map) |entry| {