aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface
diff options
context:
space:
mode:
Diffstat (limited to 'lib/erl_interface')
-rw-r--r--lib/erl_interface/Makefile2
-rw-r--r--lib/erl_interface/doc/src/ei.xml6
-rw-r--r--lib/erl_interface/doc/src/notes.xml76
-rw-r--r--lib/erl_interface/include/ei.h13
-rw-r--r--lib/erl_interface/src/connect/ei_connect.c4
-rw-r--r--lib/erl_interface/src/connect/ei_resolve.c12
-rw-r--r--lib/erl_interface/src/decode/decode_fun.c13
-rw-r--r--lib/erl_interface/src/decode/decode_skip.c1
-rw-r--r--lib/erl_interface/src/encode/encode_pid.c11
-rw-r--r--lib/erl_interface/src/encode/encode_port.c11
-rw-r--r--lib/erl_interface/src/encode/encode_ref.c10
-rw-r--r--lib/erl_interface/src/epmd/ei_epmd.h5
-rw-r--r--lib/erl_interface/src/epmd/epmd_publish.c28
-rw-r--r--lib/erl_interface/src/misc/ei_portio.c2
-rw-r--r--lib/erl_interface/src/misc/ei_printterm.c68
-rw-r--r--lib/erl_interface/src/prog/erl_call.c3
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl8
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c1
-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/test/erl_eterm_SUITE.erl10
-rw-r--r--lib/erl_interface/vsn.mk2
22 files changed, 465 insertions, 91 deletions
diff --git a/lib/erl_interface/Makefile b/lib/erl_interface/Makefile
index 9471b0df18..633e705b3f 100644
--- a/lib/erl_interface/Makefile
+++ b/lib/erl_interface/Makefile
@@ -31,3 +31,5 @@ SPECIAL_TARGETS =
# Default Subdir Targets
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_subdir.mk
+
+include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml
index c22f3fb0ce..70af5642da 100644
--- a/lib/erl_interface/doc/src/ei.xml
+++ b/lib/erl_interface/doc/src/ei.xml
@@ -183,7 +183,7 @@ typedef enum {
</func>
<func>
- <name since="OTP @OTP-15712@"><ret>int</ret><nametext>ei_decode_bitstring(const char *buf, int *index, const char **pp, unsigned int *bitoffsp, size_t *nbitsp)</nametext></name>
+ <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>
@@ -498,9 +498,9 @@ typedef enum {
</func>
<func>
- <name since="OTP @OTP-15712@"><ret>int</ret>
+ <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 @OTP-15712@"><ret>int</ret>
+ <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>
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 3d7f7e5637..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>
diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h
index b138118f04..7d39043bb2 100644
--- a/lib/erl_interface/include/ei.h
+++ b/lib/erl_interface/include/ei.h
@@ -323,13 +323,24 @@ typedef struct {
#define EI_SCLBK_FLG_FULL_IMPL (1 << 0)
+/*
+ * HACK: AIX defines many socket functions like accept to be naccept, which
+ * pollutes the global namespace. Set up an ugly ifdef for consumers of this
+ * API here so they get a mangled name for AIX and the sane name elsewhere.
+ */
+#ifdef _AIX
+#define EI_ACCEPT_NAME accept_ei
+#else
+#define EI_ACCEPT_NAME accept
+#endif
+
typedef struct {
int flags;
int (*socket)(void **ctx, void *setup_ctx);
int (*close)(void *ctx);
int (*listen)(void *ctx, void *addr, int *len, int backlog);
- int (*accept)(void **ctx, void *addr, int *len, unsigned tmo);
+ int (*EI_ACCEPT_NAME)(void **ctx, void *addr, int *len, unsigned tmo);
int (*connect)(void *ctx, void *addr, int len, unsigned tmo);
int (*writev)(void *ctx, const void *iov, int iovcnt, ssize_t *len, unsigned tmo);
int (*write)(void *ctx, const char *buf, ssize_t *len, unsigned tmo);
diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c
index 1b1479d2e9..f600758385 100644
--- a/lib/erl_interface/src/connect/ei_connect.c
+++ b/lib/erl_interface/src/connect/ei_connect.c
@@ -659,7 +659,7 @@ int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
return ERL_ERROR;
}
- ec->creation = creation & 0x3; /* 2 bits */
+ ec->creation = creation;
if (cookie) {
if (strlen(cookie) >= sizeof(ec->ei_connect_cookie)) {
@@ -698,7 +698,7 @@ int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
strcpy(ec->self.node,thisnodename);
ec->self.num = 0;
ec->self.serial = 0;
- ec->self.creation = creation & 0x3; /* 2 bits */
+ ec->self.creation = creation;
ec->cbs = cbs;
ec->setup_context = setup_context;
diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c
index 225fddc784..5a8ca0c567 100644
--- a/lib/erl_interface/src/connect/ei_resolve.c
+++ b/lib/erl_interface/src/connect/ei_resolve.c
@@ -55,6 +55,16 @@
#include "ei_resolve.h"
#include "ei_locking.h"
+/* AIX has a totally different signature (allegedly shared with some other
+ * Unices) that isn't compatible. It turns out that the _r version isn't
+ * thread-safe according to curl - but bizarrely, since AIX 4.3, libc
+ * is thread-safe in a manner that makes the normal gethostbyname OK
+ * for re-entrant use.
+ */
+#ifdef _AIX
+#undef HAVE_GETHOSTBYNAME_R
+#endif
+
#ifdef HAVE_GETHOSTBYNAME_R
int ei_init_resolve(void)
@@ -75,7 +85,7 @@ int ei_init_resolve(void)
static ei_mutex_t *ei_gethost_sem = NULL;
#endif /* _REENTRANT */
static int ei_resolve_initialized = 0;
-#ifndef __WIN32__
+#if !defined(__WIN32__) && !defined(_AIX)
int h_errno;
#endif
diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c
index 3a7a2b01c1..db71007505 100644
--- a/lib/erl_interface/src/decode/decode_fun.c
+++ b/lib/erl_interface/src/decode/decode_fun.c
@@ -77,10 +77,12 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
}
if (p != NULL) {
p->u.closure.n_free_vars = n;
- p->u.closure.free_var_len = ix - ix0;
- p->u.closure.free_vars = ei_malloc(ix - ix0);
- if (!(p->u.closure.free_vars)) return -1;
- memcpy(p->u.closure.free_vars, s + ix0, ix - ix0);
+ 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;
@@ -146,6 +148,7 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
else {
p_arity = NULL;
}
+ ix = 0;
if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8,
NULL, NULL) < 0)
return -1;
@@ -171,6 +174,8 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
}
if (ei_decode_long(s, &ix, p_arity) < 0)
return -1;
+ s += ix;
+ *index += s - s0;
return 0;
}
default:
diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c
index 736c00e074..0622ce7d59 100644
--- a/lib/erl_interface/src/decode/decode_skip.c
+++ b/lib/erl_interface/src/decode/decode_skip.c
@@ -97,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_pid.c b/lib/erl_interface/src/encode/encode_pid.c
index d14746b40f..0dfdb16372 100644
--- a/lib/erl_interface/src/encode/encode_pid.c
+++ b/lib/erl_interface/src/encode/encode_pid.c
@@ -25,7 +25,6 @@
int ei_encode_pid(char *buf, int *index, const erlang_pid *p)
{
char* s = buf + *index;
- const char tag = (p->creation > 3) ? ERL_NEW_PID_EXT : ERL_PID_EXT;
++(*index); /* skip ERL_PID_EXT */
if (ei_encode_atom_len_as(buf, index, p->node, strlen(p->node),
@@ -33,21 +32,17 @@ int ei_encode_pid(char *buf, int *index, const erlang_pid *p)
return -1;
if (buf) {
- put8(s, tag);
+ put8(s, ERL_NEW_PID_EXT);
s = buf + *index;
/* now the integers */
put32be(s,p->num & 0x7fff); /* 15 bits */
put32be(s,p->serial & 0x1fff); /* 13 bits */
- if (tag == ERL_PID_EXT) {
- put8(s,(p->creation & 0x03)); /* 2 bits */
- } else {
- put32be(s, p->creation); /* 32 bits */
- }
+ put32be(s, p->creation); /* 32 bits */
}
- *index += 4 + 4 + (tag == ERL_PID_EXT ? 1 : 4);
+ *index += 4 + 4 + 4;
return 0;
}
diff --git a/lib/erl_interface/src/encode/encode_port.c b/lib/erl_interface/src/encode/encode_port.c
index eb464380c0..0fb4018db1 100644
--- a/lib/erl_interface/src/encode/encode_port.c
+++ b/lib/erl_interface/src/encode/encode_port.c
@@ -25,7 +25,6 @@
int ei_encode_port(char *buf, int *index, const erlang_port *p)
{
char *s = buf + *index;
- const char tag = p->creation > 3 ? ERL_NEW_PORT_EXT : ERL_PORT_EXT;
++(*index); /* skip ERL_PORT_EXT */
if (ei_encode_atom_len_as(buf, index, p->node, strlen(p->node), ERLANG_UTF8,
@@ -33,19 +32,15 @@ int ei_encode_port(char *buf, int *index, const erlang_port *p)
return -1;
}
if (buf) {
- put8(s, tag);
+ put8(s, ERL_NEW_PORT_EXT);
s = buf + *index;
/* now the integers */
put32be(s,p->id & 0x0fffffff /* 28 bits */);
- if (tag == ERL_PORT_EXT) {
- put8(s,(p->creation & 0x03));
- } else {
- put32be(s, p->creation);
- }
+ put32be(s, p->creation);
}
- *index += 4 + (tag == ERL_PORT_EXT ? 1 : 4);
+ *index += 4 + 4;
return 0;
}
diff --git a/lib/erl_interface/src/encode/encode_ref.c b/lib/erl_interface/src/encode/encode_ref.c
index 5ccfc32c6d..8c2e0a25f7 100644
--- a/lib/erl_interface/src/encode/encode_ref.c
+++ b/lib/erl_interface/src/encode/encode_ref.c
@@ -24,7 +24,6 @@
int ei_encode_ref(char *buf, int *index, const erlang_ref *p)
{
- const char tag = (p->creation > 3) ? ERL_NEWER_REFERENCE_EXT : ERL_NEW_REFERENCE_EXT;
char *s = buf + *index;
int i;
@@ -37,7 +36,7 @@ int ei_encode_ref(char *buf, int *index, const erlang_ref *p)
/* Always encode as an extended reference; all participating parties
are now expected to be able to decode extended references. */
if (buf) {
- put8(s, tag);
+ put8(s, ERL_NEWER_REFERENCE_EXT);
/* first, number of integers */
put16be(s, p->len);
@@ -46,15 +45,12 @@ int ei_encode_ref(char *buf, int *index, const erlang_ref *p)
s = buf + *index;
/* now the integers */
- if (tag == ERL_NEW_REFERENCE_EXT)
- put8(s,(p->creation & 0x03));
- else
- put32be(s, p->creation);
+ put32be(s, p->creation);
for (i = 0; i < p->len; i++)
put32be(s,p->n[i]);
}
- *index += p->len*4 + (tag == ERL_NEW_REFERENCE_EXT ? 1 : 4);
+ *index += p->len*4 + 4;
return 0;
}
diff --git a/lib/erl_interface/src/epmd/ei_epmd.h b/lib/erl_interface/src/epmd/ei_epmd.h
index ac153b6e66..597a955676 100644
--- a/lib/erl_interface/src/epmd/ei_epmd.h
+++ b/lib/erl_interface/src/epmd/ei_epmd.h
@@ -25,8 +25,8 @@
#endif
#ifndef EI_DIST_HIGH
-#define EI_DIST_HIGH 5 /* R4 and later */
-#define EI_DIST_LOW 1 /* R3 and earlier */
+#define EI_DIST_HIGH 6 /* OTP 23 and later */
+#define EI_DIST_LOW 5 /* OTP R4 - 22 */
#endif
#ifndef EPMD_PORT
@@ -45,6 +45,7 @@
#ifndef EI_EPMD_ALIVE2_REQ
#define EI_EPMD_ALIVE2_REQ 120
#define EI_EPMD_ALIVE2_RESP 121
+#define EI_EPMD_ALIVE2_X_RESP 118
#define EI_EPMD_PORT2_REQ 122
#define EI_EPMD_PORT2_RESP 119
#define EI_EPMD_STOP_REQ 's'
diff --git a/lib/erl_interface/src/epmd/epmd_publish.c b/lib/erl_interface/src/epmd/epmd_publish.c
index 20b8e867e8..ef8a5d6b70 100644
--- a/lib/erl_interface/src/epmd/epmd_publish.c
+++ b/lib/erl_interface/src/epmd/epmd_publish.c
@@ -68,7 +68,8 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms)
int nlen = strlen(alive);
int len = elen + nlen + 13; /* hard coded: be careful! */
int n;
- int err, res, creation;
+ int err, response, res;
+ unsigned creation;
ssize_t dlen;
unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
@@ -124,8 +125,10 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms)
/* Don't close fd here! It keeps us registered with epmd */
s = buf;
- if (((res=get8(s)) != EI_EPMD_ALIVE2_RESP)) { /* response */
- EI_TRACE_ERR1("ei_epmd_r4_publish","<- unknown (%d)",res);
+ response = get8(s);
+ if (response != EI_EPMD_ALIVE2_RESP &&
+ response != EI_EPMD_ALIVE2_X_RESP) {
+ EI_TRACE_ERR1("ei_epmd_r4_publish","<- unknown (%d)",response);
EI_TRACE_ERR0("ei_epmd_r4_publish","-> CLOSE");
ei_close__(fd);
erl_errno = EIO;
@@ -141,18 +144,21 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms)
return -1;
}
- creation = get16be(s);
+ if (response == EI_EPMD_ALIVE2_RESP)
+ creation = get16be(s);
+ else /* EI_EPMD_ALIVE2_X_RESP */
+ creation = get32be(s);
EI_TRACE_CONN2("ei_epmd_r4_publish",
- " result=%d (ok) creation=%d",res,creation);
+ " result=%d (ok) creation=%u",res,creation);
- /* probably should save fd so we can close it later... */
- /* epmd_saveconn(OPEN,fd,alive); */
+ /*
+ * Would be nice to somehow use the nice "unique" creation value
+ * received here from epmd instead of using the crappy one
+ * passed (already) to ei_connect_init.
+ */
- /* return the creation number, for no good reason */
- /* return creation;*/
-
- /* no - return the descriptor */
+ /* return the descriptor */
return fd;
}
diff --git a/lib/erl_interface/src/misc/ei_portio.c b/lib/erl_interface/src/misc/ei_portio.c
index bccc86c1b1..bfe67a732c 100644
--- a/lib/erl_interface/src/misc/ei_portio.c
+++ b/lib/erl_interface/src/misc/ei_portio.c
@@ -622,7 +622,7 @@ int ei_accept_ctx_t__(ei_socket_callbacks *cbs, void **ctx,
} while (error == EINTR);
}
do {
- error = cbs->accept(ctx, addr, len, ms);
+ error = cbs->EI_ACCEPT_NAME(ctx, addr, len, ms);
} while (error == EINTR);
return error;
}
diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c
index 5c40fb7747..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;
@@ -239,41 +241,47 @@ 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 char* cp;
+ const unsigned char* cp;
size_t bits;
unsigned int bitoffs;
int trunc = 0;
- if (ei_decode_bitstring(buf, index, &cp, &bitoffs, &bits) < 0
+ if (ei_decode_bitstring(buf, index, (const char**)&cp, &bitoffs, &bits) < 0
|| bitoffs != 0) {
goto err;
}
ch_written += xprintf(fp, x, "#Bits<");
- m = (bits+7) / 8;
- if (m > BINPRINTSIZE) {
+ if ((bits+7) / 8 > BINPRINTSIZE) {
m = BINPRINTSIZE;
trunc = 1;
}
- --m;
+ else
+ m = bits / 8;
+
+ delim = "";
for (i = 0; i < m; ++i) {
- ch_written += xprintf(fp, x, "%d,", cp[i]);
+ ch_written += xprintf(fp, x, "%s%u", delim, cp[i]);
+ delim = ",";
}
- ch_written += xprintf(fp, x, "%d", cp[i]);
if (trunc)
ch_written += xprintf(fp, x, ",...");
- else if (bits % 8 != 0)
- ch_written += xprintf(fp, x, ":%u", (unsigned)(bits % 8));
+ 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;
}
@@ -306,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/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
index ab91157035..dce2ecdec2 100644
--- a/lib/erl_interface/src/prog/erl_call.c
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -292,8 +292,7 @@ int erl_call(int argc, char **argv)
flags.cookie = NULL;
}
- /* FIXME decide how many bits etc or leave to connect_xinit? */
- creation = (time(NULL) % 3) + 1; /* "random" */
+ creation = time(NULL) + 1; /* "random" */
if (flags.hidden == NULL) {
/* As default we are c17@gethostname */
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index 3451d9f503..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,7 +117,7 @@ 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})),
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 85ca6c56e9..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
@@ -564,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);
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/test/erl_eterm_SUITE.erl b/lib/erl_interface/test/erl_eterm_SUITE.erl
index 77910a9fc7..4605293c74 100644
--- a/lib/erl_interface/test/erl_eterm_SUITE.erl
+++ b/lib/erl_interface/test/erl_eterm_SUITE.erl
@@ -73,6 +73,10 @@
-import(runner, [get_term/1]).
+-define(REFERENCE_EXT, $e).
+-define(NEW_REFERENCE_EXT, $r).
+-define(NEWER_REFERENCE_EXT, $Z).
+
%% This test suite controls the running of the C language functions
%% in eterm_test.c and print_term.c.
@@ -1026,9 +1030,11 @@ cnode_1(Config) when is_list(Config) ->
check_ref(Ref) ->
case bin_ext_type(Ref) of
- 101 ->
+ ?REFERENCE_EXT ->
ct:fail(oldref);
- 114 ->
+ ?NEW_REFERENCE_EXT ->
+ ok;
+ ?NEWER_REFERENCE_EXT ->
ok;
Type ->
ct:fail({type, Type})
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)