aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/doc/src/filelib.xml2
-rw-r--r--lib/stdlib/doc/src/notes.xml138
-rw-r--r--lib/stdlib/doc/src/unicode_usage.xml12
-rw-r--r--lib/stdlib/src/base64.erl113
-rw-r--r--lib/stdlib/src/c.erl52
-rw-r--r--lib/stdlib/src/erl_lint.erl22
-rw-r--r--lib/stdlib/src/erl_posix_msg.erl285
-rw-r--r--lib/stdlib/src/escript.erl4
-rw-r--r--lib/stdlib/src/filename.erl14
-rw-r--r--lib/stdlib/src/io.erl38
-rw-r--r--lib/stdlib/src/re.erl42
-rw-r--r--lib/stdlib/test/base64_SUITE.erl89
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl16
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl22
-rw-r--r--lib/stdlib/test/ets_SUITE.erl18
-rw-r--r--lib/stdlib/vsn.mk2
16 files changed, 580 insertions, 289 deletions
diff --git a/lib/stdlib/doc/src/filelib.xml b/lib/stdlib/doc/src/filelib.xml
index 969aff4fcb..47d64f245c 100644
--- a/lib/stdlib/doc/src/filelib.xml
+++ b/lib/stdlib/doc/src/filelib.xml
@@ -105,7 +105,7 @@ dirname() = filename()</code>
interpreted as Unicode may be encountered, in which case the
<c>fun()</c> must be prepared to handle raw file names
(i.e. binaries). If the regular expression contains
- codepoints beyond 255, it will not match file names that does
+ codepoints beyond 255, it will not match file names that do
not conform to the expected character encoding (i.e. are not
encoded in valid UTF-8).</p>
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 6c618bc798..a8fe41f000 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -30,6 +30,144 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 1.17.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Several type specifications for standard libraries were
+ wrong in the R14B01 release. This is now corrected. The
+ corrections concern types in re,io,filename and the
+ module erlang itself.</p>
+ <p>
+ Own Id: OTP-9008</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 1.17.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> When several clients accessed a Dets table
+ simultaneously, one of them calling
+ <c>dets:insert_new/2</c>, the Dets server could crash.
+ Alternatively, under the same conditions, <c>ok</c> was
+ sometimes returned instead of <c>true</c>. (Thanks to
+ John Hughes.) </p>
+ <p>
+ Own Id: OTP-8856</p>
+ </item>
+ <item>
+ <p> When several clients accessed a Dets table
+ simultaneously, inserted or updated objects were
+ sometimes lost due to the Dets file being truncated.
+ (Thanks to John Hughes.) </p>
+ <p>
+ Own Id: OTP-8898</p>
+ </item>
+ <item>
+ <p> When several clients accessed a Dets table
+ simultaneously, modifications of the Dets server's
+ internal state were sometimes thrown away. The symptoms
+ are diverse: error with reason <c>bad_object</c>;
+ inserted objects not returned by <c>lookup()</c>; et
+ cetera. (Thanks to John Hughes.) </p>
+ <p>
+ Own Id: OTP-8899</p>
+ </item>
+ <item>
+ <p> If a Dets table was closed after calling
+ <c>bchunk/2</c>, <c>match/1,3</c>,
+ <c>match_object/1,3</c>, or <c>select/1,3</c> and then
+ opened again, a subsequent call using the returned
+ continuation would normally return a reply. This bug has
+ fixed; now the call fails with reason <c>badarg</c>. </p>
+ <p>
+ Own Id: OTP-8903</p>
+ </item>
+ <item>
+ <p> Cover did not collect coverage data for files such as
+ Yecc parses containing include directives. The bug has
+ been fixed by modifying <c>epp</c>, the Erlang Code
+ Preprocessor. </p>
+ <p>
+ Own Id: OTP-8911</p>
+ </item>
+ <item>
+ <p> If a Dets table with fewer slots than keys was opened
+ and then closed after just a lookup, the contents were no
+ longer well-formed. This bug has been fixed. (Thanks to
+ Matthew Evans.) </p>
+ <p>
+ Own Id: OTP-8923</p>
+ </item>
+ <item>
+ <p>
+ In a supervisor, when it terminates a child, if that
+ child happens to have exited fractionally early, with
+ normal, the supervisor reports this as an error. This
+ should not be reported as an error.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8938 Aux Id: seq11615 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The documentation filelib:wildcard/1,2 now describes the
+ character set syntax for wildcards.</p>
+ <p>
+ Own Id: OTP-8879 Aux Id: seq11683 </p>
+ </item>
+ <item>
+ <p>Buffer overflows have been prevented in <c>erlc</c>,
+ <c>dialyzer</c>, <c>typer</c>, <c>run_test</c>,
+ <c>heart</c>, <c>escript</c>, and <c>erlexec</c>.</p>
+ (Thanks to Michael Santos.)
+ <p>
+ Own Id: OTP-8892</p>
+ </item>
+ <item>
+ <p>
+ Using a float for the number of copies for
+ <c>string:copies/2</c> resulted in an infinite loop. Now
+ it will fail with an exception instead. (Thanks to
+ Michael Santos.)</p>
+ <p>
+ Own Id: OTP-8915</p>
+ </item>
+ <item>
+ <p>
+ New ETS option <c>compressed</c>, to enable a more
+ compact storage format at the expence of heavier table
+ operations. For test and evaluation, <c>erl +ec</c> can
+ be used to force compression on all ETS tables.</p>
+ <p>
+ Own Id: OTP-8922 Aux Id: seq11658 </p>
+ </item>
+ <item>
+ <p> The default maximum number of slots of a Dets table
+ has been changed as to be equal to the maximum number of
+ slots. (Thanks to Richard Carlsson.) </p>
+ <p>
+ Own Id: OTP-8959</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 1.17.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml
index c02ea3cbcb..416df1f02c 100644
--- a/lib/stdlib/doc/src/unicode_usage.xml
+++ b/lib/stdlib/doc/src/unicode_usage.xml
@@ -173,19 +173,19 @@ Eshell V5.7 (abort with ^G)
<taglist>
<tag>Mandatory Unicode file naming</tag>
<item>
-<p>Windows and, for most common uses, MacOSX enforces Unicode support for file names. All files created in the filesystem has names that can consistently be interpreted. In MacOSX, all file names are retrieved in UTF-8 encoding, while Windows have selected an approach where each system call handling file names has a special Unicode aware variant, giving much the same effect. There are no file names on these systems that are not Unicode file names, why the default behavior of the Erlang VM is to work in &quot;Unicode file name translation mode&quot;, meaning that a file name can be given as a Unicode list and that will be automatically translated to the proper name encoding for the underlying operating and file system.</p>
+<p>Windows and, for most common uses, MacOSX enforces Unicode support for file names. All files created in the filesystem have names that can consistently be interpreted. In MacOSX, all file names are retrieved in UTF-8 encoding, while Windows has selected an approach where each system call handling file names has a special Unicode aware variant, giving much the same effect. There are no file names on these systems that are not Unicode file names, why the default behavior of the Erlang VM is to work in &quot;Unicode file name translation mode&quot;, meaning that a file name can be given as a Unicode list and that will be automatically translated to the proper name encoding for the underlying operating and file system.</p>
<p>Doing i.e. a <c>file:list_dir/1</c> on one of these systems may return Unicode lists with codepoints beyond 255, depending on the content of the actual filesystem.</p>
<p>As the feature is fairly new, you may still stumble upon non core applications that cannot handle being provided with file names containing characters with codepoints larger than 255, but the core Erlang system should have no problems with Unicode file names.</p>
</item>
<tag>Transparent file naming</tag>
<item>
<p>Most Unix operating systems have adopted a simpler approach, namely that Unicode file naming is not enforced, but by convention. Those systems usually use UTF-8 encoding for Unicode file names, but do not enforce it. On such a system, a file name containing characters having codepoints between 128 and 255 may be named either as plain ISO-latin-1 or using UTF-8 encoding. As no consistency is enforced, the Erlang VM can do no consistent translation of all file names. If the VM would automatically select encoding based on heuristics, one could get unexpected behavior on these systems, therefore file names not being encoded in UTF-8 are returned as &quot;raw file names&quot; if Unicode file naming support is turned on.</p>
-<p>A raw file name is not a list, but a binary. Many non core applications still does not handle file names given as binaries, why such raw names are avoided by default. This means that systems having implemented Unicode file naming through transparent file systems and an UTF-8 convention, does not by default have Unicode file naming turned on. Explicitly turning Unicode file name handling on for these types of systems is considered experimental.</p>
+<p>A raw file name is not a list, but a binary. Many non core applications still do not handle file names given as binaries, why such raw names are avoided by default. This means that systems having implemented Unicode file naming through transparent file systems and an UTF-8 convention, do not by default have Unicode file naming turned on. Explicitly turning Unicode file name handling on for these types of systems is considered experimental.</p>
</item>
</taglist>
<p>The Unicode file naming support was introduced with OTP release R14B01. A VM operating in Unicode file mode can work with files having names in any language or character set (as long as it's supported by the underlying OS and file system). The Unicode character list is used to denote file or directory names and if the file system content is listed, you will also be able to get Unicode lists as return value. The support lies in the kernel and stdlib modules, why most applications (that does not explicitly require the file names to be in the ISO-latin-1 range) will benefit from the Unicode support without change.</p>
-<p>On Operating systems with mandatory Unicode file names, this means that you more easily conform to the file names of other (non Erlang) applications, and you can also process file names that, at least on Windows, where completely inaccessible (due to having names that could not be represented in ISO-latin-1). Also you will avoid creating incomprehensible file names on MacOSX as the vfs layer of the OS will accept all your file names as UTF-8 and will not rewrite them.</p>
+<p>On Operating systems with mandatory Unicode file names, this means that you more easily conform to the file names of other (non Erlang) applications, and you can also process file names that, at least on Windows, were completely inaccessible (due to having names that could not be represented in ISO-latin-1). Also you will avoid creating incomprehensible file names on MacOSX as the vfs layer of the OS will accept all your file names as UTF-8 and will not rewrite them.</p>
<p>For most systems, turning on Unicode file name translation is no problem even if it uses transparent file naming. Very few systems have mixed file name encodings. A consistent UTF-8 named system will work perfectly in Unicode file name mode. It is still however considered experimental in R14B01. Unicode file name translation is turned on with the <c>+fnu</c> switch to the <c>erl</c> program. If the VM is started in Unicode file name translation mode, <c>file:native_name_encoding/0</c> will return the atom <c>utf8</c>.</p>
@@ -197,10 +197,10 @@ Eshell V5.7 (abort with ^G)
<section>
<title>Notes about raw file names and automatic file name conversion</title>
-<p>Raw file names is introduced together with Unicode file name support in erts-5.8.2 (OTP R14B01). The reason the &quot;raw file names&quot; is introduced in the system is to be able to consistently represent file names given in different encodings on the same system. Having the VM automatically translate a file name that is not in UTF-8 when to a list of Unicode characters might seem practical, but this would open up for both duplicate file names and other inconsistent behavior. Consider a directory containing a file named &quot;bj�rn&quot; in ISO-latin-1, while the Erlang VM is operating in Unicode file name mode (and therefore expecting UTF-8 file naming). The ISO-latin-1 name is not valid UTF-8 and one could be tempted to think that automatic conversion in for example <c>file:list_dir/1</c> is a good idea. But what would happen if we later tried to open the file and has the name as a Unicode list (magically converted from the ISO-latin-1 file name)? The VM will convert the file name given to UTF-8, as this is the encoding expected. Effectively this means trying to open the file named &lt;&lt;&quot;bj�rn&quot;/utf8&gt;&gt;. This file does not exist, and even if it existed it would not be the same file as the one that was listed. We could even create two files named &quot;bj�rn&quot;, one named in the UTF-8 encoding and one not. If <c>file:list_dir/1</c> would automatically convert the ISO-latin-1 file name to a list, we would get two identical file names as the result. To avoid this, we need to differentiate between file names being properly encoded according to the Unicode file naming convention (i.e. UTF-8) and file names being invalid under the encoding. This is done by representing invalid encoding as &quot;raw&quot; file names, i.e. as binaries.</p>
-<p>The core system of Erlang (kernel and stdlib) accept raw file names except for loadable drivers and executables invoked using <c>open_port({spawn, ...} ...)</c>. <c>open_port({spawn_executable, ...} ...)</c> however does accept them. As mentioned earlier, the arguments given in the option list to <c>open_port({spawn_executable, ...} ...)</c> undergo the same conversion as the file names, meaning that the executable will be provided with arguments in UTF-8 as well. This translation is avoided consistently with how the file names are treated, by giving the argument as a binary.</p>
+<p>Raw file names is introduced together with Unicode file name support in erts-5.8.2 (OTP R14B01). The reason &quot;raw file names&quot; is introduced in the system is to be able to consistently represent file names given in different encodings on the same system. Having the VM automatically translate a file name that is not in UTF-8 to a list of Unicode characters might seem practical, but this would open up for both duplicate file names and other inconsistent behavior. Consider a directory containing a file named &quot;bj�rn&quot; in ISO-latin-1, while the Erlang VM is operating in Unicode file name mode (and therefore expecting UTF-8 file naming). The ISO-latin-1 name is not valid UTF-8 and one could be tempted to think that automatic conversion in for example <c>file:list_dir/1</c> is a good idea. But what would happen if we later tried to open the file and have the name as a Unicode list (magically converted from the ISO-latin-1 file name)? The VM will convert the file name given to UTF-8, as this is the encoding expected. Effectively this means trying to open the file named &lt;&lt;&quot;bj�rn&quot;/utf8&gt;&gt;. This file does not exist, and even if it existed it would not be the same file as the one that was listed. We could even create two files named &quot;bj�rn&quot;, one named in the UTF-8 encoding and one not. If <c>file:list_dir/1</c> would automatically convert the ISO-latin-1 file name to a list, we would get two identical file names as the result. To avoid this, we need to differentiate between file names being properly encoded according to the Unicode file naming convention (i.e. UTF-8) and file names being invalid under the encoding. This is done by representing invalid encoding as &quot;raw&quot; file names, i.e. as binaries.</p>
+<p>The core system of Erlang (kernel and stdlib) accepts raw file names except for loadable drivers and executables invoked using <c>open_port({spawn, ...} ...)</c>. <c>open_port({spawn_executable, ...} ...)</c> however does accept them. As mentioned earlier, the arguments given in the option list to <c>open_port({spawn_executable, ...} ...)</c> undergo the same conversion as the file names, meaning that the executable will be provided with arguments in UTF-8 as well. This translation is avoided consistently with how the file names are treated, by giving the argument as a binary.</p>
<p>To force Unicode file name translation mode on systems where this is not the default is considered experimental in OTP R14B01 due to the raw file names possibly being a new experience to the programmer and that the non core applications of OTP are not tested for compliance with raw file names yet. Unicode file name translation is expected to be default in future releases.</p>
-<p>If working with raw file names, one can still conform to the encoding convention of the Erlang VM by using the <c>file:native_name_encoding/0</c> function, which returns either the atom <c>latin1</c> or the atom <c>utf8</c> depending on the file name translation mode. On Linux, an VM started without explicitly stating the file name translation mode will default to <c>latin1</c> as the native file name encoding, why file names on the disk encoded as UTF-8 will be returned as a list of the names interpreted as ISO-latin-1. The &quot;UTF-8 list&quot; is not a practical type for displaying or operating on in Erlang, but it is backward compatible and usable in all functions requiring a file name. On Windows and MacOSX, the default behavior is that of file name translation, why the <c>file:native_name_encoding/0</c> by default returns <c>utf8</c> on those systems (the fact that Windows actually does not use UTF-8 on the file system level can safely be ignored by the Erlang programmer). The default behavior can be changed using the <c>+fnu</c> or <c>+fnl</c> options to the VM, see the <c>erl</c> command manual page.</p>
+<p>If working with raw file names, one can still conform to the encoding convention of the Erlang VM by using the <c>file:native_name_encoding/0</c> function, which returns either the atom <c>latin1</c> or the atom <c>utf8</c> depending on the file name translation mode. On Linux, a VM started without explicitly stating the file name translation mode will default to <c>latin1</c> as the native file name encoding, why file names on the disk encoded as UTF-8 will be returned as a list of the names interpreted as ISO-latin-1. The &quot;UTF-8 list&quot; is not a practical type for displaying or operating on in Erlang, but it is backward compatible and usable in all functions requiring a file name. On Windows and MacOSX, the default behavior is that of file name translation, why the <c>file:native_name_encoding/0</c> by default returns <c>utf8</c> on those systems (the fact that Windows actually does not use UTF-8 on the file system level can safely be ignored by the Erlang programmer). The default behavior can be changed using the <c>+fnu</c> or <c>+fnl</c> options to the VM, see the <c>erl</c> command manual page.</p>
<p>Even if you are operating without Unicode file naming translation automatically done by the VM, you can access and create files with names in UTF-8 encoding by using raw file names encoded as UTF-8. Enforcing the UTF-8 encoding regardless of the mode the Erlang VM is started in might, in some circumstances be a good idea, as the convention of using UTF-8 file names is spreading.</p>
</section>
<section>
diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl
index ebef998ee1..a14a72ac6d 100644
--- a/lib/stdlib/src/base64.erl
+++ b/lib/stdlib/src/base64.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. 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
@@ -114,7 +114,7 @@ decode(List) when is_list(List) ->
mime_decode(Bin) when is_binary(Bin) ->
mime_decode_binary(<<>>, Bin);
mime_decode(List) when is_list(List) ->
- list_to_binary(mime_decode_l(List)).
+ mime_decode(list_to_binary(List)).
-spec decode_l(string()) -> string().
@@ -125,7 +125,7 @@ decode_l(List) ->
-spec mime_decode_l(string()) -> string().
mime_decode_l(List) ->
- L = strip_illegal(List, []),
+ L = strip_illegal(List, [], 0),
decode(L, []).
%%-------------------------------------------------------------------------
@@ -198,6 +198,9 @@ decode_binary(Result, <<>>) ->
true = is_binary(Result),
Result.
+%% Skipping pad character if not at end of string. Also liberal about
+%% excess padding and skipping of other illegal (non-base64 alphabet)
+%% characters. See section 3.3 of RFC4648
mime_decode_binary(Result, <<0:8,T/bits>>) ->
mime_decode_binary(Result, T);
mime_decode_binary(Result0, <<C:8,T/bits>>) ->
@@ -205,15 +208,27 @@ mime_decode_binary(Result0, <<C:8,T/bits>>) ->
Bits when is_integer(Bits) ->
mime_decode_binary(<<Result0/bits,Bits:6>>, T);
eq ->
- case tail_contains_equal(T) of
- true ->
- Split = byte_size(Result0) - 1,
- <<Result:Split/bytes,_:4>> = Result0,
- Result;
- false ->
- Split = byte_size(Result0) - 1,
- <<Result:Split/bytes,_:2>> = Result0,
- Result
+ case tail_contains_more(T, false) of
+ {<<>>, Eq} ->
+ %% No more valid data.
+ case bit_size(Result0) rem 8 of
+ 0 ->
+ %% '====' is not uncommon.
+ Result0;
+ 4 when Eq ->
+ %% enforce at least one more '=' only ignoring illegals and spacing
+ Split = byte_size(Result0) - 1,
+ <<Result:Split/bytes,_:4>> = Result0,
+ Result;
+ 2 ->
+ %% remove 2 bits
+ Split = byte_size(Result0) - 1,
+ <<Result:Split/bytes,_:2>> = Result0,
+ Result
+ end;
+ {More, _} ->
+ %% More valid data, skip the eq as invalid
+ mime_decode_binary(Result0, More)
end;
_ ->
mime_decode_binary(Result0, T)
@@ -262,31 +277,63 @@ strip_ws(<<$\s,T/binary>>) ->
strip_ws(T);
strip_ws(T) -> T.
-strip_illegal([0|Cs], A) ->
- strip_illegal(Cs, A);
-strip_illegal([C|Cs], A) ->
+%% Skipping pad character if not at end of string. Also liberal about
+%% excess padding and skipping of other illegal (non-base64 alphabet)
+%% characters. See section 3.3 of RFC4648
+strip_illegal([], A, _Cnt) ->
+ A;
+strip_illegal([0|Cs], A, Cnt) ->
+ strip_illegal(Cs, A, Cnt);
+strip_illegal([C|Cs], A, Cnt) ->
case element(C, ?DECODE_MAP) of
- bad -> strip_illegal(Cs, A);
- ws -> strip_illegal(Cs, A);
- eq -> strip_illegal_end(Cs, [$=|A]);
- _ -> strip_illegal(Cs, [C|A])
- end;
-strip_illegal([], A) -> A.
+ bad ->
+ strip_illegal(Cs, A, Cnt);
+ ws ->
+ strip_illegal(Cs, A, Cnt);
+ eq ->
+ case {tail_contains_more(Cs, false), Cnt rem 4} of
+ {{[], _}, 0} ->
+ A; %% Ignore extra =
+ {{[], true}, 2} ->
+ [$=|[$=|A]]; %% 'XX=='
+ {{[], _}, 3} ->
+ [$=|A]; %% 'XXX='
+ {{[H|T], _}, _} ->
+ %% more data, skip equals
+ strip_illegal(T, [H|A], Cnt+1)
+ end;
+ _ ->
+ strip_illegal(Cs, [C|A], Cnt+1)
+ end.
-strip_illegal_end([0|Cs], A) ->
- strip_illegal_end(Cs, A);
-strip_illegal_end([C|Cs], A) ->
+%% Search the tail for more valid data and remember if we saw
+%% another equals along the way.
+tail_contains_more([], Eq) ->
+ {[], Eq};
+tail_contains_more(<<>>, Eq) ->
+ {<<>>, Eq};
+tail_contains_more([C|T]=More, Eq) ->
case element(C, ?DECODE_MAP) of
- bad -> strip_illegal(Cs, A);
- ws -> strip_illegal(Cs, A);
- eq -> [C|A];
- _ -> strip_illegal(Cs, [C|A])
+ bad ->
+ tail_contains_more(T, Eq);
+ ws ->
+ tail_contains_more(T, Eq);
+ eq ->
+ tail_contains_more(T, true);
+ _ ->
+ {More, Eq}
end;
-strip_illegal_end([], A) -> A.
-
-tail_contains_equal(<<$=,_/binary>>) -> true;
-tail_contains_equal(<<_,T/binary>>) -> tail_contains_equal(T);
-tail_contains_equal(<<>>) -> false.
+tail_contains_more(<<C:8,T/bits>> =More, Eq) ->
+ case element(C, ?DECODE_MAP) of
+ bad ->
+ tail_contains_more(T, Eq);
+ ws ->
+ tail_contains_more(T, Eq);
+ eq ->
+ tail_contains_more(T, true);
+ _ ->
+ {More, Eq}
+ end.
%% accessors
b64e(X) ->
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index d04d8f191f..235ea939a8 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. 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
@@ -42,31 +42,31 @@
-spec help() -> 'ok'.
help() ->
- format("bt(Pid) -- stack backtrace for a process\n"
- "c(File) -- compile and load code in <File>\n"
- "cd(Dir) -- change working directory\n"
- "flush() -- flush any messages sent to the shell\n"
- "help() -- help info\n"
- "i() -- information about the system\n"
- "ni() -- information about the networked system\n"
- "i(X,Y,Z) -- information about pid <X,Y,Z>\n"
- "l(Module) -- load or reload module\n"
- "lc([File]) -- compile a list of Erlang modules\n"
- "ls() -- list files in the current directory\n"
- "ls(Dir) -- list files in directory <Dir>\n"
- "m() -- which modules are loaded\n"
- "m(Mod) -- information about module <Mod>\n"
- "memory() -- memory allocation information\n"
- "memory(T) -- memory allocation information of type <T>\n"
- "nc(File) -- compile and load code in <File> on all nodes\n"
- "nl(Module) -- load module on all nodes\n"
- "pid(X,Y,Z) -- convert X,Y,Z to a Pid\n"
- "pwd() -- print working directory\n"
- "q() -- quit - shorthand for init:stop()\n"
- "regs() -- information about registered processes\n"
- "nregs() -- information about all registered processes\n"
- "xm(M) -- cross reference check a module\n"
- "y(File) -- generate a Yecc parser\n").
+ io:put_chars(<<"bt(Pid) -- stack backtrace for a process\n"
+ "c(File) -- compile and load code in <File>\n"
+ "cd(Dir) -- change working directory\n"
+ "flush() -- flush any messages sent to the shell\n"
+ "help() -- help info\n"
+ "i() -- information about the system\n"
+ "ni() -- information about the networked system\n"
+ "i(X,Y,Z) -- information about pid <X,Y,Z>\n"
+ "l(Module) -- load or reload module\n"
+ "lc([File]) -- compile a list of Erlang modules\n"
+ "ls() -- list files in the current directory\n"
+ "ls(Dir) -- list files in directory <Dir>\n"
+ "m() -- which modules are loaded\n"
+ "m(Mod) -- information about module <Mod>\n"
+ "memory() -- memory allocation information\n"
+ "memory(T) -- memory allocation information of type <T>\n"
+ "nc(File) -- compile and load code in <File> on all nodes\n"
+ "nl(Module) -- load module on all nodes\n"
+ "pid(X,Y,Z) -- convert X,Y,Z to a Pid\n"
+ "pwd() -- print working directory\n"
+ "q() -- quit - shorthand for init:stop()\n"
+ "regs() -- information about registered processes\n"
+ "nregs() -- information about all registered processes\n"
+ "xm(M) -- cross reference check a module\n"
+ "y(File) -- generate a Yecc parser\n">>).
%% c(FileName)
%% Compile a file/module.
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 0c2d3db8ec..cfb9f0ca98 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. 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
@@ -60,6 +60,10 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
(_Opt, Def) -> Def
end, Default, Opts).
+%% The maximum number of arguments allowed for a function.
+
+-define(MAX_ARGUMENTS, 255).
+
%% The error and warning info structures, {Line,Module,Descriptor},
%% are kept in their seperate fields in the lint state record together
%% with the name of the file (when a new file is entered, marked by
@@ -226,6 +230,9 @@ 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]);
%% --- patterns and guards ---
format_error(illegal_pattern) -> "illegal pattern";
format_error(illegal_bin_pattern) ->
@@ -1307,13 +1314,18 @@ define_function(Line, Name, Arity, St0) ->
true ->
add_error(Line, {redefine_function,NA}, St1);
false ->
- St2 = St1#lint{defined=gb_sets:add_element(NA, St1#lint.defined)},
- case imported(Name, Arity, St2) of
- {yes,_M} -> add_error(Line, {define_import,NA}, St2);
- no -> St2
+ St2 = function_check_max_args(Line, Arity, St1),
+ St3 = St2#lint{defined=gb_sets:add_element(NA, St2#lint.defined)},
+ case imported(Name, Arity, St3) of
+ {yes,_M} -> add_error(Line, {define_import,NA}, St3);
+ no -> St3
end
end.
+function_check_max_args(Line, Arity, St) when Arity > ?MAX_ARGUMENTS ->
+ add_error(Line, {too_many_arguments,Arity}, St);
+function_check_max_args(_, _, St) -> St.
+
%% clauses([Clause], VarTable, State) -> {VarTable, State}.
clauses(Cs, Vt, St) ->
diff --git a/lib/stdlib/src/erl_posix_msg.erl b/lib/stdlib/src/erl_posix_msg.erl
index fe981b23a7..909cc1d102 100644
--- a/lib/stdlib/src/erl_posix_msg.erl
+++ b/lib/stdlib/src/erl_posix_msg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2010. 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
@@ -24,143 +24,146 @@
-spec message(atom()) -> string().
-message(e2big) -> "argument list too long";
-message(eacces) -> "permission denied";
-message(eaddrinuse) -> "address already in use";
-message(eaddrnotavail) -> "can't assign requested address";
-message(eadv) -> "advertise error";
-message(eafnosupport) -> "address family not supported by protocol family";
-message(eagain) -> "resource temporarily unavailable";
-message(ealign) -> "EALIGN";
-message(ealready) -> "operation already in progress";
-message(ebade) -> "bad exchange descriptor";
-message(ebadf) -> "bad file number";
-message(ebadfd) -> "file descriptor in bad state";
-message(ebadmsg) -> "not a data message";
-message(ebadr) -> "bad request descriptor";
-message(ebadrpc) -> "RPC structure is bad";
-message(ebadrqc) -> "bad request code";
-message(ebadslt) -> "invalid slot";
-message(ebfont) -> "bad font file format";
-message(ebusy) -> "file busy";
-message(echild) -> "no children";
-message(echrng) -> "channel number out of range";
-message(ecomm) -> "communication error on send";
-message(econnaborted) -> "software caused connection abort";
-message(econnrefused) -> "connection refused";
-message(econnreset) -> "connection reset by peer";
-message(edeadlk) -> "resource deadlock avoided";
-message(edeadlock) -> "resource deadlock avoided";
-message(edestaddrreq) -> "destination address required";
-message(edirty) -> "mounting a dirty fs w/o force";
-message(edom) -> "math argument out of range";
-message(edotdot) -> "cross mount point";
-message(edquot) -> "disk quota exceeded";
-message(eduppkg) -> "duplicate package name";
-message(eexist) -> "file already exists";
-message(efault) -> "bad address in system call argument";
-message(efbig) -> "file too large";
-message(ehostdown) -> "host is down";
-message(ehostunreach) -> "host is unreachable";
-message(eidrm) -> "identifier removed";
-message(einit) -> "initialization error";
-message(einprogress) -> "operation now in progress";
-message(eintr) -> "interrupted system call";
-message(einval) -> "invalid argument";
-message(eio) -> "I/O error";
-message(eisconn) -> "socket is already connected";
-message(eisdir) -> "illegal operation on a directory";
-message(eisnam) -> "is a name file";
-message(elbin) -> "ELBIN";
-message(el2hlt) -> "level 2 halted";
-message(el2nsync) -> "level 2 not synchronized";
-message(el3hlt) -> "level 3 halted";
-message(el3rst) -> "level 3 reset";
-message(elibacc) -> "can not access a needed shared library";
-message(elibbad) -> "accessing a corrupted shared library";
-message(elibexec) -> "can not exec a shared library directly";
-message(elibmax) ->
- "attempting to link in more shared libraries than system limit";
-message(elibscn) -> ".lib section in a.out corrupted";
-message(elnrng) -> "link number out of range";
-message(eloop) -> "too many levels of symbolic links";
-message(emfile) -> "too many open files";
-message(emlink) -> "too many links";
-message(emsgsize) -> "message too long";
-message(emultihop) -> "multihop attempted";
-message(enametoolong) -> "file name too long";
-message(enavail) -> "not available";
-message(enet) -> "ENET";
-message(enetdown) -> "network is down";
-message(enetreset) -> "network dropped connection on reset";
-message(enetunreach) -> "network is unreachable";
-message(enfile) -> "file table overflow";
-message(enoano) -> "anode table overflow";
-message(enobufs) -> "no buffer space available";
-message(enocsi) -> "no CSI structure available";
-message(enodata) -> "no data available";
-message(enodev) -> "no such device";
-message(enoent) -> "no such file or directory";
-message(enoexec) -> "exec format error";
-message(enolck) -> "no locks available";
-message(enolink) -> "link has be severed";
-message(enomem) -> "not enough memory";
-message(enomsg) -> "no message of desired type";
-message(enonet) -> "machine is not on the network";
-message(enopkg) -> "package not installed";
-message(enoprotoopt) -> "bad proocol option";
-message(enospc) -> "no space left on device";
-message(enosr) -> "out of stream resources or not a stream device";
-message(enosym) -> "unresolved symbol name";
-message(enosys) -> "function not implemented";
-message(enotblk) -> "block device required";
-message(enotconn) -> "socket is not connected";
-message(enotdir) -> "not a directory";
-message(enotempty) -> "directory not empty";
-message(enotnam) -> "not a name file";
-message(enotsock) -> "socket operation on non-socket";
-message(enotsup) -> "operation not supported";
-message(enotty) -> "inappropriate device for ioctl";
-message(enotuniq) -> "name not unique on network";
-message(enxio) -> "no such device or address";
-message(eopnotsupp) -> "operation not supported on socket";
-message(eperm) -> "not owner";
-message(epfnosupport) -> "protocol family not supported";
-message(epipe) -> "broken pipe";
-message(eproclim) -> "too many processes";
-message(eprocunavail) -> "bad procedure for program";
-message(eprogmismatch) -> "program version wrong";
-message(eprogunavail) -> "RPC program not available";
-message(eproto) -> "protocol error";
-message(eprotonosupport) -> "protocol not suppored";
-message(eprototype) -> "protocol wrong type for socket";
-message(erange) -> "math result unrepresentable";
-message(erefused) -> "EREFUSED";
-message(eremchg) -> "remote address changed";
-message(eremdev) -> "remote device";
-message(eremote) -> "pathname hit remote file system";
-message(eremoteio) -> "remote i/o error";
-message(eremoterelease) -> "EREMOTERELEASE";
-message(erofs) -> "read-only file system";
-message(erpcmismatch) -> "RPC version is wrong";
-message(erremote) -> "object is remote";
-message(eshutdown) -> "can't send after socket shutdown";
-message(esocktnosupport) -> "socket type not supported";
-message(espipe) -> "invalid seek";
-message(esrch) -> "no such process";
-message(esrmnt) -> "srmount error";
-message(estale) -> "stale remote file handle";
-message(esuccess) -> "Error 0";
-message(etime) -> "timer expired";
-message(etimedout) -> "connection timed out";
-message(etoomanyrefs) -> "too many references: can't splice";
-message(etxtbsy) -> "text file or pseudo-device busy";
-message(euclean) -> "structure needs cleaning";
-message(eunatch) -> "protocol driver not attached";
-message(eusers) -> "too many users";
-message(eversion) -> "version mismatch";
-message(ewouldblock) -> "operation would block";
-message(exdev) -> "cross-domain link";
-message(exfull) -> "message tables full";
-message(nxdomain) -> "non-existing domain";
-message(_) -> "unknown POSIX error".
+message(T) ->
+ binary_to_list(message_1(T)).
+
+message_1(e2big) -> <<"argument list too long">>;
+message_1(eacces) -> <<"permission denied">>;
+message_1(eaddrinuse) -> <<"address already in use">>;
+message_1(eaddrnotavail) -> <<"can't assign requested address">>;
+message_1(eadv) -> <<"advertise error">>;
+message_1(eafnosupport) -> <<"address family not supported by protocol family">>;
+message_1(eagain) -> <<"resource temporarily unavailable">>;
+message_1(ealign) -> <<"EALIGN">>;
+message_1(ealready) -> <<"operation already in progress">>;
+message_1(ebade) -> <<"bad exchange descriptor">>;
+message_1(ebadf) -> <<"bad file number">>;
+message_1(ebadfd) -> <<"file descriptor in bad state">>;
+message_1(ebadmsg) -> <<"not a data message">>;
+message_1(ebadr) -> <<"bad request descriptor">>;
+message_1(ebadrpc) -> <<"RPC structure is bad">>;
+message_1(ebadrqc) -> <<"bad request code">>;
+message_1(ebadslt) -> <<"invalid slot">>;
+message_1(ebfont) -> <<"bad font file format">>;
+message_1(ebusy) -> <<"file busy">>;
+message_1(echild) -> <<"no children">>;
+message_1(echrng) -> <<"channel number out of range">>;
+message_1(ecomm) -> <<"communication error on send">>;
+message_1(econnaborted) -> <<"software caused connection abort">>;
+message_1(econnrefused) -> <<"connection refused">>;
+message_1(econnreset) -> <<"connection reset by peer">>;
+message_1(edeadlk) -> <<"resource deadlock avoided">>;
+message_1(edeadlock) -> <<"resource deadlock avoided">>;
+message_1(edestaddrreq) -> <<"destination address required">>;
+message_1(edirty) -> <<"mounting a dirty fs w/o force">>;
+message_1(edom) -> <<"math argument out of range">>;
+message_1(edotdot) -> <<"cross mount point">>;
+message_1(edquot) -> <<"disk quota exceeded">>;
+message_1(eduppkg) -> <<"duplicate package name">>;
+message_1(eexist) -> <<"file already exists">>;
+message_1(efault) -> <<"bad address in system call argument">>;
+message_1(efbig) -> <<"file too large">>;
+message_1(ehostdown) -> <<"host is down">>;
+message_1(ehostunreach) -> <<"host is unreachable">>;
+message_1(eidrm) -> <<"identifier removed">>;
+message_1(einit) -> <<"initialization error">>;
+message_1(einprogress) -> <<"operation now in progress">>;
+message_1(eintr) -> <<"interrupted system call">>;
+message_1(einval) -> <<"invalid argument">>;
+message_1(eio) -> <<"I/O error">>;
+message_1(eisconn) -> <<"socket is already connected">>;
+message_1(eisdir) -> <<"illegal operation on a directory">>;
+message_1(eisnam) -> <<"is a name file">>;
+message_1(elbin) -> <<"ELBIN">>;
+message_1(el2hlt) -> <<"level 2 halted">>;
+message_1(el2nsync) -> <<"level 2 not synchronized">>;
+message_1(el3hlt) -> <<"level 3 halted">>;
+message_1(el3rst) -> <<"level 3 reset">>;
+message_1(elibacc) -> <<"can not access a needed shared library">>;
+message_1(elibbad) -> <<"accessing a corrupted shared library">>;
+message_1(elibexec) -> <<"can not exec a shared library directly">>;
+message_1(elibmax) ->
+ <<"attempting to link in more shared libraries than system limit">>;
+message_1(elibscn) -> <<".lib section in a.out corrupted">>;
+message_1(elnrng) -> <<"link number out of range">>;
+message_1(eloop) -> <<"too many levels of symbolic links">>;
+message_1(emfile) -> <<"too many open files">>;
+message_1(emlink) -> <<"too many links">>;
+message_1(emsgsize) -> <<"message too long">>;
+message_1(emultihop) -> <<"multihop attempted">>;
+message_1(enametoolong) -> <<"file name too long">>;
+message_1(enavail) -> <<"not available">>;
+message_1(enet) -> <<"ENET">>;
+message_1(enetdown) -> <<"network is down">>;
+message_1(enetreset) -> <<"network dropped connection on reset">>;
+message_1(enetunreach) -> <<"network is unreachable">>;
+message_1(enfile) -> <<"file table overflow">>;
+message_1(enoano) -> <<"anode table overflow">>;
+message_1(enobufs) -> <<"no buffer space available">>;
+message_1(enocsi) -> <<"no CSI structure available">>;
+message_1(enodata) -> <<"no data available">>;
+message_1(enodev) -> <<"no such device">>;
+message_1(enoent) -> <<"no such file or directory">>;
+message_1(enoexec) -> <<"exec format error">>;
+message_1(enolck) -> <<"no locks available">>;
+message_1(enolink) -> <<"link has be severed">>;
+message_1(enomem) -> <<"not enough memory">>;
+message_1(enomsg) -> <<"no message of desired type">>;
+message_1(enonet) -> <<"machine is not on the network">>;
+message_1(enopkg) -> <<"package not installed">>;
+message_1(enoprotoopt) -> <<"bad proocol option">>;
+message_1(enospc) -> <<"no space left on device">>;
+message_1(enosr) -> <<"out of stream resources or not a stream device">>;
+message_1(enosym) -> <<"unresolved symbol name">>;
+message_1(enosys) -> <<"function not implemented">>;
+message_1(enotblk) -> <<"block device required">>;
+message_1(enotconn) -> <<"socket is not connected">>;
+message_1(enotdir) -> <<"not a directory">>;
+message_1(enotempty) -> <<"directory not empty">>;
+message_1(enotnam) -> <<"not a name file">>;
+message_1(enotsock) -> <<"socket operation on non-socket">>;
+message_1(enotsup) -> <<"operation not supported">>;
+message_1(enotty) -> <<"inappropriate device for ioctl">>;
+message_1(enotuniq) -> <<"name not unique on network">>;
+message_1(enxio) -> <<"no such device or address">>;
+message_1(eopnotsupp) -> <<"operation not supported on socket">>;
+message_1(eperm) -> <<"not owner">>;
+message_1(epfnosupport) -> <<"protocol family not supported">>;
+message_1(epipe) -> <<"broken pipe">>;
+message_1(eproclim) -> <<"too many processes">>;
+message_1(eprocunavail) -> <<"bad procedure for program">>;
+message_1(eprogmismatch) -> <<"program version wrong">>;
+message_1(eprogunavail) -> <<"RPC program not available">>;
+message_1(eproto) -> <<"protocol error">>;
+message_1(eprotonosupport) -> <<"protocol not suppored">>;
+message_1(eprototype) -> <<"protocol wrong type for socket">>;
+message_1(erange) -> <<"math result unrepresentable">>;
+message_1(erefused) -> <<"EREFUSED">>;
+message_1(eremchg) -> <<"remote address changed">>;
+message_1(eremdev) -> <<"remote device">>;
+message_1(eremote) -> <<"pathname hit remote file system">>;
+message_1(eremoteio) -> <<"remote i/o error">>;
+message_1(eremoterelease) -> <<"EREMOTERELEASE">>;
+message_1(erofs) -> <<"read-only file system">>;
+message_1(erpcmismatch) -> <<"RPC version is wrong">>;
+message_1(erremote) -> <<"object is remote">>;
+message_1(eshutdown) -> <<"can't send after socket shutdown">>;
+message_1(esocktnosupport) -> <<"socket type not supported">>;
+message_1(espipe) -> <<"invalid seek">>;
+message_1(esrch) -> <<"no such process">>;
+message_1(esrmnt) -> <<"srmount error">>;
+message_1(estale) -> <<"stale remote file handle">>;
+message_1(esuccess) -> <<"Error 0">>;
+message_1(etime) -> <<"timer expired">>;
+message_1(etimedout) -> <<"connection timed out">>;
+message_1(etoomanyrefs) -> <<"too many references: can't splice">>;
+message_1(etxtbsy) -> <<"text file or pseudo-device busy">>;
+message_1(euclean) -> <<"structure needs cleaning">>;
+message_1(eunatch) -> <<"protocol driver not attached">>;
+message_1(eusers) -> <<"too many users">>;
+message_1(eversion) -> <<"version mismatch">>;
+message_1(ewouldblock) -> <<"operation would block">>;
+message_1(exdev) -> <<"cross-domain link">>;
+message_1(exfull) -> <<"message tables full">>;
+message_1(nxdomain) -> <<"non-existing domain">>;
+message_1(_) -> <<"unknown POSIX error">>.
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index 99e454f593..7cb02afb11 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -570,9 +570,7 @@ parse_beam(S, File, HeaderSz, CheckOnly) ->
forms_or_bin = Bin}
end;
{error, beam_lib, Reason} when is_tuple(Reason) ->
- fatal(element(1, Reason));
- {error, beam_lib, Reason} ->
- fatal(Reason)
+ fatal(element(1, Reason))
end.
parse_source(S, File, Fd, StartLine, HeaderSz, CheckOnly) ->
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index e38b8957f2..24abf1e977 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -165,8 +165,6 @@ basename1([$/|[]], Tail, DirSep2) ->
basename1([], Tail, DirSep2);
basename1([$/|Rest], _Tail, DirSep2) ->
basename1(Rest, [], DirSep2);
-basename1([[_|_]=List|Rest], Tail, DirSep2) ->
- basename1(List++Rest, Tail, DirSep2);
basename1([DirSep2|Rest], Tail, DirSep2) when is_integer(DirSep2) ->
basename1([$/|Rest], Tail, DirSep2);
basename1([Char|Rest], Tail, DirSep2) when is_integer(Char) ->
@@ -280,8 +278,6 @@ dirname(Name0) ->
Name = flatten(Name0),
dirname(Name, [], [], separators()).
-dirname([[_|_]=List|Rest], Dir, File, Seps) ->
- dirname(List++Rest, Dir, File, Seps);
dirname([$/|Rest], Dir, File, Seps) ->
dirname(Rest, File++Dir, [$/], Seps);
dirname([DirSep|Rest], Dir, File, {DirSep,_}=Seps) when is_integer(DirSep) ->
@@ -346,8 +342,6 @@ extension(Name) when is_binary(Name) ->
[]
end,
case binary:matches(Name,[<<".">>]) of
- nomatch -> % Bug in binary workaround :(
- <<>>;
[] ->
<<>>;
List ->
@@ -479,6 +473,12 @@ maybe_remove_dirsep(Name, _) ->
%% by a previous call to join/{1,2}.
-spec append(file:filename(), file:name()) -> file:filename().
+append(Dir, Name) when is_binary(Dir), is_binary(Name) ->
+ <<Dir/binary,$/:8,Name/binary>>;
+append(Dir, Name) when is_binary(Dir) ->
+ append(Dir,filename_string_to_binary(Name));
+append(Dir, Name) when is_binary(Name) ->
+ append(filename_string_to_binary(Dir),Name);
append(Dir, Name) ->
Dir ++ [$/|Name].
@@ -685,8 +685,6 @@ split([$/|Rest], Comp, Components, OsType) ->
split(Rest, [], [lists:reverse(Comp)|Components], OsType);
split([Char|Rest], Comp, Components, OsType) when is_integer(Char) ->
split(Rest, [Char|Comp], Components, OsType);
-split([List|Rest], Comp, Components, OsType) when is_list(List) ->
- split(List++Rest, Comp, Components, OsType);
split([], [], Components, _OsType) ->
lists:reverse(Components);
split([], Comp, Components, OsType) ->
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index 1d0f9374bc..3efa68ca09 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -39,6 +39,8 @@
-type device() :: atom() | pid().
-type prompt() :: atom() | string().
+-type error_description() :: term(). % Whatever the io-server sends.
+-type request_error() :: {'error',error_description()}.
%% XXX: Some uses of line() in this file may need to read erl_scan:location()
-type line() :: pos_integer().
@@ -53,26 +55,12 @@
to_tuple(T) when is_tuple(T) -> T;
to_tuple(T) -> {T}.
-%% Problem: the variables Other, Name and Args may collide with surrounding
-%% ones.
-%% Give extra args to macro, being the variables to use.
--define(O_REQUEST(Io, Request),
- case request(Io, Request) of
- {error, Reason} ->
- [Name | Args] = tuple_to_list(to_tuple(Request)),
- erlang:error(conv_reason(Name, Reason), [Name, Io | Args]);
- Other ->
- Other
- end).
-
o_request(Io, Request, Func) ->
case request(Io, Request) of
{error, Reason} ->
[_Name | Args] = tuple_to_list(to_tuple(Request)),
- {'EXIT',{undef,[_Current|Mfas]}} = (catch erlang:error(undef)),
- MFA = {io, Func, [Io | Args]},
- exit({conv_reason(Func, Reason),[MFA|Mfas]});
-% erlang:error(conv_reason(Name, Reason), [Name, Io | Args]);
+ {'EXIT',{get_stacktrace,[_Current|Mfas]}} = (catch erlang:error(get_stacktrace)),
+ erlang:raise(error, conv_reason(Func, Reason), [{io, Func, [Io | Args]}|Mfas]);
Other ->
Other
end.
@@ -299,32 +287,32 @@ format(Io, Format, Args) ->
%% Scanning Erlang code.
--spec scan_erl_exprs(prompt()) -> erl_scan:tokens_result().
+-spec scan_erl_exprs(prompt()) -> erl_scan:tokens_result() | request_error().
scan_erl_exprs(Prompt) ->
scan_erl_exprs(default_input(), Prompt, 1).
--spec scan_erl_exprs(device(), prompt()) -> erl_scan:tokens_result().
+-spec scan_erl_exprs(device(), prompt()) -> erl_scan:tokens_result() | request_error().
scan_erl_exprs(Io, Prompt) ->
scan_erl_exprs(Io, Prompt, 1).
--spec scan_erl_exprs(device(), prompt(), line()) -> erl_scan:tokens_result().
+-spec scan_erl_exprs(device(), prompt(), line()) -> erl_scan:tokens_result() | request_error().
scan_erl_exprs(Io, Prompt, Pos0) ->
request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}).
--spec scan_erl_form(prompt()) -> erl_scan:tokens_result().
+-spec scan_erl_form(prompt()) -> erl_scan:tokens_result() | request_error().
scan_erl_form(Prompt) ->
scan_erl_form(default_input(), Prompt, 1).
--spec scan_erl_form(device(), prompt()) -> erl_scan:tokens_result().
+-spec scan_erl_form(device(), prompt()) -> erl_scan:tokens_result() | request_error().
scan_erl_form(Io, Prompt) ->
scan_erl_form(Io, Prompt, 1).
--spec scan_erl_form(device(), prompt(), line()) -> erl_scan:tokens_result().
+-spec scan_erl_form(device(), prompt(), line()) -> erl_scan:tokens_result() | request_error().
scan_erl_form(Io, Prompt, Pos0) ->
request(Io, {get_until,unicode,Prompt,erl_scan,tokens,[Pos0]}).
@@ -335,7 +323,8 @@ scan_erl_form(Io, Prompt, Pos0) ->
-type parse_ret() :: {'ok', erl_parse_expr_list(), line()}
| {'eof', line()}
- | {'error', erl_scan:error_info(), line()}.
+ | {'error', erl_scan:error_info(), line()}
+ | request_error().
-spec parse_erl_exprs(prompt()) -> parse_ret().
@@ -364,7 +353,8 @@ parse_erl_exprs(Io, Prompt, Pos0) ->
-type parse_form_ret() :: {'ok', erl_parse_absform(), line()}
| {'eof', line()}
- | {'error', erl_scan:error_info(), line()}.
+ | {'error', erl_scan:error_info(), line()}
+ | request_error().
-spec parse_erl_form(prompt()) -> parse_form_ret().
diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl
index 296a6b3d23..9642de17b4 100644
--- a/lib/stdlib/src/re.erl
+++ b/lib/stdlib/src/re.erl
@@ -208,29 +208,25 @@ replace(Subject,RE,Replacement,Options) ->
process_repl_params(Options,iodata,false),
FlatSubject = to_binary(Subject, Unicode),
FlatReplacement = to_binary(Replacement, Unicode),
- case do_replace(FlatSubject,Subject,RE,FlatReplacement,NewOpt) of
- {error,_Err} ->
- throw(badre);
- IoList ->
- case Convert of
- iodata ->
- IoList;
- binary ->
- case Unicode of
- false ->
- iolist_to_binary(IoList);
- true ->
- unicode:characters_to_binary(IoList,unicode)
- end;
- list ->
- case Unicode of
- false ->
- binary_to_list(iolist_to_binary(IoList));
- true ->
- unicode:characters_to_list(IoList,unicode)
- end
- end
- end
+ IoList = do_replace(FlatSubject,Subject,RE,FlatReplacement,NewOpt),
+ case Convert of
+ iodata ->
+ IoList;
+ binary ->
+ case Unicode of
+ false ->
+ iolist_to_binary(IoList);
+ true ->
+ unicode:characters_to_binary(IoList,unicode)
+ end;
+ list ->
+ case Unicode of
+ false ->
+ binary_to_list(iolist_to_binary(IoList));
+ true ->
+ unicode:characters_to_list(IoList,unicode)
+ end
+ end
catch
throw:badopt ->
erlang:error(badarg,[Subject,RE,Replacement,Options]);
diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl
index 44742063b3..d8bb2dfb60 100644
--- a/lib/stdlib/test/base64_SUITE.erl
+++ b/lib/stdlib/test/base64_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. 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
@@ -18,7 +18,6 @@
%%
-module(base64_SUITE).
--author('[email protected]').
-include("test_server.hrl").
-include("test_server_line.hrl").
@@ -29,7 +28,7 @@
%% Test cases must be exported.
-export([base64_encode/1, base64_decode/1, base64_otp_5635/1,
base64_otp_6279/1, big/1, illegal/1, mime_decode/1,
- roundtrip/1]).
+ mime_decode_to_string/1, roundtrip/1]).
init_per_testcase(_, Config) ->
Dog = test_server:timetrap(?t:minutes(2)),
@@ -50,7 +49,7 @@ all(doc) ->
all(suite) ->
[base64_encode, base64_decode, base64_otp_5635,
base64_otp_6279, big, illegal, mime_decode,
- roundtrip].
+ mime_decode_to_string, roundtrip].
%%-------------------------------------------------------------------------
@@ -59,7 +58,7 @@ base64_encode(doc) ->
base64_encode(suite) ->
[];
base64_encode(Config) when is_list(Config) ->
- %% Two pads
+ %% Two pads
<<"QWxhZGRpbjpvcGVuIHNlc2FtZQ==">> =
base64:encode("Aladdin:open sesame"),
%% One pad
@@ -77,8 +76,8 @@ base64_decode(doc) ->
base64_decode(suite) ->
[];
base64_decode(Config) when is_list(Config) ->
- %% Two pads
- <<"Aladdin:open sesame">> =
+ %% Two pads
+ <<"Aladdin:open sesame">> =
base64:decode("QWxhZGRpbjpvcGVuIHNlc2FtZQ=="),
%% One pad
<<"Hello World">> = base64:decode(<<"SGVsbG8gV29ybGQ=">>),
@@ -138,20 +137,85 @@ illegal(Config) when is_list(Config) ->
{'EXIT',{function_clause, _}} = (catch base64:decode("()")),
ok.
%%-------------------------------------------------------------------------
+%% mime_decode and mime_decode_to_string have different implementations
+%% so test both with the same input separately. Both functions have
+%% the same implementation for binary/string arguments.
mime_decode(doc) ->
["Test base64:mime_decode/1."];
mime_decode(suite) ->
[];
mime_decode(Config) when is_list(Config) ->
- %% Two pads
- <<"Aladdin:open sesame">> =
+ %% Test correct padding
+ <<"one">> = base64:mime_decode(<<"b25l">>),
+ <<"on">> = base64:mime_decode(<<"b24=">>),
+ <<"o">> = base64:mime_decode(<<"bw==">>),
+ %% Test 1 extra padding
+ <<"one">> = base64:mime_decode(<<"b25l= =">>),
+ <<"on">> = base64:mime_decode(<<"b24== =">>),
+ <<"o">> = base64:mime_decode(<<"bw=== =">>),
+ %% Test 2 extra padding
+ <<"one">> = base64:mime_decode(<<"b25l===">>),
+ <<"on">> = base64:mime_decode(<<"b24====">>),
+ <<"o">> = base64:mime_decode(<<"bw=====">>),
+ %% Test misc embedded padding
+ <<"one">> = base64:mime_decode(<<"b2=5l===">>),
+ <<"on">> = base64:mime_decode(<<"b=24====">>),
+ <<"o">> = base64:mime_decode(<<"b=w=====">>),
+ %% Test misc white space and illegals with embedded padding
+ <<"one">> = base64:mime_decode(<<" b~2=\r\n5()l===">>),
+ <<"on">> = base64:mime_decode(<<"\tb =2\"�4=�= ==">>),
+ <<"o">> = base64:mime_decode(<<"\nb=w=====">>),
+ %% Two pads
+ <<"Aladdin:open sesame">> =
base64:mime_decode("QWxhZGRpbjpvc()GVuIHNlc2FtZQ=="),
- %% One pad, followed by ignored text
- <<"Hello World">> = base64:mime_decode(<<"SGVsb)(G8gV29ybGQ=apa">>),
+ %% One pad to ignore, followed by more text
+ <<"Hello World!!">> = base64:mime_decode(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
+ %% No pad
+ <<"Aladdin:open sesam">> =
+ base64:mime_decode("QWxhZGRpbjpvcG�\")(VuIHNlc2Ft"),
+ %% Encoded base 64 strings may be divided by non base 64 chars.
+ %% In this cases whitespaces.
+ <<"0123456789!@#0^&*();:<>,. []{}">> =
+ base64:mime_decode(
+ <<"MDEy MzQ1Njc4 \tOSFAIzBeJ \nio)(oKTs6 PD4sLi \r\nBbXXt9">>),
+ ok.
+
+%%-------------------------------------------------------------------------
+
+%% Repeat of mime_decode() tests
+mime_decode_to_string(doc) ->
+ ["Test base64:mime_decode_to_string/1."];
+mime_decode_to_string(suite) ->
+ [];
+mime_decode_to_string(Config) when is_list(Config) ->
+ %% Test correct padding
+ "one" = base64:mime_decode_to_string(<<"b25l">>),
+ "on" = base64:mime_decode_to_string(<<"b24=">>),
+ "o" = base64:mime_decode_to_string(<<"bw==">>),
+ %% Test 1 extra padding
+ "one" = base64:mime_decode_to_string(<<"b25l= =">>),
+ "on" = base64:mime_decode_to_string(<<"b24== =">>),
+ "o" = base64:mime_decode_to_string(<<"bw=== =">>),
+ %% Test 2 extra padding
+ "one" = base64:mime_decode_to_string(<<"b25l===">>),
+ "on" = base64:mime_decode_to_string(<<"b24====">>),
+ "o" = base64:mime_decode_to_string(<<"bw=====">>),
+ %% Test misc embedded padding
+ "one" = base64:mime_decode_to_string(<<"b2=5l===">>),
+ "on" = base64:mime_decode_to_string(<<"b=24====">>),
+ "o" = base64:mime_decode_to_string(<<"b=w=====">>),
+ %% Test misc white space and illegals with embedded padding
+ "one" = base64:mime_decode_to_string(<<" b~2=\r\n5()l===">>),
+ "on" = base64:mime_decode_to_string(<<"\tb =2\"�4=�= ==">>),
+ "o" = base64:mime_decode_to_string(<<"\nb=w=====">>),
+ %% Two pads
+ "Aladdin:open sesame" =
+ base64:mime_decode_to_string("QWxhZGRpbjpvc()GVuIHNlc2FtZQ=="),
+ %% One pad to ignore, followed by more text
+ "Hello World!!" = base64:mime_decode_to_string(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
%% No pad
"Aladdin:open sesam" =
base64:mime_decode_to_string("QWxhZGRpbjpvcG�\")(VuIHNlc2Ft"),
-
%% Encoded base 64 strings may be divided by non base 64 chars.
%% In this cases whitespaces.
"0123456789!@#0^&*();:<>,. []{}" =
@@ -159,6 +223,7 @@ mime_decode(Config) when is_list(Config) ->
<<"MDEy MzQ1Njc4 \tOSFAIzBeJ \nio)(oKTs6 PD4sLi \r\nBbXXt9">>),
ok.
+%%-------------------------------------------------------------------------
roundtrip(Config) when is_list(Config) ->
Sizes = lists:seq(1, 255) ++ lists:seq(2400-5, 2440),
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index c60a558fa1..254ce0095d 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-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2010. 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
@@ -38,7 +38,8 @@
otp_8133/1,
funs/1,
try_catch/1,
- eval_expr_5/1]).
+ eval_expr_5/1,
+ zero_width/1]).
%%
%% Define to run outside of test server
@@ -76,7 +77,8 @@ all(suite) ->
[guard_1, guard_2, match_pattern, string_plusplus, 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].
+ otp_6787, otp_6977, otp_7550, otp_8133, funs, try_catch, eval_expr_5,
+ zero_width].
guard_1(doc) ->
["(OTP-2405)"];
@@ -1326,6 +1328,14 @@ eval_expr_5(Config) when is_list(Config) ->
ok
end.
+zero_width(Config) when is_list(Config) ->
+ ?line check(fun() ->
+ {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>),
+ ok
+ end, "begin {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>), "
+ "ok end.", ok),
+ ok.
+
%% Check the string in different contexts: as is; in fun; from compiled code.
check(F, String, Result) ->
check1(F, String, Result),
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index d0c0d68b4a..c4158abf32 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. 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
@@ -54,7 +54,8 @@
otp_7550/1,
otp_8051/1,
format_warn/1,
- on_load/1, on_load_successful/1, on_load_failing/1
+ on_load/1, on_load_successful/1, on_load_failing/1,
+ too_many_arguments/1
]).
% Default timetrap timeout (set in init_per_testcase).
@@ -77,7 +78,7 @@ all(suite) ->
otp_5362, otp_5371, otp_7227, otp_5494, otp_5644, otp_5878, otp_5917, otp_6585,
otp_6885, export_all, bif_clash,
behaviour_basic, behaviour_multiple, otp_7550, otp_8051, format_warn,
- on_load].
+ on_load,too_many_arguments].
unused_vars_warn(suite) ->
[unused_vars_warn_basic, unused_vars_warn_lc, unused_vars_warn_rec,
@@ -2913,6 +2914,21 @@ on_load_failing(Config) when is_list(Config) ->
?line [] = run(Config, Ts),
ok.
+too_many_arguments(doc) ->
+ "Test that too many arguments is not accepted.";
+too_many_arguments(suite) -> [];
+too_many_arguments(Config) when is_list(Config) ->
+ Ts = [{too_many_1,
+ <<"f(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ok.">>,
+ [],
+ {errors,
+ [{1,erl_lint,{too_many_arguments,256}}],[]}}
+ ],
+
+ ?line [] = 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/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 620848003c..4e789790f6 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -5325,7 +5325,25 @@ my_tab_to_list(_Ts,'$end_of_table', Acc) -> lists:reverse(Acc);
my_tab_to_list(Ts,Key, Acc) ->
my_tab_to_list(Ts,ets:next(Ts,Key),[ets:lookup(Ts, Key)| Acc]).
+wait_for_all_schedulers_online_to_execute() ->
+ PMs = lists:map(fun (Sched) ->
+ spawn_opt(fun () -> ok end,
+ [monitor, {scheduler, Sched}])
+ end,
+ lists:seq(1,erlang:system_info(schedulers_online))),
+ lists:foreach(fun ({P, M}) ->
+ receive
+ {'DOWN', M, process, P, _} -> ok
+ end
+ end,
+ PMs),
+ ok.
+
etsmem() ->
+ %% Wait until it is guaranteed that all already scheduled
+ %% deallocations of DbTable structures have completed.
+ wait_for_all_schedulers_online_to_execute(),
+
AllTabs = lists:map(fun(T) -> {T,ets:info(T,name),ets:info(T,size),
ets:info(T,memory),ets:info(T,type)}
end, ets:all()),
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index db7954af04..ac02e1f359 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 1.17.2
+STDLIB_VSN = 1.17.3