1 (***********************************************************************)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 1997 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
11 (***********************************************************************)
13 (* $Id: loadprinter.ml 9226 2009-04-02 09:44:21Z xclerc $ *)
15 (* Loading and installation of user-defined printer functions *)
25 | Load_failure of Dynlink.error
26 | Unbound_identifier of Longident.t
27 | Unavailable_module of string * Longident.t
28 | Wrong_type of Longident.t
29 | No_active_printer of Longident.t
31 exception Error of error
33 (* Symtable has global state, and normally holds the symbol table
34 for the debuggee. We need to switch it temporarily to the
35 symbol table for the debugger. *)
37 let debugger_symtable = ref (None: Symtable.global_map option)
39 let use_debugger_symtable fn arg =
40 let old_symtable = Symtable.current_state() in
41 begin match !debugger_symtable with
44 Dynlink.allow_unsafe_modules true;
45 debugger_symtable := Some(Symtable.current_state())
47 Symtable.restore_state st
50 let result = fn arg in
51 debugger_symtable := Some(Symtable.current_state());
52 Symtable.restore_state old_symtable;
55 Symtable.restore_state old_symtable;
58 (* Load a .cmo or .cma file *)
62 let rec loadfiles ppf name =
64 let filename = find_in_path !Config.load_path name in
65 use_debugger_symtable Dynlink.loadfile filename;
66 let d = Filename.dirname name in
67 if d <> Filename.current_dir_name then begin
68 if not (List.mem d !Config.load_path) then
69 Config.load_path := d :: !Config.load_path;
71 fprintf ppf "File %s loaded@." filename;
74 | Dynlink.Error (Dynlink.Unavailable_unit unit) ->
75 loadfiles ppf (String.uncapitalize unit ^ ".cmo")
79 fprintf ppf "Cannot find file %s@." name;
82 raise(Error(Load_failure e))
84 let loadfile ppf name =
85 ignore(loadfiles ppf name)
87 (* Return the value referred to by a path (as in toplevel/topdirs) *)
88 (* Note: evaluation proceeds in the debugger memory space, not in
91 let rec eval_path = function
92 Pident id -> Symtable.get_global_value id
93 | Pdot(p, s, pos) -> Obj.field (eval_path p) pos
94 | Papply(p1, p2) -> fatal_error "Loadprinter.eval_path"
96 (* Install, remove a printer (as in toplevel/topdirs) *)
98 let match_printer_type desc typename =
99 let (printer_type, _) =
101 Env.lookup_type (Ldot(Lident "Topdirs", typename)) Env.empty
103 raise (Error(Unbound_identifier(Ldot(Lident "Topdirs", typename)))) in
104 Ctype.init_def(Ident.current_time());
106 let ty_arg = Ctype.newvar() in
107 Ctype.unify Env.empty
108 (Ctype.newconstr printer_type [ty_arg])
109 (Ctype.instance desc.val_type);
111 Ctype.generalize ty_arg;
114 let find_printer_type lid =
116 let (path, desc) = Env.lookup_value lid Env.empty in
117 let (ty_arg, is_old_style) =
119 (match_printer_type desc "printer_type_new", false)
120 with Ctype.Unify _ ->
121 (match_printer_type desc "printer_type_old", true) in
122 (ty_arg, path, is_old_style)
124 | Not_found -> raise(Error(Unbound_identifier lid))
125 | Ctype.Unify _ -> raise(Error(Wrong_type lid))
127 let install_printer ppf lid =
128 let (ty_arg, path, is_old_style) = find_printer_type lid in
131 use_debugger_symtable eval_path path
132 with Symtable.Error(Symtable.Undefined_global s) ->
133 raise(Error(Unavailable_module(s, lid))) in
136 (fun formatter repr -> Obj.obj v (Obj.obj repr))
138 (fun formatter repr -> Obj.obj v formatter (Obj.obj repr)) in
139 Printval.install_printer path ty_arg ppf print_function
141 let remove_printer lid =
142 let (ty_arg, path, is_old_style) = find_printer_type lid in
144 Printval.remove_printer path
146 raise(Error(No_active_printer lid))
152 let report_error ppf = function
154 fprintf ppf "@[Error during code loading: %s@]@."
155 (Dynlink.error_message e)
156 | Unbound_identifier lid ->
157 fprintf ppf "@[Unbound identifier %a@]@."
158 Printtyp.longident lid
159 | Unavailable_module(md, lid) ->
161 "@[The debugger does not contain the code for@ %a.@ \
162 Please load an implementation of %s first.@]@."
163 Printtyp.longident lid md
165 fprintf ppf "@[%a has the wrong type for a printing function.@]@."
166 Printtyp.longident lid
167 | No_active_printer lid ->
168 fprintf ppf "@[%a is not currently active as a printing function.@]@."
169 Printtyp.longident lid