diff options
Diffstat (limited to 'erts/preloaded/src/erlang.erl')
-rw-r--r-- | erts/preloaded/src/erlang.erl | 333 |
1 files changed, 231 insertions, 102 deletions
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 9e814ae54b..061db72dd8 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -79,6 +79,7 @@ -export([bump_reductions/1, byte_size/1, call_on_load_function/1]). -export([cancel_timer/1, check_old_code/1, check_process_code/2, crc32/1]). -export([crc32/2, crc32_combine/3, date/0, decode_packet/3]). +-export([delete_element/2]). -export([delete_module/1, demonitor/1, demonitor/2, display/1]). -export([display_nl/0, display_string/1, dist_exit/3, erase/0, erase/1]). -export([error/1, error/2, exit/1, exit/2, external_size/1]). @@ -88,6 +89,7 @@ -export([garbage_collect_message_area/0, get/0, get/1, get_keys/1]). -export([get_module_info/1, get_stacktrace/0, group_leader/0]). -export([group_leader/2, halt/0, halt/1, halt/2, hash/2, hibernate/3]). +-export([insert_element/3]). -export([integer_to_list/1, iolist_size/1, iolist_to_binary/1]). -export([is_alive/0, is_builtin/3, is_process_alive/1, length/1, link/1]). -export([list_to_atom/1, list_to_binary/1, list_to_bitstr/1]). @@ -529,6 +531,14 @@ date() -> decode_packet(_Type, _Bin, _Options) -> erlang:nif_error(undefined). +%% delete_element/2 +-spec erlang:delete_element(Index, Tuple1) -> Tuple2 when + Index :: pos_integer(), + Tuple1 :: tuple(), + Tuple2 :: tuple(). +delete_element(_Index, _Tuple1) -> + erlang:nif_error(undefined). + %% delete_module/1 -spec delete_module(Module) -> true | undefined when Module :: module(). @@ -820,6 +830,15 @@ hash(_Term, _Range) -> hibernate(_Module, _Function, _Args) -> erlang:nif_error(undefined). +%% insert_element/3 +-spec erlang:insert_element(Index, Tuple1, Term) -> Tuple2 when + Index :: pos_integer(), + Tuple1 :: tuple(), + Tuple2 :: tuple(), + Term :: term(). +insert_element(_Index, _Tuple1, _Term) -> + erlang:nif_error(undefined). + %% integer_to_list/1 -spec integer_to_list(Integer) -> string() when Integer :: integer(). @@ -1075,57 +1094,6 @@ phash2(_Term, _Range) -> pid_to_list(_Pid) -> erlang:nif_error(undefined). -%% port_close/1 --spec port_close(Port) -> true when - Port :: port() | atom(). -port_close(_Port) -> - erlang:nif_error(undefined). - -%% port_command/2 --spec port_command(Port, Data) -> true when - Port :: port() | atom(), - Data :: iodata(). -port_command(_Port, _Data) -> - erlang:nif_error(undefined). - -%% port_command/3 --spec port_command(Port, Data, OptionList) -> boolean() when - Port :: port() | atom(), - Data :: iodata(), - OptionList :: [Option], - Option :: force | nosuspend. -port_command(_Port, _Data, _OptionList) -> - erlang:nif_error(undefined). - -%% port_connect/2 --spec port_connect(Port, Pid) -> true when - Port :: port() | atom(), - Pid :: pid(). -port_connect(_Port, _Pid) -> - erlang:nif_error(undefined). - -%% port_control/3 --spec port_control(Port, Operation, Data) -> Res when - Port :: port() | atom(), - Operation :: integer(), - Data :: iodata(), - Res :: string() | binary(). -port_control(_Port, _Operation, _Data) -> - erlang:nif_error(undefined). - -%% port_get_data/1 --spec erlang:port_get_data(P1) -> term() when - P1 :: port() | atom(). -port_get_data(_P1) -> - erlang:nif_error(undefined). - -%% port_set_data/2 --spec erlang:port_set_data(P1, P2) -> true when - P1 :: port() | atom(), - P2 :: term(). -port_set_data(_P1, _P2) -> - erlang:nif_error(undefined). - %% port_to_list/1 -spec erlang:port_to_list(Port) -> string() when Port :: port(). @@ -1700,60 +1668,11 @@ nodes(_Arg) -> | out | binary | eof + | {parallelism, Boolean :: boolean()} | hide. open_port(_PortName,_PortSettings) -> erlang:nif_error(undefined). -%% Shadowed by erl_bif_types: erlang:port_call/2 --spec erlang:port_call(Port, Data) -> term() when - Port :: port() | atom(), - Data :: term(). -port_call(_Port, _Data) -> - erlang:nif_error(undefined). - -%% Shadowed by erl_bif_types: erlang:port_call/3 --spec erlang:port_call(Port, Operation, Data) -> term() when - Port :: port() | atom(), - Operation :: integer(), - Data :: term(). -port_call(_Port, _Operation, _Data) -> - erlang:nif_error(undefined). - --type port_info_item() :: - registered_name | - id | - connected | - links | - name | - input | - output | - os_pid. - --type port_info_result_item() :: - {registered_name, RegName :: atom()} | - {id, Index :: non_neg_integer()} | - {connected, Pid :: pid()} | - {links, Pids :: [pid()]} | - {name, String :: string()} | - {input, Bytes :: non_neg_integer()} | - {output, Bytes :: non_neg_integer()} | - {os_pid, OsPid :: non_neg_integer() | 'undefined'}. - -%% Shadowed by erl_bif_types: erlang:port_info/1 --spec erlang:port_info(Port) -> Result when - Port :: port() | atom(), - Result :: [port_info_result_item()] | undefined. -port_info(_Result) -> - erlang:nif_error(undefined). - -%% Shadowed by erl_bif_types: erlang:port_info/2 --spec erlang:port_info(Port, Item) -> Result when - Port :: port() | atom(), - Item :: port_info_item(), - Result :: port_info_result_item() | undefined. -port_info(_Result, _Item) -> - erlang:nif_error(undefined). - -type priority_level() :: low | normal | high | max. @@ -1837,7 +1756,7 @@ process_flag(_Flag, _Value) -> {group_leader, GroupLeader :: pid()} | {heap_size, Size :: non_neg_integer()} | {initial_call, mfa()} | - {links, Pids :: [pid() | port()]} | + {links, PidsAndPorts :: [pid() | port()]} | {last_calls, false | (Calls :: [mfa()])} | {memory, Size :: non_neg_integer()} | {message_que_len, MessageQueueLen :: non_neg_integer()} | @@ -2531,6 +2450,216 @@ suspend_process(P) -> end. %% +%% Port BIFs +%% +%% Currently all port BIFs calls the corresponding +%% erts_internal:port_*() native function which perform +%% most of the actual work. These native functions should +%% *never* be called directly by other functionality. The +%% native functions may be changed, or removed without any +%% notice whatsoever! +%% +%% IMPORTANT NOTE: +%% When the erts_internal:port_*() native functions return +%% a reference, they have also internally prepared the +%% message queue of the caller for a receive that will +%% unconditionally wait for a message containing this +%% reference. If the erlang code calling these native +%% functions do not do this, subsequent receives will not +%% work as expected! That is, it is of *vital importance* +%% that the receive is performed as described above! +%% + +-spec port_command(Port, Data) -> 'true' when + Port :: port() | atom(), + Data :: iodata(). + +port_command(Port, Data) -> + case case erts_internal:port_command(Port, Data, []) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + true -> true; + Error -> erlang:error(Error, [Port, Data]) + end. + +-spec port_command(Port, Data, OptionList) -> boolean() when + Port :: port() | atom(), + Data :: iodata(), + Option :: force | nosuspend, + OptionList :: [Option]. + +port_command(Port, Data, Flags) -> + case case erts_internal:port_command(Port, Data, Flags) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + Bool when Bool == true; Bool == false -> Bool; + Error -> erlang:error(Error, [Port, Data, Flags]) + end. + +-spec port_connect(Port, Pid) -> 'true' when + Port :: port() | atom(), + Pid :: pid(). + +port_connect(Port, Pid) -> + case case erts_internal:port_connect(Port, Pid) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + true -> true; + Error -> erlang:error(Error, [Port, Pid]) + end. + +-spec port_close(Port) -> 'true' when + Port :: port() | atom(). + +port_close(Port) -> + case case erts_internal:port_close(Port) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + true -> true; + Error -> erlang:error(Error, [Port]) + end. + +-spec port_control(Port, Operation, Data) -> iodata() | binary() when + Port :: port() | atom(), + Operation :: integer(), + Data :: iodata(). + +port_control(Port, Operation, Data) -> + case case erts_internal:port_control(Port, Operation, Data) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + badarg -> erlang:error(badarg, [Port, Operation, Data]); + Result -> Result + end. + +-spec erlang:port_call(Port, Data) -> term() when + Port :: port() | atom(), + Data :: term(). + +port_call(Port, Data) -> + case case erts_internal:port_call(Port, 0, Data) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + {ok, Result} -> Result; + Error -> erlang:error(Error, [Port, Data]) + end. + +-spec erlang:port_call(Port, Operation, Data) -> term() when + Port :: port() | atom(), + Operation :: integer(), + Data :: term(). + +port_call(Port, Operation, Data) -> + case case erts_internal:port_call(Port, Operation, Data) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + {ok, Result} -> Result; + Error -> erlang:error(Error, [Port, Operation, Data]) + end. + +-spec erlang:port_info(Port) -> Result when + Port :: port() | atom(), + ResultItem :: {registered_name, RegisteredName :: atom()} + | {id, Index :: non_neg_integer()} + | {connected, Pid :: pid()} + | {links, Pids :: [pid()]} + | {name, String :: string()} + | {input, Bytes :: non_neg_integer()} + | {output, Bytes :: non_neg_integer()} + | {os_pid, OsPid :: non_neg_integer() | 'undefined'}, + Result :: [ResultItem] | 'undefined'. + +port_info(Port) -> + case case erts_internal:port_info(Port) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + badarg -> erlang:error(badarg, [Port]); + Result -> Result + end. + +-spec erlang:port_info(Port, connected) -> {connected, Pid} | 'undefined' when + Port :: port() | atom(), + Pid :: pid(); + (Port, id) -> {id, Index} | 'undefined' when + Port :: port() | atom(), + Index :: non_neg_integer(); + (Port, input) -> {input, Bytes} | 'undefined' when + Port :: port() | atom(), + Bytes :: non_neg_integer(); + (Port, links) -> {links, Pids} | 'undefined' when + Port :: port() | atom(), + Pids :: [pid()]; + (Port, locking) -> {locking, Locking} | 'undefined' when + Port :: port() | atom(), + Locking :: 'false' | 'port_level' | 'driver_level'; + (Port, memory) -> {memory, Bytes} | 'undefined' when + Port :: port() | atom(), + Bytes :: non_neg_integer(); + (Port, monitors) -> {monitors, Monitors} | 'undefined' when + Port :: port() | atom(), + Monitors :: [{process, pid()}]; + (Port, name) -> {name, Name} | 'undefined' when + Port :: port() | atom(), + Name :: string(); + (Port, os_pid) -> {os_pid, OsPid} | 'undefined' when + Port :: port() | atom(), + OsPid :: non_neg_integer() | 'undefined'; + (Port, output) -> {output, Bytes} | 'undefined' when + Port :: port() | atom(), + Bytes :: non_neg_integer(); + (Port, parallelism) -> {parallelism, Boolean} | 'undefined' when + Port :: port() | atom(), + Boolean :: boolean(); + (Port, queue_size) -> {queue_size, Bytes} | 'undefined' when + Port :: port() | atom(), + Bytes :: non_neg_integer(); + (Port, registered_name) -> {registered_name, RegisteredName} | [] | 'undefined' when + Port :: port() | atom(), + RegisteredName :: atom(). + +port_info(Port, Item) -> + case case erts_internal:port_info(Port, Item) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + badarg -> erlang:error(badarg, [Port, Item]); + Result -> Result + end. + +-spec erlang:port_set_data(Port, Data) -> 'true' when + Port :: port() | atom(), + Data :: term(). + +port_set_data(Port, Data) -> + case case erts_internal:port_set_data(Port, Data) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + badarg -> erlang:error(badarg, [Port, Data]); + Result -> Result + end. + +-spec erlang:port_get_data(Port) -> term() when + Port :: port() | atom(). + +port_get_data(Port) -> + case case erts_internal:port_get_data(Port) of + Ref when erlang:is_reference(Ref) -> receive {Ref, Res} -> Res end; + Res -> Res + end of + {ok, Data} -> Data; + Error -> erlang:error(Error, [Port]) + end. + +%% %% If the emulator wants to perform a distributed command and %% a connection is not established to the actual node the following %% functions are called in order to set up the connection and then |