diff options
author | Björn Gustavsson <bjorn@erlang.org> | 2022-06-29 12:59:14 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-29 12:59:14 +0200 |
commit | ab0ea053e2053eb77c37480cdf82994ac972ebde (patch) | |
tree | 48d57abe0f6a7f2aad66f0b5bda5b32d8c6afecd | |
parent | fe943ccd02d2fe390687a414cb058c86ec7493e2 (diff) | |
parent | f6a337dfdbc27e17b0beb246be915817870bbf8a (diff) | |
download | erlang-ab0ea053e2053eb77c37480cdf82994ac972ebde.tar.gz |
Merge pull request #6111 from bjorng/bjorn/stdlib/stricter-integers
Add integer guard tests to some modules in STDLIB
-rw-r--r-- | lib/stdlib/src/array.erl | 43 | ||||
-rw-r--r-- | lib/stdlib/src/erl_lint.erl | 15 | ||||
-rw-r--r-- | lib/stdlib/src/erl_scan.erl | 233 | ||||
-rw-r--r-- | lib/stdlib/src/filename.erl | 12 | ||||
-rw-r--r-- | lib/stdlib/src/gb_sets.erl | 24 | ||||
-rw-r--r-- | lib/stdlib/src/gb_trees.erl | 6 | ||||
-rw-r--r-- | lib/stdlib/src/io_lib.erl | 37 | ||||
-rw-r--r-- | lib/stdlib/src/string.erl | 81 | ||||
-rw-r--r-- | lib/stdlib/test/erl_scan_SUITE.erl | 7 | ||||
-rw-r--r-- | lib/stdlib/uc_spec/gen_unicode_mod.escript | 62 |
10 files changed, 315 insertions, 205 deletions
diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl index 1504326c61..03dedabd55 100644 --- a/lib/stdlib/src/array.erl +++ b/lib/stdlib/src/array.erl @@ -462,7 +462,7 @@ fix_test_() -> -spec relax(Array :: array(Type)) -> array(Type). -relax(#array{size = N}=A) -> +relax(#array{size = N}=A) when is_integer(N), N >= 0 -> A#array{max = find_max(N-1, ?LEAFSIZE)}. @@ -489,7 +489,9 @@ relax_test_() -> array(Type). resize(Size, #array{size = N, max = M, elements = E}=A) - when is_integer(Size), Size >= 0 -> + when is_integer(Size), Size >= 0, + is_integer(N), N >= 0, + is_integer(M), M >= 0 -> if Size > N -> {E1, M1} = grow(Size-1, E, if M > 0 -> M; @@ -570,7 +572,7 @@ resize_test_() -> -spec set(I :: array_indx(), Value :: Type, Array :: array(Type)) -> array(Type). set(I, Value, #array{size = N, max = M, default = D, elements = E}=A) - when is_integer(I), I >= 0 -> + when is_integer(I), I >= 0, is_integer(N), is_integer(M) -> if I < N -> A#array{elements = set_1(I, E, Value, D)}; I < M -> @@ -599,7 +601,7 @@ set_1(I, E, X, _D) -> %% Enlarging the array upwards to accommodate an index `I' -grow(I, E, _M) when is_integer(E) -> +grow(I, E, _M) when is_integer(I), is_integer(E) -> M1 = find_max(I, E), {M1, M1}; grow(I, E, M) -> @@ -633,7 +635,7 @@ expand(I, _S, X, D) -> -spec get(I :: array_indx(), Array :: array(Type)) -> Value :: Type. get(I, #array{size = N, max = M, elements = E, default = D}) - when is_integer(I), I >= 0 -> + when is_integer(I), I >= 0, is_integer(N), is_integer(M) -> if I < N -> get_1(I, E, D); M > 0 -> @@ -673,7 +675,7 @@ get_1(I, E, _D) -> -spec reset(I :: array_indx(), Array :: array(Type)) -> array(Type). reset(I, #array{size = N, max = M, default = D, elements = E}=A) - when is_integer(I), I >= 0 -> + when is_integer(I), I >= 0, is_integer(N), is_integer(M) -> if I < N -> try A#array{elements = reset_1(I, E, D)} catch throw:default -> A @@ -760,7 +762,7 @@ set_get_test_() -> to_list(#array{size = 0}) -> []; -to_list(#array{size = N, elements = E, default = D}) -> +to_list(#array{size = N, elements = E, default = D}) when is_integer(N) -> to_list_1(E, D, N - 1); to_list(_) -> erlang:error(badarg). @@ -833,7 +835,7 @@ to_list_test_() -> sparse_to_list(#array{size = 0}) -> []; -sparse_to_list(#array{size = N, elements = E, default = D}) -> +sparse_to_list(#array{size = N, elements = E, default = D}) when is_integer(N) -> sparse_to_list_1(E, D, N - 1); sparse_to_list(_) -> erlang:error(badarg). @@ -1011,7 +1013,7 @@ from_list_test_() -> to_orddict(#array{size = 0}) -> []; -to_orddict(#array{size = N, elements = E, default = D}) -> +to_orddict(#array{size = N, elements = E, default = D}) when is_integer(N) -> I = N - 1, to_orddict_1(E, I, D, I); to_orddict(_) -> @@ -1030,7 +1032,7 @@ to_orddict_1(E, R, D, I) when is_integer(E) -> to_orddict_1(E, R, _D, I) -> push_tuple_pairs(I+1, R, E, []). -to_orddict_2(E=?NODEPATTERN(S), R, D, L) -> +to_orddict_2(E=?NODEPATTERN(S), R, D, L) when is_integer(S) -> to_orddict_3(?NODESIZE, R, D, L, E, S); to_orddict_2(E, R, D, L) when is_integer(E) -> push_pairs(E, R, D, L); @@ -1103,7 +1105,8 @@ to_orddict_test_() -> sparse_to_orddict(#array{size = 0}) -> []; -sparse_to_orddict(#array{size = N, elements = E, default = D}) -> +sparse_to_orddict(#array{size = N, elements = E, default = D}) + when is_integer(N) -> I = N - 1, sparse_to_orddict_1(E, I, D, I); sparse_to_orddict(_) -> @@ -1122,7 +1125,7 @@ sparse_to_orddict_1(E, _R, _D, _I) when is_integer(E) -> sparse_to_orddict_1(E, R, D, I) -> sparse_push_tuple_pairs(I+1, R, D, E, []). -sparse_to_orddict_2(E=?NODEPATTERN(S), R, D, L) -> +sparse_to_orddict_2(E=?NODEPATTERN(S), R, D, L) when is_integer(S) -> sparse_to_orddict_3(?NODESIZE, R, D, L, E, S); sparse_to_orddict_2(E, _R, _D, L) when is_integer(E) -> L; @@ -1223,7 +1226,7 @@ from_orddict_0([], N, _Max, _D, Es) -> end; from_orddict_0(Xs=[{Ix1, _}|_], Ix, Max0, D, Es0) - when Ix1 > Max0, is_integer(Ix1) -> + when is_integer(Ix1), Ix1 > Max0 -> %% We have a hole larger than a leaf Hole = Ix1-Ix, Step = Hole - (Hole rem ?LEAFSIZE), @@ -1393,7 +1396,7 @@ from_orddict_test_() -> Function :: fun((Index :: array_indx(), Type1) -> Type2). map(Function, Array=#array{size = N, elements = E, default = D}) - when is_function(Function, 2) -> + when is_function(Function, 2), is_integer(N) -> if N > 0 -> A = Array#array{elements = []}, % kill reference, for GC A#array{elements = map_1(N-1, E, 0, Function, D)}; @@ -1485,7 +1488,7 @@ map_test_() -> Function :: fun((Index :: array_indx(), Type1) -> Type2). sparse_map(Function, Array=#array{size = N, elements = E, default = D}) - when is_function(Function, 2) -> + when is_function(Function, 2), is_integer(N) -> if N > 0 -> A = Array#array{elements = []}, % kill reference, for GC A#array{elements = sparse_map_1(N-1, E, 0, Function, D)}; @@ -1581,7 +1584,7 @@ sparse_map_test_() -> Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). foldl(Function, A, #array{size = N, elements = E, default = D}) - when is_function(Function, 3) -> + when is_function(Function, 3), is_integer(N) -> if N > 0 -> foldl_1(N-1, E, A, 0, Function, D); true -> @@ -1653,7 +1656,7 @@ foldl_test_() -> Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). sparse_foldl(Function, A, #array{size = N, elements = E, default = D}) - when is_function(Function, 3) -> + when is_function(Function, 3), is_integer(N) -> if N > 0 -> sparse_foldl_1(N-1, E, A, 0, Function, D); true -> @@ -1730,7 +1733,7 @@ sparse_foldl_test_() -> Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). foldr(Function, A, #array{size = N, elements = E, default = D}) - when is_function(Function, 3) -> + when is_function(Function, 3), is_integer(N) -> if N > 0 -> I = N - 1, foldr_1(I, E, I, A, Function, D); @@ -1808,7 +1811,7 @@ foldr_test_() -> Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). sparse_foldr(Function, A, #array{size = N, elements = E, default = D}) - when is_function(Function, 3) -> + when is_function(Function, 3), is_integer(N) -> if N > 0 -> I = N - 1, sparse_foldr_1(I, E, I, A, Function, D); @@ -1862,7 +1865,7 @@ sparse_size(A) -> try sparse_foldr(F, [], A) of [] -> 0 catch - {value, I} -> + {value, I} when is_integer(I) -> I + 1 end. diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index c2f9ad3703..36caf8612b 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -2084,7 +2084,8 @@ bit_size_check(Anno, all, #bittype{type=Type}, St) -> binary -> {all,St}; _ -> {unknown,add_error(Anno, illegal_bitsize, St)} end; -bit_size_check(Anno, Size, #bittype{type=Type,unit=Unit}, St) -> +bit_size_check(Anno, Size, #bittype{type=Type,unit=Unit}, St) + when is_integer(Size), is_integer(Unit) -> Sz = Unit * Size, %Total number of bits! St2 = elemtype_check(Anno, Type, Sz, St), {Sz,St2}. @@ -4370,9 +4371,11 @@ extract_sequences(Fmt, Need0) -> end end. -extract_sequence(1, [$-,C|Fmt], Need) when C >= $0, C =< $9 -> +extract_sequence(1, [$-,C|Fmt], Need) + when is_integer(C), C >= $0, C =< $9 -> extract_sequence_digits(1, Fmt, Need); -extract_sequence(1, [C|Fmt], Need) when C >= $0, C =< $9 -> +extract_sequence(1, [C|Fmt], Need) + when is_integer(C), C >= $0, C =< $9 -> extract_sequence_digits(1, Fmt, Need); extract_sequence(1, [$-,$*|Fmt], Need) -> extract_sequence(2, Fmt, [int|Need]); @@ -4381,7 +4384,8 @@ extract_sequence(1, [$*|Fmt], Need) -> extract_sequence(1, Fmt, Need) -> extract_sequence(2, Fmt, Need); -extract_sequence(2, [$.,C|Fmt], Need) when C >= $0, C =< $9 -> +extract_sequence(2, [$.,C|Fmt], Need) + when is_integer(C), C >= $0, C =< $9 -> extract_sequence_digits(2, Fmt, Need); extract_sequence(2, [$.,$*|Fmt], Need) -> extract_sequence(3, Fmt, [int|Need]); @@ -4435,7 +4439,8 @@ extract_sequence(5, [C|Fmt], Need0) -> end; extract_sequence(_, [], _Need) -> {error,"truncated"}. -extract_sequence_digits(Fld, [C|Fmt], Need) when C >= $0, C =< $9 -> +extract_sequence_digits(Fld, [C|Fmt], Need) + when is_integer(C), C >= $0, C =< $9 -> extract_sequence_digits(Fld, Fmt, Need); extract_sequence_digits(Fld, Fmt, Need) -> extract_sequence(Fld+1, Fmt, Need). diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl index f2e9d2d7b9..e7e2582c03 100644 --- a/lib/stdlib/src/erl_scan.erl +++ b/lib/stdlib/src/erl_scan.erl @@ -264,15 +264,15 @@ string_thing(_) -> "string". -define(WHITE_SPACE(C), is_integer(C) andalso (C >= $\000 andalso C =< $\s orelse C >= $\200 andalso C =< $\240)). --define(DIGIT(C), C >= $0 andalso C =< $9). --define(CHAR(C), is_integer(C), C >= 0). +-define(DIGIT(C), (is_integer(C) andalso $0 =< C andalso C =< $9)). +-define(CHAR(C), (is_integer(C) andalso 0 =< C andalso C < 16#110000)). -define(UNICODE(C), - is_integer(C) andalso + (is_integer(C) andalso (C >= 0 andalso C < 16#D800 orelse C > 16#DFFF andalso C < 16#FFFE orelse - C > 16#FFFF andalso C =< 16#10FFFF)). + C > 16#FFFF andalso C =< 16#10FFFF))). --define(UNI255(C), C >= 0, C =< 16#ff). +-define(UNI255(C), (is_integer(C) andalso 0 =< C andalso C =< 16#ff)). options(Opts0) when is_list(Opts0) -> Opts = lists:foldr(fun expand_opt/2, [], Opts0), @@ -363,7 +363,7 @@ string1(Cs, St, Line, Col, Toks) -> Error end. -scan(Cs, St, Line, Col, Toks, _) -> +scan(Cs, #erl_scan{}=St, Line, Col, Toks, _) -> scan1(Cs, St, Line, Col, Toks). scan1([$\s|Cs], St, Line, Col, Toks) when St#erl_scan.ws -> @@ -374,10 +374,6 @@ scan1([$\n|Cs], St, Line, Col, Toks) when St#erl_scan.ws -> scan_newline(Cs, St, Line, Col, Toks); scan1([$\n|Cs], St, Line, Col, Toks) -> skip_white_space(Cs, St, Line+1, new_column(Col, 1), Toks, 0); -scan1([C|Cs], St, Line, Col, Toks) when C >= $A, C =< $Z -> - scan_variable(Cs, St, Line, Col, Toks, [C]); -scan1([C|Cs], St, Line, Col, Toks) when C >= $a, C =< $z -> - scan_atom(Cs, St, Line, Col, Toks, [C]); %% Optimization: some very common punctuation characters: scan1([$,|Cs], St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, ",", ',', 1); @@ -397,11 +393,17 @@ scan1([$;|Cs], St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, ";", ';', 1); scan1([$_=C|Cs], St, Line, Col, Toks) -> scan_variable(Cs, St, Line, Col, Toks, [C]); -%% More punctuation characters below. scan1([$\%|Cs], St, Line, Col, Toks) when not St#erl_scan.comment -> skip_comment(Cs, St, Line, Col, Toks, 1); scan1([$\%=C|Cs], St, Line, Col, Toks) -> scan_comment(Cs, St, Line, Col, Toks, [C]); +%% More punctuation characters below. +scan1([C|_], _St, _Line, _Col0, _Toks) when not ?CHAR(C) -> + error({not_character,C}); +scan1([C|Cs], St, Line, Col, Toks) when C >= $A, C =< $Z -> + scan_variable(Cs, St, Line, Col, Toks, [C]); +scan1([C|Cs], St, Line, Col, Toks) when C >= $a, C =< $z -> + scan_atom(Cs, St, Line, Col, Toks, [C]); scan1([C|Cs], St, Line, Col, Toks) when ?DIGIT(C) -> scan_number(Cs, St, Line, Col, Toks, [C], no_underscore); scan1("..."++Cs, St, Line, Col, Toks) -> @@ -557,39 +559,49 @@ scan1([]=Cs, _St, Line, Col, Toks) -> scan1(eof=Cs, _St, Line, Col, Toks) -> {ok,Toks,Cs,Line,Col}. +scan_atom_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_atom(Cs, St, Line, Col, Toks, Ncs). + scan_atom(Cs0, St, Line, Col, Toks, Ncs0) -> case scan_name(Cs0, Ncs0) of {more,Ncs} -> - {more,{[],Col,Toks,Line,Ncs,fun scan_atom/6}}; + {more,{[],Col,Toks,Line,Ncs,fun scan_atom_fun/6}}; {Wcs,Cs} -> - case catch list_to_atom(Wcs) of - Name when is_atom(Name) -> + try list_to_atom(Wcs) of + Name -> case (St#erl_scan.resword_fun)(Name) of true -> tok2(Cs, St, Line, Col, Toks, Wcs, Name); false -> tok3(Cs, St, Line, Col, Toks, atom, Wcs, Name) - end; - _Error -> + end + catch + _:_ -> Ncol = incr_column(Col, length(Wcs)), scan_error({illegal,atom}, Line, Col, Line, Ncol, Cs) end end. +scan_variable_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_variable(Cs, St, Line, Col, Toks, Ncs). + scan_variable(Cs0, St, Line, Col, Toks, Ncs0) -> case scan_name(Cs0, Ncs0) of {more,Ncs} -> - {more,{[],Col,Toks,Line,Ncs,fun scan_variable/6}}; + {more,{[],Col,Toks,Line,Ncs,fun scan_variable_fun/6}}; {Wcs,Cs} -> - case catch list_to_atom(Wcs) of - Name when is_atom(Name) -> - tok3(Cs, St, Line, Col, Toks, var, Wcs, Name); - _Error -> + try list_to_atom(Wcs) of + Name -> + tok3(Cs, St, Line, Col, Toks, var, Wcs, Name) + catch + _:_ -> Ncol = incr_column(Col, length(Wcs)), scan_error({illegal,var}, Line, Col, Line, Ncol, Cs) end end. +scan_name([C|_]=Cs, Ncs) when not ?CHAR(C) -> + {lists:reverse(Ncs),Cs}; scan_name([C|Cs], Ncs) when C >= $a, C =< $z -> scan_name(Cs, [C|Ncs]); scan_name([C|Cs], Ncs) when C >= $A, C =< $Z -> @@ -663,20 +675,31 @@ scan_newline([], _St, Line, Col, Toks) -> scan_newline(Cs, St, Line, Col, Toks) -> scan_nl_white_space(Cs, St, Line, Col, Toks, "\n"). +scan_nl_spcs_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) + when is_integer(N) -> + scan_nl_spcs(Cs, St, Line, Col, Toks, N). + scan_nl_spcs([$\s|Cs], St, Line, Col, Toks, N) when N < 17 -> scan_nl_spcs(Cs, St, Line, Col, Toks, N+1); scan_nl_spcs([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun scan_nl_spcs/6}}; + {more,{Cs,Col,Toks,Line,N,fun scan_nl_spcs_fun/6}}; scan_nl_spcs(Cs, St, Line, Col, Toks, N) -> newline_end(Cs, St, Line, Col, Toks, N, nl_spcs(N)). +scan_nl_tabs_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) + when is_integer(N) -> + scan_nl_tabs(Cs, St, Line, Col, Toks, N). + scan_nl_tabs([$\t|Cs], St, Line, Col, Toks, N) when N < 11 -> scan_nl_tabs(Cs, St, Line, Col, Toks, N+1); scan_nl_tabs([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun scan_nl_tabs/6}}; + {more,{Cs,Col,Toks,Line,N,fun scan_nl_tabs_fun/6}}; scan_nl_tabs(Cs, St, Line, Col, Toks, N) -> newline_end(Cs, St, Line, Col, Toks, N, nl_tabs(N)). +scan_nl_white_space_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_nl_white_space(Cs, St, Line, Col, Toks, Ncs). + %% Note: returning {more,Cont} is meaningless here; one could just as %% well return several tokens. But since tokens() scans up to a full %% stop anyway, nothing is gained by not collecting all white spaces. @@ -689,10 +712,11 @@ scan_nl_white_space([$\n|Cs], St, Line, Col, Toks, Ncs0) -> Anno = anno(Line, Col, St, ?STR(white_space, St, Ncs)), Token = {white_space,Anno,Ncs}, scan_newline(Cs, St, Line+1, new_column(Col, length(Ncs)), [Token|Toks]); -scan_nl_white_space([C|Cs], St, Line, Col, Toks, Ncs) when ?WHITE_SPACE(C) -> +scan_nl_white_space([C|Cs], St, Line, Col, Toks, Ncs) + when ?WHITE_SPACE(C) -> scan_nl_white_space(Cs, St, Line, Col, Toks, [C|Ncs]); scan_nl_white_space([]=Cs, _St, Line, Col, Toks, Ncs) -> - {more,{Cs,Col,Toks,Line,Ncs,fun scan_nl_white_space/6}}; + {more,{Cs,Col,Toks,Line,Ncs,fun scan_nl_white_space_fun/6}}; scan_nl_white_space(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, Ncs) -> Anno = anno(Line), @@ -706,40 +730,54 @@ scan_nl_white_space(Cs, St, Line, Col, Toks, Ncs0) -> newline_end(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, _N, Ncs) -> scan1(Cs, St, Line+1, Col, [{white_space,anno(Line),Ncs}|Toks]); -newline_end(Cs, St, Line, Col, Toks, N, Ncs) -> +newline_end(Cs, #erl_scan{}=St, Line, Col, Toks, N, Ncs) -> Anno = anno(Line, Col, St, ?STR(white_space, St, Ncs)), scan1(Cs, St, Line+1, new_column(Col, N), [{white_space,Anno,Ncs}|Toks]). +scan_spcs_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) + when is_integer(N), N >= 1 -> + scan_spcs(Cs, St, Line, Col, Toks, N). + scan_spcs([$\s|Cs], St, Line, Col, Toks, N) when N < 16 -> scan_spcs(Cs, St, Line, Col, Toks, N+1); scan_spcs([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun scan_spcs/6}}; + {more,{Cs,Col,Toks,Line,N,fun scan_spcs_fun/6}}; scan_spcs(Cs, St, Line, Col, Toks, N) -> white_space_end(Cs, St, Line, Col, Toks, N, spcs(N)). +scan_tabs_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) + when is_integer(N), N >= 1 -> + scan_tabs(Cs, St, Line, Col, Toks, N). + scan_tabs([$\t|Cs], St, Line, Col, Toks, N) when N < 10 -> scan_tabs(Cs, St, Line, Col, Toks, N+1); scan_tabs([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun scan_tabs/6}}; + {more,{Cs,Col,Toks,Line,N,fun scan_tabs_fun/6}}; scan_tabs(Cs, St, Line, Col, Toks, N) -> white_space_end(Cs, St, Line, Col, Toks, N, tabs(N)). +skip_white_space_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) -> + skip_white_space(Cs, St, Line, Col, Toks, N). + skip_white_space([$\n|Cs], St, Line, Col, Toks, _N) -> skip_white_space(Cs, St, Line+1, new_column(Col, 1), Toks, 0); skip_white_space([C|Cs], St, Line, Col, Toks, N) when ?WHITE_SPACE(C) -> skip_white_space(Cs, St, Line, Col, Toks, N+1); skip_white_space([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun skip_white_space/6}}; + {more,{Cs,Col,Toks,Line,N,fun skip_white_space_fun/6}}; skip_white_space(Cs, St, Line, Col, Toks, N) -> scan1(Cs, St, Line, incr_column(Col, N), Toks). +scan_white_space_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_white_space(Cs, St, Line, Col, Toks, Ncs). + %% Maybe \t and \s should break the loop. scan_white_space([$\n|_]=Cs, St, Line, Col, Toks, Ncs) -> white_space_end(Cs, St, Line, Col, Toks, length(Ncs), lists:reverse(Ncs)); scan_white_space([C|Cs], St, Line, Col, Toks, Ncs) when ?WHITE_SPACE(C) -> scan_white_space(Cs, St, Line, Col, Toks, [C|Ncs]); scan_white_space([]=Cs, _St, Line, Col, Toks, Ncs) -> - {more,{Cs,Col,Toks,Line,Ncs,fun scan_white_space/6}}; + {more,{Cs,Col,Toks,Line,Ncs,fun scan_white_space_fun/6}}; scan_white_space(Cs, St, Line, Col, Toks, Ncs) -> white_space_end(Cs, St, Line, Col, Toks, length(Ncs), lists:reverse(Ncs)). @@ -778,7 +816,7 @@ scan_char([], _St, Line, Col, Toks) -> scan_char(eof, _St, Line, Col, _Toks) -> scan_error(char, Line, Col, Line, incr_column(Col, 1), eof). -scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> +scan_string(Cs, #erl_scan{}=St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> case scan_string0(Cs, St, Line, Col, $\", Str, Wcs) of %" {more,Ncs,Nline,Ncol,Nstr,Nwcs} -> State = {Nwcs,Nstr,Line0,Col0}, @@ -793,7 +831,7 @@ scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> scan1(Ncs, St, Nline, Ncol, [{string,Anno,Nwcs}|Toks]) end. -scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> +scan_qatom(Cs, #erl_scan{}=St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> case scan_string0(Cs, St, Line, Col, $\', Str, Wcs) of %' {more,Ncs,Nline,Ncol,Nstr,Nwcs} -> State = {Nwcs,Nstr,Line0,Col0}, @@ -803,12 +841,13 @@ scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> {error,Nline,Ncol,Nwcs,Ncs} -> Estr = string:slice(Nwcs, 0, 16), % Expanded escape chars. scan_error({string,$\',Estr}, Line0, Col0, Nline, Ncol, Ncs); %' - {Ncs,Nline,Ncol,Nstr,Nwcs} -> - case catch list_to_atom(Nwcs) of + {Ncs,Nline,Ncol,Nstr,Nwcs} -> + try list_to_atom(Nwcs) of A when is_atom(A) -> Anno = anno(Line0, Col0, St, ?STR(atom, St, Nstr)), - scan1(Ncs, St, Nline, Ncol, [{atom,Anno,A}|Toks]); - _ -> + scan1(Ncs, St, Nline, Ncol, [{atom,Anno,A}|Toks]) + catch + _:_ -> scan_error({illegal,atom}, Line0, Col0, Nline, Ncol, Ncs) end end. @@ -884,10 +923,11 @@ scan_string1([]=Cs, Line, Col, _Q, Str, Wcs) -> scan_string1(eof, Line, Col, _Q, _Str, Wcs) -> {error,Line,Col,lists:reverse(Wcs),eof}. --define(OCT(C), C >= $0, C =< $7). --define(HEX(C), C >= $0 andalso C =< $9 orelse - C >= $A andalso C =< $F orelse - C >= $a andalso C =< $f). +-define(OCT(C), (is_integer(C) andalso $0 =< C andalso C =< $7)). +-define(HEX(C), (is_integer(C) andalso + (C >= $0 andalso C =< $9 orelse + C >= $A andalso C =< $F orelse + C >= $a andalso C =< $f))). %% \<1-3> octal digits scan_escape([O1,O2,O3|Cs], Col) when ?OCT(O1), ?OCT(O2), ?OCT(O3) -> @@ -939,26 +979,31 @@ scan_escape([], _Col) -> scan_escape(eof, Col) -> {eof,Col}. -scan_hex([C|Cs], no_col=Col, Wcs) when ?HEX(C) -> - scan_hex(Cs, Col, [C|Wcs]); scan_hex([C|Cs], Col, Wcs) when ?HEX(C) -> - scan_hex(Cs, Col+1, [C|Wcs]); + scan_hex(Cs, incr_column(Col, 1), [C|Wcs]); scan_hex(Cs, Col, Wcs) -> - scan_esc_end(Cs, Col, Wcs, 16, "x{"). + scan_hex_end(Cs, Col, Wcs, "x{"). -scan_esc_end([$}|Cs], Col, Wcs0, B, Str0) -> +scan_hex_end([$}|Cs], Col, [], _Str) -> + %% Empty escape sequence. + {error,Cs,{illegal,character},incr_column(Col, 1)}; +scan_hex_end([$}|Cs], Col, Wcs0, Str0) -> Wcs = lists:reverse(Wcs0), - case catch erlang:list_to_integer(Wcs, B) of + try list_to_integer(Wcs, 16) of Val when ?UNICODE(Val) -> {Val,Str0++Wcs++[$}],Cs,incr_column(Col, 1)}; - _ -> + _Val -> + {error,Cs,{illegal,character},incr_column(Col, 1)} + catch + error:system_limit -> + %% Extremely unlikely to occur in practice. {error,Cs,{illegal,character},incr_column(Col, 1)} end; -scan_esc_end([], _Col, _Wcs, _B, _Str0) -> +scan_hex_end([], _Col, _Wcs, _Str0) -> more; -scan_esc_end(eof, Col, _Wcs, _B, _Str0) -> +scan_hex_end(eof, Col, _Wcs, _Str0) -> {eof,Col}; -scan_esc_end(Cs, Col, _Wcs, _B, _Str0) -> +scan_hex_end(Cs, Col, _Wcs, _Str0) -> {error,Cs,{illegal,character},Col}. escape_char($n) -> $\n; % \n = LF @@ -972,7 +1017,7 @@ escape_char($s) -> $\s; % \s = SPC escape_char($d) -> $\d; % \d = DEL escape_char(C) -> C. -scan_number(Cs, St, Line, Col, Toks, {Ncs, Us}) -> +scan_number(Cs, #erl_scan{}=St, Line, Col, Toks, {Ncs, Us}) -> scan_number(Cs, St, Line, Col, Toks, Ncs, Us). scan_number([C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> @@ -988,22 +1033,28 @@ scan_number([$.]=Cs, _St, Line, Col, Toks, Ncs, Us) -> {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_number/6}}; scan_number([$#|Cs]=Cs0, St, Line, Col, Toks, Ncs0, Us) -> Ncs = lists:reverse(Ncs0), - case catch list_to_integer(remove_digit_separators(Ncs, Us)) of - B when B >= 2, B =< 1+$Z-$A+10 -> + try list_to_integer(remove_digit_separators(Ncs, Us)) of + B when is_integer(B), 2 =< B, B =< 1+$Z-$A+10 -> Bcs = Ncs++[$#], scan_based_int(Cs, St, Line, Col, Toks, B, [], Bcs, no_underscore); - B -> + B when is_integer(B) -> Len = length(Ncs), scan_error({base,B}, Line, Col, Line, incr_column(Col, Len), Cs0) + catch + error:system_limit -> + %% Extremely unlikely to occur in practice. + scan_error({illegal,base}, Line, Col, Line, Col, Cs0) end; scan_number([]=Cs, _St, Line, Col, Toks, Ncs, Us) -> {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_number/6}}; scan_number(Cs, St, Line, Col, Toks, Ncs0, Us) -> Ncs = lists:reverse(Ncs0), - case catch list_to_integer(remove_digit_separators(Ncs, Us)) of - N when is_integer(N) -> - tok3(Cs, St, Line, Col, Toks, integer, Ncs, N); - _ -> + try list_to_integer(remove_digit_separators(Ncs, Us), 10) of + N -> + tok3(Cs, St, Line, Col, Toks, integer, Ncs, N) + catch + error:system_limit -> + %% Extremely unlikely to occur in practice. Ncol = incr_column(Col, length(Ncs)), scan_error({illegal,integer}, Line, Col, Line, Ncol, Cs) end. @@ -1014,11 +1065,14 @@ remove_digit_separators(Number, with_underscore) -> [C || C <- Number, C =/= $_]. -define(BASED_DIGIT(C, B), - ((?DIGIT(C) andalso C < $0 + B) - orelse (C >= $A andalso B > 10 andalso C < $A + B - 10) - orelse (C >= $a andalso B > 10 andalso C < $a + B - 10))). - -scan_based_int(Cs, St, Line, Col, Toks, {B,NCs,BCs,Us}) -> + (is_integer(C) + andalso + ((?DIGIT(C) andalso C < $0 + B) + orelse (C >= $A andalso B > 10 andalso C < $A + B - 10) + orelse (C >= $a andalso B > 10 andalso C < $a + B - 10)))). + +scan_based_int(Cs, #erl_scan{}=St, Line, Col, Toks, {B,NCs,BCs,Us}) + when is_integer(B), 2 =< B, B =< 1+$Z-$A+10 -> scan_based_int(Cs, St, Line, Col, Toks, B, NCs, BCs, Us). scan_based_int([C|Cs], St, Line, Col, Toks, B, Ncs, Bcs, Us) when @@ -1032,18 +1086,25 @@ scan_based_int([$_]=Cs, _St, Line, Col, Toks, B, NCs, BCs, Us) -> {more,{Cs,Col,Toks,Line,{B,NCs,BCs,Us},fun scan_based_int/6}}; scan_based_int([]=Cs, _St, Line, Col, Toks, B, NCs, BCs, Us) -> {more,{Cs,Col,Toks,Line,{B,NCs,BCs,Us},fun scan_based_int/6}}; -scan_based_int(Cs, St, Line, Col, Toks, B, Ncs0, Bcs, Us) -> +scan_based_int(Cs, _St, Line, Col, _Toks, _B, [], Bcs, _Us) -> + %% No actual digits following the base. + Len = length(Bcs), + Ncol = incr_column(Col, Len), + scan_error({illegal,integer}, Line, Col, Line, Ncol, Cs); +scan_based_int(Cs, St, Line, Col, Toks, B, Ncs0, [_|_]=Bcs, Us) -> Ncs = lists:reverse(Ncs0), - case catch erlang:list_to_integer(remove_digit_separators(Ncs, Us), B) of - N when is_integer(N) -> - tok3(Cs, St, Line, Col, Toks, integer, Bcs++Ncs, N); - _ -> + try list_to_integer(remove_digit_separators(Ncs, Us), B) of + N -> + tok3(Cs, St, Line, Col, Toks, integer, Bcs++Ncs, N) + catch + error:system_limit -> + %% Extremely unlikely to occur in practice. Len = length(Bcs)+length(Ncs), Ncol = incr_column(Col, Len), scan_error({illegal,integer}, Line, Col, Line, Ncol, Cs) end. -scan_fraction(Cs, St, Line, Col, Toks, {Ncs,Us}) -> +scan_fraction(Cs, #erl_scan{}=St, Line, Col, Toks, {Ncs,Us}) -> scan_fraction(Cs, St, Line, Col, Toks, Ncs, Us). scan_fraction([C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> @@ -1060,7 +1121,7 @@ scan_fraction([]=Cs, _St, Line, Col, Toks, Ncs, Us) -> scan_fraction(Cs, St, Line, Col, Toks, Ncs, Us) -> float_end(Cs, St, Line, Col, Toks, Ncs, Us). -scan_exponent_sign(Cs, St, Line, Col, Toks, {Ncs, Us}) -> +scan_exponent_sign(Cs, #erl_scan{}=St, Line, Col, Toks, {Ncs, Us}) -> scan_exponent_sign(Cs, St, Line, Col, Toks, Ncs, Us). scan_exponent_sign([C|Cs], St, Line, Col, Toks, Ncs, Us) when @@ -1071,7 +1132,7 @@ scan_exponent_sign([]=Cs, _St, Line, Col, Toks, Ncs, Us) -> scan_exponent_sign(Cs, St, Line, Col, Toks, Ncs, Us) -> scan_exponent(Cs, St, Line, Col, Toks, Ncs, Us). -scan_exponent(Cs, St, Line, Col, Toks, {Ncs, Us}) -> +scan_exponent(Cs, #erl_scan{}=St, Line, Col, Toks, {Ncs, Us}) -> scan_exponent(Cs, St, Line, Col, Toks, Ncs, Us). scan_exponent([C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> @@ -1088,14 +1149,18 @@ scan_exponent(Cs, St, Line, Col, Toks, Ncs, Us) -> float_end(Cs, St, Line, Col, Toks, Ncs0, Us) -> Ncs = lists:reverse(Ncs0), - case catch list_to_float(remove_digit_separators(Ncs, Us)) of - F when is_float(F) -> - tok3(Cs, St, Line, Col, Toks, float, Ncs, F); - _ -> + try list_to_float(remove_digit_separators(Ncs, Us)) of + F -> + tok3(Cs, St, Line, Col, Toks, float, Ncs, F) + catch + _:_ -> Ncol = incr_column(Col, length(Ncs)), scan_error({illegal,float}, Line, Col, Line, Ncol, Cs) end. +skip_comment_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) -> + skip_comment(Cs, St, Line, Col, Toks, N). + skip_comment([C|Cs], St, Line, Col, Toks, N) when C =/= $\n, ?CHAR(C) -> case ?UNICODE(C) of true -> @@ -1105,11 +1170,15 @@ skip_comment([C|Cs], St, Line, Col, Toks, N) when C =/= $\n, ?CHAR(C) -> scan_error({illegal,character}, Line, Col, Line, Ncol, Cs) end; skip_comment([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun skip_comment/6}}; + {more,{Cs,Col,Toks,Line,N,fun skip_comment_fun/6}}; skip_comment(Cs, St, Line, Col, Toks, N) -> scan1(Cs, St, Line, incr_column(Col, N), Toks). -scan_comment([C|Cs], St, Line, Col, Toks, Ncs) when C =/= $\n, ?CHAR(C) -> +scan_comment_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_comment(Cs, St, Line, Col, Toks, Ncs). + +scan_comment([C|Cs], St, Line, Col, Toks, Ncs) + when C =/= $\n, ?CHAR(C) -> case ?UNICODE(C) of true -> scan_comment(Cs, St, Line, Col, Toks, [C|Ncs]); @@ -1118,33 +1187,33 @@ scan_comment([C|Cs], St, Line, Col, Toks, Ncs) when C =/= $\n, ?CHAR(C) -> scan_error({illegal,character}, Line, Col, Line, Ncol, Cs) end; scan_comment([]=Cs, _St, Line, Col, Toks, Ncs) -> - {more,{Cs,Col,Toks,Line,Ncs,fun scan_comment/6}}; + {more,{Cs,Col,Toks,Line,Ncs,fun scan_comment_fun/6}}; scan_comment(Cs, St, Line, Col, Toks, Ncs0) -> Ncs = lists:reverse(Ncs0), tok3(Cs, St, Line, Col, Toks, comment, Ncs, Ncs). tok2(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, _Wcs, P) -> scan1(Cs, St, Line, Col, [{P,anno(Line)}|Toks]); -tok2(Cs, St, Line, Col, Toks, Wcs, P) -> +tok2(Cs, #erl_scan{}=St, Line, Col, Toks, Wcs, P) -> Anno = anno(Line, Col, St, ?STR(P, St, Wcs)), scan1(Cs, St, Line, incr_column(Col, length(Wcs)), [{P,Anno}|Toks]). tok2(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, _Wcs, P, _N) -> scan1(Cs, St, Line, Col, [{P,anno(Line)}|Toks]); -tok2(Cs, St, Line, Col, Toks, Wcs, P, N) -> +tok2(Cs, #erl_scan{}=St, Line, Col, Toks, Wcs, P, N) -> Anno = anno(Line, Col, St, ?STR(P,St,Wcs)), scan1(Cs, St, Line, incr_column(Col, N), [{P,Anno}|Toks]). tok3(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, Item, _S, Sym) -> scan1(Cs, St, Line, Col, [{Item,anno(Line),Sym}|Toks]); -tok3(Cs, St, Line, Col, Toks, Item, String, Sym) -> +tok3(Cs, #erl_scan{}=St, Line, Col, Toks, Item, String, Sym) -> Token = {Item,anno(Line, Col, St, ?STR(Item, St, String)),Sym}, scan1(Cs, St, Line, incr_column(Col, length(String)), [Token|Toks]). tok3(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, Item, _String, Sym, _Length) -> scan1(Cs, St, Line, Col, [{Item,anno(Line),Sym}|Toks]); -tok3(Cs, St, Line, Col, Toks, Item, String, Sym, Length) -> +tok3(Cs, #erl_scan{}=St, Line, Col, Toks, Item, String, Sym, Length) -> Token = {Item,anno(Line, Col, St, ?STR(Item, St, String)),Sym}, scan1(Cs, St, Line, incr_column(Col, Length), [Token|Toks]). diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index 8bf4e97b9f..fc8e8110a0 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -78,8 +78,10 @@ -include_lib("kernel/include/file.hrl"). --define(IS_DRIVELETTER(Letter),(((Letter >= $A) andalso (Letter =< $Z)) orelse - ((Letter >= $a) andalso (Letter =< $z)))). +-define(IS_DRIVELETTER(Letter), + (is_integer(Letter) + andalso (($A =< Letter andalso Letter =< $Z) + orelse ($a =< Letter andalso Letter =< $z)))). %% Converts a relative filename to an absolute filename %% or the filename itself if it already is an absolute filename @@ -333,8 +335,7 @@ dirname([$/|Rest], Dir, File, Seps) -> dirname([DirSep|Rest], Dir, File, {DirSep,_}=Seps) when is_integer(DirSep) -> dirname(Rest, File++Dir, [$/], Seps); dirname([Dl,DrvSep|Rest], [], [], {_,DrvSep}=Seps) - when is_integer(DrvSep), ((($a =< Dl) and (Dl =< $z)) or - (($A =< Dl) and (Dl =< $Z))) -> + when is_integer(DrvSep), ?IS_DRIVELETTER(Dl) -> dirname(Rest, [DrvSep,Dl], [], Seps); dirname([Char|Rest], Dir, File, Seps) when is_integer(Char) -> dirname(Rest, Dir, [Char|File], Seps); @@ -757,7 +758,8 @@ win32_split([X, $\\|Rest]) when is_integer(X) -> win32_split([X, $/|Rest]); win32_split([X, Y, $\\|Rest]) when is_integer(X), is_integer(Y) -> win32_split([X, Y, $/|Rest]); -win32_split([UcLetter, $:|Rest]) when UcLetter >= $A, UcLetter =< $Z -> +win32_split([UcLetter, $:|Rest]) + when is_integer(UcLetter), $A =< UcLetter, UcLetter =< $Z -> win32_split([UcLetter+$a-$A, $:|Rest]); win32_split([Letter, $:, $/|Rest]) -> split(Rest, [], [[Letter, $:, $/]], win32); diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl index 8dda0d4ee0..93131d1b24 100644 --- a/lib/stdlib/src/gb_sets.erl +++ b/lib/stdlib/src/gb_sets.erl @@ -259,13 +259,13 @@ is_member_1(_, nil) -> Set1 :: set(Element), Set2 :: set(Element). -insert(Key, {S, T}) -> +insert(Key, {S, T}) when is_integer(S), S >= 0 -> S1 = S + 1, {S1, insert_1(Key, T, ?pow(S1, ?p))}. insert_1(Key, {Key1, Smaller, Bigger}, S) when Key < Key1 -> case insert_1(Key, Smaller, ?div2(S)) of - {T1, H1, S1} when is_integer(H1) -> + {T1, H1, S1} when is_integer(H1), is_integer(S1) -> T = {Key1, T1, Bigger}, {H2, S2} = count(Bigger), H = ?mul2(erlang:max(H1, H2)), @@ -282,7 +282,7 @@ insert_1(Key, {Key1, Smaller, Bigger}, S) when Key < Key1 -> end; insert_1(Key, {Key1, Smaller, Bigger}, S) when Key > Key1 -> case insert_1(Key, Bigger, ?div2(S)) of - {T1, H1, S1} when is_integer(H1) -> + {T1, H1, S1} when is_integer(H1), is_integer(S1) -> T = {Key1, Smaller, T1}, {H2, S2} = count(Smaller), H = ?mul2(erlang:max(H1, H2)), @@ -317,7 +317,7 @@ count(nil) -> Set1 :: set(Element), Set2 :: set(Element). -balance({S, T}) -> +balance({S, T}) when is_integer(S), S >= 0 -> {S, balance(T, S)}. balance(T, S) -> @@ -550,9 +550,9 @@ next([]) -> Set2 :: set(Element), Set3 :: set(Element). -union({N1, T1}, {N2, T2}) when N2 < N1 -> +union({N1, T1}, {N2, T2}) when is_integer(N1), is_integer(N2), N2 < N1 -> union(to_list_1(T2), N2, T1, N1); -union({N1, T1}, {N2, T2}) -> +union({N1, T1}, {N2, T2}) when is_integer(N1), is_integer(N2) -> union(to_list_1(T1), N1, T2, N2). %% We avoid the expensive mathematical computations if there is little @@ -633,7 +633,7 @@ push([X | Xs], As) -> push([], As) -> As. -balance_revlist(L, S) -> +balance_revlist(L, S) when is_integer(S) -> {T, _} = balance_revlist_1(L, S), T. @@ -670,9 +670,9 @@ union_list(S, []) -> S. Set2 :: set(Element), Set3 :: set(Element). -intersection({N1, T1}, {N2, T2}) when N2 < N1 -> +intersection({N1, T1}, {N2, T2}) when is_integer(N1), is_integer(N2), N2 < N1 -> intersection(to_list_1(T2), N2, T1, N1); -intersection({N1, T1}, {N2, T2}) -> +intersection({N1, T1}, {N2, T2}) when is_integer(N1), is_integer(N2) -> intersection(to_list_1(T1), N1, T2, N2). intersection(L, _N1, T2, N2) when N2 < 10 -> @@ -770,7 +770,8 @@ subtract(S1, S2) -> Set2 :: set(Element), Set3 :: set(Element). -difference({N1, T1}, {N2, T2}) -> +difference({N1, T1}, {N2, T2}) when is_integer(N1), N1 >= 0, + is_integer(N2), N2 >= 0 -> difference(to_list_1(T1), N1, T2, N2). difference(L, N1, T2, N2) when N2 < 10 -> @@ -820,7 +821,8 @@ difference_2(Xs, [], As, S) -> Set1 :: set(Element), Set2 :: set(Element). -is_subset({N1, T1}, {N2, T2}) -> +is_subset({N1, T1}, {N2, T2}) when is_integer(N1), N1 >= 0, + is_integer(N2), N2 >= 0 -> is_subset(to_list_1(T1), N1, T2, N2). is_subset(L, _N1, T2, N2) when N2 < 10 -> diff --git a/lib/stdlib/src/gb_trees.erl b/lib/stdlib/src/gb_trees.erl index c0cdde012e..2d5d013a25 100644 --- a/lib/stdlib/src/gb_trees.erl +++ b/lib/stdlib/src/gb_trees.erl @@ -279,7 +279,7 @@ insert(Key, Val, {S, T}) when is_integer(S) -> insert_1(Key, Value, {Key1, V, Smaller, Bigger}, S) when Key < Key1 -> case insert_1(Key, Value, Smaller, ?div2(S)) of - {T1, H1, S1} -> + {T1, H1, S1} when is_integer(H1), is_integer(S1) -> T = {Key1, V, T1, Bigger}, {H2, S2} = count(Bigger), H = ?mul2(erlang:max(H1, H2)), @@ -296,7 +296,7 @@ insert_1(Key, Value, {Key1, V, Smaller, Bigger}, S) when Key < Key1 -> end; insert_1(Key, Value, {Key1, V, Smaller, Bigger}, S) when Key > Key1 -> case insert_1(Key, Value, Bigger, ?div2(S)) of - {T1, H1, S1} -> + {T1, H1, S1} when is_integer(H1), is_integer(S1) -> T = {Key1, V, Smaller, T1}, {H2, S2} = count(Smaller), H = ?mul2(erlang:max(H1, H2)), @@ -349,7 +349,7 @@ count(nil) -> Tree1 :: tree(Key, Value), Tree2 :: tree(Key, Value). -balance({S, T}) -> +balance({S, T}) when is_integer(S), S >= 0 -> {S, balance(T, S)}. balance(T, S) -> diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl index e2823b70f2..9f7e05a740 100644 --- a/lib/stdlib/src/io_lib.erl +++ b/lib/stdlib/src/io_lib.erl @@ -350,9 +350,9 @@ write(Term, Options) when is_list(Options) -> if Depth =:= 0; CharsLimit =:= 0 -> "..."; - CharsLimit < 0 -> + is_integer(CharsLimit), CharsLimit < 0, is_integer(Depth) -> write1(Term, Depth, Encoding); - CharsLimit > 0 -> + is_integer(CharsLimit), CharsLimit > 0 -> RecDefFun = fun(_, _) -> no end, If = io_lib_pretty:intermediate (Term, Depth, CharsLimit, RecDefFun, Encoding, _Str=false), @@ -439,7 +439,7 @@ write_binary(B, D) when is_integer(D) -> {S, _} = write_binary(B, D, -1), S. -write_binary(B, D, T) -> +write_binary(B, D, T) when is_integer(T) -> {S, Rest} = write_binary_body(B, D, tsub(T, 4), []), {[$<,$<,lists:reverse(S),$>,$>], Rest}. @@ -509,15 +509,16 @@ quote_atom(Atom, Cs0) -> true -> true; false -> case Cs0 of - [C|Cs] when C >= $a, C =< $z -> + [C|Cs] when is_integer(C), C >= $a, C =< $z -> not name_chars(Cs); - [C|Cs] when C >= $ß, C =< $ÿ, C =/= $÷ -> + [C|Cs] when is_integer(C), C >= $ß, C =< $ÿ, C =/= $÷ -> not name_chars(Cs); - _ -> true + [C|_] when is_integer(C) -> true; + [] -> true end end. -name_chars([C|Cs]) -> +name_chars([C|Cs]) when is_integer(C) -> case name_char(C) of true -> name_chars(Cs); false -> false @@ -580,7 +581,7 @@ write_string_as_latin1(S, Q) -> write_string1(_,[], Q) -> [Q]; -write_string1(Enc,[C|Cs], Q) -> +write_string1(Enc,[C|Cs], Q) when is_integer(C) -> string_char(Enc,C, Q, write_string1(Enc,Cs, Q)). string_char(_,Q, Q, Tail) -> [$\\,Q|Tail]; %Must check these first! @@ -803,7 +804,7 @@ collect_chars(Tag, Data, N) -> collect_chars(Tag, Data, latin1, N). %% Now we are aware of encoding... -collect_chars(start, Data, unicode, N) when is_binary(Data) -> +collect_chars(start, Data, unicode, N) when is_binary(Data), is_integer(N) -> {Size,Npos} = count_and_find_utf8(Data,N), if Size > N -> {B1,B2} = split_binary(Data, Npos), @@ -813,7 +814,7 @@ collect_chars(start, Data, unicode, N) when is_binary(Data) -> true -> {stop,Data,eof} end; -collect_chars(start, Data, latin1, N) when is_binary(Data) -> +collect_chars(start, Data, latin1, N) when is_binary(Data), is_integer(N) -> Size = byte_size(Data), if Size > N -> {B1,B2} = split_binary(Data, N), @@ -823,13 +824,13 @@ collect_chars(start, Data, latin1, N) when is_binary(Data) -> true -> {stop,Data,eof} end; -collect_chars(start,Data,_,N) when is_list(Data) -> +collect_chars(start,Data,_,N) when is_list(Data), is_integer(N) -> collect_chars_list([], N, Data); collect_chars(start, eof, _,_) -> {stop,eof,eof}; collect_chars({binary,Stack,_N}, eof, _,_) -> {stop,binrev(Stack),eof}; -collect_chars({binary,Stack,N}, Data,unicode, _) -> +collect_chars({binary,Stack,N}, Data,unicode, _) when is_integer(N) -> {Size,Npos} = count_and_find_utf8(Data,N), if Size > N -> {B1,B2} = split_binary(Data, Npos), @@ -839,7 +840,7 @@ collect_chars({binary,Stack,N}, Data,unicode, _) -> true -> {stop,binrev(Stack, [Data]),eof} end; -collect_chars({binary,Stack,N}, Data,latin1, _) -> +collect_chars({binary,Stack,N}, Data,latin1, _) when is_integer(N) -> Size = byte_size(Data), if Size > N -> {B1,B2} = split_binary(Data, N), @@ -849,7 +850,7 @@ collect_chars({binary,Stack,N}, Data,latin1, _) -> true -> {stop,binrev(Stack, [Data]),eof} end; -collect_chars({list,Stack,N}, Data, _,_) -> +collect_chars({list,Stack,N}, Data, _,_) when is_integer(N) -> collect_chars_list(Stack, N, Data); %% collect_chars(Continuation, MoreChars, Count) @@ -857,9 +858,9 @@ collect_chars({list,Stack,N}, Data, _,_) -> %% {done,Result,RestChars} %% {more,Continuation} -collect_chars([], Chars, _, N) -> +collect_chars([], Chars, _, N) when is_integer(N) -> collect_chars1(N, Chars, []); -collect_chars({Left,Sofar}, Chars, _, _N) -> +collect_chars({Left,Sofar}, Chars, _, _N) when is_integer(Left) -> collect_chars1(Left, Chars, Sofar). collect_chars1(N, Chars, Stack) when N =< 0 -> @@ -991,13 +992,13 @@ binrev(L) -> binrev(L, T) -> list_to_binary(lists:reverse(L, T)). --spec limit_term(term(), non_neg_integer()) -> term(). +-spec limit_term(term(), depth()) -> term(). %% The intention is to mimic the depth limitation of io_lib:write() %% and io_lib_pretty:print(). The leaves ('...') should never be %% seen when printed with the same depth. Bitstrings are never %% truncated, which is OK as long as they are not sent to other nodes. -limit_term(Term, Depth) -> +limit_term(Term, Depth) when is_integer(Depth), Depth >= -1 -> try test_limit(Term, Depth) of ok -> Term catch diff --git a/lib/stdlib/src/string.erl b/lib/stdlib/src/string.erl index a418754caf..3c62dd9333 100644 --- a/lib/stdlib/src/string.erl +++ b/lib/stdlib/src/string.erl @@ -76,7 +76,9 @@ -import(lists,[member/2]). -compile({no_auto_import,[length/1]}). -compile({inline, [btoken/2, rev/1, append/2, stack/2, search_compile/1]}). --define(ASCII_LIST(CP1,CP2), CP1 < 256, CP2 < 256, CP1 =/= $\r). +-define(ASCII_LIST(CP1,CP2), + is_integer(CP1), 0 =< CP1, CP1 < 256, + is_integer(CP2), 0 =< CP2, CP2 < 256, CP1 =/= $\r). -export_type([grapheme_cluster/0]). @@ -198,7 +200,7 @@ slice(CD, N, Length) [] when is_binary(CD) -> <<>>; L -> slice_trail(L, Length) end; -slice(CD, N, infinity) -> +slice(CD, N, infinity) when is_integer(N), N >= 0 -> case slice_l0(CD, N) of [] when is_binary(CD) -> <<>>; Res -> Res @@ -261,11 +263,13 @@ trim(Str, Dir) -> Dir :: direction() | 'both', Characters :: [grapheme_cluster()]. trim(Str, _, []) -> Str; -trim(Str, leading, [Sep]) when is_list(Str), Sep < 256 -> +trim(Str, leading, [Sep]) + when is_list(Str), is_integer(Sep), 0 =< Sep, Sep < 256 -> trim_ls(Str, Sep); trim(Str, leading, Sep) when is_list(Sep) -> trim_l(Str, Sep); -trim(Str, trailing, [Sep]) when is_list(Str), Sep < 256 -> +trim(Str, trailing, [Sep]) + when is_list(Str), is_integer(Sep), 0 =< Sep, Sep < 256 -> trim_ts(Str, Sep); trim(Str, trailing, Seps0) when is_list(Seps0) -> Seps = search_pattern(Seps0), @@ -630,9 +634,10 @@ slice_l0(<<CP1/utf8, Bin/binary>>, N) when N > 0 -> slice_l0(L, N) -> slice_l(L, N). -slice_l([CP1|[CP2|_]=Cont], N) when ?ASCII_LIST(CP1,CP2),N > 0 -> +slice_l([CP1|[CP2|_]=Cont], N) + when ?ASCII_LIST(CP1,CP2), is_integer(N), N > 0 -> slice_l(Cont, N-1); -slice_l(CD, N) when N > 0 -> +slice_l(CD, N) when is_integer(N), N > 0 -> case unicode_util:gc(CD) of [_|Cont] -> slice_l(Cont, N-1); [] -> []; @@ -641,7 +646,8 @@ slice_l(CD, N) when N > 0 -> slice_l(Cont, 0) -> Cont. -slice_lb(<<CP2/utf8, Bin/binary>>, CP1, N) when ?ASCII_LIST(CP1,CP2), N > 1 -> +slice_lb(<<CP2/utf8, Bin/binary>>, CP1, N) + when ?ASCII_LIST(CP1,CP2), is_integer(N), N > 1 -> slice_lb(Bin, CP2, N-1); slice_lb(Bin, CP1, N) -> [_|Rest] = unicode_util:gc([CP1|Bin]), @@ -693,9 +699,13 @@ slice_bin(CD, CP1, N) when N > 0 -> slice_bin(CD, CP1, 0) -> byte_size(CD)+byte_size(<<CP1/utf8>>). -uppercase_list([CP1|[CP2|_]=Cont], _Changed) when $a =< CP1, CP1 =< $z, CP2 < 256 -> +uppercase_list([CP1|[CP2|_]=Cont], _Changed) + when is_integer(CP1), $a =< CP1, CP1 =< $z, + is_integer(CP2), 0 =< CP2, CP2 < 256 -> [CP1-32|uppercase_list(Cont, true)]; -uppercase_list([CP1|[CP2|_]=Cont], Changed) when CP1 < 128, CP2 < 256 -> +uppercase_list([CP1|[CP2|_]=Cont], Changed) + when is_integer(CP1), 0 =< CP1, CP1 < 128, + is_integer(CP2), 0 =< CP2, CP2 < 256 -> [CP1|uppercase_list(Cont, Changed)]; uppercase_list([], true) -> []; @@ -709,16 +719,16 @@ uppercase_list(CPs0, Changed) -> end. uppercase_bin(CP1, <<CP2/utf8, Bin/binary>>, _Changed) - when $a =< CP1, CP1 =< $z, CP2 < 256 -> + when is_integer(CP1), $a =< CP1, CP1 =< $z, CP2 < 256 -> [CP1-32|uppercase_bin(CP2, Bin, true)]; uppercase_bin(CP1, <<CP2/utf8, Bin/binary>>, Changed) - when CP1 < 128, CP2 < 256 -> + when is_integer(CP1), 0 =< CP1, CP1 < 128, CP2 < 256 -> [CP1|uppercase_bin(CP2, Bin, Changed)]; uppercase_bin(CP1, Bin, Changed) -> case unicode_util:uppercase([CP1|Bin]) of [CP1|CPs] -> case unicode_util:cp(CPs) of - [Next|Rest] -> + [Next|Rest] when is_integer(Next), Next >= 0 -> [CP1|uppercase_bin(Next, Rest, Changed)]; [] when Changed -> [CP1]; @@ -729,7 +739,7 @@ uppercase_bin(CP1, Bin, Changed) -> end; [Char|CPs] -> case unicode_util:cp(CPs) of - [Next|Rest] -> + [Next|Rest] when is_integer(Next), Next >= 0 -> [Char|uppercase_bin(Next, Rest, true)]; [] -> [Char]; @@ -738,9 +748,13 @@ uppercase_bin(CP1, Bin, Changed) -> end end. -lowercase_list([CP1|[CP2|_]=Cont], _Changed) when $A =< CP1, CP1 =< $Z, CP2 < 256 -> +lowercase_list([CP1|[CP2|_]=Cont], _Changed) + when is_integer(CP1), $A =< CP1, CP1 =< $Z, + is_integer(CP2), 0 =< CP2, CP2 < 256 -> [CP1+32|lowercase_list(Cont, true)]; -lowercase_list([CP1|[CP2|_]=Cont], Changed) when CP1 < 128, CP2 < 256 -> +lowercase_list([CP1|[CP2|_]=Cont], Changed) + when is_integer(CP1), 0 =< CP1, CP1 < 128, + is_integer(CP2), 0 =< CP2, CP2 < 256 -> [CP1|lowercase_list(Cont, Changed)]; lowercase_list([], true) -> []; @@ -754,16 +768,16 @@ lowercase_list(CPs0, Changed) -> end. lowercase_bin(CP1, <<CP2/utf8, Bin/binary>>, _Changed) - when $A =< CP1, CP1 =< $Z, CP2 < 256 -> + when is_integer(CP1), $A =< CP1, CP1 =< $Z, CP2 < 256 -> [CP1+32|lowercase_bin(CP2, Bin, true)]; lowercase_bin(CP1, <<CP2/utf8, Bin/binary>>, Changed) - when CP1 < 128, CP2 < 256 -> + when is_integer(CP1), 0 =< CP1, CP1 < 128, CP2 < 256 -> [CP1|lowercase_bin(CP2, Bin, Changed)]; lowercase_bin(CP1, Bin, Changed) -> case unicode_util:lowercase([CP1|Bin]) of [CP1|CPs] -> case unicode_util:cp(CPs) of - [Next|Rest] -> + [Next|Rest] when is_integer(Next), Next >= 0 -> [CP1|lowercase_bin(Next, Rest, Changed)]; [] when Changed -> [CP1]; @@ -774,7 +788,7 @@ lowercase_bin(CP1, Bin, Changed) -> end; [Char|CPs] -> case unicode_util:cp(CPs) of - [Next|Rest] -> + [Next|Rest] when is_integer(Next), Next >= 0 -> [Char|lowercase_bin(Next, Rest, true)]; [] -> [Char]; @@ -783,9 +797,13 @@ lowercase_bin(CP1, Bin, Changed) -> end end. -casefold_list([CP1|[CP2|_]=Cont], _Changed) when $A =< CP1, CP1 =< $Z, CP2 < 256 -> +casefold_list([CP1|[CP2|_]=Cont], _Changed) + when is_integer(CP1), $A =< CP1, CP1 =< $Z, + is_integer(CP2), 0 =< CP2, CP2 < 256 -> [CP1+32|casefold_list(Cont, true)]; -casefold_list([CP1|[CP2|_]=Cont], Changed) when CP1 < 128, CP2 < 256 -> +casefold_list([CP1|[CP2|_]=Cont], Changed) + when is_integer(CP1), 0 =< CP1, CP1 < 128, + is_integer(CP2), 0 =< CP2, CP2 < 256 -> [CP1|casefold_list(Cont, Changed)]; casefold_list([], true) -> []; @@ -799,16 +817,16 @@ casefold_list(CPs0, Changed) -> end. casefold_bin(CP1, <<CP2/utf8, Bin/binary>>, _Changed) - when $A =< CP1, CP1 =< $Z, CP2 < 256 -> + when is_integer(CP1), $A =< CP1, CP1 =< $Z, CP2 < 256 -> [CP1+32|casefold_bin(CP2, Bin, true)]; casefold_bin(CP1, <<CP2/utf8, Bin/binary>>, Changed) - when CP1 < 128, CP2 < 256 -> + when is_integer(CP1), 0 =< CP1, CP1 < 128, CP2 < 256 -> [CP1|casefold_bin(CP2, Bin, Changed)]; casefold_bin(CP1, Bin, Changed) -> case unicode_util:casefold([CP1|Bin]) of [CP1|CPs] -> case unicode_util:cp(CPs) of - [Next|Rest] -> + [Next|Rest] when is_integer(Next), Next >= 0 -> [CP1|casefold_bin(Next, Rest, Changed)]; [] when Changed -> [CP1]; @@ -819,7 +837,7 @@ casefold_bin(CP1, Bin, Changed) -> end; [Char|CPs] -> case unicode_util:cp(CPs) of - [Next|Rest] -> + [Next|Rest] when is_integer(Next), Next >= 0 -> [Char|casefold_bin(Next, Rest, true)]; [] -> [Char]; @@ -1734,7 +1752,7 @@ bin_search_str_2(Bin0, Start, Cont, First, SearchCPs) -> <<_:Start/binary, Bin/binary>> = Bin0, case binary:match(Bin, First) of nomatch -> {nomatch, byte_size(Bin0), Cont}; - {Where0, _} -> + {Where0, _} when is_integer(Where0) -> Where = Start+Where0, <<Keep:Where/binary, Cs0/binary>> = Bin0, [GC|Cs]=unicode_util:gc(Cs0), @@ -1979,7 +1997,7 @@ chars(C, N) -> chars(C, N, []). Tail :: string(), String :: string(). -chars(C, N, Tail) when N > 0 -> +chars(C, N, Tail) when is_integer(N), N > 0 -> chars(C, N-1, [C|Tail]); chars(C, 0, Tail) when is_integer(C) -> Tail. @@ -2109,7 +2127,7 @@ left(String, Len) when is_integer(Len) -> left(String, Len, $\s). Number :: non_neg_integer(), Character :: char(). -left(String, Len, Char) when is_integer(Char) -> +left(String, Len, Char) when is_integer(Len), is_integer(Char) -> Slen = erlang:length(String), if Slen > Len -> substr(String, 1, Len); @@ -2134,7 +2152,7 @@ right(String, Len) when is_integer(Len) -> right(String, Len, $\s). Number :: non_neg_integer(), Character :: char(). -right(String, Len, Char) when is_integer(Char) -> +right(String, Len, Char) when is_integer(Len), is_integer(Char) -> Slen = erlang:length(String), if Slen > Len -> substr(String, Slen-Len+1); @@ -2161,7 +2179,7 @@ centre(String, Len) when is_integer(Len) -> centre(String, Len, $\s). centre(String, 0, Char) when is_list(String), is_integer(Char) -> []; % Strange cases to centre string -centre(String, Len, Char) when is_integer(Char) -> +centre(String, Len, Char) when is_integer(Len), is_integer(Char) -> Slen = erlang:length(String), if Slen > Len -> substr(String, (Slen-Len) div 2 + 1, Len); @@ -2186,7 +2204,8 @@ sub_string(String, Start) -> substr(String, Start). Start :: pos_integer(), Stop :: pos_integer(). -sub_string(String, Start, Stop) -> substr(String, Start, Stop - Start + 1). +sub_string(String, Start, Stop) when is_integer(Start), is_integer(Stop) -> + substr(String, Start, Stop - Start + 1). %% ISO/IEC 8859-1 (latin1) letters are converted, others are ignored %% diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl index ee8bc8420f..6c4694bebe 100644 --- a/lib/stdlib/test/erl_scan_SUITE.erl +++ b/lib/stdlib/test/erl_scan_SUITE.erl @@ -676,6 +676,8 @@ illegal() -> crashes() -> {'EXIT',_} = (catch {foo, erl_scan:string([-1])}), % type error + {'EXIT',_} = (catch erl_scan:string("'a" ++ [999999999] ++ "c'")), + {'EXIT',_} = (catch {foo, erl_scan:string("$"++[-1])}), {'EXIT',_} = (catch {foo, erl_scan:string("$\\"++[-1])}), {'EXIT',_} = (catch {foo, erl_scan:string("$\\^"++[-1])}), @@ -698,6 +700,7 @@ crashes() -> (catch {foo, erl_scan:string("% foo"++[a],{1,1})}), {'EXIT',_} = (catch {foo, erl_scan:string([3.0])}), % type error + {'EXIT',_} = (catch {foo, erl_scan:string("A" ++ [999999999])}), ok. @@ -867,8 +870,8 @@ unicode() -> erl_scan:string([1089]), {error,{{1,1},erl_scan,{illegal,character}},{1,2}} = erl_scan:string([1089], {1,1}), - {error,{{1,3},erl_scan,{illegal,character}},{1,4}} = - erl_scan:string("'a" ++ [999999999] ++ "c'", {1,1}), + {error,{{1,1},erl_scan,{illegal,character}},{1,2}} = + erl_scan:string([16#D800], {1,1}), test("\"a"++[1089]++"b\""), {ok,[{char,1,1}],1} = diff --git a/lib/stdlib/uc_spec/gen_unicode_mod.escript b/lib/stdlib/uc_spec/gen_unicode_mod.escript index b459141d68..6f55f6da45 100644 --- a/lib/stdlib/uc_spec/gen_unicode_mod.escript +++ b/lib/stdlib/uc_spec/gen_unicode_mod.escript @@ -335,7 +335,7 @@ gen_norm(Fd) -> "-spec nfd(unicode:chardata()) -> maybe_improper_list(gc(),unicode:chardata()) | {error, unicode:chardata()}.\n" "nfd(Str0) ->\n" " case gc(Str0) of\n" - " [GC|R] when GC < 128 -> [GC|R];\n" + " [GC|R] when is_integer(GC), 0 =< GC, GC < 128 -> [GC|R];\n" " [GC|Str] -> [decompose(GC)|Str];\n" " [] -> [];\n" " {error,_}=Error -> Error\n end.\n\n" @@ -345,7 +345,7 @@ gen_norm(Fd) -> "-spec nfkd(unicode:chardata()) -> maybe_improper_list(gc(),unicode:chardata()) | {error, unicode:chardata()}.\n" "nfkd(Str0) ->\n" " case gc(Str0) of\n" - " [GC|R] when GC < 128 -> [GC|R];\n" + " [GC|R] when is_integer(GC), 0 =< GC, GC < 128 -> [GC|R];\n" " [GC|Str] -> [decompose_compat(GC)|Str];\n" " [] -> [];\n" " {error,_}=Error -> Error\n end.\n\n" @@ -355,7 +355,7 @@ gen_norm(Fd) -> "-spec nfc(unicode:chardata()) -> maybe_improper_list(gc(),unicode:chardata()) | {error, unicode:chardata()}.\n" "nfc(Str0) ->\n" " case gc(Str0) of\n" - " [GC|R] when GC < 256 -> [GC|R];\n" + " [GC|R] when is_integer(GC), 0 =< GC, GC < 256 -> [GC|R];\n" " [GC|Str] -> [compose(decompose(GC))|Str];\n" " [] -> [];\n" " {error,_}=Error -> Error\n end.\n\n" @@ -365,7 +365,7 @@ gen_norm(Fd) -> "-spec nfkc(unicode:chardata()) -> maybe_improper_list(gc(),unicode:chardata()) | {error, unicode:chardata()}.\n" "nfkc(Str0) ->\n" " case gc(Str0) of\n" - " [GC|R] when GC < 128 -> [GC|R];\n" + " [GC|R] when is_integer(GC), 0 =< GC, GC < 128 -> [GC|R];\n" " [GC|Str] -> [compose_compat_0(decompose_compat(GC))|Str];\n" " [] -> [];\n" " {error,_}=Error -> Error\n end.\n\n" @@ -380,7 +380,7 @@ gen_norm(Fd) -> "decompose(CP) ->\n" " canonical_order(decompose_1(CP)).\n" "\n" - "decompose_1(CP) when 16#AC00 =< CP, CP =< 16#D7A3 ->\n" + "decompose_1(CP) when is_integer(CP), 16#AC00 =< CP, CP =< 16#D7A3 ->\n" " Syll = CP-16#AC00,\n" " T = 28,\n" " N = 588,\n" @@ -424,7 +424,7 @@ gen_norm(Fd) -> "decompose_compat(CP) ->\n" " canonical_order(decompose_compat_1(CP)).\n" "\n" - "decompose_compat_1(CP) when 16#AC00 =< CP, CP =< 16#D7A3 ->\n" + "decompose_compat_1(CP) when is_integer(CP), 16#AC00 =< CP, CP =< 16#D7A3 ->\n" " Syll = CP-16#AC00,\n" " T = 28,\n" " N = 588,\n" @@ -442,17 +442,18 @@ gen_norm(Fd) -> " end;\n" "decompose_compat_1([CP|CPs]) ->\n" " decompose_compat_1(CP) ++ decompose_compat_1(CPs);\n" - "decompose_compat_1([]) -> [].\n"), + "decompose_compat_1([]) -> [].\n\n"), io:put_chars(Fd, "compose(CP) when is_integer(CP) -> CP;\n" "compose([Lead,Vowel|Trail]) %% Hangul\n" - " when 16#1100 =< Lead, Lead =< 16#1112 ->\n" + " when is_integer(Lead), 16#1100 =< Lead, Lead =< 16#1112, is_integer(Vowel) ->\n" " if 16#1161 =< Vowel, Vowel =< 16#1175 ->\n" " CP = 16#AC00 + ((Lead - 16#1100) * 588) + ((Vowel - 16#1161) * 28),\n" " case Trail of\n" - " [T|Acc] when 16#11A7 =< T, T =< 16#11C2 -> nolist(CP+T-16#11A7,Acc);\n" + " [T|Acc] when is_integer(T), 16#11A7 =< T, T =< 16#11C2 ->" + " nolist(CP+T-16#11A7,Acc);\n" " Acc -> nolist(CP,Acc)\n" " end;\n" " true ->\n" @@ -494,11 +495,12 @@ gen_norm(Fd) -> " end.\n\n" "compose_compat(CP) when is_integer(CP) -> CP;\n" "compose_compat([Lead,Vowel|Trail]) %% Hangul\n" - " when 16#1100 =< Lead, Lead =< 16#1112 ->\n" + " when is_integer(Lead), 16#1100 =< Lead, Lead =< 16#1112, is_integer(Vowel) ->\n" " if 16#1161 =< Vowel, Vowel =< 16#1175 ->\n" " CP = 16#AC00 + ((Lead - 16#1100) * 588) + ((Vowel - 16#1161) * 28),\n" " case Trail of\n" - " [T|Acc] when 16#11A7 =< T, T =< 16#11C2 -> nolist(CP+T-16#11A7,Acc);\n" + " [T|Acc] when is_integer(T), 16#11A7 =< T, T =< 16#11C2 ->" + " nolist(CP+T-16#11A7,Acc);\n" " Acc -> nolist(CP,Acc)\n" " end;\n" " true ->\n" @@ -634,12 +636,12 @@ gen_gc(Fd, GBP) -> " [$\\n|R1] -> [[$\\r,$\\n]|R1];\n" " T -> [CP|T]\n" " end;\n" - "gc([CP1|T1]=T) when CP1 < 256 andalso ?IS_CP(CP1) ->\n" + "gc([CP1|T1]=T) when ?IS_CP(CP1), CP1 < 256 ->\n" " case T1 of\n" - " [CP2|_] when CP2 < 256 -> T; %% Ascii Fast path\n" + " [CP2|_] when is_integer(CP2), 0 =< CP2, CP2 < 256 -> T; %% Ascii Fast path\n" " _ -> %% Keep the tail binary.\n" " case cp_no_bin(T1) of\n" - " [CP2|_]=T3 when CP2 < 256 -> [CP1|T3]; %% Asciii Fast path\n" + " [CP2|_]=T3 when is_integer(CP2), 0 =< CP2, CP2 < 256 -> [CP1|T3]; %% Asciii Fast path\n" " binary_found -> gc_1(T);\n" " T4 -> gc_1([CP1|T4])\n" " end\n" @@ -682,13 +684,14 @@ gen_gc(Fd, GBP) -> io:put_chars(Fd, "\n%% Optimize Latin-1\n"), [GenExtP(CP) || CP <- merge_ranges(ExtendedPictographicLow)], - io:format(Fd, - "gc_1([CP|R]=R0) when CP < 256 ->\n" - " case R of\n" - " [CP2|_] when CP2 < 256 -> R0;\n" - " _ -> gc_extend(cp(R), R, CP)\n" - " end;\n", - []), + io:put_chars(Fd, + "gc_1([CP|R]=R0) when is_integer(CP), 0 =< CP, CP < 256 ->\n" + " case R of\n" + " [CP2|_] when is_integer(CP2), 0 =< CP2, CP2 < 256 -> R0;\n" + " _ -> gc_extend(cp(R), R, CP)\n" + " end;\n" + "gc_1([CP|_]) when not ?IS_CP(CP) ->\n" + " error({badarg,CP});\n"), io:put_chars(Fd, "\n%% Continue control\n"), [GenControl(CP) || CP <- Crs], %% One clause per CP @@ -709,7 +712,7 @@ gen_gc(Fd, GBP) -> GenHangulT = fun(Range) -> io:format(Fd, "gc_1~s gc_h_T(R1,[CP]);\n", [gen_clause(Range)]) end, [GenHangulT(CP) || CP <- merge_ranges(maps:get(t,GBP))], io:put_chars(Fd, "%% Handle Hangul LV and LVT special, since they are large\n"), - io:put_chars(Fd, "gc_1([CP|_]=R0) when 44000 < CP, CP < 56000 -> gc_h_lv_lvt(R0, R0, []);\n"), + io:put_chars(Fd, "gc_1([CP|_]=R0) when is_integer(CP), 44000 < CP, CP < 56000 -> gc_h_lv_lvt(R0, R0, []);\n"), io:put_chars(Fd, "\n%% Handle Regional\n"), GenRegional = fun(Range) -> io:format(Fd, "gc_1~s gc_regional(R1,CP);\n", [gen_clause(Range)]) end, @@ -825,7 +828,9 @@ gen_gc(Fd, GBP) -> [{RLess,RLarge}] = merge_ranges(maps:get(regional_indicator,GBP)), io:put_chars(Fd,"gc_regional(R0, CP0) ->\n" " case cp(R0) of\n"), - io:format(Fd, " [CP|R1] when ~w =< CP,CP =< ~w-> gc_extend2(cp(R1),R1,[CP,CP0]);~n",[RLess, RLarge]), + io:format(Fd, " [CP|R1] when is_integer(CP), ~w =< CP, CP =< ~w ->\n" + " gc_extend2(cp(R1),R1,[CP,CP0]);~n", + [RLess, RLarge]), io:put_chars(Fd," R1 -> gc_extend(R1, R0, CP0)\n" " end.\n\n"), @@ -893,7 +898,8 @@ gen_compose_pairs(Fd, ExclData, Data) -> [io:format(Fd, "compose_pair(~w,~w) -> ~w;~n", [A,B,CP]) || {[A,B],CP} <- lists:sort(DeCmp2)], io:put_chars(Fd, "compose_pair(_,_) -> false.\n\n"), - io:put_chars(Fd, "nolist(CP, []) -> CP;\nnolist(CP,L) -> [CP|L].\n\n"), + io:put_chars(Fd, "nolist(CP, []) when ?IS_CP(CP) -> CP;\n" + "nolist(CP, L) when ?IS_CP(CP) -> [CP|L].\n\n"), ok. gen_case_table(Fd, Data) -> @@ -1164,23 +1170,23 @@ gen_width_table(Fd, WideChars) -> gen_clause({R0, undefined}) -> io_lib:format("([~w=CP|R1]=R0) ->", [R0]); gen_clause({R0, R1}) -> - io_lib:format("([CP|R1]=R0) when ~w =< CP, CP =< ~w ->", [R0,R1]). + io_lib:format("([CP|R1]=R0) when is_integer(CP), ~w =< CP, CP =< ~w ->", [R0,R1]). gen_clause2({R0, undefined}) -> io_lib:format("([~w=CP|R1], R0, Acc) ->", [R0]); gen_clause2({R0, R1}) -> - io_lib:format("([CP|R1], R0, Acc) when ~w =< CP, CP =< ~w ->", [R0,R1]). + io_lib:format("([CP|R1], R0, Acc) when is_integer(CP), ~w =< CP, CP =< ~w ->", [R0,R1]). gen_case_clause({R0, undefined}) -> io_lib:format("[~w=CP|R1] ->", [R0]); gen_case_clause({R0, R1}) -> - io_lib:format("[CP|R1] when ~w =< CP, CP =< ~w ->", [R0,R1]). + io_lib:format("[CP|R1] when is_integer(CP), ~w =< CP, CP =< ~w ->", [R0,R1]). gen_single_clause({R0, undefined}) -> io_lib:format("(~w) ->", [R0]); gen_single_clause({R0, R1}) -> - io_lib:format("(CP) when ~w =< CP, CP =< ~w ->", [R0,R1]). + io_lib:format("(CP) when is_integer(CP), ~w =< CP, CP =< ~w ->", [R0,R1]). merge_ranges(List) -> |