aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/doc/src/filelib.xml5
-rw-r--r--lib/stdlib/doc/src/io.xml12
-rw-r--r--lib/stdlib/doc/src/io_lib.xml14
-rw-r--r--lib/stdlib/src/binary.erl2
-rw-r--r--lib/stdlib/src/erl_pp.erl18
-rw-r--r--lib/stdlib/src/io.erl7
-rw-r--r--lib/stdlib/src/io_lib.erl48
-rw-r--r--lib/stdlib/src/io_lib_pretty.erl55
-rw-r--r--lib/stdlib/src/shell.erl27
-rw-r--r--lib/stdlib/test/epp_SUITE.erl33
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl40
-rw-r--r--lib/stdlib/test/escript_SUITE.erl2
-rwxr-xr-xlib/stdlib/test/escript_SUITE_data/unicode12
-rw-r--r--lib/stdlib/test/io_SUITE.erl101
-rw-r--r--lib/stdlib/test/io_proto_SUITE.erl6
-rw-r--r--lib/stdlib/test/shell_SUITE.erl32
16 files changed, 310 insertions, 94 deletions
diff --git a/lib/stdlib/doc/src/filelib.xml b/lib/stdlib/doc/src/filelib.xml
index ac67596f3c..bd780b2b2f 100644
--- a/lib/stdlib/doc/src/filelib.xml
+++ b/lib/stdlib/doc/src/filelib.xml
@@ -36,8 +36,9 @@
<description>
<p>This module contains utilities on a higher level than the <c>file</c>
module.</p>
- <p>The module supports Unicode file names, so that it will match against regular expressions given in Unicode and that it will find and process raw file names (i.e. files named in a way that does not confirm to the expected encoding).</p>
- <p>If the VM operates in Unicode file naming mode on a machine with transparent file naming, the <c>fun()</c> provided to <c>fold_files/5</c> needs to be prepared to handle binary file names.</p>
+ <p>This module does not support "raw" file names (i.e. files whose names
+ do not comply with the expected encoding). Such files will be ignored
+ by the functions in this module.</p>
<p>For more information about raw file names, see the <seealso marker="kernel:file">file</seealso> module.</p>
</description>
diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml
index 63f814ad2e..90f24c4cbc 100644
--- a/lib/stdlib/doc/src/io.xml
+++ b/lib/stdlib/doc/src/io.xml
@@ -211,6 +211,18 @@
</desc>
</func>
<func>
+ <name name="printable_range" arity="0"/>
+ <fsummary>Get user requested printable character range</fsummary>
+ <desc>
+ <p>Return the user requested range of printable Unicode characters.</p>
+ <p>The user can request a range of characters that are to be considered printable in heuristic detection of strings by the shell and by the formatting functions. This is done by supplying <c>+pc &lt;range&gt;</c> when starting Erlang.</p>
+ <p>Currently the only valid values for <c>&lt;range&gt;</c> are <c>latin1</c> and <c>unicode</c>. <c>latin1</c> means that only code points below 256 (with the exception of control characters etc) will be considered printable. <c>unicode</c> means that all printable characters in all unicode character ranges are considered printable by the io functions.</p>
+ <p>By default, Erlang is started so that only the <c>latin1</c> range of characters will indicate that a list of integers is a string.</p>
+ <p>The simplest way to utilize the setting is to call <seealso marker="io_lib#printable_list/1">io_lib:printable_list/1</seealso>, which will use the return value of this function to decide if a list is a string of printable characters or not.</p>
+ <note><p>In the future, this function may return more values and ranges. It is recommended to use the io_lib:printable_list/1 function to avoid compatibility problems.</p></note>
+ </desc>
+ </func>
+ <func>
<name name="setopts" arity="1"/>
<name name="setopts" arity="2"/>
<fsummary>Set options</fsummary>
diff --git a/lib/stdlib/doc/src/io_lib.xml b/lib/stdlib/doc/src/io_lib.xml
index 001d34a7c2..3dac259477 100644
--- a/lib/stdlib/doc/src/io_lib.xml
+++ b/lib/stdlib/doc/src/io_lib.xml
@@ -301,7 +301,11 @@
<fsummary>Test for a list of printable characters</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
- printable Unicode characters, otherwise it returns <c>false</c>.</p>
+ printable characters, otherwise it returns <c>false</c>.</p>
+ <p>What is a printable character in this case is determined by the
+ <c>+pc</c> start up flag to the Erlang VM. See
+ <seealso marker="io#printable_range/0">io:printable_range/0</seealso>
+ and <seealso marker="erts:erl#erl">erl(1)</seealso>.</p>
</desc>
</func>
<func>
@@ -312,6 +316,14 @@
printable ISO-latin-1 characters, otherwise it returns <c>false</c>.</p>
</desc>
</func>
+ <func>
+ <name name="printable_unicode_list" arity="1"/>
+ <fsummary>Test for a list of printable Unicode characters</fsummary>
+ <desc>
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a flat list of
+ printable Unicode characters, otherwise it returns <c>false</c>.</p>
+ </desc>
+ </func>
</funcs>
</erlref>
diff --git a/lib/stdlib/src/binary.erl b/lib/stdlib/src/binary.erl
index de18b6cd54..1fb241fd1d 100644
--- a/lib/stdlib/src/binary.erl
+++ b/lib/stdlib/src/binary.erl
@@ -58,7 +58,7 @@ bin_to_list(_, _) ->
-spec bin_to_list(Subject, Pos, Len) -> [byte()] when
Subject :: binary(),
Pos :: non_neg_integer(),
- Len :: non_neg_integer().
+ Len :: integer().
bin_to_list(_, _, _) ->
erlang:nif_error(undef).
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 06dae51cc9..7c7566e4ec 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -42,7 +42,7 @@
| {encoding, latin1 | unicode | utf8}).
-type(options() :: hook_function() | [option()]).
--record(pp, {string_fun, char_fun, term_fun}).
+-record(pp, {string_fun, char_fun}).
-record(options, {hook, encoding, opts}).
@@ -182,13 +182,11 @@ state(_Hook) ->
state() ->
#pp{string_fun = fun io_lib:write_string_as_latin1/1,
- char_fun = fun io_lib:write_char_as_latin1/1,
- term_fun = fun(T) -> io_lib:format("~p", [T]) end}.
+ char_fun = fun io_lib:write_char_as_latin1/1}.
unicode_state() ->
#pp{string_fun = fun io_lib:write_string/1,
- char_fun = fun io_lib:write_char/1,
- term_fun = fun(T) -> io_lib:format("~tp", [T]) end}.
+ char_fun = fun io_lib:write_char/1}.
encoding(Options) ->
case proplists:get_value(encoding, Options, epp:default_encoding()) of
@@ -204,10 +202,10 @@ lform({function,Line,Name,Arity,Clauses}, Opts, _State) ->
lform({rule,Line,Name,Arity,Clauses}, Opts, _State) ->
lrule({rule,Line,Name,Arity,Clauses}, Opts);
%% These are specials to make it easier for the compiler.
-lform({error,E}, _Opts, State) ->
- leaf((State#pp.term_fun)({error,E})++"\n");
-lform({warning,W}, _Opts, State) ->
- leaf((State#pp.term_fun)({warning,W})++"\n");
+lform({error,E}, _Opts, _State) ->
+ leaf(format("~p\n", [{error,E}]));
+lform({warning,W}, _Opts, _State) ->
+ leaf(format("~p\n", [{warning,W}]));
lform({eof,_Line}, _Opts, _State) ->
$\n.
@@ -233,7 +231,7 @@ lattribute(import, Name, _Opts, _State) when is_list(Name) ->
lattribute(import, {From,Falist}, _Opts, _State) ->
attr("import",[{var,0,pname(From)},falist(Falist)]);
lattribute(file, {Name,Line}, _Opts, State) ->
- attr("file", [{var,0,(State#pp.term_fun)(Name)},{integer,0,Line}]);
+ attr("file", [{var,0,(State#pp.string_fun)(Name)},{integer,0,Line}]);
lattribute(record, {Name,Is}, Opts, _State) ->
Nl = leaf(format("-record(~w,", [Name])),
[{first,Nl,record_fields(Is, Opts)},$)];
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index 3dddb0d6e7..c92e9e3ade 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -32,6 +32,8 @@
parse_erl_exprs/4,parse_erl_form/1,parse_erl_form/2,
parse_erl_form/3,parse_erl_form/4]).
-export([request/1,request/2,requests/1,requests/2]).
+%% Implemented in native code
+-export([printable_range/0]).
-export_type([device/0, format/0, server_no_data/0]).
@@ -66,6 +68,11 @@ o_request(Io, Request, Func) ->
Other
end.
+%% Request what the user considers printable characters
+-spec printable_range() -> 'unicode' | 'latin1'.
+printable_range() ->
+ erlang:nif_error(undefined).
+
%% Put chars takes mixed *unicode* list from R13 onwards.
-spec put_chars(CharData) -> 'ok' when
CharData :: unicode:chardata().
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index b7ec848e1e..a9b6d4131e 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -72,7 +72,7 @@
-export([quote_atom/2, char_list/1, latin1_char_list/1,
deep_char_list/1, deep_latin1_char_list/1,
- printable_list/1, printable_latin1_list/1]).
+ printable_list/1, printable_latin1_list/1, printable_unicode_list/1]).
%% Utilities for collecting characters.
-export([collect_chars/3, collect_chars/4,
@@ -533,27 +533,45 @@ printable_latin1_list(_) -> false. %Everything else is false
%% Return true if CharList is a list of printable characters, else
%% false. The notion of printable in Unicode terms is somewhat floating.
%% Everything that is not a control character and not invalid unicode
-%% will be considered printable.
+%% will be considered printable.
+%% What the user has noted as printable characters is what actually
+%% specifies when this function will return true. If the VM is started
+%% with +pc latin1, only the latin1 range will be deemed as printable
+%% if on the other hand +pc unicode is given, all characters in the Unicode
+%% character set are deemed printable. latin1 is default.
-spec printable_list(Term) -> boolean() when
Term :: term().
-printable_list([C|Cs]) when is_integer(C), C >= $\040, C =< $\176 ->
- printable_list(Cs);
-printable_list([C|Cs])
+printable_list(L) ->
+ %% There will be more alternatives returns from io:printable range
+ %% in the future. To not have a catch-all clause is deliberate.
+ case io:printable_range() of
+ latin1 ->
+ printable_latin1_list(L);
+ unicode ->
+ printable_unicode_list(L)
+ end.
+
+-spec printable_unicode_list(Term) -> boolean() when
+ Term :: term().
+
+printable_unicode_list([C|Cs]) when is_integer(C), C >= $\040, C =< $\176 ->
+ printable_unicode_list(Cs);
+printable_unicode_list([C|Cs])
when is_integer(C), C >= 16#A0, C < 16#D800;
is_integer(C), C > 16#DFFF, C < 16#FFFE;
is_integer(C), C > 16#FFFF, C =< 16#10FFFF ->
- printable_list(Cs);
-printable_list([$\n|Cs]) -> printable_list(Cs);
-printable_list([$\r|Cs]) -> printable_list(Cs);
-printable_list([$\t|Cs]) -> printable_list(Cs);
-printable_list([$\v|Cs]) -> printable_list(Cs);
-printable_list([$\b|Cs]) -> printable_list(Cs);
-printable_list([$\f|Cs]) -> printable_list(Cs);
-printable_list([$\e|Cs]) -> printable_list(Cs);
-printable_list([]) -> true;
-printable_list(_) -> false. %Everything else is false
+ printable_unicode_list(Cs);
+printable_unicode_list([$\n|Cs]) -> printable_unicode_list(Cs);
+printable_unicode_list([$\r|Cs]) -> printable_unicode_list(Cs);
+printable_unicode_list([$\t|Cs]) -> printable_unicode_list(Cs);
+printable_unicode_list([$\v|Cs]) -> printable_unicode_list(Cs);
+printable_unicode_list([$\b|Cs]) -> printable_unicode_list(Cs);
+printable_unicode_list([$\f|Cs]) -> printable_unicode_list(Cs);
+printable_unicode_list([$\e|Cs]) -> printable_unicode_list(Cs);
+printable_unicode_list([]) -> true;
+printable_unicode_list(_) -> false. %Everything else is false
%% List = nl()
%% Return a list of characters to generate a newline.
diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl
index 525b534249..7637ad7a3d 100644
--- a/lib/stdlib/src/io_lib_pretty.erl
+++ b/lib/stdlib/src/io_lib_pretty.erl
@@ -485,13 +485,18 @@ printable_bin(Bin, Len, D, latin1) ->
false
end;
printable_bin(Bin, Len, D, _Uni) ->
- case printable_unicode(Bin, Len, []) of
- {_, <<>>, L} ->
- {byte_size(Bin) =:= length(L), L};
- {NC, Bin1, L} when D > 0, Len - NC >= D ->
- {byte_size(Bin)-byte_size(Bin1) =:= length(L), true, L};
- {_NC, _Bin, _L} ->
- false
+ case valid_utf8(Bin,Len) of
+ true ->
+ case printable_unicode(Bin, Len, [], io:printable_range()) of
+ {_, <<>>, L} ->
+ {byte_size(Bin) =:= length(L), L};
+ {NC, Bin1, L} when D > 0, Len - NC >= D ->
+ {byte_size(Bin)-byte_size(Bin1) =:= length(L), true, L};
+ {_NC, _Bin, _L} ->
+ false
+ end;
+ false ->
+ printable_bin(Bin, Len, D, latin1)
end.
printable_bin1(_Bin, _Start, 0) ->
@@ -522,24 +527,36 @@ 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
+valid_utf8(<<>>,_) ->
+ true;
+valid_utf8(_,0) ->
+ true;
+valid_utf8(<<_/utf8, R/binary>>,N) ->
+ valid_utf8(R,N-1);
+valid_utf8(_,_) ->
+ false.
+
+printable_unicode(<<C/utf8, R/binary>>=Bin, I, L, Range) when I > 0 ->
+ case printable_char(C,Range) of
true ->
- printable_unicode(R, I - 1, [C | L]);
+ printable_unicode(R, I - 1, [C | L],Range);
false ->
{I, Bin, lists:reverse(L)}
end;
-printable_unicode(Bin, I, L) ->
+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) ->
+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,latin1) ->
+ C >= $\s andalso C =< $~ orelse
+ C >= 16#A0 andalso C =< 16#FF;
+printable_char(C,unicode) ->
C >= $\s andalso C =< $~ orelse
C >= 16#A0 andalso C < 16#D800 orelse
C > 16#DFFF andalso C < 16#FFFE orelse
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index df66acb97b..96f3e5dd32 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -129,7 +129,7 @@ start_restricted(RShMod) when is_atom(RShMod) ->
error_logger:error_report(
lists:flatten(
io_lib:fwrite(
- "Restricted shell module ~w not found: ~"++cs_p() ++"\n",
+ "Restricted shell module ~w not found: ~tp\n",
[RShMod,What]))),
Error
end.
@@ -214,8 +214,7 @@ server(StartSync) ->
ok;
{RShMod2,What2} ->
io:fwrite(
- ("Warning! Restricted shell module ~w not found: ~"
- ++cs_p()++".\n"
+ ("Warning! Restricted shell module ~w not found: ~tp.\n"
"Only the commands q() and init:stop() will be allowed!\n"),
[RShMod2,What2]),
application:set_env(stdlib, restricted_shell, ?MODULE)
@@ -337,7 +336,7 @@ get_prompt_func() ->
end.
bad_prompt_func(M) ->
- fwrite_severity(benign, "Bad prompt function: ~"++cs_p(), [M]).
+ fwrite_severity(benign, "Bad prompt function: ~tp", [M]).
default_prompt(N) ->
%% Don't bother flattening the list irrespective of what the
@@ -1380,27 +1379,18 @@ pp(V, I, RT, Enc) ->
{record_print_fun, record_print_fun(RT)}]
++ Enc)).
-%% Control sequence 'p' possibly with Unicode translation modifier
-cs_p() ->
- case encoding() of
- latin1 -> "p";
- unicode -> "tp"
- end.
-
columns() ->
case io:columns() of
{ok,N} -> N;
_ -> 80
end.
-
encoding() ->
[{encoding, Encoding}] = enc(),
Encoding.
-
enc() ->
case lists:keyfind(encoding, 1, io:getopts()) of
- false -> [{encoding,latin1}]; % should never happen
- Enc -> [Enc]
+ false -> [{encoding,latin1}]; % should never happen
+ Enc -> [Enc]
end.
garb(Shell) ->
@@ -1424,10 +1414,9 @@ check_env(V) ->
{ok, Val} when is_integer(Val), Val >= 0 ->
ok;
{ok, Val} ->
- Txt = io_lib:fwrite(
- ("Invalid value of STDLIB configuration parameter ~w: ~"
- ++cs_p()++"\n"),
- [V, Val]),
+ Txt = io_lib:fwrite
+ ("Invalid value of STDLIB configuration parameter"
+ "~w: ~tp\n", [V, Val]),
error_logger:info_report(lists:flatten(Txt))
end.
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 041d521514..b2f1aa955a 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -25,7 +25,7 @@
variable_1/1, otp_4870/1, otp_4871/1, otp_5362/1,
pmod/1, not_circular/1, skip_header/1, otp_6277/1, otp_7702/1,
otp_8130/1, overload_mac/1, otp_8388/1, otp_8470/1, otp_8503/1,
- otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1]).
+ otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1]).
-export([epp_parse_erl_form/2]).
@@ -67,7 +67,7 @@ all() ->
{group, variable}, otp_4870, otp_4871, otp_5362, pmod,
not_circular, skip_header, otp_6277, otp_7702, otp_8130,
overload_mac, otp_8388, otp_8470, otp_8503, otp_8562,
- otp_8665, otp_8911, otp_10302].
+ otp_8665, otp_8911, otp_10302, otp_10820].
groups() ->
[{upcase_mac, [], [upcase_mac_1, upcase_mac_2]},
@@ -1359,6 +1359,30 @@ encoding_nocom(Enc, File) ->
ok = file:close(Fd),
E = epp:read_encoding(File, Options).
+otp_10820(doc) ->
+ "OTP-10820. Unicode filenames.";
+otp_10820(suite) ->
+ [];
+otp_10820(Config) when is_list(Config) ->
+ L = [915,953,959,973,957,953,954,959,957,964],
+ Dir = ?config(priv_dir, Config),
+ File = filename:join(Dir, L++".erl"),
+ C1 = <<"%% coding: utf-8\n -module(any).">>,
+ ok = do_otp_10820(File, C1, "+pc latin1"),
+ ok = do_otp_10820(File, C1, "+pc unicode"),
+ C2 = <<"\n-module(any).">>,
+ ok = do_otp_10820(File, C2, "+pc latin1"),
+ ok = do_otp_10820(File, C2, "+pc unicode").
+
+do_otp_10820(File, C, PC) ->
+ {ok,Node} = start_node(erl_pp_helper, "+fnu " ++ PC),
+ ok = rpc:call(Node, file, write_file, [File, C]),
+ {ok,[{attribute,1,file,{File,1}},
+ {attribute,2,module,any},
+ {eof,2}]} = rpc:call(Node, epp, parse_file, [File, [],[]]),
+ true = test_server:stop_node(Node),
+ ok.
+
check(Config, Tests) ->
eval_tests(Config, fun check_test/2, Tests).
@@ -1475,3 +1499,8 @@ ln2({error,M}) ->
{error,ln2(M)};
ln2(M) ->
M.
+
+%% +fnu means a peer node has to be started; slave will not do
+start_node(Name, Xargs) ->
+ ?line PA = filename:dirname(code:which(?MODULE)),
+ test_server:start_node(Name, peer, [{args, "-pa " ++ PA ++ " " ++ Xargs}]).
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 37be61d665..9c0a43abcc 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-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
@@ -49,7 +49,7 @@
otp_6321/1, otp_6911/1, otp_6914/1, otp_8150/1, otp_8238/1,
otp_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1,
- otp_10302/1]).
+ otp_10302/1, otp_10820/1]).
%% Internal export.
-export([ehook/6]).
@@ -80,7 +80,8 @@ groups() ->
{attributes, [], [misc_attrs, import_export]},
{tickets, [],
[otp_6321, otp_6911, otp_6914, otp_8150, otp_8238,
- otp_8473, otp_8522, otp_8567, otp_8664, otp_9147, otp_10302]}].
+ otp_8473, otp_8522, otp_8567, otp_8664, otp_9147,
+ otp_10302, otp_10820]}].
init_per_suite(Config) ->
Config.
@@ -1074,6 +1075,34 @@ otp_10302(Config) when is_list(Config) ->
unicode_hook({foo,E}, I, P, H) ->
erl_pp:expr({call,0,{atom,0,foo},[E]}, I, P, H).
+otp_10820(doc) ->
+ "OTP-10820. Unicode filenames.";
+otp_10820(suite) -> [];
+otp_10820(Config) when is_list(Config) ->
+ C1 = <<"%% coding: utf-8\n -module(any).">>,
+ ok = do_otp_10820(Config, C1, "+pc latin1"),
+ ok = do_otp_10820(Config, C1, "+pc unicode"),
+ C2 = <<"-module(any).">>,
+ ok = do_otp_10820(Config, C2, "+pc latin1"),
+ ok = do_otp_10820(Config, C2, "+pc unicode").
+
+do_otp_10820(Config, C, PC) ->
+ {ok,Node} = start_node(erl_pp_helper, "+fnu " ++ PC),
+ L = [915,953,959,973,957,953,954,959,957,964],
+ FileName = filename(L++".erl", Config),
+ ok = rpc:call(Node, file, write_file, [FileName, C]),
+ {ok, _, []} = rpc:call(Node, compile, file,
+ [FileName, [return,'P',{outdir,?privdir}]]),
+ PFileName = filename(L++".P", Config),
+ {ok, Bin} = rpc:call(Node, file, read_file, [PFileName]),
+ true = test_server:stop_node(Node),
+ true = file_attr_is_string(binary_to_list(Bin)),
+ ok.
+
+file_attr_is_string("-file(\"" ++ _) -> true;
+file_attr_is_string([_ | L]) ->
+ file_attr_is_string(L).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
compile(Config, Tests) ->
@@ -1247,3 +1276,8 @@ filename(Name, Config) ->
fail() ->
io:format("failed~n"),
?t:fail().
+
+%% +fnu means a peer node has to be started; slave will not do
+start_node(Name, Xargs) ->
+ ?line PA = filename:dirname(code:which(?MODULE)),
+ test_server:start_node(Name, peer, [{args, "-pa " ++ PA ++ " " ++ Xargs}]).
diff --git a/lib/stdlib/test/escript_SUITE.erl b/lib/stdlib/test/escript_SUITE.erl
index be8fb1b37a..cf5fb12686 100644
--- a/lib/stdlib/test/escript_SUITE.erl
+++ b/lib/stdlib/test/escript_SUITE.erl
@@ -913,7 +913,7 @@ unicode(Config) when is_list(Config) ->
run(Dir, "unicode1",
[<<"escript: exception error: an error occurred when evaluating"
" an arithmetic expression\n in operator '/'/2\n "
- "called as <<170>> / <<170>>\nExitCode:127">>]),
+ "called as <<224,170,170>> / <<224,170,170>>\nExitCode:127">>]),
run(Dir, "unicode2",
[<<"escript: exception error: an error occurred when evaluating"
" an arithmetic expression\n in operator '/'/2\n "
diff --git a/lib/stdlib/test/escript_SUITE_data/unicode1 b/lib/stdlib/test/escript_SUITE_data/unicode1
index a77574625e..351bb785e5 100755
--- a/lib/stdlib/test/escript_SUITE_data/unicode1
+++ b/lib/stdlib/test/escript_SUITE_data/unicode1
@@ -6,7 +6,7 @@
main(_) ->
ok = io:setopts([{encoding,unicode}]),
_D = erlang:system_flag(backtrace_depth, 0),
- A = <<"\x{aa}">>,
+ A = <<"\x{aaa}"/utf8>>,
S = lists:flatten(io_lib:format("~p/~p.", [A, A])),
{ok, Ts, _} = erl_scan:string(S, 1, [unicode]),
{ok, Es} = erl_parse:parse_exprs(Ts),
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index aa698ecaa2..9f828c6d2d 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -29,9 +29,12 @@
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,
+ printable_range/1,
io_lib_print_binary_depth_one/1, otp_10302/1, otp_10755/1,
otp_10836/1]).
+-export([pretty/2]).
+
%-define(debug, true).
-ifdef(debug).
@@ -66,6 +69,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,
+ printable_range,
io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836].
groups() ->
@@ -2026,6 +2030,79 @@ io_lib_fread_literal(Suite) when is_list(Suite) ->
?line {done,{ok,[]},[]} = io_lib:fread(C2, "d\n", " d"),
ok.
+
+printable_range(doc) ->
+ "Check that the printable range set by the user actually works";
+printable_range(Suite) when is_list(Suite) ->
+ Pa = filename:dirname(code:which(?MODULE)),
+ {ok, UNode} = test_server:start_node(printable_range_unicode, slave,
+ [{args, " +pc unicode -pa " ++ Pa}]),
+ {ok, LNode} = test_server:start_node(printable_range_latin1, slave,
+ [{args, " +pc latin1 -pa " ++ Pa}]),
+ {ok, DNode} = test_server:start_node(printable_range_default, slave,
+ [{args, " -pa " ++ Pa}]),
+ unicode = rpc:call(UNode,io,printable_range,[]),
+ latin1 = rpc:call(LNode,io,printable_range,[]),
+ latin1 = rpc:call(DNode,io,printable_range,[]),
+ test_server:stop_node(UNode),
+ test_server:stop_node(LNode),
+ {ok, UNode} = test_server:start_node(printable_range_unicode, slave,
+ [{args, " +pcunicode -pa " ++ Pa}]),
+ {ok, LNode} = test_server:start_node(printable_range_latin1, slave,
+ [{args, " +pclatin1 -pa " ++ Pa}]),
+ unicode = rpc:call(UNode,io,printable_range,[]),
+ latin1 = rpc:call(LNode,io,printable_range,[]),
+ {error, _} = test_server:start_node(printable_range_unnicode, slave,
+ [{args, " +pcunnicode -pa " ++ Pa}]),
+ PrettyOptions = [{column,1},
+ {line_length,109},
+ {depth,30},
+ {max_chars,60},
+ {record_print_fun,
+ fun(_,_) -> no end},
+ {encoding,unicode}],
+ 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib_pretty,print,
+ [{hello, [1024,1025]},
+ PrettyOptions]))),
+ 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib_pretty,print,
+ [{hello, [1024,1025]},
+ PrettyOptions]))),
+ 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib_pretty,print,
+ [{hello, [1024,1025]},
+ PrettyOptions]))),
+ 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib_pretty,print,
+ [{hello, <<1024/utf8,1025/utf8>>},
+ PrettyOptions]))),
+ 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib_pretty,print,
+ [{hello, <<1024/utf8,1025/utf8>>},
+ PrettyOptions]))),
+ 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib_pretty,print,
+ [{hello, <<1024/utf8,1025/utf8>>},
+ PrettyOptions]))),
+
+ 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib,format,
+ ["~tp",[{hello, [1024,1025]}]]))),
+ 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib,format,
+ ["~tp",[{hello, [1024,1025]}]]))),
+ 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib,format,
+ ["~tp",[{hello, [1024,1025]}]]))),
+ 1025 = lists:max(lists:flatten(rpc:call(UNode,io_lib,format,
+ ["~tp",
+ [{hello,
+ <<1024/utf8,1025/utf8>>}]]))),
+ 125 = lists:max(lists:flatten(rpc:call(LNode,io_lib,format,
+ ["~tp",
+ [{hello,
+ <<1024/utf8,1025/utf8>>}]]))),
+ 125 = lists:max(lists:flatten(rpc:call(DNode,io_lib,format,
+ ["~tp",
+ [{hello,
+ <<1024/utf8,1025/utf8>>}]]))),
+ test_server:stop_node(UNode),
+ test_server:stop_node(LNode),
+ test_server:stop_node(DNode),
+ ok.
+
io_lib_print_binary_depth_one(doc) ->
"Test binaries printed with a depth of one behave correctly";
io_lib_print_binary_depth_one(Suite) when is_list(Suite) ->
@@ -2040,16 +2117,30 @@ io_lib_print_binary_depth_one(Suite) when is_list(Suite) ->
otp_10302(doc) ->
"OTP-10302. Unicode";
otp_10302(Suite) when is_list(Suite) ->
- "\"\x{400}\"" = pretty("\x{400}", -1),
- "<<\"\x{400}\"/utf8>>" = pretty(<<"\x{400}"/utf8>>, -1),
+ Pa = filename:dirname(code:which(?MODULE)),
+ {ok, UNode} = test_server:start_node(printable_range_unicode, slave,
+ [{args, " +pc unicode -pa " ++ Pa}]),
+ {ok, LNode} = test_server:start_node(printable_range_latin1, slave,
+ [{args, " +pc latin1 -pa " ++ Pa}]),
+ "\"\x{400}\"" = rpc:call(UNode,?MODULE,pretty,["\x{400}", -1]),
+ "<<\"\x{400}\"/utf8>>" = rpc:call(UNode,?MODULE,pretty,
+ [<<"\x{400}"/utf8>>, -1]),
+
+ "<<\"\x{400}foo\"/utf8>>" = rpc:call(UNode,?MODULE,pretty,
+ [<<"\x{400}foo"/utf8>>, 2]),
+ "[1024]" = rpc:call(LNode,?MODULE,pretty,["\x{400}", -1]),
+ "<<208,128>>" = rpc:call(LNode,?MODULE,pretty,[<<"\x{400}"/utf8>>, -1]),
+
+ "<<208,...>>" = rpc:call(LNode,?MODULE,pretty,[<<"\x{400}foo"/utf8>>, 2]),
+ test_server:stop_node(UNode),
+ test_server:stop_node(LNode),
- "<<\"\x{400}foo\"/utf8>>" = pretty(<<"\x{400}foo"/utf8>>, 2),
"<<\"äppl\"/utf8>>" = pretty(<<"äppl"/utf8>>, 2),
"<<\"äppl\"/utf8...>>" = pretty(<<"äpple"/utf8>>, 2),
"<<\"apel\">>" = pretty(<<"apel">>, 2),
"<<\"apel\"...>>" = pretty(<<"apelsin">>, 2),
- "<<228,112,112,108>>" = fmt("~tp", [<<"äppl">>]),
- "<<228,...>>" = fmt("~tP", [<<"äppl">>, 2]),
+ "<<\"äppl\">>" = fmt("~tp", [<<"äppl">>]),
+ "<<\"äppl\"...>>" = fmt("~tP", [<<"äpple">>, 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>>]),
diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl
index 299daf0e42..ddcc8dfdab 100644
--- a/lib/stdlib/test/io_proto_SUITE.erl
+++ b/lib/stdlib/test/io_proto_SUITE.erl
@@ -716,7 +716,7 @@ binary_options(Config) when is_list(Config) ->
{getline, "<<\"hej\\n\">>"},
{putline, "io:get_line('')."},
{putline, binary_to_list(<<"\345\344\366"/utf8>>)},
- {getline, "<<\""++binary_to_list(unicode:characters_to_binary(<<"\345\344\366"/utf8>>,latin1,utf8))++"\\n\">>"}
+ {getline, "<<\""++binary_to_list(<<"\345\344\366"/utf8>>)++"\\n\"/utf8>>"}
],[])
end,
%% And one with oldshell
@@ -1784,8 +1784,8 @@ get_default_shell() ->
{putline, "whereis(user_drv)."},
{getline, "undefined"}],[]),
old
- catch E:R ->
- ?dbg({E,R}),
+ catch _E:_R ->
+ ?dbg({_E,_R}),
new
end.
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index f22df96697..990b1f5eb2 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-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
@@ -2742,6 +2742,9 @@ otp_10302(doc) ->
"OTP-10302. Unicode.";
otp_10302(suite) -> [];
otp_10302(Config) when is_list(Config) ->
+ {ok,Node} = start_node(shell_suite_helper_2,
+ "-pa "++?config(priv_dir,Config)++
+ " +pc unicode"),
Test1 =
<<"begin
io:setopts([{encoding,utf8}]),
@@ -2749,13 +2752,13 @@ otp_10302(Config) when is_list(Config) ->
rd(rec, {a = \"\\x{400}\"}),
ok = rl(rec)
end.">>,
- "-record(rec,{a = \"\x{400}\"}).\nok.\n" = t(Test1),
+ "-record(rec,{a = \"\x{400}\"}).\nok.\n" = t({Node,Test1}),
Test3 =
<<"io:setopts([{encoding,utf8}]).
rd(rec, {a = \"\\x{400}\"}).
ok = rp(#rec{}).">>,
- "ok.\nrec\n#rec{a = \"\x{400}\"}.\nok.\n" = t(Test3),
+ "ok.\nrec\n#rec{a = \"\x{400}\"}.\nok.\n" = t({Node,Test3}),
Test4 =
<<"io:setopts([{encoding,utf8}]).
@@ -2766,7 +2769,7 @@ otp_10302(Config) when is_list(Config) ->
"ok.\n\"\x{400}\"\nA = \"\x{400}\".\nok.\n"
"1: io:setopts([{encoding,utf8}])\n-> ok.\n"
"2: A = [1024] = \"\x{400}\"\n-> \"\x{400}\"\n"
- "3: b()\n-> ok.\nok.\n" = t(Test4),
+ "3: b()\n-> ok.\nok.\n" = t({Node,Test4}),
Test5 =
<<"begin
@@ -2776,18 +2779,20 @@ otp_10302(Config) when is_list(Config) ->
b(),
h()
end.">>,
- "A = \"\x{400}\".\nok.\n" = t(Test5),
+ "A = \"\x{400}\".\nok.\n" = t({Node,Test5}),
%% One $" is "lost":
true =
"\x{400}\": command not found" =:=
- prompt_err({<<"io:setopts([{encoding,utf8}]). v(\"\x{400}\")."/utf8>>,
+ prompt_err({Node,
+ <<"io:setopts([{encoding,utf8}]). v(\"\x{400}\")."/utf8>>,
unicode}),
"ok.\ndefault\n* Bad prompt function: \"\x{400}\".\n" =
- t({<<"io:setopts([{encoding,utf8}]). "
+ t({Node,<<"io:setopts([{encoding,utf8}]). "
"shell:prompt_func(\"\x{400}\")."/utf8>>,
unicode}),
+ rpc:call(Node,shell, prompt_func, [default]),
_ = shell:prompt_func(default),
%% Test lib:format_exception() (cf. OTP-6554)
@@ -2812,10 +2817,10 @@ otp_10302(Config) when is_list(Config) ->
{ok, Es} = erl_parse:parse_exprs(Ts),
B = erl_eval:new_bindings(),
erl_eval:exprs(Es, B).">>,
-
+
"ok.\n** exception error: an error occurred when evaluating"
" an arithmetic expression\n in operator '/'/2\n"
- " called as <<170>> / <<170>>.\n" = t(Test7),
+ " called as <<\"�\">> / <<\"�\">>.\n" = t({Node,Test7}),
Test8 =
<<"begin
A = [1089],
@@ -2839,7 +2844,7 @@ otp_10302(Config) when is_list(Config) ->
"ok.\n** exception error: an error occurred when evaluating"
" an arithmetic expression\n in operator '/'/2\n"
- " called as \"\x{441}\" / \"\x{441}\".\n" = t(Test9),
+ " called as \"\x{441}\" / \"\x{441}\".\n" = t({Node,Test9}),
Test10 =
<<"A = {\"1\\xaa\",
$\\xaa,
@@ -2861,7 +2866,7 @@ otp_10302(Config) when is_list(Config) ->
"ok.\n** exception error: no function clause matching \n"
" erl_eval:'-inside-an-interpreted-fun-'"
"({\"1\xaa\",170,<<\"hi\">>,\n "
- " <<\"1\xaa\"/utf8>>}) .\n" = t(Test11),
+ " <<\"1\xaa\"/utf8>>}) .\n" = t({Node,Test11}),
Test12 = <<"fun(a, b) -> false end(65, [1089]).">>,
"** exception error: no function clause matching \n"
" erl_eval:'-inside-an-interpreted-fun-'(65,[1089])"
@@ -2871,8 +2876,9 @@ otp_10302(Config) when is_list(Config) ->
fun(a, b) -> false end(65, [1089]).">>,
"ok.\n** exception error: no function clause matching \n"
" erl_eval:'-inside-an-interpreted-fun-'(65,\"\x{441}\")"
- " .\n" = t(Test13),
+ " .\n" = t({Node,Test13}),
+ test_server:stop_node(Node),
ok.
scan(B) ->
@@ -2895,6 +2901,8 @@ scan(S0, F) ->
[]
end.
+t({Node,Bin,Enc}) when is_atom(Node),is_binary(Bin), is_atom(Enc) ->
+ t0({Bin,Enc}, fun() -> start_new_shell(Node) end);
t({Node,Bin}) when is_atom(Node),is_binary(Bin) ->
t0({Bin,latin1}, fun() -> start_new_shell(Node) end);
t(Bin) when is_binary(Bin) ->