aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface/src/decode
diff options
context:
space:
mode:
Diffstat (limited to 'lib/erl_interface/src/decode')
-rw-r--r--lib/erl_interface/src/decode/decode_atom.c42
-rw-r--r--lib/erl_interface/src/decode/decode_big.c331
-rw-r--r--lib/erl_interface/src/decode/decode_bignum.c75
-rw-r--r--lib/erl_interface/src/decode/decode_binary.c42
-rw-r--r--lib/erl_interface/src/decode/decode_boolean.c57
-rw-r--r--lib/erl_interface/src/decode/decode_char.c69
-rw-r--r--lib/erl_interface/src/decode/decode_double.c39
-rw-r--r--lib/erl_interface/src/decode/decode_fun.c123
-rw-r--r--lib/erl_interface/src/decode/decode_intlist.c82
-rw-r--r--lib/erl_interface/src/decode/decode_list_header.c45
-rw-r--r--lib/erl_interface/src/decode/decode_long.c86
-rw-r--r--lib/erl_interface/src/decode/decode_longlong.c100
-rw-r--r--lib/erl_interface/src/decode/decode_pid.c54
-rw-r--r--lib/erl_interface/src/decode/decode_port.c53
-rw-r--r--lib/erl_interface/src/decode/decode_ref.c94
-rw-r--r--lib/erl_interface/src/decode/decode_skip.c90
-rw-r--r--lib/erl_interface/src/decode/decode_skip.h27
-rw-r--r--lib/erl_interface/src/decode/decode_string.c85
-rw-r--r--lib/erl_interface/src/decode/decode_trace.c43
-rw-r--r--lib/erl_interface/src/decode/decode_tuple_header.c47
-rw-r--r--lib/erl_interface/src/decode/decode_ulong.c78
-rw-r--r--lib/erl_interface/src/decode/decode_ulonglong.c83
-rw-r--r--lib/erl_interface/src/decode/decode_version.c38
23 files changed, 1783 insertions, 0 deletions
diff --git a/lib/erl_interface/src/decode/decode_atom.c b/lib/erl_interface/src/decode/decode_atom.c
new file mode 100644
index 0000000000..b247bd4e17
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_atom.c
@@ -0,0 +1,42 @@
+/*
+ * %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 <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_decode_atom(const char *buf, int *index, char *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int len;
+
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+
+ len = get16be(s);
+
+ if (p) {
+ memmove(p,s,len);
+ p[len] = (char)0;
+ }
+ s += len;
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_big.c b/lib/erl_interface/src/decode/decode_big.c
new file mode 100644
index 0000000000..efe9c6e5d9
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_big.c
@@ -0,0 +1,331 @@
+/*
+ * %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%
+ */
+#include <string.h>
+#include <stdlib.h>
+
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_decode_big(const char *buf, int *index, erlang_big *b) {
+ unsigned int digit_bytes;
+ const unsigned char *s = (unsigned char*) buf + *index;
+ const unsigned char *s0 = s;
+
+ switch ( get8(s) ) {
+ case ERL_SMALL_BIG_EXT:
+ digit_bytes = get8(s);
+ break;
+ case ERL_LARGE_BIG_EXT:
+ digit_bytes = get32be(s);
+ break;
+ default:
+ return -1;
+ }
+ if ( b ) {
+ unsigned short *dt = b->digits;
+ unsigned int n = (digit_bytes+1)/2;
+ int i;
+
+ if ( digit_bytes != b->arity ) {
+ return -1;
+ }
+
+ b->is_neg = get8(s);
+
+ for (i = 0; i < n; ++i) {
+ dt[i] = s[i*2];
+ if ((i*2 + 1) < digit_bytes) {
+ dt[i] |= ((unsigned short) s[(i*2)+1]) << 8;
+ }
+ }
+ } else {
+ s++; /* skip sign byte */
+ }
+
+ s += digit_bytes;
+
+ *index += s-s0;
+
+ return 0;
+}
+
+erlang_big *ei_alloc_big(unsigned int digit_bytes) {
+ erlang_big *b;
+ unsigned int n = (digit_bytes+1)/2;
+
+ if ( (b = malloc(sizeof(erlang_big))) == NULL) return NULL;
+ memset(b,(char)0,sizeof(erlang_big));
+ if ( (b->digits = malloc(2*n)) == NULL) {
+ free(b);
+ return 0;
+ }
+
+ b->arity = digit_bytes;
+ memset(b->digits,(char)0, 2*n);
+ return b;
+}
+
+void ei_free_big(erlang_big *b)
+{
+ if (!b) return;
+ if (b->digits) free(b->digits);
+ free(b);
+}
+
+/* big compare functions */
+
+typedef unsigned short Uint16;
+typedef unsigned int Uint;
+
+typedef Uint16 digit_t;
+typedef Uint dsize_t;
+
+static int I_comp(digit_t *x, dsize_t xl, digit_t *y, dsize_t yl)
+{
+ if (xl<yl) {
+ return -1;
+ } else if (xl>yl) {
+ return 1;
+ } else {
+ if ( x == y ) return 0;
+ x += (xl-1);
+ y += (yl-1);
+ while( (xl>0) && (*x==*y) ) {
+ x--;
+ y--;
+ xl--;
+ }
+ if ( xl == 0 ) return 0;
+ return ( *x < *y ) ? -1 : 1;
+ }
+}
+
+int ei_big_comp(erlang_big *x, erlang_big *y)
+{
+ if ( x->is_neg == y->is_neg ) {
+ int c = I_comp(x->digits,(x->arity+1)/2,y->digits,(y->arity+1)/2);
+ if ( x->is_neg )
+ return -c;
+ else
+ return c;
+ } else {
+ return x->is_neg ? -1 : 1;
+ }
+}
+
+#define D_EXP 16
+#define D_BASE (1<<D_EXP)
+
+#define D_DECIMAL_EXP 4 /* 10^4 == 10000 */
+#define D_DECIMAL_BASE 10000 /* Max decimal exponent in a digit */
+
+#define DLOW(x) ((digit_t)((x) & (D_BASE-1)))
+#define DHIGH(x) ((digit_t)((x) >> D_EXP))
+
+/*
+ * Handling of floating point exceptions.
+ */
+
+#if defined(VXWORKS) && CPU == PPC860
+#undef NO_FPE_SIGNALS
+#define NO_FPE_SIGNALS 1
+#undef INLINED_FP_CONVERSION
+#define INLINED_FP_CONVERSION 1
+#endif
+
+#ifdef USE_ISINF_ISNAN /* simulate finite() */
+# define finite(f) (!isinf(f) && !isnan(f))
+# define HAVE_FINITE
+#endif
+
+#ifdef NO_FPE_SIGNALS
+# define ERTS_FP_CHECK_INIT() do {} while (0)
+# define ERTS_FP_ERROR(f, Action) if (!finite(f)) { Action; } else {}
+# define ERTS_SAVE_FP_EXCEPTION()
+# define ERTS_RESTORE_FP_EXCEPTION()
+#else
+/* extern volatile int erl_fp_exception; */
+static volatile int erl_fp_exception;
+# define ERTS_FP_CHECK_INIT() do {erl_fp_exception = 0;} while (0)
+# if defined(__i386__) && defined(__GNUC__)
+/* extern void erts_restore_x87(void); */
+
+static void unmask_fpe(void)
+{
+ unsigned short cw;
+ __asm__ __volatile__("fstcw %0" : "=m"(cw));
+ cw &= ~(0x01|0x04|0x08); /* unmask IM, ZM, OM */
+ __asm__ __volatile__("fldcw %0" : : "m"(cw));
+}
+
+static void erts_restore_x87(void)
+{
+ __asm__ __volatile__("fninit");
+ unmask_fpe();
+}
+
+static int erts_check_x87(double f)
+{
+ __asm__ __volatile__("fwait" : "=m"(erl_fp_exception) : "m"(f));
+ if( !erl_fp_exception )
+ return 0;
+ erts_restore_x87();
+ return 1;
+}
+# define ERTS_FP_ERROR(f, Action) do { if( erts_check_x87((f)) ) { Action; } } while (0)
+# else
+# define ERTS_FP_ERROR(f, Action) if (erl_fp_exception) { Action; } else {}
+# endif
+# define ERTS_SAVE_FP_EXCEPTION() int old_erl_fp_exception = erl_fp_exception
+# define ERTS_RESTORE_FP_EXCEPTION() \
+ do {erl_fp_exception = old_erl_fp_exception;} while (0)
+#endif
+
+
+#ifdef INLINED_FP_CONVERSION
+static void join(unsigned d_split[4], unsigned *d)
+{
+ d[0] = (d_split[0] << 31) | /* Sign bit */
+ ((d_split[1] & 0x7FFU) << 20) | /* Exponent */
+ (d_split[2] & 0xFFFFFU); /* Mantissa MS bits */
+ d[1] = d_split[3]; /* Mantissa LS bits */
+}
+
+static int blength(unsigned long l)
+{
+ int i;
+ for(i = 0; l; ++i)
+ l >>= 1;
+ return i;
+}
+
+static int bblength(erlang_big *b)
+{
+ unsigned int wholebytes = (b->arity+1)/2;
+ digit_t *dp = b->digits;
+
+ while(wholebytes > 0 && dp[--wholebytes] == 0U)
+ ;
+
+ return (wholebytes * sizeof(digit_t) * 8) + blength(dp[wholebytes]);
+}
+
+static unsigned long bindex(erlang_big *b, int ndx) {
+ digit_t *dp = b->digits;
+ int skipdigits;
+ int dnum;
+
+ if (ndx < 0)
+ return 0;
+
+ skipdigits = ndx / (sizeof(digit_t) * 8);
+ dnum = ndx % (sizeof(digit_t) * 8);
+ return !!(dp[skipdigits] & (1UL << dnum));
+}
+
+
+#endif
+
+
+int ei_big_to_double(erlang_big *b, double *resp)
+{
+#ifdef INLINED_FP_CONVERSION
+ unsigned d_split[4];
+ unsigned *uresp = (unsigned *) resp;
+ unsigned len = bblength(b);
+ int i;
+ unsigned long msm = 0, lsm = 0;
+
+ /* OK, this is not the most efficient conversion in the world, especially
+ not the bit-by-bit copying to the mantissa.... Simple, working and
+ only for vxworks ppc860 where no sane person would use floating
+ point anyway, eh? /Patrik */
+
+ if (!len) {
+ memset(d_split,0,sizeof(d_split)); /* 0 */
+ } else {
+ --len;
+ if (len > 1023) { /* Infinite */
+ d_split[1] = 2047;
+ d_split[2] = d_split[3] = 0;
+ } else {
+ d_split[1] = 1023 + len;
+ --len; /* skip the implicit binary 1. */
+ for (i = 0; i < 20; ++i, --len) {
+ msm <<= 1;
+ msm |= bindex(b,len);
+ }
+ for (i = 0; i < 32; ++i, --len) {
+ lsm <<= 1;
+ lsm |= bindex(b,len);
+ }
+ d_split[2] = msm;
+ d_split[3] = lsm;
+ }
+ }
+ d_split[0] = (unsigned) !!(b->is_neg);
+ join(d_split,uresp);
+ return 0;
+#else
+ double d = 0.0;
+ double d_base = 1.0;
+
+ digit_t* s = (digit_t *)b->digits;
+ dsize_t xl = (b->arity + 1)/2;
+ short xsgn = b->is_neg;
+ ERTS_SAVE_FP_EXCEPTION();
+
+ ERTS_FP_CHECK_INIT();
+ while(xl--) {
+ digit_t ds = *s;
+ double d_next = ds * d_base + d;
+
+ ERTS_FP_ERROR(d_next, ERTS_RESTORE_FP_EXCEPTION(); {fprintf(stderr,"\r\n### fp exception ###\r\n"); return -1;});
+ s++;
+ d = d_next;
+ d_base *= D_BASE;
+ }
+
+ /*
+ * Note: The last multiplication in the loop could trigger an exception,
+ * which we will ignore because the result will never be used.
+ */
+
+ *resp = xsgn ? -d : d;
+ ERTS_FP_ERROR(*resp,;);
+ ERTS_RESTORE_FP_EXCEPTION();
+ return 0;
+#endif
+}
+
+int ei_small_to_big(int s, erlang_big *b)
+{
+ digit_t *d;
+ unsigned int n = (b->arity+1)/2;
+
+ if ( n < 2 ) return -1;
+
+ b->is_neg = ( s < 0 );
+ d = (digit_t *)b->digits;
+ d[0] = DLOW(s);
+ d[1] = DHIGH(s);
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_bignum.c b/lib/erl_interface/src/decode/decode_bignum.c
new file mode 100644
index 0000000000..f10052f9fe
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_bignum.c
@@ -0,0 +1,75 @@
+/*
+ * %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%
+ */
+
+#include "eidef.h"
+
+#if defined(HAVE_GMP_H) && defined(HAVE_LIBGMP)
+
+#include <gmp.h>
+
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+
+int ei_decode_bignum(const char *buf, int *index, mpz_t obj)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int arity;
+ int sign;
+ unsigned long n;
+
+ switch (get8(s)) {
+ case ERL_SMALL_INTEGER_EXT:
+ n = get8(s);
+ mpz_set_ui(obj, n);
+ break;
+
+ case ERL_INTEGER_EXT:
+ n = get32be(s);
+ mpz_set_ui(obj, n);
+ break;
+
+ case ERL_SMALL_BIG_EXT:
+ arity = get8(s);
+ goto decode_bytes;
+
+ case ERL_LARGE_BIG_EXT:
+ arity = get32be(s);
+ decode_bytes:
+ sign = get8(s);
+ mpz_import(obj, arity, -1, 1, 0, 0, s);
+ s += arity;
+ if (sign) {
+ mpz_neg(obj, obj);
+ }
+
+ break;
+
+ default:
+ return -1;
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
+
+#endif /* HAVE_GMP_H && HAVE_LIBGMP */
diff --git a/lib/erl_interface/src/decode/decode_binary.c b/lib/erl_interface/src/decode/decode_binary.c
new file mode 100644
index 0000000000..713e621e60
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_binary.c
@@ -0,0 +1,42 @@
+/*
+ * %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 <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_decode_binary(const char *buf, int *index, void *p, long *lenp)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ long len;
+
+ if (get8(s) != ERL_BINARY_EXT) return -1;
+
+ len = get32be(s);
+ if (p) memmove(p,s,len);
+ s += len;
+
+ if (lenp) *lenp = len;
+ *index += s-s0;
+
+ return 0;
+}
+
+
diff --git a/lib/erl_interface/src/decode/decode_boolean.c b/lib/erl_interface/src/decode/decode_boolean.c
new file mode 100644
index 0000000000..9fd09c63f1
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_boolean.c
@@ -0,0 +1,57 @@
+/*
+ * %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 <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+/* c non-zero -> erlang "true" atom, otherwise "false" */
+int ei_decode_boolean(const char *buf, int *index, int *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int len;
+ int t;
+
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+
+ len = get16be(s);
+
+ switch (len) {
+ case 4:
+ /* typecast makes ansi happy */
+ if (strncmp((char*)s,"true",4)) return -1;
+ t = 1;
+ break;
+
+ case 5:
+ if (strncmp((char*)s,"false",5)) return -1;
+ t = 0;
+ break;
+
+ default:
+ return -1;
+ }
+
+ s += len;
+ if (p) *p = t;
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_char.c b/lib/erl_interface/src/decode/decode_char.c
new file mode 100644
index 0000000000..0f9b3f6cff
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_char.c
@@ -0,0 +1,69 @@
+/*
+ * %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"
+
+int ei_decode_char(const char *buf, int *index, char *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ long n;
+ int arity;
+
+ switch (get8(s)) {
+ case ERL_SMALL_INTEGER_EXT:
+ n = get8(s);
+ break;
+
+ case ERL_INTEGER_EXT:
+ n = get32be(s);
+ if (n < 0 || n > 255)
+ return -1;
+ break;
+
+ case ERL_SMALL_BIG_EXT:
+ arity = get8(s);
+ goto decode_big;
+ case ERL_LARGE_BIG_EXT:
+ arity = get32be(s);
+ decode_big:
+ {
+ int sign = get8(s);
+ int i;
+
+ if (sign) return -1; /* Char is always > 0 */
+
+ n = get8(s); /* First byte is our value */
+
+ for (i = 1; i < arity; i++) {
+ if (*(s++) != 0) return -1; /* All but first byte have to be 0 */
+ }
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ if (p) *p = n;
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_double.c b/lib/erl_interface/src/decode/decode_double.c
new file mode 100644
index 0000000000..66dbe474ec
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_double.c
@@ -0,0 +1,39 @@
+/*
+ * %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 <stdio.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+
+int ei_decode_double(const char *buf, int *index, double *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ double f;
+
+ if (get8(s) != ERL_FLOAT_EXT) return -1;
+
+ if (sscanf(s, "%lf", &f) != 1) return -1;
+
+ s += 31;
+ if (p) *p = f;
+ *index += s-s0;
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c
new file mode 100644
index 0000000000..64fb9e86d8
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_fun.c
@@ -0,0 +1,123 @@
+/*
+ * %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 <stdlib.h>
+
+#include "eidef.h"
+#include "eiext.h"
+#include "ei_malloc.h"
+#include "decode_skip.h"
+#include "putget.h"
+
+int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int i, ix, ix0, n;
+
+ switch (get8(s)) {
+ case ERL_FUN_EXT:
+ /* mark as old (R7 and older) external fun */
+ if (p != NULL) p->arity = -1;
+ /* first number of free vars (environment) */
+ n = get32be(s);
+ /* then the pid */
+ ix = 0;
+ if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0)
+ return -1;
+ /* then the module (atom) */
+ if (ei_decode_atom(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0)
+ return -1;
+ /* then the index */
+ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->index)) < 0)
+ return -1;
+ /* then the uniq */
+ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0)
+ return -1;
+ /* finally the free vars */
+ ix0 = ix;
+ for (i = 0; i < n; ++i) {
+ if (ei_skip_term(s, &ix) < 0)
+ return -1;
+ }
+ if (p != NULL) {
+ p->n_free_vars = n;
+ p->free_var_len = ix - ix0;
+ p->free_vars = ei_malloc(ix - ix0);
+ if (!(p->free_vars)) return -1;
+ memcpy(p->free_vars, s + ix0, ix - ix0);
+ }
+ s += ix;
+ *index += s-s0;
+ return 0;
+ break;
+ case ERL_NEW_FUN_EXT:
+ /* first total size */
+ n = get32be(s);
+ /* then the arity */
+ i = get8(s);
+ if (p != NULL) p->arity = i;
+ /* then md5 */
+ if (p != NULL) memcpy(p->md5, s, 16);
+ s += 16;
+ /* then index */
+ i = get32be(s);
+ if (p != NULL) p->index = i;
+ /* then the number of free vars (environment) */
+ i = get32be(s);
+ if (p != NULL) p->n_free_vars = i;
+ /* then the module (atom) */
+ ix = 0;
+ if (ei_decode_atom(s, &ix, (p == NULL ? (char*)NULL : p->module)) < 0)
+ return -1;
+ /* then the old_index */
+ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->old_index)) < 0)
+ return -1;
+ /* then the old_uniq */
+ if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0)
+ return -1;
+ /* the the pid */
+ if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0)
+ return -1;
+ /* finally the free vars */
+ s += ix;
+ n = n - (s - s0) + 1;
+ if (n < 0) return -1;
+ if (p != NULL) {
+ p->free_var_len = n;
+ if (n > 0) {
+ p->free_vars = malloc(n);
+ if (!(p->free_vars)) return -1;
+ memcpy(p->free_vars, s, n);
+ }
+ }
+ s += n;
+ *index += s-s0;
+ return 0;
+ break;
+ default:
+ return -1;
+ }
+}
+
+void free_fun(erlang_fun* f)
+{
+ if (f->free_var_len > 0)
+ ei_free(f->free_vars);
+}
diff --git a/lib/erl_interface/src/decode/decode_intlist.c b/lib/erl_interface/src/decode/decode_intlist.c
new file mode 100644
index 0000000000..65552a4ed4
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_intlist.c
@@ -0,0 +1,82 @@
+/*
+ * %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%
+ */
+/* since Erlang sends int-lists as either lists or strings, this
+ * function can be used when the caller needs an array but doesn't
+ * know which type to decode
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_decode_intlist(const char *buf, int *index, long *a, int *count)
+{
+ const unsigned char *s = (const unsigned char *)(buf + *index);
+ const unsigned char *s0 = s;
+ int idx;
+ int len;
+ int i;
+
+ switch (get8(s)) {
+ case ERL_STRING_EXT:
+ len = get16be(s);
+
+ /* transfer and cast chars one at a time into array */
+ if (a) {
+ for (i=0; i<len; i++) {
+ a[i] = (long)(s[i]);
+ }
+ }
+ if (count) *count = len;
+ s += len;
+ break;
+
+ case ERL_LIST_EXT:
+ len = get32be(s);
+ idx = 0;
+
+ if (a) {
+ for (i=0; i<len; i++) {
+ if (ei_decode_long((char*)s,&idx,a+i) < 0) {
+ if (count) *count = i;
+ return -1;
+ }
+ }
+ }
+ else {
+ for (i=0; i<len; i++) {
+ if (ei_decode_long((char*)s,&idx,NULL) < 0) {
+ if (count) *count = i;
+ return -1;
+ }
+ }
+ }
+
+ if (count) *count = len;
+ s += idx;
+ break;
+
+ default:
+ return -1;
+ }
+
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_list_header.c b/lib/erl_interface/src/decode/decode_list_header.c
new file mode 100644
index 0000000000..dda711f9fd
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_list_header.c
@@ -0,0 +1,45 @@
+/*
+ * %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"
+
+int ei_decode_list_header(const char *buf, int *index, int *arity)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+
+ switch (get8(s)) {
+ case ERL_NIL_EXT:
+ if (arity) *arity = 0;
+ break;
+
+ case ERL_LIST_EXT:
+ if (arity) *arity = get32be(s);
+ else s+= 4;
+ break;
+
+ default:
+ return -1;
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_long.c b/lib/erl_interface/src/decode/decode_long.c
new file mode 100644
index 0000000000..b4138247e0
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_long.c
@@ -0,0 +1,86 @@
+/*
+ * %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"
+
+#ifndef EI_64BIT
+int ei_decode_long(const char *buf, int *index, long *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ long n;
+ int arity;
+
+ switch (get8(s)) {
+ case ERL_SMALL_INTEGER_EXT:
+ n = get8(s);
+ break;
+
+ case ERL_INTEGER_EXT:
+ n = get32be(s);
+ break;
+
+ case ERL_SMALL_BIG_EXT:
+ arity = get8(s);
+ goto decode_big;
+
+ case ERL_LARGE_BIG_EXT:
+ arity = get32be(s);
+
+ decode_big:
+ {
+ int sign = get8(s);
+ int i;
+ unsigned long u = 0;
+
+ /* Little Endian, and n always positive, except for LONG_MIN */
+ for (i = 0; i < arity; i++) {
+ if (i < 4) {
+ u |= get8(s) << (i * 8);
+ } else if (get8(s) != 0) {
+ return -1; /* All but first byte have to be 0 */
+ }
+ }
+
+ /* check for overflow */
+ if (sign) {
+ if (u > 0x80000000UL) {
+ return -1;
+ }
+ n = -((long)u);
+ } else {
+ if (u > 0x7FFFFFFF) {
+ return -1;
+ }
+ n = (long)u;
+ }
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ if (p) *p = n;
+ *index += s-s0;
+
+ return 0;
+}
+#endif /* !EI_64BIT */
diff --git a/lib/erl_interface/src/decode/decode_longlong.c b/lib/erl_interface/src/decode/decode_longlong.c
new file mode 100644
index 0000000000..8ec9f76995
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_longlong.c
@@ -0,0 +1,100 @@
+/*
+ * %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%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+#ifdef EI_64BIT
+int ei_decode_long(const char *buf, int *index, long *p)
+{
+ return ei_decode_longlong(buf, index, (EI_LONGLONG *)p);
+}
+#endif
+
+#ifdef _MSC_VER
+#define MAX_TO_NEGATE 0x8000000000000000Ui64
+#define MAX_TO_NOT_NEGATE 0x7FFFFFFFFFFFFFFFUi64
+#else
+#define MAX_TO_NEGATE 0x8000000000000000ULL
+#define MAX_TO_NOT_NEGATE 0x7FFFFFFFFFFFFFFFULL
+#endif
+
+int ei_decode_longlong(const char *buf, int *index, EI_LONGLONG *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ EI_LONGLONG n;
+ int arity;
+
+ switch (get8(s)) {
+ case ERL_SMALL_INTEGER_EXT:
+ n = get8(s);
+ break;
+
+ case ERL_INTEGER_EXT:
+ n = get32be(s);
+ break;
+
+ case ERL_SMALL_BIG_EXT:
+ arity = get8(s);
+ goto decode_big;
+
+ case ERL_LARGE_BIG_EXT:
+ arity = get32be(s);
+
+ decode_big:
+ {
+ int sign = get8(s);
+ int i;
+ EI_ULONGLONG u = 0;
+
+ /* Little Endian, and n always positive, except for LONG_MIN */
+ for (i = 0; i < arity; i++) {
+ if (i < 8) {
+ /* Use ULONGLONG not to get a negative integer if > 127 */
+ u |= ((EI_ULONGLONG)get8(s)) << (i * 8);
+ } else if (get8(s) != 0) {
+ return -1; /* All but first byte have to be 0 */
+ }
+ }
+
+ /* check for overflow */
+ if (sign) {
+ if (u > MAX_TO_NEGATE) {
+ return -1;
+ }
+ n = -((EI_LONGLONG) u);
+ } else {
+ if (u > MAX_TO_NOT_NEGATE) {
+ return -1;
+ }
+ n = (EI_LONGLONG) u;
+ }
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ if (p) *p = n;
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_pid.c b/lib/erl_interface/src/decode/decode_pid.c
new file mode 100644
index 0000000000..5f2aec3b44
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_pid.c
@@ -0,0 +1,54 @@
+/*
+ * %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 <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_decode_pid(const char *buf, int *index, erlang_pid *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int len;
+
+ if (get8(s) != ERL_PID_EXT) return -1;
+
+ /* first the nodename */
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+
+ len = get16be(s);
+
+ if (p) {
+ memmove(p->node, s, len);
+ p->node[len] = (char)0;
+ }
+ s += len;
+
+ /* now the numbers: num (4), serial (4), creation (1) */
+ if (p) {
+ p->num = get32be(s) & 0x7fff; /* 15 bits */
+ p->serial = get32be(s) & 0x1fff; /* 13 bits */
+ p->creation = get8(s) & 0x03; /* 2 bits */
+ }
+ else s+= 9;
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_port.c b/lib/erl_interface/src/decode/decode_port.c
new file mode 100644
index 0000000000..7fb7d8d414
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_port.c
@@ -0,0 +1,53 @@
+/*
+ * %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 <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_decode_port(const char *buf, int *index, erlang_port *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int len;
+
+ if (get8(s) != ERL_PORT_EXT) return -1;
+
+ /* first the nodename */
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+
+ len = get16be(s);
+
+ if (p) {
+ memmove(p->node, s, len);
+ p->node[len] = (char)0;
+ }
+ s += len;
+
+ /* now the numbers: num (4), creation (1) */
+ if (p) {
+ p->id = get32be(s) & 0x0fffffff /* 28 bits */;
+ p->creation = get8(s) & 0x03;
+ }
+ else s += 5;
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_ref.c b/lib/erl_interface/src/decode/decode_ref.c
new file mode 100644
index 0000000000..6fc2cd6533
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_ref.c
@@ -0,0 +1,94 @@
+/*
+ * %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 <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+int ei_decode_ref(const char *buf, int *index, erlang_ref *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int count, len, i;
+
+ switch (get8(s)) {
+ case ERL_REFERENCE_EXT:
+
+ /* first the nodename */
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+
+ len = get16be(s);
+
+ if (p) {
+ memmove(p->node, s, len);
+ p->node[len] = (char)0;
+ }
+ s += len;
+
+ /* now the numbers: num (4), creation (1) */
+ if (p) {
+ p->n[0] = get32be(s);
+ p->len = 1;
+ p->creation = get8(s) & 0x03;
+ }
+ else s += 5;
+
+ *index += s-s0;
+
+ return 0;
+ break;
+
+ case ERL_NEW_REFERENCE_EXT:
+ /* first the integer count */
+ count = get16be(s);
+ if (p) p->len = count;
+
+ /* then the nodename */
+ if (get8(s) != ERL_ATOM_EXT) return -1;
+ len = get16be(s);
+
+ if (p) {
+ memmove(p->node, s, len);
+ p->node[len] = (char)0;
+ }
+ s += len;
+
+ /* creation */
+ if (p) {
+ p->creation = get8(s) & 0x03;
+ }
+ else s += 1;
+
+ /* finally the id integers */
+ if (p) {
+ for (i = 0; (i<count) && (i<3); i++) {
+ p->n[i] = get32be(s);
+ }
+ }
+ else s += 4 * count;
+
+ *index += s-s0;
+
+ return 0;
+ break;
+
+ default:
+ return -1;
+ }
+}
diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c
new file mode 100644
index 0000000000..2fc68a3601
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_skip.c
@@ -0,0 +1,90 @@
+/*
+ * %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%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "decode_skip.h"
+
+int ei_skip_term(const char* buf, int* index)
+{
+ int i, n, ty;
+
+ /* ASSERT(ep != NULL); */
+
+ ei_get_type_internal(buf, index, &ty, &n);
+ switch (ty) {
+ case ERL_ATOM_EXT:
+ /* FIXME: what if some weird locale is in use? */
+ if (ei_decode_atom(buf, index, NULL) < 0) return -1;
+ break;
+ case ERL_PID_EXT:
+ if (ei_decode_pid(buf, index, NULL) < 0) return -1;
+ break;
+ case ERL_PORT_EXT:
+ if (ei_decode_port(buf, index, NULL) < 0) return -1;
+ break;
+ case ERL_NEW_REFERENCE_EXT:
+ case ERL_REFERENCE_EXT:
+ if (ei_decode_ref(buf, index, NULL) < 0) return -1;
+ break;
+ case ERL_NIL_EXT:
+ if (ei_decode_list_header(buf, index, &n) < 0) return -1;
+ break;
+ case ERL_LIST_EXT:
+ if (ei_decode_list_header(buf, index, &n) < 0) return -1;
+ for (i = 0; i < n; ++i)
+ ei_skip_term(buf, index);
+ if (ei_get_type_internal(buf, index, &ty, &n) < 0) return -1;
+ if (ty != ERL_NIL_EXT)
+ ei_skip_term(buf, index);
+ else
+ if (ei_decode_list_header(buf, index, &n) < 0) return -1;
+ break;
+ case ERL_STRING_EXT:
+ if (ei_decode_string(buf, index, NULL) < 0) return -1;
+ break;
+ case ERL_SMALL_TUPLE_EXT:
+ case ERL_LARGE_TUPLE_EXT:
+ if (ei_decode_tuple_header(buf, index, &n) < 0) return -1;
+ for (i = 0; i < n; ++i)
+ ei_skip_term(buf, index);
+ break;
+ case ERL_BINARY_EXT:
+ if (ei_decode_binary(buf, index, NULL, NULL) < 0)
+ return -1;
+ break;
+ case ERL_SMALL_INTEGER_EXT:
+ case ERL_INTEGER_EXT:
+ if (ei_decode_long(buf, index, NULL) < 0) return -1;
+ break;
+ case ERL_SMALL_BIG_EXT:
+ case ERL_LARGE_BIG_EXT:
+ if (ei_decode_big(buf, index, NULL) < 0) return -1;
+ break;
+ case ERL_FLOAT_EXT:
+ if (ei_decode_double(buf, index, NULL) < 0) return -1;
+ break;
+ case ERL_FUN_EXT:
+ if (ei_decode_fun(buf, index, NULL) < 0) return -1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
diff --git a/lib/erl_interface/src/decode/decode_skip.h b/lib/erl_interface/src/decode/decode_skip.h
new file mode 100644
index 0000000000..b6c7b09fe4
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_skip.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%
+ */
+/*
+ * Function:
+ * ei_print_term to print out a binary coded term
+ */
+
+#ifndef _DECODE_SKIP_H
+#define _DECODE_SKIP_H
+
+#endif /* _DECODE_SKIP_H */
diff --git a/lib/erl_interface/src/decode/decode_string.c b/lib/erl_interface/src/decode/decode_string.c
new file mode 100644
index 0000000000..bcbdca0438
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_string.c
@@ -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%
+ */
+#include <string.h>
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+/* FIXME fix or document that special requirements on
+ the in data.... */
+
+int ei_decode_string(const char *buf, int *index, char *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int len;
+ int i;
+ int etype;
+
+ switch (get8(s)) {
+ case ERL_STRING_EXT:
+ len = get16be(s);
+
+ if (p) {
+ memmove(p,s,len);
+ p[len] = (char)0;
+ }
+ s += len;
+ break;
+
+ case ERL_LIST_EXT:
+ /* Really long strings are represented as lists of small integers.
+ * We don't know in advance if the whole list is small integers,
+ * but we decode as much as we can, exiting early if we run into a
+ * non-character in the list.
+ */
+ len = get32be(s);
+ if (p) {
+ for (i=0; i<len; i++) {
+ if ((etype = get8(s)) != ERL_SMALL_INTEGER_EXT) {
+ p[i] = (char)0;
+ return -1;
+ }
+ p[i] = get8(s);
+ }
+ p[i] = (char)0;
+ }
+ else {
+ for (i=0; i<len; i++) {
+ if ((etype = get8(s)) != ERL_SMALL_INTEGER_EXT) return -1;
+ s++;
+ }
+ }
+ /* Check NIL tail */
+ if ((etype = get8(s)) != ERL_NIL_EXT) return -1;
+ break;
+
+ case ERL_NIL_EXT:
+ if (p) p[0] = (char)0;
+ break;
+
+ default:
+ return -1;
+ }
+
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_trace.c b/lib/erl_interface/src/decode/decode_trace.c
new file mode 100644
index 0000000000..ebaa78e29e
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_trace.c
@@ -0,0 +1,43 @@
+/*
+ * %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 "putget.h"
+
+int ei_decode_trace(const char *buf, int *index, erlang_trace *p)
+{
+ int arity = 0;
+ int tindex = *index;
+
+ /* use a temporary index if any function should fail */
+
+ /* { Flags, Label, Serial, FromPid, Prev } */
+ if (ei_decode_tuple_header(buf, &tindex, &arity)
+ || (arity != 5)
+ || ei_decode_long(buf, &tindex, &p->flags)
+ || ei_decode_long(buf, &tindex, &p->label)
+ || ei_decode_long(buf, &tindex, &p->serial)
+ || ei_decode_pid( buf, &tindex, &p->from)
+ || ei_decode_long(buf, &tindex, &p->prev)) return -1;
+
+ /* index is updated by the functions we called */
+
+ *index = tindex;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_tuple_header.c b/lib/erl_interface/src/decode/decode_tuple_header.c
new file mode 100644
index 0000000000..c0ba14ea47
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_tuple_header.c
@@ -0,0 +1,47 @@
+/*
+ * %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"
+
+int ei_decode_tuple_header(const char *buf, int *index, int *arity)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int i;
+
+ switch ((i=get8(s))) {
+ case ERL_SMALL_TUPLE_EXT:
+ if (arity) *arity = get8(s);
+ else s++;
+ break;
+
+ case ERL_LARGE_TUPLE_EXT:
+ if (arity) *arity = get32be(s);
+ else s += 4;
+ break;
+
+ default:
+ return -1;
+ }
+
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_ulong.c b/lib/erl_interface/src/decode/decode_ulong.c
new file mode 100644
index 0000000000..dcf3703be7
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_ulong.c
@@ -0,0 +1,78 @@
+/*
+ * %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"
+
+#ifndef EI_64BIT
+int ei_decode_ulong(const char *buf, int *index, unsigned long *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ unsigned long n;
+ long sn;
+ int arity;
+
+ switch (get8(s)) {
+ case ERL_SMALL_INTEGER_EXT:
+ n = get8(s);
+ break;
+
+ case ERL_INTEGER_EXT:
+ sn = get32be(s);
+ if (sn < 0) return -1;
+ n = (unsigned long)sn;
+ break;
+
+ case ERL_SMALL_BIG_EXT:
+ arity = get8(s);
+ goto decode_big;
+
+ case ERL_LARGE_BIG_EXT:
+ arity = get32be(s);
+
+ decode_big:
+ {
+ int sign = get8(s);
+ int i;
+ n = 0;
+
+ if (sign) return -1;
+
+ /* Little Endian, up to four bytes always fit into unsigned long */
+ for (i = 0; i < arity; i++) {
+ if (i < 4) {
+ n |= get8(s) << (i * 8);
+ } else if (get8(s) != 0) {
+ return -1; /* All but first byte have to be 0 */
+ }
+ }
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ if (p) *p = (unsigned long)n;
+ *index += s-s0;
+
+ return 0;
+}
+#endif /* EI_64BIT */
diff --git a/lib/erl_interface/src/decode/decode_ulonglong.c b/lib/erl_interface/src/decode/decode_ulonglong.c
new file mode 100644
index 0000000000..17ecea848d
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_ulonglong.c
@@ -0,0 +1,83 @@
+/*
+ * %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%
+ */
+#include "eidef.h"
+#include "eiext.h"
+#include "putget.h"
+
+#ifdef EI_64BIT
+int ei_decode_ulong(const char *buf, int *index, unsigned long *p)
+{
+ return ei_decode_ulonglong(buf, index, (EI_ULONGLONG *)p);
+}
+#endif
+
+int ei_decode_ulonglong(const char *buf, int *index, EI_ULONGLONG *p)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ EI_ULONGLONG n;
+ int arity;
+ int sn;
+
+ switch (get8(s)) {
+ case ERL_SMALL_INTEGER_EXT:
+ n = get8(s);
+ break;
+
+ case ERL_INTEGER_EXT:
+ sn = get32be(s);
+ if (sn < 0) return -1;
+ n = (EI_ULONGLONG)sn;
+ break;
+
+ case ERL_SMALL_BIG_EXT:
+ arity = get8(s);
+ goto decode_big;
+
+ case ERL_LARGE_BIG_EXT:
+ arity = get32be(s);
+
+ decode_big:
+ {
+ int sign = get8(s);
+ int i;
+ n = 0;
+
+ if (sign) return -1;
+
+ /* Little Endian, up to four bytes always fit into unsigned long */
+ for (i = 0; i < arity; i++) {
+ if (i < 8) {
+ n |= ((EI_ULONGLONG)get8(s)) << (i * 8);
+ } else if (get8(s) != 0) {
+ return -1; /* All but first byte have to be 0 */
+ }
+ }
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ if (p) *p = n;
+ *index += s-s0;
+
+ return 0;
+}
diff --git a/lib/erl_interface/src/decode/decode_version.c b/lib/erl_interface/src/decode/decode_version.c
new file mode 100644
index 0000000000..124d7272f4
--- /dev/null
+++ b/lib/erl_interface/src/decode/decode_version.c
@@ -0,0 +1,38 @@
+/*
+ * %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"
+
+/* remove version identifier from the start of the buffer */
+int ei_decode_version(const char *buf, int *index, int *version)
+{
+ const char *s = buf + *index;
+ const char *s0 = s;
+ int v;
+
+ v = get8(s);
+ if (version) *version = v;
+ if (v != ERL_VERSION_MAGIC)
+ return -1;
+
+ *index += s-s0;
+
+ return 0;
+}