summaryrefslogtreecommitdiff
path: root/lib/erl_interface/src/misc
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2009-11-20 14:54:40 +0000
committerErlang/OTP <otp@erlang.org>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/erl_interface/src/misc
downloaderlang-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/erl_interface/src/misc')
-rw-r--r--lib/erl_interface/src/misc/ei_compat.c39
-rw-r--r--lib/erl_interface/src/misc/ei_decode_term.c156
-rw-r--r--lib/erl_interface/src/misc/ei_decode_term.h31
-rw-r--r--lib/erl_interface/src/misc/ei_format.c466
-rw-r--r--lib/erl_interface/src/misc/ei_format.h26
-rw-r--r--lib/erl_interface/src/misc/ei_internal.h157
-rw-r--r--lib/erl_interface/src/misc/ei_locking.c164
-rw-r--r--lib/erl_interface/src/misc/ei_locking.h76
-rw-r--r--lib/erl_interface/src/misc/ei_malloc.c41
-rw-r--r--lib/erl_interface/src/misc/ei_malloc.h28
-rw-r--r--lib/erl_interface/src/misc/ei_portio.c377
-rw-r--r--lib/erl_interface/src/misc/ei_portio.h35
-rw-r--r--lib/erl_interface/src/misc/ei_printterm.c342
-rw-r--r--lib/erl_interface/src/misc/ei_printterm.h24
-rw-r--r--lib/erl_interface/src/misc/ei_pthreads.c226
-rw-r--r--lib/erl_interface/src/misc/ei_trace.c56
-rw-r--r--lib/erl_interface/src/misc/ei_trace.h26
-rw-r--r--lib/erl_interface/src/misc/ei_x_encode.c255
-rw-r--r--lib/erl_interface/src/misc/ei_x_encode.h31
-rw-r--r--lib/erl_interface/src/misc/eidef.h51
-rw-r--r--lib/erl_interface/src/misc/eiext.h35
-rw-r--r--lib/erl_interface/src/misc/eimd5.c319
-rw-r--r--lib/erl_interface/src/misc/eimd5.h48
-rw-r--r--lib/erl_interface/src/misc/get_type.c149
-rw-r--r--lib/erl_interface/src/misc/putget.h85
-rw-r--r--lib/erl_interface/src/misc/show_msg.c584
-rw-r--r--lib/erl_interface/src/misc/show_msg.h27
27 files changed, 3854 insertions, 0 deletions
diff --git a/lib/erl_interface/src/misc/ei_compat.c b/lib/erl_interface/src/misc/ei_compat.c
new file mode 100644
index 0000000000..45ea6e3a72
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_compat.c
@@ -0,0 +1,39 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#include "ei.h"
+#include "ei_internal.h"
+
+#define EI_COMPAT_NO_REL (~((unsigned) 0))
+
+static unsigned compat_rel = EI_COMPAT_NO_REL;
+
+void
+ei_set_compat_rel(unsigned rel)
+{
+ if (compat_rel == EI_COMPAT_NO_REL)
+ compat_rel = rel;
+}
+
+int
+ei_internal_use_r9_pids_ports(void)
+{
+ return compat_rel < 10;
+}
diff --git a/lib/erl_interface/src/misc/ei_decode_term.c b/lib/erl_interface/src/misc/ei_decode_term.c
new file mode 100644
index 0000000000..7b95ff232f
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_decode_term.c
@@ -0,0 +1,156 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#include <string.h>
+
+#include "eidef.h"
+#include "eiext.h"
+#include "ei_decode_term.h"
+#include "putget.h"
+
+/* Returns 1 if term is decoded, 0 if term is OK, but not decoded here
+ and -1 if something is wrong.
+ ONLY changes index if term is decoded (return value 1)! */
+
+int ei_decode_ei_term(const char* buf, int* index, ei_term* term)
+{
+ const char* s = buf + *index, * s0 = s;
+ int len, i, n, sign;
+ char c;
+ double f;
+
+ if (term == NULL) return -1;
+ c = term->ei_type = get8(s);
+ switch (c) {
+ case ERL_SMALL_INTEGER_EXT:
+ term->value.i_val = get8(s);
+ break;
+ case ERL_INTEGER_EXT:
+ term->value.i_val = get32be(s);
+ break;
+ case ERL_FLOAT_EXT:
+ if (s[30]) return -1;
+ if (sscanf(s, "%lf", &f) != 1) return -1;
+ s += 31;
+ term->value.d_val = f;
+ break;
+ case ERL_ATOM_EXT:
+ len = get16be(s);
+ memcpy(term->value.atom_name, s, len);
+ term->value.atom_name[len] = '\0';
+ s += len;
+ break;
+ case ERL_REFERENCE_EXT:
+ /* first the nodename */
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+ len = get16be(s);
+ memcpy(term->value.ref.node, s, len);
+ term->value.ref.node[len] = '\0';
+ s += len;
+ /* now the numbers: num (4), creation (1) */
+ term->value.ref.n[0] = get32be(s);
+ term->value.ref.len = 1;
+ term->value.ref.creation = get8(s) & 0x03;
+ break;
+ case ERL_NEW_REFERENCE_EXT:
+ /* first the integer count */
+ term->value.ref.len = get16be(s);
+ /* then the nodename */
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+ len = get16be(s);
+ memcpy(term->value.ref.node, s, len);
+ term->value.ref.node[len] = '\0';
+ s += len;
+ /* creation */
+ term->value.ref.creation = get8(s) & 0x03;
+ /* finally the id integers */
+ for (i = 0; (i<term->value.ref.len) && (i<3); i++) {
+ term->value.ref.n[i] = get32be(s);
+ }
+ if (term->value.ref.len > 3) {
+ s += 4 * (term->value.ref.len - 3);
+ }
+ break;
+ case ERL_PORT_EXT:
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+ len = get16be(s);
+ memcpy(term->value.port.node, s, len);
+ term->value.port.node[len] = '\0';
+ term->value.port.id = get32be(s) & 0x0fffffff; /* 28 bits */;
+ term->value.port.creation = get8(s) & 0x03;
+ break;
+ case ERL_PID_EXT:
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+ /* name first */
+ len = get16be(s);
+ memcpy(term->value.pid.node, s, len);
+ term->value.pid.node[len] = '\0';
+ s += len;
+ /* now the numbers: num (4), serial (4), creation (1) */
+ term->value.pid.num = get32be(s) & 0x7fff; /* 15 bits */
+ term->value.pid.serial = get32be(s) & 0x1fff; /* 13 bits */
+ term->value.pid.creation = get8(s) & 0x03; /* 2 bits */
+ break;
+ case ERL_SMALL_TUPLE_EXT:
+ term->arity = get8(s);
+ break; /*return 0;*/
+ case ERL_LARGE_TUPLE_EXT:
+ term->arity = get32be(s);
+ break; /*return 0;*/
+ case ERL_NIL_EXT:
+ term->arity = 0;
+ break;
+ case ERL_STRING_EXT:
+ term->size = get16be(s);
+ return 0;
+ case ERL_LIST_EXT:
+ term->arity = get32be(s);
+ break; /*return 0;*/
+ case ERL_BINARY_EXT:
+ term->size = get32be(s);
+ return 0;
+ case ERL_SMALL_BIG_EXT:
+ if ((term->arity = get8(s)) != 4) return -1;
+ sign = get8(s);
+ /* Little Endian, and n always positive, except for LONG_MIN */
+ n = get32le(s);
+ if (sign) {
+ /* check for overflow */
+ if ((n - 1) < 0) return -1;
+ n = -n;
+ } else {
+ /* check for overflow */
+ if (n < 0) return -1;
+ }
+ break;
+ case ERL_LARGE_BIG_EXT:
+ return 0;
+ case ERL_PASS_THROUGH:
+ return 0;
+ case ERL_NEW_CACHE:
+ return -1;
+ case ERL_CACHED_ATOM:
+ return -1;
+ default:
+ return -1;
+ }
+ *index += s-s0;
+ return 1;
+}
diff --git a/lib/erl_interface/src/misc/ei_decode_term.h b/lib/erl_interface/src/misc/ei_decode_term.h
new file mode 100644
index 0000000000..76a71ae0a6
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_decode_term.h
@@ -0,0 +1,31 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+
+#ifndef _EI_DECODE_TERM_H
+#define _EI_DECODE_TERM_H
+
+/* Returns 1 if term is decoded, 0 if term is OK, but not decoded here
+ and -1 if something is wrong.
+ ONLY changes index if term is decoded (return value 1)! */
+
+int ei_decode_ei_term(const char* buf, int* index, ei_term* term);
+
+#endif /* _EI_DECODE_TERM_H */
diff --git a/lib/erl_interface/src/misc/ei_format.c b/lib/erl_interface/src/misc/ei_format.c
new file mode 100644
index 0000000000..08235d0ebe
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_format.c
@@ -0,0 +1,466 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+/*
+ * Function:
+ * ei_format to build binary format terms a bit like printf
+ */
+
+#ifdef VXWORKS
+#include <vxWorks.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef VRTX
+#define __READY_EXTENSIONS__
+#include <errno.h>
+#endif
+
+#include "eidef.h"
+#include "ei_malloc.h"
+#include "ei_format.h"
+
+/*
+ * To avoid problems we read the variable number of arguments to an
+ * array of unions.
+ */
+union arg {
+ char* s;
+ long l;
+ unsigned long u;
+ double d;
+};
+
+static int eiformat(const char** s, union arg** args, ei_x_buff* x);
+
+/* forwards of parse functions */
+static int pformat(const char** fmt, union arg**, ei_x_buff* x);
+static int plist(const char** fmt, union arg**, ei_x_buff* x, int size);
+static int ptuple(const char** fmt, union arg**, ei_x_buff* x, int size);
+static int pquotedatom(const char** fmt, ei_x_buff* x);
+static int pdigit(const char** fmt, ei_x_buff* x);
+static int patom(const char** fmt, ei_x_buff* x);
+static int pstring(const char** fmt, ei_x_buff* x);
+
+/* format a string into an ei_x_buff, except the version token */
+static int eiformat(const char** fmt, union arg** args, ei_x_buff* x)
+{
+ const char* p = *fmt;
+ int res;
+ ei_x_buff x2;
+
+ while (isspace((int)*p))
+ ++p;
+ switch (*p) {
+ case '~':
+ res = pformat(&p, args, x);
+ break;
+ case '[':
+ res = ei_x_new(&x2);
+ if (res >= 0)
+ res = plist(&p, args, &x2, 0);
+ if (res > 0)
+ res = ei_x_encode_list_header(x, res);
+ if (res >= 0)
+ res = ei_x_append(x, &x2);
+ ei_x_free(&x2);
+ break;
+ case '{':
+ res = ei_x_new(&x2);
+ if (res >= 0)
+ res = ptuple(&p, args, &x2, 0);
+ if (res >= 0)
+ res = ei_x_encode_tuple_header(x, res);
+ if (res >= 0)
+ res = ei_x_append(x, &x2);
+ ei_x_free(&x2);
+ break;
+ case '"':
+ res = pstring(&p, x);
+ break;
+ case '\'':
+ res = pquotedatom(&p, x);
+ break;
+ default:
+ if (isdigit((int)*p))
+ res = pdigit(&p, x);
+ else if (islower((int)*p))
+ res = patom(&p, x);
+ else
+ res = -1;
+ break;
+ /*
+ Variables
+ */
+ }
+ *fmt = p;
+ return res;
+}
+
+static int patom(const char** fmt, ei_x_buff* x)
+{
+ const char* start = *fmt;
+ char c;
+ int len;
+
+ for (;;) {
+ c = *(*fmt)++;
+ if (isalnum((int) c) || (c == '_') || (c == '@'))
+ continue;
+ else
+ break;
+ }
+ --(*fmt);
+ len = *fmt - start;
+ /* FIXME why truncate atom name and not fail?! */
+ if (len > MAXATOMLEN)
+ len = MAXATOMLEN;
+ return ei_x_encode_atom_len(x, start, len);
+}
+
+/* Check if integer or float */
+static int pdigit(const char** fmt, ei_x_buff* x)
+{
+ const char* start = *fmt;
+ char c;
+ int len, dotp=0;
+ double d;
+ long l;
+
+ for (;;) {
+ c = *(*fmt)++;
+ if (isdigit((int)c))
+ continue;
+ else if (!dotp && (c == '.')) {
+ dotp = 1;
+ continue;
+ } else
+ break;
+ }
+ --(*fmt);
+ len = *fmt - start;
+ if (dotp) {
+ sscanf(start, "%lf", &d);
+ return ei_x_encode_double(x, d);
+ } else {
+ sscanf(start, "%ld", &l);
+ return ei_x_encode_long(x, l);
+ }
+}
+
+/* "string" */
+static int pstring(const char** fmt, ei_x_buff* x)
+{
+ const char* start = ++(*fmt); /* skip first quote */
+ char c;
+ int res;
+
+ for (;;) {
+ c = *(*fmt)++;
+ if (c == '\0')
+ return -1;
+ if (c == '"') {
+ if (*((*fmt)-1) == '\\')
+ continue;
+ else
+ break;
+ } else
+ continue;
+ }
+ res = ei_x_encode_string_len(x, start, *fmt - start - 1);
+ return res;
+}
+
+/* 'atom' */
+static int pquotedatom(const char** fmt, ei_x_buff* x)
+{
+ const char* start = ++(*fmt); /* skip first quote */
+ char c;
+ int res;
+
+ for (;;) {
+ c = *(*fmt)++;
+ if (c == 0)
+ return -1;
+ if (c == '\'') {
+ if (*((*fmt)-1) == '\\')
+ continue;
+ else
+ break;
+ } else
+ continue;
+ }
+ res = ei_x_encode_atom_len(x, start, *fmt - start - 1);
+ return res;
+}
+
+
+ /*
+ * The format letters are:
+ * a - An atom
+ * s - A string
+ * i - An integer
+ * l - A long integer
+ * u - An unsigned long integer
+ * f - A float
+ * d - A double float
+ */
+static int pformat(const char** fmt, union arg** args, ei_x_buff* x)
+{
+ int res = 0;
+ ++(*fmt); /* skip tilde */
+ switch (*(*fmt)++) {
+ case 'a':
+ res = ei_x_encode_atom(x, (*args)->s);
+ (*args)++;
+ break;
+ case 's':
+ res = ei_x_encode_string(x, (*args)->s);
+ (*args)++;
+ break;
+ case 'i':
+ res = ei_x_encode_long(x, (*args)->l);
+ (*args)++;
+ break;
+ case 'l':
+ res = ei_x_encode_long(x, (*args)->l);
+ (*args)++;
+ break;
+ case 'u':
+ res = ei_x_encode_ulong(x, (*args)->u);
+ (*args)++;
+ break;
+ case 'f': /* float is expanded to double (C calling conventions) */
+ case 'd':
+ res = ei_x_encode_double(x, (*args)->d);
+ (*args)++;
+ break;
+ default:
+ res = -1;
+ break;
+ }
+ return res;
+}
+
+/* encode a tuple */
+static int ptuple(const char** fmt, union arg** args, ei_x_buff* x, int size)
+{
+ int res = 0;
+ const char* p = *fmt;
+ char after = *p++;
+
+ if (after == '}') {
+ *fmt = p;
+ return size;
+ }
+ while (isspace((int)*p))
+ ++p;
+ switch (*p++) {
+ case '}':
+ if (after == ',')
+ res = -1;
+ else
+ res = size;
+ break;
+ case ',':
+ if (after == ',' || after == '{')
+ res = -1;
+ else
+ res = ptuple(&p, args, x, size);
+ break;
+ default:
+ --p;
+ res = eiformat(&p, args, x);
+ if (res >= 0)
+ res = ptuple(&p, args, x, size + 1);
+ break;
+ /*
+ Variables
+ */
+ }
+ *fmt = p;
+ return res;
+}
+
+/* encode a list */
+static int plist(const char** fmt, union arg** args, ei_x_buff* x, int size)
+{
+ int res = 0;
+ const char* p = *fmt;
+ char after = *p++;
+
+ if (after == ']')
+ --p;
+ while (isspace((int)*p))
+ ++p;
+ switch (*p++) {
+ case ']':
+ if (after == ',')
+ res = -1;
+ else {
+ if (after != '|')
+ ei_x_encode_empty_list(x);
+ res = size;
+ }
+ break;
+ case '|':
+ if (after == '|' || after == ',')
+ res = -1;
+ else
+ res = plist(&p, args, x, size);
+ break;
+ case ',':
+ if (after == '|' || after == ',')
+ res = -1;
+ else
+ res = plist(&p, args, x, size);
+ break;
+ default:
+ --p;
+ res = eiformat(&p, args, x);
+ ++size;
+ if (res >= 0) {
+ if (after == '|') {
+ while (isspace((int)*p))
+ ++p;
+ if (*p != ']')
+ res = -1;
+ } else
+ res = plist(&p, args, x, size);
+ }
+ break;
+ /*
+ Variables
+ */
+ }
+ *fmt = p;
+ return res;
+}
+
+static int read_args(const char* fmt, va_list ap, union arg **argp)
+{
+ const char* p = fmt;
+ int arg_count = 0;
+ union arg* args;
+ int i = 0;
+
+ /* Count the number of format strings. Assume null terminated string. */
+
+ *argp = NULL;
+
+ while (*p) if (*p++ == '~') arg_count++;
+
+
+ if (!arg_count) {
+ return 0;
+ }
+ /* Allocate space for the arguments */
+
+ args = (union arg*)ei_malloc(arg_count * sizeof(union arg));
+
+ if (!args)
+ return -1;
+
+ p = fmt; /* Start again and fill array */
+
+ while (*p) {
+ if (*p++ == '~') {
+ if (!*p) {
+ ei_free(args);
+ return -1; /* Error, string not complete */
+ }
+ switch (*p++) {
+ case 'a':
+ case 's':
+ args[i++].s = va_arg(ap, char*);
+ break;
+ case 'i':
+#ifdef EI_64BIT
+ args[i++].l = (long) va_arg(ap, int);
+ break;
+#endif
+ case 'l':
+ args[i++].l = va_arg(ap, long);
+ break;
+ case 'u':
+ args[i++].u = va_arg(ap, unsigned long);
+ break;
+ case 'f': /* float is expanded to double (C calling conventions) */
+ case 'd':
+ args[i++].d = va_arg(ap, double);
+ break;
+ default:
+ ei_free(args); /* Invalid specifier */
+ return -1;
+ }
+ }
+ }
+ *argp = args;
+ return 0;
+}
+
+int ei_x_format(ei_x_buff* x, const char* fmt, ... )
+{
+ va_list ap;
+ union arg* args;
+ union arg* saved_args;
+ int res;
+
+ res = ei_x_encode_version(x);
+ if (res < 0) return res;
+
+ va_start(ap, fmt);
+ res = read_args(fmt,ap,&args);
+ saved_args = args;
+ va_end(ap);
+ if (res < 0) {
+ return -1;
+ }
+
+ res = eiformat(&fmt, &args, x);
+ ei_free(saved_args);
+
+ return res;
+}
+
+int ei_x_format_wo_ver(ei_x_buff* x, const char* fmt, ... )
+{
+ va_list ap;
+ union arg* args;
+ union arg* saved_args;
+ int res;
+
+ va_start(ap, fmt);
+ res = read_args(fmt,ap,&args);
+ saved_args = args;
+ va_end(ap);
+ if (res < 0) {
+ return -1;
+ }
+ res = eiformat(&fmt, &args, x);
+ ei_free(saved_args);
+
+ return res;
+}
diff --git a/lib/erl_interface/src/misc/ei_format.h b/lib/erl_interface/src/misc/ei_format.h
new file mode 100644
index 0000000000..e94d0531f5
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_format.h
@@ -0,0 +1,26 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+
+#ifndef _EI_FORMAT_H
+#define _EI_FORMAT_H
+
+#endif /* _EI_FORMAT_H */
+
diff --git a/lib/erl_interface/src/misc/ei_internal.h b/lib/erl_interface/src/misc/ei_internal.h
new file mode 100644
index 0000000000..9f51d1f61b
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_internal.h
@@ -0,0 +1,157 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifndef _EI_INTERNAL_H
+#define _EI_INTERNAL_H
+
+/*
+ * Some useful stuff not to be exported to users.
+ */
+
+#ifdef __WIN32__
+#define MAXPATHLEN 256
+#define writesocket(sock,buf,nbyte) send(sock,buf,nbyte,0)
+#define readsocket(sock,buf,nbyte) recv(sock,buf,nbyte,0)
+#else /* not __WIN32__ */
+#define writesocket write
+#define readsocket read
+#define closesocket close
+#define ioctlsocket ioctl
+#endif
+
+/*
+ * Trace functions
+ *
+ * The variable ei_tracelevel means
+ * 0 No tracing
+ * 1 Write verbose error messages
+ * 2 Write verbose warning messages + 1
+ * 3 Write progress reports for connect handlin + 1 + 2
+ * 4 Write progress reports for communication + 1 + 2 + 3
+ * 5 Write progress reports for data conversion + 1 + 2 + 3 + 4
+ *
+ */
+
+#define EI_TRACE_ERR0(NAME,FORMAT) \
+ {if (ei_tracelevel >= 1) ei_trace_printf(NAME,1,FORMAT);}
+#define EI_TRACE_ERR1(NAME,FORMAT,ARG1) \
+ {if (ei_tracelevel >= 1) ei_trace_printf(NAME,1,FORMAT,ARG1);}
+#define EI_TRACE_ERR2(NAME,FORMAT,ARG1,ARG2) \
+ {if (ei_tracelevel >= 1) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2);}
+#define EI_TRACE_ERR3(NAME,FORMAT,ARG1,ARG2,ARG3) \
+ {if (ei_tracelevel >= 1) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3);}
+#define EI_TRACE_ERR4(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4) \
+ {if (ei_tracelevel >= 1) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4);}
+#define EI_TRACE_ERR5(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5) \
+ {if (ei_tracelevel >= 1) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5);}
+#define EI_TRACE_ERR6(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) \
+ {if (ei_tracelevel >= 1) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6);}
+#define EI_TRACE_ERR7(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) \
+ {if (ei_tracelevel >= 1) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6,ARG7);}
+
+#define EI_TRACE_WARN0(NAME,FORMAT) \
+ {if (ei_tracelevel >= 2) ei_trace_printf(NAME,1,FORMAT);}
+#define EI_TRACE_WARN1(NAME,FORMAT,ARG1) \
+ {if (ei_tracelevel >= 2) ei_trace_printf(NAME,1,FORMAT,ARG1);}
+#define EI_TRACE_WARN2(NAME,FORMAT,ARG1,ARG2) \
+ {if (ei_tracelevel >= 2) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2);}
+#define EI_TRACE_WARN3(NAME,FORMAT,ARG1,ARG2,ARG3) \
+ {if (ei_tracelevel >= 2) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3);}
+#define EI_TRACE_WARN4(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4) \
+ {if (ei_tracelevel >= 2) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4);}
+#define EI_TRACE_WARN5(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5) \
+ {if (ei_tracelevel >= 2) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5);}
+#define EI_TRACE_WARN6(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) \
+ {if (ei_tracelevel >= 2) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6);}
+#define EI_TRACE_WARN7(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) \
+ {if (ei_tracelevel >= 2) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6,ARG7);}
+
+#define EI_TRACE_CONN0(NAME,FORMAT) \
+ {if (ei_tracelevel >= 3) ei_trace_printf(NAME,1,FORMAT);}
+#define EI_TRACE_CONN1(NAME,FORMAT,ARG1) \
+ {if (ei_tracelevel >= 3) ei_trace_printf(NAME,1,FORMAT,ARG1);}
+#define EI_TRACE_CONN2(NAME,FORMAT,ARG1,ARG2) \
+ {if (ei_tracelevel >= 3) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2);}
+#define EI_TRACE_CONN3(NAME,FORMAT,ARG1,ARG2,ARG3) \
+ {if (ei_tracelevel >= 3) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3);}
+#define EI_TRACE_CONN4(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4) \
+ {if (ei_tracelevel >= 3) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4);}
+#define EI_TRACE_CONN5(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5) \
+ {if (ei_tracelevel >= 3) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5);}
+#define EI_TRACE_CONN6(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) \
+ {if (ei_tracelevel >= 3) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6);}
+#define EI_TRACE_CONN7(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) \
+ {if (ei_tracelevel >= 3) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6,ARG7);}
+
+#define EI_TRACE_COMM0(NAME,FORMAT) \
+ {if (ei_tracelevel >= 4) ei_trace_printf(NAME,1,FORMAT);}
+#define EI_TRACE_COMM1(NAME,FORMAT,ARG1) \
+ {if (ei_tracelevel >= 4) ei_trace_printf(NAME,1,FORMAT,ARG1);}
+#define EI_TRACE_COMM2(NAME,FORMAT,ARG1,ARG2) \
+ {if (ei_tracelevel >= 4) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2);}
+#define EI_TRACE_COMM3(NAME,FORMAT,ARG1,ARG2,ARG3) \
+ {if (ei_tracelevel >= 4) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3);}
+#define EI_TRACE_COMM4(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4) \
+ {if (ei_tracelevel >= 4) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4);}
+#define EI_TRACE_COMM5(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5) \
+ {if (ei_tracelevel >= 4) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5);}
+#define EI_TRACE_COMM6(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) \
+ {if (ei_tracelevel >= 4) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6);}
+#define EI_TRACE_COMM7(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) \
+ {if (ei_tracelevel >= 4) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6,ARG7);}
+
+#define EI_TRACE0(NAME,FORMAT) \
+ {if (ei_tracelevel >= 5) ei_trace_printf(NAME,1,FORMAT);}
+#define EI_TRACE1(NAME,FORMAT,ARG1) \
+ {if (ei_tracelevel >= 5) ei_trace_printf(NAME,1,FORMAT,ARG1);}
+#define EI_TRACE2(NAME,FORMAT,ARG1,ARG2) \
+ {if (ei_tracelevel >= 5) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2);}
+#define EI_TRACE3(NAME,FORMAT,ARG1,ARG2,ARG3) \
+ {if (ei_tracelevel >= 5) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3);}
+#define EI_TRACE4(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4) \
+ {if (ei_tracelevel >= 5) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4);}
+#define EI_TRACE5(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5) \
+ {if (ei_tracelevel >= 5) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5);}
+#define EI_TRACE6(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) \
+ {if (ei_tracelevel >= 5) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6);}
+#define EI_TRACE7(NAME,FORMAT,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) \
+ {if (ei_tracelevel >= 5) ei_trace_printf(NAME,1,FORMAT,ARG1,ARG2,ARG3,ARG4, \
+ ARG5,ARG6,ARG7);}
+
+int ei_tracelevel;
+
+void ei_trace_printf(const char *name, int level, const char *format, ...);
+
+int ei_internal_use_r9_pids_ports(void);
+#endif /* _EI_INTERNAL_H */
diff --git a/lib/erl_interface/src/misc/ei_locking.c b/lib/erl_interface/src/misc/ei_locking.c
new file mode 100644
index 0000000000..e3f57d5ba2
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_locking.c
@@ -0,0 +1,164 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1997-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+/*
+ * common interface to some simple synchronisation primitives for
+ * internal use by ei.
+ */
+
+/* Note that these locks are NOT recursive on Win32 or Solaris,
+ * i.e. self-deadlock will occur if a thread tries to obtain a lock it
+ * is already holding. The primitives used on VxWorks are recursive however.
+ */
+
+#include "eidef.h"
+
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <windows.h>
+#include <winbase.h>
+
+#elif VXWORKS
+#include <vxWorks.h>
+#include <semLib.h>
+
+#else /* unix */
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#endif /* platforms */
+
+#include "ei_malloc.h"
+#include "ei_locking.h"
+
+#ifdef _REENTRANT
+
+/*
+ * Create a new mutex object.
+ * Returns a pointer to the mutex if successful, NULL otherwise.
+ */
+ei_mutex_t *ei_mutex_create(void)
+{
+ ei_mutex_t *l;
+
+ if ((l = ei_malloc(sizeof(*l))) == NULL) return NULL;
+
+#ifdef __WIN32__
+ l->lock = CreateMutex(NULL,FALSE,NULL);
+
+#elif VXWORKS
+ if (!(l->lock = semMCreate(SEM_DELETE_SAFE))) {
+ ei_free(l);
+ return NULL;
+ }
+#else /* unix */
+ l->lock = ei_m_create();
+#endif
+
+ return l;
+}
+
+/*
+ * Free a mutex and the structure asociated with it.
+ *
+ * This function attempts to obtain the mutex before releasing it;
+ * If nblock == 1 and the mutex was unavailable, the function will
+ * return failure and the mutex will not have been removed.
+ *
+ * If nblock == 0 the function will block until the mutex becomes
+ * available, at which time it will be removed and the function will
+ * succeed.
+ *
+ * returns 0 if the mutex is removed, -1 on failure (busy)
+ */
+int ei_mutex_free(ei_mutex_t *l, int nblock)
+{
+ /* attempt to lock it first, to make sure it's really free */
+ if (ei_mutex_lock(l,nblock)) return -1; /* attempt failed */
+
+ /* we are now holding the lock */
+#ifdef __WIN32__
+ CloseHandle(l->lock);
+
+#elif VXWORKS
+ if (semDelete(l->lock) == ERROR) return -1;
+
+#else /* unix */
+ ei_m_destroy(l->lock);
+#endif
+
+ ei_free(l);
+
+ return 0;
+}
+
+/* Grab a mutex. If the mutex is not held by any other process the
+ * function returns so that the caller may enter a critical section.
+ * Processes subsequently wishing to obtain the lock will block
+ * until this process releases it.
+ *
+ * If the mutex is busy (held by some other process) and nblock == 0,
+ * the function will block until the mutex is freed by the process
+ * holding it, returning only when the mutex has been grabbed.
+ *
+ * If the mutex is busy and nblock != 0, the function will not block.
+ * Instead it will return -1 immediately, indicating that the
+ * operation failed.
+
+ * Returns 0 on success, -1 on failure.
+ */
+int ei_mutex_lock(ei_mutex_t *l, int nblock)
+{
+#ifdef __WIN32__
+ /* check valid values for timeout: is 0 ok? */
+ if (WaitForSingleObject(l->lock,(nblock? 0 : INFINITE)) != WAIT_OBJECT_0)
+ return -1;
+
+#elif VXWORKS
+ if (semTake(l->lock,(nblock? NO_WAIT : WAIT_FOREVER)) == ERROR)
+ return -1;
+
+#else /* unix */
+ if (nblock) {
+ if (ei_m_trylock(l->lock) < 0) return -1;
+ }
+ else ei_m_lock(l->lock);
+#endif
+
+ return 0;
+}
+
+/* Release a mutex */
+int ei_mutex_unlock(ei_mutex_t *l)
+{
+#ifdef __WIN32__
+ ReleaseMutex(l->lock);
+
+#elif VXWORKS
+ semGive(l->lock);
+
+#else /* unix */
+ ei_m_unlock(l->lock);
+#endif
+
+ return 0;
+}
+
+#endif /* _REENTRANT */
diff --git a/lib/erl_interface/src/misc/ei_locking.h b/lib/erl_interface/src/misc/ei_locking.h
new file mode 100644
index 0000000000..f97683e40d
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_locking.h
@@ -0,0 +1,76 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1997-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifndef _EI_LOCKING_H
+#define _EI_LOCKING_H
+
+#include "config.h"
+
+#if defined(VXWORKS)
+#include <taskLib.h>
+#include <taskVarLib.h>
+#endif
+
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <windows.h>
+#include <winbase.h>
+#endif
+
+#ifdef HAVE_MIT_PTHREAD_H
+#include <pthread/mit/pthread.h>
+#elif HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+
+typedef struct ei_mutex_s {
+#ifdef __WIN32__
+ HANDLE lock;
+#elif VXWORKS
+ SEM_ID lock;
+#else /* unix */
+#if defined(HAVE_MIT_PTHREAD_H) || defined(HAVE_PTHREAD_H)
+ pthread_mutex_t *lock;
+#else /* ! (HAVE_MIT_PTHREAD_H || HAVE_PTHREAD_H) */
+ void *dummy; /* Actually never used */
+#endif /* ! (HAVE_MIT_PTHREAD_H || HAVE_PTHREAD_H) */
+#endif /* unix */
+} ei_mutex_t;
+
+extern ei_mutex_t* ei_sockets_lock; /* FIXME global variable! */
+
+ei_mutex_t *ei_mutex_create(void);
+int ei_mutex_free(ei_mutex_t *l, int nblock);
+int ei_mutex_lock(ei_mutex_t *l, int nblock);
+int ei_mutex_unlock(ei_mutex_t *l);
+
+
+#if defined(_REENTRANT) && !defined(VXWORKS) && !defined(__WIN32__)
+
+void *ei_m_create(void);
+int ei_m_destroy(void *l);
+int ei_m_lock(void *l);
+int ei_m_trylock(void *l);
+int ei_m_unlock(void *l);
+
+#endif /* _REENTRANT && !VXWORKS && !__WIN32__ */
+
+#endif /* _EI_LOCKING_H */
diff --git a/lib/erl_interface/src/misc/ei_malloc.c b/lib/erl_interface/src/misc/ei_malloc.c
new file mode 100644
index 0000000000..b122c0f7b8
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_malloc.c
@@ -0,0 +1,41 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+
+#include "eidef.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include "ei_malloc.h"
+
+void* ei_malloc (long size)
+{
+ return malloc(size);
+}
+
+void* ei_realloc(void* orig, long size)
+{
+ return realloc(orig, size);
+}
+
+void ei_free (void *ptr)
+{
+ free(ptr);
+}
diff --git a/lib/erl_interface/src/misc/ei_malloc.h b/lib/erl_interface/src/misc/ei_malloc.h
new file mode 100644
index 0000000000..ef8efaf9ea
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_malloc.h
@@ -0,0 +1,28 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifndef _EI_MALLOC_H
+#define _EI_MALLOC_H
+
+void* ei_malloc (long size);
+void* ei_realloc(void* orig, long size);
+void ei_free (void *ptr);
+
+#endif /* _EI_MALLOC_H */
diff --git a/lib/erl_interface/src/misc/ei_portio.c b/lib/erl_interface/src/misc/ei_portio.c
new file mode 100644
index 0000000000..b73ebebbe1
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_portio.c
@@ -0,0 +1,377 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifdef __WIN32__
+#include <winsock2.h>
+#include <windows.h>
+#include <process.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+
+static unsigned long param_zero = 0;
+static unsigned long param_one = 1;
+#define SET_BLOCKING(Sock) ioctlsocket((Sock),FIONBIO,&param_zero)
+#define SET_NONBLOCKING(Sock) ioctlsocket((Sock),FIONBIO,&param_one)
+
+#define ERROR_WOULDBLOCK WSAEWOULDBLOCK
+#define ERROR_TIMEDOUT WSAETIMEDOUT
+#define ERROR_INPROGRESS WSAEINPROGRESS
+#define GET_SOCKET_ERROR() WSAGetLastError()
+#define MEANS_SOCKET_ERROR(Ret) ((Ret == SOCKET_ERROR))
+#define IS_INVALID_SOCKET(Sock) ((Sock) == INVALID_SOCKET)
+
+#elif VXWORKS
+#include <vxWorks.h>
+#include <hostLib.h>
+#include <ifLib.h>
+#include <sockLib.h>
+#include <taskLib.h>
+#include <inetLib.h>
+#include <selectLib.h>
+#include <sys/types.h>
+#include <ioLib.h>
+#include <unistd.h>
+
+static unsigned long param_zero = 0;
+static unsigned long param_one = 1;
+#define SET_BLOCKING(Sock) ioctl((Sock),FIONBIO,(int)&param_zero)
+#define SET_NONBLOCKING(Sock) ioctl((Sock),FIONBIO,(int)&param_one)
+#define ERROR_WOULDBLOCK EWOULDBLOCK
+#define ERROR_TIMEDOUT ETIMEDOUT
+#define ERROR_INPROGRESS EINPROGRESS
+#define GET_SOCKET_ERROR() (errno)
+#define MEANS_SOCKET_ERROR(Ret) ((Ret) == ERROR)
+#define IS_INVALID_SOCKET(Sock) ((Sock) < 0)
+
+#else /* other unix */
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#ifndef EWOULDBLOCK
+#define ERROR_WOULDBLOCK EAGAIN
+#else
+#define ERROR_WOULDBLOCK EWOULDBLOCK
+#endif
+#define SET_BLOCKING(fd) fcntl((fd), F_SETFL, \
+ fcntl((fd), F_GETFL, 0) & ~O_NONBLOCK)
+#define SET_NONBLOCKING(fd) fcntl((fd), F_SETFL, \
+ fcntl((fd), F_GETFL, 0) | O_NONBLOCK)
+#define ERROR_TIMEDOUT ETIMEDOUT
+#define ERROR_INPROGRESS EINPROGRESS
+#define GET_SOCKET_ERROR() (errno)
+#define MEANS_SOCKET_ERROR(Ret) ((Ret) < 0)
+#define IS_INVALID_SOCKET(Sock) ((Sock) < 0)
+
+#endif
+
+/* common includes */
+#include "eidef.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ei_portio.h"
+#include "ei_internal.h"
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+
+#ifdef HAVE_WRITEV
+static int ei_writev_t(int fd, struct iovec *iov, int iovcnt, unsigned ms)
+{
+ int res;
+ if (ms != 0) {
+ fd_set writemask;
+ struct timeval tv;
+ tv.tv_sec = (time_t) (ms / 1000U);
+ ms %= 1000U;
+ tv.tv_usec = (time_t) (ms * 1000U);
+ FD_ZERO(&writemask);
+ FD_SET(fd,&writemask);
+ switch (select(fd+1, NULL, &writemask, NULL, &tv)) {
+ case -1 :
+ return -1; /* i/o error */
+ case 0:
+ return -2; /* timeout */
+ default:
+ if (!FD_ISSET(fd, &writemask)) {
+ return -1; /* Other error */
+ }
+ }
+ }
+ res = writev(fd, iov, iovcnt);
+ return (res < 0) ? -1 : res;
+}
+
+int ei_writev_fill_t(int fd, const struct iovec *iov, int iovcnt, unsigned ms)
+{
+ int i;
+ int done;
+ struct iovec *iov_base = NULL;
+ struct iovec *current_iov;
+ int current_iovcnt;
+ int sum;
+
+ for (sum = 0, i = 0; i < iovcnt; ++i) {
+ sum += iov[i].iov_len;
+ }
+ if (ms != 0U) {
+ SET_NONBLOCKING(fd);
+ }
+ current_iovcnt = iovcnt;
+ current_iov = (struct iovec *) iov;
+ done = 0;
+ for (;;) {
+ i = ei_writev_t(fd, current_iov, current_iovcnt, ms);
+ if (i <= 0) { /* ei_writev_t should always return at least 1 */
+ if (ms != 0U) {
+ SET_BLOCKING(fd);
+ }
+ if (iov_base != NULL) {
+ free(iov_base);
+ }
+ return (i);
+ }
+ done += i;
+
+ if (done < sum) {
+ if (iov_base == NULL) {
+ iov_base = malloc(sizeof(struct iovec) * iovcnt);
+ memcpy(iov_base, iov, sizeof(struct iovec) * iovcnt);
+ current_iov = iov_base;
+ }
+ while (i > 0) {
+ if (i < current_iov[0].iov_len) {
+ current_iov[0].iov_len -= i;
+ i = 0;
+ } else {
+ i -= current_iov[0].iov_len;
+ current_iov++;
+ current_iovcnt--;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ if (ms != 0U) {
+ SET_BLOCKING(fd);
+ }
+ if (iov_base != NULL) {
+ free(iov_base);
+ }
+ return (sum);
+}
+
+
+#endif
+
+int ei_connect_t(int fd, void *sinp, int sin_siz, unsigned ms)
+{
+ int res;
+ int error;
+ int s_res;
+ struct timeval tv;
+ fd_set writefds;
+ fd_set exceptfds;
+
+ if (ms == 0) {
+ res = connect(fd, sinp, sin_siz);
+ return (res < 0) ? -1 : res;
+ } else {
+ SET_NONBLOCKING(fd);
+ res = connect(fd, sinp, sin_siz);
+ error = GET_SOCKET_ERROR();
+ SET_BLOCKING(fd);
+ if (!MEANS_SOCKET_ERROR(res)) {
+ return (res < 0) ? -1 : res;
+ } else {
+ if (error != ERROR_WOULDBLOCK &&
+ error != ERROR_INPROGRESS) {
+ return -1;
+ } else {
+ tv.tv_sec = (long) (ms/1000U);
+ ms %= 1000U;
+ tv.tv_usec = (long) (ms * 1000U);
+ FD_ZERO(&writefds);
+ FD_SET(fd,&writefds);
+ FD_ZERO(&exceptfds);
+ FD_SET(fd,&exceptfds);
+ s_res = select(fd + 1, NULL, &writefds, &exceptfds, &tv);
+ switch (s_res) {
+ case 0:
+ return -2;
+ case 1:
+ if (FD_ISSET(fd, &exceptfds)) {
+ return -1;
+ } else {
+ return 0; /* Connect completed */
+ }
+ default:
+ return -1;
+ }
+ }
+ }
+ }
+}
+
+int ei_accept_t(int fd, void *addr, void *addrlen, unsigned ms)
+{
+ int res;
+ if (ms != 0) {
+ fd_set readmask;
+ struct timeval tv;
+ tv.tv_sec = (time_t) (ms / 1000U);
+ ms %= 1000U;
+ tv.tv_usec = (time_t) (ms * 1000U);
+ FD_ZERO(&readmask);
+ FD_SET(fd,&readmask);
+ switch (select(fd+1, &readmask, NULL, NULL, &tv)) {
+ case -1 :
+ return -1; /* i/o error */
+ case 0:
+ return -2; /* timeout */
+ default:
+ if (!FD_ISSET(fd, &readmask)) {
+ return -1; /* Other error */
+ }
+ }
+ }
+ res = (int) accept(fd,addr,addrlen);
+ return (res < 0) ? -1 : res;
+}
+
+
+
+static int ei_read_t(int fd, char* buf, int len, unsigned ms)
+{
+ int res;
+ if (ms != 0) {
+ fd_set readmask;
+ struct timeval tv;
+ tv.tv_sec = (time_t) (ms / 1000U);
+ ms %= 1000U;
+ tv.tv_usec = (time_t) (ms * 1000U);
+ FD_ZERO(&readmask);
+ FD_SET(fd,&readmask);
+ switch (select(fd+1, &readmask, NULL, NULL, &tv)) {
+ case -1 :
+ return -1; /* i/o error */
+ case 0:
+ return -2; /* timeout */
+ default:
+ if (!FD_ISSET(fd, &readmask)) {
+ return -1; /* Other error */
+ }
+ }
+ }
+ res = readsocket(fd, buf, len);
+ return (res < 0) ? -1 : res;
+}
+
+static int ei_write_t(int fd, const char* buf, int len, unsigned ms)
+{
+ int res;
+ if (ms != 0) {
+ fd_set writemask;
+ struct timeval tv;
+ tv.tv_sec = (time_t) (ms / 1000U);
+ ms %= 1000U;
+ tv.tv_usec = (time_t) (ms * 1000U);
+ FD_ZERO(&writemask);
+ FD_SET(fd,&writemask);
+ switch (select(fd+1, NULL, &writemask, NULL, &tv)) {
+ case -1 :
+ return -1; /* i/o error */
+ case 0:
+ return -2; /* timeout */
+ default:
+ if (!FD_ISSET(fd, &writemask)) {
+ return -1; /* Other error */
+ }
+ }
+ }
+ res = writesocket(fd, buf, len);
+ return (res < 0) ? -1 : res;
+}
+
+/*
+ * Fill buffer, return buffer length, 0 for EOF, < 0 (and sets errno)
+ * for error. */
+int ei_read_fill_t(int fd, char* buf, int len, unsigned ms)
+{
+ int i,got=0;
+
+ do {
+ i = ei_read_t(fd, buf+got, len-got, ms);
+ if (i <= 0)
+ return (i);
+ got += i;
+ } while (got < len);
+ return (len);
+
+} /* read_fill */
+
+int ei_read_fill(int fd, char* buf, int len)
+{
+ return ei_read_fill_t(fd, buf, len, 0);
+}
+
+/* write entire buffer on fd or fail (setting errno)
+ */
+int ei_write_fill_t(int fd, const char *buf, int len, unsigned ms)
+{
+ int i,done=0;
+ if (ms != 0U) {
+ SET_NONBLOCKING(fd);
+ }
+ do {
+ i = ei_write_t(fd, buf+done, len-done, ms);
+ if (i <= 0) {
+ if (ms != 0U) {
+ SET_BLOCKING(fd);
+ }
+ return (i);
+ }
+ done += i;
+ } while (done < len);
+ if (ms != 0U) {
+ SET_BLOCKING(fd);
+ }
+ return (len);
+}
+
+int ei_write_fill(int fd, const char *buf, int len)
+{
+ return ei_write_fill_t(fd, buf, len, 0);
+}
+
diff --git a/lib/erl_interface/src/misc/ei_portio.h b/lib/erl_interface/src/misc/ei_portio.h
new file mode 100644
index 0000000000..f2c92278db
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_portio.h
@@ -0,0 +1,35 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifndef _EI_PORTIO_H
+#define _EI_PORTIO_H
+
+int ei_accept_t(int fd, void *addr, void *addrlen, unsigned ms);
+int ei_connect_t(int fd, void *sinp, int sin_siz, unsigned ms);
+int ei_read_fill(int fd, char* buf, int len);
+int ei_write_fill(int fd, const char *buf, int len);
+int ei_read_fill_t(int fd, char* buf, int len, unsigned ms);
+int ei_write_fill_t(int fd, const char *buf, int len, unsigned ms);
+#ifdef HAVE_WRITEV
+int ei_writev_fill_t(int fd, const struct iovec *iov, int iovcnt,
+ unsigned ms);
+#endif
+
+#endif /* _EI_PORTIO_H */
diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c
new file mode 100644
index 0000000000..8d0eef5e79
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_printterm.c
@@ -0,0 +1,342 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+/*
+ * Function:
+ * ei_print_term to print out a binary coded term
+ */
+
+#ifdef VXWORKS
+#include <vxWorks.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef VRTX
+#define __READY_EXTENSIONS__
+#include <errno.h>
+#endif
+
+#include "eidef.h"
+#include "eiext.h"
+#include "ei_printterm.h"
+#include "ei_malloc.h"
+
+#define BINPRINTSIZE 30
+
+/*
+ * PRINT out a binary term (hacked from 'erl'_print_term)
+ */
+
+static int print_string(FILE* fp, ei_x_buff* x, char* s, int len);
+static int print_term(FILE* fp, ei_x_buff* x,
+ const char* buf, int* index);
+
+static void xputc(char c, FILE* fp, ei_x_buff* x)
+{
+ if (fp != NULL)
+ putc(c, fp);
+ else
+ ei_x_append_buf(x, &c, 1);
+}
+
+static void xputs(const char* s, FILE* fp, ei_x_buff* x)
+{
+ if (fp != NULL)
+ fputs(s, fp);
+ else
+ ei_x_append_buf(x, s, strlen(s));
+}
+
+static int xprintf(FILE* fp, ei_x_buff* x, const char* fmt, ...)
+{
+ int r = 0;
+ va_list ap;
+ va_start(ap, fmt);
+ if (fp != NULL) {
+ r = vfprintf(fp, fmt, ap);
+ } else {
+ /* FIXME always enough in buffer??? */
+ char tmpbuf[2000];
+ r = vsprintf(tmpbuf, fmt, ap);
+ ei_x_append_buf(x, tmpbuf, strlen(tmpbuf));
+ }
+ va_end(ap);
+ return r;
+}
+
+static char *ei_big_to_str(erlang_big *b)
+{
+ int buf_len;
+ char *s,*buf;
+ unsigned short *sp;
+ int i;
+
+ buf_len = 64+b->is_neg+10*b->arity;
+ if ( (buf=malloc(buf_len)) == NULL) return NULL;
+
+ memset(buf,(char)0,buf_len);
+
+ s = buf;
+ if ( b->is_neg )
+ s += sprintf(s,"-");
+ s += sprintf(s,"#integer(%d) = {",b->arity);
+ for(sp=b->digits,i=0;i<b->arity;i++) {
+ s += sprintf(s,"%d",sp[i]);
+ if ( (i+1) != b->arity )
+ s += sprintf(s,",");
+ }
+ s += sprintf(s,"}");
+ return buf;
+}
+
+static int print_term(FILE* fp, ei_x_buff* x,
+ const char* buf, int* index)
+{
+ int i, doquote, n, m, ty, r;
+ char a[MAXATOMLEN+1], *p;
+ int ch_written = 0; /* counter of written chars */
+ erlang_pid pid;
+ erlang_port port;
+ erlang_ref ref;
+ double d;
+ long l;
+
+ int tindex = *index;
+
+ /* use temporary index for multiple (and failable) decodes */
+
+ if (fp == NULL && x == NULL) return -1;
+
+ doquote = 0;
+ ei_get_type_internal(buf, index, &ty, &n);
+ switch (ty) {
+ case ERL_ATOM_EXT:
+ if (ei_decode_atom(buf, index, a) < 0)
+ goto err;
+ doquote = !islower((int)a[0]);
+ for (p = a; !doquote && *p != '\0'; ++p)
+ doquote = !(isalnum((int)*p) || *p == '_' || *p == '@');
+ if (doquote) {
+ xputc('\'', fp, x); ++ch_written;
+ }
+ xputs(a, fp, x); ch_written += strlen(a);
+ if (doquote) {
+ xputc('\'', fp, x); ++ch_written;
+ }
+ break;
+ case ERL_PID_EXT:
+ if (ei_decode_pid(buf, index, &pid) < 0) goto err;
+ ch_written += xprintf(fp, x, "<%s.%d.%d>", pid.node,
+ pid.num, pid.serial);
+ break;
+ case ERL_PORT_EXT:
+ if (ei_decode_port(buf, index, &port) < 0) goto err;
+ ch_written += xprintf(fp, x, "#Port<%d.%d>", port.id, port.creation);
+ break;
+ case ERL_NEW_REFERENCE_EXT:
+ case ERL_REFERENCE_EXT:
+ if (ei_decode_ref(buf, index, &ref) < 0) goto err;
+ ch_written += xprintf(fp, x, "#Ref<");
+ for (i = 0; i < ref.len; ++i) {
+ ch_written += xprintf(fp, x, "%d", ref.n[i]);
+ if (i < ref.len - 1) {
+ xputc('.', fp, x); ++ch_written;
+ }
+ }
+ xputc('>', fp, x); ++ch_written;
+ break;
+ case ERL_NIL_EXT:
+ if (ei_decode_list_header(buf, index, &n) < 0) goto err;
+ ch_written += xprintf(fp, x, "[]");
+ break;
+ case ERL_LIST_EXT:
+ if (ei_decode_list_header(buf, &tindex, &n) < 0) goto err;
+ xputc('[', fp, x); ch_written++;
+ for (i = 0; i < n; ++i) {
+ 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;
+ }
+ }
+ if (ei_get_type_internal(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);
+ if (r < 0) goto err;
+ ch_written += r;
+ } else {
+ if (ei_decode_list_header(buf, &tindex, &n) < 0) goto err;
+ }
+ xputc(']', fp, x); ch_written++;
+ *index = tindex;
+ break;
+ case ERL_STRING_EXT:
+ p = ei_malloc(n+1);
+ if (p == NULL) goto err;
+ if (ei_decode_string(buf, index, p) < 0) {
+ ei_free(p);
+ goto err;
+ }
+ ch_written += print_string(fp, x, p, n);
+ ei_free(p);
+ break;
+ case ERL_SMALL_TUPLE_EXT:
+ case ERL_LARGE_TUPLE_EXT:
+ if (ei_decode_tuple_header(buf, &tindex, &n) < 0) goto err;
+ xputc('{', fp, x); ch_written++;
+
+ for (i = 0; i < n; ++i) {
+ 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_BINARY_EXT:
+ p = ei_malloc(n);
+ if (p == NULL) goto err;
+ if (ei_decode_binary(buf, index, p, &l) < 0) {
+ ei_free(p);
+ goto err;
+ }
+ ch_written += xprintf(fp, x, "#Bin<");
+ if (l > BINPRINTSIZE)
+ m = BINPRINTSIZE;
+ else
+ m = l;
+ --m;
+ for (i = 0; i < m; ++i) {
+ ch_written += xprintf(fp, x, "%d,", p[i]);
+ }
+ 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_SMALL_INTEGER_EXT:
+ case ERL_INTEGER_EXT:
+ if (ei_decode_long(buf, index, &l) < 0) goto err;
+ ch_written += xprintf(fp, x, "%ld", l);
+ break;
+ case ERL_SMALL_BIG_EXT:
+ case ERL_LARGE_BIG_EXT:
+ {
+ erlang_big *b;
+ char *ds;
+
+ b = ei_alloc_big(n);
+ if (ei_decode_big(buf, index, b) < 0) {
+ ei_free_big(b);
+ goto err;
+ }
+
+ if ( (ds = ei_big_to_str(b)) == NULL ) {
+ ei_free_big(b);
+ goto err;
+ }
+
+ ch_written += xprintf(fp, x, ds);
+ free(ds);
+ ei_free_big(b);
+
+ }
+ break;
+
+ case ERL_FLOAT_EXT:
+ if (ei_decode_double(buf, index, &d) < 0) goto err;
+ ch_written += xprintf(fp, x, "%f", d);
+ break;
+ default:
+ goto err;
+ }
+ return ch_written;
+ err:
+ return -1;
+}
+
+static int print_string(FILE* fp, ei_x_buff* x, char* s, int len)
+{
+ int ch_written = 0; /* counter of written chars */
+
+ xputc('"', fp, x);
+ ++ch_written;
+ for (; len > 0; ++s, --len) {
+ int c = *s;
+ if (c >= ' ') {
+ xputc((char)c, fp, x); ++ch_written; }
+ else {
+ switch (c) {
+ case '\n': xputs("\\n", fp, x); ch_written += 2; break;
+ case '\r': xputs("\\r", fp, x); ch_written += 2; break;
+ case '\t': xputs("\\t", fp, x); ch_written += 2; break;
+ case '\v': xputs("\\v", fp, x); ch_written += 2; break;
+ case '\b': xputs("\\b", fp, x); ch_written += 2; break;
+ case '\f': xputs("\\f", fp, x); ch_written += 2; break;
+ break;
+ default:
+ ch_written += xprintf(fp, x, "\\x%x", c);
+ break;
+ }
+ }
+ }
+ xputc('"', fp, x); ch_written++;
+ return ch_written;
+}
+
+/* ------------------------------------------ */
+
+/*
+ * skip a binary term
+ */
+
+
+int ei_print_term(FILE *fp, const char* buf, int* index)
+{
+ return print_term(fp, NULL, buf, index);
+}
+
+int ei_s_print_term(char** s, const char* buf, int* index)
+{
+ int r;
+ ei_x_buff x;
+ if (*s != NULL) {
+ x.buff = *s;
+ x.index = 0;
+ x.buffsz = BUFSIZ;
+ } else {
+ ei_x_new(&x);
+ }
+ r = print_term(NULL, &x, buf, index);
+ ei_x_append_buf(&x, "", 1); /* append '\0' */
+ *s = x.buff;
+ return r;
+}
diff --git a/lib/erl_interface/src/misc/ei_printterm.h b/lib/erl_interface/src/misc/ei_printterm.h
new file mode 100644
index 0000000000..13350e3ecd
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_printterm.h
@@ -0,0 +1,24 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifndef _EI_PRINTTERM_H
+#define _EI_PRINTTERM_H
+
+#endif /* _EI_PRINTTERM_H */
diff --git a/lib/erl_interface/src/misc/ei_pthreads.c b/lib/erl_interface/src/misc/ei_pthreads.c
new file mode 100644
index 0000000000..a741dfd5c2
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_pthreads.c
@@ -0,0 +1,226 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+
+/* FIXME why not use ei_malloc here? */
+
+#include "eidef.h"
+
+#include <stdlib.h>
+#include "ei.h"
+#include "ei_locking.h"
+
+#ifdef __WIN32__
+#ifdef USE_DECLSPEC_THREAD
+/* Define (and initialize) the variable __erl_errno */
+volatile __declspec(thread) int __erl_errno = 0;
+#else
+static volatile DWORD errno_tls_index = TLS_OUT_OF_INDEXES;
+static LONG volatile tls_init_mutex = 0;
+#endif
+#endif
+
+#if defined(VXWORKS)
+
+/*
+ Moved to each of the erl_*threads.c files, as they seem to know how
+ to get thread-safety.
+*/
+static volatile int __erl_errno;
+volatile int *__erl_errno_place(void)
+{
+ /* This check is somewhat insufficient, double task var entries will occur
+ if __erl_errno is actually -1, which on the other hand is an invalid
+ error code. */
+ if (taskVarGet(taskIdSelf(), &__erl_errno) == ERROR) {
+ taskVarAdd(taskIdSelf(), &__erl_errno);
+ }
+ return &__erl_errno;
+}
+#endif /* VXWORKS */
+
+#if defined(__WIN32__)
+
+#ifdef USE_DECLSPEC_THREAD
+
+volatile int *__erl_errno_place(void)
+{
+ return &__erl_errno;
+}
+
+#else
+static void tls_init_once(void)
+{
+
+ if (errno_tls_index != TLS_OUT_OF_INDEXES) {
+ return;
+ }
+ if (InterlockedExchange((LPLONG) &tls_init_mutex,1L) == 0) {
+ /* I was first */
+ errno_tls_index = TlsAlloc();
+ if (errno_tls_index == TLS_OUT_OF_INDEXES) {
+ fprintf(stderr,
+ "FATAL ERROR: can not allocate TLS index for "
+ "erl_errno (error code = %d)!\n",GetLastError());
+ exit(1);
+ }
+ } else {
+ while (errno_tls_index == TLS_OUT_OF_INDEXES) {
+ SwitchToThread();
+ }
+ }
+}
+
+volatile int *__erl_errno_place(void)
+{
+ volatile int *ptr;
+ tls_init_once();
+ ptr = TlsGetValue(errno_tls_index);
+ if (ptr == NULL) {
+ ptr = malloc(sizeof(int));
+ *ptr = 0;
+ TlsSetValue(errno_tls_index, (PVOID) ptr);
+ }
+ return ptr;
+}
+
+#endif /* USE_DECLSPEC_THREAD */
+
+#endif /* __WIN32__ */
+
+#if defined(_REENTRANT) && !defined(VXWORKS) && !defined(__WIN32__)
+
+#if defined(HAVE_PTHREAD_H) || defined(HAVE_MIT_PTHREAD_H)
+
+void *ei_m_create(void)
+{
+ pthread_mutex_t *l;
+
+ if ((l = malloc(sizeof(*l)))) { /* FIXME get memory or abort */
+ pthread_mutex_init(l,NULL);
+ }
+
+ return l;
+}
+
+int ei_m_destroy(void *l)
+{
+ int r = pthread_mutex_destroy(l);
+ free(l);
+
+ return r;
+}
+
+int ei_m_lock(void *l)
+{
+ return pthread_mutex_lock(l);
+}
+
+int ei_m_trylock(void *l)
+{
+ return pthread_mutex_trylock(l);
+}
+
+int ei_m_unlock(void *l)
+{
+ return pthread_mutex_unlock(l);
+}
+
+
+/*
+ * Thread-specific erl_errno variable.
+ *
+ * The second line below will give a "missing braces around initializer"
+ * on Solaris but the code will work.
+ */
+
+static pthread_key_t erl_errno_key;
+static pthread_once_t erl_errno_key_once = PTHREAD_ONCE_INIT;
+
+/*
+ * Destroy per-thread erl_errno locus
+ */
+static void erl_errno_destroy(void * ptr)
+{
+ free(ptr);
+}
+
+/*
+ * Allocate erl_errno key.
+ * This will be done once for all threads
+ */
+static void erl_errno_key_alloc(void)
+{
+ pthread_key_create(&erl_errno_key, erl_errno_destroy);
+}
+
+/*
+ * Return a pointer to the erl_errno locus.
+ * If pthread functions fail we fall back to using fallback_errno
+ * so that the main thread (actually not a thread in all ascpects)
+ * still will set and get an erl_errno value.
+ * Actually this is a bit to nice, it would be preferrable to exit fatal
+ * as we do on windows, but we might break some code with one thread
+ * but still compiled with -D_REENTRANT, so we'll leave it here.
+ */
+volatile int *__erl_errno_place(void)
+{
+ int *erl_errno_p;
+ static volatile int use_fallback = 0;
+ static volatile int fallback_errno = 0;
+
+ if (use_fallback) {
+ return &fallback_errno;
+ }
+
+ /* This will create the key once for all threads */
+ if (pthread_once(&erl_errno_key_once, erl_errno_key_alloc) != 0) {
+ use_fallback = 1;
+ return &fallback_errno;
+ }
+
+ /* This is the normal case, return the pointer to the data */
+ if ((erl_errno_p = pthread_getspecific(erl_errno_key)) != NULL) {
+ return erl_errno_p;
+ }
+
+ if ((erl_errno_p = malloc(sizeof(int))) == NULL) {
+ use_fallback = 1;
+ return &fallback_errno;
+ }
+
+ if (pthread_setspecific(erl_errno_key, erl_errno_p) != 0 ||
+ (erl_errno_p = pthread_getspecific(erl_errno_key)) == NULL) {
+ free(erl_errno_p);
+ return &fallback_errno;
+ }
+
+ return erl_errno_p;
+}
+
+#endif /* HAVE_PTHREAD_H || HAVE_MIT_PTHREAD_H */
+
+#endif /* _REENTRANT && !VXWORKS && !__WIN32__ */
+
+#if !defined(_REENTRANT) && !defined(VXWORKS) && !defined(__WIN32__)
+
+volatile int __erl_errno;
+
+#endif
diff --git a/lib/erl_interface/src/misc/ei_trace.c b/lib/erl_interface/src/misc/ei_trace.c
new file mode 100644
index 0000000000..fb183c8be4
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_trace.c
@@ -0,0 +1,56 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#include "eidef.h"
+#include "ei_trace.h"
+
+/* this is our lamport clock */
+erlang_trace *ei_trace(int query, erlang_trace *token)
+{
+ /* FIXME problem for threaded ? */
+ static erlang_trace save_token;
+ static int tracing = 0;
+ static int clock = 0;
+
+
+ switch (query) {
+ case -1: /* we are no longer tracing */
+ tracing = 0;
+ break;
+
+ case 0: /* are we tracing? */
+ if (tracing) {
+ clock++;
+ save_token.prev = save_token.serial++;
+ return &save_token;
+ }
+ break;
+
+ case 1: /* we are now tracing */
+ tracing = 1;
+ save_token = *token;
+ if (save_token.serial > clock)
+ save_token.prev = clock = token->serial;
+ break;
+ }
+
+ return NULL;
+}
+
diff --git a/lib/erl_interface/src/misc/ei_trace.h b/lib/erl_interface/src/misc/ei_trace.h
new file mode 100644
index 0000000000..d3513c9353
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_trace.h
@@ -0,0 +1,26 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifndef _EI_TRACE_H
+#define _EI_TRACE_H
+
+erlang_trace *ei_trace(int query, erlang_trace *token);
+
+#endif /* _EI_TRACE_H */
diff --git a/lib/erl_interface/src/misc/ei_x_encode.c b/lib/erl_interface/src/misc/ei_x_encode.c
new file mode 100644
index 0000000000..fa1e26ccbb
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_x_encode.c
@@ -0,0 +1,255 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+/*
+ * ei_x_encode to encode in a self-expanding buffer
+ */
+
+#ifdef VXWORKS
+#include <vxWorks.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef VRTX
+#define __READY_EXTENSIONS__
+#include <errno.h>
+#endif
+
+#include "eidef.h"
+#include "ei_x_encode.h"
+#include "ei_malloc.h"
+
+int ei_x_extra = 100;
+
+int ei_x_new(ei_x_buff* x)
+{
+ x->buff = ei_malloc(ei_x_extra);
+ x->buffsz = ei_x_extra;
+ x->index = 0;
+ return x->buff != NULL ? 0 : -1;
+}
+
+int ei_x_new_with_version(ei_x_buff* x)
+{
+ if (ei_x_new(x) < 0)
+ return -1;
+ return ei_encode_version(x->buff, &x->index);
+}
+
+int ei_x_free(ei_x_buff* x)
+{
+ if (x->buff == NULL)
+ return -1;
+ ei_free(x->buff);
+ x->buff = NULL;
+ return 0;
+}
+
+int x_fix_buff(ei_x_buff* x, int szneeded)
+{
+ int sz = szneeded + ei_x_extra;
+ if (sz > x->buffsz) {
+ sz += ei_x_extra; /* to avoid reallocating each and every time */
+ x->buffsz = sz;
+ x->buff = ei_realloc(x->buff, sz);
+ }
+ return x->buff != NULL;
+}
+
+int ei_x_append(ei_x_buff* x, const ei_x_buff* x2)
+{
+ return ei_x_append_buf(x, x2->buff, x2->index);
+}
+
+int ei_x_append_buf(ei_x_buff* x, const char* buf, int len)
+{
+ if (!x_fix_buff(x, x->index+len))
+ return -1;
+ memcpy(&x->buff[x->index], buf, len);
+ x->index += len;
+ return 0;
+}
+
+int ei_x_encode_string(ei_x_buff* x, const char* s)
+{
+ return ei_x_encode_string_len(x, s, strlen(s));
+}
+
+int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len)
+{
+ int i = x->index;
+ ei_encode_string_len(NULL, &i, s, len);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_string_len(x->buff, &x->index, s, len);
+}
+
+int ei_x_encode_binary(ei_x_buff* x, const void* p, int len)
+{
+ int i = x->index;
+ ei_encode_binary(NULL, &i, p, len);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_binary(x->buff, &x->index, p, len);
+}
+
+int ei_x_encode_long(ei_x_buff* x, long n)
+{
+ int i = x->index;
+ ei_encode_long(NULL, &i, n);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_long(x->buff, &x->index, n);
+}
+
+int ei_x_encode_ulong(ei_x_buff* x, unsigned long n)
+{
+ int i = x->index;
+ ei_encode_ulong(NULL, &i, n);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_ulong(x->buff, &x->index, n);
+}
+
+int ei_x_encode_char(ei_x_buff* x, char p)
+{
+ int i = x->index;
+ ei_encode_char(NULL, &i, p);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_char(x->buff, &x->index, p);
+}
+
+int ei_x_encode_boolean(ei_x_buff* x, int p)
+{
+ int i = x->index;
+ ei_encode_boolean(NULL, &i, p);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_boolean(x->buff, &x->index, p);
+}
+
+int ei_x_encode_double(ei_x_buff* x, double dbl)
+{
+ int i = x->index;
+ ei_encode_double(NULL, &i, dbl);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_double(x->buff, &x->index, dbl);
+}
+
+int ei_x_encode_list_header(ei_x_buff* x, long n)
+{
+ int i = x->index;
+ ei_encode_list_header(NULL, &i, n);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_list_header(x->buff, &x->index, n);
+}
+
+int ei_x_encode_empty_list(ei_x_buff* x)
+{
+ int i = x->index;
+ ei_encode_empty_list(NULL, &i);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_empty_list(x->buff, &x->index);
+}
+
+int ei_x_encode_version(ei_x_buff* x)
+{
+ int i = x->index;
+ ei_encode_version(NULL, &i);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_version(x->buff, &x->index);
+}
+
+int ei_x_encode_tuple_header(ei_x_buff* x, long n)
+{
+ int i = x->index;
+ ei_encode_tuple_header(NULL, &i, n);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_tuple_header(x->buff, &x->index, n);
+}
+
+int ei_x_encode_atom(ei_x_buff* x, const char* s)
+{
+ return ei_x_encode_atom_len(x, s, strlen(s));
+}
+
+int ei_x_encode_atom_len(ei_x_buff* x, const char* s, int len)
+{
+ int i = x->index;
+ ei_encode_atom_len(NULL, &i, s, len);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_atom_len(x->buff, &x->index, s, len);
+}
+
+int ei_x_encode_pid(ei_x_buff* x, const erlang_pid* pid)
+{
+ int i = x->index;
+ ei_encode_pid(NULL, &i, pid);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_pid(x->buff, &x->index, pid);
+}
+
+int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun)
+{
+ int i = x->index;
+ ei_encode_fun(NULL, &i, fun);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_fun(x->buff, &x->index, fun);
+}
+
+int ei_x_encode_ref(ei_x_buff* x, const erlang_ref* ref)
+{
+ int i = x->index;
+ ei_encode_ref(NULL, &i, ref);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_ref(x->buff, &x->index, ref);
+}
+
+int ei_x_encode_port(ei_x_buff* x, const erlang_port* port)
+{
+ int i = x->index;
+ ei_encode_port(NULL, &i, port);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_port(x->buff, &x->index, port);
+}
+
+int ei_x_encode_trace(ei_x_buff* x, const erlang_trace* trace)
+{
+ int i = x->index;
+ ei_encode_trace(NULL, &i, trace);
+ if (!x_fix_buff(x, i))
+ return -1;
+ return ei_encode_trace(x->buff, &x->index, trace);
+}
diff --git a/lib/erl_interface/src/misc/ei_x_encode.h b/lib/erl_interface/src/misc/ei_x_encode.h
new file mode 100644
index 0000000000..3eab23ce0a
--- /dev/null
+++ b/lib/erl_interface/src/misc/ei_x_encode.h
@@ -0,0 +1,31 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2001-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+/*
+ * Function:
+ * ei_x_encode to encode in a self-expanding buffer
+ */
+
+#ifndef _EI_X_ENCODE_H
+#define _EI_X_ENCODE_H
+
+int x_fix_buff(ei_x_buff* x, int szneeded);
+
+#endif /* _EI_X_ENCODE_H */
diff --git a/lib/erl_interface/src/misc/eidef.h b/lib/erl_interface/src/misc/eidef.h
new file mode 100644
index 0000000000..bd3d0bf631
--- /dev/null
+++ b/lib/erl_interface/src/misc/eidef.h
@@ -0,0 +1,51 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+
+#ifndef _EIDEF_H
+#define _EIDEF_H
+
+/* Common definitions used in ei user interface */
+
+#include "config.h" /* Central include of config.h */
+
+/* vxWorks.h needs to be before stddef.h */
+#ifdef VXWORKS
+#include <vxWorks.h>
+#endif
+
+#include <stddef.h> /* We want to get definition of NULL */
+
+#include "ei.h" /* Want the API function declarations */
+
+#define EISMALLBUF 2048
+
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+typedef unsigned char uint8; /* FIXME use configure */
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed int int32;
+
+#endif /* _EIDEF_H */
diff --git a/lib/erl_interface/src/misc/eiext.h b/lib/erl_interface/src/misc/eiext.h
new file mode 100644
index 0000000000..85ed9e0d50
--- /dev/null
+++ b/lib/erl_interface/src/misc/eiext.h
@@ -0,0 +1,35 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifndef _EIEXT_H
+#define _EIEXT_H
+
+/* FIXME maybe put into eidef.h */
+
+#define ERL_VERSION_MAGIC 131 /* 130 in erlang 4.2 */
+
+/* from erl_eterm.h */
+#define ERL_MAX ((1 << 27)-1)
+#define ERL_MIN -(1 << 27)
+
+/* FIXME we removed lots of defines, maybe some C files don't need to include
+ this header any longer? */
+
+#endif /* _EIEXT_H */
diff --git a/lib/erl_interface/src/misc/eimd5.c b/lib/erl_interface/src/misc/eimd5.c
new file mode 100644
index 0000000000..426b96d962
--- /dev/null
+++ b/lib/erl_interface/src/misc/eimd5.c
@@ -0,0 +1,319 @@
+/*
+ * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#include "eidef.h"
+
+#include <string.h>
+#include "eimd5.h"
+
+/*
+ * Constants for MD5Transform routine.
+ */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform(UINT4 [4], unsigned char [64]);
+static void Encode(unsigned char *, UINT4 *, unsigned int);
+static void Decode(UINT4 *, unsigned char *, unsigned int);
+
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/*
+ * ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/*
+ * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+}
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+}
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+}
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+}
+
+
+/*
+ * MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void ei_MD5Init(MD5_CTX* context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /*
+ * Load magic initialization constants.
+ */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/*
+ * MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+void ei_MD5Update (MD5_CTX *context, unsigned char *input,
+ unsigned int inputLen)
+{
+ unsigned int i, index, partLen;
+
+ /*
+ * Compute number of bytes mod 64
+ */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((UINT4)inputLen << 3))
+ < ((UINT4)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4)inputLen >> 29);
+
+ partLen = 64 - index;
+
+ /*
+ * Transform as many times as possible.
+ */
+ if (inputLen >= partLen) {
+ memcpy
+ ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform (context->state, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /*
+ * Buffer remaining input
+ */
+ memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
+}
+
+/*
+ * MD5 finalization. Ends an MD5 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+void ei_MD5Final (unsigned char digest[16], MD5_CTX *context)
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /*
+ * Save number of bits
+ */
+ Encode (bits, context->count, 8);
+
+ /*
+ * Pad out to 56 mod 64.
+ */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ ei_MD5Update (context, PADDING, padLen);
+
+ /*
+ * Append length (before padding)
+ */
+ ei_MD5Update (context, bits, 8);
+
+ /*
+ * Store state in digest
+ */
+ Encode (digest, context->state, 16);
+
+ /*
+ * Zeroize sensitive information.
+ */
+ memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/*
+ * MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (UINT4 state[4], unsigned char block[64])
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /*
+ * Zeroize sensitive information.
+ */
+ memset ((POINTER)x, 0, sizeof (x));
+}
+
+/*
+ * Encodes input (UINT4) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/*
+ * Decodes input (unsigned char) into output (UINT4). Assumes len is
+ * a multiple of 4.
+ */
+static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
diff --git a/lib/erl_interface/src/misc/eimd5.h b/lib/erl_interface/src/misc/eimd5.h
new file mode 100644
index 0000000000..746f06e236
--- /dev/null
+++ b/lib/erl_interface/src/misc/eimd5.h
@@ -0,0 +1,48 @@
+/*
+ * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#ifndef _EIMD5_H
+#define _EIMD5_H
+
+typedef unsigned UINT4; /* Should be 32 bits. */
+typedef void *POINTER;
+
+
+/*
+ * MD5 context.
+ */
+
+typedef struct {
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} MD5_CTX;
+
+void ei_MD5Init(MD5_CTX *);
+void ei_MD5Update(MD5_CTX *, unsigned char *, unsigned int);
+void ei_MD5Final(unsigned char [16], MD5_CTX *);
+
+#endif /* _EIMD5_H */
diff --git a/lib/erl_interface/src/misc/get_type.c b/lib/erl_interface/src/misc/get_type.c
new file mode 100644
index 0000000000..d67a6a80d3
--- /dev/null
+++ b/lib/erl_interface/src/misc/get_type.c
@@ -0,0 +1,149 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+/* report type identifier from the start of the buffer */
+/* 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);
+}
+
+#if 0
+int ei_get_type(const char *buf, const int *index, int *type, int *len)
+{
+ const char *s = buf + *index;
+ int itype = get8(s); /* Internal type */
+
+ *len = 0;
+
+ switch (*type) {
+
+ case ERL_SMALL_INTEGER_EXT:
+ case ERL_INTEGER_EXT:
+ case ERL_SMALL_BIG_EXT:
+ case ERL_LARGE_BIG_EXT:
+ *type = EI_TYPE_INTEGER;
+ break;
+
+ case ERL_FLOAT_EXT:
+ *type = EI_TYPE_FLOAT;
+ break;
+
+ case ERL_SMALL_TUPLE_EXT:
+ *len = get8(s);
+ break;
+
+ case ERL_ATOM_EXT:
+ case ERL_STRING_EXT:
+ *len = get16be(s);
+ break;
+
+ case ERL_LARGE_TUPLE_EXT:
+ case ERL_LIST_EXT:
+ case ERL_BINARY_EXT:
+ *len = get32be(s);
+ break;
+
+ case ERL_SMALL_BIG_EXT:
+ *len = (get8(s)+1)/2; /* big arity */
+ break;
+
+ case ERL_LARGE_BIG_EXT:
+ *len = (get32be(s)+1)/2; /* big arity */
+ break;
+
+ case ERL_BINARY_EXT:
+ *type = EI_TYPE_BINARY;
+ break;
+
+ case ERL_PID_EXT:
+ *type = EI_TYPE_PID;
+ break;
+
+ case ERL_PORT_EXT:
+ *type = EI_TYPE_PORT;
+ break;
+
+ case ERL_REFERENCE_EXT:
+ case ERL_NEW_REFERENCE_EXT:
+ *type = EI_TYPE_REF;
+ break;
+
+ default:
+ break;
+ }
+
+ /* leave index unchanged */
+ return 0;
+}
+#endif
+
+
+/* Old definition of function above */
+
+int ei_get_type_internal(const char *buf, const int *index,
+ int *type, int *len)
+{
+ const char *s = buf + *index;
+
+ *type = get8(s);
+
+ switch (*type) {
+ case ERL_SMALL_TUPLE_EXT:
+ *len = get8(s);
+ break;
+
+ case ERL_ATOM_EXT:
+ case ERL_STRING_EXT:
+ *len = get16be(s);
+ break;
+
+ case ERL_LARGE_TUPLE_EXT:
+ case ERL_LIST_EXT:
+ case ERL_BINARY_EXT:
+ *len = get32be(s);
+ break;
+
+ case ERL_SMALL_BIG_EXT:
+ *len = get8(s); /* #digit_bytes */
+ break;
+
+ case ERL_LARGE_BIG_EXT:
+ *len = get32be(s); /* #digit_bytes */
+ break;
+
+ default:
+ *len = 0;
+ break;
+ }
+
+ /* leave index unchanged */
+ return 0;
+}
+
+
diff --git a/lib/erl_interface/src/misc/putget.h b/lib/erl_interface/src/misc/putget.h
new file mode 100644
index 0000000000..98d9ebb64c
--- /dev/null
+++ b/lib/erl_interface/src/misc/putget.h
@@ -0,0 +1,85 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifndef _PUTGET_H
+#define _PUTGET_H
+
+#define put8(s,n) do { \
+ (s)[0] = (char)((n) & 0xff); \
+ (s) += 1; \
+} while (0)
+
+#define put16le(s,n) do { \
+ (s)[0] = (n) & 0xff; \
+ (s)[1] = ((n) >> 8) & 0xff; \
+ (s) += 2; \
+} while (0) \
+
+#define put32le(s,n) do { \
+ (s)[0] = (n) & 0xff; \
+ (s)[1] = ((n) >> 8) & 0xff; \
+ (s)[2] = ((n) >> 16) & 0xff; \
+ (s)[3] = ((n) >> 24) & 0xff; \
+ (s) += 4; \
+} while (0)
+
+#define put16be(s,n) do { \
+ (s)[0] = ((n) >> 8) & 0xff; \
+ (s)[1] = (n) & 0xff; \
+ (s) += 2; \
+} while (0)
+
+#define put32be(s,n) do { \
+ (s)[0] = ((n) >> 24) & 0xff; \
+ (s)[1] = ((n) >> 16) & 0xff; \
+ (s)[2] = ((n) >> 8) & 0xff; \
+ (s)[3] = (n) & 0xff; \
+ (s) += 4; \
+} while (0)
+
+#define get8(s) \
+ ((s) += 1, \
+ ((unsigned char *)(s))[-1] & 0xff)
+
+#define get16le(s) \
+ ((s) += 2, \
+ (((((unsigned char *)(s))[-1] << 8) | \
+ ((unsigned char *)(s))[-2])) & 0xffff)
+
+#define get32le(s) \
+ ((s) += 4, \
+ ((((unsigned char *)(s))[-1] << 24) | \
+ (((unsigned char *)(s))[-2] << 16) | \
+ (((unsigned char *)(s))[-3] << 8) | \
+ ((unsigned char *)(s))[-4]))
+
+#define get16be(s) \
+ ((s) += 2, \
+ (((((unsigned char *)(s))[-2] << 8) | \
+ ((unsigned char *)(s))[-1])) & 0xffff)
+
+#define get32be(s) \
+ ((s) += 4, \
+ ((((unsigned char *)(s))[-4] << 24) | \
+ (((unsigned char *)(s))[-3] << 16) | \
+ (((unsigned char *)(s))[-2] << 8) | \
+ ((unsigned char *)(s))[-1]))
+
+#endif /* _PUTGET_H */
diff --git a/lib/erl_interface/src/misc/show_msg.c b/lib/erl_interface/src/misc/show_msg.c
new file mode 100644
index 0000000000..25865d6f8e
--- /dev/null
+++ b/lib/erl_interface/src/misc/show_msg.c
@@ -0,0 +1,584 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include "eidef.h"
+
+#ifndef __WIN32__
+# ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+# else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+# endif
+#endif
+
+#include "eiext.h"
+#include "putget.h"
+#include "ei_printterm.h"
+#include "ei_internal.h"
+#include "show_msg.h"
+
+#ifndef EISHOWBUF
+#define EISHOWBUF 512
+#endif
+
+static void show_term(const char *termbuf, int *index, FILE *stream);
+static void show_pid(FILE *stream, const erlang_pid *pid);
+static void show_trace(FILE *stream, const erlang_trace *t);
+static void show_msg(FILE *stream, int direction, const erlang_msg *msg,
+ const char *buf);
+static void ei_efprint(FILE *stream, const char *termbuf);
+static int ei_decode_skip_bignum(const char *buf, int *index, void *p);
+static int printable_list_p(const uint8 *buf, int buflen);
+
+
+/***************************************************************************
+ *
+ * Write trace information to stderr
+ *
+ ***************************************************************************/
+
+void ei_trace_printf(const char *name, int level, const char *format,...)
+{
+ time_t now;
+ char *timestr;
+ char buf[2048];
+ int len;
+ va_list args;
+
+ va_start(args, format);
+
+ time(&now);
+ timestr = (char *)ctime(&now);
+ sprintf(buf, "%s: %.*s: ", name, (int) strlen(timestr)-1, timestr);
+ len = strlen(buf);
+ vsprintf(buf + len, format, args);
+ fprintf(stderr,"%s\r\n",buf);
+ va_end(args);
+}
+
+
+/***************************************************************************
+ *
+ * Debug printing of incoming and outgoing messages
+ *
+ ***************************************************************************/
+
+/*
+ * FIXME maybe this function should be rewritten to use ei_printterm instead
+ * (or the other way around)
+ */
+
+/*
+ * the new TT stuff has been added, but when these messages are shown
+ * they will look just like the non-tt ones for now.
+ */
+
+/*
+ * this should be long enough for longest atoms (256) but short enough for
+ * fprintf to handle all at once (a few kb probably).
+ */
+
+
+void ei_show_recmsg(FILE *stream, erlang_msg *msg, char *buf)
+{
+ show_msg(stream, 0, msg, buf);
+}
+
+
+/* decode the buffer again before showing it */
+int ei_show_sendmsg(FILE *stream, const char *header, const char *msgbuf)
+{
+ erlang_msg msg;
+ const char *mbuf = NULL;
+ int index = 0;
+ int arity = 0;
+ int version = 0;
+
+ /* skip five bytes */
+ index = 5;
+ ei_decode_version(header,&index,&version);
+ ei_decode_tuple_header(header,&index,&arity);
+ ei_decode_long(header,&index,&msg.msgtype);
+
+ switch (msg.msgtype) {
+ case ERL_SEND:
+ if (ei_decode_atom(header,&index,msg.cookie)
+ || ei_decode_pid(header,&index,&msg.to)) return -1;
+ mbuf = msgbuf;
+ break;
+
+ case ERL_SEND_TT:
+ if (ei_decode_atom(header,&index,msg.cookie)
+ || ei_decode_pid(header,&index,&msg.to)
+ || ei_decode_trace(header,&index,&msg.token)) return -1;
+ mbuf = msgbuf;
+ break;
+
+ case ERL_REG_SEND:
+ if (ei_decode_pid(header,&index,&msg.from)
+ || ei_decode_atom(header,&index,msg.cookie)
+ || ei_decode_atom(header,&index,msg.toname)) return -1;
+ mbuf = msgbuf;
+ break;
+
+ case ERL_REG_SEND_TT:
+ if (ei_decode_pid(header,&index,&msg.from)
+ || ei_decode_atom(header,&index,msg.cookie)
+ || ei_decode_atom(header,&index,msg.toname)
+ || ei_decode_trace(header,&index,&msg.token)) return -1;
+ mbuf = msgbuf;
+ break;
+
+ case ERL_EXIT:
+ case ERL_EXIT2:
+ if (ei_decode_pid(header,&index,&msg.from)
+ || ei_decode_pid(header,&index,&msg.to)) return -1;
+ mbuf = header+index;
+
+ case ERL_EXIT_TT:
+ case ERL_EXIT2_TT:
+ if (ei_decode_pid(header,&index,&msg.from)
+ || ei_decode_pid(header,&index,&msg.to)
+ || ei_decode_trace(header,&index,&msg.token)) return -1;
+ mbuf = header+index;
+ break;
+
+ case ERL_LINK:
+ case ERL_UNLINK:
+ case ERL_GROUP_LEADER:
+ if (ei_decode_pid(header,&index,&msg.from)
+ || ei_decode_pid(header,&index,&msg.to)) return -1;
+ mbuf = header;
+ break;
+
+ case ERL_NODE_LINK:
+ /* nothing to do */
+ mbuf = header;
+ break;
+
+ default:
+ break;
+ }
+
+ show_msg(stream, 1, &msg, mbuf);
+
+ return 0;
+}
+
+
+/***************************************************************************
+ *
+ * Common function for ei_show_recmsg() and ei_show_sendmsg()
+ *
+ ***************************************************************************/
+
+static void show_msg(FILE *stream, int direction, const erlang_msg *msg,
+ const char *buf)
+{
+ if (direction) fprintf(stream,"-> ");
+ else fprintf(stream,"<- ");
+
+ switch (msg->msgtype) {
+ case ERL_LINK:
+ fprintf(stream,"LINK From: ");
+ show_pid(stream,&msg->from);
+ fprintf(stream," To: ");
+ show_pid(stream,&msg->to);
+ break;
+
+ case ERL_SEND:
+ fprintf(stream,"SEND To: ");
+ show_pid(stream,&msg->to);
+ fprintf(stream,"\n ");
+ /* show the message */
+ ei_efprint(stream,buf);
+ break;
+
+ case ERL_EXIT:
+ fprintf(stream,"EXIT From: ");
+ show_pid(stream,&msg->from);
+ fprintf(stream," To: ");
+ show_pid(stream,&msg->to);
+ /* show the reason */
+ fprintf(stream,"\n Reason: ");
+ ei_efprint(stream,buf);
+ break;
+
+ case ERL_UNLINK:
+ fprintf(stream,"UNLINK From: ");
+ show_pid(stream,&msg->from);
+ fprintf(stream," To: ");
+ show_pid(stream,&msg->to);
+ break;
+
+ case ERL_NODE_LINK:
+ fprintf(stream,"NODE_LINK");
+ break;
+
+ case ERL_REG_SEND:
+ fprintf(stream,"REG_SEND From: ");
+ show_pid(stream,&msg->from);
+ fprintf(stream," To: %s\n ",msg->toname);
+ /* show the message */
+ ei_efprint(stream,buf);
+ break;
+
+ case ERL_GROUP_LEADER:
+ fprintf(stream,"GROUP_LEADER From: ");
+ show_pid(stream,&msg->from);
+ fprintf(stream," To: ");
+ show_pid(stream,&msg->to);
+ break;
+
+ case ERL_EXIT2:
+ fprintf(stream,"EXIT2 From: ");
+ show_pid(stream,&msg->from);
+ fprintf(stream," To: ");
+ show_pid(stream,&msg->to);
+ /* show the reason */
+ fprintf(stream,"\n Reason: ");
+ ei_efprint(stream,buf);
+ break;
+
+ /* the new TT stuff below */
+
+ case ERL_EXIT_TT:
+ fprintf(stream,"EXIT_TT From: ");
+ show_pid(stream,&msg->from);
+ fprintf(stream," To: ");
+ show_pid(stream,&msg->to);
+ fprintf(stream,"\n ");
+ show_trace(stream,&msg->token);
+ /* show the reason */
+ fprintf(stream,"\n Reason: ");
+ ei_efprint(stream,buf);
+ break;
+
+ case ERL_EXIT2_TT:
+ fprintf(stream,"EXIT2_TT From: ");
+ show_pid(stream,&msg->from);
+ fprintf(stream," To: ");
+ show_pid(stream,&msg->to);
+ fprintf(stream,"\n ");
+ show_trace(stream,&msg->token);
+ /* show the reason */
+ fprintf(stream,"\n Reason: ");
+ ei_efprint(stream,buf);
+ break;
+
+ case ERL_SEND_TT:
+ fprintf(stream,"SEND_TT To: ");
+ show_pid(stream,&msg->to);
+ fprintf(stream,"\n ");
+ show_trace(stream,&msg->token);
+ fprintf(stream,"\n ");
+ /* show the message */
+ ei_efprint(stream,buf);
+ break;
+
+ case ERL_REG_SEND_TT:
+ fprintf(stream,"REG_SEND_TT From: ");
+ show_pid(stream,&msg->from);
+ fprintf(stream," To: %s\n ",msg->toname);
+ show_trace(stream,&msg->token);
+ fprintf(stream,"\n ");
+ /* show the message */
+ ei_efprint(stream,buf);
+ break;
+
+ default:
+ fprintf(stream,"Unknown message type: %ld",msg->msgtype);
+ }
+ fprintf(stream,"\n");
+}
+
+/***************************************************************************
+ *
+ * Print term to stream with fprintf
+ *
+ ***************************************************************************/
+
+
+static void ei_efprint(FILE *stream, const char *termbuf)
+{
+ int index = 0;
+ show_term(termbuf,&index,stream);
+}
+
+static void show_term(const char *termbuf, int *index, FILE *stream)
+{
+ int type;
+ char smallbuf[EISHOWBUF];
+ int version;
+ long num;
+ double fnum;
+ erlang_pid pid;
+ erlang_port port;
+ erlang_ref ref;
+ int i, len;
+ char *s;
+
+ ei_get_type_internal(termbuf,index,&type,&len);
+
+ switch (type) {
+ case ERL_VERSION_MAGIC:
+ /* just skip past this */
+ ei_decode_version(termbuf,index,&version);
+ show_term(termbuf,index,stream);
+ break;
+
+ case ERL_ATOM_EXT:
+ ei_decode_atom(termbuf,index,smallbuf);
+ fprintf(stream,"%s",smallbuf);
+ break;
+
+ case ERL_STRING_EXT:
+ /* strings can be much longer than EISHOWBUF */
+ if (len < EISHOWBUF) s = smallbuf;
+ else if (!(s = malloc(len+1))) break; /* FIXME just break if can't? */
+
+ ei_decode_string(termbuf,index,s);
+
+ if (printable_list_p((uint8 *)s,len)) {
+ /* just show it as it is */
+ fprintf(stream,"\"%s\"",s);
+ } else {
+ /* show it as a list instead */
+ fprintf(stream,"[");
+ for (i=0; i<len; i++) {
+ if (i > 0) fprintf(stream,", ");
+ fprintf(stream,"%d",s[i]);
+ }
+ fprintf(stream,"]");
+ }
+
+ /* did we allocate anything? */
+ if (s && (s != smallbuf)) free(s);
+
+ break;
+
+ /* FIXME add case using ei_decode_longlong */
+ case ERL_SMALL_BIG_EXT:
+ case ERL_SMALL_INTEGER_EXT:
+ case ERL_INTEGER_EXT:
+ if (ei_decode_long(termbuf,index,&num) == 0) {
+ fprintf(stream,"%ld",num);
+ } else {
+ ei_decode_skip_bignum(termbuf,index,NULL);
+ fprintf(stream,"#Bignum");
+ }
+ break;
+
+ case ERL_FLOAT_EXT:
+ ei_decode_double(termbuf,index,&fnum);
+ fprintf(stream,"%f",fnum);
+ break;
+
+ case ERL_PID_EXT:
+ ei_decode_pid(termbuf,index,&pid);
+ show_pid(stream,&pid);
+ break;
+
+ case ERL_SMALL_TUPLE_EXT:
+ case ERL_LARGE_TUPLE_EXT:
+ ei_decode_tuple_header(termbuf,index,&len);
+ fprintf(stream,"{");
+ for (i=0; i<len; i++) {
+ if (i > 0) fprintf(stream,", ");
+ show_term(termbuf,index,stream);
+ }
+ fprintf(stream,"}");
+ break;
+
+ case ERL_LIST_EXT:
+ ei_decode_list_header(termbuf,index,&len);
+ fprintf(stream,"[");
+ for (i=0; i<len; i++) {
+ if (i > 0) fprintf(stream,", ");
+ show_term(termbuf,index,stream);
+ }
+ /* get the empty list at the end */
+ ei_decode_list_header(termbuf,index,&len);
+ fprintf(stream,"]");
+ break;
+
+ case ERL_NIL_EXT:
+ ei_decode_list_header(termbuf,index,&len);
+ fprintf(stream,"[]");
+ break;
+
+ case ERL_REFERENCE_EXT:
+ case ERL_NEW_REFERENCE_EXT:
+ ei_decode_ref(termbuf,index,&ref);
+ fprintf(stream,"#Ref<%s",ref.node);
+ for (i = 0; i < ref.len; i++) {
+ fprintf(stream,".%u",ref.n[i]);
+ }
+ fprintf(stream,".%u>",ref.creation);
+ break;
+
+ case ERL_PORT_EXT:
+ ei_decode_port(termbuf,index,&port);
+ fprintf(stream,"#Port<%s.%u.%u>",port.node,port.id,port.creation);
+ break;
+
+ case ERL_BINARY_EXT:
+ ei_decode_binary(termbuf,index,NULL,&num);
+ fprintf(stream,"#Bin<%ld>",num);
+ break;
+
+ case ERL_LARGE_BIG_EXT:
+ /* doesn't actually decode - just skip over it */
+ /* FIXME if GMP, what to do here?? */
+ ei_decode_skip_bignum(termbuf,index,NULL);
+ fprintf(stream,"#Bignum");
+ break;
+
+ case ERL_FUN_EXT: {
+ char atom[MAXATOMLEN+1];
+ long idx;
+ long uniq;
+ const char* s = termbuf + *index, * s0 = s;
+ int n_free;
+
+ ++s;
+ n_free = get32be(s);
+ *index += s - s0;
+ ei_decode_pid(termbuf, index, NULL); /* skip pid */
+ ei_decode_atom(termbuf, index, atom); /* get module, index, uniq */
+ ei_decode_long(termbuf, index, &idx);
+ ei_decode_long(termbuf, index, &uniq);
+ fprintf(stream,"#Fun<%s.%ld.%ld>", atom, idx, uniq);
+ for (i = 0; i < n_free; ++i) {
+ /* FIXME how to report error ?! */
+ if (ei_skip_term(termbuf, index) != 0)
+ fprintf(stderr,"<ERROR> show_msg: unknown type of term !");
+ }
+ break;
+ }
+ default:
+ fprintf(stream,"#Unknown<%d.%d>",type,len);
+ /* unfortunately we don't know how to skip over this type in
+ * the buffer if we don't even know what it is, so we return.
+ */
+ return;
+ break;
+ }
+}
+
+/***************************************************************************
+ *
+ * this help function does the actual decoding of the
+ * terms and is used by both ei_efprint and ei_sprintt.
+ *
+ * termbuf contains the undecoded term.
+ * idx is the current position in termbuf.
+ * stream is print destination, e.g. a FILE*
+ *
+ ***************************************************************************/
+
+static void show_pid(FILE *stream, const erlang_pid *pid)
+{
+ fprintf(stream,"#Pid<%s.%u.%u.%u>",
+ pid->node,pid->num,pid->serial,pid->creation);
+}
+
+static void show_trace(FILE *stream, const erlang_trace *t)
+{
+ fprintf(stream,
+ "Trace: Label: %ld, Flags: 0x%lx serial: %ld, prev: %ld From: ",
+ t->label,t->flags,t->serial,t->prev);
+ show_pid(stream,&t->from);
+}
+
+/***************************************************************************
+ *
+ * Try do decide if a buffer only contains printable characters
+ *
+ ***************************************************************************/
+
+/* we only need to initialize some of these (after 32 everything printable) */
+/* FIXME they are not!!!! We use isprint() for now but we could create a */
+/* custom print function that escape some non printable like \t and \n */
+#if 0
+static int non_printable[256] = {
+ /* 1 2 3 */
+ /* 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 */
+ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+ /* \b\t\n\v\f\r */
+};
+#endif
+
+static int printable_list_p(const uint8 *buf, int buflen)
+{
+ int i;
+
+ for (i=0; i<buflen; i++) if (!isprint(buf[i])) return 0;
+
+ /* is printable */
+ return 1;
+}
+
+/***************************************************************************
+ *
+ * Skip over bignums, we can't print them
+ *
+ ***************************************************************************/
+
+/* FIXME we can if bignum small enough or if we use Per's functions or
+ if we have compiled in gmp support */
+
+/* this function doesn't do anything but skip over the number in the buffer */
+/* it doesn't really belong here either... */
+
+static int ei_decode_skip_bignum(const char *buf, int *index, void *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ long n;
+
+ switch (get8(s)) {
+ case ERL_LARGE_BIG_EXT:
+ n = get32be(s);
+ s += n+1;
+ break;
+
+ default:
+ erl_errno = EIO;
+ return -1;
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/misc/show_msg.h b/lib/erl_interface/src/misc/show_msg.h
new file mode 100644
index 0000000000..fac51f3278
--- /dev/null
+++ b/lib/erl_interface/src/misc/show_msg.h
@@ -0,0 +1,27 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2002-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ *
+
+ */
+#ifndef _SHOW_MSG_H
+#define _SHOW_MSG_H
+
+void ei_show_recmsg(FILE *dest, erlang_msg *msg, char *buf);
+int ei_show_sendmsg(FILE *dest, const char *header, const char *msgbuf);
+
+#endif /* _SHOW_MSG_H */