File 9207-io-modules-Eliminate-old-style-catches.patch of Package erlang
From e94ffd425d6b18f6e16386847a151be64bf368a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Sat, 11 Jan 2025 09:44:55 +0100
Subject: [PATCH 7/7] io modules: Eliminate old-style catches
---
lib/stdlib/src/io.erl | 17 ++--
lib/stdlib/src/io_lib.erl | 12 +--
lib/stdlib/src/io_lib_format.erl | 7 +-
lib/stdlib/src/io_lib_fread.erl | 143 +++++++++++++++----------------
lib/stdlib/test/io_SUITE.erl | 97 ++++++++++++++++++++-
5 files changed, 186 insertions(+), 90 deletions(-)
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index a08ce554f2..3d72406026 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -1761,30 +1759,39 @@ io_request(Pid, {put_chars,Enc,Chars}=Request0)
when is_list(Chars), node(Pid) =:= node() ->
%% Convert to binary data if the I/O server is guaranteed to be new
Request =
- case catch unicode:characters_to_binary(Chars,Enc) of
+ try unicode:characters_to_binary(Chars,Enc) of
Binary when is_binary(Binary) ->
{put_chars,Enc,Binary};
_ ->
Request0
+ catch
+ _:_ ->
+ Request0
end,
{false,Request};
io_request(Pid, {put_chars,Enc,Chars}=Request0)
when is_list(Chars) ->
case net_kernel:dflag_unicode_io(Pid) of
true ->
- case catch unicode:characters_to_binary(Chars,Enc,unicode) of
+ try unicode:characters_to_binary(Chars,Enc,unicode) of
Binary when is_binary(Binary) ->
{false,{put_chars,unicode,Binary}};
_ ->
{false,Request0}
+ catch
+ _:_ ->
+ {false,Request0}
end;
false ->
%% Convert back to old style put_chars message...
- case catch unicode:characters_to_binary(Chars,Enc,latin1) of
+ try unicode:characters_to_binary(Chars,Enc,latin1) of
Binary when is_binary(Binary) ->
{false,{put_chars,Binary}};
_ ->
{false,{put_chars,Chars}}
+ catch
+ _:_ ->
+ {false,{put_chars,Chars}}
end
end;
io_request(Pid, {fread,Prompt,Format}) ->
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index b9ddc63978..25cab90f50 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -522,10 +520,12 @@ format_prompt(Prompt, Encoding) ->
do_format_prompt(add_modifier(Encoding, "p"), [Prompt]).
do_format_prompt(Format, Args) ->
- case catch format(Format, Args) of
- {'EXIT',_} -> "???";
- List -> List
- end.
+ try format(Format, Args) of
+ List -> List
+ catch
+ _:_ ->
+ "???"
+ end.
add_modifier(latin1, C) ->
"~"++C;
diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl
index f151717281..b0470f5aea 100644
--- a/lib/stdlib/src/io_lib_format.erl
+++ b/lib/stdlib/src/io_lib_format.erl
@@ -825,9 +823,12 @@ cdata_to_chars([I|Cs]) ->
cdata_to_chars([]) ->
[];
cdata_to_chars(B) when is_binary(B) ->
- case catch unicode:characters_to_list(B) of
+ try unicode:characters_to_list(B) of
L when is_list(L) -> L;
_ -> binary_to_list(B)
+ catch
+ _:_ ->
+ binary_to_list(B)
end.
limit_cdata_to_chars(Cs, 0, normal) ->
diff --git a/lib/stdlib/src/io_lib_fread.erl b/lib/stdlib/src/io_lib_fread.erl
index c61d236afb..f76574ce02 100644
--- a/lib/stdlib/src/io_lib_fread.erl
+++ b/lib/stdlib/src/io_lib_fread.erl
@@ -34,6 +32,8 @@
((C) =:= $\s orelse (C) =:= $\t
orelse (C) =:= $\r orelse (C) =:= $\n)).
+-define(is_valid_base(B), (is_integer(B) andalso B >= 2 andalso B =< 1+$Z-$A+10)).
+
%%-----------------------------------------------------------------------
%% fread(Continuation, CharList, FormatString)
@@ -122,7 +122,7 @@ fread([$~|Format0]=AllFormat, Line, N, Results) ->
fread1(Format, F, Sup, Unicode, Line, N, Results, AllFormat);
fread([C|Format], Line, N, Results) when ?is_whitespace(C) ->
fread_skip_white(Format, Line, N, Results);
-fread([C|Format], [C|Line], N, Results) ->
+fread([C|Format], [C|Line], N, Results) when is_integer(C) ->
fread(Format, Line, N+1, Results);
fread([_F|_Format], [_C|_Line], _N, _Results) ->
fread_error(input);
@@ -134,8 +134,16 @@ fread([_|_], eof, 0, []) ->
fread([_|_], eof, _N, _Results) ->
%% This is an error as there is no more input.
fread_error(input);
-fread([], Line, _N, Results) ->
- {ok,reverse(Results),Line}.
+fread([], Line, _N, Results0) ->
+ Results = reverse(Results0),
+ case Line of
+ [C|_] when is_integer(C) ->
+ {ok,Results,Line};
+ [] ->
+ {ok,Results,Line};
+ _ ->
+ fread_error(input)
+ end.
fread_skip_white(Format, [C|Line], N, Results) when ?is_whitespace(C) ->
fread_skip_white(Format, Line, N+1, Results);
@@ -143,21 +151,21 @@ fread_skip_white(Format, Line, N, Results) ->
fread(Format, Line, N, Results).
%% fread_field(Format)
-%% Reads the field specification paramters. Returns:
+%% Reads the field specification parameters. Returns:
%%
%% {RestFormat,FieldWidth,Suppress}
fread_field([$*|Format]) -> fread_field(Format, true, false);
fread_field(Format) -> fread_field(Format, false, false).
-fread_field([C|Format], Sup, Unic) when C >= $0, C =< $9 ->
+fread_field([C|Format], Sup, Unic) when is_integer(C), C >= $0, C =< $9 ->
fread_field(Format, C - $0, Sup, Unic);
fread_field([$t|Format], Sup, _Unic) ->
{Format,none,Sup,true};
fread_field(Format, Sup, Unic) ->
{Format,none,Sup,Unic}.
-fread_field([C|Format], F, Sup, Unic) when C >= $0, C =< $9 ->
+fread_field([C|Format], F, Sup, Unic) when is_integer(C), C >= $0, C =< $9 ->
fread_field(Format, 10*F + C - $0, Sup, Unic);
fread_field([$t|Format], F, Sup, _Unic) ->
{Format,F,Sup,true};
@@ -198,44 +206,38 @@ fread1([$d|Format], F, Sup, false, Line0, N, Res) ->
fread1([$u|Format], none, Sup, false, Line0, N0, Res) ->
{Line,N,Cs} = fread_digits(Line0, N0, 10, []),
fread_unsigned(Cs, 10, Sup, Format, Line, N, Res);
-fread1([$u|Format], F, Sup, false, Line0, N0, Res) when F >= 2, F =< 1+$Z-$A+10 ->
+fread1([$u|Format], F, Sup, false, Line0, N0, Res) when ?is_valid_base(F) ->
{Line,N,Cs} = fread_digits(Line0, N0, F, []),
fread_unsigned(Cs, F, Sup, Format, Line, N, Res);
fread1([$-|Format], _F, Sup, false, Line, N, Res) ->
fread_sign_char(Sup, Format, Line, N, Res);
fread1([$#|Format], none, Sup, false, Line0, N0, Res) ->
- case catch
- begin
- {Line1,N1,B1} = fread_base(Line0, N0),
- B = abs(B1),
- true = B >= 2 andalso B =< 1+$Z-$A+10,
- {Line2,N2,Cs2} = fread_digits(Line1, N1, B, []),
- fread_based(reverse(Cs2), B1, Sup, Format, Line2, N2, Res)
- end of
- {'EXIT',_} ->
- fread_error(based);
- Other ->
- Other
+ try
+ {Line1,N1,B1} = fread_base(Line0, N0),
+ B = abs(B1),
+ true = ?is_valid_base(B),
+ {Line2,N2,Cs2} = fread_digits(Line1, N1, B, []),
+ fread_based(reverse(Cs2), B1, Sup, Format, Line2, N2, Res)
+ catch
+ _:_ ->
+ fread_error(based)
end;
fread1([$#|Format], F, Sup, false, Line0, N, Res) ->
- case catch
- begin
- {Line1,Cs1} = fread_chars(Line0, F, false),
- {Line2,_,B2} = fread_base(reverse(Cs1), N),
- true = is_integer(B2) andalso B2 >= 2 andalso B2 =< 1+$Z-$A+10,
- fread_based(Line2, B2, Sup, Format, Line1, N+F, Res)
- end of
- {'EXIT',_} ->
- fread_error(based);
- Other ->
- Other
+ try
+ {Line1,Cs1} = fread_chars(Line0, F, false),
+ {Line2,_,B2} = fread_base(reverse(Cs1), N),
+ true = ?is_valid_base(B2),
+ fread_based(Line2, B2, Sup, Format, Line1, N+F, Res)
+ catch
+ _:_ ->
+ fread_error(based)
end;
fread1([$s|Format], none, Sup, U, Line0, N0, Res) ->
{Line,N,Cs} = fread_string_cs(Line0, N0, U),
- fread_string(Cs, Sup, U, Format, Line, N, Res);
+ fread_string(Cs, Sup, Format, Line, N, Res);
fread1([$s|Format], F, Sup, U, Line0, N, Res) ->
{Line,Cs} = fread_chars(Line0, F, U),
- fread_string(Cs, Sup, U, Format, Line, N+F, Res);
+ fread_string(Cs, Sup, Format, Line, N+F, Res);
fread1([$a|Format], none, Sup, U, Line0, N0, Res) ->
{Line,N,Cs} = fread_string_cs(Line0, N0, U),
fread_atom(Cs, Sup, Format, Line, N, Res);
@@ -244,10 +246,10 @@ fread1([$a|Format], F, Sup, false, Line0, N, Res) ->
fread_atom(Cs, Sup, Format, Line, N+F, Res);
fread1([$c|Format], none, Sup, U, Line0, N, Res) ->
{Line,Cs} = fread_chars(Line0, 1, U),
- fread_chars(Cs, Sup, U, Format, Line, N+1, Res);
+ fread_chars(Cs, Sup, Format, Line, N+1, Res);
fread1([$c|Format], F, Sup, U, Line0, N, Res) ->
{Line,Cs} = fread_chars(Line0, F, U),
- fread_chars(Cs, Sup, U, Format, Line, N+F, Res);
+ fread_chars(Cs, Sup, Format, Line, N+F, Res);
fread1([$~|Format], _F, _Sup, _U, [$~|Line], N, Res) ->
fread(Format, Line, N+1, Res);
fread1(_Format, _F, _Sup, _U, _Line, _N, _Res) ->
@@ -256,34 +258,36 @@ fread1(_Format, _F, _Sup, _U, _Line, _N, _Res) ->
%% fread_float(FloatChars, Suppress, Format, Line, N, Results)
fread_float(Cs, Sup, Format, Line, N, Res) ->
- case catch list_to_float(fread_skip_white(reverse(Cs))) of
- {'EXIT',_} ->
- fread_error(float);
+ try list_to_float(fread_skip_white(reverse(Cs))) of
Float ->
fread(Format, Line, N, fread_result(Sup, Float, Res))
+ catch
+ _:_ ->
+ fread_error(float)
end.
%% fread_integer(IntegerChars, Base, Suppress, Format, Line, N, Results)
fread_integer(Cs, Base, Sup, Format, Line, N, Res) ->
- case catch erlang:list_to_integer(fread_skip_white(reverse(Cs)), Base) of
- {'EXIT',_} ->
- fread_error(integer);
+ try list_to_integer(fread_skip_white(reverse(Cs)), Base) of
Integer ->
fread(Format, Line, N, fread_result(Sup, Integer, Res))
+ catch
+ _:_ ->
+ fread_error(integer)
end.
%% fread_unsigned(IntegerChars, Base, Suppress, Format, Line, N, Results)
fread_unsigned(Cs, Base, Sup, Format, Line, N, Res) ->
- case catch erlang:list_to_integer(fread_skip_white(reverse(Cs)), Base) of
- {'EXIT',_} ->
- fread_error(unsigned);
+ try list_to_integer(fread_skip_white(reverse(Cs)), Base) of
Integer ->
fread(Format, Line, N, fread_result(Sup, Integer, Res))
+ catch
+ _:_ ->
+ fread_error(unsigned)
end.
-
%% fread_based(IntegerChars, Base, Suppress, Format, Line, N, Results)
@@ -291,9 +295,8 @@ fread_based(Cs0, B, Sup, Format, Line, N, Res) ->
{Cs,Base} = if B < 0 -> {[$-|Cs0],-B};
true -> {Cs0,B}
end,
- I = erlang:list_to_integer(Cs, Base),
+ I = list_to_integer(Cs, Base),
fread(Format, Line, N, fread_result(Sup, I, Res)).
-
%% fread_sign_char(Suppress, Format, Line, N, Results)
@@ -307,11 +310,11 @@ fread_sign_char(Sup, Format, Line, N, Res) ->
%% fread_string(StringChars, Suppress, Format, Line, N, Results)
-fread_string(error, _Sup, _U, _Format, _Line, _N, _Res) ->
+fread_string(error, _Sup, _Format, _Line, _N, _Res) ->
fread_error(string);
-fread_string(Cs0, Sup, U, Format, Line, N, Res) ->
+fread_string(Cs0, Sup, Format, Line, N, Res) ->
Cs = fread_skip_white(reverse(fread_skip_white(Cs0))),
- fread(Format, Line, N, fread_convert(fread_result(Sup, Cs, Res),U)).
+ fread(Format, Line, N, fread_result(Sup, Cs, Res)).
%% fread_atom(AtomChars, Suppress, Format, Line, N, Results)
@@ -323,10 +326,10 @@ fread_atom(Cs0, Sup, Format, Line, N, Res) ->
%% fread_chars(Characters, Suppress, Format, Line, N, Results)
-fread_chars(error, _Sup, _U, _Format, _Line, _N, _Res) ->
+fread_chars(error, _Sup, _Format, _Line, _N, _Res) ->
fread_error(character);
-fread_chars(Cs, Sup, U, Format, Line, N, Res) ->
- fread(Format, Line, N, fread_convert(fread_result(Sup, reverse(Cs), Res),U)).
+fread_chars(Cs, Sup, Format, Line, N, Res) ->
+ fread(Format, Line, N, fread_result(Sup, reverse(Cs), Res)).
%% fread_chars(Line, Count)
@@ -335,14 +338,12 @@ fread_chars(Line, C, U) ->
fread_chars(0, Line, _U, Cs) -> {Line,Cs};
fread_chars(_N, [$\n|Line], _U, _Cs) -> {[$\n|Line],error};
-fread_chars(N, [C|Line], true, Cs) ->
+fread_chars(N, [C|Line], true, Cs) when is_integer(C) ->
fread_chars(N-1, Line, true, [C|Cs]);
-fread_chars(N, [C|Line], false, Cs) when C >= 0, C =< 255 ->
+fread_chars(N, [C|Line], false, Cs) when is_integer(C), C >= 0, C =< 255 ->
fread_chars(N-1, Line, false, [C|Cs]);
fread_chars(_N, L, _U, _Cs) ->
{L,error}.
-%%fread_chars(_N, [], _U,_Cs) ->
-%% {[],error}.
%% fread_int_cs(Line, N)
@@ -406,14 +407,18 @@ fread_skip_latin1_nonwhite([C|Line], N, []) when C > 255 ->
{[C|Line],N,error};
fread_skip_latin1_nonwhite([C|Line], N, Cs) when C > 255 ->
{[C|Line],N,Cs};
-fread_skip_latin1_nonwhite([C|Line], N, Cs) ->
+fread_skip_latin1_nonwhite([C|Line], N, Cs) when is_integer(C) ->
fread_skip_latin1_nonwhite(Line, N+1, [C|Cs]);
+fread_skip_latin1_nonwhite([_|_]=Line, N, _Cs) ->
+ {Line,N,error};
fread_skip_latin1_nonwhite([], N, Cs) -> {[],N,Cs}.
fread_skip_nonwhite([C|Line], N, Cs) when ?is_whitespace(C) ->
{[C|Line],N,Cs};
-fread_skip_nonwhite([C|Line], N, Cs) ->
+fread_skip_nonwhite([C|Line], N, Cs) when is_integer(C) ->
fread_skip_nonwhite(Line, N+1, [C|Cs]);
+fread_skip_nonwhite([_|_]=Line, N, _Cs) ->
+ {Line,N,error};
fread_skip_nonwhite([], N, Cs) -> {[],N,Cs}.
fread_sign([$+|Line], N, Cs) -> {Line,N+1,[$+|Cs]};
@@ -425,33 +430,23 @@ fread_base(Line0, N0) ->
B = list_to_integer(reverse(Cs1)),
{Line1,N1+1,B}.
-fread_digits([C|Line], N, Cs) when C >= $0, C =< $9 ->
+fread_digits([C|Line], N, Cs) when is_integer(C), C >= $0, C =< $9 ->
fread_digits(Line, N+1, [C|Cs]);
fread_digits(Line, N, Cs) -> {Line,N,Cs}.
-fread_digits([C|Line], N, Base, Cs) when C >= $0, C =< $9 ->
+fread_digits([C|Line], N, Base, Cs) when is_integer(C), C >= $0, C =< $9 ->
fread_digits(Line, N+1, Base, [C|Cs]);
-fread_digits([C|Line], N, Base, Cs) when C >= $A, C < $A+Base-10 ->
+fread_digits([C|Line], N, Base, Cs) when is_integer(C), C >= $A, C < $A+Base-10 ->
fread_digits(Line, N+1, Base, [C|Cs]);
-fread_digits([C|Line], N, Base, Cs) when C >= $a, C < $a+Base-10 ->
+fread_digits([C|Line], N, Base, Cs) when is_integer(C), C >= $a, C < $a+Base-10 ->
fread_digits(Line, N+1, Base, [C|Cs]);
fread_digits(Line, N, _Base, Cs) -> {Line,N,Cs}.
-
%% fread_result(Suppress, Value, Results)
fread_result(true, _V, Res) -> Res;
fread_result(false, V, Res) -> [V|Res].
--ifdef(UNICODE_AS_BINARIES).
-fread_convert([L|R],true) when is_list(L) ->
- [unicode:characters_to_binary(L) | R];
-fread_convert(Any,_) ->
- Any.
--else.
-fread_convert(Any,_) ->
- Any.
--endif.
fread_error(In) ->
{error,{fread,In}}.
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 15d69993b7..7f3cb79841 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -33,7 +33,8 @@
maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1,
otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1,
otp_15159/1, otp_15639/1, otp_15705/1, otp_15847/1, otp_15875/1,
- github_4801/1, chars_limit/1, error_info/1, otp_17525/1]).
+ github_4801/1, chars_limit/1, error_info/1, otp_17525/1,
+ cover_fread/1]).
-export([pretty/2, trf/3]).
@@ -67,7 +68,8 @@ all() ->
format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175,
otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159,
otp_15639, otp_15705, otp_15847, otp_15875, github_4801, chars_limit,
- error_info, otp_17525].
+ error_info, otp_17525,
+ cover_fread].
%% Error cases for output.
error_1(Config) when is_list(Config) ->
@@ -3150,3 +3152,95 @@ otp_17525(_Config) ->
" {...}|...]" =
lists:flatten(S),
ok.
+
+cover_fread(_Config) ->
+ {[-42], ""} = fread_good("~d", "-42"),
+ {[537], ""} = fread_good("int:~4d", "int: 537"),
+ integer = fread_bad("~10d", "abc"),
+
+ {[42], ""} = fread_good("~u", "42"),
+ {[1,27,31,505043], ""} =
+ fread_good("~2u ~8u ~16u ~36u",
+ "1 33 1F atoz"),
+
+ format = fread_bad("~0u", "\n"),
+ format = fread_bad("~1u", "\n"),
+ format = fread_bad("~37u", "\n"),
+ unsigned = fread_bad("~u", "-42\n"),
+
+ {[1,27,31,505043], ""} =
+ fread_good("~#;~#;~#;~#",
+ "2#1;8#33;16#1F;36#atoz"),
+ {[5,27,31,395], ""} =
+ fread_good("~5#;~4#;~5#;~5#",
+ "2#101;8#33;16#1F;36#az"),
+ based = fread_bad("~#", "0#"),
+ based = fread_bad("~#", "1#"),
+ based = fread_bad("~#", "37#"),
+ based = fread_bad("~0#", "\n"),
+ based = fread_bad("~4#", "100#abcdef"),
+ based = fread_bad("~4#", "-99#abcdef"),
+ based = fread_bad("~9#", "99#\nabcdef"),
+
+ {[-1,+1,+1], "7"} = fread_good("~- ~- ~-", "- + 7"),
+
+ {["string"], " "} = fread_good("~s", " string "),
+ {["str"], "ing "} = fread_good("~3s", "string "),
+ {["string"], " "} = fread_good("~ts", " string "),
+ {["str"], "ing "} = fread_good("~3ts", "string "),
+ {["строка"], " "} = fread_good("~ts", " строка "),
+ {["стр"], "ока "} = fread_good("~3ts", "строка "),
+ string = fread_bad("~s", "плохо"),
+
+ {[atom], ""} = fread_good("~a", " atom"),
+ {[at], "om"} = fread_good("~2a", "atom"),
+ {['атом'], ""} = fread_good("~ta", "атом"),
+ atom = fread_bad("~a", "плохо"),
+
+ {[42.0,107.0], ""} = fread_good("~f ~f", "42.0 1.07e+2"),
+ {[42.0,107.0], ""} = fread_good("~4f ~7f", "42.0 1.07E+2"),
+ float = fread_bad("~f", "0"),
+ float = fread_bad("~f", ".0"),
+ float = fread_bad("~2f", "100.0"),
+
+ {["a","bc","def",7,"ghi"], ""} =
+ fread_good("~c~2c ~3c~l ~3c", "abc def ghi"),
+ character = fread_bad("~c", "плохо"),
+
+ {[150.0], ""} = fread_good("~~ ~f", "~ 1.5E+2"),
+
+ {["def"], ""} = fread_good("~*3c ~s", "abc def"),
+
+ ok.
+
+fread_good(Format, String) ->
+ {ok,Term,Remaining} = io_lib:fread(Format, String),
+ fread_float_not_accepted(Format, String, []),
+ {Term,Remaining}.
+
+fread_bad(Format, String) ->
+ {error,{fread,Hint}} = io_lib:fread(Format, String),
+ Hint.
+
+fread_float_not_accepted(Format, [C|Cs], Prefix) ->
+ String = lists:reverse(Prefix) ++ [float(C)|Cs],
+ case io_lib:fread(Format, String) of
+ {error,{fread,_}} ->
+ ok;
+ {ok,_Terms,[H|T]}=Result when is_integer(H) ->
+ %% We accept the success if the float is hidden
+ %% in the leftover part of the input.
+ case [F || F <- T, is_float(F)] of
+ [_] ->
+ ok;
+ [] ->
+ io:format("io_lib:fread(~p, ~p) should fail;\n"
+ "but returned ~p\n",
+ [Format,String,Result]),
+ error(failed)
+ end
+ end,
+ fread_float_not_accepted(Format, Cs, [C|Prefix]);
+fread_float_not_accepted(_, [], _) ->
+ ok.
+
--
2.51.0