1 (***********************************************************************)
5 (* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *)
6 (* Objective Caml port by John Malecki and Xavier Leroy *)
8 (* Copyright 1996 Institut National de Recherche en Informatique et *)
9 (* en Automatique. All rights reserved. This file is distributed *)
10 (* under the terms of the Q Public License version 1.0. *)
12 (***********************************************************************)
14 (* $Id: command_line.ml 9299 2009-06-17 08:15:39Z xclerc $ *)
16 (************************ Reading and executing commands ***************)
34 open Program_management
48 (** Instructions, variables and infos lists. **)
49 type dbg_instruction =
50 { instr_name: string; (* Name of command *)
51 instr_prio: bool; (* Has priority *)
52 instr_action: formatter -> lexbuf -> unit;
54 instr_repeat: bool; (* Can be repeated *)
55 instr_help: string } (* Help message *)
57 let instruction_list = ref ([] : dbg_instruction list)
60 { var_name: string; (* Name of variable *)
61 var_action: (lexbuf -> unit) * (formatter -> unit);
62 (* Reading, writing fns *)
63 var_help: string } (* Help message *)
65 let variable_list = ref ([] : dbg_variable list)
68 { info_name: string; (* Name of info *)
69 info_action: lexbuf -> unit; (* What to do *)
70 info_help: string } (* Help message *)
72 let info_list = ref ([] : dbg_info list)
79 let check_not_windows feature =
80 match Sys.os_type with
82 error ("'"^feature^"' feature not supported on Windows")
87 end_of_line Lexer.lexeme
89 let matching_elements list name instr =
90 List.filter (function a -> isprefix instr (name a)) !list
92 let all_matching_instructions =
93 matching_elements instruction_list (fun i -> i.instr_name)
95 (* itz 04-21-96 don't do priority completion in emacs mode *)
96 (* XL 25-02-97 why? I find it very confusing. *)
98 let matching_instructions instr =
99 let all = all_matching_instructions instr in
100 let prio = List.filter (fun i -> i.instr_prio) all in
101 if prio = [] then all else prio
103 let matching_variables =
104 matching_elements variable_list (fun v -> v.var_name)
107 matching_elements info_list (fun i -> i.info_name)
109 let find_ident name matcher action alternative ppf lexbuf =
110 match identifier_or_eol Lexer.lexeme lexbuf with
111 | None -> alternative ppf
113 match matcher ident with
114 | [] -> error ("Unknown " ^ name ^ ".")
115 | [a] -> action a ppf lexbuf
116 | _ -> error ("Ambiguous " ^ name ^ ".")
118 let find_variable action alternative ppf lexbuf =
119 find_ident "variable name" matching_variables action alternative ppf lexbuf
121 let find_info action alternative ppf lexbuf =
122 find_ident "info command" matching_infos action alternative ppf lexbuf
124 let add_breakpoint_at_pc pc =
126 new_breakpoint (any_event_at_pc pc)
129 eprintf "Can't add breakpoint at pc %i : no event there.@." pc;
132 let add_breakpoint_after_pc pc =
136 new_breakpoint (any_event_at_pc (pc + n * 4))
142 "Can't add breakpoint at beginning of function: no event there"
146 let module_of_longident id =
148 | Some x -> Some (String.concat "." (Longident.flatten x))
151 let convert_module mdle =
154 (* Strip .ml extension if any, and capitalize *)
155 String.capitalize(if Filename.check_suffix m ".ml"
156 then Filename.chop_suffix m ".ml"
160 (get_current_event ()).ev_module
163 error "Not in a module."
166 let current_line = ref ""
168 let interprete_line ppf line =
169 current_line := line;
170 let lexbuf = Lexing.from_string line in
172 match identifier_or_eol Lexer.lexeme lexbuf with
174 begin match matching_instructions x with
176 error "Unknown command."
178 i.instr_action ppf lexbuf;
179 resume_user_input ();
182 error "Ambiguous command."
185 resume_user_input ();
188 | Parsing.Parse_error ->
189 error "Syntax error."
191 let line_loop ppf line_buffer =
192 resume_user_input ();
193 let previous_line = ref "" in
197 History.add_current_time ();
198 let new_line = string_trim (line line_buffer) in
200 if new_line <> "" then
206 if interprete_line ppf line then
207 previous_line := line
213 error ("System error : " ^ s)
215 (** Instructions. **)
216 let instr_cd ppf lexbuf =
217 let dir = argument_eol argument lexbuf in
218 if ask_kill_program () then
220 Sys.chdir (expand_path dir)
225 let instr_shell ppf lexbuf =
226 let cmdarg = argument_list_eol argument lexbuf in
227 let cmd = String.concat " " cmdarg in
228 (* perhaps we should use $SHELL -c ? *)
229 let err = Sys.command cmd in
231 eprintf "Shell command %S failed with exit code %d\n%!" cmd err
233 let instr_pwd ppf lexbuf =
235 fprintf ppf "%s@." (Sys.getcwd ())
237 let instr_dir ppf lexbuf =
238 let new_directory = argument_list_eol argument lexbuf in
239 if new_directory = [] then begin
240 if yes_or_no "Reinitialize directory list" then begin
241 Config.load_path := !default_load_path;
242 Envaux.reset_cache ();
243 Hashtbl.clear Debugger_config.load_path_for;
248 let new_directory' = List.rev new_directory in
249 match new_directory' with
250 | mdl :: for_keyw :: tl when (String.lowercase for_keyw) = "for" && (List.length tl) > 0 ->
251 List.iter (function x -> add_path_for mdl (expand_path x)) tl
253 List.iter (function x -> add_path (expand_path x)) new_directory'
255 let print_dirs ppf l = List.iter (function x -> fprintf ppf "@ %s" x) l in
256 fprintf ppf "@[<2>Directories :%a@]@." print_dirs !Config.load_path;
259 fprintf ppf "@[<2>Source directories for %s :%a@]@." mdl print_dirs dirs)
260 Debugger_config.load_path_for
262 let instr_kill ppf lexbuf =
264 if not !loaded then error "The program is not being run.";
265 if (yes_or_no "Kill the program being debugged") then begin
270 let instr_run ppf lexbuf =
273 reset_named_values ();
275 show_current_event ppf;;
277 let instr_reverse ppf lexbuf =
279 check_not_windows "reverse";
281 reset_named_values();
283 show_current_event ppf
285 let instr_step ppf lexbuf =
287 match opt_signed_int64_eol Lexer.lexeme lexbuf with
292 reset_named_values();
294 show_current_event ppf
296 let instr_back ppf lexbuf =
298 match opt_signed_int64_eol Lexer.lexeme lexbuf with
302 check_not_windows "backstep";
304 reset_named_values();
305 step (_0 -- step_count);
306 show_current_event ppf
308 let instr_finish ppf lexbuf =
311 reset_named_values();
313 show_current_event ppf
315 let instr_next ppf lexbuf =
317 match opt_integer_eol Lexer.lexeme lexbuf with
322 reset_named_values();
324 show_current_event ppf
326 let instr_start ppf lexbuf =
328 check_not_windows "start";
330 reset_named_values();
332 show_current_event ppf
334 let instr_previous ppf lexbuf =
336 match opt_integer_eol Lexer.lexeme lexbuf with
340 check_not_windows "previous";
342 reset_named_values();
344 show_current_event ppf
346 let instr_goto ppf lexbuf =
347 let time = int64_eol Lexer.lexeme lexbuf in
349 reset_named_values();
351 show_current_event ppf
356 let print_variable_list ppf =
357 let pr_vars ppf = List.iter (fun v -> fprintf ppf "%s@ " v.var_name) in
358 fprintf ppf "List of variables :%a@." pr_vars !variable_list
360 let print_info_list ppf =
361 let pr_infos ppf = List.iter (fun i -> fprintf ppf "%s@ " i.info_name) in
362 fprintf ppf "List of info commands :%a@." pr_infos !info_list
364 let instr_complete ppf lexbuf =
365 let ppf = Format.err_formatter in
366 let rec print_list l =
369 List.iter (function i -> fprintf ppf "%s@." i) l
371 remove_file !user_channel
372 and match_list lexbuf =
373 match identifier_or_eol Lexer.lexeme lexbuf with
375 List.map (fun i -> i.instr_name) !instruction_list
377 match matching_instructions x with
378 | [ {instr_name = ("set" | "show" as i_full)} ] ->
379 if x = i_full then begin
380 match identifier_or_eol Lexer.lexeme lexbuf with
382 begin match matching_variables ident with
383 | [v] -> if v.var_name = ident then [] else [v.var_name]
384 | l -> List.map (fun v -> v.var_name) l
387 List.map (fun v -> v.var_name) !variable_list
390 | [ {instr_name = "info"} ] ->
391 if x = "info" then begin
392 match identifier_or_eol Lexer.lexeme lexbuf with
394 begin match matching_infos ident with
395 | [i] -> if i.info_name = ident then [] else [i.info_name]
396 | l -> List.map (fun i -> i.info_name) l
399 List.map (fun i -> i.info_name) !info_list
402 | [ {instr_name = "help"} ] ->
403 if x = "help" then match_list lexbuf else ["help"]
405 if x = i.instr_name then [] else [i.instr_name]
407 List.map (fun i -> i.instr_name) l
409 print_list(match_list lexbuf)
411 let instr_help ppf lexbuf =
413 List.iter (fun i -> fprintf ppf "%s@ " i.instr_name) in
414 match identifier_or_eol Lexer.lexeme lexbuf with
416 let print_help nm hlp =
418 fprintf ppf "%s : %s@." nm hlp in
419 begin match matching_instructions x with
422 fprintf ppf "No matching command.@."
423 | [ {instr_name = "set"} ] ->
426 print_help ("set " ^ v.var_name) ("set " ^ v.var_help))
428 print_help "set" "set debugger variable.";
429 print_variable_list ppf)
432 | [ {instr_name = "show"} ] ->
435 print_help ("show " ^ v.var_name) ("show " ^ v.var_help))
437 print_help "show" "display debugger variable.";
438 print_variable_list ppf)
441 | [ {instr_name = "info"} ] ->
443 (fun i _ _ -> print_help ("info " ^ i.info_name) i.info_help)
446 "display infos about the program being debugged.";
451 print_help i.instr_name i.instr_help
454 fprintf ppf "Ambiguous command \"%s\" : %a@." x pr_instrs l
457 fprintf ppf "List of commands :%a@." pr_instrs !instruction_list
459 (* Printing values *)
461 let print_expr depth ev env ppf expr =
463 let (v, ty) = Eval.expression ev env expr in
464 print_named_value depth expr env v ppf ty
467 Eval.report_error ppf msg;
470 let print_command depth ppf lexbuf =
471 let exprs = expression_list_eol Lexer.lexeme lexbuf in
475 Envaux.env_of_event !selected_event
477 | Envaux.Error msg ->
478 Envaux.report_error ppf msg;
481 List.iter (print_expr depth !selected_event env ppf) exprs
483 let instr_print ppf lexbuf = print_command !max_printer_depth ppf lexbuf
485 let instr_display ppf lexbuf = print_command 1 ppf lexbuf
487 (* Loading of command files *)
489 let extract_filename arg =
490 (* Allow enclosing filename in quotes *)
491 let l = String.length arg in
492 let pos1 = if l > 0 && arg.[0] = '"' then 1 else 0 in
493 let pos2 = if l > 0 && arg.[l-1] = '"' then l-1 else l in
494 String.sub arg pos1 (pos2 - pos1)
496 let instr_source ppf lexbuf =
497 let file = extract_filename(argument_eol argument lexbuf)
498 and old_state = !interactif
499 and old_channel = !user_channel in
503 (openfile (find_in_path !Config.load_path (expand_path file))
506 | Not_found -> error "Source file not found."
507 | (Unix_error _) as x -> Unix_tools.report_error x; raise Toplevel
511 user_channel := io_chan;
512 line_loop ppf (Lexing.from_function read_user_input);
514 interactif := old_state;
515 user_channel := old_channel
520 interactif := old_state;
521 user_channel := old_channel;
526 (fun {var_action = (funct, _)} ppf lexbuf -> funct lexbuf)
527 (function ppf -> error "Argument required.")
531 (fun {var_action = (_, funct)} ppf lexbuf -> eol lexbuf; funct ppf)
534 (function {var_name = nm; var_action = (_, funct)} ->
535 fprintf ppf "%s : " nm;
541 (fun i ppf lexbuf -> i.info_action lexbuf)
543 error "\"info\" must be followed by the name of an info command.")
545 let instr_break ppf lexbuf =
546 let argument = break_argument_eol Lexer.lexeme lexbuf in
549 | BA_none -> (* break *)
550 (match !selected_event with
554 error "Can't add breakpoint at this point.")
555 | BA_pc pc -> (* break PC *)
556 add_breakpoint_at_pc pc
557 | BA_function expr -> (* break FUNCTION *)
560 Envaux.env_of_event !selected_event
562 | Envaux.Error msg ->
563 Envaux.report_error ppf msg;
567 let (v, ty) = Eval.expression !selected_event env expr in
568 match (Ctype.repr ty).desc with
570 add_breakpoint_after_pc (Remote_value.closure_code v)
572 eprintf "Not a function.@.";
576 Eval.report_error ppf msg;
579 | BA_pos1 (mdle, line, column) -> (* break @ [MODULE] LINE [COL] *)
580 let module_name = convert_module (module_of_longident mdle) in
584 try get_buffer Lexing.dummy_pos module_name with
586 eprintf "No source file for %s.@." module_name;
591 event_at_pos module_name (fst (pos_of_line buffer line))
593 event_near_pos module_name (point_of_coord buffer line col)
595 | Not_found -> (* event_at_pos / event_near pos *)
596 eprintf "Can't find any event there.@.";
598 | Out_of_range -> (* pos_of_line / point_of_coord *)
599 eprintf "Position out of range.@.";
601 | BA_pos2 (mdle, position) -> (* break @ [MODULE] # POSITION *)
603 new_breakpoint (event_near_pos (convert_module (module_of_longident mdle)) position)
606 eprintf "Can't find any event there.@."
608 let instr_delete ppf lexbuf =
609 match integer_list_eol Lexer.lexeme lexbuf with
611 if breakpoints_count () <> 0 && yes_or_no "Delete all breakpoints"
612 then remove_all_breakpoints ()
615 (function x -> try remove_breakpoint x with | Not_found -> ())
618 let instr_frame ppf lexbuf =
620 match opt_integer_eol Lexer.lexeme lexbuf with
621 | None -> !current_frame
626 select_frame frame_number;
627 show_current_frame ppf true
630 error ("No frame number " ^ string_of_int frame_number ^ ".")
632 let instr_backtrace ppf lexbuf =
634 match opt_signed_integer_eol Lexer.lexeme lexbuf with
638 match current_report() with
639 | None | Some {rep_type = Exited | Uncaught_exc} -> ()
641 let frame_counter = ref 0 in
642 let print_frame first_frame last_frame = function
645 "(Encountered a function with no debugging information)@.";
648 if !frame_counter >= first_frame then
649 show_one_frame !frame_counter ppf event;
651 if !frame_counter >= last_frame then begin
652 fprintf ppf "(More frames follow)@."
654 !frame_counter < last_frame in
655 fprintf ppf "Backtrace:@.";
657 do_backtrace (print_frame 0 max_int)
658 else if number > 0 then
659 do_backtrace (print_frame 0 number)
661 let num_frames = stack_depth() in
662 if num_frames < 0 then
664 "(Encountered a function with no debugging information)@."
666 do_backtrace (print_frame (num_frames + number) max_int)
669 let instr_up ppf lexbuf =
671 match opt_signed_integer_eol Lexer.lexeme lexbuf with
677 select_frame (!current_frame + offset);
678 show_current_frame ppf true
680 | Not_found -> error "No such frame."
682 let instr_down ppf lexbuf =
684 match opt_signed_integer_eol Lexer.lexeme lexbuf with
690 select_frame (!current_frame - offset);
691 show_current_frame ppf true
693 | Not_found -> error "No such frame."
695 let instr_last ppf lexbuf =
697 match opt_signed_int64_eol Lexer.lexeme lexbuf with
701 check_not_windows "last";
702 reset_named_values();
703 go_to (History.previous_time count);
704 show_current_event ppf
706 let instr_list ppf lexbuf =
707 let (mo, beg, e) = list_arguments_eol Lexer.lexeme lexbuf in
708 let (curr_mod, line, column) =
715 let mdle = convert_module (module_of_longident mo) in
716 let pos = Lexing.dummy_pos in
718 try get_buffer pos mdle with
719 | Not_found -> error ("No source file for " ^ mdle ^ ".") in
722 (point_of_coord buffer line 1) + column
727 | None when (mo <> None) || (line = -1) ->
739 | None -> beginning + 20
742 if mdle = curr_mod then
743 show_listing pos mdle beginning en point
744 (current_event_is_before ())
746 show_listing pos mdle beginning en (-1) true
749 let raw_variable kill name =
751 let argument = argument_eol argument lexbuf in
752 if (not kill) || ask_kill_program () then name := argument),
753 function ppf -> fprintf ppf "%s@." !name
755 let raw_line_variable kill name =
757 let argument = argument_eol line_argument lexbuf in
758 if (not kill) || ask_kill_program () then name := argument),
759 function ppf -> fprintf ppf "%s@." !name
761 let integer_variable kill min msg name =
763 let argument = integer_eol Lexer.lexeme lexbuf in
764 if argument < min then print_endline msg
765 else if (not kill) || ask_kill_program () then name := argument),
766 function ppf -> fprintf ppf "%i@." !name
768 let int64_variable kill min msg name =
770 let argument = int64_eol Lexer.lexeme lexbuf in
771 if argument < min then print_endline msg
772 else if (not kill) || ask_kill_program () then name := argument),
773 function ppf -> fprintf ppf "%Li@." !name
775 let boolean_variable kill name =
778 match identifier_eol Lexer.lexeme lexbuf with
780 | "of" | "off" -> false
781 | _ -> error "Syntax error."
783 if (not kill) || ask_kill_program () then name := argument),
784 function ppf -> fprintf ppf "%s@." (if !name then "on" else "off")
786 let path_variable kill name =
788 let argument = argument_eol argument lexbuf in
789 if (not kill) || ask_kill_program () then
790 name := make_absolute (expand_path argument)),
791 function ppf -> fprintf ppf "%s@." !name
793 let loading_mode_variable ppf =
796 (matching_elements (ref loading_modes) fst)
797 (fun (_, mode) ppf lexbuf ->
798 eol lexbuf; set_launching_function mode)
799 (function ppf -> error "Syntax error.")
802 let rec find = function
804 | (name, funct) :: l ->
805 if funct == !launching_func then fprintf ppf "%s" name else find l
812 let pr_modules ppf mods =
813 let pr_mods ppf = List.iter (function x -> fprintf ppf "%s@ " x) in
814 fprintf ppf "Used modules :@.%a@?" pr_mods mods
816 let info_modules ppf lexbuf =
819 pr_modules ppf !modules
821 print_endline "Opened modules :";
822 if !opened_modules_names = [] then
823 print_endline "(no module opened)."
825 (List.iter (function x -> print_string x; print_space) !opened_modules_names;
829 let info_checkpoints ppf lexbuf =
831 if !checkpoints = [] then fprintf ppf "No checkpoint.@."
833 (if !debug_breakpoints then
834 (prerr_endline " Time Pid Version";
837 {c_time = time; c_pid = pid; c_breakpoint_version = version} ->
838 Printf.printf "%19Ld %5d %d\n" time pid version)
841 (print_endline " Time Pid";
844 {c_time = time; c_pid = pid} ->
845 Printf.printf "%19Ld %5d\n" time pid)
848 let info_one_breakpoint ppf (num, ev) =
849 fprintf ppf "%3d %10d %s@." num ev.ev_pos (Pos.get_desc ev);
852 let info_breakpoints ppf lexbuf =
854 if !breakpoints = [] then fprintf ppf "No breakpoints.@."
856 fprintf ppf "Num Address Where@.";
857 List.iter (info_one_breakpoint ppf) (List.rev !breakpoints);
861 let info_events ppf lexbuf =
863 let mdle = convert_module (module_of_longident (opt_longident_eol Lexer.lexeme lexbuf)) in
864 print_endline ("Module : " ^ mdle);
865 print_endline " Address Characters Kind Repr.";
868 let start_char, end_char =
870 let buffer = get_buffer (Events.get_pos ev) ev.ev_module in
871 (snd (start_and_cnum buffer ev.ev_loc.Location.loc_start)),
872 (snd (start_and_cnum buffer ev.ev_loc.Location.loc_end))
874 ev.ev_loc.Location.loc_start.Lexing.pos_cnum,
875 ev.ev_loc.Location.loc_end.Lexing.pos_cnum in
877 "%10d %6d-%-6d %10s %10s\n"
881 ((match ev.ev_kind with
882 Event_before -> "before"
883 | Event_after _ -> "after"
884 | Event_pseudo -> "pseudo")
886 (match ev.ev_info with
887 Event_function -> "/fun"
888 | Event_return _ -> "/ret"
889 | Event_other -> ""))
890 (match ev.ev_repr with
892 | Event_parent _ -> "(repr)"
893 | Event_child repr -> string_of_int !repr))
894 (events_in_module mdle)
896 (** User-defined printers **)
898 let instr_load_printer ppf lexbuf =
899 let filename = extract_filename(argument_eol argument lexbuf) in
901 Loadprinter.loadfile ppf filename
902 with Loadprinter.Error e ->
903 Loadprinter.report_error ppf e; raise Toplevel
905 let instr_install_printer ppf lexbuf =
906 let lid = longident_eol Lexer.lexeme lexbuf in
908 Loadprinter.install_printer ppf lid
909 with Loadprinter.Error e ->
910 Loadprinter.report_error ppf e; raise Toplevel
912 let instr_remove_printer ppf lexbuf =
913 let lid = longident_eol Lexer.lexeme lexbuf in
915 Loadprinter.remove_printer lid
916 with Loadprinter.Error e ->
917 Loadprinter.report_error ppf e; raise Toplevel
919 (** Initialization. **)
921 instruction_list := [
922 { instr_name = "cd"; instr_prio = false;
923 instr_action = instr_cd; instr_repeat = true; instr_help =
924 "set working directory to DIR for debugger and program being debugged." };
925 { instr_name = "complete"; instr_prio = false;
926 instr_action = instr_complete; instr_repeat = false; instr_help =
927 "complete word at cursor according to context. Useful for Emacs." };
928 { instr_name = "pwd"; instr_prio = false;
929 instr_action = instr_pwd; instr_repeat = true; instr_help =
930 "print working directory." };
931 { instr_name = "directory"; instr_prio = false;
932 instr_action = instr_dir; instr_repeat = false; instr_help =
933 "add directory DIR to beginning of search path for source and\n\
935 Forget cached info on source file locations and line positions.\n\
936 With no argument, reset the search path." };
937 { instr_name = "kill"; instr_prio = false;
938 instr_action = instr_kill; instr_repeat = true; instr_help =
939 "kill the program being debugged." };
940 { instr_name = "help"; instr_prio = false;
941 instr_action = instr_help; instr_repeat = true; instr_help =
942 "print list of commands." };
943 { instr_name = "quit"; instr_prio = false;
944 instr_action = instr_quit; instr_repeat = false; instr_help =
945 "exit the debugger." };
946 { instr_name = "shell"; instr_prio = false;
947 instr_action = instr_shell; instr_repeat = true; instr_help =
948 "Execute a given COMMAND thru the system shell." };
950 { instr_name = "run"; instr_prio = true;
951 instr_action = instr_run; instr_repeat = true; instr_help =
952 "run the program from current position." };
953 { instr_name = "reverse"; instr_prio = false;
954 instr_action = instr_reverse; instr_repeat = true; instr_help =
955 "run the program backward from current position." };
956 { instr_name = "step"; instr_prio = true;
957 instr_action = instr_step; instr_repeat = true; instr_help =
958 "step program until it reaches the next event.\n\
959 Argument N means do this N times (or till program stops for another reason)." };
960 { instr_name = "backstep"; instr_prio = true;
961 instr_action = instr_back; instr_repeat = true; instr_help =
962 "step program backward until it reaches the previous event.\n\
963 Argument N means do this N times (or till program stops for another reason)." };
964 { instr_name = "goto"; instr_prio = false;
965 instr_action = instr_goto; instr_repeat = true; instr_help =
966 "go to the given time." };
967 { instr_name = "finish"; instr_prio = true;
968 instr_action = instr_finish; instr_repeat = true; instr_help =
969 "execute until topmost stack frame returns." };
970 { instr_name = "next"; instr_prio = true;
971 instr_action = instr_next; instr_repeat = true; instr_help =
972 "step program until it reaches the next event.\n\
973 Skip over function calls.\n\
974 Argument N means do this N times (or till program stops for another reason)." };
975 { instr_name = "start"; instr_prio = false;
976 instr_action = instr_start; instr_repeat = true; instr_help =
977 "execute backward until the current function is exited." };
978 { instr_name = "previous"; instr_prio = false;
979 instr_action = instr_previous; instr_repeat = true; instr_help =
980 "step program until it reaches the previous event.\n\
981 Skip over function calls.\n\
982 Argument N means do this N times (or till program stops for another reason)." };
983 { instr_name = "print"; instr_prio = true;
984 instr_action = instr_print; instr_repeat = true; instr_help =
985 "print value of expressions (deep printing)." };
986 { instr_name = "display"; instr_prio = true;
987 instr_action = instr_display; instr_repeat = true; instr_help =
988 "print value of expressions (shallow printing)." };
989 { instr_name = "source"; instr_prio = false;
990 instr_action = instr_source; instr_repeat = true; instr_help =
991 "read command from file FILE." };
993 { instr_name = "break"; instr_prio = false;
994 instr_action = instr_break; instr_repeat = false; instr_help =
995 "Set breakpoint at specified line or function.\n\
996 Syntax: break function-name\n\
997 break @ [module] linenum\n\
998 break @ [module] # characternum" };
999 { instr_name = "delete"; instr_prio = false;
1000 instr_action = instr_delete; instr_repeat = false; instr_help =
1001 "delete some breakpoints.\n\
1002 Arguments are breakpoint numbers with spaces in between.\n\
1003 To delete all breakpoints, give no argument." };
1004 { instr_name = "set"; instr_prio = false;
1005 instr_action = instr_set; instr_repeat = false; instr_help =
1007 { instr_name = "show"; instr_prio = false;
1008 instr_action = instr_show; instr_repeat = true; instr_help =
1010 { instr_name = "info"; instr_prio = false;
1011 instr_action = instr_info; instr_repeat = true; instr_help =
1014 { instr_name = "frame"; instr_prio = false;
1015 instr_action = instr_frame; instr_repeat = true; instr_help =
1016 "select and print a stack frame.\n\
1017 With no argument, print the selected stack frame.\n\
1018 An argument specifies the frame to select." };
1019 { instr_name = "backtrace"; instr_prio = false;
1020 instr_action = instr_backtrace; instr_repeat = true; instr_help =
1021 "print backtrace of all stack frames, or innermost COUNT frames.\n\
1022 With a negative argument, print outermost -COUNT frames." };
1023 { instr_name = "bt"; instr_prio = false;
1024 instr_action = instr_backtrace; instr_repeat = true; instr_help =
1025 "print backtrace of all stack frames, or innermost COUNT frames.\n\
1026 With a negative argument, print outermost -COUNT frames." };
1027 { instr_name = "up"; instr_prio = false;
1028 instr_action = instr_up; instr_repeat = true; instr_help =
1029 "select and print stack frame that called this one.\n\
1030 An argument says how many frames up to go." };
1031 { instr_name = "down"; instr_prio = false;
1032 instr_action = instr_down; instr_repeat = true; instr_help =
1033 "select and print stack frame called by this one.\n\
1034 An argument says how many frames down to go." };
1035 { instr_name = "last"; instr_prio = true;
1036 instr_action = instr_last; instr_repeat = true; instr_help =
1037 "go back to previous time." };
1038 { instr_name = "list"; instr_prio = false;
1039 instr_action = instr_list; instr_repeat = true; instr_help =
1040 "list the source code." };
1041 (* User-defined printers *)
1042 { instr_name = "load_printer"; instr_prio = false;
1043 instr_action = instr_load_printer; instr_repeat = false; instr_help =
1044 "load in the debugger a .cmo or .cma file containing printing functions." };
1045 { instr_name = "install_printer"; instr_prio = false;
1046 instr_action = instr_install_printer; instr_repeat = false; instr_help =
1047 "use the given function for printing values of its input type.\n\
1048 The code for the function must have previously been loaded in the debugger\n\
1049 using \"load_printer\"." };
1050 { instr_name = "remove_printer"; instr_prio = false;
1051 instr_action = instr_remove_printer; instr_repeat = false; instr_help =
1052 "stop using the given function for printing values of its input type." }
1055 (* variable name, (writing, reading), help reading, help writing *)
1056 { var_name = "arguments";
1057 var_action = raw_line_variable true arguments;
1059 "arguments to give program being debugged when it is started." };
1060 { var_name = "program";
1061 var_action = path_variable true program_name;
1063 "name of program to be debugged." };
1064 { var_name = "loadingmode";
1065 var_action = loading_mode_variable ppf;
1067 "mode of loading.\n\
1069 direct : the program is directly called by the debugger.\n\
1070 runtime : the debugger execute `ocamlrun programname arguments'.\n\
1071 manual : the program is not launched by the debugger,\n\
1072 but manually by the user." };
1073 { var_name = "processcount";
1074 var_action = integer_variable false 1 "Must be >= 1."
1075 checkpoint_max_count;
1077 "maximum number of process to keep." };
1078 { var_name = "checkpoints";
1079 var_action = boolean_variable false make_checkpoints;
1081 "whether to make checkpoints or not." };
1082 { var_name = "bigstep";
1083 var_action = int64_variable false _1 "Must be >= 1."
1084 checkpoint_big_step;
1086 "step between checkpoints during long displacements." };
1087 { var_name = "smallstep";
1088 var_action = int64_variable false _1 "Must be >= 1."
1089 checkpoint_small_step;
1091 "step between checkpoints during small displacements." };
1092 { var_name = "socket";
1093 var_action = raw_variable true socket_name;
1095 "name of the socket used by communications debugger-runtime." };
1096 { var_name = "history";
1097 var_action = integer_variable false 0 "" history_size;
1100 { var_name = "print_depth";
1101 var_action = integer_variable false 1 "Must be at least 1"
1104 "maximal depth for printing of values." };
1105 { var_name = "print_length";
1106 var_action = integer_variable false 1 "Must be at least 1"
1109 "maximal number of value nodes printed." }];
1112 (* info name, function, help *)
1113 [{ info_name = "modules";
1114 info_action = info_modules ppf;
1115 info_help = "list opened modules." };
1116 { info_name = "checkpoints";
1117 info_action = info_checkpoints ppf;
1118 info_help = "list checkpoints." };
1119 { info_name = "breakpoints";
1120 info_action = info_breakpoints ppf;
1121 info_help = "list breakpoints." };
1122 { info_name = "events";
1123 info_action = info_events ppf;
1124 info_help = "list events in MODULE (default is current module)." }]
1126 let _ = init std_formatter