8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- #[ cfg( not( stage0) ) ] use cast:: transmute;
11
+ // #[cfg(not(stage0))] use cast::transmute;
12
12
use container:: MutableSet ;
13
13
use hashmap:: HashSet ;
14
14
use option:: { Some , None } ;
15
15
use vec:: ImmutableVector ;
16
16
17
+ /// Imports for old crate map versions
18
+ use cast:: transmute;
19
+ use libc:: c_char;
20
+ use ptr;
21
+ use str:: raw:: from_c_str;
22
+ use vec;
23
+
17
24
// Need to tell the linker on OS X to not barf on undefined symbols
18
25
// and instead look them up at runtime, which we need to resolve
19
26
// the crate_map properly.
@@ -28,14 +35,27 @@ extern {
28
35
static CRATE_MAP : CrateMap < ' static > ;
29
36
}
30
37
31
- pub struct ModEntry < ' self > {
32
- name : & ' self str ,
38
+ /// structs for old crate map versions
39
+ pub struct ModEntryV0 {
40
+ name : * c_char ,
33
41
log_level : * mut u32
34
42
}
43
+ pub struct CrateMapV0 {
44
+ entries : * ModEntryV0 ,
45
+ children: [ * CrateMapV0 , ..1 ]
46
+ }
35
47
36
- pub struct CrateMapV0 < ' self > {
37
- entries : & ' self [ ModEntry < ' self > ] ,
38
- children : & ' self [ & ' self CrateMap < ' self > ]
48
+ pub struct CrateMapV1 {
49
+ version : i32 ,
50
+ entries : * ModEntryV0 ,
51
+ /// a dynamically sized struct, where all pointers to children are listed adjacent
52
+ /// to the struct, terminated with NULL
53
+ children: [ * CrateMapV1 , ..1 ]
54
+ }
55
+
56
+ pub struct ModEntry < ' self > {
57
+ name : & ' self str ,
58
+ log_level : * mut u32
39
59
}
40
60
41
61
pub struct CrateMap < ' self > {
@@ -46,6 +66,8 @@ pub struct CrateMap<'self> {
46
66
children : & ' self [ & ' self CrateMap < ' self > ]
47
67
}
48
68
69
+
70
+
49
71
#[ cfg( not( windows) ) ]
50
72
pub fn get_crate_map( ) -> & ' static CrateMap < ' static > {
51
73
& ' static CRATE_MAP
@@ -71,51 +93,60 @@ pub fn get_crate_map() -> &'static CrateMap<'static> {
71
93
72
94
fn version ( crate_map : & CrateMap ) -> i32 {
73
95
match crate_map. version {
96
+ 2 => return 2 ,
74
97
1 => return 1 ,
75
98
_ => return 0
76
99
}
77
100
}
78
101
79
- #[ cfg( not( stage0) ) ]
80
- fn get_entries_and_children < ' a > ( crate_map : & ' a CrateMap < ' a > ) ->
81
- ( & ' a [ ModEntry < ' a > ] , & ' a [ & ' a CrateMap < ' a > ] ) {
82
- match version ( crate_map) {
83
- 0 => {
84
- unsafe {
85
- let v0: & ' a CrateMapV0 < ' a > = transmute ( crate_map) ;
86
- return ( v0. entries , v0. children ) ;
87
- }
88
- }
89
- 1 => return ( * crate_map) . entries ,
90
- _ => fail2 ! ( "Unknown crate map version!" )
91
- }
92
- }
93
-
94
- #[ cfg( not( stage0) ) ]
95
102
fn iter_module_map ( mod_entries : & [ ModEntry ] , f : & fn ( & ModEntry ) ) {
96
103
for entry in mod_entries. iter ( ) {
97
104
f ( entry) ;
98
105
}
99
106
}
100
107
101
- #[ cfg( not( stage0) ) ]
108
+ unsafe fn iter_module_map_v0 ( entries : * ModEntryV0 , f : & fn ( & ModEntry ) ) {
109
+ let mut curr = entries;
110
+ while !( * curr) . name . is_null ( ) {
111
+ let mod_entry = ModEntry { name : from_c_str ( ( * curr) . name ) , log_level : ( * curr) . log_level } ;
112
+ f ( & mod_entry) ;
113
+ curr = curr. offset ( 1 ) ;
114
+ }
115
+ }
116
+
102
117
fn do_iter_crate_map < ' a > ( crate_map : & ' a CrateMap < ' a > , f : & fn ( & ModEntry ) ,
103
118
visited : & mut HashSet < * CrateMap < ' a > > ) {
104
119
if visited. insert ( crate_map as * CrateMap ) {
105
- let ( entries, children) = get_entries_and_children ( crate_map) ;
106
- iter_module_map ( entries, |x| f ( x) ) ;
107
- for child in children. iter ( ) {
108
- do_iter_crate_map ( * child, |x| f ( x) , visited) ;
120
+ match version ( crate_map) {
121
+ 2 => {
122
+ let ( entries, children) = ( crate_map. entries , crate_map. children ) ;
123
+ iter_module_map ( entries, |x| f ( x) ) ;
124
+ for child in children. iter ( ) {
125
+ do_iter_crate_map ( * child, |x| f ( x) , visited) ;
126
+ }
127
+ } ,
128
+ /// code for old crate map versions
129
+ 1 => unsafe {
130
+ let v1: * CrateMapV1 = transmute ( crate_map) ;
131
+ iter_module_map_v0 ( ( * v1) . entries , |x| f ( x) ) ;
132
+ let children = vec:: raw:: to_ptr ( ( * v1) . children ) ;
133
+ do ptr:: array_each ( children) |child| {
134
+ do_iter_crate_map ( transmute ( child) , |x| f ( x) , visited) ;
135
+ }
136
+ } ,
137
+ 0 => unsafe {
138
+ let v0: * CrateMapV0 = transmute ( crate_map) ;
139
+ iter_module_map_v0 ( ( * v0) . entries , |x| f ( x) ) ;
140
+ let children = vec:: raw:: to_ptr ( ( * v0) . children ) ;
141
+ do ptr:: array_each ( children) |child| {
142
+ do_iter_crate_map ( transmute ( child) , |x| f ( x) , visited) ;
143
+ }
144
+ } ,
145
+ _ => fail2 ! ( "invalid crate map version" )
109
146
}
110
147
}
111
148
}
112
149
113
- #[ cfg( stage0) ]
114
- /// Iterates recursively over `crate_map` and all child crate maps
115
- pub fn iter_crate_map < ' a > ( crate_map : & ' a CrateMap < ' a > , f : & fn ( & ModEntry ) ) {
116
- }
117
-
118
- #[ cfg( not( stage0) ) ]
119
150
/// Iterates recursively over `crate_map` and all child crate maps
120
151
pub fn iter_crate_map < ' a > ( crate_map : & ' a CrateMap < ' a > , f : & fn ( & ModEntry ) ) {
121
152
// XXX: use random numbers as keys from the OS-level RNG when there is a nice
@@ -137,13 +168,13 @@ mod tests {
137
168
] ;
138
169
139
170
let child_crate = CrateMap {
140
- version : 1 ,
171
+ version : 2 ,
141
172
entries : entries,
142
173
children : [ ]
143
174
} ;
144
175
145
176
let root_crate = CrateMap {
146
- version : 1 ,
177
+ version : 2 ,
147
178
entries : [ ] ,
148
179
children : [ & child_crate, & child_crate]
149
180
} ;
@@ -163,7 +194,7 @@ mod tests {
163
194
let mut level2: u32 = 2 ;
164
195
let mut level3: u32 = 3 ;
165
196
let child_crate2 = CrateMap {
166
- version : 1 ,
197
+ version : 2 ,
167
198
entries : [
168
199
ModEntry { name : "c::m1" , log_level : & mut level2} ,
169
200
ModEntry { name : "c::m2" , log_level : & mut level3} ,
@@ -172,15 +203,15 @@ mod tests {
172
203
} ;
173
204
174
205
let child_crate1 = CrateMap {
175
- version : 1 ,
206
+ version : 2 ,
176
207
entries : [
177
208
ModEntry { name : "t::f1" , log_level : & mut 1 } ,
178
209
] ,
179
210
children : [ & child_crate2]
180
211
} ;
181
212
182
213
let root_crate = CrateMap {
183
- version : 1 ,
214
+ version : 2 ,
184
215
entries : [
185
216
ModEntry { name : "t::f2" , log_level : & mut 0 } ,
186
217
] ,
@@ -196,4 +227,106 @@ mod tests {
196
227
assert ! ( cnt == 4 ) ;
197
228
}
198
229
}
230
+
231
+
232
+ /// Tests for old crate map versions
233
+ #[ test]
234
+ fn iter_crate_map_duplicates_v1( ) {
235
+ use c_str:: ToCStr ;
236
+ use cast:: transmute;
237
+ use ptr;
238
+ use rt:: crate_map:: { CrateMapV1 , ModEntryV0 , iter_crate_map} ;
239
+ use vec;
240
+
241
+ struct CrateMapT3 {
242
+ version : i32 ,
243
+ entries : * ModEntryV0 ,
244
+ children: [ * CrateMapV1 , ..3 ]
245
+ }
246
+
247
+ unsafe {
248
+ let mod_name1 = "c::m1" . to_c_str ( ) ;
249
+ let mut level3: u32 = 3 ;
250
+
251
+ let entries: ~[ ModEntryV0 ] = ~[
252
+ ModEntryV0 { name : mod_name1. with_ref ( |buf| buf) , log_level : & mut level3} ,
253
+ ModEntryV0 { name : ptr:: null ( ) , log_level : ptr:: mut_null ( ) }
254
+ ] ;
255
+ let child_crate = CrateMapV1 {
256
+ version : 1 ,
257
+ entries : vec:: raw:: to_ptr ( entries) ,
258
+ children : [ ptr:: null ( ) ]
259
+ } ;
260
+
261
+ let root_crate = CrateMapT3 {
262
+ version : 1 ,
263
+ entries : vec:: raw:: to_ptr ( [ ModEntryV0 { name : ptr:: null ( ) , log_level : ptr:: mut_null ( ) } ] ) ,
264
+ children : [ & child_crate as * CrateMapV1 , & child_crate as * CrateMapV1 , ptr:: null ( ) ]
265
+ } ;
266
+
267
+ let mut cnt = 0 ;
268
+ do iter_crate_map ( transmute ( & root_crate) ) |entry| {
269
+ assert ! ( * ( * entry) . log_level == 3 ) ;
270
+ cnt += 1 ;
271
+ }
272
+ assert ! ( cnt == 1 ) ;
273
+ }
274
+ }
275
+
276
+ #[ test]
277
+ fn iter_crate_map_follow_children_v1 ( ) {
278
+ use c_str:: ToCStr ;
279
+ use cast:: transmute;
280
+ use ptr;
281
+ use rt:: crate_map:: { CrateMapV1 , ModEntryV0 , iter_crate_map} ;
282
+ use vec;
283
+
284
+ struct CrateMapT2 {
285
+ version : i32 ,
286
+ entries : * ModEntryV0 ,
287
+ children: [ * CrateMapV1 , ..2 ]
288
+ }
289
+
290
+ unsafe {
291
+ let mod_name1 = "c::m1" . to_c_str ( ) ;
292
+ let mod_name2 = "c::m2" . to_c_str ( ) ;
293
+ let mut level2: u32 = 2 ;
294
+ let mut level3: u32 = 3 ;
295
+ let child_crate2 = CrateMapV1 {
296
+ version : 1 ,
297
+ entries : vec:: raw:: to_ptr ( [
298
+ ModEntryV0 { name : mod_name1. with_ref ( |buf| buf) , log_level : & mut level2} ,
299
+ ModEntryV0 { name : mod_name2. with_ref ( |buf| buf) , log_level : & mut level3} ,
300
+ ModEntryV0 { name : ptr:: null ( ) , log_level : ptr:: mut_null ( ) }
301
+ ] ) ,
302
+ children : [ ptr:: null ( ) ]
303
+ } ;
304
+
305
+ let child_crate1 = CrateMapT2 {
306
+ version : 1 ,
307
+ entries : vec:: raw:: to_ptr ( [
308
+ ModEntryV0 { name : "t::f1" . with_c_str ( |buf| buf) , log_level : & mut 1 } ,
309
+ ModEntryV0 { name : ptr:: null ( ) , log_level : ptr:: mut_null ( ) }
310
+ ] ) ,
311
+ children : [ & child_crate2 as * CrateMapV1 , ptr:: null ( ) ]
312
+ } ;
313
+
314
+ let child_crate1_ptr: * CrateMapV1 = transmute ( & child_crate1) ;
315
+ let root_crate = CrateMapT2 {
316
+ version : 1 ,
317
+ entries : vec:: raw:: to_ptr ( [
318
+ ModEntryV0 { name : "t::f1" . with_c_str ( |buf| buf) , log_level : & mut 0 } ,
319
+ ModEntryV0 { name : ptr:: null ( ) , log_level : ptr:: mut_null ( ) }
320
+ ] ) ,
321
+ children : [ child_crate1_ptr, ptr:: null ( ) ]
322
+ } ;
323
+
324
+ let mut cnt = 0 ;
325
+ do iter_crate_map ( transmute ( & root_crate) ) |entry| {
326
+ assert ! ( * ( * entry) . log_level == cnt) ;
327
+ cnt += 1 ;
328
+ }
329
+ assert ! ( cnt == 4 ) ;
330
+ }
331
+ }
199
332
}
0 commit comments