summaryrefslogtreecommitdiff
path: root/debugger/main.ml
blob: 9cfcf447ffeb48cae884f85bc66b100b0b10b119 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*          Jerome Vouillon, projet Cristal, INRIA Rocquencourt        *)
(*          Objective Caml port by John Malecki and Xavier Leroy       *)
(*                                                                     *)
(*  Copyright 1996 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  under the terms of the Q Public License version 1.0.               *)
(*                                                                     *)
(***********************************************************************)

(* $Id$ *)

open Input_handling
open Question
open Command_line
open Debugger_config
open Checkpoints
open Time_travel
open Parameters
open Program_management
open Frames
open Show_information
open Format

let line_buffer = Lexing.from_function read_user_input

let rec loop ppf =
  line_loop ppf line_buffer;
  if !loaded && (not (yes_or_no "The program is running. Quit anyway")) then
    loop ppf

let current_duration = ref (-1L)

let rec protect ppf restart loop =
  try
    loop ppf
  with
  | End_of_file ->
      protect ppf restart (function ppf ->
        forget_process
          !current_checkpoint.c_fd
          !current_checkpoint.c_pid;
        pp_print_flush ppf ();
        stop_user_input ();
        restart ppf)
  | Toplevel ->
      protect ppf restart (function ppf ->
        pp_print_flush ppf ();
        stop_user_input ();
        restart ppf)
  | Sys.Break ->
      protect ppf restart (function ppf ->
        fprintf ppf "Interrupted.@.";
        Exec.protect (function () ->
          stop_user_input ();
          if !loaded then begin
            try_select_frame 0;
            show_current_event ppf;
          end);
        restart ppf)
  | Current_checkpoint_lost ->
      protect ppf restart (function ppf ->
        fprintf ppf "Trying to recover...@.";
        stop_user_input ();
        recover ();
        try_select_frame 0;
        show_current_event ppf;
        restart ppf)
  | Current_checkpoint_lost_start_at (time, init_duration) ->
      protect ppf restart (function ppf ->
        let b =
          if !current_duration = -1L then begin
            let msg = sprintf "Restart from time %Ld and try to get closer of the problem" time in
            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;
            restart ppf
          end)
  | x ->
      kill_program ();
      raise x

let toplevel_loop () = protect Format.std_formatter loop loop

(* Parsing of command-line arguments *)

exception Found_program_name

let anonymous s =
  program_name := Unix_tools.make_absolute s; raise Found_program_name
let add_include d =
  default_load_path :=
    Misc.expand_directory Config.standard_library d :: !default_load_path
let set_socket s =
  socket_name := s
let set_checkpoints n =
  checkpoint_max_count := n
let set_directory dir =
  Sys.chdir dir
let print_version () =
  printf "The Objective Caml debugger, version %s@." Sys.ocaml_version;
  exit 0;
;;

let speclist = [
   "-c", Arg.Int set_checkpoints,
      "<count>  Set max number of checkpoints kept";
   "-cd", Arg.String set_directory,
      "<dir>  Change working directory";
   "-emacs", Arg.Set emacs,
      "For running the debugger under emacs";
   "-I", Arg.String add_include,
      "<dir>  Add <dir> to the list of include directories";
   "-s", Arg.String set_socket,
      "<filename>  Set the name of the communication socket";
   "-version", Arg.Unit print_version,
      " Print version and exit";
   ]

let main () =
  try
    socket_name := 
      (match Sys.os_type with
        "Win32" -> 
          (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 ())))
      );
    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 ->
      for j = !Arg.current + 1 to Array.length Sys.argv - 1 do
        arguments := !arguments ^ " " ^ (Filename.quote Sys.argv.(j))
      done
    end;
    current_prompt := debugger_prompt;
    printf "\tObjective Caml Debugger version %s@.@." Config.version;
    Config.load_path := !default_load_path;
    Clflags.recursive_types := true;    (* Allow recursive types. *)
    toplevel_loop ();                   (* Toplevel. *)
    kill_program ();
    exit 0
  with
    Toplevel ->
      exit 2
  | Env.Error e ->
      eprintf "Debugger [version %s] environment error:@ @[@;" Config.version;
      Env.report_error err_formatter e;
      eprintf "@]@.";
      exit 2

let _ =
  Printexc.catch (Unix.handle_unix_error main) ()