about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2013-09-10 00:04:29 +0200
committerFlorian Hahn <flo@fhahn.com>2013-09-13 00:47:30 +0200
commit2b5f4b55c0238932ee991102b612858d4b3deb6c (patch)
tree88dc41b1bac43ac174ea23fa233bfdd36855e29e
parentb0e13e0d0e61b4147c8c62856c50cf727f7c918f (diff)
downloadrust-2b5f4b55c0238932ee991102b612858d4b3deb6c.tar.gz
rust-2b5f4b55c0238932ee991102b612858d4b3deb6c.zip
Convert rust_crate_map.cpp to Rust
Conflicts:
	src/libstd/rt/logging.rs
-rw-r--r--mk/rt.mk1
-rw-r--r--src/libstd/rt/crate_map.rs200
-rw-r--r--src/libstd/rt/logging.rs64
-rw-r--r--src/libstd/rt/mod.rs3
-rw-r--r--src/rt/rust_crate_map.cpp69
-rw-r--r--src/rt/rust_crate_map.h105
-rw-r--r--src/rt/rustrt.def.in1
7 files changed, 213 insertions, 230 deletions
diff --git a/mk/rt.mk b/mk/rt.mk
index 4dff262330a..e31f2228e3f 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -75,7 +75,6 @@ RUNTIME_CXXS_$(1)_$(2) := \
               rt/rust_rng.cpp \
               rt/rust_upcall.cpp \
               rt/rust_uv.cpp \
-              rt/rust_crate_map.cpp \
               rt/isaac/randport.cpp \
               rt/miniz.cpp \
               rt/memory_region.cpp \
diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs
new file mode 100644
index 00000000000..270b5e5b137
--- /dev/null
+++ b/src/libstd/rt/crate_map.rs
@@ -0,0 +1,200 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+use libc::{c_void, c_char};
+use ptr;
+use ptr::RawPtr;
+use vec;
+use hashmap::HashSet;
+use container::MutableSet;
+
+pub struct ModEntry{
+    name: *c_char,
+    log_level: *mut u32
+}
+struct CrateMapV0 {
+    entries: *ModEntry,
+    children: [*CrateMap, ..1]
+}
+
+struct CrateMap {
+    version: i32,
+    annihilate_fn: *c_void,
+    entries: *ModEntry,
+    /// a dynamically sized struct, where all pointers to children are listed adjacent
+    /// to the struct, terminated with NULL
+    children: [*CrateMap, ..1]
+}
+
+unsafe fn version(crate_map: *CrateMap) -> i32 {
+    match (*crate_map).version {
+        1 => return 1,
+        _ => return 0
+    }
+}
+
+/// Returns a pointer to the annihilate function of the CrateMap
+pub unsafe fn annihilate_fn(crate_map: *CrateMap) -> *c_void {
+    match version(crate_map) {
+        0 => return ptr::null(),
+        1 => return (*crate_map).annihilate_fn,
+        _ => fail!("Unknown crate map version!")
+    }
+}
+
+unsafe fn entries(crate_map: *CrateMap) -> *ModEntry {
+    match version(crate_map) {
+        0 => {
+            let v0 = crate_map as (*CrateMapV0);
+            return (*v0).entries;
+        }
+        1 => return (*crate_map).entries,
+        _ => fail!("Unknown crate map version!")
+    }
+}
+
+unsafe fn iterator(crate_map: *CrateMap) -> **CrateMap {
+    match version(crate_map) {
+        0 => {
+            let v0 = crate_map as (*CrateMapV0);
+            return vec::raw::to_ptr((*v0).children);
+        }
+        1 => return vec::raw::to_ptr((*crate_map).children),
+        _ => fail!("Unknown crate map version!")
+    }
+}
+
+unsafe fn iter_module_map(mod_entries: *ModEntry, f: &fn(*mut ModEntry)) {
+    let mut curr = mod_entries;
+
+    while !(*curr).name.is_null() {
+        f(curr as *mut ModEntry);
+        curr = curr.offset(1);
+    }
+}
+
+unsafe fn do_iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry),
+                            visited: &mut HashSet<*CrateMap>) {
+    if visited.insert(crate_map) {
+        iter_module_map(entries(crate_map), |x| f(x));
+        let child_crates = iterator(crate_map);
+        do ptr::array_each(child_crates) |child| {
+            do_iter_crate_map(child, |x| f(x), visited);
+        }
+    }
+}
+
+/// Iterates recursively over `crate_map` and all child crate maps
+pub unsafe fn iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry)) {
+    // XXX: use random numbers as keys from the OS-level RNG when there is a nice
+    //        way to do this
+    let mut v: HashSet<*CrateMap> = HashSet::with_capacity_and_keys(0, 0, 32);
+    do_iter_crate_map(crate_map, f, &mut v);
+}
+
+#[test]
+fn iter_crate_map_duplicates() {
+    use c_str::ToCStr;
+    use cast::transmute;
+
+    struct CrateMapT3 {
+        version: i32,
+        annihilate_fn: *c_void,
+        entries: *ModEntry,
+        children: [*CrateMap, ..3]
+    }
+
+    unsafe {
+        let mod_name1 = "c::m1".to_c_str();
+        let mut level3: u32 = 3;
+
+        let entries: ~[ModEntry] = ~[
+            ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3},
+            ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
+        ];
+        let child_crate = CrateMap {
+            version: 1,
+            annihilate_fn: ptr::null(),
+            entries: vec::raw::to_ptr(entries),
+            children: [ptr::null()]
+        };
+
+        let root_crate = CrateMapT3 {
+            version: 1, annihilate_fn: ptr::null(),
+            entries: vec::raw::to_ptr([ModEntry { name: ptr::null(), log_level: ptr::mut_null()}]),
+            children: [&child_crate as *CrateMap, &child_crate as *CrateMap, 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() {
+    use c_str::ToCStr;
+    use cast::transmute;
+
+    struct CrateMapT2 {
+        version: i32,
+        annihilate_fn: *c_void,
+        entries: *ModEntry,
+        children: [*CrateMap, ..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 = CrateMap {
+            version: 1,
+            annihilate_fn: ptr::null(),
+            entries: vec::raw::to_ptr([
+                ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2},
+                ModEntry { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3},
+                ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
+            ]),
+            children: [ptr::null()]
+        };
+
+        let child_crate1 = CrateMapT2 {
+            version: 1,
+            annihilate_fn: ptr::null(),
+            entries: vec::raw::to_ptr([
+                ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 1},
+                ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
+            ]),
+            children: [&child_crate2 as *CrateMap, ptr::null()]
+        };
+
+        let child_crate1_ptr: *CrateMap = transmute(&child_crate1);
+        let root_crate = CrateMapT2 {
+            version: 1, annihilate_fn: ptr::null(),
+            entries: vec::raw::to_ptr([
+                ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 0},
+                ModEntry { 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);
+    }
+}
diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs
index 8a4aba3eb87..0dd096b5bf3 100644
--- a/src/libstd/rt/logging.rs
+++ b/src/libstd/rt/logging.rs
@@ -7,66 +7,24 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-use cast::transmute;
 use either::*;
-use libc::{c_void, uintptr_t, c_char, exit, STDERR_FILENO};
+use libc::{uintptr_t, exit, STDERR_FILENO};
 use option::{Some, None, Option};
 use rt::util::dumb_println;
+use rt::crate_map::{ModEntry, iter_crate_map};
 use str::StrSlice;
 use str::raw::from_c_str;
 use u32;
-use unstable::raw::Closure;
 use vec::ImmutableVector;
-
+use cast::transmute;
 
 struct LogDirective {
     name: Option<~str>,
     level: u32
 }
 
-// This is the Rust representation of the mod_entry struct in src/rt/rust_crate_map.h
-struct ModEntry{
-    name: *c_char,
-    log_level: *mut u32
-}
-
 static MAX_LOG_LEVEL: u32 = 255;
 static DEFAULT_LOG_LEVEL: u32 = 1;
-
-fn iter_crate_map(map: *u8, f: &fn(*mut ModEntry)) {
-    unsafe {
-        let closure : Closure = transmute(f);
-        let code = transmute(closure.code);
-        let env = transmute(closure.env);
-        rust_iter_crate_map(transmute(map), iter_cb, code, env);
-    }
-
-    extern fn iter_cb(code: *c_void, env: *c_void, entry: *ModEntry){
-         unsafe {
-            let closure: Closure = Closure {
-                code: transmute(code),
-                env: transmute(env),
-            };
-            let closure: &fn(*ModEntry) = transmute(closure);
-            return closure(entry);
-        }
-    }
-    extern {
-        #[cfg(not(stage0))]
-        #[rust_stack]
-        fn rust_iter_crate_map(map: *c_void,
-                    f: extern "C" fn(*c_void, *c_void, entry: *ModEntry),
-                    code: *c_void,
-                    data: *c_void);
-
-        #[cfg(stage0)]
-        #[rust_stack]
-        fn rust_iter_crate_map(map: *c_void,
-                    f: *u8,
-                    code: *c_void,
-                    data: *c_void);
-    }
-}
 static log_level_names : &'static[&'static str] = &'static["error", "warn", "info", "debug"];
 
 /// Parse an individual log level that is either a number or a symbolic log level
@@ -96,12 +54,10 @@ fn parse_log_level(level: &str) -> Option<u32> {
     log_level
 }
 
-
 /// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1")
 /// and return a vector with log directives.
 /// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in std::).
 /// Also supports string log levels of error, warn, info, and debug
-
 fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
     let mut dirs = ~[];
     for s in spec.split_iter(',') {
@@ -186,12 +142,10 @@ fn update_log_settings(crate_map: *u8, settings: ~str) {
     if settings.len() > 0 {
         if settings == ~"::help" || settings == ~"?" {
             dumb_println("\nCrate log map:\n");
-            do iter_crate_map(crate_map) |entry: *mut ModEntry| {
-                unsafe {
+            unsafe {
+                do iter_crate_map(transmute(crate_map)) |entry: *mut ModEntry| {
                     dumb_println(" "+from_c_str((*entry).name));
                 }
-            }
-            unsafe {
                 exit(1);
             }
         }
@@ -199,9 +153,11 @@ fn update_log_settings(crate_map: *u8, settings: ~str) {
     }
 
     let mut n_matches: u32 = 0;
-    do iter_crate_map(crate_map) |entry: *mut ModEntry| {
-        let m = update_entry(dirs, entry);
-        n_matches += m;
+    unsafe {
+        do iter_crate_map(transmute(crate_map)) |entry: *mut ModEntry| {
+            let m = update_entry(dirs, entry);
+            n_matches += m;
+        }
     }
 
     if n_matches < (dirs.len() as u32) {
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index c9c3c4ec6da..53f62786b62 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -126,6 +126,9 @@ pub mod local_heap;
 /// The Logger trait and implementations
 pub mod logging;
 
+/// Crate map
+pub mod crate_map;
+
 /// Tools for testing the runtime
 pub mod test;
 
diff --git a/src/rt/rust_crate_map.cpp b/src/rt/rust_crate_map.cpp
deleted file mode 100644
index e6206fd7bcb..00000000000
--- a/src/rt/rust_crate_map.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#include "rust_crate_map.h"
-#include <set>
-
-void iter_module_map(const mod_entry* map,
-                    void (*fn)(void* fptr, void* env, const mod_entry *entry),
-                    void* fptr,
-                    void* env
-                    ) {
-    for (const mod_entry* cur = map; cur->name; cur++) {
-        fn(fptr, env, cur);
-    }
-}
-
-void iter_crate_map(const cratemap* map,
-                    void (*fn)(void* fptr, void* env, const mod_entry *entry),
-                    void *fptr,
-                    void *env,
-                    std::set<const cratemap*>& visited) {
-    if (visited.find(map) == visited.end()) {
-        // Mark this crate visited
-        visited.insert(map);
-        // First iterate this crate
-        iter_module_map(map->entries(), fn, fptr, env);
-        // Then recurse on linked crates
-        for (cratemap::iterator i = map->begin(),
-                e = map->end(); i != e; ++i) {
-            iter_crate_map(*i, fn, fptr, env, visited);
-        }
-    }
-}
-
-void iter_crate_map(const cratemap* map,
-                    void (*fn)(void* fptr, void* env, const mod_entry *entry),
-                    void *fptr,
-                    void *env
-                    ) {
-    std::set<const cratemap*> visited;
-    iter_crate_map(map, fn, fptr, env, visited);
-}
-
-extern "C" CDECL void
-rust_iter_crate_map(const cratemap* map,
-                    void (*fn)(void* fptr, void* env, const mod_entry *entry),
-                    void *fptr,
-                    void *env
-                    ) {
-    return iter_crate_map(map, fn, fptr, env);
-}
-
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
diff --git a/src/rt/rust_crate_map.h b/src/rt/rust_crate_map.h
deleted file mode 100644
index 1bcb2aa8f7e..00000000000
--- a/src/rt/rust_crate_map.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#ifndef RUST_CRATE_MAP_H
-#define RUST_CRATE_MAP_H
-
-#include "rust_globals.h"
-#include <stdint.h>
-
-struct mod_entry {
-    const char* name;
-    uint32_t* log_level;
-};
-
-class cratemap;
-
-class cratemap_v0 {
-    friend class cratemap;
-    const mod_entry *m_entries;
-    const cratemap* m_children[1];
-};
-
-class cratemap {
-private:
-    int32_t m_version;
-    const void *m_annihilate_fn;
-    const mod_entry* m_entries;
-    const cratemap* m_children[1];
-
-    inline int32_t version() const {
-        switch (m_version) {
-        case 1:     return 1;
-        default:    return 0;
-        }
-    }
-
-public:
-    typedef const cratemap *const *iterator;
-
-    inline const void *annihilate_fn() const {
-        switch (version()) {
-        case 0: return NULL;
-        case 1: return m_annihilate_fn;
-        default: assert(false && "Unknown crate map version!");
-            return NULL; // Appease -Werror=return-type
-        }
-    }
-
-    inline const mod_entry *entries() const {
-        switch (version()) {
-        case 0: return reinterpret_cast<const cratemap_v0 *>(this)->m_entries;
-        case 1: return m_entries;
-        default: assert(false && "Unknown crate map version!");
-            return NULL; // Appease -Werror=return-type
-        }
-    }
-
-    inline const iterator begin() const {
-        switch (version()) {
-        case 0:
-            return &reinterpret_cast<const cratemap_v0 *>(this)->
-                m_children[0];
-        case 1:
-            return &m_children[0];
-        default: assert(false && "Unknown crate map version!");
-            return NULL; // Appease -Werror=return-type
-        }
-    }
-
-    inline const iterator end() const {
-        iterator i = begin();
-        while (*i)
-            i++;
-        return i;
-    }
-};
-
-void iter_module_map(const mod_entry* map,
-                     void (*fn)(void* fptr, void* env, const mod_entry *entry),
-                     void *fptr,
-                     void *env);
-
-void iter_crate_map(const cratemap* map,
-                    void (*fn)(void* fptr, void* env, const mod_entry *entry),
-                    void *fptr,
-                    void *env);
-
-//
-// Local Variables:
-// mode: C++
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
-
-#endif /* RUST_CRATE_MAP_H */
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index bf3500e4c72..af6daed1a3e 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -181,7 +181,6 @@ rust_valgrind_stack_register
 rust_valgrind_stack_deregister
 rust_take_env_lock
 rust_drop_env_lock
-rust_iter_crate_map
 rust_running_on_valgrind
 rust_get_num_cpus
 rust_get_global_args_ptr