1997-02-14 08:30:00 -08:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Objective Caml *)
|
|
|
|
(* *)
|
|
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
|
|
|
(* Copyright 1997 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the Q Public License version 1.0. *)
|
1997-02-14 08:30:00 -08:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(* $Id$ *)
|
|
|
|
|
|
|
|
(* Loading and installation of user-defined printer functions *)
|
|
|
|
|
|
|
|
open Misc
|
|
|
|
open Debugger_config
|
2001-07-03 04:04:10 -07:00
|
|
|
open Longident
|
1997-02-14 08:30:00 -08:00
|
|
|
open Path
|
|
|
|
open Types
|
|
|
|
|
|
|
|
(* Error report *)
|
|
|
|
|
|
|
|
type error =
|
2000-03-06 14:12:09 -08:00
|
|
|
| Load_failure of Dynlink.error
|
1997-02-14 08:30:00 -08:00
|
|
|
| Unbound_identifier of Longident.t
|
|
|
|
| Unavailable_module of string * Longident.t
|
|
|
|
| Wrong_type of Longident.t
|
|
|
|
| No_active_printer of Longident.t
|
|
|
|
|
|
|
|
exception Error of error
|
|
|
|
|
|
|
|
(* Symtable has global state, and normally holds the symbol table
|
|
|
|
for the debuggee. We need to switch it temporarily to the
|
|
|
|
symbol table for the debugger. *)
|
|
|
|
|
|
|
|
let debugger_symtable = ref (None: Symtable.global_map option)
|
|
|
|
|
|
|
|
let use_debugger_symtable fn arg =
|
|
|
|
let old_symtable = Symtable.current_state() in
|
|
|
|
begin match !debugger_symtable with
|
2000-03-06 14:12:09 -08:00
|
|
|
| None ->
|
1997-02-14 08:30:00 -08:00
|
|
|
Symtable.init_toplevel();
|
|
|
|
debugger_symtable := Some(Symtable.current_state())
|
|
|
|
| Some st ->
|
|
|
|
Symtable.restore_state st
|
|
|
|
end;
|
|
|
|
try
|
1997-02-19 08:09:23 -08:00
|
|
|
let result = fn arg in
|
1997-02-14 08:30:00 -08:00
|
|
|
debugger_symtable := Some(Symtable.current_state());
|
1997-02-19 08:09:23 -08:00
|
|
|
Symtable.restore_state old_symtable;
|
|
|
|
result
|
1997-02-14 08:30:00 -08:00
|
|
|
with exn ->
|
|
|
|
Symtable.restore_state old_symtable;
|
|
|
|
raise exn
|
|
|
|
|
|
|
|
(* Load a .cmo or .cma file *)
|
|
|
|
|
2000-03-06 14:12:09 -08:00
|
|
|
open Format
|
1997-05-12 02:57:13 -07:00
|
|
|
|
2000-03-06 14:12:09 -08:00
|
|
|
let rec loadfiles ppf name =
|
1997-05-12 02:57:13 -07:00
|
|
|
try
|
|
|
|
let filename = find_in_path !Config.load_path name in
|
|
|
|
use_debugger_symtable Dynlink.loadfile filename;
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf "File %s loaded@." filename;
|
1997-05-12 02:57:13 -07:00
|
|
|
true
|
|
|
|
with
|
2000-03-06 14:12:09 -08:00
|
|
|
| Dynlink.Error (Dynlink.Unavailable_unit unit) ->
|
2000-03-07 10:22:19 -08:00
|
|
|
loadfiles ppf (String.uncapitalize unit ^ ".cmo")
|
1997-05-12 02:57:13 -07:00
|
|
|
&&
|
2000-03-07 10:22:19 -08:00
|
|
|
loadfiles ppf name
|
1997-05-12 02:57:13 -07:00
|
|
|
| Not_found ->
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf "Cannot find file %s@." name;
|
1997-05-12 02:57:13 -07:00
|
|
|
false
|
|
|
|
| Dynlink.Error e ->
|
|
|
|
raise(Error(Load_failure e))
|
|
|
|
|
2000-03-07 10:22:19 -08:00
|
|
|
let loadfile ppf name =
|
1997-02-14 08:30:00 -08:00
|
|
|
if !debugger_symtable = None then begin
|
|
|
|
Dynlink.add_interfaces stdlib_units [Config.standard_library];
|
|
|
|
Dynlink.allow_unsafe_modules true
|
|
|
|
end;
|
2000-03-07 10:22:19 -08:00
|
|
|
ignore(loadfiles ppf name)
|
1997-02-14 08:30:00 -08:00
|
|
|
|
|
|
|
(* Return the value referred to by a path (as in toplevel/topdirs) *)
|
|
|
|
(* Note: evaluation proceeds in the debugger memory space, not in
|
|
|
|
the debuggee. *)
|
|
|
|
|
|
|
|
let rec eval_path = function
|
|
|
|
Pident id -> Symtable.get_global_value id
|
|
|
|
| Pdot(p, s, pos) -> Obj.field (eval_path p) pos
|
|
|
|
| Papply(p1, p2) -> fatal_error "Loadprinter.eval_path"
|
|
|
|
|
|
|
|
(* Install, remove a printer (as in toplevel/topdirs) *)
|
|
|
|
|
2001-07-03 04:04:10 -07:00
|
|
|
let match_printer_type desc typename =
|
|
|
|
let (printer_type, _) =
|
|
|
|
try
|
|
|
|
Env.lookup_type (Ldot(Lident "Topdirs", typename)) Env.empty
|
|
|
|
with Not_found ->
|
|
|
|
raise (Error(Unbound_identifier(Ldot(Lident "Topdirs", typename)))) in
|
|
|
|
Ctype.init_def(Ident.current_time());
|
|
|
|
Ctype.begin_def();
|
|
|
|
let ty_arg = Ctype.newvar() in
|
|
|
|
Ctype.unify Env.empty
|
|
|
|
(Ctype.newconstr printer_type [ty_arg])
|
|
|
|
(Ctype.instance desc.val_type);
|
|
|
|
Ctype.end_def();
|
|
|
|
Ctype.generalize ty_arg;
|
|
|
|
ty_arg
|
|
|
|
|
1997-02-14 08:30:00 -08:00
|
|
|
let find_printer_type lid =
|
|
|
|
try
|
|
|
|
let (path, desc) = Env.lookup_value lid Env.empty in
|
2001-07-03 04:04:10 -07:00
|
|
|
let (ty_arg, is_old_style) =
|
|
|
|
try
|
|
|
|
(match_printer_type desc "printer_type_new", false)
|
|
|
|
with Ctype.Unify _ ->
|
|
|
|
(match_printer_type desc "printer_type_old", true) in
|
|
|
|
(ty_arg, path, is_old_style)
|
1997-02-14 08:30:00 -08:00
|
|
|
with
|
2000-03-06 14:12:09 -08:00
|
|
|
| Not_found -> raise(Error(Unbound_identifier lid))
|
1997-02-14 08:30:00 -08:00
|
|
|
| Ctype.Unify _ -> raise(Error(Wrong_type lid))
|
|
|
|
|
2000-03-06 14:12:09 -08:00
|
|
|
let install_printer ppf lid =
|
2001-07-03 04:04:10 -07:00
|
|
|
let (ty_arg, path, is_old_style) = find_printer_type lid in
|
1997-02-14 08:30:00 -08:00
|
|
|
let v =
|
|
|
|
try
|
|
|
|
use_debugger_symtable eval_path path
|
|
|
|
with Symtable.Error(Symtable.Undefined_global s) ->
|
|
|
|
raise(Error(Unavailable_module(s, lid))) in
|
2001-07-03 04:04:10 -07:00
|
|
|
let print_function =
|
|
|
|
if is_old_style then
|
|
|
|
(fun formatter repr -> (Obj.obj v) (Obj.obj repr))
|
|
|
|
else
|
|
|
|
(fun formatter repr -> (Obj.obj v) formatter (Obj.obj repr)) in
|
|
|
|
Printval.install_printer path ty_arg ppf print_function
|
1997-02-14 08:30:00 -08:00
|
|
|
|
|
|
|
let remove_printer lid =
|
2001-07-03 04:04:10 -07:00
|
|
|
let (ty_arg, path, is_old_style) = find_printer_type lid in
|
1997-02-14 08:30:00 -08:00
|
|
|
try
|
|
|
|
Printval.remove_printer path
|
|
|
|
with Not_found ->
|
|
|
|
raise(Error(No_active_printer lid))
|
|
|
|
|
|
|
|
(* Error report *)
|
|
|
|
|
2000-03-06 14:12:09 -08:00
|
|
|
open Format
|
1997-02-14 08:30:00 -08:00
|
|
|
|
2000-03-06 14:12:09 -08:00
|
|
|
let report_error ppf = function
|
|
|
|
| Load_failure e ->
|
|
|
|
fprintf ppf "@[Error during code loading: %s@]@."
|
|
|
|
(Dynlink.error_message e)
|
1997-02-14 08:30:00 -08:00
|
|
|
| Unbound_identifier lid ->
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf "@[Unbound identifier %a@]@."
|
1997-02-14 08:30:00 -08:00
|
|
|
Printtyp.longident lid
|
|
|
|
| Unavailable_module(md, lid) ->
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf
|
|
|
|
"@[The debugger does not contain the code for@ %a.@ \
|
|
|
|
Please load an implementation of %s first.@]@."
|
|
|
|
Printtyp.longident lid md
|
1997-02-14 08:30:00 -08:00
|
|
|
| Wrong_type lid ->
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf "@[%a has the wrong type for a printing function.@]@."
|
|
|
|
Printtyp.longident lid
|
1997-02-14 08:30:00 -08:00
|
|
|
| No_active_printer lid ->
|
2000-03-06 14:12:09 -08:00
|
|
|
fprintf ppf "@[%a is not currently active as a printing function.@]@."
|
|
|
|
Printtyp.longident lid
|
1997-02-14 08:30:00 -08:00
|
|
|
|
|
|
|
|