diff options
Diffstat (limited to 'lib/tools/src')
-rw-r--r-- | lib/tools/src/Makefile | 8 | ||||
-rw-r--r-- | lib/tools/src/cover.erl | 434 | ||||
-rw-r--r-- | lib/tools/src/eprof.erl | 219 | ||||
-rw-r--r-- | lib/tools/src/fprof.erl | 10 | ||||
-rw-r--r-- | lib/tools/src/lcnt.erl | 13 | ||||
-rw-r--r-- | lib/tools/src/make.erl | 14 | ||||
-rw-r--r-- | lib/tools/src/tags.erl | 12 | ||||
-rw-r--r-- | lib/tools/src/xref.erl | 4 | ||||
-rw-r--r-- | lib/tools/src/xref_base.erl | 60 | ||||
-rw-r--r-- | lib/tools/src/xref_compiler.erl | 26 | ||||
-rw-r--r-- | lib/tools/src/xref_reader.erl | 11 | ||||
-rw-r--r-- | lib/tools/src/xref_utils.erl | 12 |
12 files changed, 512 insertions, 311 deletions
diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile index abe1389771..e606b97a48 100644 --- a/lib/tools/src/Makefile +++ b/lib/tools/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1996-2012. All Rights Reserved. +# Copyright Ericsson AB 1996-2013. 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 @@ -75,7 +75,7 @@ APPUP_TARGET = $(EBIN)/$(APPUP_FILE) # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- -ERL_COMPILE_FLAGS += +ERL_COMPILE_FLAGS += -Werror # ---------------------------------------------------- # Targets @@ -94,10 +94,10 @@ docs: # ---------------------------------------------------- $(APP_TARGET): $(APP_SRC) ../vsn.mk - sed -e 's;%VSN%;$(VSN);' $< > $@ + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk - sed -e 's;%VSN%;$(VSN);' $< > $@ + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ # ---------------------------------------------------- # Release Target diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index e21bd1b88c..13d9aefb0c 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2013. 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 @@ -26,12 +26,17 @@ %% ARCHITECTURE %% The coverage tool consists of one process on each node involved in %% coverage analysis. The process is registered as 'cover_server' -%% (?SERVER). All cover_servers in the distributed system are linked -%% together. The cover_server on the 'main' node is in charge, and it -%% traps exits so it can detect nodedown or process crashes on the -%% remote nodes. This process is implemented by the functions -%% init_main/1 and main_process_loop/1. The cover_server on the remote -%% nodes are implemented by the functions init_remote/2 and +%% (?SERVER). The cover_server on the 'main' node is in charge, and +%% it monitors the cover_servers on all remote nodes. When it gets a +%% 'DOWN' message for another cover_server, it marks the node as +%% 'lost'. If a nodeup is received for a lost node the main node +%% ensures that the cover compiled modules are loaded again. If the +%% remote node was alive during the disconnected periode, cover data +%% for this periode will also be included in the analysis. +%% +%% The cover_server process on the main node is implemented by the +%% functions init_main/1 and main_process_loop/1. The cover_server on +%% the remote nodes are implemented by the functions init_remote/2 and %% remote_process_loop/1. %% %% TABLES @@ -81,15 +86,17 @@ export/1, export/2, import/1, modules/0, imported/0, imported_modules/0, which_nodes/0, is_compiled/1, reset/1, reset/0, + flush/1, stop/0, stop/1]). --export([remote_start/1]). +-export([remote_start/1,get_main_node/0]). %-export([bump/5]). -export([transform/4]). % for test purposes -record(main_state, {compiled=[], % [{Module,File}] imported=[], % [{Module,File,ImportFile}] stopper, % undefined | pid() - nodes=[]}). % [Node] + nodes=[], % [Node] + lost_nodes=[]}). % [Node] -record(remote_state, {compiled=[], % [{Module,File}] main_node}). % atom() @@ -248,16 +255,7 @@ compile_directory(Dir, Options) when is_list(Dir), is_list(Options) -> end. compile_modules(Files,Options) -> - Options2 = lists:filter(fun(Option) -> - case Option of - {i, Dir} when is_list(Dir) -> true; - {d, _Macro} -> true; - {d, _Macro, _Value} -> true; - export_all -> true; - _ -> false - end - end, - Options), + Options2 = filter_options(Options), compile_modules(Files,Options2,[]). compile_modules([File|Files], Options, Result) -> @@ -266,6 +264,17 @@ compile_modules([File|Files], Options, Result) -> compile_modules([],_Opts,Result) -> reverse(Result). +filter_options(Options) -> + lists:filter(fun(Option) -> + case Option of + {i, Dir} when is_list(Dir) -> true; + {d, _Macro} -> true; + {d, _Macro, _Value} -> true; + export_all -> true; + _ -> false + end + end, + Options). %% compile_beam(ModFile) -> Result | {error,Reason} %% ModFile - see compile/1 @@ -497,6 +506,19 @@ stop(Node) when is_atom(Node) -> stop(Nodes) -> call({stop,remove_myself(Nodes,[])}). +%% flush(Nodes) -> ok | {error,not_main_node} +%% Nodes = [Node] | Node +%% Node = atom() +%% Error = {not_cover_compiled,Module} +flush(Node) when is_atom(Node) -> + flush([Node]); +flush(Nodes) -> + call({flush,remove_myself(Nodes,[])}). + +%% Used by test_server only. Not documented. +get_main_node() -> + call(get_main_node). + %% bump(Module, Function, Arity, Clause, Line) %% Module = Function = atom() %% Arity = Clause = Line = integer() @@ -541,7 +563,10 @@ remote_call(Node,Request) -> Return = receive {'DOWN', Ref, _Type, _Object, _Info} -> - {error,node_dead}; + case Request of + {remote,stop} -> ok; + _ -> {error,node_dead} + end; {?SERVER,Reply} -> Reply end, @@ -569,40 +594,14 @@ init_main(Starter) -> ets:new(?BINARY_TABLE, [set, named_table]), ets:new(?COLLECTION_TABLE, [set, public, named_table]), ets:new(?COLLECTION_CLAUSE_TABLE, [set, public, named_table]), - process_flag(trap_exit,true), + net_kernel:monitor_nodes(true), Starter ! {?SERVER,started}, main_process_loop(#main_state{}). main_process_loop(State) -> receive {From, {start_nodes,Nodes}} -> - ThisNode = node(), - StartedNodes = - lists:foldl( - fun(Node,Acc) -> - case rpc:call(Node,cover,remote_start,[ThisNode]) of - {ok,RPid} -> - link(RPid), - [Node|Acc]; - Error -> - io:format("Could not start cover on ~w: ~p\n", - [Node,Error]), - Acc - end - end, - [], - Nodes), - - %% In case some of the compiled modules have been unloaded they - %% should not be loaded on the new node. - {_LoadedModules,Compiled} = - get_compiled_still_loaded(State#main_state.nodes, - State#main_state.compiled), - remote_load_compiled(StartedNodes,Compiled), - - State1 = - State#main_state{nodes = State#main_state.nodes ++ StartedNodes, - compiled = Compiled}, + {StartedNodes,State1} = do_start_nodes(Nodes, State), reply(From, {ok,StartedNodes}), main_process_loop(State1); @@ -625,8 +624,9 @@ main_process_loop(State) -> Compiled0 = State#main_state.compiled, case get_beam_file(Module,BeamFile0,Compiled0) of {ok,BeamFile} -> + UserOptions = get_compile_options(Module,BeamFile), {Reply,Compiled} = - case do_compile_beam(Module,BeamFile,[]) of + case do_compile_beam(Module,BeamFile,UserOptions) of {ok, Module} -> remote_load_compiled(State#main_state.nodes, [{Module,BeamFile}]), @@ -707,8 +707,15 @@ main_process_loop(State) -> {From, {stop,Nodes}} -> remote_collect('_',Nodes,true), reply(From, ok), - State1 = State#main_state{nodes=State#main_state.nodes--Nodes}, - main_process_loop(State1); + Nodes1 = State#main_state.nodes--Nodes, + LostNodes1 = State#main_state.lost_nodes--Nodes, + main_process_loop(State#main_state{nodes=Nodes1, + lost_nodes=LostNodes1}); + + {From, {flush,Nodes}} -> + remote_collect('_',Nodes,false), + reply(From, ok), + main_process_loop(State); {From, stop} -> lists:foreach( @@ -717,6 +724,11 @@ main_process_loop(State) -> end, State#main_state.nodes), reload_originals(State#main_state.compiled), + ets:delete(?COVER_TABLE), + ets:delete(?COVER_CLAUSE_TABLE), + ets:delete(?BINARY_TABLE), + ets:delete(?COLLECTION_TABLE), + ets:delete(?COLLECTION_CLAUSE_TABLE), unregister(?SERVER), reply(From, ok); @@ -788,16 +800,39 @@ main_process_loop(State) -> end, main_process_loop(S); - {'EXIT',Pid,_Reason} -> - %% Exit is trapped on the main node only, so this will only happen - %% there. I assume that I'm only linked to cover_servers on remote - %% nodes, so this must be one of them crashing. - %% Remove node from list! - State1 = State#main_state{nodes=State#main_state.nodes--[node(Pid)]}, + {'DOWN', _MRef, process, {?SERVER,Node}, _Info} -> + %% A remote cover_server is down, mark as lost + {Nodes,Lost} = + case lists:member(Node,State#main_state.nodes) of + true -> + N = State#main_state.nodes--[Node], + L = [Node|State#main_state.lost_nodes], + {N,L}; + false -> % node stopped + {State#main_state.nodes,State#main_state.lost_nodes} + end, + main_process_loop(State#main_state{nodes=Nodes,lost_nodes=Lost}); + + {nodeup,Node} -> + State1 = + case lists:member(Node,State#main_state.lost_nodes) of + true -> + sync_compiled(Node,State); + false -> + State + end, main_process_loop(State1); + + {nodedown,_} -> + %% Will be taken care of when 'DOWN' message arrives + main_process_loop(State); + {From, get_main_node} -> + reply(From, node()), + main_process_loop(State); + get_status -> - io:format("~p~n",[State]), + io:format("~tp~n",[State]), main_process_loop(State) end. @@ -849,11 +884,22 @@ remote_process_loop(State) -> {remote,stop} -> reload_originals(State#remote_state.compiled), + ets:delete(?COVER_TABLE), + ets:delete(?COVER_CLAUSE_TABLE), unregister(?SERVER), - remote_reply(State#remote_state.main_node, ok); + ok; % not replying since 'DOWN' message will be received anyway + + {remote,get_compiled} -> + remote_reply(State#remote_state.main_node, + State#remote_state.compiled), + remote_process_loop(State); + + {From, get_main_node} -> + remote_reply(From, State#remote_state.main_node), + remote_process_loop(State); get_status -> - io:format("~p~n",[State]), + io:format("~tp~n",[State]), remote_process_loop(State); M -> @@ -961,6 +1007,36 @@ unload([]) -> %%%--Handling of remote nodes-------------------------------------------- +do_start_nodes(Nodes, State) -> + ThisNode = node(), + StartedNodes = + lists:foldl( + fun(Node,Acc) -> + case rpc:call(Node,cover,remote_start,[ThisNode]) of + {ok,_RPid} -> + erlang:monitor(process,{?SERVER,Node}), + [Node|Acc]; + Error -> + io:format("Could not start cover on ~w: ~tp\n", + [Node,Error]), + Acc + end + end, + [], + Nodes), + + %% In case some of the compiled modules have been unloaded they + %% should not be loaded on the new node. + {_LoadedModules,Compiled} = + get_compiled_still_loaded(State#main_state.nodes, + State#main_state.compiled), + remote_load_compiled(StartedNodes,Compiled), + + State1 = + State#main_state{nodes = State#main_state.nodes ++ StartedNodes, + compiled = Compiled}, + {StartedNodes, State1}. + %% start the cover_server on a remote node remote_start(MainNode) -> case whereis(?SERVER) of @@ -984,6 +1060,30 @@ remote_start(MainNode) -> {error,{already_started,Pid}} end. +%% If a lost node comes back, ensure that main and remote node has the +%% same cover compiled modules. Note that no action is taken if the +%% same {Mod,File} eksists on both, i.e. code change is not handled! +sync_compiled(Node,State) -> + #main_state{compiled=Compiled0,nodes=Nodes,lost_nodes=Lost}=State, + State1 = + case remote_call(Node,{remote,get_compiled}) of + {error,node_dead} -> + {_,S} = do_start_nodes([Node],State), + S; + {error,_} -> + State; + RemoteCompiled -> + {_,Compiled} = get_compiled_still_loaded(Nodes,Compiled0), + Unload = [UM || {UM,_}=U <- RemoteCompiled, + false == lists:member(U,Compiled)], + remote_unload([Node],Unload), + Load = [L || L <- Compiled, + false == lists:member(L,RemoteCompiled)], + remote_load_compiled([Node],Load), + State#main_state{compiled=Compiled, nodes=[Node|Nodes]} + end, + State1#main_state{lost_nodes=Lost--[Node]}. + %% Load a set of cover compiled modules on remote nodes, %% We do it ?MAX_MODS modules at a time so that we don't %% run out of memory on the cover_server node. @@ -1049,9 +1149,14 @@ remote_collect(Module,Nodes,Stop) -> do_collection(Node, Module, Stop) -> CollectorPid = spawn(fun collector_proc/0), - remote_call(Node,{remote,collect,Module,CollectorPid, self()}), - if Stop -> remote_call(Node,{remote,stop}); - true -> ok + case remote_call(Node,{remote,collect,Module,CollectorPid, self()}) of + {error,node_dead} -> + CollectorPid ! done, + ok; + ok when Stop -> + remote_call(Node,{remote,stop}); + ok -> + ok end. %% Process which receives chunks of data from remote nodes - either when @@ -1094,7 +1199,6 @@ remove_myself([Node|Nodes],Acc) -> remove_myself(Nodes,[Node|Acc]); remove_myself([],Acc) -> Acc. - %%%--Handling of modules state data-------------------------------------- @@ -1134,7 +1238,7 @@ do_get_all_importfiles([],Acc) -> imported_info(Text,Module,Imported) -> case lists:keysearch(Module,1,Imported) of {value,{Module,_File,ImportFiles}} -> - io:format("~s includes data from imported files\n~p\n", + io:format("~ts includes data from imported files\n~tp\n", [Text,ImportFiles]); false -> ok @@ -1148,7 +1252,7 @@ add_imported(Module, File, ImportFile, Imported) -> add_imported(M, F1, ImportFile, [{M,_F2,ImportFiles}|Imported], Acc) -> case lists:member(ImportFile,ImportFiles) of true -> - io:fwrite("WARNING: Module ~w already imported from ~p~n" + io:fwrite("WARNING: Module ~w already imported from ~tp~n" "Not importing again!~n",[M,ImportFile]), dont_import; false -> @@ -1166,7 +1270,7 @@ remove_imported(Module,Imported) -> case lists:keysearch(Module,1,Imported) of {value,{Module,_,ImportFiles}} -> io:fwrite("WARNING: Deleting data for module ~w imported from~n" - "~p~n",[Module,ImportFiles]), + "~tp~n",[Module,ImportFiles]), lists:keydelete(Module,1,Imported); false -> Imported @@ -1283,10 +1387,15 @@ do_compile_beam(Module,Beam,UserOptions) -> Forms0 = epp:interpret_file_attribute(Code), {Forms,Vars} = transform(Vsn, Forms0, Module, Beam), + %% We need to recover the source from the compilation + %% info otherwise the newly compiled module will have + %% source pointing to the current directory + SourceInfo = get_source_info(Module, Beam), + %% Compile and load the result %% It's necessary to check the result of loading since it may %% fail, for example if Module resides in a sticky directory - {ok, Module, Binary} = compile:forms(Forms, UserOptions), + {ok, Module, Binary} = compile:forms(Forms, SourceInfo ++ UserOptions), case code:load_binary(Module, ?TAG, Binary) of {module, Module} -> @@ -1314,6 +1423,28 @@ get_abstract_code(Module, Beam) -> Error -> Error end. +get_source_info(Module, Beam) -> + Compile = get_compile_info(Module, Beam), + case lists:keyfind(source, 1, Compile) of + { source, _ } = Tuple -> [Tuple]; + false -> [] + end. + +get_compile_options(Module, Beam) -> + Compile = get_compile_info(Module, Beam), + case lists:keyfind(options, 1, Compile) of + {options, Options } -> filter_options(Options); + false -> [] + end. + +get_compile_info(Module, Beam) -> + case beam_lib:chunks(Beam, [compile_info]) of + {ok, {Module, [{compile_info, Compile}]}} -> + Compile; + _ -> + [] + end. + transform(Vsn, Code, Module, Beam) when Vsn=:=abstract_v1; Vsn=:=abstract_v2 -> Vars0 = #vars{module=Module, vsn=Vsn}, MainFile=find_main_filename(Code), @@ -1430,12 +1561,6 @@ aux_var(Vars, N) -> %% This way we will be able to exclude functions defined in include files. munge({function,0,module_info,_Arity,_Clauses},_Vars,_MainFile,_Switch) -> ignore; % module_info will be added again when the forms are recompiled -munge(Form={function,_,'MNEMOSYNE QUERY',_,_},Vars,_MainFile,Switch) -> - {Form,Vars,Switch}; % No bumps in Mnemosyne code. -munge(Form={function,_,'MNEMOSYNE RULE',_,_},Vars,_MainFile,Switch) -> - {Form,Vars,Switch}; -munge(Form={function,_,'MNEMOSYNE RECFUNDEF',_,_},Vars,_MainFile,Switch) -> - {Form,Vars,Switch}; munge({function,Line,Function,Arity,Clauses},Vars,_MainFile,on) -> Vars2 = Vars#vars{function=Function, arity=Arity, @@ -1700,17 +1825,11 @@ munge_expr({'catch',Line,Expr}, Vars) -> {MungedExpr, Vars2} = munge_expr(Expr, Vars), {{'catch',Line,MungedExpr}, Vars2}; munge_expr({call,Line1,{remote,Line2,ExprM,ExprF},Exprs}, - Vars) when Vars#vars.is_guard=:=false-> + Vars) -> {MungedExprM, Vars2} = munge_expr(ExprM, Vars), {MungedExprF, Vars3} = munge_expr(ExprF, Vars2), {MungedExprs, Vars4} = munge_exprs(Exprs, Vars3, []), {{call,Line1,{remote,Line2,MungedExprM,MungedExprF},MungedExprs}, Vars4}; -munge_expr({call,Line1,{remote,_Line2,_ExprM,ExprF},Exprs}, - Vars) when Vars#vars.is_guard=:=true -> - %% Difference in abstract format after preprocessing: BIF calls in guards - %% are translated to {remote,...} (which is not allowed as source form) - %% NOT NECESSARY FOR Vsn=raw_abstract_v1 - munge_expr({call,Line1,ExprF,Exprs}, Vars); munge_expr({call,Line,Expr,Exprs}, Vars) -> {MungedExpr, Vars2} = munge_expr(Expr, Vars), {MungedExprs, Vars3} = munge_exprs(Exprs, Vars2, []), @@ -1858,32 +1977,62 @@ move_clauses([{M,F,A,C,_L}|Clauses]) -> move_clauses(Clauses); move_clauses([]) -> ok. - %% Given a .beam file, find the .erl file. Look first in same directory as -%% the .beam file, then in <beamdir>/../src -find_source(File0) -> - case filename:rootname(File0,".beam") of - File0 -> - File0; - File -> - InSameDir = File++".erl", - case filelib:is_file(InSameDir) of - true -> - InSameDir; - false -> - Dir = filename:dirname(File), - Mod = filename:basename(File), - InDotDotSrc = filename:join([Dir,"..","src",Mod++".erl"]), - case filelib:is_file(InDotDotSrc) of - true -> - InDotDotSrc; - false -> - {beam,File0} - end - end +%% the .beam file, then in ../src, then in compile info. +find_source(Module, File0) -> + try + Root = filename:rootname(File0, ".beam"), + Root == File0 andalso throw(File0), %% not .beam + %% Look for .erl in pwd. + File = Root ++ ".erl", + throw_file(File), + %% Not in pwd: look in ../src. + BeamDir = filename:dirname(File), + Base = filename:basename(File), + throw_file(filename:join([BeamDir, "..", "src", Base])), + %% Not in ../src: look for source path in compile info, but + %% first look relative the beam directory. + Info = lists:keyfind(source, 1, Module:module_info(compile)), + false == Info andalso throw({beam, File0}), %% stripped + {source, SrcFile} = Info, + throw_file(splice(BeamDir, SrcFile)), %% below ../src + throw_file(SrcFile), %% or absolute + %% No success means that source is either not under ../src or + %% its relative path differs from that of compile info. (For + %% example, compiled under src/x but installed under src/y.) + %% An option to specify an arbitrary source path explicitly is + %% probably a better solution than either more heuristics or a + %% potentially slow filesystem search. + {beam, File0} + catch + Path -> Path + end. + +throw_file(Path) -> + false /= Path andalso filelib:is_file(Path) andalso throw(Path). + +%% Splice the tail of a source path, starting from the last "src" +%% component, onto the parent of a beam directory, or return false if +%% no "src" component is found. +%% +%% Eg. splice("/path/to/app-1.0/ebin", "/compiled/path/to/app/src/x/y.erl") +%% --> "/path/to/app-1.0/ebin/../src/x/y.erl" +%% +%% This handles the case of source in subdirectories of ../src with +%% beams that have moved since compilation. +%% +splice(BeamDir, SrcFile) -> + case lists:splitwith(fun(C) -> C /= "src" end, revsplit(SrcFile)) of + {T, [_|_]} -> %% found src component + filename:join([BeamDir, "..", "src" | lists:reverse(T)]); + {_, []} -> %% or not + false end. +revsplit(Path) -> + lists:reverse(filename:split(Path)). + do_parallel_analysis(Module, Analysis, Level, Loaded, From, State) -> analyse_info(Module,State#main_state.imported), C = case Loaded of @@ -1987,7 +2136,7 @@ do_parallel_analysis_to_file(Module, OutFile, Opts, Loaded, From, State) -> {imported, File0, _} -> File0 end, - case find_source(File) of + case find_source(Module, File) of {beam,_BeamFile} -> reply(From, {error,no_source_code_found}); ErlFile -> @@ -2007,30 +2156,40 @@ do_analyse_to_file(Module, OutFile, ErlFile, HTML) -> case file:open(OutFile, [write]) of {ok, OutFd} -> if HTML -> - io:format(OutFd, - "<html>\n" - "<head><title>~s</title></head>" - "<body bgcolor=white text=black>\n" - "<pre>\n", - [OutFile]); + Encoding = encoding(ErlFile), + Header = + ["<!DOCTYPE HTML PUBLIC " + "\"-//W3C//DTD HTML 3.2 Final//EN\">\n" + "<html>\n" + "<head>\n" + "<meta http-equiv=\"Content-Type\"" + " content=\"text/html; charset=", + Encoding,"\"/>\n" + "<title>",OutFile,"</title>\n" + "</head>" + "<body style='background-color: white;" + " color: black'>\n" + "<pre>\n"], + file:write(OutFd,Header); true -> ok end, %% Write some initial information to the output file {{Y,Mo,D},{H,Mi,S}} = calendar:local_time(), - io:format(OutFd, "File generated from ~s by COVER " - "~p-~s-~s at ~s:~s:~s~n", - [ErlFile, - Y, - string:right(integer_to_list(Mo), 2, $0), - string:right(integer_to_list(D), 2, $0), - string:right(integer_to_list(H), 2, $0), - string:right(integer_to_list(Mi), 2, $0), - string:right(integer_to_list(S), 2, $0)]), - io:format(OutFd, "~n" - "**************************************" - "**************************************" - "~n~n", []), + Timestamp = + io_lib:format("~p-~s-~s at ~s:~s:~s", + [Y, + string:right(integer_to_list(Mo), 2, $0), + string:right(integer_to_list(D), 2, $0), + string:right(integer_to_list(H), 2, $0), + string:right(integer_to_list(Mi), 2, $0), + string:right(integer_to_list(S), 2, $0)]), + file:write(OutFd, + ["File generated from ",ErlFile," by COVER ", + Timestamp,"\n\n" + "**************************************" + "**************************************" + "\n\n"]), print_lines(Module, InFd, OutFd, 1, HTML), @@ -2254,7 +2413,13 @@ do_reset2([]) -> do_clear(Module) -> ets:match_delete(?COVER_CLAUSE_TABLE, {Module,'_'}), ets:match_delete(?COVER_TABLE, {#bump{module=Module},'_'}), - ets:match_delete(?COLLECTION_TABLE, {#bump{module=Module},'_'}). + case lists:member(?COLLECTION_TABLE, ets:all()) of + true -> + %% We're on the main node + ets:match_delete(?COLLECTION_TABLE, {#bump{module=Module},'_'}); + false -> + ok + end. not_loaded(Module, unloaded, State) -> do_clear(Module), @@ -2307,7 +2472,7 @@ pmap(Fun, [E | Rest], Pids, Limit, Cnt, Acc) when Cnt < Limit -> pmap(Fun, Rest, Pids ++ [Pid], Limit, Cnt + 1, Acc); pmap(Fun, List, [Pid | Pids], Limit, Cnt, Acc) -> receive - {'DOWN', _Ref, process, _, _} -> + {'DOWN', _Ref, process, X, _} when is_pid(X) -> pmap(Fun, List, [Pid | Pids], Limit, Cnt - 1, Acc); {res, Pid, Res} -> pmap(Fun, List, Pids, Limit, Cnt, [Res | Acc]) @@ -2316,6 +2481,23 @@ pmap(_Fun, [], [], _Limit, 0, Acc) -> lists:reverse(Acc); pmap(Fun, [], [], Limit, Cnt, Acc) -> receive - {'DOWN', _Ref, process, _, _} -> + {'DOWN', _Ref, process, X, _} when is_pid(X) -> pmap(Fun, [], [], Limit, Cnt - 1, Acc) end. + +%%%----------------------------------------------------------------- +%%% Read encoding from source file +encoding(File) -> + Encoding = + case epp:read_encoding(File) of + none -> + epp:default_encoding(); + E -> + E + end, + html_encoding(Encoding). + +html_encoding(latin1) -> + "iso-8859-1"; +html_encoding(utf8) -> + "utf-8". diff --git a/lib/tools/src/eprof.erl b/lib/tools/src/eprof.erl index 87fdc1fa34..bfbbefb473 100644 --- a/lib/tools/src/eprof.erl +++ b/lib/tools/src/eprof.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. 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 @@ -26,7 +26,7 @@ -export([start/0, stop/0, dump/0, - start_profiling/1, start_profiling/2, + start_profiling/1, start_profiling/2, start_profiling/3, profile/1, profile/2, profile/3, profile/4, profile/5, stop_profiling/0, analyze/0, analyze/1, analyze/2, @@ -39,6 +39,8 @@ handle_info/2, terminate/2, code_change/3]). + + -record(bpd, { n = 0, % number of total calls us = 0, % sum of uS for all calls @@ -46,14 +48,18 @@ mfa = [] % list of {Mfa, {Count, Us}} }). +-define(default_options, [{set_on_spawn, true}]). +-define(default_pattern, {'_','_','_'}). + -record(state, { - profiling = false, - pattern = {'_','_','_'}, - rootset = [], - fd = undefined, - start_ts = undefined, - reply = undefined, - bpd = #bpd{} + profiling = false, + pattern = ?default_pattern, + rootset = [], + trace_opts = [], + fd = undefined, + start_ts = undefined, + reply = undefined, + bpd = #bpd{} }). @@ -67,26 +73,6 @@ start() -> gen_server:start({local, ?MODULE}, ?MODULE, [], []). stop() -> gen_server:call(?MODULE, stop, infinity). -profile(Fun) when is_function(Fun) -> - profile([], Fun); -profile(Rs) when is_list(Rs) -> - start_profiling(Rs). - -profile(Pids, Fun) -> - profile(Pids, Fun, {'_','_','_'}). - -profile(Pids, Fun, Pattern) -> - profile(Pids, erlang, apply, [Fun,[]], Pattern). - -profile(Pids, M, F, A) -> - profile(Pids, M, F, A, {'_','_','_'}). - -profile(Pids, M, F, A, Pattern) -> - start(), - gen_server:call(?MODULE, {profile,Pids,Pattern,M,F,A},infinity). - -dump() -> - gen_server:call(?MODULE, dump, infinity). analyze() -> analyze(procs). @@ -98,17 +84,53 @@ analyze(Opts) when is_list(Opts) -> analyze(Type, Opts) when is_list(Opts) -> gen_server:call(?MODULE, {analyze, Type, Opts}, infinity). +%% odd duck, should only been start_profiling/1 +profile(Rootset) when is_list(Rootset) -> + start_profiling(Rootset); + +profile(Fun) when is_function(Fun) -> + profile([], Fun). + +profile(Fun, Opts) when is_function(Fun), is_list(Opts) -> + profile([], erlang, apply, [Fun, []], ?default_pattern, Opts); + +profile(Rootset, Fun) when is_list(Rootset), is_function(Fun) -> + profile(Rootset, Fun, ?default_pattern). + +profile(Rootset, Fun, Pattern) when is_list(Rootset), is_function(Fun) -> + profile(Rootset, Fun, Pattern, ?default_options). + +profile(Rootset, Fun, Pattern, Options) when is_list(Rootset), is_function(Fun), is_list(Options) -> + profile(Rootset, erlang, apply, [Fun,[]], Pattern, Options); + +profile(Rootset, M, F, A) when is_list(Rootset), is_atom(M), is_atom(F), is_list(A) -> + profile(Rootset, M, F, A, ?default_pattern). + +profile(Rootset, M, F, A, Pattern) when is_list(Rootset), is_atom(M), is_atom(F), is_list(A) -> + profile(Rootset, M, F, A, Pattern, ?default_options). + +%% Returns when M:F/A has terminated +profile(Rootset, M, F, A, Pattern, Options) -> + start(), + gen_server:call(?MODULE, {profile_start, Rootset, Pattern, {M,F,A}, Options}, infinity). + +dump() -> + gen_server:call(?MODULE, dump, infinity). + log(File) -> gen_server:call(?MODULE, {logfile, File}, infinity). +%% Does not block start_profiling(Rootset) -> - start_profiling(Rootset, {'_','_','_'}). + start_profiling(Rootset, ?default_pattern). start_profiling(Rootset, Pattern) -> + start_profiling(Rootset, Pattern, ?default_options). +start_profiling(Rootset, Pattern, Options) -> start(), - gen_server:call(?MODULE, {profile, Rootset, Pattern}, infinity). + gen_server:call(?MODULE, {profile_start, Rootset, Pattern, undefined, Options}, infinity). stop_profiling() -> - gen_server:call(?MODULE, stop_profiling, infinity). + gen_server:call(?MODULE, profile_stop, infinity). %% -------------------------------------------------------------------- %% @@ -151,74 +173,75 @@ handle_call({analyze, Type, _Opts}, _, S) -> %% profile -handle_call({profile, _Rootset, _Pattern, _M,_F,_A}, _From, #state{ profiling = true } = S) -> +handle_call({profile_start, _Rootset, _Pattern, _MFA, _Opts}, _From, #state{ profiling = true } = S) -> {reply, {error, already_profiling}, S}; -handle_call({profile, Rootset, Pattern, M,F,A}, From, #state{fd = Fd } = S) -> +handle_call({profile_start, Rootset, Pattern, {M,F,A}, Opts}, From, #state{fd = Fd } = S) -> + + ok = set_pattern_trace(false, S#state.pattern), + _ = set_process_trace(false, S#state.rootset, S#state.trace_opts), - set_pattern_trace(false, S#state.pattern), - set_process_trace(false, S#state.rootset), + Topts = get_trace_options(Opts), + Pid = setup_profiling(M,F,A), - Pid = setup_profiling(M,F,A), - case set_process_trace(true, [Pid|Rootset]) of + case set_process_trace(true, [Pid|Rootset], Topts) of true -> - set_pattern_trace(true, Pattern), + ok = set_pattern_trace(true, Pattern), T0 = now(), - execute_profiling(Pid), + ok = execute_profiling(Pid), {noreply, #state{ - profiling = true, - rootset = [Pid|Rootset], - start_ts = T0, - reply = From, - fd = Fd, - pattern = Pattern + profiling = true, + rootset = [Pid|Rootset], + start_ts = T0, + reply = From, + fd = Fd, + trace_opts = Topts, + pattern = Pattern }}; false -> exit(Pid, eprof_kill), {reply, error, #state{ fd = Fd}} end; -handle_call({profile, _Rootset, _Pattern}, _From, #state{ profiling = true } = S) -> - {reply, {error, already_profiling}, S}; - -handle_call({profile, Rootset, Pattern}, From, #state{ fd = Fd } = S) -> +handle_call({profile_start, Rootset, Pattern, undefined, Opts}, From, #state{ fd = Fd } = S) -> - set_pattern_trace(false, S#state.pattern), - set_process_trace(false, S#state.rootset), + ok = set_pattern_trace(false, S#state.pattern), + true = set_process_trace(false, S#state.rootset, S#state.trace_opts), + Topts = get_trace_options(Opts), - case set_process_trace(true, Rootset) of + case set_process_trace(true, Rootset, Topts) of true -> T0 = now(), - set_pattern_trace(true, Pattern), + ok = set_pattern_trace(true, Pattern), {reply, profiling, #state{ - profiling = true, - rootset = Rootset, - start_ts = T0, - reply = From, - fd = Fd, - pattern = Pattern + profiling = true, + rootset = Rootset, + start_ts = T0, + reply = From, + fd = Fd, + trace_opts = Topts, + pattern = Pattern }}; false -> {reply, error, #state{ fd = Fd }} end; -handle_call(stop_profiling, _From, #state{ profiling = false } = S) -> +handle_call(profile_stop, _From, #state{ profiling = false } = S) -> {reply, profiling_already_stopped, S}; -handle_call(stop_profiling, _From, #state{ profiling = true } = S) -> - - set_pattern_trace(pause, S#state.pattern), +handle_call(profile_stop, _From, #state{ profiling = true } = S) -> + ok = set_pattern_trace(pause, S#state.pattern), Bpd = collect_bpd(), - - set_process_trace(false, S#state.rootset), - set_pattern_trace(false, S#state.pattern), + _ = set_process_trace(false, S#state.rootset, S#state.trace_opts), + ok = set_pattern_trace(false, S#state.pattern), {reply, profiling_stopped, S#state{ - profiling = false, - rootset = [], - pattern = {'_','_','_'}, - bpd = Bpd + profiling = false, + rootset = [], + trace_opts = [], + pattern = ?default_pattern, + bpd = Bpd }}; %% logfile @@ -261,33 +284,33 @@ handle_info({'EXIT', _, eprof_kill}, S) -> {noreply, S}; handle_info({'EXIT', _, Reason}, #state{ reply = FromTag } = S) -> - set_process_trace(false, S#state.rootset), - set_pattern_trace(false, S#state.pattern), + _ = set_process_trace(false, S#state.rootset, S#state.trace_opts), + ok = set_pattern_trace(false, S#state.pattern), gen_server:reply(FromTag, {error, Reason}), {noreply, S#state{ - profiling = false, - rootset = [], - pattern = {'_','_','_'} + profiling = false, + rootset = [], + trace_opts = [], + pattern = ?default_pattern }}; % check if Pid is spawned process? handle_info({_Pid, {answer, Result}}, #state{ reply = {From,_} = FromTag} = S) -> - set_pattern_trace(pause, S#state.pattern), - - Bpd = collect_bpd(), - - set_process_trace(false, S#state.rootset), - set_pattern_trace(false, S#state.pattern), + ok = set_pattern_trace(pause, S#state.pattern), + Bpd = collect_bpd(), + _ = set_process_trace(false, S#state.rootset, S#state.trace_opts), + ok = set_pattern_trace(false, S#state.pattern), catch unlink(From), gen_server:reply(FromTag, {ok, Result}), {noreply, S#state{ - profiling = false, - rootset = [], - pattern = {'_','_','_'}, - bpd = Bpd + profiling = false, + rootset = [], + trace_opts = [], + pattern = ?default_pattern, + bpd = Bpd }}. %% -------------------------------------------------------------------- %% @@ -297,11 +320,11 @@ handle_info({_Pid, {answer, Result}}, #state{ reply = {From,_} = FromTag} = S) - %% -------------------------------------------------------------------- %% terminate(_Reason, #state{ fd = undefined }) -> - set_pattern_trace(false, {'_','_','_'}), + ok = set_pattern_trace(false, ?default_pattern), ok; terminate(_Reason, #state{ fd = Fd }) -> - file:close(Fd), - set_pattern_trace(false, {'_','_','_'}), + ok = file:close(Fd), + ok = set_pattern_trace(false, ?default_pattern), ok. %% -------------------------------------------------------------------- %% @@ -330,7 +353,19 @@ spin_profile(M, F, A) -> end. execute_profiling(Pid) -> - Pid ! {self(), execute}. + Pid ! {self(), execute}, + ok. + + +get_trace_options([]) -> + [call]; +get_trace_options([{set_on_spawn, true}|Opts]) -> + [set_on_spawn | get_trace_options(Opts)]; +get_trace_options([set_on_spawn|Opts]) -> + [set_on_spawn | get_trace_options(Opts)]; +get_trace_options([_|Opts]) -> + get_trace_options(Opts). + set_pattern_trace(Flag, Pattern) -> erlang:system_flag(multi_scheduling, block), @@ -339,10 +374,6 @@ set_pattern_trace(Flag, Pattern) -> erlang:system_flag(multi_scheduling, unblock), ok. -set_process_trace(Flag, Pids) -> - % do we need procs for meta info? - % could be useful - set_process_trace(Flag, Pids, [call, set_on_spawn]). set_process_trace(_, [], _) -> true; set_process_trace(Flag, [Pid|Pids], Options) when is_pid(Pid) -> try diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl index 4cbb910f11..75840e54ff 100644 --- a/lib/tools/src/fprof.erl +++ b/lib/tools/src/fprof.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2012. All Rights Reserved. +%% Copyright Ericsson AB 2001-2013. 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 @@ -1226,10 +1226,7 @@ spawn_3step(Spawn, FunPrelude, FunAck, FunBody) MRef = erlang:monitor(process, Parent), receive {Parent, Ref, Go} -> - erlang:demonitor(MRef), - receive {'DOWN', MRef, _, _, _} -> ok - after 0 -> ok - end, + erlang:demonitor(MRef, [flush]), FunBody(Go); {'DOWN', MRef, _, _, _} -> ok @@ -1238,8 +1235,7 @@ spawn_3step(Spawn, FunPrelude, FunAck, FunBody) MRef = erlang:monitor(process, Child), receive {Child, Ref, Ack} -> - erlang:demonitor(MRef), - receive {'DOWN', MRef, _, _, _} -> ok after 0 -> ok end, + erlang:demonitor(MRef, [flush]), try FunAck(Ack) of {Result, Go} -> catch Child ! {Parent, Ref, Go}, diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl index 989a661b75..f13a297ecf 100644 --- a/lib/tools/src/lcnt.erl +++ b/lib/tools/src/lcnt.erl @@ -1,7 +1,8 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. 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 @@ -271,7 +272,7 @@ handle_call({locations, InOpts}, _From, #state{ locks = Locks } = State) when is Opts = options(InOpts, Default), Printables = filter_print([#print{ name = string_names(Names), - entry = term2string("~p:~p", [Stats#stats.file, Stats#stats.line]), + entry = term2string("~tp:~p", [Stats#stats.file, Stats#stats.line]), colls = Stats#stats.colls, tries = Stats#stats.tries, cr = percent(Stats#stats.colls, Stats#stats.tries), @@ -566,7 +567,7 @@ stats2print(Stats, Duration) -> lists:map(fun (S) -> #print{ - entry = term2string("~p:~p", [S#stats.file, S#stats.line]), + entry = term2string("~tp:~p", [S#stats.file, S#stats.line]), colls = S#stats.colls, tries = S#stats.tries, cr = percent(S#stats.colls, S#stats.tries), @@ -797,20 +798,20 @@ options1([{Key, Value}|Opts], Defaults) -> %%% AUX STRING FORMATTING -print(String) -> io:format("~s~n", [String]). +print(String) -> io:format("~ts~n", [String]). kv(Key, Value) -> kv(Key, Value, 20). kv(Key, Value, Offset) -> term2string(term2string("~~~ps : ~~s", [Offset]),[Key, Value]). s(T) when is_float(T) -> term2string("~.4f", [T]); -s(T) when is_list(T) -> term2string("~s", [T]); +s(T) when is_list(T) -> term2string("~ts", [T]); s(T) -> term2string(T). strings(Strings) -> strings(Strings, []). strings([], Out) -> Out; strings([{space, N, S} | Ss], Out) -> strings(Ss, Out ++ term2string(term2string("~~~ps", [N]), [S])); strings([{format, Format, S} | Ss], Out) -> strings(Ss, Out ++ term2string(Format, [S])); -strings([S|Ss], Out) -> strings(Ss, Out ++ term2string("~s", [S])). +strings([S|Ss], Out) -> strings(Ss, Out ++ term2string("~ts", [S])). term2string({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) -> term2string("~p:~p/~p", [M,F,A]); diff --git a/lib/tools/src/make.erl b/lib/tools/src/make.erl index 5cc8d47faa..c8ef0a04a5 100644 --- a/lib/tools/src/make.erl +++ b/lib/tools/src/make.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. 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 @@ -90,7 +90,7 @@ read_emakefile(Emakefile,Opts) -> Mods = [filename:rootname(F) || F <- filelib:wildcard("*.erl")], [{Mods, Opts}]; {error,Other} -> - io:format("make: Trouble reading 'Emakefile':~n~p~n",[Other]), + io:format("make: Trouble reading 'Emakefile':~n~tp~n",[Other]), error end. @@ -145,7 +145,7 @@ get_opts_from_emakefile(Mods,Emakefile,Opts) -> {error,enoent} -> [{Mods, Opts}]; {error,Other} -> - io:format("make: Trouble reading 'Emakefile':~n~p~n",[Other]), + io:format("make: Trouble reading 'Emakefile':~n~tp~n",[Other]), error end. @@ -253,15 +253,15 @@ include_opt([]) -> %% Where load can be netload | load | noload recompile(File, true, _Load, _Opts) -> - io:format("Out of date: ~s\n",[File]); + io:format("Out of date: ~ts\n",[File]); recompile(File, false, noload, Opts) -> - io:format("Recompile: ~s\n",[File]), + io:format("Recompile: ~ts\n",[File]), compile:file(File, [report_errors, report_warnings, error_summary |Opts]); recompile(File, false, load, Opts) -> - io:format("Recompile: ~s\n",[File]), + io:format("Recompile: ~ts\n",[File]), c:c(File, Opts); recompile(File, false, netload, Opts) -> - io:format("Recompile: ~s\n",[File]), + io:format("Recompile: ~ts\n",[File]), c:nc(File, Opts). exists(File) -> diff --git a/lib/tools/src/tags.erl b/lib/tools/src/tags.erl index e740d38c91..e3cc51cdb2 100644 --- a/lib/tools/src/tags.erl +++ b/lib/tools/src/tags.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2013. 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 @@ -157,7 +157,7 @@ files_loop([F | Fs], Os) -> ok -> ok; error -> - %% io:format("Could not open ~s~n", [F]), + %% io:format("Could not open ~ts~n", [F]), error end, files_loop(Fs, Os). @@ -292,7 +292,7 @@ word_char(C) when C >= $0, C =< $9 -> true; word_char($_) -> true; word_char(_) -> false. - + %%% Output routines %% Check the options `outfile' and `outdir'. @@ -315,15 +315,15 @@ close_out(Os) -> pfnote(Str, {LineNo, CharNo}) -> - io_lib:format("~s\177~w,~w~n", [flatrev(Str), LineNo, CharNo]). + io_lib:format("~ts\177~w,~w~n", [flatrev(Str), LineNo, CharNo]). genout(Os, Name, Entries) -> - io:format(Os, "\^l~n~s,~w~n", [Name, reclength(Entries)]), + io:format(Os, "\^l~n~ts,~w~n", [Name, reclength(Entries)]), io:put_chars(Os, lists:reverse(Entries)). - + %%% help routines %% Flatten and reverse a nested list. diff --git a/lib/tools/src/xref.erl b/lib/tools/src/xref.erl index 0693bec019..abc184c84d 100644 --- a/lib/tools/src/xref.erl +++ b/lib/tools/src/xref.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% Copyright Ericsson AB 2000-2013. 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 @@ -297,7 +297,7 @@ set_default(Name, Option, Value) -> format_error({error, Module, Error}) -> Module:format_error(Error); format_error(E) -> - io_lib:format("~p~n", [E]). + io_lib:format("~tp~n", [E]). %%%---------------------------------------------------------------------- %%%Callback functions from gen_server diff --git a/lib/tools/src/xref_base.erl b/lib/tools/src/xref_base.erl index 93f0e9c0c8..30c5f3d12d 100644 --- a/lib/tools/src/xref_base.erl +++ b/lib/tools/src/xref_base.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2010. All Rights Reserved. +%% Copyright Ericsson AB 2000-2013. 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 @@ -480,43 +480,43 @@ set_default(State, Options) -> format_error({error, Module, Error}) -> Module:format_error(Error); format_error({invalid_options, Options}) -> - io_lib:format("Unknown option(s) or invalid option value(s): ~p~n", + io_lib:format("Unknown option(s) or invalid option value(s): ~tp~n", [Options]); format_error({invalid_filename, Term}) -> - io_lib:format("A file name (a string) was expected: ~p~n", [Term]); + io_lib:format("A file name (a string) was expected: ~tp~n", [Term]); format_error({no_debug_info, FileName}) -> - io_lib:format("The BEAM file ~p has no debug info~n", [FileName]); + io_lib:format("The BEAM file ~tp has no debug info~n", [FileName]); format_error({invalid_path, Term}) -> - io_lib:format("A path (a list of strings) was expected: ~p~n", [Term]); + io_lib:format("A path (a list of strings) was expected: ~tp~n", [Term]); format_error({invalid_query, Term}) -> - io_lib:format("A query (a string or an atom) was expected: ~p~n", [Term]); + io_lib:format("A query (a string or an atom) was expected: ~tp~n", [Term]); format_error({not_user_variable, Variable}) -> - io_lib:format("~p is not a user variable~n", [Variable]); + io_lib:format("~tp is not a user variable~n", [Variable]); format_error({unknown_analysis, Term}) -> - io_lib:format("~p is not a predefined analysis~n", [Term]); + io_lib:format("~tp is not a predefined analysis~n", [Term]); format_error({module_mismatch, Module, ReadModule}) -> - io_lib:format("Name of read module ~p does not match analyzed module ~p~n", + io_lib:format("Name of read module ~tp does not match analyzed module ~tp~n", [ReadModule, Module]); format_error({release_clash, {Release, Dir, OldDir}}) -> - io_lib:format("The release ~p read from ~p clashes with release " - "already read from ~p~n", [Release, Dir, OldDir]); + io_lib:format("The release ~tp read from ~tp clashes with release " + "already read from ~tp~n", [Release, Dir, OldDir]); format_error({application_clash, {Application, Dir, OldDir}}) -> - io_lib:format("The application ~p read from ~p clashes with application " - "already read from ~p~n", [Application, Dir, OldDir]); + io_lib:format("The application ~tp read from ~tp clashes with application " + "already read from ~tp~n", [Application, Dir, OldDir]); format_error({module_clash, {Module, Dir, OldDir}}) -> - io_lib:format("The module ~p read from ~p clashes with module " - "already read from ~p~n", [Module, Dir, OldDir]); + io_lib:format("The module ~tp read from ~tp clashes with module " + "already read from ~tp~n", [Module, Dir, OldDir]); format_error({no_such_release, Name}) -> - io_lib:format("There is no analyzed release ~p~n", [Name]); + io_lib:format("There is no analyzed release ~tp~n", [Name]); format_error({no_such_application, Name}) -> - io_lib:format("There is no analyzed application ~p~n", [Name]); + io_lib:format("There is no analyzed application ~tp~n", [Name]); format_error({no_such_module, Name}) -> - io_lib:format("There is no analyzed module ~p~n", [Name]); + io_lib:format("There is no analyzed module ~tp~n", [Name]); format_error({no_such_info, Term}) -> - io_lib:format("~p is not one of 'modules', 'applications', " + io_lib:format("~tp is not one of 'modules', 'applications', " "'releases' and 'libraries'~n", [Term]); format_error(E) -> - io_lib:format("~p~n", [E]). + io_lib:format("~tp~n", [E]). %% %% Local functions @@ -1506,7 +1506,7 @@ do_variables(State) -> _Else -> {[Name | P], U} end; ({{tmp, V}, _}, A) -> - io:format("Bug in ~p: temporary ~p~n", [?MODULE, V]), A; + io:format("Bug in ~tp: temporary ~tp~n", [?MODULE, V]), A; (_V, A) -> A end, {U,P} = foldl(Fun, {[],[]}, dict:to_list(State#xref.variables)), @@ -1766,23 +1766,23 @@ tpack(T, I, L) -> message(true, What, Arg) -> case What of reading_beam -> - io:format("~s... ", Arg); + io:format("~ts... ", Arg); skipped_beam -> io:format("skipped (no debug information)~n", Arg); no_debug_info -> - io:format("Skipping ~s (no debug information)~n", Arg); + io:format("Skipping ~ts (no debug information)~n", Arg); unresolved_summary1 -> - io:format("~p: 1 unresolved call~n", Arg); + io:format("~tp: 1 unresolved call~n", Arg); unresolved_summary -> - io:format("~p: ~p unresolved calls~n", Arg); + io:format("~tp: ~tp unresolved calls~n", Arg); jam -> - io:format("Skipping ~s (probably JAM file)~n", [Arg]); + io:format("Skipping ~ts (probably JAM file)~n", [Arg]); unreadable -> - io:format("Skipping ~s (unreadable)~n", [Arg]); + io:format("Skipping ~ts (unreadable)~n", [Arg]); xref_attr -> - io:format("~s: Skipping 'xref' attribute ~w~n", Arg); + io:format("~ts: Skipping 'xref' attribute ~w~n", Arg); depr_attr -> - io:format("~s: Skipping 'deprecated' attribute ~w~n", Arg); + io:format("~ts: Skipping 'deprecated' attribute ~w~n", Arg); lib_search -> io:format("Scanning library path for BEAM files... ", []); lib_check -> @@ -1794,7 +1794,7 @@ message(true, What, Arg) -> error -> io:format("error~n", Arg); Else -> - io:format("~p~n", [{Else,Arg}]) + io:format("~tp~n", [{Else,Arg}]) end; message(_, _, _) -> true. diff --git a/lib/tools/src/xref_compiler.erl b/lib/tools/src/xref_compiler.erl index 22312c6754..f0fed502a5 100644 --- a/lib/tools/src/xref_compiler.erl +++ b/lib/tools/src/xref_compiler.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2011. All Rights Reserved. +%% Copyright Ericsson AB 2000-2013. 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 @@ -83,19 +83,19 @@ format_error({error, Module, Error}) -> format_error({parse_error, Line, Error}) -> format_parse_error(Error, format_line(Line)); format_error({variable_reassigned, Expr}) -> - io_lib:format("Variable assigned more than once: ~s~n", [Expr]); + io_lib:format("Variable assigned more than once: ~ts~n", [Expr]); format_error({unknown_variable, Name}) -> - io_lib:format("Variable ~p used before set~n", [Name]); + io_lib:format("Variable ~tp used before set~n", [Name]); format_error({type_error, Expr}) -> io_lib:format("Operator applied to argument(s) of different or " - "invalid type(s): ~s~n", [Expr]); + "invalid type(s): ~ts~n", [Expr]); format_error({type_mismatch, Expr1, Expr2}) -> - io_lib:format("Constants of different types: ~s, ~s~n", + io_lib:format("Constants of different types: ~ts, ~ts~n", [Expr1, Expr2]); format_error({unknown_constant, Constant}) -> - io_lib:format("Unknown constant ~s~n", [Constant]); + io_lib:format("Unknown constant ~ts~n", [Constant]); format_error(E) -> - io_lib:format("~p~n", [E]). + io_lib:format("~tp~n", [E]). %% %% Local functions @@ -908,21 +908,21 @@ fetch_value(V, D) -> Value. format_parse_error(["invalid_regexp", String, Error], Line) -> - io_lib:format("Invalid regular expression \"~s\"~s: ~s~n", + io_lib:format("Invalid regular expression \"~ts\"~s: ~ts~n", [String, Line, lists:flatten(Error)]); format_parse_error(["invalid_regexp_variable", Var], Line) -> - io_lib:format("Invalid wildcard variable ~p~s " + io_lib:format("Invalid wildcard variable ~tp~s " "(only '_' is allowed)~n", [Var, Line]); format_parse_error(["missing_type", Expr], Line) -> - io_lib:format("Missing type of regular expression ~s~s~n", + io_lib:format("Missing type of regular expression ~ts~s~n", [Expr, Line]); format_parse_error(["type_mismatch", Expr], Line) -> - io_lib:format("Type does not match structure of constant~s: ~s~n", + io_lib:format("Type does not match structure of constant~s: ~ts~n", [Line, Expr]); format_parse_error(["invalid_operator", Op], Line) -> - io_lib:format("Invalid operator ~p~s~n", [Op, Line]); + io_lib:format("Invalid operator ~tp~s~n", [Op, Line]); format_parse_error(Error, Line) -> - io_lib:format("Parse error~s: ~s~n", [Line, lists:flatten(Error)]). + io_lib:format("Parse error~s: ~ts~n", [Line, lists:flatten(Error)]). format_line(-1) -> " at end of string"; diff --git a/lib/tools/src/xref_reader.erl b/lib/tools/src/xref_reader.erl index 92f0c45c7b..d3601c6ea0 100644 --- a/lib/tools/src/xref_reader.erl +++ b/lib/tools/src/xref_reader.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2010. All Rights Reserved. +%% Copyright Ericsson AB 2000-2013. 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 @@ -80,12 +80,6 @@ form({attribute, Line, xref, Calls}, S) -> % experimental attr(Calls, Line, M, Fun, L, X, B, S); form({attribute, _Line, _Attr, _Val}, S) -> S; -form({function, 0, 'MNEMOSYNE RULE', 1, _Clauses}, S) -> - S; -form({function, 0, 'MNEMOSYNE QUERY', 2, _Clauses}, S) -> - S; -form({function, 0, 'MNEMOSYNE RECFUNDEF', 1, _Clauses}, S) -> - S; form({function, 0, module_info, 0, _Clauses}, S) -> S; form({function, 0, module_info, 1, _Clauses}, S) -> @@ -331,9 +325,6 @@ handle_call(Locality, Module, Name, Arity, Line, S) -> handle_call(Locality, To, Line, S, false) end. -handle_call(_Locality, {_, 'MNEMOSYNE RULE',1}, _Line, S, _) -> S; -handle_call(_Locality, {_, 'MNEMOSYNE QUERY', 2}, _Line, S, _) -> S; -handle_call(_Locality, {_, 'MNEMOSYNE RECFUNDEF',1}, _Line, S, _) -> S; handle_call(Locality, To0, Line, S, IsUnres) -> From = S#xrefr.function, To = adjust_arity(S, To0), diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl index 680563e9df..7b72165e6f 100644 --- a/lib/tools/src/xref_utils.erl +++ b/lib/tools/src/xref_utils.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2012. All Rights Reserved. +%% Copyright Ericsson AB 2000-2013. 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 @@ -517,16 +517,16 @@ subprocess(Fun, Opts) -> format_error({error, Module, Error}) -> Module:format_error(Error); format_error({file_error, FileName, Reason}) -> - io_lib:format("~s: ~p~n", [FileName, file:format_error(Reason)]); + io_lib:format("~ts: ~tp~n", [FileName, file:format_error(Reason)]); format_error({unrecognized_file, FileName}) -> - io_lib:format("~p is neither a regular file nor a directory~n", + io_lib:format("~tp is neither a regular file nor a directory~n", [FileName]); format_error({no_such_module, Module}) -> - io_lib:format("Cannot find module ~p using the code path~n", [Module]); + io_lib:format("Cannot find module ~tp using the code path~n", [Module]); format_error({interpreted, Module}) -> - io_lib:format("Cannot use BEAM code of interpreted module ~p~n", [Module]); + io_lib:format("Cannot use BEAM code of interpreted module ~tp~n", [Module]); format_error(E) -> - io_lib:format("~p~n", [E]). + io_lib:format("~tp~n", [E]). %% %% Local functions |