1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20%% Purpose : User interface to the Erlang debugger/interpreter.
21
22-module(i).
23
24-export([help/0,ia/1,ia/2,ia/3,ia/4,iaa/1,iaa/2,
25	 ib/2,ib/3,ib/4,ibd/2,ibe/2,iba/3,ibc/3,ic/0,ii/1,ii/2,
26	 il/0,im/0,ini/1,ini/2,inq/1,ip/0,ipb/0,ipb/1,iq/1,
27	 ir/0,ir/1,ir/2,ir/3,iv/0,ist/1]).
28
29-import(io, [format/1,format/2]).
30-import(lists, [sort/1,foreach/2]).
31
32iv() ->
33    Vsn = string:slice(filename:basename(code:lib_dir(debugger)), 9),
34    list_to_atom(Vsn).
35
36%% -------------------------------------------
37%% Start a new graphical monitor.
38%% A monitor displays status for all processes
39%% running interpreted modules.
40%% -------------------------------------------
41
42im() ->
43    case debugger:start() of
44	{ok, Pid} ->
45	    Pid;
46	{error, {already_started, Pid}} ->
47	    Pid
48    end.
49
50%% -------------------------------------------
51%% Add Module(s) as being interpreted.
52%% The actual paths will be searched for the
53%% corresponding source file(s) (Module.erl).
54%% Module(s) can be given with absolute path.
55%% -------------------------------------------
56
57ii(Module) ->
58    int:i(Module).
59
60ii(Module,_Options) ->
61    int:i(Module).
62
63%% -------------------------------------------
64%% Don't interpret module(s). The module will be
65%% removed from the set of modules interpreted.
66%% -------------------------------------------
67
68iq(Module) ->
69    int:n(Module).
70
71%% -------------------------------------------
72%% The corresponding functions for distributed
73%% erlang. The loading ... will be performed
74%% at all nodes using the broadcast facility.
75%% -------------------------------------------
76
77ini(Module) ->
78    int:ni(Module).
79
80ini(Module,_Options) ->
81    int:ni(Module).
82
83inq(Module) ->
84    int:nn(Module).
85
86%% -------------------------------------------
87%% Add a new break point at Line in Module.
88%% -------------------------------------------
89
90ib(Module,Line) ->
91    int:break(Module,Line).
92
93%% -------------------------------------------
94%% Break at entrance of specified function.
95%% Breaks is set at the first expression for
96%% all function clauses.
97%% -------------------------------------------
98
99ib(Module,Function,Arity) ->
100    int:break_in(Module,Function,Arity).
101
102%% -------------------------------------------
103%% Break at entrance of specified function.
104%% Breaks is set at the first expression for
105%% all function clauses.
106%% Associate the condition to the break.
107%% -------------------------------------------
108
109ib(Module,Function,Arity,Cond) ->
110    Breaks1 = int:all_breaks(Module),
111    ok = int:break_in(Module,Function,Arity),
112    Breaks2 = int:all_breaks(Module),
113    lists:foreach(fun({Mod,Line}) -> int:test_at_break(Mod,Line,Cond) end,
114		  Breaks2--Breaks1).
115
116%% -------------------------------------------
117%% Make an existing break point inactive.
118%% -------------------------------------------
119
120ibd(Mod,Line) ->
121    int:disable_break(Mod,Line).
122
123%% -------------------------------------------
124%% Make an existing break point active.
125%% -------------------------------------------
126
127ibe(Mod,Line) ->
128    int:enable_break(Mod,Line).
129
130%% -------------------------------------------
131%% Set which status a break point shall have
132%% after it has been triggered the next time.
133%% Action is: enable, disable or delete.
134%% -------------------------------------------
135
136iba(Mod,Line,Action) ->
137    int:action_at_break(Mod,Line,Action).
138
139%% -------------------------------------------
140%% Add a conditional function to a break point.
141%% The given function shall have arity 1 and
142%% return either true or false.
143%% The argument of the given function is the
144%% current variable bindings of the process at
145%% the place of the break point, the bindings
146%% can be inspected using int:get_binding/2.
147
148%% Fnk == {Module,Function}
149%% Fnk == {Module,Function,ExtraArgs}
150%% -------------------------------------------
151
152ibc(Mod,Line,Fnk) ->
153    int:test_at_break(Mod,Line,Fnk).
154
155%% -------------------------------------------
156%% Delete break point.
157%% -------------------------------------------
158
159ir(Module,Line) ->
160    int:delete_break(Module,Line).
161
162%% -------------------------------------------
163%% Delete break at entrance of specified function.
164%% -------------------------------------------
165
166ir(Module,Function,Arity) ->
167    int:del_break_in(Module,Function,Arity).
168
169%% -------------------------------------------
170%% Delete all break points in module.
171%% -------------------------------------------
172
173ir(Module) ->
174    int:no_break(Module).
175
176%% -------------------------------------------
177%% Delete all break points (for all modules).
178%% -------------------------------------------
179
180ir() ->
181    int:no_break().
182
183%% -------------------------------------------
184%% Print all interpreted modules.
185%% -------------------------------------------
186
187il() ->
188    Mods = sort(int:interpreted()),
189    ilformat("Module","File"),
190    foreach(fun(Mod) -> ilformat(atom_to_list(Mod), get_file(Mod)) end, Mods).
191
192get_file(Mod) ->
193    case int:file(Mod) of
194	{error,not_loaded} -> % Marked interpreted but not loaded
195	    "not loaded";
196	File ->
197	    File
198    end.
199
200ilformat(A1, A2) ->
201    format("~-20s     ~ts\n", [A1,A2]).
202
203%% -------------------------------------------
204%% Print all break points in modules.
205%% -------------------------------------------
206
207ipb() ->
208    Bps = lists:keysort(1,int:all_breaks()),
209    bhformat("Module","Line","Status","Action","Condition"),
210    pb_print(Bps).
211
212ipb(Module) when is_atom(Module) ->
213    ipb1(Module);
214ipb(Module) when is_list(Module) ->
215    ipb1(list_to_atom(Module)).
216
217ipb1(Module) ->
218    Bps = lists:keysort(1,int:all_breaks(Module)),
219    bhformat("Module","Line","Status","Action","Condition"),
220    pb_print(Bps).
221
222pb_print([{{Mod,Line},[Status,Action,_,null|_]}|Bps]) ->
223    bformat(Mod,Line,Status,Action,""),
224    pb_print(Bps);
225pb_print([{{Mod,Line},[Status,Action,_,Cond|_]}|Bps]) ->
226    bformat(Mod,Line,Status,Action,
227	    io_lib:format("~w",[Cond])),
228    pb_print(Bps);
229pb_print(_) ->
230    ok.
231
232bhformat(A1, A2, A3, A4, A5) ->
233    format("~-15s ~-9s ~-12s ~-12s ~-21s~n", [A1,A2,A3,A4,A5]).
234
235bformat(A1, A2, A3, A4, A5) ->
236    format("~-15w ~-9w ~-12w ~-12w ~-21s~n", [A1,A2,A3,A4,A5]).
237
238%% -------------------------------------------
239%% Set the stack trace flag.
240%% Flag can be all (true), no_tail or false.
241%% -------------------------------------------
242
243ist(Flag) ->
244    int:stack_trace(Flag),
245    true.
246
247%% -------------------------------------------
248%% Set the automatic attachment flag.
249%% Flags can be init, break and exit.
250%% iaa(Flag) or ia([Flag,Flag,...])
251%% -------------------------------------------
252
253iaa(Flag) ->
254    iaa(Flag,{dbg_wx_trace,start,[]}).
255
256%% -------------------------------------------
257%% Set the automatic attachment flag.
258%% Flags can be init, break and exit.
259%% Use given function to start up an attachment
260%% window.
261%% ia(Flag,Fnk) or ia([Flag,Flag,...],Fnk)
262%%   where Fnk == {M,F}
263%% The given Fnk must have arity 3 or 4.
264%% -------------------------------------------
265
266iaa(Flag,Fnk) ->
267    int:auto_attach(Flag,Fnk),
268    true.
269
270%% -------------------------------------------
271%% Attach to process.
272%% -------------------------------------------
273
274ia(Pid) ->
275    ia(Pid,{dbg_wx_trace,start}).
276
277%% -------------------------------------------
278%% Attach to process.
279%% X,Y,Z is combind to a process identity.
280%% -------------------------------------------
281
282ia(X,Y,Z) ->
283    ia(c:pid(X,Y,Z)).
284
285%% -------------------------------------------
286%% Attach to process.
287%% Use Fnk == {M,F} as the attaching interface.
288%% -------------------------------------------
289
290ia(Pid,Fnk) ->
291    case lists:keymember(Pid, 1, int:snapshot()) of
292	false -> no_proc;
293	true  -> int:attach(Pid,Fnk)
294    end.
295
296ia(X,Y,Z,Fnk) ->
297    ia(c:pid(X,Y,Z),Fnk).
298
299%% -------------------------------------------
300%% Print status for all interpreted processes.
301%% -------------------------------------------
302
303ip() ->
304    Stats = int:snapshot(),
305    hformat("Pid","Initial Call","Status","Info"),
306    ip(Stats).
307
308ip([{Pid,{M,F,A},Status,{}}|Stats]) ->
309    hformat(io_lib:format("~w",[Pid]),
310	    io_lib:format("~w:~tw/~w",[M,F,length(A)]),
311	    io_lib:format("~w",[Status]),
312	    ""),
313    ip(Stats);
314ip([{Pid,{M,F,A},Status,Info}|Stats]) ->
315    hformat(io_lib:format("~w",[Pid]),
316	    io_lib:format("~w:~tw/~w",[M,F,length(A)]),
317	    io_lib:format("~w",[Status]),
318	    io_lib:format("~w",[Info])),
319    ip(Stats);
320ip([]) ->
321    ok.
322
323hformat(A1, A2, A3, A4) ->
324    format("~-12s ~-21ts ~-9s ~-21s~n", [A1,A2,A3,A4]).
325
326
327%% -------------------------------------------
328%% Delete all terminated processes from the
329%% interpreter.
330%% -------------------------------------------
331
332ic() ->
333    int:clear().
334
335%% -------------------------------------------
336%% Help printout
337%% -------------------------------------------
338
339help() ->
340    format("iv()         -- print the current version of the interpreter~n"),
341    format("im()         -- pop up a monitor window~n"),
342    format("ii(Mod)      -- interpret Mod(s) (or AbsMod(s))~n"),
343    format("ii(Mod,Op)   -- interpret Mod(s) (or AbsMod(s))~n"),
344    format("                use Op as options (same as for compile)~n"),
345    format("iq(Mod)      -- do not interpret Mod(s)~n"),
346    format("ini(Mod)     -- ii/1 at all Erlang nodes~n"),
347    format("ini(Mod,Op)  -- ii/2 at all Erlang nodes~n"),
348    format("inq(Mod)     -- iq at all Erlang nodes~n"),
349    format("ib(Mod,Line) -- set a break point at Line in Mod~n"),
350    format("ib(M,F,Arity)-- set a break point in M:F/Arity~n"),
351    format("ibd(Mod,Line)-- disable the break point at Line in Mod~n"),
352    format("ibe(Mod,Line)-- enable the break point at Line in Mod~n"),
353    format("iba(M,L,Action)-- set a new action at break~n"),
354    format("ibc(M,L,Action)-- set a new condition for break~n"),
355    format("ir(Mod,Line) -- remove the break point at Line in Mod~n"),
356    format("ir(M,F,Arity)-- remove the break point in M:F/Arity~n"),
357    format("ir(Mod)      -- remove all break points in Mod~n"),
358    format("ir()         -- remove all existing break points~n"),
359    format("il()         -- list all interpreted modules~n"),
360    format("ip()         -- print status of all interpreted processes~n"),
361    format("ic()         -- remove all terminated interpreted processes~n"),
362    format("ipb()        -- list all break points~n"),
363    format("ipb(Mod)     -- list all break points in Mod~n"),
364    format("ia(Pid)      -- attach to Pid~n"),
365    format("ia(X,Y,Z)    -- attach to pid(X,Y,Z)~n"),
366    format("ia(Pid,Fun)  -- use own Fun = {M,F} as attach application~n"),
367    format("ia(X,Y,Z,Fun)-- use own Fun = {M,F} as attach application~n"),
368    format("iaa([Flag])  -- set automatic attach to process~n"),
369    format("                Flag is init,break and exit~n"),
370    format("iaa([Fl],Fun)-- use own Fun = {M,F} as attach application~n"),
371    format("ist(Flag)    -- set stack trace flag~n"),
372    format("                Flag is all (true),no_tail or false~n"),
373    ok.
374
375
376