Skip to content

Commit

Permalink
Merge pull request #1474 from pguyot/w02/add-epmd
Browse files Browse the repository at this point in the history
Add support for formatting ports

Add support for io_lib (and io, etc...) to format ports.
Adds port_to_list/1 to erlang module exports to keep dialyzer happy.
Adds a missing clause to handle port terms in `memory_estimate_usage(term)`
function that is necessary for formatting ports for io or other purposes.

This is a continuation of #1473.

These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).

SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
  • Loading branch information
bettio committed Jan 19, 2025
2 parents 439f9eb + b31dea1 commit 6da1e93
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 0 deletions.
11 changes: 11 additions & 0 deletions libs/estdlib/src/erlang.erl
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
integer_to_list/2,
fun_to_list/1,
pid_to_list/1,
port_to_list/1,
ref_to_list/1,
register/2,
unregister/1,
Expand Down Expand Up @@ -853,6 +854,16 @@ fun_to_list(_Fun) ->
pid_to_list(_Pid) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param Port port to convert to a string
%% @returns a string representation of the port
%% @doc Create a string representing a port.
%% @end
%%-----------------------------------------------------------------------------
-spec port_to_list(Port :: port()) -> string().
port_to_list(_Port) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param Ref reference to convert to a string
%% @returns a string representation of the reference
Expand Down
2 changes: 2 additions & 0 deletions libs/estdlib/src/io_lib.erl
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ format_spw(_Format, T) when is_float(T) ->
erlang:float_to_list(T);
format_spw(_Format, T) when is_pid(T) ->
erlang:pid_to_list(T);
format_spw(_Format, T) when is_port(T) ->
erlang:port_to_list(T);
format_spw(_Format, T) when is_reference(T) ->
erlang:ref_to_list(T);
format_spw(_Format, T) when is_function(T) ->
Expand Down
4 changes: 4 additions & 0 deletions src/libAtomVM/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,10 @@ static void memory_scan_and_copy(HeapFragment *old_fragment, term *mem_start, co
TRACE("Found PID (%" TERM_X_FMT ")\n", t);
ptr++;

} else if (term_is_local_port(t)) {
TRACE("Found port (%" TERM_X_FMT ")\n", t);
ptr++;

} else if ((t & 0x3) == 0x0) {
TRACE("Found boxed header (%" TERM_X_FMT ")\n", t);

Expand Down
2 changes: 2 additions & 0 deletions tests/erlang_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ compile_erlang(test_concat_badarg)
compile_erlang(register_and_whereis_badarg)
compile_erlang(test_send)
compile_erlang(test_open_port_badargs)
compile_erlang(test_port_to_list)
compile_erlang(echo)
compile_erlang(pingpong)
compile_erlang(prime_ext)
Expand Down Expand Up @@ -641,6 +642,7 @@ add_custom_target(erlang_test_modules DEPENDS
register_and_whereis_badarg.beam
test_send.beam
test_open_port_badargs.beam
test_port_to_list.beam
echo.beam
pingpong.beam
prime_ext.beam
Expand Down
71 changes: 71 additions & 0 deletions tests/erlang_tests/test_port_to_list.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
%%
%% This file is part of AtomVM.
%%
%% Copyright (c) 2025 <winford@object.stream>
%% All rights reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%%
%% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
%%
-module(test_port_to_list).

-export([start/0, test_echo_port_to_list/0]).

-define(PORTBEGIN, "#Port<0.").
-define(PORTEND, ">").

start() ->
test_echo_port_to_list().

test_echo_port_to_list() ->
Port = open_port({spawn, "echo"}, []),
validate_port_fmt(Port).

%% internal
validate_port_fmt(Port) ->
case get_valid_portchars(Port) of
{ok, PortChars} ->
Res = port_to_list(Port) =:= flatten([?PORTBEGIN, PortChars, ?PORTEND], []),
case Res of
true -> 0;
_ -> 2
end;
{invalid_format, Port} ->
1
end.

get_valid_portchars(Port) ->
PList = port_to_list(Port),
Bin = list_to_binary(PList),
[_, Portend] = binary:split(Bin, <<?PORTBEGIN>>),
[PortNum, _] = binary:split(Portend, <<?PORTEND>>),
try binary_to_integer(PortNum) of
Num when is_integer(Num) ->
{ok, binary_to_list(PortNum)};
_ ->
{invalid_format, Port}
catch
_:_ ->
{invalid_format, Port}
end.

flatten([], Accum) ->
Accum;
flatten([H | T], Accum) when is_list(H) ->
FlattenedT = flatten(T, Accum),
flatten(H, FlattenedT);
flatten([H | T], Accum) ->
FlattenedT = flatten(T, Accum),
[H | FlattenedT].
1 change: 1 addition & 0 deletions tests/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ struct Test tests[] = {
TEST_CASE_EXPECTED(register_and_whereis_badarg, 333),
TEST_CASE(test_send),
TEST_CASE_EXPECTED(test_open_port_badargs, -21),
TEST_CASE(test_port_to_list),
TEST_CASE_EXPECTED(prime_ext, 1999),
TEST_CASE_EXPECTED(test_try_case_end, 256),
TEST_CASE(test_exception_classes),
Expand Down

0 comments on commit 6da1e93

Please sign in to comment.