diff options
Diffstat (limited to 'lib/stdlib/src')
-rw-r--r-- | lib/stdlib/src/Makefile | 17 | ||||
-rw-r--r-- | lib/stdlib/src/array.erl | 16 | ||||
-rw-r--r-- | lib/stdlib/src/c.erl | 4 | ||||
-rw-r--r-- | lib/stdlib/src/dets_v8.erl | 40 | ||||
-rw-r--r-- | lib/stdlib/src/edlin.erl | 46 | ||||
-rw-r--r-- | lib/stdlib/src/edlin_expand.erl | 49 | ||||
-rw-r--r-- | lib/stdlib/src/epp.erl | 265 | ||||
-rw-r--r-- | lib/stdlib/src/erl_lint.erl | 114 | ||||
-rw-r--r-- | lib/stdlib/src/escript.erl | 84 | ||||
-rw-r--r-- | lib/stdlib/src/file_sorter.erl | 34 | ||||
-rw-r--r-- | lib/stdlib/src/filelib.erl | 22 | ||||
-rw-r--r-- | lib/stdlib/src/gen_fsm.erl | 7 | ||||
-rw-r--r-- | lib/stdlib/src/io_lib.erl | 14 | ||||
-rw-r--r-- | lib/stdlib/src/otp_internal.erl | 4 | ||||
-rw-r--r-- | lib/stdlib/src/qlc.erl | 159 | ||||
-rw-r--r-- | lib/stdlib/src/qlc_pt.erl | 32 | ||||
-rw-r--r-- | lib/stdlib/src/re.erl | 71 | ||||
-rw-r--r-- | lib/stdlib/src/shell.erl | 104 | ||||
-rw-r--r-- | lib/stdlib/src/shell_default.erl | 11 | ||||
-rw-r--r-- | lib/stdlib/src/supervisor.erl | 59 | ||||
-rw-r--r-- | lib/stdlib/src/sys.erl | 11 |
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. |