1996-11-29 08:55:09 -08:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
2011-07-27 07:17:02 -07:00
|
|
|
(* OCaml *)
|
1996-11-29 08:55:09 -08:00
|
|
|
(* *)
|
|
|
|
(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *)
|
2011-07-27 07:17:02 -07:00
|
|
|
(* OCaml port by John Malecki and Xavier Leroy *)
|
1996-11-29 08:55:09 -08:00
|
|
|
(* *)
|
|
|
|
(* Copyright 1996 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. *)
|
1996-11-29 08:55:09 -08:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
open Input_handling
|
2006-12-09 05:49:10 -08:00
|
|
|
open Question
|
1997-05-08 11:00:18 -07:00
|
|
|
open Command_line
|
1996-11-29 08:55:09 -08:00
|
|
|
open Debugger_config
|
|
|
|
open Checkpoints
|
|
|
|
open Time_travel
|
|
|
|
open Parameters
|
|
|
|
open Program_management
|
|
|
|
open Frames
|
|
|
|
open Show_information
|
2000-03-21 07:16:28 -08:00
|
|
|
open Format
|
2010-01-20 08:26:46 -08:00
|
|
|
open Primitives
|
1996-11-29 08:55:09 -08:00
|
|
|
|
1997-03-22 15:28:07 -08:00
|
|
|
let line_buffer = Lexing.from_function read_user_input
|
|
|
|
|
2013-12-19 06:23:49 -08:00
|
|
|
let rec loop ppf = line_loop ppf line_buffer
|
1997-03-22 15:28:07 -08:00
|
|
|
|
2006-11-20 02:29:45 -08:00
|
|
|
let current_duration = ref (-1L)
|
|
|
|
|
|
|
|
let rec protect ppf restart loop =
|
1997-03-22 15:28:07 -08:00
|
|
|
try
|
2002-11-02 14:36:46 -08:00
|
|
|
loop ppf
|
1997-03-22 15:28:07 -08:00
|
|
|
with
|
2000-03-07 10:22:19 -08:00
|
|
|
| End_of_file ->
|
2006-11-20 02:29:45 -08:00
|
|
|
protect ppf restart (function ppf ->
|
1997-03-22 15:28:07 -08:00
|
|
|
forget_process
|
|
|
|
!current_checkpoint.c_fd
|
|
|
|
!current_checkpoint.c_pid;
|
2000-03-21 07:16:28 -08:00
|
|
|
pp_print_flush ppf ();
|
1997-03-22 15:28:07 -08:00
|
|
|
stop_user_input ();
|
2009-05-20 04:52:42 -07:00
|
|
|
restart ppf)
|
1997-03-22 15:28:07 -08:00
|
|
|
| Toplevel ->
|
2006-11-20 02:29:45 -08:00
|
|
|
protect ppf restart (function ppf ->
|
2000-03-21 07:16:28 -08:00
|
|
|
pp_print_flush ppf ();
|
1997-03-22 15:28:07 -08:00
|
|
|
stop_user_input ();
|
2009-05-20 04:52:42 -07:00
|
|
|
restart ppf)
|
1997-03-22 15:28:07 -08:00
|
|
|
| Sys.Break ->
|
2006-11-20 02:29:45 -08:00
|
|
|
protect ppf restart (function ppf ->
|
2000-03-21 07:16:28 -08:00
|
|
|
fprintf ppf "Interrupted.@.";
|
1997-11-13 01:04:16 -08:00
|
|
|
Exec.protect (function () ->
|
1996-11-29 08:55:09 -08:00
|
|
|
stop_user_input ();
|
1997-03-22 15:28:07 -08:00
|
|
|
if !loaded then begin
|
|
|
|
try_select_frame 0;
|
2000-03-07 10:22:19 -08:00
|
|
|
show_current_event ppf;
|
1997-03-22 15:28:07 -08:00
|
|
|
end);
|
2009-05-20 04:52:42 -07:00
|
|
|
restart ppf)
|
1997-03-22 15:28:07 -08:00
|
|
|
| Current_checkpoint_lost ->
|
2006-11-20 02:29:45 -08:00
|
|
|
protect ppf restart (function ppf ->
|
2000-03-21 07:16:28 -08:00
|
|
|
fprintf ppf "Trying to recover...@.";
|
1997-03-22 15:28:07 -08:00
|
|
|
stop_user_input ();
|
|
|
|
recover ();
|
|
|
|
try_select_frame 0;
|
2000-03-07 10:22:19 -08:00
|
|
|
show_current_event ppf;
|
2009-05-20 04:52:42 -07:00
|
|
|
restart ppf)
|
2006-11-20 02:29:45 -08:00
|
|
|
| Current_checkpoint_lost_start_at (time, init_duration) ->
|
|
|
|
protect ppf restart (function ppf ->
|
|
|
|
let b =
|
|
|
|
if !current_duration = -1L then begin
|
2013-03-09 14:38:52 -08:00
|
|
|
let msg = sprintf "Restart from time %Ld and try to get \
|
|
|
|
closer of the problem" time in
|
2006-11-20 02:29:45 -08:00
|
|
|
stop_user_input ();
|
|
|
|
if yes_or_no msg then
|
|
|
|
(current_duration := init_duration; true)
|
|
|
|
else
|
|
|
|
false
|
|
|
|
end
|
|
|
|
else
|
|
|
|
true in
|
|
|
|
if b then
|
|
|
|
begin
|
|
|
|
go_to time;
|
|
|
|
current_duration := Int64.div !current_duration 10L;
|
|
|
|
if !current_duration > 0L then
|
|
|
|
while true do
|
|
|
|
step !current_duration
|
|
|
|
done
|
|
|
|
else begin
|
|
|
|
current_duration := -1L;
|
|
|
|
stop_user_input ();
|
|
|
|
show_current_event ppf;
|
|
|
|
restart ppf;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
recover ();
|
|
|
|
show_current_event ppf;
|
2006-12-09 05:49:10 -08:00
|
|
|
restart ppf
|
2006-11-20 02:29:45 -08:00
|
|
|
end)
|
1997-03-22 15:28:07 -08:00
|
|
|
| x ->
|
|
|
|
kill_program ();
|
|
|
|
raise x
|
|
|
|
|
2010-01-20 08:26:46 -08:00
|
|
|
let execute_file_if_any () =
|
|
|
|
let buffer = Buffer.create 128 in
|
|
|
|
begin
|
|
|
|
try
|
|
|
|
let base = ".ocamldebug" in
|
|
|
|
let file =
|
|
|
|
if Sys.file_exists base then
|
|
|
|
base
|
|
|
|
else
|
|
|
|
Filename.concat (Sys.getenv "HOME") base in
|
|
|
|
let ch = open_in file in
|
|
|
|
fprintf Format.std_formatter "Executing file %s@." file;
|
|
|
|
while true do
|
|
|
|
let line = string_trim (input_line ch) in
|
|
|
|
if line <> "" && line.[0] <> '#' then begin
|
|
|
|
Buffer.add_string buffer line;
|
|
|
|
Buffer.add_char buffer '\n'
|
|
|
|
end
|
|
|
|
done;
|
|
|
|
with _ -> ()
|
|
|
|
end;
|
|
|
|
let len = Buffer.length buffer in
|
|
|
|
if len > 0 then
|
|
|
|
let commands = Buffer.sub buffer 0 (pred len) in
|
|
|
|
line_loop Format.std_formatter (Lexing.from_string commands)
|
|
|
|
|
|
|
|
let toplevel_loop () =
|
|
|
|
interactif := false;
|
|
|
|
current_prompt := "";
|
|
|
|
execute_file_if_any ();
|
|
|
|
interactif := true;
|
|
|
|
current_prompt := debugger_prompt;
|
|
|
|
protect Format.std_formatter loop loop
|
1996-11-29 08:55:09 -08:00
|
|
|
|
1997-06-13 08:50:32 -07:00
|
|
|
(* Parsing of command-line arguments *)
|
|
|
|
|
|
|
|
exception Found_program_name
|
|
|
|
|
1996-11-29 08:55:09 -08:00
|
|
|
let anonymous s =
|
2002-11-02 14:36:46 -08:00
|
|
|
program_name := Unix_tools.make_absolute s; raise Found_program_name
|
1996-11-29 08:55:09 -08:00
|
|
|
let add_include d =
|
2002-05-07 04:26:20 -07:00
|
|
|
default_load_path :=
|
|
|
|
Misc.expand_directory Config.standard_library d :: !default_load_path
|
1996-11-29 08:55:09 -08:00
|
|
|
let set_socket s =
|
|
|
|
socket_name := s
|
|
|
|
let set_checkpoints n =
|
|
|
|
checkpoint_max_count := n
|
|
|
|
let set_directory dir =
|
|
|
|
Sys.chdir dir
|
2004-11-26 17:04:19 -08:00
|
|
|
let print_version () =
|
2011-04-26 05:16:50 -07:00
|
|
|
printf "The OCaml debugger, version %s@." Sys.ocaml_version;
|
2004-11-26 17:04:19 -08:00
|
|
|
exit 0;
|
|
|
|
;;
|
2010-05-20 07:06:29 -07:00
|
|
|
let print_version_num () =
|
|
|
|
printf "%s@." Sys.ocaml_version;
|
|
|
|
exit 0;
|
|
|
|
;;
|
1996-11-29 08:55:09 -08:00
|
|
|
|
2004-11-26 17:04:19 -08:00
|
|
|
let speclist = [
|
1997-06-13 08:50:32 -07:00
|
|
|
"-c", Arg.Int set_checkpoints,
|
|
|
|
"<count> Set max number of checkpoints kept";
|
|
|
|
"-cd", Arg.String set_directory,
|
|
|
|
"<dir> Change working directory";
|
2014-01-23 01:07:09 -08:00
|
|
|
"-emacs", Arg.Tuple [Arg.Set emacs; Arg.Set machine_readable],
|
|
|
|
"For running the debugger under emacs; implies -machine-readable";
|
2004-11-26 17:04:19 -08:00
|
|
|
"-I", Arg.String add_include,
|
|
|
|
"<dir> Add <dir> to the list of include directories";
|
2014-01-23 01:07:09 -08:00
|
|
|
"-machine-readable", Arg.Set machine_readable,
|
|
|
|
"Print information in a format more suitable for machines";
|
2004-11-26 17:04:19 -08:00
|
|
|
"-s", Arg.String set_socket,
|
|
|
|
"<filename> Set the name of the communication socket";
|
|
|
|
"-version", Arg.Unit print_version,
|
|
|
|
" Print version and exit";
|
2010-05-20 07:06:29 -07:00
|
|
|
"-vnum", Arg.Unit print_version_num,
|
|
|
|
" Print version number and exit";
|
2004-11-26 17:04:19 -08:00
|
|
|
]
|
1997-06-13 08:50:32 -07:00
|
|
|
|
2012-03-08 11:52:03 -08:00
|
|
|
let function_placeholder () =
|
|
|
|
raise Not_found
|
|
|
|
|
1996-11-29 08:55:09 -08:00
|
|
|
let main () =
|
2012-03-08 11:52:03 -08:00
|
|
|
Callback.register "Debugger.function_placeholder" function_placeholder;
|
1996-11-29 08:55:09 -08:00
|
|
|
try
|
2010-01-22 04:48:24 -08:00
|
|
|
socket_name :=
|
2008-07-29 01:31:41 -07:00
|
|
|
(match Sys.os_type with
|
2010-01-22 04:48:24 -08:00
|
|
|
"Win32" ->
|
2008-07-29 01:31:41 -07:00
|
|
|
(Unix.string_of_inet_addr Unix.inet_addr_loopback)^
|
|
|
|
":"^
|
|
|
|
(string_of_int (10000 + ((Unix.getpid ()) mod 10000)))
|
|
|
|
| _ -> Filename.concat Filename.temp_dir_name
|
|
|
|
("camldebug" ^ (string_of_int (Unix.getpid ())))
|
|
|
|
);
|
1997-06-13 08:50:32 -07:00
|
|
|
begin try
|
|
|
|
Arg.parse speclist anonymous "";
|
|
|
|
Arg.usage speclist
|
|
|
|
"No program name specified\n\
|
|
|
|
Usage: ocamldebug [options] <program> [arguments]\n\
|
|
|
|
Options are:";
|
|
|
|
exit 2
|
|
|
|
with Found_program_name ->
|
1997-07-03 07:31:28 -07:00
|
|
|
for j = !Arg.current + 1 to Array.length Sys.argv - 1 do
|
2002-11-02 14:36:46 -08:00
|
|
|
arguments := !arguments ^ " " ^ (Filename.quote Sys.argv.(j))
|
1997-06-13 08:50:32 -07:00
|
|
|
done
|
|
|
|
end;
|
2011-04-26 05:16:50 -07:00
|
|
|
printf "\tOCaml Debugger version %s@.@." Config.version;
|
1996-11-29 08:55:09 -08:00
|
|
|
Config.load_path := !default_load_path;
|
2008-01-11 08:13:18 -08:00
|
|
|
Clflags.recursive_types := true; (* Allow recursive types. *)
|
1997-03-22 15:28:07 -08:00
|
|
|
toplevel_loop (); (* Toplevel. *)
|
1996-11-29 08:55:09 -08:00
|
|
|
kill_program ();
|
|
|
|
exit 0
|
2006-01-04 08:55:50 -08:00
|
|
|
with
|
2003-12-04 02:44:35 -08:00
|
|
|
Toplevel ->
|
|
|
|
exit 2
|
2006-01-04 08:55:50 -08:00
|
|
|
| Env.Error e ->
|
2003-12-04 04:32:04 -08:00
|
|
|
eprintf "Debugger [version %s] environment error:@ @[@;" Config.version;
|
2003-12-04 02:44:35 -08:00
|
|
|
Env.report_error err_formatter e;
|
|
|
|
eprintf "@]@.";
|
|
|
|
exit 2
|
2012-05-30 07:52:37 -07:00
|
|
|
| Cmi_format.Error e ->
|
|
|
|
eprintf "Debugger [version %s] environment error:@ @[@;" Config.version;
|
|
|
|
Cmi_format.report_error err_formatter e;
|
|
|
|
eprintf "@]@.";
|
|
|
|
exit 2
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
let _ =
|
|
|
|
Printexc.catch (Unix.handle_unix_error main) ()
|