From 9c80b9ec06fc0ca89dcc8d797a2dbc408a162098 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 13 Nov 2015 16:50:33 +0100 Subject: erl_interface: Support 32-bit creation for pid,port,refs --- lib/erl_interface/src/decode/decode_pid.c | 10 +- lib/erl_interface/src/decode/decode_port.c | 10 +- lib/erl_interface/src/decode/decode_ref.c | 14 +- lib/erl_interface/src/decode/decode_skip.c | 3 + lib/erl_interface/src/encode/encode_pid.c | 13 +- lib/erl_interface/src/encode/encode_port.c | 12 +- lib/erl_interface/src/encode/encode_ref.c | 10 +- lib/erl_interface/src/legacy/erl_eterm.c | 14 +- lib/erl_interface/src/legacy/erl_eterm.h | 6 +- lib/erl_interface/src/legacy/erl_marshal.c | 199 ++++++++++++++++++++-------- lib/erl_interface/src/misc/ei_decode_term.c | 48 ++----- lib/erl_interface/src/misc/ei_printterm.c | 3 + lib/erl_interface/src/misc/get_type.c | 9 ++ lib/erl_interface/src/misc/show_msg.c | 3 + 14 files changed, 237 insertions(+), 117 deletions(-) (limited to 'lib/erl_interface/src') diff --git a/lib/erl_interface/src/decode/decode_pid.c b/lib/erl_interface/src/decode/decode_pid.c index 7fbb818b31..e5750caba6 100644 --- a/lib/erl_interface/src/decode/decode_pid.c +++ b/lib/erl_interface/src/decode/decode_pid.c @@ -27,18 +27,22 @@ int ei_decode_pid(const char *buf, int *index, erlang_pid *p) { const char *s = buf + *index; const char *s0 = s; + const char tag = get8(s); - if (get8(s) != ERL_PID_EXT) return -1; + if (tag != ERL_PID_EXT && tag != ERL_NEW_PID_EXT) return -1; if (p) { if (get_atom(&s, p->node, NULL) < 0) return -1; p->num = get32be(s) & 0x7fff; /* 15 bits */ p->serial = get32be(s) & 0x1fff; /* 13 bits */ - p->creation = get8(s) & 0x03; /* 2 bits */ + if (tag == ERL_PID_EXT) + p->creation = get8(s) & 0x03; /* 2 bits */ + else + p->creation = get32be(s); /* 32 bits */ } else { if (get_atom(&s, NULL, NULL) < 0) return -1; - s+= 9; + s+= (tag == ERL_PID_EXT ? 9 : 12); } *index += s-s0; diff --git a/lib/erl_interface/src/decode/decode_port.c b/lib/erl_interface/src/decode/decode_port.c index e039b5b845..7b61f254ff 100644 --- a/lib/erl_interface/src/decode/decode_port.c +++ b/lib/erl_interface/src/decode/decode_port.c @@ -26,17 +26,21 @@ int ei_decode_port(const char *buf, int *index, erlang_port *p) { const char *s = buf + *index; const char *s0 = s; + const char tag = get8(s); - if (get8(s) != ERL_PORT_EXT) return -1; + if (tag != ERL_PORT_EXT && tag != ERL_NEW_PORT_EXT) return -1; if (p) { if (get_atom(&s, p->node, NULL) < 0) return -1; p->id = get32be(s) & 0x0fffffff /* 28 bits */; - p->creation = get8(s) & 0x03; + if (tag == ERL_PORT_EXT) + p->creation = get8(s) & 0x03; + else + p->creation = get32be(s); } else { if (get_atom(&s, NULL, NULL) < 0) return -1; - s += 5; + s += (tag == ERL_PORT_EXT ? 5 : 8); } *index += s-s0; diff --git a/lib/erl_interface/src/decode/decode_ref.c b/lib/erl_interface/src/decode/decode_ref.c index a6b87e5a21..b8e1ebfedd 100644 --- a/lib/erl_interface/src/decode/decode_ref.c +++ b/lib/erl_interface/src/decode/decode_ref.c @@ -28,8 +28,9 @@ int ei_decode_ref(const char *buf, int *index, erlang_ref *p) const char *s = buf + *index; const char *s0 = s; int count, i; + const char tag = get8(s); - switch (get8(s)) { + switch (tag) { case ERL_REFERENCE_EXT: if (p) { if (get_atom(&s, p->node, NULL) < 0) return -1; @@ -47,18 +48,23 @@ int ei_decode_ref(const char *buf, int *index, erlang_ref *p) return 0; break; - case ERL_NEW_REFERENCE_EXT: + case ERL_NEW_REFERENCE_EXT: + case ERL_NEWER_REFERENCE_EXT: + /* first the integer count */ count = get16be(s); if (p) { p->len = count; if (get_atom(&s, p->node, NULL) < 0) return -1; - p->creation = get8(s) & 0x03; + if (tag == ERL_NEW_REFERENCE_EXT) + p->creation = get8(s) & 0x03; + else + p->creation = get32be(s); } else { if (get_atom(&s, NULL, NULL) < 0) return -1; - s += 1; + s += (tag == ERL_NEW_REFERENCE_EXT ? 1 : 4); } /* finally the id integers */ diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c index d49ae0007f..4ba94a658a 100644 --- a/lib/erl_interface/src/decode/decode_skip.c +++ b/lib/erl_interface/src/decode/decode_skip.c @@ -35,12 +35,15 @@ int ei_skip_term(const char* buf, int* index) NULL, NULL) < 0) return -1; break; case ERL_PID_EXT: + case ERL_NEW_PID_EXT: if (ei_decode_pid(buf, index, NULL) < 0) return -1; break; case ERL_PORT_EXT: + case ERL_NEW_PORT_EXT: if (ei_decode_port(buf, index, NULL) < 0) return -1; break; case ERL_NEW_REFERENCE_EXT: + case ERL_NEWER_REFERENCE_EXT: case ERL_REFERENCE_EXT: if (ei_decode_ref(buf, index, NULL) < 0) return -1; break; diff --git a/lib/erl_interface/src/encode/encode_pid.c b/lib/erl_interface/src/encode/encode_pid.c index 7b01b7045f..3eabbdcc02 100644 --- a/lib/erl_interface/src/encode/encode_pid.c +++ b/lib/erl_interface/src/encode/encode_pid.c @@ -24,7 +24,8 @@ int ei_encode_pid(char *buf, int *index, const erlang_pid *p) { - char *s = buf + *index; + char* s = buf + *index; + const char tag = (p->creation > 3) ? ERL_NEW_PID_EXT : ERL_PID_EXT; ++(*index); /* skip ERL_PID_EXT */ if (ei_encode_atom_len_as(buf, index, p->node, strlen(p->node), @@ -32,17 +33,21 @@ int ei_encode_pid(char *buf, int *index, const erlang_pid *p) return -1; if (buf) { - put8(s,ERL_PID_EXT); + put8(s, tag); s = buf + *index; /* now the integers */ put32be(s,p->num & 0x7fff); /* 15 bits */ put32be(s,p->serial & 0x1fff); /* 13 bits */ - put8(s,(p->creation & 0x03)); /* 2 bits */ + if (tag == ERL_PID_EXT) { + put8(s,(p->creation & 0x03)); /* 2 bits */ + } else { + put32be(s, p->creation); /* 32 bits */ + } } - *index += 4 + 4 + 1; + *index += 4 + 4 + (tag == ERL_PID_EXT ? 1 : 4); return 0; } diff --git a/lib/erl_interface/src/encode/encode_port.c b/lib/erl_interface/src/encode/encode_port.c index a7468e5917..a6e7d3541a 100644 --- a/lib/erl_interface/src/encode/encode_port.c +++ b/lib/erl_interface/src/encode/encode_port.c @@ -25,6 +25,7 @@ int ei_encode_port(char *buf, int *index, const erlang_port *p) { char *s = buf + *index; + const char tag = p->creation > 3 ? ERL_NEW_PORT_EXT : ERL_PORT_EXT; ++(*index); /* skip ERL_PORT_EXT */ if (ei_encode_atom_len_as(buf, index, p->node, strlen(p->node), ERLANG_UTF8, @@ -32,16 +33,19 @@ int ei_encode_port(char *buf, int *index, const erlang_port *p) return -1; } if (buf) { - put8(s,ERL_PORT_EXT); + put8(s, tag); s = buf + *index; /* now the integers */ put32be(s,p->id & 0x0fffffff /* 28 bits */); - put8(s,(p->creation & 0x03)); + if (tag == ERL_PORT_EXT) { + put8(s,(p->creation & 0x03)); + } else { + put32be(s, p->creation); + } } - - *index += 4 + 1; + *index += 4 + (tag == ERL_PORT_EXT ? 1 : 4); return 0; } diff --git a/lib/erl_interface/src/encode/encode_ref.c b/lib/erl_interface/src/encode/encode_ref.c index 0f27a086f0..956a9a7e16 100644 --- a/lib/erl_interface/src/encode/encode_ref.c +++ b/lib/erl_interface/src/encode/encode_ref.c @@ -24,6 +24,7 @@ int ei_encode_ref(char *buf, int *index, const erlang_ref *p) { + const char tag = (p->creation > 3) ? ERL_NEWER_REFERENCE_EXT : ERL_NEW_REFERENCE_EXT; char *s = buf + *index; int i; @@ -36,7 +37,7 @@ int ei_encode_ref(char *buf, int *index, const erlang_ref *p) /* Always encode as an extended reference; all participating parties are now expected to be able to decode extended references. */ if (buf) { - put8(s,ERL_NEW_REFERENCE_EXT); + put8(s, tag); /* first, number of integers */ put16be(s, p->len); @@ -45,12 +46,15 @@ int ei_encode_ref(char *buf, int *index, const erlang_ref *p) s = buf + *index; /* now the integers */ - put8(s,(p->creation & 0x03)); + if (tag == ERL_NEW_REFERENCE_EXT) + put8(s,(p->creation & 0x03)); + else + put32be(s, p->creation); for (i = 0; i < p->len; i++) put32be(s,p->n[i]); } - *index += p->len*4 + 1; + *index += p->len*4 + (tag == ERL_NEW_REFERENCE_EXT ? 1 : 4); return 0; } diff --git a/lib/erl_interface/src/legacy/erl_eterm.c b/lib/erl_interface/src/legacy/erl_eterm.c index f2f35ab693..8fcb39b91d 100644 --- a/lib/erl_interface/src/legacy/erl_eterm.c +++ b/lib/erl_interface/src/legacy/erl_eterm.c @@ -285,12 +285,12 @@ ETERM *erl_mk_pid(const char *node, erl_errno = ENOMEM; return NULL; } - erl_mk_pid_helper(ep, number, serial, creation); + erl_mk_pid_helper(ep, number, serial, creation & 0x03); return ep; } void erl_mk_pid_helper(ETERM *ep, unsigned int number, - unsigned int serial, unsigned char creation) + unsigned int serial, unsigned int creation) { ERL_PID_NUMBER(ep) = number & 0x7fff; /* 15 bits */ if (ei_internal_use_r9_pids_ports()) { @@ -299,7 +299,7 @@ void erl_mk_pid_helper(ETERM *ep, unsigned int number, else { ERL_PID_SERIAL(ep) = serial & 0x1fff; /* 13 bits */ } - ERL_PID_CREATION(ep) = creation & 0x03; /* 2 bits */ + ERL_PID_CREATION(ep) = creation; /* 32 bits */ } /* @@ -326,7 +326,7 @@ ETERM *erl_mk_port(const char *node, return ep; } -void erl_mk_port_helper(ETERM* ep, unsigned number, unsigned char creation) +void erl_mk_port_helper(ETERM* ep, unsigned number, unsigned int creation) { if (ei_internal_use_r9_pids_ports()) { ERL_PORT_NUMBER(ep) = number & 0x3ffff; /* 18 bits */ @@ -334,7 +334,7 @@ void erl_mk_port_helper(ETERM* ep, unsigned number, unsigned char creation) else { ERL_PORT_NUMBER(ep) = number & 0x0fffffff; /* 18 bits */ } - ERL_PORT_CREATION(ep) = creation & 0x03; /* 2 bits */ + ERL_PORT_CREATION(ep) = creation; /* 32 bits */ } /* @@ -344,7 +344,7 @@ ETERM *__erl_mk_reference (ETERM* t, const char *node, size_t len, unsigned int n[], - unsigned char creation) + unsigned int creation) { if (t == NULL) { if (node == NULL) return NULL; @@ -363,7 +363,7 @@ ETERM *__erl_mk_reference (ETERM* t, ERL_REF_NUMBERS(t)[0] = n[0] & 0x3ffff; /* 18 bits */ ERL_REF_NUMBERS(t)[1] = n[1]; ERL_REF_NUMBERS(t)[2] = n[2]; - ERL_REF_CREATION(t) = creation & 0x03; /* 2 bits */ + ERL_REF_CREATION(t) = creation; /* 32 bits */ return t; } diff --git a/lib/erl_interface/src/legacy/erl_eterm.h b/lib/erl_interface/src/legacy/erl_eterm.h index d9a26b2541..1b3f20f25c 100644 --- a/lib/erl_interface/src/legacy/erl_eterm.h +++ b/lib/erl_interface/src/legacy/erl_eterm.h @@ -56,9 +56,9 @@ typedef struct _heapmark { } Erl_HeapMark; -void erl_mk_port_helper(ETERM* ep, unsigned number, unsigned char creation); -void erl_mk_pid_helper(ETERM*, unsigned,unsigned, unsigned char); -ETERM * __erl_mk_reference(ETERM*, const char *, size_t, unsigned int n[], unsigned char); +void erl_mk_port_helper(ETERM* ep, unsigned number, unsigned int creation); +void erl_mk_pid_helper(ETERM*, unsigned,unsigned, unsigned int); +ETERM * __erl_mk_reference(ETERM*, const char *, size_t, unsigned int n[], unsigned int); int erl_current_fix_desc(void); #endif /* _ERL_ETERM_H */ diff --git a/lib/erl_interface/src/legacy/erl_marshal.c b/lib/erl_interface/src/legacy/erl_marshal.c index a4216c9541..ebb6b78540 100644 --- a/lib/erl_interface/src/legacy/erl_marshal.c +++ b/lib/erl_interface/src/legacy/erl_marshal.c @@ -120,10 +120,13 @@ void erl_init_marshal(void) cmp_array[ERL_SMALL_ATOM_UTF8_EXT] = ERL_ATOM_CMP; cmp_array[ERL_REFERENCE_EXT] = ERL_REF_CMP; cmp_array[ERL_NEW_REFERENCE_EXT] = ERL_REF_CMP; + cmp_array[ERL_NEWER_REFERENCE_EXT]=ERL_REF_CMP; cmp_array[ERL_FUN_EXT] = ERL_FUN_CMP; cmp_array[ERL_NEW_FUN_EXT] = ERL_FUN_CMP; cmp_array[ERL_PORT_EXT] = ERL_PORT_CMP; + cmp_array[ERL_NEW_PORT_EXT] = ERL_PORT_CMP; cmp_array[ERL_PID_EXT] = ERL_PID_CMP; + cmp_array[ERL_NEW_PID_EXT] = ERL_PID_CMP; cmp_array[ERL_SMALL_TUPLE_EXT] = ERL_TUPLE_CMP; cmp_array[ERL_LARGE_TUPLE_EXT] = ERL_TUPLE_CMP; cmp_array[ERL_NIL_EXT] = ERL_NIL_CMP; @@ -304,8 +307,8 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) *(*ext)++ = ul & 0xff; return 0; - case ERL_PID: - *(*ext)++ = ERL_PID_EXT; + case ERL_PID: { + unsigned char* tagp = (*ext)++; /* First poke in node as an atom */ encode_atom(&ep->uval.pidval.node, ext); /* And then fill in the integer fields */ @@ -319,17 +322,29 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) *(*ext)++ = (i >> 16) &0xff; *(*ext)++ = (i >> 8) &0xff; *(*ext)++ = i &0xff; - *(*ext)++ = ERL_PID_CREATION(ep); + + i = ERL_PID_CREATION(ep); + if ((unsigned int)i <= 3) { + *tagp = ERL_PID_EXT; + *(*ext)++ = i; + } else { + *tagp = ERL_NEW_PID_EXT; + *(*ext)++ = (i >> 24) &0xff; + *(*ext)++ = (i >> 16) &0xff; + *(*ext)++ = (i >> 8) &0xff; + *(*ext)++ = i &0xff; + } return 0; + } case ERL_REF: { + unsigned char* tagp = (*ext)++; + int len, j; /* Always encode as an extended reference; all participating parties are now expected to be able to decode extended references. */ - *(*ext)++ = ERL_NEW_REFERENCE_EXT; - i = strlen((char *)ERL_REF_NODE(ep)); len = ERL_REF_LEN(ep); *(*ext)++ = (len >> 8) &0xff; @@ -337,7 +352,18 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) encode_atom(&ep->uval.refval.node, ext); - *(*ext)++ = ERL_REF_CREATION(ep); + i = ERL_REF_CREATION(ep); + if ((unsigned int)i <= 3) { + *tagp = ERL_NEW_REFERENCE_EXT; + *(*ext)++ = i; + } else { + *tagp = ERL_NEWER_REFERENCE_EXT; + *(*ext)++ = (i >> 24) &0xff; + *(*ext)++ = (i >> 16) &0xff; + *(*ext)++ = (i >> 8) &0xff; + *(*ext)++ = i &0xff; + } + /* Then the integer fields */ for (j = 0; j < ERL_REF_LEN(ep); j++) { i = ERL_REF_NUMBERS(ep)[j]; @@ -348,8 +374,8 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) } } return 0; - case ERL_PORT: - *(*ext)++ = ERL_PORT_EXT; + case ERL_PORT: { + unsigned char* tagp = (*ext)++; /* First poke in node as an atom */ encode_atom(&ep->uval.portval.node, ext); /* Then the integer fields */ @@ -358,8 +384,20 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) *(*ext)++ = (i >> 16) &0xff; *(*ext)++ = (i >> 8) &0xff; *(*ext)++ = i &0xff; - *(*ext)++ = ERL_PORT_CREATION(ep); + + i = ERL_PORT_CREATION(ep); + if ((unsigned int)i <= 3) { + *tagp = ERL_PORT_EXT; + *(*ext)++ = i; + } else { + *tagp = ERL_NEW_PORT_EXT; + *(*ext)++ = (i >> 24) &0xff; + *(*ext)++ = (i >> 16) &0xff; + *(*ext)++ = (i >> 8) &0xff; + *(*ext)++ = i &0xff; + } return 0; + } case ERL_EMPTY_LIST: *(*ext)++ = ERL_NIL_EXT; break; @@ -698,12 +736,14 @@ static ETERM *erl_decode_it(unsigned char **ext) unsigned int u,sign; int i,j,arity; double ff; + unsigned char tag; /* Assume we are going to decode an integer */ ep = erl_alloc_eterm(ERL_INTEGER); ERL_COUNT(ep) = 1; - switch (*(*ext)++) + tag = *(*ext)++; + switch (tag) { case ERL_INTEGER_EXT: i = (int) (**ext << 24) | ((*ext)[1] << 16) | @@ -801,9 +841,10 @@ static ETERM *erl_decode_it(unsigned char **ext) return ep; case ERL_PID_EXT: + case ERL_NEW_PID_EXT: { unsigned int number, serial; - unsigned char creation; + unsigned int creation; ERL_TYPE(ep) = ERL_PID; if (read_atom(ext, &ep->uval.pidval.node) < 0) return NULL; @@ -815,7 +856,13 @@ static ETERM *erl_decode_it(unsigned char **ext) serial = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | ((*ext)[2]) << 8 | ((*ext)[3]); *ext += 4; - creation = *(*ext)++; + if (tag == ERL_PID_EXT) + creation = *(*ext)++; + else { + creation = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | + ((*ext)[2]) << 8 | ((*ext)[3]); + *ext += 4; + } erl_mk_pid_helper(ep, number, serial, creation); return ep; } @@ -836,11 +883,12 @@ static ETERM *erl_decode_it(unsigned char **ext) return ep; } - case ERL_NEW_REFERENCE_EXT: + case ERL_NEW_REFERENCE_EXT: + case ERL_NEWER_REFERENCE_EXT: { size_t cnt, i; unsigned int n[3]; - unsigned char creation; + unsigned int creation; ERL_TYPE(ep) = ERL_REF; cnt = ((*ext)[0] << 8) | (*ext)[1]; @@ -849,7 +897,13 @@ static ETERM *erl_decode_it(unsigned char **ext) if (read_atom(ext, &ep->uval.refval.node) < 0) return NULL; /* get the integers */ - creation = *(*ext)++; + if (tag == ERL_NEW_REFERENCE_EXT) + creation = *(*ext)++; + else { + creation = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | + ((*ext)[2]) << 8 | ((*ext)[3]); + *ext += 4; + } for(i = 0; i < cnt; i++) { n[i] = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | @@ -861,9 +915,10 @@ static ETERM *erl_decode_it(unsigned char **ext) } case ERL_PORT_EXT: + case ERL_NEW_PORT_EXT: { unsigned int number; - unsigned char creation; + unsigned int creation; ERL_TYPE(ep) = ERL_PORT; if (read_atom(ext, &ep->uval.portval.node) < 0) return NULL; @@ -872,7 +927,13 @@ static ETERM *erl_decode_it(unsigned char **ext) number = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | ((*ext)[2]) << 8 | ((*ext)[3]); *ext += 4; - creation = *(*ext)++; + if (tag == ERL_PORT_EXT) + creation = *(*ext)++; + else { + creation = (((*ext)[0] << 24) | ((*ext)[1]) << 16 | + ((*ext)[2]) << 8 | ((*ext)[3])); + *ext += 4; + } erl_mk_port_helper(ep, number, creation); return ep; } @@ -1114,11 +1175,14 @@ unsigned char erl_ext_type(unsigned char *ext) case ERL_SMALL_ATOM_UTF8_EXT: return ERL_ATOM; case ERL_PID_EXT: + case ERL_NEW_PID_EXT: return ERL_PID; case ERL_PORT_EXT: + case ERL_NEW_PORT_EXT: return ERL_PORT; case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: + case ERL_NEWER_REFERENCE_EXT: return ERL_REF; case ERL_NIL_EXT: return ERL_EMPTY_LIST; @@ -1167,9 +1231,12 @@ int erl_ext_size(unsigned char *t) case ERL_SMALL_ATOM_EXT: case ERL_SMALL_ATOM_UTF8_EXT: case ERL_PID_EXT: + case ERL_NEW_PID_EXT: case ERL_PORT_EXT: + case ERL_NEW_PORT_EXT: case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: + case ERL_NEWER_REFERENCE_EXT: case ERL_NIL_EXT: case ERL_BINARY_EXT: case ERL_STRING_EXT: @@ -1240,8 +1307,9 @@ static int jump(unsigned char **ext) { int j,k,i=0; int n; + const int tag = *(*ext)++; - switch (*(*ext)++) { + switch (tag) { case ERL_VERSION_MAGIC: return jump(ext); case ERL_INTEGER_EXT: @@ -1257,22 +1325,29 @@ static int jump(unsigned char **ext) jump_atom(ext); break; case ERL_PID_EXT: - /* eat first atom */ if (!jump_atom(ext)) return 0; - *ext += 9; /* Two int's and the creation field */ + *ext += 4 + 4 + 1; break; + case ERL_NEW_PID_EXT: + if (!jump_atom(ext)) return 0; + *ext += 4 + 4 + 4; + break; case ERL_REFERENCE_EXT: case ERL_PORT_EXT: - /* first field is an atom */ if (!jump_atom(ext)) return 0; - *ext += 5; /* One int and the creation field */ + *ext += 4 + 1; break; + case ERL_NEW_PORT_EXT: + if (!jump_atom(ext)) return 0; + *ext += 4 + 4; + break; case ERL_NEW_REFERENCE_EXT: + case ERL_NEWER_REFERENCE_EXT: n = (**ext << 8) | (*ext)[1]; *ext += 2; /* first field is an atom */ if (!jump_atom(ext)) return 0; - *ext += 4*n+1; + *ext += 4*n + (tag == ERL_NEW_REFERENCE_EXT ? 1 : 4); break; case ERL_NIL_EXT: /* We just passed it... */ @@ -1605,7 +1680,6 @@ static int cmp_exe2(unsigned char **e1, unsigned char **e2) { int min, ret,i,j,k; double ff1, ff2; - unsigned char *tmp1, *tmp2; unsigned char tag1, tag2; if ( ((*e1)[0] == ERL_STRING_EXT) && ((*e2)[0] == ERL_LIST_EXT) ) { @@ -1649,47 +1723,68 @@ static int cmp_exe2(unsigned char **e1, unsigned char **e2) *e1 += i; *e2 += j; return ret; - case ERL_PID_EXT: { - unsigned char *n1 = *e1; - unsigned char *n2 = *e2; - CMP_EXT_SKIP_ATOM(*e1); CMP_EXT_SKIP_ATOM(*e2); - *e1 += 9; *e2 += 9; + case ERL_PID_EXT: + case ERL_NEW_PID_EXT: { + erlang_pid pid1, pid2; + unsigned char* buf1 = *e1 - 1; + unsigned char* buf2 = *e2 - 1; + int ix1 = 0, ix2 = 0; + + if (ei_decode_pid((char*)buf1, &ix1, &pid1) || + ei_decode_pid((char*)buf2, &ix2, &pid2)) + return CMP_EXT_ERROR_CODE; + + *e1 = buf1 + ix1; + *e2 = buf2 + ix2; /* First compare serials ... */ - tmp1 = *e1 - 5; tmp2 = *e2 - 5; - CMP_EXT_INT32_BE(tmp1, tmp2); + if (pid1.serial < pid2.serial) return -1; + else if (pid1.serial > pid2.serial) return 1; /* ... then ids ... */ - tmp1 -= 4; tmp2 -= 4; - CMP_EXT_INT32_BE(tmp1, tmp2); + if (pid1.num < pid2.num) return -1; + else if (pid1.num > pid2.num) return 1; /* ... then node names ... */ - ret = cmp_exe2(&n1, &n2); - if (ret != 0) - return ret; + j = strcmp(pid1.node, pid2.node); + if (j < 0) return -1; + else if (j > 0) return 1; /* ... and then finaly creations. */ - tmp1 += 8; tmp2 += 8; - if (*tmp1 != *tmp2) - return *tmp1 < *tmp2 ? -1 : 1; + if (pid1.creation < pid2.creation) return -1; + else if (pid1.creation > pid2.creation) return 1; + return 0; } case ERL_PORT_EXT: - /* First compare node names ... */ - if (!IS_ERL_ATOM(**e1) || !IS_ERL_ATOM(**e2)) - return CMP_EXT_ERROR_CODE; - ret = cmp_exe2(e1, e2); - *e1 += 5; *e2 += 5; - if (ret != 0) - return ret; + case ERL_NEW_PORT_EXT: { + erlang_port port1, port2; + unsigned char* buf1 = *e1 - 1; + unsigned char* buf2 = *e2 - 1; + int ix1 = 0, ix2 = 0; + + if (ei_decode_port((char*)buf1, &ix1, &port1) || + ei_decode_port((char*)buf2, &ix2, &port2)) + return CMP_EXT_ERROR_CODE; + + *e1 = buf1 + ix1; + *e2 = buf2 + ix2; + + /* First compare node names ... */ + j = strcmp(port1.node, port2.node); + if (j < 0) return -1; + else if (j > 0) return 1; + /* ... then creations ... */ - tmp1 = *e1 - 1; tmp2 = *e2 - 1; - if (*tmp1 != *tmp2) - return *tmp1 < *tmp2 ? -1 : 1; + if (port1.creation < port2.creation) return -1; + else if (port1.creation > port2.creation) return 1; + /* ... and then finaly ids. */ - tmp1 -= 4; tmp2 -= 4; - CMP_EXT_INT32_BE(tmp1, tmp2); - return 0; + if (port1.id < port2.id) return -1; + else if (port1.id > port2.id) return 1; + + return 0; + } case ERL_NIL_EXT: return 0; case ERL_LIST_EXT: i = (**e1 << 24) | ((*e1)[1] << 16) |((*e1)[2] << 8) | (*e1)[3]; diff --git a/lib/erl_interface/src/misc/ei_decode_term.c b/lib/erl_interface/src/misc/ei_decode_term.c index 0ec67dde09..37375b4e8e 100644 --- a/lib/erl_interface/src/misc/ei_decode_term.c +++ b/lib/erl_interface/src/misc/ei_decode_term.c @@ -33,7 +33,7 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term) { const char* s = buf + *index, * s0 = s; - int i, n, sign; + int n, sign; char c; if (term == NULL) return -1; @@ -47,47 +47,27 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term) break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: - return ei_decode_double(buf, index, &term->value.d_val); + return (ei_decode_double(buf, index, &term->value.d_val) < 0 + ? -1 : 1); case ERL_ATOM_EXT: case ERL_ATOM_UTF8_EXT: case ERL_SMALL_ATOM_EXT: case ERL_SMALL_ATOM_UTF8_EXT: - return ei_decode_atom(buf, index, term->value.atom_name); + return (ei_decode_atom(buf, index, term->value.atom_name) < 0 + ? -1 : 1); case ERL_REFERENCE_EXT: - /* first the nodename */ - if (get_atom(&s, term->value.ref.node, NULL) < 0) return -1; - /* 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 (get_atom(&s, term->value.ref.node, NULL) < 0) return -1; - /* creation */ - term->value.ref.creation = get8(s) & 0x03; - /* finally the id integers */ - for (i = 0; (ivalue.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_NEWER_REFERENCE_EXT: + return (ei_decode_ref(buf, index, &term->value.ref) < 0 + ? -1 : 1); case ERL_PORT_EXT: - if (get_atom(&s, term->value.port.node, NULL) < 0) return -1; - term->value.port.id = get32be(s) & 0x0fffffff; /* 28 bits */; - term->value.port.creation = get8(s) & 0x03; - break; + case ERL_NEW_PORT_EXT: + return (ei_decode_port(buf, index, &term->value.port) < 0 + ? -1 : 1); case ERL_PID_EXT: - if (get_atom(&s, term->value.pid.node, NULL) < 0) return -1; - /* 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_NEW_PID_EXT: + return (ei_decode_pid(buf, index, &term->value.pid) < 0 + ? -1 : 1); case ERL_SMALL_TUPLE_EXT: term->arity = get8(s); break; diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c index 702ee9566d..8b216b2b96 100644 --- a/lib/erl_interface/src/misc/ei_printterm.c +++ b/lib/erl_interface/src/misc/ei_printterm.c @@ -151,15 +151,18 @@ static int print_term(FILE* fp, ei_x_buff* x, } break; case ERL_PID_EXT: + case ERL_NEW_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: + case ERL_NEW_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_NEWER_REFERENCE_EXT: case ERL_REFERENCE_EXT: if (ei_decode_ref(buf, index, &ref) < 0) goto err; ch_written += xprintf(fp, x, "#Ref<"); diff --git a/lib/erl_interface/src/misc/get_type.c b/lib/erl_interface/src/misc/get_type.c index 6b95c1f470..62eac4a30e 100644 --- a/lib/erl_interface/src/misc/get_type.c +++ b/lib/erl_interface/src/misc/get_type.c @@ -76,6 +76,15 @@ int ei_get_type_internal(const char *buf, const int *index, *len = get32be(s); /* #digit_bytes */ break; + case ERL_NEW_PID_EXT: + *type = ERL_PID_EXT; + break; + case ERL_NEW_PORT_EXT: + *type = ERL_PORT_EXT; + break; + case ERL_NEWER_REFERENCE_EXT: + *type = ERL_NEW_REFERENCE_EXT; + break; default: *len = 0; break; diff --git a/lib/erl_interface/src/misc/show_msg.c b/lib/erl_interface/src/misc/show_msg.c index b08b17aea4..3b9f934c62 100644 --- a/lib/erl_interface/src/misc/show_msg.c +++ b/lib/erl_interface/src/misc/show_msg.c @@ -398,6 +398,7 @@ static void show_term(const char *termbuf, int *index, FILE *stream) break; case ERL_PID_EXT: + case ERL_NEW_PID_EXT: ei_decode_pid(termbuf,index,&pid); show_pid(stream,&pid); break; @@ -432,6 +433,7 @@ static void show_term(const char *termbuf, int *index, FILE *stream) case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: + case ERL_NEWER_REFERENCE_EXT: ei_decode_ref(termbuf,index,&ref); fprintf(stream,"#Ref<%s",ref.node); for (i = 0; i < ref.len; i++) { @@ -441,6 +443,7 @@ static void show_term(const char *termbuf, int *index, FILE *stream) break; case ERL_PORT_EXT: + case ERL_NEW_PORT_EXT: ei_decode_port(termbuf,index,&port); fprintf(stream,"#Port<%s.%u.%u>",port.node,port.id,port.creation); break; -- cgit v1.2.3