summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debugger/.depend158
-rw-r--r--debugger/Makefile95
-rw-r--r--debugger/breakpoints.ml212
-rw-r--r--debugger/breakpoints.mli60
-rw-r--r--debugger/checkpoints.ml78
-rw-r--r--debugger/checkpoints.mli56
-rw-r--r--debugger/command_line_interpreter.ml1052
-rw-r--r--debugger/command_line_interpreter.mli20
-rw-r--r--debugger/debugcom.ml240
-rw-r--r--debugger/debugcom.mli90
-rw-r--r--debugger/debugger_config.ml72
-rw-r--r--debugger/debugger_config.mli33
-rw-r--r--debugger/envaux.ml62
-rw-r--r--debugger/envaux.mli21
-rw-r--r--debugger/eval.ml48
-rw-r--r--debugger/eval.mli15
-rw-r--r--debugger/events.ml113
-rw-r--r--debugger/events.mli43
-rw-r--r--debugger/exec.ml49
-rw-r--r--debugger/exec.mli18
-rw-r--r--debugger/frames.ml127
-rw-r--r--debugger/frames.mli54
-rw-r--r--debugger/history.ml42
-rw-r--r--debugger/history.mli19
-rw-r--r--debugger/input_handling.ml145
-rw-r--r--debugger/input_handling.mli62
-rw-r--r--debugger/lexer.ml747
-rw-r--r--debugger/main.ml133
-rw-r--r--debugger/parameters.ml33
-rw-r--r--debugger/parameters.mli25
-rw-r--r--debugger/parser.ml405
-rw-r--r--debugger/parser.mli57
-rw-r--r--debugger/parser_aux.mli37
-rw-r--r--debugger/pattern_matching.ml250
-rw-r--r--debugger/pattern_matching.mli20
-rw-r--r--debugger/primitives.ml194
-rw-r--r--debugger/primitives.mli85
-rw-r--r--debugger/printval.ml279
-rw-r--r--debugger/printval.mli18
-rw-r--r--debugger/program_loading.ml111
-rw-r--r--debugger/program_loading.mli33
-rw-r--r--debugger/program_management.ml154
-rw-r--r--debugger/program_management.mli26
-rw-r--r--debugger/show_information.ml107
-rw-r--r--debugger/show_information.mli23
-rw-r--r--debugger/show_source.ml80
-rw-r--r--debugger/show_source.mli22
-rw-r--r--debugger/source.ml152
-rw-r--r--debugger/source.mli57
-rw-r--r--debugger/symbols.ml111
-rw-r--r--debugger/symbols.mli26
-rw-r--r--debugger/time_travel.ml553
-rw-r--r--debugger/time_travel.mli33
-rw-r--r--debugger/trap_barrier.ml46
-rw-r--r--debugger/trap_barrier.mli26
-rw-r--r--debugger/unix_tools.ml139
-rw-r--r--debugger/unix_tools.mli31
57 files changed, 6997 insertions, 0 deletions
diff --git a/debugger/.depend b/debugger/.depend
new file mode 100644
index 000000000..1ecb39b0a
--- /dev/null
+++ b/debugger/.depend
@@ -0,0 +1,158 @@
+breakpoints.cmi: ../bytecomp/instruct.cmi primitives.cmi
+checkpoints.cmi: debugcom.cmi primitives.cmi
+debugcom.cmi: primitives.cmi
+envaux.cmi: ../typing/env.cmi
+eval.cmi: debugcom.cmi ../bytecomp/instruct.cmi ../typing/path.cmi
+events.cmi: ../bytecomp/instruct.cmi
+frames.cmi: ../bytecomp/instruct.cmi primitives.cmi
+input_handling.cmi: primitives.cmi
+parser.cmi: parser_aux.cmi
+parser_aux.cmi: primitives.cmi
+pattern_matching.cmi: debugcom.cmi parser_aux.cmi ../typing/typedtree.cmi
+primitives.cmi: ../otherlibs/unix/unix.cmi
+printval.cmi: debugcom.cmi ../typing/env.cmi ../typing/types.cmi
+program_loading.cmi: primitives.cmi
+show_information.cmi: ../bytecomp/instruct.cmi
+symbols.cmi: ../bytecomp/instruct.cmi
+time_travel.cmi: primitives.cmi
+unix_tools.cmi: ../otherlibs/unix/unix.cmi
+breakpoints.cmo: checkpoints.cmi debugcom.cmi exec.cmi \
+ ../bytecomp/instruct.cmi primitives.cmi source.cmi breakpoints.cmi
+breakpoints.cmx: checkpoints.cmx debugcom.cmx exec.cmx \
+ ../bytecomp/instruct.cmx primitives.cmx source.cmx breakpoints.cmi
+checkpoints.cmo: debugcom.cmi primitives.cmi checkpoints.cmi
+checkpoints.cmx: debugcom.cmx primitives.cmx checkpoints.cmi
+command_line_interpreter.cmo: breakpoints.cmi checkpoints.cmi \
+ ../utils/config.cmi ../typing/ctype.cmi debugcom.cmi debugger_config.cmi \
+ ../typing/env.cmi envaux.cmi eval.cmi events.cmi frames.cmi history.cmi \
+ input_handling.cmi ../bytecomp/instruct.cmi ../parsing/lexer.cmi \
+ ../parsing/longident.cmi ../utils/misc.cmi parameters.cmi parser.cmi \
+ parser_aux.cmi primitives.cmi ../typing/printtyp.cmi printval.cmi \
+ program_loading.cmi program_management.cmi show_information.cmi \
+ show_source.cmi source.cmi symbols.cmi time_travel.cmi \
+ ../typing/types.cmi ../otherlibs/unix/unix.cmi unix_tools.cmi \
+ command_line_interpreter.cmi
+command_line_interpreter.cmx: breakpoints.cmx checkpoints.cmx \
+ ../utils/config.cmx ../typing/ctype.cmx debugcom.cmx debugger_config.cmx \
+ ../typing/env.cmx envaux.cmx eval.cmx events.cmx frames.cmx history.cmx \
+ input_handling.cmx ../bytecomp/instruct.cmx ../parsing/lexer.cmx \
+ ../parsing/longident.cmx ../utils/misc.cmx parameters.cmx parser.cmx \
+ parser_aux.cmi primitives.cmx ../typing/printtyp.cmx printval.cmx \
+ program_loading.cmx program_management.cmx show_information.cmx \
+ show_source.cmx source.cmx symbols.cmx time_travel.cmx \
+ ../typing/types.cmx ../otherlibs/unix/unix.cmx unix_tools.cmx \
+ command_line_interpreter.cmi
+debugcom.cmo: ../utils/misc.cmi primitives.cmi debugcom.cmi
+debugcom.cmx: ../utils/misc.cmx primitives.cmx debugcom.cmi
+debugger_config.cmo: debugger_config.cmi
+debugger_config.cmx: debugger_config.cmi
+envaux.cmo: ../typing/env.cmi ../utils/misc.cmi ../typing/mtype.cmi \
+ ../typing/types.cmi envaux.cmi
+envaux.cmx: ../typing/env.cmx ../utils/misc.cmx ../typing/mtype.cmx \
+ ../typing/types.cmx envaux.cmi
+eval.cmo: debugcom.cmi debugger_config.cmi ../typing/ident.cmi \
+ ../bytecomp/instruct.cmi ../utils/misc.cmi ../typing/path.cmi \
+ ../typing/printtyp.cmi ../bytecomp/symtable.cmi eval.cmi
+eval.cmx: debugcom.cmx debugger_config.cmx ../typing/ident.cmx \
+ ../bytecomp/instruct.cmx ../utils/misc.cmx ../typing/path.cmx \
+ ../typing/printtyp.cmx ../bytecomp/symtable.cmx eval.cmi
+events.cmo: checkpoints.cmi ../bytecomp/instruct.cmi primitives.cmi \
+ symbols.cmi events.cmi
+events.cmx: checkpoints.cmx ../bytecomp/instruct.cmx primitives.cmx \
+ symbols.cmx events.cmi
+exec.cmo: exec.cmi
+exec.cmx: exec.cmi
+frames.cmo: checkpoints.cmi debugcom.cmi events.cmi ../bytecomp/instruct.cmi \
+ ../utils/misc.cmi primitives.cmi symbols.cmi frames.cmi
+frames.cmx: checkpoints.cmx debugcom.cmx events.cmx ../bytecomp/instruct.cmx \
+ ../utils/misc.cmx primitives.cmx symbols.cmx frames.cmi
+history.cmo: checkpoints.cmi debugger_config.cmi ../utils/misc.cmi \
+ primitives.cmi history.cmi
+history.cmx: checkpoints.cmx debugger_config.cmx ../utils/misc.cmx \
+ primitives.cmx history.cmi
+input_handling.cmo: ../parsing/lexer.cmi primitives.cmi \
+ ../otherlibs/unix/unix.cmi input_handling.cmi
+input_handling.cmx: ../parsing/lexer.cmx primitives.cmx \
+ ../otherlibs/unix/unix.cmx input_handling.cmi
+lexer.cmo: parser.cmi primitives.cmi
+lexer.cmx: parser.cmx primitives.cmx
+main.cmo: checkpoints.cmi command_line_interpreter.cmi ../utils/config.cmi \
+ debugger_config.cmi exec.cmi frames.cmi input_handling.cmi \
+ ../utils/misc.cmi parameters.cmi primitives.cmi program_management.cmi \
+ show_information.cmi time_travel.cmi ../otherlibs/unix/unix.cmi
+main.cmx: checkpoints.cmx command_line_interpreter.cmx ../utils/config.cmx \
+ debugger_config.cmx exec.cmx frames.cmx input_handling.cmx \
+ ../utils/misc.cmx parameters.cmx primitives.cmx program_management.cmx \
+ show_information.cmx time_travel.cmx ../otherlibs/unix/unix.cmx
+parameters.cmo: ../utils/config.cmi envaux.cmi ../utils/misc.cmi \
+ primitives.cmi parameters.cmi
+parameters.cmx: ../utils/config.cmx envaux.cmx ../utils/misc.cmx \
+ primitives.cmx parameters.cmi
+parser.cmo: input_handling.cmi parser_aux.cmi primitives.cmi parser.cmi
+parser.cmx: input_handling.cmx parser_aux.cmi primitives.cmx parser.cmi
+pattern_matching.cmo: ../typing/ctype.cmi debugcom.cmi debugger_config.cmi \
+ ../utils/misc.cmi parser_aux.cmi ../typing/typedtree.cmi \
+ pattern_matching.cmi
+pattern_matching.cmx: ../typing/ctype.cmx debugcom.cmx debugger_config.cmx \
+ ../utils/misc.cmx parser_aux.cmi ../typing/typedtree.cmx \
+ pattern_matching.cmi
+primitives.cmo: ../otherlibs/unix/unix.cmi primitives.cmi
+primitives.cmx: ../otherlibs/unix/unix.cmx primitives.cmi
+printval.cmo: ../typing/ctype.cmi debugcom.cmi ../typing/env.cmi \
+ ../typing/ident.cmi ../parsing/longident.cmi ../utils/misc.cmi \
+ ../typing/path.cmi ../typing/predef.cmi ../typing/printtyp.cmi \
+ ../typing/types.cmi printval.cmi
+printval.cmx: ../typing/ctype.cmx debugcom.cmx ../typing/env.cmx \
+ ../typing/ident.cmx ../parsing/longident.cmx ../utils/misc.cmx \
+ ../typing/path.cmx ../typing/predef.cmx ../typing/printtyp.cmx \
+ ../typing/types.cmx printval.cmi
+program_loading.cmo: debugger_config.cmi input_handling.cmi ../utils/misc.cmi \
+ parameters.cmi primitives.cmi ../otherlibs/unix/unix.cmi unix_tools.cmi \
+ program_loading.cmi
+program_loading.cmx: debugger_config.cmx input_handling.cmx ../utils/misc.cmx \
+ parameters.cmx primitives.cmx ../otherlibs/unix/unix.cmx unix_tools.cmx \
+ program_loading.cmi
+program_management.cmo: debugcom.cmi debugger_config.cmi history.cmi \
+ input_handling.cmi ../bytecomp/instruct.cmi ../utils/misc.cmi \
+ parameters.cmi primitives.cmi program_loading.cmi symbols.cmi \
+ time_travel.cmi ../otherlibs/unix/unix.cmi unix_tools.cmi \
+ program_management.cmi
+program_management.cmx: debugcom.cmx debugger_config.cmx history.cmx \
+ input_handling.cmx ../bytecomp/instruct.cmx ../utils/misc.cmx \
+ parameters.cmx primitives.cmx program_loading.cmx symbols.cmx \
+ time_travel.cmx ../otherlibs/unix/unix.cmx unix_tools.cmx \
+ program_management.cmi
+show_information.cmo: breakpoints.cmi checkpoints.cmi debugcom.cmi events.cmi \
+ frames.cmi ../bytecomp/instruct.cmi ../utils/misc.cmi primitives.cmi \
+ show_source.cmi symbols.cmi show_information.cmi
+show_information.cmx: breakpoints.cmx checkpoints.cmx debugcom.cmx events.cmx \
+ frames.cmx ../bytecomp/instruct.cmx ../utils/misc.cmx primitives.cmx \
+ show_source.cmx symbols.cmx show_information.cmi
+show_source.cmo: debugger_config.cmi ../utils/misc.cmi parameters.cmi \
+ primitives.cmi source.cmi show_source.cmi
+show_source.cmx: debugger_config.cmx ../utils/misc.cmx parameters.cmx \
+ primitives.cmx source.cmx show_source.cmi
+source.cmo: ../utils/config.cmi ../utils/misc.cmi primitives.cmi source.cmi
+source.cmx: ../utils/config.cmx ../utils/misc.cmx primitives.cmx source.cmi
+symbols.cmo: ../utils/config.cmi debugcom.cmi debugger_config.cmi \
+ ../bytecomp/instruct.cmi ../bytecomp/symtable.cmi symbols.cmi
+symbols.cmx: ../utils/config.cmx debugcom.cmx debugger_config.cmx \
+ ../bytecomp/instruct.cmx ../bytecomp/symtable.cmx symbols.cmi
+test3.cmo: ../otherlibs/unix/unix.cmi
+test3.cmx: ../otherlibs/unix/unix.cmx
+test9.cmo: ../otherlibs/unix/unix.cmi
+test9.cmx: ../otherlibs/unix/unix.cmx
+time_travel.cmo: breakpoints.cmi checkpoints.cmi debugcom.cmi \
+ debugger_config.cmi events.cmi exec.cmi input_handling.cmi \
+ ../bytecomp/instruct.cmi primitives.cmi program_loading.cmi \
+ trap_barrier.cmi time_travel.cmi
+time_travel.cmx: breakpoints.cmx checkpoints.cmx debugcom.cmx \
+ debugger_config.cmx events.cmx exec.cmx input_handling.cmx \
+ ../bytecomp/instruct.cmx primitives.cmx program_loading.cmx \
+ trap_barrier.cmx time_travel.cmi
+trap_barrier.cmo: checkpoints.cmi debugcom.cmi exec.cmi trap_barrier.cmi
+trap_barrier.cmx: checkpoints.cmx debugcom.cmx exec.cmx trap_barrier.cmi
+unix_tools.cmo: ../utils/misc.cmi primitives.cmi ../otherlibs/unix/unix.cmi \
+ unix_tools.cmi
+unix_tools.cmx: ../utils/misc.cmx primitives.cmx ../otherlibs/unix/unix.cmx \
+ unix_tools.cmi
diff --git a/debugger/Makefile b/debugger/Makefile
new file mode 100644
index 000000000..b6fea4e8b
--- /dev/null
+++ b/debugger/Makefile
@@ -0,0 +1,95 @@
+CAMLC=../boot/ocamlrun ../boot/ocamlc -I ../boot
+COMPFLAGS=$(INCLUDES)
+LINKFLAGS=-custom
+CAMLYACC=../boot/ocamlyacc
+YACCFLAGS=
+CAMLLEX=../boot/ocamlrun ../boot/ocamllex
+CAMLDEP=../boot/ocamlrun ../tools/ocamldep
+DEPFLAGS=$(INCLUDES)
+
+INCLUDES=-I ../otherlibs/unix -I ../utils -I ../parsing -I ../typing -I ../bytecomp
+
+OTHEROBJS=\
+ ../otherlibs/unix/unix.cma \
+ ../utils/misc.cmo ../utils/config.cmo \
+ ../utils/tbl.cmo ../utils/clflags.cmo \
+ ../parsing/longident.cmo \
+ ../typing/ident.cmo ../typing/path.cmo ../typing/types.cmo \
+ ../typing/primitive.cmo ../typing/typedtree.cmo \
+ ../typing/subst.cmo ../typing/predef.cmo \
+ ../typing/datarepr.cmo ../typing/env.cmo \
+ ../typing/ctype.cmo ../typing/printtyp.cmo ../typing/mtype.cmo \
+ ../bytecomp/runtimedef.cmo ../bytecomp/symtable.cmo
+
+OBJS=\
+ primitives.cmo \
+ unix_tools.cmo \
+ debugger_config.cmo \
+ envaux.cmo \
+ parameters.cmo \
+ lexer.cmo \
+ debugcom.cmo \
+ exec.cmo \
+ input_handling.cmo \
+ source.cmo \
+ checkpoints.cmo \
+ symbols.cmo \
+ events.cmo \
+ breakpoints.cmo \
+ trap_barrier.cmo \
+ history.cmo \
+ program_loading.cmo \
+ eval.cmo \
+ printval.cmo \
+ show_source.cmo \
+ time_travel.cmo \
+ program_management.cmo \
+ frames.cmo \
+ show_information.cmo \
+ parser.cmo \
+ command_line_interpreter.cmo \
+ main.cmo
+# debugger.cmo
+
+xOBJS=\
+ debugcom.cmo \
+ symbols.cmo \
+ envaux.cmo \
+ eval.cmo \
+ printval.cmo \
+ source.cmo \
+ show_source.cmo \
+ debugger.cmo
+
+all: ocamldebug
+
+ocamldebug: $(OBJS)
+ $(CAMLC) $(LINKFLAGS) -o ocamldebug $(OTHEROBJS) $(OBJS) ../otherlibs/unix/libunix.a
+
+clean::
+ rm -f ocamldebug
+ rm -f *.cmo *.cmi
+ rm -f lexer.ml parser.ml parser.mli
+
+.SUFFIXES:
+.SUFFIXES: .ml .cmo .mli .cmi
+
+.ml.cmo:
+ $(CAMLC) -c $(COMPFLAGS) $<
+
+.mli.cmi:
+ $(CAMLC) -c $(COMPFLAGS) $<
+
+depend: lexer.ml parser.ml parser.mli
+ $(CAMLDEP) $(DEPFLAGS) *.mli *.ml > .depend
+
+lexer.ml: lexer.mll
+ $(CAMLLEX) lexer.mll
+
+parser.ml parser.mli: parser.mly
+ $(CAMLYACC) parser.mly
+
+sharfile: Makefile *.ml *.mli *.mll *.mly
+ shar -o $@ $^
+
+include .depend
diff --git a/debugger/breakpoints.ml b/debugger/breakpoints.ml
new file mode 100644
index 000000000..af7f4d0c4
--- /dev/null
+++ b/debugger/breakpoints.ml
@@ -0,0 +1,212 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(******************************* Breakpoints ***************************)
+
+open Instruct
+open Primitives
+open Debugcom
+open Checkpoints
+open Source
+
+(*** Debugging. ***)
+let debug_breakpoints = ref true
+
+(*** Data. ***)
+
+(* Number of the last added breakpoint. *)
+let breakpoint_number = ref 0
+
+(* Breakpoint number -> event. *)
+let breakpoints = ref ([] : (int * debug_event) list)
+
+(* Program counter -> breakpoint count. *)
+let positions = ref ([] : (int * int ref) list)
+
+(* Versions of the breakpoint list. *)
+let current_version = ref 0
+let max_version = ref 0
+
+(*** Miscellaneous. ***)
+
+(* Mark breakpoints as installed in current checkpoint. *)
+let copy_breakpoints () =
+ !current_checkpoint.c_breakpoints <- !positions;
+ !current_checkpoint.c_breakpoint_version <- !current_version
+
+(* Announce a new version of the breakpoint list. *)
+let new_version () =
+ incr max_version;
+ current_version := !max_version;
+ copy_breakpoints ()
+
+(*** Information about breakpoints. ***)
+
+let breakpoints_count () =
+ List.length !breakpoints
+
+(* Is there a breakpoint at `pc' ? *)
+let breakpoint_at_pc pc =
+ List.mem_assoc pc !positions
+
+(* List of breakpoints at `pc'. *)
+let breakpoints_at_pc pc =
+ List.map fst (filter (function (_, {ev_pos = pos}) -> pos = pc) !breakpoints)
+
+(*** Set and remove breakpoints ***)
+
+(* Remove all breakpoints. *)
+let remove_breakpoints pos =
+ if !debug_breakpoints then
+ (print_string "Removing breakpoints..."; print_newline ());
+ List.iter
+ (function (pos, _) ->
+ if !debug_breakpoints then begin
+ print_int pos;
+ print_newline()
+ end;
+ reset_instr pos)
+ pos
+
+(* Set all breakpoints. *)
+let set_breakpoints pos =
+ if !debug_breakpoints then
+ (print_string "Setting breakpoints..."; print_newline ());
+ List.iter
+ (function (pos, _) ->
+ if !debug_breakpoints then begin
+ print_int pos;
+ print_newline()
+ end;
+ set_breakpoint pos)
+ pos
+
+(* Ensure the current version in installed in current checkpoint. *)
+let update_breakpoints () =
+ if !current_checkpoint.c_breakpoint_version <> !current_version then
+ Exec.protected
+ (function () ->
+ remove_breakpoints !current_checkpoint.c_breakpoints;
+ set_breakpoints !positions;
+ copy_breakpoints ())
+
+let change_version version pos =
+ Exec.protected
+ (function () ->
+ current_version := version;
+ positions := pos)
+
+(* Execute given function with no breakpoint in current checkpoint. *)
+(* --- `goto' runs faster this way (does not stop on each breakpoint). *)
+let execute_without_breakpoints f =
+ let version = !current_version
+ and pos = !positions
+ in
+ change_version 0 [];
+ try
+ f ();
+ change_version version pos
+ with
+ x ->
+ change_version version pos
+
+(* Add a position in the position list. *)
+(* Change version if necessary. *)
+let insert_position pos =
+ try
+ incr (List.assoc pos !positions)
+ with
+ Not_found ->
+ set_breakpoint pos;
+ positions := (pos, ref 1) :: !positions;
+ new_version ()
+
+(* Remove a position in the position list. *)
+(* Change version if necessary. *)
+let remove_position pos =
+ let count = List.assoc pos !positions in
+ decr count;
+ if !count = 0 then begin
+ positions := assoc_remove !positions pos;
+ new_version ();
+ reset_instr pos;
+ ()
+ end
+
+(* Insert a new breakpoint in lists. *)
+let new_breakpoint event =
+ Exec.protected
+ (function () ->
+ incr breakpoint_number;
+ insert_position event.ev_pos;
+ breakpoints := (!breakpoint_number, event) :: !breakpoints);
+ print_string "Breakpoint ";
+ print_int !breakpoint_number;
+ print_string " at ";
+ print_int event.ev_pos;
+ print_string " : file ";
+ print_string event.ev_file;
+ print_string ".ml, line ";
+ (let (start, line) = line_of_pos (get_buffer event.ev_file) event.ev_char in
+ print_int line;
+ print_string " column ";
+ print_int (event.ev_char - start + 1));
+ print_newline ()
+
+(* Remove a breakpoint from lists. *)
+let remove_breakpoint number =
+ try
+ let pos = (List.assoc number !breakpoints).ev_pos in
+ Exec.protected
+ (function () ->
+ breakpoints := assoc_remove !breakpoints number;
+ remove_position pos)
+ with
+ Not_found ->
+ prerr_endline ("No breakpoint number " ^ (string_of_int number) ^ ".");
+ raise Not_found
+
+let remove_all_breakpoints () =
+ List.iter (function (number, _) -> remove_breakpoint number) !breakpoints
+
+(*** Temporary breakpoints. ***)
+
+(* Temporary breakpoint position. *)
+let temporary_breakpoint_position = ref (None : int option)
+
+(* Execute `funct' with a breakpoint added at `pc'. *)
+(* --- Used by `finish'. *)
+let exec_with_temporary_breakpoint pc funct =
+ let previous_version = !current_version in
+ let remove () =
+ temporary_breakpoint_position := None;
+ current_version := previous_version;
+ let count = List.assoc pc !positions in
+ decr count;
+ if !count = 0 then begin
+ positions := assoc_remove !positions pc;
+ reset_instr pc;
+ ()
+ end
+
+ in
+ Exec.protected (function () -> insert_position pc);
+ temporary_breakpoint_position := Some pc;
+ try
+ funct ();
+ Exec.protected remove
+ with
+ x ->
+ Exec.protected remove;
+ raise x
diff --git a/debugger/breakpoints.mli b/debugger/breakpoints.mli
new file mode 100644
index 000000000..a4fa93e85
--- /dev/null
+++ b/debugger/breakpoints.mli
@@ -0,0 +1,60 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(******************************* Breakpoints ***************************)
+
+open Primitives
+open Instruct
+
+(*** Debugging. ***)
+val debug_breakpoints : bool ref
+
+(*** Information about breakpoints. ***)
+
+val breakpoints_count : unit -> int
+
+(* Breakpoint number -> debug_event_kind. *)
+val breakpoints : (int * debug_event) list ref
+
+(* Is there a breakpoint at `pc' ? *)
+val breakpoint_at_pc : int -> bool
+
+(* List of breakpoints at `pc'. *)
+val breakpoints_at_pc : int -> int list
+
+(*** Set and remove breakpoints ***)
+
+(* Ensure the current version in installed in current checkpoint. *)
+val update_breakpoints : unit -> unit
+
+(* Execute given function with no breakpoint in current checkpoint. *)
+(* --- `goto' run faster so (does not stop on each breakpoint). *)
+val execute_without_breakpoints : (unit -> unit) -> unit
+
+(* Insert a new breakpoint in lists. *)
+val new_breakpoint : debug_event -> unit
+
+(* Remove a breakpoint from lists. *)
+val remove_breakpoint : int -> unit
+
+val remove_all_breakpoints : unit -> unit
+
+(*** Temporary breakpoints. ***)
+
+(* Temporary breakpoint position. *)
+val temporary_breakpoint_position : int option ref
+
+(* Execute `funct' with a breakpoint added at `pc'. *)
+(* --- Used by `finish'. *)
+val exec_with_temporary_breakpoint : int -> (unit -> unit) -> unit
diff --git a/debugger/checkpoints.ml b/debugger/checkpoints.ml
new file mode 100644
index 000000000..f65e308ef
--- /dev/null
+++ b/debugger/checkpoints.ml
@@ -0,0 +1,78 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(*************************** Checkpoints *******************************)
+
+open Debugcom
+open Primitives
+
+(*** A type for checkpoints. ***)
+
+type checkpoint_state =
+ C_stopped
+ | C_running of int
+
+(* `c_valid' is true if and only if the corresponding
+ * process is connected to the debugger.
+ * `c_parent' is the checkpoint whose process is parent
+ * of the checkpoint one (`root' if no parent).
+ * c_pid = -2 for root pseudo-checkpoint.
+ * c_pid = 0 for ghost checkpoints.
+ * c_pid = -1 for kill checkpoints.
+ *)
+type checkpoint = {
+ mutable c_time : int;
+ mutable c_pid : int;
+ mutable c_fd : io_channel;
+ mutable c_valid : bool;
+ mutable c_report : report option;
+ mutable c_state : checkpoint_state;
+ mutable c_parent : checkpoint;
+ mutable c_breakpoint_version : int;
+ mutable c_breakpoints : (int * int ref) list;
+ mutable c_trap_barrier : int
+ }
+
+(*** Pseudo-checkpoint `root'. ***)
+(* --- Parents of all checkpoints which have no parent. *)
+let rec root = {
+ c_time = 0;
+ c_pid = -2;
+ c_fd = std_io;
+ c_valid = false;
+ c_report = None;
+ c_state = C_stopped;
+ c_parent = root;
+ c_breakpoint_version = 0;
+ c_breakpoints = [];
+ c_trap_barrier = 0
+ }
+
+(*** Current state ***)
+let checkpoints =
+ ref ([] : checkpoint list)
+
+let current_checkpoint =
+ ref root
+
+let current_time () =
+ !current_checkpoint.c_time
+
+let current_report () =
+ !current_checkpoint.c_report
+
+let current_pc () =
+ match current_report () with
+ None | Some {rep_type = Exited | Uncaught_exc} -> None
+ | Some {rep_program_pointer = pc } -> Some pc
diff --git a/debugger/checkpoints.mli b/debugger/checkpoints.mli
new file mode 100644
index 000000000..f7b099f80
--- /dev/null
+++ b/debugger/checkpoints.mli
@@ -0,0 +1,56 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(***************************** Checkpoints *****************************)
+
+open Primitives
+open Debugcom
+
+(*** A type for checkpoints. ***)
+
+type checkpoint_state =
+ C_stopped
+ | C_running of int
+
+(* `c_valid' is true if and only if the corresponding
+ * process is connected to the debugger.
+ * `c_parent' is the checkpoint whose process is parent
+ * of the checkpoint one (`root' if no parent).
+ * c_pid = 2 for root pseudo-checkpoint.
+ * c_pid = 0 for ghost checkpoints.
+ * c_pid = -1 for kill checkpoints.
+ *)
+type checkpoint =
+ {mutable c_time : int;
+ mutable c_pid : int;
+ mutable c_fd : io_channel;
+ mutable c_valid : bool;
+ mutable c_report : report option;
+ mutable c_state : checkpoint_state;
+ mutable c_parent : checkpoint;
+ mutable c_breakpoint_version : int;
+ mutable c_breakpoints : (int * int ref) list;
+ mutable c_trap_barrier : int}
+
+(*** Pseudo-checkpoint `root'. ***)
+(* --- Parents of all checkpoints which have no parent. *)
+val root : checkpoint
+
+(*** Current state ***)
+val checkpoints : checkpoint list ref
+val current_checkpoint : checkpoint ref
+
+val current_time : unit -> int
+val current_report : unit -> report option
+val current_pc : unit -> int option
diff --git a/debugger/command_line_interpreter.ml b/debugger/command_line_interpreter.ml
new file mode 100644
index 000000000..3eb6bb3ee
--- /dev/null
+++ b/debugger/command_line_interpreter.ml
@@ -0,0 +1,1052 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(************************ Reading and executing commands ***************)
+
+open Format
+open Misc
+open Instruct
+open Unix
+open Debugger_config
+open Types
+open Primitives
+open Unix_tools
+open Parser
+open Parser_aux
+open Lexer
+open Input_handling
+open Debugcom
+open Program_loading
+open Program_management
+open Lexing
+open Parameters
+open Show_source
+open Show_information
+open Time_travel
+open Events
+open Symbols
+open Source
+open Breakpoints
+open Checkpoints
+open Frames
+(*open Pattern_matching*)
+
+(** Instructions, variables and infos lists. **)
+type dbg_instruction =
+ { instr_name: string; (* Name of command *)
+ instr_prio: bool; (* Has priority *)
+ instr_action: lexbuf -> unit; (* What to do *)
+ instr_repeat: bool; (* Can be repeated *)
+ instr_help: string } (* Help message *)
+
+let instruction_list = ref ([] : dbg_instruction list)
+
+type dbg_variable =
+ { var_name: string; (* Name of variable *)
+ var_action: (lexbuf -> unit) * (unit -> unit); (* Writing, reading fns *)
+ var_help: string } (* Help message *)
+
+let variable_list = ref ([] : dbg_variable list)
+
+type dbg_info =
+ { info_name: string; (* Name of info *)
+ info_action: lexbuf -> unit; (* What to do *)
+ info_help: string } (* Help message *)
+
+let info_list = ref ([] : dbg_info list)
+
+(** Utilities. **)
+let error text =
+ prerr_endline text;
+ raise Toplevel
+
+let eol =
+ end_of_line Lexer.lexeme
+
+let matching_elements list name instr =
+ filter (function a -> isprefix instr (name a)) !list
+
+let all_matching_instructions =
+ matching_elements instruction_list (fun i -> i.instr_name)
+
+(* itz 04-21-96 don't do priority completion in emacs mode *)
+let matching_instructions instr =
+ let all = all_matching_instructions instr in
+ let prio = filter (fun i -> i.instr_prio) all in
+ if prio = [] || !emacs then all else prio
+
+let matching_variables =
+ matching_elements variable_list (fun v -> v.var_name)
+
+let matching_infos =
+ matching_elements info_list (fun i -> i.info_name)
+
+let find_ident name matcher action alternative lexbuf =
+ match identifier_or_eol Lexer.lexeme lexbuf with
+ None ->
+ alternative ()
+ | Some ident ->
+ match matcher ident with
+ [] ->
+ error ("Unknown " ^ name ^ ".")
+ | [a] ->
+ action a lexbuf
+ | _ ->
+ error ("Ambiguous " ^ name ^ ".")
+
+let find_variable action alternative lexbuf =
+ find_ident "variable name" matching_variables action alternative lexbuf
+
+let find_info action alternative lexbuf =
+ find_ident "info command" matching_infos action alternative lexbuf
+
+let add_breakpoint_at_pc pc =
+ try
+ new_breakpoint (event_at_pc pc)
+ with
+ Not_found ->
+ prerr_string "Can't add breakpoint at pc ";
+ prerr_int pc;
+ prerr_endline " : no event there.";
+ raise Toplevel
+
+let convert_module mdle =
+ match mdle with
+ Some x ->
+ x
+ | None ->
+ try
+ let (x, _) = current_point () in x
+ with Not_found ->
+ prerr_endline "Not in a module.";
+ raise Toplevel
+
+(** Toplevel. **)
+let current_line = ref ""
+
+let interprete_line line =
+ current_line := line;
+ let lexbuf = Lexing.from_string line in
+ try
+ match identifier_or_eol Lexer.lexeme lexbuf with
+ Some x ->
+ begin match matching_instructions x with
+ [] ->
+ error "Unknown command."
+ | [i] ->
+ i.instr_action lexbuf;
+ resume_user_input ();
+ i.instr_repeat
+ | l ->
+ error "Ambiguous command."
+ end
+ | None ->
+ resume_user_input ();
+ false
+ with
+ Parsing.Parse_error ->
+ error "Syntax error."
+
+let line_loop line_buffer =
+ resume_user_input ();
+ let previous_line = ref "" in
+ try
+ while true do
+ if !loaded then
+ History.add_current_time ();
+ let new_line = string_trim (line line_buffer) in
+ let line =
+ if new_line <> "" then
+ new_line
+ else
+ !previous_line
+ in
+ previous_line := "";
+ if interprete_line line then
+ previous_line := line
+ done
+ with
+ Exit ->
+ stop_user_input ()
+ | Sys_error s ->
+ prerr_endline ("System error : " ^ s);
+ raise Toplevel
+
+
+(** Instructions. **)
+let instr_cd lexbuf =
+ let dir = argument_eol argument lexbuf in
+ if ask_kill_program () then
+ try
+ Sys.chdir (expand_path dir)
+ with
+ Sys_error s ->
+ prerr_endline s;
+ raise Toplevel
+
+let instr_pwd lexbuf =
+ eol lexbuf;
+ system "/bin/pwd";
+ ()
+
+let instr_dir lexbuf =
+ let new_directory = argument_list_eol argument lexbuf in
+ if new_directory = [] then begin
+ if yes_or_no "Reinitialize directory list" then begin
+ Config.load_path := !default_load_path;
+ Envaux.reset_cache ();
+ flush_buffer_list ()
+ end
+ end
+ else
+ List.iter (function x -> add_path (expand_path x)) (List.rev new_directory);
+ print_string "Directories :";
+ List.iter (function x -> print_space(); print_string x) !Config.load_path;
+ print_newline ()
+
+let instr_kill lexbuf =
+ eol lexbuf;
+ if not !loaded then
+ (prerr_endline "The program is not being run."; raise Toplevel);
+ if (yes_or_no "Kill the program being debugged") then begin
+ kill_program ();
+ show_no_point()
+ end
+
+let instr_run lexbuf =
+ eol lexbuf;
+ ensure_loaded ();
+ run ();
+ show_current_event ()
+
+let instr_reverse lexbuf =
+ eol lexbuf;
+ ensure_loaded ();
+ back_run ();
+ show_current_event ()
+
+let instr_step lexbuf =
+ let step_count =
+ match opt_signed_integer_eol Lexer.lexeme lexbuf with
+ None -> 1
+ | Some x -> x
+ in
+ ensure_loaded ();
+ step step_count;
+ show_current_event ()
+
+let instr_back lexbuf =
+ let step_count =
+ match opt_signed_integer_eol Lexer.lexeme lexbuf with
+ None -> 1
+ | Some x -> x
+ in
+ ensure_loaded ();
+ step (-step_count);
+ show_current_event ()
+
+let instr_finish lexbuf =
+ eol lexbuf;
+ ensure_loaded ();
+ finish ();
+ show_current_event ()
+
+let instr_next lexbuf =
+ let step_count =
+ match opt_integer_eol Lexer.lexeme lexbuf with
+ None -> 1
+ | Some x -> x
+ in
+ ensure_loaded ();
+ next step_count;
+ show_current_event ()
+
+let instr_goto lexbuf =
+ let time = integer_eol Lexer.lexeme lexbuf in
+ ensure_loaded ();
+ go_to time;
+ show_current_event ()
+
+let instr_quit _ =
+ raise Exit
+
+let print_variable_list () =
+ print_endline "List of variables :";
+ List.iter (fun v -> print_string v.var_name; print_space()) !variable_list;
+ print_newline ()
+
+let print_info_list () =
+ print_endline "List of info commands :";
+ List.iter (fun i -> print_string i.info_name; print_space()) !info_list;
+ print_newline ()
+
+let instr_complete lexbuf =
+ let rec print_list l =
+ try
+ eol lexbuf;
+ List.iter (function i -> print_string i; print_newline ()) l
+ with _ ->
+ remove_file !user_channel
+ and match_list lexbuf =
+ match identifier_or_eol Lexer.lexeme lexbuf with
+ None ->
+ List.map (fun i -> i.instr_name) !instruction_list
+ | Some x ->
+ match matching_instructions x with
+ [ {instr_name = ("set" | "show" as i_full)} ] ->
+ if x = i_full then begin
+ match identifier_or_eol Lexer.lexeme lexbuf with
+ Some ident ->
+ begin match matching_variables ident with
+ [v] -> if v.var_name = ident then [] else [v.var_name]
+ | l -> List.map (fun v -> v.var_name) l
+ end
+ | None ->
+ List.map (fun v -> v.var_name) !variable_list
+ end
+ else [i_full]
+ | [ {instr_name = "info"} ] ->
+ if x = "info" then begin
+ match identifier_or_eol Lexer.lexeme lexbuf with
+ Some ident ->
+ begin match matching_infos ident with
+ [i] -> if i.info_name = ident then [] else [i.info_name]
+ | l -> List.map (fun i -> i.info_name) l
+ end
+ | None ->
+ List.map (fun i -> i.info_name) !info_list
+ end
+ else ["info"]
+ | [ {instr_name = "help"} ] ->
+ if x = "help" then match_list lexbuf else ["help"]
+ | [ i ] ->
+ if x = i.instr_name then [] else [i.instr_name]
+ | l ->
+ List.map (fun i -> i.instr_name) l
+ in
+ print_list(match_list lexbuf)
+
+let instr_help lexbuf =
+ match identifier_or_eol Lexer.lexeme lexbuf with
+ Some x ->
+ let print_help nm hlp =
+ eol lexbuf;
+ print_string nm;
+ print_string " : ";
+ print_string hlp;
+ print_newline ()
+ in
+ begin match matching_instructions x with
+ [] ->
+ eol lexbuf;
+ print_string "No matching command.";
+ print_newline ()
+ | [ {instr_name = "set"} ] ->
+ find_variable
+ (fun v _ ->
+ print_help ("set " ^ v.var_name) ("set " ^ v.var_help))
+ (fun () ->
+ print_help "set" "set debugger variable.";
+ print_variable_list ())
+ lexbuf
+ | [ {instr_name = "show"} ] ->
+ find_variable
+ (fun v _ ->
+ print_help ("show " ^ v.var_name) ("show " ^ v.var_help))
+ (fun () ->
+ print_help "show" "display debugger variable.";
+ print_variable_list ())
+ lexbuf
+ | [ {instr_name = "info"} ] ->
+ find_info
+ (fun i _ -> print_help ("info " ^ i.info_name) i.info_help)
+ (fun () ->
+ print_help "info" "display infos about the program being debugged.";
+ print_info_list ())
+ lexbuf
+ | [i] ->
+ print_help i.instr_name i.instr_help
+ | l ->
+ eol lexbuf;
+ print_string ("Ambiguous command \"" ^ x ^ "\" : ");
+ List.iter
+ (fun i -> print_string i.instr_name; print_space())
+ l;
+ print_newline ()
+ end
+ | None ->
+ print_endline "List of commands :";
+ List.iter
+ (fun i -> print_string i.instr_name; print_space())
+ !instruction_list;
+ print_newline ()
+
+let longident idlist =
+ let rec longid = function
+ [] -> fatal_error "Debugger.longident"
+ | [s] -> Longident.Lident s
+ | f::l -> Longident.Ldot(longid l, f) in
+ longid (List.rev idlist)
+
+let print_val valu var typ env =
+ (* prints the classic "var : typ = val" message *)
+ print_string var;
+ print_string " : ";
+ Printtyp.type_scheme typ;
+ print_string " = ";
+ Printval.print_value valu typ env;
+ Format.print_newline()
+
+let instr_print lexbuf =
+ let e = match !selected_event with
+ None -> raise Toplevel
+ | Some x -> x in
+ let variables = variable_list_eol Lexer.lexeme lexbuf in
+ ensure_loaded ();
+ List.iter
+ (function vari ->
+ open_hovbox 0;
+ let lid = longident(split_string '.' vari) in
+ let env = Envaux.env_from_summary e.ev_typenv in
+ begin try
+ let (path, valdesc) = Env.lookup_value lid env in
+ let exp_type = (Ctype.instance valdesc.Types.val_type)
+ and valu = Eval.path e.ev_compenv e.ev_stacksize path in
+ print_val valu vari exp_type env
+ with Not_found ->
+ print_string "Unbound identifier "; print_string vari
+ end;
+ close_box();
+ print_newline ())
+ variables
+
+let instr_match lexbuf =
+ ()
+(***
+ let (var, pattern) = match_arguments_eol Lexer.lexeme lexbuf in
+ ensure_loaded ();
+ let (valu, typ) = variable var in
+ List.iter
+ (function
+ (name, valu, typ) ->
+ open_hovbox 0;
+ print_string name;
+ print_string " :"; print_space();
+ print_one_type typ;
+ print_string " ="; print_space();
+ print_value valu typ;
+ close_box();
+ print_newline ())
+ (pattern_matching pattern valu typ)
+***)
+
+let instr_source lexbuf =
+ let file = argument_eol argument lexbuf
+ and old_state = !interactif
+ and old_channel = !user_channel in
+ let io_chan =
+ try
+ io_channel_of_descr (openfile (expand_path file) [O_RDONLY] 0)
+ with
+ (Unix_error _) as x -> Unix_tools.report_error x; raise Toplevel
+ in
+ try
+ interactif := false;
+ user_channel := io_chan;
+ line_loop (Lexing.from_function read_user_input);
+ close_io io_chan;
+ interactif := old_state;
+ user_channel := old_channel
+ with
+ x ->
+ stop_user_input ();
+ close_io io_chan;
+ interactif := old_state;
+ user_channel := old_channel;
+ raise x
+
+let instr_open lexbuf = ()
+(***
+ let mdles = argument_list_eol argument lexbuf in
+ List.iter open_module mdles ***)
+
+let instr_close lexbuf = ()
+(***
+ let mdles = argument_list_eol argument lexbuf in
+ List.iter close_module mdles ***)
+
+let instr_set =
+ find_variable
+ (function {var_action = (funct, _)} -> funct)
+ (function () -> prerr_endline "Argument required."; raise Toplevel)
+
+let instr_show =
+ find_variable
+ (fun {var_action = (_, funct)} lexbuf -> eol lexbuf; funct ())
+ (function () ->
+ List.iter
+ (function {var_name = nm; var_action = (_, funct)} ->
+ print_string (nm ^ " : ");
+ funct ())
+ !variable_list)
+
+let instr_info =
+ find_info
+ (fun i lexbuf -> i.info_action lexbuf)
+ (function () ->
+ prerr_endline
+ "\"info\" must be followed by the name of an info command.";
+ raise Toplevel)
+
+let instr_break lexbuf =
+ let argument = break_argument_eol Lexer.lexeme lexbuf in
+ ensure_loaded ();
+ match argument with
+ BA_none -> (* break *)
+ (match current_pc () with
+ Some pc ->
+ add_breakpoint_at_pc pc
+ | None ->
+ prerr_endline "Can't add breakpoint at this point.";
+ raise Toplevel)
+ | BA_pc pc -> (* break PC *)
+ add_breakpoint_at_pc pc
+ | BA_function vari -> (* break FUNCTION *)
+ let e = match !current_event with
+ None -> raise Toplevel
+ | Some x -> x in
+ let lid = longident(split_string '.' vari) in
+ let env = Envaux.env_from_summary e.ev_typenv in
+ (try
+ let (path, valdesc) = Env.lookup_value lid env in
+ let typ = (Ctype.instance valdesc.Types.val_type)
+ and valu = Eval.path e.ev_compenv e.ev_stacksize path in
+ match (Ctype.repr typ).desc with
+ Tarrow (_, _) ->
+ prerr_endline "Not Yet Implemented"
+ | _ ->
+ prerr_endline "Not a function.";
+ raise Toplevel
+ with Not_found ->
+ print_string "Unbound identifier"; print_newline())
+ | BA_pos1 (mdle, line, column) -> (* break @ [MODULE] LINE [COL] *)
+ let module_name = convert_module mdle in
+ new_breakpoint
+ (try
+ match column with
+ None ->
+ event_after_pos
+ module_name
+ (fst (pos_of_line (get_buffer module_name) line))
+ | Some col ->
+ event_near_pos
+ module_name
+ (point_of_coord (get_buffer module_name) line col)
+ with
+ Not_found ->
+ prerr_endline "Can't find any event there.";
+ raise Toplevel
+ | Out_of_range ->
+ prerr_endline "Position out of range.";
+ raise Toplevel)
+ | BA_pos2 (mdle, position) -> (* break @ [MODULE] # POSITION *)
+ try
+ new_breakpoint (event_near_pos (convert_module mdle) position)
+ with
+ Not_found ->
+ prerr_endline "Can't find any event there."
+
+let instr_delete lexbuf =
+ match integer_list_eol Lexer.lexeme lexbuf with
+ [] ->
+ if (breakpoints_count () <> 0) & (yes_or_no "Delete all breakpoints")
+ then remove_all_breakpoints ()
+ | breakpoints ->
+ List.iter
+ (function x ->
+ try
+ remove_breakpoint x
+ with
+ Not_found ->
+ ())
+ breakpoints
+
+let instr_frame lexbuf =
+ let frame_number =
+ match opt_integer_eol Lexer.lexeme lexbuf with
+ None -> !current_frame
+ | Some x -> x
+ in
+ ensure_loaded ();
+ try
+ select_frame frame_number;
+ show_current_frame true
+ with
+ Not_found ->
+ prerr_endline ("No frame number " ^ (string_of_int frame_number) ^ ".");
+ raise Toplevel
+
+let instr_backtrace lexbuf =
+ let number =
+ match opt_signed_integer_eol Lexer.lexeme lexbuf with
+ None -> 0
+ | Some x -> x in
+ ensure_loaded ();
+ match current_report() with
+ None | Some {rep_type = Exited | Uncaught_exc} -> ()
+ | Some _ ->
+ let frame_counter = ref 0 in
+ let print_frame first_frame last_frame = function
+ None ->
+ print_string "(Encountered a function with no debugging information)";
+ print_newline();
+ false
+ | Some event ->
+ if !frame_counter >= first_frame then
+ show_one_frame !frame_counter event;
+ incr frame_counter;
+ if !frame_counter >= last_frame then begin
+ print_string "(More frames follow)"; print_newline()
+ end;
+ !frame_counter < last_frame in
+ if number = 0 then
+ do_backtrace (print_frame 0 max_int)
+ else if number > 0 then
+ do_backtrace (print_frame 0 number)
+ else begin
+ let num_frames = stack_depth() in
+ if num_frames < 0 then begin
+ print_string "(Encountered a function with no debugging information)";
+ print_newline()
+ end else
+ do_backtrace (print_frame (num_frames + number) max_int)
+ end
+
+let do_up rep =
+ let stack_pointer = rep.rep_stack_pointer in
+ let pc = rep.rep_program_pointer in
+ let ev = ref (event_at_pc pc) in
+ print_string !ev.ev_file; print_string " char "; print_int !ev.ev_char;
+ print_newline();
+ let (stackpos, pc) = Debugcom.up_frame !ev.ev_stacksize in
+ if stackpos = -1 then raise Exit;
+ current_event := Some (event_at_pc pc)
+
+let instr_up lexbuf =
+ let offset =
+ match opt_signed_integer_eol Lexer.lexeme lexbuf with
+ None -> 1
+ | Some x -> x
+ in
+ ensure_loaded ();
+ try
+ select_frame (!current_frame + offset);
+ show_current_frame true
+ with
+ Not_found ->
+ prerr_endline "No such frame.";
+ raise Toplevel
+
+let instr_down lexbuf =
+ let offset =
+ match opt_signed_integer_eol Lexer.lexeme lexbuf with
+ None -> 1
+ | Some x -> x
+ in
+ ensure_loaded ();
+ try
+ select_frame (!current_frame - offset);
+ show_current_frame true
+ with
+ Not_found ->
+ prerr_endline "No such frame.";
+ raise Toplevel
+
+let instr_last lexbuf =
+ let count =
+ match opt_signed_integer_eol Lexer.lexeme lexbuf with
+ None -> 1
+ | Some x -> x
+ in
+ go_to (History.previous_time count);
+ show_current_event ()
+
+let instr_list lexbuf =
+ let (mo, beg, e) = list_arguments_eol Lexer.lexeme lexbuf in
+ let (curr_mod, point) =
+ try
+ selected_point ()
+ with
+ Not_found ->
+ ("", -1)
+ in
+ let mdle = convert_module mo in
+ let beginning =
+ match beg with
+ None ->
+ if point = -1 then
+ (prerr_endline "No current point."; raise Toplevel);
+ (max 1 ((snd (line_of_pos (get_buffer mdle) point)) - 10))
+ | Some x -> x
+ in
+ let en =
+ match e with
+ None -> beginning + 20
+ | Some x -> x
+ in
+ if mdle = curr_mod then
+ show_listing mdle beginning en point
+ (current_event_is_before ())
+ else
+ show_listing mdle beginning en (-1) true
+
+(** Variables. **)
+let raw_variable kill name =
+ (function
+ lexbuf ->
+ let argument = argument_eol argument lexbuf in
+ if (not kill) or (ask_kill_program ()) then
+ name := argument),
+ function
+ () ->
+ print_string !name;
+ print_newline ()
+
+let raw_line_variable kill name =
+ (function
+ lexbuf ->
+ let argument = argument_eol line_argument lexbuf in
+ if (not kill) or (ask_kill_program ()) then
+ name := argument),
+ function
+ () ->
+ print_string !name;
+ print_newline ()
+
+let integer_variable kill min msg name =
+ (function
+ lexbuf ->
+ let argument = integer_eol Lexer.lexeme lexbuf in
+ if argument < min then
+ print_endline msg
+ else
+ if (not kill) or (ask_kill_program ()) then
+ name := argument),
+ function
+ () ->
+ print_int !name;
+ print_newline ()
+
+let boolean_variable kill name =
+ (function
+ lexbuf ->
+ let argument =
+ match identifier_eol Lexer.lexeme lexbuf with
+ "on" -> true
+ | "of" | "off" -> false
+ | _ -> error "Syntax error."
+ in
+ if (not kill) or (ask_kill_program ()) then
+ name := argument),
+ function
+ () ->
+ print_string (if !name then "on" else "off");
+ print_newline ()
+
+let path_variable kill name =
+ (function
+ lexbuf ->
+ let argument = argument_eol argument lexbuf in
+ if (not kill) or (ask_kill_program ()) then
+ name := (expand_path argument)),
+ function
+ () ->
+ print_string !name;
+ print_newline ()
+
+let loading_mode_variable =
+ (find_ident
+ "loading mode"
+ (matching_elements (ref loading_modes) fst)
+ (fun (_, mode) lexbuf ->
+ eol lexbuf; set_launching_function mode)
+ (function () -> error "Syntax error.")),
+ function
+ () ->
+ let rec find =
+ function
+ [] -> ()
+ | (name, funct)::l ->
+ if funct == !launching_func then
+ print_string name
+ else
+ find l
+ in
+ find loading_modes;
+ print_newline ()
+
+(** Infos. **)
+
+let info_modules lexbuf =
+ eol lexbuf
+(********
+ print_endline "Used modules :";
+ List.iter (function x -> print_string x; print_space()) !modules;
+ print_newline ();
+ print_endline "Opened modules :";
+ if !opened_modules_names = [] then
+ print_endline "(no module opened)."
+ else
+ (List.iter (function x -> print_string x; print_space) !opened_modules_names;
+ print_newline ())
+*********)
+
+let info_checkpoints lexbuf =
+ eol lexbuf;
+ if !checkpoints = [] then
+ (print_string "No checkpoint."; print_newline ())
+ else
+ (if !debug_breakpoints then
+ (prerr_endline " Time Pid Version";
+ List.iter
+ (function
+ {c_time = time; c_pid = pid; c_breakpoint_version = version} ->
+ Printf.printf "%10d %5d %d\n" time pid version)
+ !checkpoints)
+ else
+ (print_endline " Time Pid";
+ List.iter
+ (function
+ {c_time = time; c_pid = pid} ->
+ Printf.printf "%10d %5d\n" time pid)
+ !checkpoints))
+
+let info_breakpoints lexbuf =
+ eol lexbuf;
+ if !breakpoints = [] then
+ (print_string "No breakpoint."; print_newline ())
+ else
+ (print_endline "Num Address Where";
+ List.iter
+ (function (num, {ev_pos = pc; ev_file = file; ev_char = char}) ->
+ Printf.printf "%3d %10d in %s.ml, character %d\n" num pc file char)
+ (List.rev !breakpoints))
+
+let info_events lexbuf =
+ if not !loaded then
+ (prerr_endline "Not in a module."; raise Toplevel);
+ let mdle =
+ match opt_identifier_eol Lexer.lexeme lexbuf with
+ Some x -> x
+ | None ->
+ match !current_event with
+ None ->
+ prerr_endline "Not in a module."; raise Toplevel
+ | Some {ev_file = f} -> f
+ in
+ print_endline ("Module : " ^ mdle);
+ print_endline " Address Character Kind";
+ List.iter
+ (function {ev_pos = pc; ev_char = char; ev_kind = kind} ->
+ Printf.printf
+ "%10d %10d %s\n"
+ pc
+ char
+ (match kind with
+ Event_before -> "before"
+ | Event_after _ -> "after"))
+ (events_in_module mdle)
+
+(** Initialization. **)
+let _ =
+ instruction_list := [
+ { instr_name = "cd"; instr_prio = false;
+ instr_action = instr_cd; instr_repeat = true; instr_help =
+"set working directory to DIR for debugger and program being debugged." };
+ { instr_name = "complete"; instr_prio = false;
+ instr_action = instr_complete; instr_repeat = false; instr_help =
+"complete word at cursor according to context. Useful for Emacs." };
+ { instr_name = "pwd"; instr_prio = false;
+ instr_action = instr_pwd; instr_repeat = true; instr_help =
+"print working directory." };
+ { instr_name = "directory"; instr_prio = false;
+ instr_action = instr_dir; instr_repeat = false; instr_help =
+"add directory DIR to beginning of search path for source and\n\
+interface files.\n\
+Forget cached info on source file locations and line positions.\n\
+With no argument, reset the search path." };
+ { instr_name = "kill"; instr_prio = false;
+ instr_action = instr_kill; instr_repeat = true; instr_help =
+"kill the program being debugged." };
+ { instr_name = "help"; instr_prio = false;
+ instr_action = instr_help; instr_repeat = true; instr_help =
+"print list of commands." };
+ { instr_name = "quit"; instr_prio = false;
+ instr_action = instr_quit; instr_repeat = false; instr_help =
+"exit the debugger." };
+ (* Displacements *)
+ { instr_name = "run"; instr_prio = true;
+ instr_action = instr_run; instr_repeat = true; instr_help =
+"run the program from current position." };
+ { instr_name = "reverse"; instr_prio = false;
+ instr_action = instr_reverse; instr_repeat = true; instr_help =
+"run the program backward from current position." };
+ { instr_name = "step"; instr_prio = true;
+ instr_action = instr_step; instr_repeat = true; instr_help =
+"step program until it reaches the next event.\n\
+Argument N means do this N times (or till program stops for another reason)." };
+ { instr_name = "backstep"; instr_prio = true;
+ instr_action = instr_back; instr_repeat = true; instr_help =
+"step program backward until it reaches the previous event.\n\
+Argument N means do this N times (or till program stops for another reason)." };
+ { instr_name = "goto"; instr_prio = false;
+ instr_action = instr_goto; instr_repeat = true; instr_help =
+"go to the given time." };
+ { instr_name = "finish"; instr_prio = true;
+ instr_action = instr_finish; instr_repeat = true; instr_help =
+"execute until selected stack frame returns." };
+ { instr_name = "next"; instr_prio = true;
+ instr_action = instr_next; instr_repeat = true; instr_help =
+"step program until it reaches the next event.\n\
+Skip over function calls.\n\
+Argument N means do this N times (or till program stops for another reason)." };
+ { instr_name = "print"; instr_prio = true;
+ instr_action = instr_print; instr_repeat = true; instr_help =
+"print value of variables (`*' stand for the accumulator)." };
+ { instr_name = "match"; instr_prio = false;
+ instr_action = instr_match; instr_repeat = true; instr_help =
+"match the value of a variable against a pattern." };
+ { instr_name = "source"; instr_prio = false;
+ instr_action = instr_source; instr_repeat = true; instr_help =
+"read command from file FILE." };
+ { instr_name = "open"; instr_prio = false;
+ instr_action = instr_open; instr_repeat = false; instr_help =
+"open modules." };
+ { instr_name = "close"; instr_prio = false;
+ instr_action = instr_close; instr_repeat = false; instr_help =
+"close modules." };
+ (* Breakpoints *)
+ { instr_name = "break"; instr_prio = false;
+ instr_action = instr_break; instr_repeat = false; instr_help =
+"Set breakpoint at specified line or function." };
+ { instr_name = "delete"; instr_prio = false;
+ instr_action = instr_delete; instr_repeat = false; instr_help =
+"delete some breakpoints.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To delete all breakpoints, give no argument." };
+ { instr_name = "set"; instr_prio = false;
+ instr_action = instr_set; instr_repeat = false; instr_help =
+"--unused--" };
+ { instr_name = "show"; instr_prio = false;
+ instr_action = instr_show; instr_repeat = true; instr_help =
+"--unused--" };
+ { instr_name = "info"; instr_prio = false;
+ instr_action = instr_info; instr_repeat = true; instr_help =
+"--unused--" };
+ (* Frames *)
+ { instr_name = "frame"; instr_prio = false;
+ instr_action = instr_frame; instr_repeat = true; instr_help =
+"Select and print a stack frame.\n\
+With no argument, print the selected stack frame.\n\
+An argument specifies the frame to select." };
+ { instr_name = "backtrace"; instr_prio = false;
+ instr_action = instr_backtrace; instr_repeat = true; instr_help =
+"print backtrace of all stack frames, or innermost COUNT frames.\n\
+With a negative argument, print outermost -COUNT frames." };
+ { instr_name = "bt"; instr_prio = false;
+ instr_action = instr_backtrace; instr_repeat = true; instr_help =
+"print backtrace of all stack frames, or innermost COUNT frames.\n\
+With a negative argument, print outermost -COUNT frames." };
+ { instr_name = "up"; instr_prio = false;
+ instr_action = instr_up; instr_repeat = true; instr_help =
+"select and print stack frame that called this one.\n\
+An argument says how many frames up to go." };
+ { instr_name = "down"; instr_prio = false;
+ instr_action = instr_down; instr_repeat = true; instr_help =
+"select and print stack frame called by this one.\n\
+An argument says how many frames down to go." };
+ { instr_name = "last"; instr_prio = true;
+ instr_action = instr_last; instr_repeat = true; instr_help =
+"go back to previous time." };
+ { instr_name = "list"; instr_prio = false;
+ instr_action = instr_list; instr_repeat = true; instr_help =
+"list the source code." }
+];
+ variable_list := [
+ (* variable name, (writing, reading), help reading, help writing *)
+ { var_name = "arguments";
+ var_action = raw_line_variable true arguments;
+ var_help =
+"arguments to give program being debugged when it is started." };
+ { var_name = "program";
+ var_action = path_variable true program_name;
+ var_help =
+"name of program to be debugged." };
+ { var_name = "loadingmode";
+ var_action = loading_mode_variable;
+ var_help =
+"mode of loading.\n\
+It can be either :
+ direct : the program is directly called by the debugger.\n\
+ runtime : the debugger execute `camlrun -D socket programname arguments'.\n\
+ manual : the program is not launched by the debugger,\n\
+ but manually by the user." };
+ { var_name = "processcount";
+ var_action = integer_variable false 1 "Must be > 1."
+ checkpoint_max_count;
+ var_help =
+"maximum number of process to keep." };
+ { var_name = "checkpoints";
+ var_action = boolean_variable false make_checkpoints;
+ var_help =
+"whether to make checkpoints or not." };
+ { var_name = "bigstep";
+ var_action = integer_variable false 1 "Must be > 1."
+ checkpoint_big_step;
+ var_help =
+"step between checkpoints during long displacements." };
+ { var_name = "smallstep";
+ var_action = integer_variable false 1 "Must be > 1."
+ checkpoint_small_step;
+ var_help =
+"step between checkpoints during small displacements." };
+ { var_name = "socket";
+ var_action = raw_variable true socket_name;
+ var_help =
+"name of the socket used by communications debugger-runtime." };
+ { var_name = "history";
+ var_action = integer_variable false 0 "" history_size;
+ var_help =
+"history size." };
+ { var_name = "print_depth";
+ var_action = integer_variable false 1 "Must be at least 1"
+ Printval.max_printer_depth;
+ var_help =
+"maximal depth for printing of values." };
+ { var_name = "print_length";
+ var_action = integer_variable false 1 "Must be at least 1"
+ Printval.max_printer_steps;
+ var_help =
+"maximal number of value nodes printed." }];
+
+ info_list :=
+ (* info name, function, help *)
+ [{ info_name = "modules"; info_action = info_modules; info_help =
+"list opened modules." };
+ { info_name = "checkpoints"; info_action = info_checkpoints; info_help =
+"list checkpoints." };
+ { info_name = "breakpoints"; info_action = info_breakpoints; info_help =
+"list breakpoints." };
+ { info_name = "events"; info_action = info_events; info_help =
+"list events in MODULE (default is current module)." }]
diff --git a/debugger/command_line_interpreter.mli b/debugger/command_line_interpreter.mli
new file mode 100644
index 000000000..f4bf9edea
--- /dev/null
+++ b/debugger/command_line_interpreter.mli
@@ -0,0 +1,20 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(************************ Reading and executing commands ***************)
+
+open Lexing;;
+
+val interprete_line : string -> bool;;
+val line_loop : lexbuf -> unit;;
diff --git a/debugger/debugcom.ml b/debugger/debugcom.ml
new file mode 100644
index 000000000..9ce5472fc
--- /dev/null
+++ b/debugger/debugcom.ml
@@ -0,0 +1,240 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Low-level communication with the debuggee *)
+
+open Primitives
+
+(* The current connection with the debuggee *)
+
+let conn = ref Primitives.std_io
+
+let set_current_connection io_chan =
+ conn := io_chan
+
+(* Modify the program code *)
+
+let set_event pos =
+ output_char !conn.io_out 'e';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out
+
+let set_breakpoint pos =
+ output_char !conn.io_out 'B';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out
+
+let reset_instr pos =
+ output_char !conn.io_out 'i';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out
+
+(* Basic commands for flow control *)
+
+type execution_summary =
+ Event
+ | Breakpoint
+ | Exited
+ | Trap_barrier
+ | Uncaught_exc
+
+type report = {
+ rep_type : execution_summary;
+ rep_event_count : int;
+ rep_stack_pointer : int;
+ rep_program_pointer : int
+}
+
+type checkpoint_report =
+ Checkpoint_done of int
+ | Checkpoint_failed
+
+(* Run the debuggee for N events *)
+
+let do_go n =
+ output_char !conn.io_out 'g';
+ output_binary_int !conn.io_out n;
+ flush !conn.io_out;
+ let summary =
+ match input_char !conn.io_in with
+ 'e' -> Event
+ | 'b' -> Breakpoint
+ | 'x' -> Exited
+ | 's' -> Trap_barrier
+ | 'u' -> Uncaught_exc
+ | _ -> Misc.fatal_error "Debugcom.do_go" in
+ let event_counter = input_binary_int !conn.io_in in
+ let stack_pos = input_binary_int !conn.io_in in
+ let pc = input_binary_int !conn.io_in in
+ { rep_type = summary;
+ rep_event_count = event_counter;
+ rep_stack_pointer = stack_pos;
+ rep_program_pointer = pc }
+
+(* Perform a checkpoint *)
+
+let do_checkpoint () =
+ output_char !conn.io_out 'c';
+ flush !conn.io_out;
+ let pid = input_binary_int !conn.io_in in
+ if pid = -1 then Checkpoint_failed else Checkpoint_done pid
+
+(* Kill the given process. *)
+let stop chan =
+ try
+ try
+ output_char chan.io_out 's';
+ flush chan.io_out
+ with
+ Sys_error _ -> ()
+ with
+ End_of_file -> ()
+
+(* Ask a process to wait for its child which has been killed. *)
+(* (so as to eliminate zombies). *)
+let wait_child chan =
+ try
+ try
+ output_char chan.io_out 'w';
+ flush chan.io_out
+ with
+ Sys_error _ -> ()
+ with
+ End_of_file -> ()
+
+(* Move to initial frame (that of current function). *)
+(* Return stack position and current pc *)
+
+let initial_frame () =
+ output_char !conn.io_out '0';
+ flush !conn.io_out;
+ let stack_pos = input_binary_int !conn.io_in in
+ let pc = input_binary_int !conn.io_in in
+ (stack_pos, pc)
+
+(* Move up one frame *)
+(* Return stack position and current pc.
+ If there's no frame above, return (-1, 0). *)
+
+let up_frame stacksize =
+ output_char !conn.io_out 'U';
+ output_binary_int !conn.io_out stacksize;
+ flush !conn.io_out;
+ let stack_pos = input_binary_int !conn.io_in in
+ let pc = if stack_pos = -1 then 0 else input_binary_int !conn.io_in in
+ (stack_pos, pc)
+
+(* Get and set the current frame position *)
+
+let get_frame () =
+ output_char !conn.io_out 'f';
+ flush !conn.io_out;
+ let stack_pos = input_binary_int !conn.io_in in
+ let pc = input_binary_int !conn.io_in in
+ (stack_pos, pc)
+
+let set_frame stack_pos =
+ output_char !conn.io_out 'S';
+ output_binary_int !conn.io_out stack_pos;
+ flush !conn.io_out
+
+(* Set the trap barrier to given stack position. *)
+
+let set_trap_barrier pos =
+ output_char !conn.io_out 'b';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out
+
+(* Handling of remote values *)
+
+type remote_value = string
+
+let value_size = if 1 lsl 31 = 0 then 4 else 8
+let big_endian =
+ let s = (Obj.magic [|0|] : string) in
+ String.unsafe_get s 0 = '\000'
+let lsb_pos = if big_endian then value_size - 1 else 0
+
+let input_remote_value ic =
+ let v = String.create value_size in
+ really_input ic v 0 value_size; v
+
+let output_remote_value ic v =
+ output ic v 0 value_size
+
+let remote_value_is_int v =
+ not(Obj.is_block(Array.unsafe_get (Obj.magic v : Obj.t array) 0))
+
+let int_value v =
+ Array.unsafe_get (Obj.magic v : int array) 0
+
+let get_local pos =
+ output_char !conn.io_out 'L';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out;
+ input_remote_value !conn.io_in
+
+let get_environment pos =
+ output_char !conn.io_out 'E';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out;
+ input_remote_value !conn.io_in
+
+let get_global pos =
+ output_char !conn.io_out 'G';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out;
+ input_remote_value !conn.io_in
+
+let get_accu () =
+ output_char !conn.io_out 'A';
+ flush !conn.io_out;
+ input_remote_value !conn.io_in
+
+let get_obj v =
+ output_char !conn.io_out 'O';
+ output_remote_value !conn.io_out v;
+ flush !conn.io_out;
+ let header = input_binary_int !conn.io_in in
+ let size = header lsr 10 in
+ let fields = Array.create size "" in
+ for i = 0 to size - 1 do fields.(i) <- input_remote_value !conn.io_in done;
+ (header land 0xFF, fields)
+
+let get_header v =
+ output_char !conn.io_out 'H';
+ output_remote_value !conn.io_out v;
+ flush !conn.io_out;
+ let header = input_binary_int !conn.io_in in
+ (header land 0xFF, header lsr 10)
+
+let get_field v n =
+ output_char !conn.io_out 'F';
+ output_remote_value !conn.io_out v;
+ output_binary_int !conn.io_out n;
+ flush !conn.io_out;
+ input_remote_value !conn.io_in
+
+let marshal_obj v =
+ output_char !conn.io_out 'M';
+ output_remote_value !conn.io_out v;
+ flush !conn.io_out;
+ input_value !conn.io_in
+
+let get_closure_code v =
+ output_char !conn.io_out 'C';
+ output_remote_value !conn.io_out v;
+ flush !conn.io_out;
+ input_binary_int !conn.io_in
+
diff --git a/debugger/debugcom.mli b/debugger/debugcom.mli
new file mode 100644
index 000000000..79d4d14dc
--- /dev/null
+++ b/debugger/debugcom.mli
@@ -0,0 +1,90 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Low-level communication with the debuggee *)
+
+type execution_summary =
+ Event
+ | Breakpoint
+ | Exited
+ | Trap_barrier
+ | Uncaught_exc
+
+type report =
+ { rep_type : execution_summary;
+ rep_event_count : int;
+ rep_stack_pointer : int;
+ rep_program_pointer : int }
+
+type checkpoint_report =
+ Checkpoint_done of int
+ | Checkpoint_failed
+
+(* Set the current connection with the debuggee *)
+val set_current_connection : Primitives.io_channel -> unit
+
+(* Put an event at given pc *)
+val set_event : int -> unit
+
+(* Put a breakpoint at given pc *)
+val set_breakpoint : int -> unit
+
+(* Remove breakpoint or event at given pc *)
+val reset_instr : int -> unit
+
+(* Create a new checkpoint (the current process forks). *)
+val do_checkpoint : unit -> checkpoint_report
+
+(* Step N events. *)
+val do_go : int -> report
+
+(* Tell given process to terminate *)
+val stop : Primitives.io_channel -> unit
+
+(* Tell given process to wait for its children *)
+val wait_child : Primitives.io_channel -> unit
+
+(* Move to initial frame (that of current function). *)
+(* Return stack position and current pc *)
+val initial_frame : unit -> int * int
+
+(* Get the current frame position *)
+(* Return stack position and current pc *)
+val get_frame : unit -> int * int
+
+(* Set the current frame *)
+val set_frame : int -> unit
+
+(* Move up one frame *)
+(* Return stack position and current pc.
+ If there's no frame above, return (-1, 0). *)
+val up_frame : int -> int * int
+
+(* Set the trap barrier to given stack position. *)
+val set_trap_barrier : int -> unit
+
+(* Handling of remote values *)
+type remote_value
+val remote_value_is_int : remote_value -> bool
+val int_value : remote_value -> int
+val get_local : int -> remote_value
+val get_environment : int -> remote_value
+val get_global : int -> remote_value
+val get_accu : unit -> remote_value
+val get_obj : remote_value -> int * remote_value array
+val get_header : remote_value -> int * int
+val get_field : remote_value -> int -> remote_value
+val marshal_obj : remote_value -> 'a
+val get_closure_code : remote_value -> int
+
diff --git a/debugger/debugger_config.ml b/debugger/debugger_config.ml
new file mode 100644
index 000000000..4f0f8bff0
--- /dev/null
+++ b/debugger/debugger_config.ml
@@ -0,0 +1,72 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(**************************** Configuration file ***********************)
+
+exception Toplevel
+
+(*** Miscellaneous parameters. ***)
+
+(*ISO 6429 color sequences
+00 to restore default color
+01 for brighter colors
+04 for underlined text
+05 for flashing text
+30 for black foreground
+31 for red foreground
+32 for green foreground
+33 for yellow (or brown) foreground
+34 for blue foreground
+35 for purple foreground
+36 for cyan foreground
+37 for white (or gray) foreground
+40 for black background
+41 for red background
+42 for green background
+43 for yellow (or brown) background
+44 for blue background
+45 for purple background
+46 for cyan background
+47 for white (or gray) background
+let debugger_prompt = "\027[1;04m(ocd)\027[0m "
+and event_mark_before = "\027[1;31m$\027[0m"
+and event_mark_after = "\027[1;34m$\027[0m"
+*)
+let debugger_prompt = "(ocd) "
+let event_mark_before = "<|b|>"
+let event_mark_after = "<|a|>"
+
+(* Name of shell used to launch the debuggee *)
+let shell = "/bin/sh"
+
+(* Name of the Objective Caml runtime. *)
+(* let runtime_program = "ocamlrun" *)
+let runtime_program = "/home/mouton/xleroy/csl-debugger/byterun/ocamlrun"
+
+(* Time history size (for `last') *)
+let history_size = ref 30
+
+(*** Time travel parameters. ***)
+
+(* Step between checkpoints for long displacements.*)
+let checkpoint_big_step = ref 10000
+
+(* Idem for small ones. *)
+let checkpoint_small_step = ref 1000
+
+(* Maximum number of checkpoints. *)
+let checkpoint_max_count = ref 15
+
+(* Whether to keep checkpoints or not. *)
+let make_checkpoints = ref true
diff --git a/debugger/debugger_config.mli b/debugger/debugger_config.mli
new file mode 100644
index 000000000..f463c7ef1
--- /dev/null
+++ b/debugger/debugger_config.mli
@@ -0,0 +1,33 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(********************** Configuration file *****************************)
+
+exception Toplevel
+
+(*** Miscellaneous parameters. ***)
+
+val debugger_prompt : string
+val event_mark_before : string
+val event_mark_after : string
+val shell : string
+val runtime_program : string
+val history_size : int ref
+
+(*** Time travel paramaters. ***)
+
+val checkpoint_big_step : int ref
+val checkpoint_small_step : int ref
+val checkpoint_max_count : int ref
+val make_checkpoints : bool ref
diff --git a/debugger/envaux.ml b/debugger/envaux.ml
new file mode 100644
index 000000000..fd1ff3e76
--- /dev/null
+++ b/debugger/envaux.ml
@@ -0,0 +1,62 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Misc
+open Types
+open Env
+
+let env_cache =
+ (Hashtbl.create 59 : (Env.summary, Env.t) Hashtbl.t)
+
+let reset_cache () =
+ Hashtbl.clear env_cache;
+ Env.reset_cache()
+
+let extract_sig env mty =
+ match Mtype.scrape env mty with
+ Tmty_signature sg -> sg
+ | _ -> fatal_error "Envaux.extract_sig"
+
+let rec env_from_summary sum =
+ try
+ Hashtbl.find env_cache sum
+ with Not_found ->
+ let env =
+ match sum with
+ Env_empty ->
+ Env.empty
+ | Env_value(s, id, desc) ->
+ Env.add_value id desc (env_from_summary s)
+ | Env_type(s, id, desc) ->
+ Env.add_type id desc (env_from_summary s)
+ | Env_exception(s, id, desc) ->
+ Env.add_exception id desc (env_from_summary s)
+ | Env_module(s, id, desc) ->
+ Env.add_module id desc (env_from_summary s)
+ | Env_modtype(s, id, desc) ->
+ Env.add_modtype id desc (env_from_summary s)
+ | Env_class(s, id, desc) ->
+ Env.add_class id desc (env_from_summary s)
+ | Env_open(s, path) ->
+ let env = env_from_summary s in
+ let mty =
+ try
+ Env.find_module path env
+ with Not_found ->
+ fatal_error "Envaux.env_from_summary"
+ in
+ Env.open_signature path (extract_sig env mty) env
+ in
+ Hashtbl.add env_cache sum env;
+ env
diff --git a/debugger/envaux.mli b/debugger/envaux.mli
new file mode 100644
index 000000000..d50ee4738
--- /dev/null
+++ b/debugger/envaux.mli
@@ -0,0 +1,21 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Convert environment summaries to environments *)
+
+val env_from_summary: Env.summary -> Env.t
+
+(* Empty the environment caches. To be called when load_path changes. *)
+
+val reset_cache: unit -> unit
diff --git a/debugger/eval.ml b/debugger/eval.ml
new file mode 100644
index 000000000..514202ce1
--- /dev/null
+++ b/debugger/eval.ml
@@ -0,0 +1,48 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Debugger_config
+open Misc
+open Path
+open Instruct
+
+let rec path env sz = function
+ Pident id ->
+ if Ident.global id then
+ Debugcom.get_global (Symtable.get_global_position id)
+ else begin
+ try
+ let pos = Ident.find_same id env.ce_stack in
+ Debugcom.get_local (sz - pos)
+ with Not_found ->
+ try
+ let pos = Ident.find_same id env.ce_heap in
+ Debugcom.get_environment pos
+ with Not_found ->
+ Format.print_string "Cannot evaluate ";
+ Printtyp.ident id;
+ Format.print_newline();
+ raise Toplevel
+ end
+ | Pdot(root, fieldname, pos) ->
+ let v = path env sz root in
+ if Debugcom.remote_value_is_int v then begin
+ Printtyp.path root;
+ Format.print_string " has not yet been initialized";
+ Format.print_newline();
+ raise Toplevel
+ end;
+ Debugcom.get_field v pos
+ | Papply(p1, p2) ->
+ fatal_error "Eval.path: Papply"
diff --git a/debugger/eval.mli b/debugger/eval.mli
new file mode 100644
index 000000000..589650d47
--- /dev/null
+++ b/debugger/eval.mli
@@ -0,0 +1,15 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+val path : Instruct.compilation_env -> int -> Path.t -> Debugcom.remote_value
diff --git a/debugger/events.ml b/debugger/events.ml
new file mode 100644
index 000000000..60178ee69
--- /dev/null
+++ b/debugger/events.ml
@@ -0,0 +1,113 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(********************************* Events ******************************)
+
+open Instruct
+open Primitives
+open Checkpoints
+
+(* Previous `pc'. *)
+(* Save time if `update_current_event' is called *)
+(* several times at the same point. *)
+let old_pc = ref (None : int option)
+
+(*** Current events. ***)
+
+(* Event at current position *)
+let current_event =
+ ref (None : debug_event option)
+
+(* Recompute the current event *)
+let update_current_event () =
+ match current_pc () with
+ None ->
+ current_event := None;
+ old_pc := None
+ | (Some pc) as opt_pc ->
+ if opt_pc <> !old_pc then begin
+ current_event := Some (Symbols.event_at_pc pc);
+ old_pc := opt_pc
+ end
+
+(* Current position in source. *)
+(* Raise `Not_found' if not on an event (beginning or end of program). *)
+let current_point () =
+ match !current_event with
+ None ->
+ raise Not_found
+ | Some {ev_char = point; ev_file = mdle} ->
+ (mdle, point)
+
+let current_event_is_before () =
+ match !current_event with
+ None ->
+ raise Not_found
+ | Some {ev_kind = Event_before} ->
+ true
+ | _ ->
+ false
+
+(*** Finding events. ***)
+
+(* List the events in `module'. *)
+let events_in_module mdle =
+ let filename = String.uncapitalize mdle ^ ".ml" in
+ filter
+ (function {ev_file = f} -> f = filename)
+ !Symbols.events
+
+(* First event after the given position. *)
+(* Raise `Not_found' if no such event. *)
+let event_after_pos mdle position =
+ match
+ List.fold_right
+ (function
+ ({ev_char = pos1} as ev) ->
+ if pos1 < position then
+ function x -> x
+ else
+ function
+ None ->
+ Some ev
+ | (Some {ev_char = pos2} as old) ->
+ if pos1 < pos2 then
+ Some ev
+ else
+ old)
+ (events_in_module mdle)
+ None
+ with
+ None ->
+ raise Not_found
+ | Some x ->
+ x
+
+(* Nearest event from given position. *)
+(* Raise `Not_found' if no such event. *)
+let event_near_pos mdle position =
+ match events_in_module mdle with
+ [] ->
+ raise Not_found
+ | [event] ->
+ event
+ | a::l ->
+ List.fold_right
+ (fun ({ev_char = pos1} as ev) ({ev_char = pos2} as old) ->
+ if abs (position - pos1) < abs (position - pos2) then
+ ev
+ else
+ old)
+ l
+ a
diff --git a/debugger/events.mli b/debugger/events.mli
new file mode 100644
index 000000000..43fa8600b
--- /dev/null
+++ b/debugger/events.mli
@@ -0,0 +1,43 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Instruct
+
+(** Current events. **)
+
+(* The event at current position. *)
+val current_event : debug_event option ref
+
+(* Recompute the current event *)
+val update_current_event : unit -> unit
+
+(* Current position in source. *)
+(* Raise `Not_found' if not on an event (beginning or end of program). *)
+val current_point : unit -> string * int
+
+val current_event_is_before : unit -> bool
+
+(** Finding events. **)
+
+(* List the events in `module'. *)
+(* ### module -> event_list *)
+val events_in_module : string -> debug_event list
+
+(* First event after the given position. *)
+(* --- Raise `Not_found' if no such event. *)
+val event_after_pos : string -> int -> debug_event
+
+(* Nearest event from given position. *)
+(* --- Raise `Not_found' if no such event. *)
+val event_near_pos : string -> int -> debug_event
diff --git a/debugger/exec.ml b/debugger/exec.ml
new file mode 100644
index 000000000..d35becb37
--- /dev/null
+++ b/debugger/exec.ml
@@ -0,0 +1,49 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Handling of keyboard interrupts *)
+
+let interrupted = ref false
+
+let protect = ref false
+
+let break signum =
+ if !protect
+ then interrupted := true
+ else raise Sys.Break
+
+let _ =
+ Sys.signal Sys.sigint (Sys.Signal_handle break);
+ Sys.signal Sys.sigpipe (Sys.Signal_handle (fun _ -> raise End_of_file))
+
+let protected f =
+ if !protect then
+ f ()
+ else begin
+ protect := true;
+ if not !interrupted then
+ f ();
+ protect := false;
+ if !interrupted then begin interrupted := false; raise Sys.Break end
+ end
+
+let unprotected f =
+ if not !protect then
+ f ()
+ else begin
+ protect := false;
+ if !interrupted then begin interrupted := false; raise Sys.Break end;
+ f ();
+ protect := true
+ end
diff --git a/debugger/exec.mli b/debugger/exec.mli
new file mode 100644
index 000000000..ab2034621
--- /dev/null
+++ b/debugger/exec.mli
@@ -0,0 +1,18 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Handling of keyboard interrupts *)
+
+val protected : (unit -> unit) -> unit
+val unprotected : (unit -> unit) -> unit
diff --git a/debugger/frames.ml b/debugger/frames.ml
new file mode 100644
index 000000000..b85426b5a
--- /dev/null
+++ b/debugger/frames.ml
@@ -0,0 +1,127 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(***************************** Frames **********************************)
+
+open Instruct
+open Primitives
+open Debugcom
+open Checkpoints
+open Events
+open Symbols
+
+(* Current frame number *)
+let current_frame = ref 0
+
+(* Event at selected position *)
+let selected_event = ref (None : debug_event option)
+
+(* Selected position in source. *)
+(* Raise `Not_found' if not on an event. *)
+let selected_point () =
+ match !selected_event with
+ None ->
+ raise Not_found
+ | Some {ev_char = point; ev_file = mdle} ->
+ (mdle, point)
+
+let selected_event_is_before () =
+ match !selected_event with
+ None ->
+ raise Not_found
+ | Some {ev_kind = Event_before} ->
+ true
+ | _ ->
+ false
+
+(* Move up `frame_count' frames, assuming current frame pointer
+ corresponds to event `event'. Return event of final frame. *)
+
+let rec move_up frame_count event =
+ if frame_count <= 0 then event else begin
+ let (sp, pc) = up_frame event.ev_stacksize in
+ if sp < 0 then raise Not_found;
+ move_up (frame_count - 1) (event_at_pc pc)
+ end
+
+(* Select a frame. *)
+(* Raise `Not_found' if no such frame. *)
+(* --- Assume the current events have already been updated. *)
+let select_frame frame_number =
+ let (initial_sp, _) = get_frame() in
+ try
+ match !current_event with
+ None ->
+ raise Not_found
+ | Some curr_event ->
+ match !selected_event with
+ Some sel_event when frame_number >= !current_frame ->
+ selected_event :=
+ Some(move_up (frame_number - !current_frame) sel_event);
+ current_frame := frame_number
+ | _ ->
+ initial_frame();
+ selected_event := Some(move_up frame_number curr_event);
+ current_frame := frame_number
+ with Not_found ->
+ set_frame initial_sp;
+ raise Not_found
+
+(* Select a frame. *)
+(* Same as `select_frame' but raise no exception if the frame is not found. *)
+(* --- Assume the currents events have already been updated. *)
+let try_select_frame frame_number =
+ try
+ select_frame frame_number
+ with
+ Not_found ->
+ ()
+
+(* Return to default frame (frame 0). *)
+let reset_frame () =
+ initial_frame();
+ selected_event := !current_event;
+ current_frame := 0
+
+(* Perform a stack backtrace.
+ Call the given function with the events for each stack frame,
+ or None if we've encountered a stack frame with no debugging info
+ attached. Stop when the function returns false, or frame with no
+ debugging info reached, or top of stack reached. *)
+
+let do_backtrace action =
+ match !current_event with
+ None -> Misc.fatal_error "Frames.do_backtrace"
+ | Some curr_ev ->
+ let (initial_sp, _) = get_frame() in
+ initial_frame();
+ let event = ref curr_ev in
+ begin try
+ while action (Some !event) do
+ let (sp, pc) = up_frame !event.ev_stacksize in
+ if sp < 0 then raise Exit;
+ event := event_at_pc pc
+ done
+ with Exit -> ()
+ | Not_found -> action None; ()
+ end;
+ set_frame initial_sp
+
+(* Return the number of frames in the stack *)
+
+let stack_depth () =
+ let num_frames = ref 0 in
+ do_backtrace (function Some ev -> incr num_frames; true
+ | None -> num_frames := -1; false);
+ !num_frames
diff --git a/debugger/frames.mli b/debugger/frames.mli
new file mode 100644
index 000000000..7a683c834
--- /dev/null
+++ b/debugger/frames.mli
@@ -0,0 +1,54 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(****************************** Frames *********************************)
+
+open Instruct
+open Primitives
+
+(* Current frame number *)
+val current_frame : int ref
+
+(* Event at selected position. *)
+val selected_event : debug_event option ref
+
+(* Selected position in source. *)
+(* Raise `Not_found' if not on an event. *)
+val selected_point : unit -> string * int
+
+val selected_event_is_before : unit -> bool
+
+(* Select a frame. *)
+(* Raise `Not_found' if no such frame. *)
+(* --- Assume the currents events have already been updated. *)
+val select_frame : int -> unit
+
+(* Select a frame. *)
+(* Same as `select_frame' but raise no exception if the frame is not found. *)
+(* --- Assume the currents events have already been updated. *)
+val try_select_frame : int -> unit
+
+(* Return to default frame (frame 0). *)
+val reset_frame : unit -> unit
+
+(* Perform a stack backtrace.
+ Call the given function with the events for each stack frame,
+ or None if we've encountered a stack frame with no debugging info
+ attached. Stop when the function returns false, or frame with no
+ debugging info reached, or top of stack reached. *)
+val do_backtrace : (debug_event option -> bool) -> unit
+
+(* Return the number of frames in the stack, or (-1) if it can't be
+ determined because some frames have no debugging info. *)
+val stack_depth : unit -> int
diff --git a/debugger/history.ml b/debugger/history.ml
new file mode 100644
index 000000000..de3d95221
--- /dev/null
+++ b/debugger/history.ml
@@ -0,0 +1,42 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Checkpoints
+open Misc
+open Primitives
+open Debugger_config
+
+let history = ref ([] : int list)
+
+let empty_history () =
+ history := []
+
+let add_current_time () =
+ let time = current_time () in
+ if history = ref [] then
+ history := [time]
+ else if time <> List.hd !history then
+ history := list_truncate !history_size (time::!history)
+
+let previous_time_1 () =
+ match !history with
+ _::((time::_) as hist) ->
+ history := hist; time
+ | _ ->
+ prerr_endline "No more information."; raise Toplevel
+
+let rec previous_time n =
+ if n = 1
+ then previous_time_1()
+ else begin previous_time_1(); previous_time(n-1) end
diff --git a/debugger/history.mli b/debugger/history.mli
new file mode 100644
index 000000000..78b208fb1
--- /dev/null
+++ b/debugger/history.mli
@@ -0,0 +1,19 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+val empty_history : unit -> unit
+
+val add_current_time : unit -> unit
+
+val previous_time : int -> int
diff --git a/debugger/input_handling.ml b/debugger/input_handling.ml
new file mode 100644
index 000000000..47f466cd7
--- /dev/null
+++ b/debugger/input_handling.ml
@@ -0,0 +1,145 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(**************************** Input control ****************************)
+
+open Unix
+open Primitives
+
+(*** Actives files. ***)
+
+(* List of the actives files. *)
+let active_files =
+ ref ([] : (file_descr * ((io_channel -> unit) * io_channel)) list)
+
+(* Add a file to the list of actives files. *)
+let add_file file controller =
+ active_files := (file.io_fd, (controller, file))::!active_files
+
+(* Remove a file from the list of actives files. *)
+let remove_file file =
+ active_files := assoc_remove !active_files file.io_fd
+
+(* Change the controller for the given file. *)
+let change_controller file controller =
+ remove_file file; add_file file controller
+
+(* Return the controller currently attached to the given file. *)
+let current_controller file =
+ fst (List.assoc file.io_fd !active_files)
+
+(* Execute a function with `controller' attached to `file'. *)
+(* ### controller file funct *)
+let execute_with_other_controller controller file funct =
+ let old_controller = current_controller file in
+ change_controller file controller;
+ try
+ let result = funct () in
+ change_controller file old_controller;
+ result
+ with
+ x ->
+ change_controller file old_controller;
+ raise x
+
+(*** The "Main Loop" ***)
+
+let continue_main_loop =
+ ref true
+
+let exit_main_loop _ =
+ continue_main_loop := false
+
+(* Handle active files until `continue_main_loop' is false. *)
+let main_loop () =
+ let old_state = !continue_main_loop in
+ try
+ continue_main_loop := true;
+ while !continue_main_loop do
+ try
+ let (input, _, _) = select (List.map fst !active_files) [] [] (-1.) in
+ List.iter
+ (function fd ->
+ let (funct, iochan) = (List.assoc fd !active_files) in
+ funct iochan)
+ input
+ with
+ Unix_error (EINTR, _, _) -> prerr_endline "EINTR";()
+ done;
+ continue_main_loop := old_state
+ with
+ x ->
+ continue_main_loop := old_state;
+ raise x
+
+(*** Managing user inputs ***)
+
+(* Are we in interactive mode ? *)
+let interactif = ref true
+
+let current_prompt = ref ""
+
+(* Where the user input come from. *)
+let user_channel = ref std_io
+
+let read_user_input buffer length =
+ main_loop ();
+ input !user_channel.io_in buffer 0 length
+
+(* Stop reading user input. *)
+let stop_user_input () =
+ remove_file !user_channel
+
+(* Resume reading user input. *)
+let resume_user_input () =
+ if not (List.mem_assoc !user_channel.io_fd !active_files) then begin
+ if !interactif then begin
+ print_string !current_prompt;
+ flush Pervasives.stdout
+ end;
+ add_file !user_channel exit_main_loop
+ end
+
+(* Ask user a yes or no question. *)
+let yes_or_no message =
+ if !interactif then
+ let old_prompt = !current_prompt in
+ try
+ current_prompt := message ^ " ? (y or n) ";
+ let answer =
+ let rec ask () =
+ resume_user_input ();
+ let line =
+ string_trim (Lexer.line (Lexing.from_function read_user_input))
+ in
+ stop_user_input ();
+ match (if String.length line > 0 then line.[0] else ' ') with
+ 'y' -> true
+ | 'n' -> false
+ | _ ->
+ print_string "Please answer y or n.";
+ print_newline ();
+ ask ()
+ in
+ ask ()
+ in
+ current_prompt := old_prompt;
+ answer
+ with
+ x ->
+ current_prompt := old_prompt;
+ stop_user_input ();
+ raise x
+ else
+ false
diff --git a/debugger/input_handling.mli b/debugger/input_handling.mli
new file mode 100644
index 000000000..b3fbc4ff9
--- /dev/null
+++ b/debugger/input_handling.mli
@@ -0,0 +1,62 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(***************************** Input control ***************************)
+
+open Primitives
+
+(*** Actives files. ***)
+
+(* Add a file to the list of active files. *)
+val add_file : io_channel -> (io_channel -> unit) -> unit
+
+(* Remove a file from the list of actives files. *)
+val remove_file : io_channel -> unit
+
+(* Return the controller currently attached to the given file. *)
+val current_controller : io_channel -> (io_channel -> unit)
+
+(* Execute a function with `controller' attached to `file'. *)
+(* ### controller file funct *)
+val execute_with_other_controller :
+ (io_channel -> unit) -> io_channel -> (unit -> 'a) -> 'a
+
+(*** The "Main Loop" ***)
+
+(* Call this function for exiting the main loop. *)
+val exit_main_loop : 'a -> unit
+
+(* Handle active files until `continue_main_loop' is false. *)
+val main_loop : unit -> unit
+
+(*** Managing user inputs ***)
+
+(* Are we in interactive mode ? *)
+val interactif : bool ref
+
+val current_prompt : string ref
+
+(* Where the user input come from. *)
+val user_channel : io_channel ref
+
+val read_user_input : string -> int -> int
+
+(* Stop reading user input. *)
+val stop_user_input : unit -> unit
+
+(* Resume reading user input. *)
+val resume_user_input : unit -> unit
+
+(* Ask user a yes or no question. *)
+val yes_or_no : string -> bool
diff --git a/debugger/lexer.ml b/debugger/lexer.ml
new file mode 100644
index 000000000..a74b9d477
--- /dev/null
+++ b/debugger/lexer.ml
@@ -0,0 +1,747 @@
+
+
+open Primitives
+open Parser
+
+let lex_tables = {
+ Lexing.lex_base =
+ "\000\000\002\000\001\000\035\000\232\255\231\255\000\000\194\000\
+ \100\000\247\255\242\255\241\255\231\000\244\255\012\001\029\001\
+ \053\000\053\000\236\255\083\001\120\001\157\001\219\001\240\255\
+ \239\255\017\000\171\002\238\255\237\255\123\003\075\004\027\005\
+ \235\005\187\006\139\007\091\008\248\255\058\009\245\255\065\000\
+ \075\000\087\000\038\002\246\002\100\000\084\000\228\000\252\255\
+ \229\000\254\255\003\000\253\255\233\000\234\000\238\000\251\000\
+ \004\000\255\255";
+ Lexing.lex_backtrk =
+ "\001\000\255\255\000\000\255\255\255\255\255\255\000\000\022\000\
+ \024\000\255\255\255\255\255\255\005\000\255\255\006\000\004\000\
+ \004\000\024\000\255\255\020\000\021\000\009\000\002\000\255\255\
+ \255\255\012\000\002\000\255\255\255\255\002\000\255\255\002\000\
+ \002\000\002\000\002\000\001\000\255\255\022\000\255\255\004\000\
+ \255\255\255\255\255\255\004\000\004\000\004\000\255\255\255\255\
+ \000\000\255\255\000\000\255\255\000\000\001\000\001\000\000\000\
+ \001\000\255\255";
+ Lexing.lex_default =
+ "\056\000\052\000\050\000\022\000\000\000\000\000\255\255\255\255\
+ \046\000\000\000\000\000\000\000\255\255\000\000\255\255\255\255\
+ \255\255\255\255\000\000\255\255\255\255\255\255\255\255\000\000\
+ \000\000\255\255\255\255\000\000\000\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\000\000\255\255\000\000\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\046\000\000\000\
+ \255\255\000\000\050\000\000\000\055\000\255\255\255\255\055\000\
+ \056\000\000\000";
+ Lexing.lex_trans =
+ "\051\000\049\000\051\000\255\255\255\255\000\000\000\000\000\000\
+ \000\000\048\000\057\000\053\000\000\000\000\000\057\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \048\000\000\000\053\000\004\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\006\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\006\000\007\000\008\000\009\000\005\000\
+ \007\000\007\000\005\000\010\000\011\000\012\000\007\000\013\000\
+ \014\000\005\000\007\000\015\000\016\000\016\000\016\000\016\000\
+ \016\000\016\000\016\000\016\000\016\000\017\000\018\000\007\000\
+ \019\000\020\000\007\000\021\000\255\255\039\000\039\000\039\000\
+ \039\000\039\000\039\000\039\000\039\000\039\000\039\000\038\000\
+ \036\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\
+ \039\000\039\000\039\000\045\000\045\000\000\000\023\000\005\000\
+ \024\000\007\000\025\000\005\000\045\000\045\000\047\000\044\000\
+ \044\000\044\000\044\000\044\000\044\000\044\000\044\000\000\000\
+ \000\000\000\000\000\000\026\000\044\000\044\000\044\000\044\000\
+ \044\000\044\000\044\000\044\000\000\000\000\000\027\000\007\000\
+ \028\000\007\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\
+ \005\000\005\000\005\000\037\000\255\255\000\000\037\000\037\000\
+ \037\000\255\255\000\000\000\000\037\000\037\000\048\000\037\000\
+ \037\000\037\000\255\255\054\000\000\000\000\000\000\000\054\000\
+ \000\000\000\000\005\000\255\255\037\000\037\000\037\000\037\000\
+ \037\000\037\000\037\000\000\000\255\255\048\000\047\000\000\000\
+ \037\000\255\255\054\000\037\000\037\000\037\000\054\000\000\000\
+ \000\000\037\000\037\000\000\000\037\000\037\000\037\000\000\000\
+ \000\000\000\000\005\000\255\255\000\000\000\000\000\000\000\000\
+ \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\
+ \000\000\000\000\000\000\000\000\000\000\037\000\000\000\000\000\
+ \037\000\037\000\037\000\000\000\000\000\000\000\037\000\037\000\
+ \000\000\037\000\037\000\037\000\000\000\000\000\037\000\000\000\
+ \037\000\000\000\000\000\000\000\000\000\037\000\037\000\037\000\
+ \037\000\037\000\037\000\037\000\037\000\039\000\039\000\039\000\
+ \039\000\039\000\039\000\039\000\039\000\039\000\039\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\040\000\
+ \000\000\000\000\000\000\037\000\000\000\037\000\000\000\000\000\
+ \000\000\000\000\037\000\000\000\041\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\037\000\042\000\000\000\037\000\
+ \037\000\037\000\000\000\000\000\000\000\037\000\037\000\040\000\
+ \037\000\037\000\037\000\000\000\000\000\000\000\000\000\000\000\
+ \037\000\000\000\037\000\000\000\041\000\037\000\037\000\037\000\
+ \037\000\037\000\037\000\037\000\000\000\042\000\000\000\000\000\
+ \000\000\037\000\000\000\000\000\037\000\037\000\037\000\000\000\
+ \000\000\000\000\037\000\037\000\000\000\037\000\037\000\037\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\
+ \037\000\000\000\000\000\000\000\000\000\000\000\037\000\000\000\
+ \000\000\037\000\037\000\037\000\000\000\000\000\000\000\037\000\
+ \037\000\000\000\037\000\037\000\037\000\000\000\000\000\037\000\
+ \000\000\037\000\000\000\000\000\000\000\000\000\037\000\037\000\
+ \037\000\037\000\037\000\037\000\037\000\037\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\037\000\000\000\037\000\000\000\
+ \000\000\000\000\000\000\037\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\029\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\
+ \000\000\037\000\000\000\037\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\030\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\043\000\043\000\
+ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\043\000\
+ \043\000\043\000\043\000\043\000\043\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\043\000\
+ \043\000\043\000\043\000\043\000\043\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\030\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\031\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\043\000\043\000\
+ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\043\000\
+ \043\000\043\000\043\000\043\000\043\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\043\000\
+ \043\000\043\000\043\000\043\000\043\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\030\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\030\000\000\000\029\000\029\000\029\000\029\000\
+ \032\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\030\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\033\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\030\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\034\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\030\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\035\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\030\000\000\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\000\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\037\000\000\000\000\000\037\000\037\000\
+ \037\000\000\000\000\000\000\000\037\000\037\000\000\000\037\000\
+ \037\000\037\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\037\000\037\000\037\000\037\000\
+ \037\000\037\000\037\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \037\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\037\000\000\000\
+ \037\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+ \000\000\000\000";
+ Lexing.lex_check =
+ "\000\000\002\000\001\000\050\000\056\000\255\255\255\255\255\255\
+ \255\255\006\000\000\000\001\000\255\255\255\255\056\000\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \006\000\255\255\001\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\008\000\016\000\016\000\016\000\
+ \016\000\016\000\016\000\016\000\016\000\016\000\016\000\017\000\
+ \025\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\
+ \039\000\039\000\039\000\040\000\040\000\255\255\003\000\003\000\
+ \003\000\003\000\003\000\003\000\045\000\045\000\008\000\041\000\
+ \041\000\041\000\041\000\041\000\041\000\041\000\041\000\255\255\
+ \255\255\255\255\255\255\003\000\044\000\044\000\044\000\044\000\
+ \044\000\044\000\044\000\044\000\255\255\255\255\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\003\000\003\000\003\000\003\000\003\000\
+ \003\000\003\000\003\000\007\000\046\000\255\255\007\000\007\000\
+ \007\000\052\000\255\255\255\255\007\000\007\000\048\000\007\000\
+ \007\000\007\000\052\000\053\000\255\255\255\255\255\255\054\000\
+ \255\255\255\255\003\000\055\000\007\000\007\000\007\000\007\000\
+ \007\000\007\000\007\000\255\255\055\000\048\000\046\000\255\255\
+ \012\000\052\000\053\000\012\000\012\000\012\000\054\000\255\255\
+ \255\255\012\000\012\000\255\255\012\000\012\000\012\000\255\255\
+ \255\255\255\255\003\000\055\000\255\255\255\255\255\255\255\255\
+ \007\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\
+ \255\255\255\255\255\255\255\255\255\255\014\000\255\255\255\255\
+ \014\000\014\000\014\000\255\255\255\255\255\255\014\000\014\000\
+ \255\255\014\000\014\000\014\000\255\255\255\255\007\000\255\255\
+ \007\000\255\255\255\255\255\255\255\255\012\000\014\000\014\000\
+ \014\000\014\000\014\000\014\000\014\000\015\000\015\000\015\000\
+ \015\000\015\000\015\000\015\000\015\000\015\000\015\000\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\015\000\
+ \255\255\255\255\255\255\012\000\255\255\012\000\255\255\255\255\
+ \255\255\255\255\014\000\255\255\015\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\019\000\015\000\255\255\019\000\
+ \019\000\019\000\255\255\255\255\255\255\019\000\019\000\015\000\
+ \019\000\019\000\019\000\255\255\255\255\255\255\255\255\255\255\
+ \014\000\255\255\014\000\255\255\015\000\019\000\019\000\019\000\
+ \019\000\019\000\019\000\019\000\255\255\015\000\255\255\255\255\
+ \255\255\020\000\255\255\255\255\020\000\020\000\020\000\255\255\
+ \255\255\255\255\020\000\020\000\255\255\020\000\020\000\020\000\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\019\000\020\000\020\000\020\000\020\000\020\000\020\000\
+ \020\000\255\255\255\255\255\255\255\255\255\255\021\000\255\255\
+ \255\255\021\000\021\000\021\000\255\255\255\255\255\255\021\000\
+ \021\000\255\255\021\000\021\000\021\000\255\255\255\255\019\000\
+ \255\255\019\000\255\255\255\255\255\255\255\255\020\000\021\000\
+ \021\000\021\000\021\000\021\000\021\000\021\000\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\020\000\255\255\020\000\255\255\
+ \255\255\255\255\255\255\021\000\255\255\255\255\255\255\255\255\
+ \255\255\255\255\022\000\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\255\255\255\255\255\255\
+ \255\255\021\000\255\255\021\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\255\255\255\255\
+ \255\255\255\255\022\000\255\255\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\042\000\042\000\
+ \042\000\042\000\042\000\042\000\042\000\042\000\042\000\042\000\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\042\000\
+ \042\000\042\000\042\000\042\000\042\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\042\000\
+ \042\000\042\000\042\000\042\000\042\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\255\255\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\026\000\022\000\022\000\022\000\022\000\022\000\
+ \022\000\022\000\022\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\255\255\255\255\
+ \255\255\255\255\026\000\255\255\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\043\000\043\000\
+ \043\000\043\000\043\000\043\000\043\000\043\000\043\000\043\000\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\043\000\
+ \043\000\043\000\043\000\043\000\043\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\043\000\
+ \043\000\043\000\043\000\043\000\043\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\255\255\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\029\000\026\000\026\000\026\000\026\000\026\000\
+ \026\000\026\000\026\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\255\255\255\255\
+ \255\255\255\255\029\000\255\255\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\255\255\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\030\000\029\000\029\000\029\000\029\000\029\000\
+ \029\000\029\000\029\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\255\255\255\255\
+ \255\255\255\255\255\255\255\255\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\255\255\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\031\000\030\000\030\000\030\000\030\000\030\000\
+ \030\000\030\000\030\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\255\255\255\255\
+ \255\255\255\255\031\000\255\255\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\255\255\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\032\000\031\000\031\000\031\000\031\000\031\000\
+ \031\000\031\000\031\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\255\255\255\255\
+ \255\255\255\255\032\000\255\255\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\255\255\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\033\000\032\000\032\000\032\000\032\000\032\000\
+ \032\000\032\000\032\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\255\255\255\255\
+ \255\255\255\255\033\000\255\255\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\255\255\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\034\000\033\000\033\000\033\000\033\000\033\000\
+ \033\000\033\000\033\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\255\255\255\255\
+ \255\255\255\255\034\000\255\255\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\255\255\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\035\000\034\000\034\000\034\000\034\000\034\000\
+ \034\000\034\000\034\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\255\255\255\255\
+ \255\255\255\255\035\000\255\255\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\255\255\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\255\255\035\000\035\000\035\000\035\000\035\000\
+ \035\000\035\000\035\000\037\000\255\255\255\255\037\000\037\000\
+ \037\000\255\255\255\255\255\255\037\000\037\000\255\255\037\000\
+ \037\000\037\000\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\037\000\037\000\037\000\037\000\
+ \037\000\037\000\037\000\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \037\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\037\000\255\255\
+ \037\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+ \255\255\255\255"
+}
+
+let rec line lexbuf =
+ match Lexing.engine lex_tables 0 lexbuf with
+ 0 -> ( let line =
+ Lexing.lexeme lexbuf
+ in
+ String.sub line 0 (String.length line - 1) )
+ | 1 -> ( Lexing.lexeme lexbuf )
+ | 2 -> ( raise Exit )
+ | _ -> lexbuf.Lexing.refill_buff lexbuf; line lexbuf
+
+and argument lexbuf =
+ match Lexing.engine lex_tables 1 lexbuf with
+ 0 -> ( ARGUMENT (Lexing.lexeme lexbuf) )
+ | 1 -> ( argument lexbuf )
+ | 2 -> ( EOL )
+ | 3 -> ( raise Parsing.Parse_error )
+ | _ -> lexbuf.Lexing.refill_buff lexbuf; argument lexbuf
+
+and line_argument lexbuf =
+ match Lexing.engine lex_tables 2 lexbuf with
+ 0 -> ( ARGUMENT (Lexing.lexeme lexbuf) )
+ | 1 -> ( EOL )
+ | _ -> lexbuf.Lexing.refill_buff lexbuf; line_argument lexbuf
+
+and lexeme lexbuf =
+ match Lexing.engine lex_tables 3 lexbuf with
+ 0 -> ( lexeme lexbuf )
+ | 1 -> ( PREFIX )
+ | 2 -> ( IDENTIFIER (Lexing.lexeme lexbuf) )
+ | 3 -> ( let s = Lexing.lexeme lexbuf in
+ IDENTIFIER (String.sub s 1 (String.length s - 2)) )
+ | 4 -> ( INTEGER (int_of_string (Lexing.lexeme lexbuf)) )
+ | 5 -> ( STAR )
+ | 6 -> ( MINUS )
+ | 7 -> ( UNDERUNDER )
+ | 8 -> ( SHARP )
+ | 9 -> ( AT )
+ | 10 -> ( COLONCOLON )
+ | 11 -> ( COMMA )
+ | 12 -> ( UNDERSCORE )
+ | 13 -> ( LPAREN )
+ | 14 -> ( RPAREN )
+ | 15 -> ( LBRACKET )
+ | 16 -> ( RBRACKET )
+ | 17 -> ( LBRACE )
+ | 18 -> ( RBRACE )
+ | 19 -> ( SEMI )
+ | 20 -> ( EQUAL )
+ | 21 -> ( SUPERIOR )
+ | 22 -> ( OPERATOR (Lexing.lexeme lexbuf) )
+ | 23 -> ( EOL )
+ | 24 -> ( raise Parsing.Parse_error )
+ | _ -> lexbuf.Lexing.refill_buff lexbuf; lexeme lexbuf
+
diff --git a/debugger/main.ml b/debugger/main.ml
new file mode 100644
index 000000000..c988dc2bf
--- /dev/null
+++ b/debugger/main.ml
@@ -0,0 +1,133 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Primitives
+open Misc
+open Input_handling
+open Command_line_interpreter
+open Debugger_config
+open Checkpoints
+open Time_travel
+open Parameters
+open Program_management
+open Frames
+open Show_information
+
+let toplevel_loop () =
+ let line_buffer = Lexing.from_function read_user_input in
+ let rec loop () =
+ try
+ let rec loop2 () =
+ (try
+ line_loop line_buffer
+ with
+ End_of_file ->
+ forget_process
+ !current_checkpoint.c_fd
+ !current_checkpoint.c_pid;
+ flush stdout;
+ stop_user_input ();
+ loop2 ());
+ if !loaded & (not (yes_or_no "The program is running. Quit anyway")) then
+ loop2 ()
+ in
+ loop2 ()
+ with
+ Toplevel ->
+ flush stdout;
+ stop_user_input ();
+ loop ()
+ | Sys.Break ->
+ (try
+ print_endline "Interrupted.";
+ Exec.protected
+ (function () ->
+ flush stdout;
+ stop_user_input ();
+ if !loaded then
+ ((try select_frame 0 with Not_found -> ());
+ show_current_event ()))
+ with Sys.Break -> ());
+ loop ()
+ | Current_checkpoint_lost ->
+ (try
+ print_endline "Trying to recover...";
+ flush stdout;
+ stop_user_input ();
+ recover ();
+ (try select_frame 0 with Not_found -> ());
+ show_current_event ()
+ with
+ x ->
+ if x = Sys.Break then
+ print_endline "Interrupted";
+ print_endline "Can't recover; killing program...";
+ flush stdout;
+ kill_program ());
+ loop ()
+ | Not_found ->
+ print_endline "Cannot find file ";
+ flush stdout;
+ stop_user_input ();
+ loop ()
+ | x ->
+ kill_program ();
+ raise x
+ in
+ loop ()
+
+let anonymous s =
+ if !program_name = ""
+ then program_name := s
+ else arguments := Printf.sprintf "%s '%s'" !arguments s
+let add_include d =
+ default_load_path := 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 set_emacs () =
+ emacs := true
+
+let main () =
+ try
+ socket_name := "/tmp/camldebug" ^ (string_of_int (Unix.getpid ()));
+ Arg.parse
+ ["-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";
+ "-c", Arg.Int set_checkpoints,
+ "<count> Set max number of checkpoints kept";
+ "-cd", Arg.String set_directory,
+ "<dir> Change working directory";
+ "-emacs", Arg.Unit set_emacs,
+ "For running the debugger under emacs"]
+ anonymous
+ "";
+ current_prompt := debugger_prompt;
+ print_string "\tObjective Caml Debugger version ";
+ print_string Config.version;
+ print_newline(); print_newline();
+ Config.load_path := !default_load_path;
+ toplevel_loop (); (* Toplevel. *)
+ kill_program ();
+ exit 0
+ with Toplevel ->
+ exit 2
+
+let _ =
+ Printexc.catch (Unix.handle_unix_error main) ()
diff --git a/debugger/parameters.ml b/debugger/parameters.ml
new file mode 100644
index 000000000..c70dc4c93
--- /dev/null
+++ b/debugger/parameters.ml
@@ -0,0 +1,33 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Miscellaneous parameters *)
+
+open Primitives
+open Config
+open Misc
+
+let program_loaded = ref false
+let program_name = ref ""
+let socket_name = ref ""
+let arguments = ref ""
+
+let default_load_path = ref [ "."; Config.standard_library ]
+
+let add_path dir =
+ load_path := dir :: except dir !load_path;
+ Envaux.reset_cache()
+
+(* Used by emacs ? *)
+let emacs = ref false
diff --git a/debugger/parameters.mli b/debugger/parameters.mli
new file mode 100644
index 000000000..11505a4c7
--- /dev/null
+++ b/debugger/parameters.mli
@@ -0,0 +1,25 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Miscellaneous parameters *)
+
+val program_name : string ref
+val socket_name : string ref
+val arguments : string ref
+val default_load_path : string list ref
+
+val add_path : string -> unit
+
+(* Used by emacs ? *)
+val emacs : bool ref
diff --git a/debugger/parser.ml b/debugger/parser.ml
new file mode 100644
index 000000000..98fb5ffa0
--- /dev/null
+++ b/debugger/parser.ml
@@ -0,0 +1,405 @@
+type token =
+ ARGUMENT of (string)
+ | IDENTIFIER of (string)
+ | INTEGER of (int)
+ | STAR
+ | MINUS
+ | UNDERUNDER
+ | SHARP
+ | AT
+ | COLONCOLON
+ | COMMA
+ | UNDERSCORE
+ | LPAREN
+ | RPAREN
+ | LBRACKET
+ | RBRACKET
+ | LBRACE
+ | RBRACE
+ | SEMI
+ | EQUAL
+ | SUPERIOR
+ | PREFIX
+ | OPERATOR of (string)
+ | EOL
+
+open Parsing
+
+open Primitives
+open Input_handling
+open Parser_aux
+
+(* Line 8, file parser.ml *)
+let yytransl_const = [|
+ 260 (* STAR *);
+ 261 (* MINUS *);
+ 262 (* UNDERUNDER *);
+ 263 (* SHARP *);
+ 264 (* AT *);
+ 265 (* COLONCOLON *);
+ 266 (* COMMA *);
+ 267 (* UNDERSCORE *);
+ 268 (* LPAREN *);
+ 269 (* RPAREN *);
+ 270 (* LBRACKET *);
+ 271 (* RBRACKET *);
+ 272 (* LBRACE *);
+ 273 (* RBRACE *);
+ 274 (* SEMI *);
+ 275 (* EQUAL *);
+ 276 (* SUPERIOR *);
+ 277 (* PREFIX *);
+ 279 (* EOL *);
+ 0|]
+
+let yytransl_block = [|
+ 257 (* ARGUMENT *);
+ 258 (* IDENTIFIER *);
+ 259 (* INTEGER *);
+ 278 (* OPERATOR *);
+ 0|]
+
+let yylhs = "\255\255\
+\001\000\001\000\002\000\003\000\003\000\004\000\005\000\006\000\
+\006\000\007\000\007\000\008\000\009\000\010\000\010\000\017\000\
+\017\000\011\000\011\000\012\000\012\000\019\000\020\000\020\000\
+\020\000\020\000\020\000\020\000\020\000\018\000\018\000\018\000\
+\013\000\013\000\013\000\013\000\013\000\015\000\015\000\014\000\
+\022\000\022\000\023\000\023\000\024\000\025\000\025\000\021\000\
+\021\000\021\000\021\000\021\000\026\000\026\000\026\000\026\000\
+\026\000\026\000\026\000\016\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000"
+
+let yylen = "\002\000\
+\002\000\001\000\002\000\002\000\001\000\002\000\001\000\002\000\
+\001\000\002\000\001\000\001\000\002\000\001\000\001\000\001\000\
+\000\000\002\000\001\000\002\000\001\000\002\000\001\000\002\000\
+\002\000\002\000\002\000\002\000\002\000\001\000\003\000\001\000\
+\001\000\001\000\001\000\004\000\004\000\003\000\001\000\003\000\
+\003\000\001\000\003\000\001\000\003\000\003\000\003\000\001\000\
+\003\000\001\000\002\000\002\000\001\000\001\000\002\000\003\000\
+\003\000\003\000\003\000\001\000\002\000\002\000\002\000\002\000\
+\002\000\002\000\002\000\002\000\002\000\002\000\002\000\002\000\
+\002\000\002\000\002\000\002\000"
+
+let yydefred = "\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\060\000\061\000\002\000\000\000\062\000\000\000\
+\063\000\005\000\000\000\064\000\007\000\065\000\000\000\066\000\
+\009\000\000\000\011\000\067\000\012\000\068\000\000\000\069\000\
+\014\000\070\000\015\000\000\000\071\000\019\000\000\000\032\000\
+\000\000\072\000\021\000\000\000\030\000\000\000\034\000\073\000\
+\033\000\000\000\035\000\074\000\000\000\000\000\039\000\075\000\
+\000\000\076\000\001\000\003\000\004\000\006\000\008\000\010\000\
+\013\000\018\000\000\000\024\000\025\000\026\000\027\000\028\000\
+\029\000\020\000\016\000\000\000\022\000\000\000\000\000\053\000\
+\000\000\000\000\000\000\000\000\054\000\000\000\000\000\000\000\
+\048\000\000\000\023\000\031\000\000\000\000\000\000\000\000\000\
+\055\000\000\000\000\000\000\000\000\000\000\000\052\000\051\000\
+\000\000\000\000\040\000\000\000\038\000\036\000\037\000\000\000\
+\058\000\000\000\056\000\000\000\057\000\000\000\000\000\000\000\
+\000\000\041\000\000\000\043\000"
+
+let yydgoto = "\017\000\
+\020\000\023\000\025\000\028\000\030\000\032\000\036\000\093\000\
+\040\000\042\000\045\000\050\000\056\000\060\000\064\000\033\000\
+\065\000\094\000\059\000\053\000\106\000\107\000\109\000\110\000\
+\096\000\097\000"
+
+let yysindex = "\159\000\
+\007\255\026\255\022\255\006\255\041\255\047\255\016\255\021\255\
+\051\255\008\255\009\255\045\255\034\255\070\255\020\255\033\255\
+\000\000\007\255\000\000\000\000\000\000\033\255\000\000\022\255\
+\000\000\000\000\033\255\000\000\000\000\000\000\033\255\000\000\
+\000\000\006\255\000\000\000\000\000\000\000\000\033\255\000\000\
+\000\000\000\000\000\000\033\255\000\000\000\000\061\255\000\000\
+\137\255\000\000\000\000\045\255\000\000\074\255\000\000\000\000\
+\000\000\033\255\000\000\000\000\132\255\033\255\000\000\000\000\
+\041\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\014\255\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\119\255\000\000\061\255\087\255\000\000\
+\132\255\117\255\070\255\174\255\000\000\174\255\042\255\090\255\
+\000\000\047\255\000\000\000\000\047\255\006\255\132\255\093\255\
+\000\000\053\255\092\255\086\255\095\255\107\255\000\000\000\000\
+\132\255\132\255\000\000\132\255\000\000\000\000\000\000\101\255\
+\000\000\132\255\000\000\132\255\000\000\070\255\101\255\083\255\
+\083\255\000\000\083\255\000\000"
+
+let yyrindex = "\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\112\255\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\097\255\000\000\
+\000\000\000\000\000\000\000\000\000\000\120\255\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\127\255\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\071\255\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\178\255\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+\000\000\125\255\000\000\000\000\000\000\118\255\000\000\000\000\
+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\187\255\
+\000\000\000\000\000\000\000\000\000\000\000\000\196\255\203\255\
+\210\255\000\000\133\255\000\000"
+
+let yygindex = "\000\000\
+\129\000\000\000\125\000\250\255\089\000\253\255\000\000\147\000\
+\000\000\000\000\143\000\126\000\000\000\000\000\000\000\002\000\
+\123\000\244\255\000\000\104\000\201\255\058\000\056\000\000\000\
+\000\000\239\255"
+
+let yytablesize = 233
+let yytable = "\052\000\
+\058\000\061\000\021\000\035\000\026\000\095\000\055\000\018\000\
+\027\000\041\000\044\000\043\000\046\000\051\000\057\000\099\000\
+\046\000\066\000\031\000\021\000\034\000\062\000\037\000\068\000\
+\024\000\026\000\022\000\072\000\070\000\019\000\019\000\019\000\
+\071\000\104\000\049\000\047\000\027\000\048\000\019\000\052\000\
+\073\000\054\000\019\000\029\000\019\000\074\000\047\000\120\000\
+\048\000\031\000\113\000\114\000\039\000\051\000\049\000\019\000\
+\019\000\127\000\128\000\085\000\129\000\113\000\114\000\074\000\
+\019\000\049\000\075\000\019\000\131\000\019\000\122\000\047\000\
+\023\000\048\000\111\000\083\000\112\000\023\000\108\000\012\000\
+\012\000\023\000\023\000\012\000\023\000\012\000\023\000\012\000\
+\012\000\103\000\049\000\113\000\114\000\012\000\117\000\119\000\
+\115\000\118\000\023\000\116\000\023\000\113\000\114\000\023\000\
+\124\000\121\000\123\000\023\000\023\000\113\000\023\000\125\000\
+\023\000\108\000\017\000\023\000\023\000\023\000\086\000\023\000\
+\048\000\101\000\017\000\087\000\126\000\102\000\017\000\088\000\
+\089\000\016\000\090\000\105\000\091\000\086\000\044\000\048\000\
+\092\000\049\000\087\000\042\000\076\000\077\000\088\000\089\000\
+\078\000\090\000\067\000\091\000\069\000\045\000\045\000\092\000\
+\049\000\098\000\038\000\079\000\080\000\063\000\081\000\001\000\
+\002\000\003\000\004\000\005\000\006\000\007\000\008\000\009\000\
+\010\000\011\000\012\000\013\000\014\000\015\000\016\000\037\000\
+\084\000\082\000\100\000\130\000\087\000\132\000\000\000\000\000\
+\088\000\089\000\050\000\090\000\000\000\091\000\050\000\000\000\
+\050\000\000\000\050\000\050\000\059\000\000\000\000\000\059\000\
+\050\000\059\000\000\000\059\000\059\000\049\000\000\000\000\000\
+\049\000\059\000\049\000\000\000\049\000\049\000\000\000\047\000\
+\000\000\047\000\049\000\047\000\047\000\000\000\046\000\000\000\
+\046\000\047\000\046\000\046\000\000\000\000\000\000\000\000\000\
+\046\000"
+
+let yycheck = "\012\000\
+\013\000\014\000\001\000\007\000\003\000\061\000\013\000\001\001\
+\003\001\002\001\002\001\010\000\011\000\012\000\013\000\002\001\
+\015\000\016\000\003\001\018\000\005\001\002\001\002\001\022\000\
+\003\001\024\000\001\001\034\000\027\000\023\001\023\001\023\001\
+\031\000\089\000\021\001\002\001\003\001\004\001\023\001\052\000\
+\039\000\008\001\023\001\003\001\023\001\044\000\002\001\103\000\
+\004\001\003\001\009\001\010\001\002\001\052\000\021\001\023\001\
+\023\001\113\000\114\000\058\000\116\000\009\001\010\001\062\000\
+\023\001\021\001\006\001\023\001\124\000\023\001\018\001\002\001\
+\002\001\004\001\092\000\002\001\094\000\007\001\091\000\009\001\
+\010\001\011\001\012\001\013\001\014\001\015\001\016\001\017\001\
+\018\001\003\001\021\001\009\001\010\001\023\001\098\000\102\000\
+\095\000\101\000\002\001\010\001\004\001\009\001\010\001\007\001\
+\019\001\013\001\015\001\011\001\012\001\009\001\014\001\017\001\
+\016\001\126\000\003\001\019\001\020\001\021\001\002\001\023\001\
+\004\001\003\001\003\001\007\001\018\001\007\001\007\001\011\001\
+\012\001\003\001\014\001\015\001\016\001\002\001\017\001\004\001\
+\020\001\021\001\007\001\015\001\004\001\005\001\011\001\012\001\
+\008\001\014\001\018\000\016\001\024\000\017\001\018\001\020\001\
+\021\001\065\000\008\000\019\001\020\001\015\000\022\001\001\000\
+\002\000\003\000\004\000\005\000\006\000\007\000\008\000\009\000\
+\010\000\011\000\012\000\013\000\014\000\015\000\016\000\002\001\
+\054\000\052\000\075\000\122\000\007\001\126\000\255\255\255\255\
+\011\001\012\001\009\001\014\001\255\255\016\001\013\001\255\255\
+\015\001\255\255\017\001\018\001\010\001\255\255\255\255\013\001\
+\023\001\015\001\255\255\017\001\018\001\010\001\255\255\255\255\
+\013\001\023\001\015\001\255\255\017\001\018\001\255\255\013\001\
+\255\255\015\001\023\001\017\001\018\001\255\255\013\001\255\255\
+\015\001\023\001\017\001\018\001\255\255\255\255\255\255\255\255\
+\023\001"
+
+let yyact = [|
+ (fun _ -> failwith "parser")
+(* Rule 1, file parser.mly, line 105 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 1 : string)::(peek_val parser_env 0 : string list) ) : string list))
+(* Rule 2, file parser.mly, line 107 *)
+; (fun parser_env -> Obj.repr(( [] ) : string list))
+(* Rule 3, file parser.mly, line 111 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 1 : string) ) : string))
+(* Rule 4, file parser.mly, line 117 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 1 : int)::(peek_val parser_env 0 : int list) ) : int list))
+(* Rule 5, file parser.mly, line 119 *)
+; (fun parser_env -> Obj.repr(( [] ) : int list))
+(* Rule 6, file parser.mly, line 123 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 1 : int) ) : int))
+(* Rule 7, file parser.mly, line 127 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 0 : int) ) : int))
+(* Rule 8, file parser.mly, line 131 *)
+; (fun parser_env -> Obj.repr(( Some (peek_val parser_env 1 : int) ) : int option))
+(* Rule 9, file parser.mly, line 133 *)
+; (fun parser_env -> Obj.repr(( None ) : int option))
+(* Rule 10, file parser.mly, line 137 *)
+; (fun parser_env -> Obj.repr(( Some (- (peek_val parser_env 0 : int)) ) : int option))
+(* Rule 11, file parser.mly, line 139 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 0 : int option) ) : int option))
+(* Rule 12, file parser.mly, line 145 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 0 : string) ) : string))
+(* Rule 13, file parser.mly, line 149 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 1 : string) ) : string))
+(* Rule 14, file parser.mly, line 153 *)
+; (fun parser_env -> Obj.repr(( Some (peek_val parser_env 0 : string) ) : string option))
+(* Rule 15, file parser.mly, line 155 *)
+; (fun parser_env -> Obj.repr(( None ) : string option))
+(* Rule 16, file parser.mly, line 159 *)
+; (fun parser_env -> Obj.repr(( Some (peek_val parser_env 0 : string) ) : 'opt_identifier))
+(* Rule 17, file parser.mly, line 161 *)
+; (fun parser_env -> Obj.repr(( None ) : 'opt_identifier))
+(* Rule 18, file parser.mly, line 165 *)
+; (fun parser_env -> Obj.repr(( Some (peek_val parser_env 1 : string) ) : string option))
+(* Rule 19, file parser.mly, line 167 *)
+; (fun parser_env -> Obj.repr(( None ) : string option))
+(* Rule 20, file parser.mly, line 173 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 1 : 'variable)::(peek_val parser_env 0 : string list) ) : string list))
+(* Rule 21, file parser.mly, line 175 *)
+; (fun parser_env -> Obj.repr(( [] ) : string list))
+(* Rule 22, file parser.mly, line 179 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 1 : 'variable) ) : 'variable_eol))
+(* Rule 23, file parser.mly, line 183 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 0 : string) ) : 'local_name))
+(* Rule 24, file parser.mly, line 185 *)
+; (fun parser_env -> Obj.repr(( "*" ) : 'local_name))
+(* Rule 25, file parser.mly, line 187 *)
+; (fun parser_env -> Obj.repr(( "-" ) : 'local_name))
+(* Rule 26, file parser.mly, line 189 *)
+; (fun parser_env -> Obj.repr(( "@" ) : 'local_name))
+(* Rule 27, file parser.mly, line 191 *)
+; (fun parser_env -> Obj.repr(( "=" ) : 'local_name))
+(* Rule 28, file parser.mly, line 193 *)
+; (fun parser_env -> Obj.repr(( ">" ) : 'local_name))
+(* Rule 29, file parser.mly, line 195 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 0 : string) ) : 'local_name))
+(* Rule 30, file parser.mly, line 199 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 0 : 'local_name) ) : 'variable))
+(* Rule 31, file parser.mly, line 201 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 2 : string) ^ "." ^ (peek_val parser_env 0 : 'local_name) ) : 'variable))
+(* Rule 32, file parser.mly, line 203 *)
+; (fun parser_env -> Obj.repr(( "" ) : 'variable))
+(* Rule 33, file parser.mly, line 210 *)
+; (fun parser_env -> Obj.repr(( BA_none ) : Parser_aux.break_arg))
+(* Rule 34, file parser.mly, line 212 *)
+; (fun parser_env -> Obj.repr(( BA_pc (peek_val parser_env 0 : int) ) : Parser_aux.break_arg))
+(* Rule 35, file parser.mly, line 214 *)
+; (fun parser_env -> Obj.repr(( BA_function (peek_val parser_env 0 : 'variable_eol) ) : Parser_aux.break_arg))
+(* Rule 36, file parser.mly, line 216 *)
+; (fun parser_env -> Obj.repr(( BA_pos1 ((peek_val parser_env 2 : 'opt_identifier), (peek_val parser_env 1 : int), (peek_val parser_env 0 : int option)) ) : Parser_aux.break_arg))
+(* Rule 37, file parser.mly, line 218 *)
+; (fun parser_env -> Obj.repr(( BA_pos2 ((peek_val parser_env 2 : 'opt_identifier), (peek_val parser_env 0 : int)) ) : Parser_aux.break_arg))
+(* Rule 38, file parser.mly, line 224 *)
+; (fun parser_env -> Obj.repr(( ((peek_val parser_env 2 : 'opt_identifier), Some (peek_val parser_env 1 : int), (peek_val parser_env 0 : int option)) ) : string option * int option * int option))
+(* Rule 39, file parser.mly, line 226 *)
+; (fun parser_env -> Obj.repr(( ((peek_val parser_env 0 : string option), None, None) ) : string option * int option * int option))
+(* Rule 40, file parser.mly, line 232 *)
+; (fun parser_env -> Obj.repr(( ((peek_val parser_env 2 : 'variable), (peek_val parser_env 1 : 'pattern)) ) : string * Parser_aux.pattern))
+(* Rule 41, file parser.mly, line 236 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 2 : 'pattern)::(peek_val parser_env 0 : 'pattern_sm_list) ) : 'pattern_sm_list))
+(* Rule 42, file parser.mly, line 238 *)
+; (fun parser_env -> Obj.repr(( [(peek_val parser_env 0 : 'pattern)] ) : 'pattern_sm_list))
+(* Rule 43, file parser.mly, line 243 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 2 : 'pattern_label)::(peek_val parser_env 0 : 'pattern_label_list) ) : 'pattern_label_list))
+(* Rule 44, file parser.mly, line 245 *)
+; (fun parser_env -> Obj.repr(( [(peek_val parser_env 0 : 'pattern_label)] ) : 'pattern_label_list))
+(* Rule 45, file parser.mly, line 250 *)
+; (fun parser_env -> Obj.repr(( ((peek_val parser_env 2 : 'variable), (peek_val parser_env 0 : 'pattern)) ) : 'pattern_label))
+(* Rule 46, file parser.mly, line 255 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 0 : 'pattern) :: (peek_val parser_env 2 : 'pattern_comma_list) ) : 'pattern_comma_list))
+(* Rule 47, file parser.mly, line 257 *)
+; (fun parser_env -> Obj.repr(( [(peek_val parser_env 0 : 'pattern); (peek_val parser_env 2 : 'pattern)] ) : 'pattern_comma_list))
+(* Rule 48, file parser.mly, line 262 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 0 : 'simple_pattern) ) : 'pattern))
+(* Rule 49, file parser.mly, line 264 *)
+; (fun parser_env -> Obj.repr(( P_concat ((peek_val parser_env 2 : 'pattern), (peek_val parser_env 0 : 'pattern)) ) : 'pattern))
+(* Rule 50, file parser.mly, line 266 *)
+; (fun parser_env -> Obj.repr(( P_tuple (List.rev (peek_val parser_env 0 : 'pattern_comma_list)) ) : 'pattern))
+(* Rule 51, file parser.mly, line 268 *)
+; (fun parser_env -> Obj.repr(( P_constr ((peek_val parser_env 1 : 'variable), (peek_val parser_env 0 : 'simple_pattern)) ) : 'pattern))
+(* Rule 52, file parser.mly, line 270 *)
+; (fun parser_env -> Obj.repr(( P_constr ("", (peek_val parser_env 0 : 'simple_pattern)) ) : 'pattern))
+(* Rule 53, file parser.mly, line 275 *)
+; (fun parser_env -> Obj.repr(( P_dummy ) : 'simple_pattern))
+(* Rule 54, file parser.mly, line 277 *)
+; (fun parser_env -> Obj.repr(( P_variable (peek_val parser_env 0 : string) ) : 'simple_pattern))
+(* Rule 55, file parser.mly, line 279 *)
+; (fun parser_env -> Obj.repr(( P_list [] ) : 'simple_pattern))
+(* Rule 56, file parser.mly, line 281 *)
+; (fun parser_env -> Obj.repr(( P_list (peek_val parser_env 1 : 'pattern_sm_list) ) : 'simple_pattern))
+(* Rule 57, file parser.mly, line 283 *)
+; (fun parser_env -> Obj.repr(( P_record (peek_val parser_env 1 : 'pattern_label_list) ) : 'simple_pattern))
+(* Rule 58, file parser.mly, line 285 *)
+; (fun parser_env -> Obj.repr(( (peek_val parser_env 1 : 'pattern) ) : 'simple_pattern))
+(* Rule 59, file parser.mly, line 287 *)
+; (fun parser_env -> Obj.repr(( P_nth ((peek_val parser_env 1 : int), (peek_val parser_env 0 : 'pattern)) ) : 'simple_pattern))
+(* Rule 60, file parser.mly, line 294 *)
+; (fun parser_env -> Obj.repr(( stop_user_input () ) : unit))
+(* Entry argument_list_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry argument_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry integer_list_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry integer_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry integer *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry opt_integer_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry opt_signed_integer_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry identifier *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry identifier_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry identifier_or_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry opt_identifier_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry variable_list_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry break_argument_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry match_arguments_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry list_arguments_eol *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+(* Entry end_of_line *)
+; (fun parser_env -> raise (YYexit (peek_val parser_env 0)))
+|]
+let yytables =
+ { actions=yyact;
+ transl_const=yytransl_const;
+ transl_block=yytransl_block;
+ lhs=yylhs;
+ len=yylen;
+ defred=yydefred;
+ dgoto=yydgoto;
+ sindex=yysindex;
+ rindex=yyrindex;
+ gindex=yygindex;
+ tablesize=yytablesize;
+ table=yytable;
+ check=yycheck;
+ error_function=parse_error }
+let argument_list_eol lexfun lexbuf = yyparse yytables 1 lexfun lexbuf
+let argument_eol lexfun lexbuf = yyparse yytables 2 lexfun lexbuf
+let integer_list_eol lexfun lexbuf = yyparse yytables 3 lexfun lexbuf
+let integer_eol lexfun lexbuf = yyparse yytables 4 lexfun lexbuf
+let integer lexfun lexbuf = yyparse yytables 5 lexfun lexbuf
+let opt_integer_eol lexfun lexbuf = yyparse yytables 6 lexfun lexbuf
+let opt_signed_integer_eol lexfun lexbuf = yyparse yytables 7 lexfun lexbuf
+let identifier lexfun lexbuf = yyparse yytables 8 lexfun lexbuf
+let identifier_eol lexfun lexbuf = yyparse yytables 9 lexfun lexbuf
+let identifier_or_eol lexfun lexbuf = yyparse yytables 10 lexfun lexbuf
+let opt_identifier_eol lexfun lexbuf = yyparse yytables 11 lexfun lexbuf
+let variable_list_eol lexfun lexbuf = yyparse yytables 12 lexfun lexbuf
+let break_argument_eol lexfun lexbuf = yyparse yytables 13 lexfun lexbuf
+let match_arguments_eol lexfun lexbuf = yyparse yytables 14 lexfun lexbuf
+let list_arguments_eol lexfun lexbuf = yyparse yytables 15 lexfun lexbuf
+let end_of_line lexfun lexbuf = yyparse yytables 16 lexfun lexbuf
diff --git a/debugger/parser.mli b/debugger/parser.mli
new file mode 100644
index 000000000..c29e2c0a8
--- /dev/null
+++ b/debugger/parser.mli
@@ -0,0 +1,57 @@
+type token =
+ ARGUMENT of (string)
+ | IDENTIFIER of (string)
+ | INTEGER of (int)
+ | STAR
+ | MINUS
+ | UNDERUNDER
+ | SHARP
+ | AT
+ | COLONCOLON
+ | COMMA
+ | UNDERSCORE
+ | LPAREN
+ | RPAREN
+ | LBRACKET
+ | RBRACKET
+ | LBRACE
+ | RBRACE
+ | SEMI
+ | EQUAL
+ | SUPERIOR
+ | PREFIX
+ | OPERATOR of (string)
+ | EOL
+
+val argument_list_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> string list
+val argument_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> string
+val integer_list_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> int list
+val integer_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> int
+val integer :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> int
+val opt_integer_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> int option
+val opt_signed_integer_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> int option
+val identifier :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> string
+val identifier_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> string
+val identifier_or_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> string option
+val opt_identifier_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> string option
+val variable_list_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> string list
+val break_argument_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> Parser_aux.break_arg
+val match_arguments_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> string * Parser_aux.pattern
+val list_arguments_eol :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> string option * int option * int option
+val end_of_line :
+ (Lexing.lexbuf -> token) -> Lexing.lexbuf -> unit
diff --git a/debugger/parser_aux.mli b/debugger/parser_aux.mli
new file mode 100644
index 000000000..ddbc560eb
--- /dev/null
+++ b/debugger/parser_aux.mli
@@ -0,0 +1,37 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(*open Globals*)
+type global_reference = string
+open Primitives
+
+type break_arg =
+ BA_none (* break *)
+ | BA_pc of int (* break PC *)
+ | BA_function of global_reference (* break FUNCTION *)
+ | BA_pos1 of string option * int * int option
+ (* break @ [MODULE] LINE [POS] *)
+ | BA_pos2 of string option * int (* break @ [MODULE] # OFFSET *)
+
+type pattern =
+ P_dummy (* _ *)
+ | P_variable of string (* x *)
+ | P_record of (* {A = x; ...; D = z} *)
+ (global_reference * pattern) list
+ | P_list of pattern list (* [a;,,,;d] *)
+ | P_nth of int * pattern (* # 10 l *)
+ | P_concat of pattern * pattern (* a::l *)
+ | P_tuple of pattern list (* a,...,d *)
+ | P_constr of (* A p *)
+ global_reference * pattern (* > p *)
diff --git a/debugger/pattern_matching.ml b/debugger/pattern_matching.ml
new file mode 100644
index 000000000..3f5810655
--- /dev/null
+++ b/debugger/pattern_matching.ml
@@ -0,0 +1,250 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(************************ Simple pattern matching **********************)
+
+open Debugger_config
+(*open Primitives*)
+open Misc
+(*open Const*)
+(*open Globals*)
+(*open Builtins*)
+open Typedtree
+(*open Modules*)
+(*open Symtable*)
+(*open Value*)
+open Parser_aux
+
+(*
+let rec find_constr tag = function
+ [] ->
+ fatal_error "find_constr: unknown constructor for this type"
+ | constr::rest ->
+ match constr.info.cs_tag with
+ ConstrRegular(t, _) ->
+ if t == tag then constr else find_constr tag rest
+ | ConstrExtensible _ ->
+ fatal_error "find_constr: extensible"
+
+let find_exception tag =
+ let (qualid, stamp) = get_exn_of_num tag in
+ let rec select_exn = function
+ [] ->
+ raise Not_found
+ | constr :: rest ->
+ match constr.info.cs_tag with
+ ConstrExtensible(_,st) ->
+ if st == stamp then constr else select_exn rest
+ | ConstrRegular(_,_) ->
+ fatal_error "find_exception: regular" in
+ select_exn(hashtbl__find_all (find_module qualid.qual).mod_constrs qualid.id)
+*)
+
+let error_matching () =
+ prerr_endline "Pattern matching failed";
+ raise Toplevel
+
+(*
+let same_name {qualid = name1} =
+ function
+ GRname name2 ->
+ (name2 = "") or (name1.id = name2)
+ | GRmodname name2 ->
+ name1 = name2
+
+let check_same_constr constr constr2 =
+ try
+ if not (same_name constr constr2) then
+ error_matching ()
+ with
+ Desc_not_found ->
+ prerr_endline "Undefined constructor.";
+ raise Toplevel
+*)
+
+let rec pattern_matching pattern obj ty =
+ match pattern with
+ P_dummy ->
+ []
+ | P_variable var ->
+ [var, obj, ty]
+ | _ ->
+ match (Ctype.repr ty).desc with
+ Tvar | Tarrow _ ->
+ error_matching ()
+ | Ttuple(ty_list) ->
+ (match pattern with
+ P_tuple pattern_list ->
+ pattern_matching_list pattern_list obj ty_list
+ | P_nth (n, patt) ->
+ if n >= List.length ty_list then
+ (prerr_endline "Out of range."; raise Toplevel);
+ pattern_matching patt (Debugcom.get_field obj n) (List.nth ty_list n)
+ | _ ->
+ error_matching ())
+ | Tconstr(cstr, [ty_arg],_) when same_type_constr cstr constr_type_list ->
+ (match pattern with
+ P_list pattern_list ->
+ let (last, list) =
+ it_list
+ (fun (current, list) pattern ->
+ if value_tag current = 0 then error_matching ();
+ (Debugcom.get_field current 1,
+ (pattern, Debugcom.get_field current 0)::list))
+ (obj, [])
+ pattern_list
+ in
+ if value_tag last <> 0 then error_matching ();
+ flat_map
+ (function (x, y) -> pattern_matching x y ty_arg)
+ (rev list)
+ | P_nth (n, patt) ->
+ let rec find k current =
+ if value_tag current = 0 then
+ (prerr_endline "Out of range."; raise Toplevel);
+ if k = 0 then
+ pattern_matching patt (Debugcom.get_field current 0) ty_arg
+ else
+ find (k - 1) (Debugcom.get_field current 1)
+ in
+ find n obj
+ | P_concat (pattern1, pattern2) ->
+ if value_tag obj == 0 then error_matching ();
+ (pattern_matching pattern1 (Debugcom.get_field obj 0) ty_arg)
+ @ (pattern_matching pattern2 (Debugcom.get_field obj 1) ty)
+ | _ ->
+ error_matching ())
+ | Tconstr(cstr, [ty_arg]) when same_type_constr cstr constr_type_vect ->
+ (match pattern with
+ P_nth (n, patt) ->
+ if n >= value_size obj then
+ (prerr_endline "Out of range."; raise Toplevel);
+ pattern_matching patt (Debugcom.get_field obj n) ty_arg
+ | _ ->
+ error_matching ())
+ | Tconstr(cstr, ty_list) ->
+ (match cstr.info.ty_abbr with
+ Tabbrev(params, body) ->
+ pattern_matching pattern obj (expand_abbrev params body ty_list)
+ | _ ->
+ match_concrete_type pattern obj cstr ty ty_list)
+
+and match_concrete_type pattern obj cstr ty ty_list =
+ let typ_descr =
+ type_descr_of_type_constr cstr in
+ match typ_descr.info.ty_desc with
+ Abstract_type ->
+ error_matching ()
+ | Variant_type constr_list ->
+ let tag = value_tag obj in
+ (try
+ let constr =
+ if same_type_constr cstr constr_type_exn then
+ find_exception tag
+ else
+ find_constr tag constr_list
+ in
+ let (ty_res, ty_arg) =
+ type_pair_instance (constr.info.cs_res, constr.info.cs_arg)
+ in
+ filter (ty_res, ty);
+ match constr.info.cs_kind with
+ Constr_constant ->
+ error_matching ()
+ | Constr_regular ->
+ (match pattern with
+ P_constr (constr2, patt) ->
+ check_same_constr constr constr2;
+ pattern_matching patt (Debugcom.get_field obj 0) ty_arg
+ | _ ->
+ error_matching ())
+ | Constr_superfluous n ->
+ (match pattern with
+ P_constr (constr2, patt) ->
+ check_same_constr constr constr2;
+ (match patt with
+ P_tuple pattern_list ->
+ pattern_matching_list
+ pattern_list
+ obj
+ (filter_product n ty_arg)
+ | P_nth (n2, patt) ->
+ let ty_list = filter_product n ty_arg in
+ if n2 >= n then
+ (prerr_endline "Out of range.";
+ raise Toplevel);
+ pattern_matching
+ patt
+ (Debugcom.get_field obj n2)
+ (List.nth ty_list n2)
+ | P_variable var ->
+ [var,
+ obj,
+ {typ_desc = Tproduct (filter_product n ty_arg);
+ typ_level = generic}]
+ | P_dummy ->
+ []
+ | _ ->
+ error_matching ())
+ | _ ->
+ error_matching ())
+ with
+ Not_found ->
+ error_matching ()
+ | Unify ->
+ fatal_error "pattern_matching: types should match")
+ | Record_type label_list ->
+ let match_field (label, patt) =
+ let lbl =
+ try
+ primitives__find
+ (function l -> same_name l label)
+ label_list
+ with Not_found ->
+ prerr_endline "Label not found.";
+ raise Toplevel
+ in
+ let (ty_res, ty_arg) =
+ type_pair_instance (lbl.info.lbl_res, lbl.info.lbl_arg)
+ in
+ (try
+ filter (ty_res, ty)
+ with Unify ->
+ fatal_error "pattern_matching: types should match");
+ pattern_matching patt (Debugcom.get_field obj lbl.info.lbl_pos) ty_arg
+ in
+ (match pattern with
+ P_record pattern_label_list ->
+ flat_map match_field pattern_label_list
+ | _ ->
+ error_matching ())
+ | Abbrev_type(_,_) ->
+ fatal_error "pattern_matching: abbrev type"
+
+and pattern_matching_list pattern_list obj ty_list =
+ let val_list =
+ try
+ pair__combine (pattern_list, ty_list)
+ with
+ Invalid_argument _ -> error_matching ()
+ in
+ flat_map
+ (function (x, y, z) -> pattern_matching x y z)
+ (rev
+ (snd
+ (it_list
+ (fun (num, list) (pattern, typ) ->
+ (num + 1, (pattern, Debugcom.get_field obj num, typ)::list))
+ (0, [])
+ val_list)))
diff --git a/debugger/pattern_matching.mli b/debugger/pattern_matching.mli
new file mode 100644
index 000000000..23a67c9cb
--- /dev/null
+++ b/debugger/pattern_matching.mli
@@ -0,0 +1,20 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(************************ Simple pattern matching **********************)
+
+open Parser_aux
+
+val pattern_matching :
+ pattern -> Debugcom.remote_value -> Typedtree.type_expr -> (string * Debugcom.remote_value * Typedtree.type_expr) list;;
diff --git a/debugger/primitives.ml b/debugger/primitives.ml
new file mode 100644
index 000000000..19eeaad1c
--- /dev/null
+++ b/debugger/primitives.ml
@@ -0,0 +1,194 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(*********************** Basic functions and types *********************)
+
+(*** Miscellaneous ***)
+exception Out_of_range
+
+let nothing _ = ()
+
+(*** Operations on lists. ***)
+
+(* Remove an element from a list *)
+let except e l =
+ let rec except_e = function
+ [] -> []
+ | elem::l -> if e = elem then l else elem::except_e l
+ in except_e l
+
+(* Position of an element in a list. Head of list has position 0. *)
+let index a l =
+ let rec index_rec i = function
+ [] -> raise Not_found
+ | b::l -> if a = b then i else index_rec (i + 1) l
+ in index_rec 0 l
+
+(* Remove an element from an association list *)
+let assoc_remove lst elem =
+ let rec remove =
+ function
+ [] -> []
+ | ((a, _) as c::t) ->
+ if a = elem then t
+ else c::(remove t)
+ in remove lst
+
+(* Nth element of a list. *)
+let rec list_nth p0 p1 =
+ match (p0,p1) with
+ ([], _) ->
+ invalid_arg "list_nth"
+ | ((a::_), 0) ->
+ a
+ | ((_::l), n) ->
+ list_nth l (n - 1)
+
+(* Return the `n' first elements of `l' *)
+(* ### n l -> l' *)
+let rec list_truncate =
+ fun
+ p0 p1 -> match (p0,p1) with (0, _) -> []
+ | (_, []) -> []
+ | (n, (a::l)) -> a::(list_truncate (n - 1) l)
+
+(* Separe the `n' first elements of `l' and the others *)
+(* ### n list -> (first, last) *)
+let rec list_truncate2 =
+ fun
+ p0 p1 -> match (p0,p1) with (0, l) ->
+ ([], l)
+ | (_, []) ->
+ ([], [])
+ | (n, (a::l)) ->
+ let (first, last) = (list_truncate2 (n - 1) l) in
+ (a::first, last)
+
+(* Replace x by y in list l *)
+(* ### x y l -> l' *)
+let list_replace x y =
+ let rec repl =
+ function
+ [] -> []
+ | a::l ->
+ if a == x then y::l
+ else a::(repl l)
+ in repl
+
+(* Filter `list' according to `predicate'. *)
+(* ### predicate list -> list' *)
+let filter p =
+ let rec filter2 =
+ function
+ [] ->
+ []
+ | a::l ->
+ if p a then
+ a::(filter2 l)
+ else
+ filter2 l
+ in filter2
+
+(* Find the first element `element' of `list' *)
+(* so that `predicate element' holds. *)
+(* ### predicate list -> element *)
+let find p =
+ let rec find2 =
+ function
+ [] ->
+ raise Not_found
+ | a::l ->
+ if p a then a
+ else find2 l
+ in find2
+
+(*** Operations on strings. ***)
+
+(* Return the position of the first occurence of char `c' in string `s' *)
+(* Raise `Not_found' if `s' does not contain `c'. *)
+(* ### c s -> pos *)
+let string_pos s c =
+ let i = ref 0 and l = String.length s in
+ while (!i < l) & (String.get s !i != c) do i := !i + 1 done;
+ if !i = l then raise Not_found;
+ !i
+
+(* Remove blanks (spaces and tabs) at beginning and end of a string. *)
+let string_trim s =
+ let l = String.length s and i = ref 0 in
+ while
+ (!i < l) & (match String.get s !i with ' ' | '\t' -> true | _ -> false)
+ do
+ incr i
+ done;
+ let j = ref (l - 1) in
+ while
+ (!j >= !i) & (match String.get s !j with ' ' | '\t' -> true | _ -> false)
+ do
+ decr j
+ done;
+ String.sub s !i (!j - !i + 1)
+
+(* isprefix s1 s2 returns true if s1 is a prefix of s2. *)
+
+let isprefix s1 s2 =
+ let l1 = String.length s1 and l2 = String.length s2 in
+ (l1 = l2 && s1 = s2) || (l1 < l2 && s1 = String.sub s2 0 l1)
+
+(* Split a string at the given delimiter char *)
+
+let split_string sep str =
+ let rec split i j =
+ if j >= String.length str then
+ if i >= j then [] else [String.sub str i (j-i)]
+ else if str.[j] = sep then
+ if i >= j
+ then skip_sep (j+1)
+ else String.sub str i (j-i) :: skip_sep (j+1)
+ else
+ split i (j+1)
+ and skip_sep j =
+ if j < String.length str && str.[j] = sep
+ then skip_sep (j+1)
+ else split j j
+ in split 0 0
+
+(*** I/O channels ***)
+
+type io_channel = {
+ io_in : in_channel;
+ io_out : out_channel;
+ io_fd : Unix.file_descr
+ }
+
+let io_channel_of_descr fd = {
+ io_in = Unix.in_channel_of_descr fd;
+ io_out = Unix.out_channel_of_descr fd;
+ io_fd = fd
+ }
+
+let close_io io_channel =
+ (try
+ (try
+ close_out io_channel.io_out
+ with
+ Sys_error _ -> ())
+ with End_of_file -> ()); (* SIGPIPE during flush. *)
+ close_in io_channel.io_in
+
+let std_io = {
+ io_in = stdin;
+ io_out = stdout;
+ io_fd = Unix.stdin
+ }
diff --git a/debugger/primitives.mli b/debugger/primitives.mli
new file mode 100644
index 000000000..b9ef59043
--- /dev/null
+++ b/debugger/primitives.mli
@@ -0,0 +1,85 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(********************* Basic functions and types ***********************)
+
+(*** Miscellaneous ***)
+val nothing : 'a -> unit
+
+(*** Types and exceptions. ***)
+exception Out_of_range
+
+(*** Operations on lists. ***)
+
+(* Remove an element from a list *)
+val except : 'a -> 'a list -> 'a list
+
+(* Position of an element in a list. Head of list has position 0. *)
+val index : 'a -> 'a list -> int
+
+(* Remove on element from an association list. *)
+val assoc_remove : ('a * 'b) list -> 'a -> ('a * 'b) list
+
+(* Nth element of a list. *)
+val list_nth : 'a list -> int -> 'a
+
+(* Return the `n' first elements of `l'. *)
+(* ### n l -> l' *)
+val list_truncate : int -> 'a list -> 'a list
+
+(* Separe the `n' first elements of `l' and the others. *)
+(* ### n list -> (first, last) *)
+val list_truncate2 : int -> 'a list -> 'a list * 'a list
+
+(* Replace x by y in list l *)
+(* ### x y l -> l' *)
+val list_replace : 'a -> 'a -> 'a list -> 'a list
+
+(* Filter `list' according to `predicate'. *)
+(* ### predicate list -> list' *)
+val filter : ('a -> bool) -> 'a list -> 'a list
+
+(* Find the first element `element' of `list' *)
+(* so that `predicate element' holds. *)
+(* Raise `Not_found' if no such element. *)
+(* ### predicate list -> element *)
+val find : ('a -> bool) -> 'a list -> 'a
+
+(*** Operations on strings. ***)
+
+(* Return the position of the first occurence of char `c' in string `s' *)
+(* Raise `Not_found' if `s' does not contain `c'. *)
+(* ### c s -> pos *)
+val string_pos : string -> char -> int
+
+(* Remove blanks (spaces and tabs) at beginning and end of a string. *)
+val string_trim : string -> string
+
+(* isprefix s1 s2 returns true if s1 is a prefix of s2. *)
+val isprefix : string -> string -> bool
+
+(* Split a string at the given delimiter char *)
+val split_string : char -> string -> string list
+
+(*** I/O channels ***)
+
+type io_channel = {
+ io_in : in_channel;
+ io_out : out_channel;
+ io_fd : Unix.file_descr
+ }
+
+val io_channel_of_descr : Unix.file_descr -> io_channel
+val close_io : io_channel -> unit
+val std_io : io_channel
diff --git a/debugger/printval.ml b/debugger/printval.ml
new file mode 100644
index 000000000..2209c8b8f
--- /dev/null
+++ b/debugger/printval.ml
@@ -0,0 +1,279 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* To print values *)
+
+open Misc
+open Obj
+open Format
+open Longident
+open Path
+open Types
+
+(* Given an exception value, we cannot recover its type,
+ hence we cannot print its arguments in general.
+ Here, we do a feeble attempt to print
+ integer, string and float arguments... *)
+
+let print_exception obj =
+ print_string
+ (Debugcom.marshal_obj(Debugcom.get_field (Debugcom.get_field obj 0) 0));
+ let (tag, field) = Debugcom.get_obj obj in
+ if Array.length field > 1 then begin
+ open_hovbox 1;
+ print_string "(";
+ for i = 1 to Array.length field - 1 do
+ if i > 1 then begin print_string ","; print_space() end;
+ let arg = field.(i) in
+ if Debugcom.remote_value_is_int arg then
+ print_int(Debugcom.int_value arg) (* Note: this could be a char! *)
+ else begin
+ let (tag, sz) = Debugcom.get_header arg in
+ if tag = 252 then begin
+ print_string "\"";
+ print_string (String.escaped (Debugcom.marshal_obj arg : string));
+ print_string "\""
+ end else if tag = 253 then
+ print_float (Debugcom.marshal_obj arg : float)
+ else
+ print_string "_"
+ end
+ done;
+ print_string ")";
+ close_box()
+ end
+
+(* Recover a constructor by its tag *)
+
+exception Constr_not_found
+
+let rec find_constr tag num_const num_nonconst = function
+ [] ->
+ raise Constr_not_found
+ | (name, [] as cstr) :: rem ->
+ if tag = Cstr_constant num_const
+ then cstr
+ else find_constr tag (num_const + 1) num_nonconst rem
+ | (name, _ as cstr) :: rem ->
+ if tag = Cstr_block num_nonconst
+ then cstr
+ else find_constr tag num_const (num_nonconst + 1) rem
+
+(* The user-defined printers. Also used for some builtin types. *)
+
+let printers = ref ([
+ Pident(Ident.create "print_int"), Predef.type_int,
+ (fun x -> print_int (Debugcom.int_value x));
+ Pident(Ident.create "print_float"), Predef.type_float,
+ (fun x -> print_float(Debugcom.marshal_obj x : float));
+ Pident(Ident.create "print_char"), Predef.type_char,
+ (fun x -> print_string "'";
+ print_string (Char.escaped(Char.chr(Debugcom.int_value x)));
+ print_string "'");
+ Pident(Ident.create "print_string"), Predef.type_string,
+ (fun x -> print_string "\"";
+ print_string (String.escaped(Debugcom.marshal_obj x : string));
+ print_string "\"")
+] : (Path.t * type_expr * (Debugcom.remote_value -> unit)) list)
+
+let find_printer env ty =
+ let rec find = function
+ [] -> raise Not_found
+ | (name, sch, printer) :: remainder ->
+ if Ctype.moregeneral env sch ty
+ then printer
+ else find remainder
+ in find !printers
+
+(* Print a constructor or label, giving it the same prefix as the type
+ it comes from. Attempt to omit the prefix if the type comes from
+ a module that has been opened. *)
+
+let print_qualified lookup_fun env ty_path name =
+ match ty_path with
+ Pident id ->
+ print_string name
+ | Pdot(p, s, pos) ->
+ if try
+ match (lookup_fun (Lident name) env).desc with
+ Tconstr(ty_path', _, _) -> Path.same ty_path ty_path'
+ | _ -> false
+ with Not_found -> false
+ then print_string name
+ else (Printtyp.path p; print_string "."; print_string name)
+ | Papply(p1, p2) ->
+ Printtyp.path ty_path
+
+let print_constr =
+ print_qualified (fun lid env -> (Env.lookup_constructor lid env).cstr_res)
+and print_label =
+ print_qualified (fun lid env -> (Env.lookup_label lid env).lbl_res)
+
+(* The main printing function *)
+
+let max_printer_depth = ref 100
+let max_printer_steps = ref 300
+exception Ellipsis
+
+let cautious f arg =
+ try f arg with Ellipsis -> print_string "..."
+
+let print_value obj ty env =
+
+ let printer_steps = ref !max_printer_steps in
+
+ let rec print_val prio depth obj ty =
+ decr printer_steps;
+ if !printer_steps < 0 or depth < 0 then raise Ellipsis;
+ try
+ find_printer env ty obj; ()
+ with Not_found ->
+ match (Ctype.repr ty).desc with
+ Tvar ->
+ print_string "<poly>"
+ | Tarrow(ty1, ty2) ->
+ print_string "<fun>"
+ | Ttuple(ty_list) ->
+ if prio > 0
+ then begin open_hovbox 1; print_string "(" end
+ else open_hovbox 0;
+ print_val_list 1 depth obj ty_list;
+ if prio > 0 then print_string ")";
+ close_box()
+ | Tconstr(path, [], _) when Path.same path Predef.path_exn ->
+ if prio > 1
+ then begin open_hovbox 2; print_string "(" end
+ else open_hovbox 1;
+ print_exception obj;
+ if prio > 1 then print_string ")";
+ close_box()
+ | Tconstr(path, [ty_arg], _) when Path.same path Predef.path_list ->
+ let rec print_conses depth cons =
+ if not (Debugcom.remote_value_is_int cons) then begin
+ print_val 0 (depth - 1) (Debugcom.get_field cons 0) ty_arg;
+ let next_obj = Debugcom.get_field cons 1 in
+ if not (Debugcom.remote_value_is_int next_obj) then begin
+ print_string ";"; print_space();
+ print_conses (depth - 1) next_obj
+ end
+ end in
+ open_hovbox 1;
+ print_string "[";
+ cautious (print_conses depth) obj;
+ print_string "]";
+ close_box()
+ | Tconstr(path, [ty_arg], _) when Path.same path Predef.path_array ->
+ let (tag, fields) = Debugcom.get_obj obj in
+ let rec print_items depth i =
+ if i < Array.length fields then begin
+ if i > 0 then begin print_string ";"; print_space() end;
+ print_val 0 (depth - 1) fields.(i) ty_arg;
+ print_items (depth - 1) (i + 1)
+ end in
+ open_hovbox 2;
+ print_string "[|";
+ cautious (print_items depth) 0;
+ print_string "|]";
+ close_box()
+ | Tconstr(path, ty_list, _) ->
+ begin try
+ let decl = Env.find_type path env in
+ match decl with
+ {type_kind = Type_abstract; type_manifest = None} ->
+ print_string "<abstr>"
+ | {type_kind = Type_abstract; type_manifest = Some body} ->
+ print_val prio depth obj
+ (Ctype.substitute [] decl.type_params ty_list body)
+ | {type_kind = Type_variant constr_list} ->
+ let tag =
+ if Debugcom.remote_value_is_int obj then
+ Cstr_constant(Debugcom.int_value obj)
+ else
+ let (tag, sz) = Debugcom.get_header obj in
+ Cstr_block tag in
+ let (constr_name, constr_args) =
+ find_constr tag 0 0 constr_list in
+ let ty_args =
+ List.map (Ctype.substitute [] decl.type_params ty_list)
+ constr_args in
+ begin match ty_args with
+ [] ->
+ print_constr env path constr_name
+ | [ty1] ->
+ if prio > 1
+ then begin open_hovbox 2; print_string "(" end
+ else open_hovbox 1;
+ print_constr env path constr_name;
+ print_space();
+ cautious
+ (print_val 2 (depth - 1) (Debugcom.get_field obj 0))
+ ty1;
+ if prio > 1 then print_string ")";
+ close_box()
+ | tyl ->
+ if prio > 1
+ then begin open_hovbox 2; print_string "(" end
+ else open_hovbox 1;
+ print_constr env path constr_name;
+ print_space();
+ open_hovbox 1;
+ print_string "(";
+ print_val_list 1 depth obj tyl;
+ print_string ")";
+ close_box();
+ if prio > 1 then print_string ")";
+ close_box()
+ end
+ | {type_kind = Type_record lbl_list} ->
+ let rec print_fields depth pos = function
+ [] -> ()
+ | (lbl_name, _, lbl_arg) :: remainder ->
+ if pos > 0 then begin print_string ";"; print_space() end;
+ open_hovbox 1;
+ print_label env path lbl_name;
+ print_string "="; print_cut();
+ let ty_arg =
+ Ctype.substitute [] decl.type_params ty_list lbl_arg in
+ cautious
+ (print_val 0 (depth - 1) (Debugcom.get_field obj pos))
+ ty_arg;
+ close_box();
+ print_fields (depth - 1) (pos + 1) remainder in
+ open_hovbox 1;
+ print_string "{";
+ cautious (print_fields depth 0) lbl_list;
+ print_string "}";
+ close_box()
+ with
+ Not_found -> (* raised by Env.find_type *)
+ print_string "<abstr>"
+ | Constr_not_found -> (* raised by find_constr *)
+ print_string "<unknown constructor>"
+ end
+ | Tobject (_, _) ->
+ print_string "<obj>"
+ | Tfield(_, _, _) | Tnil | Tlink _ ->
+ fatal_error "Printval.print_value"
+
+ and print_val_list prio depth obj ty_list =
+ let rec print_list depth i = function
+ [] -> ()
+ | ty :: ty_list ->
+ if i > 0 then begin print_string ","; print_space() end;
+ print_val prio (depth - 1) (Debugcom.get_field obj i) ty;
+ print_list (depth - 1) (i + 1) ty_list in
+ cautious (print_list depth 0) ty_list
+
+in print_val 0 !max_printer_depth obj ty
+
diff --git a/debugger/printval.mli b/debugger/printval.mli
new file mode 100644
index 000000000..30439ad0a
--- /dev/null
+++ b/debugger/printval.mli
@@ -0,0 +1,18 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+val max_printer_depth : int ref
+val max_printer_steps : int ref
+
+val print_value : Debugcom.remote_value -> Types.type_expr -> Env.t -> unit
diff --git a/debugger/program_loading.ml b/debugger/program_loading.ml
new file mode 100644
index 000000000..89b678291
--- /dev/null
+++ b/debugger/program_loading.ml
@@ -0,0 +1,111 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Program loading *)
+
+open Unix
+open Misc
+open Debugger_config
+open Parameters
+open Input_handling
+
+(*** Debugging. ***)
+
+let debug_loading = ref true
+
+(*** Load a program. ***)
+
+(* Function used for launching the program. *)
+let launching_func = ref (function () -> ())
+
+let load_program () =
+ !launching_func ();
+ main_loop ()
+
+(*** Launching functions. ***)
+
+(* A generic function for launching the program *)
+let generic_exec cmdline = function () ->
+ if !debug_loading then
+ prerr_endline "Launching program...";
+ let child =
+ try
+ fork ()
+ with x ->
+ Unix_tools.report_error x;
+ raise Toplevel in
+ match child with
+ 0 ->
+ begin try
+ match fork () with
+ 0 -> (* setsid(); *)
+ execv shell [| shell; "-c"; cmdline() |]
+ | _ -> exit 0
+ with x ->
+ Unix_tools.report_error x;
+ exit 1
+ end
+ | _ ->
+ match wait () with
+ (_, WEXITED 0) -> ()
+ | _ -> raise Toplevel
+
+(* Execute the program by calling the runtime explicitely *)
+let exec_with_runtime =
+ generic_exec
+ (function () ->
+ Printf.sprintf "CAML_DEBUG_SOCKET=%s %s %s %s"
+ !socket_name
+ runtime_program
+ !program_name
+ !arguments)
+
+(* Excute the program directly *)
+let exec_direct =
+ generic_exec
+ (function () ->
+ Printf.sprintf "CAML_DEBUG_SOCKET=%s %s %s"
+ !socket_name
+ !program_name
+ !arguments)
+
+(* Ask the user. *)
+let exec_manual =
+ function () ->
+ print_newline ();
+ print_string "Waiting for connection...";
+ print_string ("(the socket is " ^ !socket_name ^ ")");
+ print_newline ()
+
+(*** Selection of the launching function. ***)
+
+type launching_function = (unit -> unit)
+
+let loading_modes =
+ ["direct", exec_direct;
+ "runtime", exec_with_runtime;
+ "manual", exec_manual]
+
+let set_launching_function func =
+ launching_func := func
+
+(* Initialization *)
+
+let _ =
+ set_launching_function exec_direct
+
+(*** Connection. ***)
+
+let connection = ref Primitives.std_io
+let connection_opened = ref false
diff --git a/debugger/program_loading.mli b/debugger/program_loading.mli
new file mode 100644
index 000000000..bfe6de841
--- /dev/null
+++ b/debugger/program_loading.mli
@@ -0,0 +1,33 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(*** Debugging. ***)
+
+val debug_loading : bool ref
+
+(*** Load program ***)
+
+(* Function used for launching the program. *)
+val launching_func : (unit -> unit) ref
+
+val load_program : unit -> unit
+
+type launching_function = (unit -> unit)
+
+val loading_modes : (string * launching_function) list
+val set_launching_function : launching_function -> unit
+
+(** Connection **)
+val connection : Primitives.io_channel ref
+val connection_opened : bool ref
diff --git a/debugger/program_management.ml b/debugger/program_management.ml
new file mode 100644
index 000000000..8619017ae
--- /dev/null
+++ b/debugger/program_management.ml
@@ -0,0 +1,154 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Manage the loading of the program *)
+
+open Unix
+open Unix_tools
+open Debugger_config
+open Misc
+open Instruct
+open Primitives
+open Parameters
+open Input_handling
+open Debugcom
+open Program_loading
+open Time_travel
+
+(*** Connection opening and control. ***)
+
+(* Name of the file if the socket is in the unix domain.*)
+let file_name = ref (None : string option)
+
+(* Default connection handler. *)
+let buffer = String.create 1024
+let control_connection pid fd =
+ if (read fd.io_fd buffer 0 1024) = 0 then
+ forget_process fd pid
+ else begin
+ prerr_string "Garbage data from process ";
+ prerr_int pid;
+ prerr_endline ""
+ end
+
+(* Accept a connection from another process. *)
+let loaded = ref false
+
+let accept_connection continue fd =
+ let (sock, _) = accept fd.io_fd in
+ let io_chan = io_channel_of_descr sock in
+ let pid = input_binary_int io_chan.io_in in
+ if not !loaded then begin
+ (*loaded := true;*)
+ new_checkpoint pid io_chan;
+ Input_handling.add_file io_chan (control_connection pid);
+ continue ()
+ end
+ else begin
+ if set_file_descriptor pid io_chan then
+ Input_handling.add_file io_chan (control_connection pid)
+ end
+
+(* Initialize the socket. *)
+let open_connection address continue =
+ try
+ let (sock_domain, sock_address) = convert_address address in
+ file_name :=
+ (match sock_address with
+ ADDR_UNIX file ->
+ Some file
+ | _ ->
+ None);
+ let sock = socket sock_domain SOCK_STREAM 0 in
+ (try
+ bind sock sock_address;
+ listen sock 3;
+ connection := io_channel_of_descr sock;
+ Input_handling.add_file !connection (accept_connection continue);
+ connection_opened := true
+ with x -> close sock; raise x)
+ with
+ Failure _ -> raise Toplevel
+ | (Unix_error _) as err -> report_error err; raise Toplevel
+
+(* Close the socket. *)
+let close_connection () =
+ if !connection_opened then begin
+ connection_opened := false;
+ Input_handling.remove_file !connection;
+ close_io !connection;
+ match !file_name with
+ Some file ->
+ unlink file
+ | None ->
+ ()
+ end
+
+(*** Kill program. ***)
+let kill_program () =
+ loaded := false;
+ close_connection ();
+ kill_all_checkpoints ();
+ History.empty_history ()
+
+let ask_kill_program () =
+ if not !loaded then
+ true
+ else
+ let answer = yes_or_no "A program is being debugged already. Kill it" in
+ if answer then
+ kill_program ();
+ answer
+
+(*** Program loading and initializations. ***)
+
+let initialize_loading () =
+ if !debug_loading then
+ prerr_endline "Loading debugging informations...";
+ Symbols.read_symbols
+ (try search_in_path !program_name with
+ Not_found ->
+ prerr_endline "Program not found.";
+ raise Toplevel);
+ if !debug_loading then
+ prerr_endline "Opening a socket...";
+ open_connection !socket_name
+ (function () ->
+ go_to 0;
+ Symbols.set_all_events();
+ exit_main_loop ())
+
+(* Ensure the program is already loaded. *)
+let ensure_loaded () =
+ if not !loaded then begin
+ print_string "Loading program...";
+ flush Pervasives.stdout;
+ if !program_name = "" then begin
+ prerr_endline "No program specified.";
+ raise Toplevel
+ end;
+ try
+ initialize_loading();
+ !launching_func ();
+ if !debug_loading then
+ prerr_endline "Waiting for connection...";
+ main_loop ();
+ loaded := true;
+ if !debug_loading then
+ prerr_endline "done."
+ with
+ x ->
+ kill_program();
+ raise x
+ end
diff --git a/debugger/program_management.mli b/debugger/program_management.mli
new file mode 100644
index 000000000..fa43cb3d1
--- /dev/null
+++ b/debugger/program_management.mli
@@ -0,0 +1,26 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(*** Program loading and initializations. ***)
+
+val loaded : bool ref
+val ensure_loaded : unit -> unit
+
+(*** Kill program. ***)
+val kill_program : unit -> unit
+
+(* Ask wether to kill the program or not. *)
+(* If yes, kill it. *)
+(* Return true iff the program has been killed. *)
+val ask_kill_program : unit -> bool
diff --git a/debugger/show_information.ml b/debugger/show_information.ml
new file mode 100644
index 000000000..c13be2e99
--- /dev/null
+++ b/debugger/show_information.ml
@@ -0,0 +1,107 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Instruct
+open Format
+open Primitives
+open Debugcom
+open Checkpoints
+open Events
+open Symbols
+open Frames
+open Show_source
+open Breakpoints
+
+(* Display information about the current event. *)
+let show_current_event () =
+ print_string "Time : "; print_int (current_time ());
+ (match current_pc () with
+ Some pc ->
+ print_string " - pc : "; print_int pc
+ | _ -> ());
+ update_current_event ();
+ reset_frame ();
+ match current_report () with
+ None ->
+ print_newline ();
+ print_string "Beginning of program."; print_newline ();
+ show_no_point ()
+ | Some {rep_type = (Event | Breakpoint); rep_program_pointer = pc} ->
+ let (mdle, point) = current_point () in
+ print_string (" - module " ^ mdle);
+ print_newline ();
+ (match breakpoints_at_pc pc with
+ [] ->
+ ()
+ | [breakpoint] ->
+ print_string "Breakpoint : "; print_int breakpoint;
+ print_newline ()
+ | breakpoints ->
+ print_string "Breakpoints : ";
+ List.iter (function x -> print_int x; print_string " ") breakpoints;
+ print_newline ());
+ show_point mdle point (current_event_is_before ()) true
+ | Some {rep_type = Exited} ->
+ print_newline (); print_string "Program exit."; print_newline ();
+ show_no_point ()
+ | Some {rep_type = Uncaught_exc} ->
+ print_newline ();
+ print_string "Program end.";
+ print_newline ();
+ open_hovbox 0;
+ print_string "Uncaught exception:"; print_space();
+ (*print_value (get_accu ()) type_exn;*)
+ close_box();
+ print_newline();
+ show_no_point ()
+ | Some {rep_type = Trap_barrier} ->
+ (* Trap_barrier not visible outside *)
+ (* of module `time_travel'. *)
+ Misc.fatal_error "Show_information.show_current_event"
+
+(* Display short information about one frame. *)
+
+let show_one_frame framenum event =
+ print_string "#";
+ print_int framenum;
+ print_string " Pc : ";
+ print_int event.ev_pos;
+ print_string " ";
+ print_string event.ev_file;
+ print_string " char ";
+ print_int event.ev_char;
+ print_newline ()
+
+(* Display information about the current frame. *)
+(* --- `select frame' must have succeded before calling this function. *)
+let show_current_frame selected =
+ match !selected_event with
+ None ->
+ print_newline ();
+ print_string "No frame selected.";
+ print_newline ()
+ | Some sel_ev ->
+ show_one_frame !current_frame sel_ev;
+ begin match breakpoints_at_pc sel_ev.ev_pos with
+ [] ->
+ ()
+ | [breakpoint] ->
+ print_string "Breakpoint : "; print_int breakpoint; print_newline ()
+ | breakpoints ->
+ print_string "Breakpoints : ";
+ List.iter (function x -> print_int x; print_string " ") breakpoints;
+ print_newline ()
+ end;
+ show_point sel_ev.ev_file sel_ev.ev_char
+ (selected_event_is_before ()) selected
diff --git a/debugger/show_information.mli b/debugger/show_information.mli
new file mode 100644
index 000000000..45ee3b10b
--- /dev/null
+++ b/debugger/show_information.mli
@@ -0,0 +1,23 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Display information about the current event. *)
+val show_current_event : unit -> unit;;
+
+(* Display information about the current frame. *)
+(* --- `select frame' must have succeded before calling this function. *)
+val show_current_frame : bool -> unit;;
+
+(* Display short information about one frame. *)
+val show_one_frame : int -> Instruct.debug_event -> unit
diff --git a/debugger/show_source.ml b/debugger/show_source.ml
new file mode 100644
index 000000000..86e26ac47
--- /dev/null
+++ b/debugger/show_source.ml
@@ -0,0 +1,80 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+open Debugger_config
+open Parameters
+open Misc
+open Primitives
+open Source
+
+(* Print a line; return the beginning of the next line *)
+let print_line buffer line_number start point before =
+ let next = next_linefeed buffer start
+ and content = buffer_content buffer
+ in
+ print_int line_number;
+ print_string " ";
+ if (point <= next) & (point >= start) then
+ (print_string (String.sub content start (point - start));
+ print_string (if before then event_mark_before else event_mark_after);
+ print_string (String.sub content point (next - point)))
+ else
+ print_string (String.sub content start (next - start));
+ print_newline ();
+ next
+
+(* Tell Emacs we are nowhere in the source. *)
+let show_no_point () =
+ if !emacs then begin
+ print_string "\026\026H";
+ print_newline ()
+ end
+
+(* Print the line containing the point *)
+let show_point mdle point before selected =
+ if !emacs & selected then begin
+ let source = source_of_module mdle in
+ print_string "\026\026M";
+ print_string source;
+ print_string ":";
+ print_int point;
+ print_string (if before then ":before" else ":after");
+ print_newline ()
+ end
+ else begin
+ try
+ let buffer = get_buffer mdle in
+ let (start, line_number) = line_of_pos buffer point in
+ print_line buffer line_number start point before; ()
+ with
+ Out_of_range ->
+ prerr_endline "Position out of range."
+ | Not_found ->
+ prerr_endline ("Cannot find " ^ mdle ^ ".")
+ end
+
+(* Display part of the source. *)
+let show_listing mdle start stop point before =
+ let buffer = get_buffer mdle in
+ try
+ let rec aff (line_start, line_number) =
+ if line_number <= stop then
+ aff (print_line buffer line_number line_start point before + 1, line_number + 1)
+ in
+ aff (pos_of_line buffer start)
+ with
+ Out_of_range ->
+ prerr_endline "Position out of range."
+ | Not_found ->
+ prerr_endline ("Cannot find " ^ mdle ^ ".")
diff --git a/debugger/show_source.mli b/debugger/show_source.mli
new file mode 100644
index 000000000..f7a6e567d
--- /dev/null
+++ b/debugger/show_source.mli
@@ -0,0 +1,22 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Print the line containing the point *)
+val show_point : string -> int -> bool -> bool -> unit;;
+
+(* Tell Emacs we are nowhere in the source. *)
+val show_no_point : unit -> unit;;
+
+(* Display part of the source. *)
+val show_listing : string -> int -> int -> int -> bool -> unit;;
diff --git a/debugger/source.ml b/debugger/source.ml
new file mode 100644
index 000000000..87494c560
--- /dev/null
+++ b/debugger/source.ml
@@ -0,0 +1,152 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(************************ Source management ****************************)
+
+open Misc
+open Primitives
+
+(*** Conversion function. ***)
+
+let source_of_module mdle =
+ find_in_path !Config.load_path mdle
+
+(*** Buffer cache ***)
+
+(* Buffer and cache (to associate lines and positions in the buffer). *)
+type buffer = string * (int * int) list ref
+
+let buffer_max_count = ref 10
+
+let cache_size = 30
+
+let buffer_list =
+ ref ([] : (string * buffer) list)
+
+let flush_buffer_list () =
+ buffer_list := []
+
+let get_buffer mdle =
+ try List.assoc mdle !buffer_list with
+ Not_found ->
+ let inchan = open_in (source_of_module mdle) in
+ let (content, _) as buffer =
+ (String.create (in_channel_length inchan), ref [])
+ in
+ unsafe_really_input inchan content 0 (in_channel_length inchan);
+ buffer_list :=
+ (list_truncate !buffer_max_count ((mdle, buffer)::!buffer_list));
+ buffer
+
+let buffer_content =
+ (fst : buffer -> string)
+
+let buffer_length x =
+ String.length (buffer_content x)
+
+(*** Position conversions. ***)
+
+type position = int * int
+
+(* Insert a new pair (position, line) in the cache of the given buffer. *)
+let insert_pos buffer ((position, line) as pair) =
+ let rec new_list =
+ function
+ [] ->
+ [(position, line)]
+ | ((pos, lin) as a::l) as l' ->
+ if lin < line then
+ pair::l'
+ else if lin = line then
+ l'
+ else
+ a::(new_list l)
+ in
+ let buffer_cache = snd buffer in
+ buffer_cache := new_list !buffer_cache
+
+(* Position of the next linefeed after `pos'. *)
+(* Position just after the buffer end if no linefeed found. *)
+(* Raise `Out_of_range' if already there. *)
+let next_linefeed (buffer, _) pos =
+ let len = String.length buffer in
+ if pos >= len then
+ raise Out_of_range
+ else
+ let rec search p =
+ if (p = len) or (String.get buffer p = '\n') then
+ p
+ else
+ search (succ p)
+ in
+ search pos
+
+(* Go to next line. *)
+let next_line buffer (pos, line) =
+ (next_linefeed buffer pos + 1, line + 1)
+
+(* Convert a position in the buffer to a line number. *)
+let line_of_pos buffer position =
+ let rec find =
+ function
+ [] ->
+ if position < 0 then
+ raise Out_of_range
+ else
+ (0, 1)
+ | ((pos, line) as pair)::l ->
+ if pos > position then
+ find l
+ else
+ pair
+ and find_line previous =
+ let (pos, line) as next = next_line buffer previous in
+ if pos <= position then
+ find_line next
+ else
+ previous
+ in
+ let result = find_line (find !(snd buffer)) in
+ insert_pos buffer result;
+ result
+
+(* Convert a line number to a position. *)
+let pos_of_line buffer line =
+ let rec find =
+ function
+ [] ->
+ if line <= 0 then
+ raise Out_of_range
+ else
+ (0, 1)
+ | ((pos, lin) as pair)::l ->
+ if lin > line then
+ find l
+ else
+ pair
+ and find_pos previous =
+ let (_, lin) as next = next_line buffer previous in
+ if lin <= line then
+ find_pos next
+ else
+ previous
+ in
+ let result = find_pos (find !(snd buffer)) in
+ insert_pos buffer result;
+ result
+
+(* Convert a coordinate (line / column) into a position. *)
+(* --- The first line and column are line 1 and column 1. *)
+let point_of_coord buffer line column =
+ fst (pos_of_line buffer line) + (pred column)
diff --git a/debugger/source.mli b/debugger/source.mli
new file mode 100644
index 000000000..cd0826542
--- /dev/null
+++ b/debugger/source.mli
@@ -0,0 +1,57 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(************************ Source management ****************************)
+
+(*** Conversion function. ***)
+
+val source_of_module: string -> string
+
+(*** buffer cache ***)
+
+type buffer
+
+val buffer_max_count : int ref
+
+val flush_buffer_list : unit -> unit
+
+val get_buffer : string -> buffer
+
+val buffer_content : buffer -> string
+val buffer_length : buffer -> int
+
+(*** Position conversions. ***)
+
+(* Pair (position, line) where `position' is the position in character of *)
+(* the beginning of the line (first character is 0) and `line' is its *)
+(* number (first line number is 1). *)
+type position = int * int
+
+(* Position of the next linefeed after `pos'. *)
+(* Position just after the buffer end if no linefeed found. *)
+(* Raise `Out_of_range' if already there. *)
+val next_linefeed : buffer -> int -> int
+
+(* Go to next line. *)
+val next_line : buffer -> position -> position
+
+(* Convert a position in the buffer to a line number. *)
+val line_of_pos : buffer -> int -> position
+
+(* Convert a line number to a position. *)
+val pos_of_line : buffer -> int -> position
+
+(* Convert a coordinate (line / column) into a position. *)
+(* --- The first line and column are line 1 and column 1. *)
+val point_of_coord : buffer -> int -> int -> int
diff --git a/debugger/symbols.ml b/debugger/symbols.ml
new file mode 100644
index 000000000..8af8b8a38
--- /dev/null
+++ b/debugger/symbols.ml
@@ -0,0 +1,111 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Handling of symbol tables (globals and events) *)
+
+open Instruct
+open Debugger_config (* Toplevel *)
+
+let verbose = ref true
+
+let modules =
+ ref ([] : string list)
+
+let events =
+ ref ([] : debug_event list)
+let events_by_pc =
+ (Hashtbl.create 257 : (int, debug_event) Hashtbl.t)
+let events_by_file =
+ (Hashtbl.create 17 : (string, debug_event array) Hashtbl.t)
+
+let read_symbols' bytecode_file =
+ let ic = open_in_bin bytecode_file in
+ let pos_trailer =
+ in_channel_length ic - 16 - String.length Config.exec_magic_number in
+ seek_in ic pos_trailer;
+ let code_size = input_binary_int ic in
+ let data_size = input_binary_int ic in
+ let symbol_size = input_binary_int ic in
+ let debug_size = input_binary_int ic in
+ let magic = String.create (String.length Config.exec_magic_number) in
+ really_input ic magic 0 (String.length Config.exec_magic_number);
+ if magic <> Config.exec_magic_number then begin
+ prerr_string bytecode_file; prerr_endline " is not a bytecode file.";
+ exit 2
+ end;
+ if debug_size = 0 then begin
+ prerr_string bytecode_file; prerr_endline " has no debugging info.";
+ exit 2
+ end;
+ seek_in ic (pos_trailer - debug_size - symbol_size);
+ Symtable.restore_state (input_value ic);
+ let all_events = (input_value ic : debug_event list list) in
+ close_in ic;
+ all_events
+
+let read_symbols bytecode_file =
+ let all_events = read_symbols' bytecode_file in
+ List.iter
+ (fun evl ->
+ List.iter
+ (fun ev ->
+ events := ev :: !events;
+ Hashtbl.add events_by_pc ev.ev_pos ev)
+ evl)
+ all_events;
+
+ List.iter
+ (function
+ [] -> ()
+ | ev :: _ as evl ->
+ let file = ev.ev_file
+ and sorted_evl = Sort.list (fun ev1 ev2 -> ev1.ev_char <= ev2.ev_char) evl in
+ modules := file :: !modules;
+ Hashtbl.add events_by_file file (Array.of_list sorted_evl))
+ all_events
+
+let event_at_pc pc =
+ Hashtbl.find events_by_pc pc
+(*
+ try
+ Hashtbl.find events_by_pc pc
+ with Not_found ->
+ prerr_string "No event at pc="; prerr_int pc; prerr_endline ".";
+ (*exit 2*)
+ raise Toplevel
+*)
+
+(* Return the list of events at `pc' *)
+let events_at_pc =
+ Hashtbl.find_all events_by_pc
+
+let event_at_pos file char =
+ let ev = Hashtbl.find events_by_file file in
+ (* Binary search of event at or just after char *)
+ let rec bsearch lo hi =
+ if lo >= hi then
+ if hi + 1 < Array.length ev then ev.(hi+1) else ev.(hi)
+ else begin
+ let pivot = (lo + hi) / 2 in
+ let e = ev.(pivot) in
+ if char = e.ev_char then e else
+ if char < e.ev_char then bsearch lo (pivot - 1)
+ else bsearch (pivot + 1) hi
+ end in
+ bsearch 0 (Array.length ev - 1)
+
+let set_all_events () =
+ Hashtbl.iter
+ (fun pc ev -> Debugcom.set_event ev.ev_pos)
+ events_by_pc
diff --git a/debugger/symbols.mli b/debugger/symbols.mli
new file mode 100644
index 000000000..d212a139e
--- /dev/null
+++ b/debugger/symbols.mli
@@ -0,0 +1,26 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Modules used by the program. *)
+val modules : string list ref
+
+(* Events used by the program *)
+val events : Instruct.debug_event list ref
+val events_by_pc : (int, Instruct.debug_event) Hashtbl.t
+val events_by_file : (string, Instruct.debug_event array) Hashtbl.t
+
+val read_symbols : string -> unit
+val event_at_pc : int -> Instruct.debug_event
+val event_at_pos : string -> int -> Instruct.debug_event
+val set_all_events : unit -> unit
diff --git a/debugger/time_travel.ml b/debugger/time_travel.ml
new file mode 100644
index 000000000..525f1c6a7
--- /dev/null
+++ b/debugger/time_travel.ml
@@ -0,0 +1,553 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(**************************** Time travel ******************************)
+
+open Instruct
+open Events
+open Debugcom
+open Primitives
+open Checkpoints
+open Breakpoints
+open Trap_barrier
+open Input_handling
+open Debugger_config
+open Program_loading
+
+exception Current_checkpoint_lost
+
+let remove_1st key list =
+ let rec remove =
+ function
+ [] -> []
+ | a::l -> if a == key then l else a::(remove l)
+ in
+ remove list
+
+(*** Debugging. ***)
+
+let debug_time_travel = ref false
+
+(*** Internal utilities. ***)
+
+(* Select a checkpoint at current. *)
+let set_current_checkpoint checkpoint =
+ current_checkpoint := checkpoint;
+ set_current_connection checkpoint.c_fd
+
+(* Insert a checkpoint in the checkpoint list.
+ * Raise `Exit' if there is already a checkpoint at the same time.
+ *)
+let insert_checkpoint ({c_time = time} as checkpoint) =
+ let rec traverse =
+ function
+ [] -> [checkpoint]
+ | (({c_time = t} as a)::l) as l' ->
+ if t > time then
+ a::(traverse l)
+ else if t = time then
+ raise Exit
+ else
+ checkpoint::l'
+ in
+ checkpoints := traverse !checkpoints
+
+(* Remove a checkpoint from the checkpoint list.
+ * --- No error if not found.
+ *)
+let remove_checkpoint checkpoint =
+ checkpoints := remove_1st checkpoint !checkpoints
+
+(* Wait for the process used by `checkpoint' to connect.
+ * --- Usually not called (the process is already connected).
+ *)
+let wait_for_connection checkpoint =
+ try
+ Exec.unprotected
+ (function () ->
+ let old_controller = Input_handling.current_controller !connection in
+ execute_with_other_controller
+ (function
+ fd ->
+ old_controller fd;
+ if checkpoint.c_valid = true then
+ exit_main_loop ())
+ !connection
+ main_loop)
+ with
+ Sys.Break ->
+ checkpoint.c_parent = root;
+ remove_checkpoint checkpoint;
+ checkpoint.c_pid <- -1;
+ raise Sys.Break
+
+(* Kill `checkpoint'. *)
+let kill_checkpoint checkpoint =
+ if !debug_time_travel then
+ prerr_endline ("Kill : " ^ (string_of_int checkpoint.c_pid));
+ if checkpoint.c_pid > 0 then (* Ghosts don't have to be killed ! *)
+ (if not checkpoint.c_valid then
+ wait_for_connection checkpoint;
+ stop checkpoint.c_fd;
+ if checkpoint.c_parent.c_pid > 0 then
+ wait_child checkpoint.c_parent.c_fd;
+ checkpoint.c_parent = root;
+ close_io checkpoint.c_fd;
+ remove_file checkpoint.c_fd;
+ remove_checkpoint checkpoint);
+ checkpoint.c_pid <- -1 (* Don't exist anymore *)
+
+(*** Cleaning the checkpoint list. ***)
+
+(* Separe checkpoints before (<=) and after (>) `t'. *)
+(* ### t checkpoints -> (after, before) *)
+let cut t =
+ let rec cut_t =
+ function
+ [] -> ([], [])
+ | ({c_time = t'} as a::l) as l' ->
+ if t' <= t then
+ ([], l')
+ else
+ let (b, e) = cut_t l in
+ (a::b, e)
+ in
+ cut_t
+
+(* Partition the checkpoints list. *)
+let cut2 t0 t l =
+ let rec cut2_t0 t =
+ function
+ [] -> []
+ | l ->
+ let (after, before) = cut (t0 - t - 1) l in
+ let l = cut2_t0 (2 * t) before in
+ after::l
+ in
+ let (after, before) = cut (t0 - 1) l in
+ after::(cut2_t0 t before)
+
+(* Separe first elements and last element of a list of checkpoint. *)
+let chk_merge2 cont =
+ let rec chk_merge2_cont =
+ function
+ [] -> cont
+ | [a] ->
+ let (accepted, rejected) = cont in
+ (a::accepted, rejected)
+ | a::l ->
+ let (accepted, rejected) = chk_merge2_cont l in
+ (accepted, a::rejected)
+ in chk_merge2_cont
+
+(* Separe the checkpoint list. *)
+(* ### list -> accepted * rejected *)
+let rec chk_merge =
+ function
+ [] -> ([], [])
+ | l::tail ->
+ chk_merge2 (chk_merge tail) l
+
+let new_checkpoint_list checkpoint_count accepted rejected =
+ if List.length accepted >= checkpoint_count then
+ let (k, l) = list_truncate2 checkpoint_count accepted in
+ (k, l @ rejected)
+ else
+ let (k, l) =
+ list_truncate2 (checkpoint_count - List.length accepted) rejected
+ in
+ (Sort.merge (fun {c_time = t1} {c_time = t2} -> t1 > t2) accepted k,
+ l)
+
+(* Clean the checkpoint list. *)
+(* Reference time is `time'. *)
+let clean_checkpoints time checkpoint_count =
+ let (after, before) = cut time !checkpoints in
+ let (accepted, rejected) =
+ chk_merge (cut2 time !checkpoint_small_step before)
+ in
+ let (kept, lost) =
+ new_checkpoint_list checkpoint_count accepted after
+ in
+ List.map kill_checkpoint (lost @ rejected);
+ checkpoints := kept
+
+(*** Internal functions for moving. ***)
+
+(* Find the first checkpoint before (or at) `time'.
+ * Ask for reloading the program if necessary.
+ *)
+let find_checkpoint_before time =
+ let rec find =
+ function
+ [] ->
+ print_string "Can't go that far in the past !"; print_newline ();
+ if yes_or_no "Reload program" then begin
+ load_program ();
+ find !checkpoints
+ end
+ else
+ raise Toplevel
+ | { c_time = t } as a::l ->
+ if t > time then
+ find l
+ else
+ a
+ in find !checkpoints
+
+(* Make a copy of the current checkpoint and clean the checkpoint list. *)
+(* --- The new checkpoint in not put in the list. *)
+let duplicate_current_checkpoint () =
+ let checkpoint = !current_checkpoint in
+ if not checkpoint.c_valid then
+ wait_for_connection checkpoint;
+ let new_checkpoint = (* Ghost *)
+ {c_time = checkpoint.c_time;
+ c_pid = 0;
+ c_fd = checkpoint.c_fd;
+ c_valid = false;
+ c_report = checkpoint.c_report;
+ c_state = C_stopped;
+ c_parent = checkpoint;
+ c_breakpoint_version = checkpoint.c_breakpoint_version;
+ c_breakpoints = checkpoint.c_breakpoints;
+ c_trap_barrier = checkpoint.c_trap_barrier}
+ in
+ checkpoints := list_replace checkpoint new_checkpoint !checkpoints;
+ set_current_checkpoint checkpoint;
+ clean_checkpoints (checkpoint.c_time + 1) (!checkpoint_max_count - 1);
+ if new_checkpoint.c_pid = 0 then (* The ghost has not been killed *)
+ (match do_checkpoint () with (* Duplicate checkpoint *)
+ Checkpoint_done pid ->
+ (new_checkpoint.c_pid <- pid;
+ if !debug_time_travel then
+ prerr_endline ("Waiting for connection : " ^ (string_of_int pid)))
+ | Checkpoint_failed ->
+ prerr_endline
+ "A fork failed. Reducing maximum number of checkpoints.";
+ checkpoint_max_count := List.length !checkpoints - 1;
+ remove_checkpoint new_checkpoint)
+
+(* Ensure we stop on an event. *)
+let rec stop_on_event report =
+ let find_event () =
+ if !debug_time_travel then
+ (print_string "Searching next event..."; print_newline ());
+ let report = do_go 1 in
+ !current_checkpoint.c_report <- Some report;
+ stop_on_event report
+ in
+ match report with
+ {rep_type = Breakpoint; rep_program_pointer = pc} ->
+ if Some pc = !temporary_breakpoint_position then begin
+ (* Others breakpoints are on events. *)
+ try (* Check if we are on an event. *)
+ update_current_event ()
+ with
+ Not_found -> find_event ()
+ end
+ | {rep_type = Trap_barrier; rep_stack_pointer = trap_frame} ->
+ (* No event at current position. *)
+ find_event ()
+ | _ ->
+ ()
+
+(* Was the movement interrupted ? *)
+(* --- An exception could have been used instead, *)
+(* --- but it is not clear where it should be caught. *)
+(* --- For instance, we can't caught it should not be caught in `step' *)
+(* --- (as `step' is used in `next_1'). *)
+(* --- On the other side, other modules does not need to know *)
+(* --- about this exception. *)
+let interrupted = ref false
+
+(* Internal function for running debugged program.
+ * Requires `duration > 0'.
+ *)
+let internal_step duration =
+ match current_report () with
+ Some {rep_type = Exited | Uncaught_exc} -> ()
+ | _ ->
+ Exec.protected
+ (function () ->
+ if !make_checkpoints then
+ duplicate_current_checkpoint ()
+ else
+ remove_checkpoint !current_checkpoint;
+ update_breakpoints ();
+ update_trap_barrier ();
+ !current_checkpoint.c_state <- C_running duration;
+ let report = do_go duration in
+ !current_checkpoint.c_report <- Some report;
+ !current_checkpoint.c_state <- C_stopped;
+ if report.rep_type = Event then begin
+ !current_checkpoint.c_time <-
+ !current_checkpoint.c_time + duration;
+ interrupted := false
+ end
+ else begin
+ !current_checkpoint.c_time <-
+ !current_checkpoint.c_time + duration
+ - report.rep_event_count + 1;
+ interrupted := true;
+ stop_on_event report
+ end;
+ (try
+ insert_checkpoint !current_checkpoint
+ with
+ Exit ->
+ kill_checkpoint !current_checkpoint;
+ set_current_checkpoint
+ (find_checkpoint_before (current_time ()))));
+ if !debug_time_travel then begin
+ print_string "Checkpoints : pid(time)"; print_newline ();
+ List.map
+ (function {c_time = time; c_pid = pid; c_valid = valid} ->
+ print_int pid;
+ print_string "("; print_int time; print_string ")";
+ if not valid then print_string "(invalid)";
+ print_string " ")
+ !checkpoints;
+ print_newline ()
+ end
+
+(*** Miscellaneous functions (exported). ***)
+
+(* Create a checkpoint at time 0 (new program). *)
+let new_checkpoint pid fd =
+ let new_checkpoint =
+ {c_time = 0;
+ c_pid = pid;
+ c_fd = fd;
+ c_valid = true;
+ c_report = None;
+ c_state = C_stopped;
+ c_parent = root;
+ c_breakpoint_version = 0;
+ c_breakpoints = [];
+ c_trap_barrier = 0}
+ in
+ insert_checkpoint new_checkpoint
+
+(* Set the file descriptor of a checkpoint *)
+(* (a new process has connected with the debugger). *)
+(* --- Return `true' on success (close the connection otherwise). *)
+let set_file_descriptor pid fd =
+ let rec find =
+ function
+ [] ->
+ prerr_endline "Unexpected connection";
+ close_io fd;
+ false
+ | ({c_pid = pid'} as checkpoint)::l ->
+ if pid <> pid' then
+ find l
+ else
+ (checkpoint.c_fd <- fd;
+ checkpoint.c_valid <- true;
+ true)
+ in
+ if !debug_time_travel then
+ prerr_endline ("Nouvelle connection : " ^(string_of_int pid));
+ find (!current_checkpoint::!checkpoints)
+
+(* Kill all the checkpoints. *)
+let kill_all_checkpoints () =
+ List.iter kill_checkpoint (!current_checkpoint::!checkpoints)
+
+(* Kill a checkpoint without killing the process. *)
+(* (used when connection with the process is lost). *)
+(* --- Assume that the checkpoint is valid. *)
+let forget_process fd pid =
+ let checkpoint =
+ find (function c -> c.c_pid = pid) (!current_checkpoint::!checkpoints)
+ in
+ prerr_string "Lost connection with process ";
+ prerr_int pid;
+ if checkpoint = !current_checkpoint then begin
+ prerr_endline " (active process)";
+ match !current_checkpoint.c_state with
+ C_stopped ->
+ prerr_string "at time ";
+ prerr_int !current_checkpoint.c_time
+ | C_running duration ->
+ prerr_string "between time ";
+ prerr_int !current_checkpoint.c_time;
+ prerr_string " and time ";
+ prerr_int (!current_checkpoint.c_time + duration)
+ end;
+ prerr_endline "";
+ Input_handling.remove_file fd;
+ close_io checkpoint.c_fd;
+ remove_file checkpoint.c_fd;
+ remove_checkpoint checkpoint;
+ checkpoint.c_pid <- -1; (* Don't exist anymore *)
+ if checkpoint.c_parent.c_pid > 0 then
+ wait_child checkpoint.c_parent.c_fd;
+ if checkpoint = !current_checkpoint then
+ raise Current_checkpoint_lost
+
+(* Try to recover when the current checkpoint is lost. *)
+let recover () =
+ set_current_checkpoint
+ (find_checkpoint_before (current_time ()))
+
+(*** Simple movements. ***)
+
+(* Forward stepping. Requires `duration >= 0'. *)
+let rec step_forward duration =
+ if duration > !checkpoint_small_step then begin
+ let first_step =
+ if duration > !checkpoint_big_step then
+ !checkpoint_big_step
+ else
+ !checkpoint_small_step
+ in
+ internal_step first_step;
+ if not !interrupted then
+ step_forward (duration - first_step)
+ end
+ else if duration != 0 then
+ internal_step duration
+
+(* Go to time `time' from current checkpoint (internal). *)
+let internal_go_to time =
+ let duration = time - current_time () in
+ if duration > 0 then
+ step_forward duration
+
+(* Move to a given time. *)
+let go_to time =
+ let checkpoint = find_checkpoint_before time in
+ set_current_checkpoint checkpoint;
+ internal_go_to time
+
+(* Return the time of the last breakpoint *)
+(* between current time and `max_time'. *)
+let rec find_last_breakpoint max_time =
+ let on_breakpoint () =
+ match current_report () with
+ Some {rep_program_pointer = pc} ->
+ breakpoint_at_pc pc
+ | _ ->
+ false
+ in
+ let rec find break =
+ let time = current_time () in
+ step_forward (max_time - time);
+ if ((on_breakpoint ()) & (current_time () < max_time)) then
+ find true
+ else
+ (time, break)
+ in
+ find (on_breakpoint ())
+
+(* Run from `time_max' back to `time'. *)
+(* --- Assume 0 <= time < time_max *)
+let rec back_to time time_max =
+ let
+ {c_time = t} as checkpoint = find_checkpoint_before (time_max - 1)
+ in
+ go_to (max time t);
+ let (new_time, break) = find_last_breakpoint time_max in
+ if break or (new_time <= time) then
+ go_to new_time
+ else
+ back_to time new_time
+
+(* Backward stepping. *)
+(* --- Assume duration > 1 *)
+let step_backward duration =
+ let time = current_time () in
+ if time > 0 then
+ back_to (max 0 (time - duration)) time
+
+(* Run the program from current time. *)
+(* Stop at the first breakpoint, or at the end of the program. *)
+let rec run () =
+ internal_step !checkpoint_big_step;
+ if not !interrupted then
+ run ()
+
+(* Run backward the program form current time. *)
+(* Stop at the first breakpoint, or at the beginning of the program. *)
+let back_run () =
+ if current_time () > 0 then
+ back_to 0 (current_time ())
+
+(* Step in any direction. *)
+(* Stop at the first brakpoint, or after `duration' steps. *)
+let step duration =
+ if duration >= 0 then
+ step_forward duration
+ else
+ step_backward (-duration)
+
+(*** Next, finish. ***)
+
+(* Finish current fucntion. *)
+let finish () =
+ match !current_event with
+ None ->
+ prerr_endline "Program is currently not running."; raise Toplevel
+ | Some curr_event ->
+ initial_frame();
+ let (frame, pc) = up_frame curr_event.ev_stacksize in
+ if frame < 0 then begin
+ prerr_endline "`finish' not meaningful in outermost frame.";
+ raise Toplevel
+ end;
+ exec_with_trap_barrier
+ frame
+ (fun () ->
+ exec_with_temporary_breakpoint
+ pc
+ (fun () ->
+ while
+ run ();
+ match current_report () with
+ Some {rep_type = Breakpoint;
+ rep_stack_pointer = sp;
+ rep_program_pointer = pc2} ->
+ (pc = pc2) && (frame <> sp)
+ | _ ->
+ false
+ do
+ ()
+ done))
+
+let next_1 () =
+ match !current_event with
+ None -> (* Beginning of the program. *)
+ step 1
+ | Some event1 ->
+ let (frame1, pc1) = initial_frame() in
+ step 1;
+ match !current_event with
+ None -> ()
+ | Some event2 ->
+ let (frame2, pc2) = initial_frame() in
+ (* Call `finish' if we've entered a function. *)
+ if frame1 >= 0 && frame2 >= 0 &&
+ frame2 + event2.ev_stacksize < frame1 + event1.ev_stacksize
+ then finish()
+
+(* Same as `step' (forward) but skip over function calls. *)
+let rec next =
+ function
+ 0 -> ()
+ | n ->
+ next_1 ();
+ if not !interrupted then
+ next (n - 1)
diff --git a/debugger/time_travel.mli b/debugger/time_travel.mli
new file mode 100644
index 000000000..521932e12
--- /dev/null
+++ b/debugger/time_travel.mli
@@ -0,0 +1,33 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(**************************** Time travel ******************************)
+
+open Primitives
+
+exception Current_checkpoint_lost
+
+val new_checkpoint : int -> io_channel -> unit
+val set_file_descriptor : int -> io_channel -> bool
+val kill_all_checkpoints : unit -> unit
+val forget_process : io_channel -> int -> unit
+val recover : unit -> unit
+
+val go_to : int -> unit
+
+val run : unit -> unit
+val back_run : unit -> unit
+val step : int -> unit
+val finish : unit -> unit
+val next : int -> unit
diff --git a/debugger/trap_barrier.ml b/debugger/trap_barrier.ml
new file mode 100644
index 000000000..ae627c96a
--- /dev/null
+++ b/debugger/trap_barrier.ml
@@ -0,0 +1,46 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(************************** Trap barrier *******************************)
+
+open Debugcom
+open Checkpoints
+
+let current_trap_barrier = ref 0
+
+let install_trap_barrier pos =
+ current_trap_barrier := pos
+
+let remove_trap_barrier () =
+ current_trap_barrier := 0
+
+(* Ensure the trap barrier state is up to date in current checkpoint. *)
+let update_trap_barrier () =
+ if !current_checkpoint.c_trap_barrier <> !current_trap_barrier then
+ Exec.protected
+ (function () ->
+ set_trap_barrier !current_trap_barrier;
+ !current_checkpoint.c_trap_barrier <- !current_trap_barrier)
+
+(* Execute `funct' with a trap barrier. *)
+(* --- Used by `finish'. *)
+let exec_with_trap_barrier trap_barrier funct =
+ try
+ install_trap_barrier trap_barrier;
+ funct ();
+ remove_trap_barrier ()
+ with
+ x ->
+ remove_trap_barrier ();
+ raise x
diff --git a/debugger/trap_barrier.mli b/debugger/trap_barrier.mli
new file mode 100644
index 000000000..6f10ca060
--- /dev/null
+++ b/debugger/trap_barrier.mli
@@ -0,0 +1,26 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(************************* Trap barrier ********************************)
+
+val install_trap_barrier : int -> unit
+
+val remove_trap_barrier : unit -> unit
+
+(* Ensure the trap barrier state is up to date in current checkpoint. *)
+val update_trap_barrier : unit -> unit
+
+(* Execute `funct' with a trap barrier. *)
+(* --- Used by `finish'. *)
+val exec_with_trap_barrier : int -> (unit -> unit) -> unit
diff --git a/debugger/unix_tools.ml b/debugger/unix_tools.ml
new file mode 100644
index 000000000..4bcfc25c4
--- /dev/null
+++ b/debugger/unix_tools.ml
@@ -0,0 +1,139 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(****************** Tools for Unix *************************************)
+
+open Misc
+open Unix
+open Primitives
+
+(*** Convert a socket name into a socket address. ***)
+let convert_address address =
+ try
+ let n = string_pos address ':' in
+ let host = String.sub address 0 (n - 1)
+ and port = String.sub address (n + 1) (String.length address)
+ in
+ (PF_INET,
+ ADDR_INET
+ ((try inet_addr_of_string host with Failure _ ->
+ try (gethostbyname host).h_addr_list.(0) with Not_found ->
+ prerr_endline ("Unknown host : " ^ host);
+ failwith "Can't convert address"),
+ (try int_of_string port with Failure _ ->
+ prerr_endline "The port number should be an integer";
+ failwith "Can't convert address")))
+ with Not_found ->
+ (PF_UNIX, ADDR_UNIX address)
+
+(*** Report an unix error. ***)
+let report_error = function
+ Unix_error (err, fun_name, arg) ->
+ prerr_string "Unix error : '";
+ prerr_string fun_name;
+ prerr_string "' failed";
+ if String.length arg > 0 then
+ (prerr_string " on '";
+ prerr_string arg;
+ prerr_string "'");
+ prerr_string " : ";
+ prerr_endline (error_message err)
+ | _ -> fatal_error "report_error: not an Unix error"
+
+(* Find program `name' in `PATH'. *)
+(* Return the full path if found. *)
+(* Raise `Not_found' otherwise. *)
+let search_in_path name =
+ let check name =
+ try access name [X_OK]; name with Unix_error _ -> raise Not_found
+ in
+ if (try string_pos name '/'; true with Not_found -> false) then
+ check name
+ else
+ let path = Sys.getenv "PATH" in
+ let length = String.length path in
+ let rec traverse pointer =
+ if (pointer >= length) or (path.[pointer] = ':') then
+ pointer
+ else
+ traverse (pointer + 1)
+ in
+ let rec find pos =
+ let pos2 = traverse pos in
+ let directory = (String.sub path pos (pos2 - pos)) in
+ let fullname =
+ if directory = "" then
+ name
+ else
+ directory ^ "/" ^ name
+ in
+ try check fullname with
+ Not_found ->
+ if pos2 < length then
+ find (pos2 + 1)
+ else
+ raise Not_found
+ in
+ find 0
+
+(* Expand a path. *)
+(* ### path -> path' *)
+let rec expand_path ch =
+ let rec subst_variable ch =
+ try
+ let pos = string_pos ch '$' in
+ if (pos + 1 < String.length ch) & (ch.[pos + 1] = '$') then
+ (String.sub ch 0 (pos + 1))
+ ^ (subst_variable
+ (String.sub ch (pos + 2) (String.length ch - pos - 2)))
+ else
+ (String.sub ch 0 pos)
+ ^ (subst2 (String.sub ch (pos + 1) (String.length ch - pos - 1)))
+ with Not_found ->
+ ch
+ and subst2 ch =
+ let suiv =
+ let i = ref 0 in
+ while !i < String.length ch &&
+ (let c = ch.[!i] in (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c = '_')
+ do incr i done;
+ !i
+ in (Sys.getenv (String.sub ch 0 suiv))
+ ^ (subst_variable (String.sub ch suiv (String.length ch - suiv)))
+ in
+ let ch = subst_variable ch in
+ let concat_root nom ch2 =
+ try Filename.concat (getpwnam nom).pw_dir ch2
+ with Not_found ->
+ "~" ^ nom
+ in
+ if ch.[0] = '~' then
+ try
+ match string_pos ch '/' with
+ 1 ->
+ (let tail = String.sub ch 2 (String.length ch - 2)
+ in
+ try Filename.concat (Sys.getenv "HOME") tail
+ with Not_found ->
+ concat_root (Sys.getenv "LOGNAME") tail)
+ | n -> concat_root
+ (String.sub ch 1 (n - 1))
+ (String.sub ch (n + 1) (String.length ch - n - 1))
+ with
+ Not_found ->
+ expand_path (ch ^ "/")
+ else ch
diff --git a/debugger/unix_tools.mli b/debugger/unix_tools.mli
new file mode 100644
index 000000000..6672e925c
--- /dev/null
+++ b/debugger/unix_tools.mli
@@ -0,0 +1,31 @@
+(***********************************************************************)
+(* *)
+(* 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 *)
+(* Automatique. Distributed only by permission. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(**************************** Tools for Unix ***************************)
+
+open Unix
+
+(* Convert a socket name into a socket address. *)
+val convert_address : string -> socket_domain * sockaddr
+
+(* Report an unix error. *)
+val report_error : exn -> unit
+
+(* Find program `name' in `PATH'. *)
+(* Return the full path if found. *)
+(* Raise `Not_found' otherwise. *)
+val search_in_path : string -> string
+
+(* Path expansion. *)
+val expand_path : string -> string