diff options
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/bif.c | 69 | ||||
-rw-r--r-- | erts/emulator/beam/bif.tab | 1 | ||||
-rw-r--r-- | erts/emulator/test/list_bif_SUITE.erl | 21 |
3 files changed, 88 insertions, 3 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 075909a881..84c9f9d7c4 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -4254,6 +4254,75 @@ BIF_RETTYPE list_to_pid_1(BIF_ALIST_1) BIF_ERROR(BIF_P, BADARG); } +BIF_RETTYPE list_to_port_1(BIF_ALIST_1) +{ + /* + * A valid port identifier is on the format + * "#Port<N.P>" where N is node and P is + * the port id. Both N and P are of type Uint32. + */ + Uint32 n, p; + char* cp; + int i; + DistEntry *dep = NULL; + char buf[6 /* #Port< */ + + (2)*(10 + 1) /* N.P> */ + + 1 /* \0 */]; + + /* walk down the list and create a C string */ + if ((i = intlist_to_buf(BIF_ARG_1, buf, sizeof(buf)-1)) < 0) + goto bad; + + buf[i] = '\0'; /* null terminal */ + + cp = &buf[0]; + if (strncmp("#Port<", cp, 6) != 0) + goto bad; + + cp += 6; /* strlen("#Port<") */ + + if (sscanf(cp, "%u.%u>", &n, &p) < 2) + goto bad; + + if (p > ERTS_MAX_PORT_NUMBER) + goto bad; + + dep = erts_channel_no_to_dist_entry(n); + + if (!dep) + goto bad; + + if(dep == erts_this_dist_entry) { + erts_deref_dist_entry(dep); + BIF_RET(make_internal_port(p)); + } + else { + ExternalThing *etp; + ErlNode *enp; + + if (is_nil(dep->cid)) + goto bad; + + enp = erts_find_or_insert_node(dep->sysname, dep->creation); + ASSERT(enp != erts_this_node); + + etp = (ExternalThing *) HAlloc(BIF_P, EXTERNAL_THING_HEAD_SIZE + 1); + etp->header = make_external_port_header(1); + etp->next = MSO(BIF_P).first; + etp->node = enp; + etp->data.ui[0] = p; + + MSO(BIF_P).first = (struct erl_off_heap_header*) etp; + erts_deref_dist_entry(dep); + BIF_RET(make_external_port(etp)); + } + + bad: + if (dep) + erts_deref_dist_entry(dep); + BIF_ERROR(BIF_P, BADARG); +} + BIF_RETTYPE list_to_ref_1(BIF_ALIST_1) { /* diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index 5aee795088..3f6d82d65c 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -88,6 +88,7 @@ bif erlang:list_to_binary/1 bif erlang:list_to_float/1 bif erlang:list_to_integer/1 bif erlang:list_to_pid/1 +bif erlang:list_to_port/1 bif erlang:list_to_ref/1 bif erlang:list_to_tuple/1 bif erlang:loaded/0 diff --git a/erts/emulator/test/list_bif_SUITE.erl b/erts/emulator/test/list_bif_SUITE.erl index 9c40929926..08574bff71 100644 --- a/erts/emulator/test/list_bif_SUITE.erl +++ b/erts/emulator/test/list_bif_SUITE.erl @@ -23,7 +23,7 @@ -export([all/0, suite/0]). -export([hd_test/1,tl_test/1,t_length/1,t_list_to_pid/1, - t_list_to_float/1,t_list_to_integer/1]). + t_list_to_port/1,t_list_to_float/1,t_list_to_integer/1]). suite() -> @@ -32,7 +32,7 @@ suite() -> all() -> - [hd_test, tl_test, t_length, t_list_to_pid, + [hd_test, tl_test, t_length, t_list_to_pid, t_list_to_port, t_list_to_float, t_list_to_integer]. %% Tests list_to_integer and string:to_integer @@ -106,10 +106,25 @@ t_list_to_pid(Config) when is_list(Config) -> {'EXIT', {badarg, _}} -> ok; Res -> - ct:fail("list_to_pid/1 with incorrect arg succeeded.~nResult: ~p", [Res]) + ct:fail("list_to_pid/1 with incorrect arg succeeded.~n" + "Result: ~p", [Res]) end, ok. +%% Test list_to_port/1 with correct and incorrect arguments. + +t_list_to_port(Config) when is_list(Config) -> + Me = hd(erlang:ports()), + MyListedPid = port_to_list(Me), + Me = list_to_port(MyListedPid), + case catch list_to_port(id("Incorrect list")) of + {'EXIT', {badarg, _}} -> + ok; + Res -> + ct:fail("list_to_port/1 with incorrect arg succeeded.~n" + "Result: ~p", [Res]) + end, + ok. %% Test list_to_float/1 with correct and incorrect arguments. |