diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 36827b73ba0..928c934a7ec 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -98,6 +98,7 @@ fn usage(session.session sess, str argv0) { log " -glue generate glue.bc file"; log " -shared compile a shared-library crate"; log " -pp pretty-print the input instead of compiling"; + log " -ls list the symbols defined by a crate file"; log " -L add a directory to the library search path"; log " -h display this message"; log ""; @@ -130,6 +131,7 @@ impure fn main(vec[str] args) { let bool do_warn = true; let bool shared = false; let bool pretty = false; + let bool ls = false; let bool glue = false; // FIXME: Maybe we should support -O0, -O1, -Os, etc @@ -152,6 +154,8 @@ impure fn main(vec[str] args) { shared = true; } else if (_str.eq(arg, "-pp")) { pretty = true; + } else if (_str.eq(arg, "-ls")) { + ls = true; } else if (_str.eq(arg, "-o")) { if (i+1u < len) { output_file = some(args.(i+1u)); @@ -214,8 +218,9 @@ impure fn main(vec[str] args) { auto env = default_environment(sess, args.(0), ifile); if (pretty) { pretty_print_input(sess, env, ifile); - } - else { + } else if (ls) { + front.creader.list_file_metadata(ifile, std.io.stdout()); + } else { alt (output_file) { case (none[str]) { let vec[str] parts = _str.split(ifile, '.' as u8); diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs index b561367c8b3..7fc6e24726c 100644 --- a/src/comp/front/creader.rs +++ b/src/comp/front/creader.rs @@ -566,6 +566,72 @@ fn get_tag_variants(session.session sess, ast.def_id def) ret infos; } +impure fn list_file_metadata(str path, io.writer out) { + alt (get_metadata_section(path)) { + case (option.some[vec[u8]](?bytes)) { + list_crate_metadata(bytes, out); + } + case (option.none[vec[u8]]) { + out.write_str("Could not find metadata in " + path + ".\n"); + } + } +} + +fn read_path(&ebml.doc d) -> tup(str, uint) { + auto desc = ebml.doc_data(d); + auto pos = ebml.be_uint_from_bytes(desc, 0u, 4u); + auto pathbytes = _vec.slice[u8](desc, 4u, _vec.len[u8](desc)); + auto path = _str.unsafe_from_bytes(pathbytes); + ret tup(path, pos); +} + +impure fn list_crate_metadata(vec[u8] bytes, io.writer out) { + auto md = ebml.new_doc(bytes); + auto paths = ebml.get_doc(md, metadata.tag_paths); + auto items = ebml.get_doc(md, metadata.tag_items); + auto index = ebml.get_doc(paths, metadata.tag_index); + auto bs = ebml.get_doc(index, metadata.tag_index_buckets); + for each (ebml.doc bucket in + ebml.tagged_docs(bs, metadata.tag_index_buckets_bucket)) { + auto et = metadata.tag_index_buckets_bucket_elt; + for each (ebml.doc elt in ebml.tagged_docs(bucket, et)) { + auto data = read_path(elt); + auto def = ebml.doc_at(bytes, data._1); + auto did_doc = ebml.get_doc(def, metadata.tag_def_id); + auto did = parse_def_id(ebml.doc_data(did_doc)); + out.write_str(#fmt("%s (%s)\n", data._0, + describe_def(items, did))); + } + } +} + +fn describe_def(&ebml.doc items, ast.def_id id) -> str { + if (id._0 != 0) {ret "external";} + alt (maybe_find_item(id._1 as int, items)) { + case (option.some[ebml.doc](?item)) { + ret item_kind_to_str(item_kind(item)); + } + case (option.none[ebml.doc]) { + ret "??"; // Native modules don't seem to get item entries. + } + } +} + +fn item_kind_to_str(u8 kind) -> str { + alt (kind as char) { + case ('c') {ret "const";} + case ('f') {ret "fn";} + case ('F') {ret "native fn";} + case ('y') {ret "type";} + case ('o') {ret "obj";} + case ('T') {ret "native type";} + case ('t') {ret "type";} + case ('m') {ret "mod";} + case ('n') {ret "native mod";} + case ('v') {ret "tag";} + } +} + // Local Variables: // mode: rust // fill-column: 78;