Skip to content

Commit 6da1e93

Browse files
committed
Merge pull request #1474 from pguyot/w02/add-epmd
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
2 parents 439f9eb + b31dea1 commit 6da1e93

File tree

6 files changed

+91
-0
lines changed

6 files changed

+91
-0
lines changed

libs/estdlib/src/erlang.erl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
integer_to_list/2,
7575
fun_to_list/1,
7676
pid_to_list/1,
77+
port_to_list/1,
7778
ref_to_list/1,
7879
register/2,
7980
unregister/1,
@@ -853,6 +854,16 @@ fun_to_list(_Fun) ->
853854
pid_to_list(_Pid) ->
854855
erlang:nif_error(undefined).
855856

857+
%%-----------------------------------------------------------------------------
858+
%% @param Port port to convert to a string
859+
%% @returns a string representation of the port
860+
%% @doc Create a string representing a port.
861+
%% @end
862+
%%-----------------------------------------------------------------------------
863+
-spec port_to_list(Port :: port()) -> string().
864+
port_to_list(_Port) ->
865+
erlang:nif_error(undefined).
866+
856867
%%-----------------------------------------------------------------------------
857868
%% @param Ref reference to convert to a string
858869
%% @returns a string representation of the reference

libs/estdlib/src/io_lib.erl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,8 @@ format_spw(_Format, T) when is_float(T) ->
292292
erlang:float_to_list(T);
293293
format_spw(_Format, T) when is_pid(T) ->
294294
erlang:pid_to_list(T);
295+
format_spw(_Format, T) when is_port(T) ->
296+
erlang:port_to_list(T);
295297
format_spw(_Format, T) when is_reference(T) ->
296298
erlang:ref_to_list(T);
297299
format_spw(_Format, T) when is_function(T) ->

src/libAtomVM/memory.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,10 @@ static void memory_scan_and_copy(HeapFragment *old_fragment, term *mem_start, co
594594
TRACE("Found PID (%" TERM_X_FMT ")\n", t);
595595
ptr++;
596596

597+
} else if (term_is_local_port(t)) {
598+
TRACE("Found port (%" TERM_X_FMT ")\n", t);
599+
ptr++;
600+
597601
} else if ((t & 0x3) == 0x0) {
598602
TRACE("Found boxed header (%" TERM_X_FMT ")\n", t);
599603

tests/erlang_tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ compile_erlang(test_concat_badarg)
162162
compile_erlang(register_and_whereis_badarg)
163163
compile_erlang(test_send)
164164
compile_erlang(test_open_port_badargs)
165+
compile_erlang(test_port_to_list)
165166
compile_erlang(echo)
166167
compile_erlang(pingpong)
167168
compile_erlang(prime_ext)
@@ -641,6 +642,7 @@ add_custom_target(erlang_test_modules DEPENDS
641642
register_and_whereis_badarg.beam
642643
test_send.beam
643644
test_open_port_badargs.beam
645+
test_port_to_list.beam
644646
echo.beam
645647
pingpong.beam
646648
prime_ext.beam
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
%%
2+
%% This file is part of AtomVM.
3+
%%
4+
%% Copyright (c) 2025 <winford@object.stream>
5+
%% All rights reserved.
6+
%%
7+
%% Licensed under the Apache License, Version 2.0 (the "License");
8+
%% you may not use this file except in compliance with the License.
9+
%% You may obtain a copy of the License at
10+
%%
11+
%% http://www.apache.org/licenses/LICENSE-2.0
12+
%%
13+
%% Unless required by applicable law or agreed to in writing, software
14+
%% distributed under the License is distributed on an "AS IS" BASIS,
15+
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
%% See the License for the specific language governing permissions and
17+
%% limitations under the License.
18+
%%
19+
%%
20+
%% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
21+
%%
22+
-module(test_port_to_list).
23+
24+
-export([start/0, test_echo_port_to_list/0]).
25+
26+
-define(PORTBEGIN, "#Port<0.").
27+
-define(PORTEND, ">").
28+
29+
start() ->
30+
test_echo_port_to_list().
31+
32+
test_echo_port_to_list() ->
33+
Port = open_port({spawn, "echo"}, []),
34+
validate_port_fmt(Port).
35+
36+
%% internal
37+
validate_port_fmt(Port) ->
38+
case get_valid_portchars(Port) of
39+
{ok, PortChars} ->
40+
Res = port_to_list(Port) =:= flatten([?PORTBEGIN, PortChars, ?PORTEND], []),
41+
case Res of
42+
true -> 0;
43+
_ -> 2
44+
end;
45+
{invalid_format, Port} ->
46+
1
47+
end.
48+
49+
get_valid_portchars(Port) ->
50+
PList = port_to_list(Port),
51+
Bin = list_to_binary(PList),
52+
[_, Portend] = binary:split(Bin, <<?PORTBEGIN>>),
53+
[PortNum, _] = binary:split(Portend, <<?PORTEND>>),
54+
try binary_to_integer(PortNum) of
55+
Num when is_integer(Num) ->
56+
{ok, binary_to_list(PortNum)};
57+
_ ->
58+
{invalid_format, Port}
59+
catch
60+
_:_ ->
61+
{invalid_format, Port}
62+
end.
63+
64+
flatten([], Accum) ->
65+
Accum;
66+
flatten([H | T], Accum) when is_list(H) ->
67+
FlattenedT = flatten(T, Accum),
68+
flatten(H, FlattenedT);
69+
flatten([H | T], Accum) ->
70+
FlattenedT = flatten(T, Accum),
71+
[H | FlattenedT].

tests/test.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ struct Test tests[] = {
208208
TEST_CASE_EXPECTED(register_and_whereis_badarg, 333),
209209
TEST_CASE(test_send),
210210
TEST_CASE_EXPECTED(test_open_port_badargs, -21),
211+
TEST_CASE(test_port_to_list),
211212
TEST_CASE_EXPECTED(prime_ext, 1999),
212213
TEST_CASE_EXPECTED(test_try_case_end, 256),
213214
TEST_CASE(test_exception_classes),

0 commit comments

Comments
 (0)