diff options
Diffstat (limited to 'lib/erl_interface')
54 files changed, 1381 insertions, 615 deletions
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in index 7728cb97be..72ac8c7bbf 100644 --- a/lib/erl_interface/configure.in +++ b/lib/erl_interface/configure.in @@ -288,13 +288,7 @@ case "$threads_disabled" in ;; win32_threads) EI_THREADS="true" - AC_MSG_CHECKING([for __declspec(thread) usability]) - if test "X$GCC" = "Xyes"; then - AC_MSG_RESULT([no]) - else - THR_DEFS="$THR_DEFS -DUSE_DECLSPEC_THREAD" - AC_MSG_RESULT([yes]) - fi + THR_DEFS="$THR_DEFS -D_WIN32_WINNT=0x0500 -DWINVER=0x0500" ;; pthread) EI_THREADS="true" diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml index 9083ae02b0..de4e4b4301 100644 --- a/lib/erl_interface/doc/src/ei.xml +++ b/lib/erl_interface/doc/src/ei.xml @@ -581,7 +581,7 @@ ei_x_encode_empty_list(&x); <c><![CDATA[term]]></c> union, it is decoded, and the appropriate field in <c><![CDATA[term->value]]></c> is set, and <c><![CDATA[*index]]></c> is incremented by the term size.</p> - <p>The function returns 0 on successful encoding, -1 on error, + <p>The function returns 0 on successful decoding, -1 on error, and 1 if the term seems alright, but does not fit in the <c><![CDATA[term]]></c> structure. If it returns 0, the <c><![CDATA[index]]></c> will be incremented, and the <c><![CDATA[term]]></c> contains the @@ -641,12 +641,14 @@ ei_x_encode_empty_list(&x); <p></p> <pre> ~a - an atom, char* +~c - a character, char ~s - a string, char* ~i - an integer, int ~l - a long integer, long int ~u - a unsigned long integer, unsigned long int ~f - a float, float ~d - a double float, double float +~p - an Erlang PID, erlang_pid* </pre> <p>For instance, to encode a tuple with some stuff:</p> <pre> diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml index abf705f9e2..f562615ddd 100644 --- a/lib/erl_interface/doc/src/ei_connect.xml +++ b/lib/erl_interface/doc/src/ei_connect.xml @@ -4,7 +4,7 @@ <cref> <header> <copyright> - <year>2001</year><year>2009</year> + <year>2001</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -54,7 +54,7 @@ the operation, if the primitive does not complete within the time specified, the function will return an error and <c><![CDATA[erl_errno]]></c> will be set to <c><![CDATA[ETIMEDOUT]]></c>. With - communication primitive is ment an operation on the socket, like + communication primitive is meant an operation on the socket, like <c><![CDATA[connect]]></c>, <c><![CDATA[accept]]></c>, <c><![CDATA[recv]]></c> or <c><![CDATA[send]]></c>.</p> <p>Obviously the timeouts are for implementing fault tolerance, not to keep hard realtime promises. The <c><![CDATA[_tmo]]></c> functions @@ -116,7 +116,7 @@ int n = 0; struct in_addr addr; ei_cnode ec; -addr = inet_addr("150.236.14.75"); +addr.s_addr = inet_addr("150.236.14.75"); if (ei_connect_xinit(&ec, "chivas", "madonna", @@ -132,7 +132,7 @@ if (ei_connect_xinit(&ec, </p> <code type="none"><![CDATA[ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) { - fprintf("ERROR when initializing: %d",erl_errno); + fprintf(stderr,"ERROR when initializing: %d",erl_errno); exit(-1); } ]]></code> @@ -177,7 +177,7 @@ int fd = ei_connect(&ec, NODE); /*** Variant 2 ***/ struct in_addr addr; -addr = inet_addr(IP_ADDR); +addr.s_addr = inet_addr(IP_ADDR); fd = ei_xconnect(&ec, &addr, ALIVE); ]]></code> </desc> @@ -508,7 +508,7 @@ if (ei_decode_version(result.buff, &index) < 0 same as the port number that was previously bound to the socket.</p> <p><c><![CDATA[addr]]></c> is the 32-bit IP address of the local host.</p> <p>To unregister with epmd, simply close the returned - descriptor. See also <c><![CDATA[ei_unpublish()]]></c>.</p> + descriptor. Do not use <c><![CDATA[ei_unpublish()]]></c>, which is deprecated anyway.</p> <p>On success, the functions return a descriptor connecting the calling process to epmd. On failure, they return -1 and set <c><![CDATA[erl_errno]]></c> to <c><![CDATA[EIO]]></c>.</p> @@ -558,18 +558,21 @@ typedef struct { </func> <func> <name><ret>int</ret><nametext>ei_unpublish(ei_cnode *ec)</nametext></name> - <fsummary>Unpublish a node name</fsummary> + <fsummary>Forcefully unpublish a node name</fsummary> <desc> <p>This function can be called by a process to unregister a - specified node from epmd on the localhost. This may be - useful, for example, when epmd has not detected the failure of a - node, and will not allow the name to be reused. If you use this - function to unregister your own process, be sure to also close - the descriptor that was returned by <c><![CDATA[ei_publish()]]></c>.</p> - <note> - <p>Careless use of this function may have unpredictable - results, if the registered node is in fact still running.</p> - </note> + specified node from epmd on the localhost. This is however usually not + allowed, unless epmd was started with the -relaxed_command_check + flag, which it normally isn't.</p> + + <p>To unregister a node you have published, you should + close the descriptor that was returned by + <c><![CDATA[ei_publish()]]></c>.</p> + + <warning> + <p>This function is deprecated and will be removed in a future + release.</p> + </warning> <p><c><![CDATA[ec]]></c> is the node structure of the node to unregister.</p> <p>If the node was successfully unregistered from epmd, the function returns 0. Otherwise, it returns -1 and sets diff --git a/lib/erl_interface/doc/src/erl_connect.xml b/lib/erl_interface/doc/src/erl_connect.xml index b2235925b2..bd5e637244 100644 --- a/lib/erl_interface/doc/src/erl_connect.xml +++ b/lib/erl_interface/doc/src/erl_connect.xml @@ -4,7 +4,7 @@ <cref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -451,7 +451,7 @@ typedef struct { <p><c><![CDATA[port]]></c> is the local name to register, and should be the same as the port number that was previously bound to the socket.</p> <p>To unregister with epmd, simply close the returned - descriptor. See also <c><![CDATA[erl_unpublish()]]></c>. + descriptor. </p> <p>On success, the functions return a descriptor connecting the calling process to epmd. On failure, they return -1 and set @@ -507,21 +507,24 @@ typedef struct { </func> <func> <name><ret>int</ret><nametext>erl_unpublish(alive)</nametext></name> - <fsummary>Unpublish a node name</fsummary> + <fsummary>Forcefully unpublish a node name</fsummary> <type> <v>char *alive;</v> </type> <desc> - <p>This function can be called by a process to unregister a - specified node name from epmd on the localhost. This may be - useful, for example, when epmd has not detected the failure of a - node, and will not allow the name to be reused. If you use this - function to unregister your own process, be sure to also close - the descriptor that was returned by <c><![CDATA[erl_publish()]]></c>.</p> - <note> - <p>Careless use of this function may have unpredictable - results, if the registered node is in fact still running.</p> - </note> + <p>This function can be called by a process to unregister a + specified node from epmd on the localhost. This is however usually not + allowed, unless epmd was started with the -relaxed_command_check + flag, which it normally isn't.</p> + + <p>To unregister a node you have published, you should instead + close the descriptor that was returned by + <c><![CDATA[ei_publish()]]></c>.</p> + + <warning> + <p>This function is deprecated and will be removed in a future + release.</p> + </warning> <p><c><![CDATA[alive]]></c> is the name of the node to unregister, i.e., the first component of the nodename, without the <c><![CDATA[@hostname]]></c>.</p> <p>If the node was successfully unregistered from epmd, the diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml index 14aec4a4d9..de5ba61938 100644 --- a/lib/erl_interface/doc/src/notes.xml +++ b/lib/erl_interface/doc/src/notes.xml @@ -30,6 +30,163 @@ </header> <p>This document describes the changes made to the Erl_interface application.</p> +<section><title>Erl_Interface 3.7.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + erl_call: remove get_hostent</p> + <p> + get_hostent does not properly handle IPv4 addresses on + little endian platforms and fails with hostnames + beginning with a number. Remove get_hostent and use + ei_gethostbyname directly since gethostbyname supports + IPv4 addresses.</p> + <p> + (Thanks to Michael Santos)</p> + <p> + Own Id: OTP-8890</p> + </item> + <item> + <p> teach ei_x_format to handle unary - and + (Thanks to + Steve Vinoski)</p> + <p> + Own Id: OTP-8891</p> + </item> + <item> + <p>Fix zero byte allocation in registry. (Thanks to + Michael Santos)</p> + <p> + Own Id: OTP-8893</p> + </item> + <item> + <p> Check the length of the node name to prevent an + overflow. Memory error control of ei_alloc_big. (Thanks + to Michael Santos) </p> + <p> + Own Id: OTP-8943</p> + </item> + <item> + <p> + erl_term_len() in erl_interface could returned too large + values for integers (since R14B) and too small values for + refs (since R9B).</p> + <p> + Own Id: OTP-8945</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.7.1.1</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The <c>erl_interface</c> tracelevel for erlang messages was incorrect. This has now been fixed. + </p> + <p> + Own Id: OTP-8874</p> + </item> + </list> + </section> + +</section> +<section><title>Erl_Interface 3.7.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Removed unused variable in <c>ei_decode_term.c</c>.</p> + <p> + Fixed faulty deallocation in <c>erl_call</c>.</p> + <p> + Own Id: OTP-8748</p> + </item> + <item> + <p>ei_connect: correct man page examples (Thanks to + Michael Santos)</p> + <p> + Own Id: OTP-8813</p> + </item> + <item> + <p>ei: prevent overflow in <c>ei_connect_init</c> and + <c>ei_xconnect</c></p> <p>Add length check of the buffer + before copying. (Thanks to Michael Santos)</p> + <p> + Own Id: OTP-8814</p> + </item> + <item> + <p>Remove DECLSPEC feature which fails on Windows Vista + and use the fallback implementation instead.</p> + <p> + Own Id: OTP-8826</p> + </item> + <item> + <p>erl_call: fix multiple buffer overflows (Thanks to + Michael Santos)</p> + <p> + Own Id: OTP-8827</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Fix incorrect writev iovec buffer handling in + <c>erl_interface</c> (Thanks to Steve Vinoski)</p> + <p> + Own Id: OTP-8837</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Interface 3.7</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>compact IEEE 754 double encoding in external binary + format for ei</p> <list><item><p>Implement the compact + IEEE 754 double encoding in external binary format for + ei. Encoding for ei now always produces the NEW_FLOAT_EXT + format. Decoding and term printing handle both the old + ERL_FLOAT_EXT encoding and the new NEW_FLOAT_EXT + encoding. </p></item> <item><p>Legacy erl_interface code + also handles the new encoding, but still produces the + ERL_FLOAT_EXT encoding by default.</p></item> + <item><p>Also enable the DFLAG_NEW_FLOATS distribution + flag.</p></item> <item><p>ei_get_type() will return + ERL_FLOAT_EXT regardless if the external format is + encoded with ERL_FLOAT_EXT or NEW_FLOAT_EXT for + doubles.</p></item> <item><p>Reduce the number of copies + of the code for encoding and decoding doubles throughout + ei and erl_interface by instead calling the ei encoding + and decoding functions wherever possible.</p></item> + <item><p>Restore commented-out float tests in + ei_decode_SUITE and ei_encode_SUITE in + lib/erl_interface/test. Modify them to make them match + the style of other tests in the same suites.</p></item> + </list> <p>These changes are based on an ei float patch + from Serge Aleynikov originally submitted against R12B-2 + in July 2008 and reworked by Steve Vinoski May 2010.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-8684</p> + </item> + </list> + </section> + +</section> + <section><title>Erl_Interface 3.6.5</title> <section><title>Improvements and New Features</title> diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h index d1a697615a..ae815b414a 100644 --- a/lib/erl_interface/include/ei.h +++ b/lib/erl_interface/include/ei.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. 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_H @@ -80,21 +80,24 @@ #define ERL_NO_TIMEOUT -1 /* these are the control message types */ -#define ERL_LINK 1 -#define ERL_SEND 2 -#define ERL_EXIT 3 -#define ERL_UNLINK 4 -#define ERL_NODE_LINK 5 -#define ERL_REG_SEND 6 -#define ERL_GROUP_LEADER 7 -#define ERL_EXIT2 8 -#define ERL_PASS_THROUGH 'p' +#define ERL_LINK 1 +#define ERL_SEND 2 +#define ERL_EXIT 3 +#define ERL_UNLINK 4 +#define ERL_NODE_LINK 5 +#define ERL_REG_SEND 6 +#define ERL_GROUP_LEADER 7 +#define ERL_EXIT2 8 +#define ERL_PASS_THROUGH 'p' /* new ones for tracing, from Kenneth */ -#define ERL_SEND_TT 12 -#define ERL_EXIT_TT 13 -#define ERL_REG_SEND_TT 16 -#define ERL_EXIT2_TT 18 +#define ERL_SEND_TT 12 +#define ERL_EXIT_TT 13 +#define ERL_REG_SEND_TT 16 +#define ERL_EXIT2_TT 18 +#define ERL_MONITOR_P 19 +#define ERL_DEMONITOR_P 20 +#define ERL_MONITOR_P_EXIT 21 /* -------------------------------------------------------------------- */ @@ -110,6 +113,7 @@ #define ERL_SMALL_INTEGER_EXT 'a' #define ERL_INTEGER_EXT 'b' #define ERL_FLOAT_EXT 'c' +#define NEW_FLOAT_EXT 'F' #define ERL_ATOM_EXT 'd' #define ERL_REFERENCE_EXT 'e' #define ERL_NEW_REFERENCE_EXT 'r' @@ -718,11 +722,9 @@ int ei_x_encode_bignum(ei_x_buff *x, mpz_t obj); #define EI_LONGLONG __int64 #define EI_ULONGLONG unsigned __int64 #else -#ifndef VXWORKS #define EI_LONGLONG long long #define EI_ULONGLONG unsigned long long #endif -#endif #ifndef VXWORKS int ei_decode_longlong(const char *buf, int *index, EI_LONGLONG *p); diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c index d2d0a7e7c1..6dc6ebb348 100644 --- a/lib/erl_interface/src/connect/ei_connect.c +++ b/lib/erl_interface/src/connect/ei_connect.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2000-2010. 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% */ /* @@ -366,16 +366,16 @@ static int initWinSock(void) WORD wVersionRequested; WSADATA wsaData; int i; - /* FIXME problem for threaded ? */ - static int initialized = 0; + + static LONG volatile initialized = 0; wVersionRequested = MAKEWORD(1, 1); - if (!initialized) { - initialized = 1; + if (InterlockedCompareExchange((LPLONG) &initialized,1L,0L) == 0L) { /* FIXME not terminate, just a message?! */ if ((i = WSAStartup(wVersionRequested, &wsaData))) { EI_TRACE_ERR1("ei_connect_init", "ERROR: can't initialize windows sockets: %d",i); + initialized = 2L; return 0; } @@ -383,10 +383,14 @@ static int initWinSock(void) EI_TRACE_ERR0("initWinSock","ERROR: this version of windows " "sockets not supported"); WSACleanup(); + initialized = 2L; return 0; } + initialized = 3L; + } else while (initialized < 2) { + SwitchToThread(); } - return 1; + return (int) (initialized - 2); } #endif @@ -502,10 +506,14 @@ int ei_connect_init(ei_cnode* ec, const char* this_node_name, return ERL_ERROR; } - if (this_node_name == NULL) + if (this_node_name == NULL) { sprintf(thisalivename, "c%d", (int) getpid()); - else + } else if (strlen(this_node_name) >= sizeof(thisalivename)) { + EI_TRACE_ERR0("ei_connect_init","ERROR: this_node_name too long"); + return ERL_ERROR; + } else { strcpy(thisalivename, this_node_name); + } if ((hp = ei_gethostbyname(thishostname)) == 0) { /* Looking up IP given hostname fails. We must be on a standalone @@ -930,7 +938,7 @@ int ei_do_receive_msg(int fd, int staticbuffer_p, return ERL_ERROR; } x->index = x->buffsz; - switch (msg->msgtype) { /* FIXME are these all? */ + switch (msg->msgtype) { /* FIXME does not handle trace tokens and monitors */ case ERL_SEND: case ERL_REG_SEND: case ERL_LINK: @@ -938,7 +946,6 @@ int ei_do_receive_msg(int fd, int staticbuffer_p, case ERL_GROUP_LEADER: case ERL_EXIT: case ERL_EXIT2: - case ERL_NODE_LINK: return ERL_MSG; default: @@ -1321,9 +1328,11 @@ static int send_name_or_challenge(int fd, char *nodename, put8(s, 'n'); put16be(s, version); put32be(s, (DFLAG_EXTENDED_REFERENCES + | DFLAG_DIST_MONITOR | DFLAG_EXTENDED_PIDS_PORTS | DFLAG_FUN_TAGS - | DFLAG_NEW_FUN_TAGS)); + | DFLAG_NEW_FUN_TAGS + | DFLAG_NEW_FLOATS)); if (f_chall) put32be(s, challenge); memcpy(s, nodename, strlen(nodename)); @@ -1393,6 +1402,11 @@ static int recv_challenge(int fd, unsigned *challenge, goto error; } + if (!(*flags & DFLAG_NEW_FLOATS)) { + EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE peer cannot " + "handle binary float encoding"); + goto error; + } if (getpeername(fd, (struct sockaddr *) &sin, &sin_len) < 0) { EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE can't get peername"); diff --git a/lib/erl_interface/src/connect/ei_connect_int.h b/lib/erl_interface/src/connect/ei_connect_int.h index 9926f799df..3c42b49b82 100644 --- a/lib/erl_interface/src/connect/ei_connect_int.h +++ b/lib/erl_interface/src/connect/ei_connect_int.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2001-2010. 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% */ /* @@ -101,6 +101,7 @@ extern int h_errno; #define DFLAG_FUN_TAGS 16 #define DFLAG_NEW_FUN_TAGS 0x80 #define DFLAG_EXTENDED_PIDS_PORTS 0x100 +#define DFLAG_NEW_FLOATS 0x800 ei_cnode *ei_fd_to_cnode(int fd); int ei_distversion(int fd); diff --git a/lib/erl_interface/src/connect/ei_resolve.c b/lib/erl_interface/src/connect/ei_resolve.c index 42aeab22b1..24a030c468 100644 --- a/lib/erl_interface/src/connect/ei_resolve.c +++ b/lib/erl_interface/src/connect/ei_resolve.c @@ -601,7 +601,7 @@ struct hostent *ei_gethostbyaddr_r(const char *addr, #ifndef HAVE_GETHOSTBYNAME_R return my_gethostbyaddr_r(addr,length,type,hostp,buffer,buflen,h_errnop); #else -#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000)) +#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__)) struct hostent *result; gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, &result, @@ -628,7 +628,7 @@ struct hostent *ei_gethostbyname_r(const char *name, #ifndef HAVE_GETHOSTBYNAME_R return my_gethostbyname_r(name,hostp,buffer,buflen,h_errnop); #else -#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000)) +#if (defined(__GLIBC__) || (__FreeBSD_version >= 602000) || defined(__DragonFly__)) struct hostent *result; gethostbyname_r(name, hostp, buffer, buflen, &result, h_errnop); diff --git a/lib/erl_interface/src/connect/eirecv.c b/lib/erl_interface/src/connect/eirecv.c index 51fc32d65c..86852f947d 100644 --- a/lib/erl_interface/src/connect/eirecv.c +++ b/lib/erl_interface/src/connect/eirecv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * Copyright Ericsson AB 1998-2010. 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 @@ -107,7 +107,7 @@ ei_recv_internal (int fd, switch (msg->msgtype) { case ERL_SEND: /* { SEND, Cookie, ToPid } */ - if (ei_tracelevel > 0) show_this_msg = 1; + if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_atom(header,&index,msg->cookie) || ei_decode_pid(header,&index,&msg->to)) { @@ -118,7 +118,7 @@ ei_recv_internal (int fd, break; case ERL_REG_SEND: /* { REG_SEND, From, Cookie, ToName } */ - if (ei_tracelevel > 0) show_this_msg = 1; + if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_atom(header,&index,msg->cookie) || ei_decode_atom(header,&index,msg->toname)) @@ -133,7 +133,7 @@ ei_recv_internal (int fd, case ERL_LINK: /* { LINK, From, To } */ case ERL_UNLINK: /* { UNLINK, From, To } */ case ERL_GROUP_LEADER: /* { GROUP_LEADER, From, To } */ - if (ei_tracelevel > 1) show_this_msg = 1; + if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_pid(header,&index,&msg->to)) { @@ -145,7 +145,7 @@ ei_recv_internal (int fd, case ERL_EXIT: /* { EXIT, From, To, Reason } */ case ERL_EXIT2: /* { EXIT2, From, To, Reason } */ - if (ei_tracelevel > 1) show_this_msg = 1; + if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_pid(header,&index,&msg->to)) { @@ -156,7 +156,7 @@ ei_recv_internal (int fd, break; case ERL_SEND_TT: /* { SEND_TT, Cookie, ToPid, TraceToken } */ - if (ei_tracelevel > 0) show_this_msg = 1; + if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_atom(header,&index,msg->cookie) || ei_decode_pid(header,&index,&msg->to) || ei_decode_trace(header,&index,&msg->token)) @@ -169,7 +169,7 @@ ei_recv_internal (int fd, break; case ERL_REG_SEND_TT: /* { REG_SEND_TT, From, Cookie, ToName, TraceToken } */ - if (ei_tracelevel > 0) show_this_msg = 1; + if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_atom(header,&index,msg->cookie) || ei_decode_atom(header,&index,msg->toname) @@ -184,7 +184,7 @@ ei_recv_internal (int fd, case ERL_EXIT_TT: /* { EXIT_TT, From, To, TraceToken, Reason } */ case ERL_EXIT2_TT: /* { EXIT2_TT, From, To, TraceToken, Reason } */ - if (ei_tracelevel > 1) show_this_msg = 1; + if (ei_tracelevel >= 4) show_this_msg = 1; if (ei_decode_pid(header,&index,&msg->from) || ei_decode_pid(header,&index,&msg->to) || ei_decode_trace(header,&index,&msg->token)) @@ -196,10 +196,6 @@ ei_recv_internal (int fd, ei_trace(1,&msg->token); /* turn on tracing */ break; - case ERL_NODE_LINK: /* { NODE_LINK } */ - if (ei_tracelevel > 1) show_this_msg = 1; - break; - default: /* unknown type, just put any remaining bytes into buffer */ break; diff --git a/lib/erl_interface/src/connect/send.c b/lib/erl_interface/src/connect/send.c index cd832db4ea..57e32903cf 100644 --- a/lib/erl_interface/src/connect/send.c +++ b/lib/erl_interface/src/connect/send.c @@ -87,8 +87,7 @@ int ei_send_encoded_tmo(int fd, const erlang_pid *to, put8(s, ERL_PASS_THROUGH); /* 1 */ /*** sum: 1070 */ - /* FIXME incorrect level */ - if (ei_tracelevel > 0) + if (ei_tracelevel >= 4) ei_show_sendmsg(stderr,header,msg); #ifdef HAVE_WRITEV diff --git a/lib/erl_interface/src/connect/send_exit.c b/lib/erl_interface/src/connect/send_exit.c index 098797c96d..d4e6605a2c 100644 --- a/lib/erl_interface/src/connect/send_exit.c +++ b/lib/erl_interface/src/connect/send_exit.c @@ -88,8 +88,7 @@ int ei_send_exit_tmo(int fd, const erlang_pid *from, const erlang_pid *to, put32be(s, index - 4); /* 4 */ put8(s, ERL_PASS_THROUGH); /* 1 */ /*** sum: len + 1080 */ - /* FIXME incorrect level */ - if (ei_tracelevel > 1) + if (ei_tracelevel >= 4) ei_show_sendmsg(stderr,msgbuf,NULL); ei_write_fill_t(fd,msgbuf,index,ms); diff --git a/lib/erl_interface/src/connect/send_reg.c b/lib/erl_interface/src/connect/send_reg.c index 8f0e40309c..779b1b8359 100644 --- a/lib/erl_interface/src/connect/send_reg.c +++ b/lib/erl_interface/src/connect/send_reg.c @@ -82,8 +82,7 @@ int ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, put32be(s, index + msglen - 4); /* 4 */ put8(s, ERL_PASS_THROUGH); /* 1 */ /*** sum: 1336 */ - /* FIXME incorrect level.... */ - if (ei_tracelevel > 0) + if (ei_tracelevel >= 4) ei_show_sendmsg(stderr,header,msg); #ifdef HAVE_WRITEV diff --git a/lib/erl_interface/src/decode/decode_big.c b/lib/erl_interface/src/decode/decode_big.c index efe9c6e5d9..b5e9b45a3b 100644 --- a/lib/erl_interface/src/decode/decode_big.c +++ b/lib/erl_interface/src/decode/decode_big.c @@ -74,7 +74,7 @@ erlang_big *ei_alloc_big(unsigned int digit_bytes) { memset(b,(char)0,sizeof(erlang_big)); if ( (b->digits = malloc(2*n)) == NULL) { free(b); - return 0; + return NULL; } b->arity = digit_bytes; diff --git a/lib/erl_interface/src/decode/decode_double.c b/lib/erl_interface/src/decode/decode_double.c index 66dbe474ec..ed6e39655e 100644 --- a/lib/erl_interface/src/decode/decode_double.c +++ b/lib/erl_interface/src/decode/decode_double.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. 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> @@ -26,14 +26,22 @@ int ei_decode_double(const char *buf, int *index, double *p) { const char *s = buf + *index; const char *s0 = s; - double f; + FloatExt f; - if (get8(s) != ERL_FLOAT_EXT) return -1; - - if (sscanf(s, "%lf", &f) != 1) return -1; + switch (get8(s)) { + case ERL_FLOAT_EXT: + if (sscanf(s, "%lf", &f.d) != 1) return -1; + s += 31; + break; + case NEW_FLOAT_EXT: + /* IEEE 754 format */ + f.val = get64be(s); + break; + default: + return -1; + } - s += 31; - if (p) *p = f; + if (p) *p = f.d; *index += s-s0; return 0; } diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c index 316b5bee98..f6c5d861ab 100644 --- a/lib/erl_interface/src/decode/decode_skip.c +++ b/lib/erl_interface/src/decode/decode_skip.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2002-2010. 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" @@ -77,6 +77,7 @@ int ei_skip_term(const char* buf, int* index) if (ei_decode_big(buf, index, NULL) < 0) return -1; break; case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: if (ei_decode_double(buf, index, NULL) < 0) return -1; break; case ERL_FUN_EXT: diff --git a/lib/erl_interface/src/encode/encode_double.c b/lib/erl_interface/src/encode/encode_double.c index 53f3d52ba6..148a49f73a 100644 --- a/lib/erl_interface/src/encode/encode_double.c +++ b/lib/erl_interface/src/encode/encode_double.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. 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> @@ -27,13 +27,13 @@ int ei_encode_double(char *buf, int *index, double p) char *s = buf + *index; char *s0 = s; - if (!buf) s ++; + if (!buf) + s += 9; else { - put8(s,ERL_FLOAT_EXT); - memset(s, 0, 31); - sprintf(s, "%.20e", p); + /* IEEE 754 format */ + put8(s, NEW_FLOAT_EXT); + put64be(s, ((FloatExt*)&p)->val); } - s += 31; *index += s-s0; diff --git a/lib/erl_interface/src/epmd/ei_epmd.h b/lib/erl_interface/src/epmd/ei_epmd.h index 40e5ece572..ccacfed244 100644 --- a/lib/erl_interface/src/epmd/ei_epmd.h +++ b/lib/erl_interface/src/epmd/ei_epmd.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * Copyright Ericsson AB 1998-2010. 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 @@ -40,20 +40,13 @@ #define EI_MYPROTO 0 /* tcp/ip */ #endif -/* epmd r3 protocol */ -#ifndef EI_EPMD_ALIVE_REQ -#define EI_EPMD_ALIVE_REQ 'a' -#define EI_EPMD_ALIVE_OK_RESP 'Y' -#define EI_EPMD_PORT_REQ 'p' -#define EI_EPMD_STOP_REQ 's' -#endif - /* epmd r4 */ #ifndef EI_EPMD_ALIVE2_REQ #define EI_EPMD_ALIVE2_REQ 120 #define EI_EPMD_ALIVE2_RESP 121 #define EI_EPMD_PORT2_REQ 122 #define EI_EPMD_PORT2_RESP 119 +#define EI_EPMD_STOP_REQ 's' #endif /* internal functions */ diff --git a/lib/erl_interface/src/epmd/epmd_port.c b/lib/erl_interface/src/epmd/epmd_port.c index 663b38d2d4..698c75c217 100644 --- a/lib/erl_interface/src/epmd/epmd_port.c +++ b/lib/erl_interface/src/epmd/epmd_port.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * Copyright Ericsson AB 1998-2010. 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 @@ -92,64 +92,6 @@ int ei_epmd_connect_tmo(struct in_addr *inaddr, unsigned ms) return sd; } -/* get the given node's listen port using old epmd protocol */ -static int ei_epmd_r3_port (struct in_addr *addr, const char *alive, - unsigned ms) -{ - char buf[EPMDBUF]; - char *s = buf; - int len = strlen(alive) + 1; - int fd; - int port; - int res; -#if defined(VXWORKS) - char ntoabuf[32]; -#endif - - put16be(s,len); - put8(s,EI_EPMD_PORT_REQ); - strcpy(s,alive); - - /* connect to epmd */ - if ((fd = ei_epmd_connect_tmo(addr,ms)) < 0) - { - /* ei_epmd_connect_tmo() sets erl_errno */ - return -1; - } - - if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) { - closesocket(fd); - erl_errno = (res == -2) ? ETIMEDOUT : EIO; - return -1; - } - -#ifdef VXWORKS - /* FIXME use union/macro for level. Correct level? */ - if (ei_tracelevel > 2) { - inet_ntoa_b(*addr,ntoabuf); - EI_TRACE_CONN2("ei_epmd_r3_port", - "-> PORT_REQ alive=%s ip=%s",alive,ntoabuf); - } -#else - EI_TRACE_CONN2("ei_epmd_r3_port", - "-> PORT_REQ alive=%s ip=%s",alive,inet_ntoa(*addr)); -#endif - - if ((res = ei_read_fill_t(fd, buf, 2, ms)) != 2) { - EI_TRACE_ERR0("ei_epmd_r3_port","<- CLOSE"); - closesocket(fd); - erl_errno = (res == -2) ? ETIMEDOUT : EIO; - return -1; - } - closesocket(fd); - s = buf; - port = get16be(s); - - EI_TRACE_CONN1("ei_epmd_r3_port","<- PORT_RESP port=%d",port); - - return port; -} - static int ei_epmd_r4_port (struct in_addr *addr, const char *alive, int *dist, unsigned ms) { @@ -164,6 +106,12 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive, #if defined(VXWORKS) char ntoabuf[32]; #endif + + if (len > sizeof(buf) - 3) + { + erl_errno = ERANGE; + return -1; + } put16be(s,len); put8(s,EI_EPMD_PORT2_REQ); @@ -285,15 +233,6 @@ int ei_epmd_port_tmo (struct in_addr *addr, const char *alive, int *dist, { int i; - /* try the new one first, then the old one */ - i = ei_epmd_r4_port(addr,alive,dist,ms); - - /* -2: new protocol not understood */ - if (i == -2) { - *dist = 0; - i = ei_epmd_r3_port(addr,alive,ms); - } - - return i; + return ei_epmd_r4_port(addr,alive,dist,ms); } diff --git a/lib/erl_interface/src/epmd/epmd_publish.c b/lib/erl_interface/src/epmd/epmd_publish.c index 09b3dce43b..d45fe644c0 100644 --- a/lib/erl_interface/src/epmd/epmd_publish.c +++ b/lib/erl_interface/src/epmd/epmd_publish.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. + * Copyright Ericsson AB 1998-2010. 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 @@ -55,62 +55,6 @@ /* publish our listen port and alive name */ /* return the (useless) creation number */ -static int ei_epmd_r3_publish (int port, const char *alive, unsigned ms) -{ - char buf[EPMDBUF]; - char *s = buf; - int fd; - int len = strlen(alive) + 3; - int res,creation; - - s = buf; - put16be(s,len); - put8(s,EI_EPMD_ALIVE_REQ); - put16be(s,port); - strcpy(s, alive); - - if ((fd = ei_epmd_connect_tmo(NULL,ms)) < 0) return fd; - - if ((res = ei_write_fill_t(fd, buf, len+2, ms)) != len+2) { - closesocket(fd); - erl_errno = (res == -2) ? ETIMEDOUT : EIO; - return -1; - } - - EI_TRACE_CONN2("ei_epmd_r3_publish", - "-> ALIVE_REQ alive=%s port=%d",alive,port); - - if ((res = ei_read_fill_t(fd, buf, 3, ms)) != 3) { - closesocket(fd); - erl_errno = (res == -2) ? ETIMEDOUT : EIO; - return -1; - } - - s = buf; - if ((res=get8(s)) != EI_EPMD_ALIVE_OK_RESP) { - EI_TRACE_ERR1("ei_epmd_r3_publish", - "<- ALIVE_NOK result=%d (failure)",res); - closesocket(fd); - erl_errno = EIO; - return -1; - } - - creation = get16be(s); - - EI_TRACE_CONN1("ei_epmd_r3_publish","<- ALIVE_OK creation=%d",creation); - - /* Don't close fd here! It keeps us registered with epmd */ - - /* probably should save fd so we can close it later... */ - /* epmd_saveconn(OPEN,fd,alive); */ - - /* return the creation number, for no good reason */ - /* return creation; */ - - /* no! return the descriptor */ - return fd; -} - /* publish our listen port and alive name */ /* return the (useless) creation number */ /* this protocol is a lot more complex than the old one */ @@ -125,6 +69,12 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms) int n; int res, creation; + if (len > sizeof(buf)-2) + { + erl_errno = ERANGE; + return -1; + } + s = buf; put16be(s,len); @@ -200,15 +150,7 @@ int ei_epmd_publish(int port, const char *alive) int ei_epmd_publish_tmo(int port, const char *alive, unsigned ms) { - int i; - - /* try the new one first, then the old one */ - i = ei_epmd_r4_publish(port,alive, ms); - - /* -2: new protocol not understood */ - if (i == -2) i = ei_epmd_r3_publish(port,alive, ms); - - return i; + return ei_epmd_r4_publish(port,alive, ms);; } diff --git a/lib/erl_interface/src/epmd/epmd_unpublish.c b/lib/erl_interface/src/epmd/epmd_unpublish.c index 08662fe1ec..495cbab44c 100644 --- a/lib/erl_interface/src/epmd/epmd_unpublish.c +++ b/lib/erl_interface/src/epmd/epmd_unpublish.c @@ -59,6 +59,11 @@ int ei_unpublish_tmo(const char *alive, unsigned ms) int len = 1 + strlen(alive); int fd, res; + if (len > sizeof(buf)-3) { + erl_errno = ERANGE; + return -1; + } + put16be(s,len); put8(s,EI_EPMD_STOP_REQ); strcpy(s, alive); diff --git a/lib/erl_interface/src/legacy/decode_term.c b/lib/erl_interface/src/legacy/decode_term.c index ef29d6f57d..796cebdfef 100644 --- a/lib/erl_interface/src/legacy/decode_term.c +++ b/lib/erl_interface/src/legacy/decode_term.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. 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" @@ -59,6 +59,7 @@ int ei_decode_term(const char *buf, int *index, void *t) return ei_decode_long(buf,index,NULL); case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: return ei_decode_double(buf,index,NULL); case ERL_ATOM_EXT: diff --git a/lib/erl_interface/src/legacy/erl_marshal.c b/lib/erl_interface/src/legacy/erl_marshal.c index 4b5f28178f..70949a7adf 100644 --- a/lib/erl_interface/src/legacy/erl_marshal.c +++ b/lib/erl_interface/src/legacy/erl_marshal.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1996-2010. 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% */ /* @@ -26,6 +26,7 @@ #include <ctype.h> #include <sys/types.h> #include <string.h> +#include <limits.h> #include "erl_interface.h" #include "erl_marshal.h" @@ -102,6 +103,7 @@ void erl_init_marshal(void) cmp_array[ERL_SMALL_INTEGER_EXT] = 1; cmp_array[ERL_INTEGER_EXT] = 1; cmp_array[ERL_FLOAT_EXT] = 1; + cmp_array[NEW_FLOAT_EXT] = 1; cmp_array[ERL_SMALL_BIG_EXT] = 1; cmp_array[ERL_LARGE_BIG_EXT] = 1; cmp_array[ERL_ATOM_EXT] = 2; @@ -124,6 +126,7 @@ void erl_init_marshal(void) cmp_num_class[ERL_SMALL_INTEGER_EXT] = SMALL; cmp_num_class[ERL_INTEGER_EXT] = SMALL; cmp_num_class[ERL_FLOAT_EXT] = FLOAT; + cmp_num_class[NEW_FLOAT_EXT] = FLOAT; cmp_num_class[ERL_SMALL_BIG_EXT] = BIG; cmp_num_class[ERL_LARGE_BIG_EXT] = BIG; init_cmp_num_class_p = 0; @@ -176,26 +179,14 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) return 0; case ERL_INTEGER: - i = ep->uval.ival.i; - /* ERL_SMALL_BIG */ - if ((i > ERL_MAX) || (i < ERL_MIN)) { - *(*ext)++ = ERL_SMALL_BIG_EXT; - *(*ext)++ = 4; /* four bytes */ - if ((*(*ext)++ = ((i>>31) & 0x01))) /* sign byte */ - i = -i; - *(*ext)++ = i & 0xff; /* LSB first */ - *(*ext)++ = (i >> 8) & 0xff; - *(*ext)++ = (i >> 16) & 0xff; - *(*ext)++ = (i >> 24) & 0x7f; /* Don't include the sign bit */ - return 0; - } + i = ep->uval.ival.i; /* SMALL_INTEGER */ if ((i < 256) && (i >= 0)) { *(*ext)++ = ERL_SMALL_INTEGER_EXT; *(*ext)++ = i & 0xff; return 0; } - /* INTEGER */ + /* R14B: Use all 32 bits of INTEGER_EXT */ *(*ext)++ = ERL_INTEGER_EXT; *(*ext)++ = (i >> 24) & 0xff; *(*ext)++ = (i >> 16) & 0xff; @@ -206,23 +197,23 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) case ERL_U_INTEGER: u = ep->uval.uival.u; /* ERL_U_SMALL_BIG */ - if (u > ERL_MAX) { - *(*ext)++ = ERL_SMALL_BIG_EXT; - *(*ext)++ = 4; /* four bytes */ - *(*ext)++ = 0; /* sign byte */ - *(*ext)++ = u & 0xff; /* LSB first */ - *(*ext)++ = (u >> 8) & 0xff; - *(*ext)++ = (u >> 16) & 0xff; - *(*ext)++ = (u >> 24) & 0xff; - return 0; + if ((int)u < 0) { + *(*ext)++ = ERL_SMALL_BIG_EXT; + *(*ext)++ = 4; /* four bytes */ + *(*ext)++ = 0; /* sign byte */ + *(*ext)++ = u & 0xff; /* LSB first */ + *(*ext)++ = (u >> 8) & 0xff; + *(*ext)++ = (u >> 16) & 0xff; + *(*ext)++ = (u >> 24) & 0xff; + return 0; } /* SMALL_INTEGER */ - if ((u < 256) && (u >= 0)) { + if (u < 256) { *(*ext)++ = ERL_SMALL_INTEGER_EXT; *(*ext)++ = u & 0xff; return 0; } - /* INTEGER */ + /* R14B: Use all 32 bits of INTEGER_EXT */ *(*ext)++ = ERL_INTEGER_EXT; *(*ext)++ = (u >> 24) & 0xff; *(*ext)++ = (u >> 16) & 0xff; @@ -232,29 +223,28 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) case ERL_LONGLONG: l = ep->uval.llval.i; /* ERL_SMALL_BIG */ - if ((l > ((long long) ERL_MAX)) || - (l < ((long long) ERL_MIN))) { - *(*ext)++ = ERL_SMALL_BIG_EXT; - *(*ext)++ = 8; /* eight bytes */ - if ((*(*ext)++ = ((l>>63) & 0x01))) /* sign byte */ + if (l > ((long long) INT_MAX) || l < ((long long) INT_MIN)) { + *(*ext)++ = ERL_SMALL_BIG_EXT; + *(*ext)++ = 8; + if ((*(*ext)++ = (l<0))) /* sign byte */ l = -l; - *(*ext)++ = l & 0xff; /* LSB first */ + *(*ext)++ = l & 0xff; /* LSB first */ *(*ext)++ = (l >> 8) & 0xff; *(*ext)++ = (l >> 16) & 0xff; - *(*ext)++ = (l >> 24) & 0xff; - *(*ext)++ = (l >> 32) & 0xff; - *(*ext)++ = (l >> 40) & 0xff; - *(*ext)++ = (l >> 48) & 0xff; - *(*ext)++ = (l >> 56) & 0x7f; /* Don't include the sign bit */ + *(*ext)++ = (l >> 24) & 0xff; + *(*ext)++ = (l >> 32) & 0xff; + *(*ext)++ = (l >> 40) & 0xff; + *(*ext)++ = (l >> 48) & 0xff; + *(*ext)++ = (l >> 56) & 0xff; return 0; } /* SMALL_INTEGER */ if ((l < 256) && (l >= 0)) { - *(*ext)++ = ERL_SMALL_INTEGER_EXT; - *(*ext)++ = l & 0xff; - return 0; + *(*ext)++ = ERL_SMALL_INTEGER_EXT; + *(*ext)++ = l & 0xff; + return 0; } - /* INTEGER */ + /* R14B: Use all 32 bits of INTEGER_EXT */ *(*ext)++ = ERL_INTEGER_EXT; *(*ext)++ = (l >> 24) & 0xff; *(*ext)++ = (l >> 16) & 0xff; @@ -265,7 +255,7 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) case ERL_U_LONGLONG: ul = ep->uval.ullval.u; /* ERL_U_SMALL_BIG */ - if (ul > ((unsigned long long) ERL_MAX)) { + if (ul > ((unsigned long long) INT_MAX)) { *(*ext)++ = ERL_SMALL_BIG_EXT; *(*ext)++ = 8; /* eight bytes */ *(*ext)++ = 0; /* sign byte */ @@ -285,7 +275,7 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) *(*ext)++ = ul & 0xff; return 0; } - /* INTEGER */ + /* R14B: Use all 32 bits of INTEGER_EXT */ *(*ext)++ = ERL_INTEGER_EXT; *(*ext)++ = (ul >> 24) & 0xff; *(*ext)++ = (ul >> 16) & 0xff; @@ -521,29 +511,28 @@ static int erl_term_len_helper(ETERM *ep, int dist) case ERL_INTEGER: i = ep->uval.ival.i; - if ((i > ERL_MAX) || (i < ERL_MIN)) len = 7; - else if ((i < 256) && (i >= 0)) len = 2; + if ((i < 256) && (i >= 0)) len = 2; else len = 5; break; case ERL_U_INTEGER: u = ep->uval.uival.u; - if (u > ERL_MAX) len = 7; + if ((int)u < 0) len = 7; else if (u < 256) len = 2; else len = 5; break; case ERL_LONGLONG: l = ep->uval.llval.i; - if ((l > ((long long) ERL_MAX)) || - (l < ((long long) ERL_MIN))) len = 11; + if ((l > ((long long) INT_MAX)) || + (l < ((long long) INT_MIN))) len = 11; else if ((l < 256) && (l >= 0)) len = 2; else len = 5; break; case ERL_U_LONGLONG: ul = ep->uval.ullval.u; - if (ul > ((unsigned long long) ERL_MAX)) len = 11; + if (ul > ((unsigned long long) INT_MAX)) len = 11; else if (ul < 256) len = 2; else len = 5; break; @@ -556,12 +545,7 @@ static int erl_term_len_helper(ETERM *ep, int dist) case ERL_REF: i = strlen((char *)ERL_REF_NODE(ep)); - if (dist >= 4 && ERL_REF_LEN(ep) > 1) { - len = 1 + 2 + (i+3) + 1 + ERL_REF_LEN(ep) * 4; - } else { - /* 1 + N + 4 + 1 where N = 3 + strlen */ - len = 9 + i; - } + len = 1 + 2 + (i+3) + 1 + ERL_REF_LEN(ep) * 4; break; case ERL_PORT: @@ -730,11 +714,6 @@ static ETERM *erl_decode_it(unsigned char **ext) if (arity > 8) goto big_truncate; - if (arity == 8 && ((*ext)[7] & 0x80) && sign) { - /* MSB already occupied ! */ - goto big_truncate; - } - if (arity == 4 && ((*ext)[3] & 0x80) && !sign) { /* It will fit into an unsigned int !! */ u = (((*ext)[3] << 24)|((*ext)[2])<< 16|((*ext)[1]) << 8 |(**ext)); @@ -745,14 +724,10 @@ static ETERM *erl_decode_it(unsigned char **ext) return ep; } else if (arity == 4 && !((*ext)[3] & 0x80)) { /* It will fit into an int !! - * Note: It comes in "one's-complement notation" */ - if (sign) - i = (int) (~(((*ext)[3] << 24) | ((*ext)[2])<< 16 | - ((*ext)[1]) << 8 | (**ext)) | (unsigned int) sign); - else - i = (int) (((*ext)[3] << 24) | ((*ext)[2])<< 16 | - ((*ext)[1]) << 8 | (**ext)); + i = (int) (((*ext)[3] << 24) | ((*ext)[2])<< 16 | + ((*ext)[1]) << 8 | (**ext)); + if (sign) i = -i; ERL_TYPE(ep) = ERL_INTEGER; ep->uval.ival.i = i; *ext += arity; @@ -778,8 +753,10 @@ static ETERM *erl_decode_it(unsigned char **ext) for(x = 0 ; x < arity ; x++) { l |= ((long long)(*ext)[x]) << ((long long)(8*x)); } - - if (sign) l = (long long) (~l | (unsigned long long) sign); + if (sign) { + l = -l; + if (l > 0) goto big_truncate; + } ERL_TYPE(ep) = ERL_LONGLONG; ep->uval.llval.i = l; @@ -1008,10 +985,13 @@ static ETERM *erl_decode_it(unsigned char **ext) return ep; case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: ERL_TYPE(ep) = ERL_FLOAT; - if (sscanf((char *) *ext, "%lf", &ff) != 1) + cp = (char *) *ext; + i = -1; + if (ei_decode_double(cp, &i, &ff) == -1) goto failure; - *ext += 31; + *ext += i; ep->uval.fval.f = ff; return ep; @@ -1176,6 +1156,7 @@ unsigned char erl_ext_type(unsigned char *ext) case ERL_LARGE_TUPLE_EXT: return ERL_TUPLE; case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: return ERL_FLOAT; case ERL_BINARY_EXT: return ERL_BINARY; @@ -1218,6 +1199,7 @@ int erl_ext_size(unsigned char *t) case ERL_BINARY_EXT: case ERL_STRING_EXT: case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: return 0; @@ -1332,6 +1314,9 @@ static int jump(unsigned char **ext) case ERL_FLOAT_EXT: *ext += 31; break; + case NEW_FLOAT_EXT: + *ext += 8; + break; case ERL_BINARY_EXT: i = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3]; *ext += 4+i; @@ -1661,11 +1646,14 @@ static int cmp_exe2(unsigned char **e1, unsigned char **e2) min = (i < j) ? i : j; k = 0; while (1) { - if (k++ == min) - return compare_top_ext(e1 , e2); - if ((ret = compare_top_ext(e1 , e2)) == 0) - continue; - return ret; + if (k++ == min){ + if (i == j) return 0; + if (i < j) return -1; + return 1; + } + if ((ret = compare_top_ext(e1 , e2)) == 0) + continue; + return ret; } case ERL_STRING_EXT: i = (**e1 << 8) | ((*e1)[1]); @@ -1696,12 +1684,15 @@ static int cmp_exe2(unsigned char **e1, unsigned char **e2) } return 0; case ERL_FLOAT_EXT: - if (sscanf((char *) *e1, "%lf", &ff1) != 1) - return -1; - *e1 += 31; - if (sscanf((char *) *e2, "%lf", &ff2) != 1) - return -1; - *e2 += 31; + case NEW_FLOAT_EXT: + i = -1; + if (ei_decode_double((char *) *e1, &i, &ff1) != 0) + return -1; + *e1 += i; + j = -1; + if (ei_decode_double((char *) *e2, &j, &ff2) != 0) + return -1; + *e2 += j; return cmp_floats(ff1,ff2); case ERL_BINARY_EXT: @@ -1896,8 +1887,11 @@ static int cmp_big_big(unsigned char**e1, unsigned char **e2) ei_get_type((char *)*e1,&i1,&t1,&n1); ei_get_type((char *)*e2,&i2,&t2,&n2); - b1 = ei_alloc_big(n1); - b2 = ei_alloc_big(n2); + if ( (b1 = ei_alloc_big(n1)) == NULL) return -1; + if ( (b2 = ei_alloc_big(n2)) == NULL) { + ei_free_big(b1); + return 1; + } ei_decode_big((char *)*e1,&i1,b1); ei_decode_big((char *)*e2,&i2,b2); diff --git a/lib/erl_interface/src/legacy/global_register.c b/lib/erl_interface/src/legacy/global_register.c index 3a4de8b08e..f12eb6b448 100644 --- a/lib/erl_interface/src/legacy/global_register.c +++ b/lib/erl_interface/src/legacy/global_register.c @@ -31,7 +31,7 @@ int erl_global_register(int fd, const char *name, ETERM *pid) int index = 0; erlang_pid self; erlang_msg msg; - int needlink, needatom; + int needlink, needatom, needmonitor; int arity; int version; int msglen; @@ -65,7 +65,7 @@ int erl_global_register(int fd, const char *name, ETERM *pid) if (ei_send_reg_encoded(fd,&self,"rex",buf,index)) return -1; /* get the reply: expect link and an atom, or just an atom */ - needlink = needatom = 1; + needlink = needatom = needmonitor = 1; while (1) { /* get message */ while (1) { @@ -78,9 +78,15 @@ int erl_global_register(int fd, const char *name, ETERM *pid) case ERL_LINK: /* got link */ if (!needlink) return -1; - needlink = 0; + needlink = 0; break; + case ERL_MONITOR_P-10: + /* got monitor */ + if (!needmonitor) { return -1;} + needmonitor = 0; + break; + case ERL_SEND: /* got message - does it contain our atom? */ if (!needatom) return -1; diff --git a/lib/erl_interface/src/legacy/global_unregister.c b/lib/erl_interface/src/legacy/global_unregister.c index 514dbc3c68..97a1c2d03c 100644 --- a/lib/erl_interface/src/legacy/global_unregister.c +++ b/lib/erl_interface/src/legacy/global_unregister.c @@ -37,7 +37,7 @@ int erl_global_unregister(int fd, const char *name) erlang_msg msg; int i; int version,arity,msglen; - int needunlink, needatom; + int needunlink, needatom, needdemonitor; /* make a self pid */ self->num = fd; @@ -57,7 +57,7 @@ int erl_global_unregister(int fd, const char *name) if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return -1; /* get the reply: expect unlink and an atom, or just an atom */ - needunlink = needatom = 1; + needunlink = needatom = needdemonitor = 1; while (1) { /* get message */ while (1) { @@ -68,11 +68,17 @@ int erl_global_unregister(int fd, const char *name) switch (i) { case ERL_UNLINK: - /* got link */ + /* got unlink */ if (!needunlink) return -1; needunlink = 0; break; + case ERL_DEMONITOR_P-10: + /* got demonitor */ + if (!needdemonitor) return -1; + needdemonitor = 0; + break; + case ERL_SEND: /* got message - does it contain our atom? */ if (!needatom) return -1; diff --git a/lib/erl_interface/src/misc/ei_decode_term.c b/lib/erl_interface/src/misc/ei_decode_term.c index 7b95ff232f..75c5dc9460 100644 --- a/lib/erl_interface/src/misc/ei_decode_term.c +++ b/lib/erl_interface/src/misc/ei_decode_term.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2001-2010. 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% * @@ -25,16 +25,15 @@ #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)! */ +/* Returns 0 on successful encoding, -1 on error, and 1 if the term seems + alright, but does not fit in the term structure. If it returns 0, the + index will be incremented, and the term contains the decoded term. */ 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); @@ -46,11 +45,8 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term) 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 NEW_FLOAT_EXT: + return ei_decode_double(buf, index, &term->value.d_val); case ERL_ATOM_EXT: len = get16be(s); memcpy(term->value.atom_name, s, len); diff --git a/lib/erl_interface/src/misc/ei_format.c b/lib/erl_interface/src/misc/ei_format.c index 08235d0ebe..dbd7a4479a 100644 --- a/lib/erl_interface/src/misc/ei_format.c +++ b/lib/erl_interface/src/misc/ei_format.c @@ -47,10 +47,12 @@ * array of unions. */ union arg { + char c; char* s; long l; unsigned long u; double d; + erlang_pid* pid; }; static int eiformat(const char** s, union arg** args, ei_x_buff* x); @@ -106,6 +108,8 @@ static int eiformat(const char** fmt, union arg** args, ei_x_buff* x) default: if (isdigit((int)*p)) res = pdigit(&p, x); + else if ((*p == '-' || *p == '+') && isdigit((int)*(p+1))) + res = pdigit(&p, x); else if (islower((int)*p)) res = patom(&p, x); else @@ -149,6 +153,8 @@ static int pdigit(const char** fmt, ei_x_buff* x) double d; long l; + if (**fmt == '-' || **fmt == '+') + (*fmt)++; for (;;) { c = *(*fmt)++; if (isdigit((int)c)) @@ -220,12 +226,14 @@ static int pquotedatom(const char** fmt, ei_x_buff* x) /* * The format letters are: * a - An atom + * c - A character * s - A string * i - An integer * l - A long integer * u - An unsigned long integer * f - A float * d - A double float + * p - An Erlang PID */ static int pformat(const char** fmt, union arg** args, ei_x_buff* x) { @@ -236,6 +244,10 @@ static int pformat(const char** fmt, union arg** args, ei_x_buff* x) res = ei_x_encode_atom(x, (*args)->s); (*args)++; break; + case 'c': + res = ei_x_encode_char(x, (*args)->c); + (*args)++; + break; case 's': res = ei_x_encode_string(x, (*args)->s); (*args)++; @@ -257,6 +269,10 @@ static int pformat(const char** fmt, union arg** args, ei_x_buff* x) res = ei_x_encode_double(x, (*args)->d); (*args)++; break; + case 'p': + res = ei_x_encode_pid(x, (*args)->pid); + (*args)++; + break; default: res = -1; break; @@ -392,6 +408,9 @@ static int read_args(const char* fmt, va_list ap, union arg **argp) return -1; /* Error, string not complete */ } switch (*p++) { + case 'c': + args[i++].c = (char) va_arg(ap, int); + break; case 'a': case 's': args[i++].s = va_arg(ap, char*); @@ -411,6 +430,9 @@ static int read_args(const char* fmt, va_list ap, union arg **argp) case 'd': args[i++].d = va_arg(ap, double); break; + case 'p': + args[i++].pid = va_arg(ap, erlang_pid*); + break; default: ei_free(args); /* Invalid specifier */ return -1; diff --git a/lib/erl_interface/src/misc/ei_portio.c b/lib/erl_interface/src/misc/ei_portio.c index b73ebebbe1..a3f6f63fff 100644 --- a/lib/erl_interface/src/misc/ei_portio.c +++ b/lib/erl_interface/src/misc/ei_portio.c @@ -166,11 +166,16 @@ int ei_writev_fill_t(int fd, const struct iovec *iov, int iovcnt, unsigned if (done < sum) { if (iov_base == NULL) { iov_base = malloc(sizeof(struct iovec) * iovcnt); + if (iov_base == NULL) { + return -1; + } memcpy(iov_base, iov, sizeof(struct iovec) * iovcnt); current_iov = iov_base; } while (i > 0) { if (i < current_iov[0].iov_len) { + char *p = (char*)current_iov[0].iov_base; + current_iov[0].iov_base = p + i; current_iov[0].iov_len -= i; i = 0; } else { diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c index 8d0eef5e79..5fc6b3542c 100644 --- a/lib/erl_interface/src/misc/ei_printterm.c +++ b/lib/erl_interface/src/misc/ei_printterm.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2001-2010. 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% * @@ -253,7 +253,8 @@ static int print_term(FILE* fp, ei_x_buff* x, erlang_big *b; char *ds; - b = ei_alloc_big(n); + if ( (b = ei_alloc_big(n)) == NULL) goto err; + if (ei_decode_big(buf, index, b) < 0) { ei_free_big(b); goto err; @@ -272,6 +273,7 @@ static int print_term(FILE* fp, ei_x_buff* x, break; case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: if (ei_decode_double(buf, index, &d) < 0) goto err; ch_written += xprintf(fp, x, "%f", d); break; diff --git a/lib/erl_interface/src/misc/get_type.c b/lib/erl_interface/src/misc/get_type.c index d67a6a80d3..2a680d0f94 100644 --- a/lib/erl_interface/src/misc/get_type.c +++ b/lib/erl_interface/src/misc/get_type.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. 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% * @@ -122,7 +122,12 @@ int ei_get_type_internal(const char *buf, const int *index, case ERL_STRING_EXT: *len = get16be(s); break; - + + case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: + *type = ERL_FLOAT_EXT; + break; + case ERL_LARGE_TUPLE_EXT: case ERL_LIST_EXT: case ERL_BINARY_EXT: diff --git a/lib/erl_interface/src/misc/putget.h b/lib/erl_interface/src/misc/putget.h index 98d9ebb64c..7a43de324b 100644 --- a/lib/erl_interface/src/misc/putget.h +++ b/lib/erl_interface/src/misc/putget.h @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. 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% * @@ -54,6 +54,18 @@ (s) += 4; \ } while (0) +#define put64be(s,n) do { \ + (s)[0] = ((n) >> 56) & 0xff; \ + (s)[1] = ((n) >> 48) & 0xff; \ + (s)[2] = ((n) >> 40) & 0xff; \ + (s)[3] = ((n) >> 32) & 0xff; \ + (s)[4] = ((n) >> 24) & 0xff; \ + (s)[5] = ((n) >> 16) & 0xff; \ + (s)[6] = ((n) >> 8) & 0xff; \ + (s)[7] = (n) & 0xff; \ + (s) += 8; \ +} while (0) + #define get8(s) \ ((s) += 1, \ ((unsigned char *)(s))[-1] & 0xff) @@ -82,4 +94,20 @@ (((unsigned char *)(s))[-2] << 8) | \ ((unsigned char *)(s))[-1])) +#define get64be(s) \ + ((s) += 8, \ + (((EI_ULONGLONG)((unsigned char *)(s))[-8] << 56) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-7] << 48) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-6] << 40) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-5] << 32) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-4] << 24) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-3] << 16) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-2] << 8) | \ + (EI_ULONGLONG)((unsigned char *)(s))[-1])) + +typedef union float_ext { + double d; + EI_ULONGLONG val; +} FloatExt; + #endif /* _PUTGET_H */ diff --git a/lib/erl_interface/src/misc/show_msg.c b/lib/erl_interface/src/misc/show_msg.c index 25865d6f8e..194296798b 100644 --- a/lib/erl_interface/src/misc/show_msg.c +++ b/lib/erl_interface/src/misc/show_msg.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 1998-2010. 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% * @@ -181,11 +181,6 @@ int ei_show_sendmsg(FILE *stream, const char *header, const char *msgbuf) mbuf = header; break; - case ERL_NODE_LINK: - /* nothing to do */ - mbuf = header; - break; - default: break; } @@ -241,10 +236,6 @@ static void show_msg(FILE *stream, int direction, const erlang_msg *msg, 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); @@ -400,6 +391,7 @@ static void show_term(const char *termbuf, int *index, FILE *stream) break; case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: ei_decode_double(termbuf,index,&fnum); fprintf(stream,"%f",fnum); break; diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c index f0d638324d..33ff6da7c9 100644 --- a/lib/erl_interface/src/prog/erl_call.c +++ b/lib/erl_interface/src/prog/erl_call.c @@ -118,11 +118,14 @@ static void usage_arg(const char *progname, const char *switchname); static void usage_error(const char *progname, const char *switchname); static void usage(const char *progname); static int get_module(char **mbuf, char **mname); -static struct hostent* get_hostent(char *host); static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags); static int read_stdin(char **buf); static void split_apply_string(char *str, char **mod, char **fun, char **args); +static void* ei_chk_malloc(size_t size); +static void* ei_chk_calloc(size_t nmemb, size_t size); +static void* ei_chk_realloc(void *old, size_t size); +static char* ei_chk_strdup(char *s); /*************************************************************************** @@ -132,7 +135,6 @@ static void split_apply_string(char *str, char **mod, ***************************************************************************/ /* FIXME isn't VxWorks to handle arguments differently? */ -/* FIXME check errors from malloc */ #if !defined(VXWORKS) int main(int argc, char *argv[]) @@ -165,8 +167,7 @@ int erl_call(int argc, char **argv) usage_arg(progname, "-sname "); } - flags.node = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.node, argv[i+1]); + flags.node = ei_chk_strdup(argv[i+1]); i++; flags.use_long_name = 0; } else if (strcmp(argv[i], "-name") == 0) { /* -name NAME */ @@ -174,8 +175,7 @@ int erl_call(int argc, char **argv) usage_arg(progname, "-name "); } - flags.node = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.node, argv[i+1]); + flags.node = ei_chk_strdup(argv[i+1]); i++; flags.use_long_name = 1; } else { @@ -210,16 +210,14 @@ int erl_call(int argc, char **argv) usage_arg(progname, "-c "); } flags.cookiep = 1; - flags.cookie = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.cookie, argv[i+1]); + flags.cookie = ei_chk_strdup(argv[i+1]); i++; break; case 'n': if (i+1 >= argc) { usage_arg(progname, "-n "); } - flags.node = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.node, argv[i+1]); + flags.node = ei_chk_strdup(argv[i+1]); flags.use_long_name = 1; i++; break; @@ -227,24 +225,21 @@ int erl_call(int argc, char **argv) if (i+1 >= argc) { usage_arg(progname, "-h "); } - flags.hidden = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.hidden, argv[i+1]); + flags.hidden = ei_chk_strdup(argv[i+1]); i++; break; case 'x': if (i+1 >= argc) { usage_arg(progname, "-x "); } - flags.script = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.script, argv[i+1]); + flags.script = ei_chk_strdup(argv[i+1]); i++; break; case 'a': if (i+1 >= argc) { usage_arg(progname, "-a "); } - flags.apply = (char *) malloc(strlen(argv[i+1]) + 1); - strcpy(flags.apply, argv[i+1]); + flags.apply = ei_chk_strdup(argv[i+1]); i++; break; case '?': @@ -304,8 +299,7 @@ int erl_call(int argc, char **argv) if (flags.hidden == NULL) { /* As default we are c17@gethostname */ i = flags.randomp ? (time(NULL) % 997) : 17; - /* FIXME allocates to small !!! */ - flags.hidden = (char *) malloc(3 + 2 ); /* c17 or cXYZ */ + flags.hidden = (char *) ei_chk_malloc(10 + 2 ); /* c17 or cXYZ */ #if defined(VXWORKS) sprintf(flags.hidden, "c%d", i < 0 ? (int) taskIdSelf() : i); @@ -330,17 +324,25 @@ int erl_call(int argc, char **argv) initWinSock(); #endif - gethostname(h_hostname, EI_MAXHOSTNAMELEN); + if (gethostname(h_hostname, EI_MAXHOSTNAMELEN) < 0) { + fprintf(stderr,"erl_call: failed to get host name: %d\n", errno); + exit(1); + } if ((hp = ei_gethostbyname(h_hostname)) == 0) { fprintf(stderr,"erl_call: can't resolve hostname %s\n", h_hostname); exit(1); } - /* If shortnames cut of the name at first '.' */ + /* If shortnames, cut off the name at first '.' */ if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) { *ct = '\0'; } - strcpy(h_hostname, hp->h_name); + strncpy(h_hostname, hp->h_name, EI_MAXHOSTNAMELEN); + h_hostname[EI_MAXHOSTNAMELEN] = '\0'; memcpy(&h_ipadr.s_addr, *hp->h_addr_list, sizeof(struct in_addr)); + if (strlen(h_alivename) + strlen(h_hostname) + 2 > sizeof(h_nodename)) { + fprintf(stderr,"erl_call: hostname too long: %s\n", h_hostname); + exit(1); + } sprintf(h_nodename, "%s@%s", h_alivename, h_hostname); if (ei_connect_xinit(&ec, h_hostname, h_alivename, h_nodename, @@ -364,15 +366,20 @@ int erl_call(int argc, char **argv) * Expand name to a real name (may be ip-address) */ /* FIXME better error string */ - if ((hp = get_hostent(host)) == 0) { - fprintf(stderr,"erl_call: can't get_hostent(%s)\n", host); + if ((hp = ei_gethostbyname(host)) == 0) { + fprintf(stderr,"erl_call: can't ei_gethostbyname(%s)\n", host); exit(1); } - /* If shortnames cut of the name at first '.' */ + /* If shortnames, cut off the name at first '.' */ if (flags.use_long_name == 0 && (ct = strchr(hp->h_name, '.')) != NULL) { *ct = '\0'; } - strcpy(host_name, hp->h_name); + strncpy(host_name, hp->h_name, EI_MAXHOSTNAMELEN); + host_name[EI_MAXHOSTNAMELEN] = '\0'; + if (strlen(flags.node) + strlen(host_name) + 2 > sizeof(nodename)) { + fprintf(stderr,"erl_call: nodename too long: %s\n", flags.node); + exit(1); + } sprintf(nodename, "%s@%s", flags.node, host_name); /* @@ -401,7 +408,7 @@ int erl_call(int argc, char **argv) ei_encode_empty_list(NULL, &i); - p = (char *)malloc(i); + p = (char *)ei_chk_malloc(i); i = 0; /* Reset */ ei_encode_empty_list(p, &i); @@ -426,6 +433,10 @@ int erl_call(int argc, char **argv) if (flags.modp && (modname != NULL)) { char fname[256]; + if (strlen(modname) + 4 + 1 > sizeof(fname)) { + fprintf(stderr,"erl_call: module name too long: %s\n", modname); + exit(1); + } strcpy(fname, modname); strcat(fname, ".erl"); @@ -443,7 +454,7 @@ int erl_call(int argc, char **argv) ei_encode_binary(NULL, &i, module, modsize); ei_encode_empty_list(NULL, &i); - p = (char *)malloc(i); + p = (char *)ei_chk_malloc(i); i = 0; /* Reset */ ei_encode_list_header(p, &i, 2); @@ -476,7 +487,7 @@ int erl_call(int argc, char **argv) ei_encode_empty_list(NULL, &i); ei_encode_empty_list(NULL, &i); - p = (char *)malloc(i); + p = (char *)ei_chk_malloc(i); i = 0; /* Reset */ ei_encode_list_header(p, &i, 2); @@ -521,7 +532,7 @@ int erl_call(int argc, char **argv) ei_encode_binary(NULL, &i, evalbuf, len); ei_encode_empty_list(NULL, &i); - p = (char *)malloc(i); + p = (char *)ei_chk_malloc(i); i = 0; /* Reset */ ei_encode_list_header(p, &i, 1); @@ -592,32 +603,6 @@ int erl_call(int argc, char **argv) * ***************************************************************************/ -/* - * Get host entry (by address or name) - */ -/* FIXME: will fail on names like '2fun4you'. */ -static struct hostent* get_hostent(char *host) -{ - if (isdigit((int)*host)) { - struct in_addr ip_addr; - int b1, b2, b3, b4; - long addr; - - /* FIXME: Use inet_aton() (or inet_pton() and get v6 for free). */ - if (sscanf(host, "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4) { - return NULL; - } - addr = inet_addr(host); - ip_addr.s_addr = htonl(addr); - - return ei_gethostbyaddr((char *)&ip_addr,sizeof(struct in_addr), AF_INET); - } - - return ei_gethostbyname(host); -} /* get_hostent */ - - - /* * This function does only return on success. @@ -719,32 +704,28 @@ static void split_apply_string(char *str, EAT(str); len = str-begin; - *mod = (char *) calloc(len + 1, sizeof(char)); + *mod = (char *) ei_chk_calloc(len + 1, sizeof(char)); memcpy(*mod, begin, len); SKIP_SPACE(str); if (*str == '\0') { - *fun = (char *) calloc(strlen(start)+1, sizeof(char)); - strcpy(*fun, start); - *args = (char *) calloc(strlen(empty_list)+1, sizeof(char)); - strcpy(*args, empty_list); + *fun = ei_chk_strdup(start); + *args = ei_chk_strdup(empty_list); return; } begin = str; EAT(str); len = str-begin; - *fun = (char *) calloc(len + 1, sizeof(char)); + *fun = (char *) ei_chk_calloc(len + 1, sizeof(char)); memcpy(*fun, begin, len); SKIP_SPACE(str); if (*str == '\0') { - *args = (char *) calloc(strlen(empty_list)+1, sizeof(char)); - strcpy(*args, empty_list); + *args = ei_chk_strdup(empty_list); return; } - *args = (char *) calloc(strlen(str) + 1, sizeof(char)); - strcpy(*args, str); + *args = ei_chk_strdup(str); return; @@ -760,7 +741,7 @@ static int read_stdin(char **buf) int bsize = BUFSIZ; int len = 0; int i; - char *tmp = (char *) malloc(bsize); + char *tmp = (char *) ei_chk_malloc(bsize); while (1) { if ((i = read(0, &tmp[len], bsize-len)) < 0) { @@ -772,7 +753,7 @@ static int read_stdin(char **buf) len += i; if ((len+50) > bsize) { bsize = len * 2; - tmp = (char *) realloc(tmp, bsize); + tmp = (char *) ei_chk_realloc(tmp, bsize); } else { continue; } @@ -809,10 +790,11 @@ static int get_module(char **mbuf, char **mname) } } /* while */ i = tmp - start; - *mname = (char *) calloc(i+1, sizeof(char)); + *mname = (char *) ei_chk_calloc(i+1, sizeof(char)); memcpy(*mname, start, i); } - free(mbuf); /* Allocated in read_stdin() */ + if (*mbuf) + free(*mbuf); /* Allocated in read_stdin() */ return len; @@ -904,3 +886,51 @@ static void initWinSock(void) } } #endif + + +/*************************************************************************** + * + * Utility functions + * + ***************************************************************************/ + +static void* ei_chk_malloc(size_t size) +{ + void *p = malloc(size); + if (p == NULL) { + fprintf(stderr,"erl_call: insufficient memory\n"); + exit(1); + } + return p; +} + +static void* ei_chk_calloc(size_t nmemb, size_t size) +{ + void *p = calloc(nmemb, size); + if (p == NULL) { + fprintf(stderr,"erl_call: insufficient memory\n"); + exit(1); + } + return p; +} + +static void* ei_chk_realloc(void *old, size_t size) +{ + void *p = realloc(old, size); + if (!p) { + fprintf(stderr, "erl_call: cannot reallocate %u bytes of memory from %p\n", + (unsigned) size, old); + exit (1); + } + return p; +} + +static char* ei_chk_strdup(char *s) +{ + char *p = strdup(s); + if (p == NULL) { + fprintf(stderr,"erl_call: insufficient memory\n"); + exit(1); + } + return p; +} diff --git a/lib/erl_interface/src/registry/reg_dump.c b/lib/erl_interface/src/registry/reg_dump.c index 50a6949177..dfec96b43c 100644 --- a/lib/erl_interface/src/registry/reg_dump.c +++ b/lib/erl_interface/src/registry/reg_dump.c @@ -157,7 +157,7 @@ static int mn_send_delete(int fd, erlang_pid *mnesia, const char *key) int len = strlen(key) + 32; /* 32 is a slight overestimate */ if (len > EISMALLBUF) - if (!(dbuf = malloc(index))) + if (!(dbuf = malloc(len))) return -1; msgbuf = (dbuf ? dbuf : sbuf); @@ -187,7 +187,7 @@ static int mn_send_write(int fd, erlang_pid *mnesia, const char *key, ei_reg_obj int len = 32 + keylen + obj->size; if (len > EISMALLBUF) - if (!(dbuf = malloc(index))) + if (!(dbuf = malloc(len))) return -1; msgbuf = (dbuf ? dbuf : sbuf); diff --git a/lib/erl_interface/src/registry/reg_restore.c b/lib/erl_interface/src/registry/reg_restore.c index 27918d2364..aeb33c784a 100644 --- a/lib/erl_interface/src/registry/reg_restore.c +++ b/lib/erl_interface/src/registry/reg_restore.c @@ -266,7 +266,7 @@ int ei_reg_restore(int fd, ei_reg *reg, const char *mntab) /* make sure receive buffer can handle largest expected message */ len = maxkey + maxobj + 512; if (len > EISMALLBUF) - if (!(dbuf = malloc(index))) { + if (!(dbuf = malloc(len))) { ei_send_exit(fd,&self,&mnesia,"cannot allocate space for incoming data"); return -1; } diff --git a/lib/erl_interface/test/Makefile b/lib/erl_interface/test/Makefile index b7a1a4e4d8..07404fda4d 100644 --- a/lib/erl_interface/test/Makefile +++ b/lib/erl_interface/test/Makefile @@ -33,6 +33,7 @@ MODULES= \ ei_print_SUITE \ ei_tmo_SUITE \ erl_connect_SUITE \ + erl_global_SUITE \ erl_eterm_SUITE \ erl_ext_SUITE \ erl_format_SUITE \ diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl index bc83d6a62e..a97c874e5f 100644 --- a/lib/erl_interface/test/ei_accept_SUITE.erl +++ b/lib/erl_interface/test/ei_accept_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2010. 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 @@ -31,7 +31,7 @@ all(suite) -> [ei_accept, ei_threaded_accept]. init_per_testcase(_Case, Config) -> - Dog = ?t:timetrap(?t:minutes(0.25)), + Dog = ?t:timetrap(?t:seconds(30)), [{watchdog, Dog}|Config]. fin_per_testcase(_Case, Config) -> @@ -43,8 +43,6 @@ ei_accept(Config) when is_list(Config) -> ?line P = runner:start(?interpret), ?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), -% ?line AMsg={a,[message, with], " strings in it!", [-12, -23], 1.001}, - %% shouldn't this be a bif or function or something? ?line Myname= hd(tl(string:tokens(atom_to_list(node()), "@"))), ?line io:format("Myname ~p ~n", [Myname]), ?line EINode= list_to_atom("c42@"++Myname), @@ -52,9 +50,13 @@ ei_accept(Config) when is_list(Config) -> ?line Self= self(), ?line TermToSend= {call, Self, "Test"}, ?line F= fun() -> - timer:sleep(500), - {any, EINode} ! TermToSend, - Self ! sent_ok, + case waitfornode("c42",20) of + true -> + {any, EINode} ! TermToSend, + Self ! sent_ok; + false -> + Self ! never_published + end, ok end, @@ -72,7 +74,7 @@ ei_accept(Config) when is_list(Config) -> after 1000 -> io:format("timeout ~n") end, - ?line ok= ei_unpublish(P), + ?line runner:finish(P), ok. ei_threaded_accept(Config) when is_list(Config) -> @@ -90,12 +92,29 @@ ei_threaded_accept(Config) when is_list(Config) -> || I <- lists:seq(0, N-1) ], ok. +waitfornode(String,0) -> + io:format("~s never published itself.~n",[String]), + false; +waitfornode(String,N) -> + Registered = [X || {X,_} <- element(2,erl_epmd:names())], + case lists:member(String,Registered) of + true -> + true; + false -> + timer:sleep(1000), + waitfornode(String,N-1) + end. + send_rec_einode(N, TestServerPid) -> ?line Myname= hd(tl(string:tokens(atom_to_list(node()), "@"))), - ?line EINode= list_to_atom("eiacc" ++ integer_to_list(N) ++ "@" ++ Myname), + ?line FirstPart = "eiacc" ++ integer_to_list(N), + ?line EINode= list_to_atom(FirstPart ++ "@" ++ Myname), ?line io:format("EINode ~p ~n", [EINode]), ?line Self= self(), - ?line timer:sleep(10*1000), + ?line case waitfornode(FirstPart,20) of + true -> ok; + false -> test_server:fail({never_published,EINode}) + end, ?line {any, EINode} ! Self, ?line receive {N,_}=X -> @@ -136,13 +155,6 @@ ei_receive(P, Fd) -> {term, T}= get_term(P), T. -ei_unpublish(P) -> - send_command(P, ei_unpublish, []), - case get_term(P) of - {term,{0, _}} -> ok; - {term,{_X, Errno}} -> {error,Errno} - end. - send_command(P, Name, Args) -> runner:send_term(P, {Name,list_to_tuple(Args)}). diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl index 56f478edad..3c72188e16 100644 --- a/lib/erl_interface/test/ei_connect_SUITE.erl +++ b/lib/erl_interface/test/ei_connect_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2010. 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 @@ -30,6 +30,7 @@ ei_send/1, ei_reg_send/1, + ei_format_pid/1, ei_rpc/1, rpc_test/1, ei_send_funs/1, @@ -41,6 +42,7 @@ all(suite) -> [ ei_send, ei_reg_send, + ei_format_pid, ei_rpc, ei_send_funs, ei_threaded_send, @@ -67,6 +69,19 @@ ei_send(Config) when is_list(Config) -> ?line runner:recv_eot(P), ok. +ei_format_pid(Config) when is_list(Config) -> + ?line S = self(), + ?line P = runner:start(?interpret), + ?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + ?line {ok,Fd} = ei_connect(P, node()), + + ?line ok = ei_format_pid(P, Fd, S), + ?line receive S -> ok end, + + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + ei_send_funs(Config) when is_list(Config) -> ?line P = runner:start(?interpret), ?line 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), @@ -103,10 +118,12 @@ ei_threaded_send(Config) when is_list(Config) -> ?line Einode = filename:join(?config(data_dir, Config), "einode"), ?line N = 15, ?line Host = atom_to_list(node()), - ?line spawn_link(fun() -> start_einode(Einode, N, Host) end), ?line TestServerPid = self(), ?line [ spawn_link(fun() -> rec_einode(I, TestServerPid) end) || I <- lists:seq(0, N-1) ], + ?line [ receive {I,registered} -> ok end + || I <- lists:seq(0, N-1) ], + ?line spawn_link(fun() -> start_einode(Einode, N, Host) end), ?line [ receive I -> ok end || I <- lists:seq(0, N-1) ], ok. @@ -114,6 +131,7 @@ ei_threaded_send(Config) when is_list(Config) -> rec_einode(N, TestServerPid) -> ?line Regname = list_to_atom("mth"++integer_to_list(N)), ?line register(Regname, self()), + ?line TestServerPid ! {N, registered}, ?line io:format("~p waiting~n", [Regname]), ?line receive X -> @@ -186,6 +204,10 @@ ei_send(P, Fd, To, Msg) -> send_command(P, ei_send, [Fd,To,Msg]), get_send_result(P). +ei_format_pid(P, Fd, To) -> + send_command(P, ei_format_pid, [Fd, To]), + get_send_result(P). + ei_send_funs(P, Fd, To, Msg) -> send_command(P, ei_send_funs, [Fd,To,Msg]), get_send_result(P). diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c index debd3e789b..8183ac9dd8 100644 --- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c +++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c @@ -35,6 +35,7 @@ static void cmd_ei_connect_init(char* buf, int len); static void cmd_ei_connect(char* buf, int len); static void cmd_ei_send(char* buf, int len); +static void cmd_ei_format_pid(char* buf, int len); static void cmd_ei_send_funs(char* buf, int len); static void cmd_ei_reg_send(char* buf, int len); static void cmd_ei_rpc(char* buf, int len); @@ -57,6 +58,7 @@ static struct { "ei_reg_send", 3, cmd_ei_reg_send, "ei_rpc", 4, cmd_ei_rpc, "ei_set_get_tracelevel", 1, cmd_ei_set_get_tracelevel, + "ei_format_pid", 2, cmd_ei_format_pid, }; @@ -111,7 +113,7 @@ static void cmd_ei_connect_init(char* buf, int len) ei_x_buff res; if (ei_decode_long(buf, &index, &l) < 0) fail("expected int"); - sprintf(b, "c%d", l); + sprintf(b, "c%ld", l); /* FIXME don't use internal and maybe use skip?! */ ei_get_type_internal(buf, &index, &type, &size); if (ei_decode_atom(buf, &index, cookie) < 0) @@ -183,6 +185,25 @@ static void cmd_ei_send(char* buf, int len) ei_x_free(&x); } +static void cmd_ei_format_pid(char* buf, int len) +{ + int index = 0; + long fd; + erlang_pid pid; + ei_x_buff x; + + if (ei_decode_long(buf, &index, &fd) < 0) + fail("expected long"); + if (ei_decode_pid(buf, &index, &pid) < 0) + fail("expected pid (node)"); + if (ei_x_new_with_version(&x) < 0) + fail("ei_x_new_with_version"); + if (ei_x_format_wo_ver(&x, "~p", &pid) < 0) + fail("ei_x_format_wo_ver"); + send_errno_result(ei_send(fd, &pid, x.buff, x.index)); + ei_x_free(&x); +} + static void cmd_ei_send_funs(char* buf, int len) { int index = 0, n; diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl index ea528728ab..524a04a3b4 100644 --- a/lib/erl_interface/test/ei_decode_SUITE.erl +++ b/lib/erl_interface/test/ei_decode_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2010. 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% %% @@ -181,22 +181,9 @@ test_ei_decode_misc(suite) -> []; test_ei_decode_misc(Config) when is_list(Config) -> ?line P = runner:start(?test_ei_decode_misc), -% ?line <<131>> = get_binaries(P), - -% ?line {term,F} = get_term(P), -% ?line match_float(F, 0.0), -% ?line {term,F} = get_term(P), -% ?line match_float(F, 0.0), - -% ?line {term,F} = get_term(P), -% ?line true = match_float(F, -1.0), -% ?line {term,F} = get_term(P), -% ?line true = match_float(F, -1.0), - -% ?line {term,F} = get_term(P), -% ?line true = match_float(F, 1.0), -% ?line {term,F} = get_term(P), -% ?line true = match_float(F, 1.0), + ?line send_term_as_binary(P,0.0), + ?line send_term_as_binary(P,-1.0), + ?line send_term_as_binary(P,1.0), ?line send_term_as_binary(P,false), ?line send_term_as_binary(P,true), @@ -235,15 +222,17 @@ send_integers(P) -> ?line send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*) ?line send_term_as_binary(P,-1), % INTEGER_EXT largest neg - ?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT largest (28 bits) - ?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT smallest - ?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT smallest pos(*) - ?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT largest neg (*) + ?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT old largest (28 bits) + ?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT old smallest + ?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT old smallest pos(*) + ?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT old largest neg (*) - ?line send_term_as_binary(P, 16#7fffffff), % SMALL_BIG_EXT largest i32 - ?line send_term_as_binary(P,-16#80000000), % SMALL_BIG_EXT smallest i32 - - case erlang:system_info(wordsize) of + ?line send_term_as_binary(P, 16#7fffffff), % INTEGER_EXT new largest (32 bits) + ?line send_term_as_binary(P,-16#80000000), % INTEGER_EXT new smallest (32 bis) + ?line send_term_as_binary(P, 16#80000000), % SMALL_BIG_EXT new smallest pos(*) + ?line send_term_as_binary(P,-16#80000001), % SMALL_BIG_EXT new largest neg (*) + + case erlang:system_info({wordsize,external}) of 4 -> ?line send_term_as_binary(P, 16#80000000),% SMALL_BIG_EXT u32 ?line send_term_as_binary(P, 16#ffffffff),% SMALL_BIG_EXT largest u32 @@ -279,15 +268,17 @@ send_integers2(P) -> ?line send_term_as_binary(P,255), % SMALL_INTEGER_EXT largest ?line send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*) ?line send_term_as_binary(P,-1), % INTEGER_EXT largest neg + + ?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT old largest (28 bits) + ?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT old smallest + ?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT old smallest pos(*) + ?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT old largest neg (*) - ?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT largest (28 bits) - ?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT smallest - ?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT smallest pos(*) - ?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT largest neg (*) + ?line send_term_as_binary(P, 16#7fffffff), % INTEGER_EXT new largest (32 bits) + ?line send_term_as_binary(P,-16#80000000), % INTEGER_EXT new smallest + ?line send_term_as_binary(P, 16#80000000), % SMALL_BIG_EXT new smallest pos(*) + ?line send_term_as_binary(P,-16#80000001), % SMALL_BIG_EXT new largest neg (*) - ?line send_term_as_binary(P, 16#7fffffff), % SMALL_BIG_EXT largest i32 - ?line send_term_as_binary(P,-16#80000000), % SMALL_BIG_EXT smallest i32 - ?line send_term_as_binary(P, 16#80000000),% SMALL_BIG_EXT u32 ?line send_term_as_binary(P, 16#ffffffff),% SMALL_BIG_EXT largest u32 ?line send_term_as_binary(P, 16#7fffffffffff), % largest i48 diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c index d81ea88437..b349138ae9 100644 --- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c +++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2004-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2004-2010. 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% */ @@ -246,13 +246,23 @@ TESTCASE(test_ei_decode_long) EI_DECODE_2 (decode_long, 5, long, 256); EI_DECODE_2 (decode_long, 5, long, -1); + /* Old 28 bit limits for INTEGER_EXT */ EI_DECODE_2 (decode_long, 5, long, 0x07ffffff); EI_DECODE_2 (decode_long, 5, long, -0x08000000); - EI_DECODE_2 (decode_long, 7, long, 0x08000000); - EI_DECODE_2 (decode_long, 7, long, -0x08000001); + EI_DECODE_2 (decode_long, 5, long, 0x08000000); + EI_DECODE_2 (decode_long, 5, long, -0x08000001); - EI_DECODE_2 (decode_long, 7, long, 0x7fffffff); - EI_DECODE_2 (decode_long, 7, long, -ll(0x80000000)); /* Strange :-( */ + /* New 32 bit limits for INTEGER_EXT */ + EI_DECODE_2 (decode_long, 5, long, 0x7fffffff); + EI_DECODE_2 (decode_long, 5, long, -ll(0x80000000)); /* Strange :-( */ + if (sizeof(long) > 4) { + EI_DECODE_2(decode_long, 7, long, 0x80000000); + EI_DECODE_2(decode_long, 7, long, -ll(0x80000001)); + } + else { + EI_DECODE_2_FAIL(decode_long, 7, long, 0x80000000); + EI_DECODE_2_FAIL(decode_long, 7, long, -ll(0x80000001)); + } EI_DECODE_2_FAIL(decode_long, 7, long, 0x80000000); EI_DECODE_2_FAIL(decode_long, 7, long, 0xffffffff); @@ -280,11 +290,13 @@ TESTCASE(test_ei_decode_ulong) EI_DECODE_2 (decode_ulong, 5, unsigned long, 0x07ffffff); EI_DECODE_2_FAIL(decode_ulong, 5, unsigned long, -0x08000000); - EI_DECODE_2 (decode_ulong, 7, unsigned long, 0x08000000); - EI_DECODE_2_FAIL(decode_ulong, 7, unsigned long, -0x08000001); + EI_DECODE_2 (decode_ulong, 5, unsigned long, 0x08000000); + EI_DECODE_2_FAIL(decode_ulong, 5, unsigned long, -0x08000001); - EI_DECODE_2 (decode_ulong, 7, unsigned long, 0x7fffffff); - EI_DECODE_2_FAIL(decode_ulong, 7, unsigned long, -ll(0x80000000)); + EI_DECODE_2 (decode_ulong, 5, unsigned long, 0x7fffffff); + EI_DECODE_2_FAIL(decode_ulong, 5, unsigned long, -ll(0x80000000)); + EI_DECODE_2 (decode_ulong, 7, unsigned long, 0x80000000); + EI_DECODE_2_FAIL(decode_ulong, 7, unsigned long, -ll(0x80000001)); if (sizeof(long) > 4) { EI_DECODE_2 (decode_ulong, 11, unsigned long, ll(0x8000000000000000)); @@ -319,13 +331,14 @@ TESTCASE(test_ei_decode_longlong) EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, 0x07ffffff); EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, -0x08000000); - EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, 0x08000000); - EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, -0x08000001); - - EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, 0x7fffffff); - EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, -ll(0x80000000)); + EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, 0x08000000); + EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, -0x08000001); + EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, 0x7fffffff); + EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, -ll(0x80000000)); EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, 0x80000000); + EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, -ll(0x80000001)); + EI_DECODE_2 (decode_longlong, 7, EI_LONGLONG, 0xffffffff); EI_DECODE_2 (decode_longlong, 9, EI_LONGLONG, ll(0x7fffffffffff)); @@ -352,13 +365,14 @@ TESTCASE(test_ei_decode_ulonglong) EI_DECODE_2 (decode_ulonglong, 5, EI_ULONGLONG, 0x07ffffff); EI_DECODE_2_FAIL(decode_ulonglong, 5, EI_ULONGLONG, -0x08000000); - EI_DECODE_2 (decode_ulonglong, 7, EI_ULONGLONG, 0x08000000); - EI_DECODE_2_FAIL(decode_ulonglong, 7, EI_ULONGLONG, -0x08000001); - - EI_DECODE_2 (decode_ulonglong, 7, EI_ULONGLONG, 0x7fffffff); - EI_DECODE_2_FAIL(decode_ulonglong, 7, EI_ULONGLONG, -ll(0x80000000)); + EI_DECODE_2 (decode_ulonglong, 5, EI_ULONGLONG, 0x08000000); + EI_DECODE_2_FAIL(decode_ulonglong, 5, EI_ULONGLONG, -0x08000001); + EI_DECODE_2 (decode_ulonglong, 5, EI_ULONGLONG, 0x7fffffff); + EI_DECODE_2_FAIL(decode_ulonglong, 5, EI_ULONGLONG, -ll(0x80000000)); EI_DECODE_2 (decode_ulonglong, 7, EI_ULONGLONG, 0x80000000); + EI_DECODE_2_FAIL(decode_ulonglong, 7, EI_ULONGLONG, -0x80000001); + EI_DECODE_2 (decode_ulonglong, 7, EI_ULONGLONG, 0xffffffff); EI_DECODE_2 (decode_ulonglong, 9, EI_ULONGLONG, ll(0x7fffffffffff)); @@ -515,11 +529,10 @@ TESTCASE(test_ei_decode_misc) /* EI_DECODE_0(decode_version); */ -/* - EI_DECODE_2(decode_double, 0.0); - EI_DECODE_2(decode_double, -1.0); - EI_DECODE_2(decode_double, 1.0); -*/ + EI_DECODE_2(decode_double, 32, double, 0.0); + EI_DECODE_2(decode_double, 32, double, -1.0); + EI_DECODE_2(decode_double, 32, double, 1.0); + EI_DECODE_2(decode_boolean, 8, int, 0); EI_DECODE_2(decode_boolean, 7, int, 1); diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl index fb790eb7c3..6b9de4f093 100644 --- a/lib/erl_interface/test/ei_encode_SUITE.erl +++ b/lib/erl_interface/test/ei_encode_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2010. 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% %% @@ -181,20 +181,14 @@ test_ei_encode_misc(Config) when is_list(Config) -> ?line <<131>> = get_binaries(P), -% ?line {term,F} = get_term(P), -% ?line match_float(F, 0.0), -% ?line {term,F} = get_term(P), -% ?line match_float(F, 0.0), + ?line {<<70,_:8/binary>>,F0} = get_buf_and_term(P), + ?line true = match_float(F0, 0.0), -% ?line {term,F} = get_term(P), -% ?line true = match_float(F, -1.0), -% ?line {term,F} = get_term(P), -% ?line true = match_float(F, -1.0), + ?line {<<70,_:8/binary>>,Fn1} = get_buf_and_term(P), + ?line true = match_float(Fn1, -1.0), -% ?line {term,F} = get_term(P), -% ?line true = match_float(F, 1.0), -% ?line {term,F} = get_term(P), -% ?line true = match_float(F, 1.0), + ?line {<<70,_:8/binary>>,Fp1} = get_buf_and_term(P), + ?line true = match_float(Fp1, 1.0), ?line {<<100,0,5,"false">>,false} = get_buf_and_term(P), ?line {<<100,0,4,"true">> ,true} = get_buf_and_term(P), @@ -310,6 +304,8 @@ get_term(P) -> %% +match_float(F, Match) when is_float(F), is_float(Match), F == Match -> + true; match_float(F, Match) when is_float(F), F > Match*0.99, F < Match*1.01 -> true. diff --git a/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c b/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c index f8de0b7878..c373658152 100644 --- a/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c +++ b/lib/erl_interface/test/ei_encode_SUITE_data/ei_encode_test.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2004-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2004-2010. 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% */ @@ -350,13 +350,13 @@ TESTCASE(test_ei_encode_char) TESTCASE(test_ei_encode_misc) { EI_ENCODE_0(encode_version); -/* + EI_ENCODE_1(encode_double, 0.0); EI_ENCODE_1(encode_double, -1.0); EI_ENCODE_1(encode_double, 1.0); -*/ + EI_ENCODE_1(encode_boolean, 0) /* Only case it should be false */; EI_ENCODE_1(encode_boolean, 1); diff --git a/lib/erl_interface/test/ei_format_SUITE.erl b/lib/erl_interface/test/ei_format_SUITE.erl index 7871f07ae9..6d44e0adf3 100644 --- a/lib/erl_interface/test/ei_format_SUITE.erl +++ b/lib/erl_interface/test/ei_format_SUITE.erl @@ -155,7 +155,7 @@ format_wo_ver(suite) -> []; format_wo_ver(Config) when is_list(Config) -> ?line P = runner:start(?format_wo_ver), - ?line {term, [{a, "b"}, {c, 10}]} = get_term(P), + ?line {term, [-1, 2, $c, {a, "b"}, {c, 10}]} = get_term(P), ?line runner:recv_eot(P), ok. diff --git a/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c b/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c index a969ded3dc..a6eeb25abc 100644 --- a/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c +++ b/lib/erl_interface/test/ei_format_SUITE_data/ei_format_test.c @@ -176,7 +176,7 @@ TESTCASE(format_wo_ver) { ei_x_buff x; ei_x_new (&x); - ei_x_format(&x, "[{~a,~s},{~a,~i}]", "a", "b", "c", 10); + ei_x_format(&x, "[-1, +2, ~c, {~a,~s},{~a,~i}]", 'c', "a", "b", "c", 10); send_bin_term(&x); free(x.buff); diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl index 0c211aa148..e7a2465421 100644 --- a/lib/erl_interface/test/ei_tmo_SUITE.erl +++ b/lib/erl_interface/test/ei_tmo_SUITE.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2003-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2003-2010. 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% %% @@ -349,10 +349,12 @@ make_and_check_dummy() -> -define(DFLAG_ATOM_CACHE,2). -define(DFLAG_EXTENDED_REFERENCES,4). -define(DFLAG_EXTENDED_PIDS_PORTS,16#100). +-define(DFLAG_NEW_FLOATS,16#800). -define(DFLAG_DIST_MONITOR,8). %% From R9 and forward extended references is compulsory --define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor ?DFLAG_EXTENDED_PIDS_PORTS)). +%% From 14 and forward new float is compulsory +-define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor ?DFLAG_EXTENDED_PIDS_PORTS bor ?DFLAG_NEW_FLOATS)). -define(shutdown(X), exit(X)). -define(int16(X), [((X) bsr 8) band 16#ff, (X) band 16#ff]). diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/eterm_test.c b/lib/erl_interface/test/erl_eterm_SUITE_data/eterm_test.c index 6b2ec8f766..80d7f69520 100644 --- a/lib/erl_interface/test/erl_eterm_SUITE_data/eterm_test.c +++ b/lib/erl_interface/test/erl_eterm_SUITE_data/eterm_test.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1997-2009. All Rights Reserved. + * Copyright Ericsson AB 1997-2010. 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 @@ -63,32 +63,124 @@ TESTCASE(build_terms) report(1); } +static int abs_and_sign(ETERM* v, unsigned long long* av, int* sign) +{ + long long sv; + switch (ERL_TYPE(v)) { + case ERL_INTEGER: sv = ERL_INT_VALUE(v); break; + case ERL_U_INTEGER: *av = ERL_INT_UVALUE(v); *sign = 0; return 1; + case ERL_LONGLONG: sv = ERL_LL_VALUE(v); break; + case ERL_U_LONGLONG: *av = ERL_LL_UVALUE(v); *sign = 0; return 1; + default: return 0; + } + if (sv < 0) { + *av = -sv; + *sign = 1; + } + else { + *av = sv; + *sign = 0; + } + return 1; +} + +/* Shouldn't erl_match() cope with this? +*/ +static int eq_ints(ETERM* a, ETERM* b) +{ + unsigned long long a_abs, b_abs; + int a_sign, b_sign; + return abs_and_sign(a, &a_abs, &a_sign) && abs_and_sign(b, &b_abs, &b_sign) + && (a_abs == b_abs) && (a_sign == b_sign); +} + +static void encode_decode(ETERM* original, const char* text) +{ + static unsigned char encoded[16*1024]; + ETERM* new_terms; + ETERM* head; + int bytes; + int len; + + /* If a list, check the elements one by one first */ + head = erl_hd(original); + if (head != NULL) { + encode_decode(head, "CAR"); + encode_decode(erl_tl(original), "CDR"); + } + + bytes = erl_encode(original, encoded); + if (bytes == 0) { + fail("failed to encode terms"); + } + else if (bytes > sizeof(encoded)) { + fail("encoded terms buffer overflow"); + } + else if (bytes != (len=erl_term_len(original))) { + fprintf(stderr, "bytes(%d) != len(%d) for term ", bytes, len); + erl_print_term(stderr, original); + fprintf(stderr, " [%s]\r\n", text); + fail("erl_encode and erl_term_len do not agree"); + } + else if ((new_terms = erl_decode(encoded)) == NULL) { + fail("failed to decode terms"); + } + else if (!erl_match(original, new_terms) && !eq_ints(original, new_terms)) { + erl_print_term(stderr, original); + fprintf(stderr, "(%i) != (%i)", ERL_TYPE(original), ERL_TYPE(new_terms)); + erl_print_term(stderr, new_terms); + fprintf(stderr, " [%s]\r\n", text); + fail("decoded terms didn't match original"); + } + erl_free_term(original); + erl_free_term(new_terms); +} /* * Converts an Erlang term to the external term format and back again. */ TESTCASE(round_trip_conversion) { - ETERM* original; - ETERM* new_terms; - char encoded[16*1024]; - int n; + int n, i; erl_init(NULL, 0); - original = all_types(); - if (erl_encode(original, encoded) == 0) + encode_decode(all_types(), "ALL"); + { - fail("failed to encode terms"); - } else if ((new_terms = erl_decode(encoded)) == NULL) + int v; + for (v = 8; v; v <<= 1) { + for (i=-4; i<4; i++) { + encode_decode(erl_mk_int(v+i), "INT"); + encode_decode(erl_mk_int(-(v+i)), "NEG INT"); + } + } + } { - fail("failed to decode terms"); - } else if (!erl_match(original, new_terms)) + unsigned int v; + for (v = 8; v; v <<= 1) { + for (i=-4; i<4; i++) { + encode_decode(erl_mk_uint(v+i), "UINT"); + } + } + } { - fail("decoded terms didn't match original"); + long long v; + for (v = 8; v; v <<= 1) { + for (i=-4; i<4; i++) { + encode_decode(erl_mk_longlong(v+i), "LONGLONG"); + encode_decode(erl_mk_longlong(-(v+i)), "NEG LONGLONG"); + } + } + } + { + unsigned long long v; + for (v = 8; v; v <<= 1) { + for (i=-4; i<4; i++) { + encode_decode(erl_mk_ulonglong(v+i), "ULONGLONG"); + } + } } - erl_free_term(original); - erl_free_term(new_terms); report(1); } diff --git a/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c index ba1a6c66da..59e0e0cce7 100644 --- a/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c +++ b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c @@ -82,6 +82,11 @@ TESTCASE(compare_list) { // erlang:term_to_binary([34,{a,n},a,erlang]) unsigned char term2[] = {131,108,0,0,0,4,97,34,104,2,100,0,1,97,100,0,1,110,100,0,1,97,100,0,6,101,114,108,97,110,103,106}; + // erlang:term_to_binary([0]) + unsigned char term3[] = {131,107,0,1,0}; + // erlang:term_to_binary([0, 1000]) + unsigned char term4[] = {131,108,0,0,0,2,97,0,98,0,0,3,232,106}; + erl_init(NULL, 0); start_a = term1; start_b = term2; @@ -90,6 +95,13 @@ TESTCASE(compare_list) { test_compare_ext("lists", start_a, end_a, start_b, end_b, 1); + start_a = term3; + start_b = term4; + end_a = term3 + sizeof(term3); + end_b = term4 + sizeof(term4); + + test_compare_ext("lists1", start_a, end_a, start_b, end_b, -1); + report(1); } diff --git a/lib/erl_interface/test/erl_global_SUITE.erl b/lib/erl_interface/test/erl_global_SUITE.erl new file mode 100644 index 0000000000..4f332037c6 --- /dev/null +++ b/lib/erl_interface/test/erl_global_SUITE.erl @@ -0,0 +1,133 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-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% +%% + +%% +-module(erl_global_SUITE). + +-include("test_server.hrl"). +-include("erl_global_SUITE_data/erl_global_test_cases.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + erl_global_registration/1, erl_global_whereis/1, erl_global_names/1]). + +-import(runner, [get_term/1,send_term/2]). + +-define(GLOBAL_NAME, global_register_node_test). + +all(suite) -> + [erl_global_registration, erl_global_whereis, erl_global_names]. + +init_per_testcase(_Case, Config) -> + Dog = ?t:timetrap(?t:minutes(0.25)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +erl_global_registration(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line {ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0), + + ?line ok = erl_global_register(P, Fd, ?GLOBAL_NAME), + ?line ok = erl_global_unregister(P, Fd, ?GLOBAL_NAME), + + ?line 0 = erl_close_connection(P,Fd), + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +erl_global_whereis(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line {ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0), + + ?line Self = self(), + ?line yes = global:register_name(?GLOBAL_NAME, Self), + ?line Self = erl_global_whereis(P, Fd, ?GLOBAL_NAME), + ?line global:unregister_name(?GLOBAL_NAME), + ?line 0 = erl_close_connection(P, Fd), + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +erl_global_names(Config) when is_list(Config) -> + ?line P = runner:start(?interpret), + ?line {ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0), + + ?line Self = self(), + ?line global:register_name(?GLOBAL_NAME, Self), + ?line {Names1, _N1} = erl_global_names(P, Fd), + ?line true = lists:member(atom_to_list(?GLOBAL_NAME), Names1), + ?line global:unregister_name(?GLOBAL_NAME), + ?line {Names2, _N2} = erl_global_names(P, Fd), + ?line false = lists:member(atom_to_list(?GLOBAL_NAME), Names2), + ?line 0 = erl_close_connection(P, Fd), + ?line runner:send_eot(P), + ?line runner:recv_eot(P), + ok. + +%%% Interface functions for erl_interface functions. + +erl_connect(P, Node, Num, Cookie, Creation) -> + send_command(P, erl_connect, [Num, Node, Cookie, Creation]), + case get_term(P) of + {term,{Fd,_}} when Fd >= 0 -> {ok,Fd}; + {term,{-1,Errno}} -> {error,Errno} + end. + +erl_close_connection(P, FD) -> + send_command(P, erl_close_connection, [FD]), + case get_term(P) of + {term,Int} when is_integer(Int) -> Int + end. + +erl_global_register(P, Fd, Name) -> + send_command(P, erl_global_register, [Fd,Name]), + get_send_result(P). + +erl_global_whereis(P, Fd, Name) -> + send_command(P, erl_global_whereis, [Fd,Name]), + case get_term(P) of + {term, What} -> + What + end. + +erl_global_names(P, Fd) -> + send_command(P, erl_global_names, [Fd]), + case get_term(P) of + {term, What} -> + What + end. + +erl_global_unregister(P, Fd, Name) -> + send_command(P, erl_global_unregister, [Fd,Name]), + get_send_result(P). + +get_send_result(P) -> + case get_term(P) of + {term,{1,_}} -> ok; + {term,{0, 0}} -> ok; + {term,{-1, Errno}} -> {error,Errno}; + {term,{_,_}}-> + ?t:fail(bad_return_value) + end. + +send_command(P, Name, Args) -> + runner:send_term(P, {Name,list_to_tuple(Args)}). diff --git a/lib/erl_interface/test/erl_global_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_global_SUITE_data/Makefile.first new file mode 100644 index 0000000000..8e3fcb924e --- /dev/null +++ b/lib/erl_interface/test/erl_global_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2010. 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% +# + +erl_global_test_decl.c: erl_global_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run erl_global_test -s erlang halt diff --git a/lib/erl_interface/test/erl_global_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_global_SUITE_data/Makefile.src new file mode 100644 index 0000000000..ef846bc440 --- /dev/null +++ b/lib/erl_interface/test/erl_global_SUITE_data/Makefile.src @@ -0,0 +1,41 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2000-2010. 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 @erl_interface_mk_include@@[email protected] + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBERL = $(LIBPATH)/@erl_interface_lib@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/runner@obj@ \ + $(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +OBJS = erl_global_test@obj@ erl_global_test_decl@obj@ + +all: erl_global_test@exe@ + +erl_global_test@exe@: $(OBJS) $(LIBERL) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(OBJS) $(LIBFLAGS) + +clean: + $(RM) $(OBJS) + $(RM) erl_global_test@exe@ diff --git a/lib/erl_interface/test/erl_global_SUITE_data/erl_global_test.c b/lib/erl_interface/test/erl_global_SUITE_data/erl_global_test.c new file mode 100644 index 0000000000..dc0d8a0091 --- /dev/null +++ b/lib/erl_interface/test/erl_global_SUITE_data/erl_global_test.c @@ -0,0 +1,263 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2000-2010. 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% + */ + +/* + * Purpose: Tests the functions in erl_global.c. + * + * See the erl_global_SUITE.erl file for a "table of contents". + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "runner.h" + +static void cmd_erl_connect(ETERM* args); +static void cmd_erl_global_register(ETERM *args); +static void cmd_erl_global_whereis(ETERM *args); +static void cmd_erl_global_names(ETERM *args); +static void cmd_erl_global_unregister(ETERM *args); +static void cmd_erl_close_connection(ETERM *args); + +static void send_errno_result(int value); + +static struct { + char* name; + int num_args; /* Number of arguments. */ + void (*func)(ETERM* args); +} commands[] = { + "erl_connect", 4, cmd_erl_connect, + "erl_close_connection", 1, cmd_erl_close_connection, + "erl_global_register", 2, cmd_erl_global_register, + "erl_global_whereis", 2, cmd_erl_global_whereis, + "erl_global_names", 1, cmd_erl_global_names, + "erl_global_unregister", 2, cmd_erl_global_unregister, +}; + + +/* + * Sends a list contaning all data types to the Erlang side. + */ + +TESTCASE(interpret) +{ + ETERM* term; + + erl_init(NULL, 0); + + outer_loop: + + term = get_term(); + + if (term == NULL) { + report(1); + return; + } else { + ETERM* Func; + ETERM* Args; + int i; + + if (!ERL_IS_TUPLE(term) || ERL_TUPLE_SIZE(term) != 2) { + fail("term should be a tuple of size 2"); + } + + Func = erl_element(1, term); + if (!ERL_IS_ATOM(Func)) { + fail("function name should be an atom"); + } + Args = erl_element(2, term); + if (!ERL_IS_TUPLE(Args)) { + fail("function arguments should be a tuple"); + } + erl_free_term(term); + for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) { + int n = strlen(commands[i].name); + if (ERL_ATOM_SIZE(Func) != n) { + continue; + } + if (memcmp(ERL_ATOM_PTR(Func), commands[i].name, n) == 0) { + erl_free_term(Func); + if (ERL_TUPLE_SIZE(Args) != commands[i].num_args) { + fail("wrong number of arguments"); + } + commands[i].func(Args); + erl_free_term(Args); + goto outer_loop; + } + } + fail("bad command"); + } +} + +#define VERIFY_TYPE(Test, Term) \ +if (!Test(Term)) { \ + fail("wrong type for " #Term); \ +} else { \ +} + +static void +cmd_erl_connect(ETERM* args) +{ + ETERM* number; + ETERM* node; + ETERM* cookie; + + int res; + char buffer[256]; + + number = ERL_TUPLE_ELEMENT(args, 0); + VERIFY_TYPE(ERL_IS_INTEGER, number); + node = ERL_TUPLE_ELEMENT(args, 1); + VERIFY_TYPE(ERL_IS_ATOM, node); + cookie = ERL_TUPLE_ELEMENT(args, 2); + VERIFY_TYPE(ERL_IS_ATOM, cookie); + + if (ERL_ATOM_SIZE(cookie) == 0) { + res = erl_connect_init(ERL_INT_VALUE(number), 0, 0); + } else { + memcpy(buffer, ERL_ATOM_PTR(cookie), ERL_ATOM_SIZE(cookie)); + buffer[ERL_ATOM_SIZE(cookie)] = '\0'; + res = erl_connect_init(ERL_INT_VALUE(number), buffer, 0); + } + + if(!res) { + send_errno_result(res); + return; + } + + memcpy(buffer, ERL_ATOM_PTR(node), ERL_ATOM_SIZE(node)); + buffer[ERL_ATOM_SIZE(node)] = '\0'; + send_errno_result(erl_connect(buffer)); +} + +static void +cmd_erl_close_connection(ETERM* args) +{ + ETERM* number; + ETERM* res; + + number = ERL_TUPLE_ELEMENT(args, 0); + VERIFY_TYPE(ERL_IS_INTEGER, number); + res = erl_mk_int(erl_close_connection(ERL_INT_VALUE(number))); + send_term(res); + erl_free_term(res); +} + +static void +cmd_erl_global_register(ETERM* args) +{ + ETERM* fd_term = ERL_TUPLE_ELEMENT(args, 0); + ETERM* name = ERL_TUPLE_ELEMENT(args, 1); + ETERM* pid = erl_mk_pid(erl_thisnodename(), 14, 0, 0); + + char buffer[256]; + + VERIFY_TYPE(ERL_IS_INTEGER, fd_term); + VERIFY_TYPE(ERL_IS_ATOM, name); + + memcpy(buffer, ERL_ATOM_PTR(name), ERL_ATOM_SIZE(name)); + buffer[ERL_ATOM_SIZE(name)] = '\0'; + + send_errno_result(erl_global_register(ERL_INT_VALUE(fd_term), buffer, pid)); + erl_free_term(pid); +} + +static void +cmd_erl_global_whereis(ETERM* args) +{ + ETERM* fd_term = ERL_TUPLE_ELEMENT(args, 0); + ETERM* name = ERL_TUPLE_ELEMENT(args, 1); + ETERM* pid = NULL; + + char buffer[256]; + + VERIFY_TYPE(ERL_IS_INTEGER, fd_term); + VERIFY_TYPE(ERL_IS_ATOM, name); + + memcpy(buffer, ERL_ATOM_PTR(name), ERL_ATOM_SIZE(name)); + buffer[ERL_ATOM_SIZE(name)] = '\0'; + + pid = erl_global_whereis(ERL_INT_VALUE(fd_term), buffer, NULL); + send_term(pid); + erl_free_term(pid); +} + +static void +cmd_erl_global_names(ETERM* args) +{ + ETERM* fd_term = ERL_TUPLE_ELEMENT(args, 0); + + ETERM* res_array[2], *res_tuple, *name; + char** names = NULL; + int count = 0, i; + + VERIFY_TYPE(ERL_IS_INTEGER, fd_term); + + names = erl_global_names(ERL_INT_VALUE(fd_term), &count); + + res_array[0] = erl_mk_empty_list(); + for(i=0; i<count; i++) { + name = erl_mk_string(names[i]); + res_array[0] = erl_cons(name, res_array[0]); + } + + free(names); + + res_array[1] = erl_mk_int(count); + res_tuple = erl_mk_tuple(res_array, 2); + + send_term(res_tuple); + + erl_free_compound(res_array[0]); + erl_free_term(res_array[1]); + erl_free_term(res_tuple); +} + +static void +cmd_erl_global_unregister(ETERM* args) +{ + ETERM* fd_term = ERL_TUPLE_ELEMENT(args, 0); + ETERM* name = ERL_TUPLE_ELEMENT(args, 1); + + char buffer[256]; + + VERIFY_TYPE(ERL_IS_INTEGER, fd_term); + VERIFY_TYPE(ERL_IS_ATOM, name); + + memcpy(buffer, ERL_ATOM_PTR(name), ERL_ATOM_SIZE(name)); + buffer[ERL_ATOM_SIZE(name)] = '\0'; + + send_errno_result(erl_global_unregister(ERL_INT_VALUE(fd_term), buffer)); +} + +static void +send_errno_result(int value) +{ + ETERM* res_array[2]; + ETERM* res_tuple; + + res_array[0] = erl_mk_int(value); + res_array[1] = erl_mk_int(erl_errno); + res_tuple = erl_mk_tuple(res_array, 2); + send_term(res_tuple); + erl_free_term(res_array[0]); + erl_free_term(res_array[1]); + erl_free_term(res_tuple); +} diff --git a/lib/erl_interface/test/port_call_SUITE.erl b/lib/erl_interface/test/port_call_SUITE.erl index 895e29ad2e..2c550e4c0c 100644 --- a/lib/erl_interface/test/port_call_SUITE.erl +++ b/lib/erl_interface/test/port_call_SUITE.erl @@ -42,6 +42,8 @@ all(suite) -> basic(suite) -> []; basic(Config) when is_list(Config) -> case os:type() of + {unix, linux} -> + do_basic(Config); {unix, sunos} -> do_basic(Config); {win32,_} -> diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk index 589b9e2f9c..ffda886553 100644 --- a/lib/erl_interface/vsn.mk +++ b/lib/erl_interface/vsn.mk @@ -1 +1 @@ -EI_VSN = 3.6.5 +EI_VSN = 3.7.2 |