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/binary.erl194
-rw-r--r--lib/stdlib/src/dets.erl151
-rw-r--r--lib/stdlib/src/digraph_utils.erl4
-rw-r--r--lib/stdlib/src/epp.erl2
-rw-r--r--lib/stdlib/src/erl_compile.erl14
-rw-r--r--lib/stdlib/src/erl_eval.erl1
-rw-r--r--lib/stdlib/src/erl_expand_records.erl2
-rw-r--r--lib/stdlib/src/erl_internal.erl3
-rw-r--r--lib/stdlib/src/erl_lint.erl79
-rw-r--r--lib/stdlib/src/erl_scan.erl2
-rw-r--r--lib/stdlib/src/error_logger_file_h.erl2
-rw-r--r--lib/stdlib/src/error_logger_tty_h.erl2
-rw-r--r--lib/stdlib/src/escript.erl32
-rw-r--r--lib/stdlib/src/ets.erl442
-rw-r--r--lib/stdlib/src/filelib.erl41
-rw-r--r--lib/stdlib/src/filename.erl4
-rw-r--r--lib/stdlib/src/gen.erl22
-rw-r--r--lib/stdlib/src/gen_event.erl12
-rw-r--r--lib/stdlib/src/gen_fsm.erl29
-rw-r--r--lib/stdlib/src/gen_server.erl27
-rw-r--r--lib/stdlib/src/io_lib.erl7
-rw-r--r--lib/stdlib/src/lib.erl4
-rw-r--r--lib/stdlib/src/lists.erl65
-rw-r--r--lib/stdlib/src/math.erl112
-rw-r--r--lib/stdlib/src/ms_transform.erl2
-rw-r--r--lib/stdlib/src/otp_internal.erl20
-rw-r--r--lib/stdlib/src/qlc_pt.erl4
-rw-r--r--lib/stdlib/src/re.erl72
-rw-r--r--lib/stdlib/src/stdlib.appup.src12
-rw-r--r--lib/stdlib/src/string.erl26
-rw-r--r--lib/stdlib/src/supervisor.erl195
-rw-r--r--lib/stdlib/src/unicode.erl48
-rw-r--r--lib/stdlib/src/zip.erl4
34 files changed, 1338 insertions, 315 deletions
diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile
index 90e239b00f..14304824d3 100644
--- a/lib/stdlib/src/Makefile
+++ b/lib/stdlib/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2011. All Rights Reserved.
+# Copyright Ericsson AB 1996-2012. 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
@@ -167,6 +167,7 @@ docs:
# This is a trick so that the preloaded files will get the correct type
# specifications.
primary_bootstrap_compiler: \
+ $(BOOTSTRAP_COMPILER)/ebin/epp.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_scan.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_parse.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_lint.beam \
@@ -198,13 +199,13 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(ERL_FILES) erl_parse.yrl $(RELSYSDIR)/src
- $(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DIR) $(RELSYSDIR)/include
- $(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
- $(INSTALL_DIR) $(RELSYSDIR)/ebin
- $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ERL_FILES) erl_parse.yrl "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
+ $(INSTALL_DIR) "$(RELSYSDIR)/include"
+ $(INSTALL_DATA) $(HRL_FILES) "$(RELSYSDIR)/include"
+ $(INSTALL_DIR) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/stdlib/src/binary.erl b/lib/stdlib/src/binary.erl
index cb1e12ae46..1ed3422bc5 100644
--- a/lib/stdlib/src/binary.erl
+++ b/lib/stdlib/src/binary.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. 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
@@ -18,29 +18,185 @@
%%
-module(binary).
%%
-%% The following functions implemented as BIF's
-%% binary:compile_pattern/1
-%% binary:match/{2,3}
-%% binary:matches/{2,3}
-%% binary:longest_common_prefix/1
-%% binary:longest_common_suffix/1
-%% binary:first/1
-%% binary:last/1
-%% binary:at/2
-%% binary:part/{2,3}
-%% binary:bin_to_list/{1,2,3}
-%% binary:list_to_bin/1
-%% binary:copy/{1,2}
-%% binary:referenced_byte_size/1
-%% binary:decode_unsigned/{1,2}
-%% - Not yet:
-%%
%% Implemented in this module:
-export([split/2,split/3,replace/3,replace/4]).
--opaque cp() :: tuple().
+-opaque cp() :: {'am' | 'bm', binary()}.
-type part() :: {Start :: non_neg_integer(), Length :: integer()}.
+%%% BIFs.
+
+-export([at/2, bin_to_list/1, bin_to_list/2, bin_to_list/3,
+ compile_pattern/1, copy/1, copy/2, decode_unsigned/1,
+ decode_unsigned/2, encode_unsigned/1, encode_unsigned/2,
+ first/1, last/1, list_to_bin/1, longest_common_prefix/1,
+ longest_common_suffix/1, match/2, match/3, matches/2,
+ matches/3, part/2, part/3, referenced_byte_size/1]).
+
+-spec at(Subject, Pos) -> byte() when
+ Subject :: binary(),
+ Pos :: non_neg_integer().
+
+at(_, _) ->
+ erlang:nif_error(undef).
+
+-spec bin_to_list(Subject) -> [byte()] when
+ Subject :: binary().
+
+bin_to_list(_) ->
+ erlang:nif_error(undef).
+
+-spec bin_to_list(Subject, PosLen) -> [byte()] when
+ Subject :: binary(),
+ PosLen :: part().
+
+bin_to_list(_, _) ->
+ erlang:nif_error(undef).
+
+-spec bin_to_list(Subject, Pos, Len) -> [byte()] when
+ Subject :: binary(),
+ Pos :: non_neg_integer(),
+ Len :: non_neg_integer().
+
+bin_to_list(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec compile_pattern(Pattern) -> cp() when
+ Pattern :: binary() | [binary()].
+
+compile_pattern(_) ->
+ erlang:nif_error(undef).
+
+-spec copy(Subject) -> binary() when
+ Subject :: binary().
+
+copy(_) ->
+ erlang:nif_error(undef).
+
+-spec copy(Subject, N) -> binary() when
+ Subject :: binary(),
+ N :: non_neg_integer().
+
+copy(_, _) ->
+ erlang:nif_error(undef).
+
+-spec decode_unsigned(Subject) -> Unsigned when
+ Subject :: binary(),
+ Unsigned :: non_neg_integer().
+
+decode_unsigned(_) ->
+ erlang:nif_error(undef).
+
+-spec decode_unsigned(Subject, Endianess) -> Unsigned when
+ Subject :: binary(),
+ Endianess :: big | little,
+ Unsigned :: non_neg_integer().
+
+decode_unsigned(_, _) ->
+ erlang:nif_error(undef).
+
+-spec encode_unsigned(Unsigned) -> binary() when
+ Unsigned :: non_neg_integer().
+
+encode_unsigned(_) ->
+ erlang:nif_error(undef).
+
+-spec encode_unsigned(Unsigned, Endianess) -> binary() when
+ Unsigned :: non_neg_integer(),
+ Endianess :: big | little.
+
+encode_unsigned(_, _) ->
+ erlang:nif_error(undef).
+
+-spec first(Subject) -> byte() when
+ Subject :: binary().
+
+first(_) ->
+ erlang:nif_error(undef).
+
+-spec last(Subject) -> byte() when
+ Subject :: binary().
+
+last(_) ->
+ erlang:nif_error(undef).
+
+-spec list_to_bin(ByteList) -> binary() when
+ ByteList :: iodata().
+
+list_to_bin(_) ->
+ erlang:nif_error(undef).
+
+-spec longest_common_prefix(Binaries) -> non_neg_integer() when
+ Binaries :: [binary()].
+
+longest_common_prefix(_) ->
+ erlang:nif_error(undef).
+
+-spec longest_common_suffix(Binaries) -> non_neg_integer() when
+ Binaries :: [binary()].
+
+longest_common_suffix(_) ->
+ erlang:nif_error(undef).
+
+-spec match(Subject, Pattern) -> Found | nomatch when
+ Subject :: binary(),
+ Pattern :: binary() | [binary()] | cp(),
+ Found :: part().
+
+match(_, _) ->
+ erlang:nif_error(undef).
+
+-spec match(Subject, Pattern, Options) -> Found | nomatch when
+ Subject :: binary(),
+ Pattern :: binary() | [binary()] | cp(),
+ Found :: part(),
+ Options :: [Option],
+ Option :: {scope, part()}.
+
+match(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec matches(Subject, Pattern) -> Found when
+ Subject :: binary(),
+ Pattern :: binary() | [binary()] | cp(),
+ Found :: [part()].
+
+matches(_, _) ->
+ erlang:nif_error(undef).
+
+-spec matches(Subject, Pattern, Options) -> Found when
+ Subject :: binary(),
+ Pattern :: binary() | [binary()] | cp(),
+ Found :: [part()],
+ Options :: [Option],
+ Option :: {scope, part()}.
+
+matches(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec part(Subject, PosLen) -> binary() when
+ Subject :: binary(),
+ PosLen :: part().
+
+part(_, _) ->
+ erlang:nif_error(undef).
+
+-spec part(Subject, Pos, Len) -> binary() when
+ Subject :: binary(),
+ Pos :: non_neg_integer(),
+ Len :: non_neg_integer().
+
+part(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec referenced_byte_size(Binary) -> non_neg_integer() when
+ Binary :: binary().
+
+referenced_byte_size(_) ->
+ erlang:nif_error(undef).
+
+%%% End of BIFs.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% split
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index c0f9ce34b0..6a937f8fa2 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -319,7 +319,7 @@ foldr(Fun, Acc, Tab) ->
foldl(Fun, Acc, Tab) ->
Ref = make_ref(),
- do_traverse(Fun, Acc, Tab, Ref).
+ badarg(do_traverse(Fun, Acc, Tab, Ref), [Fun, Acc, Tab]).
-spec from_ets(Name, EtsTab) -> 'ok' | {'error', Reason} when
Name :: tab_name(),
@@ -515,7 +515,7 @@ match(Tab, Pat) ->
Reason :: term().
match(Tab, Pat, N) ->
- badarg(init_chunk_match(Tab, Pat, bindings, N), [Tab, Pat, N]).
+ badarg(init_chunk_match(Tab, Pat, bindings, N, no_safe), [Tab, Pat, N]).
-spec match(Continuation) ->
{[Match], Continuation2} | '$end_of_table' | {'error', Reason} when
@@ -525,7 +525,7 @@ match(Tab, Pat, N) ->
Reason :: term().
match(State) when State#dets_cont.what =:= bindings ->
- badarg(chunk_match(State), [State]);
+ badarg(chunk_match(State, no_safe), [State]);
match(Term) ->
erlang:error(badarg, [Term]).
@@ -538,26 +538,26 @@ match_delete(Tab, Pat) ->
badarg(match_delete(Tab, Pat, delete), [Tab, Pat]).
match_delete(Tab, Pat, What) ->
- safe_fixtable(Tab, true),
case compile_match_spec(What, Pat) of
{Spec, MP} ->
- Proc = dets_server:get_pid(Tab),
- R = req(Proc, {match_delete_init, MP, Spec}),
- do_match_delete(Tab, Proc, R, What, 0);
+ case catch dets_server:get_pid(Tab) of
+ {'EXIT', _Reason} ->
+ badarg;
+ Proc ->
+ R = req(Proc, {match_delete_init, MP, Spec}),
+ do_match_delete(Proc, R, What, 0)
+ end;
badarg ->
badarg
end.
-do_match_delete(Tab, _Proc, {done, N1}, select, N) ->
- safe_fixtable(Tab, false),
+do_match_delete(_Proc, {done, N1}, select, N) ->
N + N1;
-do_match_delete(Tab, _Proc, {done, _N1}, _What, _N) ->
- safe_fixtable(Tab, false),
+do_match_delete(_Proc, {done, _N1}, _What, _N) ->
ok;
-do_match_delete(Tab, Proc, {cont, State, N1}, What, N) ->
- do_match_delete(Tab, Proc, req(Proc, {match_delete, State}), What, N+N1);
-do_match_delete(Tab, _Proc, Error, _What, _N) ->
- safe_fixtable(Tab, false),
+do_match_delete(Proc, {cont, State, N1}, What, N) ->
+ do_match_delete(Proc, req(Proc, {match_delete, State}), What, N+N1);
+do_match_delete(_Proc, Error, _What, _N) ->
Error.
-spec match_object(Name, Pattern) -> Objects | {'error', Reason} when
@@ -579,7 +579,7 @@ match_object(Tab, Pat) ->
Reason :: term().
match_object(Tab, Pat, N) ->
- badarg(init_chunk_match(Tab, Pat, object, N), [Tab, Pat, N]).
+ badarg(init_chunk_match(Tab, Pat, object, N, no_safe), [Tab, Pat, N]).
-spec match_object(Continuation) ->
{Objects, Continuation2} | '$end_of_table' | {'error', Reason} when
@@ -589,7 +589,7 @@ match_object(Tab, Pat, N) ->
Reason :: term().
match_object(State) when State#dets_cont.what =:= object ->
- badarg(chunk_match(State), [State]);
+ badarg(chunk_match(State, no_safe), [State]);
match_object(Term) ->
erlang:error(badarg, [Term]).
@@ -712,7 +712,7 @@ select(Tab, Pat) ->
Reason :: term().
select(Tab, Pat, N) ->
- badarg(init_chunk_match(Tab, Pat, select, N), [Tab, Pat, N]).
+ badarg(init_chunk_match(Tab, Pat, select, N, no_safe), [Tab, Pat, N]).
-spec select(Continuation) ->
{Selection, Continuation2} | '$end_of_table' | {'error', Reason} when
@@ -722,7 +722,7 @@ select(Tab, Pat, N) ->
Reason :: term().
select(State) when State#dets_cont.what =:= select ->
- badarg(chunk_match(State), [State]);
+ badarg(chunk_match(State, no_safe), [State]);
select(Term) ->
erlang:error(badarg, [Term]).
@@ -898,7 +898,7 @@ traverse(Tab, Fun) ->
throw({Ref, Other})
end
end,
- do_traverse(TFun, [], Tab, Ref).
+ badarg(do_traverse(TFun, [], Tab, Ref), [Tab, Fun]).
-spec update_counter(Name, Key, Increment) -> Result when
Name :: tab_name(),
@@ -929,20 +929,21 @@ where(Tab, Object) ->
badarg(treq(Tab, {where, Object}), [Tab, Object]).
do_traverse(Fun, Acc, Tab, Ref) ->
- safe_fixtable(Tab, true),
- Proc = dets_server:get_pid(Tab),
- try
- do_trav(Proc, Acc, Fun)
- catch {Ref, Result} ->
- Result
- after
- safe_fixtable(Tab, false)
+ case catch dets_server:get_pid(Tab) of
+ {'EXIT', _Reason} ->
+ badarg;
+ Proc ->
+ try
+ do_trav(Proc, Acc, Fun)
+ catch {Ref, Result} ->
+ Result
+ end
end.
do_trav(Proc, Acc, Fun) ->
{Spec, MP} = compile_match_spec(object, '_'),
%% MP not used
- case req(Proc, {match, MP, Spec, default}) of
+ case req(Proc, {match, MP, Spec, default, safe}) of
{cont, State} ->
do_trav(State, Proc, Acc, Fun);
Error ->
@@ -952,7 +953,7 @@ do_trav(Proc, Acc, Fun) ->
do_trav(#dets_cont{bin = eof}, _Proc, Acc, _Fun) ->
Acc;
do_trav(State, Proc, Acc, Fun) ->
- case req(Proc, {match_init, State}) of
+ case req(Proc, {match_init, State, safe}) of
{cont, {Bins, NewState}} ->
do_trav_bins(NewState, Proc, Acc, Fun, lists:reverse(Bins));
Error ->
@@ -972,44 +973,47 @@ do_trav_bins(State, Proc, Acc, Fun, [Bin | Bins]) ->
end.
safe_match(Tab, Pat, What) ->
- safe_fixtable(Tab, true),
- R = do_safe_match(init_chunk_match(Tab, Pat, What, default), []),
- safe_fixtable(Tab, false),
- R.
+ do_safe_match(init_chunk_match(Tab, Pat, What, default, safe), []).
do_safe_match({error, Error}, _L) ->
{error, Error};
do_safe_match({L, C}, LL) ->
- do_safe_match(chunk_match(C), L++LL);
+ do_safe_match(chunk_match(C, safe), L++LL);
do_safe_match('$end_of_table', L) ->
L;
do_safe_match(badarg, _L) ->
badarg.
%% What = object | bindings | select
-init_chunk_match(Tab, Pat, What, N) when is_integer(N), N >= 0;
- N =:= default ->
+init_chunk_match(Tab, Pat, What, N, Safe) when is_integer(N), N >= 0;
+ N =:= default ->
case compile_match_spec(What, Pat) of
{Spec, MP} ->
- Proc = dets_server:get_pid(Tab),
- case req(Proc, {match, MP, Spec, N}) of
- {done, L} ->
- {L, #dets_cont{tab = Tab, proc = Proc, what = What,
- bin = eof}};
- {cont, State} ->
- chunk_match(State#dets_cont{what = What, tab = Tab,
- proc = Proc});
- Error ->
- Error
+ case catch dets_server:get_pid(Tab) of
+ {'EXIT', _Reason} ->
+ badarg;
+ Proc ->
+ case req(Proc, {match, MP, Spec, N, Safe}) of
+ {done, L} ->
+ {L, #dets_cont{tab = Tab, proc = Proc,
+ what = What, bin = eof}};
+ {cont, State} ->
+ chunk_match(State#dets_cont{what = What,
+ tab = Tab,
+ proc = Proc},
+ Safe);
+ Error ->
+ Error
+ end
end;
badarg ->
badarg
end;
-init_chunk_match(_Tab, _Pat, _What, _) ->
+init_chunk_match(_Tab, _Pat, _What, _N, _Safe) ->
badarg.
-chunk_match(#dets_cont{proc = Proc}=State) ->
- case req(Proc, {match_init, State}) of
+chunk_match(#dets_cont{proc = Proc}=State, Safe) ->
+ case req(Proc, {match_init, State, Safe}) of
'$end_of_table'=Reply ->
Reply;
{cont, {Bins, NewState}} ->
@@ -1024,7 +1028,7 @@ chunk_match(#dets_cont{proc = Proc}=State) ->
badarg
end;
[] ->
- chunk_match(NewState);
+ chunk_match(NewState, Safe);
Terms ->
{Terms, NewState}
end;
@@ -1301,7 +1305,7 @@ open_file_loop(Head, N) ->
%% - wait 1 ms after each update.
%% next is normally followed by lookup, but since lookup is also
%% used when not traversing the table, it is not prioritized.
- ?DETS_CALL(From, {match_init, _State} = Op) ->
+ ?DETS_CALL(From, {match_init, _State, _Safe} = Op) ->
do_apply_op(Op, From, Head, N);
?DETS_CALL(From, {bchunk, _State} = Op) ->
do_apply_op(Op, From, Head, N);
@@ -1558,12 +1562,17 @@ apply_op(Op, From, Head, N) ->
H2;
{lookup_keys, _Keys} ->
stream_op(Op, From, [], Head, N);
- {match_init, State} ->
- {H2, Res} = fmatch_init(Head, State),
+ {match_init, State, Safe} ->
+ {H1, Res} = fmatch_init(Head, State),
+ H2 = case Res of
+ {cont,_} -> H1;
+ _ when Safe =:= no_safe-> H1;
+ _ when Safe =:= safe -> do_safe_fixtable(H1, From, false)
+ end,
From ! {self(), Res},
H2;
- {match, MP, Spec, NObjs} ->
- {H2, Res} = fmatch(Head, MP, Spec, NObjs),
+ {match, MP, Spec, NObjs, Safe} ->
+ {H2, Res} = fmatch(Head, MP, Spec, NObjs, Safe, From),
From ! {self(), Res},
H2;
{member, Key} when Head#head.version =:= 8 ->
@@ -1577,11 +1586,15 @@ apply_op(Op, From, Head, N) ->
From ! {self(), Res},
H2;
{match_delete, State} when Head#head.update_mode =:= dirty ->
- {H2, Res} = fmatch_delete(Head, State),
+ {H1, Res} = fmatch_delete(Head, State),
+ H2 = case Res of
+ {cont,_S,_N} -> H1;
+ _ -> do_safe_fixtable(H1, From, false)
+ end,
From ! {self(), Res},
{N + 1, H2};
{match_delete_init, MP, Spec} when Head#head.update_mode =:= dirty ->
- {H2, Res} = fmatch_delete_init(Head, MP, Spec),
+ {H2, Res} = fmatch_delete_init(Head, MP, Spec, From),
From ! {self(), Res},
{N + 1, H2};
{safe_fixtable, Bool} ->
@@ -2229,13 +2242,18 @@ fmatch_init(Head, C) ->
end.
%% -> {NewHead, Result}
-fmatch(Head, MP, Spec, N) ->
+fmatch(Head, MP, Spec, N, Safe, From) ->
KeyPos = Head#head.keypos,
case find_all_keys(Spec, KeyPos, []) of
[] ->
%% Complete match
case catch write_cache(Head) of
- {NewHead, []} ->
+ {Head1, []} ->
+ NewHead =
+ case Safe of
+ safe -> do_safe_fixtable(Head1, From, true);
+ no_safe -> Head1
+ end,
C0 = init_scan(NewHead, N),
{NewHead, {cont, C0#dets_cont{match_program = MP}}};
{NewHead, _} = HeadError when is_record(NewHead, head) ->
@@ -2300,12 +2318,12 @@ contains_variable(_) ->
false.
%% -> {NewHead, Res}
-fmatch_delete_init(Head, MP, Spec) ->
+fmatch_delete_init(Head, MP, Spec, From) ->
KeyPos = Head#head.keypos,
case catch
case find_all_keys(Spec, KeyPos, []) of
[] ->
- do_fmatch_delete_var_keys(Head, MP, Spec);
+ do_fmatch_delete_var_keys(Head, MP, Spec, From);
List ->
Keys = lists:usort(List),
do_fmatch_constant_keys(Head, Keys, MP)
@@ -2336,7 +2354,7 @@ fmatch_delete(Head, C) ->
end
end.
-do_fmatch_delete_var_keys(Head, _MP, ?PATTERN_TO_TRUE_MATCH_SPEC('_'))
+do_fmatch_delete_var_keys(Head, _MP, ?PATTERN_TO_TRUE_MATCH_SPEC('_'), _From)
when Head#head.fixed =:= false ->
%% Handle the case where the file is emptied efficiently.
%% Empty the cache just to get the number of objects right.
@@ -2348,8 +2366,9 @@ do_fmatch_delete_var_keys(Head, _MP, ?PATTERN_TO_TRUE_MATCH_SPEC('_'))
Reply ->
Reply
end;
-do_fmatch_delete_var_keys(Head, MP, _Spec) ->
- {NewHead, []} = write_cache(Head),
+do_fmatch_delete_var_keys(Head, MP, _Spec, From) ->
+ Head1 = do_safe_fixtable(Head, From, true),
+ {NewHead, []} = write_cache(Head1),
C0 = init_scan(NewHead, default),
{NewHead, {cont, C0#dets_cont{match_program = MP}, 0}}.
diff --git a/lib/stdlib/src/digraph_utils.erl b/lib/stdlib/src/digraph_utils.erl
index e221be15a1..807b5c12a1 100644
--- a/lib/stdlib/src/digraph_utils.erl
+++ b/lib/stdlib/src/digraph_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. 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
@@ -370,5 +370,5 @@ condense('$end_of_table', _T, _SC, _G, _SCG, _I2C) ->
condense(I, T, SC, G, SCG, I2C) ->
[{_,C}] = ets:lookup(I2C, I),
digraph:add_vertex(SCG, C),
- digraph:add_edge(SCG, SC, C),
+ [digraph:add_edge(SCG, SC, C) || C =/= SC],
condense(ets:next(T, I), T, SC, G, SCG, I2C).
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index ccc14610d7..2c8d84a9e1 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index ff032b129c..81bec21a3f 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. 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
@@ -57,17 +57,7 @@ compile_cmdline(List) ->
end.
my_halt(Reason) ->
- case process_info(group_leader(), status) of
- {_,waiting} ->
- %% Now all output data is down in the driver.
- %% Give the driver some extra time before halting.
- receive after 1 -> ok end,
- halt(Reason);
- _ ->
- %% Probably still processing I/O requests.
- erlang:yield(),
- my_halt(Reason)
- end.
+ erlang:halt(Reason).
%% Run the the compiler in a separate process, trapping EXITs.
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index bf3c7b3504..95ba6b1096 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -947,7 +947,6 @@ type_test(integer) -> is_integer;
type_test(float) -> is_float;
type_test(number) -> is_number;
type_test(atom) -> is_atom;
-type_test(constant) -> is_constant;
type_test(list) -> is_list;
type_test(tuple) -> is_tuple;
type_test(pid) -> is_pid;
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index 1c69a131f9..9759a8f001 100644
--- a/lib/stdlib/src/erl_expand_records.erl
+++ b/lib/stdlib/src/erl_expand_records.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. 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
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index cd3b531d10..3063881890 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2012. 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
@@ -287,6 +287,7 @@ bif(group_leader, 0) -> true;
bif(group_leader, 2) -> true;
bif(halt, 0) -> true;
bif(halt, 1) -> true;
+bif(halt, 2) -> true;
bif(hd, 1) -> true;
bif(integer_to_list, 1) -> true;
bif(integer_to_list, 2) -> true;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index cfbcf54d95..1e5f962375 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -248,6 +248,8 @@ format_error({illegal_guard_local_call, {F,A}}) ->
io_lib:format("call to local/imported function ~w/~w is illegal in guard",
[F,A]);
format_error(illegal_guard_expr) -> "illegal guard expression";
+format_error(deprecated_tuple_fun) ->
+ "tuple funs are deprecated and will be removed in R16";
%% --- exports ---
format_error({explicit_export,F,A}) ->
io_lib:format("in this release, the call to ~w/~w must be written "
@@ -363,6 +365,12 @@ format_error(callback_wrong_arity) ->
format_error({imported_predefined_type, Name}) ->
io_lib:format("referring to built-in type ~w as a remote type; "
"please take out the module name", [Name]);
+format_error({not_exported_opaque, {TypeName, Arity}}) ->
+ io_lib:format("opaque type ~w~s is not exported",
+ [TypeName, gen_type_paren(Arity)]);
+format_error({underspecified_opaque, {TypeName, Arity}}) ->
+ io_lib:format("opaque type ~w~s is underspecified and therefore meaningless",
+ [TypeName, gen_type_paren(Arity)]);
%% --- obsolete? unused? ---
format_error({format_error, {Fmt, Args}}) ->
io_lib:format(Fmt, Args);
@@ -849,7 +857,8 @@ post_traversal_check(Forms, St0) ->
StC = check_untyped_records(Forms, StB),
StD = check_on_load(StC),
StE = check_unused_records(Forms, StD),
- check_callback_information(StE).
+ StF = check_local_opaque_types(StE),
+ check_callback_information(StF).
%% check_behaviour(State0) -> State
%% Check that the behaviour attribute is valid.
@@ -1914,8 +1923,6 @@ gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,F}},As}, Vt, St0) ->
true -> {Asvt,St1};
false -> {Asvt,add_error(Line, illegal_guard_expr, St1)}
end;
-gexpr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,F}]},As}, Vt, St) ->
- gexpr({call,L,{remote,Lt,{atom,Lm,erlang},{atom,Lf,F}},As}, Vt, St);
gexpr({op,Line,Op,A}, Vt, St0) ->
{Avt,St1} = gexpr(A, Vt, St0),
case is_gexpr_op(Op, 1) of
@@ -2554,15 +2561,24 @@ find_field(_F, []) -> error.
%% Attr :: 'type' | 'opaque'
%% Checks that a type definition is valid.
+-record(typeinfo, {attr, line}).
+
type_def(_Attr, _Line, {record, _RecName}, Fields, [], St0) ->
%% The record field names and such are checked in the record format.
%% We only need to check the types.
Types = [T || {typed_record_field, _, T} <- Fields],
check_type({type, -1, product, Types}, St0);
-type_def(_Attr, Line, TypeName, ProtoType, Args, St0) ->
+type_def(Attr, Line, TypeName, ProtoType, Args, St0) ->
TypeDefs = St0#lint.types,
Arity = length(Args),
TypePair = {TypeName, Arity},
+ Info = #typeinfo{attr = Attr, line = Line},
+ StoreType =
+ fun(St) ->
+ NewDefs = dict:store(TypePair, Info, TypeDefs),
+ CheckType = {type, -1, product, [ProtoType|Args]},
+ check_type(CheckType, St#lint{types=NewDefs})
+ end,
case (dict:is_key(TypePair, TypeDefs) orelse is_var_arity_type(TypeName)) of
true ->
case dict:is_key(TypePair, default_types()) of
@@ -2572,20 +2588,29 @@ type_def(_Attr, Line, TypeName, ProtoType, Args, St0) ->
true ->
Warn = {new_builtin_type, TypePair},
St1 = add_warning(Line, Warn, St0),
- NewDefs = dict:store(TypePair, Line, TypeDefs),
- CheckType = {type, -1, product, [ProtoType|Args]},
- check_type(CheckType, St1#lint{types=NewDefs});
+ StoreType(St1);
false ->
add_error(Line, {builtin_type, TypePair}, St0)
end;
false -> add_error(Line, {redefine_type, TypePair}, St0)
end;
false ->
- NewDefs = dict:store(TypePair, Line, TypeDefs),
- CheckType = {type, -1, product, [ProtoType|Args]},
- check_type(CheckType, St0#lint{types=NewDefs})
+ St1 = case
+ Attr =:= opaque andalso
+ is_underspecified(ProtoType, Arity)
+ of
+ true ->
+ Warn = {underspecified_opaque, TypePair},
+ add_warning(Line, Warn, St0);
+ false -> St0
+ end,
+ StoreType(St1)
end.
+is_underspecified({type,_,term,[]}, 0) -> true;
+is_underspecified({type,_,any,[]}, 0) -> true;
+is_underspecified(_ProtType, _Arity) -> false.
+
check_type(Types, St) ->
{SeenVars, St1} = check_type(Types, dict:new(), St),
dict:fold(fun(Var, {seen_once, Line}, AccSt) ->
@@ -2895,7 +2920,7 @@ check_unused_types(Forms, #lint{usage=Usage, types=Ts, exp_types=ExpTs}=St) ->
fun(_Type, -1, AccSt) ->
%% Default type
AccSt;
- (Type, FileLine, AccSt) ->
+ (Type, #typeinfo{line = FileLine}, AccSt) ->
case loc(FileLine) of
{FirstFile, _} ->
case gb_sets:is_member(Type, UsedTypes) of
@@ -2914,6 +2939,24 @@ check_unused_types(Forms, #lint{usage=Usage, types=Ts, exp_types=ExpTs}=St) ->
St
end.
+check_local_opaque_types(St) ->
+ #lint{types=Ts, exp_types=ExpTs} = St,
+ FoldFun =
+ fun(_Type, -1, AccSt) ->
+ %% Default type
+ AccSt;
+ (_Type, #typeinfo{attr = type}, AccSt) ->
+ AccSt;
+ (Type, #typeinfo{attr = opaque, line = FileLine}, AccSt) ->
+ case gb_sets:is_element(Type, ExpTs) of
+ true -> AccSt;
+ false ->
+ Warn = {not_exported_opaque,Type},
+ add_warning(FileLine, Warn, AccSt)
+ end
+ end,
+ dict:fold(FoldFun, St, Ts).
+
%% icrt_clauses(Clauses, In, ImportVarTable, State) ->
%% {NewVts,State}.
@@ -3436,17 +3479,11 @@ obsolete_guard({call,Line,{atom,Lr,F},As}, St0) ->
false ->
deprecated_function(Line, erlang, F, As, St0);
true ->
- St1 = case F of
- constant ->
- deprecated_function(Lr, erlang, is_constant, As, St0);
- _ ->
- St0
- end,
- case is_warn_enabled(obsolete_guard, St1) of
+ case is_warn_enabled(obsolete_guard, St0) of
true ->
- add_warning(Lr,{obsolete_guard, {F, Arity}}, St1);
+ add_warning(Lr,{obsolete_guard, {F, Arity}}, St0);
false ->
- St1
+ St0
end
end;
obsolete_guard(_G, St) ->
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl
index 10b2ed2e49..8e59e01f48 100644
--- a/lib/stdlib/src/erl_scan.erl
+++ b/lib/stdlib/src/erl_scan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl
index 08f1873803..e9364ed787 100644
--- a/lib/stdlib/src/error_logger_file_h.erl
+++ b/lib/stdlib/src/error_logger_file_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl
index 48e069a407..ad5891f191 100644
--- a/lib/stdlib/src/error_logger_tty_h.erl
+++ b/lib/stdlib/src/error_logger_tty_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index ad49d89908..498d850df3 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. 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
@@ -22,7 +22,7 @@
-export([script_name/0, create/2, extract/2]).
%% Internal API.
--export([start/0, start/1]).
+-export([start/0, start/1, parse_file/1]).
%%-----------------------------------------------------------------------
@@ -346,7 +346,8 @@ parse_and_run(File, Args, Options) ->
case Source of
archive ->
{ok, FileInfo} = file:read_file_info(File),
- case code:set_primary_archive(File, FormsOrBin, FileInfo) of
+ case code:set_primary_archive(File, FormsOrBin, FileInfo,
+ fun escript:parse_file/1) of
ok when CheckOnly ->
case code:load_file(Module) of
{module, _} ->
@@ -396,6 +397,19 @@ parse_and_run(File, Args, Options) ->
%% Parse script
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Only used as callback by erl_prim_loader
+parse_file(File) ->
+ try parse_file(File, false) of
+ {_Source, _Module, FormsOrBin, _HasRecs, _Mode}
+ when is_binary(FormsOrBin) ->
+ {ok, FormsOrBin};
+ _ ->
+ {error, no_archive_bin}
+ catch
+ throw:Reason ->
+ {error, Reason}
+ end.
+
parse_file(File, CheckOnly) ->
{HeaderSz, NextLineNo, Fd, Sections} =
parse_header(File, false),
@@ -848,17 +862,7 @@ fatal(Str) ->
throw(Str).
my_halt(Reason) ->
- case process_info(group_leader(), status) of
- {_,waiting} ->
- %% Now all output data is down in the driver.
- %% Give the driver some extra time before halting.
- receive after 1 -> ok end,
- halt(Reason);
- _ ->
- %% Probably still processing I/O requests.
- erlang:yield(),
- my_halt(Reason)
- end.
+ erlang:halt(Reason).
hidden_apply(App, M, F, Args) ->
try
diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl
index afa914a456..ee6cff1b75 100644
--- a/lib/stdlib/src/ets.erl
+++ b/lib/stdlib/src/ets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -42,11 +42,16 @@
-export([i/0, i/1, i/2, i/3]).
--export_type([tab/0, tid/0, match_spec/0]).
+-export_type([tab/0, tid/0, match_spec/0, comp_match_spec/0]).
%%-----------------------------------------------------------------------------
+-type access() :: public | protected | private.
-type tab() :: atom() | tid().
+-type type() :: set | ordered_set | bag | duplicate_bag.
+-type continuation() :: '$end_of_table'
+ | {tab(),integer(),integer(),binary(),list(),integer()}
+ | {tab(),_,_,integer(),binary(),list(),integer(),integer()}.
%% a similar definition is also in erl_types
-opaque tid() :: integer().
@@ -57,59 +62,398 @@
%%-----------------------------------------------------------------------------
-%% The following functions used to be found in this module, but
-%% are now BIFs (i.e. implemented in C).
-%%
-%% all/0
-%% new/2
-%% delete/1
-%% delete/2
-%% first/1
-%% info/1
-%% info/2
-%% safe_fixtable/2
-%% lookup/2
-%% lookup_element/3
-%% insert/2
-%% is_compiled_ms/1
-%% last/1
-%% member/2
-%% next/2
-%% prev/2
-%% rename/2
-%% slot/2
-%% match/1
-%% match/2
-%% match/3
-%% match_object/1
-%% match_object/2
-%% match_object/3
-%% match_spec_compile/1
-%% match_spec_run_r/3
-%% select/1
-%% select/2
-%% select/3
-%% select_count/2
-%% select_reverse/1
-%% select_reverse/2
-%% select_reverse/3
-%% select_delete/2
-%% setopts/2
-%% update_counter/3
-%% update_element/3
-%%
+%%% BIFs
+
+-export([all/0, delete/1, delete/2, delete_all_objects/1,
+ delete_object/2, first/1, give_away/3, info/1, info/2,
+ insert/2, insert_new/2, is_compiled_ms/1, last/1, lookup/2,
+ lookup_element/3, match/1, match/2, match/3, match_object/1,
+ match_object/2, match_object/3, match_spec_compile/1,
+ match_spec_run_r/3, member/2, new/2, next/2, prev/2,
+ rename/2, safe_fixtable/2, select/1, select/2, select/3,
+ select_count/2, select_delete/2, select_reverse/1,
+ select_reverse/2, select_reverse/3, setopts/2, slot/2,
+ update_counter/3, update_element/3]).
+
+-spec all() -> [Tab] when
+ Tab :: tab().
+
+all() ->
+ erlang:nif_error(undef).
+
+-spec delete(Tab) -> true when
+ Tab :: tab().
+
+delete(_) ->
+ erlang:nif_error(undef).
+
+-spec delete(Tab, Key) -> true when
+ Tab :: tab(),
+ Key :: term().
+
+delete(_, _) ->
+ erlang:nif_error(undef).
+
+-spec delete_all_objects(Tab) -> true when
+ Tab :: tab().
+
+delete_all_objects(_) ->
+ erlang:nif_error(undef).
+
+-spec delete_object(Tab, Object) -> true when
+ Tab :: tab(),
+ Object :: tuple().
+
+delete_object(_, _) ->
+ erlang:nif_error(undef).
+
+-spec first(Tab) -> Key | '$end_of_table' when
+ Tab :: tab(),
+ Key :: term().
+
+first(_) ->
+ erlang:nif_error(undef).
+
+-spec give_away(Tab, Pid, GiftData) -> true when
+ Tab :: tab(),
+ Pid :: pid(),
+ GiftData :: term().
+
+give_away(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec info(Tab) -> InfoList | undefined when
+ Tab :: tab(),
+ InfoList :: [InfoTuple],
+ InfoTuple :: {compressed, boolean()}
+ | {heir, pid() | none}
+ | {keypos, pos_integer()}
+ | {memory, non_neg_integer()}
+ | {name, atom()}
+ | {named_table, boolean()}
+ | {node, node()}
+ | {owner, pid()}
+ | {protection, access()}
+ | {size, non_neg_integer()}
+ | {type, type()}.
+
+info(_) ->
+ erlang:nif_error(undef).
+
+-spec info(Tab, Item) -> Value | undefined when
+ Tab :: tab(),
+ Item :: compressed | fixed | heir | keypos | memory
+ | name | named_table | node | owner | protection
+ | safe_fixed | size | stats | type,
+ Value :: term().
+
+info(_, _) ->
+ erlang:nif_error(undef).
+
+-spec insert(Tab, ObjectOrObjects) -> true when
+ Tab :: tab(),
+ ObjectOrObjects :: tuple() | [tuple()].
+
+insert(_, _) ->
+ erlang:nif_error(undef).
+
+-spec insert_new(Tab, ObjectOrObjects) -> boolean() when
+ Tab :: tab(),
+ ObjectOrObjects :: tuple() | [tuple()].
+
+insert_new(_, _) ->
+ erlang:nif_error(undef).
+
+-spec is_compiled_ms(Term) -> boolean() when
+ Term :: term().
+
+is_compiled_ms(_) ->
+ erlang:nif_error(undef).
+
+-spec last(Tab) -> Key | '$end_of_table' when
+ Tab :: tab(),
+ Key :: term().
+
+last(_) ->
+ erlang:nif_error(undef).
+
+-spec lookup(Tab, Key) -> [Object] when
+ Tab :: tab(),
+ Key :: term(),
+ Object :: tuple().
+
+lookup(_, _) ->
+ erlang:nif_error(undef).
+
+-spec lookup_element(Tab, Key, Pos) -> Elem when
+ Tab :: tab(),
+ Key :: term(),
+ Pos :: pos_integer(),
+ Elem :: term() | [term()].
+
+lookup_element(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec match(Tab, Pattern) -> [Match] when
+ Tab :: tab(),
+ Pattern :: match_pattern(),
+ Match :: [term()].
+
+match(_, _) ->
+ erlang:nif_error(undef).
+
+-spec match(Tab, Pattern, Limit) -> {[Match], Continuation} |
+ '$end_of_table' when
+ Tab :: tab(),
+ Pattern :: match_pattern(),
+ Limit :: pos_integer(),
+ Match :: [term()],
+ Continuation :: continuation().
+
+match(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec match(Continuation) -> {[Match], Continuation} |
+ '$end_of_table' when
+ Match :: [term()],
+ Continuation :: continuation().
+
+match(_) ->
+ erlang:nif_error(undef).
+
+-spec match_object(Tab, Pattern) -> [Object] when
+ Tab :: tab(),
+ Pattern :: match_pattern(),
+ Object :: tuple().
+
+match_object(_, _) ->
+ erlang:nif_error(undef).
+
+-spec match_object(Tab, Pattern, Limit) -> {[Match], Continuation} |
+ '$end_of_table' when
+ Tab :: tab(),
+ Pattern :: match_pattern(),
+ Limit :: pos_integer(),
+ Match :: [term()],
+ Continuation :: continuation().
+
+match_object(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec match_object(Continuation) -> {[Match], Continuation} |
+ '$end_of_table' when
+ Match :: [term()],
+ Continuation :: continuation().
+
+match_object(_) ->
+ erlang:nif_error(undef).
+
+-spec match_spec_compile(MatchSpec) -> CompiledMatchSpec when
+ MatchSpec :: match_spec(),
+ CompiledMatchSpec :: comp_match_spec().
--opaque comp_match_spec() :: any(). %% this one is REALLY opaque
+match_spec_compile(_) ->
+ erlang:nif_error(undef).
--spec match_spec_run([tuple()], comp_match_spec()) -> [term()].
+-spec match_spec_run_r(List, CompiledMatchSpec, list()) -> list() when
+ List :: [tuple()],
+ CompiledMatchSpec :: comp_match_spec().
+
+match_spec_run_r(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec member(Tab, Key) -> boolean() when
+ Tab :: tab(),
+ Key :: term().
+
+member(_, _) ->
+ erlang:nif_error(undef).
+
+-spec new(Name, Options) -> tid() | atom() when
+ Name :: atom(),
+ Options :: [Option],
+ Option :: Type | Access | named_table | {keypos,Pos}
+ | {heir, Pid :: pid(), HeirData} | {heir, none} | Tweaks,
+ Type :: type(),
+ Access :: access(),
+ Tweaks :: {write_concurrency, boolean()}
+ | {read_concurrency, boolean()}
+ | compressed,
+ Pos :: pos_integer(),
+ HeirData :: term().
+
+new(_, _) ->
+ erlang:nif_error(undef).
+
+-spec next(Tab, Key1) -> Key2 | '$end_of_table' when
+ Tab :: tab(),
+ Key1 :: term(),
+ Key2 :: term().
+
+next(_, _) ->
+ erlang:nif_error(undef).
+
+-spec prev(Tab, Key1) -> Key2 | '$end_of_table' when
+ Tab :: tab(),
+ Key1 :: term(),
+ Key2 :: term().
+
+prev(_, _) ->
+ erlang:nif_error(undef).
+
+%% Shadowed by erl_bif_types: ets:rename/2
+-spec rename(Tab, Name) -> Name when
+ Tab :: tab(),
+ Name :: atom().
+
+rename(_, _) ->
+ erlang:nif_error(undef).
+
+-spec safe_fixtable(Tab, Fix) -> true when
+ Tab :: tab(),
+ Fix :: boolean().
+
+safe_fixtable(_, _) ->
+ erlang:nif_error(undef).
+
+-spec select(Tab, MatchSpec) -> [Match] when
+ Tab :: tab(),
+ MatchSpec :: match_spec(),
+ Match :: term().
+
+select(_, _) ->
+ erlang:nif_error(undef).
+
+-spec select(Tab, MatchSpec, Limit) -> {[Match],Continuation} |
+ '$end_of_table' when
+ Tab :: tab(),
+ MatchSpec :: match_spec(),
+ Limit :: pos_integer(),
+ Match :: term(),
+ Continuation :: continuation().
+
+select(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec select(Continuation) -> {[Match],Continuation} | '$end_of_table' when
+ Match :: term(),
+ Continuation :: continuation().
+
+select(_) ->
+ erlang:nif_error(undef).
+
+-spec select_count(Tab, MatchSpec) -> NumMatched when
+ Tab :: tab(),
+ MatchSpec :: match_spec(),
+ NumMatched :: non_neg_integer().
+
+select_count(_, _) ->
+ erlang:nif_error(undef).
+
+-spec select_delete(Tab, MatchSpec) -> NumDeleted when
+ Tab :: tab(),
+ MatchSpec :: match_spec(),
+ NumDeleted :: non_neg_integer().
+
+select_delete(_, _) ->
+ erlang:nif_error(undef).
+
+-spec select_reverse(Tab, MatchSpec) -> [Match] when
+ Tab :: tab(),
+ MatchSpec :: match_spec(),
+ Match :: term().
+
+select_reverse(_, _) ->
+ erlang:nif_error(undef).
+
+-spec select_reverse(Tab, MatchSpec, Limit) -> {[Match],Continuation} |
+ '$end_of_table' when
+ Tab :: tab(),
+ MatchSpec :: match_spec(),
+ Limit :: pos_integer(),
+ Match :: term(),
+ Continuation :: continuation().
+
+select_reverse(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec select_reverse(Continuation) -> {[Match],Continuation} |
+ '$end_of_table' when
+ Continuation :: continuation(),
+ Match :: term().
+
+select_reverse(_) ->
+ erlang:nif_error(undef).
+
+-spec setopts(Tab, Opts) -> true when
+ Tab :: tab(),
+ Opts :: Opt | [Opt],
+ Opt :: {heir, pid(), HeirData} | {heir,none},
+ HeirData :: term().
+
+setopts(_, _) ->
+ erlang:nif_error(undef).
+
+-spec slot(Tab, I) -> [Object] | '$end_of_table' when
+ Tab :: tab(),
+ I :: non_neg_integer(),
+ Object :: tuple().
+
+slot(_, _) ->
+ erlang:nif_error(undef).
+
+-spec update_counter(Tab, Key, UpdateOp) -> Result when
+ Tab :: tab(),
+ Key :: term(),
+ UpdateOp :: {Pos, Incr} | {Pos, Incr, Threshold, SetValue},
+ Pos :: integer(),
+ Incr :: integer(),
+ Threshold :: integer(),
+ SetValue :: integer(),
+ Result :: integer();
+ (Tab, Key, [UpdateOp]) -> [Result] when
+ Tab :: tab(),
+ Key :: term(),
+ UpdateOp :: {Pos, Incr} | {Pos, Incr, Threshold, SetValue},
+ Pos :: integer(),
+ Incr :: integer(),
+ Threshold :: integer(),
+ SetValue :: integer(),
+ Result :: integer();
+ (Tab, Key, Incr) -> Result when
+ Tab :: tab(),
+ Key :: term(),
+ Incr :: integer(),
+ Result :: integer().
+
+update_counter(_, _, _) ->
+ erlang:nif_error(undef).
+
+-spec update_element(Tab, Key, ElementSpec :: {Pos, Value}) -> boolean() when
+ Tab :: tab(),
+ Key :: term(),
+ Pos :: pos_integer(),
+ Value :: term();
+ (Tab, Key, ElementSpec :: [{Pos, Value}]) -> boolean() when
+ Tab :: tab(),
+ Key :: term(),
+ Pos :: pos_integer(),
+ Value :: term().
+
+update_element(_, _, _) ->
+ erlang:nif_error(undef).
+
+%%% End of BIFs
+
+-opaque comp_match_spec() :: binary(). %% this one is REALLY opaque
+
+-spec match_spec_run(List, CompiledMatchSpec) -> list() when
+ List :: [tuple()],
+ CompiledMatchSpec :: comp_match_spec().
match_spec_run(List, CompiledMS) ->
lists:reverse(ets:match_spec_run_r(List, CompiledMS, [])).
--type continuation() :: '$end_of_table'
- | {tab(),integer(),integer(),binary(),list(),integer()}
- | {tab(),_,_,integer(),binary(),list(),integer(),integer()}.
-
-spec repair_continuation(Continuation, MatchSpec) -> Continuation when
Continuation :: continuation(),
MatchSpec :: match_spec().
diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl
index d532cea187..318f3b87b8 100644
--- a/lib/stdlib/src/filelib.erl
+++ b/lib/stdlib/src/filelib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. 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
@@ -132,6 +132,8 @@ do_wildcard_comp({compiled_wildcard,{exists,File}}, Mod) ->
{ok,_} -> [File];
_ -> []
end;
+do_wildcard_comp({compiled_wildcard,[cwd,Base|Rest]}, Mod) ->
+ do_wildcard_1([Base], Rest, Mod);
do_wildcard_comp({compiled_wildcard,[Base|Rest]}, Mod) ->
do_wildcard_1([Base], Rest, Mod).
@@ -143,7 +145,11 @@ do_wildcard_comp({compiled_wildcard,{exists,File}}, Cwd, Mod) ->
{ok,_} -> [File];
_ -> []
end;
-do_wildcard_comp({compiled_wildcard,[current|Rest]}, Cwd0, Mod) ->
+do_wildcard_comp({compiled_wildcard,[cwd|Rest0]}, Cwd0, Mod) ->
+ case Rest0 of
+ [current|Rest] -> ok;
+ Rest -> ok
+ end,
{Cwd,PrefixLen} = case filename:join([Cwd0]) of
Bin when is_binary(Bin) -> {Bin,byte_size(Bin)+1};
Other -> {Other,length(Other)+1}
@@ -264,6 +270,9 @@ ensure_dir(F) ->
case do_is_dir(Dir, file) of
true ->
ok;
+ false when Dir =:= F ->
+ %% Protect against infinite loop
+ {error,einval};
false ->
ensure_dir(Dir),
case file:make_dir(Dir) of
@@ -292,6 +301,8 @@ do_wildcard_2([File|Rest], Pattern, Result, Mod) ->
do_wildcard_2([], _, Result, _Mod) ->
Result.
+do_wildcard_3(Base, [[double_star]|Rest], Result, Mod) ->
+ lists:sort(do_double_star(current, [Base], Rest, Result, Mod, true));
do_wildcard_3(Base, [Pattern|Rest], Result, Mod) ->
case do_list_dir(Base, Mod) of
{ok, Files0} ->
@@ -325,6 +336,8 @@ wildcard_5([question|Rest1], [_|Rest2]) ->
wildcard_5(Rest1, Rest2);
wildcard_5([accept], _) ->
true;
+wildcard_5([double_star], _) ->
+ true;
wildcard_5([star|Rest], File) ->
do_star(Rest, File);
wildcard_5([{one_of, Ordset}|Rest], [C|File]) ->
@@ -345,6 +358,21 @@ wildcard_5([], [_|_]) ->
wildcard_5([_|_], []) ->
false.
+do_double_star(Base, [H|T], Rest, Result, Mod, Root) ->
+ Full = join(Base, H),
+ Result1 = case do_list_dir(Full, Mod) of
+ {ok, Files} ->
+ do_double_star(Full, Files, Rest, Result, Mod, false);
+ _ -> Result
+ end,
+ Result2 = case Root andalso Rest == [] of
+ true -> Result1;
+ false -> do_wildcard_3(Full, Rest, Result1, Mod)
+ end,
+ do_double_star(Base, T, Rest, Result2, Mod, Root);
+do_double_star(_Base, [], _Rest, Result, _Mod, _Root) ->
+ Result.
+
do_star(Pattern, [X|Rest]) ->
case wildcard_5(Pattern, [X|Rest]) of
true -> true;
@@ -380,7 +408,10 @@ compile_wildcard_1(Pattern) ->
[Root|Rest] = filename:split(Pattern),
case filename:pathtype(Root) of
relative ->
- compile_wildcard_2([Root|Rest], current);
+ case compile_wildcard_2([Root|Rest], current) of
+ {exists,_}=Wc -> Wc;
+ [_|_]=Wc -> [cwd|Wc]
+ end;
_ ->
compile_wildcard_2(Rest, [Root])
end.
@@ -413,6 +444,10 @@ compile_part([$}|Rest], true, Result) ->
{ok, $}, lists:reverse(Result), Rest};
compile_part([$?|Rest], Upto, Result) ->
compile_part(Rest, Upto, [question|Result]);
+compile_part([$*,$*], Upto, Result) ->
+ compile_part([], Upto, [double_star|Result]);
+compile_part([$*,$*|Rest], Upto, Result) ->
+ compile_part(Rest, Upto, [star|Result]);
compile_part([$*], Upto, Result) ->
compile_part([], Upto, [accept|Result]);
compile_part([$*|Rest], Upto, Result) ->
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index dbfcbea4f7..a6b42cc68c 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2012. 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
@@ -726,6 +726,8 @@ nativename(Name0) ->
_ -> Name
end.
+win32_nativename(Name) when is_binary(Name) ->
+ binary:replace(Name, <<"/">>, <<"\\">>, [global]);
win32_nativename([$/|Rest]) ->
[$\\|win32_nativename(Rest)];
win32_nativename([C|Rest]) ->
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index 5d803091b6..42555aedd7 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -36,7 +36,7 @@
%%-----------------------------------------------------------------
-type linkage() :: 'link' | 'nolink'.
--type emgr_name() :: {'local', atom()} | {'global', term()}.
+-type emgr_name() :: {'local', atom()} | {'global', term()} | {via, atom(), term()}.
-type start_ret() :: {'ok', pid()} | 'ignore' | {'error', term()}.
@@ -53,7 +53,7 @@
%% start(GenMod, LinkP, Name, Mod, Args, Options)
%% GenMod = atom(), callback module implementing the 'real' fsm
%% LinkP = link | nolink
-%% Name = {local, atom()} | {global, term()}
+%% Name = {local, atom()} | {global, term()} | {via, atom(), term()}
%% Args = term(), init arguments (to Mod:init/1)
%% Options = [{timeout, Timeout} | {debug, [Flag]} | {spawn_opt, OptionList}]
%% Flag = trace | log | {logfile, File} | statistics | debug
@@ -158,9 +158,12 @@ call(Name, Label, Request, Timeout)
exit(noproc)
end;
%% Global by name
-call({global, _Name}=Process, Label, Request, Timeout)
- when Timeout =:= infinity;
- is_integer(Timeout), Timeout >= 0 ->
+call(Process, Label, Request, Timeout)
+ when ((tuple_size(Process) == 2 andalso element(1, Process) == global)
+ orelse
+ (tuple_size(Process) == 3 andalso element(1, Process) == via))
+ andalso
+ (Timeout =:= infinity orelse (is_integer(Timeout) andalso Timeout >= 0)) ->
case where(Process) of
Pid when is_pid(Pid) ->
Node = node(Pid),
@@ -274,6 +277,7 @@ reply({To, Tag}, Reply) ->
%%% Misc. functions.
%%%-----------------------------------------------------------------
where({global, Name}) -> global:whereis_name(Name);
+where({via, Module, Name}) -> Module:whereis_name(Name);
where({local, Name}) -> whereis(Name).
name_register({local, Name} = LN) ->
@@ -287,8 +291,16 @@ name_register({global, Name} = GN) ->
case global:register_name(Name, self()) of
yes -> true;
no -> {false, where(GN)}
+ end;
+name_register({via, Module, Name} = GN) ->
+ case Module:register_name(Name, self()) of
+ yes ->
+ true;
+ no ->
+ {false, where(GN)}
end.
+
timeout(Options) ->
case opt(timeout, Options) of
{ok, Time} ->
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index 3317b30e5c..2b8ba86909 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -107,8 +107,10 @@
-type add_handler_ret() :: ok | term() | {'EXIT',term()}.
-type del_handler_ret() :: ok | term() | {'EXIT',term()}.
--type emgr_name() :: {'local', atom()} | {'global', atom()}.
--type emgr_ref() :: atom() | {atom(), atom()} | {'global', atom()} | pid().
+-type emgr_name() :: {'local', atom()} | {'global', atom()}
+ | {'via', atom(), term()}.
+-type emgr_ref() :: atom() | {atom(), atom()} | {'global', atom()}
+ | {'via', atom(), term()} | pid().
-type start_ret() :: {'ok', pid()} | {'error', term()}.
%%---------------------------------------------------------------------------
@@ -143,6 +145,7 @@ init_it(Starter, Parent, Name0, _, _, Options) ->
name({local,Name}) -> Name;
name({global,Name}) -> Name;
+name({via,_, Name}) -> Name;
name(Pid) when is_pid(Pid) -> Pid.
-spec add_handler(emgr_ref(), handler(), term()) -> term().
@@ -209,6 +212,9 @@ call1(M, Handler, Query, Timeout) ->
send({global, Name}, Cmd) ->
catch global:send(Name, Cmd),
ok;
+send({via, Mod, Name}, Cmd) ->
+ catch Mod:send(Name, Cmd),
+ ok;
send(M, Cmd) ->
M ! Cmd,
ok.
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index 57734a075c..e480e2ac11 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -165,7 +165,7 @@
%%% start(Name, Mod, Args, Options)
%%% start_link(Mod, Args, Options)
%%% start_link(Name, Mod, Args, Options) where:
-%%% Name ::= {local, atom()} | {global, atom()}
+%%% Name ::= {local, atom()} | {global, atom()} | {via, atom(), term()}
%%% Mod ::= atom(), callback module implementing the 'real' fsm
%%% Args ::= term(), init arguments (to Mod:init/1)
%%% Options ::= [{debug, [Flag]}]
@@ -191,6 +191,9 @@ start_link(Name, Mod, Args, Options) ->
send_event({global, Name}, Event) ->
catch global:send(Name, {'$gen_event', Event}),
ok;
+send_event({via, Mod, Name}, Event) ->
+ catch Mod:send(Name, {'$gen_event', Event}),
+ ok;
send_event(Name, Event) ->
Name ! {'$gen_event', Event},
ok.
@@ -214,6 +217,9 @@ sync_send_event(Name, Event, Timeout) ->
send_all_state_event({global, Name}, Event) ->
catch global:send(Name, {'$gen_all_state_event', Event}),
ok;
+send_all_state_event({via, Mod, Name}, Event) ->
+ catch Mod:send(Name, {'$gen_all_state_event', Event}),
+ ok;
send_all_state_event(Name, Event) ->
Name ! {'$gen_all_state_event', Event},
ok.
@@ -273,7 +279,10 @@ cancel_timer(Ref) ->
enter_loop(Mod, Options, StateName, StateData) ->
enter_loop(Mod, Options, StateName, StateData, self(), infinity).
-enter_loop(Mod, Options, StateName, StateData, ServerName = {_,_}) ->
+enter_loop(Mod, Options, StateName, StateData, {Scope,_} = ServerName)
+ when Scope == local; Scope == global ->
+ enter_loop(Mod, Options, StateName, StateData, ServerName,infinity);
+enter_loop(Mod, Options, StateName, StateData, {via,_,_} = ServerName) ->
enter_loop(Mod, Options, StateName, StateData, ServerName,infinity);
enter_loop(Mod, Options, StateName, StateData, Timeout) ->
enter_loop(Mod, Options, StateName, StateData, self(), Timeout).
@@ -303,6 +312,15 @@ get_proc_name({global, Name}) ->
Name;
_Pid ->
exit(process_not_registered_globally)
+ end;
+get_proc_name({via, Mod, Name}) ->
+ case Mod:whereis_name(Name) of
+ undefined ->
+ exit({process_not_registered_via, Mod});
+ Pid when Pid =:= self() ->
+ Name;
+ _Pid ->
+ exit({process_not_registered_via, Mod})
end.
get_parent() ->
@@ -320,7 +338,7 @@ name_to_pid(Name) ->
undefined ->
case global:whereis_name(Name) of
undefined ->
- exit(could_not_find_registerd_name);
+ exit(could_not_find_registered_name);
Pid ->
Pid
end;
@@ -367,12 +385,15 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
name({local,Name}) -> Name;
name({global,Name}) -> Name;
+name({via,_, Name}) -> Name;
name(Pid) when is_pid(Pid) -> Pid.
unregister_name({local,Name}) ->
_ = (catch unregister(Name));
unregister_name({global,Name}) ->
_ = global:unregister_name(Name);
+unregister_name({via, Mod, Name}) ->
+ _ = Mod:unregister_name(Name);
unregister_name(Pid) when is_pid(Pid) ->
Pid.
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index af07bc988a..04308a51b7 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -142,7 +142,7 @@
%%% start(Name, Mod, Args, Options)
%%% start_link(Mod, Args, Options)
%%% start_link(Name, Mod, Args, Options) where:
-%%% Name ::= {local, atom()} | {global, atom()}
+%%% Name ::= {local, atom()} | {global, atom()} | {via, atom(), term()}
%%% Mod ::= atom(), callback module implementing the 'real' server
%%% Args ::= term(), init arguments (to Mod:init/1)
%%% Options ::= [{timeout, Timeout} | {debug, [Flag]}]
@@ -194,6 +194,9 @@ call(Name, Request, Timeout) ->
cast({global,Name}, Request) ->
catch global:send(Name, cast_msg(Request)),
ok;
+cast({via, Mod, Name}, Request) ->
+ catch Mod:send(Name, cast_msg(Request)),
+ ok;
cast({Name,Node}=Dest, Request) when is_atom(Name), is_atom(Node) ->
do_cast(Dest, Request);
cast(Dest, Request) when is_atom(Dest) ->
@@ -266,7 +269,11 @@ multi_call(Nodes, Name, Req, Timeout)
enter_loop(Mod, Options, State) ->
enter_loop(Mod, Options, State, self(), infinity).
-enter_loop(Mod, Options, State, ServerName = {_, _}) ->
+enter_loop(Mod, Options, State, ServerName = {Scope, _})
+ when Scope == local; Scope == global ->
+ enter_loop(Mod, Options, State, ServerName, infinity);
+
+enter_loop(Mod, Options, State, ServerName = {via, _, _}) ->
enter_loop(Mod, Options, State, ServerName, infinity);
enter_loop(Mod, Options, State, Timeout) ->
@@ -327,12 +334,15 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
name({local,Name}) -> Name;
name({global,Name}) -> Name;
+name({via,_, Name}) -> Name;
name(Pid) when is_pid(Pid) -> Pid.
unregister_name({local,Name}) ->
_ = (catch unregister(Name));
unregister_name({global,Name}) ->
_ = global:unregister_name(Name);
+unregister_name({via, Mod, Name}) ->
+ _ = Mod:unregister_name(Name);
unregister_name(Pid) when is_pid(Pid) ->
Pid.
@@ -827,6 +837,15 @@ get_proc_name({global, Name}) ->
Name;
_Pid ->
exit(process_not_registered_globally)
+ end;
+get_proc_name({via, Mod, Name}) ->
+ case Mod:whereis_name(Name) of
+ undefined ->
+ exit({process_not_registered_via, Mod});
+ Pid when Pid =:= self() ->
+ Name;
+ _Pid ->
+ exit({process_not_registered_via, Mod})
end.
get_parent() ->
@@ -844,7 +863,7 @@ name_to_pid(Name) ->
undefined ->
case global:whereis_name(Name) of
undefined ->
- exit(could_not_find_registerd_name);
+ exit(could_not_find_registered_name);
Pid ->
Pid
end;
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index 0252cdf742..ab62b72519 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -82,7 +82,10 @@
-type chars() :: [char() | chars()].
-type depth() :: -1 | non_neg_integer().
--opaque continuation() :: {_, _, _, _}. % XXX: refine
+-opaque continuation() :: {Format :: string(),
+ Stack :: chars(),
+ Nchars :: non_neg_integer(),
+ Results :: [term()]}.
%%----------------------------------------------------------------------
diff --git a/lib/stdlib/src/lib.erl b/lib/stdlib/src/lib.erl
index 314fd60903..cf4b87d7eb 100644
--- a/lib/stdlib/src/lib.erl
+++ b/lib/stdlib/src/lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -209,7 +209,7 @@ explain_reason(badarg, error, [], _PF, _S) ->
explain_reason({badarg,V}, error=Cl, [], PF, S) -> % orelse, andalso
format_value(V, <<"bad argument: ">>, Cl, PF, S);
explain_reason(badarith, error, [], _PF, _S) ->
- <<"bad argument in an arithmetic expression">>;
+ <<"an error occurred when evaluating an arithmetic expression">>;
explain_reason({badarity,{Fun,As}}, error, [], _PF, _S)
when is_function(Fun) ->
%% Only the arity is displayed, not the arguments As.
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index e73c087753..961c060019 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -33,9 +33,6 @@
keysort/2, keymerge/3, rkeymerge/3, rukeymerge/3,
ukeysort/2, ukeymerge/3, keymap/3]).
-%% Bifs: member/2, reverse/2
-%% Bifs: keymember/3, keysearch/3, keyfind/3
-
-export([merge/3, rmerge/3, sort/2, umerge/3, rumerge/3, usort/2]).
-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,
@@ -43,6 +40,60 @@
mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2,
split/2]).
+%%% BIFs
+-export([keyfind/3, keymember/3, keysearch/3, member/2, reverse/2]).
+
+%% Shadowed by erl_bif_types: lists:keyfind/3
+-spec keyfind(Key, N, TupleList) -> Tuple | false when
+ Key :: term(),
+ N :: pos_integer(),
+ TupleList :: [Tuple],
+ Tuple :: tuple().
+
+keyfind(_, _, _) ->
+ erlang:nif_error(undef).
+
+%% Shadowed by erl_bif_types: lists:keymember/3
+-spec keymember(Key, N, TupleList) -> boolean() when
+ Key :: term(),
+ N :: pos_integer(),
+ TupleList :: [Tuple],
+ Tuple :: tuple().
+
+keymember(_, _, _) ->
+ erlang:nif_error(undef).
+
+%% Shadowed by erl_bif_types: lists:keysearch/3
+-spec keysearch(Key, N, TupleList) -> {value, Tuple} | false when
+ Key :: term(),
+ N :: pos_integer(),
+ TupleList :: [Tuple],
+ Tuple :: tuple().
+
+keysearch(_, _, _) ->
+ erlang:nif_error(undef).
+
+%% Shadowed by erl_bif_types: lists:member/2
+-spec member(Elem, List) -> boolean() when
+ Elem :: T,
+ List :: [T],
+ T :: term().
+
+member(_, _) ->
+ erlang:nif_error(undef).
+
+%% Shadowed by erl_bif_types: lists:reverse/2
+-spec reverse(List1, Tail) -> List2 when
+ List1 :: [T],
+ Tail :: term(),
+ List2 :: [T],
+ T :: term().
+
+reverse(_, _) ->
+ erlang:nif_error(undef).
+
+%%% End of BIFs
+
%% member(X, L) -> (true | false)
%% test if X is a member of the list L
%% Now a BIF!
@@ -84,7 +135,7 @@ append([]) -> [].
subtract(L1, L2) -> L1 -- L2.
-%% reverse(L) reverse all elements in the list L. Is now a BIF!
+%% reverse(L) reverse all elements in the list L. reverse/2 is now a BIF!
-spec reverse(List1) -> List2 when
List1 :: [T],
@@ -581,6 +632,7 @@ flatlength([_|T], L) ->
flatlength([], L) -> L.
%% keymember(Key, Index, [Tuple]) Now a BIF!
+%% keyfind(Key, Index, [Tuple]) A BIF!
%% keysearch(Key, Index, [Tuple]) Now a BIF!
%% keydelete(Key, Index, [Tuple])
%% keyreplace(Key, Index, [Tuple], NewTuple)
@@ -1126,8 +1178,7 @@ rumerge(T1, [H2 | T2]) ->
%% takewhile(Predicate, List)
%% dropwhile(Predicate, List)
%% splitwith(Predicate, List)
-%% for list programming. Function here is a 'fun'. For backward compatibility,
-%% {Module,Function} is still accepted.
+%% for list programming. Function here is a 'fun'.
%%
%% The name zf is a joke!
%%
diff --git a/lib/stdlib/src/math.erl b/lib/stdlib/src/math.erl
index b2ea6195c5..c3fb684ec3 100644
--- a/lib/stdlib/src/math.erl
+++ b/lib/stdlib/src/math.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -20,6 +20,116 @@
-export([pi/0]).
+%%% BIFs
+
+-export([sin/1, cos/1, tan/1, asin/1, acos/1, atan/1, atan2/2, sinh/1,
+ cosh/1, tanh/1, asinh/1, acosh/1, atanh/1, exp/1, log/1,
+ log10/1, pow/2, sqrt/1, erf/1, erfc/1]).
+
+-spec acos(X) -> float() when
+ X :: number().
+acos(_) ->
+ erlang:nif_error(undef).
+
+-spec acosh(X) -> float() when
+ X :: number().
+acosh(_) ->
+ erlang:nif_error(undef).
+
+-spec asin(X) -> float() when
+ X :: number().
+asin(_) ->
+ erlang:nif_error(undef).
+
+-spec asinh(X) -> float() when
+ X :: number().
+asinh(_) ->
+ erlang:nif_error(undef).
+
+-spec atan(X) -> float() when
+ X :: number().
+atan(_) ->
+ erlang:nif_error(undef).
+
+-spec atan2(X, Y) -> float() when
+ X :: number(),
+ Y :: number().
+atan2(_, _) ->
+ erlang:nif_error(undef).
+
+-spec atanh(X) -> float() when
+ X :: number().
+atanh(_) ->
+ erlang:nif_error(undef).
+
+-spec cos(X) -> float() when
+ X :: number().
+cos(_) ->
+ erlang:nif_error(undef).
+
+-spec cosh(X) -> float() when
+ X :: number().
+cosh(_) ->
+ erlang:nif_error(undef).
+
+-spec erf(X) -> float() when
+ X :: number().
+erf(_) ->
+ erlang:nif_error(undef).
+
+-spec erfc(X) -> float() when
+ X :: number().
+erfc(_) ->
+ erlang:nif_error(undef).
+
+-spec exp(X) -> float() when
+ X :: number().
+exp(_) ->
+ erlang:nif_error(undef).
+
+-spec log(X) -> float() when
+ X :: number().
+log(_) ->
+ erlang:nif_error(undef).
+
+-spec log10(X) -> float() when
+ X :: number().
+log10(_) ->
+ erlang:nif_error(undef).
+
+-spec pow(X, Y) -> float() when
+ X :: number(),
+ Y :: number().
+pow(_, _) ->
+ erlang:nif_error(undef).
+
+-spec sin(X) -> float() when
+ X :: number().
+sin(_) ->
+ erlang:nif_error(undef).
+
+-spec sinh(X) -> float() when
+ X :: number().
+sinh(_) ->
+ erlang:nif_error(undef).
+
+-spec sqrt(X) -> float() when
+ X :: number().
+sqrt(_) ->
+ erlang:nif_error(undef).
+
+-spec tan(X) -> float() when
+ X :: number().
+tan(_) ->
+ erlang:nif_error(undef).
+
+-spec tanh(X) -> float() when
+ X :: number().
+tanh(_) ->
+ erlang:nif_error(undef).
+
+%%% End of BIFs
+
-spec pi() -> float().
pi() -> 3.1415926535897932.
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index 63b397f3a5..4389fd457c 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -881,7 +881,6 @@ translate_language_element(Atom) ->
end.
old_bool_test(atom,1) -> is_atom;
-old_bool_test(constant,1) -> is_constant;
old_bool_test(float,1) -> is_float;
old_bool_test(integer,1) -> is_integer;
old_bool_test(list,1) -> is_list;
@@ -896,7 +895,6 @@ old_bool_test(record,2) -> is_record;
old_bool_test(_,_) -> undefined.
bool_test(is_atom,1) -> true;
-bool_test(is_constant,1) -> true;
bool_test(is_float,1) -> true;
bool_test(is_integer,1) -> true;
bool_test(is_list,1) -> true;
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 7bacc05ff2..cddf345c76 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. 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
@@ -337,11 +337,11 @@ obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 ->
%% Added in R14B03.
obsolete_1(docb_gen, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
obsolete_1(docb_transform, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
obsolete_1(docb_xml_check, _, _) ->
- {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"};
+ {removed,"the DocBuilder application was removed in R15B"};
%% Added in R15B
obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver ->
@@ -349,11 +349,19 @@ obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver ->
obsolete_1(ssl, pid, 1) ->
{deprecated,"deprecated (will be removed in R17); is no longer needed"};
obsolete_1(inviso, _, _) ->
- {deprecated,"the inviso application has been deprecated and will be removed in R16"};
+ {removed,"the inviso application was removed in R16"};
+
+%% Added in R15B01.
+obsolete_1(gs, _, _) ->
+ {deprecated,"the gs application has been deprecated and will be removed in R16; use the wx application instead"};
+obsolete_1(ssh, sign_data, 2) ->
+ {deprecated,"deprecated (will be removed in R16A); use public_key:pem_decode/1, public_key:pem_entry_decode/1 "
+ "and public_key:sign/3 instead"};
+obsolete_1(ssh, verify_data, 3) ->
+ {deprecated,"deprecated (will be removed in R16A); use public_key:ssh_decode/1, and public_key:verify/4 instead"};
obsolete_1(_, _, _) ->
no.
-
-spec is_snmp_agent_function(atom(), byte()) -> boolean().
is_snmp_agent_function(c, 1) -> true;
diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl
index 21504d707b..ad25fd559c 100644
--- a/lib/stdlib/src/qlc_pt.erl
+++ b/lib/stdlib/src/qlc_pt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2012. 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
@@ -2186,7 +2186,7 @@ try_ms(E, P, Fltr, State) ->
{function,L,foo,0,[{clause,L,[],[],[MS0]}]} = lists:last(X),
MS = erl_parse:normalise(var2const(MS0)),
XMS = ets:match_spec_compile(MS),
- true = is_binary(XMS),
+ true = ets:is_compiled_ms(XMS),
{ok, MS, MS0}
end of
{'EXIT', _Reason} ->
diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl
index 246d535943..c5109ec455 100644
--- a/lib/stdlib/src/re.erl
+++ b/lib/stdlib/src/re.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. 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
@@ -30,11 +30,65 @@
| {newline, nl_spec()}| bsr_anycrlf
| bsr_unicode.
-%% Emulator builtins in this module:
-%% re:compile/1
-%% re:compile/2
-%% re:run/2
-%% re:run/3
+%%% BIFs
+
+-export([compile/1, compile/2, run/2, run/3]).
+
+-spec compile(Regexp) -> {ok, MP} | {error, ErrSpec} when
+ Regexp :: iodata(),
+ MP :: mp(),
+ ErrSpec :: {ErrString :: string(), Position :: non_neg_integer()}.
+
+compile(_) ->
+ erlang:nif_error(undef).
+
+-spec compile(Regexp, Options) -> {ok, MP} | {error, ErrSpec} when
+ Regexp :: iodata() | unicode:charlist(),
+ Options :: [Option],
+ Option :: compile_option(),
+ MP :: mp(),
+ ErrSpec :: {ErrString :: string(), Position :: non_neg_integer()}.
+
+compile(_, _) ->
+ erlang:nif_error(undef).
+
+-spec run(Subject, RE) -> {match, Captured} | nomatch when
+ Subject :: iodata() | unicode:charlist(),
+ RE :: mp() | iodata(),
+ Captured :: [CaptureData],
+ CaptureData :: {integer(), integer()}.
+
+run(_, _) ->
+ erlang:nif_error(undef).
+
+-spec run(Subject, RE, Options) -> {match, Captured} |
+ match |
+ nomatch when
+ Subject :: iodata() | unicode:charlist(),
+ RE :: mp() | iodata() | unicode:charlist(),
+ Options :: [Option],
+ Option :: anchored | global | notbol | noteol | notempty
+ | {offset, non_neg_integer()} |
+ {newline, NLSpec :: nl_spec()} |
+ bsr_anycrlf | bsr_unicode | {capture, ValueSpec} |
+ {capture, ValueSpec, Type} | CompileOpt,
+ Type :: index | list | binary,
+ ValueSpec :: all | all_but_first | first | none | ValueList,
+ ValueList :: [ValueID],
+ ValueID :: integer() | string() | atom(),
+ CompileOpt :: compile_option(),
+ Captured :: [CaptureData] | [[CaptureData]],
+ CaptureData :: {integer(), integer()}
+ | ListConversionData
+ | binary(),
+ ListConversionData :: string()
+ | {error, string(), binary()}
+ | {incomplete, string(), binary()}.
+
+run(_, _, _) ->
+ erlang:nif_error(undef).
+
+%%% End of BIFs
-spec split(Subject, RE) -> SplitList when
Subject :: iodata() | unicode:charlist(),
@@ -355,6 +409,12 @@ apply_mlist(Subject,Replacement,Mlist) ->
precomp_repl(<<>>) ->
[];
+precomp_repl(<<$\\,$g,${,Rest/binary>>) when byte_size(Rest) > 0 ->
+ {NS, <<$},NRest/binary>>} = pick_int(Rest),
+ [list_to_integer(NS) | precomp_repl(NRest)];
+precomp_repl(<<$\\,$g,Rest/binary>>) when byte_size(Rest) > 0 ->
+ {NS,NRest} = pick_int(Rest),
+ [list_to_integer(NS) | precomp_repl(NRest)];
precomp_repl(<<$\\,X,Rest/binary>>) when X < $1 ; X > $9 ->
%% Escaped character
case precomp_repl(Rest) of
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 94e81188b5..55c8087475 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -17,11 +17,11 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max two major revisions back
- [{<<"1\\.18(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
- {<<"1\\.17(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14
- {<<"1\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R13
+ [{<<"1\\.19(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R16
+ {<<"1\\.18(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"1\\.17(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R14
%% Down to - max two major revisions back
- [{<<"1\\.18(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
- {<<"1\\.17(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14
- {<<"1\\.16(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R13
+ [{<<"1\\.19(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R16
+ {<<"1\\.18(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"1\\.17(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R14
}.
diff --git a/lib/stdlib/src/string.erl b/lib/stdlib/src/string.erl
index 30eac4f07d..fc029a582f 100644
--- a/lib/stdlib/src/string.erl
+++ b/lib/stdlib/src/string.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -29,6 +29,30 @@
%%---------------------------------------------------------------------------
+%%% BIFs
+
+-export([to_float/1, to_integer/1]).
+
+-spec to_float(String) -> {Float, Rest} | {error, Reason} when
+ String :: string(),
+ Float :: float(),
+ Rest :: string(),
+ Reason :: no_float | not_a_list.
+
+to_float(_) ->
+ erlang:nif_error(undef).
+
+-spec to_integer(String) -> {Int, Rest} | {error, Reason} when
+ String :: string(),
+ Int :: integer(),
+ Rest :: string(),
+ Reason :: no_integer | not_a_list.
+
+to_integer(_) ->
+ erlang:nif_error(undef).
+
+%%% End of BIFs
+
%% Robert's bit
%% len(String)
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index ac5b078c29..7d3c5a0e21 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2012. 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
@@ -28,8 +28,9 @@
check_childspecs/1]).
%% Internal exports
--export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]).
--export([handle_cast/2]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+-export([try_again_restart/2]).
%%--------------------------------------------------------------------------
@@ -37,7 +38,7 @@
%%--------------------------------------------------------------------------
--type child() :: 'undefined' | pid() | [pid()].
+-type child() :: 'undefined' | pid().
-type child_id() :: term().
-type mfargs() :: {M :: module(), F :: atom(), A :: [term()] | undefined}.
-type modules() :: [module()] | 'dynamic'.
@@ -62,8 +63,8 @@
%%--------------------------------------------------------------------------
-record(child, {% pid is undefined when child is not running
- pid = undefined :: child(),
- name,
+ pid = undefined :: child() | {restarting,pid()} | [pid()],
+ name :: child_id(),
mfargs :: mfargs(),
restart_type :: restart(),
shutdown :: shutdown(),
@@ -95,6 +96,8 @@
[ChildSpec :: child_spec()]}}
| ignore.
+-define(restarting(_Pid_), {restarting,_Pid_}).
+
%%% ---------------------------------------------------
%%% This is a general process supervisor built upon gen_server.erl.
%%% Servers/processes should/could also be built using gen_server.erl.
@@ -139,7 +142,8 @@ start_child(Supervisor, ChildSpec) ->
Result :: {'ok', Child :: child()}
| {'ok', Child :: child(), Info :: term()}
| {'error', Error},
- Error :: 'running' | 'not_found' | 'simple_one_for_one' | term().
+ Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one' |
+ term().
restart_child(Supervisor, Name) ->
call(Supervisor, {restart_child, Name}).
@@ -147,7 +151,7 @@ restart_child(Supervisor, Name) ->
SupRef :: sup_ref(),
Id :: child_id(),
Result :: 'ok' | {'error', Error},
- Error :: 'running' | 'not_found' | 'simple_one_for_one'.
+ Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one'.
delete_child(Supervisor, Name) ->
call(Supervisor, {delete_child, Name}).
@@ -169,7 +173,7 @@ terminate_child(Supervisor, Name) ->
-spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when
SupRef :: sup_ref(),
Id :: child_id() | undefined,
- Child :: child(),
+ Child :: child() | 'restarting',
Type :: worker(),
Modules :: modules().
which_children(Supervisor) ->
@@ -198,6 +202,17 @@ check_childspecs(ChildSpecs) when is_list(ChildSpecs) ->
end;
check_childspecs(X) -> {error, {badarg, X}}.
+%%%-----------------------------------------------------------------
+%%% Called by timer:apply_after from restart/2
+-spec try_again_restart(SupRef, Child) -> ok when
+ SupRef :: sup_ref(),
+ Child :: child_id() | pid().
+try_again_restart(Supervisor, Child) ->
+ cast(Supervisor, {try_again_restart, Child}).
+
+cast(Supervisor, Req) ->
+ gen_server:cast(Supervisor, Req).
+
%%% ---------------------------------------------------
%%%
%%% Initialize the supervisor.
@@ -384,6 +399,8 @@ handle_call({restart_child, Name}, _From, State) ->
Error ->
{reply, Error, State}
end;
+ {value, #child{pid=?restarting(_)}} ->
+ {reply, {error, restarting}, State};
{value, _} ->
{reply, {error, running}, State};
_ ->
@@ -395,6 +412,8 @@ handle_call({delete_child, Name}, _From, State) ->
{value, Child} when Child#child.pid =:= undefined ->
NState = remove_child(Child, State),
{reply, ok, NState};
+ {value, #child{pid=?restarting(_)}} ->
+ {reply, {error, restarting}, State};
{value, _} ->
{reply, {error, running}, State};
_ ->
@@ -413,13 +432,17 @@ handle_call(which_children, _From, #state{children = [#child{restart_type = RTyp
child_type = CT,
modules = Mods}]} =
State) when ?is_simple(State) ->
- Reply = lists:map(fun({Pid, _}) -> {undefined, Pid, CT, Mods} end,
+ Reply = lists:map(fun({?restarting(_),_}) -> {undefined,restarting,CT,Mods};
+ ({Pid, _}) -> {undefined, Pid, CT, Mods} end,
?DICT:to_list(dynamics_db(RType, State#state.dynamics))),
{reply, Reply, State};
handle_call(which_children, _From, State) ->
Resp =
- lists:map(fun(#child{pid = Pid, name = Name,
+ lists:map(fun(#child{pid = ?restarting(_), name = Name,
+ child_type = ChildType, modules = Mods}) ->
+ {Name, restarting, ChildType, Mods};
+ (#child{pid = Pid, name = Name,
child_type = ChildType, modules = Mods}) ->
{Name, Pid, ChildType, Mods}
end,
@@ -432,8 +455,11 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = temp
when ?is_simple(State) ->
{Active, Count} =
?SETS:fold(fun(Pid, {Alive, Tot}) ->
- if is_pid(Pid) -> {Alive+1, Tot +1};
- true -> {Alive, Tot + 1} end
+ case is_pid(Pid) andalso is_process_alive(Pid) of
+ true ->{Alive+1, Tot +1};
+ false ->
+ {Alive, Tot + 1}
+ end
end, {0, 0}, dynamics_db(temporary, State#state.dynamics)),
Reply = case CT of
supervisor -> [{specs, 1}, {active, Active},
@@ -448,8 +474,12 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = RTy
when ?is_simple(State) ->
{Active, Count} =
?DICT:fold(fun(Pid, _Val, {Alive, Tot}) ->
- if is_pid(Pid) -> {Alive+1, Tot +1};
- true -> {Alive, Tot + 1} end
+ case is_pid(Pid) andalso is_process_alive(Pid) of
+ true ->
+ {Alive+1, Tot +1};
+ false ->
+ {Alive, Tot + 1}
+ end
end, {0, 0}, dynamics_db(RType, State#state.dynamics)),
Reply = case CT of
supervisor -> [{specs, 1}, {active, Active},
@@ -486,14 +516,42 @@ count_child(#child{pid = Pid, child_type = supervisor},
end.
-%%% Hopefully cause a function-clause as there is no API function
-%%% that utilizes cast.
--spec handle_cast('null', state()) -> {'noreply', state()}.
+%%% If a restart attempt failed, this message is sent via
+%%% timer:apply_after(0,...) in order to give gen_server the chance to
+%%% check it's inbox before trying again.
+-spec handle_cast({try_again_restart, child_id() | pid()}, state()) ->
+ {'noreply', state()} | {stop, shutdown, state()}.
-handle_cast(null, State) ->
- error_logger:error_msg("ERROR: Supervisor received cast-message 'null'~n",
- []),
- {noreply, State}.
+handle_cast({try_again_restart,Pid}, #state{children=[Child]}=State)
+ when ?is_simple(State) ->
+ RT = Child#child.restart_type,
+ RPid = restarting(Pid),
+ case dynamic_child_args(RPid, dynamics_db(RT, State#state.dynamics)) of
+ {ok, Args} ->
+ {M, F, _} = Child#child.mfargs,
+ NChild = Child#child{pid = RPid, mfargs = {M, F, Args}},
+ case restart(NChild,State) of
+ {ok, State1} ->
+ {noreply, State1};
+ {shutdown, State1} ->
+ {stop, shutdown, State1}
+ end;
+ error ->
+ {noreply, State}
+ end;
+
+handle_cast({try_again_restart,Name}, State) ->
+ case lists:keyfind(Name,#child.name,State#state.children) of
+ Child = #child{pid=?restarting(_)} ->
+ case restart(Child,State) of
+ {ok, State1} ->
+ {noreply, State1};
+ {shutdown, State1} ->
+ {stop, shutdown, State1}
+ end;
+ _ ->
+ {noreply,State}
+ end.
%%
%% Take care of terminated children.
@@ -566,13 +624,12 @@ check_flags(What) ->
{bad_flags, What}.
update_childspec(State, StartSpec) when ?is_simple(State) ->
- case check_startspec(StartSpec) of
- {ok, [Child]} ->
- {ok, State#state{children = [Child]}};
- Error ->
- {error, Error}
- end;
-
+ case check_startspec(StartSpec) of
+ {ok, [Child]} ->
+ {ok, State#state{children = [Child]}};
+ Error ->
+ {error, Error}
+ end;
update_childspec(State, StartSpec) ->
case check_startspec(StartSpec) of
{ok, Children} ->
@@ -592,7 +649,7 @@ update_childspec1([Child|OldC], Children, KeepOld) ->
end;
update_childspec1([], Children, KeepOld) ->
%% Return them in (kept) reverse start order.
- lists:reverse(Children ++ KeepOld).
+ lists:reverse(Children ++ KeepOld).
update_chsp(OldCh, Children) ->
case lists:map(fun(Ch) when OldCh#child.name =:= Ch#child.name ->
@@ -624,7 +681,7 @@ handle_start_child(Child, State) ->
{error, What} ->
{{error, {What, Child}}, State}
end;
- {value, OldChild} when OldChild#child.pid =/= undefined ->
+ {value, OldChild} when is_pid(OldChild#child.pid) ->
{{error, {already_started, OldChild#child.pid}}, State};
{value, _OldChild} ->
{{error, already_present}, State}
@@ -678,7 +735,21 @@ do_restart(temporary, Reason, Child, State) ->
restart(Child, State) ->
case add_restart(State) of
{ok, NState} ->
- restart(NState#state.strategy, Child, NState);
+ case restart(NState#state.strategy, Child, NState) of
+ {try_again,NState2} ->
+ %% Leaving control back to gen_server before
+ %% trying again. This way other incoming requsts
+ %% for the supervisor can be handled - e.g. a
+ %% shutdown request for the supervisor or the
+ %% child.
+ Id = if ?is_simple(State) -> Child#child.pid;
+ true -> Child#child.name
+ end,
+ timer:apply_after(0,?MODULE,try_again_restart,[self(),Id]),
+ {ok,NState2};
+ Other ->
+ Other
+ end;
{terminate, NState} ->
report_error(shutdown, reached_max_restart_intensity,
Child, State#state.name),
@@ -686,9 +757,9 @@ restart(Child, State) ->
end.
restart(simple_one_for_one, Child, State) ->
- #child{mfargs = {M, F, A}} = Child,
- Dynamics = ?DICT:erase(Child#child.pid, dynamics_db(Child#child.restart_type,
- State#state.dynamics)),
+ #child{pid = OldPid, mfargs = {M, F, A}} = Child,
+ Dynamics = ?DICT:erase(OldPid, dynamics_db(Child#child.restart_type,
+ State#state.dynamics)),
case do_start_child_i(M, F, A) of
{ok, Pid} ->
NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)},
@@ -697,10 +768,13 @@ restart(simple_one_for_one, Child, State) ->
NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)},
{ok, NState};
{error, Error} ->
+ NState = State#state{dynamics = ?DICT:store(restarting(OldPid), A,
+ Dynamics)},
report_error(start_error, Error, Child, State#state.name),
- restart(Child, State)
+ {try_again, NState}
end;
restart(one_for_one, Child, State) ->
+ OldPid = Child#child.pid,
case do_start_child(State#state.name, Child) of
{ok, Pid} ->
NState = replace_child(Child#child{pid = Pid}, State),
@@ -709,8 +783,9 @@ restart(one_for_one, Child, State) ->
NState = replace_child(Child#child{pid = Pid}, State),
{ok, NState};
{error, Reason} ->
+ NState = replace_child(Child#child{pid = restarting(OldPid)}, State),
report_error(start_error, Reason, Child, State#state.name),
- restart(Child, State)
+ {try_again, NState}
end;
restart(rest_for_one, Child, State) ->
{ChAfter, ChBefore} = split_child(Child#child.pid, State#state.children),
@@ -719,7 +794,9 @@ restart(rest_for_one, Child, State) ->
{ok, ChAfter3} ->
{ok, State#state{children = ChAfter3 ++ ChBefore}};
{error, ChAfter3} ->
- restart(Child, State#state{children = ChAfter3 ++ ChBefore})
+ NChild = Child#child{pid=restarting(Child#child.pid)},
+ NState = State#state{children = ChAfter3 ++ ChBefore},
+ {try_again, replace_child(NChild,NState)}
end;
restart(one_for_all, Child, State) ->
Children1 = del_child(Child#child.pid, State#state.children),
@@ -728,9 +805,14 @@ restart(one_for_all, Child, State) ->
{ok, NChs} ->
{ok, State#state{children = NChs}};
{error, NChs} ->
- restart(Child, State#state{children = NChs})
+ NChild = Child#child{pid=restarting(Child#child.pid)},
+ NState = State#state{children = NChs},
+ {try_again, replace_child(NChild,NState)}
end.
+restarting(Pid) when is_pid(Pid) -> ?restarting(Pid);
+restarting(RPid) -> RPid.
+
%%-----------------------------------------------------------------
%% Func: terminate_children/2
%% Args: Children = [child_rec()] in termination order
@@ -754,7 +836,7 @@ terminate_children([Child | Children], SupName, Res) ->
terminate_children([], _SupName, Res) ->
Res.
-do_terminate(Child, SupName) when Child#child.pid =/= undefined ->
+do_terminate(Child, SupName) when is_pid(Child#child.pid) ->
case shutdown(Child#child.pid, Child#child.shutdown) of
ok ->
ok;
@@ -765,7 +847,7 @@ do_terminate(Child, SupName) when Child#child.pid =/= undefined ->
end,
Child#child{pid = undefined};
do_terminate(Child, _SupName) ->
- Child.
+ Child#child{pid = undefined}.
%%-----------------------------------------------------------------
%% Shutdowns a child. We must check the EXIT value
@@ -866,7 +948,7 @@ terminate_dynamic_children(Child, Dynamics, SupName) ->
TRef = erlang:start_timer(Time, self(), kill),
wait_dynamic_children(Child, Pids, Sz, TRef, EStack0)
end,
- %% Unrool stacked errors and report them
+ %% Unroll stacked errors and report them
?DICT:fold(fun(Reason, Ls, _) ->
report_error(shutdown_error, Reason,
Child#child{pid=Ls}, SupName)
@@ -885,7 +967,7 @@ monitor_dynamic_children(#child{restart_type=temporary}, Dynamics) ->
end
end, {?SETS:new(), ?DICT:new()}, Dynamics);
monitor_dynamic_children(#child{restart_type=RType}, Dynamics) ->
- ?DICT:fold(fun(P, _, {Pids, EStack}) ->
+ ?DICT:fold(fun(P, _, {Pids, EStack}) when is_pid(P) ->
case monitor_child(P) of
ok ->
{?SETS:add_element(P, Pids), EStack};
@@ -893,7 +975,9 @@ monitor_dynamic_children(#child{restart_type=RType}, Dynamics) ->
{Pids, EStack};
{error, Reason} ->
{Pids, ?DICT:append(Reason, P, EStack)}
- end
+ end;
+ (?restarting(_), _, {Pids, EStack}) ->
+ {Pids, EStack}
end, {?SETS:new(), ?DICT:new()}, Dynamics).
@@ -1020,13 +1104,20 @@ get_child(Name, State, _) ->
lists:keysearch(Name, #child.name, State#state.children).
get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) ->
- case is_dynamic_pid(Pid, dynamics_db(Child#child.restart_type, Dynamics)) of
+ DynamicsDb = dynamics_db(Child#child.restart_type, Dynamics),
+ case is_dynamic_pid(Pid, DynamicsDb) of
true ->
{value, Child#child{pid=Pid}};
false ->
- case erlang:is_process_alive(Pid) of
- true -> false;
- false -> {value, Child}
+ RPid = restarting(Pid),
+ case is_dynamic_pid(RPid, DynamicsDb) of
+ true ->
+ {value, Child#child{pid=RPid}};
+ false ->
+ case erlang:is_process_alive(Pid) of
+ true -> false;
+ false -> {value, Child}
+ end
end
end.
@@ -1056,9 +1147,9 @@ remove_child(Child, State) ->
%% Args: SupName = {local, atom()} | {global, atom()} | self
%% Type = {Strategy, MaxIntensity, Period}
%% Strategy = one_for_one | one_for_all | simple_one_for_one |
-%% rest_for_one
-%% MaxIntensity = integer()
-%% Period = integer()
+%% rest_for_one
+%% MaxIntensity = integer() >= 0
+%% Period = integer() > 0
%% Mod :== atom()
%% Args :== term()
%% Purpose: Check that Type is of correct type (!)
@@ -1109,7 +1200,7 @@ supname(N, _) -> N.
%%% where Name is an atom
%%% Func is {Mod, Fun, Args} == {atom(), atom(), list()}
%%% RestartType is permanent | temporary | transient
-%%% Shutdown = integer() | infinity | brutal_kill
+%%% Shutdown = integer() > 0 | infinity | brutal_kill
%%% ChildType = supervisor | worker
%%% Modules = [atom()] | dynamic
%%% Returns: {ok, [child_rec()]} | Error
diff --git a/lib/stdlib/src/unicode.erl b/lib/stdlib/src/unicode.erl
index e9b90befe6..8b9412fb1b 100644
--- a/lib/stdlib/src/unicode.erl
+++ b/lib/stdlib/src/unicode.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2012. 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
@@ -18,13 +18,6 @@
%%
-module(unicode).
-%% Implemented in the emulator:
-%% characters_to_binary/2 (will trap to characters_to_binary_int/2
-%% if InEncoding is not {latin1 | unicode | utf8})
-%% characters_to_list/2 (will trap to characters_to_list_int/2 if
-%% InEncoding is not {latin1 | unicode | utf8})
-%%
-
-export([characters_to_list/1, characters_to_list_int/2,
characters_to_binary/1, characters_to_binary_int/2,
characters_to_binary/3,
@@ -52,6 +45,45 @@
-type latin1_charlist() :: [latin1_char() | latin1_binary()
| latin1_charlist()].
+%%% BIFs
+%%%
+%%% characters_to_binary/2 (will trap to characters_to_binary_int/2
+%%% if InEncoding is not {latin1 | unicode | utf8})
+%%% characters_to_list/2 (will trap to characters_to_list_int/2 if
+%%% InEncoding is not {latin1 | unicode | utf8})
+
+-export([bin_is_7bit/1, characters_to_binary/2, characters_to_list/2]).
+
+-spec bin_is_7bit(Binary) -> boolean() when
+ Binary :: binary().
+
+bin_is_7bit(_) ->
+ erlang:nif_error(undef).
+
+-spec characters_to_binary(Data, InEncoding) -> Result when
+ Data :: latin1_chardata() | chardata() | external_chardata(),
+ InEncoding :: encoding(),
+ Result :: binary()
+ | {error, binary(), RestData}
+ | {incomplete, binary(), binary()},
+ RestData :: latin1_chardata() | chardata() | external_chardata().
+
+characters_to_binary(_, _) ->
+ erlang:nif_error(undef).
+
+-spec characters_to_list(Data, InEncoding) -> Result when
+ Data :: latin1_chardata() | chardata() | external_chardata(),
+ InEncoding :: encoding(),
+ Result :: list()
+ | {error, list(), RestData}
+ | {incomplete, list(), binary()},
+ RestData :: latin1_chardata() | chardata() | external_chardata().
+
+characters_to_list(_, _) ->
+ erlang:nif_error(undef).
+
+%%% End of BIFs
+
-spec characters_to_list(Data) -> Result when
Data :: latin1_chardata() | chardata() | external_chardata(),
Result :: list()
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index c82c8159b6..c383540db7 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2012. 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
@@ -1017,7 +1017,7 @@ cd_file_header_from_lh_and_pos(LH, Pos) ->
file_name_length = FileNameLength,
extra_field_length = ExtraFieldLength,
file_comment_length = 0, % FileCommentLength,
- disk_num_start = 1, % DiskNumStart,
+ disk_num_start = 0, % DiskNumStart,
internal_attr = 0, % InternalAttr,
external_attr = 0, % ExternalAttr,
local_header_offset = Pos}.