diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile | 7 | ||||
-rw-r--r-- | tools/cmt2annot.ml | 81 | ||||
-rw-r--r-- | tools/read_cmt.ml | 125 |
3 files changed, 145 insertions, 68 deletions
diff --git a/tools/Makefile b/tools/Makefile index e5ad82f575..f640d7fd57 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -275,6 +275,13 @@ READ_CMT= \ # Reading cmt files $(call byte_and_opt,read_cmt,$(READ_CMT),) +install:: + if test -f read_cmt.opt; then \ + cp read_cmt.opt "$(INSTALL_BINDIR)/ocamlcmt$(EXE)"; \ + else \ + cp read_cmt "$(INSTALL_BINDIR)/ocamlcmt$(EXE)"; \ + fi + # The bytecode disassembler diff --git a/tools/cmt2annot.ml b/tools/cmt2annot.ml index 53299f9867..0d975f4cf8 100644 --- a/tools/cmt2annot.ml +++ b/tools/cmt2annot.ml @@ -54,6 +54,12 @@ let bind_cases l = ) l +let record_module_binding scope mb = + Stypes.record (Stypes.An_ident + (mb.mb_name.loc, + mb.mb_name.txt, + Annot.Idef scope)) + let rec iterator ~scope rebuild_env = let super = Tast_mapper.default in let class_expr sub node = @@ -99,6 +105,9 @@ let rec iterator ~scope rebuild_env = | Texp_function { cases = f; } | Texp_try (_, f) -> bind_cases f + | Texp_letmodule (_, modname, _, body ) -> + Stypes.record (Stypes.An_ident + (modname.loc,modname.txt,Annot.Idef body.exp_loc)) | _ -> () end; Stypes.record (Stypes.Ti_expr exp); @@ -109,21 +118,28 @@ let rec iterator ~scope rebuild_env = super.pat sub p in - let structure_item_rem sub s rem = - begin match s with - | {str_desc = Tstr_value (rec_flag, bindings); str_loc = loc} -> - let open Location in + let structure_item_rem sub str rem = + let open Location in + let loc = str.str_loc in + begin match str.str_desc with + | Tstr_value (rec_flag, bindings) -> let doit loc_start = bind_bindings {scope with loc_start} bindings in begin match rec_flag, rem with | Recursive, _ -> doit loc.loc_start | Nonrecursive, [] -> doit loc.loc_end | Nonrecursive, {str_loc = loc2} :: _ -> doit loc2.loc_start end + | Tstr_module mb -> + record_module_binding + { scope with Location.loc_start = loc.loc_end } mb + | Tstr_recmodule mbs -> + List.iter (record_module_binding + { scope with Location.loc_start = loc.loc_start }) mbs | _ -> () end; - Stypes.record_phrase s.str_loc; - super.structure_item sub s + Stypes.record_phrase loc; + super.structure_item sub str in let structure_item sub s = (* This will be used for Partial_structure_item. @@ -153,19 +169,45 @@ let binary_part iter x = | Partial_signature_item x -> app iter.signature_item x | Partial_module_type x -> app iter.module_type x -let gen_annot target_filename filename - {Cmt_format.cmt_loadpath; cmt_annots; cmt_use_summaries; _} = +(* Save cmt information as faked annotations, attached to + Location.none, on top of the .annot file. Only when -save-cmt-info is + provided to ocaml_cmt. +*) +let record_cmt_info cmt = + let location_none = { + Location.none with Location.loc_ghost = false } + in + let location_file file = { + Location.none with + Location.loc_start = { + Location.none.Location.loc_start with + Lexing.pos_fname = file }} + in + let record_info name value = + let ident = Printf.sprintf ".%s" name in + Stypes.record (Stypes.An_ident (location_none, ident, + Annot.Idef (location_file value))) + in + let open Cmt_format in + (* record in reverse order to get them in correct order... *) + List.iter (fun dir -> record_info "include" dir) (List.rev cmt.cmt_loadpath); + record_info "chdir" cmt.cmt_builddir; + (match cmt.cmt_sourcefile with + None -> () | Some file -> record_info "source" file) + +let gen_annot ?(save_cmt_info=false) target_filename filename cmt = let open Cmt_format in Envaux.reset_cache (); - Config.load_path := cmt_loadpath; + Config.load_path := cmt.cmt_loadpath @ !Config.load_path; let target_filename = match target_filename with | None -> Some (filename ^ ".annot") | Some "-" -> None | Some _ -> target_filename in - let iterator = iterator ~scope:Location.none cmt_use_summaries in - match cmt_annots with + if save_cmt_info then record_cmt_info cmt; + let iterator = iterator ~scope:Location.none cmt.cmt_use_summaries in + match cmt.cmt_annots with | Implementation typedtree -> ignore (iterator.structure iterator typedtree); Stypes.dump target_filename @@ -175,26 +217,27 @@ let gen_annot target_filename filename | Partial_implementation parts -> Array.iter (binary_part iterator) parts; Stypes.dump target_filename - | _ -> + | Packed _ -> + Printf.fprintf stderr "Packed files not yet supported\n%!"; + Stypes.dump target_filename + | Partial_interface _ -> Printf.fprintf stderr "File was generated with an error\n%!"; exit 2 - - let gen_ml target_filename filename cmt = let (printer, ext) = match cmt.Cmt_format.cmt_annots with | Cmt_format.Implementation typedtree -> - (fun ppf -> Pprintast.structure ppf + (fun ppf -> Pprintast.structure ppf (Untypeast.untype_structure typedtree)), - ".ml" + ".ml" | Cmt_format.Interface typedtree -> - (fun ppf -> Pprintast.signature ppf + (fun ppf -> Pprintast.signature ppf (Untypeast.untype_signature typedtree)), - ".mli" + ".mli" | _ -> Printf.fprintf stderr "File was generated with an error\n%!"; - exit 2 + exit 2 in let target_filename = match target_filename with None -> Some (filename ^ ext) diff --git a/tools/read_cmt.ml b/tools/read_cmt.ml index ea8e3c05a4..1e221339f1 100644 --- a/tools/read_cmt.ml +++ b/tools/read_cmt.ml @@ -17,20 +17,27 @@ let gen_annot = ref false let gen_ml = ref false let print_info_arg = ref false let target_filename = ref None +let save_cmt_info = ref false -let arg_list = [ +let arg_list = Arg.align [ "-o", Arg.String (fun s -> target_filename := Some s), - " FILE (or -) : dump to file FILE (or stdout)"; - "-annot", Arg.Set gen_annot, " : generate the corresponding .annot file"; + "<file> Dump to file <file> (or stdout if -)"; + "-annot", Arg.Set gen_annot, + " Generate the corresponding .annot file"; + "-save-cmt-info", Arg.Set save_cmt_info, + " Encapsulate additional cmt information in annotations"; "-src", Arg.Set gen_ml, - " : convert .cmt or .cmti back to source code (without comments)"; + " Convert .cmt or .cmti back to source code (without comments)"; "-info", Arg.Set print_info_arg, " : print information on the file"; "-args", Arg.Expand Arg.read_arg, - " <file> Read additional newline separated command line arguments \n\ + "<file> Read additional newline separated command line arguments \n\ \ from <file>"; "-args0", Arg.Expand Arg.read_arg0, "<file> Read additional NUL separated command line arguments from \n\ \ <file>"; + "-I", Arg.String (fun s -> + Clflags.include_dirs := s :: !Clflags.include_dirs), + "<dir> Add <dir> to the list of include directories"; ] let arg_usage = @@ -39,50 +46,58 @@ let arg_usage = let dummy_crc = String.make 32 '-' let print_info cmt = + let oc = match !target_filename with + | None -> stdout + | Some filename -> open_out filename + in let open Cmt_format in - Printf.printf "module name: %s\n" cmt.cmt_modname; - begin match cmt.cmt_annots with - Packed (_, list) -> - Printf.printf "pack: %s\n" (String.concat " " list) - | Implementation _ -> Printf.printf "kind: implementation\n" - | Interface _ -> Printf.printf "kind: interface\n" - | Partial_implementation _ -> - Printf.printf "kind: implementation with errors\n" - | Partial_interface _ -> Printf.printf "kind: interface with errors\n" - end; - Printf.printf "command: %s\n" - (String.concat " " (Array.to_list cmt.cmt_args)); - begin match cmt.cmt_sourcefile with - None -> () - | Some name -> - Printf.printf "sourcefile: %s\n" name; - end; - Printf.printf "build directory: %s\n" cmt.cmt_builddir; - List.iter (Printf.printf "load path: %s\n%!") cmt.cmt_loadpath; - begin - match cmt.cmt_source_digest with - None -> () - | Some digest -> - Printf.printf "source digest: %s\n" (Digest.to_hex digest); - end; - begin - match cmt.cmt_interface_digest with - None -> () - | Some digest -> - Printf.printf "interface digest: %s\n" (Digest.to_hex digest); - end; - List.iter (fun (name, crco) -> - let crc = - match crco with - None -> dummy_crc - | Some crc -> Digest.to_hex crc - in - Printf.printf "import: %s %s\n" name crc; - ) (List.sort compare cmt.cmt_imports); - Printf.printf "%!"; - () + Printf.fprintf oc "module name: %s\n" cmt.cmt_modname; + begin match cmt.cmt_annots with + Packed (_, list) -> + Printf.fprintf oc "pack: %s\n" (String.concat " " list) + | Implementation _ -> Printf.fprintf oc "kind: implementation\n" + | Interface _ -> Printf.fprintf oc "kind: interface\n" + | Partial_implementation _ -> + Printf.fprintf oc "kind: implementation with errors\n" + | Partial_interface _ -> Printf.fprintf oc "kind: interface with errors\n" + end; + Printf.fprintf oc "command: %s\n" + (String.concat " " (Array.to_list cmt.cmt_args)); + begin match cmt.cmt_sourcefile with + None -> () + | Some name -> + Printf.fprintf oc "sourcefile: %s\n" name; + end; + Printf.fprintf oc "build directory: %s\n" cmt.cmt_builddir; + List.iter (Printf.fprintf oc "load path: %s\n%!") cmt.cmt_loadpath; + begin + match cmt.cmt_source_digest with + None -> () + | Some digest -> + Printf.fprintf oc "source digest: %s\n" (Digest.to_hex digest); + end; + begin + match cmt.cmt_interface_digest with + None -> () + | Some digest -> + Printf.fprintf oc "interface digest: %s\n" (Digest.to_hex digest); + end; + List.iter (fun (name, crco) -> + let crc = + match crco with + None -> dummy_crc + | Some crc -> Digest.to_hex crc + in + Printf.fprintf oc "import: %s %s\n" name crc; + ) (List.sort compare cmt.cmt_imports); + Printf.fprintf oc "%!"; + begin match !target_filename with + | None -> () + | Some _ -> close_out oc + end; + () -let _ = +let main () = Clflags.annotations := true; Arg.parse_expand arg_list (fun filename -> @@ -90,9 +105,11 @@ let _ = Filename.check_suffix filename ".cmt" || Filename.check_suffix filename ".cmti" then begin - (* init_path(); *) + Compmisc.init_path false; let cmt = Cmt_format.read_cmt filename in - if !gen_annot then Cmt2annot.gen_annot !target_filename filename cmt; + if !gen_annot then + Cmt2annot.gen_annot ~save_cmt_info: !save_cmt_info + !target_filename filename cmt; if !gen_ml then Cmt2annot.gen_ml !target_filename filename cmt; if !print_info_arg || not (!gen_ml || !gen_annot) then print_info cmt; end else begin @@ -101,3 +118,13 @@ let _ = Arg.usage arg_list arg_usage end ) arg_usage + + +let () = + try + main () + with x -> + Printf.eprintf "Exception in main ()\n%!"; + Location.report_exception Format.err_formatter x; + Format.fprintf Format.err_formatter "@."; + exit 2 |