diff options
Diffstat (limited to 'lib/debugger/src/i.erl')
-rw-r--r-- | lib/debugger/src/i.erl | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/lib/debugger/src/i.erl b/lib/debugger/src/i.erl new file mode 100644 index 0000000000..7c2fb22946 --- /dev/null +++ b/lib/debugger/src/i.erl @@ -0,0 +1,376 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% Purpose : User interface to the Erlang debugger/interpreter. + +-module(i). + +-export([help/0,ia/1,ia/2,ia/3,ia/4,iaa/1,iaa/2, + ib/2,ib/3,ib/4,ibd/2,ibe/2,iba/3,ibc/3,ic/0,ii/1,ii/2, + il/0,im/0,ini/1,ini/2,inq/1,ip/0,ipb/0,ipb/1,iq/1, + ir/0,ir/1,ir/2,ir/3,iv/0,ist/1]). + +-import(io, [format/1,format/2]). +-import(lists, [sort/1,foreach/2]). + +iv() -> + Vsn = string:substr(filename:basename(code:lib_dir(debugger)), 10), + list_to_atom(Vsn). + + +%% ------------------------------------------- +%% Start a new graphical monitor. +%% A monitor displays status for all processes +%% running interpreted modules. +%% ------------------------------------------- + +im() -> + case debugger:start() of + {ok, Pid} -> + Pid; + {error, {already_started, Pid}} -> + Pid + end. + +%% ------------------------------------------- +%% Add Module(s) as being interpreted. +%% The actual paths will be searched for the +%% corresponding source file(s) (Module.erl). +%% Module(s) can be given with absolute path. +%% ------------------------------------------- + +ii(Module) -> + int:i(Module). + +ii(Module,_Options) -> + int:i(Module). + +%% ------------------------------------------- +%% Don't interpret module(s). The module will be +%% removed from the set of modules interpreted. +%% ------------------------------------------- + +iq(Module) -> + int:n(Module). + +%% ------------------------------------------- +%% The corresponding functions for distributed +%% erlang. The loading ... will be performed +%% at all nodes using the broadcast facility. +%% ------------------------------------------- + +ini(Module) -> + int:ni(Module). + +ini(Module,_Options) -> + int:ni(Module). + +inq(Module) -> + int:nn(Module). + +%% ------------------------------------------- +%% Add a new break point at Line in Module. +%% ------------------------------------------- + +ib(Module,Line) -> + int:break(Module,Line). + +%% ------------------------------------------- +%% Break at entrance of specified function. +%% Breaks is set at the first expression for +%% all function clauses. +%% ------------------------------------------- + +ib(Module,Function,Arity) -> + int:break_in(Module,Function,Arity). + +%% ------------------------------------------- +%% Break at entrance of specified function. +%% Breaks is set at the first expression for +%% all function clauses. +%% Associate the condition to the break. +%% ------------------------------------------- + +ib(Module,Function,Arity,Cond) -> + Breaks1 = int:all_breaks(Module), + int:break_in(Module,Function,Arity), + Breaks2 = int:all_breaks(Module), + lists:foreach(fun({Mod,Line}) -> int:test_at_break(Mod,Line,Cond) end, + Breaks2--Breaks1). + +%% ------------------------------------------- +%% Make an existing break point inactive. +%% ------------------------------------------- + +ibd(Mod,Line) -> + int:disable_break(Mod,Line). + +%% ------------------------------------------- +%% Make an existing break point active. +%% ------------------------------------------- + +ibe(Mod,Line) -> + int:enable_break(Mod,Line). + +%% ------------------------------------------- +%% Set which status a break point shall have +%% after it has been triggered the next time. +%% Action is: enable, disable or delete. +%% ------------------------------------------- + +iba(Mod,Line,Action) -> + int:action_at_break(Mod,Line,Action). + +%% ------------------------------------------- +%% Add a conditional function to a break point. +%% The given function shall have arity 1 and +%% return either true or false. +%% The argument of the given function is the +%% current variable bindings of the process at +%% the place of the break point, the bindings +%% can be inspected using int:get_binding/2. + +%% Fnk == {Module,Function} +%% Fnk == {Module,Function,ExtraArgs} +%% ------------------------------------------- + +ibc(Mod,Line,Fnk) -> + int:test_at_break(Mod,Line,Fnk). + +%% ------------------------------------------- +%% Delete break point. +%% ------------------------------------------- + +ir(Module,Line) -> + int:delete_break(Module,Line). + +%% ------------------------------------------- +%% Delete break at entrance of specified function. +%% ------------------------------------------- + +ir(Module,Function,Arity) -> + int:del_break_in(Module,Function,Arity). + +%% ------------------------------------------- +%% Delete all break points in module. +%% ------------------------------------------- + +ir(Module) -> + int:no_break(Module). + +%% ------------------------------------------- +%% Delete all break points (for all modules). +%% ------------------------------------------- + +ir() -> + int:no_break(). + +%% ------------------------------------------- +%% Print all interpreted modules. +%% ------------------------------------------- + +il() -> + Mods = sort(int:interpreted()), + ilformat("Module","File"), + foreach(fun(Mod) -> ilformat(atom_to_list(Mod), get_file(Mod)) end, Mods). + +get_file(Mod) -> + case int:file(Mod) of + {error,not_loaded} -> % Marked interpreted but not loaded + "not loaded"; + File -> + File + end. + +ilformat(A1, A2) -> + format("~-20s ~s\n", [A1,A2]). + +%% ------------------------------------------- +%% Print all break points in modules. +%% ------------------------------------------- + +ipb() -> + Bps = lists:keysort(1,int:all_breaks()), + bhformat("Module","Line","Status","Action","Condition"), + pb_print(Bps). + +ipb(Module) when is_atom(Module) -> + ipb1(Module); +ipb(Module) when is_list(Module) -> + ipb1(list_to_atom(Module)). + +ipb1(Module) -> + Bps = lists:keysort(1,int:all_breaks(Module)), + bhformat("Module","Line","Status","Action","Condition"), + pb_print(Bps). + +pb_print([{{Mod,Line},[Status,Action,_,null|_]}|Bps]) -> + bformat(Mod,Line,Status,Action,""), + pb_print(Bps); +pb_print([{{Mod,Line},[Status,Action,_,Cond|_]}|Bps]) -> + bformat(Mod,Line,Status,Action, + io_lib:format("~w",[Cond])), + pb_print(Bps); +pb_print(_) -> + ok. + +bhformat(A1, A2, A3, A4, A5) -> + format("~-15s ~-9s ~-12s ~-12s ~-21s~n", [A1,A2,A3,A4,A5]). + +bformat(A1, A2, A3, A4, A5) -> + format("~-15w ~-9w ~-12w ~-12w ~-21s~n", [A1,A2,A3,A4,A5]). + +%% ------------------------------------------- +%% Set the stack trace flag. +%% Flag can be all (true), no_tail or false. +%% ------------------------------------------- + +ist(Flag) -> + int:stack_trace(Flag), + true. + +%% ------------------------------------------- +%% Set the automatic attachment flag. +%% Flags can be init, break and exit. +%% iaa(Flag) or ia([Flag,Flag,...]) +%% ------------------------------------------- + +iaa(Flag) -> + iaa(Flag,{dbg_ui_trace,start,[]}). + +%% ------------------------------------------- +%% Set the automatic attachment flag. +%% Flags can be init, break and exit. +%% Use given function to start up an attachment +%% window. +%% ia(Flag,Fnk) or ia([Flag,Flag,...],Fnk) +%% where Fnk == {M,F} +%% The given Fnk must have arity 3 or 4. +%% ------------------------------------------- + +iaa(Flag,Fnk) -> + int:auto_attach(Flag,Fnk), + true. + +%% ------------------------------------------- +%% Attach to process. +%% ------------------------------------------- + +ia(Pid) -> + ia(Pid,{dbg_ui_trace,start}). + +%% ------------------------------------------- +%% Attach to process. +%% X,Y,Z is combind to a process identity. +%% ------------------------------------------- + +ia(X,Y,Z) -> + ia(c:pid(X,Y,Z)). + +%% ------------------------------------------- +%% Attach to process. +%% Use Fnk == {M,F} as the attaching interface. +%% ------------------------------------------- + +ia(Pid,Fnk) -> + case lists:keysearch(Pid, 1, int:snapshot()) of + {value, _PidTuple} -> + int:attach(Pid,Fnk); + false -> no_proc + end. + +ia(X,Y,Z,Fnk) -> + ia(c:pid(X,Y,Z),Fnk). + +%% ------------------------------------------- +%% Print status for all interpreted processes. +%% ------------------------------------------- + +ip() -> + Stats = int:snapshot(), + hformat("Pid","Initial Call","Status","Info"), + ip(Stats). + +ip([{Pid,{M,F,A},Status,{}}|Stats]) -> + hformat(io_lib:format("~w",[Pid]), + io_lib:format("~p:~p/~p",[M,F,length(A)]), + io_lib:format("~w",[Status]), + ""), + ip(Stats); +ip([{Pid,{M,F,A},Status,Info}|Stats]) -> + hformat(io_lib:format("~w",[Pid]), + io_lib:format("~p:~p/~p",[M,F,length(A)]), + io_lib:format("~w",[Status]), + io_lib:format("~w",[Info])), + ip(Stats); +ip([]) -> + ok. + +hformat(A1, A2, A3, A4) -> + format("~-12s ~-21s ~-9s ~-21s~n", [A1,A2,A3,A4]). + + +%% ------------------------------------------- +%% Delete all terminated processes from the +%% interpreter. +%% ------------------------------------------- + +ic() -> + int:clear(). + +%% ------------------------------------------- +%% Help printout +%% ------------------------------------------- + +help() -> + format("iv() -- print the current version of the interpreter~n"), + format("im() -- pop up a monitor window~n"), + format("ii(Mod) -- interpret Mod(s) (or AbsMod(s))~n"), + format("ii(Mod,Op) -- interpret Mod(s) (or AbsMod(s))~n"), + format(" use Op as options (same as for compile)~n"), + format("iq(Mod) -- do not interpret Mod(s)~n"), + format("ini(Mod) -- ii/1 at all Erlang nodes~n"), + format("ini(Mod,Op) -- ii/2 at all Erlang nodes~n"), + format("inq(Mod) -- iq at all Erlang nodes~n"), + format("ib(Mod,Line) -- set a break point at Line in Mod~n"), + format("ib(M,F,Arity)-- set a break point in M:F/Arity~n"), + format("ibd(Mod,Line)-- disable the break point at Line in Mod~n"), + format("ibe(Mod,Line)-- enable the break point at Line in Mod~n"), + format("iba(M,L,Action)-- set a new action at break~n"), + format("ibc(M,L,Action)-- set a new condition for break~n"), + format("ir(Mod,Line) -- remove the break point at Line in Mod~n"), + format("ir(M,F,Arity)-- remove the break point in M:F/Arity~n"), + format("ir(Mod) -- remove all break points in Mod~n"), + format("ir() -- remove all existing break points~n"), + format("il() -- list all interpreted modules~n"), + format("ip() -- print status of all interpreted processes~n"), + format("ic() -- remove all terminated interpreted processes~n"), + format("ipb() -- list all break points~n"), + format("ipb(Mod) -- list all break points in Mod~n"), + format("ia(Pid) -- attach to Pid~n"), + format("ia(X,Y,Z) -- attach to pid(X,Y,Z)~n"), + format("ia(Pid,Fun) -- use own Fun = {M,F} as attach application~n"), + format("ia(X,Y,Z,Fun)-- use own Fun = {M,F} as attach application~n"), + format("iaa([Flag]) -- set automatic attach to process~n"), + format(" Flag is init,break and exit~n"), + format("iaa([Fl],Fun)-- use own Fun = {M,F} as attach application~n"), + format("ist(Flag) -- set stack trace flag~n"), + format(" Flag is all (true),no_tail or false~n"), + ok. + + |