aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface
diff options
context:
space:
mode:
Diffstat (limited to 'lib/erl_interface')
-rw-r--r--lib/erl_interface/configure.in6
-rw-r--r--lib/erl_interface/doc/src/ei.xml138
-rw-r--r--lib/erl_interface/doc/src/ei_connect.xml3
-rw-r--r--lib/erl_interface/doc/src/ei_users_guide.xml12
-rw-r--r--lib/erl_interface/doc/src/erl_connect.xml9
-rw-r--r--lib/erl_interface/doc/src/erl_eterm.xml9
-rw-r--r--lib/erl_interface/doc/src/erl_global.xml9
-rw-r--r--lib/erl_interface/doc/src/erl_interface.xml12
-rw-r--r--lib/erl_interface/doc/src/erl_malloc.xml8
-rw-r--r--lib/erl_interface/doc/src/erl_marshal.xml8
-rw-r--r--lib/erl_interface/doc/src/notes.xml126
-rw-r--r--lib/erl_interface/doc/src/ref_man.xml8
-rw-r--r--lib/erl_interface/doc/src/ref_man_ei.xml10
-rw-r--r--lib/erl_interface/doc/src/ref_man_erl_interface.xml8
-rw-r--r--lib/erl_interface/include/ei.h61
-rw-r--r--lib/erl_interface/include/erl_interface.h213
-rw-r--r--lib/erl_interface/src/INSTALL4
-rw-r--r--lib/erl_interface/src/Makefile2
-rw-r--r--lib/erl_interface/src/Makefile.in4
-rw-r--r--lib/erl_interface/src/README.internal8
-rw-r--r--lib/erl_interface/src/connect/ei_connect.c18
-rw-r--r--lib/erl_interface/src/connect/ei_connect_int.h2
-rw-r--r--lib/erl_interface/src/decode/decode_binary.c37
-rw-r--r--lib/erl_interface/src/decode/decode_fun.c103
-rw-r--r--lib/erl_interface/src/decode/decode_skip.c9
-rw-r--r--lib/erl_interface/src/encode/encode_binary.c107
-rw-r--r--lib/erl_interface/src/encode/encode_fun.c114
-rw-r--r--lib/erl_interface/src/legacy/erl_eterm.c14
-rw-r--r--lib/erl_interface/src/misc/ei_compat.c17
-rw-r--r--lib/erl_interface/src/misc/ei_decode_term.c8
-rw-r--r--lib/erl_interface/src/misc/ei_internal.h2
-rw-r--r--lib/erl_interface/src/misc/ei_printterm.c82
-rw-r--r--lib/erl_interface/src/misc/ei_pthreads.c2
-rw-r--r--lib/erl_interface/src/misc/ei_x_encode.c10
-rw-r--r--lib/erl_interface/src/misc/get_type.c11
-rw-r--r--lib/erl_interface/src/misc/show_msg.c8
-rw-r--r--lib/erl_interface/src/prog/ei_fake_prog.c1
-rw-r--r--lib/erl_interface/src/prog/erl_start.c2
-rw-r--r--lib/erl_interface/src/registry/reg_dump.c2
-rw-r--r--lib/erl_interface/test/all_SUITE_data/ei_runner.h1
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE.erl21
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c22
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE.erl5
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c14
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE.erl3
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c198
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl30
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c101
-rw-r--r--lib/erl_interface/test/ei_print_SUITE.erl68
-rw-r--r--lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c202
-rw-r--r--lib/erl_interface/vsn.mk2
51 files changed, 1479 insertions, 395 deletions
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in
index 747750c1fb..f0e9b2eb3f 100644
--- a/lib/erl_interface/configure.in
+++ b/lib/erl_interface/configure.in
@@ -29,11 +29,6 @@ dnl m4_define(EI_VERSION,regexp(m4_include(VERSION),[version \([-.0-9A-Za-z]+\)]
AC_INIT()
-if test "x$no_recursion" != "xyes" -a "x$OVERRIDE_CONFIG_CACHE" = "x"; then
- # We do not want to use a common cache!
- cache_file=/dev/null
-fi
-
dnl How to set srcdir absolute is taken from the GNU Emacs distribution
#### Make srcdir absolute, if it isn't already. It's important to
#### avoid running the path through pwd unnecessary, since pwd can
@@ -365,6 +360,7 @@ LDFLAGS="$LDFLAGS $sanitizers"
# XXX
# ---------------------------------------------------------------------------
+
AC_OUTPUT(
src/$host/Makefile:src/Makefile.in
src/$host/eidefs.mk:src/eidefs.mk.in
diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml
index 179dbbd966..70af5642da 100644
--- a/lib/erl_interface/doc/src/ei.xml
+++ b/lib/erl_interface/doc/src/ei.xml
@@ -35,6 +35,9 @@
<lib>ei</lib>
<libsummary>Routines for handling the Erlang binary term format.</libsummary>
<description>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+
<p>The library <c>ei</c> contains macros and functions to encode
and decode the Erlang binary term format.</p>
@@ -180,6 +183,43 @@ typedef enum {
</func>
<func>
+ <name since="OTP 22.0"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, const char **pp, unsigned int *bitoffsp, size_t *nbitsp)</nametext></name>
+ <fsummary>Decode a bitstring.</fsummary>
+ <desc>
+ <p>Decodes a bit string from the binary format.</p>
+ <taglist>
+ <tag><c>pp</c></tag>
+ <item><p>Either <c>NULL</c> or <c>*pp</c> returns a pointer to
+ the first byte of the bit string. The returned bit string is
+ readable as long as the buffer pointed to by <c>buf</c> is
+ readable and not written to.</p>
+ </item>
+ <tag><c>bitoffsp</c></tag>
+ <item><p>Either <c>NULL</c> or <c>*bitoffsp</c> returns the
+ number of unused bits in the first byte pointed to by
+ <c>*pp</c>. The value of <c>*bitoffsp</c> is between 0 and 7.
+ Unused bits in the first byte are the most significant bits.</p>
+ </item>
+ <tag><c>nbitsp</c></tag>
+ <item><p>Either <c>NULL</c> or <c>*nbitsp</c> returns the length
+ of the bit string in <em>bits</em>.</p>
+ </item>
+ </taglist>
+ <p>Returns <c>0</c> if it was a bit string term.</p>
+ <p>The number of <em>bytes</em> pointed to by <c>*pp</c>, which are
+ part of the bit string, is <c>(*bitoffsp + *nbitsp + 7)/8</c>. If
+ <c>(*bitoffsp + *bitsp)%8 > 0</c> then only <c>(*bitoffsp +
+ *bitsp)%8</c> bits of the last byte are used. Unused bits in
+ the last byte are the least significant bits.</p>
+ <p>The values of unused bits in the first and last byte are undefined
+ and cannot be relied on.</p>
+ <p>Number of bits may be divisible by 8, which means a binary
+ decodable by <c>ei_decode_binary</c> is also decodable by
+ <c>ei_decode_bitstring</c>.</p>
+ </desc>
+ </func>
+
+ <func>
<name since=""><ret>int</ret><nametext>ei_decode_boolean(const char *buf, int *index, int *p)</nametext></name>
<fsummary>Decode a boolean.</fsummary>
<desc>
@@ -346,8 +386,10 @@ typedef enum {
<c>t</c> is actually an <c>ETERM**</c> (see
<seealso marker="erl_eterm"><c>erl_eterm</c></seealso>).
The term is later to be deallocated.</p>
- <p>Notice that this function is located in the <c>Erl_Interface</c>
- library.</p>
+ <note><p>This function is deprecated as of OTP 22 and will be removed in
+ OTP 23 together with the old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>).</p>
+ </note>
</desc>
</func>
@@ -456,6 +498,28 @@ typedef enum {
</func>
<func>
+ <name since="OTP 22.0"><ret>int</ret>
+ <nametext>ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t nbits)</nametext></name>
+ <name since="OTP 22.0"><ret>int</ret>
+ <nametext>ei_x_encode_bitstring(ei_x_buff* x, const char *p, size_t bitoffs, size_t nbits)</nametext></name>
+ <fsummary>Encode a bitstring.</fsummary>
+ <desc>
+ <p>Encodes a bit string in the binary format.</p>
+ <p>The data is at <c>p</c>. The length of the bit string is <c>nbits</c>
+ bits. The first <c>bitoffs</c> bits of the data at <c>p</c> are unused.
+ The first byte which is part of the bit string is
+ <c>p[bitoffs/8]</c>. The <c>bitoffs%8</c> most significant bits of
+ the first byte <c>p[bitoffs/8]</c> are unused.</p>
+ <p>The number of bytes which is part of the bit string is <c>(bitoffs +
+ nbits + 7)/8</c>. If <c>(bitoffs + nbits)%8 > 0</c> then only <c>(bitoffs +
+ nbits)%8</c> bits of the last byte are used. Unused bits in
+ the last byte are the least significant bits.</p>
+ <p>The values of unused bits are disregarded and does not need to be
+ cleared.</p>
+ </desc>
+ </func>
+
+ <func>
<name since=""><ret>int</ret><nametext>ei_encode_boolean(char *buf, int *index, int p)</nametext></name>
<name since=""><ret>int</ret><nametext>ei_x_encode_boolean(ei_x_buff* x, int p)</nametext></name>
<fsummary>Encode a boolean.</fsummary>
@@ -653,6 +717,10 @@ ei_x_encode_string(&amp;x, "Banana");</pre>
<c>erl_interface</c>. Parameter <c>t</c> is
actually an <c>ETERM</c> pointer. This function
does not free the <c>ETERM</c>.</p>
+ <note><p>These functions are deprecated as of OTP 22 and will be removed in
+ OTP 23 together with the old legacy <c>erl_interface</c> library
+ (functions with prefix <c>erl_</c>).</p>
+ </note>
</desc>
</func>
<func>
@@ -722,12 +790,12 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
<name since=""><ret>int</ret><nametext>ei_get_type(const char *buf, const int *index, int *type, int *size)</nametext></name>
<fsummary>Fetch the type and size of an encoded term.</fsummary>
<desc>
- <p>Returns the type in <c>type</c> and size in
- <c>size</c> of the encoded term. For strings and atoms,
+ <p>Returns the type in <c>*type</c> and size in
+ <c>*size</c> of the encoded term. For strings and atoms,
size is the number of characters <em>not</em> including the
- terminating <c>NULL</c>. For binaries, <c>size</c> is the number of
- bytes. For lists and tuples, <c>size</c> is the arity of
- the object. For other types, <c>size</c> is 0. In all
+ terminating <c>NULL</c>. For binaries and bitstrings, <c>*size</c> is
+ the number of bytes. For lists, tuples and maps, <c>*size</c> is the
+ arity of the object. For other types, <c>*size</c> is 0. In all
cases, <c>index</c> is left unchanged.</p>
</desc>
</func>
@@ -781,30 +849,48 @@ ei_encode_tuple_header(buf, &amp;i, 0);</pre>
</type>
<desc>
<marker id="ei_set_compat_rel"></marker>
- <p>By default, the <c>ei</c> library is only guaranteed
- to be compatible with other Erlang/OTP components from the same
- release as the <c>ei</c> library itself. For example,
- <c>ei</c> from
- Erlang/OTP R10 is not compatible with an Erlang emulator
- from Erlang/OTP R9 by default.</p>
- <p>A call to <c>ei_set_compat_rel(release_number)</c> sets
- the <c>ei</c> library in compatibility mode of release
- <c>release_number</c>. Valid range of
- <c>release_number</c>
- is <c>[7, current release]</c>. This makes it possible to
- communicate with Erlang/OTP components from earlier releases.</p>
+ <p>In general, the <c>ei</c> library is guaranteed
+ to be compatible with other Erlang/OTP components that are 2 major
+ releases older or newer than the <c>ei</c> library itself.</p>
+ <p>Sometimes an exception to the above rule has to be made to make new
+ features (or even bug fixes) possible. A call to
+ <c>ei_set_compat_rel(release_number)</c> sets
+ the <c>ei</c> library in compatibility mode of OTP release
+ <c>release_number</c>.</p>
+ <p>The only useful value for <c>release_number</c> is currently
+ <c>21</c>. This will only be useful and have an effect if <em>bit
+ strings</em> or <em>export funs</em> are received from a connected
+ node. Before OTP 22, bit strings and export funs were not supported by
+ <c>ei</c>. They were instead encoded using an undocumented fallback
+ tuple format when sent from the emulator to <c>ei</c>:</p>
+ <taglist>
+ <tag><c>Bit string</c></tag>
+ <item><p>The term <c>&lt;&lt;42, 1:1>></c> was encoded as
+ <c>{&lt;&lt;42, 128>>, 1}</c>. The first element of the tuple is a
+ binary and the second element denotes how many bits of the last bytes
+ are part of the bit string. In this example only the most significant
+ bit of the last byte (128) is part of the bit string.</p>
+ </item>
+ <tag><c>Export fun</c></tag>
+ <item><p>The term <c>fun lists:map/2</c> was encoded as
+ <c>{lists,map}</c>. A tuple with the module, function and a missing
+ arity.</p>
+ </item>
+ </taglist>
+ <p>If <c>ei_set_compat_rel(21)</c> is <em>not</em> called then a connected
+ emulator will send bit strings and export funs correctly encoded. The
+ functions <seealso marker="#ei_decode_bitstring"><c>ei_decode_bitstring</c></seealso>
+ and <seealso marker="#ei_decode_fun"><c>ei_decode_fun</c></seealso>
+ has to be used to decode such terms. Calling
+ <c>ei_set_compat_rel(21)</c> should only be done as a workaround to
+ keep an old implementation alive, which expects to receive the
+ undocumented tuple formats for bit strings and/or export funs.
+ </p>
<note>
<p>If this function is called, it can only be called once
and must be called before any other functions in the
<c>ei</c> library are called.</p>
</note>
- <warning>
- <p>You can run into trouble if this feature is used
- carelessly. Always ensure that all communicating
- components are either from the same Erlang/OTP release, or
- from release X and release Y where all components
- from release Y are in compatibility mode of release X.</p>
- </warning>
</desc>
</func>
diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml
index 2dd0a285fe..795f1249b3 100644
--- a/lib/erl_interface/doc/src/ei_connect.xml
+++ b/lib/erl_interface/doc/src/ei_connect.xml
@@ -34,6 +34,9 @@
<lib>ei_connect</lib>
<libsummary>Communicate with distributed Erlang.</libsummary>
<description>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+
<p>This module enables C-programs to communicate with Erlang nodes,
using the Erlang distribution over TCP/IP.</p>
diff --git a/lib/erl_interface/doc/src/ei_users_guide.xml b/lib/erl_interface/doc/src/ei_users_guide.xml
index 2dfd99e35a..7ca10d1a99 100644
--- a/lib/erl_interface/doc/src/ei_users_guide.xml
+++ b/lib/erl_interface/doc/src/ei_users_guide.xml
@@ -34,6 +34,18 @@
</header>
<section>
+ <title>Deprecation and Removal</title>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
+ </section>
+
+ <section>
<title>Introduction</title>
<p>The <c>Erl_Interface</c> library contains functions that help you
integrate programs written in C and Erlang. The functions in
diff --git a/lib/erl_interface/doc/src/erl_connect.xml b/lib/erl_interface/doc/src/erl_connect.xml
index 139ac9e2f0..9492a82864 100644
--- a/lib/erl_interface/doc/src/erl_connect.xml
+++ b/lib/erl_interface/doc/src/erl_connect.xml
@@ -35,6 +35,15 @@
<lib>erl_connect</lib>
<libsummary>Communicate with distributed Erlang.</libsummary>
<description>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
+
<p>This module provides support for communication between distributed
Erlang nodes and C-nodes, in a manner that is transparent to Erlang
processes.</p>
diff --git a/lib/erl_interface/doc/src/erl_eterm.xml b/lib/erl_interface/doc/src/erl_eterm.xml
index 070ed30dfe..295760b4e6 100644
--- a/lib/erl_interface/doc/src/erl_eterm.xml
+++ b/lib/erl_interface/doc/src/erl_eterm.xml
@@ -35,6 +35,15 @@
<lib>erl_eterm</lib>
<libsummary>Functions for Erlang term construction.</libsummary>
<description>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
+
<p>This module provides functions for creating and manipulating
Erlang terms.</p>
diff --git a/lib/erl_interface/doc/src/erl_global.xml b/lib/erl_interface/doc/src/erl_global.xml
index 72d43e81d5..39085b46f0 100644
--- a/lib/erl_interface/doc/src/erl_global.xml
+++ b/lib/erl_interface/doc/src/erl_global.xml
@@ -35,6 +35,15 @@
<lib>erl_global</lib>
<libsummary>Access globally registered names.</libsummary>
<description>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
+
<p>This module provides support for registering, looking
up, and unregistering names in the <c>global</c> module.
For more information, see
diff --git a/lib/erl_interface/doc/src/erl_interface.xml b/lib/erl_interface/doc/src/erl_interface.xml
index 4e66655b39..decd66046a 100644
--- a/lib/erl_interface/doc/src/erl_interface.xml
+++ b/lib/erl_interface/doc/src/erl_interface.xml
@@ -58,6 +58,18 @@
</list>
<section>
+ <title>Deprecation and Removal</title>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
+ </section>
+
+ <section>
<title>Compiling and Linking Your Code</title>
<p>In order to use any of the Erl_Interface functions, include the
following lines in your code:</p>
diff --git a/lib/erl_interface/doc/src/erl_malloc.xml b/lib/erl_interface/doc/src/erl_malloc.xml
index aae3b7e078..6650620064 100644
--- a/lib/erl_interface/doc/src/erl_malloc.xml
+++ b/lib/erl_interface/doc/src/erl_malloc.xml
@@ -35,6 +35,14 @@
<lib>erl_malloc</lib>
<libsummary>Memory allocation functions.</libsummary>
<description>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
<p>This module provides functions for allocating and deallocating
memory.</p>
</description>
diff --git a/lib/erl_interface/doc/src/erl_marshal.xml b/lib/erl_interface/doc/src/erl_marshal.xml
index 1a6d3bb43c..33d359d871 100644
--- a/lib/erl_interface/doc/src/erl_marshal.xml
+++ b/lib/erl_interface/doc/src/erl_marshal.xml
@@ -35,6 +35,14 @@
<lib>erl_marshal</lib>
<libsummary>Encoding and decoding of Erlang terms.</libsummary>
<description>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
<p>This module contains functions for encoding Erlang terms into
a sequence of bytes, and for decoding Erlang terms from a
sequence of bytes.</p>
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 1f95382704..c47f0d2bd1 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -31,6 +31,82 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The vxworks configure has been updated to respect the
+ environment CFLAGS.</p>
+ <p>
+ Own Id: OTP-15773</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Minor adjustments made to build system for parallel
+ configure.</p>
+ <p>
+ Own Id: OTP-15340 Aux Id: OTP-14625 </p>
+ </item>
+ <item>
+ <p>
+ The limited support for VxWorks is deprecated as of OTP
+ 22, and will be removed in OTP 23.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15621</p>
+ </item>
+ <item>
+ <p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and
+ will be removed in OTP 23. This does not apply to the
+ <c>ei</c> library. Reasonably new <c>gcc</c> compilers
+ will issue deprecation warnings. In order to disable
+ these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15622</p>
+ </item>
+ <item>
+ <p>Added support to receive, decode, encode and send both
+ bit strings and export funs (<c>fun M:F/A</c>).</p>
+ <p>New functions <c>ei_decode_bitstring</c> and
+ <c>ei_encode_bitstring</c> have been added in order to
+ decode and encode bit strings where the number of bits is
+ not necessary divisible by 8 (a whole number of bytes).
+ The existing functions <c>ei_decode_fun</c> and
+ <c>ei_encode_fun</c> can now also handle export funs.</p>
+ <p>Before this change, bit strings and export funs sent
+ to an erl_interface c-node were encoded using an
+ undocumented fallback tuple format. For bit strings
+ <c>{Binary,BitsInLastByte}</c> and for export funs
+ <c>{M,F}</c>. Existing c-node implementations expecting
+ these tuples must be changed to instead use
+ <c>ei_decode_bitstring</c> and <c>ei_decode_fun</c>. As a
+ temporary solution you can also build erl_interface with
+ macro <c>EI_COMPAT=21</c> or call
+ <c>ei_set_compat_rel(21)</c> to receive the old fallback
+ tuples.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15712 Aux Id: OTP-15774 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.11.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -64,6 +140,39 @@
</section>
+<section><title>Erl_Interface 3.11.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <c>erl_interface</c>/<c>ei</c> refused to use node names
+ with an alive name (the part of the node name preceding
+ the @ sign) longer than 63 characters and a host name
+ longer than 64 characters. The total amount of characters
+ allowed in a node name (alivename@hostname) was thus
+ limited to 128 characters. These limits applied both to
+ the own node name as well as node names of other nodes.
+ Ordinary Erlang nodes limit the node name length to 256
+ characters, which meant that you could not communicate
+ with certain Erlang nodes due to their node name used.</p>
+ <p>
+ <c>erl_interface</c>/<c>ei</c> now allow the total amount
+ of characters in a node name to be up to 256 characters.
+ These characters may be distributed between alive name
+ and host name in whatever way needed. That is, the
+ maximum amount of characters in the alive name may be 254
+ and the maximum amount of characters in the host name may
+ be 254, but in total the node name must not exceed 256
+ characters.</p>
+ <p>
+ Own Id: OTP-15781 Aux Id: ERIERL-356 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.11.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -202,6 +311,22 @@
</section>
+<section><title>Erl_Interface 3.10.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix handling of Makefile dependencies so that parallel
+ make works properly.</p>
+ <p>
+ Own Id: OTP-15757</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.10.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1652,4 +1777,3 @@
</section>
</section>
</chapter>
-
diff --git a/lib/erl_interface/doc/src/ref_man.xml b/lib/erl_interface/doc/src/ref_man.xml
index 1e20637cb7..a4f947c79f 100644
--- a/lib/erl_interface/doc/src/ref_man.xml
+++ b/lib/erl_interface/doc/src/ref_man.xml
@@ -29,6 +29,14 @@
<file>ref_man.xml</file>
</header>
<description>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
</description>
<xi:include href="ei.xml"/>
<xi:include href="ei_connect.xml"/>
diff --git a/lib/erl_interface/doc/src/ref_man_ei.xml b/lib/erl_interface/doc/src/ref_man_ei.xml
index 92ff9ed328..d8d1deaea1 100644
--- a/lib/erl_interface/doc/src/ref_man_ei.xml
+++ b/lib/erl_interface/doc/src/ref_man_ei.xml
@@ -30,8 +30,14 @@
<file>ref_man_ei.xml</file>
</header>
<description>
- <p>The <c>ei</c> library is a <c>C</c> interface library for
- communication with <c>Erlang</c>.</p>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
<note>
<p>By default, the <c>ei</c> library is only guaranteed
to be compatible with other Erlang/OTP components from the same
diff --git a/lib/erl_interface/doc/src/ref_man_erl_interface.xml b/lib/erl_interface/doc/src/ref_man_erl_interface.xml
index 4b1d0e9981..2b69d0fa74 100644
--- a/lib/erl_interface/doc/src/ref_man_erl_interface.xml
+++ b/lib/erl_interface/doc/src/ref_man_erl_interface.xml
@@ -30,6 +30,14 @@
<file>ref_man_erl_interface.xml</file>
</header>
<description>
+ <note><p>The support for VxWorks is deprecated as of OTP 22, and
+ will be removed in OTP 23.</p></note>
+ <note><p>The old legacy <c>erl_interface</c> library (functions
+ with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be
+ removed in OTP 23. This does not apply to the <c>ei</c>
+ library. Reasonably new <c>gcc</c> compilers will issue deprecation
+ warnings. In order to disable these warnings, define the macro
+ <c>EI_NO_DEPR_WARN</c>.</p></note>
<p>The <c>erl_interface</c> library is a <c>C</c> interface library
for communication with <c>Erlang</c>.</p>
<note>
diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h
index 947726208e..b138118f04 100644
--- a/lib/erl_interface/include/ei.h
+++ b/lib/erl_interface/include/ei.h
@@ -47,6 +47,25 @@ typedef LONG_PTR ssize_t; /* Sigh... */
# include <netdb.h>
#endif
+#ifdef __has_attribute
+#if __has_attribute(deprecated)
+#define EI_HAVE_DEPRECATED_ATTR__ 1
+#else
+#undef EI_HAVE_DEPRECATED_ATTR__
+#endif
+#endif
+
+#ifdef EI_NO_DEPR_WARN
+#undef EI_HAVE_DEPRECATED_ATTR__
+#endif
+
+#ifdef EI_HAVE_DEPRECATED_ATTR__
+#define EI_DEPRECATED_ATTR_NAME deprecated
+#define EI_DEPRECATED_ATTR __attribute__((EI_DEPRECATED_ATTR_NAME))
+#else
+#define EI_DEPRECATED_ATTR_NAME
+#define EI_DEPRECATED_ATTR
+#endif
/* -------------------------------------------------------------------- */
/* Defines part of API */
@@ -135,11 +154,14 @@ typedef LONG_PTR ssize_t; /* Sigh... */
#define ERL_STRING_EXT 'k'
#define ERL_LIST_EXT 'l'
#define ERL_BINARY_EXT 'm'
+#define ERL_BIT_BINARY_EXT 'M'
#define ERL_SMALL_BIG_EXT 'n'
#define ERL_LARGE_BIG_EXT 'o'
#define ERL_NEW_FUN_EXT 'p'
#define ERL_MAP_EXT 't'
#define ERL_FUN_EXT 'u'
+#define ERL_EXPORT_EXT 'q'
+
#define ERL_NEW_CACHE 'N' /* c nodes don't know these two */
#define ERL_CACHED_ATOM 'C'
@@ -250,15 +272,23 @@ typedef struct {
typedef struct {
long arity;
char module[MAXATOMLEN_UTF8];
- erlang_char_encoding module_org_enc;
- char md5[16];
- long index;
- long old_index;
- long uniq;
- long n_free_vars;
- erlang_pid pid;
- long free_var_len;
- char* free_vars;
+ enum { EI_FUN_CLOSURE, EI_FUN_EXPORT } type;
+ union {
+ struct {
+ char md5[16];
+ long index;
+ long old_index;
+ long uniq;
+ long n_free_vars;
+ erlang_pid pid;
+ long free_var_len;
+ char* free_vars;
+ } closure;
+ struct {
+ char* func;
+ int func_allocated;
+ } exprt;
+ } u;
} erlang_fun;
/* a big */
@@ -496,7 +526,9 @@ int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len);
int ei_x_encode_atom_len_as(ei_x_buff* x, const char* s, int len,
erlang_char_encoding from, erlang_char_encoding to);
int ei_encode_binary(char *buf, int *index, const void *p, long len);
+int ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t bits);
int ei_x_encode_binary(ei_x_buff* x, const void* s, int len);
+int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits);
int ei_encode_pid(char *buf, int *index, const erlang_pid *p);
int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid);
int ei_encode_fun(char* buf, int* index, const erlang_fun* p);
@@ -505,8 +537,8 @@ int ei_encode_port(char *buf, int *index, const erlang_port *p);
int ei_x_encode_port(ei_x_buff* x, const erlang_port *p);
int ei_encode_ref(char *buf, int *index, const erlang_ref *p);
int ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p);
-int ei_encode_term(char *buf, int *index, void *t); /* ETERM* actually */
-int ei_x_encode_term(ei_x_buff* x, void* t);
+int ei_encode_term(char *buf, int *index, void *t) EI_DEPRECATED_ATTR;
+int ei_x_encode_term(ei_x_buff* x, void* t) EI_DEPRECATED_ATTR;
int ei_encode_trace(char *buf, int *index, const erlang_trace *p);
int ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p);
int ei_encode_tuple_header(char *buf, int *index, int arity);
@@ -528,8 +560,6 @@ int ei_x_encode_map_header(ei_x_buff* x, long n);
*/
int ei_get_type(const char *buf, const int *index, int *type, int *size);
-int ei_get_type_internal(const char *buf, const int *index, int *type,
- int *size);
/* Step through buffer, decoding the given type into the buffer
* provided. On success, 0 is returned and index is updated to point
@@ -548,12 +578,15 @@ int ei_decode_string(const char *buf, int *index, char *p);
int ei_decode_atom(const char *buf, int *index, char *p);
int ei_decode_atom_as(const char *buf, int *index, char *p, int destlen, erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result);
int ei_decode_binary(const char *buf, int *index, void *p, long *len);
+int ei_decode_bitstring(const char *buf, int *index, const char** pp,
+ unsigned int* bitoffsp, size_t *nbitsp);
+
int ei_decode_fun(const char* buf, int* index, erlang_fun* p);
void free_fun(erlang_fun* f);
int ei_decode_pid(const char *buf, int *index, erlang_pid *p);
int ei_decode_port(const char *buf, int *index, erlang_port *p);
int ei_decode_ref(const char *buf, int *index, erlang_ref *p);
-int ei_decode_term(const char *buf, int *index, void *t); /* ETERM** actually */
+int ei_decode_term(const char *buf, int *index, void *t) EI_DEPRECATED_ATTR;
int ei_decode_trace(const char *buf, int *index, erlang_trace *p);
int ei_decode_tuple_header(const char *buf, int *index, int *arity);
int ei_decode_list_header(const char *buf, int *index, int *arity);
diff --git a/lib/erl_interface/include/erl_interface.h b/lib/erl_interface/include/erl_interface.h
index c22f21af2b..7c87223a38 100644
--- a/lib/erl_interface/include/erl_interface.h
+++ b/lib/erl_interface/include/erl_interface.h
@@ -25,8 +25,6 @@
/* Note: the 'ei' interface is the prefered C API. */
/************************************************************************/
-/* FIXME only include if needed? */
-
#include "ei.h" /* ei is the base */
/* -------------------------------------------------------------------- */
@@ -195,11 +193,11 @@ typedef struct {
int lenL;
} Erl_Atom_data;
-char* erl_atom_ptr_latin1(Erl_Atom_data*);
-char* erl_atom_ptr_utf8(Erl_Atom_data*);
-int erl_atom_size_latin1(Erl_Atom_data*);
-int erl_atom_size_utf8(Erl_Atom_data*);
-char* erl_atom_init_latin1(Erl_Atom_data*, const char*);
+char* erl_atom_ptr_latin1(Erl_Atom_data*) EI_DEPRECATED_ATTR;
+char* erl_atom_ptr_utf8(Erl_Atom_data*) EI_DEPRECATED_ATTR;
+int erl_atom_size_latin1(Erl_Atom_data*) EI_DEPRECATED_ATTR;
+int erl_atom_size_utf8(Erl_Atom_data*) EI_DEPRECATED_ATTR;
+char* erl_atom_init_latin1(Erl_Atom_data*, const char*) EI_DEPRECATED_ATTR;
typedef struct {
Erl_Header h;
@@ -324,110 +322,117 @@ typedef unsigned char Erl_Heap;
/* The functions */
/* -------------------------------------------------------------------- */
-void erl_init(void *x, long y);
-void erl_set_compat_rel(unsigned);
-int erl_connect_init(int, char*,short);
-int erl_connect_xinit(char*,char*,char*,struct in_addr*,char*,short);
-int erl_connect(char*);
-int erl_xconnect(struct in_addr*,char *);
-int erl_close_connection(int);
-int erl_receive(int, unsigned char*, int);
-int erl_receive_msg(int, unsigned char*, int, ErlMessage*);
-int erl_xreceive_msg(int, unsigned char**, int*, ErlMessage*);
-int erl_send(int, ETERM*, ETERM*);
-int erl_reg_send(int, char*, ETERM*);
-ETERM *erl_rpc(int,char*,char*,ETERM*);
-int erl_rpc_to(int,char*,char*,ETERM*);
-int erl_rpc_from(int,int,ErlMessage*);
+void erl_init(void *x, long y) EI_DEPRECATED_ATTR;
+void erl_set_compat_rel(unsigned) EI_DEPRECATED_ATTR;
+int erl_connect_init(int, char*,short) EI_DEPRECATED_ATTR;
+int erl_connect_xinit(char*,char*,char*,struct in_addr*,char*,short) EI_DEPRECATED_ATTR;
+int erl_connect(char*) EI_DEPRECATED_ATTR;
+int erl_xconnect(struct in_addr*,char *) EI_DEPRECATED_ATTR;
+int erl_close_connection(int) EI_DEPRECATED_ATTR;
+int erl_receive(int, unsigned char*, int) EI_DEPRECATED_ATTR;
+int erl_receive_msg(int, unsigned char*, int, ErlMessage*) EI_DEPRECATED_ATTR;
+int erl_xreceive_msg(int, unsigned char**, int*, ErlMessage*) EI_DEPRECATED_ATTR;
+int erl_send(int, ETERM*, ETERM*) EI_DEPRECATED_ATTR;
+int erl_reg_send(int, char*, ETERM*) EI_DEPRECATED_ATTR;
+ETERM *erl_rpc(int,char*,char*,ETERM*) EI_DEPRECATED_ATTR;
+int erl_rpc_to(int,char*,char*,ETERM*) EI_DEPRECATED_ATTR;
+int erl_rpc_from(int,int,ErlMessage*) EI_DEPRECATED_ATTR;
/* erl_publish returns open descriptor on success, or -1 */
-int erl_publish(int port);
-int erl_accept(int,ErlConnect*);
+int erl_publish(int port) EI_DEPRECATED_ATTR;
+int erl_accept(int,ErlConnect*) EI_DEPRECATED_ATTR;
-const char *erl_thiscookie(void);
-const char *erl_thisnodename(void);
-const char *erl_thishostname(void);
-const char *erl_thisalivename(void);
-short erl_thiscreation(void);
+const char *erl_thiscookie(void) EI_DEPRECATED_ATTR;
+const char *erl_thisnodename(void) EI_DEPRECATED_ATTR;
+const char *erl_thishostname(void) EI_DEPRECATED_ATTR;
+const char *erl_thisalivename(void) EI_DEPRECATED_ATTR;
+short erl_thiscreation(void) EI_DEPRECATED_ATTR;
/* returns 0 on success, -1 if node not known to epmd or epmd not reached */
-int erl_unpublish(const char *alive);
+int erl_unpublish(const char *alive) EI_DEPRECATED_ATTR;
+
+#ifdef EI_HAVE_DEPRECATED_ATTR__
+#define EI_DEPR_ATTR_EXTRA , EI_DEPRECATED_ATTR_NAME
+#else
+#define EI_DEPR_ATTR_EXTRA
+#endif
+
/* Report generic error to stderr. */
void erl_err_msg(const char * __template, ...)
- __attribute__ ((__format__ (printf, 1, 2)));
+ __attribute__ ((__format__ (printf, 1, 2) EI_DEPR_ATTR_EXTRA)) ;
/* Report generic error to stderr and die. */
void erl_err_quit(const char * __template, ...)
- __attribute__ ((__format__ (printf, 1, 2), __noreturn__));
+ __attribute__ ((__format__ (printf, 1, 2), __noreturn__ EI_DEPR_ATTR_EXTRA));
/* Report system/libc error to stderr. */
void erl_err_ret(const char * __template, ...)
- __attribute__ ((__format__ (printf, 1, 2)));
+ __attribute__ ((__format__ (printf, 1, 2) EI_DEPR_ATTR_EXTRA));
/* Report system/libc error to stderr and die. */
void erl_err_sys(const char * __template, ...)
- __attribute__ ((__format__ (printf, 1, 2), __noreturn__));
-
-ETERM *erl_cons(ETERM*,ETERM*);
-ETERM *erl_copy_term(const ETERM*);
-ETERM *erl_element(int,const ETERM*);
-
-ETERM *erl_hd(const ETERM*);
-ETERM* erl_iolist_to_binary(const ETERM* term);
-char* erl_iolist_to_string(const ETERM* term);
-int erl_iolist_length(const ETERM*);
-int erl_length(const ETERM*);
-ETERM *erl_mk_atom(const char*);
-ETERM *erl_mk_binary(const char*,int);
-ETERM *erl_mk_empty_list(void);
-ETERM *erl_mk_estring(const char*, int);
-ETERM *erl_mk_float(double);
-ETERM *erl_mk_int(int);
-ETERM *erl_mk_longlong(long long);
-ETERM *erl_mk_list(ETERM**,int);
-ETERM *erl_mk_pid(const char*,unsigned int,unsigned int,unsigned char);
-ETERM *erl_mk_port(const char*,unsigned int,unsigned char);
-ETERM *erl_mk_ref(const char*,unsigned int,unsigned char);
+ __attribute__ ((__format__ (printf, 1, 2), __noreturn__ EI_DEPR_ATTR_EXTRA));
+
+ETERM *erl_cons(ETERM*,ETERM*) EI_DEPRECATED_ATTR;
+ETERM *erl_copy_term(const ETERM*) EI_DEPRECATED_ATTR;
+ETERM *erl_element(int,const ETERM*) EI_DEPRECATED_ATTR;
+
+ETERM *erl_hd(const ETERM*) EI_DEPRECATED_ATTR;
+ETERM* erl_iolist_to_binary(const ETERM* term) EI_DEPRECATED_ATTR;
+char* erl_iolist_to_string(const ETERM* term) EI_DEPRECATED_ATTR;
+int erl_iolist_length(const ETERM*) EI_DEPRECATED_ATTR;
+int erl_length(const ETERM*) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_atom(const char*) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_binary(const char*,int) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_empty_list(void) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_estring(const char*, int) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_float(double) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_int(int) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_longlong(long long) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_list(ETERM**,int) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_pid(const char*,unsigned int,unsigned int,unsigned char) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_port(const char*,unsigned int,unsigned char) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_ref(const char*,unsigned int,unsigned char) EI_DEPRECATED_ATTR;
ETERM *erl_mk_long_ref(const char*,unsigned int,unsigned int,
- unsigned int,unsigned char);
-ETERM *erl_mk_string(const char*);
-ETERM *erl_mk_tuple(ETERM**,int);
-ETERM *erl_mk_uint(unsigned int);
-ETERM *erl_mk_ulonglong(unsigned long long);
-ETERM *erl_mk_var(const char*);
-int erl_print_term(FILE*,const ETERM*);
-/* int erl_sprint_term(char*,const ETERM*); */
-int erl_size(const ETERM*);
-ETERM *erl_tl(const ETERM*);
-ETERM *erl_var_content(const ETERM*, const char*);
-
-ETERM *erl_format(char*, ... );
-int erl_match(ETERM*, ETERM*);
-
-char **erl_global_names(int fd, int *count);
-int erl_global_register(int fd, const char *name, ETERM *pid);
-int erl_global_unregister(int fd, const char *name);
-ETERM *erl_global_whereis(int fd, const char *name, char *node);
-
-void erl_init_malloc(Erl_Heap*,long);
-ETERM *erl_alloc_eterm(unsigned char);
-void erl_eterm_release(void);
-void erl_eterm_statistics(unsigned long*,unsigned long*);
-void erl_free_array(ETERM**,int);
-void erl_free_term(ETERM*);
-void erl_free_compound(ETERM*);
-void *erl_malloc(long);
-void erl_free(void*);
-
-int erl_compare_ext(unsigned char*, unsigned char*);
-ETERM *erl_decode(unsigned char*);
-ETERM *erl_decode_buf(unsigned char**);
-int erl_encode(ETERM*,unsigned char*t);
-int erl_encode_buf(ETERM*,unsigned char**);
-int erl_ext_size(unsigned char*);
-unsigned char erl_ext_type(unsigned char*); /* Note: returned 'char' before R9C */
-unsigned char *erl_peek_ext(unsigned char*,int);
-int erl_term_len(ETERM*);
-
-int cmp_latin1_vs_utf8(const char* sL, int lenL, const char* sU, int lenU);
+ unsigned int,unsigned char) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_string(const char*) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_tuple(ETERM**,int) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_uint(unsigned int) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_ulonglong(unsigned long long) EI_DEPRECATED_ATTR;
+ETERM *erl_mk_var(const char*) EI_DEPRECATED_ATTR;
+int erl_print_term(FILE*,const ETERM*) EI_DEPRECATED_ATTR;
+/* int erl_sprint_term(char*,const ETERM*) EI_DEPRECATED_ATTR; */
+int erl_size(const ETERM*) EI_DEPRECATED_ATTR;
+ETERM *erl_tl(const ETERM*) EI_DEPRECATED_ATTR;
+ETERM *erl_var_content(const ETERM*, const char*) EI_DEPRECATED_ATTR;
+
+ETERM *erl_format(char*, ... ) EI_DEPRECATED_ATTR;
+int erl_match(ETERM*, ETERM*) EI_DEPRECATED_ATTR;
+
+char **erl_global_names(int fd, int *count) EI_DEPRECATED_ATTR;
+int erl_global_register(int fd, const char *name, ETERM *pid) EI_DEPRECATED_ATTR;
+int erl_global_unregister(int fd, const char *name) EI_DEPRECATED_ATTR;
+ETERM *erl_global_whereis(int fd, const char *name, char *node) EI_DEPRECATED_ATTR;
+
+void erl_init_malloc(Erl_Heap*,long) EI_DEPRECATED_ATTR;
+ETERM *erl_alloc_eterm(unsigned char) EI_DEPRECATED_ATTR;
+void erl_eterm_release(void) EI_DEPRECATED_ATTR;
+void erl_eterm_statistics(unsigned long*,unsigned long*) EI_DEPRECATED_ATTR;
+void erl_free_array(ETERM**,int) EI_DEPRECATED_ATTR;
+void erl_free_term(ETERM*) EI_DEPRECATED_ATTR;
+void erl_free_compound(ETERM*) EI_DEPRECATED_ATTR;
+void *erl_malloc(long) EI_DEPRECATED_ATTR;
+void erl_free(void*) EI_DEPRECATED_ATTR;
+
+int erl_compare_ext(unsigned char*, unsigned char*) EI_DEPRECATED_ATTR;
+ETERM *erl_decode(unsigned char*) EI_DEPRECATED_ATTR;
+ETERM *erl_decode_buf(unsigned char**) EI_DEPRECATED_ATTR;
+int erl_encode(ETERM*,unsigned char*t) EI_DEPRECATED_ATTR;
+int erl_encode_buf(ETERM*,unsigned char**) EI_DEPRECATED_ATTR;
+int erl_ext_size(unsigned char*) EI_DEPRECATED_ATTR;
+unsigned char erl_ext_type(unsigned char*) EI_DEPRECATED_ATTR; /* Note: returned 'char' before R9C */
+unsigned char *erl_peek_ext(unsigned char*,int) EI_DEPRECATED_ATTR;
+int erl_term_len(ETERM*) EI_DEPRECATED_ATTR;
+
+int cmp_latin1_vs_utf8(const char* sL, int lenL, const char* sU, int lenU) EI_DEPRECATED_ATTR;
/* -------------------------------------------------------------------- */
/* Wrappers around ei functions */
@@ -437,29 +442,29 @@ int cmp_latin1_vs_utf8(const char* sL, int lenL, const char* sU, int lenU);
* Undocumented before R9C, included for compatibility with old code
*/
-struct hostent *erl_gethostbyname(const char *name);
-struct hostent *erl_gethostbyaddr(const char *addr, int len, int type);
+struct hostent *erl_gethostbyname(const char *name) EI_DEPRECATED_ATTR;
+struct hostent *erl_gethostbyaddr(const char *addr, int len, int type) EI_DEPRECATED_ATTR;
struct hostent *erl_gethostbyname_r(const char *name,
struct hostent *hostp,
char *buffer,
int buflen,
- int *h_errnop);
+ int *h_errnop) EI_DEPRECATED_ATTR;
struct hostent *erl_gethostbyaddr_r(const char *addr,
int length,
int type,
struct hostent *hostp,
char *buffer,
int buflen,
- int *h_errnop);
+ int *h_errnop) EI_DEPRECATED_ATTR;
/*
* Undocumented, included for compatibility with old code
*/
-void erl_init_resolve(void);
-int erl_distversion(int fd);
-int erl_epmd_connect(struct in_addr *inaddr);
-int erl_epmd_port(struct in_addr *inaddr, const char *alive, int *dist);
+void erl_init_resolve(void) EI_DEPRECATED_ATTR;
+int erl_distversion(int fd) EI_DEPRECATED_ATTR;
+int erl_epmd_connect(struct in_addr *inaddr) EI_DEPRECATED_ATTR;
+int erl_epmd_port(struct in_addr *inaddr, const char *alive, int *dist) EI_DEPRECATED_ATTR;
#ifdef __cplusplus
}
diff --git a/lib/erl_interface/src/INSTALL b/lib/erl_interface/src/INSTALL
index b42a17ac46..bf3ca8b6a5 100644
--- a/lib/erl_interface/src/INSTALL
+++ b/lib/erl_interface/src/INSTALL
@@ -122,10 +122,10 @@ you can use the `configure' options `--x-includes=DIR' and
Specifying the System Type
==========================
- There may be some features `configure' can not figure out
+ There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
-a message saying it can not guess the host type, give it the
+a message saying it cannot guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
diff --git a/lib/erl_interface/src/Makefile b/lib/erl_interface/src/Makefile
index 800557fbfe..00c49f1622 100644
--- a/lib/erl_interface/src/Makefile
+++ b/lib/erl_interface/src/Makefile
@@ -27,7 +27,9 @@ include $(ERL_TOP)/make/output.mk
include $(ERL_TOP)/make/target.mk
debug opt shared purify quantify purecov gcov:
+ifndef TERTIARY_BOOTSTRAP
$(make_verbose)$(MAKE) -f $(TARGET)/Makefile TYPE=$@
+endif
clean depend docs release release_docs tests release_tests check xmllint:
$(make_verbose)$(MAKE) -f $(TARGET)/Makefile $@
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index 2c1a8252ae..6e0d3476c7 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -31,6 +31,8 @@
.PHONY : debug opt release clean distclean depend
+include $(ERL_TOP)/make/target.mk
+
# ----------------------------------------------------
# Application version and release dir specification
# ----------------------------------------------------
@@ -125,6 +127,8 @@ else
WARNFLAGS = @WFLAGS@
endif
+WARNFLAGS += -DEI_NO_DEPR_WARN
+
CFLAGS = @LIB_CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS)
PROG_CFLAGS = @CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -Ilegacy
diff --git a/lib/erl_interface/src/README.internal b/lib/erl_interface/src/README.internal
index c1f2d6863f..42c45b46a9 100644
--- a/lib/erl_interface/src/README.internal
+++ b/lib/erl_interface/src/README.internal
@@ -167,12 +167,12 @@ NOTE!!!! Sending a "char" to macros like isupper(), isalpha() where
the character is > 127 will cause serios problems on some
machines/OS. The reason is that
- 'char' may be unsigned, i.e. the Swedish char '�' will
+ 'char' may be unsigned, i.e. the Swedish char 'ä' will
as a number be negativ.
The implementation of isupper() and others will on some
machines use an array that is indexed with the incoming
- character code. The Swedish '�' will then create an access
+ character code. The Swedish 'ä' will then create an access
on memory outside the array!
This may give a random value as a result or a segmentation
@@ -219,7 +219,7 @@ There are some functions in the 'ei' library that uses the GCC and
VC++ "long long" type. Unfortunately this can lead to some trouble.
When user code is linked with the "libei.a" the linker will extract
-all objects files needed for resolving all symbol referenses
+all objects files needed for resolving all symbol references
found. This means that you want to follow the rule that
* To reduce executable code size we use resonably small C source
@@ -252,7 +252,7 @@ example is that in plain R9C the ei_x_encode_longlong() function is
located in the file "ei_x_encode.c". So if any "long long" ei_x
function is used we have an unessesary dependency on
"ei_encode_longlong.o" and then need to link with GNU ld on with the
-user code or explicitely link with "libgcc.a". The situation can be
+user code or explicitly link with "libgcc.a". The situation can be
visible in in plain R9C using
% nm -A erl_interface-3.4/lib/libei.a | \
diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c
index 95cb10a20c..1b1479d2e9 100644
--- a/lib/erl_interface/src/connect/ei_connect.c
+++ b/lib/erl_interface/src/connect/ei_connect.c
@@ -1854,6 +1854,7 @@ static int send_name_or_challenge(ei_socket_callbacks *cbs,
const char* function[] = {"SEND_NAME", "SEND_CHALLENGE"};
int err;
ssize_t len;
+ unsigned int flags;
if (f_chall)
siz += 4;
@@ -1875,7 +1876,7 @@ static int send_name_or_challenge(ei_socket_callbacks *cbs,
}
put8(s, 'n');
put16be(s, version);
- put32be(s, (DFLAG_EXTENDED_REFERENCES
+ flags = (DFLAG_EXTENDED_REFERENCES
| DFLAG_DIST_MONITOR
| DFLAG_EXTENDED_PIDS_PORTS
| DFLAG_FUN_TAGS
@@ -1884,7 +1885,14 @@ static int send_name_or_challenge(ei_socket_callbacks *cbs,
| DFLAG_SMALL_ATOM_TAGS
| DFLAG_UTF8_ATOMS
| DFLAG_MAP_TAG
- | DFLAG_BIG_CREATION));
+ | DFLAG_BIG_CREATION
+ | DFLAG_EXPORT_PTR_TAG
+ | DFLAG_BIT_BINARIES);
+ if (ei_internal_use_21_bitstr_expfun()) {
+ flags &= ~(DFLAG_EXPORT_PTR_TAG
+ | DFLAG_BIT_BINARIES);
+ }
+ put32be(s, flags);
if (f_chall)
put32be(s, challenge);
memcpy(s, nodename, strlen(nodename));
@@ -1949,8 +1957,7 @@ static int recv_challenge(ei_socket_callbacks *cbs, void *ctx,
goto error;
}
- if (!(*flags & DFLAG_EXTENDED_PIDS_PORTS)
- && !ei_internal_use_r9_pids_ports()) {
+ if (!(*flags & DFLAG_EXTENDED_PIDS_PORTS)) {
EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE peer cannot "
"handle extended pids and ports");
erl_errno = EIO;
@@ -2244,8 +2251,7 @@ static int recv_name(ei_socket_callbacks *cbs, void *ctx,
goto error;
}
- if (!(*flags & DFLAG_EXTENDED_PIDS_PORTS)
- && !ei_internal_use_r9_pids_ports()) {
+ if (!(*flags & DFLAG_EXTENDED_PIDS_PORTS)) {
EI_TRACE_ERR0("recv_name","<- RECV_NAME peer cannot "
"handle extended pids and ports");
erl_errno = EIO;
diff --git a/lib/erl_interface/src/connect/ei_connect_int.h b/lib/erl_interface/src/connect/ei_connect_int.h
index 0bcccaa84b..b41a5f2b23 100644
--- a/lib/erl_interface/src/connect/ei_connect_int.h
+++ b/lib/erl_interface/src/connect/ei_connect_int.h
@@ -102,6 +102,8 @@ extern int h_errno;
#define DFLAG_FUN_TAGS 16
#define DFLAG_NEW_FUN_TAGS 0x80
#define DFLAG_EXTENDED_PIDS_PORTS 0x100
+#define DFLAG_EXPORT_PTR_TAG 0x200
+#define DFLAG_BIT_BINARIES 0x400
#define DFLAG_NEW_FLOATS 0x800
#define DFLAG_SMALL_ATOM_TAGS 0x4000
#define DFLAG_UTF8_ATOMS 0x10000
diff --git a/lib/erl_interface/src/decode/decode_binary.c b/lib/erl_interface/src/decode/decode_binary.c
index 5b8d234984..0d28c67230 100644
--- a/lib/erl_interface/src/decode/decode_binary.c
+++ b/lib/erl_interface/src/decode/decode_binary.c
@@ -40,4 +40,41 @@ int ei_decode_binary(const char *buf, int *index, void *p, long *lenp)
return 0;
}
+int ei_decode_bitstring(const char *buf, int *index,
+ const char** pp,
+ unsigned int* bitoffsp,
+ size_t *nbitsp)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ unsigned char last_bits;
+ const unsigned char tag = get8(s);
+ size_t len = get32be(s);
+
+ switch(tag) {
+ case ERL_BINARY_EXT:
+ if (nbitsp)
+ *nbitsp = len * 8;
+ break;
+ case ERL_BIT_BINARY_EXT:
+ last_bits = get8(s);
+ if (((last_bits==0) != (len==0)) || last_bits > 8)
+ return -1;
+
+ if (nbitsp)
+ *nbitsp = (len == 0) ? 0 : ((len-1) * 8) + last_bits;
+ break;
+ default:
+ return -1;
+ }
+
+ if (pp)
+ *pp = s;
+ if (bitoffsp)
+ *bitoffsp = 0;
+
+ s += len;
+ *index += s-s0;
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c
index f944c028af..db71007505 100644
--- a/lib/erl_interface/src/decode/decode_fun.c
+++ b/lib/erl_interface/src/decode/decode_fun.c
@@ -33,22 +33,20 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
int i, ix, ix0, n;
erlang_pid* p_pid;
char* p_module;
- erlang_char_encoding* p_module_org_enc;
long* p_index;
long* p_uniq;
long* p_old_index;
if (p != NULL) {
- p_pid = &p->pid;
+ p_pid = &p->u.closure.pid;
p_module = &p->module[0];
- p_module_org_enc = &p->module_org_enc;
- p_index = &p->index;
- p_uniq = &p->uniq;
- p_old_index = &p->old_index;
+ p_index = &p->u.closure.index;
+ p_uniq = &p->u.closure.uniq;
+ p_old_index = &p->u.closure.old_index;
}
else {
- p_pid = NULL; p_module = NULL; p_module_org_enc = NULL;
p_index = NULL; p_uniq = NULL; p_old_index = NULL;
+ p_pid = NULL; p_module = NULL;
}
switch (get8(s)) {
@@ -63,7 +61,7 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
return -1;
/* then the module (atom) */
if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8,
- p_module_org_enc, NULL) < 0)
+ NULL, NULL) < 0)
return -1;
/* then the index */
if (ei_decode_long(s, &ix, p_index) < 0)
@@ -78,11 +76,13 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
return -1;
}
if (p != NULL) {
- p->n_free_vars = n;
- p->free_var_len = ix - ix0;
- p->free_vars = ei_malloc(ix - ix0);
- if (!(p->free_vars)) return -1;
- memcpy(p->free_vars, s + ix0, ix - ix0);
+ p->u.closure.n_free_vars = n;
+ p->u.closure.free_var_len = ix - ix0;
+ if (p->u.closure.free_var_len > 0) {
+ p->u.closure.free_vars = ei_malloc(p->u.closure.free_var_len);
+ if (!(p->u.closure.free_vars)) return -1;
+ memcpy(p->u.closure.free_vars, s + ix0, p->u.closure.free_var_len);
+ }
}
s += ix;
*index += s-s0;
@@ -93,20 +93,23 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
n = get32be(s);
/* then the arity */
i = get8(s);
- if (p != NULL) p->arity = i;
- /* then md5 */
- if (p != NULL) memcpy(p->md5, s, 16);
+ if (p != NULL) {
+ p->type = EI_FUN_CLOSURE;
+ p->arity = i;
+ /* then md5 */
+ memcpy(p->u.closure.md5, s, 16);
+ }
s += 16;
/* then index */
i = get32be(s);
- if (p != NULL) p->index = i;
+ if (p != NULL) p->u.closure.index = i;
/* then the number of free vars (environment) */
i = get32be(s);
- if (p != NULL) p->n_free_vars = i;
+ if (p != NULL) p->u.closure.n_free_vars = i;
/* then the module (atom) */
ix = 0;
if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8,
- p_module_org_enc, NULL) < 0)
+ NULL, NULL) < 0)
return -1;
/* then the old_index */
if (ei_decode_long(s, &ix, p_old_index) < 0)
@@ -122,17 +125,59 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
n = n - (s - s0) + 1;
if (n < 0) return -1;
if (p != NULL) {
- p->free_var_len = n;
+ p->u.closure.free_var_len = n;
if (n > 0) {
- p->free_vars = malloc(n);
- if (!(p->free_vars)) return -1;
- memcpy(p->free_vars, s, n);
+ p->u.closure.free_vars = malloc(n);
+ if (!(p->u.closure.free_vars)) return -1;
+ memcpy(p->u.closure.free_vars, s, n);
}
}
s += n;
*index += s-s0;
return 0;
break;
+ case ERL_EXPORT_EXT: {
+ char* p_func;
+ long* p_arity;
+ int used;
+
+ if (p) {
+ p->type = EI_FUN_EXPORT;
+ p_arity = &p->arity;
+ }
+ else {
+ p_arity = NULL;
+ }
+ ix = 0;
+ if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8,
+ NULL, NULL) < 0)
+ return -1;
+ if (p) {
+ /* try use module buffer for function name */
+ used = strlen(p->module) + 1;
+ p_func = p->module + used;
+ p->u.exprt.func = p_func;
+ p->u.exprt.func_allocated = 0;
+ }
+ else {
+ used = 0;
+ p_func = NULL;
+ }
+ while (ei_decode_atom_as(s, &ix, p_func, MAXATOMLEN_UTF8-used,
+ ERLANG_UTF8, NULL, NULL) < 0) {
+ if (!used)
+ return -1;
+ p_func = malloc(MAXATOMLEN_UTF8);
+ p->u.exprt.func = p_func;
+ p->u.exprt.func_allocated = 1;
+ used = 0;
+ }
+ if (ei_decode_long(s, &ix, p_arity) < 0)
+ return -1;
+ s += ix;
+ *index += s - s0;
+ return 0;
+ }
default:
return -1;
}
@@ -140,6 +185,14 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
void free_fun(erlang_fun* f)
{
- if (f->free_var_len > 0)
- ei_free(f->free_vars);
+ switch (f->type) {
+ case EI_FUN_CLOSURE:
+ if (f->u.closure.free_var_len > 0)
+ ei_free(f->u.closure.free_vars);
+ break;
+ case EI_FUN_EXPORT:
+ if (f->u.exprt.func_allocated)
+ ei_free(f->u.exprt.func);
+ break;
+ }
}
diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c
index 0db315f09b..0622ce7d59 100644
--- a/lib/erl_interface/src/decode/decode_skip.c
+++ b/lib/erl_interface/src/decode/decode_skip.c
@@ -27,7 +27,7 @@ int ei_skip_term(const char* buf, int* index)
/* ASSERT(ep != NULL); */
- ei_get_type_internal(buf, index, &ty, &n);
+ ei_get_type(buf, index, &ty, &n);
switch (ty) {
case ERL_ATOM_EXT:
/* FIXME: what if some weird locale is in use? */
@@ -54,7 +54,7 @@ int ei_skip_term(const char* buf, int* index)
if (ei_decode_list_header(buf, index, &n) < 0) return -1;
for (i = 0; i < n; ++i)
ei_skip_term(buf, index);
- if (ei_get_type_internal(buf, index, &ty, &n) < 0) return -1;
+ if (ei_get_type(buf, index, &ty, &n) < 0) return -1;
if (ty != ERL_NIL_EXT)
ei_skip_term(buf, index);
else
@@ -79,6 +79,10 @@ int ei_skip_term(const char* buf, int* index)
if (ei_decode_binary(buf, index, NULL, NULL) < 0)
return -1;
break;
+ case ERL_BIT_BINARY_EXT:
+ if (ei_decode_bitstring(buf, index, NULL, NULL, NULL) < 0)
+ return -1;
+ break;
case ERL_SMALL_INTEGER_EXT:
case ERL_INTEGER_EXT:
if (ei_decode_long(buf, index, NULL) < 0) return -1;
@@ -93,6 +97,7 @@ int ei_skip_term(const char* buf, int* index)
break;
case ERL_FUN_EXT:
case ERL_NEW_FUN_EXT:
+ case ERL_EXPORT_EXT:
if (ei_decode_fun(buf, index, NULL) < 0) return -1;
break;
default:
diff --git a/lib/erl_interface/src/encode/encode_binary.c b/lib/erl_interface/src/encode/encode_binary.c
index 4471c51769..0562979417 100644
--- a/lib/erl_interface/src/encode/encode_binary.c
+++ b/lib/erl_interface/src/encode/encode_binary.c
@@ -22,6 +22,10 @@
#include "eiext.h"
#include "putget.h"
+static void copy_bits(const unsigned char* src, size_t soffs,
+ unsigned char* dst, size_t n);
+
+
int ei_encode_binary(char *buf, int *index, const void *p, long len)
{
char *s = buf + *index;
@@ -40,3 +44,106 @@ int ei_encode_binary(char *buf, int *index, const void *p, long len)
return 0;
}
+int ei_encode_bitstring(char *buf, int *index,
+ const char *p,
+ size_t bitoffs,
+ size_t bits)
+{
+ char *s = buf + *index;
+ char *s0 = s;
+ size_t bytes = (bits + 7) / 8;
+ char last_bits = bits % 8;
+
+ if (!buf) s += last_bits ? 6 : 5;
+ else {
+ char* tagp = s++;
+ put32be(s, bytes);
+ if (last_bits) {
+ *tagp = ERL_BIT_BINARY_EXT;
+ put8(s, last_bits);
+ }
+ else
+ *tagp = ERL_BINARY_EXT;
+
+ copy_bits((const unsigned char*)p, bitoffs, (unsigned char*)s, bits);
+ }
+ s += bytes;
+
+ *index += s-s0;
+
+ return 0;
+}
+
+
+/*
+ * MAKE_MASK(n) constructs a mask with n bits.
+ * Example: MAKE_MASK(3) returns the binary number 00000111.
+ */
+#define MAKE_MASK(n) ((((unsigned) 1) << (n))-1)
+
+
+static
+void copy_bits(const unsigned char* src, /* Base pointer to source. */
+ size_t soffs, /* Bit offset for source relative to src. */
+ unsigned char* dst, /* Destination. */
+ size_t n) /* Number of bits to copy. */
+{
+ unsigned rmask;
+ unsigned count;
+ unsigned deoffs;
+ unsigned bits;
+ unsigned bits1;
+ unsigned rshift;
+
+ if (n == 0)
+ return;
+
+ deoffs = n & 7;
+ rmask = deoffs ? (MAKE_MASK(deoffs) << (8-deoffs)) : 0;
+
+ if (soffs == 0) {
+ unsigned nbytes = (n + 7) / 8;
+ memcpy(dst, src, nbytes);
+ if (rmask)
+ dst[nbytes-1] &= rmask;
+ return;
+ }
+
+ src += soffs / 8;
+ soffs &= 7;
+
+ if (n < 8) { /* Less than one byte */
+ bits = (*src << soffs);
+ if (soffs+n > 8) {
+ src++;
+ bits |= (*src >> (8 - soffs));
+ }
+ *dst = bits & rmask;
+ return;
+ }
+
+ count = n >> 3;
+
+ rshift = 8 - soffs;
+ bits = *src;
+ if (soffs + n > 8) {
+ src++;
+ }
+
+ while (count--) {
+ bits1 = bits << soffs;
+ bits = *src;
+ src++;
+ *dst = bits1 | (bits >> rshift);
+ dst++;
+ }
+
+ if (rmask) {
+ bits1 = bits << soffs;
+ if ((rmask << rshift) & 0xff) {
+ bits = *src;
+ bits1 |= (bits >> rshift);
+ }
+ *dst = bits1 & rmask;
+ }
+}
diff --git a/lib/erl_interface/src/encode/encode_fun.c b/lib/erl_interface/src/encode/encode_fun.c
index 3bfc7530d1..e29424f9f4 100644
--- a/lib/erl_interface/src/encode/encode_fun.c
+++ b/lib/erl_interface/src/encode/encode_fun.c
@@ -26,56 +26,72 @@ int ei_encode_fun(char *buf, int *index, const erlang_fun *p)
{
int ix = *index;
- if (p->arity == -1) {
- /* ERL_FUN_EXT */
- if (buf != NULL) {
- char* s = buf + ix;
- put8(s, ERL_FUN_EXT);
- put32be(s, p->n_free_vars);
- }
- ix += sizeof(char) + 4;
- if (ei_encode_pid(buf, &ix, &p->pid) < 0)
- return -1;
- if (ei_encode_atom_as(buf, &ix, p->module, ERLANG_UTF8, p->module_org_enc) < 0)
- return -1;
- if (ei_encode_long(buf, &ix, p->index) < 0)
- return -1;
- if (ei_encode_long(buf, &ix, p->uniq) < 0)
- return -1;
- if (buf != NULL)
- memcpy(buf + ix, p->free_vars, p->free_var_len);
- ix += p->free_var_len;
- } else {
- char *size_p;
- /* ERL_NEW_FUN_EXT */
- if (buf != NULL) {
- char* s = buf + ix;
- put8(s, ERL_NEW_FUN_EXT);
- size_p = s;
- s += 4;
- put8(s, p->arity);
- memcpy(s, p->md5, sizeof(p->md5));
- s += sizeof(p->md5);
- put32be(s, p->index);
- put32be(s, p->n_free_vars);
- } else
- size_p = NULL;
- ix += 1 + 4 + 1 + sizeof(p->md5) + 4 + 4;
- if (ei_encode_atom_as(buf, &ix, p->module, ERLANG_UTF8, p->module_org_enc) < 0)
- return -1;
- if (ei_encode_long(buf, &ix, p->old_index) < 0)
- return -1;
- if (ei_encode_long(buf, &ix, p->uniq) < 0)
- return -1;
- if (ei_encode_pid(buf, &ix, &p->pid) < 0)
- return -1;
- if (buf != NULL)
- memcpy(buf + ix, p->free_vars, p->free_var_len);
- ix += p->free_var_len;
- if (size_p != NULL) {
- int sz = buf + ix - size_p;
- put32be(size_p, sz);
+ switch (p->type) {
+ case EI_FUN_CLOSURE:
+ if (p->arity == -1) {
+ /* ERL_FUN_EXT */
+ if (buf != NULL) {
+ char* s = buf + ix;
+ put8(s, ERL_FUN_EXT);
+ put32be(s, p->u.closure.n_free_vars);
+ }
+ ix += sizeof(char) + 4;
+ if (ei_encode_pid(buf, &ix, &p->u.closure.pid) < 0)
+ return -1;
+ if (ei_encode_atom_as(buf, &ix, p->module, ERLANG_UTF8, ERLANG_UTF8) < 0)
+ return -1;
+ if (ei_encode_long(buf, &ix, p->u.closure.index) < 0)
+ return -1;
+ if (ei_encode_long(buf, &ix, p->u.closure.uniq) < 0)
+ return -1;
+ if (buf != NULL)
+ memcpy(buf + ix, p->u.closure.free_vars, p->u.closure.free_var_len);
+ ix += p->u.closure.free_var_len;
+ } else {
+ char *size_p;
+ if (buf != NULL) {
+ char* s = buf + ix;
+ put8(s, ERL_NEW_FUN_EXT);
+ size_p = s;
+ s += 4;
+ put8(s, p->arity);
+ memcpy(s, p->u.closure.md5, sizeof(p->u.closure.md5));
+ s += sizeof(p->u.closure.md5);
+ put32be(s, p->u.closure.index);
+ put32be(s, p->u.closure.n_free_vars);
+ } else
+ size_p = NULL;
+ ix += 1 + 4 + 1 + sizeof(p->u.closure.md5) + 4 + 4;
+ if (ei_encode_atom_as(buf, &ix, p->module, ERLANG_UTF8, ERLANG_UTF8) < 0)
+ return -1;
+ if (ei_encode_long(buf, &ix, p->u.closure.old_index) < 0)
+ return -1;
+ if (ei_encode_long(buf, &ix, p->u.closure.uniq) < 0)
+ return -1;
+ if (ei_encode_pid(buf, &ix, &p->u.closure.pid) < 0)
+ return -1;
+ if (buf != NULL)
+ memcpy(buf + ix, p->u.closure.free_vars, p->u.closure.free_var_len);
+ ix += p->u.closure.free_var_len;
+ if (size_p != NULL) {
+ int sz = buf + ix - size_p;
+ put32be(size_p, sz);
+ }
}
+ break;
+ case EI_FUN_EXPORT:
+ if (buf != NULL) {
+ char* s = buf + ix;
+ put8(s, ERL_EXPORT_EXT);
+ }
+ ix++;
+ if (ei_encode_atom_as(buf, &ix, p->module, ERLANG_UTF8, ERLANG_UTF8) < 0)
+ return -1;
+ if (ei_encode_atom_as(buf, &ix, p->u.exprt.func, ERLANG_UTF8, ERLANG_UTF8) < 0)
+ return -1;
+ if (ei_encode_long(buf, &ix, p->arity) < 0)
+ return -1;
+ break;
}
*index = ix;
return 0;
diff --git a/lib/erl_interface/src/legacy/erl_eterm.c b/lib/erl_interface/src/legacy/erl_eterm.c
index 7ed2bdbc93..7ecea83b1a 100644
--- a/lib/erl_interface/src/legacy/erl_eterm.c
+++ b/lib/erl_interface/src/legacy/erl_eterm.c
@@ -299,12 +299,7 @@ void erl_mk_pid_helper(ETERM *ep, unsigned int number,
unsigned int serial, unsigned int creation)
{
ERL_PID_NUMBER(ep) = number & 0x7fff; /* 15 bits */
- if (ei_internal_use_r9_pids_ports()) {
- ERL_PID_SERIAL(ep) = serial & 0x07; /* 3 bits */
- }
- else {
- ERL_PID_SERIAL(ep) = serial & 0x1fff; /* 13 bits */
- }
+ ERL_PID_SERIAL(ep) = serial & 0x1fff; /* 13 bits */
ERL_PID_CREATION(ep) = creation; /* 32 bits */
}
@@ -334,12 +329,7 @@ ETERM *erl_mk_port(const char *node,
void erl_mk_port_helper(ETERM* ep, unsigned number, unsigned int creation)
{
- if (ei_internal_use_r9_pids_ports()) {
- ERL_PORT_NUMBER(ep) = number & 0x3ffff; /* 18 bits */
- }
- else {
- ERL_PORT_NUMBER(ep) = number & 0x0fffffff; /* 18 bits */
- }
+ ERL_PORT_NUMBER(ep) = number & 0x0fffffff; /* 18 bits */
ERL_PORT_CREATION(ep) = creation; /* 32 bits */
}
diff --git a/lib/erl_interface/src/misc/ei_compat.c b/lib/erl_interface/src/misc/ei_compat.c
index 93d7dbfb83..787895992e 100644
--- a/lib/erl_interface/src/misc/ei_compat.c
+++ b/lib/erl_interface/src/misc/ei_compat.c
@@ -22,19 +22,22 @@
#include "ei.h"
#include "ei_internal.h"
-#define EI_COMPAT_NO_REL (~((unsigned) 0))
+#include <limits.h>
-static unsigned compat_rel = EI_COMPAT_NO_REL;
+#ifndef EI_COMPAT
+# define EI_COMPAT UINT_MAX
+#endif
+
+static unsigned compat_rel = EI_COMPAT;
void
ei_set_compat_rel(unsigned rel)
{
- if (compat_rel == EI_COMPAT_NO_REL)
- compat_rel = rel;
+ compat_rel = rel;
}
-int
-ei_internal_use_r9_pids_ports(void)
+int ei_internal_use_21_bitstr_expfun(void)
{
- return compat_rel < 10;
+ return compat_rel < 22;
}
+
diff --git a/lib/erl_interface/src/misc/ei_decode_term.c b/lib/erl_interface/src/misc/ei_decode_term.c
index 63a7034508..8a4f7cc30d 100644
--- a/lib/erl_interface/src/misc/ei_decode_term.c
+++ b/lib/erl_interface/src/misc/ei_decode_term.c
@@ -87,6 +87,14 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
case ERL_BINARY_EXT:
term->size = get32be(s);
return 0;
+ case ERL_BIT_BINARY_EXT: {
+ int bytes = get32be(s);
+ int last_bits = get8(s);
+ if (((last_bits==0) != (bytes==0)) || last_bits > 8)
+ return -1;
+ term->size = bytes;
+ return 0;
+ }
case ERL_SMALL_BIG_EXT:
if ((term->arity = get8(s)) != 4) return -1;
sign = get8(s);
diff --git a/lib/erl_interface/src/misc/ei_internal.h b/lib/erl_interface/src/misc/ei_internal.h
index f28dd6d668..ab12597c86 100644
--- a/lib/erl_interface/src/misc/ei_internal.h
+++ b/lib/erl_interface/src/misc/ei_internal.h
@@ -157,7 +157,7 @@ int ei_init_connect(void);
void ei_trace_printf(const char *name, int level, const char *format, ...);
-int ei_internal_use_r9_pids_ports(void);
+int ei_internal_use_21_bitstr_expfun(void);
int ei_get_cbs_ctx__(ei_socket_callbacks **cbs, void **ctx, int fd);
diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c
index 058de00de5..aee7f7eeb0 100644
--- a/lib/erl_interface/src/misc/ei_printterm.c
+++ b/lib/erl_interface/src/misc/ei_printterm.c
@@ -121,8 +121,10 @@ static int print_term(FILE* fp, ei_x_buff* x,
erlang_pid pid;
erlang_port port;
erlang_ref ref;
+ erlang_fun fun;
double d;
long l;
+ const char* delim;
int tindex = *index;
@@ -131,7 +133,7 @@ static int print_term(FILE* fp, ei_x_buff* x,
if (fp == NULL && x == NULL) return -1;
doquote = 0;
- ei_get_type_internal(buf, index, &ty, &n);
+ ei_get_type(buf, index, &ty, &n);
switch (ty) {
case ERL_ATOM_EXT:
case ERL_ATOM_UTF8_EXT:
@@ -189,7 +191,7 @@ static int print_term(FILE* fp, ei_x_buff* x,
xputs(", ", fp, x); ch_written += 2;
}
}
- if (ei_get_type_internal(buf, &tindex, &ty, &n) < 0) goto err;
+ if (ei_get_type(buf, &tindex, &ty, &n) < 0) goto err;
if (ty != ERL_NIL_EXT) {
xputs(" | ", fp, x); ch_written += 3;
r = print_term(fp, x, buf, &tindex);
@@ -239,16 +241,50 @@ static int print_term(FILE* fp, ei_x_buff* x,
m = BINPRINTSIZE;
else
m = l;
- --m;
+ delim = "";
for (i = 0; i < m; ++i) {
- ch_written += xprintf(fp, x, "%d,", p[i]);
+ ch_written += xprintf(fp, x, "%s%u", delim, (unsigned char)p[i]);
+ delim = ",";
}
- ch_written += xprintf(fp, x, "%d", p[i]);
if (l > BINPRINTSIZE)
ch_written += xprintf(fp, x, ",...");
xputc('>', fp, x); ++ch_written;
ei_free(p);
break;
+ case ERL_BIT_BINARY_EXT: {
+ const unsigned char* cp;
+ size_t bits;
+ unsigned int bitoffs;
+ int trunc = 0;
+
+ if (ei_decode_bitstring(buf, index, (const char**)&cp, &bitoffs, &bits) < 0
+ || bitoffs != 0) {
+ goto err;
+ }
+ ch_written += xprintf(fp, x, "#Bits<");
+ if ((bits+7) / 8 > BINPRINTSIZE) {
+ m = BINPRINTSIZE;
+ trunc = 1;
+ }
+ else
+ m = bits / 8;
+
+ delim = "";
+ for (i = 0; i < m; ++i) {
+ ch_written += xprintf(fp, x, "%s%u", delim, cp[i]);
+ delim = ",";
+ }
+ if (trunc)
+ ch_written += xprintf(fp, x, ",...");
+ else {
+ bits %= 8;
+ if (bits)
+ ch_written += xprintf(fp, x, "%s%u:%u", delim,
+ (cp[i] >> (8-bits)), bits);
+ }
+ xputc('>', fp, x); ++ch_written;
+ break;
+ }
case ERL_SMALL_INTEGER_EXT:
case ERL_INTEGER_EXT:
if (ei_decode_long(buf, index, &l) < 0) goto err;
@@ -278,12 +314,46 @@ static int print_term(FILE* fp, ei_x_buff* x,
}
break;
-
case ERL_FLOAT_EXT:
case NEW_FLOAT_EXT:
if (ei_decode_double(buf, index, &d) < 0) goto err;
ch_written += xprintf(fp, x, "%f", d);
break;
+ case ERL_MAP_EXT:
+ if (ei_decode_map_header(buf, &tindex, &n) < 0) goto err;
+ ch_written += xprintf(fp, x, "#{");
+ for (i = 0; i < n; ++i) {
+ r = print_term(fp, x, buf, &tindex);
+ if (r < 0) goto err;
+ ch_written += r;
+ ch_written += xprintf(fp, x, " => ");
+ r = print_term(fp, x, buf, &tindex);
+ if (r < 0) goto err;
+ ch_written += r;
+ if (i < n-1) {
+ xputs(", ", fp, x); ch_written += 2;
+ }
+ }
+ *index = tindex;
+ xputc('}', fp, x); ch_written++;
+ break;
+ case ERL_FUN_EXT:
+ case ERL_NEW_FUN_EXT:
+ case ERL_EXPORT_EXT:
+ if (ei_decode_fun(buf, &tindex, &fun) < 0) goto err;
+ if (fun.type == EI_FUN_EXPORT) {
+ ch_written += xprintf(fp, x, "fun %s:%s/%ld",
+ fun.module,
+ fun.u.exprt.func,
+ fun.arity);
+ } else {
+ ch_written += xprintf(fp, x, "#Fun{%s.%ld.%lu}",
+ fun.module,
+ fun.u.closure.index,
+ fun.u.closure.uniq);
+ }
+ *index = tindex;
+ break;
default:
goto err;
}
diff --git a/lib/erl_interface/src/misc/ei_pthreads.c b/lib/erl_interface/src/misc/ei_pthreads.c
index ec1c8d956f..c6d07a9a0a 100644
--- a/lib/erl_interface/src/misc/ei_pthreads.c
+++ b/lib/erl_interface/src/misc/ei_pthreads.c
@@ -78,7 +78,7 @@ static void tls_init_once(void)
errno_tls_index = TlsAlloc();
if (errno_tls_index == TLS_OUT_OF_INDEXES) {
fprintf(stderr,
- "FATAL ERROR: can not allocate TLS index for "
+ "FATAL ERROR: cannot allocate TLS index for "
"erl_errno (error code = %d)!\n",GetLastError());
exit(1);
}
diff --git a/lib/erl_interface/src/misc/ei_x_encode.c b/lib/erl_interface/src/misc/ei_x_encode.c
index 4ff5974663..8e77679d2a 100644
--- a/lib/erl_interface/src/misc/ei_x_encode.c
+++ b/lib/erl_interface/src/misc/ei_x_encode.c
@@ -117,6 +117,16 @@ int ei_x_encode_binary(ei_x_buff* x, const void* p, int len)
return ei_encode_binary(x->buff, &x->index, p, len);
}
+int ei_x_encode_bitstring(ei_x_buff* x, const char* p, size_t bitoffs, size_t bits)
+{
+ int i = x->index;
+ if (ei_encode_bitstring(NULL, &i, p, bitoffs, bits) == -1)
+ return -1;
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_bitstring(x->buff, &x->index, p, bitoffs, bits);
+}
+
int ei_x_encode_long(ei_x_buff* x, long n)
{
int i = x->index;
diff --git a/lib/erl_interface/src/misc/get_type.c b/lib/erl_interface/src/misc/get_type.c
index aa69cd4d60..eef58a9363 100644
--- a/lib/erl_interface/src/misc/get_type.c
+++ b/lib/erl_interface/src/misc/get_type.c
@@ -27,17 +27,8 @@
/* for types with meaningful length attributes, return the length too.
In other cases, return length 0 */
-/* FIXME working on this one.... */
-
int ei_get_type(const char *buf, const int *index, int *type, int *len)
{
- return ei_get_type_internal(buf, index, type, len);
-}
-
-
-int ei_get_type_internal(const char *buf, const int *index,
- int *type, int *len)
-{
const char *s = buf + *index;
*type = get8(s);
@@ -64,7 +55,9 @@ int ei_get_type_internal(const char *buf, const int *index,
case ERL_LARGE_TUPLE_EXT:
case ERL_LIST_EXT:
+ case ERL_MAP_EXT:
case ERL_BINARY_EXT:
+ case ERL_BIT_BINARY_EXT:
*len = get32be(s);
break;
diff --git a/lib/erl_interface/src/misc/show_msg.c b/lib/erl_interface/src/misc/show_msg.c
index 5868cccba6..805d69e9b3 100644
--- a/lib/erl_interface/src/misc/show_msg.c
+++ b/lib/erl_interface/src/misc/show_msg.c
@@ -342,7 +342,7 @@ static void show_term(const char *termbuf, int *index, FILE *stream)
int i, len;
char *s;
- ei_get_type_internal(termbuf,index,&type,&len);
+ ei_get_type(termbuf,index,&type,&len);
switch (type) {
case ERL_VERSION_MAGIC:
@@ -455,6 +455,12 @@ static void show_term(const char *termbuf, int *index, FILE *stream)
fprintf(stream,"#Bin<%ld>",num);
break;
+ case ERL_BIT_BINARY_EXT: {
+ size_t bits;
+ ei_decode_bitstring(termbuf, index, NULL, NULL, &bits);
+ fprintf(stream, "#Bits<%lu>", (unsigned long)bits);
+ break;
+ }
case ERL_LARGE_BIG_EXT:
/* doesn't actually decode - just skip over it */
/* FIXME if GMP, what to do here?? */
diff --git a/lib/erl_interface/src/prog/ei_fake_prog.c b/lib/erl_interface/src/prog/ei_fake_prog.c
index 158464b385..6f58c9833d 100644
--- a/lib/erl_interface/src/prog/ei_fake_prog.c
+++ b/lib/erl_interface/src/prog/ei_fake_prog.c
@@ -186,7 +186,6 @@ int main(void)
ei_x_encode_empty_list(&eix);
ei_get_type(charp, intp, intp, intp);
- ei_get_type_internal(charp, intp, intp, intp);
ei_decode_version(charp, intp, intp);
ei_decode_long(charp, intp, longp);
diff --git a/lib/erl_interface/src/prog/erl_start.c b/lib/erl_interface/src/prog/erl_start.c
index c766f4780e..b7aa451946 100644
--- a/lib/erl_interface/src/prog/erl_start.c
+++ b/lib/erl_interface/src/prog/erl_start.c
@@ -97,7 +97,7 @@
#endif
#ifndef RSH
-#define RSH "/usr/bin/rsh"
+#define RSH "/usr/bin/ssh"
#endif
#ifndef HAVE_SOCKLEN_T
diff --git a/lib/erl_interface/src/registry/reg_dump.c b/lib/erl_interface/src/registry/reg_dump.c
index 43c9824433..da0413e6e6 100644
--- a/lib/erl_interface/src/registry/reg_dump.c
+++ b/lib/erl_interface/src/registry/reg_dump.c
@@ -90,7 +90,7 @@ static int mn_start_dump(int fd, const erlang_pid *self,
|| (arity != 2)
|| ei_decode_atom(buf,&index,tmpbuf)
|| strcmp(tmpbuf,"rex")
- || ei_get_type_internal(buf,&index,&type,&arity)
+ || ei_get_type(buf,&index,&type,&arity)
|| (type != ERL_PID_EXT))
return -1; /* bad response from other side */
diff --git a/lib/erl_interface/test/all_SUITE_data/ei_runner.h b/lib/erl_interface/test/all_SUITE_data/ei_runner.h
index 2608661303..7c874ac82e 100644
--- a/lib/erl_interface/test/all_SUITE_data/ei_runner.h
+++ b/lib/erl_interface/test/all_SUITE_data/ei_runner.h
@@ -53,6 +53,7 @@ void free_packet(char*);
#define fail(reason) do_fail(__FILE__, __LINE__, reason)
#define fail1(reason, a1) do_fail(__FILE__, __LINE__, reason, a1)
+#define fail2(reason, a1, a2) do_fail(__FILE__, __LINE__, reason, a1, a2)
#define report(ok) do_report(__FILE__, __LINE__, ok)
void do_report(char* file, int line, int ok);
diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl
index 9c9c3f86b6..f40c67375b 100644
--- a/lib/erl_interface/test/ei_accept_SUITE.erl
+++ b/lib/erl_interface/test/ei_accept_SUITE.erl
@@ -43,8 +43,12 @@ init_per_testcase(Case, Config) ->
runner:init_per_testcase(?MODULE, Case, Config).
ei_accept(Config) when is_list(Config) ->
+ ei_accept_do(Config, 0), % default
+ ei_accept_do(Config, 21). % ei_set_compat_rel
+
+ei_accept_do(Config, CompatRel) ->
P = runner:start(Config, ?interpret),
- 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
+ 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, CompatRel),
Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
io:format("Myname ~p ~n", [Myname]),
@@ -52,15 +56,18 @@ ei_accept(Config) when is_list(Config) ->
io:format("EINode ~p ~n", [EINode]),
%% We take this opportunity to also test export-funs and bit-strings
- %% with (ugly) tuple fallbacks.
+ %% with (ugly) tuple fallbacks in OTP 21 and older.
%% Test both toward pending connection and established connection.
RealTerms = [<<1:1>>, fun lists:map/2],
- Fallbacks = [{<<128>>,1}, {lists,map}],
+ EncTerms = case CompatRel of
+ 0 -> RealTerms;
+ 21 -> [{<<128>>,1}, {lists,map}]
+ end,
Self = self(),
Funny = fun() -> hello end,
TermToSend = {call, Self, "Test", Funny, RealTerms},
- TermToGet = {call, Self, "Test", Funny, Fallbacks},
+ TermToGet = {call, Self, "Test", Funny, EncTerms},
Port = 6543,
{ok, ListenFd} = ei_publish(P, Port),
{any, EINode} ! TermToSend,
@@ -94,7 +101,7 @@ ei_threaded_accept(Config) when is_list(Config) ->
%% Test erlang:monitor toward erl_interface "processes"
monitor_ei_process(Config) when is_list(Config) ->
P = runner:start(Config, ?interpret),
- 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0),
+ 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, 0),
Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
io:format("Myname ~p ~n", [Myname]),
@@ -167,8 +174,8 @@ start_einode(Einode, N, Host) ->
%%% Interface functions for ei (erl_interface) functions.
-ei_connect_init(P, Num, Cookie, Creation) ->
- send_command(P, ei_connect_init, [Num,Cookie,Creation]),
+ei_connect_init(P, Num, Cookie, Creation, Compat) ->
+ send_command(P, ei_connect_init, [Num,Cookie,Creation,Compat]),
case get_term(P) of
{term,Int} when is_integer(Int) -> Int
end.
diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
index c209f506b1..09b0b5440b 100644
--- a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
+++ b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
@@ -58,7 +58,7 @@ static struct {
int num_args; /* Number of arguments. */
void (*func)(char* buf, int len);
} commands[] = {
- "ei_connect_init", 3, cmd_ei_connect_init,
+ "ei_connect_init", 4, cmd_ei_connect_init,
"ei_publish", 1, cmd_ei_publish,
"ei_accept", 1, cmd_ei_accept,
"ei_receive", 1, cmd_ei_receive,
@@ -106,21 +106,25 @@ TESTCASE(interpret)
static void cmd_ei_connect_init(char* buf, int len)
{
int index = 0, r = 0;
- int type, size;
- long l;
- char b[100];
+ long num, creation;
+ unsigned long compat;
+ char node_name[100];
char cookie[MAXATOMLEN], * cp = cookie;
ei_x_buff res;
- if (ei_decode_long(buf, &index, &l) < 0)
+ if (ei_decode_long(buf, &index, &num) < 0)
fail("expected int");
- sprintf(b, "c%d", l);
- /* FIXME don't use internal and maybe use skip?! */
- ei_get_type_internal(buf, &index, &type, &size);
+ sprintf(node_name, "c%d", num);
if (ei_decode_atom(buf, &index, cookie) < 0)
fail("expected atom (cookie)");
if (cookie[0] == '\0')
cp = NULL;
- r = ei_connect_init(&ec, b, cp, 0);
+ if (ei_decode_long(buf, &index, &creation) < 0)
+ fail("expected int");
+ if (ei_decode_long(buf, &index, &compat) < 0)
+ fail("expected uint");
+ if (compat)
+ ei_set_compat_rel(compat);
+ r = ei_connect_init(&ec, node_name, cp, creation);
ei_x_new_with_version(&res);
ei_x_encode_long(&res, r);
send_bin_term(&res);
diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl
index 75b6bf18da..6184ce801b 100644
--- a/lib/erl_interface/test/ei_connect_SUITE.erl
+++ b/lib/erl_interface/test/ei_connect_SUITE.erl
@@ -79,9 +79,10 @@ ei_send_funs(Config) when is_list(Config) ->
{ok,Fd} = ei_connect(P, node()),
Fun1 = fun ei_send/1,
- Fun2 = fun(X) -> P, X, Fd, Fun1 end,
+ Fun2 = fun(X) -> {P, X, Fd, Fun1} end,
+ Bits = <<1,2,3:5>>,
- AMsg={Fun1,Fun2},
+ AMsg={Fun1,Fun2,Bits},
%%AMsg={wait_with_funs, new_dist_format},
ok = ei_send_funs(P, Fd, self(), AMsg),
EIMsg = receive M -> M end,
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
index 58c0c7f8d8..385bcdd422 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
@@ -107,7 +107,6 @@ TESTCASE(interpret)
static void cmd_ei_connect_init(char* buf, int len)
{
int index = 0, r = 0;
- int type, size;
long l;
char b[100];
char cookie[MAXATOMLEN], * cp = cookie;
@@ -115,8 +114,6 @@ static void cmd_ei_connect_init(char* buf, int len)
if (ei_decode_long(buf, &index, &l) < 0)
fail("expected int");
sprintf(b, "c%ld", l);
- /* FIXME don't use internal and maybe use skip?! */
- ei_get_type_internal(buf, &index, &type, &size);
if (ei_decode_atom(buf, &index, cookie) < 0)
fail("expected atom (cookie)");
if (cookie[0] == '\0')
@@ -212,6 +209,9 @@ static void cmd_ei_send_funs(char* buf, int len)
erlang_pid pid;
ei_x_buff x;
erlang_fun fun1, fun2;
+ char* bitstring;
+ size_t bits;
+ int bitoffs;
if (ei_decode_long(buf, &index, &fd) < 0)
fail("expected long");
@@ -219,20 +219,24 @@ static void cmd_ei_send_funs(char* buf, int len)
fail("expected pid (node)");
if (ei_decode_tuple_header(buf, &index, &n) < 0)
fail("expected tuple");
- if (n != 2)
+ if (n != 3)
fail("expected tuple");
if (ei_decode_fun(buf, &index, &fun1) < 0)
fail("expected Fun1");
if (ei_decode_fun(buf, &index, &fun2) < 0)
fail("expected Fun2");
+ if (ei_decode_bitstring(buf, &index, &bitstring, &bitoffs, &bits) < 0)
+ fail("expected bitstring");
if (ei_x_new_with_version(&x) < 0)
fail("ei_x_new_with_version");
- if (ei_x_encode_tuple_header(&x, 2) < 0)
+ if (ei_x_encode_tuple_header(&x, 3) < 0)
fail("encode tuple header");
if (ei_x_encode_fun(&x, &fun1) < 0)
fail("encode fun1");
if (ei_x_encode_fun(&x, &fun2) < 0)
fail("encode fun2");
+ if (ei_x_encode_bitstring(&x, bitstring, bitoffs, bits) < 0)
+ fail("encode bitstring");
free_fun(&fun1);
free_fun(&fun2);
send_errno_result(ei_send(fd, &pid, x.buff, x.index));
diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl
index 75560ea7c9..e005ec89c7 100644
--- a/lib/erl_interface/test/ei_decode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_SUITE.erl
@@ -194,6 +194,9 @@ test_ei_decode_misc(Config) when is_list(Config) ->
send_term_as_binary(P,<<>>),
send_term_as_binary(P,<<"ÅÄÖåäö">>),
+ send_term_as_binary(P,<<1, 2, 3:5>>),
+ send_term_as_binary(P,<<1:1>>),
+
% send_term_as_binary(P,{}),
% send_term_as_binary(P,[]),
diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
index e516f310b6..46d6b8f2af 100644
--- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
+++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
@@ -256,66 +256,134 @@ int ei_decode_my_string(const char *buf, int *index, char *to,
//#define EI_DECODE_UTF8_STRING(FUNC,SIZE,VAL)
-#define EI_DECODE_BIN(FUNC,SIZE,VAL,LEN) \
- { \
- char p[1024]; \
- char *buf; \
- long len; \
- int size1 = 0; \
- int size2 = 0; \
- int err; \
- message("ei_" #FUNC " should be " #VAL); \
- buf = read_packet(NULL); \
- err = ei_ ## FUNC(buf+1, &size1, NULL, &len); \
+static void decode_bin(int exp_size, const char* val, int exp_len)
+{
+ char p[1024];
+ char *buf;
+ long len;
+ int size1 = 0;
+ int size2 = 0;
+ int err;
+ message("ei_decode_binary should be %s", val);
+ buf = read_packet(NULL);
+ err = ei_decode_binary(buf+1, &size1, NULL, &len);
message("err = %d, size = %d, len = %d, expected size = %d, expected len = %d\n",\
- err,size1,len,SIZE,LEN); \
- if (err != 0) { \
- if (err != -1) { \
- fail("returned non zero but not -1 if NULL pointer"); \
- } else { \
- fail("returned non zero"); \
- } \
- return; \
- } \
-\
- if (len != LEN) { \
- fail("size is not correct"); \
- return; \
- } \
-\
- err = ei_ ## FUNC(buf+1, &size2, p, &len); \
+ err,size1,len, exp_size, exp_len);
+ if (err != 0) {
+ if (err != -1) {
+ fail("returned non zero but not -1 if NULL pointer");
+ } else {
+ fail("returned non zero");
+ }
+ return;
+ }
+
+ if (len != exp_len) {
+ fail("size is not correct");
+ return;
+ }
+
+ err = ei_decode_binary(buf+1, &size2, p, &len);
message("err = %d, size = %d, len = %d, expected size = %d, expected len = %d\n",\
- err,size2,len,SIZE,LEN); \
- if (err != 0) { \
- if (err != -1) { \
- fail("returned non zero but not -1 if NULL pointer"); \
- } else { \
- fail("returned non zero"); \
- } \
- return; \
- } \
-\
- if (len != LEN) { \
- fail("size is not correct"); \
- return; \
- } \
-\
- if (strncmp(p,VAL,LEN) != 0) { \
- fail("value is not correct"); \
- return; \
- } \
-\
- if (size1 != size2) { \
- fail("size with and without pointer differs"); \
- return; \
- } \
-\
- if (size1 != SIZE) { \
- fail("size of encoded data is incorrect"); \
- return; \
- } \
- free_packet(buf); \
- } \
+ err,size2,len, exp_size, exp_len);
+ if (err != 0) {
+ if (err != -1) {
+ fail("returned non zero but not -1 if NULL pointer");
+ } else {
+ fail("returned non zero");
+ }
+ return;
+ }
+
+ if (len != exp_len) {
+ fail("size is not correct");
+ return;
+ }
+
+ if (strncmp(p,val,exp_len) != 0) {
+ fail("value is not correct");
+ return;
+ }
+
+ if (size1 != size2) {
+ fail("size with and without pointer differs");
+ return;
+ }
+
+ if (size1 != exp_size) {
+ fail("size of encoded data is incorrect");
+ return;
+ }
+ free_packet(buf);
+}
+
+static void decode_bits(int exp_size, const char* val, size_t exp_bits)
+{
+ const char* p;
+ char *buf;
+ size_t bits;
+ int bitoffs;
+ int size1 = 0;
+ int size2 = 0;
+ int err;
+ message("ei_decode_bitstring should be %d bits", (int)exp_bits);
+ buf = read_packet(NULL);
+ err = ei_decode_bitstring(buf+1, &size1, NULL, &bitoffs, &bits);
+ message("err = %d, size = %d, bitoffs = %d, bits = %d, expected size = %d, expected bits = %d\n",\
+ err,size1, bitoffs, (int)bits, exp_size, (int)exp_bits);
+
+ if (err != 0) {
+ if (err != -1) {
+ fail("returned non zero but not -1 if NULL pointer");
+ } else {
+ fail("returned non zero");
+ }
+ return;
+ }
+
+ if (bits != exp_bits) {
+ fail("number of bits is not correct");
+ return;
+ }
+ if (bitoffs != 0) {
+ fail("non zero bit offset");
+ return;
+ }
+
+ err = ei_decode_bitstring(buf+1, &size2, &p, NULL, &bits);
+ message("err = %d, size = %d, len = %d, expected size = %d, expected len = %d\n",\
+ err,size2, (int)bits, exp_size, (int)exp_bits);
+ if (err != 0) {
+ if (err != -1) {
+ fail("returned non zero but not -1 if NULL pointer");
+ } else {
+ fail("returned non zero");
+ }
+ return;
+ }
+
+ if (bits != exp_bits) {
+ fail("bits is not correct");
+ return;
+ }
+
+ if (memcmp(p, val, (exp_bits+7)/8) != 0) {
+ fail("value is not correct");
+ return;
+ }
+
+ if (size1 != size2) {
+ fail("size with and without pointer differs");
+ return;
+ }
+
+ if (size1 != exp_size) {
+ fail2("size of encoded data is incorrect %d != %d", size1, exp_size);
+ return;
+ }
+ free_packet(buf);
+}
+
/* ******************************************************************** */
@@ -644,9 +712,17 @@ TESTCASE(test_ei_decode_misc)
EI_DECODE_STRING(decode_my_string, 1, "");
EI_DECODE_STRING(decode_my_string, 9, "������");
- EI_DECODE_BIN(decode_binary, 8, "foo", 3);
- EI_DECODE_BIN(decode_binary, 5, "", 0);
- EI_DECODE_BIN(decode_binary, 11, "������", 6);
+ decode_bin(8, "foo", 3);
+ decode_bin(5, "", 0);
+ decode_bin(11, "������", 6);
+
+#define LAST_BYTE(V, BITS) ((V) << (8-(BITS)))
+ {
+ unsigned char bits1[] = {1, 2, LAST_BYTE(3,5) };
+ unsigned char bits2[] = {LAST_BYTE(1,1) };
+ decode_bits(9, bits1, 21);
+ decode_bits(7, bits2, 1);
+ }
/* FIXME check \0 in strings and atoms? */
/*
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index 0f23cdfbb9..0204b4cfd6 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
@@ -48,7 +48,8 @@ init_per_testcase(Case, Config) ->
test_ei_decode_encode(Config) when is_list(Config) ->
P = runner:start(Config, ?test_ei_decode_encode),
- Fun = fun (X) -> {X,true} end,
+ Fun1 = fun (X) -> {X,true} end,
+ Fun2 = fun runner:init_per_testcase/3,
Pid = self(),
Port = case os:type() of
{win32,_} ->
@@ -70,7 +71,8 @@ test_ei_decode_encode(Config) when is_list(Config) ->
BigLargeB = 1 bsl 11112 + BigSmallB,
BigLargeC = BigSmallA * BigSmallB * BigSmallC * BigSmallA,
- send_rec(P, Fun),
+ send_rec(P, Fun1),
+ send_rec(P, Fun2),
send_rec(P, Pid),
send_rec(P, Port),
send_rec(P, Ref),
@@ -115,14 +117,36 @@ test_ei_decode_encode(Config) when is_list(Config) ->
send_rec(P, {}),
send_rec(P, {atom, Pid, Port, Ref}),
send_rec(P, [atom, Pid, Port, Ref]),
- send_rec(P, [atom | Fun]),
+ send_rec(P, [atom | Fun1]),
send_rec(P, #{}),
send_rec(P, #{key => value}),
send_rec(P, maps:put(Port, Ref, #{key => value, key2 => Pid})),
+ [send_rec(P, <<16#dec0deb175:B/little>>) || B <- lists:seq(0,48)],
+
+ % And last an ugly duckling to test ei_encode_bitstring with bitoffs != 0
+ encode_bitstring(P),
+
runner:recv_eot(P),
ok.
+encode_bitstring(P) ->
+ %% Send one bitstring to c-node
+ Bits = <<16#18f6d4b2907e5c3a1:66>>,
+ P ! {self(), {command, term_to_binary(Bits, [{minor_version, 2}])}},
+
+ %% and then receive and verify a number of different sub-bitstrings
+ receive_sub_bitstring(P, Bits, 0, bit_size(Bits)).
+
+receive_sub_bitstring(_, _, _, NBits) when NBits < 0 ->
+ ok;
+receive_sub_bitstring(P, Bits, BitOffs, NBits) ->
+ <<_:BitOffs, Sub:NBits/bits, _/bits>> = Bits,
+ %%io:format("expecting term_to_binary(~p) = ~p\n", [Sub, term_to_binary(Sub)]),
+ {_B,Sub} = get_buf_and_term(P),
+ receive_sub_bitstring(P, Bits, BitOffs+1, NBits - ((NBits div 20)+1)).
+
+
%% ######################################################################## %%
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
index 55d9ed1b1a..512f9ed0c7 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
@@ -40,6 +40,13 @@ typedef struct
erlang_char_encoding enc;
}my_atom;
+typedef struct
+{
+ const char* bytes;
+ unsigned int bitoffs;
+ size_t nbits;
+}my_bitstring;
+
struct my_obj {
union {
erlang_fun fun;
@@ -49,6 +56,7 @@ struct my_obj {
erlang_trace trace;
erlang_big big;
my_atom atom;
+ my_bitstring bits;
int arity;
}u;
@@ -119,6 +127,26 @@ struct Type my_atom_type = {
(encodeFT*)ei_encode_my_atom, (x_encodeFT*)ei_x_encode_my_atom
};
+int ei_decode_my_bits(const char *buf, int *index, my_bitstring* a)
+{
+ return ei_decode_bitstring(buf, index, (a ? &a->bytes : NULL),
+ (a ? &a->bitoffs : NULL),
+ (a ? &a->nbits : NULL));
+}
+int ei_encode_my_bits(char *buf, int *index, my_bitstring* a)
+{
+ return ei_encode_bitstring(buf, index, a->bytes, a->bitoffs, a->nbits);
+}
+int ei_x_encode_my_bits(ei_x_buff* x, my_bitstring* a)
+{
+ return ei_x_encode_bitstring(x, a->bytes, a->bitoffs, a->nbits);
+}
+
+struct Type my_bitstring_type = {
+ "bits", "my_bitstring", (decodeFT*)ei_decode_my_bits,
+ (encodeFT*)ei_encode_my_bits, (x_encodeFT*)ei_x_encode_my_bits
+};
+
int my_decode_tuple_header(const char *buf, int *index, struct my_obj* obj)
{
@@ -237,11 +265,7 @@ void decode_encode(struct Type** tv, int nobj)
size1 = 0;
err = t->ei_decode_fp(inp, &size1, NULL);
if (err != 0) {
- if (err != -1) {
- fail("decode returned non zero but not -1");
- } else {
- fail1("decode '%s' returned non zero", t->name);
- }
+ fail2("decode '%s' returned non zero %d", t->name, err);
return;
}
if (size1 < 1) {
@@ -470,6 +494,66 @@ void decode_encode_big(struct Type* t)
}
+void encode_bitstring(void)
+{
+ char* packet;
+ char* inp;
+ char out_buf[BUFSZ];
+ int size;
+ int err, i;
+ ei_x_buff arg;
+ const char* p;
+ unsigned int bitoffs;
+ size_t nbits, org_nbits;
+
+ packet = read_packet(NULL);
+ inp = packet+1;
+
+ size = 0;
+ err = ei_decode_bitstring(inp, &size, &p, &bitoffs, &nbits);
+ if (err != 0) {
+ fail1("ei_decode_bitstring returned non zero %d", err);
+ return;
+ }
+
+ /*
+ * Now send a bunch of different sub-bitstrings back
+ * encoded both with ei_encode_ and ei_x_encode_.
+ */
+ org_nbits = nbits;
+ do {
+ size = 0;
+ err = ei_encode_bitstring(out_buf, &size, p, bitoffs, nbits);
+ if (err != 0) {
+ fail1("ei_encode_bitstring returned non zero %d", err);
+ return;
+ }
+
+ ei_x_new(&arg);
+ err = ei_x_encode_bitstring(&arg, p, bitoffs, nbits);
+ if (err != 0) {
+ fail1("ei_x_encode_bitstring returned non zero %d", err);
+ ei_x_free(&arg);
+ return;
+ }
+
+ if (arg.index < 1) {
+ fail("size is < 1");
+ ei_x_free(&arg);
+ return;
+ }
+
+ send_buffer(out_buf, size);
+ send_buffer(arg.buff, arg.index);
+ ei_x_free(&arg);
+
+ bitoffs++;
+ nbits -= (nbits / 20) + 1;
+ } while (nbits < org_nbits);
+
+ free_packet(packet);
+}
+
/* ******************************************************************** */
@@ -480,6 +564,7 @@ TESTCASE(test_ei_decode_encode)
ei_init();
decode_encode_one(&fun_type);
+ decode_encode_one(&fun_type);
decode_encode_one(&pid_type);
decode_encode_one(&port_type);
decode_encode_one(&ref_type);
@@ -537,6 +622,12 @@ TESTCASE(test_ei_decode_encode)
decode_encode(map, 7);
}
+ for (i=0; i <= 48; i++) {
+ decode_encode_one(&my_bitstring_type);
+ }
+
+ encode_bitstring();
+
report(1);
}
diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl
index c75ce55a7d..8a35b22ae5 100644
--- a/lib/erl_interface/test/ei_print_SUITE.erl
+++ b/lib/erl_interface/test/ei_print_SUITE.erl
@@ -26,7 +26,8 @@
-export([all/0, suite/0,
init_per_testcase/2,
- atoms/1, tuples/1, lists/1, strings/1]).
+ atoms/1, tuples/1, lists/1, strings/1,
+ maps/1, funs/1, binaries/1, bitstrings/1]).
-import(runner, [get_term/1]).
@@ -36,8 +37,8 @@
suite() ->
[{ct_hooks,[ts_install_cth]}].
-all() ->
- [atoms, tuples, lists, strings].
+all() ->
+ [atoms, tuples, lists, strings, maps, funs, binaries, bitstrings].
init_per_testcase(Case, Config) ->
runner:init_per_testcase(?MODULE, Case, Config).
@@ -142,3 +143,64 @@ strings(Config) when is_list(Config) ->
runner:recv_eot(P),
ok.
+
+maps(Config) ->
+ P = runner:start(Config, ?maps),
+
+ {term, "#{}"} = get_term(P),
+ {term, "#{key => value}"} = get_term(P),
+ {term, "#{key => value, another_key => {ok, 42}}"} = get_term(P),
+
+ runner:recv_eot(P),
+ ok.
+
+funs(Config) ->
+ P = runner:start(Config, ?funs),
+
+ {term, "#Fun{some_module.42.3735928559}"} = get_term(P),
+ {term, "#Fun{some_module.37.195935983}"} = get_term(P),
+ {term, "fun erlang:abs/1"} = get_term(P),
+
+ runner:recv_eot(P),
+ ok.
+
+binaries(Config) ->
+ P = runner:start(Config, ?binaries),
+
+ "#Bin<>" = send_term_get_printed(P, <<>>),
+ "#Bin<1,2,3>" = send_term_get_printed(P, <<1,2,3>>),
+ "#Bin<0,127,128,255>" = send_term_get_printed(P, <<0,127,128,255>>),
+ Bin30 = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30>>,
+ "#Bin<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30>"
+ = send_term_get_printed(P, Bin30),
+ "#Bin<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,...>"
+ = send_term_get_printed(P, <<Bin30/binary,31>>),
+
+ runner:recv_eot(P),
+ ok.
+
+bitstrings(Config) ->
+ P = runner:start(Config, ?bitstrings),
+
+ "#Bits<1:1>" = send_term_get_printed(P, <<1:1>>),
+ "#Bits<123:7>" = send_term_get_printed(P, <<123:7>>),
+ "#Bits<1,2,3:4>" = send_term_get_printed(P, <<1,2,3:4>>),
+ "#Bits<0,127,128,255,126:7>" = send_term_get_printed(P, <<0,127,128,255,-2:7>>),
+ Bits30 = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
+ 20,21,22,23,24,25,26,27,28,29,30:5>>,
+ "#Bits<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30:5>"
+ = send_term_get_printed(P, Bits30),
+ "#Bin<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,241>"
+ = send_term_get_printed(P, <<Bits30/bits,1:3>>),
+ "#Bits<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,240,...>"
+ = send_term_get_printed(P, <<Bits30/bits,1:4>>),
+
+ runner:recv_eot(P),
+ ok.
+
+
+
+send_term_get_printed(Port, Term) ->
+ Port ! {self(), {command, term_to_binary(Term)}},
+ {term, String} = get_term(Port),
+ String.
diff --git a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c
index 80be3016e6..27d4153250 100644
--- a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c
+++ b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c
@@ -29,6 +29,46 @@
*/
static void
+send_printed_buf(ei_x_buff* x)
+{
+ char* b = NULL;
+ char fn[256];
+ char *tmp = getenv("temp");
+ FILE* f;
+ int n, index = 0, ver;
+
+#ifdef VXWORKS
+ tmp = ".";
+#else
+ if (tmp == NULL) {
+ tmp = "/tmp";
+ }
+#endif
+ strcpy(fn, tmp);
+ strcat(fn, "/ei_print_test.txt");
+ f = fopen(fn, "w+");
+ ei_decode_version(x->buff, &index, &ver);
+ n = ei_print_term(f, x->buff, &index);
+ if (n < 0) {
+ fclose(f);
+ x->index = 0;
+ ei_x_format(x, "~s", "ERROR: term decoding failed");
+ send_bin_term(x);
+ } else {
+ fseek(f, 0, SEEK_SET);
+ b = malloc(n+1);
+ fread(b, 1, n, f);
+ b[n] = '\0';
+ fclose(f);
+ x->index = 0;
+ ei_x_format(x, "~s", b);
+ send_bin_term(x);
+ free(b);
+ }
+}
+
+
+static void
send_printed3(char* format, char* p1, char* p2, int fl)
{
char* b = NULL;
@@ -43,25 +83,7 @@ send_printed3(char* format, char* p1, char* p2, int fl)
} else {
ei_x_format(&x, format, p1, p2);
}
-#ifdef VXWORKS
- tmp = ".";
-#else
- if (tmp == NULL) tmp = "/tmp";
-#endif
- strcpy(fn, tmp);
- strcat(fn, "/ei_print_test.txt");
- f = fopen(fn, "w+");
- ei_decode_version(x.buff, &index, &ver);
- n = ei_print_term(f, x.buff, &index);
- fseek(f, 0, SEEK_SET);
- b = malloc(n+1);
- fread(b, 1, n, f);
- b[n] = '\0';
- fclose(f);
- x.index = 0;
- ei_x_format(&x, "~s", b);
- send_bin_term(&x);
- free(b);
+ send_printed_buf(&x);
ei_x_free(&x);
}
@@ -184,4 +206,146 @@ TESTCASE(strings)
report(1);
}
+TESTCASE(maps)
+{
+ ei_x_buff x;
+
+ ei_init();
+
+ ei_x_new_with_version(&x);
+ ei_x_encode_map_header(&x, 0);
+ send_printed_buf(&x);
+ ei_x_free(&x);
+
+ ei_x_new_with_version(&x);
+ ei_x_encode_map_header(&x, 1);
+ ei_x_encode_atom(&x, "key");
+ ei_x_encode_atom(&x, "value");
+ send_printed_buf(&x);
+ ei_x_free(&x);
+
+ ei_x_new_with_version(&x);
+ ei_x_encode_map_header(&x, 2);
+ ei_x_encode_atom(&x, "key");
+ ei_x_encode_atom(&x, "value");
+ ei_x_encode_atom(&x, "another_key");
+ ei_x_encode_tuple_header(&x, 2);
+ ei_x_encode_atom(&x, "ok");
+ ei_x_encode_long(&x, 42L);
+ send_printed_buf(&x);
+ ei_x_free(&x);
+
+ report(1);
+}
+
+TESTCASE(funs)
+{
+ ei_x_buff x;
+ erlang_pid self;
+ erlang_fun fun;
+
+ strcpy(self.node, "node@host");
+ self.num = 9;
+ self.serial = 99;
+ self.creation = 1;
+
+ ei_init();
+
+ ei_x_new_with_version(&x);
+ fun.arity = -1; /* Will encode as FUN_EXT */
+ strcpy(fun.module, "some_module");
+ fun.type = EI_FUN_CLOSURE;
+ fun.u.closure.pid = self;
+ fun.u.closure.index = fun.u.closure.old_index = 42;
+ fun.u.closure.uniq = 0xDEADBEEF;
+ fun.u.closure.n_free_vars = 0;
+ fun.u.closure.free_var_len = 0;
+ ei_x_encode_fun(&x, &fun);
+ send_printed_buf(&x);
+ ei_x_free(&x);
+
+ ei_x_new_with_version(&x);
+ fun.arity = 0; /* Will encode as NEW_FUN_EXT */
+ strcpy(fun.module, "some_module");
+ fun.type = EI_FUN_CLOSURE;
+ fun.u.closure.pid = self;
+ fun.u.closure.index = fun.u.closure.old_index = 37;
+ fun.u.closure.uniq = 0xBADBEEF;
+ fun.u.closure.n_free_vars = 0;
+ fun.u.closure.free_var_len = 0;
+ ei_x_encode_fun(&x, &fun);
+ send_printed_buf(&x);
+ ei_x_free(&x);
+
+ ei_x_new_with_version(&x);
+ fun.arity = 1;
+ strcpy(fun.module, "erlang");
+ fun.type = EI_FUN_EXPORT;
+ fun.u.exprt.func = "abs";
+ ei_x_encode_fun(&x, &fun);
+ send_printed_buf(&x);
+ ei_x_free(&x);
+
+ report(1);
+}
+
+TESTCASE(binaries)
+{
+ char *buf;
+ long len;
+ int err, n, index;
+ ei_x_buff x;
+
+ ei_init();
+
+ for (n = 5; n; n--) {
+ buf = read_packet(NULL);
+
+ index = 0;
+ err = ei_decode_version(buf, &index, NULL);
+ if (err != 0)
+ fail1("ei_decode_version returned %d", err);
+ err = ei_decode_binary(buf, &index, NULL, &len);
+ if (err != 0)
+ fail1("ei_decode_binary returned %d", err);
+
+ ei_x_new(&x);
+ ei_x_append_buf(&x, buf, index);
+ send_printed_buf(&x);
+ ei_x_free(&x);
+
+ free_packet(buf);
+ }
+ report(1);
+}
+
+TESTCASE(bitstrings)
+{
+ char *buf;
+ long len;
+ int err, n, index;
+ ei_x_buff x;
+
+ ei_init();
+
+ for (n = 7; n; n--) {
+ buf = read_packet(NULL);
+
+ index = 0;
+ err = ei_decode_version(buf, &index, NULL);
+ if (err != 0)
+ fail1("ei_decode_version returned %d", err);
+ err = ei_decode_bitstring(buf, &index, NULL, NULL, NULL);
+ if (err != 0)
+ fail1("ei_decode_bitstring returned %d", err);
+
+ ei_x_new(&x);
+ ei_x_append_buf(&x, buf, index);
+ send_printed_buf(&x);
+ ei_x_free(&x);
+
+ free_packet(buf);
+ }
+ report(1);
+}
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 4e31b3835d..cc72ed639a 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1,2 +1,2 @@
-EI_VSN = 3.11.3
+EI_VSN = 3.12
ERL_INTERFACE_VSN = $(EI_VSN)