aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/doc/src/unicode_usage.xml13
-rw-r--r--lib/stdlib/src/c.erl20
-rw-r--r--lib/stdlib/src/epp.erl4
-rw-r--r--lib/stdlib/src/erl_eval.erl7
-rw-r--r--lib/stdlib/src/erl_internal.erl7
-rw-r--r--lib/stdlib/src/erl_lint.erl19
-rw-r--r--lib/stdlib/src/erl_scan.erl301
-rw-r--r--lib/stdlib/src/eval_bits.erl64
-rw-r--r--lib/stdlib/src/filelib.erl224
-rw-r--r--lib/stdlib/src/filename.erl28
-rw-r--r--lib/stdlib/src/io_lib_format.erl22
-rw-r--r--lib/stdlib/src/io_lib_pretty.erl68
-rw-r--r--lib/stdlib/src/otp_internal.erl2
-rw-r--r--lib/stdlib/src/shell.erl7
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl52
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl112
-rw-r--r--lib/stdlib/test/erl_scan_SUITE.erl108
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl40
-rw-r--r--lib/stdlib/test/io_SUITE.erl13
-rw-r--r--lib/stdlib/vsn.mk2
20 files changed, 597 insertions, 516 deletions
diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml
index 0a75fbeec0..354ec58df3 100644
--- a/lib/stdlib/doc/src/unicode_usage.xml
+++ b/lib/stdlib/doc/src/unicode_usage.xml
@@ -69,12 +69,11 @@ strings.</p>
<p>Character data may be combined from several sources, sometimes available in a mix of strings and binaries. Erlang has for long had the concept of <c>iodata</c> or <c>iolists</c>, where binaries and lists can be combined to represent a sequence of bytes. In the same way, the Unicode aware modules often allow for combinations of binaries and lists where the binaries have characters encoded in UTF-8 and the lists contain such binaries or numbers representing Unicode codepoints:</p>
<code type="none">
unicode_binary() = binary() with characters encoded in UTF-8 coding standard
-unicode_char() = integer() >= 0 representing valid Unicode codepoint
chardata() = charlist() | unicode_binary()
-charlist() = [unicode_char() | unicode_binary() | charlist()]
- a unicode_binary is allowed as the tail of the list</code>
+charlist() = maybe_improper_list(char() | unicode_binary() | charlist(),
+ unicode_binary() | nil())</code>
<p>The module <c>unicode</c> in STDLIB even supports similar mixes with binaries containing other encodings than UTF-8, but that is a special case to allow for conversions to and from external data:</p>
<code type="none">
external_unicode_binary() = binary() with characters coded in
@@ -82,10 +81,10 @@ external_unicode_binary() = binary() with characters coded in
external_chardata() = external_charlist() | external_unicode_binary()
-external_charlist() = [unicode_char() |
- external_unicode_binary() |
- external_charlist()]
- an external_unicode_binary() is allowed as the tail of the list</code>
+external_charlist() = maybe_improper_list(char() |
+ external_unicode_binary() |
+ external_charlist(),
+ external_unicode_binary() | nil())</code>
</section>
<section>
<title>Basic Language Support for Unicode</title>
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index 535f2d5174..e31ae6b9ef 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -685,7 +685,7 @@ portformat(Name, Id, Cmd) ->
pwd() ->
case file:get_cwd() of
{ok, Str} ->
- ok = io:format("~ts\n", [fixup_one_bin(Str)]);
+ ok = io:format("~ts\n", [Str]);
{error, _} ->
ok = io:format("Cannot determine current directory\n")
end.
@@ -712,27 +712,11 @@ ls() ->
ls(Dir) ->
case file:list_dir(Dir) of
{ok, Entries} ->
- ls_print(sort(fixup_bin(Entries)));
+ ls_print(sort(Entries));
{error,_E} ->
format("Invalid directory\n")
end.
-fixup_one_bin(X) when is_binary(X) ->
- L = binary_to_list(X),
- [ if
- El > 127 ->
- $?;
- true ->
- El
- end || El <- L];
-fixup_one_bin(X) ->
- X.
-fixup_bin([H|T]) ->
- [fixup_one_bin(H) | fixup_bin(T)];
-fixup_bin([]) ->
- [].
-
-
ls_print([]) -> ok;
ls_print(L) ->
Width = min([max(lengths(L, [])), 40]) + 5,
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index afa39c3fb9..1bb3b95ae2 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -661,7 +661,7 @@ leave_file(From, St) ->
%% scan_toks(Tokens, From, EppState)
scan_toks(From, St) ->
- case io:scan_erl_form(St#epp.file, '', St#epp.location, [unicode]) of
+ case io:scan_erl_form(St#epp.file, '', St#epp.location) of
{ok,Toks,Cl} ->
scan_toks(Toks, From, St#epp{location=Cl});
{error,E,Cl} ->
@@ -1035,7 +1035,7 @@ new_location(Ln, {Le,_}, {Lf,_}) ->
%% nested conditionals and repeated 'else's.
skip_toks(From, St, [I|Sis]) ->
- case io:scan_erl_form(St#epp.file, '', St#epp.location, [unicode]) of
+ case io:scan_erl_form(St#epp.file, '', St#epp.location) of
{ok,[{'-',_Lh},{atom,_Li,ifdef}|_Toks],Cl} ->
skip_toks(From, St#epp{location=Cl}, [ifdef,I|Sis]);
{ok,[{'-',_Lh},{atom,_Li,ifndef}|_Toks],Cl} ->
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 1c3f91cbfc..0b57af1b6d 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -346,7 +346,12 @@ expr({call,_,{atom,_,Func},As0}, Bs0, Lf, Ef, RBs) ->
expr({call,_,Func0,As0}, Bs0, Lf, Ef, RBs) -> % function or {Mod,Fun}
{value,Func,Bs1} = expr(Func0, Bs0, Lf, Ef, none),
{As,Bs2} = expr_list(As0, Bs1, Lf, Ef),
- do_apply(Func, As, Bs2, Ef, RBs);
+ case Func of
+ {M,F} when is_atom(M), is_atom(F) ->
+ erlang:raise(error, {badfun,Func}, stacktrace());
+ _ ->
+ do_apply(Func, As, Bs2, Ef, RBs)
+ end;
expr({'catch',_,Expr}, Bs0, Lf, Ef, RBs) ->
Ref = make_ref(),
case catch {Ref,expr(Expr, Bs0, Lf, Ef, none)} of
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index 254384e877..378e629ac9 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -254,6 +254,9 @@ bif(binary_part, 2) -> true;
bif(binary_part, 3) -> true;
bif(binary_to_atom, 2) -> true;
bif(binary_to_existing_atom, 2) -> true;
+bif(binary_to_integer, 1) -> true;
+bif(binary_to_integer, 2) -> true;
+bif(binary_to_float, 1) -> true;
bif(binary_to_list, 1) -> true;
bif(binary_to_list, 3) -> true;
bif(binary_to_term, 1) -> true;
@@ -279,6 +282,8 @@ bif(exit, 2) -> true;
bif(float, 1) -> true;
bif(float_to_list, 1) -> true;
bif(float_to_list, 2) -> true;
+bif(float_to_binary, 1) -> true;
+bif(float_to_binary, 2) -> true;
bif(garbage_collect, 0) -> true;
bif(garbage_collect, 1) -> true;
bif(get, 0) -> true;
@@ -290,6 +295,8 @@ bif(halt, 0) -> true;
bif(halt, 1) -> true;
bif(halt, 2) -> true;
bif(hd, 1) -> true;
+bif(integer_to_binary, 1) -> true;
+bif(integer_to_binary, 2) -> true;
bif(integer_to_list, 1) -> true;
bif(integer_to_list, 2) -> true;
bif(iolist_size, 1) -> true;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index deae9640f5..12505b33d1 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -152,8 +152,6 @@ format_error({attribute,A}) ->
io_lib:format("attribute '~w' after function definitions", [A]);
format_error({missing_qlc_hrl,A}) ->
io_lib:format("qlc:q/~w called, but \"qlc.hrl\" not included", [A]);
-format_error({redefine_import,{bif,{F,A},M}}) ->
- io_lib:format("function ~w/~w already auto-imported from ~w", [F,A,M]);
format_error({redefine_import,{{F,A},M}}) ->
io_lib:format("function ~w/~w already imported from ~w", [F,A,M]);
format_error({bad_inline,{F,A}}) ->
@@ -222,8 +220,6 @@ format_error({removed, MFA, String}) when is_list(String) ->
io_lib:format("~s: ~s", [format_mfa(MFA), String]);
format_error({obsolete_guard, {F, A}}) ->
io_lib:format("~p/~p obsolete", [F, A]);
-format_error({reserved_for_future,K}) ->
- io_lib:format("atom ~w: future reserved keyword - rename or quote", [K]);
format_error({too_many_arguments,Arity}) ->
io_lib:format("too many arguments (~w) - "
"maximum allowed is ~w", [Arity,?MAX_ARGUMENTS]);
@@ -236,11 +232,6 @@ format_error({illegal_guard_local_call, {F,A}}) ->
io_lib:format("call to local/imported function ~w/~w is illegal in guard",
[F,A]);
format_error(illegal_guard_expr) -> "illegal guard expression";
-%% --- exports ---
-format_error({explicit_export,F,A}) ->
- io_lib:format("in this release, the call to ~w/~w must be written "
- "like this: erlang:~w/~w",
- [F,A,F,A]);
%% --- records ---
format_error({undefined_record,T}) ->
io_lib:format("record ~w undefined", [T]);
@@ -278,8 +269,6 @@ format_error({variable_in_record_def,V}) ->
%% --- binaries ---
format_error({undefined_bittype,Type}) ->
io_lib:format("bit type ~w undefined", [Type]);
-format_error({bittype_mismatch,T1,T2,What}) ->
- io_lib:format("bit type mismatch (~s) between ~p and ~p", [What,T1,T2]);
format_error(bittype_unit) ->
"a bit unit size must not be specified unless a size is specified too";
format_error(illegal_bitsize) ->
@@ -1798,11 +1787,9 @@ gexpr({call,Line,{atom,_La,F},As}, Vt, St0) ->
%% BifClash - Function called in guard
case erl_internal:guard_bif(F, A) andalso no_guard_bif_clash(St1,{F,A}) of
true ->
- %% Also check that it is auto-imported.
- case erl_internal:bif(F, A) of
- true -> {Asvt,St1};
- false -> {Asvt,add_error(Line, {explicit_export,F,A}, St1)}
- end;
+ %% Assert that it is auto-imported.
+ true = erl_internal:bif(F, A),
+ {Asvt,St1};
false ->
case is_local_function(St1#lint.locals,{F,A}) orelse
is_imported_function(St1#lint.imports,{F,A}) of
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl
index 26d5747ee7..3651f608bc 100644
--- a/lib/stdlib/src/erl_scan.erl
+++ b/lib/stdlib/src/erl_scan.erl
@@ -84,8 +84,7 @@
-type location() :: line() | {line(),column()}.
-type resword_fun() :: fun((atom()) -> boolean()).
-type option() :: 'return' | 'return_white_spaces' | 'return_comments'
- | 'text' | {'reserved_word_fun', resword_fun()}
- | 'unicode'.
+ | 'text' | {'reserved_word_fun', resword_fun()}.
-type options() :: option() | [option()].
-type symbol() :: atom() | float() | integer() | string().
-type info_line() :: integer() | term().
@@ -106,8 +105,7 @@
{resword_fun = fun reserved_word/1 :: resword_fun(),
ws = false :: boolean(),
comment = false :: boolean(),
- text = false :: boolean(),
- unicode = true :: boolean()}).
+ text = false :: boolean()}).
%%----------------------------------------------------------------------------
@@ -344,20 +342,12 @@ string_thing(_) -> "string".
C > 16#DFFF andalso C < 16#FFFE orelse
C > 16#FFFF andalso C =< 16#10FFFF)).
-%% When the option 'unicode' is false: return Unicode strings as lists
-%% of integers and Unicode characters as integers. For instance,
-%% erl_scan:string("\"b\x{aaa}c\".") is equivalent to
-%% erl_scan:string("[98,2730,99]."). This is to protect the caller
-%% from character codes greater than 255. Search for UNI to find code
-%% implementing this "feature". The 'unicode' option is undocumented
-%% and will be removed later.
--define(NO_UNICODE, 0).
--define(UNI255(C), (C =< 16#ff)).
+-define(UNI255(C), C >= 0, C =< 16#ff).
options(Opts0) when is_list(Opts0) ->
Opts = lists:foldr(fun expand_opt/2, [], Opts0),
- [RW_fun, Unicode] =
- case opts(Opts, [reserved_word_fun, unicode], []) of
+ [RW_fun] =
+ case opts(Opts, [reserved_word_fun], []) of
badarg ->
erlang:error(badarg, [Opts0]);
R ->
@@ -369,8 +359,7 @@ options(Opts0) when is_list(Opts0) ->
#erl_scan{resword_fun = RW_fun,
comment = Comment,
ws = WS,
- text = Txt,
- unicode = Unicode};
+ text = Txt};
options(Opt) ->
options([Opt]).
@@ -378,8 +367,6 @@ opts(Options, [Key|Keys], L) ->
V = case lists:keyfind(Key, 1, Options) of
{reserved_word_fun,F} when ?RESWORDFUN(F) ->
{ok,F};
- {unicode, Bool} when is_boolean(Bool) ->
- {ok,Bool};
{Key,_} ->
badarg;
false ->
@@ -395,9 +382,7 @@ opts(_Options, [], L) ->
lists:reverse(L).
default_option(reserved_word_fun) ->
- fun reserved_word/1;
-default_option(unicode) ->
- true.
+ fun reserved_word/1.
expand_opt(return, Os) ->
[return_comments,return_white_spaces|Os];
@@ -531,10 +516,10 @@ scan1("."=Cs, _St, Line, Col, Toks) ->
scan1([$.=C|Cs], St, Line, Col, Toks) ->
scan_dot(Cs, St, Line, Col, Toks, [C]);
scan1([$"|Cs], St, Line, Col, Toks) -> %" Emacs
- State0 = {[],[],Line,Col,?NO_UNICODE},
+ State0 = {[],[],Line,Col},
scan_string(Cs, St, Line, incr_column(Col, 1), Toks, State0);
scan1([$'|Cs], St, Line, Col, Toks) -> %' Emacs
- State0 = {[],[],Line,Col,?NO_UNICODE},
+ State0 = {[],[],Line,Col},
scan_qatom(Cs, St, Line, incr_column(Col, 1), Toks, State0);
scan1([$$|Cs], St, Line, Col, Toks) ->
scan_char(Cs, St, Line, Col, Toks);
@@ -655,7 +640,7 @@ scan1([$~|Cs], St, Line, Col, Toks) ->
scan1([$&|Cs], St, Line, Col, Toks) ->
tok2(Cs, St, Line, Col, Toks, "&", '&', 1);
%% End of optimization.
-scan1([C|Cs], St, Line, Col, Toks) when ?CHAR(C), ?UNI255(C) ->
+scan1([C|Cs], St, Line, Col, Toks) when ?UNI255(C) ->
Str = [C],
tok2(Cs, St, Line, Col, Toks, Str, list_to_atom(Str), 1);
scan1([C|Cs], _St, Line, Col, _Toks) when ?CHAR(C) ->
@@ -718,14 +703,16 @@ scan_name([], Ncs) ->
scan_name(Cs, Ncs) ->
{lists:reverse(Ncs),Cs}.
+-define(STR(St, S), if St#erl_scan.text -> S; true -> [] end).
+
scan_dot([$%|_]=Cs, St, Line, Col, Toks, Ncs) ->
Attrs = attributes(Line, Col, St, Ncs),
{ok,[{dot,Attrs}|Toks],Cs,Line,incr_column(Col, 1)};
scan_dot([$\n=C|Cs], St, Line, Col, Toks, Ncs) ->
- Attrs = attributes(Line, Col, St, Ncs++[C]),
+ Attrs = attributes(Line, Col, St, ?STR(St, Ncs++[C])),
{ok,[{dot,Attrs}|Toks],Cs,Line+1,new_column(Col, 1)};
scan_dot([C|Cs], St, Line, Col, Toks, Ncs) when ?WHITE_SPACE(C) ->
- Attrs = attributes(Line, Col, St, Ncs++[C]),
+ Attrs = attributes(Line, Col, St, ?STR(St, Ncs++[C])),
{ok,[{dot,Attrs}|Toks],Cs,Line,incr_column(Col, 2)};
scan_dot(eof=Cs, St, Line, Col, Toks, Ncs) ->
Attrs = attributes(Line, Col, St, Ncs),
@@ -858,26 +845,20 @@ scan_char([$\\|Cs]=Cs0, St, Line, Col, Toks) ->
{eof,Ncol} ->
scan_error(char, Line, Col, Line, Ncol, eof);
{nl,Val,Str,Ncs,Ncol} ->
- Attrs = attributes(Line, Col, St, "$\\"++Str), %"
+ Attrs = attributes(Line, Col, St, ?STR(St, "$\\"++Str)), %"
Ntoks = [{char,Attrs,Val}|Toks],
scan1(Ncs, St, Line+1, Ncol, Ntoks);
- {unicode,Val,Str,Ncs,Ncol} ->
- Attrs = attributes(Line, Col, St, "$\\"++Str), %"
- Tag = char_tag(Val, St), % UNI
- Ntoks = [{Tag,Attrs,Val}|Toks],
- scan1(Ncs, St, Line, Ncol, Ntoks);
{Val,Str,Ncs,Ncol} ->
- Attrs = attributes(Line, Col, St, "$\\"++Str), %"
+ Attrs = attributes(Line, Col, St, ?STR(St, "$\\"++Str)), %"
Ntoks = [{char,Attrs,Val}|Toks],
scan1(Ncs, St, Line, Ncol, Ntoks)
end;
scan_char([$\n=C|Cs], St, Line, Col, Toks) ->
- Attrs = attributes(Line, Col, St, [$$,C]),
+ Attrs = attributes(Line, Col, St, ?STR(St, [$$,C])),
scan1(Cs, St, Line+1, new_column(Col, 1), [{char,Attrs,C}|Toks]);
scan_char([C|Cs], St, Line, Col, Toks) when ?UNICODE(C) ->
- Tag = char_tag(C, St), % UNI
- Attrs = attributes(Line, Col, St, [$$,C]),
- scan1(Cs, St, Line, incr_column(Col, 2), [{Tag,Attrs,C}|Toks]);
+ Attrs = attributes(Line, Col, St, ?STR(St, [$$,C])),
+ scan1(Cs, St, Line, incr_column(Col, 2), [{char,Attrs,C}|Toks]);
scan_char([C|_Cs], _St, Line, Col, _Toks) when ?CHAR(C) ->
scan_error({illegal,character}, Line, Col, Line, incr_column(Col, 1), eof);
scan_char([], _St, Line, Col, Toks) ->
@@ -885,90 +866,32 @@ scan_char([], _St, Line, Col, Toks) ->
scan_char(eof, _St, Line, Col, _Toks) ->
scan_error(char, Line, Col, Line, incr_column(Col, 1), eof).
--compile({inline,[char_tag/2]}).
-
-char_tag(C, _St) when ?UNI255(C) ->
- char;
-char_tag(_C, #erl_scan{unicode = true}) ->
- char;
-char_tag(_C, _St) ->
- integer.
-
-scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0,Uni0}) ->
- case scan_string0(Cs, St, Line, Col, $\", true, Str, Wcs, Uni0) of %"
- {more,Ncs,Nline,Ncol,Nstr,Nwcs,Uni} ->
- State = {Nwcs,Nstr,Line0,Col0,Uni},
+scan_string(Cs, 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},
{more,{Ncs,Ncol,Toks,Nline,State,fun scan_string/6}};
{char_error,Ncs,Error,Nline,Ncol,EndCol} ->
scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs);
{error,Nline,Ncol,Nwcs,Ncs} ->
Estr = string:substr(Nwcs, 1, 16), % Expanded escape chars.
scan_error({string,$\",Estr}, Line0, Col0, Nline, Ncol, Ncs); %"
- {Ncs,Nline,Ncol,Nstr,Nwcs,Uni} when Uni =:= ?NO_UNICODE;
- St#erl_scan.unicode ->
+ {Ncs,Nline,Ncol,Nstr,Nwcs} ->
Attrs = attributes(Line0, Col0, St, Nstr),
- scan1(Ncs, St, Nline, Ncol, [{string,Attrs,Nwcs}|Toks]);
- {Ncs,Nline,Ncol,Nstr,_Nwcs,_Uni} ->
- Ntoks = unicode_string_to_list(Line0, Col0, St, Nstr, Toks),
- scan1(Ncs, St, Nline, Ncol, Ntoks)
+ scan1(Ncs, St, Nline, Ncol, [{string,Attrs,Nwcs}|Toks])
end.
-%% UNI
-unicode_string_to_list(Line, Col, St, [$"=C|Nstr], Toks) -> %" Emacs
- Paren = {'[',attributes(Line, Col, St, [C])},
- u2l(Nstr, Line, incr_column(Col, 1), St, [Paren|Toks]).
-
-u2l([$"]=Cs, Line, Col, St, Toks) -> %" Emacs
- [{']',attributes(Line, Col, St, Cs)}|Toks];
-u2l([$\n=C|Cs], Line, Col, St, Toks) ->
- Ntoks = unicode_nl_tokens(Line, Col, [C], C, St, Toks, Cs),
- u2l(Cs, Line+1, new_column(Col, 1), St, Ntoks);
-u2l([$\\|Cs], Line, Col, St, Toks) ->
- case scan_escape(Cs, Col) of
- {nl,Val,ValStr,Ncs,Ncol} ->
- Nstr = [$\\|ValStr],
- Ntoks = unicode_nl_tokens(Line, Col, Nstr, Val, St, Toks, Ncs),
- u2l(Ncs, Line+1, Ncol, St, Ntoks);
- {unicode,Val,ValStr,Ncs,Ncol} ->
- Nstr = [$\\|ValStr],
- Ntoks = unicode_tokens(Line, Col, Nstr, Val, St, Toks, Ncs),
- u2l(Ncs, Line, incr_column(Ncol, 1), St, Ntoks);
- {Val,ValStr,Ncs,Ncol} ->
- Nstr = [$\\|ValStr],
- Ntoks = unicode_tokens(Line, Col, Nstr, Val, St, Toks, Ncs),
- u2l(Ncs, Line, incr_column(Ncol, 1), St, Ntoks)
- end;
-u2l([C|Cs], Line, Col, St, Toks) ->
- Ntoks = unicode_tokens(Line, Col, [C], C, St, Toks, Cs),
- u2l(Cs, Line, incr_column(Col, 1), St, Ntoks).
-
-unicode_nl_tokens(Line, Col, Str, Val, St, Toks, Cs) ->
- Ccol = new_column(Col, 1),
- unicode_tokens(Line, Col, Str, Val, St, Toks, Cs, Line+1, Ccol).
-
-unicode_tokens(Line, Col, Str, Val, St, Toks, Cs) ->
- Ccol = incr_column(Col, length(Str)),
- unicode_tokens(Line, Col, Str, Val, St, Toks, Cs, Line, Ccol).
-
-unicode_tokens(Line, Col, Str, Val, St, Toks, Cs, Cline, Ccol) ->
- Attrs = attributes(Line, Col, St, Str),
- Tag = if ?UNI255(Val) -> char; true -> integer end,
- Token = {Tag,Attrs,Val},
- [{',',attributes(Cline, Ccol, St, "")} || Cs =/= "\""] ++ [Token|Toks].
-
-scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0,Uni0}) ->
- AllowUni = St#erl_scan.unicode,
- case scan_string0(Cs, St, Line, Col, $\', AllowUni, Str, Wcs, Uni0) of %'
- {more,Ncs,Nline,Ncol,Nstr,Nwcs,Uni} ->
- State = {Nwcs,Nstr,Line0,Col0,Uni},
+scan_qatom(Cs, 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},
{more,{Ncs,Ncol,Toks,Nline,State,fun scan_qatom/6}};
{char_error,Ncs,Error,Nline,Ncol,EndCol} ->
scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs);
{error,Nline,Ncol,Nwcs,Ncs} ->
Estr = string:substr(Nwcs, 1, 16), % Expanded escape chars.
scan_error({string,$\',Estr}, Line0, Col0, Nline, Ncol, Ncs); %'
- {Ncs,Nline,Ncol,Nstr,Nwcs,Uni} ->
- true = Uni =:= ?NO_UNICODE orelse AllowUni,
+ {Ncs,Nline,Ncol,Nstr,Nwcs} ->
case catch list_to_atom(Nwcs) of
A when is_atom(A) ->
Attrs = attributes(Line0, Col0, St, Nstr),
@@ -978,95 +901,75 @@ scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0,Uni0}) ->
end
end.
-scan_string0(Cs, #erl_scan{text=false}, Line, no_col=Col, Q, U, [], Wcs, Uni) ->
- scan_string_no_col(Cs, Line, Col, Q, U, Wcs, Uni);
-scan_string0(Cs, #erl_scan{text=true}, Line, no_col=Col, Q, U, Str, Wcs, Uni) ->
- scan_string1(Cs, Line, Col, Q, U, Str, Wcs, Uni);
-scan_string0(Cs, _St, Line, Col, Q, U, [], Wcs, Uni) ->
- scan_string_col(Cs, Line, Col, Q, U, Wcs, Uni);
-scan_string0(Cs, _St, Line, Col, Q, U, Str, Wcs, Uni) ->
- scan_string1(Cs, Line, Col, Q, U, Str, Wcs, Uni).
+scan_string0(Cs, #erl_scan{text=false}, Line, no_col=Col, Q, [], Wcs) ->
+ scan_string_no_col(Cs, Line, Col, Q, Wcs);
+scan_string0(Cs, #erl_scan{text=true}, Line, no_col=Col, Q, Str, Wcs) ->
+ scan_string1(Cs, Line, Col, Q, Str, Wcs);
+scan_string0(Cs, St, Line, Col, Q, [], Wcs) ->
+ scan_string_col(Cs, St, Line, Col, Q, Wcs);
+scan_string0(Cs, _St, Line, Col, Q, Str, Wcs) ->
+ scan_string1(Cs, Line, Col, Q, Str, Wcs).
%% Optimization. Col =:= no_col.
-scan_string_no_col([Q|Cs], Line, Col, Q, _U, Wcs, Uni) ->
- {Cs,Line,Col,_DontCare=[],lists:reverse(Wcs),Uni};
-scan_string_no_col([$\n=C|Cs], Line, Col, Q, U, Wcs, Uni) ->
- scan_string_no_col(Cs, Line+1, Col, Q, U, [C|Wcs], Uni);
-scan_string_no_col([C|Cs], Line, Col, Q, U, Wcs, Uni) when C =/= $\\,
- ?CHAR(C),
- ?UNI255(C) ->
- scan_string_no_col(Cs, Line, Col, Q, U, [C|Wcs], Uni);
-scan_string_no_col(Cs, Line, Col, Q, U, Wcs, Uni) ->
- scan_string1(Cs, Line, Col, Q, U, Wcs, Wcs, Uni).
+scan_string_no_col([Q|Cs], Line, Col, Q, Wcs) ->
+ {Cs,Line,Col,_DontCare=[],lists:reverse(Wcs)};
+scan_string_no_col([$\n=C|Cs], Line, Col, Q, Wcs) ->
+ scan_string_no_col(Cs, Line+1, Col, Q, [C|Wcs]);
+scan_string_no_col([C|Cs], Line, Col, Q, Wcs) when C =/= $\\, ?UNICODE(C) ->
+ scan_string_no_col(Cs, Line, Col, Q, [C|Wcs]);
+scan_string_no_col(Cs, Line, Col, Q, Wcs) ->
+ scan_string1(Cs, Line, Col, Q, Wcs, Wcs).
%% Optimization. Col =/= no_col.
-scan_string_col([Q|Cs], Line, Col, Q, _U, Wcs0, Uni) ->
+scan_string_col([Q|Cs], St, Line, Col, Q, Wcs0) ->
Wcs = lists:reverse(Wcs0),
- Str = [Q|Wcs++[Q]],
- {Cs,Line,Col+1,Str,Wcs,Uni};
-scan_string_col([$\n=C|Cs], Line, _xCol, Q, U, Wcs, Uni) ->
- scan_string_col(Cs, Line+1, 1, Q, U, [C|Wcs], Uni);
-scan_string_col([C|Cs], Line, Col, Q, U, Wcs, Uni) when C =/= $\\,
- ?CHAR(C),
- ?UNI255(C) ->
- scan_string_col(Cs, Line, Col+1, Q, U, [C|Wcs], Uni);
-scan_string_col(Cs, Line, Col, Q, U, Wcs, Uni) ->
- scan_string1(Cs, Line, Col, Q, U, Wcs, Wcs, Uni).
-
-%% UNI_STR is to be replaced by STR when the Unicode-string-to-list
-%% workaround is eventually removed.
--define(UNI_STR(Col, S), S).
+ Str = ?STR(St, [Q|Wcs++[Q]]),
+ {Cs,Line,Col+1,Str,Wcs};
+scan_string_col([$\n=C|Cs], St, Line, _xCol, Q, Wcs) ->
+ scan_string_col(Cs, St, Line+1, 1, Q, [C|Wcs]);
+scan_string_col([C|Cs], St, Line, Col, Q, Wcs) when C =/= $\\, ?UNICODE(C) ->
+ scan_string_col(Cs, St, Line, Col+1, Q, [C|Wcs]);
+scan_string_col(Cs, _St, Line, Col, Q, Wcs) ->
+ scan_string1(Cs, Line, Col, Q, Wcs, Wcs).
%% Note: in those cases when a 'char_error' tuple is returned below it
%% is tempting to skip over characters up to the first Q character,
%% but then the end location of the error tuple would not correspond
%% to the start location of the returned Rest string. (Maybe the end
%% location could be modified, but that too is ugly.)
-scan_string1([Q|Cs], Line, Col, Q, _U, Str0, Wcs0, Uni) ->
+scan_string1([Q|Cs], Line, Col, Q, Str0, Wcs0) ->
Wcs = lists:reverse(Wcs0),
- Str = ?UNI_STR(Col, [Q|lists:reverse(Str0, [Q])]),
- {Cs,Line,incr_column(Col, 1),Str,Wcs,Uni};
-scan_string1([$\n=C|Cs], Line, Col, Q, U, Str, Wcs, Uni) ->
+ Str = [Q|lists:reverse(Str0, [Q])],
+ {Cs,Line,incr_column(Col, 1),Str,Wcs};
+scan_string1([$\n=C|Cs], Line, Col, Q, Str, Wcs) ->
Ncol = new_column(Col, 1),
- scan_string1(Cs, Line+1, Ncol, Q, U, ?UNI_STR(Col, [C|Str]), [C|Wcs], Uni);
-scan_string1([$\\|Cs]=Cs0, Line, Col, Q, U, Str, Wcs, Uni) ->
+ scan_string1(Cs, Line+1, Ncol, Q, [C|Str], [C|Wcs]);
+scan_string1([$\\|Cs]=Cs0, Line, Col, Q, Str, Wcs) ->
case scan_escape(Cs, Col) of
more ->
- {more,Cs0,Line,Col,Str,Wcs,Uni};
+ {more,Cs0,Line,Col,Str,Wcs};
{error,Ncs,Error,Ncol} ->
{char_error,Ncs,Error,Line,Col,incr_column(Ncol, 1)};
{eof,Ncol} ->
{error,Line,incr_column(Ncol, 1),lists:reverse(Wcs),eof};
{nl,Val,ValStr,Ncs,Ncol} ->
- Nstr = ?UNI_STR(Ncol, lists:reverse(ValStr, [$\\|Str])),
+ Nstr = lists:reverse(ValStr, [$\\|Str]),
Nwcs = [Val|Wcs],
- scan_string1(Ncs, Line+1, Ncol, Q, U, Nstr, Nwcs, Uni);
- {unicode,_Val,_ValStr,Ncs,Ncol} when not U -> %' Emacs
- {char_error,Ncs,{illegal,character},Line,Col,incr_column(Ncol, 1)};
- {unicode,Val,ValStr,Ncs,Ncol} -> % UNI. Uni is set to Val.
- Nstr = ?UNI_STR(Ncol, lists:reverse(ValStr, [$\\|Str])),
- Nwcs = [Val|Wcs], % not used
- scan_string1(Ncs, Line, incr_column(Ncol, 1), Q, U, Nstr, Nwcs, Val);
+ scan_string1(Ncs, Line+1, Ncol, Q, Nstr, Nwcs);
{Val,ValStr,Ncs,Ncol} ->
- Nstr = ?UNI_STR(Ncol, lists:reverse(ValStr, [$\\|Str])),
+ Nstr = lists:reverse(ValStr, [$\\|Str]),
Nwcs = [Val|Wcs],
- scan_string1(Ncs, Line, incr_column(Ncol, 1), Q, U, Nstr, Nwcs, Uni)
+ scan_string1(Ncs, Line, incr_column(Ncol, 1), Q, Nstr, Nwcs)
end;
-scan_string1([C|Cs], Line, no_col=Col, Q, U, Str, Wcs, Uni) when ?CHAR(C),
- ?UNI255(C) ->
- %% scan_string1(Cs, Line, Col, Q, U, Str, [C|Wcs], Uni);
- scan_string1(Cs, Line, Col, Q, U, [C|Str], [C|Wcs], Uni); % UNI
-scan_string1([C|Cs], Line, Col, Q, U, Str, Wcs, Uni) when ?CHAR(C), ?UNI255(C) ->
- scan_string1(Cs, Line, Col+1, Q, U, [C|Str], [C|Wcs], Uni);
-scan_string1([C|Cs], Line, Col, _Q, false, _Str, _Wcs, _Uni) when ?CHAR(C) -> %' UNI
- {char_error,Cs,{illegal,character},Line,Col,incr_column(Col, 1)};
-scan_string1([C|Cs], Line, Col, Q, U, Str, Wcs, _Uni) when ?UNICODE(C) ->
- scan_string1(Cs, Line, incr_column(Col, 1), Q, U, [C|Str], [C|Wcs], C);
-scan_string1([C|Cs], Line, Col, _Q, _U, _Str, _Wcs, _Uni) when ?CHAR(C) -> % UNI
+scan_string1([C|Cs], Line, no_col=Col, Q, Str, Wcs) when ?UNICODE(C) ->
+ scan_string1(Cs, Line, Col, Q, [C|Str], [C|Wcs]);
+scan_string1([C|Cs], Line, Col, Q, Str, Wcs) when ?UNICODE(C) ->
+ scan_string1(Cs, Line, Col+1, Q, [C|Str], [C|Wcs]);
+scan_string1([C|Cs], Line, Col, _Q, _Str, _Wcs) when ?CHAR(C) ->
{char_error,Cs,{illegal,character},Line,Col,incr_column(Col, 1)};
-scan_string1([]=Cs, Line, Col, _Q, _U, Str, Wcs, Uni) ->
- {more,Cs,Line,Col,Str,Wcs,Uni};
-scan_string1(eof, Line, Col, _Q, _U, _Str, Wcs, _Uni) ->
+scan_string1([]=Cs, Line, Col, _Q, Str, Wcs) ->
+ {more,Cs,Line,Col,Str,Wcs};
+scan_string1(eof, Line, Col, _Q, _Str, Wcs) ->
{error,Line,Col,lists:reverse(Wcs),eof}.
-define(OCT(C), C >= $0, C =< $7).
@@ -1077,16 +980,16 @@ scan_string1(eof, Line, Col, _Q, _U, _Str, Wcs, _Uni) ->
%% \<1-3> octal digits
scan_escape([O1,O2,O3|Cs], Col) when ?OCT(O1), ?OCT(O2), ?OCT(O3) ->
Val = (O1*8 + O2)*8 + O3 - 73*$0,
- {Val,?UNI_STR(Col, [O1,O2,O3]),Cs,incr_column(Col, 3)};
+ {Val,[O1,O2,O3],Cs,incr_column(Col, 3)};
scan_escape([O1,O2], _Col) when ?OCT(O1), ?OCT(O2) ->
more;
scan_escape([O1,O2|Cs], Col) when ?OCT(O1), ?OCT(O2) ->
Val = (O1*8 + O2) - 9*$0,
- {Val,?UNI_STR(Col, [O1,O2]),Cs,incr_column(Col, 2)};
+ {Val,[O1,O2],Cs,incr_column(Col, 2)};
scan_escape([O1], _Col) when ?OCT(O1) ->
more;
scan_escape([O1|Cs], Col) when ?OCT(O1) ->
- {O1 - $0,?UNI_STR(Col, [O1]),Cs,incr_column(Col, 1)};
+ {O1 - $0,[O1],Cs,incr_column(Col, 1)};
%% \x{<hex digits>}
scan_escape([$x,${|Cs], Col) ->
scan_hex(Cs, incr_column(Col, 2), []);
@@ -1097,29 +1000,27 @@ scan_escape([$x|eof], Col) ->
%% \x<2> hexadecimal digits
scan_escape([$x,H1,H2|Cs], Col) when ?HEX(H1), ?HEX(H2) ->
Val = erlang:list_to_integer([H1,H2], 16),
- {Val,?UNI_STR(Col, [$x,H1,H2]),Cs,incr_column(Col, 3)};
+ {Val,[$x,H1,H2],Cs,incr_column(Col, 3)};
scan_escape([$x,H1], _Col) when ?HEX(H1) ->
more;
scan_escape([$x|Cs], Col) ->
{error,Cs,{illegal,character},incr_column(Col, 1)};
%% \^X -> CTL-X
scan_escape([$^=C0,$\n=C|Cs], Col) ->
- {nl,C,?UNI_STR(Col, [C0,C]),Cs,new_column(Col, 1)};
+ {nl,C,[C0,C],Cs,new_column(Col, 1)};
scan_escape([$^=C0,C|Cs], Col) when ?CHAR(C) ->
Val = C band 31,
- {Val,?UNI_STR(Col, [C0,C]),Cs,incr_column(Col, 2)};
+ {Val,[C0,C],Cs,incr_column(Col, 2)};
scan_escape([$^], _Col) ->
more;
scan_escape([$^|eof], Col) ->
{eof,incr_column(Col, 1)};
scan_escape([$\n=C|Cs], Col) ->
- {nl,C,?UNI_STR(Col, [C]),Cs,new_column(Col, 1)};
-scan_escape([C0|Cs], Col) when ?CHAR(C0), ?UNI255(C0) ->
+ {nl,C,[C],Cs,new_column(Col, 1)};
+scan_escape([C0|Cs], Col) when ?UNICODE(C0) ->
C = escape_char(C0),
- {C,?UNI_STR(Col, [C0]),Cs,incr_column(Col, 1)};
-scan_escape([C|Cs], Col) when ?UNICODE(C) ->
- {unicode,C,?UNI_STR(Col, [C]),Cs,incr_column(Col, 1)};
-scan_escape([C|Cs], Col) when ?CHAR(C) -> % UNI
+ {C,[C0],Cs,incr_column(Col, 1)};
+scan_escape([C|Cs], Col) when ?CHAR(C) ->
{error,Cs,{illegal,character},incr_column(Col, 1)};
scan_escape([], _Col) ->
more;
@@ -1136,10 +1037,8 @@ scan_hex(Cs, Col, Wcs) ->
scan_esc_end([$}|Cs], Col, Wcs0, B, Str0) ->
Wcs = lists:reverse(Wcs0),
case catch erlang:list_to_integer(Wcs, B) of
- Val when Val =< 16#FF ->
- {Val,?UNI_STR(Col, Str0++Wcs++[$}]),Cs,incr_column(Col, 1)};
Val when ?UNICODE(Val) ->
- {unicode,Val,?UNI_STR(Col, Str0++Wcs++[$}]),Cs,incr_column(Col,1)};
+ {Val,Str0++Wcs++[$}],Cs,incr_column(Col, 1)};
_ ->
{error,Cs,{illegal,character},incr_column(Col, 1)}
end;
@@ -1171,7 +1070,7 @@ scan_number([$#|Cs]=Cs0, St, Line, Col, Toks, Ncs0) ->
Ncs = lists:reverse(Ncs0),
case catch list_to_integer(Ncs) of
B when B >= 2, B =< 1+$Z-$A+10 ->
- Bcs = Ncs++[$#],
+ Bcs = ?STR(St, Ncs++[$#]),
scan_based_int(Cs, St, Line, Col, Toks, {B,[],Bcs});
B ->
Len = length(Ncs),
@@ -1204,7 +1103,7 @@ scan_based_int(Cs, St, Line, Col, Toks, {B,Ncs0,Bcs}) ->
Ncs = lists:reverse(Ncs0),
case catch erlang:list_to_integer(Ncs, B) of
N when is_integer(N) ->
- tok3(Cs, St, Line, Col, Toks, integer, Bcs++Ncs, N);
+ tok3(Cs, St, Line, Col, Toks, integer, ?STR(St, Bcs++Ncs), N);
_ ->
Len = length(Bcs)+length(Ncs),
Ncol = incr_column(Col, Len),
@@ -1244,36 +1143,30 @@ float_end(Cs, St, Line, Col, Toks, Ncs0) ->
scan_error({illegal,float}, Line, Col, Line, Ncol, Cs)
end.
-skip_comment(Cs, St, Line, Col, Toks, N) ->
- skip_comment(Cs, St, Line, Col, Toks, N, St#erl_scan.unicode).
-
-skip_comment([C|Cs], St, Line, Col, Toks, N, U) when C =/= $\n, ?CHAR(C) ->
- case ?UNI255(C) orelse U andalso ?UNICODE(C) of
+skip_comment([C|Cs], St, Line, Col, Toks, N) when C =/= $\n, ?CHAR(C) ->
+ case ?UNICODE(C) of
true ->
- skip_comment(Cs, St, Line, Col, Toks, N+1, U);
+ skip_comment(Cs, St, Line, Col, Toks, N+1);
false ->
Ncol = incr_column(Col, N+1),
scan_error({illegal,character}, Line, Col, Line, Ncol, Cs)
end;
-skip_comment([]=Cs, _St, Line, Col, Toks, N, _U) ->
+skip_comment([]=Cs, _St, Line, Col, Toks, N) ->
{more,{Cs,Col,Toks,Line,N,fun skip_comment/6}};
-skip_comment(Cs, St, Line, Col, Toks, N, _U) ->
+skip_comment(Cs, St, Line, Col, Toks, N) ->
scan1(Cs, St, Line, incr_column(Col, N), Toks).
-scan_comment(Cs, St, Line, Col, Toks, Ncs) ->
- scan_comment(Cs, St, Line, Col, Toks, Ncs, St#erl_scan.unicode).
-
-scan_comment([C|Cs], St, Line, Col, Toks, Ncs, U) when C =/= $\n, ?CHAR(C) ->
- case ?UNI255(C) orelse U andalso ?UNICODE(C) of
+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], U);
+ scan_comment(Cs, St, Line, Col, Toks, [C|Ncs]);
false ->
Ncol = incr_column(Col, length(Ncs)+1),
scan_error({illegal,character}, Line, Col, Line, Ncol, Cs)
end;
-scan_comment([]=Cs, _St, Line, Col, Toks, Ncs, _U) ->
+scan_comment([]=Cs, _St, Line, Col, Toks, Ncs) ->
{more,{Cs,Col,Toks,Line,Ncs,fun scan_comment/6}};
-scan_comment(Cs, St, Line, Col, Toks, Ncs0, _U) ->
+scan_comment(Cs, St, Line, Col, Toks, Ncs0) ->
Ncs = lists:reverse(Ncs0),
tok3(Cs, St, Line, Col, Toks, comment, Ncs, Ncs).
diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl
index f40904df1c..e49cbc1fd1 100644
--- a/lib/stdlib/src/eval_bits.erl
+++ b/lib/stdlib/src/eval_bits.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -67,7 +67,8 @@ expr_grp([], Bs0, _Lf, Acc) ->
{value,Acc,Bs0}.
eval_field({bin_element, _, {string, _, S}, default, default}, Bs0, _Fun) ->
- {list_to_binary(S),Bs0};
+ Latin1 = [C band 16#FF || C <- S],
+ {list_to_binary(Latin1),Bs0};
eval_field({bin_element, Line, {string, _, S}, Size0, Options0}, Bs, _Fun) ->
{_Size,[Type,_Unit,_Sign,Endian]} =
make_bit_type(Line, Size0, Options0),
@@ -162,8 +163,10 @@ bin_gen([], Bin, _Bs0, _BBs0, _Mfun, _Efun, false) ->
bin_gen_field({bin_element,_,{string,_,S},default,default},
Bin, Bs, BBs, _Mfun, _Efun) ->
- Bits = list_to_binary(S),
- Size = byte_size(Bits),
+ Bits = try list_to_binary(S)
+ catch _:_ -> <<>>
+ end,
+ Size = length(S),
case Bin of
<<Bits:Size/binary,Rest/bitstring>> ->
{match,Bs,BBs,Rest};
@@ -172,16 +175,42 @@ bin_gen_field({bin_element,_,{string,_,S},default,default},
_ ->
done
end;
+bin_gen_field({bin_element,Line,{string,SLine,S},Size0,Options0},
+ Bin0, Bs0, BBs0, Mfun, Efun) ->
+ {Size1, [Type,{unit,Unit},Sign,Endian]} =
+ make_bit_type(Line, Size0, Options0),
+ match_check_size(Mfun, Size1, BBs0),
+ {value, Size, _BBs} = Efun(Size1, BBs0),
+ F = fun(C, Bin, Bs, BBs) ->
+ bin_gen_field1(Bin, Type, Size, Unit, Sign, Endian,
+ {integer,SLine,C}, Bs, BBs, Mfun)
+ end,
+ bin_gen_field_string(S, Bin0, Bs0, BBs0, F);
bin_gen_field({bin_element,Line,VE,Size0,Options0},
Bin, Bs0, BBs0, Mfun, Efun) ->
{Size1, [Type,{unit,Unit},Sign,Endian]} =
make_bit_type(Line, Size0, Options0),
V = erl_eval:partial_eval(VE),
+ NewV = coerce_to_float(V, Type),
match_check_size(Mfun, Size1, BBs0),
{value, Size, _BBs} = Efun(Size1, BBs0),
+ bin_gen_field1(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun).
+
+bin_gen_field_string([], Rest, Bs, BBs, _F) ->
+ {match,Bs,BBs,Rest};
+bin_gen_field_string([C|Cs], Bin0, Bs0, BBs0, Fun) ->
+ case Fun(C, Bin0, Bs0, BBs0) of
+ {match,Bs,BBs,Rest} ->
+ bin_gen_field_string(Cs, Rest, Bs, BBs, Fun);
+ {nomatch,Rest} ->
+ {nomatch,Rest};
+ done ->
+ done
+ end.
+
+bin_gen_field1(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun) ->
case catch get_value(Bin, Type, Size, Unit, Sign, Endian) of
{Val,<<_/bitstring>>=Rest} ->
- NewV = coerce_to_float(V, Type),
case catch Mfun(match, {NewV,Val,Bs0}) of
{match,Bs} ->
BBs = add_bin_binding(Mfun, NewV, Bs, BBs0),
@@ -223,20 +252,41 @@ match_bits_1([F|Fs], Bits0, Bs0, BBs0, Mfun, Efun) ->
match_field_1({bin_element,_,{string,_,S},default,default},
Bin, Bs, BBs, _Mfun, _Efun) ->
- Bits = list_to_binary(S),
+ Bits = list_to_binary(S), % fails if there are characters > 255
Size = byte_size(Bits),
<<Bits:Size/binary,Rest/binary-unit:1>> = Bin,
{Bs,BBs,Rest};
+match_field_1({bin_element,Line,{string,SLine,S},Size0,Options0},
+ Bin0, Bs0, BBs0, Mfun, Efun) ->
+ {Size1, [Type,{unit,Unit},Sign,Endian]} =
+ make_bit_type(Line, Size0, Options0),
+ Size2 = erl_eval:partial_eval(Size1),
+ match_check_size(Mfun, Size2, BBs0),
+ {value, Size, _BBs} = Efun(Size2, BBs0),
+ F = fun(C, Bin, Bs, BBs) ->
+ match_field(Bin, Type, Size, Unit, Sign, Endian,
+ {integer,SLine,C}, Bs, BBs, Mfun)
+ end,
+ match_field_string(S, Bin0, Bs0, BBs0, F);
match_field_1({bin_element,Line,VE,Size0,Options0},
Bin, Bs0, BBs0, Mfun, Efun) ->
{Size1, [Type,{unit,Unit},Sign,Endian]} =
make_bit_type(Line, Size0, Options0),
V = erl_eval:partial_eval(VE),
+ NewV = coerce_to_float(V, Type),
Size2 = erl_eval:partial_eval(Size1),
match_check_size(Mfun, Size2, BBs0),
{value, Size, _BBs} = Efun(Size2, BBs0),
+ match_field(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun).
+
+match_field_string([], Rest, Bs, BBs, _Fun) ->
+ {Bs,BBs,Rest};
+match_field_string([C|Cs], Bin0, Bs0, BBs0, Fun) ->
+ {Bs,BBs,Bin} = Fun(C, Bin0, Bs0, BBs0),
+ match_field_string(Cs, Bin, Bs, BBs, Fun).
+
+match_field(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun) ->
{Val,Rest} = get_value(Bin, Type, Size, Unit, Sign, Endian),
- NewV = coerce_to_float(V, Type),
{match,Bs} = Mfun(match, {NewV,Val,Bs0}),
BBs = add_bin_binding(Mfun, NewV, Bs, BBs0),
{Bs,BBs,Rest}.
diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl
index 318f3b87b8..7df72a93e5 100644
--- a/lib/stdlib/src/filelib.erl
+++ b/lib/stdlib/src/filelib.erl
@@ -19,16 +19,14 @@
-module(filelib).
%% File utilities.
-
-%% Avoid warning for local function error/1 clashing with autoimported BIF.
--compile({no_auto_import,[error/1]}).
--export([wildcard/1, wildcard/2, is_dir/1, is_file/1, is_regular/1,
- compile_wildcard/1]).
+-export([wildcard/1, wildcard/2, is_dir/1, is_file/1, is_regular/1]).
-export([fold_files/5, last_modified/1, file_size/1, ensure_dir/1]).
-
-export([wildcard/3, is_dir/2, is_file/2, is_regular/2]).
-export([fold_files/6, last_modified/2, file_size/2]).
+%% For debugging/testing.
+-export([compile_wildcard/1]).
+
-include_lib("kernel/include/file.hrl").
-define(HANDLE_ERROR(Expr),
@@ -37,7 +35,7 @@
catch
error:{badpattern,_}=UnUsUalVaRiAbLeNaMe ->
%% Get the stack backtrace correct.
- erlang:error(UnUsUalVaRiAbLeNaMe)
+ error(UnUsUalVaRiAbLeNaMe)
end).
-type filename() :: file:name().
@@ -48,19 +46,19 @@
-spec wildcard(Wildcard) -> [file:filename()] when
Wildcard :: filename() | dirname().
wildcard(Pattern) when is_list(Pattern) ->
- ?HANDLE_ERROR(do_wildcard(Pattern, file)).
+ ?HANDLE_ERROR(do_wildcard(Pattern, ".", file)).
-spec wildcard(Wildcard, Cwd) -> [file:filename()] when
Wildcard :: filename() | dirname(),
Cwd :: dirname().
-wildcard(Pattern, Cwd) when is_list(Pattern), (is_list(Cwd) or is_binary(Cwd)) ->
+wildcard(Pattern, Cwd) when is_list(Pattern), is_list(Cwd) ->
?HANDLE_ERROR(do_wildcard(Pattern, Cwd, file));
wildcard(Pattern, Mod) when is_list(Pattern), is_atom(Mod) ->
- ?HANDLE_ERROR(do_wildcard(Pattern, Mod)).
+ ?HANDLE_ERROR(do_wildcard(Pattern, ".", Mod)).
-spec wildcard(file:name(), file:name(), atom()) -> [file:filename()].
wildcard(Pattern, Cwd, Mod)
- when is_list(Pattern), (is_list(Cwd) or is_binary(Cwd)), is_atom(Mod) ->
+ when is_list(Pattern), is_list(Cwd), is_atom(Mod) ->
?HANDLE_ERROR(do_wildcard(Pattern, Cwd, Mod)).
-spec is_dir(Name) -> boolean() when
@@ -124,47 +122,6 @@ file_size(File, Mod) when is_atom(Mod) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-do_wildcard(Pattern, Mod) when is_list(Pattern) ->
- do_wildcard_comp(do_compile_wildcard(Pattern), Mod).
-
-do_wildcard_comp({compiled_wildcard,{exists,File}}, Mod) ->
- case eval_read_file_info(File, Mod) of
- {ok,_} -> [File];
- _ -> []
- end;
-do_wildcard_comp({compiled_wildcard,[cwd,Base|Rest]}, Mod) ->
- do_wildcard_1([Base], Rest, Mod);
-do_wildcard_comp({compiled_wildcard,[Base|Rest]}, Mod) ->
- do_wildcard_1([Base], Rest, Mod).
-
-do_wildcard(Pattern, Cwd, Mod) when is_list(Pattern), (is_list(Cwd) or is_binary(Cwd)) ->
- do_wildcard_comp(do_compile_wildcard(Pattern), Cwd, Mod).
-
-do_wildcard_comp({compiled_wildcard,{exists,File}}, Cwd, Mod) ->
- case eval_read_file_info(filename:absname(File, Cwd), Mod) of
- {ok,_} -> [File];
- _ -> []
- end;
-do_wildcard_comp({compiled_wildcard,[cwd|Rest0]}, Cwd0, Mod) ->
- case Rest0 of
- [current|Rest] -> ok;
- Rest -> ok
- end,
- {Cwd,PrefixLen} = case filename:join([Cwd0]) of
- Bin when is_binary(Bin) -> {Bin,byte_size(Bin)+1};
- Other -> {Other,length(Other)+1}
- end, %Slash away redundant slashes.
- [
- if
- is_binary(N) ->
- <<_:PrefixLen/binary,Res/binary>> = N,
- Res;
- true ->
- lists:nthtail(PrefixLen, N)
- end || N <- do_wildcard_1([Cwd], Rest, Mod)];
-do_wildcard_comp({compiled_wildcard,[Base|Rest]}, _Cwd, Mod) ->
- do_wildcard_1([Base], Rest, Mod).
-
do_is_dir(Dir, Mod) ->
case eval_read_file_info(Dir, Mod) of
{ok, #file_info{type=directory}} ->
@@ -293,8 +250,24 @@ ensure_dir(F) ->
%%% Pattern matching using a compiled wildcard.
%%%
-do_wildcard_1(Files, Pattern, Mod) ->
- do_wildcard_2(Files, Pattern, [], Mod).
+do_wildcard(Pattern, Cwd, Mod) ->
+ {Compiled,PrefixLen} = compile_wildcard(Pattern, Cwd),
+ Files0 = do_wildcard_1(Compiled, Mod),
+ Files = if
+ PrefixLen =:= 0 ->
+ Files0;
+ true ->
+ [lists:nthtail(PrefixLen, File) || File <- Files0]
+ end,
+ lists:sort(Files).
+
+do_wildcard_1({exists,File}, Mod) ->
+ case eval_read_file_info(File, Mod) of
+ {ok,_} -> [File];
+ _ -> []
+ end;
+do_wildcard_1([Base|Rest], Mod) ->
+ do_wildcard_2([Base], Rest, [], Mod).
do_wildcard_2([File|Rest], Pattern, Result, Mod) ->
do_wildcard_2(Rest, Pattern, do_wildcard_3(File, Pattern, Result, Mod), Mod);
@@ -302,12 +275,12 @@ do_wildcard_2([], _, Result, _Mod) ->
Result.
do_wildcard_3(Base, [[double_star]|Rest], Result, Mod) ->
- lists:sort(do_double_star(current, [Base], Rest, Result, Mod, true));
-do_wildcard_3(Base, [Pattern|Rest], Result, Mod) ->
- case do_list_dir(Base, Mod) of
- {ok, Files0} ->
- Files = lists:sort(Files0),
- Matches = wildcard_4(Pattern, Files, Base, []),
+ do_double_star(".", [Base], Rest, Result, Mod, true);
+do_wildcard_3(Base0, [Pattern|Rest], Result, Mod) ->
+ case do_list_dir(Base0, Mod) of
+ {ok, Files} ->
+ Base = prepare_base(Base0),
+ Matches = do_wildcard_4(Pattern, Base, Files),
do_wildcard_2(Matches, Rest, Result, Mod);
_ ->
Result
@@ -315,51 +288,50 @@ do_wildcard_3(Base, [Pattern|Rest], Result, Mod) ->
do_wildcard_3(Base, [], Result, _Mod) ->
[Base|Result].
-wildcard_4(Pattern, [File|Rest], Base, Result) when is_binary(File) ->
- case wildcard_5(Pattern, binary_to_list(File)) of
- true ->
- wildcard_4(Pattern, Rest, Base, [join(Base, File)|Result]);
+do_wildcard_4(Pattern, Base, Files) ->
+ case will_always_match(Pattern) of
false ->
- wildcard_4(Pattern, Rest, Base, Result)
- end;
-wildcard_4(Pattern, [File|Rest], Base, Result) ->
- case wildcard_5(Pattern, File) of
+ [Base++F || F <- Files, match_part(Pattern, F)];
true ->
- wildcard_4(Pattern, Rest, Base, [join(Base, File)|Result]);
- false ->
- wildcard_4(Pattern, Rest, Base, Result)
- end;
-wildcard_4(_Patt, [], _Base, Result) ->
- Result.
+ [Base++F || F <- Files]
+ end.
-wildcard_5([question|Rest1], [_|Rest2]) ->
- wildcard_5(Rest1, Rest2);
-wildcard_5([accept], _) ->
+match_part([question|Rest1], [_|Rest2]) ->
+ match_part(Rest1, Rest2);
+match_part([accept], _) ->
true;
-wildcard_5([double_star], _) ->
+match_part([double_star], _) ->
true;
-wildcard_5([star|Rest], File) ->
+match_part([star|Rest], File) ->
do_star(Rest, File);
-wildcard_5([{one_of, Ordset}|Rest], [C|File]) ->
- case ordsets:is_element(C, Ordset) of
- true -> wildcard_5(Rest, File);
- false -> false
- end;
-wildcard_5([{alt, Alts}], File) ->
+match_part([{one_of, Ordset}|Rest], [C|File]) ->
+ gb_sets:is_element(C, Ordset) andalso match_part(Rest, File);
+match_part([{alt, Alts}], File) ->
do_alt(Alts, File);
-wildcard_5([C|Rest1], [C|Rest2]) when is_integer(C) ->
- wildcard_5(Rest1, Rest2);
-wildcard_5([X|_], [Y|_]) when is_integer(X), is_integer(Y) ->
+match_part([C|Rest1], [C|Rest2]) when is_integer(C) ->
+ match_part(Rest1, Rest2);
+match_part([X|_], [Y|_]) when is_integer(X), is_integer(Y) ->
false;
-wildcard_5([], []) ->
+match_part([], []) ->
true;
-wildcard_5([], [_|_]) ->
+match_part([], [_|_]) ->
false;
-wildcard_5([_|_], []) ->
+match_part([_|_], []) ->
false.
+will_always_match([accept]) -> true;
+will_always_match(_) -> false.
+
+prepare_base(Base0) ->
+ Base1 = filename:join(Base0, "x"),
+ "x"++Base2 = lists:reverse(Base1),
+ lists:reverse(Base2).
+
do_double_star(Base, [H|T], Rest, Result, Mod, Root) ->
- Full = join(Base, H),
+ Full = case Root of
+ false -> filename:join(Base, H);
+ true -> H
+ end,
Result1 = case do_list_dir(Full, Mod) of
{ok, Files} ->
do_double_star(Full, Files, Rest, Result, Mod, false);
@@ -373,62 +345,64 @@ do_double_star(Base, [H|T], Rest, Result, Mod, Root) ->
do_double_star(_Base, [], _Rest, Result, _Mod, _Root) ->
Result.
-do_star(Pattern, [X|Rest]) ->
- case wildcard_5(Pattern, [X|Rest]) of
- true -> true;
- false -> do_star(Pattern, Rest)
- end;
+do_star(Pattern, [_|Rest]=File) ->
+ match_part(Pattern, File) orelse do_star(Pattern, Rest);
do_star(Pattern, []) ->
- wildcard_5(Pattern, []).
+ match_part(Pattern, []).
do_alt([Alt|Rest], File) ->
- case wildcard_5(Alt, File) of
- true -> true;
- false -> do_alt(Rest, File)
- end;
+ match_part(Alt, File) orelse do_alt(Rest, File);
do_alt([], _File) ->
false.
-do_list_dir(current, Mod) -> eval_list_dir(".", Mod);
do_list_dir(Dir, Mod) -> eval_list_dir(Dir, Mod).
-join(current, File) -> File;
-join(Base, File) -> filename:join(Base, File).
-
%%% Compiling a wildcard.
-compile_wildcard(Pattern) ->
- ?HANDLE_ERROR(do_compile_wildcard(Pattern)).
-
-do_compile_wildcard(Pattern) ->
- {compiled_wildcard,compile_wildcard_1(Pattern)}.
+%% Only for debugging.
+compile_wildcard(Pattern) when is_list(Pattern) ->
+ {compiled_wildcard,?HANDLE_ERROR(compile_wildcard(Pattern, "."))}.
-compile_wildcard_1(Pattern) ->
+compile_wildcard(Pattern, Cwd0) ->
[Root|Rest] = filename:split(Pattern),
case filename:pathtype(Root) of
relative ->
- case compile_wildcard_2([Root|Rest], current) of
- {exists,_}=Wc -> Wc;
- [_|_]=Wc -> [cwd|Wc]
- end;
+ Cwd = filename:join([Cwd0]),
+ compile_wildcard_2([Root|Rest], {cwd,Cwd});
_ ->
- compile_wildcard_2(Rest, [Root])
+ compile_wildcard_2(Rest, {root,0,Root})
end.
compile_wildcard_2([Part|Rest], Root) ->
case compile_part(Part) of
Part ->
- compile_wildcard_2(Rest, join(Root, Part));
+ compile_wildcard_2(Rest, compile_join(Root, Part));
Pattern ->
compile_wildcard_3(Rest, [Pattern,Root])
end;
-compile_wildcard_2([], Root) -> {exists,Root}.
+compile_wildcard_2([], {root,PrefixLen,Root}) ->
+ {{exists,Root},PrefixLen}.
compile_wildcard_3([Part|Rest], Result) ->
compile_wildcard_3(Rest, [compile_part(Part)|Result]);
compile_wildcard_3([], Result) ->
- lists:reverse(Result).
+ case lists:reverse(Result) of
+ [{root,PrefixLen,Root}|Compiled] ->
+ {[Root|Compiled],PrefixLen};
+ [{cwd,Root}|Compiled] ->
+ {[Root|Compiled],length(filename:join(Root, "x"))-1}
+ end.
+
+compile_join({cwd,"."}, File) ->
+ {root,0,File};
+compile_join({cwd,Cwd}, File0) ->
+ File = filename:join([File0]),
+ Root = filename:join(Cwd, File),
+ PrefixLen = length(Root) - length(File),
+ {root,PrefixLen,Root};
+compile_join({root,PrefixLen,Root}, File) ->
+ {root,PrefixLen,filename:join(Root, File)}.
compile_part(Part) ->
compile_part(Part, false, []).
@@ -437,7 +411,7 @@ compile_part_to_sep(Part) ->
compile_part(Part, true, []).
compile_part([], true, _) ->
- error(missing_delimiter);
+ badpattern(missing_delimiter);
compile_part([$,|Rest], true, Result) ->
{ok, $,, lists:reverse(Result), Rest};
compile_part([$}|Rest], true, Result) ->
@@ -473,8 +447,6 @@ compile_part([], _Upto, Result) ->
compile_charset([$]|Rest], Ordset) ->
compile_charset1(Rest, ordsets:add_element($], Ordset));
-compile_charset([$-|Rest], Ordset) ->
- compile_charset1(Rest, ordsets:add_element($-, Ordset));
compile_charset([], _Ordset) ->
error;
compile_charset(List, Ordset) ->
@@ -483,7 +455,7 @@ compile_charset(List, Ordset) ->
compile_charset1([Lower, $-, Upper|Rest], Ordset) when Lower =< Upper ->
compile_charset1(Rest, compile_range(Lower, Upper, Ordset));
compile_charset1([$]|Rest], Ordset) ->
- {ok, {one_of, Ordset}, Rest};
+ {ok, {one_of, gb_sets:from_ordset(Ordset)}, Rest};
compile_charset1([X|Rest], Ordset) ->
compile_charset1(Rest, ordsets:add_element(X, Ordset));
compile_charset1([], _Ordset) ->
@@ -509,8 +481,8 @@ compile_alt(Pattern, Result) ->
error
end.
-error(Reason) ->
- erlang:error({badpattern,Reason}).
+badpattern(Reason) ->
+ error({badpattern,Reason}).
eval_read_file_info(File, file) ->
file:read_file_info(File);
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index 0c50eb34e6..e944dd4c43 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -61,13 +61,13 @@
%% (for WIN32): absname("/") -> "D:/"
--spec absname(Filename) -> file:filename() when
+-spec absname(Filename) -> file:filename_all() when
Filename :: file:name().
absname(Name) ->
{ok, Cwd} = file:get_cwd(),
absname(Name, Cwd).
--spec absname(Filename, Dir) -> file:filename() when
+-spec absname(Filename, Dir) -> file:filename_all() when
Filename :: file:name(),
Dir :: file:name().
absname(Name, AbsBase) when is_binary(Name), is_list(AbsBase) ->
@@ -122,7 +122,7 @@ absname_vr([[X, $:]|Name], _, _AbsBase) ->
%% This is just a join/2, but assumes that
%% AbsBase must be absolute and Name must be relative.
--spec absname_join(Dir, Filename) -> file:filename() when
+-spec absname_join(Dir, Filename) -> file:filename_all() when
Dir :: file:name(),
Filename :: file:name().
absname_join(AbsBase, Name) ->
@@ -136,7 +136,7 @@ absname_join(AbsBase, Name) ->
%% basename("/usr/foo/") -> "foo" (trailing slashes ignored)
%% basename("/") -> []
--spec basename(Filename) -> file:filename() when
+-spec basename(Filename) -> file:filename_all() when
Filename :: file:name().
basename(Name) when is_binary(Name) ->
case os:type() of
@@ -201,7 +201,7 @@ skip_prefix(Name, _) ->
%% rootname(basename("xxx.jam")) -> "xxx"
%% rootname(basename("xxx.erl")) -> "xxx"
--spec basename(Filename, Ext) -> file:filename() when
+-spec basename(Filename, Ext) -> file:filename_all() when
Filename :: file:name(),
Ext :: file:name().
basename(Name, Ext) when is_binary(Name), is_list(Ext) ->
@@ -251,7 +251,7 @@ basename([], _Ext, Tail, _DrvSep2) ->
%% Example: dirname("/usr/src/kalle.erl") -> "/usr/src",
%% dirname("kalle.erl") -> "."
--spec dirname(Filename) -> file:filename() when
+-spec dirname(Filename) -> file:filename_all() when
Filename :: file:name().
dirname(Name) when is_binary(Name) ->
{Dsep,Drivesep} = separators(),
@@ -344,7 +344,7 @@ dirjoin1([H|T],Acc,Sep) ->
%%
%% On Windows: fn:dirname("\\usr\\src/kalle.erl") -> "/usr/src"
--spec extension(Filename) -> file:filename() when
+-spec extension(Filename) -> file:filename_all() when
Filename :: file:name().
extension(Name) when is_binary(Name) ->
{Dsep,_} = separators(),
@@ -387,7 +387,7 @@ extension([], Result, _OsType) ->
%% Joins a list of filenames with directory separators.
--spec join(Components) -> file:filename() when
+-spec join(Components) -> file:filename_all() when
Components :: [file:name()].
join([Name1, Name2|Rest]) ->
join([join(Name1, Name2)|Rest]);
@@ -400,7 +400,7 @@ join([Name]) when is_atom(Name) ->
%% Joins two filenames with directory separators.
--spec join(Name1, Name2) -> file:filename() when
+-spec join(Name1, Name2) -> file:filename_all() when
Name1 :: file:name(),
Name2 :: file:name().
join(Name1, Name2) when is_list(Name1), is_list(Name2) ->
@@ -488,7 +488,7 @@ maybe_remove_dirsep(Name, _) ->
%% a given base directory, which is is assumed to be normalised
%% by a previous call to join/{1,2}.
--spec append(file:filename(), file:name()) -> file:filename().
+-spec append(file:filename_all(), file:name()) -> file:filename_all().
append(Dir, Name) when is_binary(Dir), is_binary(Name) ->
<<Dir/binary,$/:8,Name/binary>>;
append(Dir, Name) when is_binary(Dir) ->
@@ -564,7 +564,7 @@ win32_pathtype(_) -> relative.
%% Examples: rootname("/jam.src/kalle") -> "/jam.src/kalle"
%% rootname("/jam.src/foo.erl") -> "/jam.src/foo"
--spec rootname(Filename) -> file:filename() when
+-spec rootname(Filename) -> file:filename_all() when
Filename :: file:name().
rootname(Name) when is_binary(Name) ->
list_to_binary(rootname(binary_to_list(Name))); % No need to handle unicode, . is < 128
@@ -594,7 +594,7 @@ rootname([], Root, _Ext, _OsType) ->
%% Examples: rootname("/jam.src/kalle.jam", ".erl") -> "/jam.src/kalle.jam"
%% rootname("/jam.src/foo.erl", ".erl") -> "/jam.src/foo"
--spec rootname(Filename, Ext) -> file:filename() when
+-spec rootname(Filename, Ext) -> file:filename_all() when
Filename :: file:name(),
Ext :: file:name().
rootname(Name, Ext) when is_binary(Name), is_binary(Ext) ->
@@ -717,7 +717,7 @@ split([], Comp, Components, OsType) ->
%% will be converted to backslashes. On all platforms, the
%% name will be normalized as done by join/1.
--spec nativename(Path) -> file:filename() when
+-spec nativename(Path) -> file:filename_all() when
Path :: file:name().
nativename(Name0) ->
Name = join([Name0]), %Normalize.
@@ -921,7 +921,7 @@ major_os_type() ->
%% flatten(List)
%% Flatten a list, also accepting atoms.
--spec flatten(Filename) -> file:filename() when
+-spec flatten(Filename) -> file:filename_all() when
Filename :: file:name().
flatten(Bin) when is_binary(Bin) ->
Bin;
diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl
index 6a06d9448b..64d19ccf48 100644
--- a/lib/stdlib/src/io_lib_format.erl
+++ b/lib/stdlib/src/io_lib_format.erl
@@ -185,8 +185,7 @@ control($s, [L0], F, Adj, P, Pad, latin1, _I) ->
L = iolist_to_chars(L0),
string(L, F, Adj, P, Pad);
control($s, [L0], F, Adj, P, Pad, unicode, _I) ->
- L = unicode:characters_to_list(L0),
- true = is_list(L),
+ L = cdata_to_chars(L0),
uniconv(string(L, F, Adj, P, Pad));
control($e, [A], F, Adj, P, Pad, _Enc, _I) when is_float(A) ->
fwrite_e(A, F, Adj, P, Pad);
@@ -558,6 +557,25 @@ iolist_to_chars([]) ->
iolist_to_chars(B) when is_binary(B) ->
binary_to_list(B).
+%% cdata() :: clist() | cbinary()
+%% clist() :: maybe_improper_list(char() | cbinary() | clist(),
+%% cbinary() | nil())
+%% cbinary() :: unicode:unicode_binary() | unicode:latin1_binary()
+
+%% cdata_to_chars(cdata()) -> io_lib:deep_char_list()
+
+cdata_to_chars([C|Cs]) when is_integer(C), C >= $\000 ->
+ [C | cdata_to_chars(Cs)];
+cdata_to_chars([I|Cs]) ->
+ [cdata_to_chars(I) | cdata_to_chars(Cs)];
+cdata_to_chars([]) ->
+ [];
+cdata_to_chars(B) when is_binary(B) ->
+ case catch unicode:characters_to_list(B) of
+ L when is_list(L) -> L;
+ _ -> binary_to_list(B)
+ end.
+
%% string(String, Field, Adjust, Precision, PadChar)
string(S, none, _Adj, none, _Pad) -> S;
diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl
index a8f610558a..b05db3d290 100644
--- a/lib/stdlib/src/io_lib_pretty.erl
+++ b/lib/stdlib/src/io_lib_pretty.erl
@@ -452,18 +452,6 @@ printable_list(L, _D, latin1) ->
io_lib:printable_latin1_list(L);
printable_list(L, _D, _Uni) ->
io_lib:printable_list(L).
-%% Truncated lists could break some existing code.
-% printable_list(L, D, Enc) when D >= 0 ->
-% Len = ?CHARS * (D - 1),
-% case printable_list1(L, Len, Enc) of
-% all ->
-% true;
-% N when is_integer(N), Len - N >= D - 1 ->
-% {L1, _} = lists:split(Len - N, L),
-% {true, L1};
-% N when is_integer(N) ->
-% false
-% end.
printable_bin(Bin, D, Enc) when D >= 0, ?CHARS * D =< byte_size(Bin) ->
printable_bin(Bin, erlang:min(?CHARS * D, byte_size(Bin)), D, Enc);
@@ -473,7 +461,7 @@ printable_bin(Bin, D, Enc) ->
printable_bin(Bin, Len, D, latin1) ->
N = erlang:min(20, Len),
L = binary_to_list(Bin, 1, N),
- case printable_list1(L, N) of
+ case printable_latin1_list(L, N) of
all when N =:= byte_size(Bin) ->
{true, L};
all when N =:= Len -> % N < byte_size(Bin)
@@ -507,7 +495,7 @@ printable_bin1(_Bin, _Start, 0) ->
printable_bin1(Bin, Start, Len) ->
N = erlang:min(10000, Len),
L = binary_to_list(Bin, Start, Start + N - 1),
- case printable_list1(L, N) of
+ case printable_latin1_list(L, N) of
all ->
printable_bin1(Bin, Start + N, Len - N);
NC when is_integer(NC) ->
@@ -515,26 +503,44 @@ printable_bin1(Bin, Start, Len) ->
end.
%% -> all | integer() >=0. Adopted from io_lib.erl.
-% printable_list1([_ | _], 0) -> 0;
-printable_list1([C | Cs], N) when is_integer(C), C >= $\s, C =< $~ ->
- printable_list1(Cs, N - 1);
-printable_list1([C | Cs], N) when is_integer(C), C >= $\240, C =< $\377 ->
- printable_list1(Cs, N - 1);
-printable_list1([$\n | Cs], N) -> printable_list1(Cs, N - 1);
-printable_list1([$\r | Cs], N) -> printable_list1(Cs, N - 1);
-printable_list1([$\t | Cs], N) -> printable_list1(Cs, N - 1);
-printable_list1([$\v | Cs], N) -> printable_list1(Cs, N - 1);
-printable_list1([$\b | Cs], N) -> printable_list1(Cs, N - 1);
-printable_list1([$\f | Cs], N) -> printable_list1(Cs, N - 1);
-printable_list1([$\e | Cs], N) -> printable_list1(Cs, N - 1);
-printable_list1([], _) -> all;
-printable_list1(_, N) -> N.
-
-printable_unicode(<<C/utf8, R/binary>>, I, L) when I > 0 ->
- printable_unicode(R, I - 1, [C | L]);
+% printable_latin1_list([_ | _], 0) -> 0;
+printable_latin1_list([C | Cs], N) when C >= $\s, C =< $~ ->
+ printable_latin1_list(Cs, N - 1);
+printable_latin1_list([C | Cs], N) when C >= $\240, C =< $\377 ->
+ printable_latin1_list(Cs, N - 1);
+printable_latin1_list([$\n | Cs], N) -> printable_latin1_list(Cs, N - 1);
+printable_latin1_list([$\r | Cs], N) -> printable_latin1_list(Cs, N - 1);
+printable_latin1_list([$\t | Cs], N) -> printable_latin1_list(Cs, N - 1);
+printable_latin1_list([$\v | Cs], N) -> printable_latin1_list(Cs, N - 1);
+printable_latin1_list([$\b | Cs], N) -> printable_latin1_list(Cs, N - 1);
+printable_latin1_list([$\f | Cs], N) -> printable_latin1_list(Cs, N - 1);
+printable_latin1_list([$\e | Cs], N) -> printable_latin1_list(Cs, N - 1);
+printable_latin1_list([], _) -> all;
+printable_latin1_list(_, N) -> N.
+
+printable_unicode(<<C/utf8, R/binary>>=Bin, I, L) when I > 0 ->
+ case printable_char(C) of
+ true ->
+ printable_unicode(R, I - 1, [C | L]);
+ false ->
+ {I, Bin, lists:reverse(L)}
+ end;
printable_unicode(Bin, I, L) ->
{I, Bin, lists:reverse(L)}.
+printable_char($\n) -> true;
+printable_char($\r) -> true;
+printable_char($\t) -> true;
+printable_char($\v) -> true;
+printable_char($\b) -> true;
+printable_char($\f) -> true;
+printable_char($\e) -> true;
+printable_char(C) ->
+ C >= $\s andalso C =< $~ orelse
+ C >= 16#A0 andalso C < 16#D800 orelse
+ C > 16#DFFF andalso C < 16#FFFE orelse
+ C > 16#FFFF andalso C =< 16#10FFFF.
+
write_string(S, latin1) ->
io_lib:write_latin1_string(S, $"); %"
write_string(S, _Uni) ->
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 9257953071..a4f4035c79 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -353,7 +353,7 @@ obsolete_1(inviso, _, _) ->
%% Added in R15B01.
obsolete_1(gs, _, _) ->
- {deprecated,"the gs application has been deprecated and will be removed in R16; use the wx application instead"};
+ {deprecated,"the gs application has been deprecated and will be removed in R17; use the wx application instead"};
obsolete_1(ssh, sign_data, 2) ->
{deprecated,"deprecated (will be removed in R16A); use public_key:pem_decode/1, public_key:pem_entry_decode/1 "
"and public_key:sign/3 instead"};
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index 203d2a4f76..c94f052b24 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -185,7 +185,7 @@ server(StartSync) ->
%% Check if we're in user restricted mode.
RShErr =
case application:get_env(stdlib, restricted_shell) of
- {ok,RShMod} ->
+ {ok,RShMod} when is_atom(RShMod) ->
io:fwrite(<<"Restricted ">>, []),
case code:ensure_loaded(RShMod) of
{module,RShMod} ->
@@ -193,6 +193,8 @@ server(StartSync) ->
{error,What} ->
{RShMod,What}
end;
+ {ok, Term} ->
+ {Term,not_an_atom};
undefined ->
undefined
end,
@@ -948,7 +950,7 @@ local_func(rd, [{atom,_,RecName},RecDef0], Bs, _Shell, RT, _Lf, _Ef) ->
RecDef = expand_value(RecDef0),
RDs = lists:flatten(erl_pp:expr(RecDef)),
Attr = lists:concat(["-record('", RecName, "',", RDs, ")."]),
- {ok, Tokens, _} = erl_scan:string(Attr, 1, [unicode]),
+ {ok, Tokens, _} = erl_scan:string(Attr),
case erl_parse:parse_form(Tokens) of
{ok,AttrForm} ->
[RN] = add_records([AttrForm], Bs, RT),
@@ -1395,7 +1397,6 @@ enc() ->
garb(Shell) ->
erlang:garbage_collect(Shell),
catch erlang:garbage_collect(whereis(user)),
- catch erlang:garbage_collect(whereis(group)),
catch erlang:garbage_collect(group_leader()),
erlang:garbage_collect().
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index 04d49770cb..7ff4c81ea6 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -37,6 +37,7 @@
otp_6977/1,
otp_7550/1,
otp_8133/1,
+ otp_10622/1,
funs/1,
try_catch/1,
eval_expr_5/1,
@@ -79,7 +80,7 @@ all() ->
pattern_expr, match_bin, guard_3, guard_4, lc,
simple_cases, unary_plus, apply_atom, otp_5269,
otp_6539, otp_6543, otp_6787, otp_6977, otp_7550,
- otp_8133, funs, try_catch, eval_expr_5, zero_width].
+ otp_8133, otp_10622, funs, try_catch, eval_expr_5, zero_width].
groups() ->
[].
@@ -960,6 +961,7 @@ otp_8133(Config) when is_list(Config) ->
E = fun(N) ->
if
is_integer(N) -> <<N/integer>>;
+
true -> erlang:error(foo)
end
end,
@@ -980,6 +982,48 @@ otp_8133(Config) when is_list(Config) ->
ok),
ok.
+otp_10622(doc) ->
+ ["OTP-10622. Bugs."];
+otp_10622(suite) ->
+ [];
+otp_10622(Config) when is_list(Config) ->
+ check(fun() -> <<0>> = <<"\x{400}">> end,
+ "<<0>> = <<\"\\x{400}\">>. ",
+ <<0>>),
+ check(fun() -> <<"\x{aa}ff"/utf8>> = <<"\x{aa}ff"/utf8>> end,
+ "<<\"\\x{aa}ff\"/utf8>> = <<\"\\x{aa}ff\"/utf8>>. ",
+ <<"�\xaaff">>),
+ %% The same bug as last example:
+ check(fun() -> case <<"foo"/utf8>> of
+ <<"foo"/utf8>> -> true
+ end
+ end,
+ "case <<\"foo\"/utf8>> of <<\"foo\"/utf8>> -> true end.",
+ true),
+ check(fun() -> <<"\x{400}"/utf8>> = <<"\x{400}"/utf8>> end,
+ "<<\"\\x{400}\"/utf8>> = <<\"\\x{400}\"/utf8>>. ",
+ <<208,128>>),
+ error_check("<<\"\\x{aaa}\">> = <<\"\\x{aaa}\">>.",
+ {badmatch,<<"\xaa">>}),
+
+ check(fun() -> [a || <<"\x{aaa}">> <= <<2703:16>>] end,
+ "[a || <<\"\\x{aaa}\">> <= <<2703:16>>]. ",
+ []),
+ check(fun() -> [a || <<"\x{aa}"/utf8>> <= <<"\x{aa}"/utf8>>] end,
+ "[a || <<\"\\x{aa}\"/utf8>> <= <<\"\\x{aa}\"/utf8>>]. ",
+ [a]),
+ check(fun() -> [a || <<"\x{aa}x"/utf8>> <= <<"\x{aa}y"/utf8>>] end,
+ "[a || <<\"\\x{aa}x\"/utf8>> <= <<\"\\x{aa}y\"/utf8>>]. ",
+ []),
+ check(fun() -> [a || <<"\x{aaa}">> <= <<"\x{aaa}">>] end,
+ "[a || <<\"\\x{aaa}\">> <= <<\"\\x{aaa}\">>]. ",
+ []),
+ check(fun() -> [a || <<"\x{aaa}"/utf8>> <= <<"\x{aaa}"/utf8>>] end,
+ "[a || <<\"\\x{aaa}\"/utf8>> <= <<\"\\x{aaa}\"/utf8>>]. ",
+ [a]),
+
+ ok.
+
funs(doc) ->
["Simple cases, just to cover some code."];
funs(suite) ->
@@ -1042,6 +1086,10 @@ funs(Config) when is_list(Config) ->
"begin M = lists, F = fun M:reverse/1,"
" [1,2] = F([2,1]), ok end.",
ok),
+
+ %% Test that {M,F} is not accepted as a fun.
+ error_check("{" ?MODULE_STRING ",module_info}().",
+ {badfun,{?MODULE,module_info}}),
ok.
run_many_args({S, As}) ->
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 564f27a512..36229b6989 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -58,7 +58,8 @@
otp_8051/1,
format_warn/1,
on_load_successful/1, on_load_failing/1,
- too_many_arguments/1
+ too_many_arguments/1,
+ basic_errors/1,bin_syntax_errors/1
]).
% Default timetrap timeout (set in init_per_testcase).
@@ -84,7 +85,7 @@ all() ->
otp_5878, otp_5917, otp_6585, otp_6885, otp_10436, export_all,
bif_clash, behaviour_basic, behaviour_multiple,
otp_7550, otp_8051, format_warn, {group, on_load},
- too_many_arguments].
+ too_many_arguments, basic_errors, bin_syntax_errors].
groups() ->
[{unused_vars_warn, [],
@@ -1351,7 +1352,17 @@ guard(Config) when is_list(Config) ->
(is_record(X, apa)*2)].
">>,
[],
- []}],
+ []},
+ {guard8,
+ <<"t(A) when erlang:is_foobar(A) -> ok;
+ t(A) when A ! ok -> ok;
+ t(A) when A ++ [x] -> ok."
+ >>,
+ [],
+ {errors,[{1,erl_lint,illegal_guard_expr},
+ {2,erl_lint,illegal_guard_expr},
+ {3,erl_lint,illegal_guard_expr}],[]}}
+ ],
?line [] = run(Config, Ts1),
ok.
@@ -1639,6 +1650,7 @@ otp_5276(Config) when is_list(Config) ->
-deprecated([{'_','_',never}]).
-deprecated([{{badly,formed},1}]).
-deprecated([{'_','_',next_major_release}]).
+ -deprecated([{atom_to_list,1}]).
-export([t/0]).
frutt() -> ok.
t() -> ok.
@@ -1649,8 +1661,9 @@ otp_5276(Config) when is_list(Config) ->
{3,erl_lint,{invalid_deprecated,'foo bar'}},
{5,erl_lint,{bad_deprecated,{f,'_'}}},
{8,erl_lint,{invalid_deprecated,{'_','_',never}}},
- {9,erl_lint,{invalid_deprecated,{{badly,formed},1}}}],
- [{12,erl_lint,{unused_function,{frutt,0}}}]}}],
+ {9,erl_lint,{invalid_deprecated,{{badly,formed},1}}},
+ {11,erl_lint,{bad_deprecated,{atom_to_list,1}}}],
+ [{13,erl_lint,{unused_function,{frutt,0}}}]}}],
?line [] = run(Config, Ts),
ok.
@@ -1896,9 +1909,23 @@ otp_5362(Config) when is_list(Config) ->
warn_deprecated_function,
warn_bif_clash]},
{errors,
- [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}}
+ [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}},
- ],
+ {call_deprecated_function,
+ <<"t(X) -> erlang:hash(X, 2000).">>,
+ [],
+ {warnings,
+ [{1,erl_lint,{deprecated,{erlang,hash,2},
+ {erlang,phash2,2},"in a future release"}}]}},
+
+ {call_removed_function,
+ <<"t(X) -> regexp:match(X).">>,
+ [],
+ {warnings,
+ [{1,erl_lint,{removed,{regexp,match,1},
+ "removed in R15; use the re module instead"}}]}}
+
+ ],
?line [] = run(Config, Ts),
ok.
@@ -2971,6 +2998,77 @@ too_many_arguments(Config) when is_list(Config) ->
ok.
+%% Test some basic errors to improve coverage.
+basic_errors(Config) ->
+ Ts = [{redefine_module,
+ <<"-module(redefine_module).">>,
+ [],
+ {errors,[{1,erl_lint,redefine_module}],[]}},
+
+ {attr_after_function,
+ <<"f() -> ok.
+ -attr(x).">>,
+ [],
+ {errors,[{2,erl_lint,{attribute,attr}}],[]}},
+
+ {redefine_function,
+ <<"f() -> ok.
+ f() -> ok.">>,
+ [],
+ {errors,[{2,erl_lint,{redefine_function,{f,0}}}],[]}},
+
+ {redefine_record,
+ <<"-record(r, {a}).
+ -record(r, {a}).
+ f(#r{}) -> ok.">>,
+ [],
+ {errors,[{2,erl_lint,{redefine_record,r}}],[]}},
+
+ {illegal_record_info,
+ <<"f1() -> record_info(42, record).
+ f2() -> record_info(shoe_size, record).">>,
+ [],
+ {errors,[{1,erl_lint,illegal_record_info},
+ {2,erl_lint,illegal_record_info}],[]}},
+
+ {illegal_expr,
+ <<"f() -> a:b.">>,
+ [],
+ {errors,[{1,erl_lint,illegal_expr}],[]}},
+
+ {illegal_pattern,
+ <<"f(A+B) -> ok.">>,
+ [],
+ {errors,[{1,erl_lint,illegal_pattern}],[]}}
+ ],
+ [] = run(Config, Ts),
+ ok.
+
+%% Test binary syntax errors
+bin_syntax_errors(Config) ->
+ Ts = [{bin_syntax_errors,
+ <<"t(<<X:bad_size>>) -> X;
+ t(<<_:(x ! y)/integer>>) -> ok;
+ t(<<X:all/integer>>) -> X;
+ t(<<X/bad_type>>) -> X;
+ t(<<X/unit:8>>) -> X;
+ t(<<X:7/float>>) -> X;
+ t(<< <<_:8>> >>) -> ok;
+ t(<<(x ! y):8/integer>>) -> ok.
+ ">>,
+ [],
+ {error,[{1,erl_lint,illegal_bitsize},
+ {2,erl_lint,illegal_bitsize},
+ {3,erl_lint,illegal_bitsize},
+ {4,erl_lint,{undefined_bittype,bad_type}},
+ {5,erl_lint,bittype_unit},
+ {7,erl_lint,illegal_pattern},
+ {8,erl_lint,illegal_pattern}],
+ [{6,erl_lint,{bad_bitsize,"float"}}]}}
+ ],
+ [] = run(Config, Ts),
+ ok.
+
run(Config, Tests) ->
F = fun({N,P,Ws,E}, BadL) ->
case catch run_test(Config, P, Ws) of
diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl
index 3f77d40a2e..ecd181e87c 100644
--- a/lib/stdlib/test/erl_scan_SUITE.erl
+++ b/lib/stdlib/test/erl_scan_SUITE.erl
@@ -118,13 +118,13 @@ check(String) ->
%%% (This should be useful for all format_error functions.)
check_error({error, Info, EndLine}, Module0) ->
- ?line {ErrorLine, Module, Desc} = Info,
- ?line true = (Module == Module0),
- ?line assert_type(EndLine, integer),
- ?line assert_type(ErrorLine, integer),
- ?line true = (ErrorLine =< EndLine),
- ?line String = lists:flatten(Module0:format_error(Desc)),
- ?line true = io_lib:printable_list(String).
+ {ErrorLine, Module, Desc} = Info,
+ true = (Module == Module0),
+ assert_type(EndLine, integer),
+ assert_type(ErrorLine, integer),
+ true = (ErrorLine =< EndLine),
+ String = lists:flatten(Module0:format_error(Desc)),
+ true = io_lib:printable_list(String).
iso88591(doc) -> ["Tests the support for ISO-8859-1 i.e Latin-1"];
iso88591(suite) -> [];
@@ -809,77 +809,57 @@ white_spaces() ->
unicode() ->
?line {ok,[{char,1,83},{integer,1,45}],1} =
- erl_scan:string("$\\12345", 1, [{unicode,false}]), % not unicode
+ erl_scan:string("$\\12345"), % not unicode
?line {error,{1,erl_scan,{illegal,character}},1} =
- erl_scan:string([1089], 1, [{unicode,false}]),
+ erl_scan:string([1089]),
?line {error,{{1,1},erl_scan,{illegal,character}},{1,2}} =
- erl_scan:string([1089], {1,1}, [{unicode,false}]),
- ?line {error,{1,erl_scan,{illegal,character}},1} =
- %% ?line {error,{1,erl_scan,{illegal,atom}},1} =
- erl_scan:string("'a"++[1089]++"b'", 1, [{unicode,false}]),
- ?line {error,{{1,3},erl_scan,{illegal,character}},{1,4}} =
- erl_scan:string("'a"++[1089]++"b'", {1,1}, [{unicode,false}]),
+ erl_scan:string([1089], {1,1}),
+ ?line {error,{1,erl_scan,{illegal,atom}},1} =
+ erl_scan:string("'a"++[1089]++"b'", 1),
+ ?line {error,{{1,1},erl_scan,{illegal,atom}},{1,6}} =
+ erl_scan:string("'a"++[1089]++"b'", {1,1}),
?line test("\"a"++[1089]++"b\""),
?line {ok,[{char,1,1}],1} =
- erl_scan:string([$$,$\\,$^,1089], 1, [{unicode,false}]),
+ erl_scan:string([$$,$\\,$^,1089], 1),
?line {error,{1,erl_scan,Error},1} =
- erl_scan:string("\"qa\x{aaa}", 1, [{unicode,false}]),
+ erl_scan:string("\"qa\x{aaa}", 1),
?line "unterminated string starting with \"qa"++[2730]++"\"" =
erl_scan:format_error(Error),
?line {error,{{1,1},erl_scan,_},{1,11}} =
- erl_scan:string("\"qa\\x{aaa}",{1,1}, [{unicode,false}]),
- ?line {error,{{1,4},erl_scan,{illegal,character}},{1,11}} =
- erl_scan:string("'qa\\x{aaa}'",{1,1}, [{unicode,false}]),
-
- Tags = [category, column, length, line, symbol, text],
-
- %% Workaround. No character codes greater than 255! To be changed.
- %% Note: don't remove these tests, just modify them!
+ erl_scan:string("\"qa\\x{aaa}",{1,1}),
+ ?line {error,{{1,1},erl_scan,{illegal,atom}},{1,12}} =
+ erl_scan:string("'qa\\x{aaa}'",{1,1}),
- ?line {ok,[{integer,1,1089}],1} =
- erl_scan:string([$$,1089], 1, [{unicode,false}]),
- ?line {ok,[{integer,1,1089}],1} =
- erl_scan:string([$$,$\\,1089], 1, [{unicode,false}]),
+ ?line {ok,[{char,1,1089}],1} =
+ erl_scan:string([$$,1089], 1),
+ ?line {ok,[{char,1,1089}],1} =
+ erl_scan:string([$$,$\\,1089], 1),
Qs = "$\\x{aaa}",
- ?line {ok,[{integer,1,16#aaa}],1} =
- erl_scan:string(Qs, 1, [{unicode,false}]),
+ ?line {ok,[{char,1,$\x{aaa}}],1} =
+ erl_scan:string(Qs, 1),
?line {ok,[Q2],{1,9}} =
- erl_scan:string("$\\x{aaa}", {1,1}, [text,{unicode,false}]),
- ?line [{category,integer},{column,1},{length,8},
+ erl_scan:string("$\\x{aaa}", {1,1}, [text]),
+ ?line [{category,char},{column,1},{length,8},
{line,1},{symbol,16#aaa},{text,Qs}] =
erl_scan:token_info(Q2),
U1 = "\"\\x{aaa}\"",
- ?line {ok,[T1,T2,T3],{1,10}} =
- erl_scan:string(U1, {1,1}, [text,{unicode,false}]),
- ?line [{category,'['},{column,1},{length,1},{line,1},
- {symbol,'['},{text,"\""}] = erl_scan:token_info(T1, Tags),
- ?line [{category,integer},{column,2},{length,7},
- {line,1},{symbol,16#aaa},{text,"\\x{aaa}"}] =
- erl_scan:token_info(T2, Tags),
- ?line [{category,']'},{column,9},{length,1},{line,1},
- {symbol,']'},{text,"\""}] = erl_scan:token_info(T3, Tags),
- ?line {ok,[{'[',1},{integer,1,16#aaa},{']',1}],1} =
- erl_scan:string(U1, 1, [{unicode,false}]),
+ {ok,
+ [{string,[{line,1},{column,1},{text,"\"\\x{aaa}\""}],[2730]}],
+ {1,10}} = erl_scan:string(U1, {1,1}, [text]),
+ {ok,[{string,1,[2730]}],1} = erl_scan:string(U1, 1),
U2 = "\"\\x41\\x{fff}\\x42\"",
- ?line {ok,[{'[',1},{char,1,16#41},{',',1},{integer,1,16#fff},
- {',',1},{char,1,16#42},{']',1}],1} =
- erl_scan:string(U2, 1, [{unicode,false}]),
+ {ok,[{string,1,[$\x41,$\x{fff},$\x42]}],1} = erl_scan:string(U2, 1),
U3 = "\"a\n\\x{fff}\n\"",
- ?line {ok,[{'[',1},{char,1,$a},{',',1},{char,1,$\n},
- {',',2},{integer,2,16#fff},{',',2},{char,2,$\n},
- {']',3}],3} =
- erl_scan:string(U3, 1, [{unicode,false}]),
+ {ok,[{string,1,[$a,$\n,$\x{fff},$\n]}],3} = erl_scan:string(U3, 1),
U4 = "\"\\^\n\\x{aaa}\\^\n\"",
- ?line {ok,[{'[',1},{char,1,$\n},{',',2},{integer,2,16#aaa},
- {',',2},{char,2,$\n},{']',3}],3} =
- erl_scan:string(U4, 1, [{unicode,false}]),
+ {ok,[{string,1,[$\n,$\x{aaa},$\n]}],3} = erl_scan:string(U4, 1),
%% Keep these tests:
?line test(Qs),
@@ -889,21 +869,15 @@ unicode() ->
?line test(U4),
Str1 = "\"ab" ++ [1089] ++ "cd\"",
- ?line {ok,[{'[',1},{char,1,$a},{',',1},{char,1,$b},{',',1},
- {integer,1,1089},{',',1},{char,1,$c},{',',1},
- {char,1,$d},{']',1}],1} =
- erl_scan:string(Str1, 1, [{unicode,false}]),
- ?line {ok,[{'[',_},{char,_,$a},{',',_},{char,_,$b},{',',_},
- {integer,_,1089},{',',_},{char,_,$c},{',',_},
- {char,_,$d},{']',_}],{1,8}} =
- erl_scan:string(Str1, {1,1}, [{unicode,false}]),
+ {ok,[{string,1,[$a,$b,1089,$c,$d]}],1} = erl_scan:string(Str1, 1),
+ {ok,[{string,{1,1},[$a,$b,1089,$c,$d]}],{1,8}} =
+ erl_scan:string(Str1, {1,1}),
?line test(Str1),
Comment = "%% "++[1089],
- %% Returned a comment In R15B03:
- {error,{1,erl_scan,{illegal,character}},1} =
- erl_scan:string(Comment, 1, [return,{unicode,false}]),
- {error,{{1,1},erl_scan,{illegal,character}},{1,5}} =
- erl_scan:string(Comment, {1,1}, [return,{unicode,false}]),
+ {ok,[{comment,1,[$%,$%,$\s,1089]}],1} =
+ erl_scan:string(Comment, 1, [return]),
+ {ok,[{comment,{1,1},[$%,$%,$\s,1089]}],{1,5}} =
+ erl_scan:string(Comment, {1,1}, [return]),
ok.
more_chars() ->
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index 27078f0914..4a67d68428 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -65,19 +65,26 @@ wildcard_one(Config) when is_list(Config) ->
?line {ok,OldCwd} = file:get_cwd(),
?line Dir = filename:join(?config(priv_dir, Config), "wildcard_one"),
?line ok = file:make_dir(Dir),
+ do_wildcard_1(Dir,
+ fun(Wc) ->
+ filelib:wildcard(Wc, Dir, erl_prim_loader)
+ end),
?line file:set_cwd(Dir),
- ?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc) end),
+ do_wildcard_1(Dir,
+ fun(Wc) ->
+ L = filelib:wildcard(Wc),
+ L = filelib:wildcard(Wc, erl_prim_loader),
+ L = filelib:wildcard(Wc, "."),
+ L = filelib:wildcard(Wc, Dir)
+ end),
?line file:set_cwd(OldCwd),
?line ok = file:del_dir(Dir),
ok.
wildcard_two(Config) when is_list(Config) ->
?line Dir = filename:join(?config(priv_dir, Config), "wildcard_two"),
- ?line DirB = unicode:characters_to_binary(Dir, file:native_name_encoding()),
?line ok = file:make_dir(Dir),
?line do_wildcard_1(Dir, fun(Wc) -> io:format("~p~n",[{Wc,Dir, X = filelib:wildcard(Wc, Dir)}]),X end),
- ?line do_wildcard_1(Dir, fun(Wc) -> io:format("~p~n",[{Wc,DirB, X = filelib:wildcard(Wc, DirB)}]),
- [unicode:characters_to_list(Y,file:native_name_encoding()) || Y <- X] end),
?line do_wildcard_1(Dir, fun(Wc) -> filelib:wildcard(Wc, Dir++"/") end),
case os:type() of
{win32,_} ->
@@ -130,6 +137,9 @@ do_wildcard_2(Dir, Wcf) ->
?line ["abc","abcdef"] = Wcf("a*{def,}"),
?line ["abc","abcdef"] = Wcf("a*{,def}"),
+ %% Constant wildcard.
+ ["abcdef"] = Wcf("abcdef"),
+
%% Negative tests.
?line [] = Wcf("b*"),
?line [] = Wcf("bufflig"),
@@ -157,6 +167,8 @@ do_wildcard_4(Dir, Wcf) ->
All = ["a-","aA","aB","aC","a[","a]"],
?line Files = mkfiles(lists:reverse(All), Dir),
?line All = Wcf("a[][A-C-]"),
+ ["a-"] = Wcf("a[-]"),
+ ["a["] = Wcf("a["),
?line del(Files),
do_wildcard_5(Dir, Wcf).
@@ -173,6 +185,7 @@ do_wildcard_5(Dir, Wcf) ->
?line ["blurf/nisse"] = Wcf("*/nisse"),
?line [] = Wcf("mountain/*"),
?line [] = Wcf("xa/gurka"),
+ ["blurf/nisse"] = Wcf("blurf/nisse"),
%% Cleanup
?line del(Files),
@@ -233,7 +246,24 @@ do_wildcard_8(Dir, Wcf) ->
del(Files),
foreach(fun(D) ->
ok = file:del_dir(filename:join(Dir, D))
- end, Dirs2 ++ Dirs1 ++ Dirs0).
+ end, Dirs2 ++ Dirs1 ++ Dirs0),
+ do_wildcard_9(Dir, Wcf).
+
+do_wildcard_9(Dir, Wcf) ->
+ Dirs0 = ["lib","lib/app","lib/app/ebin"],
+ Dirs = [filename:join(Dir, D) || D <- Dirs0],
+ [ok = file:make_dir(D) || D <- Dirs],
+ Files0 = [filename:join("lib/app/ebin", F++".bar") ||
+ F <- ["abc","foo","foobar"]],
+ Files = [filename:join(Dir, F) || F <- Files0],
+ [ok = file:write_file(F, <<"some content\n">>) || F <- Files],
+ Files0 = Wcf("lib/app/ebin/*.bar"),
+
+ %% Cleanup.
+ del(Files),
+ [ok = file:del_dir(D) || D <- lists:reverse(Dirs)],
+ ok.
+
fold_files(Config) when is_list(Config) ->
?line Dir = filename:join(?config(priv_dir, Config), "fold_files"),
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 4d2b53b265..65a112c966 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -29,7 +29,7 @@
manpage/1, otp_6708/1, otp_7084/1, otp_7421/1,
io_lib_collect_line_3_wb/1, cr_whitespace_in_string/1,
io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1,
- io_lib_print_binary_depth_one/1, otp_10302/1]).
+ io_lib_print_binary_depth_one/1, otp_10302/1, otp_10836/1]).
%-define(debug, true).
@@ -65,7 +65,7 @@ all() ->
manpage, otp_6708, otp_7084, otp_7421,
io_lib_collect_line_3_wb, cr_whitespace_in_string,
io_fread_newlines, otp_8989, io_lib_fread_literal,
- io_lib_print_binary_depth_one, otp_10302].
+ io_lib_print_binary_depth_one, otp_10302, otp_10836].
groups() ->
[].
@@ -2049,6 +2049,8 @@ otp_10302(Suite) when is_list(Suite) ->
"<<\"apel\"...>>" = pretty(<<"apelsin">>, 2),
"<<228,112,112,108>>" = fmt("~tp", [<<"äppl">>]),
"<<228,...>>" = fmt("~tP", [<<"äppl">>, 2]),
+ "<<0,0,0,0,0,0,1,0>>" = fmt("~p", [<<256:64/unsigned-integer>>]),
+ "<<0,0,0,0,0,0,1,0>>" = fmt("~tp", [<<256:64/unsigned-integer>>]),
Chars = lists:seq(0, 512), % just a few...
[] = [C || C <- Chars, S <- io_lib:write_char_as_latin1(C),
@@ -2076,3 +2078,10 @@ pretty(Term, Opts) when is_list(Opts) ->
is_latin1(S) ->
S >= 0 andalso S =< 255.
+
+otp_10836(doc) ->
+ "OTP-10836. ~ts extended to latin1";
+otp_10836(Suite) when is_list(Suite) ->
+ S = io_lib:format("~ts", [[<<"äpple"/utf8>>, <<"äpple">>]]),
+ "äppleäpple" = lists:flatten(S),
+ ok.
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 33d7a57cc3..c1467697e3 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 1.19
+STDLIB_VSN = 1.19.1