aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib/src')
-rw-r--r--lib/stdlib/src/Makefile17
-rw-r--r--lib/stdlib/src/array.erl16
-rw-r--r--lib/stdlib/src/c.erl4
-rw-r--r--lib/stdlib/src/dets_v8.erl40
-rw-r--r--lib/stdlib/src/edlin.erl46
-rw-r--r--lib/stdlib/src/edlin_expand.erl49
-rw-r--r--lib/stdlib/src/epp.erl265
-rw-r--r--lib/stdlib/src/erl_lint.erl114
-rw-r--r--lib/stdlib/src/escript.erl84
-rw-r--r--lib/stdlib/src/file_sorter.erl34
-rw-r--r--lib/stdlib/src/filelib.erl22
-rw-r--r--lib/stdlib/src/gen_fsm.erl7
-rw-r--r--lib/stdlib/src/io_lib.erl14
-rw-r--r--lib/stdlib/src/otp_internal.erl4
-rw-r--r--lib/stdlib/src/qlc.erl159
-rw-r--r--lib/stdlib/src/qlc_pt.erl32
-rw-r--r--lib/stdlib/src/re.erl71
-rw-r--r--lib/stdlib/src/shell.erl104
-rw-r--r--lib/stdlib/src/shell_default.erl11
-rw-r--r--lib/stdlib/src/supervisor.erl59
-rw-r--r--lib/stdlib/src/sys.erl11
21 files changed, 664 insertions, 499 deletions
diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile
index 68708d6b02..237818c08b 100644
--- a/lib/stdlib/src/Makefile
+++ b/lib/stdlib/src/Makefile
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1996-2010. 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%
#
@@ -146,6 +146,9 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
# FLAGS
# ----------------------------------------------------
+ifeq ($(NATIVE_LIBS_ENABLED),yes)
+ERL_COMPILE_FLAGS += +native
+endif
ERL_COMPILE_FLAGS += -I../include -I../../kernel/include
# ----------------------------------------------------
@@ -173,8 +176,8 @@ $(BOOTSTRAP_COMPILER)/ebin/erl_parse.beam: erl_parse.yrl
$(ERLC) -o $(BOOTSTRAP_COMPILER)/egen erl_parse.yrl
$(ERLC) -o $(BOOTSTRAP_COMPILER)/ebin $(BOOTSTRAP_COMPILER)/egen/erl_parse.erl
-#$(BOOTSTRAP_COMPILER)/ebin/erl_lint.beam: erl_lint.erl
-# $(ERLC) -o $(BOOTSTRAP_COMPILER)/ebin erl_lint.erl
+$(BOOTSTRAP_TOP)/lib/stdlib/egen/erl_parse.erl: erl_parse.yrl
+ $(ERLC) $(YRL_FLAGS) -o$(BOOTSTRAP_TOP)/lib/stdlib/egen erl_parse.yrl
$(BOOTSTRAP_COMPILER)/ebin/%.beam: %.erl
$(ERLC) -o $(BOOTSTRAP_COMPILER)/ebin $<
diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl
index 295eeac221..83576c9fd3 100644
--- a/lib/stdlib/src/array.erl
+++ b/lib/stdlib/src/array.erl
@@ -741,11 +741,17 @@ set_get_test_() ->
?_assert(array:get(0, set(0, 42, set(0, 17, new()))) =:= 42),
- ?_assert(array:get(0, reset(0, new())) =:= undefined),
- ?_assert(array:get(0, reset(0, set(0, 17, new()))) =:= undefined),
- ?_assert(array:get(0, reset(0, new({default,42}))) =:= 42),
- ?_assert(array:get(0, reset(0, set(0, 17, new({default,42}))))
- =:= 42)
+ ?_assertError(badarg, array:get(0, reset(11, new([{size,10}])))),
+ ?_assertError(badarg, array:get(0, reset(-1, new([{size,10}])))),
+ ?_assert(array:get(0, reset(0, new())) =:= undefined),
+ ?_assert(array:get(0, reset(0, set(0, 17, new()))) =:= undefined),
+ ?_assert(array:get(0, reset(9, set(9, 17, new()))) =:= undefined),
+ ?_assert(array:get(0, reset(11, set(11, 17, new()))) =:= undefined),
+ ?_assert(array:get(0, reset(11, set(12, 17, new()))) =:= undefined),
+ ?_assert(array:get(0, reset(1, set(12, 17, new()))) =:= undefined),
+ ?_assert(array:get(0, reset(11, new())) =:= undefined),
+ ?_assert(array:get(0, reset(0, set(0, 17, new({default,42})))) =:= 42),
+ ?_assert(array:get(0, reset(0, new({default,42}))) =:= 42)
].
-endif.
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index 9e4cec5db2..433833e233 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -197,7 +197,9 @@ 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()]),
+ Dir = outdir(Opts),
+ Obj = filename:basename(File, ".erl") ++ code:objfile_extension(),
+ Fname = filename:join(Dir, Obj),
case file:read_file(Fname) of
{ok,Bin} ->
rpc:eval_everywhere(code,load_binary,[Mod,Fname,Bin]),
diff --git a/lib/stdlib/src/dets_v8.erl b/lib/stdlib/src/dets_v8.erl
index b24df02882..1f9f84cd27 100644
--- a/lib/stdlib/src/dets_v8.erl
+++ b/lib/stdlib/src/dets_v8.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2001-2010. 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%
%%
-module(dets_v8).
@@ -1053,14 +1053,14 @@ wl([{_Seq, {insert, Object}} | Cs], Type, _Del, Lookup, _I, _Objs)
wl(Cs, Type, delete, Lookup, 1, [{Object,-1}]);
wl([{_Seq, {insert, Object}} | Cs], Type, Del, Lookup, _I, Objs) ->
NObjs =
- case lists:keysearch(Object, 1, Objs) of
- {value, {_, 0}} ->
+ case lists:keyfind(Object, 1, Objs) of
+ {_, 0} ->
lists:keyreplace(Object, 1, Objs, {Object,-1});
- {value, {_, _C}} when Type =:= bag -> % C =:= 1; C =:= -1
+ {_, _C} when Type =:= bag -> % C =:= 1; C =:= -1
Objs;
- {value, {_, C}} when C < 0 -> % when Type =:= duplicate_bag
+ {_, C} when C < 0 -> % when Type =:= duplicate_bag
lists:keyreplace(Object, 1, Objs, {Object,C-1});
- {value, {_, C}} -> % when C > 0, Type =:= duplicate_bag
+ {_, C} -> % when C > 0, Type =:= duplicate_bag
lists:keyreplace(Object, 1, Objs, {Object,C+1});
false when Del =:= delete ->
[{Object, -1} | Objs];
@@ -1258,8 +1258,8 @@ eval_slot(Head, TrySize, Pos, WLs, L, LU) ->
find_key(Head, Pos, NextPos, Size, Term, Key, WLs, L, LU).
find_key(Head, Pos, NextPos, Size, Term, Key, WLs, L, LU) ->
- case lists:keysearch(Key, 1, WLs) of
- {value, {_, {Delete, LookUp, Objects}} = WL} ->
+ case lists:keyfind(Key, 1, WLs) of
+ {_, {Delete, LookUp, Objects}} = WL ->
NWLs = lists:delete(WL, WLs),
{NewObjects, NL, LUK} = eval_object(Size, Term, Delete, LookUp,
Objects, Head, Pos, L, []),
@@ -1297,30 +1297,30 @@ eval_key(Key, Delete, LookUp, Objects, Head, Pos, WLs, L, LU, LUK) ->
%% All objects in Objects have the key Key.
eval_object(Size, Term, Delete, LookUp, Objects, Head, Pos, L, LU) ->
Type = Head#head.type,
- case lists:keysearch(Term, 1, Objects) of
- {value, {_Object, N}} when N =:= 0 ->
+ case lists:keyfind(Term, 1, Objects) of
+ {_Object, N} when N =:= 0 ->
L1 = [{delete,Pos,Size} | L],
{Objects, L1, LU};
- {value, {_Object, N}} when N < 0, Type =:= set ->
+ {_Object, N} when N < 0, Type =:= set ->
L1 = [{old,Pos} | L],
wl_lookup(LookUp, Objects, Term, L1, LU);
- {value, {Object, _N}} when Type =:= bag -> % when N =:= 1; N =:= -1
+ {Object, _N} when Type =:= bag -> % when N =:= 1; N =:= -1
L1 = [{old,Pos} | L],
Objects1 = lists:keydelete(Object, 1, Objects),
wl_lookup(LookUp, Objects1, Term, L1, LU);
- {value, {Object, N}} when N < 0, Type =:= duplicate_bag ->
+ {Object, N} when N < 0, Type =:= duplicate_bag ->
L1 = [{old,Pos} | L],
Objects1 = lists:keyreplace(Object, 1, Objects, {Object,N+1}),
wl_lookup(LookUp, Objects1, Term, L1, LU);
- {value, {_Object, N}} when N > 0, Type =:= duplicate_bag ->
+ {_Object, N} when N > 0, Type =:= duplicate_bag ->
L1 = [{old,Pos} | L],
wl_lookup(LookUp, Objects, Term, L1, LU);
false when Type =:= set, Delete =:= delete ->
- case lists:keysearch(-1, 2, Objects) of
+ case lists:keyfind(-1, 2, Objects) of
false -> % no inserted object, perhaps deleted objects
L1 = [{delete,Pos,Size} | L],
{[], L1, LU};
- {value, {Term2,-1}} ->
+ {Term2, -1} ->
Bin2 = term_to_binary(Term2),
NSize = byte_size(Bin2),
Overwrite =
diff --git a/lib/stdlib/src/edlin.erl b/lib/stdlib/src/edlin.erl
index 31a653bda0..6cb441dbed 100644
--- a/lib/stdlib/src/edlin.erl
+++ b/lib/stdlib/src/edlin.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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%
%%
-module(edlin).
@@ -30,8 +30,6 @@
-import(lists, [reverse/1, reverse/2]).
-%-import([nthtail/2, keysearch/3, prefix/2]).
-
-export([over_word/3]).
@@ -281,12 +279,32 @@ do_op(_, Bef, Aft, Rs) ->
%% Step over word/non-word characters pushing the stepped over ones on
%% the stack.
-over_word([C|Cs], Stack, N) ->
+
+over_word(Cs, Stack, N) ->
+ L = length([1 || $\' <- Cs]),
+ case L rem 2 of
+ 0 ->
+ over_word1(Cs, Stack, N);
+ 1 ->
+ until_quote(Cs, Stack, N)
+ end.
+
+until_quote([$\'|Cs], Stack, N) ->
+ {Cs, [$\'|Stack], N+1};
+until_quote([C|Cs], Stack, N) ->
+ until_quote(Cs, [C|Stack], N+1).
+
+over_word1([$\'=C|Cs], Stack, N) ->
+ until_quote(Cs, [C|Stack], N+1);
+over_word1(Cs, Stack, N) ->
+ over_word2(Cs, Stack, N).
+
+over_word2([C|Cs], Stack, N) ->
case word_char(C) of
- true -> over_word(Cs, [C|Stack], N+1);
+ true -> over_word2(Cs, [C|Stack], N+1);
false -> {[C|Cs],Stack,N}
end;
-over_word([], Stack, N) when is_integer(N) ->
+over_word2([], Stack, N) when is_integer(N) ->
{[],Stack,N}.
over_non_word([C|Cs], Stack, N) ->
@@ -456,8 +474,8 @@ prompt({line,Pbs,_,_}) ->
%% case erlang:module_loaded(Mod) of
%% true ->
%% L = apply(Mod, module_info, []),
-%% case keysearch(exports, 1, L) of
-%% {value, {_, Exports}} ->
+%% case lists:keyfind(exports, 1, L) of
+%% {_, Exports} ->
%% match(FuncPrefix, Exports, "(");
%% _ ->
%% no
@@ -473,7 +491,7 @@ prompt({line,Pbs,_,_}) ->
%% print_matches(Matches),
%% no;
%% {partial, Str} ->
-%% case nthtail(length(Prefix), Str) of
+%% case lists:nthtail(length(Prefix), Str) of
%% [] ->
%% print_matches(Matches),
%% {yes, []};
@@ -481,7 +499,7 @@ prompt({line,Pbs,_,_}) ->
%% {yes, Remain}
%% end;
%% {complete, Str} ->
-%% {yes, nthtail(length(Prefix), Str) ++ Extra};
+%% {yes, lists:nthtail(length(Prefix), Str) ++ Extra};
%% no ->
%% no
%% end.
diff --git a/lib/stdlib/src/edlin_expand.erl b/lib/stdlib/src/edlin_expand.erl
index 7ed76a6b09..516c0aa30b 100644
--- a/lib/stdlib/src/edlin_expand.erl
+++ b/lib/stdlib/src/edlin_expand.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2010. 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%
%%
-module(edlin_expand).
@@ -46,23 +46,38 @@ expand_module_name(Prefix) ->
match(Prefix, code:all_loaded(), ":").
expand_function_name(ModStr, FuncPrefix) ->
- Mod = list_to_atom(ModStr),
- case erlang:module_loaded(Mod) of
- true ->
- L = Mod:module_info(),
- case lists:keyfind(exports, 1, L) of
- {_, Exports} ->
- match(FuncPrefix, Exports, "(");
- _ ->
- {no, [], []}
- end;
- false ->
+ case to_atom(ModStr) of
+ {ok, Mod} ->
+ case erlang:module_loaded(Mod) of
+ true ->
+ L = Mod:module_info(),
+ case lists:keyfind(exports, 1, L) of
+ {_, Exports} ->
+ match(FuncPrefix, Exports, "(");
+ _ ->
+ {no, [], []}
+ end;
+ false ->
+ {no, [], []}
+ end;
+ error ->
{no, [], []}
end.
+%% if it's a quoted atom, atom_to_list/1 will do the wrong thing.
+to_atom(Str) ->
+ case erl_scan:string(Str) of
+ {ok, [{atom,_,A}], _} ->
+ {ok, A};
+ _ ->
+ error
+ end.
+
match(Prefix, Alts, Extra) ->
Len = length(Prefix),
- Matches = [{S, A} || {H, A} <- Alts, prefix(Prefix, S=atom_to_list(H))],
+ Matches = lists:sort(
+ [{S, A} || {H, A} <- Alts,
+ prefix(Prefix, S=hd(io_lib:fwrite("~w",[H])))]),
case longest_common_head([N || {N, _} <- Matches]) of
{partial, []} ->
{no, [], Matches}; % format_matches(Matches)};
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 8b702c005b..424aed3d2e 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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%
-module(epp).
@@ -111,18 +111,24 @@ format_error({bad,W}) ->
io_lib:format("badly formed '~s'", [W]);
format_error({call,What}) ->
io_lib:format("illegal macro call '~s'",[What]);
-format_error({undefined,M}) ->
- io_lib:format("undefined macro '~w'", [M]);
+format_error({undefined,M,none}) ->
+ io_lib:format("undefined macro '~s'", [M]);
+format_error({undefined,M,A}) ->
+ io_lib:format("undefined macro '~s/~p'", [M,A]);
format_error({depth,What}) ->
io_lib:format("~s too deep",[What]);
format_error({mismatch,M}) ->
- io_lib:format("argument mismatch for macro '~w'", [M]);
+ io_lib:format("argument mismatch for macro '~s'", [M]);
format_error({arg_error,M}) ->
- io_lib:format("badly formed argument for macro '~w'", [M]);
+ io_lib:format("badly formed argument for macro '~s'", [M]);
format_error({redefine,M}) ->
- io_lib:format("redefining macro '~w'", [M]);
-format_error({circular,M}) ->
- io_lib:format("circular macro '~w'", [M]);
+ io_lib:format("redefining macro '~s'", [M]);
+format_error({redefine_predef,M}) ->
+ io_lib:format("redefining predefined macro '~s'", [M]);
+format_error({circular,M,none}) ->
+ io_lib:format("circular macro '~s'", [M]);
+format_error({circular,M,A}) ->
+ io_lib:format("circular macro '~s/~p'", [M,A]);
format_error({include,W,F}) ->
io_lib:format("can't find include ~s \"~s\"", [W,F]);
format_error({illegal,How,What}) ->
@@ -258,18 +264,23 @@ user_predef([{M,Val,redefine}|Pdm], Ms) when is_atom(M) ->
user_predef(Pdm, dict:store({atom,M}, {none,Exp}, Ms));
user_predef([{M,Val}|Pdm], Ms) when is_atom(M) ->
case dict:find({atom,M}, Ms) of
- {ok,_Def} ->
+ {ok,_Defs} when is_list(_Defs) -> %% User defined macros
{error,{redefine,M}};
+ {ok,_Def} -> %% Predefined macros
+ {error,{redefine_predef,M}};
error ->
Exp = erl_parse:tokens(erl_parse:abstract(Val)),
- user_predef(Pdm, dict:store({atom,M}, {none,Exp}, Ms))
+ user_predef(Pdm, dict:store({atom,M}, [{none, {none,Exp}}], Ms))
end;
user_predef([M|Pdm], Ms) when is_atom(M) ->
case dict:find({atom,M}, Ms) of
- {ok,_Def} ->
+ {ok,_Defs} when is_list(_Defs) -> %% User defined macros
{error,{redefine,M}};
+ {ok,_Def} -> %% Predefined macros
+ {error,{redefine_predef,M}};
error ->
- user_predef(Pdm, dict:store({atom,M}, {none,[{atom,1,true}]}, Ms))
+ user_predef(Pdm,
+ dict:store({atom,M}, [{none, {none,[{atom,1,true}]}}], Ms))
end;
user_predef([Md|_Pdm], _Ms) -> {error,{bad,Md}};
user_predef([], Ms) -> {ok,Ms}.
@@ -476,57 +487,56 @@ scan_extends(_Ts, _As, Ms) -> Ms.
%% scan_define(Tokens, DefineToken, From, EppState)
-scan_define([{'(',_Lp},{atom,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St) ->
+scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St)
+ when Type =:= atom; Type =:= var ->
case dict:find({atom,M}, St#epp.macs) of
- {ok,_OldDef} ->
- epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
- wait_req_scan(St);
- error ->
- scan_define_cont(From, St,
- {atom, M},
- {none,macro_expansion(Toks)})
- end;
-scan_define([{'(',_Lp},{atom,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
- epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
- wait_req_scan(St);
- error ->
- case catch macro_pars(Toks, []) of
- {ok, {As, Me}} ->
- scan_define_cont(From, St,
- {atom, M},
- {As, Me});
- _ ->
- epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
- wait_req_scan(St)
- end
- end;
-scan_define([{'(',_Lp},{var,_Lm,M}=Mac,{',',_Lc}|Toks], _Def, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_OldDef} ->
- epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
- wait_req_scan(St);
- error ->
- scan_define_cont(From, St,
- {atom, M},
- {none,macro_expansion(Toks)})
+ {ok, Defs} when is_list(Defs) ->
+ %% User defined macros: can be overloaded
+ case proplists:is_defined(none, Defs) of
+ true ->
+ epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
+ wait_req_scan(St);
+ false ->
+ scan_define_cont(From, St,
+ {atom, M},
+ {none, {none,macro_expansion(Toks)}})
+ end;
+ {ok, _PreDef} ->
+ %% Predefined macros: cannot be overloaded
+ epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
+ wait_req_scan(St);
+ error ->
+ scan_define_cont(From, St,
+ {atom, M},
+ {none, {none,macro_expansion(Toks)}})
end;
-scan_define([{'(',_Lp},{var,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St) ->
- case dict:find({atom,M}, St#epp.macs) of
- {ok,_Def} ->
- epp_reply(From, {error,{loc(Mac),epp,{redefine,M}}}),
- wait_req_scan(St);
- error ->
- case catch macro_pars(Toks, []) of
- {ok, {As, Me}} ->
- scan_define_cont(From, St,
- {atom, M},
- {As, Me});
- _ ->
- epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
- wait_req_scan(St)
- end
+scan_define([{'(',_Lp},{Type,_Lm,M}=Mac,{'(',_Lc}|Toks], Def, From, St)
+ when Type =:= atom; Type =:= var ->
+ case catch macro_pars(Toks, []) of
+ {ok, {As,Me}} ->
+ Len = length(As),
+ case dict:find({atom,M}, St#epp.macs) of
+ {ok, Defs} when is_list(Defs) ->
+ %% User defined macros: can be overloaded
+ case proplists:is_defined(Len, Defs) of
+ true ->
+ epp_reply(From,{error,{loc(Mac),epp,{redefine,M}}}),
+ wait_req_scan(St);
+ false ->
+ scan_define_cont(From, St, {atom, M},
+ {Len, {As, Me}})
+ end;
+ {ok, _PreDef} ->
+ %% Predefined macros: cannot be overloaded
+ %% (There are currently no predefined F(...) macros.)
+ epp_reply(From, {error,{loc(Mac),epp,{redefine_predef,M}}}),
+ wait_req_scan(St);
+ error ->
+ scan_define_cont(From, St, {atom, M}, {Len, {As, Me}})
+ end;
+ _ ->
+ epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
+ wait_req_scan(St)
end;
scan_define(_Toks, Def, From, St) ->
epp_reply(From, {error,{loc(Def),epp,{bad,define}}}),
@@ -541,13 +551,17 @@ scan_define(_Toks, Def, From, St) ->
%%% the information from St#epp.uses is traversed, and if a circularity
%%% is detected, an error message is thrown.
-scan_define_cont(F, St, M, Def) ->
- Ms = dict:store(M, Def, St#epp.macs),
- U = dict:store(M, macro_uses(Def), St#epp.uses),
- scan_toks(F, St#epp{uses=U, macs=Ms}).
+scan_define_cont(F, St, M, {Arity, Def}) ->
+ Ms = dict:append_list(M, [{Arity, Def}], St#epp.macs),
+ try dict:append_list(M, [{Arity, macro_uses(Def)}], St#epp.uses) of
+ U ->
+ scan_toks(F, St#epp{uses=U, macs=Ms})
+ catch
+ {error, Line, Reason} ->
+ epp_reply(F, {error,{Line,epp,Reason}}),
+ wait_req_scan(St)
+ end.
-macro_uses(undefined) ->
- undefined;
macro_uses({_Args, Tokens}) ->
Uses0 = macro_ref(Tokens),
lists:usort(Uses0).
@@ -556,31 +570,25 @@ macro_ref([]) ->
[];
macro_ref([{'?', _}, {'?', _} | Rest]) ->
macro_ref(Rest);
-macro_ref([{'?', _}, {atom, _, A} | Rest]) ->
- [{atom, A} | macro_ref(Rest)];
-macro_ref([{'?', _}, {var, _, A} | Rest]) ->
- [{atom, A} | macro_ref(Rest)];
+macro_ref([{'?', _}, {atom, Lm, A} | Rest]) ->
+ Arity = count_args(Rest, Lm, A),
+ [{{atom, A}, Arity} | macro_ref(Rest)];
+macro_ref([{'?', _}, {var, Lm, A} | Rest]) ->
+ Arity = count_args(Rest, Lm, A),
+ [{{atom, A}, Arity} | macro_ref(Rest)];
macro_ref([_Token | Rest]) ->
macro_ref(Rest).
-all_macro_uses(D0) ->
- L = dict:to_list(D0),
- D = dict:new(),
- add_macro_uses(L, D).
-
-add_macro_uses([], D) ->
- D;
-add_macro_uses([{Key, Def} | Rest], D0) ->
- add_macro_uses(Rest, dict:store(Key, macro_uses(Def), D0)).
-
%% scan_undef(Tokens, UndefToken, From, EppState)
scan_undef([{'(',_Llp},{atom,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From, St) ->
- scan_toks(From, St#epp{macs=dict:erase({atom,M}, St#epp.macs),
- uses=all_macro_uses(St#epp.macs)});
+ Macs = dict:erase({atom,M}, St#epp.macs),
+ Uses = dict:erase({atom,M}, St#epp.uses),
+ scan_toks(From, St#epp{macs=Macs, uses=Uses});
scan_undef([{'(',_Llp},{var,_Lm,M},{')',_Lrp},{dot,_Ld}], _Undef, From,St) ->
- scan_toks(From, St#epp{macs=dict:erase({atom,M}, St#epp.macs),
- uses=all_macro_uses(St#epp.macs)});
+ Macs = dict:erase({atom,M}, St#epp.macs),
+ Uses = dict:erase({atom,M}, St#epp.uses),
+ scan_toks(From, St#epp{macs=Macs, uses=Uses});
scan_undef(_Toks, Undef, From, St) ->
epp_reply(From, {error,{loc(Undef),epp,{bad,undef}}}),
wait_req_scan(St).
@@ -819,42 +827,57 @@ expand_macros(Type, MacT, M, Toks, Ms0) ->
%% (Type will always be 'atom')
{Ms, U} = Ms0,
Lm = loc(MacT),
- check_uses([{Type,M}], [], U, Lm),
Tinfo = element(2, MacT),
- case dict:find({Type,M}, Ms) of
+ case expand_macro1(Type, Lm, M, Toks, Ms) of
{ok,{none,Exp}} ->
- expand_macros(expand_macro(Exp, Tinfo, Toks, dict:new()), Ms0);
+ check_uses([{{Type,M}, none}], [], U, Lm),
+ Toks1 = expand_macros(expand_macro(Exp, Tinfo, [], dict:new()), Ms0),
+ expand_macros(Toks1++Toks, Ms0);
{ok,{As,Exp}} ->
+ check_uses([{{Type,M}, length(As)}], [], U, Lm),
{Bs,Toks1} = bind_args(Toks, Lm, M, As, dict:new()),
- %%io:format("Bound arguments to macro ~w (~w)~n", [M,Bs]),
- expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), Ms0);
- {ok,undefined} ->
- throw({error,Lm,{undefined,M}});
- error ->
- throw({error,Lm,{undefined,M}})
+ expand_macros(expand_macro(Exp, Tinfo, Toks1, Bs), Ms0)
+ end.
+
+expand_macro1(Type, Lm, M, Toks, Ms) ->
+ Arity = count_args(Toks, Lm, M),
+ case dict:find({Type,M}, Ms) of
+ error -> %% macro not found
+ throw({error,Lm,{undefined,M,Arity}});
+ {ok, undefined} -> %% Predefined macro without definition
+ throw({error,Lm,{undefined,M,Arity}});
+ {ok, [{none, Def}]} ->
+ {ok, Def};
+ {ok, Defs} when is_list(Defs) ->
+ case proplists:get_value(Arity, Defs) of
+ undefined ->
+ throw({error,Lm,{mismatch,M}});
+ Def ->
+ {ok, Def}
+ end;
+ {ok, PreDef} -> %% Predefined macro
+ {ok, PreDef}
end.
-check_uses(undefined, _Anc, _U, _Lm) ->
- ok;
check_uses([], _Anc, _U, _Lm) ->
ok;
check_uses([M|Rest], Anc, U, Lm) ->
case lists:member(M, Anc) of
true ->
- {_, Name} = M,
- throw({error,Lm,{circular,Name}});
+ {{_, Name},Arity} = M,
+ throw({error,Lm,{circular,Name,Arity}});
false ->
L = get_macro_uses(M, U),
check_uses(L, [M|Anc], U, Lm),
check_uses(Rest, Anc, U, Lm)
end.
-
-get_macro_uses(M, U) ->
+
+get_macro_uses({M,Arity}, U) ->
case dict:find(M, U) of
error ->
[];
{ok, L} ->
- L
+ proplists:get_value(Arity, L, proplists:get_value(none, L, []))
end.
%% Macro expansion
@@ -882,7 +905,7 @@ expand_macros([T|Ts], Ms) ->
expand_macros([], _Ms) -> [].
%% bind_args(Tokens, MacroLocation, MacroName, ArgumentVars, Bindings)
-%% Collect the arguments to a macro call and check for correct number.
+%% Collect the arguments to a macro call.
bind_args([{'(',_Llp},{')',_Lrp}|Toks], _Lm, _M, [], Bs) ->
{Bs,Toks};
@@ -890,7 +913,7 @@ bind_args([{'(',_Llp}|Toks0], Lm, M, [A|As], Bs) ->
{Arg,Toks1} = macro_arg(Toks0, [], []),
macro_args(Toks1, Lm, M, As, store_arg(Lm, M, A, Arg, Bs));
bind_args(_Toks, Lm, M, _As, _Bs) ->
- throw({error,Lm,{mismatch,M}}).
+ throw({error,Lm,{mismatch,M}}). % Cannot happen.
macro_args([{')',_Lrp}|Toks], _Lm, _M, [], Bs) ->
{Bs,Toks};
@@ -898,15 +921,39 @@ macro_args([{',',_Lc}|Toks0], Lm, M, [A|As], Bs) ->
{Arg,Toks1} = macro_arg(Toks0, [], []),
macro_args(Toks1, Lm, M, As, store_arg(Lm, M, A, Arg, Bs));
macro_args([], Lm, M, _As, _Bs) ->
- throw({error,Lm,{arg_error,M}});
+ throw({error,Lm,{arg_error,M}}); % Cannot happen.
macro_args(_Toks, Lm, M, _As, _Bs) ->
- throw({error,Lm,{mismatch,M}}).
+ throw({error,Lm,{mismatch,M}}). % Cannot happen.
store_arg(L, M, _A, [], _Bs) ->
throw({error,L,{mismatch,M}});
store_arg(_L, _M, A, Arg, Bs) ->
dict:store(A, Arg, Bs).
+%% count_args(Tokens, MacroLine, MacroName)
+%% Count the number of arguments in a macro call.
+count_args([{'(', _Llp},{')',_Lrp}|_Toks], _Lm, _M) ->
+ 0;
+count_args([{'(', _Llp},{',',_Lc}|_Toks], Lm, M) ->
+ throw({error,Lm,{arg_error,M}});
+count_args([{'(',_Llp}|Toks0], Lm, M) ->
+ {_Arg,Toks1} = macro_arg(Toks0, [], []),
+ count_args(Toks1, Lm, M, 1);
+count_args(_Toks, _Lm, _M) ->
+ none.
+
+count_args([{')',_Lrp}|_Toks], _Lm, _M, NbArgs) ->
+ NbArgs;
+count_args([{',',_Lc},{')',_Lrp}|_Toks], Lm, M, _NbArgs) ->
+ throw({error,Lm,{arg_error,M}});
+count_args([{',',_Lc}|Toks0], Lm, M, NbArgs) ->
+ {_Arg,Toks1} = macro_arg(Toks0, [], []),
+ count_args(Toks1, Lm, M, NbArgs+1);
+count_args([], Lm, M, _NbArgs) ->
+ throw({error,Lm,{arg_error,M}});
+count_args(_Toks, Lm, M, _NbArgs) ->
+ throw({error,Lm,{mismatch,M}}). % Cannot happen.
+
%% macro_arg([Tok], [ClosePar], [ArgTok]) -> {[ArgTok],[RestTok]}.
%% Collect argument tokens until we hit a ',' or a ')'. We know a
%% enough about syntax to recognise "open parentheses" and keep
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 156d68554e..91f7641af7 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -1,20 +1,20 @@
%% -*- erlang-indent-level: 4 -*-
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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%
%%
%% Do necessary checking of Erlang code.
@@ -78,7 +78,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
calls = dict:new(), %Who calls who
imported = [], %Actually imported functions
used_records=sets:new() :: set(), %Used record definitions
- used_types = sets:new() :: set() %Used type definitions
+ used_types = dict:new() :: dict() %Used type definitions
}).
%% Define the lint state record.
@@ -277,6 +277,8 @@ format_error({conflicting_behaviours,{Name,Arity},B,FirstL,FirstB}) ->
format_error({undefined_behaviour_func, {Func,Arity}, Behaviour}) ->
io_lib:format("undefined callback function ~w/~w (behaviour '~w')",
[Func,Arity,Behaviour]);
+format_error({undefined_behaviour_func, {Func,Arity,_Spec}, Behaviour}) ->
+ format_error({undefined_behaviour_func, {Func,Arity}, Behaviour});
format_error({undefined_behaviour,Behaviour}) ->
io_lib:format("behaviour ~w undefined", [Behaviour]);
format_error({undefined_behaviour_callbacks,Behaviour}) ->
@@ -288,7 +290,7 @@ format_error({ill_defined_behaviour_callbacks,Behaviour}) ->
%% --- types and specs ---
format_error({singleton_typevar, Name}) ->
io_lib:format("type variable ~w is only used once (is unbound)", [Name]);
-format_error({type_ref, {TypeName, Arity}}) ->
+format_error({undefined_type, {TypeName, Arity}}) ->
io_lib:format("type ~w~s undefined", [TypeName, gen_type_paren(Arity)]);
format_error({unused_type, {TypeName, Arity}}) ->
io_lib:format("type ~w~s is unused", [TypeName, gen_type_paren(Arity)]);
@@ -757,10 +759,11 @@ post_traversal_check(Forms, St0) ->
St7 = check_bif_clashes(Forms, St6),
St8 = check_specs_without_function(St7),
St9 = check_functions_without_spec(Forms, St8),
- StA = check_unused_types(Forms, St9),
- StB = check_untyped_records(Forms, StA),
- StC = check_on_load(StB),
- check_unused_records(Forms, StC).
+ StA = check_undefined_types(St9),
+ StB = check_unused_types(Forms, StA),
+ StC = check_untyped_records(Forms, StB),
+ StD = check_on_load(StC),
+ check_unused_records(Forms, StD).
%% check_behaviour(State0) -> State
%% Check that the behaviour attribute is valid.
@@ -786,13 +789,20 @@ behaviour_callbacks(Line, B, St0) ->
Funcs when is_list(Funcs) ->
All = all(fun({FuncName, Arity}) ->
is_atom(FuncName) andalso is_integer(Arity);
+ ({FuncName, Arity, Spec}) ->
+ is_atom(FuncName) andalso is_integer(Arity)
+ andalso is_list(Spec);
(_Other) ->
false
end,
Funcs),
+ MaybeRemoveSpec = fun({_F,_A}=FA) -> FA;
+ ({F,A,_S}) -> {F,A};
+ (Other) -> Other
+ end,
if
All =:= true ->
- {Funcs, St0};
+ {[MaybeRemoveSpec(F) || F <- Funcs], St0};
true ->
St1 = add_warning(Line,
{ill_defined_behaviour_callbacks,B},
@@ -970,6 +980,16 @@ check_undefined_functions(#lint{called=Called0,defined=Def0}=St0) ->
add_error(L, {undefined_function,NA}, St)
end, St0, Undef).
+%% check_undefined_types(State0) -> State
+
+check_undefined_types(#lint{usage=Usage,types=Def}=St0) ->
+ Used = Usage#usage.used_types,
+ UTAs = dict:fetch_keys(Used),
+ Undef = [{TA,dict:fetch(TA, Used)} || TA <- UTAs, not dict:is_key(TA, Def)],
+ foldl(fun ({TA,L}, St) ->
+ add_error(L, {undefined_type,TA}, St)
+ end, St0, Undef).
+
%% check_bif_clashes(Forms, State0) -> State
check_bif_clashes(Forms, St0) ->
@@ -1427,20 +1447,11 @@ is_pattern_expr_1({tuple,_Line,Es}) ->
all(fun is_pattern_expr/1, Es);
is_pattern_expr_1({nil,_Line}) -> true;
is_pattern_expr_1({cons,_Line,H,T}) ->
- case is_pattern_expr_1(H) of
- true -> is_pattern_expr_1(T);
- false -> false
- end;
+ is_pattern_expr_1(H) andalso is_pattern_expr_1(T);
is_pattern_expr_1({op,_Line,Op,A}) ->
- case erl_internal:arith_op(Op, 1) of
- true -> is_pattern_expr_1(A);
- false -> false
- end;
+ erl_internal:arith_op(Op, 1) andalso is_pattern_expr_1(A);
is_pattern_expr_1({op,_Line,Op,A1,A2}) ->
- case erl_internal:arith_op(Op, 2) of
- true -> all(fun is_pattern_expr/1, [A1,A2]);
- false -> false
- end;
+ erl_internal:arith_op(Op, 2) andalso all(fun is_pattern_expr/1, [A1,A2]);
is_pattern_expr_1(_Other) -> false.
%% pattern_bin([Element], VarTable, Old, BinVarTable, State) ->
@@ -1817,28 +1828,17 @@ is_gexpr({bin,_L,Fs}, RDs) ->
end, Fs);
is_gexpr({call,_L,{atom,_Lf,F},As}, RDs) ->
A = length(As),
- case erl_internal:guard_bif(F, A) of
- true -> is_gexpr_list(As, RDs);
- false -> false
- end;
+ erl_internal:guard_bif(F, A) andalso is_gexpr_list(As, RDs);
is_gexpr({call,_L,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,F}},As}, RDs) ->
A = length(As),
- case erl_internal:guard_bif(F, A) orelse is_gexpr_op(F, A) of
- true -> is_gexpr_list(As, RDs);
- false -> false
- end;
+ (erl_internal:guard_bif(F, A) orelse is_gexpr_op(F, A))
+ andalso is_gexpr_list(As, RDs);
is_gexpr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,F}]},As}, RDs) ->
is_gexpr({call,L,{remote,Lt,{atom,Lm,erlang},{atom,Lf,F}},As}, RDs);
is_gexpr({op,_L,Op,A}, RDs) ->
- case is_gexpr_op(Op, 1) of
- true -> is_gexpr(A, RDs);
- false -> false
- end;
+ is_gexpr_op(Op, 1) andalso is_gexpr(A, RDs);
is_gexpr({op,_L,Op,A1,A2}, RDs) ->
- case is_gexpr_op(Op, 2) of
- true -> is_gexpr_list([A1,A2], RDs);
- false -> false
- end;
+ is_gexpr_op(Op, 2) andalso is_gexpr_list([A1,A2], RDs);
is_gexpr(_Other, _RDs) -> false.
is_gexpr_op('andalso', 2) -> true;
@@ -2388,7 +2388,7 @@ check_type(Types, St) ->
{SeenVars, St1} = check_type(Types, dict:new(), St),
dict:fold(fun(Var, {seen_once, Line}, AccSt) ->
case atom_to_list(Var) of
- [$_|_] -> AccSt;
+ "_"++_ -> AccSt;
_ -> add_error(Line, {singleton_typevar, Var}, AccSt)
end;
(_Var, seen_multiple, AccSt) ->
@@ -2400,7 +2400,7 @@ check_type({ann_type, _L, [_Var, Type]}, SeenVars, St) ->
check_type({paren_type, _L, [Type]}, SeenVars, St) ->
check_type(Type, SeenVars, St);
check_type({remote_type, L, [{atom, _, Mod}, {atom, _, Name}, Args]},
- SeenVars, St = #lint{module=CurrentMod}) ->
+ SeenVars, #lint{module=CurrentMod} = St) ->
St1 =
case (dict:is_key({Name, length(Args)}, default_types())
orelse is_var_arity_type(Name)) of
@@ -2463,21 +2463,15 @@ check_type({type, _L, product, Args}, SeenVars, St) ->
lists:foldl(fun(T, {AccSeenVars, AccSt}) ->
check_type(T, AccSeenVars, AccSt)
end, {SeenVars, St}, Args);
-check_type({type, La, TypeName, Args}, SeenVars,
- St = #lint{types=Defs, usage=Usage}) ->
+check_type({type, La, TypeName, Args}, SeenVars, #lint{usage=Usage} = St) ->
Arity = length(Args),
- St1 =
- case dict:is_key({TypeName, Arity}, Defs) of
- true ->
- UsedTypes1 = Usage#usage.used_types,
- UsedTypes2 = sets:add_element({TypeName, Arity}, UsedTypes1),
- St#lint{usage=Usage#usage{used_types=UsedTypes2}};
- false ->
- case is_var_arity_type(TypeName) of
- true -> St;
- false -> add_error(La, {type_ref, {TypeName, Arity}}, St)
- end
- end,
+ St1 = case is_var_arity_type(TypeName) of
+ true -> St;
+ false ->
+ OldUsed = Usage#usage.used_types,
+ UsedTypes = dict:store({TypeName, Arity}, La, OldUsed),
+ St#lint{usage=Usage#usage{used_types=UsedTypes}}
+ end,
check_type({type, -1, product, Args}, SeenVars, St1).
check_record_types(Line, Name, Fields, SeenVars, St) ->
@@ -2636,7 +2630,7 @@ check_specs([FunType|Left], Arity, St0) ->
check_specs([], _Arity, St) ->
St.
-check_specs_without_function(St = #lint{module=Mod, defined=Funcs}) ->
+check_specs_without_function(#lint{module=Mod,defined=Funcs,specs=Specs}=St) ->
Fun = fun({M, F, A} = MFA, Line, AccSt) when M =:= Mod ->
case gb_sets:is_element({F, A}, Funcs) of
true -> AccSt;
@@ -2644,7 +2638,7 @@ check_specs_without_function(St = #lint{module=Mod, defined=Funcs}) ->
end;
({_M, _F, _A}, _Line, AccSt) -> AccSt
end,
- dict:fold(Fun, St, St#lint.specs).
+ dict:fold(Fun, St, Specs).
%% This generates warnings for functions without specs; if the user has
%% specified both options, we do not generate the same warnings twice.
@@ -2688,7 +2682,7 @@ check_unused_types(Forms, St = #lint{usage=Usage, types=Types}) ->
(Type, FileLine, AccSt) ->
case loc(FileLine) of
{FirstFile, _} ->
- case sets:is_element(Type, UsedTypes) of
+ case dict:is_key(Type, UsedTypes) of
true -> AccSt;
false ->
add_warning(FileLine,
@@ -3009,7 +3003,7 @@ check_old_unused_vars(Vt, Vt0, St0) ->
unused_vars(Vt, Vt0, _St0) ->
U0 = orddict:filter(fun (V, {_State,unused,_Ls}) ->
case atom_to_list(V) of
- [$_|_] -> false;
+ "_"++_ -> false;
_ -> true
end;
(_V, _How) -> false
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index 697a69b801..b2562c6169 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2007-2010. 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%
-module(escript).
@@ -139,7 +139,8 @@ start(EscriptOptions) ->
parse_and_run(File, Args, Options) ->
CheckOnly = lists:member("s", Options),
- {Source, Module, FormsOrBin, Mode} = parse_file(File, CheckOnly),
+ {Source, Module, FormsOrBin, HasRecs, Mode} =
+ parse_file(File, CheckOnly),
Mode2 =
case lists:member("d", Options) of
true ->
@@ -159,7 +160,7 @@ parse_and_run(File, Args, Options) ->
is_list(FormsOrBin) ->
case Mode2 of
interpret ->
- interpret(FormsOrBin, File, Args);
+ interpret(FormsOrBin, HasRecs, File, Args);
compile ->
case compile:forms(FormsOrBin, [report]) of
{ok, Module, BeamBin} ->
@@ -180,7 +181,8 @@ parse_and_run(File, Args, Options) ->
is_binary(FormsOrBin) ->
case Source of
archive ->
- case code:set_primary_archive(File, FormsOrBin) of
+ {ok, FileInfo} = file:read_file_info(File),
+ case code:set_primary_archive(File, FormsOrBin, FileInfo) of
ok when CheckOnly ->
case code:load_file(Module) of
{module, _} ->
@@ -245,7 +247,8 @@ parse_file(File, CheckOnly) ->
#state{mode = Mode,
source = Source,
module = Module,
- forms_or_bin = FormsOrBin} =
+ forms_or_bin = FormsOrBin,
+ has_records = HasRecs} =
case ScriptType of
archive ->
%% Archive file
@@ -259,7 +262,7 @@ parse_file(File, CheckOnly) ->
%% Source code
parse_source(S, File, Fd, StartLine, HeaderSz, CheckOnly)
end,
- {Source, Module, FormsOrBin, Mode}.
+ {Source, Module, FormsOrBin, HasRecs, Mode}.
%% Skip header and make a heuristic guess about the script type
skip_header(P, LineNo) ->
@@ -420,8 +423,7 @@ check_source(S, CheckOnly) ->
case S of
#state{n_errors = Nerrs} when Nerrs =/= 0 ->
fatal("There were compilation errors.");
- #state{exports_main = ExpMain,
- has_records = HasRecs,
+ #state{exports_main = ExpMain,
forms_or_bin = [FileForm2, ModForm2 | Forms]} ->
%% Optionally add export of main/1
Forms2 =
@@ -432,36 +434,15 @@ check_source(S, CheckOnly) ->
Forms3 = [FileForm2, ModForm2 | Forms2],
case CheckOnly of
true ->
- %% Optionally expand records
- Forms4 =
- case HasRecs of
- false -> Forms3;
- true -> erl_expand_records:module(Forms3, [])
- end,
%% Strong validation and halt
- case compile:forms(Forms4, [report,strong_validation]) of
+ case compile:forms(Forms3, [report,strong_validation]) of
{ok,_} ->
my_halt(0);
_Other ->
fatal("There were compilation errors.")
end;
false ->
- %% Basic validation before execution
- case erl_lint:module(Forms3) of
- {ok,Ws} ->
- report_warnings(Ws);
- {error,Es,Ws} ->
- report_errors(Es),
- report_warnings(Ws),
- fatal("There were compilation errors.")
- end,
- %% Optionally expand records
- Forms4 =
- case HasRecs of
- false -> Forms3;
- true -> erl_expand_records:module(Forms3, [])
- end,
- S#state{forms_or_bin = Forms4}
+ S#state{forms_or_bin = Forms3}
end
end.
@@ -494,17 +475,9 @@ epp_parse_file2(Epp, S, Forms, Parsed) ->
case Parsed of
{ok, Form} ->
case Form of
- {attribute,Ln,record,{Record,Fields}} ->
- S2 = S#state{has_records = true},
- case epp:normalize_typed_record_fields(Fields) of
- {typed, NewFields} ->
- epp_parse_file(Epp, S2,
- [{attribute, Ln, record, {Record, NewFields}},
- {attribute, Ln, type,
- {{record, Record}, Fields, []}} | Forms]);
- not_typed ->
- epp_parse_file(Epp, S2, [Form | Forms])
- end;
+ {attribute,_,record, _} ->
+ S2 = S#state{has_records = true},
+ epp_parse_file(Epp, S2, [Form | Forms]);
{attribute,Ln,mode,NewMode} ->
S2 = S#state{mode = NewMode},
if
@@ -563,8 +536,23 @@ run(Module, Args) ->
fatal(format_exception(Class, Reason))
end.
-interpret(Forms, File, Args) ->
- Dict = parse_to_dict(Forms),
+interpret(Forms, HasRecs, File, Args) ->
+ %% Basic validation before execution
+ case erl_lint:module(Forms) of
+ {ok,Ws} ->
+ report_warnings(Ws);
+ {error,Es,Ws} ->
+ report_errors(Es),
+ report_warnings(Ws),
+ fatal("There were compilation errors.")
+ end,
+ %% Optionally expand records
+ Forms2 =
+ case HasRecs of
+ false -> Forms;
+ true -> erl_expand_records:module(Forms, [])
+ end,
+ Dict = parse_to_dict(Forms2),
ArgsA = erl_parse:abstract(Args, 0),
Call = {call,0,{atom,0,main},[ArgsA]},
try
diff --git a/lib/stdlib/src/file_sorter.erl b/lib/stdlib/src/file_sorter.erl
index de9e628e22..e21a0c88f3 100644
--- a/lib/stdlib/src/file_sorter.erl
+++ b/lib/stdlib/src/file_sorter.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2001-2010. 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%
%%
-module(file_sorter).
@@ -186,7 +186,7 @@ options(Option) ->
options([{format, Format} | L], Opts) when Format =:= binary;
Format =:= term;
is_function(Format),
- is_function(Format, 1) ->
+ is_function(Format, 1) ->
options(L, Opts#opts{format = Format});
options([{format, binary_term} | L], Opts) ->
options(L, Opts#opts{format = binary_term_fun()});
@@ -419,9 +419,9 @@ culprit_found(IFun, F, FNs, W, L, I, [_Size | BT]) ->
IFun(close),
check_files(FNs, W, [{F,I,binary_to_term(BT)} | L]).
-files(_I, L, _LSz, #w{seq = 1}=W, []) ->
+files(_I, L, _LSz, #w{seq = 1, out = Out}=W, []) ->
%% No temporary files created, everything in L.
- case W#w.out of
+ case Out of
Fun when is_function(Fun) ->
SL = internal_sort(L, W),
W1 = outfun(binterm_objects(SL, []), W),
@@ -462,8 +462,8 @@ fun_run(I, L, LSz, W, []) ->
{cont, NW, Objs} ->
fun_run(I, L, LSz, NW, Objs)
end;
-fun_run(I, L, LSz, W, Objs) when LSz < W#w.runsize ->
- {NI, NObjs, NL, NLSz} = fun_objs(Objs, L, LSz, W#w.runsize, I, W),
+fun_run(I, L, LSz, #w{runsize = Runsize}=W, Objs) when LSz < Runsize ->
+ {NI, NObjs, NL, NLSz} = fun_objs(Objs, L, LSz, Runsize, I, W),
fun_run(NI, NL, NLSz, W, NObjs);
fun_run(I, L, _LSz, W, Objs) ->
NW = write_run(L, W),
@@ -1201,11 +1201,11 @@ infun(W) ->
erlang:raise(Class, Reason, erlang:get_stacktrace())
end.
-outfun(A, W) when W#w.inout_value =/= no_value ->
+outfun(A, #w{inout_value = Val} = W) when Val =/= no_value ->
W1 = W#w{inout_value = no_value},
W2 = if
W1#w.fun_out ->
- outfun(W#w.inout_value, W1);
+ outfun(Val, W1);
true -> W1
end,
outfun(A, W2);
@@ -1372,19 +1372,19 @@ cleanup(W) ->
end,
lists:foreach(F, W1#w.temp).
-close_input(W) when is_function(W#w.in) ->
- catch (W#w.in)(close),
+close_input(#w{in = In}=W) when is_function(In) ->
+ catch In(close),
W#w{in = undefined};
close_input(#w{in = undefined}=W) ->
W.
-close_out(W) when is_function(W#w.out) ->
- catch (W#w.out)(close);
+close_out(#w{out = Out}) when is_function(Out) ->
+ catch Out(close);
close_out(_) ->
ok.
close_file(Fd, W) ->
- {value, {Fd, FileName}} = lists:keysearch(Fd, 1, W#w.temp),
+ {Fd, FileName} = lists:keyfind(Fd, 1, W#w.temp),
?DEBUG("closing ~p~n", [FileName]),
file:close(Fd),
W#w{temp = [FileName | lists:keydelete(Fd, 1, W#w.temp)]}.
diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl
index d65588f0d1..74c5172137 100644
--- a/lib/stdlib/src/filelib.erl
+++ b/lib/stdlib/src/filelib.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1997-2010. 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%
-module(filelib).
@@ -228,7 +228,17 @@ ensure_dir(F) ->
ok;
false ->
ensure_dir(Dir),
- file:make_dir(Dir)
+ case file:make_dir(Dir) of
+ {error,eexist}=EExist ->
+ case do_is_dir(Dir, file) of
+ true ->
+ ok;
+ false ->
+ EExist
+ end;
+ Err ->
+ Err
+ end
end.
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index f3775f967a..ba0275ae2b 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -603,7 +603,12 @@ get_msg(Msg) -> Msg.
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, Debug, [Name, StateName, StateData, Mod, _Time]] =
StatusData,
- Header = lists:concat(["Status for state machine ", Name]),
+ NameTag = if is_pid(Name) ->
+ pid_to_list(Name);
+ is_atom(Name) ->
+ Name
+ end,
+ Header = lists:concat(["Status for state machine ", NameTag]),
Log = sys:get_debug(log, Debug, []),
Specfic =
case erlang:function_exported(Mod, format_status, 2) of
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index 2d3c86e4ea..26f6ec8931 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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%
%%
@@ -139,9 +139,9 @@ format_prompt({format,Format,Args}) ->
format_prompt(Format,Args);
format_prompt(Prompt)
when is_list(Prompt); is_atom(Prompt); is_binary(Prompt) ->
- format_prompt("~s", [Prompt]);
+ format_prompt("~ts", [Prompt]);
format_prompt(Prompt) ->
- format_prompt("~p", [Prompt]).
+ format_prompt("~tp", [Prompt]).
format_prompt(Format, Args) ->
case catch io_lib:format(Format, Args) of
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 3df6f4bb90..7ea7de8d58 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -334,6 +334,10 @@ obsolete_1(ssl_pkix, decode_cert_file, A) when A =:= 1; A =:= 2 ->
{deprecated,"deprecated (will be removed in R14B); use public_key:pem_to_der/1 and public_key:pkix_decode_cert/2 instead"};
obsolete_1(ssl_pkix, decode_cert, A) when A =:= 1; A =:= 2 ->
{deprecated,{public_key,pkix_decode_cert,2},"R14B"};
+
+%% Added in R13B04.
+obsolete_1(erlang, concat_binary, 1) ->
+ {deprecated,{erlang,list_to_binary,1},"R14B"};
obsolete_1(_, _, _) ->
no.
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index ef142e1c8a..6e48d95973 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2010. 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%
%%
-module(qlc).
@@ -528,122 +528,111 @@ options(Options0, [Key | Keys], L) when is_list(Options0) ->
false ->
Options0
end,
- V = case lists:keysearch(Key, 1, Options) of
- {value, {format_fun, U=undefined}} ->
+ V = case lists:keyfind(Key, 1, Options) of
+ {format_fun, U=undefined} ->
{ok, U};
- {value, {info_fun, U=undefined}} ->
+ {info_fun, U=undefined} ->
{ok, U};
- {value, {lookup_fun, U=undefined}} ->
+ {lookup_fun, U=undefined} ->
{ok, U};
- {value, {parent_fun, U=undefined}} ->
+ {parent_fun, U=undefined} ->
{ok, U};
- {value, {post_fun, U=undefined}} ->
+ {post_fun, U=undefined} ->
{ok, U};
- {value, {pre_fun, U=undefined}} ->
+ {pre_fun, U=undefined} ->
{ok, U};
- {value, {info_fun, Fun}} when is_function(Fun),
- is_function(Fun, 1) ->
+ {info_fun, Fun} when is_function(Fun), is_function(Fun, 1) ->
{ok, Fun};
- {value, {pre_fun, Fun}} when is_function(Fun),
- is_function(Fun, 1) ->
+ {pre_fun, Fun} when is_function(Fun), is_function(Fun, 1) ->
{ok, Fun};
- {value, {post_fun, Fun}} when is_function(Fun),
- is_function(Fun, 0) ->
+ {post_fun, Fun} when is_function(Fun), is_function(Fun, 0) ->
{ok, Fun};
- {value, {lookup_fun, Fun}} when is_function(Fun),
- is_function(Fun, 2) ->
+ {lookup_fun, Fun} when is_function(Fun), is_function(Fun, 2) ->
{ok, Fun};
- {value, {max_lookup, Max}} when is_integer(Max), Max >= 0 ->
+ {max_lookup, Max} when is_integer(Max), Max >= 0 ->
{ok, Max};
- {value, {max_lookup, infinity}} ->
+ {max_lookup, infinity} ->
{ok, -1};
- {value, {format_fun, Fun}} when is_function(Fun),
- is_function(Fun, 1) ->
+ {format_fun, Fun} when is_function(Fun), is_function(Fun, 1) ->
{ok, Fun};
- {value, {parent_fun, Fun}} when is_function(Fun),
- is_function(Fun, 0) ->
+ {parent_fun, Fun} when is_function(Fun), is_function(Fun, 0) ->
{ok, Fun};
- {value, {key_equality, KE='=='}}->
+ {key_equality, KE='=='} ->
{ok, KE};
- {value, {key_equality, KE='=:='}}->
+ {key_equality, KE='=:='} ->
{ok, KE};
- {value, {join, J=any}} ->
+ {join, J=any} ->
{ok, J};
- {value, {join, J=nested_loop}} ->
+ {join, J=nested_loop} ->
{ok, J};
- {value, {join, J=merge}} ->
+ {join, J=merge} ->
{ok, J};
- {value, {join, J=lookup}} ->
+ {join, J=lookup} ->
{ok, J};
- {value, {lookup, LookUp}} when LookUp;
- not LookUp;
- LookUp =:= any ->
+ {lookup, LookUp} when is_boolean(LookUp); LookUp =:= any ->
{ok, LookUp};
- {value, {max_list_size, Max}} when is_integer(Max), Max >= 0 ->
+ {max_list_size, Max} when is_integer(Max), Max >= 0 ->
{ok, Max};
- {value, {tmpdir_usage, TmpUsage}} when TmpUsage =:= allowed;
- TmpUsage =:= not_allowed;
- TmpUsage =:= info_msg;
- TmpUsage =:= warning_msg;
- TmpUsage =:= error_msg ->
+ {tmpdir_usage, TmpUsage} when TmpUsage =:= allowed;
+ TmpUsage =:= not_allowed;
+ TmpUsage =:= info_msg;
+ TmpUsage =:= warning_msg;
+ TmpUsage =:= error_msg ->
{ok, TmpUsage};
- {value, {unique, Unique}} when Unique; not Unique ->
+ {unique, Unique} when is_boolean(Unique) ->
{ok, Unique};
- {value, {cache, Cache}} when Cache; not Cache; Cache =:= list ->
+ {cache, Cache} when is_boolean(Cache); Cache =:= list ->
{ok, Cache};
- {value, {cache, ets}} ->
+ {cache, ets} ->
{ok, true};
- {value, {cache, no}} ->
+ {cache, no} ->
{ok, false};
- {value, {unique_all, UniqueAll}} when UniqueAll; not UniqueAll ->
+ {unique_all, UniqueAll} when is_boolean(UniqueAll) ->
{ok, UniqueAll};
- {value, {cache_all, CacheAll}} when CacheAll;
- not CacheAll;
- CacheAll =:= list ->
+ {cache_all, CacheAll} when is_boolean(CacheAll);
+ CacheAll =:= list ->
{ok, CacheAll};
- {value, {cache_all, ets}} ->
+ {cache_all, ets} ->
{ok, true};
- {value, {cache_all, no}} ->
+ {cache_all, no} ->
{ok, false};
- {value, {spawn_options, default}} ->
+ {spawn_options, default} ->
{ok, default};
- {value, {spawn_options, SpawnOptions}} ->
+ {spawn_options, SpawnOptions} ->
case is_proper_list(SpawnOptions) of
true ->
{ok, SpawnOptions};
false ->
badarg
end;
- {value, {flat, Flat}} when Flat; not Flat ->
+ {flat, Flat} when is_boolean(Flat) ->
{ok, Flat};
- {value, {format, Format}} when Format =:= string;
- Format =:= abstract_code;
- Format =:= debug ->
+ {format, Format} when Format =:= string;
+ Format =:= abstract_code;
+ Format =:= debug ->
{ok, Format};
- {value, {n_elements, NElements}} when NElements =:= infinity;
- is_integer(NElements),
- NElements > 0 ->
+ {n_elements, NElements} when NElements =:= infinity;
+ is_integer(NElements),
+ NElements > 0 ->
{ok, NElements};
- {value, {depth, Depth}} when Depth =:= infinity;
- is_integer(Depth), Depth >= 0 ->
+ {depth, Depth} when Depth =:= infinity;
+ is_integer(Depth), Depth >= 0 ->
{ok, Depth};
- {value, {order, Order}} when is_function(Order),
- is_function(Order, 2);
- (Order =:= ascending);
- (Order =:= descending) ->
+ {order, Order} when is_function(Order), is_function(Order, 2);
+ (Order =:= ascending);
+ (Order =:= descending) ->
{ok, Order};
- {value, {compressed, Comp}} when Comp ->
+ {compressed, Comp} when Comp ->
{ok, [compressed]};
- {value, {compressed, Comp}} when not Comp ->
+ {compressed, Comp} when not Comp ->
{ok, []};
- {value, {tmpdir, T}} ->
+ {tmpdir, T} ->
{ok, T};
- {value, {size, Size}} when is_integer(Size), Size > 0 ->
+ {size, Size} when is_integer(Size), Size > 0 ->
{ok, Size};
- {value, {no_files, NoFiles}} when is_integer(NoFiles),
- NoFiles > 1 ->
+ {no_files, NoFiles} when is_integer(NoFiles), NoFiles > 1 ->
{ok, NoFiles};
- {value, {Key, _}} ->
+ {Key, _} ->
badarg;
false ->
Default = default_option(Key),
@@ -1457,7 +1446,7 @@ prep_qlc_lc({qlc_v1, QFun, CodeF, Qdata0, QOpt}, Opt, GOpt, _H) ->
{?qual_data(QNum, GoI, SI, {gen, Prep}), ModGens}
end,
{Qdata, ModGens} = lists:mapfoldl(F, [], Qdata0),
- SomeLookUp = lists:keymember(true, 2, ModGens) =/= false,
+ SomeLookUp = lists:keymember(true, 2, ModGens),
check_lookup_option(Opt, SomeLookUp),
case ModGens of
[{_QNum, _LookUp, all, OnePrep}] ->
@@ -1503,7 +1492,7 @@ pos_fun('==', QOpt, QNum) ->
prep_gen(#qlc_table{lu_vals = LuV0, ms = MS0, trav_MS = TravMS,
info_fun = IF, lookup_fun = LU_fun,
- key_equality = KeyEquality}=LE0,
+ key_equality = KeyEquality}=LE0,
Prep0, PosFun0, {MS, Fs}, Opt) ->
PosFun = PosFun0(KeyEquality),
{LuV, {STag,SkipFils}} = find_const_positions(IF, LU_fun, PosFun, Opt),
@@ -1998,8 +1987,8 @@ no_cache_of_first_generator(Optz, 1) ->
Optz#optz{cache = false}.
maybe_sort(LE, QNum, DoSort, Opt) ->
- case lists:keysearch(QNum, 1, DoSort) of
- {value, {QNum, Col}} ->
+ case lists:keyfind(QNum, 1, DoSort) of
+ {QNum, Col} ->
#qlc_opt{tmpdir = TmpDir, tmpdir_usage = TmpUsage} = Opt,
SortOpts = [{tmpdir,Dir} || Dir <- [TmpDir], Dir =/= ""],
Sort = #qlc_sort{h = LE, keypos = {keysort, Col}, unique = false,
@@ -2025,7 +2014,7 @@ skip_lookup_filters(Qdata0, LU_SkipFs) ->
%% specification it must be applied _after_ the lookup join (the
%% filter must not be skipped!).
activate_join_lookup_filter(QNum, Qdata) ->
- {value, {_,GoI2,SI2,{gen,Prep2}}} = lists:keysearch(QNum, 1, Qdata),
+ {_,GoI2,SI2,{gen,Prep2}} = lists:keyfind(QNum, 1, Qdata),
Table2 = Prep2#prepared.qh,
NPrep2 = Prep2#prepared{qh = Table2#qlc_table{ms = no_match_spec}},
%% Table2#qlc_table.ms has been reset; the filter will be run.
@@ -2059,7 +2048,7 @@ opt_join(Join, JoinOption, Qdata, Opt, LU_SkipQuals) ->
opt_join_lu([{{_Q1,_C1,Q2,_C2}=J,[{lookup_join,_KEols,JKE,Skip0} | _]} | LJ],
Qdata, LU_SkipQuals) ->
- {value, {Q2,_,_,{gen,Prep2}}} = lists:keysearch(Q2, 1, Qdata),
+ {Q2,_,_,{gen,Prep2}} = lists:keyfind(Q2, 1, Qdata),
#qlc_table{ms = MS, key_equality = KE,
lookup_fun = LU_fun} = Prep2#prepared.qh,
%% If there is no filter to skip (the match spec was derived
@@ -2670,8 +2659,8 @@ sort_list_output(L) ->
%% Don't use the file_sorter unless it is known that objects will be
%% put on a temporary file (optimization).
sort_handle(H, ListFun, FileFun, SortOptions, Post, LocalPost, TmpUsageM) ->
- Size = case lists:keysearch(size, 1, SortOptions) of
- {value, {size, Size0}} -> Size0;
+ Size = case lists:keyfind(size, 1, SortOptions) of
+ {size, Size0} -> Size0;
false -> default_option(size)
end,
sort_cache(H, [], Size, {ListFun, FileFun, Post, LocalPost, TmpUsageM}).
@@ -2891,8 +2880,8 @@ ucache_recall(UTab, MTab, SeqNo) ->
Object = case ets:lookup(UTab, Hash) of
[{Hash, SeqNo, Object0}] -> Object0;
HashSeqObjects ->
- {value, {Hash, SeqNo, Object0}} =
- lists:keysearch(SeqNo, 2, HashSeqObjects),
+ {Hash, SeqNo, Object0} =
+ lists:keyfind(SeqNo, 2, HashSeqObjects),
Object0
end,
[Object | fun() -> ucache_recall(UTab, MTab, SeqNo + 1) end]
@@ -3403,8 +3392,8 @@ merge_join_id() ->
tmp_merge_file(MergeId) ->
TmpFiles = get(?MERGE_JOIN_FILE),
- case lists:keysearch(MergeId, 1, TmpFiles) of
- {value, {MergeId, Fd, FileName}} ->
+ case lists:keyfind(MergeId, 1, TmpFiles) of
+ {MergeId, Fd, FileName} ->
{Fd, FileName};
false ->
none
diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl
index 2d7874d99f..24378a0698 100644
--- a/lib/stdlib/src/qlc_pt.erl
+++ b/lib/stdlib/src/qlc_pt.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2004-2010. 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%
%%
-module(qlc_pt).
@@ -845,8 +845,8 @@ join_handle(AP, L, [F, H, O, C], Constants) ->
join_handle_constants(QId, ExtraConstants) ->
IdNo = QId#qid.no,
- case lists:keysearch(IdNo, 1, ExtraConstants) of
- {value, {IdNo, ConstOps}} ->
+ case lists:keyfind(IdNo, 1, ExtraConstants) of
+ {IdNo, ConstOps} ->
ConstOps;
false ->
[]
@@ -1231,9 +1231,9 @@ lu_skip(ColConstants, FilterData, PatternFrame, PatternVars,
%% The filter can only be skipped if all constants
%% are looked up.
LookedUpConstants =
- case lists:keysearch(Column, 1, ColConstants) of
+ case lists:keyfind(Column, 1, ColConstants) of
false -> [];
- {value, {Column,LUCs}} -> LUCs
+ {Column, LUCs} -> LUCs
end,
%% Don't try to handle filters that compare several
%% values equal. See also frames_to_columns().
@@ -1279,8 +1279,8 @@ join_gens(Cs0, Qs, Skip) ->
join_gens2(lists:filter(fun(C) -> length(C) > 2 end, Cs), FD, Skip)}.
join_gens2(Cs0, FilterData, Skip) ->
- [{J, skip_tag(case lists:keysearch(J, 1, Skip) of
- {value, {J,FilL}} ->
+ [{J, skip_tag(case lists:keyfind(J, 1, Skip) of
+ {J, FilL} ->
FilL;
false ->
[]
@@ -1296,8 +1296,8 @@ skip_tag(FilList, FilterData) ->
end, FilList}.
skip_tag(Col, ColFils, FilterData) ->
- case lists:keysearch(Col, 1, ColFils) of
- {value, {Col, FilL}} ->
+ case lists:keyfind(Col, 1, ColFils) of
+ {Col, FilL} ->
Tag = if
length(FilterData) =:= length(FilL) ->
all;
@@ -1415,7 +1415,7 @@ sel_gf([], _N, _Deps, _RDs, _Gens, _Gens1) ->
sel_gf([{#qid{no = N}=Id,{fil,F}}=Fil | FData], N, Deps, RDs, Gens, Gens1) ->
case erl_lint:is_guard_test(F, RDs) of
true ->
- {value, {Id,GIds}} = lists:keysearch(Id, 1, Deps),
+ {Id,GIds} = lists:keyfind(Id, 1, Deps),
case length(GIds) =< 1 of
true ->
case generators_in_scope(GIds, Gens1) of
@@ -2572,8 +2572,8 @@ nos_pattern([P0 | Ps0], S0, PVs0) ->
{[P | Ps], S, PVs};
nos_pattern({var,L,V}, {LI,Vs0,UV,A,Sg}, PVs0) when V =/= '_' ->
{Name, Vs, PVs} =
- case lists:keysearch(V, 1, PVs0) of
- {value, {V,VN}} ->
+ case lists:keyfind(V, 1, PVs0) of
+ {V, VN} ->
_ = used_var(V, Vs0, UV),
{VN, Vs0, PVs0};
false ->
diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl
index 5417ac02e5..296a6b3d23 100644
--- a/lib/stdlib/src/re.erl
+++ b/lib/stdlib/src/re.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2010. 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%
%%
-module(re).
@@ -32,18 +32,7 @@ split(Subject,RE,Options) ->
try
{NewOpt,Convert,Unicode,Limit,Strip,Group} =
process_split_params(Options,iodata,false,-1,false,false),
- FlatSubject =
- case is_binary(Subject) of
- true ->
- Subject;
- false ->
- case Unicode of
- true ->
- unicode:characters_to_binary(Subject,unicode);
- false ->
- iolist_to_binary(Subject)
- end
- end,
+ FlatSubject = to_binary(Subject, Unicode),
case compile_split(RE,NewOpt) of
{error,_Err} ->
throw(badre);
@@ -217,19 +206,9 @@ replace(Subject,RE,Replacement,Options) ->
try
{NewOpt,Convert,Unicode} =
process_repl_params(Options,iodata,false),
- FlatSubject =
- case is_binary(Subject) of
- true ->
- Subject;
- false ->
- case Unicode of
- true ->
- unicode:characters_to_binary(Subject,unicode);
- false ->
- iolist_to_binary(Subject)
- end
- end,
- case do_replace(FlatSubject,Subject,RE,Replacement,NewOpt) of
+ FlatSubject = to_binary(Subject, Unicode),
+ FlatReplacement = to_binary(Replacement, Unicode),
+ case do_replace(FlatSubject,Subject,RE,FlatReplacement,NewOpt) of
{error,_Err} ->
throw(badre);
IoList ->
@@ -237,7 +216,12 @@ replace(Subject,RE,Replacement,Options) ->
iodata ->
IoList;
binary ->
- iolist_to_binary(IoList);
+ case Unicode of
+ false ->
+ iolist_to_binary(IoList);
+ true ->
+ unicode:characters_to_binary(IoList,unicode)
+ end;
list ->
case Unicode of
false ->
@@ -324,8 +308,7 @@ process_split_params([H|T],C,U,L,S,G) ->
{[H|NT],NC,NU,NL,NS,NG}.
apply_mlist(Subject,Replacement,Mlist) ->
- do_mlist(Subject,Subject,0,precomp_repl(iolist_to_binary(Replacement)),
- Mlist).
+ do_mlist(Subject,Subject,0,precomp_repl(Replacement), Mlist).
precomp_repl(<<>>) ->
@@ -545,7 +528,7 @@ process_uparams([],Type) ->
ucompile(RE,Options) ->
try
- re:compile(unicode:characters_to_binary(RE,unicode))
+ re:compile(unicode:characters_to_binary(RE,unicode),Options)
catch
error:AnyError ->
{'EXIT',{new_stacktrace,[{Mod,_,L}|Rest]}} =
@@ -618,18 +601,7 @@ grun(Subject,RE,{Options,NeedClean,OrigRE}) ->
grun2(Subject,RE,{Options,NeedClean}) ->
Unicode = check_for_unicode(RE,Options),
- FlatSubject =
- case is_binary(Subject) of
- true ->
- Subject;
- false ->
- case Unicode of
- true ->
- unicode:characters_to_binary(Subject,unicode);
- false ->
- iolist_to_binary(Subject)
- end
- end,
+ FlatSubject = to_binary(Subject, Unicode),
do_grun(FlatSubject,Subject,Unicode,RE,{Options,NeedClean}).
do_grun(FlatSubject,Subject,Unicode,RE,{Options0,NeedClean}) ->
@@ -749,3 +721,10 @@ runopt(global) ->
true;
runopt(_) ->
false.
+
+to_binary(Bin, _IsUnicode) when is_binary(Bin) ->
+ Bin;
+to_binary(Data, true) ->
+ unicode:characters_to_binary(Data,unicode);
+to_binary(Data, false) ->
+ iolist_to_binary(Data).
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index a8d31b4e6b..ebb221c151 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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%
%%
-module(shell).
@@ -22,12 +22,14 @@
-export([whereis_evaluator/0, whereis_evaluator/1]).
-export([start_restricted/1, stop_restricted/0]).
-export([local_allowed/3, non_local_allowed/3]).
+-export([prompt_func/1]).
-define(LINEMAX, 30).
-define(CHAR_MAX, 60).
-define(DEF_HISTORY, 20).
-define(DEF_RESULTS, 20).
-define(DEF_CATCH_EXCEPTION, false).
+-define(DEF_PROMPT_FUNC, default).
-define(RECORDS, shell_records).
@@ -235,14 +237,15 @@ server(StartSync) ->
{History,Results} = check_and_get_history_and_results(),
server_loop(0, start_eval(Bs, RT, []), Bs, RT, [], History, Results).
-server_loop(N0, Eval_0, Bs0, RT, Ds0, History0, Results0) ->
+server_loop(N0, Eval_0, Bs00, RT, Ds00, History0, Results0) ->
N = N0 + 1,
- {Res, Eval0} = get_command(prompt(N), Eval_0, Bs0, RT, Ds0),
+ {Eval_1,Bs0,Ds0,Prompt} = prompt(N, Eval_0, Bs00, RT, Ds00),
+ {Res,Eval0} = get_command(Prompt, Eval_1, Bs0, RT, Ds0),
case Res of
{ok,Es0,_EndLine} ->
case expand_hist(Es0, N) of
{ok,Es} ->
- {V,Eval,Bs,Ds} = shell_cmd(Es, Eval0, Bs0, RT, Ds0),
+ {V,Eval,Bs,Ds} = shell_cmd(Es, Eval0, Bs0, RT, Ds0, cmd),
{History,Results} = check_and_get_history_and_results(),
add_cmd(N, Es, V),
HB1 = del_cmd(command, N - History, N - History0, false),
@@ -301,7 +304,42 @@ get_command1(Pid, Eval, Bs, RT, Ds) ->
get_command1(Pid, start_eval(Bs, RT, Ds), Bs, RT, Ds)
end.
-prompt(N) ->
+prompt(N, Eval0, Bs0, RT, Ds0) ->
+ case get_prompt_func() of
+ {M,F} ->
+ L = [{history,N}],
+ C = {call,1,{remote,1,{atom,1,M},{atom,1,F}},[{value,1,L}]},
+ {V,Eval,Bs,Ds} = shell_cmd([C], Eval0, Bs0, RT, Ds0, pmt),
+ {Eval,Bs,Ds,case V of
+ {pmt,Val} ->
+ Val;
+ _ ->
+ bad_prompt_func({M,F}),
+ default_prompt(N)
+ end};
+ default ->
+ {Eval0,Bs0,Ds0,default_prompt(N)}
+ end.
+
+get_prompt_func() ->
+ case application:get_env(stdlib, shell_prompt_func) of
+ {ok,{M,F}=PromptFunc} when is_atom(M), is_atom(F) ->
+ PromptFunc;
+ {ok,default=Default} ->
+ Default;
+ {ok,Term} ->
+ bad_prompt_func(Term),
+ default;
+ undefined ->
+ default
+ end.
+
+bad_prompt_func(M) ->
+ fwrite_severity(benign, <<"Bad prompt function: ~p">>, [M]).
+
+default_prompt(N) ->
+ %% Don't bother flattening the list irrespective of what the
+ %% I/O-protocol states.
case is_alive() of
true -> io_lib:format(<<"(~s)~w> ">>, [node(), N]);
false -> io_lib:format(<<"~w> ">>, [N])
@@ -461,14 +499,16 @@ has_bin(T, I) ->
has_bin(element(I, T)),
has_bin(T, I - 1).
-%% shell_cmd(Sequence, Evaluator, Bindings, RecordTable, Dictionary)
+%% shell_cmd(Sequence, Evaluator, Bindings, RecordTable, Dictionary, What)
%% shell_rep(Evaluator, Bindings, RecordTable, Dictionary) ->
%% {Value,Evaluator,Bindings,Dictionary}
%% Send a command to the evaluator and wait for the reply. Start a new
%% evaluator if necessary.
+%% What = pmt | cmd. When evaluating a prompt ('pmt') the evaluated value
+%% must not be displayed, and it has to be returned.
-shell_cmd(Es, Eval, Bs, RT, Ds) ->
- Eval ! {shell_cmd,self(),{eval,Es}},
+shell_cmd(Es, Eval, Bs, RT, Ds, W) ->
+ Eval ! {shell_cmd,self(),{eval,Es}, W},
shell_rep(Eval, Bs, RT, Ds).
shell_rep(Ev, Bs0, RT, Ds0) ->
@@ -559,26 +599,26 @@ evaluator(Shell, Bs, RT, Ds) ->
eval_loop(Shell, Bs0, RT) ->
receive
- {shell_cmd,Shell,{eval,Es}} ->
+ {shell_cmd,Shell,{eval,Es},W} ->
Ef = {value,
fun(MForFun, As) -> apply_fun(MForFun, As, Shell) end},
Lf = local_func_handler(Shell, RT, Ef),
- Bs = eval_exprs(Es, Shell, Bs0, RT, Lf, Ef),
+ Bs = eval_exprs(Es, Shell, Bs0, RT, Lf, Ef, W),
eval_loop(Shell, Bs, RT)
end.
restricted_eval_loop(Shell, Bs0, RT, RShMod) ->
receive
- {shell_cmd,Shell,{eval,Es}} ->
+ {shell_cmd,Shell,{eval,Es}, W} ->
{LFH,NLFH} = restrict_handlers(RShMod, Shell, RT),
put(restricted_expr_state, []),
- Bs = eval_exprs(Es, Shell, Bs0, RT, {eval,LFH}, {value,NLFH}),
+ Bs = eval_exprs(Es, Shell, Bs0, RT, {eval,LFH}, {value,NLFH}, W),
restricted_eval_loop(Shell, Bs, RT, RShMod)
end.
-eval_exprs(Es, Shell, Bs0, RT, Lf, Ef) ->
+eval_exprs(Es, Shell, Bs0, RT, Lf, Ef, W) ->
try
- {R,Bs2} = exprs(Es, Bs0, RT, Lf, Ef),
+ {R,Bs2} = exprs(Es, Bs0, RT, Lf, Ef, W),
Shell ! {shell_rep,self(),R},
Bs2
catch
@@ -614,10 +654,10 @@ do_catch(_Class, _Reason) ->
false
end.
-exprs(Es, Bs0, RT, Lf, Ef) ->
- exprs(Es, Bs0, RT, Lf, Ef, Bs0).
+exprs(Es, Bs0, RT, Lf, Ef, W) ->
+ exprs(Es, Bs0, RT, Lf, Ef, Bs0, W).
-exprs([E0|Es], Bs1, RT, Lf, Ef, Bs0) ->
+exprs([E0|Es], Bs1, RT, Lf, Ef, Bs0, W) ->
UsedRecords = used_record_defs(E0, RT),
RBs = record_bindings(UsedRecords, Bs1),
case check_command(prep_check([E0]), RBs) of
@@ -629,16 +669,20 @@ exprs([E0|Es], Bs1, RT, Lf, Ef, Bs0) ->
if
Es =:= [] ->
VS = pp(V0, 1, RT),
- io:requests([{put_chars, VS}, nl]),
+ [io:requests([{put_chars, VS}, nl]) || W =:= cmd],
%% Don't send the result back if it will be
%% discarded anyway.
- V = case result_will_be_saved() of
- true -> V0;
- false -> ignored
+ V = if
+ W =:= pmt ->
+ {W,V0};
+ true -> case result_will_be_saved() of
+ true -> V0;
+ false -> ignored
+ end
end,
{{value,V,Bs,get()},Bs};
true ->
- exprs(Es, Bs, RT, Lf, Ef, Bs0)
+ exprs(Es, Bs, RT, Lf, Ef, Bs0, W)
end;
{error,Error} ->
{{command_error,Error},Bs0}
@@ -1383,7 +1427,7 @@ pp(V, I, RT) ->
columns() ->
case io:columns() of
- {ok,N} -> N;
+ {ok,N} -> N;
_ -> 80
end.
@@ -1438,3 +1482,9 @@ results(L) when is_integer(L), L >= 0 ->
catch_exception(Bool) ->
set_env(stdlib, shell_catch_exception, Bool, ?DEF_CATCH_EXCEPTION).
+
+-type prompt_func() :: 'default' | {module(),atom()}.
+-spec prompt_func(prompt_func()) -> prompt_func().
+
+prompt_func(String) ->
+ set_env(stdlib, shell_prompt_func, String, ?DEF_PROMPT_FUNC).
diff --git a/lib/stdlib/src/shell_default.erl b/lib/stdlib/src/shell_default.erl
index 670f8cdb44..3fe359af0e 100644
--- a/lib/stdlib/src/shell_default.erl
+++ b/lib/stdlib/src/shell_default.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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%
%%
@@ -45,6 +45,7 @@ help() ->
format("h() -- history\n"),
format("history(N) -- set how many previous commands to keep\n"),
format("results(N) -- set how many previous command results to keep\n"),
+ format("catch_exception(B) -- how exceptions are handled\n"),
format("v(N) -- use the value of query <N>\n"),
format("rd(R,D) -- define a record\n"),
format("rf() -- remove all record information\n"),
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index fb1303d1eb..22269a8d1b 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. 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%
%%
-module(supervisor).
@@ -24,7 +24,7 @@
-export([start_link/2,start_link/3,
start_child/2, restart_child/2,
delete_child/2, terminate_child/2,
- which_children/1,
+ which_children/1, count_children/1,
check_childspecs/1]).
-export([behaviour_info/1]).
@@ -95,6 +95,9 @@ terminate_child(Supervisor, Name) ->
which_children(Supervisor) ->
call(Supervisor, which_children).
+count_children(Supervisor) ->
+ call(Supervisor, count_children).
+
call(Supervisor, Req) ->
gen_server:call(Supervisor, Req, infinity).
@@ -297,7 +300,49 @@ handle_call(which_children, _From, State) ->
{Name, Pid, ChildType, Mods}
end,
State#state.children),
- {reply, Resp, State}.
+ {reply, Resp, State};
+
+handle_call(count_children, _From, State) when ?is_simple(State) ->
+ [#child{child_type = CT}] = State#state.children,
+ {Active, Count} =
+ ?DICT:fold(fun(Pid, _Val, {Alive, Tot}) ->
+ if is_pid(Pid) -> {Alive+1, Tot +1};
+ true -> {Alive, Tot + 1} end
+ end, {0, 0}, State#state.dynamics),
+ Reply = case CT of
+ supervisor -> [{specs, 1}, {active, Active},
+ {supervisors, Count}, {workers, 0}];
+ worker -> [{specs, 1}, {active, Active},
+ {supervisors, 0}, {workers, Count}]
+ end,
+ {reply, Reply, State};
+
+handle_call(count_children, _From, State) ->
+
+ %% Specs and children are together on the children list...
+ {Specs, Active, Supers, Workers} =
+ lists:foldl(fun(Child, Counts) ->
+ count_child(Child, Counts)
+ end, {0,0,0,0}, State#state.children),
+
+ %% Reformat counts to a property list.
+ Reply = [{specs, Specs}, {active, Active},
+ {supervisors, Supers}, {workers, Workers}],
+ {reply, Reply, State}.
+
+
+count_child(#child{pid = Pid, child_type = worker},
+ {Specs, Active, Supers, Workers}) ->
+ case is_pid(Pid) andalso is_process_alive(Pid) of
+ true -> {Specs+1, Active+1, Supers, Workers+1};
+ false -> {Specs+1, Active, Supers, Workers+1}
+ end;
+count_child(#child{pid = Pid, child_type = supervisor},
+ {Specs, Active, Supers, Workers}) ->
+ case is_pid(Pid) andalso is_process_alive(Pid) of
+ true -> {Specs+1, Active+1, Supers+1, Workers};
+ false -> {Specs+1, Active, Supers+1, Workers}
+ end.
%%% Hopefully cause a function-clause as there is no API function
diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl
index e0f2dbcd3c..12209c16d7 100644
--- a/lib/stdlib/src/sys.erl
+++ b/lib/stdlib/src/sys.erl
@@ -245,8 +245,17 @@ do_cmd(SysState, Other, _Parent, _Mod, Debug, Misc) ->
{SysState, {error, {unknown_system_msg, Other}}, Debug, Misc}.
get_status(SysState, Parent, Mod, Debug, Misc) ->
+ PDict = get(),
+ FmtMisc =
+ case erlang:function_exported(Mod, format_status, 2) of
+ true ->
+ FmtArgs = [PDict, SysState, Parent, Debug, Misc],
+ Mod:format_status(normal, FmtArgs);
+ _ ->
+ Misc
+ end,
{status, self(), {module, Mod},
- [get(), SysState, Parent, Debug, Misc]}.
+ [PDict, SysState, Parent, Debug, FmtMisc]}.
%%-----------------------------------------------------------------
%% These are the system debug commands.