c.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 695 行 · 第 1/2 页
ERL
695 行
%% ``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 via the world wide web 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.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(c).%% Utilities to use from shell.-export([help/0,lc/1,c/1,c/2,nc/1,nc/2, nl/1,l/1,i/0,i/1,ni/0, y/1, y/2, lc_batch/0, lc_batch/1, i/3,pid/3,m/0,m/1, bt/1, q/0, erlangrc/0,erlangrc/1,bi/1, flush/0, regs/0, nregs/0,pwd/0,ls/0,ls/1,cd/1,memory/1,memory/0, xm/1]).-export([display_info/1]).-export([appcall/4]).-import(lists, [reverse/1,flatten/1,sublist/3,sort/1,keysearch/3,keysort/2, concat/1,max/1,min/1,foreach/2,foldl/3,flatmap/2]).-import(io, [format/1, format/2]).help() -> format("bt(Pid) -- stack backtrace for a process\n" "c(File) -- compile and load code in <File>\n" "cd(Dir) -- change working directory\n" "flush() -- flush any messages sent to the shell\n" "help() -- help info\n" "i() -- information about the system\n" "ni() -- information about the networked system\n" "i(X,Y,Z) -- information about pid <X,Y,Z>\n" "l(Module) -- load or reload module\n" "lc([File]) -- compile a list of Erlang modules\n" "ls() -- list files in the current directory\n" "ls(Dir) -- list files in directory <Dir>\n" "m() -- which modules are loaded\n" "m(Mod) -- information about module <Mod>\n" "memory() -- memory allocation information\n" "memory(T) -- memory allocation information of type <T>\n" "nc(File) -- compile and load code in <File> on all nodes\n" "nl(Module) -- load module on all nodes\n" "pid(X,Y,Z) -- convert X,Y,Z to a Pid\n" "pwd() -- print working directory\n" "q() -- quit - shorthand for init:stop()\n" "regs() -- information about registered processes\n" "nregs() -- information about all registered processes\n" "xm(M) -- cross reference check a module\n" "y(File) -- generate a Yecc parser\n").%% c(FileName)%% Compile a file/module.c(File) -> c(File, []).c(File, Opts0) when is_list(Opts0) -> Opts = [report_errors,report_warnings|Opts0], case compile:file(File, Opts) of {ok,Mod} -> %Listing file. machine_load(Mod, File, Opts); {ok,Mod,_Ws} -> %Warnings maybe turned on. machine_load(Mod, File, Opts); Other -> %Errors go here Other end;c(File, Opt) -> c(File, [Opt]).%%% Obtain the 'outdir' option from the argument. Return "." if no%%% such option was given.outdir([]) -> ".";outdir([Opt|Rest]) -> case Opt of {outdir, D} -> D; _ -> outdir(Rest) end.%%% We have compiled File with options Opts. Find out where the%%% output file went to, and load it.machine_load(Mod, File, Opts) -> Dir = outdir(Opts), File2 = filename:join(Dir, filename:basename(File, ".erl")), case compile:output_generated(Opts) of true -> Base = packages:last(Mod), case filename:basename(File, ".erl") of Base -> code:purge(Mod), check_load(code:load_abs(File2,Mod), Mod); _OtherMod -> format("** Module name '~p' does not match file name '~p' **~n", [Mod,File]), {error, badfile} end; false -> format("** Warning: No object file created - nothing loaded **~n", []), ok end.%%% This function previously warned if the loaded module was%%% loaded from some other place than current directory.%%% Now, loading from other than current directory is supposed to work.%%% so this function does nothing special.check_load({error, R}, _) -> {error, R};check_load(_, X) -> {ok, X}.%% Compile a list of modules%% enables the nice unix shell cmd%% erl -s c lc f1 f2 f3 @d c1=v1 @c2 @i IDir @o ODir -s erlang halt%% to compile files f1.erl , f2.erl ....... from a unix shell%% with constant c2 defined, c1=v1 (v1 must be a term!), include dir%% IDir, outdir ODir.lc(Args) -> case catch split(Args, [], []) of error -> error; {Opts, Files} -> COpts = [report_errors, report_warnings | reverse(Opts)], foreach(fun(File) -> compile:file(File, COpts) end, reverse(Files)) end.%%% lc_batch/1 works like lc/1, but halts afterwards, with appropriate%%% exit code. This is meant to be called by "erl -compile".lc_batch() -> io:format("Error: no files to compile~n"), halt(1).lc_batch(Args) -> case catch split(Args, [], []) of error -> halt(1); {Opts, Files} -> COpts = [report_errors, report_warnings | reverse(Opts)], Res = [compile:file(File, COpts) || File <- reverse(Files)], case lists:member(error, Res) of true -> halt(1); false -> halt(0) end end.split(['@i', Dir | T], Opts, Files) -> split(T, [{i, atom_to_list(Dir)} | Opts], Files);split(['@o', Dir | T], Opts, Files) -> split(T, [{outdir, atom_to_list(Dir)} | Opts], Files);split(['@d', Def | T], Opts, Files) -> split(T, [split_def(atom_to_list(Def), []) | Opts], Files);split([File | T], Opts, Files) -> split(T, Opts, [File | Files]);split([], Opts, Files) -> {Opts, Files}.split_def([$= | T], Res) -> {d, list_to_atom(reverse(Res)),make_term(T)};split_def([H | T], Res) -> split_def(T, [H | Res]);split_def([], Res) -> {d, list_to_atom(reverse(Res))}.make_term(Str) -> case erl_scan:string(Str) of {ok, Tokens, _} -> case erl_parse:parse_term(Tokens ++ [{dot, 1}]) of {ok, Term} -> Term; {error, {_,_,Reason}} -> io:format("~s: ~s~n", [Reason, Str]), throw(error) end; {error, {_,_,Reason}, _} -> io:format("~s: ~s~n", [Reason, Str]), throw(error) end.nc(File) -> nc(File, []).nc(File, Opts0) when is_list(Opts0) -> Opts = Opts0 ++ [report_errors, report_warnings], case compile:file(File, Opts) of {ok,Mod} -> Fname = concat([File, code:objfile_extension()]), case file:read_file(Fname) of {ok,Bin} -> rpc:eval_everywhere(code,load_binary,[Mod,Fname,Bin]), {ok,Mod}; Other -> Other end; Other -> %Errors go here Other end;nc(File, Opt) when is_atom(Opt) -> nc(File, [Opt]).%% l(Mod)%% Reload module Mod from file of same namel(Mod) -> code:purge(Mod), code:load_file(Mod).%% Network version of l/1nl(Mod) -> case code:get_object_code(Mod) of {_Module, Bin, Fname} -> rpc:eval_everywhere(code,load_binary,[Mod,Fname,Bin]); Other -> Other end.i() -> i(processes()).ni() -> i(all_procs()).i(Ps) -> i(Ps, length(Ps)).i(Ps, N) when N =< 100 -> iformat("Pid", "Initial Call", "Heap", "Reds", "Msgs"), iformat("Registered", "Current Function", "Stack", "", ""), {R,M,H,S} = foldl(fun(Pid, {R0,M0,H0,S0}) -> {A,B,C,D} = display_info(Pid), {R0+A,M0+B,H0+C,S0+D} end, {0,0,0,0}, Ps), iformat("Total", "", w(H), w(R), w(M)), iformat("", "", w(S), "", "");i(Ps, N) -> iformat("Pid", "Initial Call", "Heap", "Reds", "Msgs"), iformat("Registered", "Current Function", "Stack", "", ""), paged_i(Ps, {0,0,0,0}, N, 50).paged_i([], {R,M,H,S}, _, _) -> iformat("Total", "", w(H), w(R), w(M)), iformat("", "", w(S), "", "");paged_i(Ps, Acc, N, Page) -> {Pids, Rest, N1} = if N > Page -> {L1,L2} = lists:split(Page, Ps), {L1,L2,N-Page}; true -> {Ps, [], 0} end, NewAcc = foldl(fun(Pid, {R,M,H,S}) -> {A,B,C,D} = display_info(Pid), {R+A,M+B,H+C,S+D} end, Acc, Pids), case Rest of [_|_] -> choice(fun() -> paged_i(Rest, NewAcc, N1, Page) end); [] -> paged_i([], NewAcc, 0, Page) end.choice(F) -> case get_line('(c)ontinue (q)uit -->', "c\n") of "c\n" -> F(); "q\n" -> quit; _ -> choice(F) end. get_line(P, Default) -> case io:get_line(P) of "\n" -> Default; L -> L end.mfa_string(Fun) when is_function(Fun) -> {module,M} = erlang:fun_info(Fun, module), {name,F} = erlang:fun_info(Fun, name), {arity,A} = erlang:fun_info(Fun, arity), mfa_string({M,F,A});mfa_string({M,F,A}) -> io_lib:format("~w:~w/~w", [M,F,A]);mfa_string(X) -> w(X).display_info(Pid) -> case pinfo(Pid) of undefined -> {0,0,0,0}; Info -> Call = initial_call(Info), Curr = case fetch(current_function, Info) of {Mod,F,Args} when is_list(Args) -> {Mod,F,length(Args)}; Other -> Other end, Reds = fetch(reductions, Info), LM = length(fetch(messages, Info)), HS = fetch(heap_size, Info), SS = fetch(stack_size, Info), iformat(w(Pid), mfa_string(Call), w(HS), w(Reds), w(LM)), iformat(case fetch(registered_name, Info) of 0 -> ""; X -> w(X) end, mfa_string(Curr), w(SS), "", ""), {Reds, LM, HS, SS} end.%% We have to do some assumptions about the initial call.%% If the initial call is proc_lib:init_p/3,5 we can find more information%% calling the function proc_lib:initial_call/1.initial_call(Info) -> case fetch(initial_call, Info) of {proc_lib, init_p, _} -> proc_lib:translate_initial_call(Info); ICall -> ICall end.iformat(A1, A2, A3, A4, A5) -> format("~-21s ~-33s ~8s ~8s ~4s~n", [A1,A2,A3,A4,A5]).all_procs() -> case is_alive() of true -> flatmap(fun (N) -> rpc:call(N,erlang,processes,[]) end, [node()|nodes()]);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?