diff options
Diffstat (limited to 'lib/erl_interface')
132 files changed, 2133 insertions, 17526 deletions
diff --git a/lib/erl_interface/Makefile b/lib/erl_interface/Makefile index 9471b0df18..633e705b3f 100644 --- a/lib/erl_interface/Makefile +++ b/lib/erl_interface/Makefile @@ -31,3 +31,5 @@ SPECIAL_TARGETS = # Default Subdir Targets # ---------------------------------------------------- include $(ERL_TOP)/make/otp_subdir.mk + +include $(ERL_TOP)/make/app_targets.mk diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in index 230dba25d6..55baae7479 100644 --- a/lib/erl_interface/configure.in +++ b/lib/erl_interface/configure.in @@ -336,6 +336,10 @@ if test "X$host" = "Xwin32"; then LIB_CFLAGS="$CFLAGS" else if test "x$GCC" = xyes; then + # Remove all PIE stuff + CFLAGS=`echo $CFLAGS | sed 's/-f\(no-\)\?PIE//g'` + LDFLAGS=`echo $LDFLAGS | sed 's/-\(no-\)\?pie//g'` + LIB_CFLAGS="$CFLAGS -fPIC" else LIB_CFLAGS="$CFLAGS" diff --git a/lib/erl_interface/doc/src/Makefile b/lib/erl_interface/doc/src/Makefile index 03044a0ddd..95f3e77c61 100644 --- a/lib/erl_interface/doc/src/Makefile +++ b/lib/erl_interface/doc/src/Makefile @@ -36,93 +36,24 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # Target Specs # ---------------------------------------------------- -XML_REF1_FILES = erl_call.xml -XML_REF3_FILES = erl_connect.xml \ - erl_error.xml \ - erl_eterm.xml \ - erl_format.xml \ - erl_malloc.xml \ - erl_marshal.xml \ - erl_global.xml \ +XML_REF1_FILES = erl_call_cmd.xml +XML_REF3_FILES = ei_global.xml \ ei.xml \ ei_connect.xml \ registry.xml BOOK_FILES = book.xml XML_APPLICATION_FILES = ref_man.xml -#ref_man_ei.xml ref_man_erl_interface.xml + XML_PART_FILES = \ part.xml XML_CHAPTER_FILES = ei_users_guide.xml notes.xml XML_FILES = $(XML_REF1_FILES) $(XML_REF3_FILES) $(BOOK_FILES) \ $(XML_APPLICATION_FILES) $(XML_PART_FILES) $(XML_CHAPTER_FILES) -# ---------------------------------------------------- - -HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ - $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) - -INFO_FILE = ../../info - -GIF_FILES = - -MAN1_FILES = $(XML_REF1_FILES:%.xml=$(MAN1DIR)/%.1) -MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) - -HTML_REF_MAN_FILE = $(HTMLDIR)/index.html -TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf +NO_CHUNKS=$(XML_REF3_FILES) # ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -XML_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- -$(HTMLDIR)/%.gif: %.gif - $(INSTALL_DATA) $< $@ - -docs: pdf html man - -$(TOP_PDF_FILE): $(XML_FILES) - -pdf: $(TOP_PDF_FILE) - -html: gifs $(HTML_REF_MAN_FILE) - -man: $(MAN1_FILES) $(MAN3_FILES) - -gifs: $(GIF_FILES:%=$(HTMLDIR)/%) - -debug opt lcnt: - -clean clean_docs clean_tex: - rm -rf $(HTMLDIR)/* - rm -rf $(XMLDIR) - rm -f $(MAN1DIR)/* - rm -f $(MAN3DIR)/* - rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) - rm -f errs core *~ - - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_docs_spec: docs - $(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf" - $(INSTALL_DIR) "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(HTMLDIR)/* \ - "$(RELSYSDIR)/doc/html" - $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man1" - $(INSTALL_DATA) $(MAN1_FILES) "$(RELEASE_PATH)/man/man1" - $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3" - $(INSTALL_DATA) $(MAN3_FILES) "$(RELEASE_PATH)/man/man3" - -release_spec: +include $(ERL_TOP)/make/doc.mk diff --git a/lib/erl_interface/doc/src/ei.xml b/lib/erl_interface/doc/src/ei.xml index 70af5642da..232871e864 100644 --- a/lib/erl_interface/doc/src/ei.xml +++ b/lib/erl_interface/doc/src/ei.xml @@ -49,14 +49,9 @@ <p><c>ei</c> also handles C-nodes, C-programs that talks Erlang distribution with Erlang nodes (or other C-nodes) using the - Erlang distribution format. The difference between <c>ei</c> - and <c>erl_interface</c> is that <c>ei</c> uses - the binary format directly when sending and receiving terms. It is also + Erlang distribution format.The <c>ei</c> library is thread safe, and using threads, one process can handle multiple - C-nodes. The <c>erl_interface</c> library is built on top of - <c>ei</c>, but of legacy reasons, it does not allow for - multiple C-nodes. In general, <c>ei</c> is the preferred way - of doing C-nodes.</p> + C-nodes.</p> <p>The decode and encode functions use a buffer and an index into the buffer, which points at the point where to encode and @@ -378,22 +373,6 @@ typedef enum { </func> <func> - <name since=""><ret>int</ret><nametext>ei_decode_term(const char *buf, int *index, void *t)</nametext></name> - <fsummary>Decode a <c>ETERM</c>.</fsummary> - <desc> - <p>Decodes a term from the binary format. The term - is return in <c>t</c> as a <c>ETERM*</c>, so - <c>t</c> is actually an <c>ETERM**</c> (see - <seealso marker="erl_eterm"><c>erl_eterm</c></seealso>). - The term is later to be deallocated.</p> - <note><p>This function is deprecated as of OTP 22 and will be removed in - OTP 23 together with the old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>).</p> - </note> - </desc> - </func> - - <func> <name since=""><ret>int</ret><nametext>ei_decode_trace(const char *buf, int *index, erlang_trace *p)</nametext></name> <fsummary>Decode a trace token.</fsummary> <desc> @@ -707,22 +686,6 @@ ei_x_encode_string(&x, "Banana");</pre> the <c>ei_x_encode_string_len()</c> function.</p> </desc> </func> - - <func> - <name since=""><ret>int</ret><nametext>ei_encode_term(char *buf, int *index, void *t)</nametext></name> - <name since=""><ret>int</ret><nametext>ei_x_encode_term(ei_x_buff* x, void *t)</nametext></name> - <fsummary>Encode an <c>erl_interface</c> term.</fsummary> - <desc> - <p>Encodes an <c>ETERM</c>, as obtained from - <c>erl_interface</c>. Parameter <c>t</c> is - actually an <c>ETERM</c> pointer. This function - does not free the <c>ETERM</c>.</p> - <note><p>These functions are deprecated as of OTP 22 and will be removed in - OTP 23 together with the old legacy <c>erl_interface</c> library - (functions with prefix <c>erl_</c>).</p> - </note> - </desc> - </func> <func> <name since=""><ret>int</ret><nametext>ei_encode_trace(char *buf, int *index, const erlang_trace *p)</nametext></name> <name since=""><ret>int</ret><nametext>ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p)</nametext></name> @@ -806,11 +769,7 @@ ei_encode_tuple_header(buf, &i, 0);</pre> <desc> <p>Initialize the <c>ei</c> library. This function should be called once (and only once) before calling any other functionality in the <c>ei</c> - library. However, note the exception below.</p> - <p>If the <c>ei</c> library is used together with the <c>erl_interface</c> - library, this function should <em>not</em> be called directly. It will be - called by the <c>erl_init()</c> function which should be used to initialize - the combination of the two libraries instead.</p> + library.</p> <p>On success zero is returned. On failure a posix error code is returned.</p> </desc> </func> @@ -990,8 +949,4 @@ encodes the tuple {numbers,12,3.14159}</pre> </list> </section> - <section> - <title>See Also</title> - <p><seealso marker="erl_eterm"><c>erl_eterm</c></seealso></p> - </section> </cref> diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml index 795f1249b3..06fe9d1960 100644 --- a/lib/erl_interface/doc/src/ei_connect.xml +++ b/lib/erl_interface/doc/src/ei_connect.xml @@ -422,6 +422,8 @@ typedef struct { <func> <name since=""><ret>int</ret><nametext>ei_connect(ei_cnode* ec, char *nodename)</nametext></name> <name since=""><ret>int</ret><nametext>ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename)</nametext></name> + <name since="OTP @OTP-16251@"><ret>int</ret><nametext>ei_connect_host_port(ei_cnode* ec, char *hostname, int port)</nametext></name> + <name since="OTP @OTP-16251@"><ret>int</ret><nametext>ei_xconnect_host_port(ei_cnode* ec, Erl_IpAddr adr, int port)</nametext></name> <fsummary>Establish a connection to an Erlang node.</fsummary> <desc> <p>Sets up a connection to an Erlang node.</p> @@ -429,13 +431,21 @@ typedef struct { remote host and the alive name of the remote node to be specified. <c>ei_connect()</c> provides an alternative interface and determines the information from the node name - provided.</p> + provided. The <c>ei_xconnect_host_port()</c> function provides + yet another alternative that will work even if there is no + EPMD instance on the host where the remote node is running. The + <c>ei_xconnect_host_port()</c> function requires the IP + address and port of the remote node to be specified. + The <c>ei_connect_host_port()</c> function is an alternative + to <c>ei_xconnect_host_port()</c> that lets the user specify + a hostname instead of an IP address.</p> <list type="bulleted"> - <item><c>addr</c> is the 32-bit IP address of the remote + <item><c>adr</c> is the 32-bit IP address of the remote host.</item> <item><c>alive</c> is the alivename of the remote node. </item> <item><c>node</c> is the name of the remote node.</item> + <item><c>port</c> is the port number of the remote node.</item> </list> <p>These functions return an open file descriptor on success, or a negative value indicating that an error occurred. In the latter @@ -571,13 +581,16 @@ if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) { <func> <name since=""><ret>int</ret><nametext>ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned timeout_ms)</nametext></name> <name since=""><ret>int</ret><nametext>ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned timeout_ms)</nametext></name> + <name since="OTP @OTP-16251@"><ret>int</ret><nametext>ei_connect_host_port_tmo(ei_cnode* ec, char *hostname, int port, unsigned ms)</nametext></name> + <name since="OTP @OTP-16251@"><ret>int</ret><nametext>ei_xconnect_host_port_tmo(ei_cnode* ec, Erl_IpAddr adr, int port, unsigned ms)</nametext></name> <fsummary>Establish a connection to an Erlang node with optional time-out.</fsummary> <desc> - <p>Equivalent to - <c>ei_connect</c> and <c>ei_xconnect</c> with an optional time-out - argument, see the description at the beginning of this manual - page.</p> + <p>Equivalent to <c>ei_connect</c>, <c>ei_xconnect</c>, + <c>ei_connect_host_port</c> and + <c>ei_xconnect_host_port</c> with an optional time-out + argument, see the description at the beginning of this manual + page.</p> </desc> </func> diff --git a/lib/erl_interface/doc/src/erl_global.xml b/lib/erl_interface/doc/src/ei_global.xml index 39085b46f0..4c6b94f7dd 100644 --- a/lib/erl_interface/doc/src/erl_global.xml +++ b/lib/erl_interface/doc/src/ei_global.xml @@ -22,7 +22,7 @@ </legalnotice> - <title>erl_global</title> + <title>ei_global</title> <prepared>Gordon Beaton</prepared> <responsible>Gordon Beaton</responsible> <docno></docno> @@ -30,20 +30,14 @@ <checked>Gordon Beaton</checked> <date>1998-07-03</date> <rev>A</rev> - <file>erl_global.xml</file> + <file>ei_global.xml</file> </header> - <lib>erl_global</lib> + <lib>ei_global</lib> <libsummary>Access globally registered names.</libsummary> <description> <note><p>The support for VxWorks is deprecated as of OTP 22, and will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> - + <p>This module provides support for registering, looking up, and unregistering names in the <c>global</c> module. For more information, see @@ -57,15 +51,17 @@ <funcs> <func> - <name since=""><ret>char **</ret><nametext>erl_global_names(fd,count)</nametext></name> + <name since=""><ret>char **</ret><nametext>ei_global_names(ec,fd,count)</nametext></name> <fsummary>Obtain list of global names.</fsummary> <type> + <v>ei_cnode *ec;</v> <v>int fd;</v> <v>int *count;</v> </type> <desc> <p>Retrieves a list of all known global names.</p> <list type="bulleted"> + <item><c>ec</c> is the ei_cnode representing the current cnode.</item> <item><c>fd</c> is an open descriptor to an Erlang connection.</item> <item><c>count</c> is the address of an integer, or @@ -88,12 +84,12 @@ </func> <func> - <name since=""><ret>int</ret><nametext>erl_global_register(fd,name,pid)</nametext></name> + <name since=""><ret>int</ret><nametext>ei_global_register(fd,name,pid)</nametext></name> <fsummary>Register a name in global.</fsummary> <type> <v>int fd;</v> <v>const char *name;</v> - <v>ETERM *pid;</v> + <v>erlang_pid *pid;</v> </type> <desc> <p>Registers a name in <c>global</c>.</p> @@ -112,15 +108,17 @@ </func> <func> - <name since=""><ret>int</ret><nametext>erl_global_unregister(fd,name)</nametext></name> + <name since=""><ret>int</ret><nametext>ei_global_unregister(ec,fd,name)</nametext></name> <fsummary>Unregister a name from global.</fsummary> <type> + <v>ei_cnode *ec;</v> <v>int fd;</v> <v>const char *name;</v> </type> <desc> <p>Unregisters a name from <c>global</c>.</p> <list type="bulleted"> + <item><c>ec</c> is the ei_cnode representing the current cnode.</item> <item><c>fd</c> is an open descriptor to an Erlang connection.</item> <item><c>name</c> is the name to unregister from @@ -131,30 +129,35 @@ </func> <func> - <name since=""><ret>ETERM *</ret><nametext>erl_global_whereis(fd,name,node)</nametext></name> + <name since=""><ret>int</ret><nametext>ei_global_whereis(ec,fd,name,pid,node)</nametext></name> <fsummary>Look up a name in global.</fsummary> <type> + <v>ei_cnode *ec;</v> <v>int fd;</v> <v>const char *name;</v> + <v>erlang_pid* pid;</v> <v>char *node;</v> </type> <desc> <p>Looks up a name in <c>global</c>.</p> <list type="bulleted"> + <item><c>ec</c> is the ei_cnode representing the current cnode.</item> <item><c>fd</c> is an open descriptor to an Erlang connection.</item> <item><c>name</c> is the name that is to be looked up in <c>global</c>.</item> </list> + <p>The <c>pid</c> parameter is a pointer to a + <c>erlang_pid</c> that the function will update with the pid associated + with the global name, if successful.</p> <p>If <c>node</c> is not <c>NULL</c>, it is a pointer to a buffer where the function can fill in the name of the node where <c>name</c> is found. <c>node</c> can be - passed directly to <c>erl_connect()</c> if necessary.</p> - <p>On success, the function returns an Erlang pid containing the address - of the specified name, and the node is initialized to + passed directly to <c>ei_connect()</c> if necessary.</p> + <p>On success, the function returns 0, updates the <c>erlang_pid</c> + pointed to by the pid parameter, and the <c>node</c> parameter is initialized to the node name where <c>name</c> is found. On failure, - <c>NULL</c> is returned and <c>node</c> is not - modified.</p> + a negative number is returned.</p> </desc> </func> </funcs> diff --git a/lib/erl_interface/doc/src/ei_users_guide.xml b/lib/erl_interface/doc/src/ei_users_guide.xml index 7ca10d1a99..4ce8b9237f 100644 --- a/lib/erl_interface/doc/src/ei_users_guide.xml +++ b/lib/erl_interface/doc/src/ei_users_guide.xml @@ -37,12 +37,6 @@ <title>Deprecation and Removal</title> <note><p>The support for VxWorks is deprecated as of OTP 22, and will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> </section> <section> @@ -60,14 +54,12 @@ <seealso marker="mnesia:mnesia">Mnesia</seealso></item> </list> <note> - <p>By default, the <c>Erl_Interface</c> libraries are only guaranteed + <p>By default, the <c>Erl_Interface</c> library is only guaranteed to be compatible with other Erlang/OTP components from the same release as the libraries themselves. For information about how to communicate with Erlang/OTP components from earlier releases, see function <seealso marker="ei#ei_set_compat_rel"> - <c>ei:ei_set_compat_rel</c></seealso> and - <seealso marker="erl_eterm#erl_set_compat_rel"> - <c>erl_eterm:erl_set_compat_rel</c></seealso>.</p> + <c>ei_set_compat_rel</c></seealso>.</p> </note> <section> @@ -98,10 +90,9 @@ <section> <title>Compiling and Linking Your Code</title> <p>To use any of the <c>Erl_Interface</c> functions, include the - following lines in your code:</p> + following line in your code:</p> <code type="none"><![CDATA[ -#include "erl_interface.h" #include "ei.h" ]]></code> <p>Determine where the top directory of your OTP installation is. @@ -114,7 +105,7 @@ Eshell V4.7.4 (abort with ^G) /usr/local/otp ]]></code> <p>To compile your code, ensure that your C compiler knows where - to find <c>erl_interface.h</c> by specifying an appropriate + to find <c>ei.h</c> by specifying an appropriate <c>-I</c> argument on the command line, or add it to the <c>CFLAGS</c> definition in your <c>Makefile</c>. The correct value for this path is @@ -140,11 +131,9 @@ $ cc -c -I/usr/local/otp/lib/erl_interface-3.2.3/include myprog.c ]]></code> <p>When linking:</p> <list type="bulleted"> - <item>Specify the path to <c>liberl_interface.a</c> and - <c>libei.a</c> with + <item>Specify the path to <c>libei.a</c> with <c>-L$OTPROOT/lib/erl_interface-3.2.3/lib</c>.</item> - <item>Specify the name of the libraries with - <c>-lerl_interface -lei</c>.</item> + <item>Specify the name of the library with <c>-lei</c>.</item> </list> <p>Do this on the command line or add the flags to the @@ -155,7 +144,7 @@ $ cc -c -I/usr/local/otp/lib/erl_interface-3.2.3/include myprog.c ]]></code> <code type="none"><![CDATA[ $ ld -L/usr/local/otp/lib/erl_interface-3.2.3/ - lib myprog.o -lerl_interface -lei -o myprog ]]></code> + lib myprog.o -lei -o myprog ]]></code> <p>On some systems it can be necessary to link with some more libraries (for example, <c>libnsl.a</c> and @@ -174,19 +163,11 @@ $ ld -L/usr/local/otp/lib/erl_interface-3.2.3/ </section> <section> - <title>Initializing the Libraries</title> + <title>Initializing the Library</title> <p> - Before calling any of the other functions in the <c>erl_interface</c> - and <c>ei</c> libraries, call <c>erl_init()</c> exactly once to initialize - both libraries. - <c>erl_init()</c> takes two arguments. However, the arguments - are no longer used by <c>erl_interface</c> and are therefore to be - specified as <c>erl_init(NULL,0)</c>. - </p> - <p> - If you only use the <c>ei</c> library, instead initialize it by calling - <c>ei_init()</c> exactly once before calling any other functions in - the <c>ei</c> library. + Before calling any of the other functions in the library, + initialize it by calling + <c>ei_init()</c> exactly once. </p> </section> @@ -199,187 +180,93 @@ $ ld -L/usr/local/otp/lib/erl_interface-3.2.3/ <p>The <c>Erl_Interface</c> library supports this activity. It has several C functions that create and manipulate Erlang data - structures. The library also contains an encode and a decode function. - The following example shows how to create and encode an Erlang tuple - <c>{tobbe,3928}</c>:</p> + structures. The following example shows how to create and encode + an Erlang tuple <c>{tobbe,3928}</c>:</p> <code type="none"><![CDATA[ -ETERM *arr[2], *tuple; -char buf[BUFSIZ]; -int i; - -arr[0] = erl_mk_atom("tobbe"); -arr[1] = erl_mk_integer(3928); -tuple = erl_mk_tuple(arr, 2); -i = erl_encode(tuple, buf); ]]></code> - - <p>Alternatively, you can use <c>erl_send()</c> and - <c>erl_receive_msg</c>, which handle the encoding and - decoding of messages transparently.</p> - - <p>For a complete description, see the following modules:</p> - <list type="bulleted"> - <item><seealso marker="erl_eterm"><c>erl_eterm</c></seealso> - for creating Erlang terms</item> - <item><seealso marker="erl_marshal"><c>erl_marshal</c></seealso> - for encoding and decoding routines</item> - </list> +ei_x_buff buf; +ei_x_new(&buf); +int i = 0; +ei_x_encode_tuple_header(&buf, 2); +ei_x_encode_atom(&buf, "tobbe"); +ei_x_encode_long(&buf, 3928); ]]></code> + + <p>For a complete description, see the + <seealso marker="ei"><c>ei</c></seealso> module.</p> </section> <section> <marker id="building_terms_and_patterns"/> - <title>Building Terms and Patterns</title> + <title>Building Terms</title> <p>The previous example can be simplified by using the - <seealso marker="erl_format"><c>erl_format</c></seealso> module + <seealso marker="ei#ei_x_format_wo_ver"><c>ei_x_format_wo_ver</c></seealso> function to create an Erlang term:</p> <code type="none"><![CDATA[ -ETERM *ep; -ep = erl_format("{~a,~i}", "tobbe", 3928); ]]></code> +ei_x_buff buf; +ei_x_new(&buf); +ei_x_format_wo_ver(&buf, "{~a,~i}", "tobbe", 3928); ]]></code> - <p>For a complete description of the different format directives, see - the <seealso marker="erl_format"><c>erl_format</c></seealso> module.</p> + <p>For a complete description of the different format directives, see the + the <seealso marker="ei#ei_x_format_wo_ver"><c>ei_x_format_wo_ver</c></seealso> function.</p> <p>The following example is more complex:</p> <code type="none"><![CDATA[ -ETERM *ep; -ep = erl_format("[{name,~a},{age,~i},{data,~w}]", - "madonna", - 21, - erl_format("[{adr,~s,~i}]", "E-street", 42)); -erl_free_compound(ep); ]]></code> +ei_x_buff buf; +int i = 0; +ei_x_new(&buf); +ei_x_format_wo_ver(&buf, + "[{name,~a},{age,~i},{data,[{adr,~s,~i}]}]", + "madonna", + 21, + "E-street", 42); +ei_print_term(stdout, buf.buff, &i); +ei_x_free(&buf); ]]></code> <p>As in the previous examples, it is your responsibility to free the memory allocated for Erlang terms. In this example, - <c>erl_free_compound()</c> ensures that the complete term - pointed to by <c>ep</c> is released. This is necessary - because the pointer from the second call to <c>erl_format</c> is lost.</p> - - <p>The following example shows a slightly different solution:</p> - - <code type="none"><![CDATA[ -ETERM *ep,*ep2; -ep2 = erl_format("[{adr,~s,~i}]","E-street",42); -ep = erl_format("[{name,~a},{age,~i},{data,~w}]", - "madonna", 21, ep2); -erl_free_term(ep); -erl_free_term(ep2); ]]></code> - - <p>In this case, you free the two terms independently. The order in - which you free the terms <c>ep</c> and <c>ep2</c> - is not important, - because the <c>Erl_Interface</c> library uses reference counting to - determine when it is safe to remove objects.</p> - - <p>If you are unsure whether you have freed the terms properly, you - can use the following function to see the status of the fixed term - allocator:</p> - - <code type="none"><![CDATA[ -long allocated, freed; - -erl_eterm_statistics(&allocated,&freed); -printf("currently allocated blocks: %ld\n",allocated); -printf("length of freelist: %ld\n",freed); - -/* really free the freelist */ -erl_eterm_release(); - ]]></code> - - <p>For more information, see the - <seealso marker="erl_malloc"><c>erl_malloc</c></seealso> module.</p> - </section> - - <section> - <title>Pattern Matching</title> - <p>An Erlang pattern is a term that can contain unbound variables or - <c>"do not care"</c> symbols. Such a pattern can be matched - against a - term and, if the match is successful, any unbound variables in the - pattern will be bound as a side effect. The content of a bound - variable can then be retrieved:</p> - - <code type="none"><![CDATA[ -ETERM *pattern; -pattern = erl_format("{madonna,Age,_}"); ]]></code> - - <p>The <seealso marker="erl_format#erl_match"> - <c>erl_format:erl_match</c></seealso> function - performs pattern matching. It takes a - pattern and a term and tries to match them. As a side effect any unbound - variables in the pattern will be bound. In the following example, a - pattern is created with a variable <c>Age</c>, which is included at two - positions in the tuple. The pattern match is performed as follows:</p> - - <list type="bulleted"> - <item> - <p><c>erl_match</c> binds the contents of <c>Age</c> to <c>21</c> - the first time it reaches the variable.</p> - </item> - <item> - <p>The second occurrence of <c>Age</c> causes a test for - equality between the terms, as <c>Age</c> is already bound to - <c>21</c>. As <c>Age</c> is bound to <c>21</c>, the equality test - succeeds and the match continues until the end of the pattern.</p> - </item> - <item> - <p>If the end of the pattern is reached, the match succeeds and you - can retrieve the contents of the variable.</p> - </item> - </list> - - <code type="none"><![CDATA[ -ETERM *pattern,*term; -pattern = erl_format("{madonna,Age,Age}"); -term = erl_format("{madonna,21,21}"); -if (erl_match(pattern, term)) { - fprintf(stderr, "Yes, they matched: Age = "); - ep = erl_var_content(pattern, "Age"); - erl_print_term(stderr, ep); - fprintf(stderr,"\n"); - erl_free_term(ep); -} -erl_free_term(pattern); -erl_free_term(term); ]]></code> + <c>ei_x_free()</c> ensures that the data + pointed to by <c>buf</c> is released.</p> - <p>For more information, see the - <seealso marker="erl_format#erl_match"> - <c>erl_format:erl_match</c></seealso> function.</p> </section> <section> <title>Connecting to a Distributed Erlang Node</title> <p>To connect to a distributed Erlang node, you must first - initialize the connection routine with - <seealso marker="erl_connect#erl_connect_init"> - <c>erl_connect:erl_connect_init</c></seealso>, - which stores information, such as the hostname, node name, and IP - address for later use:</p> + initialize the connection routine with one of the + <seealso marker="ei_connect#ei_connect_init"> + <c>ei_connect_init_*</c></seealso> functions, + which stores information, such as the hostname, and node name + for later use:</p> <code type="none"><![CDATA[ int identification_number = 99; int creation=1; char *cookie="a secret cookie string"; /* An example */ -erl_connect_init(identification_number, cookie, creation); ]]></code> +const char* node_name = "einode@durin"; +const char *cookie = NULL; +short creation = time(NULL) + 1; +ei_cnode ec; +ei_connect_init(ec, + node_name, + cookie, + creation); ]]></code> <p>For more information, see the - <seealso marker="erl_connect"><c>erl_connect</c></seealso> module.</p> + <seealso marker="ei_connect"><c>ei_connect</c></seealso> module.</p> <p>After initialization, you set up the connection to the Erlang node. - To specify the Erlang node you want to connect to, use - <c>erl_connect()</c>. The following example sets up the + To specify the Erlang node you want to connect to, use the + <c>ei_connect_*()</c> family of functions. The following example sets up the connection and is to result in a valid socket file descriptor:</p> <code type="none"><![CDATA[ int sockfd; -char *nodename="xyz@chivas.du.etx.ericsson.se"; /* An example */ -if ((sockfd = erl_connect(nodename)) < 0) - erl_err_quit("ERROR: erl_connect failed"); ]]></code> +const char* node_name = "einode@durin"; /* An example */ +if ((sockfd = ei_connect(ec, nodename)) < 0) + fprintf(stderr, "ERROR: ei_connect failed"); ]]></code> - <p><c>erl_err_quit()</c> prints the specified string and - terminates the program. For more information, see the - <seealso marker="erl_error"><c>erl_error</c></seealso> module.</p> </section> <section> @@ -394,7 +281,7 @@ if ((sockfd = erl_connect(nodename)) < 0) correct port number to connect to.</p> <p>When you use - <seealso marker="erl_connect"><c>erl_connect</c></seealso> + <seealso marker="ei_connect"><c>ei_connect</c></seealso> to connect to an Erlang node, a connection is first made to <c>epmd</c> and, if the node is known, a connection is then made to the Erlang node.</p> @@ -409,7 +296,7 @@ if ((sockfd = erl_connect(nodename)) < 0) <code type="none"><![CDATA[ int pub; -pub = erl_publish(port); ]]></code> +pub = ei_publish(ec, port); ]]></code> <p><c>pub</c> is a file descriptor now connected to <c>epmd</c>. <c>epmd</c> @@ -424,17 +311,9 @@ pub = erl_publish(port); ]]></code> failed. If a node has failed in this way, <c>epmd</c> prevents you from registering a new node with the old name, as it thinks that the old - name is still in use. In this case, you must unregister the name - explicitly:</p> + name is still in use. In this case, you must close the port + explicitly</p> - <code type="none"><![CDATA[ -erl_unpublish(node); ]]></code> - - <p>This causes <c>epmd</c> to close the connection from the - far end. Notice - that if the name was in fact still in use by a node, the results of - this operation are unpredictable. Also, doing this does not cause the - local end of the connection to close, so resources can be consumed.</p> </section> <section> @@ -442,10 +321,10 @@ erl_unpublish(node); ]]></code> <p>Use one of the following two functions to send messages:</p> <list type="bulleted"> - <item><seealso marker="erl_connect#erl_send"> - <c>erl_connect:erl_send</c></seealso></item> - <item><seealso marker="erl_connect#erl_reg_send"> - <c>erl_connect:erl_reg_send</c></seealso></item> + <item><seealso marker="ei_connect#ei_send"> + <c>ei_send</c></seealso></item> + <item><seealso marker="ei_connect#ei_reg_send"> + <c>ei_reg_send</c></seealso></item> </list> <p>As in Erlang, messages can be sent to a @@ -456,82 +335,79 @@ erl_unpublish(node); ]]></code> <p>Use one of the following two functions to receive messages:</p> <list type="bulleted"> - <item><seealso marker="erl_connect#erl_receive"> - <c>erl_connect:erl_receive</c></seealso></item> - <item><seealso marker="erl_connect#erl_receive_msg"> - <c>erl_connect:erl_receive_msg</c></seealso></item> + <item><seealso marker="ei_connect#ei_receive"> + <c>ei_receive</c></seealso></item> + <item><seealso marker="ei_connect#ei_receive_msg"> + <c>ei_receive_msg</c></seealso></item> </list> - <p><c>erl_receive()</c> receives the message into a buffer, - while <c>erl_receive_msg()</c> decodes the message into an - Erlang term.</p> - <section> <title>Example of Sending Messages</title> <p>In the following example, <c>{Pid, hello_world}</c> is - sent to a registered process <c>my_server</c>. The message - is encoded by <c>erl_send()</c>:</p> + sent to a registered process <c>my_server</c>:</p> <code type="none"><![CDATA[ -extern const char *erl_thisnodename(void); -extern short erl_thiscreation(void); -#define SELF(fd) erl_mk_pid(erl_thisnodename(),fd,0,erl_thiscreation()) -ETERM *arr[2], *emsg; -int sockfd, creation=1; - -arr[0] = SELF(sockfd); -arr[1] = erl_mk_atom("Hello world"); -emsg = erl_mk_tuple(arr, 2); - -erl_reg_send(sockfd, "my_server", emsg); -erl_free_term(emsg); ]]></code> +ei_x_buff buf; +ei_x_new_with_version(&buf); + +ei_x_encode_tuple_header(&buf, 2); +ei_x_encode_pid(&buf, ei_self(ec)); +ei_x_encode_atom(&buf, "Hello world"); + +ei_reg_send(ec,fd,"my_server",buf,buf.index);]]></code> <p>The first element of the tuple that is sent is your own pid. This enables <c>my_server</c> to reply. For more information about the primitives, see the - <seealso marker="erl_connect"><c>erl_connect</c></seealso> module.</p> + <seealso marker="ei_connect"><c>ei_connect</c></seealso> module.</p> </section> <section> <title>Example of Receiving Messages</title> - <p>In this example, <c>{Pid, Something}</c> is received. The - received pid is then used to return - <c>{goodbye,Pid}</c>.</p> - - <code type="none"><![CDATA[ -ETERM *arr[2], *answer; -int sockfd,rc; -char buf[BUFSIZE]; -ErlMessage emsg; - -if ((rc = erl_receive_msg(sockfd , buf, BUFSIZE, &emsg)) == ERL_MSG) { - arr[0] = erl_mk_atom("goodbye"); - arr[1] = erl_element(1, emsg.msg); - answer = erl_mk_tuple(arr, 2); - erl_send(sockfd, arr[1], answer); - erl_free_term(answer); - erl_free_term(emsg.msg); - erl_free_term(emsg.to); -} ]]></code> + <p>In this example, <c>{Pid, Something}</c> is received.</p> + + <code type="none"><![CDATA[ +erlang_msg msg; +int index = 0; +int version; +int arity = 0; +erlang_pid pid; +ei_x_buff buf; +ei_x_new(&buf); +for (;;) { + int got = ei_xreceive_msg(fd, &msg, &x); + if (got == ERL_TICK) + continue; + if (got == ERL_ERROR) { + fprintf(stderr, "ei_xreceive_msg, got==%d", got); + exit(1); + } + break; +} +ei_decode_version(buf.buff, &index, &version); +ei_decode_tuple_header(buf.buff, &index, &arity); +if (arity != 2) { + fprintf(stderr, "got wrong message"); + exit(1); +} +ei_decode_pid(buf.buff, &index, &pid); ]]></code> <p>To provide robustness, a distributed Erlang node occasionally polls all its connected neighbors in an attempt to detect failed nodes or communication links. A node that receives such a message is expected to respond immediately with an <c>ERL_TICK</c> message. This is done automatically by - <c>erl_receive()</c>. However, when this has occurred, - <c>erl_receive</c> returns <c>ERL_TICK</c> to + <c>ei_xreceive_msg()</c>. However, when this has occurred, + <c>ei_xreceive_msg</c> returns <c>ERL_TICK</c> to the caller without storing a message into the - <c>ErlMessage</c> structure.</p> + <c>erlang_msg</c> structure.</p> <p>When a message has been received, it is the caller's responsibility - to free the received message <c>emsg.msg</c> and - <c>emsg.to</c> or <c>emsg.from</c>, - depending on the type of message received.</p> + to free the received message.</p> <p>For more information, see the - <seealso marker="erl_connect"><c>erl_connect</c></seealso> and - <seealso marker="erl_eterm"><c>erl_eterm</c></seealso> modules.</p> + <seealso marker="ei_connect"><c>ei_connect</c></seealso> and + <seealso marker="ei"><c>ei</c></seealso> modules.</p> </section> </section> @@ -542,31 +418,30 @@ if ((rc = erl_receive_msg(sockfd , buf, BUFSIZE, &emsg)) == ERL_MSG) { included in a function call at a remote node and is called a remote procedure call.</p> - <p>The following example shows how the - <c>Erl_Interface</c> library supports remote procedure calls:</p> + <p>The following example checks if a specific Erlang process is alive:</p> <code type="none"><![CDATA[ -char modname[]=THE_MODNAME; -ETERM *reply,*ep; -ep = erl_format("[~a,[]]", modname); -if (!(reply = erl_rpc(fd, "c", "c", ep))) - erl_err_msg("<ERROR> when compiling file: %s.erl !\n", modname); -erl_free_term(ep); -ep = erl_format("{ok,_}"); -if (!erl_match(ep, reply)) - erl_err_msg("<ERROR> compiler errors !\n"); -erl_free_term(ep); -erl_free_term(reply); ]]></code> - - <p><c>c:c/1</c> is called to compile the specified module on - the remote node. <c>erl_match()</c> checks that the - compilation was - successful by testing for the expected <c>ok</c>.</p> - - <p>For more information about <c>erl_rpc()</c> and its - companions <c>erl_rpc_to()</c> and - <c>erl_rpc_from()</c>, see the - <seealso marker="erl_connect"><c>erl_connect</c></seealso> module.</p> +int index = 0, is_alive; +ei_x_buff args, result; + +ei_x_new(&result); +ei_x_new(&args); +ei_x_encode_list_header(&args, 1); +ei_x_encode_pid(&args, &check_pid); +ei_x_encode_empty_list(&args); + +if (ei_rpc(&ec, fd, "erlang", "is_process_alive", + args.buff, args.index, &result) < 0) + handle_error(); + +if (ei_decode_version(result.buff, &index) < 0 + || ei_decode_bool(result.buff, &index, &is_alive) < 0) + handle_error(); ]]></code> + + <p>For more information about <c>ei_rpc()</c> and its + companions <c>ei_rpc_to()</c> and + <c>ei_rpc_from()</c>, see the + <seealso marker="ei_connect"><c>ei_connect</c></seealso> module.</p> </section> <section> @@ -590,7 +465,7 @@ char **names; int count; int i; -names = erl_global_names(fd,&count); +names = ei_global_names(ec,fd,&count); if (names) for (i=0; i<count; i++) @@ -598,8 +473,8 @@ if (names) free(names); ]]></code> - <p><seealso marker="erl_global#erl_global_names"> - <c>erl_global:erl_global_names</c></seealso> + <p><seealso marker="ei_global#ei_global_names"> + <c>ei_global_names</c></seealso> allocates and returns a buffer containing all the names known to the <c>global</c> module in <c>Kernel</c>. <c>count</c> is initialized to @@ -608,7 +483,7 @@ free(names); ]]></code> <c>count</c> to determine when the last name is reached.</p> <p>It is the caller's responsibility to free the array. - <c>erl_global_names</c> allocates the array and all the strings + <c>ei_global_names</c> allocates the array and all the strings using a single call to <c>malloc()</c>, so <c>free(names)</c> is all that is necessary.</p> @@ -617,16 +492,18 @@ free(names); ]]></code> <code type="none"><![CDATA[ ETERM *pid; char node[256]; +erlang_pid the_pid; -pid = erl_global_whereis(fd,"schedule",node); ]]></code> +if (ei_global_whereis(ec,fd,"schedule",&the_pid,node) < 0) + fprintf(stderr, "ei_global_whereis error\n"); ]]></code> <p>If <c>"schedule"</c> is known to the <c>global</c> module in <c>Kernel</c>, an Erlang pid is - returned that can be used to send messages to the schedule service. + written to the_pid. This pid that can be used to send messages to the schedule service. Also, <c>node</c> is initialized to contain the name of the node where the service is registered, so that you can make a connection to it by simply passing the variable to - <seealso marker="erl_connect"><c>erl_connect</c></seealso>.</p> + <seealso marker="ei_connect"><c>ei_connect</c></seealso>.</p> <p>Before registering a name, you should already have registered your port number with <c>epmd</c>. This is not strictly necessary, @@ -634,30 +511,27 @@ pid = erl_global_whereis(fd,"schedule",node); ]]></code> neglect to do so, then other nodes wishing to communicate with your service cannot find or connect to your process.</p> - <p>Create a pid that Erlang processes can use to communicate with your + <p>Create a name that Erlang processes can use to communicate with your service:</p> <code type="none"><![CDATA[ -ETERM *pid; - -pid = erl_mk_pid(thisnode,14,0,0); -erl_global_register(fd,servicename,pid); ]]></code> +ei_global_register(fd,servicename,ei_self(ec)); ]]></code> <p>After registering the name, use - <seealso marker="erl_connect#erl_accept"> - <c>erl_connect:erl_accept</c></seealso> + <seealso marker="ei_connect#ei_accept"> + <c>ei_accept</c></seealso> to wait for incoming connections.</p> <note> <p>Remember to free <c>pid</c> later with - <seealso marker="erl_malloc#erl_free_term"> - <c>erl_malloc:erl_free_term</c></seealso>.</p> + <seealso marker="ei#ei_x_free"> + <c>ei_x_free</c></seealso>.</p> </note> <p>To unregister a name:</p> <code type="none"><![CDATA[ -erl_global_unregister(fd,servicename); ]]></code> +ei_global_unregister(ec,fd,servicename); ]]></code> </section> <section> @@ -755,7 +629,7 @@ ei_reg_close(reg); ]]></code> <p>The contents of a registry can be backed up to <seealso marker="mnesia:mnesia"><c>Mnesia</c></seealso> on a "nearby" Erlang node. You must provide an open connection to the Erlang node - (see <seealso marker="erl_connect"><c>erl_connect</c></seealso>). + (see <seealso marker="ei_connect"><c>ei_connect</c></seealso>). Also, <c>Mnesia</c> 3.0 or later must be running on the Erlang node before the backup is initiated:</p> @@ -818,9 +692,9 @@ ei_reg_restore(fd, reg, "mtab"); ]]></code> <c>Mnesia</c> backup of the registry contents. This can be avoided if you mark the object as dirty after any such changes with <seealso marker="registry#ei_reg_markdirty"> - <c>registry:ei_reg_markdirty</c></seealso>, or pass appropriate flags to + <c>ei_reg_markdirty</c></seealso>, or pass appropriate flags to <seealso marker="registry#ei_reg_dump"> - <c>registry:ei_reg_dump</c></seealso>.</p> + <c>ei_reg_dump</c></seealso>.</p> </section> </section> </chapter> diff --git a/lib/erl_interface/doc/src/erl_call.xml b/lib/erl_interface/doc/src/erl_call_cmd.xml index 73b9b13e4d..91cb9dbd32 100644 --- a/lib/erl_interface/doc/src/erl_call.xml +++ b/lib/erl_interface/doc/src/erl_call_cmd.xml @@ -78,6 +78,22 @@ <c>Fun</c>, and <c>Args</c> in a manner dependent on the behavior of your command shell.</p> </item> + <tag><c>-address [Hostname:]Port</c></tag> + <item> + <p>(One of <c>-n</c>, <c>-name</c>, <c>-sname</c> or + <c>-address</c> is required.) <c>Hostname</c> is the + hostname of the machine that is running the node that + <c>erl_call</c> shall communicate with. The default + hostname is the hostname of the local machine. <c>Port</c> + is the port number of the node that <c>erl_call</c> shall + communicate with. The <c>-address</c> flag cannot be + combined with any of the flags <c>-n</c>, <c>-name</c>, + <c>-sname</c> or <c>-s</c>.</p> + <p>The <c>-address</c> flag is typically useful when one + wants to call a node that is running on machine without an + accessible <seealso marker="erts:epmd">epmd</seealso> + instance.</p> + </item> <tag><c>-c Cookie</c></tag> <item> <p>(<em>Optional.</em>) Use this option to specify a certain cookie. @@ -112,13 +128,15 @@ </item> <tag><c>-n Node</c></tag> <item> - <p>(One of <c>-n, -name, -sname</c> is required.) + <p>(One of <c>-n</c>, <c>-name</c>, <c>-sname</c> or + <c>-address</c> is required.) Has the same meaning as <c>-name</c> and can still be used for backward compatibility reasons.</p> </item> <tag><c>-name Node</c></tag> <item> - <p>(One of <c>-n, -name, -sname</c> is required.) + <p>(One of <c>-n</c>, <c>-name</c>, <c>-sname</c> or + <c>-address</c> is required.) <c>Node</c> is the name of the node to be started or communicated with. It is assumed that <c>Node</c> is started with @@ -149,7 +167,8 @@ </item> <tag><c>-sname Node</c></tag> <item> - <p>(One of <c>-n, -name, -sname</c> is required.) + <p>(One of <c>-n</c>, <c>-name</c>, <c>-sname</c> or + <c>-address</c> is required.) <c>Node</c> is the name of the node to be started or communicated with. It is assumed that <c>Node</c> is started with <c>erl -sname</c>, which means that diff --git a/lib/erl_interface/doc/src/erl_connect.xml b/lib/erl_interface/doc/src/erl_connect.xml deleted file mode 100644 index 9492a82864..0000000000 --- a/lib/erl_interface/doc/src/erl_connect.xml +++ /dev/null @@ -1,662 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE cref SYSTEM "cref.dtd"> - -<cref> - <header> - <copyright> - <year>1996</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>erl_connect</title> - <prepared>Torbjörn Törnkvist</prepared> - <responsible>Torbjörn Törnkvist</responsible> - <docno></docno> - <approved>Bjarne Däcker</approved> - <checked>Torbjörn Törnkvist</checked> - <date>1998-07-03</date> - <rev>A</rev> - <file>erl_connect.xml</file> - </header> - <lib>erl_connect</lib> - <libsummary>Communicate with distributed Erlang.</libsummary> - <description> - <note><p>The support for VxWorks is deprecated as of OTP 22, and - will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> - - <p>This module provides support for communication between distributed - Erlang nodes and C-nodes, in a manner that is transparent to Erlang - processes.</p> - - <p>A C-node appears to Erlang as a <em>hidden node</em>. - That is, Erlang processes that know the name of the - C-node can communicate with it in a normal manner, but - the node name does not appear in the listing provided by - <seealso marker="erts:erlang#nodes/0"><c>erlang:nodes/0</c></seealso> - in <c>ERTS</c>.</p> - </description> - - <funcs> - <func> - <name since=""><ret>int</ret><nametext>erl_accept(listensock, conp)</nametext></name> - <fsummary>Accept a connection.</fsummary> - <type> - <v>int listensock;</v> - <v>ErlConnect *conp;</v> - </type> - <desc> - <p>This function is used by a server process to accept a - connection from a client process.</p> - <list type="bulleted"> - <item><c>listensock</c> is an open socket descriptor on - which <c>listen()</c> has previously been called.</item> - <item><c>conp</c> is a pointer to an - <c>ErlConnect</c> struct, described as follows:</item> - </list> - <code type="none"><![CDATA[ -typedef struct { - char ipadr[4]; - char nodename[MAXNODELEN]; -} ErlConnect; - ]]></code> - <p>On success, <c>conp</c> is filled in with the address and - node name of the connecting client and a file descriptor is - returned. On failure, <c>ERL_ERROR</c> is returned and - <c>erl_errno</c> is set to <c>EIO</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_close_connection(fd)</nametext></name> - <fsummary>Close a connection to an Erlang node.</fsummary> - <type> - <v>int fd;</v> - </type> - <desc> - <p>Closes an open connection to an Erlang node.</p> - <p><c>Fd</c> is a file descriptor obtained from - <c>erl_connect()</c> or - <c>erl_xconnect()</c>.</p> - <p>Returns <c>0</c> on success. If the call fails, a non-zero value - is returned, and the reason for the error can be obtained with the - appropriate platform-dependent call.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_connect(node)</nametext></name> - <name since=""><ret>int</ret><nametext>erl_xconnect(addr, alive)</nametext></name> - <fsummary>Establish a connection to an Erlang node.</fsummary> - <type> - <v>char *node, *alive;</v> - <v>struct in_addr *addr;</v> - </type> - <desc> - <p>Sets up a connection to an Erlang node.</p> - <p><c>erl_xconnect()</c> requires the IP address of the - remote host and the alivename of the remote node to be - specified. <c>erl_connect()</c> provides an alternative - interface, and determines the information from the node name - provided.</p> - <list type="bulleted"> - <item><c>addr</c> is the 32-bit IP address of the remote - host.</item> - <item><c>alive</c> is the alivename of the remote node. - </item> - <item><c>node</c> is the name of the remote node.</item> - </list> - <p>Returns an open file descriptor on success, otherwise a negative - value. In the latter case <c>erl_errno</c> is set to one - of:</p> - <taglist> - <tag><c>EHOSTUNREACH</c></tag> - <item>The remote host <c>node</c> is unreachable.</item> - <tag><c>ENOMEM</c></tag> - <item>No more memory is available.</item> - <tag><c>EIO</c></tag> - <item>I/O error.</item> - </taglist> - <p>Also, <c>errno</c> values from - <c>socket</c><em>(2)</em> and - <c>connect</c><em>(2)</em> - system calls can be propagated into <c>erl_errno</c>.</p> - <p><em>Example:</em></p> - <code type="none"><![CDATA[ -#define NODE "madonna@chivas.du.etx.ericsson.se" -#define ALIVE "madonna" -#define IP_ADDR "150.236.14.75" - -/*** Variant 1 ***/ -erl_connect( NODE ); - -/*** Variant 2 ***/ -struct in_addr addr; -addr = inet_addr(IP_ADDR); -erl_xconnect( &addr , ALIVE ); - ]]></code> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_connect_init(number, cookie, creation)</nametext></name> - <name since=""><ret>int</ret><nametext>erl_connect_xinit(host, alive, node, addr, cookie, creation)</nametext></name> - <fsummary>Initialize communication.</fsummary> - <type> - <v>int number;</v> - <v>char *cookie;</v> - <v>short creation;</v> - <v>char *host,*alive,*node;</v> - <v>struct in_addr *addr;</v> - </type> - <desc> - <p>Initializes the <c>erl_connect</c> module. - In particular, these functions are used to identify the name of the - C-node from which they are called. One of these functions must - be called before any of the other functions in the <c>erl_connect</c> - module are used.</p> - <p><c>erl_connect_xinit()</c> stores for later use - information about:</p> - <list type="bulleted"> - <item>Hostname of the node, <c>host</c></item> - <item>Alivename, <c>alive</c></item> - <item>Node name, <c>node</c></item> - <item>IP address, <c>addr</c></item> - <item>Cookie, <c>cookie</c></item> - <item>Creation number, <c>creation</c></item> - </list> - <p><c>erl_connect_init()</c> - provides an alternative interface that does not require as much - information from the caller. Instead, - <c>erl_connect_init()</c> - uses <c>gethostbyname()</c> to obtain default values.</p> - <p>If you use <c>erl_connect_init()</c>, your node will - have a short name, that is, it will not be fully qualified. If you - need to use fully qualified (long) names, use - <c>erl_connect_xinit()</c> instead.</p> - <list type="bulleted"> - <item> - <p><c>host</c> is the name of the host on which the node - is running.</p> - </item> - <item> - <p><c>alive</c> is the alivename of the node.</p> - </item> - <item> - <p><c>node</c> is the node name. It is to - be of the form <em>alivename@hostname</em>.</p> - </item> - <item> - <p><c>addr</c> is the 32-bit IP address of - <c>host</c>.</p> - </item> - <item> - <p><c>cookie</c> is the authorization string required - for access to the remote node. If <c>NULL</c>, the user - <c>HOME</c> directory is searched for a cookie file - <c>.erlang.cookie</c>. The path to - the home directory is retrieved from environment variable - <c>HOME</c> on Unix and from the - <c>HOMEDRIVE</c> and - <c>HOMEPATH</c> variables on Windows. For more - details, see the <seealso marker="kernel:auth"> - <c>auth</c></seealso> module in Kernel.</p> - </item> - <item> - <p><c>creation</c> helps identifying a particular - instance of a C-node. In particular, it can help prevent us from - receiving messages sent to an earlier process with the same - registered name.</p> - </item> - </list> - <p>A C-node acting as a server is assigned a creation number - when it calls <c>erl_publish()</c>.</p> - <p><c>number</c> is used by - <c>erl_connect_init()</c> to - construct the actual node name. In Example 2 - below, <em>"c17@a.DNS.name"</em> is the resulting node name.</p> - <p><em>Example 1:</em></p> - <code type="none"><![CDATA[ -struct in_addr addr; -addr = inet_addr("150.236.14.75"); -if (!erl_connect_xinit("chivas", - "madonna", - "madonna@chivas.du.etx.ericsson.se", - &addr; - "samplecookiestring..."), - 0) - erl_err_quit("<ERROR> when initializing !"); - ]]></code> - <p><em>Example 2:</em></p> - <code type="none"><![CDATA[ -if (!erl_connect_init(17, "samplecookiestring...", 0)) - erl_err_quit("<ERROR> when initializing !"); - ]]></code> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_publish(port)</nametext></name> - <fsummary>Publish a node name.</fsummary> - <type> - <v>int port;</v> - </type> - <desc> - <p>This function is used by a server process to register - with the local name server EPMD, thereby allowing - other processes to send messages by using the registered name. - Before calling this function, the process should - have called <c>bind()</c> and <c>listen()</c> - on an open socket.</p> - <p><c>port</c> is the local name to register, and is to 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.</p> - <p>On success, a descriptor connecting the calling process to EPMD is - returned. On failure, <c>-1</c> is returned and - <c>erl_errno</c> is set to:</p> - <taglist> - <tag><c>EIO</c></tag> - <item>I/O error.</item> - </taglist> - <p>Also, <c>errno</c> values from - <c>socket</c><em>(2)</em> - and <c>connect</c><em>(2)</em> system calls can be - propagated into <c>erl_errno</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_receive(fd, bufp, bufsize)</nametext></name> - <fsummary>Receive a message.</fsummary> - <type> - <v>int fd;</v> - <v>char *bufp;</v> - <v>int bufsize;</v> - </type> - <desc> - <p>Receives a message consisting of a sequence - of bytes in the Erlang external format.</p> - <list type="bulleted"> - <item><c>fd</c> is an open descriptor to an Erlang - connection.</item> - <item><c>bufp</c> is a buffer large enough to hold the - expected message.</item> - <item><c>bufsize</c> indicates the size of - <c>bufp</c>.</item> - </list> - <p>If a <em>tick</em> occurs, that is, the Erlang node on the - other end of the connection has polled this node to see if it - is still alive, the function returns <c>ERL_TICK</c> and - no message is placed in the buffer. Also, - <c>erl_errno</c> is set to <c>EAGAIN</c>.</p> - <p>On success, the message is placed in the specified buffer - and the function returns the number of bytes actually read. On - failure, the function returns a negative value and sets - <c>erl_errno</c> to one of:</p> - <taglist> - <tag><c>EAGAIN</c></tag> - <item>Temporary error: Try again.</item> - <tag><c>EMSGSIZE</c></tag> - <item>Buffer is too small.</item> - <tag><c>EIO</c></tag> - <item>I/O error.</item> - </taglist> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_receive_msg(fd, bufp, bufsize, emsg)</nametext></name> - <fsummary>Receive and decode a message.</fsummary> - <type> - <v>int fd;</v> - <v>unsigned char *bufp;</v> - <v>int bufsize;</v> - <v>ErlMessage *emsg;</v> - </type> - <desc> - <p>Receives the message into the specified buffer - and decodes into <c>(ErlMessage *) emsg</c>.</p> - <list type="bulleted"> - <item><c>fd</c> is an open descriptor to an Erlang - connection.</item> - <item><c>bufp</c> is a buffer large enough to hold the - expected message.</item> - <item><c>bufsize</c> indicates the size of - <c>bufp</c>.</item> - <item>><c>emsg</c> is a pointer to an - <c>ErlMessage</c> structure - into which the message will be decoded. - <c>ErlMessage</c> is defined as follows:</item> - </list> - <code type="none"><![CDATA[ -typedef struct { - int type; - ETERM *msg; - ETERM *to; - ETERM *from; - char to_name[MAXREGLEN]; -} ErlMessage; - ]]></code> - <note> - <p>The definition of <c>ErlMessage</c> has changed since - earlier versions of <c>Erl_Interface</c>.</p> - </note> - <p><c>type</c> identifies the type of message, one of the - following:</p> - <taglist> - <tag><c>ERL_SEND</c></tag> - <item> - <p>An ordinary send operation has occurred and - <c>emsg->to</c> contains the pid of the recipient. - The message is in <c>emsg->msg</c>.</p> - </item> - <tag><c>ERL_REG_SEND</c></tag> - <item> - <p>A registered send operation has occurred and - <c>emsg->from</c> contains the pid of the sender. - The message is in <c>emsg->msg</c>.</p> - </item> - <tag><c>ERL_LINK</c> or <c>ERL_UNLINK</c> - </tag> - <item> - <p><c>emsg->to</c> and <c>emsg->from</c> - contain the pids of the sender and recipient of the link or - unlink. <c>emsg->msg</c> is not used.</p> - </item> - <tag><c>ERL_EXIT</c></tag> - <item> - <p>A link is broken. <c>emsg->to</c> and - <c>emsg->from</c> contain the pids of the linked - processes, and <c>emsg->msg</c> contains the reason - for the exit.</p> - </item> - </taglist> - <note> - <p>It is the caller's responsibility to release the - memory pointed to by <c>emsg->msg</c>, - <c>emsg->to</c>, and - <c>emsg->from</c>.</p> - </note> - <p>If a <em>tick</em> occurs, that is, the Erlang node on the - other end of the connection has polled this node to see if it - is still alive, the function returns <c>ERL_TICK</c> - indicating that the tick has been received and responded to, - but no message is placed in the buffer. In this case you - are to call <c>erl_receive_msg()</c> again.</p> - <p>On success, the function returns <c>ERL_MSG</c> and the - <c>Emsg</c> struct is initialized as described above, or - <c>ERL_TICK</c>, in which case no message is returned. On - failure, the function returns <c>ERL_ERROR</c> and sets - <c>erl_errno</c> to one of:</p> - <taglist> - <tag><c>EMSGSIZE</c></tag> - <item>Buffer is too small.</item> - <tag><c>ENOMEM</c></tag> - <item>No more memory is available.</item> - <tag><c>EIO</c></tag> - <item>I/O error.</item> - </taglist> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_reg_send(fd, to, msg)</nametext></name> - <fsummary>Send a message to a registered name.</fsummary> - <type> - <v>int fd;</v> - <v>char *to;</v> - <v>ETERM *msg;</v> - </type> - <desc> - <p>Sends an Erlang term to a registered process.</p> - <list type="bulleted"> - <item><c>fd</c> is an open descriptor to an Erlang - connection.</item> - <item><c>to</c> is a string containing the registered name - of the intended recipient of the message.</item> - <item><c>msg</c> is the Erlang term to be sent.</item> - </list> - <p>Returns <c>1</c> on success, otherwise <c>0</c>. In - the latter case <c>erl_errno</c> is set to one of:</p> - <taglist> - <tag><c>ENOMEM</c></tag> - <item>No more memory is available.</item> - <tag><c>EIO</c></tag> - <item>I/O error.</item> - </taglist> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_rpc(fd, mod, fun, args)</nametext></name> - <name since=""><ret>int</ret><nametext>erl_rpc_from(fd, timeout, emsg)</nametext></name> - <name since=""><ret>int</ret><nametext>erl_rpc_to(fd, mod, fun, args)</nametext></name> - <fsummary>Remote Procedure Call.</fsummary> - <type> - <v>int fd, timeout;</v> - <v>char *mod, *fun;</v> - <v>ETERM *args;</v> - <v>ErlMessage *emsg;</v> - </type> - <desc> - <p>Supports calling Erlang functions on remote nodes. - <c>erl_rpc_to()</c> sends an RPC request to a remote node - and <c>erl_rpc_from()</c> receives the results of such a - call. <c>erl_rpc()</c> combines the functionality of - these two functions by sending an RPC request and waiting for the - results. See also <seealso marker="kernel:rpc#call/4"> - <c>rpc:call/4</c></seealso> in <c>Kernel</c>.</p> - <list type="bulleted"> - <item><c>fd</c> is an open descriptor to an Erlang - connection.</item> - <item><c>timeout</c> is the maximum time (in milliseconds) - to wait for - results. To wait forever, specify <c>ERL_NO_TIMEOUT</c>. - When <c>erl_rpc()</c> calls <c>erl_rpc_from()</c>, the call will - never timeout.</item> - <item><c>mod</c> is the name of the module containing the - function to be run on the remote node.</item> - <item><c>fun</c> is the name of the function to run. - </item> - <item><c>args</c> is an Erlang list, containing the - arguments to be passed to the function.</item> - <item><c>emsg</c> is a message containing the result of - the function call.</item> - </list> - <p>The actual message returned by the RPC server - is a 2-tuple <c>{rex,Reply}</c>. If you use - <c>erl_rpc_from()</c> in your code, this is the message - you will need to parse. If you use <c>erl_rpc()</c>, the - tuple itself is parsed for you, and the message returned to your - program is the Erlang term containing <c>Reply</c> only. - Replies to RPC requests are always <c>ERL_SEND</c> messages.</p> - <note> - <p>It is the caller's responsibility to free the returned - <c>ETERM</c> structure and the memory pointed to by - <c>emsg->msg</c> and <c>emsg->to</c>.</p> - </note> - <p><c>erl_rpc()</c> returns the remote function's return - value on success, otherwise <c>NULL</c>.</p> - <p><c>erl_rpc_to()</c> returns <c>0</c> on - success, otherwise a negative number.</p> - <p><c>erl_rcp_from()</c> returns <c>ERL_MSG</c> - on success (with <c>Emsg</c> now - containing the reply tuple), otherwise one of - <c>ERL_TICK</c>, <c>ERL_TIMEOUT</c>, or - <c>ERL_ERROR</c>.</p> - <p>When failing, - all three functions set <c>erl_errno</c> to one of:</p> - <taglist> - <tag><c>ENOMEM</c></tag> - <item>No more memory is available.</item> - <tag><c>EIO</c></tag> - <item>I/O error.</item> - <tag><c>ETIMEDOUT</c></tag> - <item>Timeout has expired.</item> - <tag><c>EAGAIN</c></tag> - <item>Temporary error: Try again.</item> - </taglist> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_send(fd, to, msg)</nametext></name> - <fsummary>Send a message.</fsummary> - <type> - <v>int fd;</v> - <v>ETERM *to, *msg;</v> - </type> - <desc> - <p>Sends an Erlang term to a process.</p> - <list type="bulleted"> - <item><c>fd</c> is an open descriptor to an Erlang - connection.</item> - <item><c>to</c> is an Erlang term containing the pid of - the intended recipient of the message.</item> - <item>><c>msg</c> is the Erlang term to be sent.</item> - </list> - <p>Returns <c>1</c> on success, otherwise <c>0</c>. In - the latter case <c>erl_errno</c> is set to one of:</p> - <taglist> - <tag><c>EINVAL</c></tag> - <item>Invalid argument: <c>to</c> is not a valid Erlang - pid.</item> - <tag><c>ENOMEM</c></tag> - <item>No more memory is available.</item> - <tag><c>EIO</c></tag> - <item>I/O error.</item> - </taglist> - </desc> - </func> - - <func> - <name since=""><ret>const char *</ret><nametext>erl_thisalivename()</nametext></name> - <name since=""><ret>const char *</ret><nametext>erl_thiscookie()</nametext></name> - <name since=""><ret>short</ret><nametext>erl_thiscreation()</nametext></name> - <name since=""><ret>const char *</ret><nametext>erl_thishostname()</nametext></name> - <name since=""><ret>const char *</ret><nametext>erl_thisnodename()</nametext></name> - <fsummary>Retrieve some values.</fsummary> - <desc> - <p>Retrieves information about - the C-node. These values are initially set with - <c>erl_connect_init()</c> or - <c>erl_connect_xinit()</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_unpublish(alive)</nametext></name> - <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 from EPMD on the local host. This is, however, usually - not allowed, unless EPMD was started with flag - <c>-relaxed_command_check</c>, which it normally is not.</p> - <p>To unregister a node you have published, you should instead - close the descriptor that was returned by - <c>ei_publish()</c>.</p> - <warning> - <p>This function is deprecated and will be removed in a future - release.</p> - </warning> - <p><c>alive</c> is the name of the node to unregister, that - is, the first component of the node name, without - <c>@hostname</c>.</p> - <p>If the node was successfully unregistered from EPMD, <c>0</c> is - returned, otherwise <c>-1</c> is returned and - <c>erl_errno</c> is set to <c>EIO</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_xreceive_msg(fd, bufpp, bufsizep, emsg)</nametext></name> - <fsummary>Receive and decode a message.</fsummary> - <type> - <v>int fd;</v> - <v>unsigned char **bufpp;</v> - <v>int *bufsizep;</v> - <v>ErlMessage *emsg;</v> - </type> - <desc> - <p>Similar to <c>erl_receive_msg</c>. The difference is - that <c>erl_xreceive_msg</c> expects the buffer to - have been allocated by <c>malloc</c>, and reallocates it - if the received - message does not fit into the original buffer. Therefore - both buffer and buffer length are given as pointers; their values - can change by the call.</p> - <p>On success, the function returns <c>ERL_MSG</c> and the - <c>Emsg</c> struct is initialized as described above, or - <c>ERL_TICK</c>, in which case no message is returned. On - failure, the function returns <c>ERL_ERROR</c> and sets - <c>erl_errno</c> to one of:</p> - <taglist> - <tag><c>EMSGSIZE</c></tag> - <item>Buffer is too small.</item> - <tag><c>ENOMEM</c></tag> - <item>No more memory is available.</item> - <tag><c>EIO</c></tag> - <item>I/O error.</item> - </taglist> - </desc> - </func> - - <func> - <name since=""><ret>struct hostent *</ret><nametext>erl_gethostbyaddr(addr, length, type)</nametext></name> - <name since=""><ret>struct hostent *</ret><nametext>erl_gethostbyaddr_r(addr, length, type, hostp, buffer, buflen, h_errnop)</nametext></name> - <name since=""><ret>struct hostent *</ret><nametext>erl_gethostbyname(name)</nametext></name> - <name since=""><ret>struct hostent *</ret><nametext>erl_gethostbyname_r(name, hostp, buffer, buflen, h_errnop)</nametext></name> - - <fsummary>Name lookup functions.</fsummary> - <type> - <v>const char *name;</v> - <v>const char *addr;</v> - <v>int length;</v> - <v>int type;</v> - <v>struct hostent *hostp;</v> - <v>char *buffer;</v> - <v>int buflen;</v> - <v>int *h_errnop;</v> - </type> - <desc> - <p>Convenience functions for some common name lookup functions.</p> - </desc> - </func> - </funcs> - - <section> - <title>Debug Information</title> - <p>If a connection attempt fails, the following can be checked:</p> - - <list type="bulleted"> - <item><c>erl_errno</c></item> - <item>That the correct cookie was used</item> - <item>That EPMD is running</item> - <item>That the remote Erlang node on the other side is running the same - version of Erlang as the <c>erl_interface</c> library</item> - </list> - </section> -</cref> diff --git a/lib/erl_interface/doc/src/erl_error.xml b/lib/erl_interface/doc/src/erl_error.xml deleted file mode 100644 index 6fac94e442..0000000000 --- a/lib/erl_interface/doc/src/erl_error.xml +++ /dev/null @@ -1,145 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE cref SYSTEM "cref.dtd"> - -<cref> - <header> - <copyright> - <year>1996</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>erl_error</title> - <prepared>Torbjörn Törnkvist</prepared> - <responsible>Torbjörn Törnkvist</responsible> - <docno></docno> - <approved>Bjarne Däcker</approved> - <checked>Torbjörn Törnkvist</checked> - <date>1996-10-14</date> - <rev>A</rev> - <file>erl_error.xml</file> - </header> - <lib>erl_error</lib> - <libsummary>Error print routines.</libsummary> - <description> - <p>This module contains some error printing routines taken - from "Advanced Programming in the UNIX Environment" - by W. Richard Stevens.</p> - - <p>These functions are all called in the same manner as - <c>printf()</c>, that is, with a string containing format - specifiers followed by a list of corresponding arguments. All output from - these functions is to <c>stderr</c>.</p> - </description> - - <funcs> - <func> - <name since=""><ret>void</ret><nametext>erl_err_msg(FormatStr, ... )</nametext></name> - <fsummary>Non-fatal error, and not system call error.</fsummary> - <type> - <v>const char *FormatStr;</v> - </type> - <desc> - <p>The message provided by the caller is printed. This - function is simply a wrapper for <c>fprintf()</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_err_quit(FormatStr, ... )</nametext></name> - <fsummary>Fatal error, but not system call error.</fsummary> - <type> - <v>const char *FormatStr;</v> - </type> - <desc> - <p>Use this function when a fatal error has occurred that - is not because of a system call. The message provided by the - caller is printed and the process terminates with exit - value <c>1</c>. This function does not return.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_err_ret(FormatStr, ... )</nametext></name> - <fsummary>Non-fatal system call error.</fsummary> - <type> - <v>const char *FormatStr;</v> - </type> - <desc> - <p>Use this function after a failed system call. The message - provided by the caller is printed followed by a string - describing the reason for failure.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_err_sys(FormatStr, ... )</nametext></name> - <fsummary>Fatal system call error.</fsummary> - <type> - <v>const char *FormatStr;</v> - </type> - <desc> - <p>Use this function after a failed system call. The message - provided by the caller is printed followed by a string - describing the reason for failure, and the process - terminates with exit value <c>1</c>. This function does not - return.</p> - </desc> - </func> - </funcs> - - <section> - <title>Error Reporting</title> - <p>Most functions in <c>Erl_Interface</c> report failures to the caller by - returning some otherwise meaningless value (typically - <c>NULL</c> - or a negative number). As this only tells you that things did not - go well, examine the error code in <c>erl_errno</c> if you - want to find out more about the failure.</p> - </section> - - <funcs> - <func> - <name since=""><ret>volatile int</ret><nametext>erl_errno</nametext></name> - <fsummary>Variable <c>erl_errno</c> contains the - Erl_Interface error number. You can change the value if you wish. - </fsummary> - <desc> - <p><c>erl_errno</c> is initially (at program startup) zero - and is then set by many <c>Erl_Interface</c> functions on failure to - a non-zero error code to indicate what kind of error it - encountered. A successful function call can change - <c>erl_errno</c> (by calling some other function that - fails), but no function does never set it to zero. This means - that you cannot use <c>erl_errno</c> to see <em>if</em> a - function call failed. Instead, each function reports failure - in its own way (usually by returning a negative number or - <c>NULL</c>), in which case you can examine - <c>erl_errno</c> for details.</p> - <p><c>erl_errno</c> uses the error codes defined in your - system's <c><errno.h></c>.</p> - <note> - <p><c>erl_errno</c> is a "modifiable lvalue" (just - like ISO C defines <c>errno</c> to be) rather than a - variable. This means it can be implemented as a macro - (expanding to, for example, <c>*_erl_errno()</c>). - For reasons of thread safety (or task safety), this is exactly what - we do on most platforms.</p> - </note> - </desc> - </func> - </funcs> -</cref> diff --git a/lib/erl_interface/doc/src/erl_eterm.xml b/lib/erl_interface/doc/src/erl_eterm.xml deleted file mode 100644 index 295760b4e6..0000000000 --- a/lib/erl_interface/doc/src/erl_eterm.xml +++ /dev/null @@ -1,776 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE cref SYSTEM "cref.dtd"> - -<cref> - <header> - <copyright> - <year>1996</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>erl_eterm</title> - <prepared>Torbjörn Törnkvist</prepared> - <responsible>Torbjörn Törnkvist</responsible> - <docno></docno> - <approved>Bjarne Däcker</approved> - <checked>Torbjörn Törnkvist</checked> - <date>1998-07-03</date> - <rev>A</rev> - <file>erl_eterm.xml</file> - </header> - <lib>erl_eterm</lib> - <libsummary>Functions for Erlang term construction.</libsummary> - <description> - <note><p>The support for VxWorks is deprecated as of OTP 22, and - will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> - - <p>This module provides functions for creating and manipulating - Erlang terms.</p> - - <p>An Erlang term is represented by a C structure of type - <c>ETERM</c>. Applications should not reference any fields - in this structure directly, as it can be changed in future releases - to provide faster and more compact term storage. Instead, - applications should use the macros and functions provided.</p> - - <p>Each of the following macros takes a single <c>ETERM</c> pointer as an - argument. The macros return a non-zero value if the test is true, - otherwise <c>0</c>.</p> - - <taglist> - <tag><c>ERL_IS_INTEGER(t)</c></tag> - <item>True if <c>t</c> is an integer.</item> - <tag><c>ERL_IS_UNSIGNED_INTEGER(t)</c></tag> - <item>True if <c>t</c> is an integer.</item> - <tag><c>ERL_IS_FLOAT(t)</c></tag> - <item>True if <c>t</c> is a floating point number.</item> - <tag><c>ERL_IS_ATOM(t)</c></tag> - <item>True if <c>t</c> is an atom.</item> - <tag><c>ERL_IS_PID(t)</c></tag> - <item>True if <c>t</c> is a pid (process identifier).</item> - <tag><c>ERL_IS_PORT(t)</c></tag> - <item>True if <c>t</c> is a port.</item> - <tag><c>ERL_IS_REF(t)</c></tag> - <item>True if <c>t</c> is a reference.</item> - <tag><c>ERL_IS_TUPLE(t)</c></tag> - <item>True if <c>t</c> is a tuple.</item> - <tag><c>ERL_IS_BINARY(t)</c></tag> - <item>True if <c>t</c> is a binary.</item> - <tag><c>ERL_IS_LIST(t)</c></tag> - <item>True if <c>t</c> is a list with zero or more - elements.</item> - <tag><c>ERL_IS_EMPTY_LIST(t)</c></tag> - <item>True if <c>t</c> is an empty list.</item> - <tag><c>ERL_IS_CONS(t)</c></tag> - <item>True if <c>t</c> is a list with at least one - element.</item> - </taglist> - - <p>The following macros can be used for retrieving parts of Erlang - terms. None of these do any type checking. Results are undefined - if you pass an <c>ETERM*</c> containing the wrong type. For example, - passing a tuple to <c>ERL_ATOM_PTR()</c> likely results in garbage.</p> - - <taglist> - <tag><c>char *ERL_ATOM_PTR(t)</c></tag> - <item></item> - <tag><c>char *ERL_ATOM_PTR_UTF8(t)</c></tag> - <item>A string representing atom <c>t</c>.</item> - <tag><c>int ERL_ATOM_SIZE(t)</c></tag> - <item></item> - <tag><c>int ERL_ATOM_SIZE_UTF8(t)</c></tag> - <item>The length (in bytes) of atom <c>t</c>.</item> - <tag><c>void *ERL_BIN_PTR(t)</c></tag> - <item>A pointer to the contents of <c>t</c>.</item> - <tag><c>int ERL_BIN_SIZE(t)</c></tag> - <item>The length (in bytes) of binary object <c>t</c>.</item> - <tag><c>int ERL_INT_VALUE(t)</c></tag> - <item>The integer of <c>t</c>.</item> - <tag><c>unsigned int ERL_INT_UVALUE(t)</c></tag> - <item>The unsigned integer value of <c>t</c>.</item> - <tag><c>double ERL_FLOAT_VALUE(t)</c></tag> - <item>The floating point value of <c>t</c>.</item> - <tag><c>ETERM *ERL_PID_NODE(t)</c></tag> - <item></item> - <tag><c>ETERM *ERL_PID_NODE_UTF8(t)</c></tag> - <item>The node in pid <c>t</c>.</item> - <tag><c>int ERL_PID_NUMBER(t)</c></tag> - <item>The sequence number in pid <c>t</c>.</item> - <tag><c>int ERL_PID_SERIAL(t)</c></tag> - <item>The serial number in pid <c>t</c>.</item> - <tag><c>int ERL_PID_CREATION(t)</c></tag> - <item>The creation number in pid <c>t</c>.</item> - <tag><c>int ERL_PORT_NUMBER(t)</c></tag> - <item>The sequence number in port <c>t</c>.</item> - <tag><c>int ERL_PORT_CREATION(t)</c></tag> - <item>The creation number in port <c>t</c>.</item> - <tag><c>ETERM *ERL_PORT_NODE(t)</c></tag> - <item></item> - <tag><c>ETERM *ERL_PORT_NODE_UTF8(t)</c></tag> - <item>The node in port <c>t</c>.</item> - <tag><c>int ERL_REF_NUMBER(t)</c></tag> - <item>The first part of the reference number in ref <c>t</c>. - Use only for compatibility.</item> - <tag><c>int ERL_REF_NUMBERS(t)</c></tag> - <item>Pointer to the array of reference numbers in ref - <c>t</c>.</item> - <tag><c>int ERL_REF_LEN(t)</c></tag> - <item>The number of used reference numbers in ref - <c>t</c>.</item> - <tag><c>int ERL_REF_CREATION(t)</c></tag> - <item>The creation number in ref <c>t</c>.</item> - <tag><c>int ERL_TUPLE_SIZE(t)</c></tag> - <item>The number of elements in tuple <c>t</c>.</item> - <tag><c>ETERM *ERL_CONS_HEAD(t)</c></tag> - <item>The head element of list <c>t</c>.</item> - <tag><c>ETERM *ERL_CONS_TAIL(t)</c></tag> - <item>A list representing the tail elements of list - <c>t</c>.</item> - </taglist> - </description> - - <funcs> - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_cons(head, tail)</nametext></name> - <fsummary>Prepend a term to the head of a list.</fsummary> - <type> - <v>ETERM *head;</v> - <v>ETERM *tail;</v> - </type> - <desc> - <p>Concatenates two Erlang terms, prepending <c>head</c> - onto <c>tail</c> and thereby creating a - <c>cons</c> cell. - To make a proper list, <c>tail</c> is always to be a list - or an empty list. Notice that <c>NULL</c> is not a valid list.</p> - <list type="bulleted"> - <item><c>head</c> is the new term to be added.</item> - <item><c>tail</c> is the existing list to which - <c>head</c> is concatenated.</item> - </list> - <p>The function returns a new list.</p> - <p><c>ERL_CONS_HEAD(list)</c> and - <c>ERL_CONS_TAIL(list)</c> - can be used to retrieve the head and tail components - from the list. <c>erl_hd(list)</c> and - <c>erl_tl(list)</c> do - the same thing, but check that the argument really is a list.</p> - <p><em>Example:</em></p> - <code type="none"><![CDATA[ -ETERM *list,*anAtom,*anInt; -anAtom = erl_mk_atom("madonna"); -anInt = erl_mk_int(21); -list = erl_mk_empty_list(); -list = erl_cons(anAtom, list); -list = erl_cons(anInt, list); - ... /* do some work */ -erl_free_compound(list); - ]]></code> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_copy_term(term)</nametext></name> - <fsummary>Create a copy of an Erlang term.</fsummary> - <type> - <v>ETERM *term;</v> - </type> - <desc> - <p>Creates and returns a copy of the Erlang term - <c>term</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_element(position, tuple)</nametext></name> - <fsummary>Extract an element from an Erlang tuple.</fsummary> - <type> - <v>int position;</v> - <v>ETERM *tuple;</v> - </type> - <desc> - <p>Extracts a specified element from an Erlang tuple.</p> - <list type="bulleted"> - <item><c>position</c> specifies which element to retrieve - from <c>tuple</c>. The elements are numbered starting - from 1.</item> - <item><c>tuple</c> is an Erlang term containing at least - <c>position</c> elements.</item> - </list> - <p>Returns a new Erlang term corresponding to the requested element, or - <c>NULL</c> if <c>position</c> was greater - than the arity of <c>tuple</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_hd(list)</nametext></name> - <fsummary>Extract the first element from a list.</fsummary> - <type> - <v>ETERM *list;</v> - </type> - <desc> - <p>Extracts the first element from a list.</p> - <p><c>list</c> is an Erlang term containing a list.</p> - <p>Returns an Erlang term corresponding to the head - head element in the list, or a <c>NULL</c> pointer if - <c>list</c> was not a list.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_init(NULL, 0)</nametext></name> - <fsummary>Initialization routine.</fsummary> - <type> - <v>void *NULL;</v> - <v>int 0;</v> - </type> - <desc> - <p>This function must be called before any of the others in the - <c>Erl_Interface</c> library to initialize the - library functions. The arguments must be specified as - <c>erl_init(NULL,0)</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_iolist_length(list)</nametext></name> - <fsummary>Return the length of an I/O list.</fsummary> - <type> - <v>ETERM *list;</v> - </type> - <desc> - <p>Returns the length of an I/O list.</p> - <p><c>list</c> is an Erlang term containing an I/O list.</p> - <p>Returns the length of <c>list</c>, or - <c>-1</c> if <c>list</c> is not an I/O list.</p> - <p>For the definition of an I/O list, see - <seealso marker="#erl_iolist_to_binary"> - <c>erl_iolist_to_binary</c></seealso>.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_iolist_to_binary(term)</nametext></name> - <fsummary>Convert an I/O list to a binary.</fsummary> - <type> - <v>ETERM *list;</v> - </type> - <desc> - <p>Converts an I/O list to a binary term.</p> - <p><c>list</c> is an Erlang term containing a list.</p> - <p>Returns an Erlang binary term, or <c>NULL</c> if - <c>list</c> was not an I/O list.</p> - <p>Informally, an I/O list is a deep list of characters and - binaries that can be sent to an Erlang port. In BNF, an I/O - list is formally defined as follows:</p> - <code type="none"><![CDATA[ -iolist ::= [] - | Binary - | [iohead | iolist] - ; -iohead ::= Binary - | Byte (integer in the range [0..255]) - | iolist - ; - ]]></code> - </desc> - </func> - - <func> - <name since=""><ret>char *</ret><nametext>erl_iolist_to_string(list)</nametext></name> - <fsummary>Convert an I/O list to a <c>NULL</c>-terminated string.</fsummary> - <type> - <v>ETERM *list;</v> - </type> - <desc> - <p>Converts an I/O list to a <c>NULL</c>-terminated C string.</p> - <p><c>list</c> is an Erlang term containing an I/O list. - The I/O list must not contain the integer 0, as C strings may not - contain this value except as a terminating marker.</p> - <p>Returns a pointer to a dynamically allocated - buffer containing a string. If <c>list</c> is not an I/O - list, or if <c>list</c> contains the integer 0, - <c>NULL</c> is returned. It - is the caller's responsibility to free the allocated buffer - with <c>erl_free()</c>.</p> - <p>For the definition of an I/O list, see - <seealso marker="#erl_iolist_to_binary"> - <c>erl_iolist_to_binary</c></seealso>.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_length(list)</nametext></name> - <fsummary>Determine the length of a list.</fsummary> - <type> - <v>ETERM *list;</v> - </type> - <desc> - <p>Determines the length of a proper list.</p> - <p><c>list</c> is an Erlang term containing a proper list. - In a proper list, all tails except the last point to another list - cell, and the last tail points to an empty list.</p> - <p>Returns <c>-1</c> if <c>list</c> is not a proper - list.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_atom(string)</nametext></name> - <fsummary>Create an atom.</fsummary> - <type> - <v>const char *string;</v> - </type> - <desc> - <p>Creates an atom.</p> - <p><c>string</c> is the sequence of characters that will be - used to create the atom.</p> - <p>Returns an Erlang term containing an atom. Notice that it is - the caller's responsibility to ensure that <c>string</c> - contains a valid name for an atom.</p> - <p><c>ERL_ATOM_PTR(atom)</c> and - <c>ERL_ATOM_PTR_UTF8(atom)</c> - can be used to retrieve the atom name (as a <c>NULL</c>-terminated string). - <c>ERL_ATOM_SIZE(atom)</c> - and <c>ERL_ATOM_SIZE_UTF8(atom)</c> return the length - of the atom name.</p> - <note> - <p>The UTF-8 variants were introduced in Erlang/OTP R16 and the - string returned by <c>ERL_ATOM_PTR(atom)</c> was not - <c>NULL</c>-terminated on older releases.</p> - </note> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_binary(bptr, size)</nametext></name> - <fsummary>Create a binary object.</fsummary> - <type> - <v>char *bptr;</v> - <v>int size;</v> - </type> - <desc> - <p>Produces an Erlang binary object from a - buffer containing a sequence of bytes.</p> - <list type="bulleted"> - <item><c>bptr</c> is a pointer to a buffer containing - data to be converted.</item> - <item><c>size</c> indicates the length of - <c>bptr</c>.</item> - </list> - <p>Returns an Erlang binary object.</p> - <p><c>ERL_BIN_PTR(bin)</c> retrieves a pointer to - the binary data. <c>ERL_BIN_SIZE(bin)</c> retrieves the - size.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_empty_list()</nametext></name> - <fsummary>Create an empty Erlang list.</fsummary> - <desc> - <p>Creates and returns an empty Erlang list. - Notice that <c>NULL</c> is not used to represent an empty list; - Use this function instead.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_estring(string, len)</nametext></name> - <fsummary>Create an Erlang string.</fsummary> - <type> - <v>char *string;</v> - <v>int len;</v> - </type> - <desc> - <p>Creates a list from a sequence of bytes.</p> - <list type="bulleted"> - <item><c>string</c> is a buffer containing a sequence of - bytes. The buffer does not need to be <c>NULL</c>-terminated.</item> - <item><c>len</c> is the length of - <c>string</c>.</item> - </list> - <p>Returns an Erlang list object corresponding to - the character sequence in <c>string</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_float(f)</nametext></name> - <fsummary>Create an Erlang float.</fsummary> - <type> - <v>double f;</v> - </type> - <desc> - <p>Creates an Erlang float.</p> - <p><c>f</c> is a value to be converted to an Erlang - float.</p> - <p>Returns an Erlang float object with the value - specified in <c>f</c> or <c>NULL</c> if - <c>f</c> is not finite.</p> - <p><c>ERL_FLOAT_VALUE(t)</c> can be used to retrieve the - value from an Erlang float.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_int(n)</nametext></name> - <fsummary>Create an Erlang integer.</fsummary> - <type> - <v>int n;</v> - </type> - <desc> - <p>Creates an Erlang integer.</p> - <p><c>n</c> is a value to be converted to an Erlang - integer.</p> - <p>Returns an Erlang integer object with the - value specified in <c>n</c>.</p> - <p><c>ERL_INT_VALUE(t)</c> can be used to retrieve the - value from an Erlang integer.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_list(array, arrsize)</nametext></name> - <fsummary>Create a list from an array.</fsummary> - <type> - <v>ETERM **array;</v> - <v>int arrsize;</v> - </type> - <desc> - <p>Creates an Erlang list from an array of Erlang terms, such - that each element in the list corresponds to one element in - the array.</p> - <list type="bulleted"> - <item><c>array</c> is an array of Erlang terms.</item> - <item><c>arrsize</c> is the number of elements in - <c>array</c>.</item> - </list> - <p>The function creates an Erlang list object, whose length - <c>arrsize</c> and whose elements are taken from the - terms in <c>array</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_long_ref(node, n1, n2, n3, creation)</nametext></name> - <fsummary>Create an Erlang reference.</fsummary> - <type> - <v>const char *node;</v> - <v>unsigned int n1, n2, n3;</v> - <v>unsigned int creation;</v> - </type> - <desc> - <p>Creates an Erlang reference, with 82 bits.</p> - <list type="bulleted"> - <item><c>node</c> is the name of the C-node.</item> - <item><c>n1</c>, <c>n2</c>, and - <c>n3</c> can be seen as one big number - <c>n1*2^64+n2*2^32+n3</c>, which is to be chosen - uniquely for each reference created for a given C-node.</item> - <item><c>creation</c> is an arbitrary number.</item> - </list> - <p>Notice that <c>n3</c> and <c>creation</c> - are limited in precision, so only the low 18 and 2 bits of these - numbers are used.</p> - <p>Returns an Erlang reference object.</p> - <p><c>ERL_REF_NODE(ref)</c>, - <c>ERL_REF_NUMBERS(ref)</c>, - <c>ERL_REF_LEN(ref)</c>, and - <c>ERL_REF_CREATION(ref)</c> can be used to retrieve the - values used to create the reference.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_pid(node, number, serial, creation)</nametext></name> - <fsummary>Create a process identifier.</fsummary> - <type> - <v>const char *node;</v> - <v>unsigned int number;</v> - <v>unsigned int serial;</v> - <v>unsigned int creation;</v> - </type> - <desc> - <p>Creates an Erlang process identifier (pid). The - resulting pid can be used by Erlang processes wishing to - communicate with the C-node.</p> - <list type="bulleted"> - <item><c>node</c> is the name of the C-node.</item> - <item><c>number</c>, <c>serial</c>, and - <c>creation</c> are - arbitrary numbers. Notice that these are limited in - precision, so only the low 15, 3, and 2 bits of these numbers - are used.</item> - </list> - <p>Returns an Erlang pid object.</p> - <p><c>ERL_PID_NODE(pid)</c>, - <c>ERL_PID_NUMBER(pid)</c>, - <c>ERL_PID_SERIAL(pid)</c>, and - <c>ERL_PID_CREATION(pid)</c> - can be used to retrieve the four values used to create the pid.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_port(node, number, creation)</nametext></name> - <fsummary>Create a port identifier.</fsummary> - <type> - <v>const char *node;</v> - <v>unsigned int number;</v> - <v>unsigned int creation;</v> - </type> - <desc> - <p>Creates an Erlang port identifier.</p> - <list type="bulleted"> - <item><c>node</c> is the name of the C-node.</item> - <item><c>number</c> and <c>creation</c> are - arbitrary numbers. Notice that these are limited in - precision, so only the low 18 and 2 bits of these numbers - are used.</item> - </list> - <p>Returns an Erlang port object.</p> - <p><c>ERL_PORT_NODE(port)</c>, - <c>ERL_PORT_NUMBER(port)</c>, - and <c>ERL_PORT_CREATION</c> can be used to retrieve the - three values used to create the port.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_ref(node, number, creation)</nametext></name> - <fsummary>Create an old Erlang reference.</fsummary> - <type> - <v>const char *node;</v> - <v>unsigned int number;</v> - <v>unsigned int creation;</v> - </type> - <desc> - <p>Creates an old Erlang reference, with - only 18 bits - use <c>erl_mk_long_ref</c> instead.</p> - <list type="bulleted"> - <item><c>node</c> is the name of the C-node.</item> - <item><c>number</c> is to be chosen uniquely for each - reference created for a given C-node.</item> - <item><c>creation</c> is an arbitrary number.</item> - </list> - <p>Notice that <c>number</c> and <c>creation</c> - are limited in precision, so only the low 18 and 2 bits of these - numbers are used.</p> - <p>Returns an Erlang reference object.</p> - <p><c>ERL_REF_NODE(ref)</c>, - <c>ERL_REF_NUMBER(ref)</c>, and - <c>ERL_REF_CREATION(ref)</c> can be used to retrieve the - three values used to create the reference.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_string(string)</nametext></name> - <fsummary>Create a string.</fsummary> - <type> - <v>char *string;</v> - </type> - <desc> - <p>Creates a list from a <c>NULL</c>-terminated string.</p> - <p><c>string</c> is a <c>NULL</c>-terminated sequence of - characters - (that is, a C string) from which the list will be created.</p> - <p>Returns an Erlang list.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_tuple(array, arrsize)</nametext></name> - <fsummary>Create an Erlang tuple from an array.</fsummary> - <type> - <v>ETERM **array;</v> - <v>int arrsize;</v> - </type> - <desc> - <p>Creates an Erlang tuple from an array of Erlang terms.</p> - <list type="bulleted"> - <item><c>array</c> is an array of Erlang terms.</item> - <item><c>arrsize</c> is the number of elements in - <c>array</c>.</item> - </list> - <p>The function creates an Erlang tuple, whose arity is - <c>size</c> and whose elements are taken from the terms - in <c>array</c>.</p> - <p>To retrieve the size of a tuple, either use function - <c>erl_size</c> (which checks the type of the - checked term and works for a binary as well as for a tuple) or - <c>ERL_TUPLE_SIZE(tuple)</c> returns the arity of a tuple. - <c>erl_size()</c> does the same thing, but it checks - that the argument is a tuple. - <c>erl_element(index,tuple)</c> returns the element - corresponding to a given position in the tuple.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_uint(n)</nametext></name> - <fsummary>Create an unsigned integer.</fsummary> - <type> - <v>unsigned int n;</v> - </type> - <desc> - <p>Creates an Erlang unsigned integer.</p> - <p><c>n</c> is a value to be converted to an Erlang - unsigned integer.</p> - <p>Returns an Erlang unsigned integer object with - the value specified in <c>n</c>.</p> - <p><c>ERL_INT_UVALUE(t)</c> can be used to retrieve the - value from an Erlang unsigned integer.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_mk_var(name)</nametext></name> - <fsummary>Create an Erlang variable.</fsummary> - <type> - <v>char *name;</v> - </type> - <desc> - <p>Creates an unbound Erlang variable. The variable can later be bound - through pattern matching or assignment.</p> - <p><c>name</c> specifies a name for the variable.</p> - <p>Returns an Erlang variable object with the - name <c>name</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_print_term(stream, term)</nametext></name> - <fsummary>Print an Erlang term.</fsummary> - <type> - <v>FILE *stream;</v> - <v>ETERM *term;</v> - </type> - <desc> - <p>Prints the specified Erlang term to the specified output stream.</p> - <list type="bulleted"> - <item><c>stream</c> indicates where the function is to - send its output.</item> - <item><c>term</c> is the Erlang term to print.</item> - </list> - <p>Returns the number of characters written on success, otherwise a - negative value.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_set_compat_rel(release_number)</nametext></name> - <fsummary>Set the Erl_Interface library in compatibility mode.</fsummary> - <type> - <v>unsigned release_number;</v> - </type> - <desc> - <p>By default, the <c>Erl_Interface</c> library is only - guaranteed to be compatible with other Erlang/OTP components from the - same release as the <c>Erl_Interface</c> library itself. - For example, <c>Erl_Interface</c> from Erlang/OTP R10 - is not compatible - with an Erlang emulator from Erlang/OTP R9 by default.</p> - <p>A call to <c>erl_set_compat_rel(release_number)</c> sets - the <c>Erl_Interface</c> library in compatibility mode of - release <c>release_number</c>. Valid range of - <c>release_number</c> - is [7, current release]. This makes it possible to - communicate with Erlang/OTP components from earlier releases.</p> - <note> - <p>If this function is called, it may only be called once - directly after the call to function - <seealso marker="#erl_init">erl_init()</seealso>.</p> - </note> - <warning> - <p>You may run into trouble if this feature is used - carelessly. Always ensure that all communicating - components are either from the same Erlang/OTP release, or - from release X and release Y where all components - from release Y are in compatibility mode of release X.</p> - </warning> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_size(term)</nametext></name> - <fsummary>Return the arity of a tuple or binary.</fsummary> - <type> - <v>ETERM *term;</v> - </type> - <desc> - <p>Returns either the arity of an Erlang tuple or the - number of bytes in an Erlang binary object.</p> - <p><c>term</c> is an Erlang tuple or an Erlang binary - object.</p> - <p>Returns the size of <c>term</c> as described - above, or <c>-1</c> if <c>term</c> is not one of the two - supported types.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_tl(list)</nametext></name> - <fsummary>Extract the tail from a list.</fsummary> - <type> - <v>ETERM *list;</v> - </type> - <desc> - <p>Extracts the tail from a list.</p> - <p><c>list</c> is an Erlang term containing a list.</p> - <p>Returns an Erlang list corresponding to the - original list minus the first element, or <c>NULL</c> pointer if - <c>list</c> was not a list.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_var_content(term, name)</nametext></name> - <fsummary>Extract the content of a variable.</fsummary> - <type> - <v>ETERM *term;</v> - <v>char *name;</v> - </type> - <desc> - <p>Returns the contents of the specified variable in an Erlang term.</p> - <list type="bulleted"> - <item><c>term</c> is an Erlang term. In order for this - function to succeed, - <c>term</c> must either be an Erlang variable with - the specified name, or it must be an Erlang list or tuple - containing a variable with the specified name. Other Erlang - types cannot contain variables.</item> - <item><c>name</c> is the name of an Erlang variable. - </item> - </list> - <p>Returns the Erlang object corresponding to the value of - <c>name</c> in <c>term</c>. If no variable - with the name <c>name</c> is found in - <c>term</c>, or if <c>term</c> is - not a valid Erlang term, <c>NULL</c> is returned.</p> - </desc> - </func> - </funcs> -</cref> diff --git a/lib/erl_interface/doc/src/erl_format.xml b/lib/erl_interface/doc/src/erl_format.xml deleted file mode 100644 index b5e895c720..0000000000 --- a/lib/erl_interface/doc/src/erl_format.xml +++ /dev/null @@ -1,138 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE cref SYSTEM "cref.dtd"> - -<cref> - <header> - <copyright> - <year>1996</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>erl_format</title> - <prepared>Torbjörn Törnkvist</prepared> - <responsible>Torbjörn Törnkvist</responsible> - <docno></docno> - <approved>Bjarne Däcker</approved> - <checked>Torbjörn Törnkvist</checked> - <date>1996-10-16</date> - <rev>A</rev> - <file>erl_format.xml</file> - </header> - <lib>erl_format</lib> - <libsummary>Create and match Erlang terms.</libsummary> - <description> - <p>This module contains two routines: one general function for - creating Erlang terms and one for pattern matching Erlang terms.</p> - </description> - - <funcs> - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_format(FormatStr, ...)</nametext></name> - <fsummary>Create an Erlang term.</fsummary> - <type> - <v>char *FormatStr;</v> - </type> - <desc> - <p>A general function for creating Erlang terms using - a format specifier and a corresponding set of arguments, much - in the way <c>printf()</c> works.</p> - <p><c>FormatStr</c> is a format specification string. - The valid format specifiers are as follows:</p> - <list type="bulleted"> - <item><c>~i</c> - Integer</item> - <item><c>~f</c> - Floating point</item> - <item><c>~a</c> - Atom</item> - <item><c>~s</c> - String</item> - <item><c>~w</c> - Arbitrary Erlang term</item> - </list> - <p>For each format specifier included in <c>FormatStr</c>, - there must be a corresponding argument following - <c>FormatStr</c>. An Erlang term is built according to - <c>FormatStr</c> with values and Erlang terms substituted - from the corresponding arguments, and according to the individual - format specifiers. For example:</p> - <code type="none"><![CDATA[ -erl_format("[{name,~a},{age,~i},{data,~w}]", - "madonna", - 21, - erl_format("[{adr,~s,~i}]","E-street",42)); - ]]></code> - <p>This creates an <c>(ETERM *)</c> structure corresponding - to the Erlang term - <c>[{name,madonna},{age,21},{data,[{adr,"E-street",42}]}]</c></p> - <p>The function returns an Erlang term, or <c>NULL</c> if - <c>FormatStr</c> does not describe a valid Erlang - term.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_match(Pattern, Term)</nametext></name> - <fsummary>Perform pattern matching.</fsummary> - <type> - <v>ETERM *Pattern,*Term;</v> - </type> - <desc> - <p>This function is used to perform pattern matching similar - to that done in Erlang. For matching rules and more examples, see - section <seealso marker="doc/reference_manual:patterns"> - Pattern Matching</seealso> in the Erlang Reference Manual.</p> - <list type="bulleted"> - <item><c>Pattern</c> is an Erlang term, possibly - containing unbound variables.</item> - <item><c>Term</c> is an Erlang term that we wish to match - against <c>Pattern</c>.</item> - </list> - <p><c>Term</c> and <c>Pattern</c> are compared - and any unbound variables in <c>Pattern</c> are bound to - corresponding values in <c>Term</c>.</p> - <p>If <c>Term</c> and <c>Pattern</c> can be - matched, the function returns a non-zero value and binds any unbound - variables in <c>Pattern</c>. If <c>Term</c> - and <c>Pattern</c> do - not match, <c>0</c> is returned. For example:</p> - <code type="none"><![CDATA[ -ETERM *term, *pattern, *pattern2; -term1 = erl_format("{14,21}"); -term2 = erl_format("{19,19}"); -pattern1 = erl_format("{A,B}"); -pattern2 = erl_format("{F,F}"); -if (erl_match(pattern1, term1)) { - /* match succeeds: - * A gets bound to 14, - * B gets bound to 21 - */ - ... -} -if (erl_match(pattern2, term1)) { - /* match fails because F cannot be - * bound to two separate values, 14 and 21 - */ - ... -} -if (erl_match(pattern2, term2)) { - /* match succeeds and F gets bound to 19 */ - ... -} - ]]></code> - <p><c>erl_var_content()</c> can be used to retrieve the - content of any variables bound as a result of a call to - <c>erl_match()</c>.</p> - </desc> - </func> - </funcs> -</cref> diff --git a/lib/erl_interface/doc/src/erl_interface.xml b/lib/erl_interface/doc/src/erl_interface.xml deleted file mode 100644 index decd66046a..0000000000 --- a/lib/erl_interface/doc/src/erl_interface.xml +++ /dev/null @@ -1,637 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE chapter SYSTEM "chapter.dtd"> - -<chapter> - <header> - <copyright> - <year>1996</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>The Erl_Interface Library</title> - <prepared>Torbjörn Törnkvist</prepared> - <responsible>Torbjörn Törnkvist</responsible> - <docno></docno> - <approved>Bjarne Däcker</approved> - <checked>K.Lundin</checked> - <date>990113</date> - <rev>A</rev> - <file>erl_interface.sgml</file> - </header> - <p>The Erl_Interface library contains functions. which help you - integrate programs written in C and Erlang. The functions in - Erl_Interface support the following:</p> - <list type="bulleted"> - <item>manipulation of data represented as Erlang data types</item> - <item>conversion of data between C and Erlang formats</item> - <item>encoding and decoding of Erlang data types for transmission or storage</item> - <item>communication between C nodes and Erlang processes</item> - <item>backup and restore of C node state to and from Mnesia</item> - </list> - <p>In the following sections, these topics are described:</p> - <list type="bulleted"> - <item>compiling your code for use with Erl_Interface</item> - <item>initializing Erl_Interface</item> - <item>encoding, decoding, and sending Erlang terms</item> - <item>building terms and patterns</item> - <item>pattern matching</item> - <item>connecting to a distributed Erlang node</item> - <item>using EPMD</item> - <item>sending and receiving Erlang messages</item> - <item>remote procedure calls</item> - <item>global names</item> - <item>the registry</item> - </list> - - <section> - <title>Deprecation and Removal</title> - <note><p>The support for VxWorks is deprecated as of OTP 22, and - will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> - </section> - - <section> - <title>Compiling and Linking Your Code</title> - <p>In order to use any of the Erl_Interface functions, include the - following lines in your code:</p> - <code type="none"><![CDATA[ -#include "erl_interface.h" -#include "ei.h" ]]></code> - <p>Determine where the top directory of your OTP installation is. You - can find this out by starting Erlang and entering the following - command at the Eshell prompt:</p> - <code type="none"><![CDATA[ -Eshell V4.7.4 (abort with ^G) -1> code:root_dir(). -/usr/local/otp ]]></code> - <p>To compile your code, make sure that your C compiler knows where - to find <c>erl_interface.h</c> by specifying an appropriate <c>-I</c> - argument on the command line, or by adding it to the <c>CFLAGS</c> - definition in your <c>Makefile</c>. The correct value for this path is - <c>$OTPROOT/lib/erl_interface</c><em>Vsn</em><c>/include</c>, where <c>$OTPROOT</c> is the path - reported by <c>code:root_dir/0</c> in the above example, and <em>Vsn</em> is - the version of the Erl_interface application, for example - <c>erl_interface-3.2.3</c></p> - <code type="none"><![CDATA[ -$ cc -c -I/usr/local/otp/lib/erl_interface-3.2.3/include myprog.c ]]></code> - <p>When linking, you will need to specify the path to - <c>liberl_interface.a</c> and <c>libei.a</c> with - <c>-L$OTPROOT/lib/erl_interface-3.2.3/lib</c>, and you will need to specify the - name of the libraries with <c>-lerl_interface -lei</c>. You can do - this on the command line or by adding the flags to the <c>LDFLAGS</c> - definition in your <c>Makefile</c>.</p> - <code type="none"><![CDATA[ -$ ld -L/usr/local/otp/lib/erl_interface-3.2.3/ - lib myprog.o -lerl_interface -lei -o myprog ]]></code> - <p>Also, on some systems it may be necessary to link with some - additional libraries (e.g. <c>libnsl.a</c> and <c>libsocket.a</c> on - Solaris, or <c>wsock32.lib</c> on Windows) in order to use the - communication facilities of Erl_Interface.</p> - <p>If you are using Erl_Interface functions in a threaded - application based on POSIX threads or Solaris threads, then - Erl_Interface needs access to some of the synchronization - facilities in your threads package, and you will need to specify - additional compiler flags in order to indicate which of the packages - you are using. Define <c>_REENTRANT</c> and either <c>STHREADS</c> or - <c>PTHREADS</c>. The default is to use POSIX threads if - <c>_REENTRANT</c> is specified.</p> - <p>Note that both single threaded and default versions of the Erl_interface - and Ei libraries are provided. (The single threaded versions are named - <c>liberl_interface_st</c> and <c>libei_st</c>). Whether the default - versions of the libraries have support for threads or not is determined by if - the platform in question has support for POSIX or Solaris threads. To check this, - have a look in the <c>eidefs.mk</c> file in the erl_interface src directory.</p> - </section> - - <section> - <title>Initializing the erl_interface Library</title> - <p>Before calling any of the other Erl_Interface functions, you - must call <c>erl_init()</c> exactly once to initialize the library. - <c>erl_init()</c> takes two arguments, however the arguments are no - longer used by Erl_Interface, and should therefore be specified - as <c>erl_init(NULL,0)</c>.</p> - </section> - - <section> - <title>Encoding, Decoding and Sending Erlang Terms</title> - <p>Data sent between distributed Erlang nodes is encoded in the - Erlang external format. Consequently, you have to encode and decode - Erlang terms into byte streams if you want to use the distribution - protocol to communicate between a C program and Erlang. </p> - <p>The Erl_Interface library supports this activity. It has a - number of C functions which create and manipulate Erlang data - structures. The library also contains an encode and a decode function. - The example below shows how to create and encode an Erlang tuple - <c>{tobbe,3928}</c>:</p> - <code type="none"><![CDATA[ - -ETERM *arr[2], *tuple; -char buf[BUFSIZ]; -int i; - -arr[0] = erl_mk_atom("tobbe"); -arr[1] = erl_mk_integer(3928); -tuple = erl_mk_tuple(arr, 2); -i = erl_encode(tuple, buf); ]]></code> - <p>Alternatively, you can use <c>erl_send()</c> and - <c>erl_receive_msg</c>, which handle the encoding and decoding of - messages transparently.</p> - <p>Refer to the Reference Manual for a complete description of the - following modules:</p> - <list type="bulleted"> - <item>the <c>erl_eterm</c> module for creating Erlang terms</item> - <item>the <c>erl_marshal</c> module for encoding and decoding routines.</item> - </list> - </section> - - <section> - <title>Building Terms and Patterns</title> - <p>The previous example can be simplified by using - <c>erl_format()</c> to create an Erlang term.</p> - <code type="none"><![CDATA[ - -ETERM *ep; -ep = erl_format("{~a,~i}", "tobbe", 3928); ]]></code> - <p>Refer to the Reference Manual, the <c>erl_format</c> module, for a - full description of the different format directives. The following - example is more complex:</p> - <code type="none"><![CDATA[ - -ETERM *ep; -ep = erl_format("[{name,~a},{age,~i},{data,~w}]", - "madonna", - 21, - erl_format("[{adr,~s,~i}]", "E-street", 42)); -erl_free_compound(ep); ]]></code> - <p>As in previous examples, it is your responsibility to free the - memory allocated for Erlang terms. In this example, - <c>erl_free_compound()</c> ensures that the complete term pointed to - by <c>ep</c> is released. This is necessary, because the pointer from - the second call to <c>erl_format()</c> is lost. </p> - <p>The following - example shows a slightly different solution:</p> - <code type="none"><![CDATA[ - -ETERM *ep,*ep2; -ep2 = erl_format("[{adr,~s,~i}]","E-street",42); -ep = erl_format("[{name,~a},{age,~i},{data,~w}]", - "madonna", 21, ep2); -erl_free_term(ep); -erl_free_term(ep2); ]]></code> - <p>In this case, you free the two terms independently. The order in - which you free the terms <c>ep</c> and <c>ep2</c> is not important, - because the Erl_Interface library uses reference counting to - determine when it is safe to actually remove objects. </p> - <p>If you are not sure whether you have freed the terms properly, you - can use the following function to see the status of the fixed term - allocator:</p> - <code type="none"><![CDATA[ -long allocated, freed; - -erl_eterm_statistics(&allocated,&freed); -printf("currently allocated blocks: %ld\ -",allocated); -printf("length of freelist: %ld\ -",freed); - -/* really free the freelist */ -erl_eterm_release(); - ]]></code> - <p>Refer to the Reference Manual, the <c>erl_malloc</c> module for more - information.</p> - </section> - - <section> - <title>Pattern Matching</title> - <p>An Erlang pattern is a term that may contain unbound variables or - <c>"do not care"</c> symbols. Such a pattern can be matched against a - term and, if the match is successful, any unbound variables in the - pattern will be bound as a side effect. The content of a bound - variable can then be retrieved.</p> - <code type="none"><![CDATA[ - -ETERM *pattern; -pattern = erl_format("{madonna,Age,_}"); ]]></code> - <p><c>erl_match()</c> is used to perform pattern matching. It takes a - pattern and a term and tries to match them. As a side effect any unbound - variables in the pattern will be bound. In the following example, we - create a pattern with a variable <em>Age</em> which appears at two - positions in the tuple. The pattern match is performed as follows:</p> - <list type="ordered"> - <item><c>erl_match()</c> will bind the contents of - <em>Age</em> to <em>21</em> the first time it reaches the variable</item> - <item>the second occurrence of <em>Age</em> will cause a test for - equality between the terms since <em>Age</em> is already bound to - <em>21</em>. Since <em>Age</em> is bound to 21, the equality test will - succeed and the match continues until the end of the pattern.</item> - <item>if the end of the pattern is reached, the match succeeds and you - can retrieve the contents of the variable</item> - </list> - <code type="none"><![CDATA[ -ETERM *pattern,*term; -pattern = erl_format("{madonna,Age,Age}"); -term = erl_format("{madonna,21,21}"); -if (erl_match(pattern, term)) { - fprintf(stderr, "Yes, they matched: Age = "); - ep = erl_var_content(pattern, "Age"); - erl_print_term(stderr, ep); - fprintf(stderr,"\ -"); - erl_free_term(ep); -} -erl_free_term(pattern); -erl_free_term(term); ]]></code> - <p>Refer to the Reference Manual, the <c>erl_match()</c> function for - more information.</p> - </section> - - <section> - <title>Connecting to a Distributed Erlang Node</title> - <p>In order to connect to a distributed Erlang node you need to first - initialize the connection routine with <c>erl_connect_init()</c>, - which stores information such as the host name, node name, and IP - address for later use:</p> - <code type="none"><![CDATA[ -int identification_number = 99; -int creation=1; -char *cookie="a secret cookie string"; /* An example */ -erl_connect_init(identification_number, cookie, creation); ]]></code> - <p>Refer to the Reference Manual, the <c>erl_connect</c> module for more information.</p> - <p>After initialization, you set up the connection to the Erlang node. - Use <c>erl_connect()</c> to specify the Erlang node you want to - connect to. The following example sets up the connection and should - result in a valid socket file descriptor:</p> - <code type="none"><![CDATA[ -int sockfd; -char *nodename="xyz@chivas.du.etx.ericsson.se"; /* An example */ -if ((sockfd = erl_connect(nodename)) < 0) - erl_err_quit("ERROR: erl_connect failed"); ]]></code> - <p><c>erl_err_quit()</c> prints the specified string and terminates - the program. Refer to the Reference Manual, the <c>erl_error()</c> - function for more information.</p> - </section> - - <section> - <title>Using EPMD</title> - <p><c>Epmd</c> is the Erlang Port Mapper Daemon. Distributed Erlang nodes - register with <c>epmd</c> on the localhost to indicate to other nodes that - they exist and can accept connections. <c>Epmd</c> maintains a register of - node and port number information, and when a node wishes to connect to - another node, it first contacts <c>epmd</c> in order to find out the correct - port number to connect to.</p> - <p>When you use <c>erl_connect()</c> to connect to an Erlang node, a - connection is first made to <c>epmd</c> and, if the node is known, a - connection is then made to the Erlang node.</p> - <p>C nodes can also register themselves with <c>epmd</c> if they want other - nodes in the system to be able to find and connect to them.</p> - <p>Before registering with <c>epmd</c>, you need to first create a listen socket - and bind it to a port. Then:</p> - <code type="none"><![CDATA[ -int pub; - -pub = erl_publish(port); ]]></code> - <p><c>pub</c> is a file descriptor now connected to <c>epmd</c>. <c>Epmd</c> - monitors the other end of the connection, and if it detects that the - connection has been closed, the node will be unregistered. So, if you - explicitly close the descriptor or if your node fails, it will be - unregistered from <c>epmd</c>.</p> - <p>Be aware that on some systems (such as VxWorks), a failed node will - not be detected by this mechanism since the operating system does not - automatically close descriptors that were left open when the node - failed. If a node has failed in this way, <c>epmd</c> will prevent you from - registering a new node with the old name, since it thinks that the old - name is still in use. In this case, you must unregister the name - explicitly:</p> - <code type="none"><![CDATA[ -erl_unpublish(node); ]]></code> - <p>This will cause <c>epmd</c> to close the connection from the far end. Note - that if the name was in fact still in use by a node, the results of - this operation are unpredictable. Also, doing this does not cause the - local end of the connection to close, so resources may be consumed.</p> - </section> - - <section> - <title>Sending and Receiving Erlang Messages</title> - <p>Use one of the following two functions to send messages:</p> - <list type="bulleted"> - <item><c>erl_send()</c></item> - <item><c>erl_reg_send()</c></item> - </list> - <p>As in Erlang, it is possible to send messages to a - <em>Pid</em> or to a registered name. It is easier to send a - message to a registered name because it avoids the problem of finding - a suitable <em>Pid</em>.</p> - <p>Use one of the following two functions to receive messages:</p> - <list type="bulleted"> - <item><c>erl_receive()</c></item> - <item><c>erl_receive_msg()</c></item> - </list> - <p><c>erl_receive()</c> receives the message into a buffer, while - <c>erl_receive_msg()</c> decodes the message into an Erlang term. </p> - - <section> - <title>Example of Sending Messages</title> - <p>In the following example, <c>{Pid, hello_world}</c> is - sent to a registered process <c>my_server</c>. The message is encoded - by <c>erl_send()</c>:</p> - <code type="none"><![CDATA[ -extern const char *erl_thisnodename(void); -extern short erl_thiscreation(void); -#define SELF(fd) erl_mk_pid(erl_thisnodename(),fd,0,erl_thiscreation()) -ETERM *arr[2], *emsg; -int sockfd, creation=1; - -arr[0] = SELF(sockfd); -arr[1] = erl_mk_atom("Hello world"); -emsg = erl_mk_tuple(arr, 2); - -erl_reg_send(sockfd, "my_server", emsg); -erl_free_term(emsg); ]]></code> - <p>The first element of the tuple that is sent is your own - <em>Pid</em>. This enables <c>my_server</c> to reply. Refer to the - Reference Manual, the <c>erl_connect</c> module for more information - about send primitives.</p> - </section> - - <section> - <title>Example of Receiving Messages</title> - <p>In this example <c>{Pid, Something}</c> is received. The - received Pid is then used to return <c>{goodbye,Pid}</c></p> - <code type="none"><![CDATA[ -ETERM *arr[2], *answer; -int sockfd,rc; -char buf[BUFSIZE]; -ErlMessage emsg; - -if ((rc = erl_receive_msg(sockfd , buf, BUFSIZE, &emsg)) == ERL_MSG) { - arr[0] = erl_mk_atom("goodbye"); - arr[1] = erl_element(1, emsg.msg); - answer = erl_mk_tuple(arr, 2); - erl_send(sockfd, arr[1], answer); - erl_free_term(answer); - erl_free_term(emsg.msg); - erl_free_term(emsg.to); -} -} ]]></code> - <p>In order to provide robustness, a distributed Erlang node - occasionally polls all its connected neighbours in an attempt to - detect failed nodes or communication links. A node which receives such - a message is expected to respond immediately with an <c>ERL_TICK</c> message. - This is done automatically by <c>erl_receive()</c>, however when this - has occurred <c>erl_receive</c> returns <c>ERL_TICK</c> to the caller - without storing a message into the <c>ErlMessage</c> structure.</p> - <p>When a message has been received, it is the caller's responsibility - to free the received message <c>emsg.msg</c> as well as <c>emsg.to</c> - or <c>emsg.from</c>, depending on the type of message received.</p> - <p>Refer to the Reference Manual for additional information about the - following modules:</p> - <list type="bulleted"> - <item><c>erl_connect</c></item> - <item><c>erl_eterm</c>.</item> - </list> - </section> - </section> - - <section> - <title>Remote Procedure Calls</title> - <p>An Erlang node acting as a client to another Erlang node - typically sends a request and waits for a reply. Such a request is - included in a function call at a remote node and is called a remote - procedure call. The following example shows how the - Erl_Interface library supports remote procedure calls:</p> - <code type="none"><![CDATA[ - -char modname[]=THE_MODNAME; -ETERM *reply,*ep; -ep = erl_format("[~a,[]]", modname); -if (!(reply = erl_rpc(fd, "c", "c", ep))) - erl_err_msg("<ERROR> when compiling file: %s.erl !\ -", modname); -erl_free_term(ep); -ep = erl_format("{ok,_}"); -if (!erl_match(ep, reply)) - erl_err_msg("<ERROR> compiler errors !\ -"); -erl_free_term(ep); -erl_free_term(reply); ]]></code> - <p><c>c:c/1</c> is called to compile the specified module on the - remote node. <c>erl_match()</c> checks that the compilation was - successful by testing for the expected <c>ok</c>.</p> - <p>Refer to the Reference Manual, the <c>erl_connect</c> module for - more information about <c>erl_rpc()</c>, and its companions - <c>erl_rpc_to()</c> and <c>erl_rpc_from()</c>.</p> - </section> - - <section> - <title>Using Global Names</title> - <p>A C node has access to names registered through the Erlang Global - module. Names can be looked up, allowing the C node to send messages - to named Erlang services. C nodes can also register global names, - allowing them to provide named services to Erlang processes or other C - nodes. </p> - <p>Erl_Interface does not provide a native implementation of the global - service. Instead it uses the global services provided by a "nearby" - Erlang node. In order to use the services described in this section, - it is necessary to first open a connection to an Erlang node.</p> - <p>To see what names there are:</p> - <code type="none"><![CDATA[ -char **names; -int count; -int i; - -names = erl_global_names(fd,&count); - -if (names) - for (i=0; i<count; i++) - printf("%s\ -",names[i]); - -free(names); ]]></code> - <p><c>erl_global_names()</c> allocates and returns a buffer containing - all the names known to global. <c>count</c> will be initialized to - indicate how many names are in the array. The array of strings in - names is terminated by a NULL pointer, so it is not necessary to use - <c>count</c> to determine when the last name is reached.</p> - <p>It is the caller's responsibility to free the array. - <c>erl_global_names()</c> allocates the array and all of the strings - using a single call to <c>malloc()</c>, so <c>free(names)</c> is all - that is necessary.</p> - <p>To look up one of the names:</p> - <code type="none"><![CDATA[ -ETERM *pid; -char node[256]; - -pid = erl_global_whereis(fd,"schedule",node); ]]></code> - <p>If <c>"schedule"</c> is known to global, an Erlang pid is returned - that can be used to send messages to the schedule service. - Additionally, <c>node</c> will be initialized to contain the name of - the node where the service is registered, so that you can make a - connection to it by simply passing the variable to <c>erl_connect()</c>.</p> - <p>Before registering a name, you should already have registered your - port number with <c>epmd</c>. This is not strictly necessary, but if you - neglect to do so, then other nodes wishing to communicate with your - service will be unable to find or connect to your process.</p> - <p>Create a pid that Erlang processes can use to communicate with your - service:</p> - <code type="none"><![CDATA[ -ETERM *pid; - -pid = erl_mk_pid(thisnode,14,0,0); -erl_global_register(fd,servicename,pid); ]]></code> - <p>After registering the name, you should use <c>erl_accept()</c> to wait for - incoming connections.</p> - <p>Do not forget to free <c>pid</c> later with <c>erl_free_term()</c>!</p> - <p>To unregister a name:</p> - <code type="none"><![CDATA[ -erl_global_unregister(fd,servicename); ]]></code> - </section> - - <section> - <title>The Registry</title> - <p>This section describes the use of the registry, a simple mechanism - for storing key-value pairs in a C-node, as well as backing them up or - restoring them from a Mnesia table on an Erlang node. More detailed - information about the individual API functions can be found in the - Reference Manual.</p> - <p>Keys are strings, i.e. <c>NULL</c>-terminated arrays of characters, and values - are arbitrary objects. Although integers and floating point numbers - are treated specially by the registry, you can store strings or binary - objects of any type as pointers.</p> - <p>To start, you need to open a registry:</p> - <code type="none"><![CDATA[ -ei_reg *reg; - -reg = ei_reg_open(45); ]]></code> - <p>The number 45 in the example indicates the approximate number of - objects that you expect to store in the registry. Internally the - registry uses hash tables with collision chaining, so there is no - absolute upper limit on the number of objects that the registry can - contain, but if performance or memory usage are important, then you - should choose a number accordingly. The registry can be resized later.</p> - <p>You can open as many registries as you like (if memory permits).</p> - <p>Objects are stored and retrieved through set and get functions. In - the following examples you see how to store integers, floats, strings - and arbitrary binary objects:</p> - <code type="none"><![CDATA[ -struct bonk *b = malloc(sizeof(*b)); -char *name = malloc(7); - -ei_reg_setival(reg,"age",29); -ei_reg_setfval(reg,"height",1.85); - -strcpy(name,"Martin"); -ei_reg_setsval(reg,"name",name); - -b->l = 42; -b->m = 12; -ei_reg_setpval(reg,"jox",b,sizeof(*b)); ]]></code> - <p>If you attempt to store an object in the registry and there is an - existing object with the same key, the new value will replace the old - one. This is done regardless of whether the new object and the old one - have the same type, so you can, for example, replace a string with an - integer. If the existing value is a string or binary, it will be freed - before the new value is assigned.</p> - <p>Stored values are retrieved from the registry as follows:</p> - <code type="none"><![CDATA[ -long i; -double f; -char *s; -struct bonk *b; -int size; - -i = ei_reg_getival(reg,"age"); -f = ei_reg_getfval(reg,"height"); -s = ei_reg_getsval(reg,"name"); -b = ei_reg_getpval(reg,"jox",&size); ]]></code> - <p>In all of the above examples, the object must exist and it must be of - the right type for the specified operation. If you do not know the - type of a given object, you can ask:</p> - <code type="none"><![CDATA[ -struct ei_reg_stat buf; - -ei_reg_stat(reg,"name",&buf); ]]></code> - <p>Buf will be initialized to contain object attributes.</p> - <p>Objects can be removed from the registry:</p> - <code type="none"><![CDATA[ -ei_reg_delete(reg,"name"); ]]></code> - <p>When you are finished with a registry, close it to remove all the - objects and free the memory back to the system:</p> - <code type="none"><![CDATA[ -ei_reg_close(reg); ]]></code> - - <section> - <title>Backing Up the Registry to Mnesia</title> - <p>The contents of a registry can be backed up to Mnesia on a "nearby" - Erlang node. You need to provide an open connection to the Erlang node - (see <c>erl_connect()</c>). Also, Mnesia 3.0 or later must be running - on the Erlang node before the backup is initiated:</p> - <code type="none"><![CDATA[ -ei_reg_dump(fd, reg, "mtab", dumpflags); ]]></code> - <p>The example above will backup the contents of the registry to the - specified Mnesia table <c>"mtab"</c>. Once a registry has been backed - up to Mnesia in this manner, additional backups will only affect - objects that have been modified since the most recent backup, i.e. - objects that have been created, changed or deleted. The backup - operation is done as a single atomic transaction, so that the entire - backup will be performed or none of it will.</p> - <p>In the same manner, a registry can be restored from a Mnesia table:</p> - <code type="none"><![CDATA[ -ei_reg_restore(fd, reg, "mtab"); ]]></code> - <p>This will read the entire contents of <c>"mtab"</c> into the specified - registry. After the restore, all of the objects in the registry will - be marked as unmodified, so a subsequent backup will only affect - objects that you have modified since the restore.</p> - <p>Note that if you restore to a non-empty registry, objects in the - table will overwrite objects in the registry with the same keys. Also, - the <em>entire</em> contents of the registry is marked as unmodified - after the restore, including any modified objects that were not - overwritten by the restore operation. This may not be your intention.</p> - </section> - - <section> - <title>Storing Strings and Binaries</title> - <p>When string or binary objects are stored in the registry it is - important that a number of simple guidelines are followed. </p> - <p>Most importantly, the object must have been created with a single call - to <c>malloc()</c> (or similar), so that it can later be removed by a - single call to <c>free()</c>. Objects will be freed by the registry - when it is closed, or when you assign a new value to an object that - previously contained a string or binary.</p> - <p>You should also be aware that if you store binary objects that are - context-dependent (e.g. containing pointers or open file descriptors), - they will lose their meaning if they are backed up to a Mnesia table - and subsequently restored in a different context.</p> - <p>When you retrieve a stored string or binary value from the registry, - the registry maintains a pointer to the object and you are passed a - copy of that pointer. You should never free an object retrieved in - this manner because when the registry later attempts to free it, a - runtime error will occur that will likely cause the C-node to crash.</p> - <p>You are free to modify the contents of an object retrieved this way. - However when you do so, the registry will not be aware of the changes - you make, possibly causing it to be missed the next time you make a - Mnesia backup of the registry contents. This can be avoided if you - mark the object as dirty after any such changes with - <c>ei_reg_markdirty()</c>, or pass appropriate flags to - <c>ei_reg_dump()</c>.</p> - </section> - </section> -</chapter> diff --git a/lib/erl_interface/doc/src/erl_malloc.xml b/lib/erl_interface/doc/src/erl_malloc.xml deleted file mode 100644 index 6650620064..0000000000 --- a/lib/erl_interface/doc/src/erl_malloc.xml +++ /dev/null @@ -1,212 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE cref SYSTEM "cref.dtd"> - -<cref> - <header> - <copyright> - <year>1996</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>erl_malloc</title> - <prepared>Torbjörn Törnkvist</prepared> - <responsible>Torbjörn Törnkvist</responsible> - <docno></docno> - <approved>Bjarne Däcker</approved> - <checked>Torbjörn Törnkvist</checked> - <date>1998-07-03</date> - <rev>A</rev> - <file>erl_malloc.xml</file> - </header> - <lib>erl_malloc</lib> - <libsummary>Memory allocation functions.</libsummary> - <description> - <note><p>The support for VxWorks is deprecated as of OTP 22, and - will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> - <p>This module provides functions for allocating and deallocating - memory.</p> - </description> - - <funcs> - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_alloc_eterm(etype)</nametext></name> - <fsummary>Allocate an ETERM structure.</fsummary> - <type> - <v>unsigned char etype;</v> - </type> - <desc> - <p>Allocates an <c>(ETERM)</c> structure.</p> - <p>Specify <c>etype</c> as one of the following - constants:</p> - <list type="bulleted"> - <item><c>ERL_INTEGER</c> - </item> - <item><c>ERL_U_INTEGER</c> (unsigned integer) - </item> - <item><c>ERL_ATOM</c> - </item> - <item><c>ERL_PID</c> (Erlang process identifier) - </item> - <item><c>ERL_PORT</c> - </item> - <item><c>ERL_REF</c> (Erlang reference) - </item> - <item><c>ERL_LIST</c> - </item> - <item><c>ERL_EMPTY_LIST</c> - </item> - <item><c>ERL_TUPLE</c> - </item> - <item><c>ERL_BINARY</c> - </item> - <item><c>ERL_FLOAT</c> - </item> - <item><c>ERL_VARIABLE</c> - </item> - <item><c>ERL_SMALL_BIG</c> (bignum) - </item> - <item><c>ERL_U_SMALL_BIG</c> (bignum) - </item> - </list> - <p><c>ERL_SMALL_BIG</c> and - <c>ERL_U_SMALL_BIG</c> are for - creating Erlang <c>bignums</c>, which can contain integers - of any size. The size of an integer in Erlang is machine-dependent, - but any integer > 2^28 requires a bignum.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_eterm_release(void)</nametext></name> - <fsummary>Clear the ETERM freelist.</fsummary> - <desc> - <p>Clears the freelist, where blocks are placed when they are - released by <c>erl_free_term()</c> and - <c>erl_free_compound()</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_eterm_statistics(allocated, freed)</nametext></name> - <fsummary>Report term allocation statistics.</fsummary> - <type> - <v>long *allocated;</v> - <v>long *freed;</v> - </type> - <desc> - <p>Reports term allocation statistics.</p> - <p><c>allocated</c> and <c>freed</c> are - initialized to - contain information about the fix-allocator used to allocate - <c>ETERM</c> components.</p> - <list type="bulleted"> - <item> - <p><c>allocated</c> is the number of blocks currently - allocated to <c>ETERM</c> objects.</p> - </item> - <item> - <p><c>freed</c> is the length of the freelist, where - blocks are placed when they are - released by <c>erl_free_term()</c> and - <c>erl_free_compound()</c>.</p> - </item> - </list> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_free(ptr)</nametext></name> - <fsummary>Free some memory.</fsummary> - <type> - <v>void *ptr;</v> - </type> - <desc> - <p>Calls the standard - <c>free()</c> function.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_free_array(array, size)</nametext></name> - <fsummary>Free an array of ETERM structures.</fsummary> - <type> - <v>ETERM **array;</v> - <v>int size;</v> - </type> - <desc> - <p>Frees an array of Erlang terms.</p> - <list type="bulleted"> - <item><c>array</c> is an array of ETERM* objects.</item> - <item><c>size</c> is the number of terms in the array. - </item> - </list> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_free_compound(t)</nametext></name> - <fsummary>Free an array of ETERM structures.</fsummary> - <type> - <v>ETERM *t;</v> - </type> - <desc> - <p>Normally it is the programmer's responsibility to free each - Erlang term that has been returned from any of the - <c>Erl_Interface</c> functions. However, as many of the - functions that build new Erlang terms in fact share objects - with other existing terms, it can be difficult for the - programmer to maintain pointers to all such terms to - free them individually.</p> - <p><c>erl_free_compound()</c> recursively frees all of the - subterms associated with a specified Erlang term, regardless of - whether we are still holding pointers to the subterms.</p> - <p>For an example, see section - <seealso marker="ei_users_guide#building_terms_and_patterns">Building Terms and Patterns</seealso> - in the User's Guide.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_free_term(t)</nametext></name> - <fsummary>Free an ETERM structure.</fsummary> - <type> - <v>ETERM *t;</v> - </type> - <desc> - <p>Frees an Erlang term.</p> - </desc> - </func> - - <func> - <name since=""><ret>void</ret><nametext>erl_malloc(size)</nametext></name> - <fsummary>Allocate some memory.</fsummary> - <type> - <v>long size;</v> - </type> - <desc> - <p>Calls the standard - <c>malloc()</c> function.</p> - </desc> - </func> - </funcs> -</cref> diff --git a/lib/erl_interface/doc/src/erl_marshal.xml b/lib/erl_interface/doc/src/erl_marshal.xml deleted file mode 100644 index 33d359d871..0000000000 --- a/lib/erl_interface/doc/src/erl_marshal.xml +++ /dev/null @@ -1,276 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE cref SYSTEM "cref.dtd"> - -<cref> - <header> - <copyright> - <year>1996</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>erl_marshal</title> - <prepared>Torbjörn Törnkvist</prepared> - <responsible>Torbjörn Törnkvist</responsible> - <docno></docno> - <approved>Bjarne Däcker</approved> - <checked>Torbjörn Törnkvist</checked> - <date>1998-07-03</date> - <rev>A</rev> - <file>erl_marshal.xml</file> - </header> - <lib>erl_marshal</lib> - <libsummary>Encoding and decoding of Erlang terms.</libsummary> - <description> - <note><p>The support for VxWorks is deprecated as of OTP 22, and - will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> - <p>This module contains functions for encoding Erlang terms into - a sequence of bytes, and for decoding Erlang terms from a - sequence of bytes.</p> - </description> - - <funcs> - <func> - <name since=""><ret>int</ret><nametext>erl_compare_ext(bufp1, bufp2)</nametext></name> - <fsummary>Compare encoded byte sequences.</fsummary> - <type> - <v>unsigned char *bufp1,*bufp2;</v> - </type> - <desc> - <p>Compares two encoded terms.</p> - <list type="bulleted"> - <item><c>bufp1</c> is a buffer containing an encoded - Erlang term term1.</item> - <item><c>bufp2</c> is a buffer containing an encoded - Erlang term term2.</item> - </list> - <p>Returns <c>0</c> if the terms are equal, <c>-1</c> if - <c>term1</c> < <c>term2</c>, or <c>1</c> if <c>term2</c> < - <c>term1</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>ETERM *</ret><nametext>erl_decode(bufp)</nametext></name> - <name since=""><ret>ETERM *</ret><nametext>erl_decode_buf(bufpp)</nametext></name> - <fsummary>Convert a term from Erlang external format.</fsummary> - <type> - <v>unsigned char *bufp;</v> - <v>unsigned char **bufpp;</v> - </type> - <desc> - <p><c>erl_decode()</c> and - <c>erl_decode_buf()</c> decode - the contents of a buffer and return the corresponding - Erlang term. <c>erl_decode_buf()</c> provides a simple - mechanism for dealing with several encoded terms stored - consecutively in the buffer.</p> - <list type="bulleted"> - <item> - <p><c>bufp</c> is a pointer to a buffer containing one - or more encoded Erlang terms.</p> - </item> - <item> - <p><c>bufpp</c> is the address of a buffer pointer. The - buffer contains one or more consecutively encoded Erlang terms. - Following a successful call to - <c>erl_decode_buf()</c>, <c>bufpp</c> is - updated so that it points to the next encoded term.</p> - </item> - </list> - <p><c>erl_decode()</c> returns an Erlang term - corresponding to the contents of <c>bufp</c> on success, - otherwise <c>NULL</c>. <c>erl_decode_buf()</c> - returns an Erlang - term corresponding to the first of the consecutive terms in - <c>bufpp</c> and moves <c>bufpp</c> forward - to point to the - next term in the buffer. On failure, each of the functions - return <c>NULL</c>.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_encode(term, bufp)</nametext></name> - <name since=""><ret>int</ret><nametext>erl_encode_buf(term, bufpp)</nametext></name> - <fsummary>Convert a term into Erlang external format.</fsummary> - <type> - <v>ETERM *term;</v> - <v>unsigned char *bufp;</v> - <v>unsigned char **bufpp;</v> - </type> - <desc> - <p><c>erl_encode()</c> and - <c>erl_encode_buf()</c> encode - Erlang terms into external format for storage or transmission. - <c>erl_encode_buf()</c> provides a simple mechanism for - encoding several terms consecutively in the same buffer.</p> - <list type="bulleted"> - <item> - <p><c>term</c> is an Erlang term to be encoded.</p> - </item> - <item> - <p><c>bufp</c> is a pointer to a buffer containing one or - more encoded Erlang terms.</p> - </item> - <item> - <p><c>bufpp</c> is a pointer to a pointer to a buffer - containing one or more consecutively encoded Erlang terms. - Following a successful call to - <c>erl_encode_buf()</c>, <c>bufpp</c> is updated so - that it points to the - position for the next encoded term.</p> - </item> - </list> - <p>These functions return the number of bytes written to buffer - on success, otherwise <c>0</c>.</p> - <p>Notice that no bounds checking is done on the buffer. It is - the caller's responsibility to ensure that the buffer is - large enough to hold the encoded terms. You can either use a - static buffer that is large enough to hold the terms you expect - to need in your program, or use <c>erl_term_len()</c> - to determine the exact requirements for a given term.</p> - <p>The following can help you estimate the buffer - requirements for a term. Notice that this information is - implementation-specific, and can change in future versions. - If you are unsure, use <c>erl_term_len()</c>.</p> - <p>Erlang terms are encoded with a 1 byte tag that - identifies the type of object, a 2- or 4-byte length field, - and then the data itself. Specifically:</p> - <taglist> - <tag><c>Tuples</c></tag> - <item>Need 5 bytes, plus the space for each element.</item> - <tag><c>Lists</c></tag> - <item>Need 5 bytes, plus the space for each element, and 1 - more byte for the empty list at the end.</item> - <tag><c>Strings and atoms</c></tag> - <item>Need 3 bytes, plus 1 byte for each character (the - terminating 0 is not encoded). Really long strings (more - than 64k characters) are encoded as lists. Atoms cannot - contain more than 256 characters.</item> - <tag><c>Integers</c></tag> - <item>Need 5 bytes.</item> - <tag><c>Characters</c></tag> - <item>(Integers < 256) need 2 bytes.</item> - <tag><c>Floating point numbers</c></tag> - <item>Need 32 bytes.</item> - <tag><c>Pids</c></tag> - <item>Need 10 bytes, plus the space for the node name, which - is an atom.</item> - <tag><c>Ports and Refs</c></tag> - <item>Need 6 bytes, plus the space for the node name, which - is an atom.</item> - </taglist> - <p>The total space required is the result calculated - from the information above, plus 1 more byte for a - version identifier.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_ext_size(bufp)</nametext></name> - <fsummary>Count elements in encoded term.</fsummary> - <type> - <v>unsigned char *bufp;</v> - </type> - <desc> - <p>Returns the number of elements in an encoded term.</p> - </desc> - </func> - - <func> - <name since=""><ret>unsigned char</ret><nametext>erl_ext_type(bufp)</nametext></name> - <fsummary>Determine type of an encoded byte sequence.</fsummary> - <type> - <v>unsigned char *bufp;</v> - </type> - <desc> - <p>Identifies and returns the type of Erlang term encoded - in a buffer. It skips a trailing <em>magic</em> identifier.</p> - <p>Returns <c>0</c> if the type cannot be determined or - one of:</p> - <list type="bulleted"> - <item><c>ERL_INTEGER</c> - </item> - <item><c>ERL_ATOM</c> - </item> - <item><c>ERL_PID</c> (Erlang process identifier) - </item> - <item><c>ERL_PORT</c> - </item> - <item><c>ERL_REF</c> (Erlang reference) - </item> - <item><c>ERL_EMPTY_LIST</c> - </item> - <item><c>ERL_LIST</c> - </item> - <item><c>ERL_TUPLE</c> - </item> - <item><c>ERL_FLOAT</c> - </item> - <item><c>ERL_BINARY</c> - </item> - <item><c>ERL_FUNCTION</c> - </item> - </list> - </desc> - </func> - - <func> - <name since=""><ret>unsigned char *</ret><nametext>erl_peek_ext(bufp, pos)</nametext></name> - <fsummary>Step over encoded term.</fsummary> - <type> - <v>unsigned char *bufp;</v> - <v>int pos;</v> - </type> - <desc> - <p>This function is used for stepping over one or more - encoded terms in a buffer, to directly access later term.</p> - <list type="bulleted"> - <item><c>bufp</c> is a pointer to a buffer containing one - or more encoded Erlang terms.</item> - <item><c>pos</c> indicates how many terms to step over in - the buffer.</item> - </list> - <p>Returns a pointer to a subterm that can be - used in a later call to <c>erl_decode()</c> to retrieve - the term at that position. If there is no term, or - <c>pos</c> would exceed the size of the terms in the - buffer, <c>NULL</c> is returned.</p> - </desc> - </func> - - <func> - <name since=""><ret>int</ret><nametext>erl_term_len(t)</nametext></name> - <fsummary>Determine encoded size of term.</fsummary> - <type> - <v>ETERM *t;</v> - </type> - <desc> - <p>Determines the buffer space that would be - needed by <c>t</c> if it were encoded into Erlang external - format by <c>erl_encode()</c>.</p> - <p>Returns the size in bytes.</p> - </desc> - </func> - </funcs> -</cref> diff --git a/lib/erl_interface/doc/src/part_erl_interface.xml b/lib/erl_interface/doc/src/part_erl_interface.xml deleted file mode 100644 index e256cfa193..0000000000 --- a/lib/erl_interface/doc/src/part_erl_interface.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>1996</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>Erl_Interface User's Guide</title> - <prepared>Gordon Beaton</prepared> - <docno></docno> - <date>1998-11-30</date> - <rev>1.2</rev> - <file>part_erl_interface.sgml</file> - </header> - <xi:include href="erl_interface.xml"/> -</part> diff --git a/lib/erl_interface/doc/src/ref_man.xml b/lib/erl_interface/doc/src/ref_man.xml index a4f947c79f..d00868562f 100644 --- a/lib/erl_interface/doc/src/ref_man.xml +++ b/lib/erl_interface/doc/src/ref_man.xml @@ -31,22 +31,10 @@ <description> <note><p>The support for VxWorks is deprecated as of OTP 22, and will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> </description> <xi:include href="ei.xml"/> <xi:include href="ei_connect.xml"/> <xi:include href="registry.xml"/> - <xi:include href="erl_connect.xml"/> - <xi:include href="erl_error.xml"/> - <xi:include href="erl_eterm.xml"/> - <xi:include href="erl_format.xml"/> - <xi:include href="erl_global.xml"/> - <xi:include href="erl_malloc.xml"/> - <xi:include href="erl_marshal.xml"/> - <xi:include href="erl_call.xml"/> + <xi:include href="ei_global.xml"/> + <xi:include href="erl_call_cmd.xml"/> </application> diff --git a/lib/erl_interface/doc/src/ref_man_ei.xml b/lib/erl_interface/doc/src/ref_man_ei.xml deleted file mode 100644 index d8d1deaea1..0000000000 --- a/lib/erl_interface/doc/src/ref_man_ei.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE application SYSTEM "application.dtd"> - -<application xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2002</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>EI Library Reference</title> - <prepared>Gordon Beaton</prepared> - <docno></docno> - <date>1998-11-30</date> - <rev>1.2</rev> - <file>ref_man_ei.xml</file> - </header> - <description> - <note><p>The support for VxWorks is deprecated as of OTP 22, and - will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> - <note> - <p>By default, the <c>ei</c> library is only guaranteed - to be compatible with other Erlang/OTP components from the same - release as the <c>ei</c> library itself. See the documentation of the - <seealso marker="ei#ei_set_compat_rel">ei_set_compat_rel()</seealso> - function on how to communicate with Erlang/OTP components from earlier - releases.</p> - </note> - </description> - <xi:include href="ei.xml"/> - <xi:include href="ei_connect.xml"/> - <xi:include href="registry.xml"/> -</application> diff --git a/lib/erl_interface/doc/src/ref_man_erl_interface.xml b/lib/erl_interface/doc/src/ref_man_erl_interface.xml deleted file mode 100644 index 2b69d0fa74..0000000000 --- a/lib/erl_interface/doc/src/ref_man_erl_interface.xml +++ /dev/null @@ -1,60 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE application SYSTEM "application.dtd"> - -<application xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>1996</year><year>2016</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>Erl_Interface Library Reference</title> - <prepared>Gordon Beaton</prepared> - <docno></docno> - <date>1998-11-30</date> - <rev>1.2</rev> - <file>ref_man_erl_interface.xml</file> - </header> - <description> - <note><p>The support for VxWorks is deprecated as of OTP 22, and - will be removed in OTP 23.</p></note> - <note><p>The old legacy <c>erl_interface</c> library (functions - with prefix <c>erl_</c>) is deprecated as of OTP 22, and will be - removed in OTP 23. This does not apply to the <c>ei</c> - library. Reasonably new <c>gcc</c> compilers will issue deprecation - warnings. In order to disable these warnings, define the macro - <c>EI_NO_DEPR_WARN</c>.</p></note> - <p>The <c>erl_interface</c> library is a <c>C</c> interface library - for communication with <c>Erlang</c>.</p> - <note> - <p>By default, the <c>erl_interface</c> library is only guaranteed - to be compatible with other Erlang/OTP components from the same - release as the <c>erl_interface</c> library. See the documentation - of the - <seealso marker="erl_eterm#erl_set_compat_rel">erl_set_compat_rel()</seealso> - function on how to communicate with Erlang/OTP components from earlier - releases.</p> - </note> - </description> - <xi:include href="erl_connect.xml"/> - <xi:include href="erl_error.xml"/> - <xi:include href="erl_eterm.xml"/> - <xi:include href="erl_format.xml"/> - <xi:include href="erl_global.xml"/> - <xi:include href="erl_malloc.xml"/> - <xi:include href="erl_marshal.xml"/> -</application> diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h index b138118f04..7d96dac560 100644 --- a/lib/erl_interface/include/ei.h +++ b/lib/erl_interface/include/ei.h @@ -43,7 +43,7 @@ typedef LONG_PTR ssize_t; /* Sigh... */ #include <stdio.h> /* Need type FILE */ #include <errno.h> /* Need EHOSTUNREACH, ENOMEM, ... */ -#if !(defined(__WIN32__) || defined(_WIN32)) && !defined(VXWORKS) || (defined(VXWORKS) && defined(HAVE_SENS)) +#if !(defined(__WIN32__) || defined(_WIN32)) # include <netdb.h> #endif @@ -188,20 +188,20 @@ extern "C" { * the 'ei' interface as well.... :-( */ -#if defined(_REENTRANT) || defined(VXWORKS) || defined(__WIN32__) +#if defined(_REENTRANT) || defined(__WIN32__) /* 'erl_errno' as a function return value */ volatile int* __erl_errno_place(void) __attribute__ ((__const__)); #define erl_errno (*__erl_errno_place ()) -#else /* !_REENTRANT && !VXWORKS && !__WIN32__ */ +#else /* !_REENTRANT && !__WIN32__ */ extern volatile int __erl_errno; #define erl_errno __erl_errno -#endif /* !_REENTRANT && !VXWORKS && !__WIN32__ */ +#endif /* !_REENTRANT && !__WIN32__ */ /* -------------------------------------------------------------------- */ @@ -323,13 +323,24 @@ typedef struct { #define EI_SCLBK_FLG_FULL_IMPL (1 << 0) +/* + * HACK: AIX defines many socket functions like accept to be naccept, which + * pollutes the global namespace. Set up an ugly ifdef for consumers of this + * API here so they get a mangled name for AIX and the sane name elsewhere. + */ +#ifdef _AIX +#define EI_ACCEPT_NAME accept_ei +#else +#define EI_ACCEPT_NAME accept +#endif + typedef struct { int flags; int (*socket)(void **ctx, void *setup_ctx); int (*close)(void *ctx); int (*listen)(void *ctx, void *addr, int *len, int backlog); - int (*accept)(void **ctx, void *addr, int *len, unsigned tmo); + int (*EI_ACCEPT_NAME)(void **ctx, void *addr, int *len, unsigned tmo); int (*connect)(void *ctx, void *addr, int len, unsigned tmo); int (*writev)(void *ctx, const void *iov, int iovcnt, ssize_t *len, unsigned tmo); int (*write)(void *ctx, const char *buf, ssize_t *len, unsigned tmo); @@ -351,7 +362,7 @@ typedef struct ei_cnode_s { /* Currently this_ipaddr isn't used */ /* struct in_addr this_ipaddr; */ char ei_connect_cookie[EI_MAX_COOKIE_SIZE+1]; - short creation; + unsigned int creation; erlang_pid self; ei_socket_callbacks *cbs; void *setup_context; @@ -393,8 +404,12 @@ int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, int ei_connect(ei_cnode* ec, char *nodename); int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms); +int ei_connect_host_port(ei_cnode* ec, char *hostname, int port); +int ei_connect_host_port_tmo(ei_cnode* ec, char *hostname, int port, unsigned ms); int ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename); int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned ms); +int ei_xconnect_host_port(ei_cnode* ec, Erl_IpAddr adr, int port); +int ei_xconnect_host_port_tmo(ei_cnode* ec, Erl_IpAddr adr, int port, unsigned ms); int ei_receive(int fd, unsigned char *bufp, int bufsize); int ei_receive_tmo(int fd, unsigned char *bufp, int bufsize, unsigned ms); @@ -444,41 +459,6 @@ int ei_get_tracelevel(void); * We have erl_gethost*() so we include ei versions as well. */ -#if defined(VXWORKS) - -extern int h_errno; - -/* - * We need these definitions - if the user has SENS then he gets them - * from netdb.h, otherwise we define them ourselves. - * - * If you are getting "multiple definition" errors here, - * make sure you have included <netdb.h> BEFORE "erl_interface.h" - * or define HAVE_SENS in your CFLAGS. - */ - -#if !defined(HAVE_SENS) && !defined(HOST_NOT_FOUND) /* just in case */ - -struct hostent { - char *h_name; /* official name of host */ - char **h_aliases; /* alias list */ - int h_addrtype; /* host address type */ - int h_length; /* length of address */ - char **h_addr_list; /* list of addresses from name server */ -#define h_addr h_addr_list[0] /* address, for backward compatiblity */ - unsigned int unused; /* SENS defines this as ttl */ -}; - -#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ -#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ -#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ -#define NO_DATA 4 /* Valid name, no data record of requested type */ -#define NO_ADDRESS NO_DATA /* no address, look for MX record */ - -#endif /* !HAVE_SENS && !HOST_NOT_FOUND */ -#endif /* VXWORKS */ - - struct hostent *ei_gethostbyname(const char *name); struct hostent *ei_gethostbyaddr(const char *addr, int len, int type); struct hostent *ei_gethostbyname_r(const char *name, @@ -537,8 +517,6 @@ int ei_encode_port(char *buf, int *index, const erlang_port *p); int ei_x_encode_port(ei_x_buff* x, const erlang_port *p); int ei_encode_ref(char *buf, int *index, const erlang_ref *p); int ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p); -int ei_encode_term(char *buf, int *index, void *t) EI_DEPRECATED_ATTR; -int ei_x_encode_term(ei_x_buff* x, void* t) EI_DEPRECATED_ATTR; int ei_encode_trace(char *buf, int *index, const erlang_trace *p); int ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p); int ei_encode_tuple_header(char *buf, int *index, int arity); @@ -586,7 +564,6 @@ void free_fun(erlang_fun* f); int ei_decode_pid(const char *buf, int *index, erlang_pid *p); int ei_decode_port(const char *buf, int *index, erlang_port *p); int ei_decode_ref(const char *buf, int *index, erlang_ref *p); -int ei_decode_term(const char *buf, int *index, void *t) EI_DEPRECATED_ATTR; int ei_decode_trace(const char *buf, int *index, erlang_trace *p); int ei_decode_tuple_header(const char *buf, int *index, int *arity); int ei_decode_list_header(const char *buf, int *index, int *arity); @@ -802,6 +779,13 @@ int ei_reg_dump(int fd, ei_reg *reg, const char *mntab, int flags); int ei_reg_restore(int fd, ei_reg *reg, const char *mntab); int ei_reg_purge(ei_reg *reg); +/* -------------------------------------------------------------------- */ +/* The ei_global functions */ +/* -------------------------------------------------------------------- */ +char **ei_global_names(ei_cnode *ec, int fd, int *count); +int ei_global_whereis(ei_cnode *ec, int fd, const char *name, erlang_pid* pid, char *node); +int ei_global_register(int fd, const char *name, erlang_pid *self); +int ei_global_unregister(ei_cnode *ec, int fd, const char *name); /* -------------------------------------------------------------------- */ /* Encoding/decoding bugnums to GNU MP format */ @@ -832,14 +816,12 @@ int ei_x_encode_bignum(ei_x_buff *x, mpz_t obj); #define EI_ULONGLONG unsigned long long #endif -#ifndef VXWORKS int ei_decode_longlong(const char *buf, int *index, EI_LONGLONG *p); int ei_decode_ulonglong(const char *buf, int *index, EI_ULONGLONG *p); int ei_encode_longlong(char *buf, int *index, EI_LONGLONG p); int ei_encode_ulonglong(char *buf, int *index, EI_ULONGLONG p); int ei_x_encode_longlong(ei_x_buff* x, EI_LONGLONG n); int ei_x_encode_ulonglong(ei_x_buff* x, EI_ULONGLONG n); -#endif #ifdef USE_EI_UNDOCUMENTED diff --git a/lib/erl_interface/src/legacy/erl_global.h b/lib/erl_interface/include/ei_global.h index d2eec08b35..b85a31217d 100644 --- a/lib/erl_interface/src/legacy/erl_global.h +++ b/lib/erl_interface/include/ei_global.h @@ -17,12 +17,13 @@ * * %CopyrightEnd% */ -#ifndef _ERL_GLOBAL_H -#define _ERL_GLOBAL_H +#ifndef _EI_GLOBAL_H +#define _EI_GLOBAL_H +#include "ei.h" -char **erl_global_names(int fd, int *count); -ETERM *erl_global_whereis(int fd, const char *name, char *node); -int erl_global_register(int fd, const char *name, ETERM *pid); -int erl_global_unregister(int fd, const char *name); +char **ei_global_names(ei_cnode *ec, int fd, int *count); +int ei_global_whereis(ei_cnode *ec, int fd, const char *name, erlang_pid* pid, char *node); +int ei_global_register(int fd, const char *name, erlang_pid *self); +int ei_global_unregister(ei_cnode *ec, int fd, const char *name); -#endif /* _ERL_GLOBAL_H */ +#endif /* _EI_GLOBAL_H */ diff --git a/lib/erl_interface/include/erl_interface.h b/lib/erl_interface/include/erl_interface.h deleted file mode 100644 index 7c87223a38..0000000000 --- a/lib/erl_interface/include/erl_interface.h +++ /dev/null @@ -1,473 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_INTERFACE_H -#define _ERL_INTERFACE_H - -/************************************************************************/ -/* This file defines the complete interface to erl_interface */ -/* Note: the 'ei' interface is the prefered C API. */ -/************************************************************************/ - -#include "ei.h" /* ei is the base */ - -/* -------------------------------------------------------------------- */ -/* Public defines */ -/* -------------------------------------------------------------------- */ - -#define ERL_COMPOUND (1 << 7) - -#define ERL_UNDEF 0 -#define ERL_INTEGER 1 -#define ERL_U_INTEGER 2 /* unsigned int */ -#define ERL_ATOM 3 -#define ERL_PID 4 -#define ERL_PORT 5 -#define ERL_REF 6 -#define ERL_CONS (7 | ERL_COMPOUND) -#define ERL_LIST ERL_CONS -#define ERL_NIL 8 -#define ERL_EMPTY_LIST ERL_NIL -#define ERL_TUPLE (9 | ERL_COMPOUND) -#define ERL_BINARY 10 -#define ERL_FLOAT 11 -#define ERL_VARIABLE (12 | ERL_COMPOUND) /* used in patterns */ -#define ERL_SMALL_BIG 13 -#define ERL_U_SMALL_BIG 14 -#define ERL_FUNCTION (15 | ERL_COMPOUND) -#define ERL_BIG 16 -#define ERL_LONGLONG 17 -#define ERL_U_LONGLONG 18 - - -#define ERL_TYPE(x) (ERL_HEADER(x)->type) - -/* FIXME some macros left in erl_eterm.h should probably be documented */ - -#define ERL_IS_INTEGER(x) (ERL_TYPE(x) == ERL_INTEGER) -#define ERL_IS_UNSIGNED_INTEGER(x) (ERL_TYPE(x) == ERL_U_INTEGER) -#define ERL_IS_LONGLONG(x) (ERL_TYPE(x) == ERL_LONGLONG) -#define ERL_IS_UNSIGNED_LONGLONG(x) (ERL_TYPE(x) == ERL_U_LONGLONG) -#define ERL_IS_FLOAT(x) (ERL_TYPE(x) == ERL_FLOAT) -#define ERL_IS_ATOM(x) (ERL_TYPE(x) == ERL_ATOM) -#define ERL_IS_PID(x) (ERL_TYPE(x) == ERL_PID) -#define ERL_IS_PORT(x) (ERL_TYPE(x) == ERL_PORT) -#define ERL_IS_REF(x) (ERL_TYPE(x) == ERL_REF) -#define ERL_IS_TUPLE(x) (ERL_TYPE(x) == ERL_TUPLE) -#define ERL_IS_BINARY(x) (ERL_TYPE(x) == ERL_BINARY) -#define ERL_IS_NIL(x) (ERL_TYPE(x) == ERL_NIL) -#define ERL_IS_EMPTY_LIST(x) ERL_IS_NIL(x) -#define ERL_IS_CONS(x) (ERL_TYPE(x) == ERL_CONS) -#define ERL_IS_LIST(x) (ERL_IS_CONS(x) || ERL_IS_EMPTY_LIST(x)) - -/* - * Macros used for XXXX - */ - -#define ERL_HEADER(x) ((Erl_Header *)x) -#define ERL_COUNT(x) (ERL_HEADER(x)->count) - -/* - * Macros used for retrieving values from Erlang terms. - */ - -#define ERL_INT_VALUE(x) ((x)->uval.ival.i) -#define ERL_INT_UVALUE(x) ((x)->uval.uival.u) -#define ERL_LL_VALUE(x) ((x)->uval.llval.i) -#define ERL_LL_UVALUE(x) ((x)->uval.ullval.u) - -#define ERL_FLOAT_VALUE(x) ((x)->uval.fval.f) - -#define ERL_ATOM_PTR(x) erl_atom_ptr_latin1((Erl_Atom_data*) &(x)->uval.aval.d) -#define ERL_ATOM_PTR_UTF8(x) erl_atom_ptr_utf8((Erl_Atom_data*) &(x)->uval.aval.d) -#define ERL_ATOM_SIZE(x) erl_atom_size_latin1((Erl_Atom_data*) &(x)->uval.aval.d) -#define ERL_ATOM_SIZE_UTF8(x) erl_atom_size_utf8((Erl_Atom_data*) &(x)->uval.aval.d) - -#define ERL_PID_NODE(x) erl_atom_ptr_latin1((Erl_Atom_data*) &(x)->uval.pidval.node) -#define ERL_PID_NODE_UTF8(x) erl_atom_ptr_utf8((Erl_Atom_data*) &(x)->uval.pidval.node) -#define ERL_PID_NUMBER(x) ((x)->uval.pidval.number) -#define ERL_PID_SERIAL(x) ((x)->uval.pidval.serial) -#define ERL_PID_CREATION(x) ((x)->uval.pidval.creation) - -#define ERL_PORT_NODE(x) erl_atom_ptr_latin1((Erl_Atom_data*) &(x)->uval.portval.node) -#define ERL_PORT_NODE_UTF8(x) erl_atom_ptr_utf8((Erl_Atom_data*) &(x)->uval.portval.node) -#define ERL_PORT_NUMBER(x) ((x)->uval.portval.number) -#define ERL_PORT_CREATION(x) ((x)->uval.portval.creation) - -#define ERL_REF_NODE(x) erl_atom_ptr_latin1((Erl_Atom_data*) &(x)->uval.refval.node) -#define ERL_REF_NODE_UTF8(x) erl_atom_ptr_utf8((Erl_Atom_data*) &(x)->uval.refval.node) -#define ERL_REF_NUMBER(x) ((x)->uval.refval.n[0]) -#define ERL_REF_NUMBERS(x) ((x)->uval.refval.n) -#define ERL_REF_LEN(x) ((x)->uval.refval.len) -#define ERL_REF_CREATION(x) ((x)->uval.refval.creation) - -#define ERL_TUPLE_SIZE(x) ((x)->uval.tval.size) - -/* NOTE!!! This is 0-based!! (first item is number 0) - * Note too that element/2 (in Erlang) and - * erl_element() are both 1-based. - */ -#define ERL_TUPLE_ELEMS(x) ((x)->uval.tval.elems) -#define ERL_TUPLE_ELEMENT(x, i) (ERL_TUPLE_ELEMS(x)[(i)]) - -#define ERL_BIN_SIZE(x) ((x)->uval.bval.size) -#define ERL_BIN_PTR(x) ((x)->uval.bval.b) - -#define ERL_CONS_HEAD(x) ((x)->uval.lval.head) -#define ERL_CONS_TAIL(x) ((x)->uval.lval.tail) - -#define ERL_VAR_LEN(x) ((x)->uval.vval.len) -#define ERL_VAR_NAME(x) ((x)->uval.vval.name) -#define ERL_VAR_VALUE(x) ((x)->uval.vval.v) - -#define ERL_CLOSURE_SIZE(x) ((x)->uval.funcval.size) -#define ERL_FUN_CREATOR(x) ((x)->uval.funcval.creator) -#define ERL_FUN_MODULE(x) ((x)->uval.funcval.module) -#define ERL_FUN_UNIQ(x) ((x)->uval.funcval.uniq) -#define ERL_FUN_INDEX(x) ((x)->uval.funcval.index) -#define ERL_FUN_ARITY(x) ((x)->uval.funcval.arity) -#define ERL_FUN_NEW_INDEX(x) ((x)->uval.funcval.new_index) -#define ERL_FUN_MD5(x) ((x)->uval.funcval.md5) -#define ERL_CLOSURE(x) ((x)->uval.funcval.closure) -#define ERL_CLOSURE_ELEMENT(x,i) (ERL_CLOSURE(x)[(i)]) - - -#ifdef __cplusplus -extern "C" { -#endif - -/* -------------------------------------------------------------------- */ -/* Type definitions of Erlang terms in C */ -/* -------------------------------------------------------------------- */ - -typedef struct { - unsigned int count:24; /* reference counter */ - unsigned int type:8; /* type of Erlang term */ -} Erl_Header; - -typedef struct { - Erl_Header h; - int i; -} Erl_Integer; - -typedef struct { - Erl_Header h; - unsigned int u; -} Erl_Uinteger; - -typedef struct { - Erl_Header h; - long long i; -} Erl_LLInteger; - -typedef struct { - Erl_Header h; - unsigned long long u; -} Erl_ULLInteger; - -typedef struct { - Erl_Header h; - double f; -} Erl_Float; - -typedef struct { - char *utf8; - int lenU; - char *latin1; - int lenL; -} Erl_Atom_data; - -char* erl_atom_ptr_latin1(Erl_Atom_data*) EI_DEPRECATED_ATTR; -char* erl_atom_ptr_utf8(Erl_Atom_data*) EI_DEPRECATED_ATTR; -int erl_atom_size_latin1(Erl_Atom_data*) EI_DEPRECATED_ATTR; -int erl_atom_size_utf8(Erl_Atom_data*) EI_DEPRECATED_ATTR; -char* erl_atom_init_latin1(Erl_Atom_data*, const char*) EI_DEPRECATED_ATTR; - -typedef struct { - Erl_Header h; - Erl_Atom_data d; -} Erl_Atom; - -typedef struct { - Erl_Header h; - Erl_Atom_data node; - unsigned int number; - unsigned int serial; - unsigned int creation; -} Erl_Pid; - -typedef struct { - Erl_Header h; - Erl_Atom_data node; - unsigned int number; - unsigned int creation; -} Erl_Port; - -typedef struct { - Erl_Header h; - Erl_Atom_data node; - int len; - unsigned int n[3]; - unsigned int creation; -} Erl_Ref; - -typedef struct { - Erl_Header h; - int arity; - int is_neg; - unsigned short *digits; -} Erl_Big; - -struct _eterm; /* forward */ - -typedef struct { - Erl_Header h; - struct _eterm *head; - struct _eterm *tail; -} Erl_List; - -typedef struct { - Erl_Header h; -} Erl_EmptyList; - -typedef struct { - Erl_Header h; - int size; - struct _eterm **elems; -} Erl_Tuple; - -typedef struct { - Erl_Header h; - int size; - unsigned char *b; -} Erl_Binary; - -/* Variables may only exist in patterns. - * Note: identical variable names in a pattern - * denotes the same value. - */ -typedef struct { - Erl_Header h; - int len; - char *name; - struct _eterm *v; -} Erl_Variable; - - -typedef struct { - Erl_Header h; - int size; /* size of closure */ - int arity; /* arity for new (post R7) external funs */ - unsigned char md5[16]; /* md5 for new funs */ - int new_index; /* new funs */ - struct _eterm* creator; /* pid */ - struct _eterm* module; /* module */ - struct _eterm* index; - struct _eterm* uniq; - struct _eterm** closure; -} Erl_Function; - -typedef struct _eterm { - union { - Erl_Integer ival; - Erl_Uinteger uival; - Erl_LLInteger llval; - Erl_ULLInteger ullval; - Erl_Float fval; - Erl_Atom aval; - Erl_Pid pidval; - Erl_Port portval; - Erl_Ref refval; - Erl_List lval; - Erl_EmptyList nval; - Erl_Tuple tval; - Erl_Binary bval; - Erl_Variable vval; - Erl_Function funcval; - Erl_Big bigval; - } uval; -} ETERM; - - -#define MAXREGLEN (255*4) /* max length of registered (atom) name */ - -typedef struct { - int type; /* one of the message type constants in eiext.h */ - ETERM *msg; /* the actual message */ - ETERM *from; - ETERM *to; - char to_name[MAXREGLEN+1]; -} ErlMessage; - -typedef unsigned char Erl_Heap; - - -/* -------------------------------------------------------------------- */ -/* The functions */ -/* -------------------------------------------------------------------- */ - -void erl_init(void *x, long y) EI_DEPRECATED_ATTR; -void erl_set_compat_rel(unsigned) EI_DEPRECATED_ATTR; -int erl_connect_init(int, char*,short) EI_DEPRECATED_ATTR; -int erl_connect_xinit(char*,char*,char*,struct in_addr*,char*,short) EI_DEPRECATED_ATTR; -int erl_connect(char*) EI_DEPRECATED_ATTR; -int erl_xconnect(struct in_addr*,char *) EI_DEPRECATED_ATTR; -int erl_close_connection(int) EI_DEPRECATED_ATTR; -int erl_receive(int, unsigned char*, int) EI_DEPRECATED_ATTR; -int erl_receive_msg(int, unsigned char*, int, ErlMessage*) EI_DEPRECATED_ATTR; -int erl_xreceive_msg(int, unsigned char**, int*, ErlMessage*) EI_DEPRECATED_ATTR; -int erl_send(int, ETERM*, ETERM*) EI_DEPRECATED_ATTR; -int erl_reg_send(int, char*, ETERM*) EI_DEPRECATED_ATTR; -ETERM *erl_rpc(int,char*,char*,ETERM*) EI_DEPRECATED_ATTR; -int erl_rpc_to(int,char*,char*,ETERM*) EI_DEPRECATED_ATTR; -int erl_rpc_from(int,int,ErlMessage*) EI_DEPRECATED_ATTR; - -/* erl_publish returns open descriptor on success, or -1 */ -int erl_publish(int port) EI_DEPRECATED_ATTR; -int erl_accept(int,ErlConnect*) EI_DEPRECATED_ATTR; - -const char *erl_thiscookie(void) EI_DEPRECATED_ATTR; -const char *erl_thisnodename(void) EI_DEPRECATED_ATTR; -const char *erl_thishostname(void) EI_DEPRECATED_ATTR; -const char *erl_thisalivename(void) EI_DEPRECATED_ATTR; -short erl_thiscreation(void) EI_DEPRECATED_ATTR; - -/* returns 0 on success, -1 if node not known to epmd or epmd not reached */ -int erl_unpublish(const char *alive) EI_DEPRECATED_ATTR; - -#ifdef EI_HAVE_DEPRECATED_ATTR__ -#define EI_DEPR_ATTR_EXTRA , EI_DEPRECATED_ATTR_NAME -#else -#define EI_DEPR_ATTR_EXTRA -#endif - - -/* Report generic error to stderr. */ -void erl_err_msg(const char * __template, ...) - __attribute__ ((__format__ (printf, 1, 2) EI_DEPR_ATTR_EXTRA)) ; -/* Report generic error to stderr and die. */ -void erl_err_quit(const char * __template, ...) - __attribute__ ((__format__ (printf, 1, 2), __noreturn__ EI_DEPR_ATTR_EXTRA)); -/* Report system/libc error to stderr. */ -void erl_err_ret(const char * __template, ...) - __attribute__ ((__format__ (printf, 1, 2) EI_DEPR_ATTR_EXTRA)); -/* Report system/libc error to stderr and die. */ -void erl_err_sys(const char * __template, ...) - __attribute__ ((__format__ (printf, 1, 2), __noreturn__ EI_DEPR_ATTR_EXTRA)); - -ETERM *erl_cons(ETERM*,ETERM*) EI_DEPRECATED_ATTR; -ETERM *erl_copy_term(const ETERM*) EI_DEPRECATED_ATTR; -ETERM *erl_element(int,const ETERM*) EI_DEPRECATED_ATTR; - -ETERM *erl_hd(const ETERM*) EI_DEPRECATED_ATTR; -ETERM* erl_iolist_to_binary(const ETERM* term) EI_DEPRECATED_ATTR; -char* erl_iolist_to_string(const ETERM* term) EI_DEPRECATED_ATTR; -int erl_iolist_length(const ETERM*) EI_DEPRECATED_ATTR; -int erl_length(const ETERM*) EI_DEPRECATED_ATTR; -ETERM *erl_mk_atom(const char*) EI_DEPRECATED_ATTR; -ETERM *erl_mk_binary(const char*,int) EI_DEPRECATED_ATTR; -ETERM *erl_mk_empty_list(void) EI_DEPRECATED_ATTR; -ETERM *erl_mk_estring(const char*, int) EI_DEPRECATED_ATTR; -ETERM *erl_mk_float(double) EI_DEPRECATED_ATTR; -ETERM *erl_mk_int(int) EI_DEPRECATED_ATTR; -ETERM *erl_mk_longlong(long long) EI_DEPRECATED_ATTR; -ETERM *erl_mk_list(ETERM**,int) EI_DEPRECATED_ATTR; -ETERM *erl_mk_pid(const char*,unsigned int,unsigned int,unsigned char) EI_DEPRECATED_ATTR; -ETERM *erl_mk_port(const char*,unsigned int,unsigned char) EI_DEPRECATED_ATTR; -ETERM *erl_mk_ref(const char*,unsigned int,unsigned char) EI_DEPRECATED_ATTR; -ETERM *erl_mk_long_ref(const char*,unsigned int,unsigned int, - unsigned int,unsigned char) EI_DEPRECATED_ATTR; -ETERM *erl_mk_string(const char*) EI_DEPRECATED_ATTR; -ETERM *erl_mk_tuple(ETERM**,int) EI_DEPRECATED_ATTR; -ETERM *erl_mk_uint(unsigned int) EI_DEPRECATED_ATTR; -ETERM *erl_mk_ulonglong(unsigned long long) EI_DEPRECATED_ATTR; -ETERM *erl_mk_var(const char*) EI_DEPRECATED_ATTR; -int erl_print_term(FILE*,const ETERM*) EI_DEPRECATED_ATTR; -/* int erl_sprint_term(char*,const ETERM*) EI_DEPRECATED_ATTR; */ -int erl_size(const ETERM*) EI_DEPRECATED_ATTR; -ETERM *erl_tl(const ETERM*) EI_DEPRECATED_ATTR; -ETERM *erl_var_content(const ETERM*, const char*) EI_DEPRECATED_ATTR; - -ETERM *erl_format(char*, ... ) EI_DEPRECATED_ATTR; -int erl_match(ETERM*, ETERM*) EI_DEPRECATED_ATTR; - -char **erl_global_names(int fd, int *count) EI_DEPRECATED_ATTR; -int erl_global_register(int fd, const char *name, ETERM *pid) EI_DEPRECATED_ATTR; -int erl_global_unregister(int fd, const char *name) EI_DEPRECATED_ATTR; -ETERM *erl_global_whereis(int fd, const char *name, char *node) EI_DEPRECATED_ATTR; - -void erl_init_malloc(Erl_Heap*,long) EI_DEPRECATED_ATTR; -ETERM *erl_alloc_eterm(unsigned char) EI_DEPRECATED_ATTR; -void erl_eterm_release(void) EI_DEPRECATED_ATTR; -void erl_eterm_statistics(unsigned long*,unsigned long*) EI_DEPRECATED_ATTR; -void erl_free_array(ETERM**,int) EI_DEPRECATED_ATTR; -void erl_free_term(ETERM*) EI_DEPRECATED_ATTR; -void erl_free_compound(ETERM*) EI_DEPRECATED_ATTR; -void *erl_malloc(long) EI_DEPRECATED_ATTR; -void erl_free(void*) EI_DEPRECATED_ATTR; - -int erl_compare_ext(unsigned char*, unsigned char*) EI_DEPRECATED_ATTR; -ETERM *erl_decode(unsigned char*) EI_DEPRECATED_ATTR; -ETERM *erl_decode_buf(unsigned char**) EI_DEPRECATED_ATTR; -int erl_encode(ETERM*,unsigned char*t) EI_DEPRECATED_ATTR; -int erl_encode_buf(ETERM*,unsigned char**) EI_DEPRECATED_ATTR; -int erl_ext_size(unsigned char*) EI_DEPRECATED_ATTR; -unsigned char erl_ext_type(unsigned char*) EI_DEPRECATED_ATTR; /* Note: returned 'char' before R9C */ -unsigned char *erl_peek_ext(unsigned char*,int) EI_DEPRECATED_ATTR; -int erl_term_len(ETERM*) EI_DEPRECATED_ATTR; - -int cmp_latin1_vs_utf8(const char* sL, int lenL, const char* sU, int lenU) EI_DEPRECATED_ATTR; - -/* -------------------------------------------------------------------- */ -/* Wrappers around ei functions */ -/* -------------------------------------------------------------------- */ - -/* - * Undocumented before R9C, included for compatibility with old code - */ - -struct hostent *erl_gethostbyname(const char *name) EI_DEPRECATED_ATTR; -struct hostent *erl_gethostbyaddr(const char *addr, int len, int type) EI_DEPRECATED_ATTR; -struct hostent *erl_gethostbyname_r(const char *name, - struct hostent *hostp, - char *buffer, - int buflen, - int *h_errnop) EI_DEPRECATED_ATTR; -struct hostent *erl_gethostbyaddr_r(const char *addr, - int length, - int type, - struct hostent *hostp, - char *buffer, - int buflen, - int *h_errnop) EI_DEPRECATED_ATTR; - -/* - * Undocumented, included for compatibility with old code - */ - -void erl_init_resolve(void) EI_DEPRECATED_ATTR; -int erl_distversion(int fd) EI_DEPRECATED_ATTR; -int erl_epmd_connect(struct in_addr *inaddr) EI_DEPRECATED_ATTR; -int erl_epmd_port(struct in_addr *inaddr, const char *alive, int *dist) EI_DEPRECATED_ATTR; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in index 6e0d3476c7..122cc560cc 100644 --- a/lib/erl_interface/src/Makefile.in +++ b/lib/erl_interface/src/Makefile.in @@ -52,9 +52,7 @@ APPUP_FILE= erl_interface.appup APPUP_SRC= $(APPUP_FILE).src APPUP_TARGET= $(EBINDIR)/$(APPUP_FILE) -USING_MINGW=@MIXED_CYGWIN_MINGW@ -USING_MSYS_VC==@MIXED_MSYS_VC@ -USING_CYGWIN_VC==@MIXED_MSYS_VC@ +USING_MINGW=@MIXED_MINGW@ USING_VC=@MIXED_VC@ ifdef TESTROOT @@ -130,12 +128,7 @@ endif WARNFLAGS += -DEI_NO_DEPR_WARN CFLAGS = @LIB_CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -PROG_CFLAGS = @CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -Ilegacy - -ifeq ($(findstring vxworks,$(TARGET)),vxworks) -PROG_CFLAGS += -nostartfiles -Wl,-r,-d -endif - +PROG_CFLAGS = @CFLAGS@ $(WARNFLAGS) $(INCFLAGS) $(TYPE_FLAGS) -Iglobal INSTALL = @INSTALL@ INSTALL_DIR = @INSTALL_DIR@ @@ -161,7 +154,7 @@ BINDIR = $(ERL_TOP)/lib/erl_interface/bin/$(TARGET) # -Wno-char-subscripts # -Wshadow -vpath %.c connect:encode:decode:misc:epmd:legacy:registry +vpath %.c connect:encode:decode:misc:epmd:global:registry ########################################################################### # List targets @@ -193,17 +186,12 @@ ERL_CALL = $(BINDIR)/erl_call$(EXE) ifdef THR_DEFS ST_EILIB = $(OBJDIR)/$(LIBPRE)ei_st$(LIBEXT) -ST_ERLLIB = $(OBJDIR)/$(LIBPRE)erl_interface_st$(LIBEXT) MT_EILIB = $(OBJDIR)/$(LIBPRE)ei$(LIBEXT) -MT_ERLLIB = $(OBJDIR)/$(LIBPRE)erl_interface$(LIBEXT) else ST_EILIB = $(OBJDIR)/$(LIBPRE)ei$(LIBEXT) -ST_ERLLIB = $(OBJDIR)/$(LIBPRE)erl_interface$(LIBEXT) endif MD_EILIB = $(OBJDIR)/$(LIBPRE)ei_md$(LIBEXT) MDD_EILIB = $(OBJDIR)/$(LIBPRE)ei_mdd$(LIBEXT) -MD_ERLLIB = $(OBJDIR)/$(LIBPRE)erl_interface_md$(LIBEXT) -MDD_ERLLIB = $(OBJDIR)/$(LIBPRE)erl_interface_mdd$(LIBEXT) ########################################################################### # Specify targets to build @@ -225,10 +213,7 @@ TARGETS = \ OBJ_TARGETS = \ $(MT_EILIB) \ $(MD_EILIB) \ - $(MDD_EILIB) \ - $(MT_ERLLIB) \ - $(MD_ERLLIB) \ - $(MDD_ERLLIB) + $(MDD_EILIB) FAKE_TARGETS = \ $(OBJDIR)/erl_fake_prog_mt$(EXE) \ @@ -254,8 +239,7 @@ TARGETS = \ $(APPUP_TARGET) OBJ_TARGETS = \ - $(MD_EILIB) \ - $(MD_ERLLIB) + $(MD_EILIB) FAKE_TARGETS = \ $(OBJDIR)/erl_fake_prog_md$(EXE) \ @@ -275,9 +259,7 @@ TARGETS = \ OBJ_TARGETS = \ $(ST_EILIB) \ - $(ST_ERLLIB) \ - $(MT_EILIB) \ - $(MT_ERLLIB) + $(MT_EILIB) FAKE_TARGETS = \ $(ST_OBJDIR)/erl_fake_prog_st$(EXE) \ @@ -298,8 +280,7 @@ TARGETS = \ $(APPUP_TARGET) OBJ_TARGETS = \ - $(ST_EILIB) \ - $(ST_ERLLIB) + $(ST_EILIB) FAKE_TARGETS = \ $(ST_OBJDIR)/erl_fake_prog_st$(EXE) \ @@ -321,8 +302,7 @@ endif HEADERS = \ ../include/ei.h \ ../include/ei_connect.h \ - ../include/eicode.h \ - ../include/erl_interface.h + ../include/eicode.h EISOURCES = \ $(CONNECTSRC) \ @@ -330,7 +310,8 @@ EISOURCES = \ $(ENCODESRC) \ $(EPMDSRC) \ $(MISCSRC) \ - $(REGISTRYSRC) + $(REGISTRYSRC) \ + $(GLOBALSOURCES) CONNECTSRC = \ connect/ei_connect.c \ @@ -363,14 +344,9 @@ DECODESRC = \ decode/decode_version.c \ $(DECODESRC_LONGLONG) -ifneq ($(findstring vxworks,$(TARGET)),vxworks) DECODESRC_LONGLONG = \ decode/decode_longlong.c \ decode/decode_ulonglong.c -else -DECODESRC_LONGLONG = -endif - ENCODESRC = \ encode/encode_atom.c \ @@ -393,13 +369,9 @@ ENCODESRC = \ encode/encode_version.c \ $(ENCODESRC_LONGLONG) -ifneq ($(findstring vxworks,$(TARGET)),vxworks) ENCODESRC_LONGLONG = \ encode/encode_longlong.c \ encode/encode_ulonglong.c -else -ENCODESRC_LONGLONG = -endif EPMDSRC = \ @@ -457,24 +429,13 @@ REGISTRYSRC = \ registry/reg_stat.c \ registry/reg_tabstat.c -ERLSOURCES = \ - legacy/decode_term.c \ - legacy/encode_term.c \ - legacy/erl_connect.c \ - legacy/erl_error.c \ - legacy/erl_eterm.c \ - legacy/erl_fix_alloc.c \ - legacy/erl_format.c \ - legacy/erl_malloc.c \ - legacy/erl_marshal.c \ - legacy/erl_resolve.c \ - legacy/erl_timeout.c \ - legacy/global_names.c \ - legacy/global_register.c \ - legacy/global_unregister.c \ - legacy/global_whereis.c - -SOURCES = $(EISOURCES) $(ERLSOURCES) +GLOBALSOURCES = \ + global/global_names.c \ + global/global_register.c \ + global/global_unregister.c \ + global/global_whereis.c + +SOURCES = $(EISOURCES) NEVERUSED = \ whereis.c \ @@ -491,13 +452,9 @@ ERLCALL = \ # located in the erl_interface library, not ei library. ST_EIOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) -ST_ERLOBJECTS = $(addprefix $(ST_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o))) MT_EIOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) -MT_ERLOBJECTS = $(addprefix $(MT_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o))) MD_EIOBJECTS = $(addprefix $(MD_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) -MD_ERLOBJECTS = $(addprefix $(MD_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o))) MDD_EIOBJECTS = $(addprefix $(MDD_OBJDIR)/,$(notdir $(EISOURCES:.c=.o))) -MDD_ERLOBJECTS = $(addprefix $(MDD_OBJDIR)/,$(notdir $(ERLSOURCES:.c=.o))) ########################################################################### # Main targets @@ -513,10 +470,10 @@ docs: tests: clean: - rm -f $(ST_EIOBJECTS) $(ST_ERLOBJECTS) $(ST_EILIB) $(ST_ERLLIB) - rm -f $(MT_EIOBJECTS) $(MT_ERLOBJECTS) $(MT_EILIB) $(MT_ERLLIB) - rm -f $(MD_EIOBJECTS) $(MD_ERLOBJECTS) $(MD_EILIB) $(MD_ERLLIB) - rm -f $(MDD_EIOBJECTS) $(MDD_ERLOBJECTS) $(MDD_EILIB) $(MDD_ERLLIB) + rm -f $(ST_EIOBJECTS) $(ST_EILIB) + rm -f $(MT_EIOBJECTS) $(MT_EILIB) + rm -f $(MD_EIOBJECTS) $(MD_EILIB) + rm -f $(MDD_EIOBJECTS) $(MDD_EILIB) rm -f $(ERL_CALL) rm -f $(FAKE_TARGETS) rm -f $(APP_TARGET) @@ -527,20 +484,6 @@ distclean: clean ########################################################################### -# FIXME move this VxWorks stuff to configure or something -########################################################################### - -# FIXME depend on $(TARGET)/Makefile ??? - -ifeq ($(findstring vxworks,$(TARGET)),vxworks) -$(TARGET)/config.h: - $(gen_verbose) - $(V_at)echo "/* Generated by Makefile */" > $@ - $(V_at)echo "#define HAVE_STRERROR 1" >> $@ - $(V_at)echo "#define HAVE_SOCKLEN_T 1" >> $@ -endif - -########################################################################### # Default rules, normal and threaded ########################################################################### @@ -582,34 +525,18 @@ $(ST_EILIB) : $(ST_EIOBJECTS) $(V_AR) -out:$@ $(ST_EIOBJECTS) $(V_RANLIB) $@ -$(ST_ERLLIB) : $(ST_ERLOBJECTS) - $(V_AR) -out:$@ $(ST_ERLOBJECTS) - $(V_RANLIB) $@ - $(MT_EILIB) : $(MT_EIOBJECTS) $(V_AR) -out:$@ $(MT_EIOBJECTS) $(V_RANLIB) $@ -$(MT_ERLLIB) : $(MT_ERLOBJECTS) - $(V_AR) -out:$@ $(MT_ERLOBJECTS) - $(V_RANLIB) $@ - $(MD_EILIB) : $(MD_EIOBJECTS) $(V_AR) -out:$@ $(MD_EIOBJECTS) $(V_RANLIB) $@ -$(MD_ERLLIB) : $(MD_ERLOBJECTS) - $(V_AR) -out:$@ $(MD_ERLOBJECTS) - $(V_RANLIB) $@ - $(MDD_EILIB) : $(MDD_EIOBJECTS) $(V_AR) -out:$@ $(MDD_EIOBJECTS) $(V_RANLIB) $@ -$(MDD_ERLLIB) : $(MDD_ERLOBJECTS) - $(V_AR) -out:$@ $(MDD_ERLOBJECTS) - $(V_RANLIB) $@ - else # Unix archive creation @@ -621,12 +548,6 @@ ifdef RANLIB $(V_RANLIB) $@ endif -$(ST_ERLLIB) : $(ST_ERLOBJECTS) - $(V_at)rm -f $@ - $(V_AR) $(AR_FLAGS) $@ $(ST_ERLOBJECTS) -ifdef RANLIB - $(V_RANLIB) $@ -endif $(MT_EILIB) : $(MT_EIOBJECTS) $(V_at)rm -f $@ @@ -635,13 +556,6 @@ ifdef RANLIB $(V_RANLIB) $@ endif -$(MT_ERLLIB) : $(MT_ERLOBJECTS) - $(V_at)rm -f $@ - $(V_AR) $(AR_FLAGS) $@ $(MT_ERLOBJECTS) -ifdef RANLIB - $(V_RANLIB) $@ -endif - endif ########################################################################### @@ -653,17 +567,6 @@ $(ERL_CALL): $(ERLCALL) ../include/ei.h $(MD_EILIB) $(ld_verbose)$(PURIFY) $(CC) -MD $(PROG_CFLAGS) $(THR_DEFS) -o $@ $(ERLCALL) \ -L$(OBJDIR) -lei_md $(THR_LIBS) $(LIBS) -lsocket else -ifeq ($(findstring vxworks,$(TARGET)),vxworks) -$(ERL_CALL): $(ST_OBJDIR)/erl_call.o $(ST_OBJDIR)/erl_start.o ../include/ei.h $(ST_EILIB) - $(V_LD) -r -d -o $@ $(ST_OBJDIR)/erl_call.o $(ST_OBJDIR)/erl_start.o -L$(OBJDIR) -lei $(LIBS) - -$(ST_OBJDIR)/erl_call.o: prog/erl_call.c - $(V_CC) $(CFLAGS) -c $< -o $@ - -$(ST_OBJDIR)/erl_start.o: prog/erl_start.c - $(V_CC) $(CFLAGS) -c $< -o $@ - -else ifdef THR_DEFS $(ERL_CALL): $(ERLCALL) ../include/ei.h $(MT_EILIB) $(ld_verbose)$(PURIFY) $(CC) $(PROG_CFLAGS) $(THR_DEFS) $(LDFLAGS) -o $@ $(ERLCALL) \ @@ -674,7 +577,6 @@ $(ERL_CALL): $(ERLCALL) ../include/ei.h $(ST_EILIB) -L$(OBJDIR) -lei $(LIBS) endif endif -endif ########################################################################### # Fake application targets used to test header files and linking @@ -683,7 +585,7 @@ endif check: $(FAKE_TARGETS) ifndef THR_DEFS -$(ST_OBJDIR)/erl_fake_prog_st$(EXE): prog/erl_fake_prog.c $(ST_ERLLIB) $(ST_EILIB) +$(ST_OBJDIR)/erl_fake_prog_st$(EXE): prog/erl_fake_prog.c $(ST_EILIB) $(V_CC) $(PROG_CFLAGS) -o $@ $< -L$(OBJDIR) -lerl_interface -lei \ $(LIBS) @@ -691,7 +593,7 @@ $(ST_OBJDIR)/ei_fake_prog_st$(EXE): prog/ei_fake_prog.c $(ST_EILIB) $(V_CC) $(PROG_CFLAGS) -o $@ $< -L$(OBJDIR) -lei $(LIBS) $(ST_OBJDIR)/erl_fake_prog_cxx_st$(EXE): prog/erl_fake_prog.c \ - $(ST_ERLLIB) $(ST_EILIB) + $(ST_EILIB) $(V_CC) $(PROG_CFLAGS) -o $@ -xc++ $< -L$(OBJDIR) \ -lerl_interface -lei $(LIBS) @@ -700,7 +602,7 @@ $(ST_OBJDIR)/ei_fake_prog_cxx_st$(EXE): prog/ei_fake_prog.c $(ST_EILIB) else -$(ST_OBJDIR)/erl_fake_prog_st$(EXE): prog/erl_fake_prog.c $(ST_ERLLIB) $(ST_EILIB) +$(ST_OBJDIR)/erl_fake_prog_st$(EXE): prog/erl_fake_prog.c $(ST_EILIB) $(V_CC) $(PROG_CFLAGS) -o $@ $< -L$(OBJDIR) -lerl_interface_st -lei_st \ $(LIBS) @@ -708,7 +610,7 @@ $(ST_OBJDIR)/ei_fake_prog_st$(EXE): prog/ei_fake_prog.c $(ST_EILIB) $(V_CC) $(PROG_CFLAGS) -o $@ $< -L$(OBJDIR) -lei_st $(LIBS) $(ST_OBJDIR)/erl_fake_prog_cxx_st$(EXE): prog/erl_fake_prog.c \ - $(ST_ERLLIB) $(ST_EILIB) + $(ST_EILIB) $(V_CC) $(PROG_CFLAGS) -o $@ -xc++ $< -L$(OBJDIR) \ -lerl_interface_st -lei_st $(LIBS) @@ -720,7 +622,7 @@ endif #### $(MT_OBJDIR)/erl_fake_prog_mt$(EXE): prog/erl_fake_prog.c \ - $(MT_ERLLIB) $(MT_EILIB) + $(MT_EILIB) $(V_CC) $(MTFLAG) $(PROG_CFLAGS) $(THR_DEFS) -o $@ $< -L$(OBJDIR) \ -lerl_interface -lei $(THR_LIBS) $(LIBS) @@ -729,7 +631,7 @@ $(MT_OBJDIR)/ei_fake_prog_mt$(EXE): prog/ei_fake_prog.c $(MT_EILIB) -L$(OBJDIR) -lei $(THR_LIBS) $(LIBS) $(MT_OBJDIR)/erl_fake_prog_mt_cxx$(EXE): prog/erl_fake_prog.c \ - $(MT_ERLLIB) $(MT_EILIB) + $(MT_EILIB) $(V_CC) $(MTFLAG) $(PROG_CFLAGS) $(THR_DEFS) -o $@ -xc++ $< \ -L$(OBJDIR) -lerl_interface -lei \ $(THR_LIBS) $(LIBS) @@ -741,7 +643,7 @@ $(MT_OBJDIR)/ei_fake_prog_mt_cxx$(EXE): prog/ei_fake_prog.c $(MT_EILIB) #### $(MD_OBJDIR)/erl_fake_prog_md$(EXE): prog/erl_fake_prog.c \ - $(MD_ERLLIB) $(MD_EILIB) + $(MD_EILIB) $(V_CC) -MD $(PROG_CFLAGS) $(THR_DEFS) -o $@ $< -L$(OBJDIR) \ -lerl_interface_r -lei_r $(THR_LIBS) $(LIBS) @@ -750,7 +652,7 @@ $(MD_OBJDIR)/ei_fake_prog_md$(EXE): prog/ei_fake_prog.c $(MD_EILIB) -L$(OBJDIR) -lei_r $(THR_LIBS) $(LIBS) $(MD_OBJDIR)/erl_fake_prog_md_cxx$(EXE): prog/erl_fake_prog.c \ - $(MD_ERLLIB) $(MD_EILIB) + $(MD_EILIB) $(V_CC) -MD $(PROG_CFLAGS) $(THR_DEFS) -o $@ -xc++ $< \ -L$(OBJDIR) -lerl_interface_r -lei_r \ $(THR_LIBS) $(LIBS) @@ -762,7 +664,7 @@ $(MD_OBJDIR)/ei_fake_prog_md_cxx$(EXE): prog/ei_fake_prog.c $(MD_EILIB) #### $(MDD_OBJDIR)/erl_fake_prog_mdd$(EXE): prog/erl_fake_prog.c \ - $(MDD_ERLLIB) $(MDD_EILIB) + $(MDD_EILIB) $(V_CC) -MDD $(PROG_CFLAGS) $(THR_DEFS) -o $@ $< -L$(OBJDIR) \ -lerl_interface_r -lei_r $(THR_LIBS) $(LIBS) @@ -771,7 +673,7 @@ $(MDD_OBJDIR)/ei_fake_prog_mdd$(EXE): prog/ei_fake_prog.c $(MDD_EILIB) -L$(OBJDIR) -lei_r $(THR_LIBS) $(LIBS) $(MDD_OBJDIR)/erl_fake_prog_mdd_cxx$(EXE): prog/erl_fake_prog.c \ - $(MDD_ERLLIB) $(MDD_EILIB) + $(MDD_EILIB) $(V_CC) -MDD $(PROG_CFLAGS) $(THR_DEFS) -o $@ -xc++ $< \ -L$(OBJDIR) -lerl_interface_r -lei_r \ $(THR_LIBS) $(LIBS) @@ -784,32 +686,30 @@ $(MDD_OBJDIR)/ei_fake_prog_mdd_cxx$(EXE): prog/ei_fake_prog.c $(MDD_EILIB) # Create dependency file using gcc -MM ########################################################################### +ifneq ($(ERTS_SKIP_DEPEND),true) depend: $(TARGET)/depend.mk $(TARGET)/depend.mk: $(TARGET)/config.h $(gen_verbose) $(V_colon)echo "Generating dependency file depend.mk..." @echo "# Generated dependency rules" > $@ - $(V_CC) $(CFLAGS) -MM $(SOURCES) | \ - sed 's&$(TARGET)&\$$\(TARGET\)&g' | \ - sed 's/^.*:/\$$\(ST_OBJDIR\)\/&/' >> $@ - @echo >> $@ - $(V_CC) $(CFLAGS) -MM $(SOURCES) | \ - sed 's&$(TARGET)&\$$\(TARGET\)&g' | \ - sed 's/^.*:/\$$\(MT_OBJDIR\)\/&/' >> $@ - @echo >> $@ - $(V_CC) $(CFLAGS) -MM $(SOURCES) | \ - sed 's&$(TARGET)&\$$\(TARGET\)&g' | \ - sed 's/^.*:/\$$\(MD_OBJDIR\)\/&/' >> $@ - @echo >> $@ - $(V_CC) $(CFLAGS) -MM $(SOURCES) | \ - sed 's&$(TARGET)&\$$\(TARGET\)&g' | \ - sed 's/^.*:/\$$\(MDD_OBJDIR\)\/&/' >> $@ - @echo >> $@ + $(V_CC) $(CFLAGS) -MM $(SOURCES) | \ + sed 's&$(TARGET)&\$$\(TARGET\)&g' > $@.$$$$; \ + sed 's/^.*:/\$$\(ST_OBJDIR\)\/&/' < $@.$$$$ >> $@; \ + echo >> $@; \ + sed 's/^.*:/\$$\(MT_OBJDIR\)\/&/' < $@.$$$$ >> $@; \ + echo >> $@; \ + sed 's/^.*:/\$$\(MD_OBJDIR\)\/&/' < $@.$$$$ >> $@; \ + echo >> $@; \ + sed 's/^.*:/\$$\(MDD_OBJDIR\)\/&/' < $@.$$$$ >> $@; \ + echo >> $@; \ + rm -f $@.$$$$ # For some reason this has to be after 'opt' target -include $(TARGET)/depend.mk - +else +depend: +endif # ---------------------------------------------------- # Release Target # ---------------------------------------------------- @@ -832,7 +732,7 @@ release: opt $(INSTALL_DIR) "$(RELSYSDIR)/src/decode" $(INSTALL_DIR) "$(RELSYSDIR)/src/encode" $(INSTALL_DIR) "$(RELSYSDIR)/src/epmd" - $(INSTALL_DIR) "$(RELSYSDIR)/src/legacy" + $(INSTALL_DIR) "$(RELSYSDIR)/src/global" $(INSTALL_DIR) "$(RELSYSDIR)/src/misc" $(INSTALL_DIR) "$(RELSYSDIR)/src/prog" $(INSTALL_DIR) "$(RELSYSDIR)/src/registry" @@ -854,7 +754,7 @@ endif $(INSTALL_DATA) epmd/*.[ch] "$(RELSYSDIR)/src/epmd" $(INSTALL_DATA) misc/*.[ch] "$(RELSYSDIR)/src/misc" $(INSTALL_DATA) registry/*.[ch] "$(RELSYSDIR)/src/registry" - $(INSTALL_DATA) legacy/*.[ch] "$(RELSYSDIR)/src/legacy" + $(INSTALL_DATA) global/*.[ch] "$(RELSYSDIR)/src/global" $(INSTALL_DATA) prog/*.[ch] "$(RELSYSDIR)/src/prog" release_docs: diff --git a/lib/erl_interface/src/README b/lib/erl_interface/src/README index 7591615f78..823575c6b7 100644 --- a/lib/erl_interface/src/README +++ b/lib/erl_interface/src/README @@ -21,7 +21,7 @@ The cause of an assertion can be either errors in the application program (for instance, passing NULL pointers to any function that expects an ETERM pointer) or in erl_interface itself. -If you encounter any assertion failures which think you originate in +If you encounter any assertion failures which you think originate in erl_interface, I'll need the following information to track it down: 1a) The printout from the assertion, especially filename and line number. @@ -35,7 +35,7 @@ erl_interface, I'll need the following information to track it down: Changes in this version ----------------------- -There is now *one* representation for an empty list, not two as is used +There is now *one* representation for an empty list, not two as it used to be. An empty list is represented by the Erl_EmptyList structure. There are new macros, ERL_IS_EMPTY_LIST(ep), to test for an empty list, and ERL_IS_CONS(ep) to test for a cons cell (more on that below). diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c index 96823b4ee7..d97b77d3e8 100644 --- a/lib/erl_interface/src/connect/ei_connect.c +++ b/lib/erl_interface/src/connect/ei_connect.c @@ -32,26 +32,7 @@ #include <windows.h> #include <winbase.h> -#elif VXWORKS -#include <vxWorks.h> -#include <hostLib.h> -#include <selectLib.h> -#include <ifLib.h> -#include <sockLib.h> -#include <taskLib.h> -#include <inetLib.h> - -#include <unistd.h> -#include <sys/times.h> -#include <unistd.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <timers.h> - -#define getpid() taskIdSelf() - -#else /* some other unix */ +#else /* some unix */ #include <unistd.h> #include <sys/times.h> @@ -106,7 +87,8 @@ int ei_tracelevel = 0; (offsetof(ei_socket_callbacks, get_fd) \ + sizeof(int (*)(void *))) -/* FIXME why not macro? */ +typedef EI_ULONGLONG DistFlags; + static char *null_cookie = ""; static int get_cookie(char *buf, int len); @@ -120,15 +102,17 @@ static int send_status(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, char *status, unsigned ms); static int recv_status(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, unsigned ms); -static int send_challenge(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, - char *nodename, unsigned challenge, - unsigned version, unsigned ms); +static int send_challenge(ei_cnode *ec, void *ctx, int pkt_sz, + unsigned challenge, + DistFlags version, unsigned ms); static int recv_challenge(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, unsigned *challenge, unsigned *version, - unsigned *flags, char *namebuf, unsigned ms); + DistFlags *flags, char *namebuf, unsigned ms); static int send_challenge_reply(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, unsigned char digest[16], unsigned challenge, unsigned ms); +static int recv_complement(ei_socket_callbacks *cbs, void *ctx, + int pkt_sz, unsigned ms); static int recv_challenge_reply(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, unsigned our_challenge, char cookie[], @@ -139,12 +123,20 @@ static int send_challenge_ack(ei_socket_callbacks *cbs, void *ctx, static int recv_challenge_ack(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, unsigned our_challenge, char cookie[], unsigned ms); -static int send_name(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, - char *nodename, unsigned version, unsigned ms); - +static int send_name(ei_cnode *ec, void *ctx, int pkt_sz, + unsigned version, unsigned ms); +static int send_complement(ei_cnode *ec, void *ctx, int pkt_sz, + unsigned epmd_says_version, DistFlags her_flags, + unsigned ms); static int recv_name(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, - unsigned *version, unsigned *flags, char *namebuf, - unsigned ms); + char* send_name_tag, DistFlags *flags, + char *namebuf, unsigned ms); +static int ei_connect_helper(ei_cnode* ec, + Erl_IpAddr ip_addr, + char *alivename, + unsigned ms, + int rport, + int epmd_says_version); static struct hostent* dyn_gethostbyname_r(const char *name, struct hostent *hostp, char **buffer_p, @@ -659,7 +651,7 @@ int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, return ERL_ERROR; } - ec->creation = creation & 0x3; /* 2 bits */ + ec->creation = creation; if (cookie) { if (strlen(cookie) >= sizeof(ec->ei_connect_cookie)) { @@ -698,7 +690,7 @@ int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, strcpy(ec->self.node,thisnodename); ec->self.num = 0; ec->self.serial = 0; - ec->self.creation = creation & 0x3; /* 2 bits */ + ec->self.creation = creation; ec->cbs = cbs; ec->setup_context = setup_context; @@ -874,78 +866,57 @@ struct hostent *dyn_gethostbyname_r(const char *name, #endif } - /* - * Set up a connection to a given Node, and - * interchange hand shake messages with it. - * Returns a valid file descriptor at success, - * otherwise a negative error code. -*/ -int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms) +/* Finds the the IP address for hostname and saves that IP address at + the location that ip_wb points to. Returns a negative error code if + the IP address cannot be found for the hostname. */ +static int ip_address_from_hostname(char* hostname, + char** buffer_p, + size_t buffer_size, + Erl_IpAddr* ip_wb) { - char *hostname, alivename[BUFSIZ]; struct hostent *hp; -#if !defined (__WIN32__) +#ifndef __WIN32__ /* these are needed for the call to gethostbyname_r */ struct hostent host; - char buffer[1024]; - char *buf = buffer; int ei_h_errno; -#endif /* !win32 */ - int res; - - if (strlen(nodename) > MAXNODELEN) { - EI_TRACE_ERR0("ei_connect","Too long nodename"); - return ERL_ERROR; - } - - /* extract the host and alive parts from nodename */ - if (!(hostname = strchr(nodename,'@'))) { - EI_TRACE_ERR0("ei_connect","Node name has no @ in name"); - return ERL_ERROR; - } else { - strncpy(alivename, nodename, hostname - nodename); - alivename[hostname - nodename] = 0x0; - hostname++; - } - -#ifndef __WIN32__ - hp = dyn_gethostbyname_r(hostname,&host,&buf,sizeof(buffer),&ei_h_errno); + hp = dyn_gethostbyname_r(hostname,&host,buffer_p,buffer_size,&ei_h_errno); if (hp == NULL) { char thishostname[EI_MAXHOSTNAMELEN+1]; /* gethostname requies len to be max(hostname) + 1*/ if (gethostname(thishostname,EI_MAXHOSTNAMELEN+1) < 0) { - EI_TRACE_ERR0("ei_connect_tmo", + EI_TRACE_ERR0("ip_address_from_hostname", "Failed to get name of this host"); erl_errno = EHOSTUNREACH; return ERL_ERROR; } else { char *ct; - /* We use a short node name */ + /* We use a short node name */ if ((ct = strchr(thishostname, '.')) != NULL) *ct = '\0'; } if (strcmp(hostname,thishostname) == 0) /* Both nodes on same standalone host, use loopback */ - hp = dyn_gethostbyname_r("localhost",&host,&buf,sizeof(buffer),&ei_h_errno); + hp = dyn_gethostbyname_r("localhost",&host,buffer_p,buffer_size,&ei_h_errno); if (hp == NULL) { EI_TRACE_ERR2("ei_connect", - "Can't find host for %s: %d\n",nodename,ei_h_errno); + "Can't find host for %s: %d\n",hostname,ei_h_errno); erl_errno = EHOSTUNREACH; return ERL_ERROR; } } + *ip_wb = (Erl_IpAddr) *hp->h_addr_list; #else /* __WIN32__ */ if ((hp = ei_gethostbyname(hostname)) == NULL) { char thishostname[EI_MAXHOSTNAMELEN+1]; /* gethostname requires len to be max(hostname) + 1 */ if (gethostname(thishostname,EI_MAXHOSTNAMELEN+1) < 0) { - EI_TRACE_ERR1("ei_connect_tmo", - "Failed to get name of this host: %d", + EI_TRACE_ERR1("ip_address_from_hostname", + "Failed to get name of this host: %d", WSAGetLastError()); erl_errno = EHOSTUNREACH; return ERL_ERROR; } else { char *ct; - /* We use a short node name */ + /* We use a short node name */ if ((ct = strchr(thishostname, '.')) != NULL) *ct = '\0'; } if (strcmp(hostname,thishostname) == 0) @@ -955,42 +926,29 @@ int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms) char reason[1024]; win32_error(reason,sizeof(reason)); EI_TRACE_ERR2("ei_connect", - "Can't find host for %s: %s",nodename,reason); + "Can't find host for %s: %s",hostname,reason); erl_errno = EHOSTUNREACH; return ERL_ERROR; } } + *ip_wb = (Erl_IpAddr) *hp->h_addr_list; #endif /* win32 */ - - res = ei_xconnect_tmo(ec, (Erl_IpAddr) *hp->h_addr_list, alivename, ms); - -#ifndef __WIN32__ - if (buf != buffer) - free(buf); -#endif - return res; -} /* ei_connect */ - -int ei_connect(ei_cnode* ec, char *nodename) -{ - return ei_connect_tmo(ec, nodename, 0); + return 0; } - - /* ip_addr is now in network byte order - * - * first we have to get hold of the portnumber to - * the node through epmd at that host - * -*/ -int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr ip_addr, char *alivename, unsigned ms) +/* Helper function for ei_connect family of functions */ +static int ei_connect_helper(ei_cnode* ec, + Erl_IpAddr ip_addr, /* network byte order */ + char *alivename, + unsigned ms, + int rport, + int epmd_says_version) { ei_socket_callbacks *cbs = ec->cbs; void *ctx; - int rport = 0; /*uint16 rport = 0;*/ int sockd; - int dist = 0; - unsigned her_flags, her_version; + unsigned her_version; + DistFlags her_flags; unsigned our_challenge, her_challenge; unsigned char our_digest[16]; int err; @@ -999,18 +957,18 @@ int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr ip_addr, char *alivename, unsigned unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms; erl_errno = EIO; /* Default error code */ - - EI_TRACE_CONN1("ei_xconnect","-> CONNECT attempt to connect to %s", - alivename); - - if ((rport = ei_epmd_port_tmo(ip_addr,alivename,&dist, tmo)) < 0) { - EI_TRACE_ERR0("ei_xconnect","-> CONNECT can't get remote port"); - /* ei_epmd_port_tmo() has set erl_errno */ - return ERL_NO_PORT; + + if (alivename != NULL) { + EI_TRACE_CONN1("ei_xconnect","-> CONNECT attempt to connect to %s", + alivename); + } else { + EI_TRACE_CONN1("ei_xconnect","-> CONNECT attempt to connect to port %d", + rport); } - if (dist <= 4) { - EI_TRACE_ERR0("ei_xconnect","-> CONNECT remote version not compatible"); + if (epmd_says_version < EI_DIST_LOW) { + EI_TRACE_ERR1("ei_xconnect","-> CONNECT remote version %d not compatible", + epmd_says_version); return ERL_ERROR; } @@ -1050,21 +1008,24 @@ int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr ip_addr, char *alivename, unsigned goto error; } - if (send_name(cbs, ctx, pkt_sz, ec->thisnodename, (unsigned) dist, tmo)) + if (send_name(ec, ctx, pkt_sz, epmd_says_version, tmo)) goto error; if (recv_status(cbs, ctx, pkt_sz, tmo)) goto error; - if (recv_challenge(cbs, ctx, pkt_sz, &her_challenge, - &her_version, &her_flags, NULL, tmo)) + if (recv_challenge(cbs, ctx, pkt_sz, &her_challenge, &her_version, + &her_flags, NULL, tmo)) goto error; + her_version = (her_flags & DFLAG_HANDSHAKE_23) ? EI_DIST_6 : EI_DIST_5; our_challenge = gen_challenge(); gen_digest(her_challenge, ec->ei_connect_cookie, our_digest); + if (send_complement(ec, ctx, pkt_sz, epmd_says_version, her_flags, tmo)) + goto error; if (send_challenge_reply(cbs, ctx, pkt_sz, our_digest, our_challenge, tmo)) goto error; if (recv_challenge_ack(cbs, ctx, pkt_sz, our_challenge, ec->ei_connect_cookie, tmo)) goto error; - if (put_ei_socket_info(sockd, dist, null_cookie, ec, cbs, ctx) != 0) + if (put_ei_socket_info(sockd, her_version, null_cookie, ec, cbs, ctx) != 0) goto error; if (cbs->connect_handshake_complete) { @@ -1077,8 +1038,12 @@ int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr ip_addr, char *alivename, unsigned return ERL_ERROR; } } - - EI_TRACE_CONN1("ei_xconnect","-> CONNECT (ok) remote = %s",alivename); + + if (alivename != NULL) { + EI_TRACE_CONN1("ei_xconnect","-> CONNECT (ok) remote = %s",alivename); + } else { + EI_TRACE_CONN1("ei_xconnect","-> CONNECT (ok) remote port = %d",rport); + } erl_errno = 0; return sockd; @@ -1089,11 +1054,103 @@ error: return ERL_ERROR; } /* ei_xconnect */ + /* + * Set up a connection to a given Node, and + * interchange hand shake messages with it. + * Returns a valid file descriptor at success, + * otherwise a negative error code. +*/ +int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned ms) +{ + char *hostname, alivename[BUFSIZ]; + Erl_IpAddr ip; + int res; + char buffer[1024]; + char* buf = buffer; + + if (strlen(nodename) > MAXNODELEN) { + EI_TRACE_ERR0("ei_connect","Too long nodename"); + return ERL_ERROR; + } + + /* extract the host and alive parts from nodename */ + if (!(hostname = strchr(nodename,'@'))) { + EI_TRACE_ERR0("ei_connect","Node name has no @ in name"); + return ERL_ERROR; + } else { + strncpy(alivename, nodename, hostname - nodename); + alivename[hostname - nodename] = 0x0; + hostname++; + } + + res = ip_address_from_hostname(hostname, &buf, sizeof(buffer), &ip); + + if (res < 0) { + return res; + } + + res = ei_xconnect_tmo(ec, ip, alivename, ms); + + if(buf != buffer) { + free(buf); + } + + return res; +} /* ei_connect */ + +int ei_connect(ei_cnode* ec, char *nodename) +{ + return ei_connect_tmo(ec, nodename, 0); +} + +int ei_connect_host_port_tmo(ei_cnode* ec, char *host, int port, unsigned ms) +{ + Erl_IpAddr ip; + char buffer[1024]; + char* buf = buffer; + int res = ip_address_from_hostname(host, &buf, sizeof(buffer), &ip); + if (res < 0) { + return res; + } + if(buf != buffer) { + free(buf); + } + return ei_xconnect_host_port_tmo(ec, ip, port, ms); +} + +int ei_connect_host_port(ei_cnode* ec, char *host, int port) +{ + return ei_connect_host_port_tmo(ec, host, port, 0); +} + +int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr ip_addr, char *alivename, unsigned ms) +{ + int epmd_says_version = 0; + int port; + unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms; + if ((port = ei_epmd_port_tmo(ip_addr,alivename,&epmd_says_version, tmo)) < 0) { + EI_TRACE_ERR0("ei_xconnect","-> CONNECT can't get remote port"); + /* ei_epmd_port_tmo() has set erl_errno */ + return ERL_NO_PORT; + } + return ei_connect_helper(ec, ip_addr, alivename, ms, port, epmd_says_version); +} + int ei_xconnect(ei_cnode* ec, Erl_IpAddr ip_addr, char *alivename) { return ei_xconnect_tmo(ec, ip_addr, alivename, 0); } +int ei_xconnect_host_port_tmo(ei_cnode* ec, Erl_IpAddr ip_addr, int port, unsigned ms) +{ + return ei_connect_helper(ec, ip_addr, NULL, ms, port, EI_DIST_LOW); +} + +int ei_xconnect_host_port(ei_cnode* ec, Erl_IpAddr ip_addr, int port) +{ + return ei_xconnect_host_port_tmo(ec, ip_addr, port, 0); +} + int ei_listen(ei_cnode *ec, int *port, int backlog) { struct in_addr ip_addr; @@ -1209,8 +1266,9 @@ int ei_accept(ei_cnode* ec, int lfd, ErlConnect *conp) int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms) { int fd; - unsigned her_version, her_flags; + DistFlags her_flags; char tmp_nodename[MAXNODELEN+1]; + char send_name_tag; char *her_name; int pkt_sz, err; struct sockaddr_in addr; @@ -1235,6 +1293,10 @@ int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms) ctx = EI_FD_AS_CTX__(lfd); } + if (ec->cbs != cbs) { + EI_CONN_SAVE_ERRNO__(EINVAL); + return ERL_ERROR; + } EI_TRACE_CONN0("ei_accept","<- ACCEPT waiting for connection"); @@ -1281,16 +1343,14 @@ int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms) EI_TRACE_CONN0("ei_accept","<- ACCEPT connected to remote"); - if (recv_name(cbs, ctx, pkt_sz, &her_version, &her_flags, her_name, tmo)) { + if (recv_name(cbs, ctx, pkt_sz, &send_name_tag, &her_flags, + her_name, tmo)) { EI_TRACE_ERR0("ei_accept","<- ACCEPT initial ident failed"); goto error; } - if (her_version <= 4) { - EI_TRACE_ERR0("ei_accept","<- ACCEPT remote version not compatible"); - goto error; - } - else { + { + unsigned her_version = (her_flags & DFLAG_HANDSHAKE_23) ? 6 : 5; unsigned our_challenge; unsigned her_challenge; unsigned char our_digest[16]; @@ -1298,9 +1358,12 @@ int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms) if (send_status(cbs, ctx, pkt_sz, "ok", tmo)) goto error; our_challenge = gen_challenge(); - if (send_challenge(cbs, ctx, pkt_sz, ec->thisnodename, - our_challenge, her_version, tmo)) + if (send_challenge(ec, ctx, pkt_sz, our_challenge, her_flags, tmo)) goto error; + if (send_name_tag == 'n' && (her_flags & DFLAG_HANDSHAKE_23)) { + if (recv_complement(cbs, ctx, pkt_sz, tmo)) + goto error; + } if (recv_challenge_reply(cbs, ctx, pkt_sz, our_challenge, ec->ei_connect_cookie, &her_challenge, tmo)) goto error; @@ -1629,21 +1692,6 @@ unsigned int gen_challenge(void) return md_32((char*) &s, sizeof(s)); } -#elif defined(VXWORKS) - -static unsigned int gen_challenge(void) -{ - struct { - struct timespec tv; - clock_t cpu; - int pid; - } s; - s.cpu = clock(); - clock_gettime(CLOCK_REALTIME, &s.tv); - s.pid = getpid(); - return md_32((char*) &s, sizeof(s)); -} - #else /* some unix */ static unsigned int gen_challenge(void) @@ -1846,26 +1894,50 @@ error: return -1; } -static int send_name_or_challenge(ei_socket_callbacks *cbs, - void *ctx, - int pkt_sz, - char *nodename, - int f_chall, - unsigned challenge, - unsigned version, - unsigned ms) +static DistFlags preferred_flags(void) +{ + DistFlags flags = + DFLAG_EXTENDED_REFERENCES + | DFLAG_DIST_MONITOR + | DFLAG_EXTENDED_PIDS_PORTS + | DFLAG_FUN_TAGS + | DFLAG_NEW_FUN_TAGS + | DFLAG_NEW_FLOATS + | DFLAG_SMALL_ATOM_TAGS + | DFLAG_UTF8_ATOMS + | DFLAG_MAP_TAG + | DFLAG_BIG_CREATION + | DFLAG_EXPORT_PTR_TAG + | DFLAG_BIT_BINARIES + | DFLAG_HANDSHAKE_23; + if (ei_internal_use_21_bitstr_expfun()) { + flags &= ~(DFLAG_EXPORT_PTR_TAG + | DFLAG_BIT_BINARIES); + } + return flags; +} + +static int send_name(ei_cnode *ec, + void *ctx, + int pkt_sz, + unsigned version, + unsigned ms) { char *buf; unsigned char *s; char dbuf[DEFBUF_SIZ]; - int siz = pkt_sz + 1 + 2 + 4 + strlen(nodename); - const char* function[] = {"SEND_NAME", "SEND_CHALLENGE"}; + const unsigned int nodename_len = strlen(ec->thisnodename); + int siz; int err; ssize_t len; - unsigned int flags; + DistFlags flags; + const char tag = (version == EI_DIST_5) ? 'n' : 'N'; + + if (tag == 'n') + siz = pkt_sz + 1 + 2 + 4 + nodename_len; + else + siz = pkt_sz + 1 + 8 + 4 + 2 + nodename_len; - if (f_chall) - siz += 4; buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf; if (!buf) { erl_errno = ENOMEM; @@ -1882,35 +1954,95 @@ static int send_name_or_challenge(ei_socket_callbacks *cbs, default: return -1; } - put8(s, 'n'); - put16be(s, version); - flags = (DFLAG_EXTENDED_REFERENCES - | DFLAG_DIST_MONITOR - | DFLAG_EXTENDED_PIDS_PORTS - | DFLAG_FUN_TAGS - | DFLAG_NEW_FUN_TAGS - | DFLAG_NEW_FLOATS - | DFLAG_SMALL_ATOM_TAGS - | DFLAG_UTF8_ATOMS - | DFLAG_MAP_TAG - | DFLAG_BIG_CREATION - | DFLAG_EXPORT_PTR_TAG - | DFLAG_BIT_BINARIES); - if (ei_internal_use_21_bitstr_expfun()) { - flags &= ~(DFLAG_EXPORT_PTR_TAG - | DFLAG_BIT_BINARIES); + flags = preferred_flags(); + + put8(s, tag); + if (tag == 'n') { + put16be(s, EI_DIST_5); /* some impl (jinterface) demand ver==5 */ + put32be(s, flags); + } + else { /* tag == 'N' */ + put64be(s, flags); + put32be(s, ec->creation); + put16be(s, nodename_len); } - put32be(s, flags); - if (f_chall) - put32be(s, challenge); - memcpy(s, nodename, strlen(nodename)); + memcpy(s, ec->thisnodename, nodename_len); len = (ssize_t) siz; - err = ei_write_fill_ctx_t__(cbs, ctx, buf, &len, ms); + err = ei_write_fill_ctx_t__(ec->cbs, ctx, buf, &len, ms); if (!err && len != (ssize_t) siz) err = EIO; if (err) { - EI_TRACE_ERR1("send_name_or_challenge", - "-> %s socket write failed", function[f_chall]); + EI_TRACE_ERR0("send_name", "SEND_NAME -> socket write failed"); + if (buf != dbuf) + free(buf); + EI_CONN_SAVE_ERRNO__(err); + return -1; + } + + if (buf != dbuf) + free(buf); + return 0; +} + +static int send_challenge(ei_cnode *ec, + void *ctx, + int pkt_sz, + unsigned challenge, + DistFlags her_flags, + unsigned ms) +{ + char *buf; + unsigned char *s; + char dbuf[DEFBUF_SIZ]; + const unsigned int nodename_len = strlen(ec->thisnodename); + int siz; + int err; + ssize_t len; + DistFlags flags; + const char tag = (her_flags & DFLAG_HANDSHAKE_23) ? 'N' : 'n'; + + if (tag == 'n') + siz = pkt_sz + 1 + 2 + 4 + 4 + nodename_len; + else + siz = pkt_sz + 1 + 8 + 4 + 4 + 2 + nodename_len; + + buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf; + if (!buf) { + erl_errno = ENOMEM; + return -1; + } + s = (unsigned char *)buf; + switch (pkt_sz) { + case 2: + put16be(s,siz - 2); + break; + case 4: + put32be(s,siz - 4); + break; + default: + return -1; + } + + flags = preferred_flags(); + put8(s, tag); + if (tag == 'n') { + put16be(s, EI_DIST_5); /* choosen version */ + put32be(s, flags); + put32be(s, challenge); + } + else { + put64be(s, flags); + put32be(s, challenge); + put32be(s, ec->creation); + put16be(s, nodename_len); + } + memcpy(s, ec->thisnodename, nodename_len); + len = (ssize_t) siz; + err = ei_write_fill_ctx_t__(ec->cbs, ctx, buf, &len, ms); + if (!err && len != (ssize_t) siz) + err = EIO; + if (err) { + EI_TRACE_ERR0("send_challenge", "-> SEND_CHALLENGE socket write failed"); if (buf != dbuf) free(buf); EI_CONN_SAVE_ERRNO__(err); @@ -1924,13 +2056,13 @@ static int send_name_or_challenge(ei_socket_callbacks *cbs, static int recv_challenge(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, unsigned *challenge, unsigned *version, - unsigned *flags, char *namebuf, unsigned ms) + DistFlags *flags, char *namebuf, unsigned ms) { char dbuf[DEFBUF_SIZ]; char *buf = dbuf; int is_static = 1; int buflen = DEFBUF_SIZ; - int rlen; + int rlen, nodename_len; char *s; char tag; char tmp_nodename[MAXNODELEN+1]; @@ -1943,21 +2075,57 @@ static int recv_challenge(ei_socket_callbacks *cbs, void *ctx, "<- RECV_CHALLENGE socket read failed (%d)",rlen); goto error; } - if ((rlen - 11) > MAXNODELEN) { - EI_TRACE_ERR1("recv_challenge", - "<- RECV_CHALLENGE nodename too long (%d)",rlen - 11); - goto error; - } s = buf; - if ((tag = get8(s)) != 'n') { + tag = get8(s); + if (tag != 'n' && tag != 'N') { EI_TRACE_ERR2("recv_challenge", "<- RECV_CHALLENGE incorrect tag, " - "expected 'n' got '%c' (%u)",tag,tag); + "expected 'n' or 'N', got '%c' (%u)",tag,tag); goto error; } - *version = get16be(s); - *flags = get32be(s); - *challenge = get32be(s); + if (tag == 'n') { /* OLD */ + unsigned int version; + if (rlen < 1+2+4+4) { + EI_TRACE_ERR1("recv_challenge","<- RECV_CHALLENGE 'n' packet too short (%d)", + rlen) + goto error; + } + + version = get16be(s); + if (version != EI_DIST_5) { + EI_TRACE_ERR1("recv_challenge", + "<- RECV_CHALLENGE 'n' incorrect version=%d", + version); + goto error; + } + *flags = get32be(s); + *challenge = get32be(s); + nodename_len = (buf + rlen) - s; + } + else { /* NEW */ + if (rlen < 1+8+4+4+2) { + EI_TRACE_ERR1("recv_challenge","<- RECV_CHALLENGE 'N' packet too short (%d)", + rlen) + goto error; + } + *version = EI_DIST_6; + *flags = get64be(s); + *challenge = get32be(s); + s += 4; /* ignore peer 'creation' */ + nodename_len = get16be(s); + if (nodename_len > (buf + rlen) - s) { + EI_TRACE_ERR1("recv_challenge", + "<- RECV_CHALLENGE 'N' nodename too long (%d)", + nodename_len); + goto error; + } + } + + if (nodename_len > MAXNODELEN) { + EI_TRACE_ERR1("recv_challenge", + "<- RECV_CHALLENGE nodename too long (%d)", nodename_len); + goto error; + } if (!(*flags & DFLAG_EXTENDED_REFERENCES)) { EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE peer cannot " @@ -1981,8 +2149,8 @@ static int recv_challenge(ei_socket_callbacks *cbs, void *ctx, if (!namebuf) namebuf = &tmp_nodename[0]; - memcpy(namebuf, s, rlen - 11); - namebuf[rlen - 11] = '\0'; + memcpy(namebuf, s, nodename_len); + namebuf[nodename_len] = '\0'; if (!is_static) free(buf); @@ -2003,6 +2171,63 @@ error: return -1; } +static int send_complement(ei_cnode *ec, + void *ctx, + int pkt_sz, + unsigned epmd_says_version, + DistFlags her_flags, + unsigned ms) +{ + if (epmd_says_version == EI_DIST_5 && (her_flags & DFLAG_HANDSHAKE_23)) { + char *buf; + unsigned char *s; + char dbuf[DEFBUF_SIZ]; + int err; + ssize_t len; + unsigned int flagsHigh; + const int siz = pkt_sz + 1 + 4 + 4; + + buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf; + if (!buf) { + erl_errno = ENOMEM; + return -1; + } + s = (unsigned char *)buf; + switch (pkt_sz) { + case 2: + put16be(s,siz - 2); + break; + case 4: + put32be(s,siz - 4); + break; + default: + return -1; + } + flagsHigh = preferred_flags() >> 32; + + put8(s, 'c'); + put32be(s, flagsHigh); + put32be(s, ec->creation); + + len = (ssize_t) siz; + err = ei_write_fill_ctx_t__(ec->cbs, ctx, buf, &len, ms); + if (!err && len != (ssize_t) siz) + err = EIO; + if (err) { + EI_TRACE_ERR0("send_name", "SEND_NAME -> socket write failed"); + if (buf != dbuf) + free(buf); + EI_CONN_SAVE_ERRNO__(err); + return -1; + } + + if (buf != dbuf) + free(buf); + } + return 0; +} + + static int send_challenge_reply(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, unsigned char digest[16], unsigned challenge, unsigned ms) @@ -2049,6 +2274,54 @@ static int send_challenge_reply(ei_socket_callbacks *cbs, void *ctx, return 0; } +static int recv_complement(ei_socket_callbacks *cbs, + void *ctx, + int pkt_sz, + unsigned ms) +{ + char dbuf[DEFBUF_SIZ]; + char *buf = dbuf; + int is_static = 1; + int buflen = DEFBUF_SIZ; + int rlen; + char *s; + char tag; + unsigned int creation; + + erl_errno = EIO; /* Default */ + + if ((rlen = read_hs_package(cbs, ctx, pkt_sz, &buf, &buflen, &is_static, ms)) != 21) { + EI_TRACE_ERR1("recv_complement", + "<- RECV_COMPLEMENT socket read failed (%d)",rlen); + goto error; + } + + s = buf; + if ((tag = get8(s)) != 'c') { + EI_TRACE_ERR2("recv_complement", + "<- RECV_COMPLEMENT incorrect tag, " + "expected 'c' got '%c' (%u)",tag,tag); + goto error; + } + creation = get32be(s); + if (!is_static) + free(buf); + + if (ei_tracelevel >= 3) { + EI_TRACE_CONN1("recv_complement", + "<- RECV_COMPLEMENT (ok) creation = %u", + creation); + } + /* We don't have any use for 'creation' of other node, so we drop it */ + erl_errno = 0; + return 0; + +error: + if (!is_static) + free(buf); + return -1; +} + static int recv_challenge_reply(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, @@ -2204,30 +2477,16 @@ error: return -1; } -static int send_name(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, - char *nodename, unsigned version, unsigned ms) -{ - return send_name_or_challenge(cbs, ctx, pkt_sz, nodename, 0, - 0, version, ms); -} - -static int send_challenge(ei_socket_callbacks *cbs, void *ctx, int pkt_sz, - char *nodename, unsigned challenge, unsigned version, - unsigned ms) -{ - return send_name_or_challenge(cbs, ctx, pkt_sz, nodename, 1, - challenge, version, ms); -} - static int recv_name(ei_socket_callbacks *cbs, void *ctx, - int pkt_sz, unsigned *version, - unsigned *flags, char *namebuf, unsigned ms) + int pkt_sz, char *send_name_tag, + DistFlags *flags, char *namebuf, unsigned ms) { char dbuf[DEFBUF_SIZ]; char *buf = dbuf; int is_static = 1; int buflen = DEFBUF_SIZ; int rlen; + unsigned int namelen; char *s; char tmp_nodename[MAXNODELEN+1]; char tag; @@ -2239,19 +2498,40 @@ static int recv_name(ei_socket_callbacks *cbs, void *ctx, EI_TRACE_ERR1("recv_name","<- RECV_NAME socket read failed (%d)",rlen); goto error; } - if ((rlen - 7) > MAXNODELEN) { - EI_TRACE_ERR1("recv_name","<- RECV_NAME nodename too long (%d)",rlen-7); - goto error; - } s = buf; tag = get8(s); - if (tag != 'n') { + *send_name_tag = tag; + if (tag != 'n' && tag != 'N') { EI_TRACE_ERR2("recv_name","<- RECV_NAME incorrect tag, " - "expected 'n' got '%c' (%u)",tag,tag); + "expected 'n' or 'N', got '%c' (%u)",tag,tag); goto error; } - *version = get16be(s); - *flags = get32be(s); + if (tag == 'n') { + unsigned int version; + if (rlen < 1+2+4) { + EI_TRACE_ERR1("recv_name","<- RECV_NAME 'n' packet too short (%d)", + rlen) + goto error; + } + version = get16be(s); + if (version < EI_DIST_5) { + EI_TRACE_ERR1("recv_name","<- RECV_NAME 'n' invalid version=%d", + version) + goto error; + } + *flags = get32be(s); + namelen = rlen - (1+2+4); + } + else { /* tag == 'N' */ + if (rlen < 1+8+4+2) { + EI_TRACE_ERR1("recv_name","<- RECV_NAME 'N' packet too short (%d)", + rlen) + goto error; + } + *flags = get64be(s); + s += 4; /* ignore peer 'creation' */ + namelen = get16be(s); + } if (!(*flags & DFLAG_EXTENDED_REFERENCES)) { EI_TRACE_ERR0("recv_name","<- RECV_NAME peer cannot handle" @@ -2269,14 +2549,20 @@ static int recv_name(ei_socket_callbacks *cbs, void *ctx, if (!namebuf) namebuf = &tmp_nodename[0]; - memcpy(namebuf, s, rlen - 7); - namebuf[rlen - 7] = '\0'; + if (namelen > MAXNODELEN || s+namelen > buf+rlen) { + EI_TRACE_ERR2("recv_name","<- RECV_NAME '%c' nodename too long (%d)", + tag, namelen); + goto error; + } + + memcpy(namebuf, s, namelen); + namebuf[namelen] = '\0'; if (!is_static) free(buf); EI_TRACE_CONN3("recv_name", - "<- RECV_NAME (ok) node = %s, version = %u, flags = %u", - namebuf,*version,*flags); + "<- RECV_NAME (ok) node = %s, tag = %c, flags = %u", + namebuf,tag,*flags); erl_errno = 0; return 0; diff --git a/lib/erl_interface/src/connect/ei_connect_int.h b/lib/erl_interface/src/connect/ei_connect_int.h index b41a5f2b23..05cec3c824 100644 --- a/lib/erl_interface/src/connect/ei_connect_int.h +++ b/lib/erl_interface/src/connect/ei_connect_int.h @@ -38,30 +38,7 @@ #include <windows.h> #include <winbase.h> -#elif VXWORKS -#include <vxWorks.h> -#include <hostLib.h> -#include <selectLib.h> -#include <ifLib.h> -#include <sockLib.h> -#include <taskLib.h> -#include <inetLib.h> -#include <ioLib.h> - -#include <unistd.h> -#include <sys/types.h> -#include <sys/times.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <timers.h> - -#define getpid() taskIdSelf() -extern int h_errno; - -#else /* some other unix */ +#else /* some unix */ #include <unistd.h> #include <sys/types.h> #include <sys/times.h> @@ -109,6 +86,8 @@ extern int h_errno; #define DFLAG_UTF8_ATOMS 0x10000 #define DFLAG_MAP_TAG 0x20000 #define DFLAG_BIG_CREATION 0x40000 +#define DFLAG_HANDSHAKE_23 0x1000000 +#define DFLAG_HANDSHAKE_XX 0xfe000000 /* bits reserved for handshake changes */ 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 225fddc784..f6182ccaf0 100644 --- a/lib/erl_interface/src/connect/ei_resolve.c +++ b/lib/erl_interface/src/connect/ei_resolve.c @@ -21,19 +21,7 @@ * Interface functions to different versions of gethostbyname */ -#ifdef VXWORKS -#include <vxWorks.h> -#include <stdio.h> -#include <semLib.h> -#include <hostLib.h> -#include <resolvLib.h> -#include <string.h> -#include <sys/socket.h> -#include <errno.h> -#include <symLib.h> -#include <sysSymTbl.h> - -#elif __WIN32__ +#ifdef __WIN32__ #include <winsock2.h> #include <windows.h> #include <winbase.h> @@ -55,6 +43,16 @@ #include "ei_resolve.h" #include "ei_locking.h" +/* AIX has a totally different signature (allegedly shared with some other + * Unices) that isn't compatible. It turns out that the _r version isn't + * thread-safe according to curl - but bizarrely, since AIX 4.3, libc + * is thread-safe in a manner that makes the normal gethostbyname OK + * for re-entrant use. + */ +#ifdef _AIX +#undef HAVE_GETHOSTBYNAME_R +#endif + #ifdef HAVE_GETHOSTBYNAME_R int ei_init_resolve(void) @@ -75,7 +73,7 @@ int ei_init_resolve(void) static ei_mutex_t *ei_gethost_sem = NULL; #endif /* _REENTRANT */ static int ei_resolve_initialized = 0; -#ifndef __WIN32__ +#if !defined(__WIN32__) && !defined(_AIX) int h_errno; #endif @@ -85,18 +83,6 @@ int h_errno; #define DEBUGF(X) /* Nothing */ #endif -#ifdef VXWORKS -/* FIXME problem for threaded ? */ -static struct hostent *(*sens_gethostbyname)(const char *name, - char *, int) = NULL; -static struct hostent *(*sens_gethostbyaddr)(const char *addr, - char *, int) = NULL; -#endif - -#ifdef VXWORKS -static int verify_dns_configuration(void); -#endif - /* * If we find SENS resolver, use the functions found there, i.e. * resolvGetHostByName() and resolvGetHostByAddr(). Otherwise we use @@ -106,32 +92,6 @@ static int verify_dns_configuration(void); int ei_init_resolve(void) { -#ifdef VXWORKS - void *sym; - SYM_TYPE symtype; - - if (symFindByName(sysSymTbl,"resolvGetHostByName", - (char **)&sym,&symtype) == OK && - verify_dns_configuration()) { - sens_gethostbyname = sym; - DEBUGF((stderr,"found SENS resolver - using it for gethostbyname()\n")); - if (symFindByName(sysSymTbl,"resolvGetHostByAddr", - (char **)&sym,&symtype) == OK) { - sens_gethostbyaddr = sym; - DEBUGF((stderr,"found SENS resolver - " - "using it for gethostbyaddr()\n")); - } - else { - DEBUGF((stderr,"SENS resolver not found - " - "using default gethostbyaddr()\n")); - } - } - else { - DEBUGF((stderr,"SENS resolver not found - " - "using default gethostbyname()\n")); - } -#endif /* VXWORKS */ - #ifdef _REENTRANT ei_gethost_sem = ei_mutex_create(); if (!ei_gethost_sem) @@ -142,42 +102,7 @@ int ei_init_resolve(void) return 0; } -#ifdef VXWORKS -/* -** Function to verify the DNS configuration on VwXorks SENS. -** Actually configures to a default value if unconfigured... -*/ -static int verify_dns_configuration(void) -{ - /* FIXME problem for threaded ? */ - static char resolv_params[sizeof(RESOLV_PARAMS_S)]; - void (*rpg)(char *); - STATUS (*rps)(char *); - SYM_TYPE dummy; - int get_result, set_result; - - get_result = symFindByName(sysSymTbl,"resolvParamsGet", (char **) &rpg, &dummy); - set_result = symFindByName(sysSymTbl,"resolvParamsSet", (char **) &rps, &dummy); - - if (!(get_result == OK && - set_result == OK)) - return -1; - (*rpg)(resolv_params); - if (*resolv_params == '\0') { - /* It exists, but is not configured, ei_connect would fail - if we left it this way... The best we can do is to configure - it to use the local host database on the card, as a fallback */ - *resolv_params = (char) 1; - fprintf(stderr,"Trying to fix up DNS configuration.\n"); - if (((*rps)(resolv_params)) != OK) - return -1; - } - return 0; -} - -#endif - -#if defined(VXWORKS) || _REENTRANT +#if _REENTRANT /* * Copy the contents of one struct hostent to another, i.e. don't just @@ -365,9 +290,9 @@ static struct hostent *my_gethostbyname_r(const char *name, return rval; } -#endif /* defined(VXWORKS) || _REENTRANT */ +#endif /* _REENTRANT */ -#if defined(VXWORKS) || EI_THREADS != false +#if EI_THREADS != false static struct hostent *my_gethostbyaddr_r(const char *addr, int length, @@ -433,7 +358,7 @@ static struct hostent *my_gethostbyaddr_r(const char *addr, return rval; } -#endif /* defined(VXWORKS) || EI_THREADS != false */ +#endif /* EI_THREADS != false */ #endif /* !HAVE_GETHOSTBYNAME_R */ @@ -449,154 +374,6 @@ struct hostent *ei_gethostbyaddr(const char *addr, int len, int type) return gethostbyaddr(addr, len, type); } -#elif VXWORKS - - -/* these are a couple of substitutes for the real thing when we run on - * stock vxworks (i.e. no sens). - * - * len and type are ignored, but we make up some reasonable values and - * insert them - */ -static struct hostent *my_gethostbyname(const char *name) -{ - /* FIXME problem for threaded ? */ - static struct hostent h; - static char hostname[EI_MAXHOSTNAMELEN+1]; - static char *aliases[1] = {NULL}; - static char *addrp[2] = {NULL,NULL}; - static unsigned long addr = 0; - - strcpy(hostname,name); - if ((addr = (unsigned long)hostGetByName(hostname)) == ERROR) { - h_errno = HOST_NOT_FOUND; - return NULL; - } - - h_errno = 0; - h.h_name = hostname; - h.h_aliases = aliases; - h.h_length = 4; - h.h_addrtype = AF_INET; - addrp[0] = (char *)&addr; - h.h_addr_list = addrp; - - return &h; -} - -static struct hostent *my_gethostbyaddr(const char *addr, int len, int type) -{ - /* FIXME problem for threaded ? */ - static struct hostent h; - static char hostname[EI_MAXHOSTNAMELEN+1]; - static char *aliases[1] = { NULL }; - static unsigned long inaddr; - static char *addrp[2] = {(char *)&inaddr, NULL}; - - memmove(&inaddr,addr,sizeof(inaddr)); - - if ((hostGetByAddr(inaddr,hostname)) == ERROR) { - h_errno = HOST_NOT_FOUND; - return NULL; - } - - h_errno = 0; - h.h_name = hostname; - h.h_aliases = aliases; - h.h_length = 4; - h.h_addrtype = AF_INET; - h.h_addr_list = addrp; - - return &h; -} - -/* use sens functions for these, if found. */ -struct hostent *ei_gethostbyname(const char *name) -{ - struct hostent *h = NULL; - - if (!sens_gethostbyname) { - h = my_gethostbyname(name); - } - else { - /* FIXME problem for threaded ? */ - static char buf[1024]; - h = sens_gethostbyname(name,buf,1024); - } - - return h; -} - -struct hostent *ei_gethostbyaddr(const char *addr, int len, int type) -{ - struct hostent *h = NULL; - - if (!sens_gethostbyaddr) { - h = my_gethostbyaddr(addr,len,type); - } - else { - /* FIXME problem for threaded ? */ - static char buf[1024]; - h = sens_gethostbyaddr(addr,buf,1024); - } - - return h; -} - -struct hostent *ei_gethostbyaddr_r(const char *addr, - int length, - int type, - struct hostent *hostp, - char *buffer, - int buflen, - int *h_errnop) -{ - struct hostent *h = NULL; - - /* use own func if sens function not available */ - if (!sens_gethostbyaddr) { - h = my_gethostbyaddr_r(addr,length,type,hostp,buffer,buflen,h_errnop); - } - else { - if (!(h = sens_gethostbyaddr(addr,buffer,buflen))) { - /* sens returns status via errno */ - *h_errnop = errno; - } - else { - *hostp = *h; - *h_errnop = 0; - } - } - - return h; -} - -struct hostent *ei_gethostbyname_r(const char *name, - struct hostent *hostp, - char *buffer, - int buflen, - int *h_errnop) -{ - struct hostent *h = NULL; - - /* use own func if sens function not available */ - if (!sens_gethostbyname) { - h = my_gethostbyname_r(name,hostp,buffer,buflen,h_errnop); - } - else { - if (!(h = sens_gethostbyname(name,buffer,buflen))) { - /* sens returns status via errno */ - *h_errnop = errno; - } - else { - *hostp = *h; - *h_errnop = 0; - } - } - - return h; -} - #else /* unix of some kind */ struct hostent *ei_gethostbyname(const char *name) @@ -667,5 +444,5 @@ struct hostent *ei_gethostbyname_r(const char *name, #endif } -#endif /* vxworks, win, unix */ +#endif /* win, unix */ diff --git a/lib/erl_interface/src/connect/send.c b/lib/erl_interface/src/connect/send.c index d97532d123..8535b2a206 100644 --- a/lib/erl_interface/src/connect/send.c +++ b/lib/erl_interface/src/connect/send.c @@ -24,13 +24,6 @@ # include <windows.h> # include <winbase.h> -#elif VXWORKS - -# include <sys/types.h> -# include <unistd.h> -# include <sysLib.h> -# include <tickLib.h> - #else /* unix */ # include <sys/types.h> diff --git a/lib/erl_interface/src/connect/send_reg.c b/lib/erl_interface/src/connect/send_reg.c index 80d61e57b5..b34432fb6e 100644 --- a/lib/erl_interface/src/connect/send_reg.c +++ b/lib/erl_interface/src/connect/send_reg.c @@ -22,10 +22,6 @@ #include <windows.h> #include <winbase.h> -#elif VXWORKS -#include <sys/types.h> -#include <unistd.h> - #else /* unix */ #include <sys/types.h> #include <unistd.h> diff --git a/lib/erl_interface/src/decode/decode_big.c b/lib/erl_interface/src/decode/decode_big.c index cbbbd3f0b7..bd2d6662a5 100644 --- a/lib/erl_interface/src/decode/decode_big.c +++ b/lib/erl_interface/src/decode/decode_big.c @@ -144,13 +144,6 @@ int ei_big_comp(erlang_big *x, erlang_big *y) * Handling of floating point exceptions. */ -#if defined(VXWORKS) && CPU == PPC860 -#undef NO_FPE_SIGNALS -#define NO_FPE_SIGNALS 1 -#undef INLINED_FP_CONVERSION -#define INLINED_FP_CONVERSION 1 -#endif - #ifdef NO_FPE_SIGNALS # define ERTS_FP_CHECK_INIT() do {} while (0) # define ERTS_FP_ERROR(f, Action) if (!isfinite(f)) { Action; } else {} diff --git a/lib/erl_interface/src/encode/encode_pid.c b/lib/erl_interface/src/encode/encode_pid.c index d14746b40f..0dfdb16372 100644 --- a/lib/erl_interface/src/encode/encode_pid.c +++ b/lib/erl_interface/src/encode/encode_pid.c @@ -25,7 +25,6 @@ int ei_encode_pid(char *buf, int *index, const erlang_pid *p) { char* s = buf + *index; - const char tag = (p->creation > 3) ? ERL_NEW_PID_EXT : ERL_PID_EXT; ++(*index); /* skip ERL_PID_EXT */ if (ei_encode_atom_len_as(buf, index, p->node, strlen(p->node), @@ -33,21 +32,17 @@ int ei_encode_pid(char *buf, int *index, const erlang_pid *p) return -1; if (buf) { - put8(s, tag); + put8(s, ERL_NEW_PID_EXT); s = buf + *index; /* now the integers */ put32be(s,p->num & 0x7fff); /* 15 bits */ put32be(s,p->serial & 0x1fff); /* 13 bits */ - if (tag == ERL_PID_EXT) { - put8(s,(p->creation & 0x03)); /* 2 bits */ - } else { - put32be(s, p->creation); /* 32 bits */ - } + put32be(s, p->creation); /* 32 bits */ } - *index += 4 + 4 + (tag == ERL_PID_EXT ? 1 : 4); + *index += 4 + 4 + 4; return 0; } diff --git a/lib/erl_interface/src/encode/encode_port.c b/lib/erl_interface/src/encode/encode_port.c index eb464380c0..0fb4018db1 100644 --- a/lib/erl_interface/src/encode/encode_port.c +++ b/lib/erl_interface/src/encode/encode_port.c @@ -25,7 +25,6 @@ int ei_encode_port(char *buf, int *index, const erlang_port *p) { char *s = buf + *index; - const char tag = p->creation > 3 ? ERL_NEW_PORT_EXT : ERL_PORT_EXT; ++(*index); /* skip ERL_PORT_EXT */ if (ei_encode_atom_len_as(buf, index, p->node, strlen(p->node), ERLANG_UTF8, @@ -33,19 +32,15 @@ int ei_encode_port(char *buf, int *index, const erlang_port *p) return -1; } if (buf) { - put8(s, tag); + put8(s, ERL_NEW_PORT_EXT); s = buf + *index; /* now the integers */ put32be(s,p->id & 0x0fffffff /* 28 bits */); - if (tag == ERL_PORT_EXT) { - put8(s,(p->creation & 0x03)); - } else { - put32be(s, p->creation); - } + put32be(s, p->creation); } - *index += 4 + (tag == ERL_PORT_EXT ? 1 : 4); + *index += 4 + 4; return 0; } diff --git a/lib/erl_interface/src/encode/encode_ref.c b/lib/erl_interface/src/encode/encode_ref.c index 5ccfc32c6d..8c2e0a25f7 100644 --- a/lib/erl_interface/src/encode/encode_ref.c +++ b/lib/erl_interface/src/encode/encode_ref.c @@ -24,7 +24,6 @@ int ei_encode_ref(char *buf, int *index, const erlang_ref *p) { - const char tag = (p->creation > 3) ? ERL_NEWER_REFERENCE_EXT : ERL_NEW_REFERENCE_EXT; char *s = buf + *index; int i; @@ -37,7 +36,7 @@ int ei_encode_ref(char *buf, int *index, const erlang_ref *p) /* Always encode as an extended reference; all participating parties are now expected to be able to decode extended references. */ if (buf) { - put8(s, tag); + put8(s, ERL_NEWER_REFERENCE_EXT); /* first, number of integers */ put16be(s, p->len); @@ -46,15 +45,12 @@ int ei_encode_ref(char *buf, int *index, const erlang_ref *p) s = buf + *index; /* now the integers */ - if (tag == ERL_NEW_REFERENCE_EXT) - put8(s,(p->creation & 0x03)); - else - put32be(s, p->creation); + put32be(s, p->creation); for (i = 0; i < p->len; i++) put32be(s,p->n[i]); } - *index += p->len*4 + (tag == ERL_NEW_REFERENCE_EXT ? 1 : 4); + *index += p->len*4 + 4; return 0; } diff --git a/lib/erl_interface/src/epmd/ei_epmd.h b/lib/erl_interface/src/epmd/ei_epmd.h index ac153b6e66..e3cb041dc9 100644 --- a/lib/erl_interface/src/epmd/ei_epmd.h +++ b/lib/erl_interface/src/epmd/ei_epmd.h @@ -24,9 +24,12 @@ #define INADDR_LOOPBACK ((u_long) 0x7F000001) #endif +#define EI_DIST_5 5 /* OTP R4 - 22 */ +#define EI_DIST_6 6 /* OTP 23 and later */ + #ifndef EI_DIST_HIGH -#define EI_DIST_HIGH 5 /* R4 and later */ -#define EI_DIST_LOW 1 /* R3 and earlier */ +#define EI_DIST_HIGH EI_DIST_6 +#define EI_DIST_LOW EI_DIST_5 #endif #ifndef EPMD_PORT @@ -45,6 +48,7 @@ #ifndef EI_EPMD_ALIVE2_REQ #define EI_EPMD_ALIVE2_REQ 120 #define EI_EPMD_ALIVE2_RESP 121 +#define EI_EPMD_ALIVE2_X_RESP 118 #define EI_EPMD_PORT2_REQ 122 #define EI_EPMD_PORT2_RESP 119 #define EI_EPMD_STOP_REQ 's' diff --git a/lib/erl_interface/src/epmd/epmd_port.c b/lib/erl_interface/src/epmd/epmd_port.c index 492c3fb3aa..1ea2f7b9df 100644 --- a/lib/erl_interface/src/epmd/epmd_port.c +++ b/lib/erl_interface/src/epmd/epmd_port.c @@ -25,16 +25,6 @@ #include <windows.h> #include <winbase.h> -#elif VXWORKS -#include <vxWorks.h> -#include <ifLib.h> -#include <sockLib.h> -#include <inetLib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> - #else #include <unistd.h> #include <sys/types.h> @@ -114,9 +104,6 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive, int err; ssize_t dlen; unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms; -#if defined(VXWORKS) - char ntoabuf[32]; -#endif if (len > sizeof(buf) - 3) { @@ -144,17 +131,8 @@ static int ei_epmd_r4_port (struct in_addr *addr, const char *alive, 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_r4_port", - "-> PORT2_REQ alive=%s ip=%s",alive,ntoabuf); - } -#else EI_TRACE_CONN2("ei_epmd_r4_port", "-> PORT2_REQ alive=%s ip=%s",alive,inet_ntoa(*addr)); -#endif dlen = (ssize_t) 2; err = ei_read_fill_t__(fd, buf, &dlen, tmo); diff --git a/lib/erl_interface/src/epmd/epmd_publish.c b/lib/erl_interface/src/epmd/epmd_publish.c index 20b8e867e8..f2c7abbd1a 100644 --- a/lib/erl_interface/src/epmd/epmd_publish.c +++ b/lib/erl_interface/src/epmd/epmd_publish.c @@ -25,16 +25,6 @@ #include <windows.h> #include <winbase.h> -#elif VXWORKS -#include <vxWorks.h> -#include <ifLib.h> -#include <sockLib.h> -#include <inetLib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> - #else #include <unistd.h> #include <sys/types.h> @@ -68,7 +58,8 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms) int nlen = strlen(alive); int len = elen + nlen + 13; /* hard coded: be careful! */ int n; - int err, res, creation; + int err, response, res; + unsigned creation; ssize_t dlen; unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms; @@ -124,8 +115,10 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms) /* Don't close fd here! It keeps us registered with epmd */ s = buf; - if (((res=get8(s)) != EI_EPMD_ALIVE2_RESP)) { /* response */ - EI_TRACE_ERR1("ei_epmd_r4_publish","<- unknown (%d)",res); + response = get8(s); + if (response != EI_EPMD_ALIVE2_RESP && + response != EI_EPMD_ALIVE2_X_RESP) { + EI_TRACE_ERR1("ei_epmd_r4_publish","<- unknown (%d)",response); EI_TRACE_ERR0("ei_epmd_r4_publish","-> CLOSE"); ei_close__(fd); erl_errno = EIO; @@ -141,18 +134,21 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms) return -1; } - creation = get16be(s); + if (response == EI_EPMD_ALIVE2_RESP) + creation = get16be(s); + else /* EI_EPMD_ALIVE2_X_RESP */ + creation = get32be(s); EI_TRACE_CONN2("ei_epmd_r4_publish", - " result=%d (ok) creation=%d",res,creation); - - /* probably should save fd so we can close it later... */ - /* epmd_saveconn(OPEN,fd,alive); */ + " result=%d (ok) creation=%u",res,creation); - /* return the creation number, for no good reason */ - /* return creation;*/ + /* + * Would be nice to somehow use the nice "unique" creation value + * received here from epmd instead of using the crappy one + * passed (already) to ei_connect_init. + */ - /* no - return the descriptor */ + /* return the descriptor */ return fd; } diff --git a/lib/erl_interface/src/epmd/epmd_unpublish.c b/lib/erl_interface/src/epmd/epmd_unpublish.c index c112f74147..592cc0371e 100644 --- a/lib/erl_interface/src/epmd/epmd_unpublish.c +++ b/lib/erl_interface/src/epmd/epmd_unpublish.c @@ -22,16 +22,6 @@ #include <windows.h> #include <winbase.h> -#elif VXWORKS -#include <vxWorks.h> -#include <ifLib.h> -#include <sockLib.h> -#include <inetLib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> - #else #include <unistd.h> #include <sys/types.h> diff --git a/lib/erl_interface/src/legacy/global_names.c b/lib/erl_interface/src/global/global_names.c index ee808620fb..bcbe740223 100644 --- a/lib/erl_interface/src/legacy/global_names.c +++ b/lib/erl_interface/src/global/global_names.c @@ -24,8 +24,8 @@ #include "eisend.h" #include "eirecv.h" #include "ei_connect_int.h" -#include "erl_interface.h" -#include "erl_connect.h" +#include "ei.h" +#include "ei_connect.h" #define GLOBALNAMEBUF (16*1024) /* not very small actually */ @@ -36,14 +36,14 @@ * caller can make one call to free(). */ /* global:registered_names() -> [name1,name2,...] */ -char **erl_global_names(int fd, int *count) +char **ei_global_names(ei_cnode *ec, int fd, int *count) { char buf[GLOBALNAMEBUF]; char *bufp=buf; char tmpbuf[64]; int size = 0; int index = 0; - erlang_pid *self = erl_self(); + erlang_pid *self = ei_self(ec); erlang_msg msg; int i; int version; diff --git a/lib/erl_interface/src/legacy/global_register.c b/lib/erl_interface/src/global/global_register.c index 4cb6d8071f..c260ce091c 100644 --- a/lib/erl_interface/src/legacy/global_register.c +++ b/lib/erl_interface/src/global/global_register.c @@ -22,15 +22,14 @@ #include "eiext.h" #include "eisend.h" #include "eirecv.h" -#include "erl_interface.h" +#include "ei.h" -int erl_global_register(int fd, const char *name, ETERM *pid) +int ei_global_register(int fd, const char *name, erlang_pid *self) { char buf[EISMALLBUF]; char *bufp=buf; char tmpbuf[64]; int index = 0; - erlang_pid self; erlang_msg msg; int needlink, needatom, needmonitor; int arity; @@ -38,24 +37,19 @@ int erl_global_register(int fd, const char *name, ETERM *pid) int msglen; int i; - /* get that pid into a better format */ - if (!erl_encode(pid,(unsigned char*)buf)) return -1; - if (ei_decode_version(buf,&index,&version) - || ei_decode_pid(buf,&index,&self)) return -1; - /* set up rpc arguments */ /* { PidFrom, { call, Mod, Fun, Args, user }} */ index = 0; ei_encode_version(buf,&index); ei_encode_tuple_header(buf,&index,2); - ei_encode_pid(buf,&index,&self); /* PidFrom */ + ei_encode_pid(buf,&index,self); /* PidFrom */ ei_encode_tuple_header(buf,&index,5); ei_encode_atom(buf,&index,"call"); /* call */ ei_encode_atom(buf,&index,"global"); /* Mod */ ei_encode_atom(buf,&index,"register_name_external"); /* Fun */ ei_encode_list_header(buf,&index,3); /* Args: [ name, self(), cnode ] */ ei_encode_atom(buf,&index,name); - ei_encode_pid(buf,&index,&self); + ei_encode_pid(buf,&index,self); ei_encode_tuple_header(buf,&index,2); ei_encode_atom(buf,&index,"global"); /* special "resolve" treatment */ ei_encode_atom(buf,&index,"cnode"); /* i.e. we get a SEND when conflict */ @@ -63,7 +57,7 @@ int erl_global_register(int fd, const char *name, ETERM *pid) ei_encode_atom(buf,&index,"user"); /* user */ /* make the rpc call */ - if (ei_send_reg_encoded(fd,&self,"rex",buf,index)) return -1; + 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 = needmonitor = 1; diff --git a/lib/erl_interface/src/legacy/global_unregister.c b/lib/erl_interface/src/global/global_unregister.c index 27f68670ca..ee785a2abd 100644 --- a/lib/erl_interface/src/legacy/global_unregister.c +++ b/lib/erl_interface/src/global/global_unregister.c @@ -23,18 +23,18 @@ #include "eisend.h" #include "eirecv.h" #include "ei_connect_int.h" -#include "erl_interface.h" -#include "erl_connect.h" +#include "ei_connect.h" +#include "ei.h" /* remove the association between name and its pid */ /* global:unregister_name(name) -> ok */ -int erl_global_unregister(int fd, const char *name) +int ei_global_unregister(ei_cnode *ec, int fd, const char *name) { char buf[EISMALLBUF]; char *bufp=buf; char tmpbuf[64]; int index = 0; - erlang_pid *self = erl_self(); + erlang_pid *self = ei_self(ec); erlang_msg msg; int i; int version,arity,msglen; diff --git a/lib/erl_interface/src/legacy/global_whereis.c b/lib/erl_interface/src/global/global_whereis.c index 13c4c93ca7..afedc98030 100644 --- a/lib/erl_interface/src/legacy/global_whereis.c +++ b/lib/erl_interface/src/global/global_whereis.c @@ -24,23 +24,22 @@ #include "eisend.h" #include "eirecv.h" #include "ei_connect_int.h" -#include "erl_interface.h" -#include "erl_connect.h" +#include "ei.h" +#include "ei_connect.h" /* return the ETERM pid corresponding to name. If caller * provides non-NULL node, nodename will be returned there */ /* global:whereis_name(name) -> pid */ -ETERM *erl_global_whereis(int fd, const char *name, char *node) +int ei_global_whereis(ei_cnode *ec, int fd, const char *name, erlang_pid* pid, char *node) { char buf[EISMALLBUF]; char *bufp=buf; char tmpbuf[64]; int index = 0; - erlang_pid *self = erl_self(); + erlang_pid *self = ei_self(ec); erlang_pid epid; - ETERM *opid; erlang_msg msg; int i; int version,arity,msglen; @@ -60,7 +59,7 @@ ETERM *erl_global_whereis(int fd, const char *name, char *node) ei_encode_atom(buf,&index,"user"); /* user */ /* make the rpc call */ - if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return NULL; + if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return -1; while (1) { index = EISMALLBUF; @@ -68,7 +67,7 @@ ETERM *erl_global_whereis(int fd, const char *name, char *node) else break; } - if (i != ERL_SEND) return NULL; + if (i != ERL_SEND) return -1; /* expecting { rex, pid } */ index = 0; @@ -78,24 +77,18 @@ ETERM *erl_global_whereis(int fd, const char *name, char *node) || ei_decode_atom(buf,&index,tmpbuf) || strcmp(tmpbuf,"rex") || ei_decode_pid(buf,&index,&epid)) - return NULL; /* bad response from other side */ - - /* put the pid into a format for the caller */ - index = 0; - ei_encode_pid(buf,&index,&epid); - opid = erl_decode((unsigned char*)buf); + return -1; /* bad response from other side */ /* extract the nodename for the caller */ if (node) { - char* node_str = ERL_PID_NODE(opid); + char* node_str = epid.node; if (node_str) { strcpy(node, node_str); } else { - erl_free_term(opid); - return NULL; + return -1; } } - - return opid; + *pid = epid; + return 0; } diff --git a/lib/erl_interface/src/legacy/decode_term.c b/lib/erl_interface/src/legacy/decode_term.c deleted file mode 100644 index 72bacc3123..0000000000 --- a/lib/erl_interface/src/legacy/decode_term.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#include "eidef.h" -#include "eiext.h" -#include "putget.h" -#include "erl_interface.h" - -/* - * This file is actually part of the erl_interface library, - * not the newer 'ei' library. The header file is still in "ei.h" - */ - -/* FIXME: is this to be completed? */ - -#if (0) -int ei_decode_term(const char *buf, int *index, void *t) -{ - const char *s = buf + *index; - const char *s0 = s; - - if (t) { - ETERM *tmp; - - /* this decodes and advances s */ - if (!(tmp = erl_decode_buf((unsigned char **)&s))) return -1; - - *(ETERM **)t = tmp; - *index += s - s0; - - return 0; - } - else { - int tmpindex = *index; - long ttype; - int arity; - int i; - - /* these are all the external types */ - switch ((ttype = get8(s))) { - case ERL_SMALL_INTEGER_EXT: - case ERL_INTEGER_EXT: - case ERL_SMALL_BIG_EXT: - 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: - return ei_decode_atom(buf,index,NULL); - - case ERL_REFERENCE_EXT: - case ERL_NEW_REFERENCE_EXT: - return ei_decode_ref(buf,index,NULL); - - case ERL_PORT_EXT: - return ei_decode_port(buf,index,NULL); - - case ERL_PID_EXT: - return ei_decode_pid(buf,index,NULL); - - case ERL_SMALL_TUPLE_EXT: - case ERL_LARGE_TUPLE_EXT: - if (ei_decode_tuple_header(buf,index,&arity) < 0) - return -1; - - for (i=0; i<arity; i++) { - if (ei_decode_term(buf,index,NULL)) { - /* restore possibly changed index before returning */ - *index = tmpindex; - return -1; - } - } - return 0; - - case ERL_STRING_EXT: - return ei_decode_string(buf,index,NULL); - - case ERL_LIST_EXT: - case ERL_NIL_EXT: - if (ei_decode_list_header(buf,index,&arity) < 0) - return -1; - - if (arity) { - for (i=0; i<arity; i++) { - if (ei_decode_term(buf,index,NULL) < 0) { - /* restore possibly changed index before returning */ - *index = tmpindex; - return -1; - } - } - if (ei_decode_list_header(buf,index,&arity) < 0) { - *index = tmpindex; - return -1; - } - } - return 0; - - case ERL_BINARY_EXT: - return ei_decode_binary(buf,index,NULL,NULL); - - case ERL_LARGE_BIG_EXT: - default: - break; - } - } - - return -1; -} -#else -int ei_decode_term(const char *buf, int *index, void *t) -{ - const char *s = buf + *index; - const char *s0 = s; - ETERM *tmp; - - /* this decodes and advances s */ - if (!(tmp = erl_decode_buf((unsigned char **)&s))) return -1; - - if (t) *(ETERM **)t = tmp; - else erl_free_term(tmp); - - *index += s - s0; - - return 0; -} -#endif diff --git a/lib/erl_interface/src/legacy/encode_term.c b/lib/erl_interface/src/legacy/encode_term.c deleted file mode 100644 index df740ab487..0000000000 --- a/lib/erl_interface/src/legacy/encode_term.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#include "eidef.h" -#include "eiext.h" -#include "putget.h" -#include "ei_x_encode.h" -#include "erl_interface.h" -#include "erl_marshal.h" - -/* FIXME: depends on old erl_interface */ - -int ei_x_encode_term(ei_x_buff* x, void* t) -{ - int i = x->index; - ei_encode_term(NULL, &i, t); - if (!x_fix_buff(x, i)) - return -1; - return ei_encode_term(x->buff, &x->index, t); -} - -int ei_encode_term(char *buf, int *index, void *t) -{ - char *s = buf + *index; - char *s0 = s; - - if (!buf) s += erl_term_len(t) -1; /* -1 for version */ - else { - /* this encodes all but the version at the start */ - /* and it will move s forward the right number of bytes */ - if (erl_encode_it(t,(unsigned char **)&s, 5)) return -1; - } - - *index += s - s0; - - return 0; -} - diff --git a/lib/erl_interface/src/legacy/erl_config.h b/lib/erl_interface/src/legacy/erl_config.h deleted file mode 100644 index fb72169f23..0000000000 --- a/lib/erl_interface/src/legacy/erl_config.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_CONFIG_H -#define _ERL_CONFIG_H - -#endif /* _ERL_CONFIG_H */ diff --git a/lib/erl_interface/src/legacy/erl_connect.c b/lib/erl_interface/src/legacy/erl_connect.c deleted file mode 100644 index e2fd4611c0..0000000000 --- a/lib/erl_interface/src/legacy/erl_connect.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Purpose: Connect to any node at any host. - */ - -/*************************************************************************** - * - * 'erl_interface' node connection handling is to use 'ei' for all - * operations without access to the internal structure of saved data, - * e.i. it should use the public interface functions. The connection - * handling can be seen as a restricted node interface where only one - * node can be used in one operating system process. - * - ***************************************************************************/ - -#include "eidef.h" - -#include <stdlib.h> -#include <sys/types.h> -#include <fcntl.h> - -#ifdef __WIN32__ -#include <winsock2.h> -#include <windows.h> -#include <winbase.h> - -#elif VXWORKS -#include <vxWorks.h> -#include <hostLib.h> -#include <selectLib.h> -#include <ifLib.h> -#include <sockLib.h> -#include <taskLib.h> -#include <inetLib.h> - -#include <unistd.h> -#include <sys/types.h> -#include <sys/times.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <timers.h> - -#include "erl_error.h" - -#else /* some other unix */ -#include <unistd.h> -#include <sys/types.h> -#include <sys/times.h> - -#if TIME_WITH_SYS_TIME -# include <sys/time.h> -# include <time.h> -#else -# if HAVE_SYS_TIME_H -# include <sys/time.h> -# else -# include <time.h> -# endif -#endif - -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <sys/utsname.h> /* for gen_challenge (NEED FIX?) */ -#endif - -/* common includes */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -/* FIXME include less */ -#include "erl_interface.h" -#include "erl_connect.h" -#include "erl_eterm.h" -#include "erl_malloc.h" -#include "putget.h" -#include "ei.h" -#include "ei_connect_int.h" -#include "ei_locking.h" -#include "ei_epmd.h" -#include "ei_internal.h" - -/* rpc_from() uses a buffer this size */ -#ifndef MAX_RECEIVE_BUF -#define MAX_RECEIVE_BUF 32*1024 -#endif - -/* This is the global state of the old erl_* API */ - -static ei_cnode erl_if_ec; - -/*************************************************************************** - * - * API: erl_connect_init() - * API: erl_connect_xinit() - * - * Returns 1 on success and 0 on failure. - * Not documented to set erl_errno. - * - ***************************************************************************/ - -int erl_connect_init(int this_node_number, char *cookie, short creation) -{ - char nn[MAXATOMLEN]; - - sprintf(nn, "c%d", this_node_number); - - return ei_connect_init(&erl_if_ec, nn, cookie, creation) == 0; -} - -/* FIXME documented to use struct in_addr as addr */ - -int erl_connect_xinit(char *thishostname, - char *thisalivename, - char *thisnodename, - struct in_addr *thisipaddr, - char *cookie, - short creation) -{ - return ei_connect_xinit(&erl_if_ec, thishostname, thisalivename, - thisnodename, thisipaddr, cookie, creation) >= 0; -} - -/*************************************************************************** - * - * API: erl_connect() - * API: erl_xconnect() - * - * Set up a connection to a given Node, and interchange hand shake - * messages with it. - * - * Returns valid file descriptor on success and < 0 on failure. - * Set erl_errno to EHOSTUNREACH, ENOMEM, EIO or errno from socket(2) - * or connect(2). - * - ***************************************************************************/ - -int erl_connect(char *nodename) -{ - int res = ei_connect(&erl_if_ec, nodename); - if (res < 0) erl_errno = EIO; - return res; -} - -/* FIXME documented to use struct in_addr as addr */ - -int erl_xconnect(Erl_IpAddr addr, char *alivename) -{ - return ei_xconnect(&erl_if_ec, addr, alivename); -} - - -/*************************************************************************** - * - * API: erl_close_connection() - * - * Returns 0 on success and -1 on failure. - * - ***************************************************************************/ - -int erl_close_connection(int fd) -{ - return ei_close_connection(fd); -} - -/* - * Accept and initiate a connection from another - * Erlang node. Return a file descriptor at success, - * otherwise -1; - */ -int erl_accept(int lfd, ErlConnect *conp) -{ - return ei_accept(&erl_if_ec, lfd, conp); -} - - -/* Receives a message from an Erlang socket. - * If the message was a TICK it is immediately - * answered. Returns: ERL_ERROR, ERL_TICK or - * the number of bytes read. - */ -int erl_receive(int s, unsigned char *bufp, int bufsize) -{ - return ei_receive(s, bufp, bufsize); -} - -/* - * Send an Erlang message to a registered process - * at the Erlang node, connected with a socket. - */ -int erl_reg_send(int fd, char *server_name, ETERM *msg) -{ - ei_x_buff x; - int r; - - if (ei_x_new_with_version(&x) < 0) { - erl_errno = ENOMEM; - return 0; - } - if (ei_x_encode_term(&x, msg) < 0) { - erl_errno = EINVAL; - r = 0; - } else { - r = ei_reg_send(&erl_if_ec, fd, server_name, x.buff, x.index); - } - ei_x_free(&x); - return r == 0; -} - -/* - * Sends an Erlang message to a process at an Erlang node - */ -int erl_send(int fd, ETERM *to ,ETERM *msg) -{ - erlang_pid topid; - ei_x_buff x; - int r; - - ei_x_new_with_version(&x); - ei_x_encode_term(&x, msg); - /* make the to-pid */ - if (!ERL_IS_PID(to)) { - ei_x_free(&x); - erl_errno = EINVAL; - return -1; - } - - if (to->uval.pidval.node.latin1) { - strcpy(topid.node, to->uval.pidval.node.latin1); - } - else { - strcpy(topid.node, to->uval.pidval.node.utf8); - } - topid.num = ERL_PID_NUMBER(to); - topid.serial = ERL_PID_SERIAL(to); - topid.creation = ERL_PID_CREATION(to); - r = ei_send(fd, &topid, x.buff, x.index); - ei_x_free(&x); - return r == 0; -} - -static int erl_do_receive_msg(int fd, ei_x_buff* x, ErlMessage* emsg) -{ - erlang_msg msg; - - int r; - msg.from.node[0] = msg.to.node[0] = msg.toname[0] = '\0'; - r = ei_do_receive_msg(fd, 0, &msg, x, 0); - - if (r == ERL_MSG) { - int index = 0; - emsg->type = msg.msgtype; - - /* - We can't call ei_decode_term for cases where there are no - data following the type information. If there are other - types added later where there are data this case has to be - extended. - */ - - switch (msg.msgtype) { - case ERL_SEND: - case ERL_REG_SEND: - case ERL_EXIT: - case ERL_EXIT2: - if (ei_decode_term(x->buff, &index, &emsg->msg) < 0) - r = ERL_ERROR; - break; - default: - emsg->msg = NULL; /* Not needed but may avoid problems for unsafe caller */ - break; - } - } else - emsg->msg = NULL; - if (msg.from.node[0] != '\0') - emsg->from = erl_mk_pid(msg.from.node, msg.from.num, msg.from.serial, msg.from.creation); - else - emsg->from = NULL; - if (msg.to.node[0] != '\0') - emsg->to = erl_mk_pid(msg.to.node, msg.to.num, msg.to.serial, msg.to.creation); - else - emsg->to = NULL; - strcpy(emsg->to_name, msg.toname); - return r; -} - -int erl_receive_msg(int fd, unsigned char *buf, int bufsize, ErlMessage *emsg) -{ - ei_x_buff x; - int r; - - ei_x_new(&x); - r = erl_do_receive_msg(fd, &x, emsg); - /* FIXME what is this about? */ - if (bufsize > x.index) - bufsize = x.index; - memcpy(buf, x.buff, bufsize); - ei_x_free(&x); - return r; -} - -int erl_xreceive_msg(int fd, unsigned char **buf, int *bufsize, - ErlMessage *emsg) -{ - ei_x_buff x; - int r; - - ei_x_new(&x); - r = erl_do_receive_msg(fd, &x, emsg); - if (*bufsize < x.index) - *buf = erl_realloc(*buf, x.index); - *bufsize = x.index; - memcpy(*buf, x.buff, *bufsize); - ei_x_free(&x); - return r; -} - -/* - * The RPC consists of two parts, send and receive. - * Here is the send part ! - * { PidFrom, { call, Mod, Fun, Args, user }} - */ -/* - * Now returns non-negative number for success, negative for failure. - */ -int erl_rpc_to(int fd, char *mod, char *fun, ETERM *args) -{ - int r; - ei_x_buff x; - - ei_x_new(&x); - ei_x_encode_term(&x, args); - r = ei_rpc_to(&erl_if_ec, fd, mod, fun, x.buff, x.index); - ei_x_free(&x); - return r; -} /* rpc_to */ - - /* - * And here is the rpc receiving part. A negative - * timeout means 'infinity'. Returns either of: ERL_MSG, - * ERL_TICK, ERL_ERROR or ERL_TIMEOUT. -*/ -int erl_rpc_from(int fd, int timeout, ErlMessage *emsg) -{ - fd_set readmask; - struct timeval tv; - struct timeval *t = NULL; - unsigned char rbuf[MAX_RECEIVE_BUF]; - - if (timeout >= 0) { - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - t = &tv; - } - - FD_ZERO(&readmask); - FD_SET(fd,&readmask); - - switch (select(fd+1, &readmask, NULL, NULL, t)) { - case -1: - erl_errno = EIO; - return ERL_ERROR; - case 0: - erl_errno = ETIMEDOUT; - return ERL_TIMEOUT; - default: - if (FD_ISSET(fd, &readmask)) - return erl_receive_msg(fd, rbuf, MAX_RECEIVE_BUF, emsg); - else { - erl_errno = EIO; - return ERL_ERROR; - } - } -} /* rpc_from */ - -/* - * A true RPC. It return a NULL pointer - * in case of failure, otherwise a valid - * (ETERM *) pointer containing the reply - */ -ETERM *erl_rpc(int fd, char *mod, char *fun, ETERM *args) -{ - int i; - ETERM *ep; - ErlMessage emsg; - - if (erl_rpc_to(fd, mod, fun, args) < 0) { - return NULL; } - while ((i=erl_rpc_from(fd, ERL_NO_TIMEOUT, &emsg)) == ERL_TICK); - - if (i == ERL_ERROR) return NULL; - - ep = erl_element(2,emsg.msg); /* {RPC_Tag, RPC_Reply} */ - erl_free_term(emsg.msg); - erl_free_term(emsg.to); - return ep; -} /* rpc */ - - -/* - ** Handshake - */ - -int erl_publish(int port) -{ - return ei_publish(&erl_if_ec, port); -} - -int erl_unpublish(const char *alive) -{ - return ei_unpublish_tmo(alive,0); -} - -erlang_pid *erl_self(void) -{ - return ei_self(&erl_if_ec); -} - -const char *erl_thisnodename(void) -{ - return ei_thisnodename(&erl_if_ec); -} - -const char *erl_thishostname(void) -{ - return ei_thishostname(&erl_if_ec); -} - -const char *erl_thisalivename(void) -{ - return ei_thisalivename(&erl_if_ec); -} - -const char *erl_thiscookie(void) -{ - return ei_thiscookie(&erl_if_ec); -} - -short erl_thiscreation(void) -{ - return ei_thiscreation(&erl_if_ec); -} diff --git a/lib/erl_interface/src/legacy/erl_error.c b/lib/erl_interface/src/legacy/erl_error.c deleted file mode 100644 index a3bbfbc58f..0000000000 --- a/lib/erl_interface/src/legacy/erl_error.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Function: Some nice error routines taken from: - * "Advanced Programming in the UNIX Environment", - * by W.Richard Stevens - * - * void erl_err_sys(const char *fmt, ... ) fatal, sys-error - * void erl_err_ret(const char *fmt, ... ) non-fatal, sys-error - * void erl_err_quit(const char *fmt, ...) fatal, non-sys-error - * void erl_err_msg(const char *fmt, ... ) non-fatal, non-sys-error - */ - -#include <stdio.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> - -#ifdef VRTX /* What's VRIX? [sverkerw] */ -#define __READY_EXTENSIONS__ -#endif -#include <errno.h> - -#if defined(VXWORKS) -#include <taskLib.h> -#include <taskVarLib.h> -#endif - -#include "eidef.h" -#include "erl_interface.h" -#include "erl_error.h" - -/* Forward */ -static void err_doit(int, const char*, va_list); -/* __attribute__ ((format (printf, 2, 0)))*/ - -/* - * Some thoughts on flushing stdout/stderr: - * - * The defaults are reasonable (linebuffered stdout, unbuffered - * stderr). If they are in effect (the user neither knows nor cares), - * there's no need to flush. - * - * If the user changes these defaults (and knows what he's doing, so - * he knows and cares) we shouldn't surprise him by - * second-guessing. So there's a need to not flush. - * - * If the user doesn't know what he's doing, he's hosed anyway. - */ - -/* Fatal error related to a system call. - * Print a message and terminate. - */ -void erl_err_sys(const char *fmt, ... ) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(1, fmt, ap); - va_end(ap); - exit(1); -} /* erl_err_sys */ - -/* Nonfatal error related to a system call. - * Print a message and return - */ -void erl_err_ret(const char *fmt, ... ) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(1, fmt, ap); - va_end(ap); - return; -} /* erl_err_ret */ - -/* Nonfatal error unrelated to a system call. - * Print a message and return - */ -void erl_err_msg(const char *fmt, ... ) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(0, fmt, ap); - va_end(ap); - return; -} /* erl_err_msg */ - -/* Fatal error unrelated to a system call. - * Print a message and terminate - */ -void erl_err_quit(const char *fmt, ... ) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(0, fmt, ap); - va_end(ap); - exit(1); -} /* erl_err_quit */ - - - -/* - * For example on SunOS we don't have the ANSI C strerror. - * - * maybe move to a convenince lib [sverkerw] - */ -#ifndef HAVE_STRERROR - -/* FIXME: move to configure */ -/* CONFIG: probe for sys_nerr/_sys_nerr */ -extern int sys_nerr; - -/* CONFIG: probe for sys_errlist/_sys_errlist and maybe for const-ness */ -#ifdef FREEBSD -extern const char * const sys_errlist[]; -#else -extern char * sys_errlist[]; -#endif - -/* Should be in string.h */ -/* Is supposed to return 'char *' (no const-ness in ANSI's prototype), - but if you rewrite the returned string in place you deserve to - lose. */ -static const char *strerror(int errnum) -{ - if (errnum >= 0 && errnum < sys_nerr) { - return sys_errlist[errnum]; - } else { - /* Enough buffer for 64 bits of error. It should last a while. */ - /* FIXME problem for threaded ? */ - static char b[] = "(error -9223372036854775808)"; - sprintf(b, "(error %d)", errnum); - buf[sizeof(b)-1] = '\0'; - return b; - } -} -#endif /* !HAVE_STRERROR */ - - -/* Print a message and return to caller. - * Caller specifies "errnoflag". - */ -static void err_doit(int errnoflag, const char *fmt, va_list ap) -{ -#ifndef NO_ERR_MSG - int errno_save; - - errno_save = errno; - - vfprintf(stderr, fmt, ap); - if (errnoflag) - { - fputs(": ", stderr); - fputs(strerror(errno_save), stderr); - } - fputs("\n", stderr); -#endif - - return; -} /* err_doit */ - diff --git a/lib/erl_interface/src/legacy/erl_error.h b/lib/erl_interface/src/legacy/erl_error.h deleted file mode 100644 index 0cce083ae7..0000000000 --- a/lib/erl_interface/src/legacy/erl_error.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_ERROR_H -#define _ERL_ERROR_H - -/* Initialize thread/task-safe erl_errno handling */ -void erl_init_errno(void); - -#endif /* _ERL_ERROR_H */ diff --git a/lib/erl_interface/src/legacy/erl_eterm.c b/lib/erl_interface/src/legacy/erl_eterm.c deleted file mode 100644 index 7ecea83b1a..0000000000 --- a/lib/erl_interface/src/legacy/erl_eterm.c +++ /dev/null @@ -1,1413 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2017. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Purpose: Representation of Erlang terms. - */ - -#include "eidef.h" - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#if defined(HAVE_ISFINITE) -#include <math.h> -#endif - -#include "ei_locking.h" -#include "ei_resolve.h" -#include "erl_interface.h" -#include "erl_eterm.h" -#include "erl_malloc.h" -#include "erl_marshal.h" -#include "erl_error.h" -#include "erl_internal.h" -#include "ei_internal.h" -#include "putget.h" - -#define ERL_IS_BYTE(x) (ERL_IS_INTEGER(x) && (ERL_INT_VALUE(x) & ~0xFF) == 0) - -/* FIXME use unsigned char, or uint8 for buffers, cast (int) really needed? */ - -static void iolist_to_buf(const ETERM* term, char** bufp); -static char* strsave(const char *src); - -/*************************************************************************** - * - * API: erl_init() - * - * Not documented to set erl_errno. - * - ***************************************************************************/ - -/* all initialisation of erl_interface modules should be called from here */ -/* order is important: erl_malloc and erl_resolve depend on ei_locking */ -/* NOTE: don't call this directly - please use erl_init() macro defined - in ei_locking.h! */ -void erl_init(void *hp,long heap_size) -{ - erl_init_malloc(hp, heap_size); - erl_init_marshal(); - (void) ei_init(); -} - -void erl_set_compat_rel(unsigned rel) -{ - ei_set_compat_rel(rel); -} - -/* - * Create an INTEGER. Depending on its value it - * may end up as a BigNum. - */ -ETERM *erl_mk_int (int i) -{ - ETERM *ep; - - ep = erl_alloc_eterm(ERL_INTEGER); - ERL_COUNT(ep) = 1; - ERL_INT_VALUE(ep) = i; - return ep; -} - -ETERM *erl_mk_longlong (long long i) -{ - ETERM *ep; - - ep = erl_alloc_eterm(ERL_LONGLONG); - ERL_COUNT(ep) = 1; - ERL_LL_VALUE(ep) = i; - return ep; -} - -/* - * Create an UNSIGNED INTEGER. Depending on its - * value it may end up as a BigNum. - */ - -ETERM *erl_mk_uint (unsigned int u) -{ - ETERM *ep; - - ep = erl_alloc_eterm(ERL_U_INTEGER); - ERL_COUNT(ep) = 1; - ERL_INT_UVALUE(ep) = u; - return ep; -} - -ETERM *erl_mk_ulonglong (unsigned long long i) -{ - ETERM *ep; - - ep = erl_alloc_eterm(ERL_U_LONGLONG); - ERL_COUNT(ep) = 1; - ERL_LL_UVALUE(ep) = i; - return ep; -} - -/* - * Create a FLOAT. - */ -ETERM *erl_mk_float (double d) -{ - ETERM *ep; - -#if defined(HAVE_ISFINITE) - /* Erlang does not handle Inf and NaN, so we return an error - * rather than letting the Erlang VM complain about a bad external - * term. */ - if(!isfinite(d)) { - return NULL; - } -#endif - - ep = erl_alloc_eterm(ERL_FLOAT); - ERL_COUNT(ep) = 1; - ERL_FLOAT_VALUE(ep) = d; - return ep; -} - -/* - * Create an ATOM - */ -ETERM *erl_mk_atom (const char *s) -{ - ETERM *ep; - - /* ASSERT(s != NULL); */ - if (!s) return NULL; - - ep = erl_alloc_eterm(ERL_ATOM); - ERL_COUNT(ep) = 1; - if (erl_atom_init_latin1(&ep->uval.aval.d, s) == NULL) { - erl_free_term(ep); - erl_errno = ENOMEM; - return NULL; - } - return ep; -} - -char* erl_atom_ptr_latin1(Erl_Atom_data* a) -{ - if (a->latin1 == NULL) { - erlang_char_encoding enc; - a->lenL = utf8_to_latin1(NULL, a->utf8, a->lenU, a->lenU, &enc); - if (a->lenL < 0) { - a->lenL = 0; - return NULL; - } - if (enc == ERLANG_ASCII) { - a->latin1 = a->utf8; - } - else { - a->latin1 = malloc(a->lenL+1); - utf8_to_latin1(a->latin1, a->utf8, a->lenU, a->lenL, NULL); - a->latin1[a->lenL] = '\0'; - } - } - return a->latin1; -} - -char* erl_atom_ptr_utf8(Erl_Atom_data* a) -{ - if (a->utf8 == NULL) { - erlang_char_encoding enc; - a->lenU = latin1_to_utf8(NULL, a->latin1, a->lenL, a->lenL*2, &enc); - if (enc == ERLANG_ASCII) { - a->utf8 = a->latin1; - } - else { - a->utf8 = malloc(a->lenU + 1); - latin1_to_utf8(a->utf8, a->latin1, a->lenL, a->lenU, NULL); - a->utf8[a->lenU] = '\0'; - } - } - return a->utf8; -} - -int erl_atom_size_latin1(Erl_Atom_data* a) -{ - if (a->latin1 == NULL) { - erl_atom_ptr_latin1(a); - } - return a->lenL; -} -int erl_atom_size_utf8(Erl_Atom_data* a) -{ - if (a->utf8 == NULL) { - erl_atom_ptr_utf8(a); - } - return a->lenU; -} -char* erl_atom_init_latin1(Erl_Atom_data* a, const char* s) -{ - a->lenL = strlen(s); - if ((a->latin1 = strsave(s)) == NULL) - { - return NULL; - } - a->utf8 = NULL; - a->lenU = 0; - return a->latin1; -} - - -/* - * Given a string as input, creates a list. - */ -ETERM *erl_mk_string(const char *s) -{ - /* ASSERT(s != NULL); */ - if (!s) return NULL; - - return erl_mk_estring(s, strlen(s)); -} - -ETERM *erl_mk_estring(const char *s, int len) -{ - ETERM *ep; - int i; - - if ((!s) || (len < 0)) return NULL; - - /* - * ASSERT(s != NULL); - * ASSERT(len >= 0); - */ - - ep = erl_mk_empty_list(); - for (i = len-1; i >= 0; i--) { - ETERM* integer; - ETERM* cons; - - integer = erl_alloc_eterm(ERL_INTEGER); - ERL_COUNT(integer) = 1; - ERL_INT_VALUE(integer) = (unsigned char)s[i]; - - cons = erl_alloc_eterm(ERL_LIST); - ERL_COUNT(cons) = 1; - HEAD(cons) = integer; - TAIL(cons) = ep; - ep = cons; - } - return ep; -} - -/* - * Create a PID. - */ -ETERM *erl_mk_pid(const char *node, - unsigned int number, - unsigned int serial, - unsigned char creation) -{ - ETERM *ep; - - if (!node) return NULL; - /* ASSERT(node != NULL); */ - - ep = erl_alloc_eterm(ERL_PID); - ERL_COUNT(ep) = 1; - if (erl_atom_init_latin1(&ep->uval.pidval.node, node) == NULL) - { - erl_free_term(ep); - erl_errno = ENOMEM; - return NULL; - } - erl_mk_pid_helper(ep, number, serial, creation & 0x03); - return ep; -} - -void erl_mk_pid_helper(ETERM *ep, unsigned int number, - unsigned int serial, unsigned int creation) -{ - ERL_PID_NUMBER(ep) = number & 0x7fff; /* 15 bits */ - ERL_PID_SERIAL(ep) = serial & 0x1fff; /* 13 bits */ - ERL_PID_CREATION(ep) = creation; /* 32 bits */ -} - -/* - * Create a PORT. - */ -ETERM *erl_mk_port(const char *node, - unsigned int number, - unsigned char creation) -{ - ETERM *ep; - - if (!node) return NULL; - /* ASSERT(node != NULL); */ - - ep = erl_alloc_eterm(ERL_PORT); - ERL_COUNT(ep) = 1; - if (erl_atom_init_latin1(&ep->uval.portval.node, node) == NULL) - { - erl_free_term(ep); - erl_errno = ENOMEM; - return NULL; - } - erl_mk_port_helper(ep, number, creation); - return ep; -} - -void erl_mk_port_helper(ETERM* ep, unsigned number, unsigned int creation) -{ - ERL_PORT_NUMBER(ep) = number & 0x0fffffff; /* 18 bits */ - ERL_PORT_CREATION(ep) = creation; /* 32 bits */ -} - -/* - * Create any kind of reference. - */ -ETERM *__erl_mk_reference (ETERM* t, - const char *node, - size_t len, - unsigned int n[], - unsigned int creation) -{ - if (t == NULL) { - if (node == NULL) return NULL; - - t = erl_alloc_eterm(ERL_REF); - ERL_COUNT(t) = 1; - - if (erl_atom_init_latin1(&t->uval.refval.node, node) == NULL) - { - erl_free_term(t); - erl_errno = ENOMEM; - return NULL; - } - } - ERL_REF_LEN(t) = len; - ERL_REF_NUMBERS(t)[0] = n[0] & 0x3ffff; /* 18 bits */ - ERL_REF_NUMBERS(t)[1] = n[1]; - ERL_REF_NUMBERS(t)[2] = n[2]; - ERL_REF_CREATION(t) = creation; /* 32 bits */ - - return t; -} - -/* - * Create a REFERENCE. - */ -ETERM *erl_mk_ref (const char *node, - unsigned int number, - unsigned char creation) -{ - unsigned int n[3] = {0, 0, 0}; - n[0] = number; - return __erl_mk_reference(NULL, node, 1, n, creation); -} - -/* - * Create a long REFERENCE. - */ -ETERM * -erl_mk_long_ref (const char *node, - unsigned int n1, unsigned int n2, unsigned int n3, - unsigned char creation) -{ - unsigned int n[3] = {0, 0, 0}; - n[0] = n3; n[1] = n2; n[2] = n1; - return __erl_mk_reference(NULL, node, 3, n, creation); -} - -/* - * Create a BINARY. - */ -ETERM *erl_mk_binary (const char *b, int size) -{ - ETERM *ep; - - if ((!b) || (size < 0)) return NULL; - /* ASSERT(b != NULL); */ - - ep = erl_alloc_eterm(ERL_BINARY); - ERL_COUNT(ep) = 1; - ERL_BIN_SIZE(ep) = size; - ERL_BIN_PTR(ep) = (unsigned char *) erl_malloc(size); - memcpy(ERL_BIN_PTR(ep), b, size); - return ep; -} - -/* - * Create a TUPLE. For each element in the tuple - * bump its reference counter. - */ -ETERM *erl_mk_tuple (ETERM **arr,int size) -{ - ETERM *ep; - int i; - - if ((!arr) || (size < 0)) return NULL; - for (i=0; i<size; i++) if (!arr[i]) return NULL; - /* ASSERT(arr != NULL); */ - - ep = erl_alloc_eterm(ERL_TUPLE); - ERL_COUNT(ep) = 1; - ERL_TUPLE_SIZE(ep) = size; - ERL_TUPLE_ELEMS(ep) = (ETERM**) erl_malloc((size) * (sizeof(ETERM*))); - for (i = 0; i < size; i++) { - /* ASSERT(arr[i] != NULL); */ - ERL_COUNT(arr[i])++; - ERL_TUPLE_ELEMENT(ep, i) = arr[i]; - } - return ep; -} - -/* - * SET an ELEMENT in a TUPLE. Free the old element - * and bump the reference counter of the new one. - * Return 1 on success, otherwise 0. - */ -#if 0 -int erl_setelement (int ix, ETERM *ep, ETERM *vp) -{ - if ((!ep) || (!vp)) return 0; - /* ASSERT(ep != NULL); - * ASSERT(vp != NULL); - */ - - if ((ERL_TYPE(ep) == ERL_TUPLE) && (ix <= ERL_TUPLE_SIZE(ep))) { - erl_free_term(ERL_TUPLE_ELEMENT(ep, ix-1)); - ERL_TUPLE_ELEMENT(ep, ix-1) = vp; - ERL_COUNT(vp)++; - return 1; - } - erl_err_msg("<ERROR> erl_setelement: Bad type to setelement or out of range \n"); - return 0; -} -#endif - -/* - * Extract an ELEMENT from a TUPLE. Bump the - * reference counter on the extracted object. - */ -ETERM *erl_element (int ix, const ETERM *ep) -{ - if ((!ep) || (ix < 0)) return NULL; - /* - * ASSERT(ep != NULL); - * ASSERT(ix >= 0); - */ - - if ((ERL_TYPE(ep) == ERL_TUPLE) && (ix <= ERL_TUPLE_SIZE(ep))) { - ERL_COUNT(ERL_TUPLE_ELEMENT(ep, ix-1))++; - return ERL_TUPLE_ELEMENT(ep, ix-1); - } - else - return NULL; -} /* erl_element */ - -ETERM *erl_mk_empty_list(void) -{ - ETERM *ep; - - ep = erl_alloc_eterm(ERL_EMPTY_LIST); - ERL_COUNT(ep) = 1; - return ep; -} - -/* - * Construct a new list by CONS'ing a HEAD on - * to the TAIL. Bump the reference counter on - * the head and tail object. Note that we allow - * non-well formed lists to be created. - */ -ETERM *erl_cons(ETERM *hd, ETERM *tl) -{ - ETERM *ep; - - if ((!hd) || (!tl)) return NULL; - - /* - * ASSERT(hd != NULL); - * ASSERT(tl != NULL); - */ - - ep = erl_alloc_eterm(ERL_LIST); - ERL_COUNT(ep) = 1; - HEAD(ep) = hd; - TAIL(ep) = tl; - ERL_COUNT(hd)++; - ERL_COUNT(tl)++; - return ep; -} - -/* - * Extract the HEAD of a LIST. Bump the reference - * counter on the head object. - */ -ETERM *erl_hd (const ETERM *ep) -{ - if (!ep) return NULL; - /* ASSERT(ep != NULL); */ - - if (ERL_TYPE(ep) != ERL_LIST) { - return (ETERM *) NULL; - } - ERL_COUNT(ERL_CONS_HEAD(ep))++; - return ERL_CONS_HEAD(ep); -} - -/* - * Extract the TAIL of a LIST. Bump the reference - * counter on the tail object. - */ -ETERM *erl_tl (const ETERM *ep) -{ - ETERM *tl; - - if (!ep) return NULL; - /* ASSERT(ep != NULL); */ - - if (ERL_TYPE(ep) != ERL_LIST) { - return (ETERM *) NULL; - } - - tl = TAIL(ep); - ERL_COUNT(tl)++; - return tl; -} - -/* - * Create a LIST from an array of elements. Note that - * we create it from the last element in the array to - * the first. Also, note that we decrement the reference - * counter for each member in the list but the first one. - * This is done because of the use of erl_cons. - */ - -ETERM *erl_mk_list (ETERM **arr, int size) -{ - ETERM *ep; - int i; - - if ((!arr) || (size < 0)) return NULL; - for (i=0; i<size; i++) if (!arr[i]) return NULL; - - /* ASSERT(arr != NULL); */ - ep = erl_mk_empty_list(); - if (size > 0) { - ERL_COUNT(ep)--; - } - - for (i = size-1; i >= 0; i--) { - /* ASSERT(arr[i] != NULL); */ - ep = erl_cons(arr[i], ep); - if (i > 0) - ERL_COUNT(ep)--; /* Internal reference */ - } - return ep; -} - -/* - * Create an empty VARIABLE. - */ -ETERM *erl_mk_var(const char *s) -{ - ETERM *ep; - - if (!s) return NULL; - - /* ASSERT(s != NULL); */ - - ep = erl_alloc_eterm(ERL_VARIABLE); - ERL_COUNT(ep) = 1; - ERL_VAR_LEN(ep) = strlen(s); - if ((ERL_VAR_NAME(ep) = strsave(s)) == NULL) - { - erl_free_term(ep); - erl_errno = ENOMEM; - return NULL; - } - ERL_VAR_VALUE(ep) = (ETERM *) NULL; - return ep; -} - -/* - * Return the CONTENT of a VARIABLE with NAME. - * If the content is non-nil then bump its - * reference counter. - */ -ETERM *erl_var_content (const ETERM *ep, const char *name) -{ - int i; - ETERM *vp; - - if ((!ep) || (!name)) return NULL; - - /* ASSERT(ep != NULL); */ - - switch(ERL_TYPE(ep)) - { - case ERL_VARIABLE: - if (strcmp(ERL_VAR_NAME(ep), name) == 0) { - if ((vp = ERL_VAR_VALUE(ep)) != NULL) { - ERL_COUNT(vp)++; - return vp; - } - } - break; - - case ERL_LIST: - while (ep && (ERL_TYPE(ep) != ERL_EMPTY_LIST)) { - if ((vp = erl_var_content(HEAD(ep), name))) return vp; - ep = TAIL(ep); - } - break; - - case ERL_TUPLE: - for (i=0; i < ERL_TUPLE_SIZE(ep); i++) - if ((vp = erl_var_content(ERL_TUPLE_ELEMENT(ep, i), name))) - { - return vp; - } - break; - - default: - /* variables can't occur in other types */ - break; - } - - /* nothing found ! */ - return NULL; -} - -/* - * Return the SIZE of a TUPLE or a BINARY. - * At failure -1 is returned. - */ -int erl_size (const ETERM *ep) -{ - if (!ep) return -1; - - /* ASSERT(ep != NULL); */ - - switch (ERL_TYPE(ep)) { - case ERL_TUPLE: - return ERL_TUPLE_SIZE(ep); - - case ERL_BINARY: - return ERL_BIN_SIZE(ep); - - default: - return -1; - - } -} - -/* - * Return the LENGTH of a LIST. - * At failure -1 is returned (this include non-proper lists like [a|b]). - */ -int erl_length(const ETERM *ep) -{ - int n = 0; - - if (!ep) return -1; - /* ASSERT(ep != NULL); */ - - while (ERL_TYPE(ep) == ERL_LIST) { - n++; - ep = TAIL(ep); - } - - if (!ERL_IS_EMPTY_LIST(ep)) return -1; - - return n; -} - - -/*********************************************************************** - * I o l i s t f u n c t i o n s - * - * The following functions handles I/O lists. - * - * Informally, an I/O list is a deep list of characters and binaries, - * which can be sent to an Erlang port. - * - * Formally, in BNF, an I/O list is defined as: - * - * iolist ::= [] - * | Binary - * | [iohead | iolist] - * ; - * - * iohead ::= Binary - * | Byte (integer in the range [0..255]) - * | iolist - * ; - * - * Note that versions of Erlang/OTP prior to R2 had a slightly more - * restricted definition of I/O lists, in that the tail of a an I/O list - * was not allowed to be a binary. The erl_interface functions - * for I/O lists follows the more liberal rules described by the BNF - * description above. - ***********************************************************************/ - -/* - * This function converts an I/O list to a '\0' terminated C string. - * The I/O list must not contain any occurrences of the integer 0. - * - * The string will be in memory allocated by erl_malloc(). It is the - * responsibility of the caller to eventually call erl_free() to free - * the memory. - * - * Returns: NULL if the list was not an I/O list or contained - * the integer 0, otherwise a pointer to '\0' terminated string. - */ - -char* erl_iolist_to_string(const ETERM* term) -{ - ETERM* bin; - - if ((bin = erl_iolist_to_binary(term)) == NULL) { - return NULL; - } else { - char* result = NULL; - - if (memchr(ERL_BIN_PTR(bin), '\0', ERL_BIN_SIZE(bin)) == NULL) { - result = (char *) erl_malloc(ERL_BIN_SIZE(bin)+1); - memcpy(result, ERL_BIN_PTR(bin), ERL_BIN_SIZE(bin)); - result[ERL_BIN_SIZE(bin)] = '\0'; - } - erl_free_term(bin); - return result; - } -} - -/* - * This function converts an I/O list to a binary term. - * - * Returns: NULL if the list was not an I/O list, otherwise - * an ETERM pointer pointing to a binary term. - */ - -ETERM *erl_iolist_to_binary (const ETERM* term) -{ - ETERM *dest; - int size; - char* ptr; - - if (!term) return NULL; - /* ASSERT(term != NULL); */ - - /* - * Verify that the term is an I/O list and get its length. - */ - - size = erl_iolist_length(term); - if (size == -1) { - return NULL; - } - - /* - * Allocate the binary and copy the contents of the I/O list into it. - */ - - dest = erl_alloc_eterm(ERL_BINARY); - ERL_COUNT(dest) = 1; - ERL_BIN_SIZE(dest) = size; - ptr = (char *)erl_malloc(size); - ERL_BIN_PTR(dest) = (unsigned char *)ptr; - iolist_to_buf(term, &ptr); - - /* - * If ptr doesn't point exactly one byte beyond the end of the - * binary, something must be seriously wrong. - */ - - if (ERL_BIN_PTR(dest) + size != (unsigned char *) ptr) return NULL; - /* ASSERT(ERL_BIN_PTR(dest) + size == (unsigned char *) ptr); */ - - return dest; -} - -/* - * Returns the length of an I/O list. - * - * Returns: -1 if the term if the given term is not a I/O list, - * or the length otherwise. - */ - -int erl_iolist_length (const ETERM* term) -{ - int len = 0; - - while (ERL_IS_CONS(term)) { - ETERM* obj = HEAD(term); - - if (ERL_IS_BYTE(obj)) { - len++; - } else if (ERL_IS_CONS(obj)) { - int i; - if ((i = erl_iolist_length(obj)) < 0) - return i; - len += i; - } else if (ERL_IS_BINARY(obj)) { - len += ERL_BIN_SIZE(obj); - } else if (!ERL_IS_EMPTY_LIST(obj)) { - return(-1); - } - term = TAIL(term); - } - if (ERL_IS_EMPTY_LIST(term)) - return len; - else if (ERL_IS_BINARY(term)) - return len + ERL_BIN_SIZE(term); - else - return -1; -} - -static int erl_atom_copy(Erl_Atom_data* dst, const Erl_Atom_data* src) -{ - if (src->latin1 == src->utf8) { - dst->latin1 = dst->utf8 = strsave(src->latin1); - dst->lenL = dst->lenU = strlen(src->latin1); - } - else if (src->latin1) { - dst->latin1 = strsave(src->latin1); - dst->lenL = strlen(src->latin1); - dst->utf8 = NULL; - dst->lenU = 0; - } - else { - dst->utf8 = strsave(src->utf8); - dst->lenU = strlen(src->utf8); - dst->latin1 = NULL; - dst->lenL = 0; - } - return (dst->latin1 != NULL || dst->utf8 == NULL); -} - - -/* - * Return a brand NEW COPY of an ETERM. - */ -/* - * FIXME: Deep (the whole tree) or shallow (just the top term) copy? - * The documentation never says, but the code as written below will - * make a deep copy. This should be documented. - */ -ETERM *erl_copy_term(const ETERM *ep) -{ - int i; - ETERM *cp; - - if (!ep) return NULL; - /* ASSERT(ep != NULL); */ - - cp = erl_alloc_eterm(ERL_TYPE(ep)); - ERL_COUNT(cp) = 1; - - switch(ERL_TYPE(cp)) { - case ERL_INTEGER: - case ERL_SMALL_BIG: - ERL_INT_VALUE(cp) = ERL_INT_VALUE(ep); - break; - case ERL_U_INTEGER: - case ERL_U_SMALL_BIG: - ERL_INT_UVALUE(cp) = ERL_INT_UVALUE(ep); - break; - case ERL_LONGLONG: - ERL_LL_VALUE(cp) = ERL_LL_VALUE(ep); - break; - case ERL_U_LONGLONG: - ERL_LL_UVALUE(cp) = ERL_LL_UVALUE(ep); - break; - case ERL_FLOAT: - ERL_FLOAT_VALUE(cp) = ERL_FLOAT_VALUE(ep); - break; - case ERL_ATOM: - if (!erl_atom_copy(&cp->uval.aval.d, &ep->uval.aval.d)) - { - erl_free_term(cp); - erl_errno = ENOMEM; - return NULL; - } - break; - case ERL_PID: - /* FIXME: First copy the bit pattern, then duplicate the node - name and plug in. Somewhat ugly (also done with port and - ref below). */ - memcpy(&cp->uval.pidval, &ep->uval.pidval, sizeof(Erl_Pid)); - erl_atom_copy(&cp->uval.pidval.node, &ep->uval.pidval.node); - ERL_COUNT(cp) = 1; - break; - case ERL_PORT: - memcpy(&cp->uval.portval, &ep->uval.portval, sizeof(Erl_Port)); - erl_atom_copy(&cp->uval.portval.node, &ep->uval.portval.node); - ERL_COUNT(cp) = 1; - break; - case ERL_REF: - memcpy(&cp->uval.refval, &ep->uval.refval, sizeof(Erl_Ref)); - erl_atom_copy(&cp->uval.refval.node, &ep->uval.refval.node); - ERL_COUNT(cp) = 1; - break; - case ERL_LIST: - HEAD(cp) = erl_copy_term(HEAD(ep)); - TAIL(cp) = erl_copy_term(TAIL(ep)); - break; - case ERL_EMPTY_LIST: - break; - case ERL_TUPLE: - i = ERL_TUPLE_SIZE(cp) = ERL_TUPLE_SIZE(ep); - ERL_TUPLE_ELEMS(cp) = (ETERM**) erl_malloc(i * sizeof(ETERM*)); - for(i=0; i < ERL_TUPLE_SIZE(ep); i++) - ERL_TUPLE_ELEMENT(cp,i) = erl_copy_term(ERL_TUPLE_ELEMENT(ep, i)); - break; - case ERL_BINARY: - ERL_BIN_SIZE(cp) = ERL_BIN_SIZE(ep); - ERL_BIN_PTR(cp) = (unsigned char *) erl_malloc(ERL_BIN_SIZE(ep)); - memcpy(ERL_BIN_PTR(cp), ERL_BIN_PTR(ep), ERL_BIN_SIZE(ep)); - break; - case ERL_FUNCTION: - i = ERL_CLOSURE_SIZE(cp) = ERL_CLOSURE_SIZE(ep); - ERL_FUN_ARITY(cp) = ERL_FUN_ARITY(ep); - ERL_FUN_NEW_INDEX(cp) = ERL_FUN_NEW_INDEX(ep); - ERL_FUN_INDEX(cp) = erl_copy_term(ERL_FUN_INDEX(ep)); - ERL_FUN_UNIQ(cp) = erl_copy_term(ERL_FUN_UNIQ(ep)); - ERL_FUN_CREATOR(cp) = erl_copy_term(ERL_FUN_CREATOR(ep)); - ERL_FUN_MODULE(cp) = erl_copy_term(ERL_FUN_MODULE(ep)); - memcpy(ERL_FUN_MD5(cp), ERL_FUN_MD5(ep), sizeof(ERL_FUN_MD5(ep))); - ERL_CLOSURE(cp) = (ETERM**) erl_malloc(i * sizeof(ETERM*)); - for(i=0; i < ERL_CLOSURE_SIZE(ep); i++) - ERL_CLOSURE_ELEMENT(cp,i) = - erl_copy_term(ERL_CLOSURE_ELEMENT(ep, i)); - break; - default: - erl_err_msg("<ERROR> erl_copy_term: wrong type encountered !"); - erl_free_term(cp); - return (ETERM *) NULL; - } - - return cp; -} - -#ifndef SILENT - -static int print_string(FILE* fp, const ETERM* ep); -static int is_printable_list(const ETERM* term); - -/* - * PRINT out an ETERM. - */ - -int erl_print_term(FILE *fp, const ETERM *ep) -{ - int j,i,doquote; - int ch_written = 0; /* counter of written chars */ - - if ((!fp) || (!ep)) return 0; - /* ASSERT(ep != NULL); */ - - j = i = doquote = 0; - switch(ERL_TYPE(ep)) - { - case ERL_ATOM: { - char* adata = ERL_ATOM_PTR(ep); - /* FIXME: what if some weird locale is in use? */ - if (!islower(adata[0])) - doquote = 1; - - for (i = 0; !doquote && i < ERL_ATOM_SIZE(ep); i++) - { - doquote = !(isalnum(adata[i]) || (adata[i] == '_')); - } - - if (doquote) { - putc('\'', fp); - ch_written++; - } - fputs(adata, fp); - ch_written += ERL_ATOM_SIZE(ep); - if (doquote) { - putc('\'', fp); - ch_written++; - } - break; - } - case ERL_VARIABLE: - if (!isupper((int)ERL_VAR_NAME(ep)[0])) { - doquote = 1; - putc('\'', fp); - ch_written++; - } - - fputs(ERL_VAR_NAME(ep), fp); - ch_written += ERL_VAR_LEN(ep); - - if (doquote) { - putc('\'', fp); - ch_written++; - } - break; - - case ERL_PID: - ch_written += fprintf(fp, "<%s.%d.%d>", - ERL_PID_NODE(ep), - ERL_PID_NUMBER(ep), ERL_PID_SERIAL(ep)); - break; - case ERL_PORT: - ch_written += fprintf(fp, "#Port"); - break; - case ERL_REF: - ch_written += fprintf(fp, "#Ref"); - break; - case ERL_EMPTY_LIST: - ch_written += fprintf(fp, "[]"); - break; - case ERL_LIST: - if (is_printable_list(ep)) { - ch_written += print_string(fp, ep); - } else { - putc('[', fp); - ch_written++; - while (ERL_IS_CONS(ep)) { - ch_written += erl_print_term(fp, HEAD(ep)); - ep = TAIL(ep); - if (ERL_IS_CONS(ep)) { - putc(',', fp); - ch_written++; - } - } - if (!ERL_IS_EMPTY_LIST(ep)) { - putc('|', fp); - ch_written++; - ch_written += erl_print_term(fp, ep); - } - putc(']', fp); - ch_written++; - } - break; - case ERL_TUPLE: - putc('{', fp); - ch_written++; - for (i=0; i < ERL_TUPLE_SIZE(ep); i++) { - ch_written += erl_print_term(fp, ERL_TUPLE_ELEMENT(ep, j++) ); - if (i != ERL_TUPLE_SIZE(ep)-1) { - putc(',', fp); - ch_written++; - } - } - putc('}', fp); - ch_written++; - break; - case ERL_BINARY: { - int sz = (ERL_BIN_SIZE(ep) > 20) ? 20 : ERL_BIN_SIZE(ep); - unsigned char *ptr = ERL_BIN_PTR(ep); - ch_written += fprintf(fp, "#Bin<"); - for (i = 0; i < sz; i++) { - putc(ptr[i], fp); ch_written++; - } - if (sz == 20) ch_written += fprintf(fp, "(%d)....>", ERL_BIN_SIZE(ep)-20); - else ch_written += fprintf(fp, ">"); - break; - } - case ERL_INTEGER: - case ERL_SMALL_BIG: - ch_written += fprintf(fp, "%d", ERL_INT_VALUE(ep)); - break; - case ERL_U_INTEGER: - case ERL_U_SMALL_BIG: - ch_written += fprintf(fp, "%d", ERL_INT_UVALUE(ep)); - break; - case ERL_LONGLONG: - case ERL_U_LONGLONG: - ch_written += fprintf(fp, "%lld", ERL_LL_UVALUE(ep)); - break; - case ERL_FLOAT: - ch_written += fprintf(fp, "%f", ERL_FLOAT_VALUE(ep)); - break; - case ERL_FUNCTION: - ch_written += fprintf(fp, "#Fun<"); - ch_written += erl_print_term(fp, ERL_FUN_MODULE(ep)); - putc('.', fp); - ch_written++; - ch_written += erl_print_term(fp, ERL_FUN_INDEX(ep)); - putc('.', fp); - ch_written++; - ch_written += erl_print_term(fp, ERL_FUN_UNIQ(ep)); - putc('>', fp); - ch_written++; - break; - default: - ch_written = -10000; - erl_err_msg("<ERROR> erl_print_term: Bad type of term !"); - } - return ch_written; -} - -/* - * FIXME not done yet.... - */ - -#if 0 - -int erl_sprint_term(char *buf, const ETERM *ep) -{ - int j,i,doquote; - int ch_written = 0; /* counter of written chars */ - - if ((!buf) || (!ep)) return 0; - /* ASSERT(ep != NULL); */ - - j = i = doquote = 0; - switch(ERL_TYPE(ep)) - { - case ERL_ATOM: - /* FIXME: what if some weird locale is in use? */ - if (!islower((int)ERL_ATOM_PTR(ep)[0])) - doquote = 1; - - for (i = 0; !doquote && i < ERL_ATOM_SIZE(ep); i++) - { - doquote = !(isalnum((int)ERL_ATOM_PTR(ep)[i]) - || (ERL_ATOM_PTR(ep)[i] == '_')); - } - - if (doquote) { - *buf++ = '\''; - ch_written++; - } - { - int len = ERL_ATOM_SIZE(ep); - strncpy(buf, ERL_ATOM_PTR(ep), len); - buf += len; - ch_written += len; - } - if (doquote) { - *buf++ = '\''; - ch_written++; - } - break; - - case ERL_VARIABLE: - if (!isupper((int)ERL_VAR_NAME(ep)[0])) { - doquote = 1; - *buf++ = '\''; - ch_written++; - } - len = ERL_VAR_LEN(ep); - strncpy(buf, ERL_VAR_NAME(ep), len); - buf += len; - ch_written += len; - - if (doquote) { - *buf++ = '\''; - ch_written++; - } - break; - - case ERL_PID: - len = sprintf(buf, "<%s.%d.%d>", - ERL_PID_NODE(ep), - ERL_PID_NUMBER(ep), ERL_PID_SERIAL(ep)); - buf += len; - ch_written += len; - break; - case ERL_PORT: - len = sprintf(buf , "#Port"); - buf += len; - ch_written += len; - break; - case ERL_REF: - len = sprintf(buf , "#Ref"); - buf += len; - ch_written += len; - break; - case ERL_EMPTY_LIST: - len = sprintf(buf , "[]"); - buf += len; - ch_written += len; - break; - case ERL_LIST: - if (is_printable_list(ep)) { - ch_written += print_string(fp, ep); - } else { - putc('[', fp); - ch_written++; - while (ERL_IS_CONS(ep)) { - ch_written += erl_sprint_term(fp, HEAD(ep)); - ep = TAIL(ep); - if (ERL_IS_CONS(ep)) { - putc(',', fp); - ch_written++; - } - } - if (!ERL_IS_EMPTY_LIST(ep)) { - putc('|', fp); - ch_written++; - ch_written += erl_sprint_term(fp, ep); - } - putc(']', fp); - ch_written++; - } - break; - case ERL_TUPLE: - putc('{', fp); - ch_written++; - for (i=0; i < ERL_TUPLE_SIZE(ep); i++) { - ch_written += erl_sprint_term(fp, ERL_TUPLE_ELEMENT(ep, j++) ); - if (i != ERL_TUPLE_SIZE(ep)-1) { - putc(',', fp); - ch_written++; - } - } - putc('}', fp); - ch_written++; - break; - case ERL_BINARY: - len = sprintf(buf , "#Bin"); - buf += len; - ch_written += len; - break; - case ERL_INTEGER: - case ERL_SMALL_BIG: - len = sprintf(buf , "%d", ERL_INT_VALUE(ep)); - buf += len; - ch_written += len; - break; - case ERL_U_INTEGER: - case ERL_U_SMALL_BIG: - len = sprintf(buf , "%d", ERL_INT_UVALUE(ep)); - buf += len; - ch_written += len; - break; - case ERL_FLOAT: - len = sprintf(buf , "%f", ERL_FLOAT_VALUE(ep)); - buf += len; - ch_written += len; - break; - case ERL_FUNCTION: - len = sprintf(buf , "#Fun<"); - buf += len; - ch_written += len; - ch_written += erl_sprint_term(fp, ERL_FUN_MODULE(ep)); - putc('.', fp); - ch_written++; - ch_written += erl_sprint_term(fp, ERL_FUN_INDEX(ep)); - putc('.', fp); - ch_written++; - ch_written += erl_sprint_term(fp, ERL_FUN_UNIQ(ep)); - putc('>', fp); - ch_written++; - break; - default: - ch_written = -10000; - erl_err_msg("<ERROR> erl_sprint_term: Bad type of term !"); - } - return ch_written; -} -#endif - -static int print_string(FILE* fp, const ETERM* ep) -{ - int ch_written = 0; /* counter of written chars */ - - putc('"', fp); - ch_written++; - while (ERL_IS_CONS(ep)) { - int c = ERL_INT_VALUE(HEAD(ep)); - - if (c >= ' ') { - putc(c, fp); - ch_written++; - } - else { - switch (c) { - case '\n': fputs("\\n", fp); ch_written += 2; break; - case '\r': fputs("\\r", fp); ch_written += 2; break; - case '\t': fputs("\\t", fp); ch_written += 2; break; - case '\v': fputs("\\v", fp); ch_written += 2; break; - case '\b': fputs("\\b", fp); ch_written += 2; break; - case '\f': fputs("\\f", fp); ch_written += 2; break; - break; - default: - ch_written += fprintf(fp, "\\%o", c); - break; - } - } - ep = TAIL(ep); - } - putc('"', fp); - ch_written++; - return ch_written; -} - -/* - * Returns 1 if term is a list of printable character, otherwise 0. - */ - -static int is_printable_list(const ETERM* term) -{ - while (ERL_TYPE(term) == ERL_LIST) { - ETERM* head = HEAD(term); - - if (!ERL_IS_BYTE(head)) { - return 0; - } - if (ERL_INT_VALUE(head) < ' ') { - switch (ERL_INT_VALUE(head)) { - case '\n': - case '\r': - case '\t': - case '\v': - case '\b': - case '\f': - break; - default: - return 0; - } - } - term = TAIL(term); - } - - return ERL_IS_EMPTY_LIST(term); -} - -#endif - -/* - * Retrieves the bytes from an I/O list and copy into a buffer. - * - * NOTE! It is the responsibility of the caller to ensure that - * that the buffer is big enough (typically by calling - * erl_iolist_length()), and that the term is an I/O list. - * - * ETERM* term; Term to convert to bytes. - * char** bufp; Pointer to pointer to buffer - * where the bytes should be stored. - * On return, the pointer will point beyond - * the last byte stored. - */ - -static void iolist_to_buf(const ETERM* term, char** bufp) -{ - char* dest = *bufp; - - while (ERL_IS_CONS(term)) { - ETERM* obj = HEAD(term); - - if (ERL_IS_BYTE(obj)) { - *dest++ = ERL_INT_VALUE(obj); - } else if (ERL_IS_CONS(obj)) { - iolist_to_buf(obj, &dest); - } else if (ERL_IS_BINARY(obj)) { - memcpy(dest, ERL_BIN_PTR(obj), ERL_BIN_SIZE(obj)); - dest += ERL_BIN_SIZE(obj); - } else { - /* - * Types have been checked by caller. - */ - if (!ERL_IS_EMPTY_LIST(obj)) return; - /* ASSERT(ERL_IS_EMPTY_LIST(obj)); */ - } - term = TAIL(term); - } - if (ERL_IS_BINARY(term)) { - memcpy(dest, ERL_BIN_PTR(term), ERL_BIN_SIZE(term)); - dest += ERL_BIN_SIZE(term); - } else { - /* - * Types have been checked by caller. - */ - if (!ERL_IS_EMPTY_LIST(term)) return; - /* ASSERT(ERL_IS_EMPTY_LIST(term));*/ - } - *bufp = dest; -} - -static char* strsave(const char *src) -{ - char * dest = malloc(strlen(src)+1); - - if (dest != NULL) - strcpy(dest, src); - return dest; -} - - -/* - * Local Variables: - * compile-command: "cd ..; ERL_TOP=/clearcase/otp/erts make -k" - * End: - */ diff --git a/lib/erl_interface/src/legacy/erl_eterm.h b/lib/erl_interface/src/legacy/erl_eterm.h deleted file mode 100644 index e2f3a90531..0000000000 --- a/lib/erl_interface/src/legacy/erl_eterm.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_ETERM_H -#define _ERL_ETERM_H - -#ifndef SILENT -#include <stdio.h> -#endif - -#include "portability.h" - -#define ERL_MAX_COUNT 0xffffff -#define ERL_MAX ((1 << 27)-1) -#define ERL_MIN -(1 << 27) - -/* FIXME should this be documented and in erl_interface.h ??? */ -#define ERL_BIG_ARITY(x) ((x)->uval.bigval.arity) -#define ERL_BIG_IS_NEG(x) ((x)->uval.bigval.is_neg) -#define ERL_BIG_DIGITS(x) ((x)->uval.bigval.digits) -#define ERL_BIG_DIGIT(x,i) (ERL_BIG_DIGITS(x)[(i)]) - -/* - * Typing checking macros. - */ - -/* FIXME should this be documented and in erl_interface.h ??? */ -#define ERL_IS_DEFINED(x) (ERL_TYPE(x) != 0) -#define ERL_IS_COMPOUND(x) (ERL_TYPE(x) & ERL_COMPOUND) -#define ERL_IS_FUNCTION(x) (ERL_TYPE(x) == ERL_FUNCTION) -#define ERL_IS_BIG(x) (ERL_TYPE(x) == ERL_BIG) - - -typedef struct _heapmark { - unsigned long mark; /* id */ - int size; /* size of buffer */ - Erl_Heap *base; /* points to start of buffer */ - Erl_Heap *cur; /* points into buffer */ - struct _heapmark *prev; /* previous heapmark */ -} Erl_HeapMark; - - -void erl_mk_port_helper(ETERM* ep, unsigned number, unsigned int creation); -void erl_mk_pid_helper(ETERM*, unsigned,unsigned, unsigned int); -ETERM * __erl_mk_reference(ETERM*, const char *, size_t, unsigned int n[], unsigned int); -int erl_current_fix_desc(void); - -#endif /* _ERL_ETERM_H */ diff --git a/lib/erl_interface/src/legacy/erl_fix_alloc.c b/lib/erl_interface/src/legacy/erl_fix_alloc.c deleted file mode 100644 index 890a9ce291..0000000000 --- a/lib/erl_interface/src/legacy/erl_fix_alloc.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Function: General purpose Memory allocator for fixed block - * size objects. This allocater is at least an order of - * magnitude faster than malloc(). - */ -#include "eidef.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "ei_locking.h" -#include "erl_interface.h" -#include "erl_error.h" -#include "erl_malloc.h" -#include "erl_fix_alloc.h" -#include "erl_eterm.h" - -#define WIPE_CHAR ((char)0xaa) /* 10101010 */ - -/* the freelist is a singly linked list of these */ -/* i.e. the user structure and a link pointer */ -struct fix_block { - ETERM term; - struct fix_block *next; - int free; -}; - -/* this is a struct just to keep namespace pollution low on VxWorks */ -struct eterm_stateinfo { - struct fix_block *freelist; - unsigned long freed; - unsigned long allocated; -#ifdef _REENTRANT - ei_mutex_t *lock; -#endif /* _REENTRANT */ -}; -/* FIXME problem for threaded ? */ -static struct eterm_stateinfo *erl_eterm_state=NULL; - - -int erl_init_eterm_alloc (void) -{ -#if defined(PURIFY) && defined (DEBUG) - fprintf(stderr,"erl_fix_alloc() compiled for Purify - using \"real\" malloc()"); -#endif - - erl_eterm_state = malloc(sizeof(*erl_eterm_state)); - if (erl_eterm_state == NULL) goto err1; - - erl_eterm_state->freelist = NULL; - erl_eterm_state->freed = 0; - erl_eterm_state->allocated = 0; -#ifdef _REENTRANT - erl_eterm_state->lock = ei_mutex_create(); - if (erl_eterm_state->lock == NULL) goto err2; -#endif /* _REENTRANT */ - - return 1; - - /* Error cleanup */ -#ifdef _REENTRANT - err2: - /* FIXME ENOMEM is not what went wrong... */ - free(erl_eterm_state); -#endif /* _REENTRANT */ - err1: - erl_errno = ENOMEM; - return 0; -} - -/* get an eterm, from the freelist if possible or from malloc() */ -void *erl_eterm_alloc (void) -{ -#ifdef PURIFY - ETERM *p; - - if ((p = malloc(sizeof(*p)))) { - memset(p, WIPE_CHAR, sizeof(*p)); - } - return p; -#else - struct fix_block *b; - -#ifdef _REENTRANT - ei_mutex_lock(erl_eterm_state->lock, 0); -#endif /* _REENTRANT */ - - /* try to pop block from head of freelist */ - if ((b = erl_eterm_state->freelist) != NULL) { - erl_eterm_state->freelist = b->next; - erl_eterm_state->freed--; - } else if ((b = malloc(sizeof(*b))) == NULL) { - erl_errno = ENOMEM; -#ifdef _REENTRANT - ei_mutex_unlock(erl_eterm_state->lock); -#endif /* _REENTRANT */ - return NULL; - } - erl_eterm_state->allocated++; - b->free = 0; - b->next = NULL; -#ifdef _REENTRANT - ei_mutex_unlock(erl_eterm_state->lock); -#endif /* _REENTRANT */ - return (void *) &b->term; -#endif /* !PURIFY */ -} - -/* free an eterm back to the freelist */ -void erl_eterm_free(void *p) -{ -#ifdef PURIFY - if (p) { - memset(p, WIPE_CHAR, sizeof(ETERM)); - } - free(p); -#else - struct fix_block *b = p; - - if (b) { - if (b->free) { -#ifdef DEBUG - fprintf(stderr,"erl_eterm_free: attempt to free already freed block %p\n",b); -#endif - return; - } - -#ifdef _REENTRANT - ei_mutex_lock(erl_eterm_state->lock,0); -#endif /* _REENTRANT */ - b->free = 1; - b->next = erl_eterm_state->freelist; - erl_eterm_state->freelist = b; - erl_eterm_state->freed++; - erl_eterm_state->allocated--; -#ifdef _REENTRANT - ei_mutex_unlock(erl_eterm_state->lock); -#endif /* _REENTRANT */ - } -#endif /* !PURIFY */ -} - -/* really free the freelist */ -void erl_eterm_release (void) -{ -#if !defined(PURIFY) - struct fix_block *b; - -#ifdef _REENTRANT - ei_mutex_lock(erl_eterm_state->lock,0); -#endif /* _REENTRANT */ - { - while (erl_eterm_state->freelist != NULL) { - b = erl_eterm_state->freelist; - erl_eterm_state->freelist = b->next; - free(b); - erl_eterm_state->freed--; - } - } -#ifdef _REENTRANT - ei_mutex_unlock(erl_eterm_state->lock); -#endif /* _REENTRANT */ -#endif /* !PURIFY */ -} - -void erl_eterm_statistics (unsigned long *allocd, unsigned long *freed) -{ - if (allocd) *allocd = erl_eterm_state->allocated; - if (freed) *freed = erl_eterm_state->freed; - - return; -} - - -/* - * Local Variables: - * compile-command: "cd ..; ERL_TOP=/clearcase/otp/erts make -k" - * End: - */ diff --git a/lib/erl_interface/src/legacy/erl_fix_alloc.h b/lib/erl_interface/src/legacy/erl_fix_alloc.h deleted file mode 100644 index 50d1368e34..0000000000 --- a/lib/erl_interface/src/legacy/erl_fix_alloc.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_FIX_ALLOC_H -#define _ERL_FIX_ALLOC_H - -int erl_init_eterm_alloc(void); -void erl_eterm_free(void*); -void *erl_eterm_alloc(void); - -#endif /* _ERL_FIX_ALLOC_H */ diff --git a/lib/erl_interface/src/legacy/erl_format.c b/lib/erl_interface/src/legacy/erl_format.c deleted file mode 100644 index 45f5489e54..0000000000 --- a/lib/erl_interface/src/legacy/erl_format.c +++ /dev/null @@ -1,742 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Function: Provides two primitives: erl_format to build - * Erlang terms in an easy way, and erl_match to perform - * pattern match similar to what is done in Erlang. - * - */ - -#include "eidef.h" - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <ctype.h> - -#ifdef VRTX -#define __READY_EXTENSIONS__ -#include <errno.h> -#endif -#include "erl_interface.h" -#include "erl_eterm.h" -#include "erl_malloc.h" -#include "erl_error.h" -#include "erl_internal.h" - -#define ERL_TRUE 1 -#define ERL_FALSE 0 -#define ERL_OK 0 -#define ERL_FORMAT_ERROR -1 - -#define ERL_MAX_ENTRIES 255 /* Max entries in a tuple/list term */ -#define ERL_MAX_NAME_LENGTH 255 /* Max length of variable names */ - -#define PRINT(t) \ -{ \ - print_term(stderr,t); \ - fprintf(stderr,"\n"); \ - } - - -typedef struct lvar { - ETERM *var; - struct lvar *next; -} lvar; - - -/* Forward */ -static ETERM *eformat(char**, va_list*); -static int ematch(ETERM*, ETERM*); - -/* FIXME not thread safe */ -struct _ef { - lvar *chain; /* Chain of local variables */ - lvar *idle; /* Idle list of lvar's */ -} ef; - -/* Find local variable in term. - */ -static ETERM *find_lvar(char *name) -{ - lvar *tmp=ef.chain; - - while (tmp != NULL) { - if (strcmp(tmp->var->uval.vval.name,name) == 0) - return tmp->var->uval.vval.v; - tmp = tmp->next; - } - return (ETERM *) NULL; - -} /* find_lvar */ - -static void lvar_free(lvar *lv) -{ - lvar *tmp=ef.chain; - - /* Link in the chain into the idle list */ - if (ef.idle == NULL) - ef.idle = lv; - else { - tmp = ef.idle; - while (tmp->next != NULL) - tmp = tmp->next; - tmp->next = lv; - } - - - /* Clear out the variable information */ - tmp = lv; - while (tmp != NULL) { - tmp->var = (ETERM *) NULL; - tmp = tmp->next; - } - -} /* lvar_free */ - -static lvar *lvar_alloc(void) -{ - lvar *tmp; - - if ((tmp = ef.idle) == NULL) { - tmp = (lvar *) erl_malloc(sizeof(lvar)); - } - else { - tmp = ef.idle; - ef.idle = tmp->next; - } - return tmp; - -} /* lvar_alloc */ - -static void undo_bindings(void) -{ - lvar *tmp=ef.chain; - - while (tmp != NULL) { - erl_free_term(tmp->var->uval.vval.v); - tmp->var->uval.vval.v = (ETERM *) NULL; - tmp = tmp->next; - } - -} /* undo_bindings */ - -static void release_chain(void) -{ - - lvar_free(ef.chain); - ef.chain = (lvar *) NULL; - -} /* release_chain */ - -static void add_lvar(ETERM *t) -{ - lvar *lv; - - lv = lvar_alloc(); - lv->var = t; - lv->next = ef.chain; - ef.chain = lv; - -} /* add_lvar */ - -static char *pvariable(char **fmt, char *buf) -{ - char *start=*fmt; - char c; - int len; - - while (1) { - c = *(*fmt)++; - if (isalnum((int) c) || (c == '_')) - continue; - else - break; - } - (*fmt)--; - len = *fmt - start; - memcpy(buf, start, len); - buf[len] = 0; - - return buf; - -} /* pvariable */ - -static char *patom(char **fmt, char *buf) -{ - char *start=*fmt; - char c; - int len; - - while (1) { - c = *(*fmt)++; - if (isalnum((int) c) || (c == '_') || (c == '@')) - continue; - else - break; - } - (*fmt)--; - len = *fmt - start; - memcpy(buf, start, len); - buf[len] = 0; - - return buf; - -} /* patom */ - -/* Check if integer or float - */ -static char *pdigit(char **fmt, char *buf) -{ - char *start=*fmt; - char c; - int len,dotp=0; - - while (1) { - c = *(*fmt)++; - if (isdigit((int) c)) - continue; - else if (!dotp && (c == '.')) { - dotp = 1; - continue; - } - else - break; - } - (*fmt)--; - len = *fmt - start; - memcpy(buf, start, len); - buf[len] = 0; - - return buf; - -} /* pdigit */ - -static char *pstring(char **fmt, char *buf) -{ - char *start=++(*fmt); /* skip first quote */ - char c; - int len; - - while (1) { - c = *(*fmt)++; - if (c == '"') { - if (*((*fmt)-1) == '\\') - continue; - else - break; - } else - continue; - } - len = *fmt - 1 - start; /* skip last quote */ - memcpy(buf, start, len); - buf[len] = 0; - - return buf; - -} /* pstring */ - -static char *pquotedatom(char **fmt, char *buf) -{ - char *start=++(*fmt); /* skip first quote */ - char c; - int len; - - while (1) { - c = *(*fmt)++; - if (c == '\'') { - if (*((*fmt)-1) == '\\') - continue; - else - break; - } else - continue; - } - len = *fmt - 1 - start; /* skip last quote */ - memcpy(buf, start, len); - buf[len] = 0; - - return buf; - -} /* pquotedatom */ - - -/* - * The format letters are: - * w - Any Erlang term - * a - An Atom - * b - A Binary - * s - A String - * i - An Integer - * f - A Float (double) - */ -static int pformat(char **fmt, va_list *pap, ETERM *v[], int size) -{ - int rc=ERL_OK; - - /* this next section hacked to remove the va_arg calls */ - switch (*(*fmt)++) { - - case 'w': - v[size] = va_arg(*pap, ETERM*); - ERL_COUNT(v[size])++; - break; - - case 'a': - v[size] = erl_mk_atom(va_arg(*pap, char *)); - break; - - case 's': - v[size] = erl_mk_string(va_arg(*pap, char *)); - break; - - case 'i': - v[size] = erl_mk_int(va_arg(*pap, int)); - break; - - case 'f': - v[size] = erl_mk_float(va_arg(*pap, double)); - break; - - case 'b': { - char *sarg = va_arg(*pap, char *); - v[size] = erl_mk_binary(sarg, strlen(sarg)); - break; - } - - default: - rc = ERL_FORMAT_ERROR; - break; - } - - return rc; - -} /* pformat */ - -static int ptuple(char **fmt, va_list *pap, ETERM *v[], int size) -{ - int res=ERL_FORMAT_ERROR; - - switch (*(*fmt)++) { - - case '}': - res = size; - break; - - case ',': - res = ptuple(fmt, pap, v, size); - break; - - case '~': - - if (pformat(fmt, pap, v, size) == ERL_OK) - res = ptuple(fmt, pap, v, ++size); - else - erl_err_msg("ptuple(1): Wrong format sequence !"); - break; - - case ' ': - return ptuple(fmt, pap, v, size); - break; - - default: { - (*fmt)--; - if ((v[size++] = eformat(fmt, pap)) != (ETERM *) NULL) - res = ptuple(fmt, pap, v, size); - break; - - /* - if (isupper(**fmt)) { - v[size++] = erl_mk_var(pvariable(fmt, wbuf)); - res = ptuple(fmt, pap, v, size); - } - else if ((v[size++] = eformat(fmt, pap)) != (ETERM *) NULL) - res = ptuple(fmt, pap, v, size); - break; - */ - } - - } /* switch */ - - return res; - -} /* ptuple */ - - -static int plist(char **fmt, va_list *pap, ETERM *v[], int size) -{ - int res=ERL_FORMAT_ERROR; - - switch (*(*fmt)++) { - - case ']': - res = size; - break; - - case ',': - res = plist(fmt, pap, v, size); - break; - - case '~': - - if (pformat(fmt, pap, v, size) == ERL_OK) - res = plist(fmt, pap, v, ++size); - else - erl_err_msg("plist(1): Wrong format sequence !"); - break; - - case ' ': - return plist(fmt, pap, v, size); - break; - - default: { - (*fmt)--; - if ((v[size++] = eformat(fmt, pap)) != (ETERM *) NULL) - res = plist(fmt, pap, v, size); - break; - - /* - if (isupper(**fmt)) { - v[size++] = erl_mk_var(pvariable(fmt, wbuf)); - res = plist(fmt, pap, v, size); - } - else if ((v[size++] = eformat(fmt, pap)) != (ETERM *) NULL) - res = plist(fmt, pap, v, size); - break; - */ - } - - } /* switch */ - - return res; - -} /* plist */ - - -static ETERM *eformat(char **fmt, va_list *pap) -{ - int size; - ETERM *v[ERL_MAX_ENTRIES],*ep; - - switch (*(*fmt)++) { - case '{': - if ((size = ptuple(fmt, pap , v, 0)) != ERL_FORMAT_ERROR) { - ep = erl_mk_tuple(v, size); - erl_free_array(v, size); - return ep; - } - else - return (ETERM *) NULL; - break; - - case '[': - if (**fmt == ']') { - (*fmt)++; - return erl_mk_empty_list(); - } else if ((size = plist(fmt, pap , v, 0)) != ERL_FORMAT_ERROR) { - ep = erl_mk_list(v, size); - erl_free_array(v, size); - return ep; - } else - return (ETERM *) NULL; - break; - - case '$': /* char-value? */ - return erl_mk_int((int)(*(*fmt)++)); - break; - - case '~': - if (pformat(fmt, pap, v, 0) == ERL_OK) { - ep = erl_copy_term(v[0]); - erl_free_term(v[0]); - return ep; - } - break; - - case ' ': - return eformat(fmt, pap); - break; - - /* handle negative numbers too... - * case '-': - * { - * ETERM *tmp; - * - * tmp = eformat(fmt,pap); - * if (ERL_IS_INTEGER(tmp)) ERL_INT_VALUE(tmp) = -(ERL_INT_VALUE(tmp)); - * return tmp; - * } - * - * - * break; - */ - - default: - { - char wbuf[BUFSIZ]; /* now local to this function for reentrancy */ - - (*fmt)--; - if (islower((int)**fmt)) { /* atom ? */ - char *atom=patom(fmt, wbuf); - return erl_mk_atom(atom); - } - else if (isupper((int)**fmt) || (**fmt == '_')) { - char *var=pvariable(fmt, wbuf); - return erl_mk_var(var); - } - else if (isdigit((int)**fmt)) { /* integer/float ? */ - char *digit=pdigit(fmt, wbuf); - if (strchr(digit,(int) '.') == NULL) - return erl_mk_int(atoi((const char *) digit)); - else - return erl_mk_float(atof((const char *) digit)); - } - else if (**fmt == '"') { /* string ? */ - char *string=pstring(fmt, wbuf); - return erl_mk_string(string); - } - else if (**fmt == '\'') { /* quoted atom ? */ - char *qatom=pquotedatom(fmt, wbuf); - return erl_mk_atom(qatom); - } - } - break; - - } - - erl_err_msg("<ERROR> Syntax error in eformat, char was: %c !", **fmt); - return (ETERM *) NULL; - -} /* eformat */ - - -ETERM *erl_format(char *fmt, ... ) -{ - ETERM *res=NULL; - va_list ap; - - va_start(ap, fmt); - res = eformat(&fmt, &ap); - va_end(ap); - - return res; -} /* erl_format */ - - -/* - * Perform a pattern match between a pattern p and a term t. - * As a side effect bind any unbound variables in p. - * Return true or false. - */ -static int ematch(ETERM *p, ETERM *t) -{ - unsigned int type_p; - unsigned int type_t; - ETERM *tmp; - - /* two NULLs are equal, one is not... */ - if (!p && !t) return ERL_TRUE; - if (!p || !t) return ERL_FALSE; - /* - * ASSERT(p != NULL); - * ASSERT(t != NULL); - */ - - type_p = ERL_TYPE(p); - type_t = ERL_TYPE(t); - - if (type_t == ERL_VARIABLE) { - if (t->uval.vval.v == NULL) - return ERL_FALSE; /* Can't have an unbound variable here ! */ - else - t = t->uval.vval.v; - } - - if (type_p != ERL_VARIABLE && type_p != type_t) - return ERL_FALSE; - - switch (type_p) { - - case ERL_ATOM: { - Erl_Atom_data* pa = &p->uval.aval.d; - Erl_Atom_data* ta = &t->uval.aval.d; - if (pa->utf8 && ta->utf8) { - return pa->lenU == ta->lenU && memcmp(pa->utf8, ta->utf8, pa->lenU)==0; - } - else if (pa->latin1 && ta->latin1) { - return pa->lenL == ta->lenL && memcmp(pa->latin1, ta->latin1, pa->lenL)==0; - } - else if (pa->latin1) { - return cmp_latin1_vs_utf8(pa->latin1, pa->lenL, ta->utf8, ta->lenU)==0; - } - else { - return cmp_latin1_vs_utf8(ta->latin1, ta->lenL, pa->utf8, pa->lenU)==0; - } - } - case ERL_VARIABLE: - if (strcmp(p->uval.vval.name, "_") == 0) /* anon. variable */ - return ERL_TRUE; - else if ((tmp = find_lvar(p->uval.vval.name)) != (ETERM *) NULL) { - /* v points to NULL in cases like erl_format("{X,X}") for the - second variable */ - if (p->uval.vval.v == NULL) - p->uval.vval.v = erl_copy_term(tmp); - return ematch(p->uval.vval.v, t); - } - else { - /* check if the variable is bound already */ - if (p->uval.vval.v != NULL) { - if (ematch(p->uval.vval.v, t) == ERL_TRUE ){ - add_lvar(p); - return ERL_TRUE; - } - else - return ERL_FALSE; - } - else { - p->uval.vval.v = erl_copy_term(t); - add_lvar(p); - return ERL_TRUE; - } - } - break; - - case ERL_PID: - if ((strcmp(ERL_PID_NODE(p), ERL_PID_NODE(t)) == 0) && - (ERL_PID_NUMBER(p) == ERL_PID_NUMBER(t)) && - (ERL_PID_SERIAL(p) == ERL_PID_SERIAL(t)) && - (ERL_PID_CREATION(p) == ERL_PID_CREATION(t))) - return ERL_TRUE; - else - return ERL_FALSE; - break; - - case ERL_PORT: - if ((strcmp(ERL_PORT_NODE(p), ERL_PORT_NODE(t)) == 0) && - (ERL_PORT_NUMBER(p) == ERL_PORT_NUMBER(t)) && - (ERL_PORT_CREATION(p) == ERL_PORT_CREATION(t))) - return ERL_TRUE; - else - return ERL_FALSE; - break; - - case ERL_REF: { - int i, len; - - if (strcmp(ERL_REF_NODE(p), ERL_REF_NODE(t)) != 0 || - ERL_REF_CREATION(p) != ERL_REF_CREATION(t)) - return ERL_FALSE; - - /* FIXME: {len=1, n={42}} and {len=3, n={42, 17, 13}} tests equal. */ - len = ERL_REF_LEN(p); - if (len > ERL_REF_LEN(t)) - len = ERL_REF_LEN(t); - - for (i = 0; i < len; i++) - if (ERL_REF_NUMBERS(p)[i] != ERL_REF_NUMBERS(t)[i]) - return ERL_FALSE; - - return ERL_TRUE; - break; - } - - case ERL_EMPTY_LIST: - return ERL_TRUE; - - case ERL_LIST: - while (ERL_IS_CONS(p) && ERL_IS_CONS(t)) { - if (ematch(p->uval.lval.head, t->uval.lval.head) == ERL_FALSE) - return ERL_FALSE; - p = p->uval.lval.tail; - t = t ->uval.lval.tail; - } - return ematch(p, t); - - case ERL_TUPLE: - { - int i; - if (erl_size(p) != erl_size(t)) - return ERL_FALSE; - else { - for(i=0; i<erl_size(p); i++) - if (ematch(p->uval.tval.elems[i],t->uval.tval.elems[i]) == ERL_FALSE) - return ERL_FALSE; - return ERL_TRUE; - } - } - break; - - case ERL_BINARY: - { - int i; - if ((i = p->uval.bval.size) != t->uval.bval.size) - return ERL_FALSE; - else - return (memcmp(p->uval.bval.b,t->uval.bval.b,i)==0) ? ERL_TRUE : ERL_FALSE; - } - break; - - case ERL_INTEGER: - return (p->uval.ival.i == t->uval.ival.i) ? ERL_TRUE : ERL_FALSE; - break; - - case ERL_SMALL_BIG: - case ERL_U_SMALL_BIG: - /* This case can't happend since it is impossible - * to create a bignum from the C code. - */ - return ERL_FALSE; - break; - - case ERL_FLOAT: -#if defined(VXWORKS) && CPU == PPC860 - { - return (erl_fp_compare((unsigned *)&(p->uval.fval.f), - (unsigned *)&(t->uval.fval.f)) == 0) - ? ERL_TRUE : ERL_FALSE; - } -#else - return (p->uval.fval.f == t->uval.fval.f) ? ERL_TRUE : ERL_FALSE; -#endif - break; - default: - return ERL_FALSE; - break; - } - - /* erl_err_msg("ematch: Unknown type == %c\n", type_p); */ - return ERL_FALSE; - -} /* ematch */ - - -int erl_match(ETERM *p, ETERM *t) -{ - int i; - - if ((i = ematch(p, t)) == ERL_FALSE) - undo_bindings(); - release_chain(); - return i; - -} /* erl_match */ - - diff --git a/lib/erl_interface/src/legacy/erl_format.h b/lib/erl_interface/src/legacy/erl_format.h deleted file mode 100644 index 92fa068206..0000000000 --- a/lib/erl_interface/src/legacy/erl_format.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_FORMAT_H -#define _ERL_FORMAT_H - -#endif /* _ERL_FORMAT_H */ diff --git a/lib/erl_interface/src/legacy/erl_internal.h b/lib/erl_interface/src/legacy/erl_internal.h deleted file mode 100644 index 25cf3e4f42..0000000000 --- a/lib/erl_interface/src/legacy/erl_internal.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_INTERNAL_H -#define _ERL_INTERNAL_H - -/* - * Function: Some useful stuff not to be exported to users. - */ - -#define HEAD(ep) ep->uval.lval.head -#define TAIL(ep) ep->uval.lval.tail -#define ERL_NO_REF(x) (ERL_COUNT(x) == 0) - -#ifdef DEBUG -#define ASSERT(e) \ - if (e) { \ - ; \ - } else { \ - erl_assert_error(#e, __FILE__, __LINE__); \ - } - -extern void erl_assert_error(char* expr, char* file, int line) - __attribute__ ((__noreturn__)); - -#else - -#define ASSERT(e) - -#endif - -#endif /* _ERL_INTERNAL_H */ diff --git a/lib/erl_interface/src/legacy/erl_malloc.c b/lib/erl_interface/src/legacy/erl_malloc.c deleted file mode 100644 index 27ef8c4b32..0000000000 --- a/lib/erl_interface/src/legacy/erl_malloc.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#include "eidef.h" - -#include <stddef.h> -#include <stdlib.h> - -#include "erl_interface.h" -#include "erl_fix_alloc.h" -#include "erl_malloc.h" -#include "erl_internal.h" -#include "erl_eterm.h" -#include "ei_malloc.h" - -void erl_init_malloc(Erl_Heap *hp, long heap_size) -{ - erl_init_eterm_alloc(); -} /* erl_init_malloc */ - -ETERM *erl_alloc_eterm(unsigned char type) -{ - ETERM *e; - - /* Use fix size allocator */ - if (!(e = (ETERM *) erl_eterm_alloc())) - erl_err_sys("<ERROR> erl_alloc_eterm: Failed to allocate more memory\n"); - - ERL_HEADER(e)->count = 0; - ERL_HEADER(e)->type = type; - return e; - -} /* erl_alloc_eterm */ - -#define EXTERNAL 1 -#define INTERNAL 0 -#define COMPOUND 1 -#define NOT_COMPOUND 0 - -static void _erl_free_term (ETERM *ep, int external, int compound); - -/* - * Free a term, but don't deallocate it until - * the reference counter triggers. - */ -void erl_free_term(ETERM *ep) -{ - _erl_free_term(ep, EXTERNAL, NOT_COMPOUND); -} /* erl_free_term */ - -/* - * Free a term regardless of its reference - * counter value. Use this when you have - * built compound terms such as lists or tuples. - */ - -/* - * FIXME is this true?! - * Tearing down term structures no-matter-what is a horrible idea if - * any term happens to be shared (with some other structure or even - * with yourself). - */ - -void erl_free_compound (ETERM *ep) -{ - _erl_free_term(ep, EXTERNAL, COMPOUND); -} /* erl_free_compound */ - - -/* -** The actual free'ing is done here in _erl_free_term. -** It is by nature recursive, but does not recurse -** on the CDR of a list, which makes it usable for large lists. -*/ - -/* -** Convenience macro, called for variables and lists, -** avoids deep recursions. -*/ -#define RESTART(Eterm, External, Compound) \ -do { \ - ETERM *sep; \ - sep = (Eterm); \ - external = (External); \ - compound = (Compound); \ - /* Clear header info */ \ - ERL_TYPE(ep) = ERL_UNDEF; \ - erl_eterm_free((unsigned int *) ep); \ - ep = sep; \ - goto restart; \ -} while(0) - -#define FREE_AND_CLEAR(ptr) \ -do { \ - erl_free(ptr); \ - (ptr) = NULL; \ -} while (0) - -static void erl_atom_free(Erl_Atom_data* p) -{ - erl_free(p->latin1); - if (p->utf8 != p->latin1) { - erl_free(p->utf8); - } - p->latin1 = NULL; - p->utf8 = NULL; - p->lenL = 0; - p->lenU = 0; -} - -static void _erl_free_term (ETERM *ep, int external, int compound) -{ -restart: - if (ep == NULL) - return; - if (compound || ERL_NO_REF(ep)) { - /* Yes, it's time to *really* free this one ! */ - switch(ERL_TYPE(ep)) - { - case ERL_ATOM: - erl_atom_free(&ep->uval.aval.d); - break; - case ERL_VARIABLE: - FREE_AND_CLEAR(ERL_VAR_NAME(ep)); - /* Note: It may be unbound ! */ - if (ERL_VAR_VALUE(ep) != NULL) { - ERL_COUNT(ERL_VAR_VALUE(ep))--; - /* Cleanup and Restart with the actual value */ - RESTART(ERL_VAR_VALUE(ep), INTERNAL, compound); - } - break; - case ERL_LIST: - if (HEAD(ep)) { - ERL_COUNT(HEAD(ep))--; - /* FIXME added cast, is this correct? */ - _erl_free_term((ETERM *)HEAD(ep), INTERNAL, compound); - } - if (TAIL(ep)) { - ERL_COUNT(TAIL(ep))--; - /* Clean up and walk on to CDR in list */ - RESTART(TAIL(ep), INTERNAL, compound); - } - break; - case ERL_TUPLE: - { - int i; - for (i=0; i < ERL_TUPLE_SIZE(ep); i++) - if (ERL_TUPLE_ELEMENT(ep, i)) { - ERL_COUNT(ERL_TUPLE_ELEMENT(ep, i))--; - _erl_free_term(ERL_TUPLE_ELEMENT(ep, i), - INTERNAL, compound); - } - FREE_AND_CLEAR(ERL_TUPLE_ELEMS(ep)); - } - break; - case ERL_BINARY: - FREE_AND_CLEAR(ERL_BIN_PTR(ep)); - break; - case ERL_PID: - erl_atom_free(&ep->uval.pidval.node); - break; - case ERL_PORT: - erl_atom_free(&ep->uval.portval.node); - break; - case ERL_REF: - erl_atom_free(&ep->uval.refval.node); - break; - case ERL_EMPTY_LIST: - case ERL_INTEGER: - case ERL_SMALL_BIG: - case ERL_U_SMALL_BIG: - case ERL_FLOAT: - break; - case ERL_FUNCTION: - { - int i; - - _erl_free_term(ERL_FUN_INDEX(ep), INTERNAL, compound); - _erl_free_term(ERL_FUN_UNIQ(ep), INTERNAL, compound); - _erl_free_term(ERL_FUN_CREATOR(ep), INTERNAL, compound); - _erl_free_term(ERL_FUN_MODULE(ep), INTERNAL, compound); - if (ERL_CLOSURE(ep) != NULL) { - for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++) - _erl_free_term(ERL_CLOSURE_ELEMENT(ep,i), - INTERNAL, compound); - } - } - break; - } /* switch */ - - /* Clear header info for those cases where we are done */ - ERL_TYPE(ep) = ERL_UNDEF; - erl_eterm_free(ep); - } else if (external) { - ERL_COUNT(ep)--; - external = INTERNAL; - goto restart; - } -} /* _erl_free_term */ -#undef RESTART -#undef FREE_AND_CLEAR - -void erl_free_array(ETERM **arr, int size) -{ - int i; - - for (i=0; i<size; i++) - erl_free_term(arr[i]); - -} /* erl_free_array */ - - -void* erl_malloc (long size) -{ - void *res; - - if ((res = ei_malloc(size)) == NULL) - erl_err_sys("<ERROR> erl_malloc: Failed to allocate more memory"); - - return res; -} - -void* erl_realloc(void* orig, long size) -{ - void *res; - - if ((res = ei_realloc(orig, size)) == NULL) - erl_err_sys("<ERROR> erl_realloc: Failed to allocate more memory"); - return res; -} - -void erl_free (void *ptr) -{ - ei_free(ptr); -} diff --git a/lib/erl_interface/src/legacy/erl_malloc.h b/lib/erl_interface/src/legacy/erl_malloc.h deleted file mode 100644 index 6cbc01faba..0000000000 --- a/lib/erl_interface/src/legacy/erl_malloc.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_MALLOC_H -#define _ERL_MALLOC_H - -/* FIXME: not documented */ -void *erl_realloc(void*, long); -int erl_current_fix_desc(void); - -#endif /* _ERL_MALLOC_H */ diff --git a/lib/erl_interface/src/legacy/erl_marshal.c b/lib/erl_interface/src/legacy/erl_marshal.c deleted file mode 100644 index 932bba43bf..0000000000 --- a/lib/erl_interface/src/legacy/erl_marshal.c +++ /dev/null @@ -1,2267 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2018. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* - * Purpose: Decoding and encoding Erlang terms. - */ -#include "eidef.h" - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <sys/types.h> -#include <string.h> -#include <limits.h> - -#include "erl_interface.h" -#include "erl_marshal.h" -#include "erl_eterm.h" -#include "erl_malloc.h" -#include "erl_error.h" -#include "erl_internal.h" - -#include "eiext.h" /* replaces external.h */ -#include "putget.h" - -static int is_string(ETERM* term); -#if defined(VXWORKS) && CPU == PPC860 -int erl_fp_compare(unsigned *a, unsigned *b); -static void erl_long_to_fp(long l, unsigned *d); -#endif - -static int cmpbytes(unsigned char* s1,int l1,unsigned char* s2,int l2); -static int cmpatoms(unsigned char* s1, int l1, unsigned char tag1, unsigned char* s2, int l2, unsigned char tag2); - -/* Used when comparing two encoded byte arrays */ -/* this global data is ok (from threading point of view) since it is - * initialized once and never changed - */ - -#define CMP_ARRAY_SIZE 256 -/* FIXME problem for threaded ? */ - -static enum -{ - ERL_NUM_CMP=1, ERL_ATOM_CMP, ERL_REF_CMP, ERL_FUN_CMP, ERL_PORT_CMP, - ERL_PID_CMP, ERL_TUPLE_CMP, ERL_NIL_CMP, ERL_LIST_CMP, ERL_BIN_CMP -}cmp_array[CMP_ARRAY_SIZE]; - -static int init_cmp_array_p=1; /* initialize array, the first time */ - -#if defined(VXWORKS) && CPU == PPC860 -#include <limits.h> -#endif - -#if defined(__GNUC__) -# define INLINE __inline__ -#elif defined(__WIN32__) -# define INLINE __inline -#else -# define INLINE -#endif - -static int cmp_floats(double f1, double f2); -static INLINE double to_float(long l); - -#define IS_ERL_NUM(t) (cmp_array[t]==ERL_NUM_CMP) -#define IS_ERL_ATOM(t) (cmp_array[t]==ERL_ATOM_CMP) - -#define CMP_NUM_CLASS_SIZE 256 -static unsigned char cmp_num_class[CMP_NUM_CLASS_SIZE]; -static int init_cmp_num_class_p=1; /* initialize array, the first time */ - -#define MK_CMP_NUM_CODE(x,y) (((x)<<2)|(y)) -#define CMP_NUM_CLASS(x) (cmp_num_class[x] & 0x03) -#define CMP_NUM_CODE(x,y) (MK_CMP_NUM_CODE(CMP_NUM_CLASS(x),CMP_NUM_CLASS(y))) - -#define SMALL 1 -#define FLOAT 2 -#define BIG 3 - -#define SMALL_SMALL MK_CMP_NUM_CODE(SMALL,SMALL) -#define SMALL_FLOAT MK_CMP_NUM_CODE(SMALL,FLOAT) -#define SMALL_BIG MK_CMP_NUM_CODE(SMALL,BIG) -#define FLOAT_SMALL MK_CMP_NUM_CODE(FLOAT,SMALL) -#define FLOAT_FLOAT MK_CMP_NUM_CODE(FLOAT,FLOAT) -#define FLOAT_BIG MK_CMP_NUM_CODE(FLOAT,BIG) -#define BIG_SMALL MK_CMP_NUM_CODE(BIG,SMALL) -#define BIG_FLOAT MK_CMP_NUM_CODE(BIG,FLOAT) -#define BIG_BIG MK_CMP_NUM_CODE(BIG,BIG) - -void erl_init_marshal(void) -{ - if (init_cmp_array_p) { - memset(cmp_array, 0, sizeof cmp_array); - cmp_array[ERL_SMALL_INTEGER_EXT] = ERL_NUM_CMP; - cmp_array[ERL_INTEGER_EXT] = ERL_NUM_CMP; - cmp_array[ERL_FLOAT_EXT] = ERL_NUM_CMP; - cmp_array[NEW_FLOAT_EXT] = ERL_NUM_CMP; - cmp_array[ERL_SMALL_BIG_EXT] = ERL_NUM_CMP; - cmp_array[ERL_LARGE_BIG_EXT] = ERL_NUM_CMP; - cmp_array[ERL_ATOM_EXT] = ERL_ATOM_CMP; - cmp_array[ERL_ATOM_UTF8_EXT] = ERL_ATOM_CMP; - cmp_array[ERL_SMALL_ATOM_EXT] = ERL_ATOM_CMP; - cmp_array[ERL_SMALL_ATOM_UTF8_EXT] = ERL_ATOM_CMP; - cmp_array[ERL_REFERENCE_EXT] = ERL_REF_CMP; - cmp_array[ERL_NEW_REFERENCE_EXT] = ERL_REF_CMP; - cmp_array[ERL_NEWER_REFERENCE_EXT]=ERL_REF_CMP; - cmp_array[ERL_FUN_EXT] = ERL_FUN_CMP; - cmp_array[ERL_NEW_FUN_EXT] = ERL_FUN_CMP; - cmp_array[ERL_PORT_EXT] = ERL_PORT_CMP; - cmp_array[ERL_NEW_PORT_EXT] = ERL_PORT_CMP; - cmp_array[ERL_PID_EXT] = ERL_PID_CMP; - cmp_array[ERL_NEW_PID_EXT] = ERL_PID_CMP; - cmp_array[ERL_SMALL_TUPLE_EXT] = ERL_TUPLE_CMP; - cmp_array[ERL_LARGE_TUPLE_EXT] = ERL_TUPLE_CMP; - cmp_array[ERL_NIL_EXT] = ERL_NIL_CMP; - cmp_array[ERL_STRING_EXT] = ERL_LIST_CMP; - cmp_array[ERL_LIST_EXT] = ERL_LIST_CMP; - cmp_array[ERL_BINARY_EXT] = ERL_BIN_CMP; - init_cmp_array_p = 0; - } - if (init_cmp_num_class_p) { - memset(cmp_num_class, 0, CMP_NUM_CLASS_SIZE); - 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; - } -} - -/* The encoder calls length, if erl_length() should return */ -/* -1 for dotted pairs (why !!!!) we can't use erl_length() */ -/* from the encoder in erl_marshal.c */ - -static int erl_length_x(const ETERM *ep) { - int n = 0; - - if (!ep) return -1; - - while (ERL_TYPE(ep) == ERL_LIST) { - n++; - ep = TAIL(ep); - } - - return n; -} - - -/*============================================================== - * Marshalling routines. - *============================================================== - */ - -static void encode_atom(Erl_Atom_data* a, unsigned char **ext) -{ - int ix = 0; - if (a->latin1) { - ei_encode_atom_len_as((char*)*ext, &ix, a->latin1, a->lenL, - ERLANG_LATIN1, ERLANG_UTF8); - } - else { - ei_encode_atom_len_as((char*)*ext, &ix, a->utf8, a->lenU, - ERLANG_UTF8, ERLANG_UTF8); - } - *ext += ix; -} - -/* - * The actual ENCODE engine. - * Returns 0 on success, otherwise 1. - */ -int erl_encode_it(ETERM *ep, unsigned char **ext, int dist) -{ - int i; - unsigned int u; - long long l; - unsigned long long ul; - - switch(ERL_TYPE(ep)) - { - case ERL_ATOM: - encode_atom(&ep->uval.aval.d, ext); - return 0; - - case ERL_INTEGER: - i = ep->uval.ival.i; - /* SMALL_INTEGER */ - if ((i < 256) && (i >= 0)) { - *(*ext)++ = ERL_SMALL_INTEGER_EXT; - *(*ext)++ = i & 0xff; - return 0; - } - /* R14B: Use all 32 bits of INTEGER_EXT */ - *(*ext)++ = ERL_INTEGER_EXT; - *(*ext)++ = (i >> 24) & 0xff; - *(*ext)++ = (i >> 16) & 0xff; - *(*ext)++ = (i >> 8) & 0xff; - *(*ext)++ = i & 0xff; - return 0; - - case ERL_U_INTEGER: - u = ep->uval.uival.u; - /* ERL_U_SMALL_BIG */ - 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) { - *(*ext)++ = ERL_SMALL_INTEGER_EXT; - *(*ext)++ = u & 0xff; - return 0; - } - /* R14B: Use all 32 bits of INTEGER_EXT */ - *(*ext)++ = ERL_INTEGER_EXT; - *(*ext)++ = (u >> 24) & 0xff; - *(*ext)++ = (u >> 16) & 0xff; - *(*ext)++ = (u >> 8) & 0xff; - *(*ext)++ = u & 0xff; - return 0; - case ERL_LONGLONG: - l = ep->uval.llval.i; - /* ERL_SMALL_BIG */ - 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 >> 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) & 0xff; - return 0; - } - /* SMALL_INTEGER */ - if ((l < 256) && (l >= 0)) { - *(*ext)++ = ERL_SMALL_INTEGER_EXT; - *(*ext)++ = l & 0xff; - return 0; - } - /* R14B: Use all 32 bits of INTEGER_EXT */ - *(*ext)++ = ERL_INTEGER_EXT; - *(*ext)++ = (l >> 24) & 0xff; - *(*ext)++ = (l >> 16) & 0xff; - *(*ext)++ = (l >> 8) & 0xff; - *(*ext)++ = l & 0xff; - return 0; - - case ERL_U_LONGLONG: - ul = ep->uval.ullval.u; - /* ERL_U_SMALL_BIG */ - if (ul > ((unsigned long long) INT_MAX)) { - *(*ext)++ = ERL_SMALL_BIG_EXT; - *(*ext)++ = 8; /* eight bytes */ - *(*ext)++ = 0; /* sign byte */ - *(*ext)++ = ul & 0xff; /* LSB first */ - *(*ext)++ = (ul >> 8) & 0xff; - *(*ext)++ = (ul >> 16) & 0xff; - *(*ext)++ = (ul >> 24) & 0xff; - *(*ext)++ = (ul >> 32) & 0xff; - *(*ext)++ = (ul >> 40) & 0xff; - *(*ext)++ = (ul >> 48) & 0xff; - *(*ext)++ = (ul >> 56) & 0xff; - return 0; - } - /* SMALL_INTEGER */ - if (ul < 256) { - *(*ext)++ = ERL_SMALL_INTEGER_EXT; - *(*ext)++ = ul & 0xff; - return 0; - } - /* R14B: Use all 32 bits of INTEGER_EXT */ - *(*ext)++ = ERL_INTEGER_EXT; - *(*ext)++ = (ul >> 24) & 0xff; - *(*ext)++ = (ul >> 16) & 0xff; - *(*ext)++ = (ul >> 8) & 0xff; - *(*ext)++ = ul & 0xff; - return 0; - - case ERL_PID: { - unsigned char* tagp = (*ext)++; - /* First poke in node as an atom */ - encode_atom(&ep->uval.pidval.node, ext); - /* And then fill in the integer fields */ - i = ERL_PID_NUMBER(ep); - *(*ext)++ = (i >> 24) &0xff; - *(*ext)++ = (i >> 16) &0xff; - *(*ext)++ = (i >> 8) &0xff; - *(*ext)++ = i &0xff; - i = ERL_PID_SERIAL(ep); - *(*ext)++ = (i >> 24) &0xff; - *(*ext)++ = (i >> 16) &0xff; - *(*ext)++ = (i >> 8) &0xff; - *(*ext)++ = i &0xff; - - i = ERL_PID_CREATION(ep); - if ((unsigned int)i <= 3) { - *tagp = ERL_PID_EXT; - *(*ext)++ = i; - } else { - *tagp = ERL_NEW_PID_EXT; - *(*ext)++ = (i >> 24) &0xff; - *(*ext)++ = (i >> 16) &0xff; - *(*ext)++ = (i >> 8) &0xff; - *(*ext)++ = i &0xff; - } - return 0; - } - case ERL_REF: { - unsigned char* tagp = (*ext)++; - - int len, j; - - /* Always encode as an extended reference; all - participating parties are now expected to be - able to decode extended references. */ - - i = strlen((char *)ERL_REF_NODE(ep)); - len = ERL_REF_LEN(ep); - *(*ext)++ = (len >> 8) &0xff; - *(*ext)++ = len &0xff; - - encode_atom(&ep->uval.refval.node, ext); - - i = ERL_REF_CREATION(ep); - if ((unsigned int)i <= 3) { - *tagp = ERL_NEW_REFERENCE_EXT; - *(*ext)++ = i; - } else { - *tagp = ERL_NEWER_REFERENCE_EXT; - *(*ext)++ = (i >> 24) &0xff; - *(*ext)++ = (i >> 16) &0xff; - *(*ext)++ = (i >> 8) &0xff; - *(*ext)++ = i &0xff; - } - - /* Then the integer fields */ - for (j = 0; j < ERL_REF_LEN(ep); j++) { - i = ERL_REF_NUMBERS(ep)[j]; - *(*ext)++ = (i >> 24) &0xff; - *(*ext)++ = (i >> 16) &0xff; - *(*ext)++ = (i >> 8) &0xff; - *(*ext)++ = i &0xff; - } - } - return 0; - case ERL_PORT: { - unsigned char* tagp = (*ext)++; - /* First poke in node as an atom */ - encode_atom(&ep->uval.portval.node, ext); - /* Then the integer fields */ - i = ERL_PORT_NUMBER(ep); - *(*ext)++ = (i >> 24) &0xff; - *(*ext)++ = (i >> 16) &0xff; - *(*ext)++ = (i >> 8) &0xff; - *(*ext)++ = i &0xff; - - i = ERL_PORT_CREATION(ep); - if ((unsigned int)i <= 3) { - *tagp = ERL_PORT_EXT; - *(*ext)++ = i; - } else { - *tagp = ERL_NEW_PORT_EXT; - *(*ext)++ = (i >> 24) &0xff; - *(*ext)++ = (i >> 16) &0xff; - *(*ext)++ = (i >> 8) &0xff; - *(*ext)++ = i &0xff; - } - return 0; - } - case ERL_EMPTY_LIST: - *(*ext)++ = ERL_NIL_EXT; - break; - case ERL_LIST: - i = is_string(ep); - if (0 < i && i < 0x10000) { /* String. */ - *(*ext)++ = ERL_STRING_EXT; - *(*ext)++ = (i >>8) &0xff; - *(*ext)++ = i &0xff; - while (ERL_TYPE(ep) == ERL_LIST) { - *(*ext)++ = HEAD(ep)->uval.ival.i; - ep = TAIL(ep); - } - break; - } else { /* List. */ - i = erl_length_x(ep); - *(*ext)++ = ERL_LIST_EXT; - *(*ext)++ = (i >> 24) &0xff; - *(*ext)++ = (i >> 16) &0xff; - *(*ext)++ = (i >> 8) &0xff; - *(*ext)++ = i &0xff; - while (ERL_TYPE(ep) == ERL_LIST) { - if (erl_encode_it(HEAD(ep), ext, dist)) - return 1; - ep = TAIL(ep); - } - i = erl_encode_it(ep, ext, dist); - return i; - } - case ERL_TUPLE: - i = ep->uval.tval.size; - if (i <= 0xff) { - *(*ext)++ = ERL_SMALL_TUPLE_EXT; - *(*ext)++ = i & 0xff; - } - else { - *(*ext)++ = ERL_LARGE_TUPLE_EXT; - *(*ext)++ = (i >> 24) & 0xff; - *(*ext)++ = (i >> 16) & 0xff; - *(*ext)++ = (i >> 8) & 0xff; - *(*ext)++ = i & 0xff; - } - for (i=0; i<ep->uval.tval.size; i++) - if (erl_encode_it(ep->uval.tval.elems[i], ext, dist)) - return 1; - break; - case ERL_FLOAT: - *(*ext)++ = ERL_FLOAT_EXT; - memset(*ext, 0, 31); - sprintf((char *) *ext, "%.20e", ep->uval.fval.f); - *ext += 31; - break; - case ERL_BINARY: - *(*ext)++ = ERL_BINARY_EXT; - i = ep->uval.bval.size; - *(*ext)++ = (i >> 24) & 0xff; - *(*ext)++ = (i >> 16) & 0xff; - *(*ext)++ = (i >> 8) & 0xff; - *(*ext)++ = i & 0xff; - memcpy((char *) *ext, (char*) ep->uval.bval.b, i); - *ext += i; - break; - case ERL_FUNCTION: - if (ERL_FUN_ARITY(ep) != -1) { - unsigned char *size_p = *ext + 1; - *(*ext)++ = ERL_NEW_FUN_EXT; - *ext += 4; - i = ERL_FUN_ARITY(ep); - put8(*ext, i); - memcpy(*ext, ERL_FUN_MD5(ep), 16); - *ext += 16; - i = ERL_FUN_NEW_INDEX(ep); - put32be(*ext, i); - i = ERL_CLOSURE_SIZE(ep); - put32be(*ext, i); - erl_encode_it(ERL_FUN_MODULE(ep), ext, dist); - erl_encode_it(ERL_FUN_INDEX(ep), ext, dist); - erl_encode_it(ERL_FUN_UNIQ(ep), ext, dist); - erl_encode_it(ERL_FUN_CREATOR(ep), ext, dist); - for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++) - erl_encode_it(ep->uval.funcval.closure[i], ext, dist); - if (size_p != NULL) { - i = *ext - size_p; - put32be(size_p, i); - } - } else { - *(*ext)++ = ERL_FUN_EXT; - i = ERL_CLOSURE_SIZE(ep); - *(*ext)++ = (i >> 24) & 0xff; - *(*ext)++ = (i >> 16) & 0xff; - *(*ext)++ = (i >> 8) & 0xff; - *(*ext)++ = i & 0xff; - erl_encode_it(ERL_FUN_CREATOR(ep), ext, dist); - erl_encode_it(ERL_FUN_MODULE(ep), ext, dist); - erl_encode_it(ERL_FUN_INDEX(ep), ext, dist); - erl_encode_it(ERL_FUN_UNIQ(ep), ext, dist); - for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++) - erl_encode_it(ep->uval.funcval.closure[i], ext, dist); - } - break; - default: - return 1; - } - return 0; -} - -/* - * ENCODE an ETERM into a BUFFER, assuming BUFFER is of - * enough size. At success return number of bytes written - * into it, otherwise return 0. - */ -static int erl_encode3(ETERM *ep, unsigned char *t, int dist) -{ - unsigned char *x = t; - - *x++ = ERL_VERSION_MAGIC; - if (erl_encode_it(ep, &x, dist)) { -#ifdef DEBUG - erl_err_msg("<ERROR> erl_encode: Error while encoding"); -#endif - return 0; - } - return (x - t); - -} - -/* API */ - -int erl_encode(ETERM *ep, unsigned char *t) -{ - return erl_encode3(ep, t, 4); -} - -/* determine the buffer size that will be required for the eterm */ -static int erl_term_len_helper(ETERM *ep, int dist); - -/* FIXME hard coded dist version */ -int erl_term_len(ETERM *ep) -{ - return 1+erl_term_len_helper(ep, 4); -} - -static int atom_len_helper(Erl_Atom_data* a) -{ - (void) erl_atom_ptr_utf8(a); - return 1 + 1 + (a->lenU > 255) + a->lenU; -} - -static int erl_term_len_helper(ETERM *ep, int dist) -{ - int len = 0; - int i; - unsigned int u; - long long l; - unsigned long long ul; - - if (ep) { - switch (ERL_TYPE(ep)) { - case ERL_ATOM: - len = atom_len_helper(&ep->uval.aval.d); - break; - - case ERL_INTEGER: - i = ep->uval.ival.i; - if ((i < 256) && (i >= 0)) len = 2; - else len = 5; - break; - - case ERL_U_INTEGER: - u = ep->uval.uival.u; - 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) 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) INT_MAX)) len = 11; - else if (ul < 256) len = 2; - else len = 5; - break; - - case ERL_PID: - len = 1 + atom_len_helper(&ep->uval.pidval.node) + 4 + 4 + 1; - break; - - case ERL_REF: - len = 1 + 2 + atom_len_helper(&ep->uval.refval.node) + 1 + ERL_REF_LEN(ep) * 4; - break; - - case ERL_PORT: - len = 1 + atom_len_helper(&ep->uval.portval.node) + 4 + 1; - break; - - case ERL_EMPTY_LIST: - len = 1; - break; - - case ERL_LIST: - i = is_string(ep); - if ((i > 0) && (i < 0x10000)) { /* string: 3 + strlen */ - for (len = 3; ERL_TYPE(ep) == ERL_LIST; ep = TAIL(ep)) { - len++; - } - } - else { /* list: 5 + len(elem1) + len(elem2) ... */ - for (len = 5; ERL_TYPE(ep) == ERL_LIST; ep = TAIL(ep)) { - len += erl_term_len_helper(HEAD(ep), dist); - } - len += erl_term_len_helper(ep, dist); /* last element */ - } - break; - - case ERL_TUPLE: - /* (2 or 5) + len(elem1) + len(elem2) ... */ - i = ep->uval.tval.size; - if (i <= 0xff) len = 2; - else len = 5; - - for (i=0; i<ep->uval.tval.size; i++) { - len += erl_term_len_helper(ep->uval.tval.elems[i], dist); - } - break; - - case ERL_FLOAT: - len = 32; - break; - - case ERL_BINARY: - i = ep->uval.bval.size; - len = 5 + i; - break; - - case ERL_FUNCTION: - if (ERL_FUN_ARITY(ep) == -1) { - len = 1 + 4; - len += erl_term_len_helper(ERL_FUN_CREATOR(ep),dist); - len += erl_term_len_helper(ERL_FUN_MODULE(ep),dist); - len += erl_term_len_helper(ERL_FUN_INDEX(ep),dist); - len += erl_term_len_helper(ERL_FUN_UNIQ(ep),dist); - for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++) - len += erl_term_len_helper(ERL_CLOSURE_ELEMENT(ep,i), dist); - } else { - len = 1 + 4 + 16 + 4 + 4; - len += erl_term_len_helper(ERL_FUN_MODULE(ep),dist); - len += erl_term_len_helper(ERL_FUN_INDEX(ep),dist); - len += erl_term_len_helper(ERL_FUN_UNIQ(ep),dist); - len += erl_term_len_helper(ERL_FUN_CREATOR(ep),dist); - for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++) - len += erl_term_len_helper(ERL_CLOSURE_ELEMENT(ep,i), dist); - } - break; - - default: -#ifdef DEBUG - fprintf(stderr, "Shouldn't happen: erl_term_len, unknown term type: '%c'\n",ERL_TYPE(ep)); -#endif - erl_errno = EINVAL; - exit(1); - } - } - - return len; -} - -/* - * This one makes it easy to ENCODE several CONSECUTIVE - * ETERM's into the same buffer. - */ -int erl_encode_buf(ETERM *ep, unsigned char **ext) -{ - unsigned char *start=*ext; - - *(*ext)++ = ERL_VERSION_MAGIC; - if (erl_encode_it(ep, ext, 0)) { -#ifdef DEBUG - erl_err_msg("<ERROR> erl_encode_buf: Error while encoding\n"); -#endif - return 0; - } - return (*ext - start); - -} /* erl_encode_buf */ - - -static int read_atom(unsigned char** ext, Erl_Atom_data* a) -{ - char buf[MAXATOMLEN_UTF8]; - int offs = 0; - erlang_char_encoding enc; - int ret = ei_decode_atom_as((char*)*ext, &offs, buf, MAXATOMLEN_UTF8, - ERLANG_LATIN1|ERLANG_UTF8, NULL, &enc); - *ext += offs; - - if (ret == 0) { - int i = strlen(buf); - char* clone = erl_malloc(i+1); - memcpy(clone, buf, i+1); - - a->latin1 = NULL; - a->lenL = 0; - a->utf8 = NULL; - a->lenU = 0; - if (enc & (ERLANG_LATIN1 | ERLANG_ASCII)) { - a->latin1 = clone; - a->lenL = i; - } - if (enc & (ERLANG_UTF8 | ERLANG_ASCII)) { - a->utf8 = clone; - a->lenU = i; - } - } - return ret; -} - -/* - * The actual DECODE engine. - * Returns NULL in case of failure. - */ -static ETERM *erl_decode_it(unsigned char **ext) -{ - char *cp; - ETERM *ep,*tp,*np; - unsigned int u,sign; - int i,j,arity; - double ff; - unsigned char tag; - - /* Assume we are going to decode an integer */ - ep = erl_alloc_eterm(ERL_INTEGER); - ERL_COUNT(ep) = 1; - - tag = *(*ext)++; - switch (tag) - { - case ERL_INTEGER_EXT: - i = (int) (**ext << 24) | ((*ext)[1] << 16) | - ((*ext)[2] << 8) | (*ext)[3]; - *ext += 4; - ep->uval.ival.i = i; - return ep; - - case ERL_SMALL_INTEGER_EXT: - i = *(*ext)++; - ep->uval.ival.i = i; - return ep; - - /* NOTE: The arity below for bigs is not really the arity (= number of digits) */ - /* It is the byte count and this might cause problems in other parts... */ - case ERL_SMALL_BIG_EXT: - arity = *(*ext)++; - goto big_cont; - case ERL_LARGE_BIG_EXT: - arity = (**ext << 24) | ((*ext)[1])<< 16 | - ((*ext)[2]) << 8 |((*ext)[3]); - *ext += 4; - big_cont: - -#ifdef _MSC_VER -#define MAX_TO_NEGATE 0x8000000000000000Ui64 -#else -#define MAX_TO_NEGATE 0x8000000000000000ULL -#endif - - sign = *(*ext)++; - if (arity > 8) - 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)); - ERL_TYPE(ep) = ERL_U_INTEGER; - ep->uval.uival.u = u; - /* *ext += i; */ - *ext += arity; - return ep; - } else if (arity == 4 && !((*ext)[3] & 0x80)) { - /* It will fit into an int !! - */ - 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; - return ep; - } else if (arity == 8 && ((*ext)[7] & 0x80) && !sign) { - /* Fits in an unsigned long long */ - int x; - unsigned long long ul = 0LL; - - for(x = 0 ; x < arity ; x++) { - ul |= ((unsigned long long)(*ext)[x]) << ((unsigned long long)(8*x)); - } - - ERL_TYPE(ep) = ERL_U_LONGLONG; - ep->uval.ullval.u = ul; - *ext += arity; - return ep; - } else { - /* Fits in a signed long long */ - int x; - unsigned long long l = 0LL; - long long sl; - - for(x = 0 ; x < arity ; x++) { - l |= ((unsigned long long)(*ext)[x]) << ((unsigned long long)(8*x)); - } - - sl = (long long)l; - - if (sign && l != MAX_TO_NEGATE) { - sl = -sl; - if (sl > 0) goto big_truncate; - } - - ERL_TYPE(ep) = ERL_LONGLONG; - ep->uval.llval.i = sl; - *ext += arity; - return ep; - } -#undef MAX_TO_NEGATE - big_truncate: - /* truncate to: (+/-) 1 */ -#ifdef DEBUG - erl_err_msg("<WARNING> erl_decode_it: Integer truncated..."); -#endif - ERL_TYPE(ep) = ERL_INTEGER; - ep->uval.ival.i = sign?-1:1; - *ext += arity; - return ep; - - case ERL_ATOM_EXT: - case ERL_SMALL_ATOM_EXT: - case ERL_ATOM_UTF8_EXT: - case ERL_SMALL_ATOM_UTF8_EXT: - - ERL_TYPE(ep) = ERL_ATOM; - --(*ext); - if (read_atom(ext, &ep->uval.aval.d) < 0) return NULL; - return ep; - - case ERL_PID_EXT: - case ERL_NEW_PID_EXT: - { - unsigned int number, serial; - unsigned int creation; - - ERL_TYPE(ep) = ERL_PID; - if (read_atom(ext, &ep->uval.pidval.node) < 0) return NULL; - - /* get the integers */ - number = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | - ((*ext)[2]) << 8 | ((*ext)[3]); - *ext += 4; - serial = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | - ((*ext)[2]) << 8 | ((*ext)[3]); - *ext += 4; - if (tag == ERL_PID_EXT) - creation = *(*ext)++; - else { - creation = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | - ((*ext)[2]) << 8 | ((*ext)[3]); - *ext += 4; - } - erl_mk_pid_helper(ep, number, serial, creation); - return ep; - } - case ERL_REFERENCE_EXT: - { - unsigned int n[3] = {0, 0, 0}; - unsigned char creation; - - ERL_TYPE(ep) = ERL_REF; - if (read_atom(ext, &ep->uval.refval.node) < 0) return NULL; - - /* get the integers */ - n[0] = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | - ((*ext)[2]) << 8 | ((*ext)[3]); - *ext += 4; - creation = *(*ext)++; - __erl_mk_reference(ep, NULL, 1, n, creation); - return ep; - } - - case ERL_NEW_REFERENCE_EXT: - case ERL_NEWER_REFERENCE_EXT: - { - size_t cnt, i; - unsigned int n[3]; - unsigned int creation; - - ERL_TYPE(ep) = ERL_REF; - cnt = ((*ext)[0] << 8) | (*ext)[1]; - *ext += 2; - - if (read_atom(ext, &ep->uval.refval.node) < 0) return NULL; - - /* get the integers */ - if (tag == ERL_NEW_REFERENCE_EXT) - creation = *(*ext)++; - else { - creation = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | - ((*ext)[2]) << 8 | ((*ext)[3]); - *ext += 4; - } - for(i = 0; i < cnt; i++) - { - n[i] = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | - ((*ext)[2]) << 8 | ((*ext)[3]); - *ext += 4; - } - __erl_mk_reference(ep, NULL, cnt, n, creation); - return ep; - } - - case ERL_PORT_EXT: - case ERL_NEW_PORT_EXT: - { - unsigned int number; - unsigned int creation; - - ERL_TYPE(ep) = ERL_PORT; - if (read_atom(ext, &ep->uval.portval.node) < 0) return NULL; - - /* get the integers */ - number = ((*ext)[0] << 24) | ((*ext)[1]) << 16 | - ((*ext)[2]) << 8 | ((*ext)[3]); - *ext += 4; - if (tag == ERL_PORT_EXT) - creation = *(*ext)++; - else { - creation = (((*ext)[0] << 24) | ((*ext)[1]) << 16 | - ((*ext)[2]) << 8 | ((*ext)[3])); - *ext += 4; - } - erl_mk_port_helper(ep, number, creation); - return ep; - } - - case ERL_NIL_EXT: - ERL_TYPE(ep) = ERL_EMPTY_LIST; - return ep; - - case ERL_LIST_EXT: - ERL_TYPE(ep) = ERL_LIST; - i = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3]; - *ext += 4; - /* ASSERT(i != 0); */ /* Should be represented by ERL_NIL_EXT. */ - tp = ep; - for (j = 0; j < i; j++) - if ((HEAD(tp) = erl_decode_it(ext)) == NULL) - goto failure; - else if (j + 1 < i) { - /* We have to watch out for how we allocates the - * last tail element since we may encounter non- - * well formed lists. - */ - np = erl_alloc_eterm(ERL_LIST); - ERL_COUNT(np) = 1; - TAIL(np) = NULL; /* in case of failure */ - TAIL(tp) = np; - tp = np; - } - if ((TAIL(tp) = erl_decode_it(ext)) == NULL) - goto failure; - return ep; - - case ERL_STRING_EXT: - { - unsigned char* s; - - ERL_TYPE(ep) = ERL_EMPTY_LIST; - i = (**ext << 8) | ((*ext)[1]); - *ext += 2; - s = *ext+i; - - while (*ext < s) { - ETERM* integer; - ETERM* cons; - - integer = erl_alloc_eterm(ERL_INTEGER); - ERL_COUNT(integer) = 1; - integer->uval.ival.i = *--s; - - cons = erl_alloc_eterm(ERL_LIST); - ERL_COUNT(cons) = 1; - HEAD(cons) = integer; - TAIL(cons) = ep; - ep = cons; - } - *ext += i; - return ep; - } - - case ERL_SMALL_TUPLE_EXT: - ERL_TYPE(ep) = ERL_TUPLE; - i = *(*ext)++; - goto decode_tuple; - - case ERL_LARGE_TUPLE_EXT: - i = (**ext << 24) | ((*ext)[1]) << 16 | - ((*ext)[2]) << 8 | ((*ext)[3]) ; - *ext += 4; - decode_tuple: - ep->uval.tval.size = i; - j = (i + 1) * sizeof(ETERM*); - ep->uval.tval.elems = (ETERM**) erl_malloc(j); - memset(ep->uval.tval.elems, 0, j); /* in case of failure below... */ - for (i=0; i<ep->uval.tval.size; i++) - if ((tp = erl_decode_it(ext)) == NULL) - goto failure; - else - ep->uval.tval.elems[i] = tp; - return ep; - - case ERL_FLOAT_EXT: - case NEW_FLOAT_EXT: - ERL_TYPE(ep) = ERL_FLOAT; - cp = (char *) *ext; - i = -1; - if (ei_decode_double(cp, &i, &ff) == -1) - goto failure; - *ext += i; - ep->uval.fval.f = ff; - return ep; - - case ERL_BINARY_EXT: - ERL_TYPE(ep) = ERL_BINARY; - i = (**ext << 24) | ((*ext)[1] << 16) | - ((*ext)[2] << 8) | (*ext)[3]; - *ext += 4; - ep->uval.bval.size = i; - ep->uval.bval.b = (unsigned char *) erl_malloc(i); - memcpy(ep->uval.bval.b, *ext, i); - *ext += i; - return ep; - - case ERL_FUN_EXT: /* FIXME: error checking */ - ERL_TYPE(ep) = ERL_FUNCTION; - i = get32be(*ext); - /*i = *(**ext << 24) | ((*ext)[1] << 16) | ((*ext)[2] << 8) | (*ext)[3]; - *ext += 4; */ - ERL_FUN_ARITY(ep) = -1; - ERL_CLOSURE_SIZE(ep) = i; - ERL_FUN_CREATOR(ep) = erl_decode_it(ext); - ERL_FUN_MODULE(ep) = erl_decode_it(ext); - ERL_FUN_INDEX(ep) = erl_decode_it(ext); - ERL_FUN_UNIQ(ep) = erl_decode_it(ext); - j = i * sizeof(ETERM*); - ERL_CLOSURE(ep) = (ETERM**) erl_malloc(j); - memset(ERL_CLOSURE(ep), 0, j); - for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++) - ERL_CLOSURE_ELEMENT(ep,i) = erl_decode_it(ext); - return ep; - - case ERL_NEW_FUN_EXT: /* FIXME: error checking */ - ERL_TYPE(ep) = ERL_FUNCTION; - i = get32be(*ext); /* size, we don't use it here */ - ERL_FUN_ARITY(ep) = get8(*ext); - memcpy(ERL_FUN_MD5(ep), *ext, 16); - *ext += 16; - ERL_FUN_NEW_INDEX(ep) = get32be(*ext); - i = get32be(*ext); - ERL_CLOSURE_SIZE(ep) = i; - ERL_FUN_MODULE(ep) = erl_decode_it(ext); - ERL_FUN_INDEX(ep) = erl_decode_it(ext); - ERL_FUN_UNIQ(ep) = erl_decode_it(ext); - ERL_FUN_CREATOR(ep) = erl_decode_it(ext); - j = i * sizeof(ETERM*); - ERL_CLOSURE(ep) = (ETERM**) erl_malloc(j); - memset(ERL_CLOSURE(ep), 0, j); - for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++) - ERL_CLOSURE_ELEMENT(ep,i) = erl_decode_it(ext); - return ep; - - } /* switch */ - - failure: - erl_free_term(ep); - return (ETERM *) NULL; - -} /* erl_decode_it */ - -/* - * DECODE a buffer of BYTES into an ETERM. - * Returns NULL in case of failure. - */ -ETERM *erl_decode(unsigned char *t) -{ - ETERM *ep; - unsigned char *ext; - - ext = t; - - /* We ignore the version magic since it might be - * possible that the buffer has been manipulated - * with erl_peek_ext. - */ - if (*ext == ERL_VERSION_MAGIC) - ext++; - - ep = NULL; - ep = erl_decode_it(&ext); -#ifdef DEBUG - if (!ep) erl_err_msg("<ERROR> erl_decode: Error while decoding"); -#endif - return ep; - -} /* erl_decode */ - -/* - * This one makes it possible to DECODE two CONSECUTIVE - * ETERM's in the same buffer. - */ -ETERM *erl_decode_buf(unsigned char **ext) -{ - ETERM *ep; - - /* We ignore the version magic since it might be - * possible that the buffer has been manipulated - * with erl_peek_ext. - */ - if (**ext == ERL_VERSION_MAGIC) - (*ext)++; - - ep = NULL; - ep = erl_decode_it(ext); -#ifdef DEBUG - if (!ep) erl_err_msg("<ERROR> erl_decode_buf: Error while decoding"); -#endif - return ep; - -} /* erl_decode_buf */ - - -/*============================================================== - * Ok, here comes routines for inspecting/manipulating - * an encoded buffer of bytes. - *============================================================== - */ - -/* - * Return 1 if the VERSION MAGIC in the BUFFER is the - * same as the this library version. - */ -int erl_verify_magic(unsigned char *ext) -{ - - if (*ext == ERL_VERSION_MAGIC) - return 1; - else - return 0; - -} /* erl_verify_magic */ - -/* - * Return the TYPE of an ENCODED ETERM. - * At failure, return 0. - */ -unsigned char erl_ext_type(unsigned char *ext) -{ - /* FIXME old code could skip multiple magic */ - - /* Move over magic number if any */ - if (*ext == ERL_VERSION_MAGIC) ext++; - - switch (*ext) { - case ERL_SMALL_INTEGER_EXT: - case ERL_INTEGER_EXT: - return ERL_INTEGER; - case ERL_ATOM_EXT: - case ERL_ATOM_UTF8_EXT: - case ERL_SMALL_ATOM_EXT: - case ERL_SMALL_ATOM_UTF8_EXT: - return ERL_ATOM; - case ERL_PID_EXT: - case ERL_NEW_PID_EXT: - return ERL_PID; - case ERL_PORT_EXT: - case ERL_NEW_PORT_EXT: - return ERL_PORT; - case ERL_REFERENCE_EXT: - case ERL_NEW_REFERENCE_EXT: - case ERL_NEWER_REFERENCE_EXT: - return ERL_REF; - case ERL_NIL_EXT: - return ERL_EMPTY_LIST; - case ERL_LIST_EXT: - return ERL_LIST; - case ERL_SMALL_TUPLE_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; - case ERL_FUN_EXT: - case ERL_NEW_FUN_EXT: - return ERL_FUNCTION; - case ERL_SMALL_BIG_EXT: - case ERL_LARGE_BIG_EXT: - return ERL_BIG; - default: - return 0; - - } /* switch */ - -} /* erl_ext_type */ - -/* - * Returns the number of elements in compund - * terms. For other kind of terms zero is returned. - * At failure -1 is returned. - */ -int erl_ext_size(unsigned char *t) -{ - int i; - unsigned char *v; - - if (*t == ERL_VERSION_MAGIC) - return erl_ext_size(t+1); - - v = t+1; - switch(*t) { - case ERL_SMALL_INTEGER_EXT: - case ERL_INTEGER_EXT: - case ERL_ATOM_EXT: - case ERL_ATOM_UTF8_EXT: - case ERL_SMALL_ATOM_EXT: - case ERL_SMALL_ATOM_UTF8_EXT: - case ERL_PID_EXT: - case ERL_NEW_PID_EXT: - case ERL_PORT_EXT: - case ERL_NEW_PORT_EXT: - case ERL_REFERENCE_EXT: - case ERL_NEW_REFERENCE_EXT: - case ERL_NEWER_REFERENCE_EXT: - case ERL_NIL_EXT: - case ERL_BINARY_EXT: - case ERL_STRING_EXT: - case ERL_FLOAT_EXT: - case NEW_FLOAT_EXT: - case ERL_SMALL_BIG_EXT: - case ERL_LARGE_BIG_EXT: - return 0; - break; - case ERL_SMALL_TUPLE_EXT: - i = v[0]; - return i; - break; - case ERL_LIST_EXT: - case ERL_LARGE_TUPLE_EXT: - i = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3]; - return i; - break; - case ERL_FUN_EXT: - i = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3]; - return i+4; - break; - case ERL_NEW_FUN_EXT: - v += 4 + 1 + 16 + 4; - i = get32be(v); - return i + 4; - break; - default: - return -1; - break; - } /* switch */ - -} /* ext_size */ - - -static int jump_atom(unsigned char** ext) -{ - unsigned char* e = *ext; - int len; - - switch (*e++) { - case ERL_ATOM_EXT: - case ERL_ATOM_UTF8_EXT: - len = (e[0] << 8) | e[1]; - e += (len + 2); - break; - - case ERL_SMALL_ATOM_EXT: - case ERL_SMALL_ATOM_UTF8_EXT: - len = e[0]; - e += (len + 1); - break; - - default: - return 0; - } - *ext = e; - return 1; -} - - -/* - * MOVE the POINTER PAST the ENCODED ETERM we - * are currently pointing at. Returns 1 at - * success, otherwise 0. - */ -static int jump(unsigned char **ext) -{ - int j,k,i=0; - int n; - const int tag = *(*ext)++; - - switch (tag) { - case ERL_VERSION_MAGIC: - return jump(ext); - case ERL_INTEGER_EXT: - *ext += 4; - break; - case ERL_SMALL_INTEGER_EXT: - *ext += 1; - break; - case ERL_ATOM_EXT: - case ERL_ATOM_UTF8_EXT: - case ERL_SMALL_ATOM_EXT: - case ERL_SMALL_ATOM_UTF8_EXT: - jump_atom(ext); - break; - case ERL_PID_EXT: - if (!jump_atom(ext)) return 0; - *ext += 4 + 4 + 1; - break; - case ERL_NEW_PID_EXT: - if (!jump_atom(ext)) return 0; - *ext += 4 + 4 + 4; - break; - case ERL_REFERENCE_EXT: - case ERL_PORT_EXT: - if (!jump_atom(ext)) return 0; - *ext += 4 + 1; - break; - case ERL_NEW_PORT_EXT: - if (!jump_atom(ext)) return 0; - *ext += 4 + 4; - break; - case ERL_NEW_REFERENCE_EXT: - case ERL_NEWER_REFERENCE_EXT: - n = (**ext << 8) | (*ext)[1]; - *ext += 2; - /* first field is an atom */ - if (!jump_atom(ext)) return 0; - *ext += 4*n + (tag == ERL_NEW_REFERENCE_EXT ? 1 : 4); - break; - case ERL_NIL_EXT: - /* We just passed it... */ - break; - case ERL_LIST_EXT: - i = j = 0; - j = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3]; - *ext += 4; - for(k=0; k<j; k++) - if ((i = jump(ext)) == 0) - return(0); - if (**ext == ERL_NIL_EXT) { - *ext += 1; - break; - } - if (jump(ext) == 0) return 0; - break; - case ERL_STRING_EXT: - i = **ext << 8 | (*ext)[1]; - *ext += 2 + i; - break; - case ERL_SMALL_TUPLE_EXT: - i = *(*ext)++; - goto jump_tuple; - case ERL_LARGE_TUPLE_EXT: - i = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3]; - *ext += 4; - jump_tuple: - for (j = 0; j < i; j++) - if ((k = jump(ext)) == 0) - return(0); - break; - 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; - break; - case ERL_FUN_EXT: - i = (**ext << 24) | ((*ext)[1] << 16) |((*ext)[2] << 8) | (*ext)[3]; - *ext += 4; - i += 4; - for (j = 0; j < i; j++) - if ((k = jump(ext)) == 0) - return(0); - break; - case ERL_NEW_FUN_EXT: - i = get32be(*ext); - *ext += i + 4; - break; - case ERL_SMALL_BIG_EXT: - i = *(*ext); - *ext += i + 1; - break; - case ERL_LARGE_BIG_EXT: - i = get32be(*ext); - *ext += i + 4; - break; - default: - return 0; - } /* switch */ - - return 1; - -} /* jump */ - -/* - * The actual PEEK engine. - */ -static unsigned char *peek_ext(unsigned char **ext, int jumps) -{ - int i; - - switch (*(*ext)++) - { - case ERL_VERSION_MAGIC: - return peek_ext(ext, jumps); - case ERL_SMALL_TUPLE_EXT: - i = *(*ext)++; - goto do_the_peek_stuff; - case ERL_LARGE_TUPLE_EXT: - case ERL_LIST_EXT: - i = (**ext << 24) | ((*ext)[1]) << 16| ((*ext)[2]) << 8| ((*ext)[3]) ; - *ext += 4; - do_the_peek_stuff: - if (i <= jumps) { -#ifdef DEBUG - erl_err_msg("<ERROR> peek_ext: Out of range"); -#endif - return NULL; - } - for(i=0; i<jumps; i++) - if (!jump(ext)) { -#ifdef DEBUG - erl_err_msg("<ERROR> peek_ext: Bad data"); -#endif - return NULL; - } - return *ext; - default: -#ifdef DEBUG - erl_err_msg("<ERROR> peek_ext: Can't peek in non list/tuple type"); -#endif - return NULL; - } /* switch */ - -} /* peek_ext */ - -/* - * Return a POINTER TO the N:TH ELEMENT in a - * COMPUND ENCODED ETERM. - */ -unsigned char *erl_peek_ext(unsigned char *ext, int jumps) -{ - unsigned char *x=ext; - - return peek_ext(&x, jumps); - -} /* erl_peek_ext */ - -/* - * Lexically compare two strings of bytes, - * (string s1 length l1 and s2 l2). - * Return: -1 if s1 < s2 - * 0 if s1 = s2 - * 1 if s1 > s2 - */ -static int cmpbytes(unsigned char* s1,int l1,unsigned char* s2,int l2) -{ - int i; - i = 0; - while((i < l1) && (i < l2)) { - if (s1[i] < s2[i]) return(-1); - if (s1[i] > s2[i]) return(1); - i++; - } - if (l1 < l2) return(-1); - if (l1 > l2) return(1); - return(0); - -} /* cmpbytes */ - -#define tag2enc(T) ((T)==ERL_ATOM_EXT || (T)==ERL_SMALL_ATOM_EXT ? ERLANG_LATIN1 : ERLANG_UTF8) - -static int cmpatoms(unsigned char* s1, int l1, unsigned char tag1, - unsigned char* s2, int l2, unsigned char tag2) -{ - erlang_char_encoding enc1 = tag2enc(tag1); - erlang_char_encoding enc2 = tag2enc(tag2); - - if (enc1 == enc2) { - return cmpbytes(s1, l1,s2,l2); - } - - if (enc1 == ERLANG_LATIN1) { - return cmp_latin1_vs_utf8((char*)s1, l1, (char*)s2, l2); - } - else { - return -cmp_latin1_vs_utf8((char*)s2, l2, (char*)s1, l1); - } -} - -int cmp_latin1_vs_utf8(const char* strL, int lenL, const char* strU, int lenU) -{ - unsigned char* sL = (unsigned char*)strL; - unsigned char* sU = (unsigned char*)strU; - unsigned char* sL_end = sL + lenL; - unsigned char* sU_end = sU + lenU; - - while(sL < sL_end && sU < sU_end) { - unsigned char UasL; - if (*sL >= 0x80) { - if (*sU < 0xC4 && (sU+1) < sU_end) { - UasL = ((sU[0] & 0x3) << 6) | (sU[1] & 0x3F); - } - else return -1; - } - else { - UasL = *sU; - } - if (*sL < UasL) return -1; - if (*sL > UasL) return 1; - - sL++; - if (*sU < 0x80) sU++; - else if (*sU < 0xE0) sU += 2; - else if (*sU < 0xF0) sU += 3; - else /*if (*sU < 0xF8)*/ sU += 4; - } - - return (sU >= sU_end) - (sL >= sL_end); /* -1, 0 or 1 */ -} - - -#define CMP_EXT_ERROR_CODE 4711 - -#define CMP_EXT_INT32_BE(AP, BP) \ -do { \ - if ((AP)[0] != (BP)[0]) return (AP)[0] < (BP)[0] ? -1 : 1; \ - if ((AP)[1] != (BP)[1]) return (AP)[1] < (BP)[1] ? -1 : 1; \ - if ((AP)[2] != (BP)[2]) return (AP)[2] < (BP)[2] ? -1 : 1; \ - if ((AP)[3] != (BP)[3]) return (AP)[3] < (BP)[3] ? -1 : 1; \ -} while (0) - -#define CMP_EXT_SKIP_ATOM(EP) \ -do { \ - if (!jump_atom(&(EP))) \ - return CMP_EXT_ERROR_CODE; \ -} while (0) - -/* - * We now know that both byte arrays are of the same type. - */ -static int compare_top_ext(unsigned char**, unsigned char **); /* forward */ -static int cmp_exe2(unsigned char **e1, unsigned char **e2); - -static int cmp_refs(unsigned char **e1, unsigned char **e2) -{ - int tmp, n1, n2; - unsigned char *node1, *node2, *id1, *id2, cre1, cre2; - - if (*((*e1)++) == ERL_REFERENCE_EXT) { - node1 = *e1; - CMP_EXT_SKIP_ATOM(*e1); - n1 = 1; - id1 = *e1; - cre1 = (*e1)[4]; - *e1 += 5; - } else { - n1 = get16be(*e1); - node1 = *e1; - CMP_EXT_SKIP_ATOM(*e1); - cre1 = **e1; - id1 = (*e1) + 1 + (n1 - 1)*4; - *e1 = id1 + 4; - } - - if (*((*e2)++) == ERL_REFERENCE_EXT) { - node2 = *e2; - CMP_EXT_SKIP_ATOM(*e2); - n2 = 1; - id2 = *e2; - cre2 = (*e2)[4]; - *e2 += 5; - } else { - n2 = get16be(*e2); - node2 = *e2; - CMP_EXT_SKIP_ATOM(*e2); - cre2 = **e2; - id2 = (*e2) + 1 + (n2 - 1)*4; - *e2 = id2 + 4; - } - - /* First compare node names... */ - tmp = cmp_exe2(&node1, &node2); - if (tmp != 0) - return tmp; - - /* ... then creations ... */ - if (cre1 != cre2) - return cre1 < cre2 ? -1 : 1; - - /* ... and then finally ids. */ - if (n1 != n2) { - unsigned char zero[] = {0, 0, 0, 0}; - if (n1 > n2) - do { - CMP_EXT_INT32_BE(id1, zero); - id1 -= 4; - n1--; - } while (n1 > n2); - else - do { - CMP_EXT_INT32_BE(zero, id2); - id2 -= 4; - n2--; - } while (n2 > n1); - } - - for (; n1 > 0; n1--, id1 -= 4, id2 -= 4) - CMP_EXT_INT32_BE(id1, id2); - - return 0; -} - -static int cmp_string_list(unsigned char **e1, unsigned char **e2) { - - /* we need to compare a string in **e1 and a list in **e2 */ - /* convert the string to list representation and convert that with e2 */ - /* we need a temporary buffer of: */ - /* 5 (list tag + length) + 2*string length + 1 (end of list tag) */ - /* for short lists we use a stack allocated buffer, otherwise we malloc */ - - unsigned char *bp; - unsigned char buf[5+2*255+1]; /* used for short lists */ - int i,e1_len; - int res; - - e1_len = ((*e1)[1] << 8) | ((*e1)[2]); - if ( e1_len < 256 ) { - bp = buf; - } else { - bp = erl_malloc(5+(2*e1_len)+1); - } - - bp[0] = ERL_LIST_EXT; - bp[1] = bp[2] = 0; - bp[3] = (*e1)[1]; - bp[4] = (*e1)[2]; - - for(i=0;i<e1_len;i++) { - bp[5+2*i] = ERL_SMALL_INTEGER_EXT; - bp[5+2*i+1] = (*e1)[3+i]; - } - - bp[5+2*e1_len] = ERL_NIL_EXT; - - res = cmp_exe2(&bp, e2); - - if ( e1_len >= 256 ) free(bp); - - return res; -} - -static int cmp_exe2(unsigned char **e1, unsigned char **e2) -{ - int min, ret,i,j,k; - double ff1, ff2; - unsigned char tag1, tag2; - - if ( ((*e1)[0] == ERL_STRING_EXT) && ((*e2)[0] == ERL_LIST_EXT) ) { - return cmp_string_list(e1, e2); - } else if ( ((*e1)[0] == ERL_LIST_EXT) && ((*e2)[0] == ERL_STRING_EXT) ) { - return -cmp_string_list(e2, e1); - } - - tag1 = *(*e1)++; - tag2 = *(*e2)++; - i = j = 0; - switch (tag1) - { - case ERL_SMALL_INTEGER_EXT: - if (**e1 < **e2) ret = -1; - else if (**e1 > **e2) ret = 1; - else ret = 0; - *e1 += 1; *e2 += 1; - return ret; - case ERL_INTEGER_EXT: - i = (int) (**e1 << 24) | ((*e1)[1] << 16) |((*e1)[2] << 8) | (*e1)[3]; - j = (int) (**e2 << 24) | ((*e2)[1] << 16) |((*e2)[2] << 8) | (*e2)[3]; - if ( i < j) - ret = -1; - else if ( i > j) - ret = 1; - else - ret = 0; - *e1 += 4; *e2 += 4; - return ret; - case ERL_ATOM_EXT: - case ERL_ATOM_UTF8_EXT: - i = (**e1) << 8; (*e1)++; - j = (**e2) << 8; (*e2)++; - /*fall through*/ - case ERL_SMALL_ATOM_EXT: - case ERL_SMALL_ATOM_UTF8_EXT: - i |= (**e1); (*e1)++; - j |= (**e2); (*e2)++; - ret = cmpatoms(*e1, i, tag1, *e2, j, tag2); - *e1 += i; - *e2 += j; - return ret; - case ERL_PID_EXT: - case ERL_NEW_PID_EXT: { - erlang_pid pid1, pid2; - unsigned char* buf1 = *e1 - 1; - unsigned char* buf2 = *e2 - 1; - int ix1 = 0, ix2 = 0; - - if (ei_decode_pid((char*)buf1, &ix1, &pid1) || - ei_decode_pid((char*)buf2, &ix2, &pid2)) - return CMP_EXT_ERROR_CODE; - - *e1 = buf1 + ix1; - *e2 = buf2 + ix2; - - /* First compare serials ... */ - if (pid1.serial < pid2.serial) return -1; - else if (pid1.serial > pid2.serial) return 1; - - /* ... then ids ... */ - if (pid1.num < pid2.num) return -1; - else if (pid1.num > pid2.num) return 1; - - /* ... then node names ... */ - j = strcmp(pid1.node, pid2.node); - if (j < 0) return -1; - else if (j > 0) return 1; - - /* ... and then finaly creations. */ - if (pid1.creation < pid2.creation) return -1; - else if (pid1.creation > pid2.creation) return 1; - - return 0; - } - case ERL_PORT_EXT: - case ERL_NEW_PORT_EXT: { - erlang_port port1, port2; - unsigned char* buf1 = *e1 - 1; - unsigned char* buf2 = *e2 - 1; - int ix1 = 0, ix2 = 0; - - if (ei_decode_port((char*)buf1, &ix1, &port1) || - ei_decode_port((char*)buf2, &ix2, &port2)) - return CMP_EXT_ERROR_CODE; - - *e1 = buf1 + ix1; - *e2 = buf2 + ix2; - - /* First compare node names ... */ - j = strcmp(port1.node, port2.node); - if (j < 0) return -1; - else if (j > 0) return 1; - - /* ... then creations ... */ - if (port1.creation < port2.creation) return -1; - else if (port1.creation > port2.creation) return 1; - - /* ... and then finally ids. */ - if (port1.id < port2.id) return -1; - else if (port1.id > port2.id) return 1; - - return 0; - } - case ERL_NIL_EXT: return 0; - case ERL_LIST_EXT: - i = (**e1 << 24) | ((*e1)[1] << 16) |((*e1)[2] << 8) | (*e1)[3]; - *e1 += 4; - j = (**e2 << 24) | ((*e2)[1] << 16) |((*e2)[2] << 8) | (*e2)[3]; - *e2 += 4; - if ( i == j && j == 0 ) return 0; - min = (i < j) ? i : j; - k = 0; - while (1) { - if (k++ == min){ - if (i == j) return compare_top_ext(e1 , e2); - 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]); - *e1 += 2; - j = (**e2 << 8) | ((*e2)[1]); - *e2 += 2; - ret = cmpbytes(*e1, i, *e2, j); - *e1 += i; - *e2 += j; - return ret; - case ERL_SMALL_TUPLE_EXT: - i = *(*e1)++; j = *(*e2)++; - if (i < j) return -1; - if (i > j ) return 1; - while (i--) { - if ((j = compare_top_ext(e1, e2))) return j; - } - return 0; - case ERL_LARGE_TUPLE_EXT: - i = (**e1 << 24) | ((*e1)[1]) << 16| ((*e1)[2]) << 8| ((*e1)[3]) ; - *e1 += 4; - j = (**e2 << 24) | ((*e2)[1]) << 16| ((*e2)[2]) << 8| ((*e2)[3]) ; - *e2 += 4; - if (i < j) return -1; - if (i > j ) return 1; - while (i--) { - if ((j = compare_top_ext(e1, e2))) return j; - } - return 0; - case ERL_FLOAT_EXT: - 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: - i = (**e1 << 24) | ((*e1)[1] << 16) |((*e1)[2] << 8) | (*e1)[3]; - *e1 += 4; - j = (**e2 << 24) | ((*e2)[1] << 16) |((*e2)[2] << 8) | (*e2)[3]; - *e2 += 4; - ret = cmpbytes(*e1, i , *e2 , j); - *e1 += i; *e2 += j; - return ret; - - case ERL_FUN_EXT: /* FIXME: */ - case ERL_NEW_FUN_EXT: /* FIXME: */ - return -1; - - default: - return cmpbytes(*e1, 1, *e2, 1); - - } /* switch */ - -} /* cmp_exe2 */ - -/* Number compare */ - -static int cmp_floats(double f1, double f2) -{ -#if defined(VXWORKS) && CPU == PPC860 - return erl_fp_compare((unsigned *) &f1, (unsigned *) &f2); -#else - if (f1<f2) return -1; - else if (f1>f2) return 1; - else return 0; -#endif -} - -static INLINE double to_float(long l) -{ - double f; -#if defined(VXWORKS) && CPU == PPC860 - erl_long_to_fp(l, (unsigned *) &f); -#else - f = l; -#endif - return f; -} - - -static int cmp_small_big(unsigned char**e1, unsigned char **e2) -{ - int i1,i2; - int t2; - int n2; - long l1; - int res; - - erlang_big *b1,*b2; - - i1 = i2 = 0; - if ( ei_decode_long((char *)*e1,&i1,&l1) < 0 ) return -1; - - ei_get_type((char *)*e2,&i2,&t2,&n2); - - /* any small will fit in two digits */ - if ( (b1 = ei_alloc_big(2)) == NULL ) return -1; - if ( ei_small_to_big(l1,b1) < 0 ) { - ei_free_big(b1); - return -1; - } - - if ( (b2 = ei_alloc_big(n2)) == NULL ) { - ei_free_big(b1); - return 1; - } - - if ( ei_decode_big((char *)*e2,&i2,b2) < 0 ) { - ei_free_big(b1); - ei_free_big(b2); - return 1; - } - - res = ei_big_comp(b1,b2); - - ei_free_big(b1); - ei_free_big(b2); - - *e1 += i1; - *e2 += i2; - - return res; -} - -static int cmp_small_float(unsigned char**e1, unsigned char **e2) -{ - int i1,i2; - long l1; - double f1,f2; - - /* small -> float -> float_comp */ - - i1 = i2 = 0; - if ( ei_decode_long((char *)*e1,&i1,&l1) < 0 ) return -1; - if ( ei_decode_double((char *)*e2,&i2,&f2) < 0 ) return 1; - - f1 = to_float(l1); - - *e1 += i1; - *e2 += i2; - - return cmp_floats(f1,f2); -} - -static int cmp_float_big(unsigned char**e1, unsigned char **e2) -{ - int res; - int i1,i2; - int t2,n2; - double f1,f2; - erlang_big *b2; - - /* big -> float if overflow return big sign else float_comp */ - - i1 = i2 = 0; - if ( ei_decode_double((char *)*e1,&i1,&f1) < 0 ) return -1; - - if (ei_get_type((char *)*e2,&i2,&t2,&n2) < 0) return 1; - if ((b2 = ei_alloc_big(n2)) == NULL) return 1; - if (ei_decode_big((char *)*e2,&i2,b2) < 0) return 1; - - /* convert the big to float */ - if ( ei_big_to_double(b2,&f2) < 0 ) { - /* exception look at the sign */ - res = b2->is_neg ? 1 : -1; - ei_free_big(b2); - return res; - } - - ei_free_big(b2); - - *e1 += i1; - *e2 += i2; - - return cmp_floats(f1,f2); -} - -static int cmp_small_small(unsigned char**e1, unsigned char **e2) -{ - int i1,i2; - long l1,l2; - - i1 = i2 = 0; - if ( ei_decode_long((char *)*e1,&i1,&l1) < 0 ) { - fprintf(stderr,"Failed to decode 1\r\n"); - return -1; - } - if ( ei_decode_long((char *)*e2,&i2,&l2) < 0 ) { - fprintf(stderr,"Failed to decode 2\r\n"); - return 1; - } - - *e1 += i1; - *e2 += i2; - - if ( l1 < l2 ) return -1; - else if ( l1 > l2 ) return 1; - else return 0; -} - -static int cmp_float_float(unsigned char**e1, unsigned char **e2) -{ - int i1,i2; - double f1,f2; - - i1 = i2 = 0; - if ( ei_decode_double((char *)*e1,&i1,&f1) < 0 ) return -1; - if ( ei_decode_double((char *)*e2,&i2,&f2) < 0 ) return 1; - - *e1 += i1; - *e2 += i2; - - return cmp_floats(f1,f2); -} - -static int cmp_big_big(unsigned char**e1, unsigned char **e2) -{ - int res; - int i1,i2; - int t1,t2; - int n1,n2; - erlang_big *b1,*b2; - - i1 = i2 = 0; - ei_get_type((char *)*e1,&i1,&t1,&n1); - ei_get_type((char *)*e2,&i2,&t2,&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); - - res = ei_big_comp(b1,b2); - - ei_free_big(b1); - ei_free_big(b2); - - *e1 += i1; - *e2 += i2; - - return res; -} - -static int cmp_number(unsigned char**e1, unsigned char **e2) -{ - switch (CMP_NUM_CODE(**e1,**e2)) { - - case SMALL_BIG: - /* fprintf(stderr,"compare small_big\r\n"); */ - return cmp_small_big(e1,e2); - - case BIG_SMALL: - /* fprintf(stderr,"compare sbig_small\r\n"); */ - return -cmp_small_big(e2,e1); - - case SMALL_FLOAT: - /* fprintf(stderr,"compare small_float\r\n"); */ - return cmp_small_float(e1,e2); - - case FLOAT_SMALL: - /* fprintf(stderr,"compare float_small\r\n"); */ - return -cmp_small_float(e2,e1); - - case FLOAT_BIG: - /* fprintf(stderr,"compare float_big\r\n"); */ - return cmp_float_big(e1,e2); - - case BIG_FLOAT: - /* fprintf(stderr,"compare big_float\r\n"); */ - return -cmp_float_big(e2,e1); - - case SMALL_SMALL: - /* fprintf(stderr,"compare small_small\r\n"); */ - return cmp_small_small(e1,e2); - - case FLOAT_FLOAT: - /* fprintf(stderr,"compare float_float\r\n"); */ - return cmp_float_float(e1,e2); - - case BIG_BIG: - /* fprintf(stderr,"compare big_big\r\n"); */ - return cmp_big_big(e1,e2); - - default: - /* should never get here ... */ - /* fprintf(stderr,"compare standard\r\n"); */ - return cmp_exe2(e1,e2); - } - -} - -/* - * If the arrays are of the same type, then we - * have to do a real compare. - */ -/* - * COMPARE TWO encoded BYTE ARRAYS e1 and e2. - * Return: -1 if e1 < e2 - * 0 if e1 == e2 - * 1 if e2 > e1 - */ -static int compare_top_ext(unsigned char**e1, unsigned char **e2) -{ - if (**e1 == ERL_VERSION_MAGIC) (*e1)++; - if (**e2 == ERL_VERSION_MAGIC) (*e2)++; - - if (cmp_array[**e1] < cmp_array[**e2]) return -1; - if (cmp_array[**e1] > cmp_array[**e2]) return 1; - - if (IS_ERL_NUM(**e1)) - return cmp_number(e1,e2); - - if (cmp_array[**e1] == ERL_REF_CMP) - return cmp_refs(e1, e2); - - return cmp_exe2(e1, e2); -} - -int erl_compare_ext(unsigned char *e1, unsigned char *e2) -{ - return compare_top_ext(&e1, &e2); -} /* erl_compare_ext */ - -#if defined(VXWORKS) && CPU == PPC860 -/* FIXME we have no floating point but don't we have emulation?! */ -int erl_fp_compare(unsigned *a, unsigned *b) -{ - /* Big endian mode of powerPC, IEEE floating point. */ - unsigned a_split[4] = {a[0] >> 31, /* Sign bit */ - (a[0] >> 20) & 0x7FFU, /* Exponent */ - a[0] & 0xFFFFFU, /* Mantissa MS bits */ - a[1]}; /* Mantissa LS bits */ - unsigned b_split[4] = {b[0] >> 31, - (b[0] >> 20) & 0x7FFU, - b[0] & 0xFFFFFU, - b[1]}; - int a_is_infinite, b_is_infinite; - int res; - - - /* Make -0 be +0 */ - if (a_split[1] == 0 && a_split[2] == 0 && a_split[3] == 0) - a_split[0] = 0; - if (b_split[1] == 0 && b_split[2] == 0 && b_split[3] == 0) - b_split[0] = 0; - /* Check for infinity */ - a_is_infinite = (a_split[1] == 0x7FFU && a_split[2] == 0 && - a_split[3] == 0); - b_is_infinite = (b_split[1] == 0x7FFU && b_split[2] == 0 && - b_split[3] == 0); - - if (a_is_infinite && !b_is_infinite) - return (a_split[0]) ? -1 : 1; - if (b_is_infinite && !a_is_infinite) - return (b_split[0]) ? 1 : -1; - if (a_is_infinite && b_is_infinite) - return b[0] - a[0]; - /* Check for indeterminate or nan, infinite is already handled, - so we only check the exponent. */ - if((a_split[1] == 0x7FFU) || (b_split[1] == 0x7FFU)) - return INT_MAX; /* Well, they are not equal anyway, - abort() could be an alternative... */ - - if (a_split[0] && !b_split[0]) - return -1; - if (b_split[0] && !a_split[0]) - return 1; - /* Compare */ - res = memcmp(a_split + 1, b_split + 1, 3 * sizeof(unsigned)); - /* Make -1, 0 or 1 */ - res = (!!res) * ((res < 0) ? -1 : 1); - /* Turn sign if negative values */ - if (a_split[0]) /* Both are negative */ - res = -1 * res; - return res; -} - -static void join(unsigned d_split[4], unsigned *d) -{ - d[0] = (d_split[0] << 31) | /* Sign bit */ - ((d_split[1] & 0x7FFU) << 20) | /* Exponent */ - (d_split[2] & 0xFFFFFU); /* Mantissa MS bits */ - d[1] = d_split[3]; /* Mantissa LS bits */ -} - -static int blength(unsigned long l) -{ - int i; - for(i = 0; l; ++i) - l >>= 1; - return i; -} - -static void erl_long_to_fp(long l, unsigned *d) -{ - unsigned d_split[4]; - unsigned x; - if (l < 0) { - d_split[0] = 1; - x = -l; - } else { - d_split[0] = 0; - x = l; - } - - if (!l) { - memset(d_split,0,sizeof(d_split)); - } else { - int len = blength(x); - x <<= (33 - len); - d_split[2] = (x >> 12); - d_split[3] = (x << 20); - d_split[1] = 1023 + len - 1; - } - join(d_split,d); -} - -#endif - - -/* - * Checks if a term is a "string": a flat list of byte-sized integers. - * - * Returns: 0 if the term is not a string, otherwise the length is returned. - */ - -static int is_string(ETERM* term) -{ - int len = 0; - - while (ERL_TYPE(term) == ERL_LIST) { - ETERM* head = HEAD(term); - - if (!ERL_IS_INTEGER(head) || ((unsigned)head->uval.ival.i) > 255) { - return 0; - } - len++; - term = TAIL(term); - } - - if (ERL_IS_EMPTY_LIST(term)) { - return len; - } - return 0; -} diff --git a/lib/erl_interface/src/legacy/erl_marshal.h b/lib/erl_interface/src/legacy/erl_marshal.h deleted file mode 100644 index c1963b832d..0000000000 --- a/lib/erl_interface/src/legacy/erl_marshal.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_MARSHALL_H -#define _ERL_MARSHALL_H - -#include "erl_eterm.h" /* FIXME don't want to include this here */ - -/* FIXME: not documented, may be internal */ -int erl_verify_magic(unsigned char*); -void erl_init_marshal(void); -int erl_encode_it(ETERM *ep, unsigned char **ext, int dist); - -#endif /* _ERL_MARSHALL_H */ diff --git a/lib/erl_interface/src/legacy/erl_resolve.c b/lib/erl_interface/src/legacy/erl_resolve.c deleted file mode 100644 index bb09caec85..0000000000 --- a/lib/erl_interface/src/legacy/erl_resolve.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2003-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/*************************************************************************** - * - * Compatibility with the old erl_interface library that had some - * undocumented functions. - * - ***************************************************************************/ - -#include "eidef.h" - -#include "erl_interface.h" -#include "ei_resolve.h" -#include "ei_connect_int.h" -#include "ei_epmd.h" - -struct hostent *erl_gethostbyname(const char *name) -{ - return ei_gethostbyname(name); -} - - -void erl_init_resolve(void) -{ - ei_init_resolve(); -} - - -struct hostent *erl_gethostbyaddr(const char *addr, int len, int type) -{ - return ei_gethostbyaddr(addr, len, type); -} - - -struct hostent *erl_gethostbyname_r(const char *name, - struct hostent *hostp, - char *buffer, - int buflen, - int *h_errnop) -{ - return ei_gethostbyname_r(name,hostp,buffer,buflen,h_errnop); -} - - -struct hostent *erl_gethostbyaddr_r(const char *addr, - int length, - int type, - struct hostent *hostp, - char *buffer, - int buflen, - int *h_errnop) -{ - return ei_gethostbyaddr_r(addr,length,type,hostp,buffer,buflen,h_errnop); -} - - -int erl_distversion(int fd) -{ - return ei_distversion(fd); -} - -int erl_epmd_connect(struct in_addr *inaddr) -{ - return ei_epmd_connect_tmo(inaddr,0); -} - -int erl_epmd_port(struct in_addr *inaddr, const char *alive, int *dist) -{ - return ei_epmd_port(inaddr, alive, dist); -} - - - -/* FIXME !!!!! -erl_epmd_port ei_epmd_port -erl_mutex_lock ei_mutex_lock -erl_malloc erl_free ???? -erl_publish erl_unpublish -< extern int erl_epmd_connect(struct in_addr *inaddr); -< extern int erl_epmd_publish(int port, const char *alive); -< extern int erl_epmd_port(struct in_addr *inaddr, const char *alive, int *dist); - -< int erl_unpublish(const char *alive) ---- -> int ei_unpublish_alive(const char *alive) - -erl_self -erl_getfdcookie -*/ diff --git a/lib/erl_interface/src/legacy/erl_timeout.c b/lib/erl_interface/src/legacy/erl_timeout.c deleted file mode 100644 index e36ea0e250..0000000000 --- a/lib/erl_interface/src/legacy/erl_timeout.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1997-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -/* timeout.c - * - * todo: use posix timers (timer_create etc) instead of setitimer. - * - */ -#if !defined(__WIN32__) && !defined(VXWORKS) - -/* FIXME: well, at least I can compile now... */ - -#include "eidef.h" - -#include <stdio.h> -#include <stdlib.h> -#include <setjmp.h> -#include <signal.h> - -#if TIME_WITH_SYS_TIME -# include <sys/time.h> -# include <time.h> -#else -# if HAVE_SYS_TIME_H -# include <sys/time.h> -# else -# include <time.h> -# endif -#endif - -#include "erl_interface.h" -#include "erl_timeout.h" - -typedef struct jmp_s { - jmp_buf jmpbuf; - struct itimerval timerinfo; - void *siginfo; - struct jmp_s *next; -} *jmp_t; - -static jmp_t push(jmp_t j); -static jmp_t pop(void); -static void timeout_handler(int dummy); - -jmp_buf *timeout_setup(int ms) -{ - struct itimerval t; - jmp_t j; - void *s; - -#ifdef DEBUG - fprintf(stderr,"timeout setup\n"); -#endif - s=signal(SIGALRM,timeout_handler); - - /* set the timer */ - t.it_interval.tv_sec = 0; - t.it_interval.tv_usec = 0; - t.it_value.tv_sec = ms / 1000; - t.it_value.tv_usec = (ms % 1000) * 1000; - - /* get a jump buffer and save it */ - j = erl_malloc(sizeof(*j)); - j->siginfo = s; - push(j); - - setitimer(ITIMER_REAL,&t,&(j->timerinfo)); - - return &(j->jmpbuf); -} - - -int timeout_cancel(void) -{ - jmp_t j; - -#ifdef DEBUG - fprintf(stderr,"timeout cancel\n"); -#endif - /* retrieve the jump buffer */ - j=pop(); - /* restore the timer and signal disposition */ - setitimer(ITIMER_REAL,&(j->timerinfo),NULL); - signal(SIGALRM,j->siginfo); - - free(j); - - return 0; -} - -void timeout_handler(int dummy) -{ - jmp_t j; - -#ifdef DEBUG - fprintf(stderr,"timeout handler\n"); -#endif - - /* retrieve the jump buffer */ - j=pop(); - - /* restore the timer and signal disposition */ - setitimer(ITIMER_REAL,&(j->timerinfo),NULL); - signal(SIGALRM,j->siginfo); - - free(j); - longjmp(j->jmpbuf,JMPVAL); - return; /* not reached */ -} - - -/* a simple stack for saving the jump buffer allows us to pass a - * variable between functions that don't call each other, in a way - * that will survive the longjmp(). - */ - -/* FIXME problem for threaded ? */ -static jmp_t jmp_head=NULL; -#ifdef DEBUG -static int depth = 0; -static int maxdepth = 0; -#endif - -static jmp_t push(jmp_t j) -{ - j->next = jmp_head; - jmp_head = j; - -#ifdef DEBUG - depth++; - if (depth > maxdepth) maxdepth = depth; -#endif - - return j; -} - -static jmp_t pop(void) -{ - jmp_t j = jmp_head; - if (j) jmp_head = j->next; -#ifdef DEBUG - depth--; -#endif - return j; -} - -#endif /* platform */ diff --git a/lib/erl_interface/src/legacy/erl_timeout.h b/lib/erl_interface/src/legacy/erl_timeout.h deleted file mode 100644 index 6bcfa5ecbb..0000000000 --- a/lib/erl_interface/src/legacy/erl_timeout.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1997-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ -#ifndef _ERL_TIMEOUT_H -#define _ERL_TIMEOUT_H - -#if !defined (__WIN32__) && !defined (VXWORKS) - -#include <setjmp.h> - -/* - use timeout like this (delay in ms): - - if (timeout(delay,fun(a,b,c))) { - printf("timeout occurred\n"); - } - else { - ... - } - -If the call to fun() has not returned before 'delay' ms, it will be -interrupted and and timeout() will return a non-zero value. - -If fun() finishes before 'delay' ms, then timeout will return 0. - -If you need the return value from fun then assign it like this: - - if (timeout(delay,(x = fun(...)))) { - } - -These functions work by setting and catching SIGALRM, and although it -saves and restores the signal handler, it may not work in situations -where you are already using SIGALRM (this includes calls to sleep(3)). - -Note that although recursive calls to timeout will not fail, they may -not give the expected results. All invocations of timeout use the same -timer, which is set on entrance to timeout and restored on exit from -timeout. So although an inner call to timeout will restart the timer -for any pending outer call when it exits, any time that has already -elapsed against the outer timeout is forgotten. In addition, the alarm -signal will always go to the innermost (last called) timeout, which -may or may not be the intention in recursive cases. - -*/ - -#define JMPVAL 997 /* magic */ - -#define timeout(ms,funcall) \ - (setjmp(*timeout_setup(ms)) == JMPVAL ? -1: \ - ((void)(funcall), timeout_cancel())) - - -/* don't call any of these directly - use the macro! see above! */ -jmp_buf *timeout_setup(int ms); -int timeout_cancel(void); - -#endif /* WIN32 && VXWORKS */ - -#endif /* _ERL_TIMEOUT_H */ diff --git a/lib/erl_interface/src/legacy/portability.h b/lib/erl_interface/src/legacy/portability.h deleted file mode 100644 index 42a78662d5..0000000000 --- a/lib/erl_interface/src/legacy/portability.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#ifndef _PORTABILITY_H -#define _PORTABILITY_H - -#if !defined(__GNUC__) || __GNUC__ < 2 - -/* - * GCC's attributes are too useful to not use. Other compilers - * just lose opportunities to optimize and warn. - */ -# define __attribute__(foo) /* nothing */ - -#endif - -#endif /* _PORTABILITY_H */ diff --git a/lib/erl_interface/src/misc/ei_format.c b/lib/erl_interface/src/misc/ei_format.c index a188171f40..695c3404f7 100644 --- a/lib/erl_interface/src/misc/ei_format.c +++ b/lib/erl_interface/src/misc/ei_format.c @@ -24,10 +24,6 @@ * ei_format to build binary format terms a bit like printf */ -#ifdef VXWORKS -#include <vxWorks.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <stdarg.h> diff --git a/lib/erl_interface/src/misc/ei_locking.c b/lib/erl_interface/src/misc/ei_locking.c index a5ddbb85f2..20464869ad 100644 --- a/lib/erl_interface/src/misc/ei_locking.c +++ b/lib/erl_interface/src/misc/ei_locking.c @@ -26,7 +26,7 @@ /* Note that these locks are NOT recursive on Win32 or Solaris, * i.e. self-deadlock will occur if a thread tries to obtain a lock it - * is already holding. The primitives used on VxWorks are recursive however. + * is already holding. */ #include "eidef.h" @@ -36,10 +36,6 @@ #include <windows.h> #include <winbase.h> -#elif VXWORKS -#include <vxWorks.h> -#include <semLib.h> - #else /* unix */ #include <stdlib.h> #include <unistd.h> @@ -63,12 +59,6 @@ ei_mutex_t *ei_mutex_create(void) #ifdef __WIN32__ l->lock = CreateMutex(NULL,FALSE,NULL); - -#elif VXWORKS - if (!(l->lock = semMCreate(SEM_DELETE_SAFE))) { - ei_free(l); - return NULL; - } #else /* unix */ l->lock = ei_m_create(); #endif @@ -97,10 +87,6 @@ int ei_mutex_free(ei_mutex_t *l, int nblock) /* we are now holding the lock */ #ifdef __WIN32__ CloseHandle(l->lock); - -#elif VXWORKS - if (semDelete(l->lock) == ERROR) return -1; - #else /* unix */ ei_m_destroy(l->lock); #endif @@ -131,11 +117,6 @@ int ei_mutex_lock(ei_mutex_t *l, int nblock) /* check valid values for timeout: is 0 ok? */ if (WaitForSingleObject(l->lock,(nblock? 0 : INFINITE)) != WAIT_OBJECT_0) return -1; - -#elif VXWORKS - if (semTake(l->lock,(nblock? NO_WAIT : WAIT_FOREVER)) == ERROR) - return -1; - #else /* unix */ if (nblock) { if (ei_m_trylock(l->lock) < 0) return -1; @@ -151,10 +132,6 @@ int ei_mutex_unlock(ei_mutex_t *l) { #ifdef __WIN32__ ReleaseMutex(l->lock); - -#elif VXWORKS - semGive(l->lock); - #else /* unix */ ei_m_unlock(l->lock); #endif diff --git a/lib/erl_interface/src/misc/ei_locking.h b/lib/erl_interface/src/misc/ei_locking.h index 1bbee2d499..93aade6b2d 100644 --- a/lib/erl_interface/src/misc/ei_locking.h +++ b/lib/erl_interface/src/misc/ei_locking.h @@ -24,11 +24,6 @@ #include "config.h" -#if defined(VXWORKS) -#include <taskLib.h> -#include <taskVarLib.h> -#endif - #ifdef __WIN32__ #include <winsock2.h> #include <windows.h> @@ -45,8 +40,6 @@ typedef struct ei_mutex_s { #ifdef __WIN32__ HANDLE lock; -#elif VXWORKS - SEM_ID lock; #else /* unix */ #if defined(HAVE_MIT_PTHREAD_H) || defined(HAVE_PTHREAD_H) pthread_mutex_t *lock; @@ -64,7 +57,7 @@ int ei_mutex_lock(ei_mutex_t *l, int nblock); int ei_mutex_unlock(ei_mutex_t *l); -#if defined(_REENTRANT) && !defined(VXWORKS) && !defined(__WIN32__) +#if defined(_REENTRANT) && !defined(__WIN32__) void *ei_m_create(void); int ei_m_destroy(void *l); @@ -72,6 +65,6 @@ int ei_m_lock(void *l); int ei_m_trylock(void *l); int ei_m_unlock(void *l); -#endif /* _REENTRANT && !VXWORKS && !__WIN32__ */ +#endif /* _REENTRANT && !__WIN32__ */ #endif /* _EI_LOCKING_H */ diff --git a/lib/erl_interface/src/misc/ei_portio.c b/lib/erl_interface/src/misc/ei_portio.c index bccc86c1b1..afa766a776 100644 --- a/lib/erl_interface/src/misc/ei_portio.c +++ b/lib/erl_interface/src/misc/ei_portio.c @@ -42,29 +42,7 @@ static unsigned long param_one = 1; #define MEANS_SOCKET_ERROR(Ret) ((Ret == SOCKET_ERROR)) #define IS_INVALID_SOCKET(Sock) ((Sock) == INVALID_SOCKET) -#elif VXWORKS -#include <vxWorks.h> -#include <hostLib.h> -#include <ifLib.h> -#include <sockLib.h> -#include <taskLib.h> -#include <inetLib.h> -#include <selectLib.h> -#include <ioLib.h> -#include <unistd.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <timers.h> - -static unsigned long param_zero = 0; -static unsigned long param_one = 1; -#define SET_BLOCKING(Sock) ioctl((Sock),FIONBIO,(int)¶m_zero) -#define SET_NONBLOCKING(Sock) ioctl((Sock),FIONBIO,(int)¶m_one) -#define MEANS_SOCKET_ERROR(Ret) ((Ret) == ERROR) -#define IS_INVALID_SOCKET(Sock) ((Sock) < 0) - -#else /* other unix */ +#else /* unix */ #include <stdlib.h> #include <sys/socket.h> #include <unistd.h> @@ -622,7 +600,7 @@ int ei_accept_ctx_t__(ei_socket_callbacks *cbs, void **ctx, } while (error == EINTR); } do { - error = cbs->accept(ctx, addr, len, ms); + error = cbs->EI_ACCEPT_NAME(ctx, addr, len, ms); } while (error == EINTR); return error; } diff --git a/lib/erl_interface/src/misc/ei_portio.h b/lib/erl_interface/src/misc/ei_portio.h index 5172d085b4..b47b220d51 100644 --- a/lib/erl_interface/src/misc/ei_portio.h +++ b/lib/erl_interface/src/misc/ei_portio.h @@ -23,7 +23,7 @@ #define _EI_PORTIO_H #undef EI_HAVE_STRUCT_IOVEC__ -#if !defined(__WIN32__) && !defined(VXWORKS) && defined(HAVE_SYS_UIO_H) +#if !defined(__WIN32__) && defined(HAVE_SYS_UIO_H) /* Declaration of struct iovec *iov should be visible in this scope. */ # include <sys/uio.h> # define EI_HAVE_STRUCT_IOVEC__ diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c index aee7f7eeb0..0dfecb6d4b 100644 --- a/lib/erl_interface/src/misc/ei_printterm.c +++ b/lib/erl_interface/src/misc/ei_printterm.c @@ -24,10 +24,6 @@ * ei_print_term to print out a binary coded term */ -#ifdef VXWORKS -#include <vxWorks.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <stdarg.h> diff --git a/lib/erl_interface/src/misc/ei_pthreads.c b/lib/erl_interface/src/misc/ei_pthreads.c index c6d07a9a0a..df7a7fbb8f 100644 --- a/lib/erl_interface/src/misc/ei_pthreads.c +++ b/lib/erl_interface/src/misc/ei_pthreads.c @@ -38,25 +38,6 @@ static LONG volatile tls_init_mutex = 0; #endif #endif -#if defined(VXWORKS) - -/* - Moved to each of the erl_*threads.c files, as they seem to know how - to get thread-safety. -*/ -static volatile int __erl_errno; -volatile int *__erl_errno_place(void) -{ - /* This check is somewhat insufficient, double task var entries will occur - if __erl_errno is actually -1, which on the other hand is an invalid - error code. */ - if (taskVarGet(taskIdSelf(), &__erl_errno) == ERROR) { - taskVarAdd(taskIdSelf(), &__erl_errno); - } - return &__erl_errno; -} -#endif /* VXWORKS */ - #if defined(__WIN32__) #ifdef USE_DECLSPEC_THREAD @@ -106,7 +87,7 @@ volatile int *__erl_errno_place(void) #endif /* __WIN32__ */ -#if defined(_REENTRANT) && !defined(VXWORKS) && !defined(__WIN32__) +#if defined(_REENTRANT) && !defined(__WIN32__) #if defined(HAVE_PTHREAD_H) || defined(HAVE_MIT_PTHREAD_H) @@ -219,9 +200,9 @@ volatile int *__erl_errno_place(void) #endif /* HAVE_PTHREAD_H || HAVE_MIT_PTHREAD_H */ -#endif /* _REENTRANT && !VXWORKS && !__WIN32__ */ +#endif /* _REENTRANT && !__WIN32__ */ -#if !defined(_REENTRANT) && !defined(VXWORKS) && !defined(__WIN32__) +#if !defined(_REENTRANT) && !defined(__WIN32__) volatile int __erl_errno; diff --git a/lib/erl_interface/src/misc/ei_x_encode.c b/lib/erl_interface/src/misc/ei_x_encode.c index 8e77679d2a..fe3c20faff 100644 --- a/lib/erl_interface/src/misc/ei_x_encode.c +++ b/lib/erl_interface/src/misc/ei_x_encode.c @@ -23,10 +23,6 @@ * ei_x_encode to encode in a self-expanding buffer */ -#ifdef VXWORKS -#include <vxWorks.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/lib/erl_interface/src/misc/eidef.h b/lib/erl_interface/src/misc/eidef.h index f38824d826..f1fdafaa08 100644 --- a/lib/erl_interface/src/misc/eidef.h +++ b/lib/erl_interface/src/misc/eidef.h @@ -27,11 +27,6 @@ #include "config.h" /* Central include of config.h */ -/* vxWorks.h needs to be before stddef.h */ -#ifdef VXWORKS -#include <vxWorks.h> -#endif - #include <stddef.h> /* We want to get definition of NULL */ #include "ei.h" /* Want the API function declarations */ diff --git a/lib/erl_interface/src/not_used/ei_send.c b/lib/erl_interface/src/not_used/ei_send.c deleted file mode 100644 index 8071876677..0000000000 --- a/lib/erl_interface/src/not_used/ei_send.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - * - - */ -#ifdef __WIN32__ -#include <winsock2.h> -#include <windows.h> -#include <winbase.h> - -#elif VXWORKS -#include <sys/types.h> -#include <unistd.h> - -#else /* unix */ -#include <sys/types.h> -#include <unistd.h> -#include <sys/uio.h> -#endif - -#include "eidef.h" -#include "eiext.h" -#include "ei_connect.h" -#include "ei_internal.h" -#include "putget.h" -#include "ei_trace.h" -#include "show_msg.h" - -/* FIXME this is not useed !!!!! */ - -/* length (4), PASS_THROUGH (1), header, message */ -int ei_ei_send_encoded(ei_cnode* ec, int fd, const erlang_pid *to, - const char *msg, int msglen) -{ - char *s, header[1200]; /* see size calculation below */ - erlang_trace *token = NULL; - int index = 5; /* reserve 5 bytes for control message */ -#ifdef HAVE_WRITEV - struct iovec v[2]; -#endif - - /* are we tracing? */ - /* check that he can receive trace tokens first */ - if (ei_distversion(fd) > 0) - token = ei_trace(0,(erlang_trace *)NULL); - - /* header = SEND, cookie, to max sizes: */ - ei_encode_version(header,&index); /* 1 */ - if (token) { - ei_encode_tuple_header(header,&index,4); /* 2 */ - ei_encode_long(header,&index,ERL_SEND_TT); /* 2 */ - } else { - ei_encode_tuple_header(header,&index,3); - ei_encode_long(header,&index,ERL_SEND); - } - ei_encode_atom(header,&index, "" /*ei_getfdcookie(ec, fd)*/); /* 258 */ - ei_encode_pid(header,&index,to); /* 268 */ - - if (token) ei_encode_trace(header,&index,token); /* 534 */ - - /* control message (precedes header actually) */ - /* length = 1 ('p') + header len + message len */ - s = header; - put32be(s, index + msglen - 4); /* 4 */ - put8(s, ERL_PASS_THROUGH); /* 1 */ - /*** sum: 1070 */ - -#ifdef DEBUG_DIST - if (ei_trace_distribution > 0) ei_show_sendmsg(stderr,header,msg); -#endif - -#ifdef HAVE_WRITEV - - v[0].iov_base = (char *)header; - v[0].iov_len = index; - v[1].iov_base = (char *)msg; - v[1].iov_len = msglen; - - if (writev(fd,v,2) != index+msglen) return -1; - -#else /* !HAVE_WRITEV */ - - if (writesocket(fd,header,index) != index) return -1; - if (writesocket(fd,msg,msglen) != msglen) return -1; - -#endif /* !HAVE_WRITEV */ - - return 0; -} diff --git a/lib/erl_interface/src/not_used/ei_send_reg.c b/lib/erl_interface/src/not_used/ei_send_reg.c deleted file mode 100644 index ba9c7348f9..0000000000 --- a/lib/erl_interface/src/not_used/ei_send_reg.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2001-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - * - - */ -#ifdef __WIN32__ -#include <winsock2.h> -#include <windows.h> -#include <winbase.h> - -#elif VXWORKS -#include <sys/types.h> -#include <unistd.h> - -#else /* unix */ -#include <sys/types.h> -#include <unistd.h> -#include <sys/uio.h> -#endif - -#include "eidef.h" -#include "eiext.h" -#include "ei_connect.h" -#include "ei_internal.h" -#include "putget.h" -#include "ei_trace.h" -#include "show_msg.h" - -/* FIXME this is not useed !!!!! */ -/* FIXME merge with ei_send.c */ - -/* length (4), PASS_THROUGH (1), header, message */ -int ei_ei_send_reg_encoded(ei_cnode* ec, int fd, const erlang_pid *from, - const char *to, const char *msg, int msglen) -{ - char *s, header[1400]; /* see size calculation below */ - erlang_trace *token = NULL; - int index = 5; /* reserve 5 bytes for control message */ -#ifdef HAVE_WRITEV - struct iovec v[2]; -#endif - - /* are we tracing? */ - /* check that he can receive trace tokens first */ - if (ei_distversion(fd) > 0) - token = ei_trace(0,(erlang_trace *)NULL); - - /* header = REG_SEND, from, cookie, toname max sizes: */ - ei_encode_version(header,&index); /* 1 */ - if (token) { - ei_encode_tuple_header(header,&index,5); /* 2 */ - ei_encode_long(header,&index,ERL_REG_SEND_TT); /* 2 */ - } else { - ei_encode_tuple_header(header,&index,4); - ei_encode_long(header,&index,ERL_REG_SEND); - } - ei_encode_pid(header,&index,from); /* 268 */ - ei_encode_atom(header,&index,"" /*ei_getfdcookie(ec, fd)*/ ); /* 258 */ - ei_encode_atom(header,&index,to); /* 268 */ - - if (token) ei_encode_trace(header,&index,token); /* 534 */ - - /* control message (precedes header actually) */ - /* length = 1 ('p') + header len + message len */ - s = header; - put32be(s, index + msglen - 4); /* 4 */ - put8(s, ERL_PASS_THROUGH); /* 1 */ - /*** sum: 1336 */ - -#ifdef DEBUG_DIST - if (ei_trace_distribution > 0) ei_show_sendmsg(stderr,header,msg); -#endif - -#ifdef HAVE_WRITEV - - v[0].iov_base = (char *)header; - v[0].iov_len = index; - v[1].iov_base = (char *)msg; - v[1].iov_len = msglen; - - if (writev(fd,v,2) != index+msglen) return -1; - -#else - - /* no writev() */ - if (writesocket(fd,header,index) != index) return -1; - if (writesocket(fd,msg,msglen) != msglen) return -1; - -#endif - - return 0; -} diff --git a/lib/erl_interface/src/not_used/send_link.c b/lib/erl_interface/src/not_used/send_link.c deleted file mode 100644 index 38fae27df4..0000000000 --- a/lib/erl_interface/src/not_used/send_link.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - * - - */ -#ifdef __WIN32__ -#include <winsock2.h> -#include <windows.h> -#include <winbase.h> - -#elif VXWORKS -#include <unistd.h> - -#else /* unix */ -#include <unistd.h> - -#endif - -#include <string.h> -#include <stdlib.h> -#include "eidef.h" -#include "eiext.h" -#include "eisend.h" -#include "ei_internal.h" -#include "putget.h" -#include "erl_rport.h" - - -/* this sends either link or unlink ('which' decides) */ -static int link_unlink(int fd, const erlang_pid *from, const erlang_pid *to, - int which, unsigned ms) -{ - char msgbuf[EISMALLBUF]; - char *s; - int index = 0; - int n; - unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms; - - index = 5; /* max sizes: */ - ei_encode_version(msgbuf,&index); /* 1 */ - ei_encode_tuple_header(msgbuf,&index,3); - ei_encode_long(msgbuf,&index,which); - ei_encode_pid(msgbuf,&index,from); /* 268 */ - ei_encode_pid(msgbuf,&index,to); /* 268 */ - - /* 5 byte header missing */ - s = msgbuf; - put32be(s, index - 4); /* 4 */ - put8(s, ERL_PASS_THROUGH); /* 1 */ - /* sum: 542 */ - - -#ifdef DEBUG_DIST - if (ei_trace_distribution > 1) ei_show_sendmsg(stderr,msgbuf,NULL); -#endif - - n = ei_write_fill_t__(fd,msgbuf,index,tmo); - - return (n==index ? 0 : -1); -} - -/* FIXME not used? */ -#if 0 -/* use this to send a link */ -int ei_send_unlink(int fd, const erlang_pid *from, const erlang_pid *to) -{ - return link_unlink(fd, from, to, ERL_UNLINK,0); -} - -/* use this to send an unlink */ -int ei_send_link(int fd, const erlang_pid *from, const erlang_pid *to) -{ - return link_unlink(fd, from, to, ERL_LINK,0); -} -/* use this to send a link */ -int ei_send_unlink_tmo(int fd, const erlang_pid *from, const erlang_pid *to, - unsigned ms) -{ - return link_unlink(fd, from, to, ERL_UNLINK,ms); -} - -/* use this to send an unlink */ -int ei_send_link_tmo(int fd, const erlang_pid *from, const erlang_pid *to, - unsigned ms) -{ - return link_unlink(fd, from, to, ERL_LINK,ms); -} -#endif diff --git a/lib/erl_interface/src/not_used/whereis.c b/lib/erl_interface/src/not_used/whereis.c deleted file mode 100644 index 4072fa7b33..0000000000 --- a/lib/erl_interface/src/not_used/whereis.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1998-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - * - - */ -#ifdef __WIN32__ -#include <winsock2.h> -#include <windows.h> -#include <winbase.h> - -#elif VXWORKS -#include <unistd.h> - -#else /* unix */ -#include <unistd.h> - -#endif - -#include <string.h> -#include <stdlib.h> -#include "erl_interface.h" -#include "erl_connect.h" -#include "erl_format.h" -#include "erl_eterm.h" -#include "erl_malloc.h" - -/* FIXME rewrite to ei functions */ -/* FIXME not used */ - -erlang_pid *erl_whereis(int fd, const char *name) -{ - ETERM *reply; - ETERM *n; - /* FIXME problem for threaded ? */ - static erlang_pid pid; - - n = erl_format("[~a]",name); - reply = erl_rpc(fd,"erlang","whereis",n); - erl_free_term(n); - - if (reply && (ERL_IS_PID(reply))) { - char *node; - node = ERL_PID_NODE(reply); - strcpy(pid.node,node); - pid.num = ERL_PID_NUMBER(reply); - pid.serial = ERL_PID_SERIAL(reply); - pid.creation = ERL_PID_CREATION(reply); - erl_free_term(reply); - return &pid; - } - - if (reply) erl_free_term(reply); - return NULL; -} - diff --git a/lib/erl_interface/src/prog/ei_fake_prog.c b/lib/erl_interface/src/prog/ei_fake_prog.c index 6f58c9833d..c483859c8b 100644 --- a/lib/erl_interface/src/prog/ei_fake_prog.c +++ b/lib/erl_interface/src/prog/ei_fake_prog.c @@ -54,11 +54,7 @@ /* #include <netdb.h> now included by ei.h */ #include "ei.h" -#ifdef VXWORKS -int ei_fake_prog_main(void) -#else int main(void) -#endif { ErlConnect conp; Erl_IpAddr thisipaddr = (Erl_IpAddr)0; @@ -91,12 +87,10 @@ int main(void) unsigned long *ulongp = NULL; unsigned long ulongx = 0; void *voidp = NULL; -#ifndef VXWORKS EI_LONGLONG *longlongp = (EI_LONGLONG*)NULL; EI_LONGLONG longlongx = 0; EI_ULONGLONG *ulonglongp = (EI_ULONGLONG*)NULL; EI_ULONGLONG ulonglongx = 0; -#endif erlang_char_encoding enc; ei_socket_callbacks cbs; @@ -260,8 +254,6 @@ int main(void) } #endif /* HAVE_GMP_H && HAVE_LIBGMP */ -#ifndef VXWORKS - ei_decode_longlong(charp, intp, longlongp); ei_decode_ulonglong(charp, intp, ulonglongp); ei_encode_longlong(charp, intp, longlongx); @@ -269,8 +261,6 @@ int main(void) ei_x_encode_longlong(&eix, longlongx); ei_x_encode_ulonglong(&eix, ulonglongx); -#endif - #ifdef USE_EI_UNDOCUMENTED ei_decode_intlist(charp, intp, longp, intp); diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c index ab91157035..f3d025d30f 100644 --- a/lib/erl_interface/src/prog/erl_call.c +++ b/lib/erl_interface/src/prog/erl_call.c @@ -33,23 +33,6 @@ #include <windows.h> #include <winbase.h> -#elif VXWORKS - -#include <stdio.h> -#include <string.h> -#include <vxWorks.h> -#include <hostLib.h> -#include <selectLib.h> -#include <ifLib.h> -#include <sockLib.h> -#include <taskLib.h> -#include <inetLib.h> -#include <unistd.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <time.h> - #else /* unix */ #include <sys/types.h> @@ -104,6 +87,8 @@ struct call_flags { int debugp; int verbosep; int haltp; + long port; + char *hostname; char *cookie; char *node; char *hidden; @@ -131,13 +116,7 @@ static char* ei_chk_strdup(char *s); * ***************************************************************************/ -/* FIXME isn't VxWorks to handle arguments differently? */ - -#if !defined(VXWORKS) int main(int argc, char *argv[]) -#else -int erl_call(int argc, char **argv) -#endif { int i = 1,fd,creation; struct hostent *hp; @@ -152,6 +131,8 @@ int erl_call(int argc, char **argv) struct call_flags flags = {0}; /* Default 0 and NULL in all fields */ char* progname = argv[0]; ei_cnode ec; + flags.port = -1; + flags.hostname = NULL; ei_init(); @@ -177,6 +158,29 @@ int erl_call(int argc, char **argv) flags.node = ei_chk_strdup(argv[i+1]); i++; flags.use_long_name = 1; + } else if (strcmp(argv[i], "-address") == 0) { /* -address [HOST:]PORT */ + if (i+1 >= argc) { + usage_arg(progname, "-address "); + } + { + char* hostname_port_arg = ei_chk_strdup(argv[i+1]); + char* address_string_end = strchr(hostname_port_arg, ':'); + if (address_string_end == NULL) { + flags.port = strtol(hostname_port_arg, NULL, 10); + } else { + flags.port = strtol(address_string_end + 1, NULL, 10); + /* Remove port part from hostname_port_arg*/ + *address_string_end = '\0'; + if (strlen(hostname_port_arg) > 0) { + flags.hostname = hostname_port_arg; + } + } + + if (flags.port < 1 || flags.port > 65535) { + usage_error(progname, "-address"); + } + i++; + } } else { if (strlen(argv[i]) != 2) { usage_error(progname, argv[i]); @@ -251,11 +255,12 @@ int erl_call(int argc, char **argv) } /* while */ - /* * Can't have them both ! */ - if (flags.modp && flags.evalp) { + if ((flags.modp && flags.evalp) || + (flags.port != -1 && flags.startp) || + (flags.port != -1 && flags.node)) { usage(progname); } @@ -284,7 +289,7 @@ int erl_call(int argc, char **argv) /* * What we, at least, requires ! */ - if (flags.node == NULL) { + if (flags.node == NULL && flags.port == -1) { usage(progname); } @@ -292,20 +297,14 @@ int erl_call(int argc, char **argv) flags.cookie = NULL; } - /* FIXME decide how many bits etc or leave to connect_xinit? */ - creation = (time(NULL) % 3) + 1; /* "random" */ + creation = time(NULL) + 1; /* "random" */ if (flags.hidden == NULL) { /* As default we are c17@gethostname */ i = flags.randomp ? (time(NULL) % 997) : 17; flags.hidden = (char *) ei_chk_malloc(10 + 2 ); /* c17 or cXYZ */ -#if defined(VXWORKS) - sprintf(flags.hidden, "c%d", - i < 0 ? (int) taskIdSelf() : i); -#else sprintf(flags.hidden, "c%d", i < 0 ? (int) getpid() : i); -#endif } { /* A name for our hidden node was specified */ @@ -346,10 +345,15 @@ int erl_call(int argc, char **argv) } } - if ((p = strchr((const char *)flags.node, (int) '@')) == 0) { + if (flags.port != -1 && flags.hostname != NULL) { + host = flags.hostname; + strcpy(host_name, flags.hostname); + } else if ((flags.port != -1 && flags.hostname == NULL) || + (strchr((const char *)flags.node, (int) '@') == 0)) { strcpy(host_name, ei_thishostname(&ec)); host = host_name; } else { + p = strchr((const char *)flags.node, (int) '@'); *p = 0; host = p+1; } @@ -368,28 +372,45 @@ int erl_call(int argc, char **argv) } 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); + if (flags.port == -1) { + 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); } - sprintf(nodename, "%s@%s", flags.node, host_name); - /* * Try to connect. Start an Erlang system if the * start option is on and no system is running. */ if (flags.startp && !flags.haltp) { fd = do_connect(&ec, nodename, &flags); - } else if ((fd = ei_connect(&ec, nodename)) < 0) { - /* We failed to connect ourself */ - /* FIXME do we really know we failed because of node not up? */ - if (flags.haltp) { - exit(0); - } else { - fprintf(stderr,"erl_call: failed to connect to node %s\n", - nodename); - exit(1); - } + } else if (flags.port == -1) { + if ((fd = ei_connect(&ec, nodename)) < 0) { + /* We failed to connect ourself */ + /* FIXME do we really know we failed because of node not up? */ + if (flags.haltp) { + exit(0); + } else { + fprintf(stderr,"erl_call: failed to connect to node %s\n", + nodename); + exit(1); + } + } + } else { + /* Connect using address:port */ + if ((fd = ei_connect_host_port(&ec, host, (int)flags.port)) < 0) { + /* We failed to connect ourself */ + /* FIXME do we really know we failed because of node not up? */ + if (flags.haltp) { + exit(0); + } else { + fprintf(stderr,"erl_call: failed to connect to node with address \"%s:%ld\"\n", + flags.hostname == NULL ? "" : flags.hostname, + flags.port); + exit(1); + } + } } /* If we are connected and the halt switch is set */ @@ -415,8 +436,14 @@ int erl_call(int argc, char **argv) } if (flags.verbosep) { - fprintf(stderr,"erl_call: we are now connected to node \"%s\"\n", - nodename); + if (flags.port == -1) { + fprintf(stderr,"erl_call: we are now connected to node \"%s\"\n", + nodename); + } else { + fprintf(stderr,"erl_call: we are now connected to node with address \"%s:%ld\"\n", + flags.hostname == NULL ? "": flags.hostname, + flags.port); + } } /* @@ -809,7 +836,7 @@ static int get_module(char **mbuf, char **mname) static void usage_noexit(const char *progname) { fprintf(stderr,"\nUsage: %s [-[demqrsv]] [-c Cookie] [-h HiddenName] \n", progname); fprintf(stderr," [-x ErlScript] [-a [Mod [Fun [Args]]]]\n"); - fprintf(stderr," (-n Node | -sname Node | -name Node)\n\n"); + fprintf(stderr," (-n Node | -sname Node | -name Node | -address [HOSTNAME:]PORT)\n\n"); #ifdef __WIN32__ fprintf(stderr," where: -a apply(Mod,Fun,Args) (e.g -a \"erlang length [[a,b,c]]\"\n"); #else @@ -817,12 +844,18 @@ static void usage_noexit(const char *progname) { #endif fprintf(stderr," -c cookie string; by default read from ~/.erlang.cookie\n"); fprintf(stderr," -d direct Erlang output to ~/.erl_call.out.<Nodename>\n"); - fprintf(stderr," -e evaluate contents of standard input (e.g echo \"X=1,Y=2,{X,Y}.\"|erl_call -e ...)\n"); + fprintf(stderr," -e evaluate contents of standard input (e.g., echo \"X=1,Y=2,{X,Y}.\"|%s -e ...)\n", + progname); fprintf(stderr," -h specify a name for the erl_call client node\n"); fprintf(stderr," -m read and compile Erlang module from stdin\n"); fprintf(stderr," -n name of Erlang node, same as -name\n"); fprintf(stderr," -name name of Erlang node, expanded to a fully qualified\n"); fprintf(stderr," -sname name of Erlang node, short form will be used\n"); + fprintf(stderr," -address [HOSTNAME:]PORT of Erlang node\n" + " (the default hostname is the hostname of the local manchine)\n" + " (e.g., %s -address my_host:36303 ...)\n" + " (cannot be combinated with -s, -n, -name and -sname)\n", + progname); fprintf(stderr," -q halt the Erlang node (overrides the -s switch)\n"); fprintf(stderr," -r use a random name for the erl_call client node\n"); fprintf(stderr," -s start a new Erlang node if necessary\n"); diff --git a/lib/erl_interface/src/prog/erl_fake_prog.c b/lib/erl_interface/src/prog/erl_fake_prog.c deleted file mode 100644 index 093bad8d7c..0000000000 --- a/lib/erl_interface/src/prog/erl_fake_prog.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2002-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/*************************************************************************** - * - * This is a fake program that contains all functions, variables and - * defined symbols mentioned in the manual. We compile this file to see - * that the header files and created library is complete. - * - * You can't run this program, it is for compiling and linking only. - * - ***************************************************************************/ - -/* Use most of - * CFLAGS="-I../include -g -O2 - * -ansi -pedantic - * -Wall - * -Wshadow - * -Wstrict-prototypes - * -Wmissing-prototypes - * -Wmissing-declarations - * -Wnested-externs - * -Winline - * -Werror" - */ - -/* #include <netdb.h> now included by ei.h */ -#include "erl_interface.h" - -#ifdef VXWORKS -int erl_fake_prog_main(void) -#else -int main(void) -#endif -{ - ei_x_buff eix; - int index = 0; - ETERM **etermpp = NULL, *etermp = NULL; - char *charp = NULL; - unsigned char uchar, **ucharpp = NULL, *ucharp = NULL; - void *voidp = NULL; - Erl_Heap *erl_heapp = NULL; - int intx = 0; - int *intp = NULL; - unsigned int uintx, *uintp; - unsigned long *ulongp = NULL; - long longx = 0; - double doublex = 0.0; - short shortx = 42; - FILE *filep = NULL; - Erl_IpAddr erl_ipaddr = NULL; - ErlMessage *erlmessagep = NULL; - ErlConnect *erlconnectp = NULL; - struct hostent *hostp = NULL; - struct in_addr *inaddrp = NULL; - - /* Converion to erl_interface format is in liberl_interface */ - - intx = erl_errno; - - ei_encode_term(charp, &index, voidp); - ei_x_encode_term(&eix, voidp); - ei_decode_term(charp, &index, voidp); - - erl_init(voidp, longx); - erl_connect_init(intx, charp,shortx); - erl_connect_xinit(charp,charp,charp,erl_ipaddr,charp,shortx); - erl_connect(charp); - erl_xconnect(erl_ipaddr,charp); - erl_close_connection(intx); - erl_receive(intx, ucharp, intx); - erl_receive_msg(intx, ucharp, intx, erlmessagep); - erl_xreceive_msg(intx, ucharpp, intp, erlmessagep); - erl_send(intx, etermp, etermp); - erl_reg_send(intx, charp, etermp); - erl_rpc(intx,charp,charp,etermp); - erl_rpc_to(intx,charp,charp,etermp); - erl_rpc_from(intx,intx,erlmessagep); - - erl_publish(intx); - erl_accept(intx,erlconnectp); - - erl_thiscookie(); - erl_thisnodename(); - erl_thishostname(); - erl_thisalivename(); - erl_thiscreation(); - erl_unpublish(charp); - erl_err_msg(charp); - erl_err_quit(charp); - erl_err_ret(charp); - erl_err_sys(charp); - - erl_cons(etermp,etermp); - erl_copy_term(etermp); - erl_element(intx,etermp); - - erl_hd(etermp); - erl_iolist_to_binary(etermp); - erl_iolist_to_string(etermp); - erl_iolist_length(etermp); - erl_length(etermp); - erl_mk_atom(charp); - erl_mk_binary(charp,intx); - erl_mk_empty_list(); - erl_mk_estring(charp, intx); - erl_mk_float(doublex); - erl_mk_int(intx); - erl_mk_list(etermpp,intx); - erl_mk_pid(charp,uintx,uintx,uchar); - erl_mk_port(charp,uintx,uchar); - erl_mk_ref(charp,uintx,uchar); - erl_mk_long_ref(charp,uintx,uintx,uintx,uchar); - erl_mk_string(charp); - erl_mk_tuple(etermpp,intx); - erl_mk_uint(uintx); - erl_mk_var(charp); - erl_print_term(filep,etermp); - /* erl_sprint_term(charp,etermp); */ - erl_size(etermp); - erl_tl(etermp); - erl_var_content(etermp, charp); - - erl_format(charp); - erl_match(etermp, etermp); - - erl_global_names(intx, intp); - erl_global_register(intx, charp, etermp); - erl_global_unregister(intx, charp); - erl_global_whereis(intx, charp, charp); - - erl_init_malloc(erl_heapp,longx); - erl_alloc_eterm(uchar); - erl_eterm_release(); - erl_eterm_statistics(ulongp,ulongp); - erl_free_array(etermpp,intx); - erl_free_term(etermp); - erl_free_compound(etermp); - erl_malloc(longx); - erl_free(voidp); - - erl_compare_ext(ucharp, ucharp); - erl_decode(ucharp); - erl_decode_buf(ucharpp); - erl_encode(etermp,ucharp); - erl_encode_buf(etermp,ucharpp); - erl_ext_size(ucharp); - erl_ext_type(ucharp); - erl_peek_ext(ucharp,intx); - erl_term_len(etermp); - - erl_gethostbyname(charp); - erl_gethostbyaddr(charp, intx, intx); - erl_gethostbyname_r(charp, hostp, charp, intx, intp); - erl_gethostbyaddr_r(charp, intx, intx, hostp, charp, intx, intp); - - erl_init_resolve(); - erl_distversion(intx); - - erl_epmd_connect(inaddrp); - erl_epmd_port(inaddrp, charp, intp); - - charp = ERL_ATOM_PTR(etermp); - intx = ERL_ATOM_SIZE(etermp); - ucharp = ERL_BIN_PTR(etermp); - intx = ERL_BIN_SIZE(etermp); - etermp = ERL_CONS_HEAD(etermp); - etermp = ERL_CONS_TAIL(etermp); - intx = ERL_COUNT(etermp); - doublex= ERL_FLOAT_VALUE(etermp); - uintx = ERL_INT_UVALUE(etermp); - intx = ERL_INT_VALUE(etermp); - intx = ERL_IS_ATOM(etermp); - intx = ERL_IS_BINARY(etermp); - intx = ERL_IS_CONS(etermp); - intx = ERL_IS_EMPTY_LIST(etermp); - intx = ERL_IS_FLOAT(etermp); - intx = ERL_IS_INTEGER(etermp); - intx = ERL_IS_LIST(etermp); - intx = ERL_IS_PID(etermp); - intx = ERL_IS_PORT(etermp); - intx = ERL_IS_REF(etermp); - intx = ERL_IS_TUPLE(etermp); - intx = ERL_IS_UNSIGNED_INTEGER(etermp); - uchar = ERL_PID_CREATION(etermp); - charp = ERL_PID_NODE(etermp); - uintx = ERL_PID_NUMBER(etermp); - uintx = ERL_PID_SERIAL(etermp); - uchar = ERL_PORT_CREATION(etermp); - charp = ERL_PORT_NODE(etermp); - uintx = ERL_PORT_NUMBER(etermp); - uchar = ERL_REF_CREATION(etermp); - intx = ERL_REF_LEN(etermp); - charp = ERL_REF_NODE(etermp); - uintx = ERL_REF_NUMBER(etermp); - uintp = ERL_REF_NUMBERS(etermp); - etermp = ERL_TUPLE_ELEMENT(etermp,intx); - intx = ERL_TUPLE_SIZE(etermp); - - return - BUFSIZ + - EAGAIN + - EHOSTUNREACH + - EINVAL + - EIO + - EMSGSIZE + - ENOMEM + - ERL_ATOM + - ERL_BINARY + - ERL_ERROR + - ERL_EXIT + - ERL_FLOAT + - ERL_INTEGER + - ERL_LINK + - ERL_LIST + - ERL_MSG + - ERL_NO_TIMEOUT + - ERL_PID + - ERL_PORT + - ERL_REF + - ERL_REG_SEND + - ERL_SEND + - ERL_SMALL_BIG + - ERL_TICK + - ERL_TIMEOUT + - ERL_TUPLE + - ERL_UNLINK + - ERL_U_INTEGER + - ERL_U_SMALL_BIG + - ERL_VARIABLE + - ETIMEDOUT + - MAXNODELEN + - MAXREGLEN; -} diff --git a/lib/erl_interface/src/prog/erl_start.c b/lib/erl_interface/src/prog/erl_start.c index b7aa451946..a4930443d4 100644 --- a/lib/erl_interface/src/prog/erl_start.c +++ b/lib/erl_interface/src/prog/erl_start.c @@ -31,40 +31,7 @@ #include <windows.h> #include <winbase.h> -#elif VXWORKS -#include <stdio.h> -#include <string.h> -#include <vxWorks.h> -#include <hostLib.h> -#include <selectLib.h> -#include <ifLib.h> -#include <sockLib.h> -#include <taskLib.h> -#include <inetLib.h> -#include <unistd.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <symLib.h> -#include <sysSymTbl.h> -#include <sysLib.h> -#include <tickLib.h> - -#if TIME_WITH_SYS_TIME -# include <sys/time.h> -# include <time.h> -#else -# if HAVE_SYS_TIME_H -# include <sys/time.h> -# else -# include <time.h> -# endif -#endif - -#include <a_out.h> - -/* #include "netdb.h" */ -#else /* other unix */ +#else /* unix */ #include <errno.h> #include <netdb.h> #include <netinet/in.h> @@ -111,7 +78,7 @@ typedef socklen_t SocklenType; static struct in_addr *get_addr(const char *hostname, struct in_addr *oaddr); static int wait_for_erlang(int sockd, int magic, struct timeval *timeout); -#if defined(VXWORKS) || defined(__WIN32__) +#if defined(__WIN32__) static int unique_id(void); static unsigned long spawn_erlang_epmd(ei_cnode *ec, char *alive, @@ -148,7 +115,7 @@ int erl_start_sys(ei_cnode *ec, char *alive, Erl_IpAddr adr, int flags, int port; int sockd = 0; int one = 1; -#if defined(VXWORKS) || defined(__WIN32__) +#if defined(__WIN32__) unsigned long pid = 0; #else int pid = 0; @@ -177,7 +144,7 @@ int erl_start_sys(ei_cnode *ec, char *alive, Erl_IpAddr adr, int flags, listen(sockd,5); -#if defined(VXWORKS) || defined(__WIN32__) +#if defined(__WIN32__) if((pid = spawn_erlang_epmd(ec,alive,adr,flags,erl,args,port,1)) == 0) return ERL_SYS_ERROR; @@ -185,15 +152,9 @@ int erl_start_sys(ei_cnode *ec, char *alive, Erl_IpAddr adr, int flags, timeout.tv_sec = 10; /* ignoring ERL_START_TIME */ if((r = wait_for_erlang(sockd,unique_id(),&timeout)) == ERL_TIMEOUT) { -#if defined(VXWORKS) - taskDelete((int) pid); - if(taskIdVerify((int) pid) != ERROR) - taskDeleteForce((int) pid); -#else /* Windows */ /* Well, this is not a nice way to do it, and it does not always kill the emulator, but the alternatives are few.*/ TerminateProcess((HANDLE) pid,1); -#endif /* defined(VXWORKS) */ } #else /* Unix */ switch ((pid = fork())) { @@ -229,7 +190,7 @@ int erl_start_sys(ei_cnode *ec, char *alive, Erl_IpAddr adr, int flags, } } -#endif /* defined(VXWORKS) || defined(__WIN32__) */ +#endif /* defined(__WIN32__) */ done: #if defined(__WIN32__) @@ -240,18 +201,10 @@ done: return r; } /* erl_start_sys() */ -#if defined(VXWORKS) || defined(__WIN32__) -#if defined(VXWORKS) -#define DEF_ERL_COMMAND "" -#define DEF_EPMD_COMMAND "" -#define ERLANG_SYM "start_erl" -#define EPMD_SYM "start_epmd" -#define ERL_REPLY_FMT "-s erl_reply reply %s %d %d" -#else +#if defined(__WIN32__) #define DEF_ERL_COMMAND "erl" #define DEF_EPMD_COMMAND "epmd" #define ERL_REPLY_FMT "-s erl_reply reply \"%s\" \"%d\" \"%d\"" -#endif #define ERL_NAME_FMT "-noinput -name %s" #define ERL_SNAME_FMT "-noinput -sname %s" @@ -259,11 +212,7 @@ done: #define FORMATTED_INT_LEN 10 static int unique_id(void){ -#if defined(VXWORKS) - return taskIdSelf(); -#else return (int) GetCurrentThreadId(); -#endif } static int enquote_args(char **oargs, char ***qargs){ @@ -317,20 +266,7 @@ static void free_args(char **args){ free(args); } -#if defined(VXWORKS) -static FUNCPTR lookup_function(char *symname){ - char *value; - SYM_TYPE type; - if(symFindByName(sysSymTbl, - symname, - &value, - &type) == ERROR /*|| type != N_TEXT*/) - return NULL; - return (FUNCPTR) value; -} -#endif /* defined(VXWORKS) */ - -/* In NT and VxWorks, we cannot fork(), Erlang and Epmd gets +/* In NT we cannot fork(), Erlang and Epmd gets spawned by this function instead. */ static unsigned long spawn_erlang_epmd(ei_cnode *ec, @@ -342,13 +278,9 @@ static unsigned long spawn_erlang_epmd(ei_cnode *ec, int port, int is_erlang) { -#if defined(VXWORKS) - FUNCPTR erlfunc; -#else /* Windows */ STARTUPINFO sinfo; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pinfo; -#endif char *cmdbuf; int cmdlen; char *ptr; @@ -362,14 +294,10 @@ static unsigned long spawn_erlang_epmd(ei_cnode *ec, if(is_erlang){ get_addr(ei_thishostname(ec), &myaddr); -#if defined(VXWORKS) - inet_ntoa_b(myaddr, iaddrbuf); -#else /* Windows */ if((ptr = inet_ntoa(myaddr)) == NULL) return 0; else strcpy(iaddrbuf,ptr); -#endif } if ((flags & ERL_START_REMOTE) || (is_erlang && (hisaddr->s_addr != myaddr.s_addr))) { @@ -378,11 +306,7 @@ static unsigned long spawn_erlang_epmd(ei_cnode *ec, num_args = enquote_args(args, &args); for(cmdlen = i = 0; args[i] != NULL; ++i) cmdlen += strlen(args[i]) + 1; -#if !defined(VXWORKS) - /* On VxWorks, we dont actually run a command, - we call start_erl() */ if(!erl_or_epmd) -#endif erl_or_epmd = (is_erlang) ? DEF_ERL_COMMAND : DEF_EPMD_COMMAND; if(is_erlang){ @@ -417,23 +341,6 @@ static unsigned long spawn_erlang_epmd(ei_cnode *ec, fprintf(stderr,"erl_call: commands are %s\n",cmdbuf); } /* OK, one single command line... */ -#if defined(VXWORKS) - erlfunc = lookup_function((is_erlang) ? ERLANG_SYM : - EPMD_SYM); - if(erlfunc == NULL){ - if (flags & ERL_START_VERBOSE) { - fprintf(stderr,"erl_call: failed to find symbol %s\n", - (is_erlang) ? ERLANG_SYM : EPMD_SYM); - } - ret = 0; - } else { - /* Just call it, it spawns itself... */ - ret = (unsigned long) - (*erlfunc)((int) cmdbuf,0,0,0,0,0,0,0,0,0); - if(ret == (unsigned long) ERROR) - ret = 0; - } -#else /* Windows */ /* Hmmm, hidden or unhidden window??? */ memset(&sinfo,0,sizeof(sinfo)); sinfo.cb = sizeof(STARTUPINFO); @@ -460,7 +367,6 @@ static unsigned long spawn_erlang_epmd(ei_cnode *ec, ret = 0; else ret = (unsigned long) pinfo.hProcess; -#endif free(cmdbuf); return ret; } @@ -488,7 +394,7 @@ static int exec_erlang(ei_cnode *ec, char *args[], int port) { -#if !defined(__WIN32__) && !defined(VXWORKS) +#if !defined(__WIN32__) int fd,len,l,i; char **s; char *argv[4]; @@ -587,7 +493,7 @@ static int exec_erlang(ei_cnode *ec, return ERL_SYS_ERROR; } /* exec_erlang() */ -#endif /* defined(VXWORKS) || defined(WINDOWS) */ +#endif /* defined(WINDOWS) */ #if defined(__WIN32__) static void gettimeofday(struct timeval *now,void *dummy){ @@ -601,13 +507,6 @@ static void gettimeofday(struct timeval *now,void *dummy){ now->tv_usec = x % 1000000; } -#elif defined(VXWORKS) -static void gettimeofday(struct timeval *now, void *dummy){ - int rate = sysClkRateGet(); /* Ticks per second */ - unsigned long ctick = tickGet(); - now->tv_sec = ctick / rate; /* secs since reboot */ - now->tv_usec = ((ctick - (now->tv_sec * rate))*1000000)/rate; -} #endif diff --git a/lib/erl_interface/src/registry/reg_get.c b/lib/erl_interface/src/registry/reg_get.c index 67d99e231e..73975f6a91 100644 --- a/lib/erl_interface/src/registry/reg_get.c +++ b/lib/erl_interface/src/registry/reg_get.c @@ -19,10 +19,6 @@ * */ -#ifdef VXWORKS -#include <vxWorks.h> -#endif - #include <stdarg.h> #include "reg.h" diff --git a/lib/erl_interface/src/registry/reg_set.c b/lib/erl_interface/src/registry/reg_set.c index 95b90adb87..3846df1cb5 100644 --- a/lib/erl_interface/src/registry/reg_set.c +++ b/lib/erl_interface/src/registry/reg_set.c @@ -19,10 +19,6 @@ * */ -#ifdef VXWORKS -#include <vxWorks.h> -#endif - #include <stdarg.h> #include "reg.h" diff --git a/lib/erl_interface/test/Makefile b/lib/erl_interface/test/Makefile index f8f2ef0156..3e3213d3e1 100644 --- a/lib/erl_interface/test/Makefile +++ b/lib/erl_interface/test/Makefile @@ -34,12 +34,7 @@ MODULES= \ ei_print_SUITE \ ei_tmo_SUITE \ erl_call_SUITE \ - erl_connect_SUITE \ - erl_global_SUITE \ - erl_eterm_SUITE \ - erl_ext_SUITE \ - erl_format_SUITE \ - erl_match_SUITE \ + ei_global_SUITE \ port_call_SUITE \ runner diff --git a/lib/erl_interface/test/all_SUITE_data/Makefile.src b/lib/erl_interface/test/all_SUITE_data/Makefile.src index 4f27b097c8..0d242663ea 100644 --- a/lib/erl_interface/test/all_SUITE_data/Makefile.src +++ b/lib/erl_interface/test/all_SUITE_data/Makefile.src @@ -23,7 +23,7 @@ CC0 = @CC@ CC = .@DS@gccifier@exe@ -CC"$(CC0)" CFLAGS0 = @CFLAGS@ -I@erl_interface_include@ CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -EI_COMMON_OBJS = runner@obj@ ei_runner@obj@ +EI_COMMON_OBJS = runner@obj@ ei_runner@obj@ my_ussi@obj@ ALL_OBJS = gccifier@exe@ $(EI_COMMON_OBJS) CP=cp diff --git a/lib/erl_interface/test/all_SUITE_data/init_tc.erl b/lib/erl_interface/test/all_SUITE_data/init_tc.erl index d9ad291f3d..da3d8053a0 100644 --- a/lib/erl_interface/test/all_SUITE_data/init_tc.erl +++ b/lib/erl_interface/test/all_SUITE_data/init_tc.erl @@ -77,11 +77,7 @@ generate_c(Cases, File, TcName) -> lists:foreach(fun(Case) -> io:format(File, " ~s,~n", [Case]) end, Cases), io:format(File, "~s", [["};\n\n", - "#ifdef VXWORKS\n", - "int ", TcName, "(int argc, char* argv[])\n", - "#else\n", "int main(int argc, char* argv[])\n", - "#endif\n", "{\n", " run_tests(argv[0], test_cases, ", "sizeof(test_cases)/sizeof(test_cases[0]));\n", diff --git a/lib/erl_interface/test/all_SUITE_data/my_ussi.c b/lib/erl_interface/test/all_SUITE_data/my_ussi.c new file mode 100644 index 0000000000..5f8c79b7cf --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/my_ussi.c @@ -0,0 +1,198 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2019. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * %CopyrightEnd% + */ + +/* + * User Supplied Socket Implementation (ussi) + * for test purpose. + */ +#include <stdlib.h> +#include <string.h> +#include "ei.h" + +struct my_ctx +{ + void* ctx; +}; + +/* + * To minimize effort but still test a different context format + * we cheat and wrap the existing TCP default callbacks. + */ +extern ei_socket_callbacks ei_default_socket_callbacks; + +static int my_socket(void **ctx, void *setup_ctx) +{ + struct my_ctx *myctx = malloc(sizeof(struct my_ctx)); + int ret; + ret = ei_default_socket_callbacks.socket(&myctx->ctx, NULL); + *ctx = myctx; + return ret; +} + +static int my_close(void *ctx) +{ + struct my_ctx *myctx = ctx; + int ret = ei_default_socket_callbacks.close(myctx->ctx); + free(myctx); + return ret; +} + +static int my_get_fd(void *ctx, int *fd) +{ + struct my_ctx *myctx = ctx; + return ei_default_socket_callbacks.get_fd(myctx->ctx, fd); +} + +static int my_hs_packet_header_size(void *ctx, int *sz) +{ + struct my_ctx *myctx = ctx; + return ei_default_socket_callbacks.handshake_packet_header_size(myctx->ctx, sz); +} + +static int my_connect_handshake_complete(void *ctx) +{ + struct my_ctx *myctx = ctx; + return ei_default_socket_callbacks.connect_handshake_complete(myctx->ctx); +} + +static int my_accept_handshake_complete(void *ctx) +{ + struct my_ctx *myctx = ctx; + return ei_default_socket_callbacks.accept_handshake_complete(myctx->ctx); +} + +static int my_listen(void *ctx, void *addr, int *len, int backlog) +{ + struct my_ctx *myctx = ctx; + return ei_default_socket_callbacks.listen(myctx->ctx, addr, len, backlog); +} + +static int my_accept(void **ctx, void *addr, int *len, unsigned tmo) +{ + struct my_ctx *listen_ctx = *ctx; + struct my_ctx *conn_ctx = malloc(sizeof(struct my_ctx)); + int ret; + *conn_ctx = *listen_ctx; + ret = ei_default_socket_callbacks.accept(&conn_ctx->ctx, addr, len, tmo); + if (ret == 0) + *ctx = conn_ctx; + else + free(conn_ctx); + return ret; +} + +static int my_connect(void *ctx, void *addr, int len, unsigned tmo) +{ + struct my_ctx *myctx = ctx; + return ei_default_socket_callbacks.connect(myctx->ctx, addr, len, tmo); +} + +static void* memdup(const void* mem, int nbytes) +{ + void *p = malloc(nbytes); + memcpy(p, mem, nbytes); + return p; +} + +static void scramble(void* bytes, int nbytes) +{ +/* Would be nice to really test that only our callbacks are used + and the default ones are not. + Need corresponding Erlang distribution impl to work. + + unsigned char *p = bytes; + int i; + for (i=0; i < nbytes; ++i) + p[i] = ~p[i]; +*/ +} + +/* our own iovec struct to avoid config dependency HAVE_WRITEV */ +struct my_iovec { + void *iov_base; /* Starting address */ + size_t iov_len; /* Number of bytes to transfer */ +}; + +static int my_writev(void *ctx, const void *viov, int iovcnt, ssize_t *len, unsigned tmo) +{ + struct my_ctx *myctx = ctx; + struct my_iovec *iov; + int i, ret; + + /* create mutable copy of both iovec and data */ + iov = memdup(viov, sizeof(struct my_iovec) * iovcnt); + for (i=0; i < iovcnt; ++i) { + iov[i].iov_base = memdup(iov[i].iov_base, iov[i].iov_len); + scramble(iov[i].iov_base, iov[i].iov_len); + } + + ret = ei_default_socket_callbacks.writev(myctx->ctx, viov, iovcnt, len, tmo); + + for (i=0; i < iovcnt; ++i) + free(iov[i].iov_base); + free(iov); + return ret; +} + +static int my_write(void *ctx, const char* buf, ssize_t *len, unsigned tmo) +{ + struct my_ctx *myctx = ctx; + unsigned char* copy = memdup(buf, *len); + int i, ret; + + scramble(copy, *len); + ret = ei_default_socket_callbacks.write(myctx->ctx, copy, len, tmo); + free(copy); + return ret; +} + +static int my_read(void *ctx, char* buf, ssize_t *len, unsigned tmo) +{ + struct my_ctx *myctx = ctx; + int ret, i; + + ret = ei_default_socket_callbacks.read(myctx->ctx, buf, len, tmo); + if (ret == 0) + scramble(buf, *len); + return ret; +} + +ei_socket_callbacks my_ussi = { + 0, /* flags */ + my_socket, + my_close, + my_listen, + my_accept, + my_connect, + my_writev, + my_write, + my_read, + my_hs_packet_header_size, + my_connect_handshake_complete, + my_accept_handshake_complete, + my_get_fd +}; + +void my_ussi_init(void) +{ + my_ussi.flags = ei_default_socket_callbacks.flags; + if (!ei_default_socket_callbacks.writev) + my_ussi.writev = NULL; +} diff --git a/lib/erl_interface/src/legacy/erl_connect.h b/lib/erl_interface/test/all_SUITE_data/my_ussi.h index 6cb5d5cd1b..0db07c990e 100644 --- a/lib/erl_interface/src/legacy/erl_connect.h +++ b/lib/erl_interface/test/all_SUITE_data/my_ussi.h @@ -1,8 +1,8 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 1996-2016. All Rights Reserved. - * + * + * Copyright Ericsson AB 2019. All Rights Reserved. + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -14,12 +14,15 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * * %CopyrightEnd% */ -#ifndef _ERL_CONNECT_H -#define _ERL_CONNECT_H -erlang_pid *erl_self(void); +/* + * User Supplied Socket Implementation (ussi) + * for test purpose. + */ + +extern ei_socket_callbacks my_ussi; -#endif /* _ERL_CONNECT_H */ +extern void my_ussi_init(void); diff --git a/lib/erl_interface/test/all_SUITE_data/runner.c b/lib/erl_interface/test/all_SUITE_data/runner.c deleted file mode 100644 index 42e8bb03e5..0000000000 --- a/lib/erl_interface/test/all_SUITE_data/runner.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1997-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#ifndef __WIN32__ -#include <unistd.h> -#endif -#include <stdarg.h> - -#include "runner.h" - -#ifndef __WIN32__ -#define _O_BINARY 0 -#define _setmode(fd, mode) -#endif - -#define HEADER_SIZE 4 - -static char* progname; /* Name of this program (from argv[0]). */ -static int fd_from_erl; /* File descriptor from Erlang. */ -static int fd_to_erl; /* File descriptor to Erlang. */ - -static int packet_loop(); -static void ensure_buf_big_enough(); -static int readn(); -static void reply(char* buf, unsigned size); -static void dump(); - -void -run_tests(char* argv0, TestCase test_cases[], unsigned number) -{ - int i; - int n; - char* packet; - - progname = argv0; - _setmode(0, _O_BINARY); - _setmode(1, _O_BINARY); - fd_from_erl = 0; - fd_to_erl = 1; - - packet = read_packet(&n); - - /* - * Dispatch to the appropriate test function. - */ - - i = packet[0] * 256 + packet[1]; - if (i >= number) { - fprintf(stderr, "%s: bad test case number %d", - progname, i); - free(packet); - exit(1); - } else { - (*test_cases[i])(); - free(packet); - } -} - - -/*********************************************************************** - * - * R e a d i n g p a c k e t s - * - ************************************************************************/ - -/* - * Reads an Erlang term. - * - * Returns: A pointer to a term (an ETERM structure) if there was - * at term available, or a NULL pointer if there was an 'eot' (end-of-test) - * packet. Aborts if anything else received. - */ - -ETERM* -get_term(void) -{ - char* encoded; - ETERM* term; - int n; - - encoded = read_packet(&n); - - switch (encoded[0]) { - case 'e': - free(encoded); - return NULL; - case 't': - term = erl_decode(encoded+1); - free(encoded); - if (term == NULL) { - fail("Failed to decode term"); - exit(0); - } - return term; - default: - fprintf(stderr, "Garbage received: "); - dump(encoded, n, 16); - putc('\n', stderr); - fail("C program received garbage"); - free(encoded); - exit(1); - } -} - - -/* - * Reads a packet from Erlang. The packet must be a standard {packet, 2} - * packet. This function aborts if any error is detected (including EOF). - * - * Returns: The number of bytes in the packet. - */ - -char *read_packet(int *len) -{ - - unsigned char* io_buf = NULL; /* Buffer for file i/o. */ - int i; - unsigned char header[HEADER_SIZE]; - unsigned packet_length; /* Length of current packet. */ - int bytes_read; - - /* - * Read the packet header. - */ - - bytes_read = readn(fd_from_erl, header, HEADER_SIZE); - - if (bytes_read == 0) { - fprintf(stderr, "%s: Unexpected end of file\n", progname); - exit(1); - } - if (bytes_read != HEADER_SIZE) { - fprintf(stderr, "%s: Failed to read packet header\n", progname); - exit(1); - } - - /* - * Get the length of this packet. - */ - - packet_length = 0; - - for (i = 0; i < HEADER_SIZE; i++) - packet_length = (packet_length << 8) | header[i]; - - if (len) *len=packet_length; /* report length only if caller requested it */ - - if ((io_buf = (char *) malloc(packet_length)) == NULL) { - fprintf(stderr, "%s: insufficient memory for i/o buffer of size %d\n", - progname, packet_length); - exit(1); - } - - /* - * Read the packet itself. - */ - - bytes_read = readn(fd_from_erl, io_buf, packet_length); - if (bytes_read != packet_length) { - fprintf(stderr, "%s: couldn't read packet of length %d\r\n", - progname, packet_length); - free(io_buf); - exit(1); - } - - return io_buf; -} - - -/*********************************************************************** - * S e n d i n g r e p l i e s - * - * The functions below send various types of replies back to Erlang. - * Each reply start with a letter indicating the type of reply. - * - * Reply Translated to on Erlang side - * ----- ---------------------------- - * [$b|Bytes] {bytes, Bytes} - * [$e] eot - * [$f] ct:fail() - * [$f|Reason] ct:fail(Reason) - * [$t|EncodedTerm] {term, Term} - * [$N] 'NULL' - * [$m|Message] io:format("~s", [Message]) (otherwise ignored) - * - ***********************************************************************/ - -/* - * This function reports the outcome of a test fail. It is useful if - * you implement a test case entirely in C code. - * - * If the ok argument is zero, a [$f] reply will be sent to the - * Erlang side (causing ct:fail() to be called); otherwise, - * the atom 'eot' will be sent to Erlang. - * - * If you need to provide more details on a failure, use the fail() function. - */ - -void -do_report(file, line, ok) - char* file; - int line; - int ok; /* Zero if failed; non-zero otherwise. */ -{ - char reason; - unsigned long ab; - unsigned long fb; - - reason = ok ? 'e' : 'f'; - - if (!ok) { - do_fail(file, line, "Generic failure"); - } else { - /* release all unallocated blocks */ - erl_eterm_release(); - /* check mem usage stats */ - erl_eterm_statistics(&ab, &fb); - if ((ab == 0) && (fb == 0) ) { - reply(&reason, 1); - } - else { - char sbuf[128]; - - sprintf(sbuf, "still %lu terms allocated," - " %lu on freelist at end of test", ab, fb); - do_fail(file, line, sbuf); - } - } -} - - -/* - * This function causes a call to ct:fail(Reason) on the - * Erlang side. - */ - -void -do_fail(char* file, int line, char* reason) -{ - char sbuf[2048]; - - sbuf[0] = 'f'; - sprintf(sbuf+1, "%s, line %d: %s", file, line, reason); - reply(sbuf, 1+strlen(sbuf+1)); -} - -/* - * This function sends a message to the Erlang side. - * The message will be written to the test servers log file, - * but will otherwise be completly ignored. - */ - -void -message(char* format, ...) -{ - va_list ap; - char sbuf[1024]; - - sbuf[0] = 'm'; - va_start(ap, format); - vsprintf(sbuf+1, format, ap); - va_end(ap); - - reply(sbuf, 1+strlen(sbuf+1)); -} - -/* - * This function sends the given term to the Erlang side, - * where it will be received as {term, Term}. - * - * If the given pointer is NULL (indicating an invalid term), - * the result on the Erlang side will be the atom 'NULL'. - * - * After sending the term, this function frees the term by - * calling erl_free_term(). - */ - -void -send_term(term) - ETERM* term; /* Term to be sent to Erlang side. */ -{ - char encoded[64*1024]; - int n; - - if (term == NULL) { - encoded[0] = 'N'; - n = 1; - } else { - encoded[0] = 't'; - n = 1 + erl_encode(term, encoded+1); - erl_free_term(term); - } - reply(encoded, n); -} - -#if 0 - -/* Seriously broken!!! */ - -void -send_bin_term(x_ei_buff* x) -{ - x_ei_buff x2; - x_ei_new(&x2); - x2.buff[x2.index++] = 't'; - x_ei_append(&x2, x); - reply(x2.buff, x2.index); - free(x2.buff); -} -#endif - -/* - * This function sends a raw buffer of data to the - * Erlang side, where it will be received as {bytes, Bytes}. - */ - -void -send_buffer(buf, size) - char* buf; /* Buffer with bytes to send to Erlang. */ - int size; /* Size of data to send to Erlang. */ -{ - char* send_buf; - - send_buf = (char *) malloc(size+1); - send_buf[0] = 'b'; - memcpy(send_buf+1, buf, size); - reply(send_buf, size+1); - free(send_buf); -} - -/*********************************************************************** - * - * P r i v a t e h e l p e r s - * - ***********************************************************************/ - -/* - * Sends a packet back to Erlang. - */ - -static void -reply(reply_buf, size) - char* reply_buf; /* Buffer with reply. */ - unsigned size; /* Size of reply. */ -{ - int n; /* Temporary to hold size. */ - int i; /* Loop counter. */ - char* buf; - - - buf = (char *) malloc(size+HEADER_SIZE); - memcpy(buf+HEADER_SIZE, reply_buf, size); - - /* - * Fill the header starting with the least significant byte. - */ - - n = size; - for (i = HEADER_SIZE-1; i >= 0; i--) { - buf[i] = (char) n; /* Store least significant byte. */ - n = n >> 8; - } - - size += HEADER_SIZE; -/* - fprintf(stderr, "\r\nReply size: %u\r\n", - (unsigned)buf[0] << 8 + (unsigned)buf[1]); - - for (i = 0; i < size; i++) { - fprintf(stderr,"%u %c\r\n",buf[i],buf[i]); - } - - fprintf(stderr, "\r\n"); -*/ - write(fd_to_erl, buf, size); - free(buf); -} - - -/* - * Reads len number of bytes. - */ - -static int -readn(fd, buf, len) - int fd; /* File descriptor to read from. */ - unsigned char *buf; /* Store in this buffer. */ - int len; /* Number of bytes to read. */ -{ - int n; /* Byte count in last read call. */ - int sofar = 0; /* Bytes read so far. */ - - do { - if ((n = read(fd, buf+sofar, len-sofar)) <= 0) - /* error or EOF in read */ - return(n); - sofar += n; - } while (sofar < len); - return sofar; -} - -void -dump(buf, sz, max) - unsigned char* buf; - int sz; - int max; -{ - int i, imax; - char comma[5] = ","; - - if (!sz) - return; - if (sz > max) - imax = max; - else - imax = sz; - - for (i=0; i<imax; i++) { - if (i == imax-1) { - if (sz > max) - strcpy(comma, ",..."); - else - comma[0] = 0; - } - if (isdigit(buf[i])) - fprintf(stderr, "%u%s", (int)(buf[i]), comma); - else { - if (isalpha(buf[i])) { - fprintf(stderr, "%c%s", buf[i], comma); - } - else - fprintf(stderr, "%u%s", (int)(buf[i]), comma); - } - } -} - diff --git a/lib/erl_interface/test/all_SUITE_data/runner.h b/lib/erl_interface/test/all_SUITE_data/runner.h deleted file mode 100644 index 493602869f..0000000000 --- a/lib/erl_interface/test/all_SUITE_data/runner.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1997-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#include "erl_interface.h" - -typedef void (*TestCase)(void); - -#define TESTCASE(name) void name(void) -#define ASIZE(a) (sizeof(a)/sizeof(a[0])) - -void run_tests(char* argv0, TestCase cases[], unsigned number); - -/* - * Reading. - */ - -ETERM* get_term(void); -char *read_packet(int *len); - -/* - * Sending replies. - */ - -#define fail(reason) do_fail(__FILE__, __LINE__, reason) -#define report(ok) do_report(__FILE__, __LINE__, ok) - -void do_report(char* file, int line, int ok); -void do_fail(char* file, int line, char* reason); -void send_term(ETERM* term); -void send_buffer(char* buf, int size); -void message(char* format, ...); - -void send_bin_term(ei_x_buff* x); - diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl index f40c67375b..c49b8a358a 100644 --- a/lib/erl_interface/test/ei_accept_SUITE.erl +++ b/lib/erl_interface/test/ei_accept_SUITE.erl @@ -43,12 +43,15 @@ init_per_testcase(Case, Config) -> runner:init_per_testcase(?MODULE, Case, Config). ei_accept(Config) when is_list(Config) -> - ei_accept_do(Config, 0), % default - ei_accept_do(Config, 21). % ei_set_compat_rel + [ei_accept_do(Config, CR, SI) + || CR <- [0,21], + SI <- [default, ussi]], + ok. -ei_accept_do(Config, CompatRel) -> +ei_accept_do(Config, CompatRel, SockImpl) -> + io:format("CompatRel=~p, SockImpl=~p\n", [CompatRel, SockImpl]), P = runner:start(Config, ?interpret), - 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, CompatRel), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, CompatRel, SockImpl), Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))), io:format("Myname ~p ~n", [Myname]), @@ -72,7 +75,8 @@ ei_accept_do(Config, CompatRel) -> {ok, ListenFd} = ei_publish(P, Port), {any, EINode} ! TermToSend, - {ok, Fd, _Node} = ei_accept(P, ListenFd), + {ok, Fd, Node} = ei_accept(P, ListenFd), + Node = node(), Got1 = ei_receive(P, Fd), %% Send again, now without auto-connect @@ -88,9 +92,13 @@ ei_accept_do(Config, CompatRel) -> ei_threaded_accept(Config) when is_list(Config) -> Einode = filename:join(proplists:get_value(data_dir, Config), "eiaccnode"), + ei_threaded_accept_do(Einode, default), + ei_threaded_accept_do(Einode, ussi), + ok. + +ei_threaded_accept_do(Einode, SockImpl) -> N = 3, - Host = atom_to_list(node()), - start_einode(Einode, N, Host), + start_einode(Einode, N, SockImpl), io:format("started eiaccnode"), TestServerPid = self(), [spawn_link(fun() -> send_rec_einode(I, TestServerPid) end) || I <- lists:seq(0, N-1)], @@ -101,7 +109,7 @@ ei_threaded_accept(Config) when is_list(Config) -> %% Test erlang:monitor toward erl_interface "processes" monitor_ei_process(Config) when is_list(Config) -> P = runner:start(Config, ?interpret), - 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, 0, default), Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))), io:format("Myname ~p ~n", [Myname]), @@ -125,10 +133,19 @@ monitor_ei_process(Config) when is_list(Config) -> runner:finish(P), - [{'DOWN', MRef1, process, {any, EINode}, noconnection}, - {'DOWN', MRef2, process, {any, EINode}, noconnection} - ] = lists:sort(flush(2, 1000)), - + ok =receive + {'DOWN', MRef1, process, {any, EINode}, noconnection} -> + ok + after 1000 -> + timeout + end, + ok = receive + {'DOWN', MRef2, process, {any, EINode}, noconnection} -> + ok + after 1000 -> + timeout + end, + [] = flush(0, 1000), ok. waitfornode(String,0) -> @@ -164,9 +181,10 @@ send_rec_einode(N, TestServerPid) -> ct:fail(EINode) end. -start_einode(Einode, N, Host) -> +start_einode(Einode, N, SockImpl) -> Einodecmd = Einode ++ " " ++ atom_to_list(erlang:get_cookie()) - ++ " " ++ integer_to_list(N) ++ " " ++ Host, + ++ " " ++ integer_to_list(N) + ++ " " ++ atom_to_list(SockImpl), io:format("Einodecmd ~p ~n", [Einodecmd]), open_port({spawn, Einodecmd}, []), ok. @@ -174,8 +192,8 @@ start_einode(Einode, N, Host) -> %%% Interface functions for ei (erl_interface) functions. -ei_connect_init(P, Num, Cookie, Creation, Compat) -> - send_command(P, ei_connect_init, [Num,Cookie,Creation,Compat]), +ei_connect_init(P, Num, Cookie, Creation, Compat, SockImpl) -> + send_command(P, ei_connect_init, [Num,Cookie,Creation,Compat,SockImpl]), case get_term(P) of {term,Int} when is_integer(Int) -> Int end. diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src index 10ef437f8b..7fd0a123b4 100644 --- a/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src +++ b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src @@ -25,6 +25,7 @@ CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" LD = @LD@ LIBEI = @erl_interface_eilib@ LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + ../all_SUITE_data/my_ussi@obj@ \ $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ @erl_interface_threadlib@ CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c index 09b0b5440b..64cb2dc447 100644 --- a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c +++ b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c @@ -27,9 +27,6 @@ #include <stdio.h> #include <string.h> -#ifdef VXWORKS -#include "reclaim.h" -#endif #ifdef __WIN32__ #include <winsock2.h> @@ -41,6 +38,7 @@ #endif #include "ei_runner.h" +#include "my_ussi.h" static void cmd_ei_connect_init(char* buf, int len); static void cmd_ei_publish(char* buf, int len); @@ -58,7 +56,7 @@ static struct { int num_args; /* Number of arguments. */ void (*func)(char* buf, int len); } commands[] = { - "ei_connect_init", 4, cmd_ei_connect_init, + "ei_connect_init", 5, cmd_ei_connect_init, "ei_publish", 1, cmd_ei_publish, "ei_accept", 1, cmd_ei_accept, "ei_receive", 1, cmd_ei_receive, @@ -110,10 +108,11 @@ static void cmd_ei_connect_init(char* buf, int len) unsigned long compat; char node_name[100]; char cookie[MAXATOMLEN], * cp = cookie; + char socket_impl[10]; ei_x_buff res; if (ei_decode_long(buf, &index, &num) < 0) fail("expected int"); - sprintf(node_name, "c%d", num); + sprintf(node_name, "c%ld", num); if (ei_decode_atom(buf, &index, cookie) < 0) fail("expected atom (cookie)"); if (cookie[0] == '\0') @@ -124,7 +123,18 @@ static void cmd_ei_connect_init(char* buf, int len) fail("expected uint"); if (compat) ei_set_compat_rel(compat); - r = ei_connect_init(&ec, node_name, cp, creation); + if (ei_decode_atom_as(buf, &index, socket_impl, sizeof(socket_impl), + ERLANG_ASCII, NULL, NULL) < 0) + fail("expected atom (socket_impl)"); + if (strcmp(socket_impl,"default") == 0) + r = ei_connect_init(&ec, node_name, cp, creation); + else if (strcmp(socket_impl,"ussi") == 0) + r = ei_connect_init_ussi(&ec, node_name, cp, creation, + &my_ussi, sizeof(my_ussi), NULL); + else + fail1("unknown socket_impl atom '%s'", socket_impl); + + ei_x_new_with_version(&res); ei_x_encode_long(&res, r); send_bin_term(&res); @@ -152,9 +162,6 @@ static void cmd_ei_publish(char* buf, int len) if ((i = ei_publish(&ec, lport)) == -1) fail("ei_publish"); -#ifdef VXWORKS - save_fd(i); -#endif /* send listen-fd, result and errno */ ei_x_new_with_version(&x); ei_x_encode_tuple_header(&x, 3); @@ -179,9 +186,6 @@ static void cmd_ei_accept(char* buf, int len) fail("expected int (listen fd)"); r = ei_accept(&ec, listen, &conn); -#ifdef VXWORKS - save_fd(r); -#endif /* send result, errno and nodename */ ei_x_new_with_version(&x); ei_x_encode_tuple_header(&x, 3); diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c index 90c7a2259f..4ce55cacef 100644 --- a/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c +++ b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c @@ -22,35 +22,28 @@ #include <stdlib.h> #include <stdio.h> +#include <string.h> #ifdef __WIN32__ #include <winsock2.h> #include <windows.h> #include <process.h> #else -#ifndef VXWORKS #include <pthread.h> -#endif #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #endif #include "ei.h" +#include "my_ussi.h" -#ifdef VXWORKS -#include <vxWorks.h> -#include <sockLib.h> -#include <inetLib.h> -#define MAIN cnode -#else #define MAIN main -#endif /* A small einode. To be called from the test case ei_accept_SUITE:multi_thread - usage: eiaccnode <cookie> <n> + usage: eiaccnode <cookie> <n> <default|ussi> - start threads 0..n-1 - in each thread @@ -61,7 +54,8 @@ - shutdown gracefully */ -static const char* cookie, * desthost; +static const char* cookie; +static int use_ussi; #ifndef SD_SEND #ifdef SHUTWR @@ -78,7 +72,7 @@ static void* #endif einode_thread(void* num) { - int n = (int)num; + int n = (int)(long)num; int port; ei_cnode ec; char myname[100], destname[100], filename[100]; @@ -88,10 +82,15 @@ static void* FILE* file; sprintf(filename, "eiacc%d_trace.txt", n); - file = fopen(filename, "w"); + file = fopen(filename, "a"); sprintf(myname, "eiacc%d", n); fflush(file); - r = ei_connect_init(&ec, myname, cookie, 0); + fprintf(file, "---- use_ussi = %d ----\n", use_ussi); fflush(file); + if (use_ussi) + r = ei_connect_init_ussi(&ec, myname, cookie, 0, + &my_ussi, sizeof(my_ussi), NULL); + else + r = ei_connect_init(&ec, myname, cookie, 0); port = 0; listen = ei_listen(&ec, &port, 5); if (listen <= 0) { @@ -151,54 +150,52 @@ static void* return 0; } +int MAIN(int argc, char *argv[]) { int i, n, no_threads; -#ifndef VXWORKS #ifdef __WIN32__ HANDLE threads[100]; #else pthread_t threads[100]; #endif -#endif - if (argc < 3) + if (argc < 4) exit(1); cookie = argv[1]; n = atoi(argv[2]); if (n > 100) exit(2); - desthost = argv[3]; - if (argc == 3) + + if (strcmp(argv[3], "default") == 0) + use_ussi = 0; + else if (strcmp(argv[3], "ussi") == 0) + use_ussi = 1; + else + printf("bad argv[3] '%s'", argv[3]); + + if (argc == 4) no_threads = 0; else no_threads = argv[4] != NULL && strcmp(argv[4], "nothreads") == 0; -#ifdef VXWORKS - no_threads = 1; -#endif ei_init(); for (i = 0; i < n; ++i) { if (!no_threads) { -#ifndef VXWORKS #ifdef __WIN32__ unsigned tid; threads[i] = (HANDLE)_beginthreadex(NULL, 0, einode_thread, - (void*)i, 0, &tid); -#else - pthread_create(&threads[i], NULL, einode_thread, (void*)i); -#endif + (void*)(size_t)i, 0, &tid); #else - ; + pthread_create(&threads[i], NULL, einode_thread, (void*)(size_t)i); #endif } else - einode_thread((void*)i); + einode_thread((void*)(size_t)i); } if (!no_threads) -#ifndef VXWORKS for (i = 0; i < n; ++i) { #ifdef __WIN32__ if (WaitForSingleObject(threads[i], INFINITE) != WAIT_OBJECT_0) @@ -207,9 +204,6 @@ MAIN(int argc, char *argv[]) #endif printf("bad wait thread %d\n", i); } -#else - ; -#endif printf("ok\n"); return 0; } diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl index 6184ce801b..2ec1237e8e 100644 --- a/lib/erl_interface/test/ei_connect_SUITE.erl +++ b/lib/erl_interface/test/ei_connect_SUITE.erl @@ -24,7 +24,7 @@ -include_lib("common_test/include/ct.hrl"). -include("ei_connect_SUITE_data/ei_connect_test_cases.hrl"). --export([all/0, suite/0, +-export([all/0, suite/0, groups/0, init_per_testcase/2, ei_send/1, ei_reg_send/1, @@ -33,7 +33,8 @@ rpc_test/1, ei_send_funs/1, ei_threaded_send/1, - ei_set_get_tracelevel/1]). + ei_set_get_tracelevel/1, + ei_connect_host_port_test/1]). -import(runner, [get_term/1,send_term/2]). @@ -42,15 +43,30 @@ suite() -> {timetrap, {seconds, 30}}]. all() -> - [ei_send, ei_reg_send, ei_rpc, ei_format_pid, ei_send_funs, - ei_threaded_send, ei_set_get_tracelevel]. + [ei_threaded_send, + ei_connect_host_port_test, + {group, default}, + {group, ussi}]. + +groups() -> + Members = [ei_send, + ei_format_pid, + ei_send_funs, + ei_set_get_tracelevel, + ei_reg_send, + ei_rpc], + [{default, [], Members}, + {ussi, [], Members}]. + +get_group(Config) -> + proplists:get_value(name, proplists:get_value(tc_group_properties,Config)). init_per_testcase(Case, Config) -> runner:init_per_testcase(?MODULE, Case, Config). ei_send(Config) when is_list(Config) -> P = runner:start(Config, ?interpret), - 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, get_group(Config)), {ok,Fd} = ei_connect(P, node()), ok = ei_send(P, Fd, self(), AMsg={a,message}), @@ -63,7 +79,7 @@ ei_send(Config) when is_list(Config) -> ei_format_pid(Config) when is_list(Config) -> S = self(), P = runner:start(Config, ?interpret), - 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, get_group(Config)), {ok,Fd} = ei_connect(P, node()), ok = ei_format_pid(P, Fd, S), @@ -75,7 +91,7 @@ ei_format_pid(Config) when is_list(Config) -> ei_send_funs(Config) when is_list(Config) -> P = runner:start(Config, ?interpret), - 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, get_group(Config)), {ok,Fd} = ei_connect(P, node()), Fun1 = fun ei_send/1, @@ -94,7 +110,7 @@ ei_send_funs(Config) when is_list(Config) -> ei_reg_send(Config) when is_list(Config) -> P = runner:start(Config, ?interpret), - 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, get_group(Config)), {ok,Fd} = ei_connect(P, node()), ARegName = a_strange_registred_name, @@ -143,7 +159,7 @@ start_einode(Einode, N, Host) -> ei_rpc(Config) when is_list(Config) -> P = runner:start(Config, ?interpret), - 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, get_group(Config)), {ok,Fd} = ei_connect(P, node()), S= "Hej du glade!", SRev = lists:reverse(S), @@ -157,7 +173,7 @@ ei_rpc(Config) when is_list(Config) -> ei_set_get_tracelevel(Config) when is_list(Config) -> P = runner:start(Config, ?interpret), 5 = ei_set_get_tracelevel(P, 5), - 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, get_group(Config)), {ok,Fd} = ei_connect(P, node()), S= "Hej du glade!", SRev = lists:reverse(S), @@ -171,10 +187,31 @@ ei_set_get_tracelevel(Config) when is_list(Config) -> ok. +ei_connect_host_port_test(Config) when is_list(Config) -> + P = runner:start(Config, ?interpret), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, default), + [NodeName, Hostname] = string:lexemes(atom_to_list(node()), "@"), + {ok, NamePortList} = net_adm:names(), + {value, {_, Port}} + = lists:search(fun({N, _}) -> + string:equal(N, NodeName) + end, + NamePortList), + {ok,Fd} = ei_connect_host_port(P, + erlang:list_to_atom(Hostname), + Port), + ok = ei_send(P, Fd, self(), AMsg={a,message}), + receive AMsg -> ok end, + + runner:send_eot(P), + runner:recv_eot(P), + ok. + + %%% Interface functions for ei (erl_interface) functions. -ei_connect_init(P, Num, Cookie, Creation) -> - send_command(P, ei_connect_init, [Num,Cookie,Creation]), +ei_connect_init(P, Num, Cookie, Creation, SockImpl) -> + send_command(P, ei_connect_init, [Num,Cookie,Creation,SockImpl]), case get_term(P) of {term,Int} when is_integer(Int) -> Int end. @@ -186,6 +223,13 @@ ei_connect(P, Node) -> {term,{-1,Errno}} -> {error,Errno} end. +ei_connect_host_port(P, Hostname, Port) -> + send_command(P, ei_connect_host_port, [Hostname, Port]), + case get_term(P) of + {term,{Fd,_}} when Fd >= 0 -> {ok,Fd}; + {term,{-1,Errno}} -> {error,Errno} + end. + ei_set_get_tracelevel(P, Tracelevel) -> send_command(P, ei_set_get_tracelevel, [Tracelevel]), case get_term(P) of diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src index c2d8261dd8..bbea076ebd 100644 --- a/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src +++ b/lib/erl_interface/test/ei_connect_SUITE_data/Makefile.src @@ -23,10 +23,9 @@ include @erl_interface_mk_include@ CC0 = @CC@ CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" LD = @LD@ -LIBERL = @erl_interface_lib@ LIBEI = @erl_interface_eilib@ LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ - $(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ @erl_interface_threadlib@ CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data EI_CONNECT_OBJS = ei_connect_test@obj@ ei_connect_test_decl@obj@ @@ -39,7 +38,8 @@ clean: $(RM) ei_connect_test@exe@ einode@exe@ ei_connect_test@exe@: $(EI_CONNECT_OBJS) $(LIBEI) - $(LD) @CROSSLDFLAGS@ -o $@ $(EI_CONNECT_OBJS) $(LIBFLAGS) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_CONNECT_OBJS) \ + ../all_SUITE_data/my_ussi@obj@ $(LIBFLAGS) einode@exe@: $(EINODE_OBJS) $(LIBEI) 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 385bcdd422..54e78253a0 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 @@ -27,14 +27,13 @@ #include <stdio.h> #include <string.h> -#ifdef VXWORKS -#include "reclaim.h" -#endif #include "ei_runner.h" +#include "my_ussi.h" static void cmd_ei_connect_init(char* buf, int len); static void cmd_ei_connect(char* buf, int len); +static void cmd_ei_connect_host_port(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); @@ -52,8 +51,9 @@ static struct { int num_args; /* Number of arguments. */ void (*func)(char* buf, int len); } commands[] = { - "ei_connect_init", 3, cmd_ei_connect_init, + "ei_connect_init", 4, cmd_ei_connect_init, "ei_connect", 1, cmd_ei_connect, + "ei_connect_host_port", 2, cmd_ei_connect_host_port, "ei_send", 3, cmd_ei_send, "ei_send_funs", 3, cmd_ei_send_funs, "ei_reg_send", 3, cmd_ei_reg_send, @@ -107,9 +107,11 @@ TESTCASE(interpret) static void cmd_ei_connect_init(char* buf, int len) { int index = 0, r = 0; - long l; + long l, creation; char b[100]; char cookie[MAXATOMLEN], * cp = cookie; + char socket_impl[10]; + int use_ussi; ei_x_buff res; if (ei_decode_long(buf, &index, &l) < 0) fail("expected int"); @@ -118,7 +120,23 @@ static void cmd_ei_connect_init(char* buf, int len) fail("expected atom (cookie)"); if (cookie[0] == '\0') cp = NULL; - r = ei_connect_init(&ec, b, cp, 0); + if (ei_decode_long(buf, &index, &creation) < 0) + fail("expected int (creation)"); + if (ei_decode_atom_as(buf, &index, socket_impl, + sizeof(socket_impl), ERLANG_ASCII, NULL, NULL) < 0) + fail("expected atom (socket_impl)"); + if (strcmp(socket_impl, "default") == 0) + use_ussi = 0; + else if (strcmp(socket_impl, "ussi") == 0) + use_ussi = 1; + else + fail1("expected atom 'default' or 'ussi', got '%s'", socket_impl); + + if (use_ussi) + r = ei_connect_init_ussi(&ec, b, cp, (short)creation, + &my_ussi, sizeof(my_ussi), NULL); + else + r = ei_connect_init(&ec, b, cp, (short)creation); ei_x_new_with_version(&res); ei_x_encode_long(&res, r); send_bin_term(&res); @@ -133,11 +151,20 @@ static void cmd_ei_connect(char* buf, int len) if (ei_decode_atom(buf, &index, node) < 0) fail("expected atom"); i=ei_connect(&ec, node); -#ifdef VXWORKS - if(i >= 0) { - save_fd(i); - } -#endif + send_errno_result(i); +} + +static void cmd_ei_connect_host_port(char* buf, int len) +{ + int index = 0; + char hostname[256]; + int i; + long port; + if (ei_decode_atom(buf, &index, hostname) < 0) + fail("expected atom"); + if (ei_decode_long(buf, &index, &port) < 0) + fail("expected int"); + i = ei_connect_host_port(&ec, hostname, (int)port); send_errno_result(i); } @@ -225,7 +252,7 @@ static void cmd_ei_send_funs(char* buf, int len) fail("expected Fun1"); if (ei_decode_fun(buf, &index, &fun2) < 0) fail("expected Fun2"); - if (ei_decode_bitstring(buf, &index, &bitstring, &bitoffs, &bits) < 0) + if (ei_decode_bitstring(buf, &index, (const char**)&bitstring, &bitoffs, &bits) < 0) fail("expected bitstring"); if (ei_x_new_with_version(&x) < 0) fail("ei_x_new_with_version"); diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/einode.c b/lib/erl_interface/test/ei_connect_SUITE_data/einode.c index bb71575740..083ca1d372 100644 --- a/lib/erl_interface/test/ei_connect_SUITE_data/einode.c +++ b/lib/erl_interface/test/ei_connect_SUITE_data/einode.c @@ -28,20 +28,13 @@ #include <windows.h> #include <process.h> #else -#ifndef VXWORKS #include <pthread.h> -#endif #include <sys/socket.h> #endif #include "ei.h" -#include "erl_interface.h" -#ifdef VXWORKS -#define MAIN cnode -#else #define MAIN main -#endif /* A small einode. @@ -105,32 +98,25 @@ static void* MAIN(int argc, char *argv[]) { int i, n, no_threads; -#ifndef VXWORKS #ifdef __WIN32__ HANDLE threads[100]; #else pthread_t threads[100]; #endif -#endif if (argc < 3) exit(1); - erl_init(NULL, 0); + ei_init(); cookie = argv[1]; n = atoi(argv[2]); if (n > 100) exit(2); desthost = argv[3]; -#ifndef VXWORKS no_threads = argv[4] != NULL && strcmp(argv[4], "nothreads") == 0; -#else - no_threads = 1; -#endif for (i = 0; i < n; ++i) { if (!no_threads) { -#ifndef VXWORKS #ifdef __WIN32__ unsigned tid; threads[i] = (HANDLE)_beginthreadex(NULL, 0, einode_thread, @@ -138,14 +124,10 @@ MAIN(int argc, char *argv[]) #else pthread_create(&threads[i], NULL, einode_thread, (void*)i); #endif -#else - ; -#endif } else einode_thread((void*)i); } if (!no_threads) -#ifndef VXWORKS for (i = 0; i < n; ++i) { #ifdef __WIN32__ if (WaitForSingleObject(threads[i], INFINITE) != WAIT_OBJECT_0) @@ -154,9 +136,6 @@ MAIN(int argc, char *argv[]) #endif printf("bad wait thread %d\n", i); } -#else - ; -#endif printf("ok\n"); return 0; } diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl index e005ec89c7..35feeea42c 100644 --- a/lib/erl_interface/test/ei_decode_SUITE.erl +++ b/lib/erl_interface/test/ei_decode_SUITE.erl @@ -77,29 +77,19 @@ test_ei_decode_ulong(Config) when is_list(Config) -> %% ######################################################################## %% test_ei_decode_longlong(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skip,"Skipped on VxWorks"}; - _ -> - P = runner:start(Config, ?test_ei_decode_longlong), - send_integers2(P), - runner:recv_eot(P), - ok - end. + P = runner:start(Config, ?test_ei_decode_longlong), + send_integers2(P), + runner:recv_eot(P), + ok. %% ######################################################################## %% test_ei_decode_ulonglong(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skip,"Skipped on VxWorks"}; - _ -> - P = runner:start(Config, ?test_ei_decode_ulonglong), - send_integers2(P), - runner:recv_eot(P), - ok - end. + P = runner:start(Config, ?test_ei_decode_ulonglong), + send_integers2(P), + runner:recv_eot(P), + ok. %% ######################################################################## %% @@ -128,13 +118,8 @@ test_ei_decode_nonoptimal(Config) when is_list(Config) -> send_non_optimal_pos(P), % decode_char send_non_optimal(P), % decode_long send_non_optimal_pos(P), % decode_ulong - case os:type() of - vxworks -> - ok; - _ -> - send_non_optimal(P), % decode_longlong - send_non_optimal_pos(P) % decode_ulonglong - end, + send_non_optimal(P), % decode_longlong + send_non_optimal_pos(P), % decode_ulonglong runner:recv_eot(P), ok. 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 46d6b8f2af..b27c3c589c 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 @@ -20,10 +20,6 @@ #include <string.h> -#ifdef VXWORKS -#include "reclaim.h" -#endif - #include "ei_runner.h" /* @@ -31,15 +27,9 @@ * Author: Kent */ -#ifdef VXWORKS -#define MESSAGE_BACK(SIZE) \ - message("err = %d, size2 = %d, expected size = %d", \ - err, size1, SIZE); -#else #define MESSAGE_BACK(SIZE) \ message("err = %d, size2 = %d, expected size = %d, long long val = %lld", \ err, size1, SIZE, (EI_LONGLONG)p); -#endif #define ERLANG_ANY (ERLANG_ASCII|ERLANG_LATIN1|ERLANG_UTF8) @@ -483,7 +473,6 @@ TESTCASE(test_ei_decode_longlong) { ei_init(); -#ifndef VXWORKS EI_DECODE_2 (decode_longlong, 2, EI_LONGLONG, 0); EI_DECODE_2 (decode_longlong, 2, EI_LONGLONG, 255); EI_DECODE_2 (decode_longlong, 5, EI_LONGLONG, 256); @@ -509,7 +498,6 @@ TESTCASE(test_ei_decode_longlong) EI_DECODE_2_FAIL(decode_longlong, 11, EI_LONGLONG, ll(0xffffffffffffffff)); EI_DECODE_2_FAIL(decode_longlong, 1, EI_LONGLONG, 0); /* Illegal type */ -#endif report(1); } @@ -519,7 +507,6 @@ TESTCASE(test_ei_decode_ulonglong) { ei_init(); -#ifndef VXWORKS EI_DECODE_2 (decode_ulonglong, 2, EI_ULONGLONG, 0); EI_DECODE_2 (decode_ulonglong, 2, EI_ULONGLONG, 255); EI_DECODE_2 (decode_ulonglong, 5, EI_ULONGLONG, 256); @@ -545,7 +532,6 @@ TESTCASE(test_ei_decode_ulonglong) EI_DECODE_2 (decode_ulonglong,11, EI_ULONGLONG, ll(0xffffffffffffffff)); EI_DECODE_2_FAIL(decode_ulonglong, 1, EI_ULONGLONG, 0); /* Illegal type */ -#endif report(1); } @@ -637,8 +623,6 @@ TESTCASE(test_ei_decode_nonoptimal) /* ---------------------------------------------------------------- */ -#ifndef VXWORKS - EI_DECODE_2(decode_longlong, 2, EI_LONGLONG, 42); EI_DECODE_2(decode_longlong, 5, EI_LONGLONG, 42); EI_DECODE_2(decode_longlong, 4, EI_LONGLONG, 42); @@ -681,8 +665,6 @@ TESTCASE(test_ei_decode_nonoptimal) /* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ /* EI_DECODE_2(decode_ulonglong, EI_ULONGLONG, -42); */ -#endif /* !VXWORKS */ - /* ---------------------------------------------------------------- */ report(1); diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c index 512f9ed0c7..5594bec757 100644 --- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c +++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c @@ -18,10 +18,6 @@ * %CopyrightEnd% */ -#ifdef VXWORKS -#include "reclaim.h" -#endif - #include "ei_runner.h" /* diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl index 0267a5126f..10fcd6b871 100644 --- a/lib/erl_interface/test/ei_encode_SUITE.erl +++ b/lib/erl_interface/test/ei_encode_SUITE.erl @@ -101,59 +101,49 @@ test_ei_encode_ulong(Config) when is_list(Config) -> %% ######################################################################## %% test_ei_encode_longlong(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skip,"Skipped on VxWorks"}; - _ -> - P = runner:start(Config, ?test_ei_encode_longlong), - - {<<97,0>> ,0} = get_buf_and_term(P), - {<<97,255>> ,255} = get_buf_and_term(P), - {<<98,256:32/big-signed-integer>>,256} = get_buf_and_term(P), - {<<98,-1:32/big-signed-integer>> ,-1} = get_buf_and_term(P), - - {<<98, 16#07ffffff:32/big-signed-integer>>, 16#07ffffff} = get_buf_and_term(P), - {<<98,-16#08000000:32/big-signed-integer>>,-16#08000000} = get_buf_and_term(P), - {<<110,4,0, 0,0,0,8>> , 16#08000000} = get_buf_and_term(P), - {<<110,4,1, 1,0,0,8>> ,-16#08000001} = get_buf_and_term(P), - - {<<110,4,0, 255,255,255,127>> , 16#7fffffff} = get_buf_and_term(P), - {<<110,4,1, 0,0,0,128>> ,-16#80000000} = get_buf_and_term(P), - {<<110,6,0, 255,255,255,255,255,127>> , 16#7fffffffffff} = get_buf_and_term(P), - {<<110,6,1, 0,0,0,0,0,128>> ,-16#800000000000} = get_buf_and_term(P), - {<<110,8,0, 255,255,255,255,255,255,255,127>>,16#7fffffffffffffff} = get_buf_and_term(P), - {<<110,8,1, 0,0,0,0,0,0,0,128>> ,-16#8000000000000000} = get_buf_and_term(P), - - runner:recv_eot(P), - ok - end. + P = runner:start(Config, ?test_ei_encode_longlong), + + {<<97,0>> ,0} = get_buf_and_term(P), + {<<97,255>> ,255} = get_buf_and_term(P), + {<<98,256:32/big-signed-integer>>,256} = get_buf_and_term(P), + {<<98,-1:32/big-signed-integer>> ,-1} = get_buf_and_term(P), + + {<<98, 16#07ffffff:32/big-signed-integer>>, 16#07ffffff} = get_buf_and_term(P), + {<<98,-16#08000000:32/big-signed-integer>>,-16#08000000} = get_buf_and_term(P), + {<<110,4,0, 0,0,0,8>> , 16#08000000} = get_buf_and_term(P), + {<<110,4,1, 1,0,0,8>> ,-16#08000001} = get_buf_and_term(P), + + {<<110,4,0, 255,255,255,127>> , 16#7fffffff} = get_buf_and_term(P), + {<<110,4,1, 0,0,0,128>> ,-16#80000000} = get_buf_and_term(P), + {<<110,6,0, 255,255,255,255,255,127>> , 16#7fffffffffff} = get_buf_and_term(P), + {<<110,6,1, 0,0,0,0,0,128>> ,-16#800000000000} = get_buf_and_term(P), + {<<110,8,0, 255,255,255,255,255,255,255,127>>,16#7fffffffffffffff} = get_buf_and_term(P), + {<<110,8,1, 0,0,0,0,0,0,0,128>> ,-16#8000000000000000} = get_buf_and_term(P), + + runner:recv_eot(P), + ok. %% ######################################################################## %% test_ei_encode_ulonglong(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skip,"Skipped on VxWorks"}; - _ -> - P = runner:start(Config, ?test_ei_encode_ulonglong), - - {<<97,0>> ,0} = get_buf_and_term(P), - {<<97,255>> ,255} = get_buf_and_term(P), - {<<98,256:32/big-unsigned-integer>>,256} = get_buf_and_term(P), - - {<<98, 16#07ffffff:32/big-signed-integer>>,16#07ffffff} = get_buf_and_term(P), - {<<110,4,0, 0,0,0,8>> ,16#08000000} = get_buf_and_term(P), - - {<<110,4,0, 255,255,255,127>> ,16#7fffffff} = get_buf_and_term(P), - {<<110,4,0, 0,0,0,128>> ,16#80000000} = get_buf_and_term(P), - {<<110,4,0, 255,255,255,255>> ,16#ffffffff} = get_buf_and_term(P), - {<<110,6,0, 255,255,255,255,255,255>>,16#ffffffffffff} = get_buf_and_term(P), - {<<110,8,0, 255,255,255,255,255,255,255,255>>,16#ffffffffffffffff} = get_buf_and_term(P), + P = runner:start(Config, ?test_ei_encode_ulonglong), - runner:recv_eot(P), - ok - end. + {<<97,0>> ,0} = get_buf_and_term(P), + {<<97,255>> ,255} = get_buf_and_term(P), + {<<98,256:32/big-unsigned-integer>>,256} = get_buf_and_term(P), + + {<<98, 16#07ffffff:32/big-signed-integer>>,16#07ffffff} = get_buf_and_term(P), + {<<110,4,0, 0,0,0,8>> ,16#08000000} = get_buf_and_term(P), + + {<<110,4,0, 255,255,255,127>> ,16#7fffffff} = get_buf_and_term(P), + {<<110,4,0, 0,0,0,128>> ,16#80000000} = get_buf_and_term(P), + {<<110,4,0, 255,255,255,255>> ,16#ffffffff} = get_buf_and_term(P), + {<<110,6,0, 255,255,255,255,255,255>>,16#ffffffffffff} = get_buf_and_term(P), + {<<110,8,0, 255,255,255,255,255,255,255,255>>,16#ffffffffffffffff} = get_buf_and_term(P), + + runner:recv_eot(P), + ok. %% ######################################################################## %% 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 6f63cc5d7e..6f1276e016 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 @@ -18,10 +18,6 @@ * %CopyrightEnd% */ -#ifdef VXWORKS -#include "reclaim.h" -#endif - #include "ei_runner.h" /* @@ -460,8 +456,6 @@ TESTCASE(test_ei_encode_longlong) { ei_init(); -#ifndef VXWORKS - EI_ENCODE_1(encode_longlong, 0); EI_ENCODE_1(encode_longlong, 255); @@ -490,8 +484,6 @@ TESTCASE(test_ei_encode_longlong) EI_ENCODE_1(encode_longlong, -ll(0x8000000000000000)); -#endif /* !VXWORKS */ - report(1); } @@ -501,8 +493,6 @@ TESTCASE(test_ei_encode_ulonglong) { ei_init(); -#ifndef VXWORKS - EI_ENCODE_1(encode_ulonglong, 0); EI_ENCODE_1(encode_ulonglong, 255); @@ -523,8 +513,6 @@ TESTCASE(test_ei_encode_ulonglong) EI_ENCODE_1(encode_ulonglong, ll(0xffffffffffffffff)); -#endif /* !VXWORKS */ - report(1); } 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 1c0443c0f4..19d2cc1510 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 @@ -18,10 +18,6 @@ * %CopyrightEnd% */ -#ifdef VXWORKS -#include "reclaim.h" -#endif - #include "ei_runner.h" #include <string.h> diff --git a/lib/erl_interface/test/erl_global_SUITE.erl b/lib/erl_interface/test/ei_global_SUITE.erl index 6d3a75c8d7..da80ab24cd 100644 --- a/lib/erl_interface/test/erl_global_SUITE.erl +++ b/lib/erl_interface/test/ei_global_SUITE.erl @@ -19,22 +19,27 @@ %% %% --module(erl_global_SUITE). +-module(ei_global_SUITE). -include_lib("common_test/include/ct.hrl"). --include("erl_global_SUITE_data/erl_global_test_cases.hrl"). +-include("ei_global_SUITE_data/ei_global_test_cases.hrl"). -export([all/0,suite/0, init_per_testcase/2, - erl_global_registration/1, - erl_global_whereis/1, erl_global_names/1]). + ei_global_registration/1, + ei_global_whereis/1, + ei_global_names/1 + ]). -import(runner, [get_term/1,send_term/2]). -define(GLOBAL_NAME, global_register_node_test). all() -> - [erl_global_registration, erl_global_whereis, erl_global_names]. + [ei_global_registration, ei_global_whereis, ei_global_names]. + +get_group(Config) -> + proplists:get_value(name, proplists:get_value(tc_group_properties,Config)). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -43,82 +48,76 @@ suite() -> init_per_testcase(Case, Config) -> runner:init_per_testcase(?MODULE, Case, Config). -erl_global_registration(Config) when is_list(Config) -> +ei_global_registration(Config) when is_list(Config) -> P = runner:start(Config, ?interpret), - {ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, ussi), + {ok,Fd} = ei_connect(P, node()), - ok = erl_global_register(P, Fd, ?GLOBAL_NAME), - ok = erl_global_unregister(P, Fd, ?GLOBAL_NAME), + ok = ei_global_register(P, Fd, ?GLOBAL_NAME), + ok = ei_global_unregister(P, Fd, ?GLOBAL_NAME), - 0 = erl_close_connection(P,Fd), runner:send_eot(P), runner:recv_eot(P), ok. -erl_global_whereis(Config) when is_list(Config) -> +ei_global_whereis(Config) when is_list(Config) -> P = runner:start(Config, ?interpret), - {ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, ussi), + {ok,Fd} = ei_connect(P, node()), Self = self(), yes = global:register_name(?GLOBAL_NAME, Self), - Self = erl_global_whereis(P, Fd, ?GLOBAL_NAME), + Self = ei_global_whereis(P, Fd, ?GLOBAL_NAME), global:unregister_name(?GLOBAL_NAME), - 0 = erl_close_connection(P, Fd), runner:send_eot(P), runner:recv_eot(P), ok. -erl_global_names(Config) when is_list(Config) -> +ei_global_names(Config) when is_list(Config) -> P = runner:start(Config, ?interpret), - {ok, Fd} = erl_connect(P, node(), 42, erlang:get_cookie(), 0), + 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, ussi), + {ok,Fd} = ei_connect(P, node()), Self = self(), global:register_name(?GLOBAL_NAME, Self), - {Names1, _N1} = erl_global_names(P, Fd), + {Names1, _N1} = ei_global_names(P, Fd), true = lists:member(atom_to_list(?GLOBAL_NAME), Names1), global:unregister_name(?GLOBAL_NAME), - {Names2, _N2} = erl_global_names(P, Fd), + {Names2, _N2} = ei_global_names(P, Fd), false = lists:member(atom_to_list(?GLOBAL_NAME), Names2), - 0 = erl_close_connection(P, Fd), runner:send_eot(P), 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. +%% %%% Interface functions for erl_interface functions. -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_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_global_register(P, Fd, Name) -> - send_command(P, erl_global_register, [Fd,Name]), +ei_global_register(P, Fd, Name) -> + send_command(P, ei_global_register, [Fd,Name]), get_send_result(P). -erl_global_whereis(P, Fd, Name) -> - send_command(P, erl_global_whereis, [Fd,Name]), +ei_global_whereis(P, Fd, Name) -> + send_command(P, ei_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]), +ei_global_names(P, Fd) -> + send_command(P, ei_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]), +ei_global_unregister(P, Fd, Name) -> + send_command(P, ei_global_unregister, [Fd,Name]), get_send_result(P). get_send_result(P) -> @@ -132,3 +131,17 @@ get_send_result(P) -> send_command(P, Name, Args) -> runner:send_term(P, {Name,list_to_tuple(Args)}). + + +ei_connect_init(P, Num, Cookie, Creation, SockImpl) -> + send_command(P, ei_connect_init, [Num,Cookie,Creation,SockImpl]), + case get_term(P) of + {term,Int} when is_integer(Int) -> Int + end. + +ei_connect(P, Node) -> + send_command(P, ei_connect, [Node]), + case get_term(P) of + {term,{Fd,_}} when Fd >= 0 -> {ok,Fd}; + {term,{-1,Errno}} -> {error,Errno} + end. diff --git a/lib/erl_interface/test/erl_global_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_global_SUITE_data/Makefile.first index b2c62be1f2..5ec0c06af8 100644 --- a/lib/erl_interface/test/erl_global_SUITE_data/Makefile.first +++ b/lib/erl_interface/test/ei_global_SUITE_data/Makefile.first @@ -18,5 +18,5 @@ # %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 +erl_global_test_decl.c: ei_global_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_global_test -s erlang halt diff --git a/lib/erl_interface/test/erl_global_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_global_SUITE_data/Makefile.src index 1c1530d1b6..43c9095ab4 100644 --- a/lib/erl_interface/test/erl_global_SUITE_data/Makefile.src +++ b/lib/erl_interface/test/ei_global_SUITE_data/Makefile.src @@ -25,17 +25,18 @@ CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" LD = @LD@ LIBERL = @erl_interface_lib@ LIBEI = @erl_interface_eilib@ -LIBFLAGS = ../all_SUITE_data/runner@obj@ \ - $(LIBERL) $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(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@ +EI_GLOBAL_OBJS = ei_global_test@obj@ ei_global_test_decl@obj@ -all: erl_global_test@exe@ - -erl_global_test@exe@: $(OBJS) $(LIBERL) $(LIBEI) - $(LD) @CROSSLDFLAGS@ -o $@ $(OBJS) $(LIBFLAGS) +all: ei_global_test@exe@ clean: - $(RM) $(OBJS) - $(RM) erl_global_test@exe@ + $(RM) $(EI_GLOBAL_OBJS) + $(RM) ei_global_test@exe@ + +ei_global_test@exe@: $(EI_GLOBAL_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_GLOBAL_OBJS) \ + ../all_SUITE_data/my_ussi@obj@ $(LIBFLAGS) diff --git a/lib/erl_interface/test/ei_global_SUITE_data/ei_global_test.c b/lib/erl_interface/test/ei_global_SUITE_data/ei_global_test.c new file mode 100644 index 0000000000..4c018667fe --- /dev/null +++ b/lib/erl_interface/test/ei_global_SUITE_data/ei_global_test.c @@ -0,0 +1,239 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2000-2016. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * %CopyrightEnd% + */ + +/* + * Purpose: Tests the functions in erl_global.c. + * + * See the ei_global_SUITE.erl file for a "table of contents". + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ei_runner.h" +#include "my_ussi.h" +#include "ei_connect.h" + +static void cmd_ei_connect_init(char* buf, int len); +static void cmd_ei_connect(char* buf, int len); +static void cmd_ei_global_register(char* buf, int len); +static void cmd_ei_global_whereis(char* buf, int len); +static void cmd_ei_global_names(char* buf, int len); +static void cmd_ei_global_unregister(char* buf, int len); +static void cmd_ei_close_connection(char* buf, int len); + +static void send_errno_result(int value); + +ei_cnode ec; + +static struct { + char* name; + int num_args; /* Number of arguments. */ + void (*func)(char* buf, int len); +} commands[] = { + "ei_connect_init", 4, cmd_ei_connect_init, + "ei_connect", 1, cmd_ei_connect, + "ei_global_register", 2, cmd_ei_global_register, + "ei_global_whereis", 2, cmd_ei_global_whereis, + "ei_global_names", 1, cmd_ei_global_names, + "ei_global_unregister", 2, cmd_ei_global_unregister +}; + + +/* + * Sends a list contaning all data types to the Erlang side. + */ + +TESTCASE(interpret) +{ + ei_x_buff x; + int i; + ei_term term; + + ei_init(); + + ei_x_new(&x); + while (get_bin_term(&x, &term) == 0) { + char* buf = x.buff, func[MAXATOMLEN]; + int index = x.index, arity; + if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2) + fail("term should be a tuple of size 2"); + if (ei_decode_atom(buf, &index, func) < 0) + fail("function name should be an atom"); + if (ei_decode_tuple_header(buf, &index, &arity) != 0) + fail("function arguments should be a tuple"); + for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) { + if (strcmp(func, commands[i].name) == 0) { + if (arity != commands[i].num_args) + fail("wrong number of arguments"); + commands[i].func(buf + index, x.buffsz - index); + break; + } + } + if (i >= sizeof(commands)/sizeof(commands[0])) { + message("\"%d\" \n", func); + fail("bad command"); + } + } + report(1); + ei_x_free(&x); + return; +} + +static void cmd_ei_connect_init(char* buf, int len) +{ + int index = 0, r = 0; + long l, creation; + char b[100]; + char cookie[MAXATOMLEN], * cp = cookie; + char socket_impl[10]; + int use_ussi; + ei_x_buff res; + if (ei_decode_long(buf, &index, &l) < 0) + fail("expected int"); + sprintf(b, "c%ld", l); + if (ei_decode_atom(buf, &index, cookie) < 0) + fail("expected atom (cookie)"); + if (cookie[0] == '\0') + cp = NULL; + if (ei_decode_long(buf, &index, &creation) < 0) + fail("expected int (creation)"); + if (ei_decode_atom_as(buf, &index, socket_impl, + sizeof(socket_impl), ERLANG_ASCII, NULL, NULL) < 0) + fail("expected atom (socket_impl)"); + if (strcmp(socket_impl, "default") == 0) + use_ussi = 0; + else if (strcmp(socket_impl, "ussi") == 0) + use_ussi = 1; + else + fail1("expected atom 'default' or 'ussi', got '%s'", socket_impl); + + if (use_ussi) + r = ei_connect_init_ussi(&ec, b, cp, (short)creation, + &my_ussi, sizeof(my_ussi), NULL); + else + r = ei_connect_init(&ec, b, cp, (short)creation); + ei_x_new_with_version(&res); + ei_x_encode_long(&res, r); + send_bin_term(&res); + ei_x_free(&res); +} + +static void cmd_ei_connect(char* buf, int len) +{ + int index = 0; + char node[256]; + int i; + if (ei_decode_atom(buf, &index, node) < 0) + fail("expected atom"); + i=ei_connect(&ec, node); + send_errno_result(i); +} + +static void +cmd_ei_global_register(char* buf, int len) +{ + int index = 0; + long fd; + char name[256]; + if (ei_decode_long(buf, &index, &fd) < 0) + fail("expected long"); + if (ei_decode_atom(buf, &index, name) < 0) + fail("expected atom"); + send_errno_result(ei_global_register((int)fd, name, ei_self(&ec))); +} + +static void +cmd_ei_global_whereis(char* buf, int len) +{ + int index = 0; + long fd; + char name[512]; + char node_name[512]; + erlang_pid pid; + if (ei_decode_long(buf, &index, &fd) < 0) + fail("expected long"); + if (ei_decode_atom(buf, &index, name) < 0) + fail("expected atom"); + + if (ei_global_whereis(&ec, fd, name, &pid, node_name) < 0) + fail("ei_global_whereis error code"); + + { + ei_x_buff x; + ei_x_new_with_version(&x); + ei_x_encode_pid(&x, &pid); + send_bin_term(&x); + ei_x_free(&x); + } +} + +static void +cmd_ei_global_names(char* buf, int len) +{ + int index = 0; + long fd; + char** names = NULL; + int count = 0, i; + if (ei_decode_long(buf, &index, &fd) < 0) + fail("expected long"); + + names = ei_global_names(&ec, (int)fd, &count); + + { + ei_x_buff x; + ei_x_new_with_version(&x); + ei_x_encode_tuple_header(&x, 2); + ei_x_encode_list_header(&x, count); + for(i=0; i<count; i++) { + ei_x_encode_string(&x, names[i]); + } + ei_x_encode_empty_list(&x); + ei_x_encode_long(&x, count); + send_bin_term(&x); + ei_x_free(&x); + } +} + +static void +cmd_ei_global_unregister(char* buf, int len) +{ + int index = 0; + long fd; + char name[256]; + if (ei_decode_long(buf, &index, &fd) < 0) + fail("expected long"); + if (ei_decode_atom(buf, &index, name) < 0) + fail("expected atom"); + + send_errno_result(ei_global_unregister(&ec, (int)fd, name)); +} + +static void send_errno_result(int value) +{ + ei_x_buff x; + ei_x_new_with_version(&x); + ei_x_encode_tuple_header(&x, 2); + ei_x_encode_long(&x, value); + ei_x_encode_long(&x, erl_errno); + send_bin_term(&x); + ei_x_free(&x); +} diff --git a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c index 27d4153250..2d332c8b0c 100644 --- a/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c +++ b/lib/erl_interface/test/ei_print_SUITE_data/ei_print_test.c @@ -37,13 +37,9 @@ send_printed_buf(ei_x_buff* x) FILE* f; int n, index = 0, ver; -#ifdef VXWORKS - tmp = "."; -#else if (tmp == NULL) { tmp = "/tmp"; } -#endif strcpy(fn, tmp); strcat(fn, "/ei_print_test.txt"); f = fopen(fn, "w+"); diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl index 5b9de80128..8d8776949c 100644 --- a/lib/erl_interface/test/ei_tmo_SUITE.erl +++ b/lib/erl_interface/test/ei_tmo_SUITE.erl @@ -25,10 +25,12 @@ -include_lib("kernel/include/inet.hrl"). -include("ei_tmo_SUITE_data/ei_tmo_test_cases.hrl"). --export([all/0, suite/0, +-export([all/0, groups/0, suite/0, init_per_testcase/2, end_per_testcase/2, - framework_check/1, ei_accept_tmo/1, ei_connect_tmo/1, ei_send_tmo/1, - ei_connect_tmo/0, + framework_check/1, ei_accept_tmo/1, ei_connect_tmo/1, + ei_send_tmo/1, + ei_send_failure_tmo/1, + ei_connect_unreachable_tmo/0, ei_connect_unreachable_tmo/1, ei_recv_tmo/1]). suite() -> @@ -36,19 +38,25 @@ suite() -> {timetrap, {minutes, 1}}]. all() -> - [framework_check, ei_accept_tmo, ei_connect_tmo, - ei_send_tmo, ei_recv_tmo]. + [framework_check, + ei_connect_unreachable_tmo, + ei_send_failure_tmo, + {group, default}, + {group, ussi}]. + +groups() -> + Members = [ei_recv_tmo, + ei_accept_tmo, + ei_connect_tmo, + ei_send_tmo], + [{default, [], Members}, + {ussi, [], Members}]. + +get_group(Config) -> + proplists:get_value(name, proplists:get_value(tc_group_properties,Config)). init_per_testcase(Case, Config) -> - Config1 = runner:init_per_testcase(?MODULE, Case, Config), - - % test if platform is vxworks_simso - {_,Host} = split(node()), - Bool = case atom_to_list(Host) of - [$v,$x,$s,$i,$m | _] -> true; - _ -> false - end, - [{vxsim,Bool} | Config1]. + runner:init_per_testcase(?MODULE, Case, Config). end_per_testcase(_Case, _Config) -> ok. @@ -76,7 +84,8 @@ do_one_recv(Config,CNode) -> P1 = runner:start(Config, ?recv_tmo), runner:send_term(P1,{CNode, erlang:get_cookie(), - node()}), + node(), + get_group(Config)}), {term, X} = runner:get_term(P1, 10000), true = is_integer(X), CNode1 = join(CNode,Host), @@ -89,24 +98,22 @@ do_one_recv_failure(Config,CNode) -> P1 = runner:start(Config, ?recv_tmo), runner:send_term(P1,{CNode, erlang:get_cookie(), - node()}), + node(), + get_group(Config)}), {term, X} = runner:get_term(P1, 10000), true = is_integer(X), {term, {Ret,ETimedout,ETimedout}} = runner:get_term(P1, 10000), true = (Ret < 0), runner:recv_eot(P1). +-define(EI_DIST_LOW, 5). +-define(EI_DIST_HIGH, 6). %% Check send with timeouts. ei_send_tmo(Config) when is_list(Config) -> - %dbg:tracer(), - %dbg:p(self()), - VxSim = proplists:get_value(vxsim, Config), register(ei_send_tmo_1,self()), do_one_send(Config,self(),c_node_send_tmo_1), do_one_send(Config,ei_send_tmo_1,c_node_send_tmo_2), - do_one_send_failure(Config,self(),cccc1,c_nod_send_tmo_3,VxSim), - do_one_send_failure(Config,ei_send_tmo_1,cccc2,c_nod_send_tmo_4,VxSim), ok. @@ -115,7 +122,8 @@ do_one_send(Config,From,CNode) -> P1 = runner:start(Config, ?send_tmo), runner:send_term(P1,{CNode, erlang:get_cookie(), - node()}), + node(), + get_group(Config)}), {term, X} = runner:get_term(P1, 10000), true = is_integer(X), CNode1 = join(CNode,Host), @@ -130,7 +138,17 @@ do_one_send(Config,From,CNode) -> {term, 0} = runner:get_term(P1, 10000), runner:recv_eot(P1). -do_one_send_failure(Config,From,FakeName,CName,VxSim) -> +ei_send_failure_tmo(Config) when is_list(Config) -> + register(ei_send_tmo_1,self()), + [begin + io:format("Test dist version ~p\n", [Ver]), + do_one_send_failure(Config,self(),cccc1,c_nod_send_tmo_3, Ver), + do_one_send_failure(Config,ei_send_tmo_1,cccc2,c_nod_send_tmo_4, Ver) + end + || Ver <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH)], + ok. + +do_one_send_failure(Config,From,FakeName,CName, OurVer) -> {_,Host} = split(node()), OurName = join(FakeName,Host), Node = join(CName,Host), @@ -140,22 +158,23 @@ do_one_send_failure(Config,From,FakeName,CName,VxSim) -> Else -> exit(Else) end, - EpmdSocket = register(OurName, LSocket, 1, 5), + EpmdSocket = epmd_register(OurName, LSocket, OurVer), P3 = runner:start(Config, ?send_tmo), Cookie = kaksmula_som_ingen_bryr_sig_om, runner:send_term(P3,{CName, Cookie, - OurName}), + OurName, + default}), SocketB = case gen_tcp:accept(LSocket) of {ok, Socket1} -> Socket1; Else2 -> exit(Else2) end, - {hidden,Node,5} = recv_name(SocketB), % See 1) + {hidden,Node} = recv_name(SocketB, OurVer), % See 1) send_status(SocketB, ok), MyChallengeB = gen_challenge(), - send_challenge(SocketB, OurName, MyChallengeB, 5), + send_challenge(SocketB, OurName, MyChallengeB, OurVer), HisChallengeB = recv_challenge_reply(SocketB, MyChallengeB, Cookie), @@ -178,53 +197,43 @@ do_one_send_failure(Config,From,FakeName,CName,VxSim) -> %% must be large enough so there's time for the select() to time out and %% the test program to return the error tuple (below). - Res0 = if VxSim == false -> - {term,{Res,ETO,Iters,ETO}} = runner:get_term(P3, 20000), - Res; - true -> % relax the test for vxsim - case runner:get_term(P3, 20000) of - {term,{Res,ETO,Iters,ETO}} -> - Res; - {term,{Res,_,Iters,_ETO}} -> % EIO? - Res - end - end, + {term,{Res,ETO,Iters,ETO}} = runner:get_term(P3, 20000), runner:recv_eot(P3), - true = ((Res0 < 0) and (Iters > 0)), + true = ((Res < 0) and (Iters > 0)), gen_tcp:close(SocketB), gen_tcp:close(EpmdSocket), ok. %% Check accept with timeouts. -ei_connect_tmo() -> [{require, test_host_not_reachable}]. +ei_connect_unreachable_tmo() -> [{require, test_host_not_reachable}]. -ei_connect_tmo(Config) when is_list(Config) -> - %dbg:tracer(), - %dbg:p(self()), - VxSim = proplists:get_value(vxsim, Config), +ei_connect_unreachable_tmo(Config) when is_list(Config) -> DummyNode = make_and_check_dummy(), P = runner:start(Config, ?connect_tmo), runner:send_term(P,{c_nod_connect_tmo_1, kaksmula_som_ingen_bryr_sig_om, - DummyNode}), - ETimedout = - if VxSim == false -> - {term,{-3,ETO,ETO}} = runner:get_term(P, 10000), - ETO; - true -> % relax the test for vxsim - case runner:get_term(P, 10000) of - {term,{-3,ETO,ETO}} -> - ETO; - {term,{-1,_,ETO}} -> % EHOSTUNREACH = ok - ETO - end - end, + DummyNode, + default}), + {term,{-3,ETimedout,ETimedout}} = runner:get_term(P, 10000), runner:recv_eot(P), + ok. + +ei_connect_tmo(Config) when is_list(Config) -> + [begin + io:format("Test dist version ~p published as ~p\n", [OurVer,OurEpmdVer]), + do_ei_connect_tmo(Config, OurVer, OurEpmdVer) + end + || OurVer <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH), + OurEpmdVer <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH), + OurVer >= OurEpmdVer]. + +do_ei_connect_tmo(Config, OurVer, OurEpmdVer) -> P2 = runner:start(Config, ?connect_tmo), runner:send_term(P2,{c_nod_connect_tmo_2, erlang:get_cookie(), - node()}), + node(), + get_group(Config)}), {term, X} = runner:get_term(P2, 10000), runner:recv_eot(P2), true = is_integer(X), @@ -238,22 +247,24 @@ ei_connect_tmo(Config) when is_list(Config) -> Else -> exit(Else) end, - EpmdSocket = register(OurName, LSocket, 1, 5), + EpmdSocket = epmd_register(OurName, LSocket, OurEpmdVer), P3 = runner:start(Config, ?connect_tmo), Cookie = kaksmula_som_ingen_bryr_sig_om, runner:send_term(P3,{c_nod_connect_tmo_3, Cookie, - OurName}), + OurName, + get_group(Config)}), SocketB = case gen_tcp:accept(LSocket) of {ok, Socket1} -> Socket1; Else2 -> exit(Else2) end, - {hidden,Node,5} = recv_name(SocketB), % See 1) + {hidden,Node} = recv_name(SocketB, OurEpmdVer), % See 1) send_status(SocketB, ok), MyChallengeB = gen_challenge(), - send_challenge(SocketB, OurName, MyChallengeB, 5), + send_challenge(SocketB, OurName, MyChallengeB, OurVer), + recv_complement(SocketB, OurVer, OurEpmdVer), _HisChallengeB = recv_challenge_reply(SocketB, MyChallengeB, Cookie), @@ -266,16 +277,27 @@ ei_connect_tmo(Config) when is_list(Config) -> %% Check accept with timeouts. ei_accept_tmo(Config) when is_list(Config) -> - %%dbg:tracer(), - %%dbg:p(self()), + [begin + io:format("Test our dist ver=~p and assumed ver=~p\n", + [OurVer, AssumedVer]), + do_ei_accept_tmo(Config, OurVer, AssumedVer) + end + || OurVer <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH), + AssumedVer <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH), + OurVer >= AssumedVer], + ok. + +do_ei_accept_tmo(Config, OurVer, AssumedVer) -> P = runner:start(Config, ?accept_tmo), runner:send_term(P,{c_nod_som_ingen_kontaktar_1, - kaksmula_som_ingen_bryr_sig_om}), + kaksmula_som_ingen_bryr_sig_om, + get_group(Config)}), {term,{-1,ETimedout,ETimedout}} = runner:get_term(P, 10000), runner:recv_eot(P), P2 = runner:start(Config, ?accept_tmo), runner:send_term(P2,{c_nod_som_vi_kontaktar_1, - erlang:get_cookie()}), + erlang:get_cookie(), + get_group(Config)}), receive after 1000 -> ok end, CNode1 = make_node(c_nod_som_vi_kontaktar_1), {ignored,CNode1} ! tjenare, @@ -284,19 +306,20 @@ ei_accept_tmo(Config) when is_list(Config) -> true = is_integer(X), P3 = runner:start(Config, ?accept_tmo), runner:send_term(P3,{c_nod_som_vi_kontaktar_2, - erlang:get_cookie()}), + erlang:get_cookie(), + get_group(Config)}), receive after 1000 -> ok end, CNode2 = make_node(c_nod_som_vi_kontaktar_2), {NA,NB} = split(CNode2), {_,Host} = split(node()), OurName = join(ccc,Host), - {port,PortNo,_} = erl_epmd:port_please(NA,NB), + {port,PortNo,?EI_DIST_HIGH} = erl_epmd:port_please(NA,NB), {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo, [{active,false}, {packet,2}]), - send_name(SocketA,OurName,5), + send_name(SocketA,OurName,OurVer,AssumedVer), ok = recv_status(SocketA), - {hidden,_Node,5,HisChallengeA} = recv_challenge(SocketA), % See 1) + {hidden,_Node,HisChallengeA} = recv_challenge(SocketA,OurVer), % See 1) _OurChallengeA = gen_challenge(), _OurDigestA = gen_digest(HisChallengeA, erlang:get_cookie()), %% Dont do the last two steps of the connection setup... @@ -342,6 +365,7 @@ make_and_check_dummy() -> -define(DFLAG_EXTENDED_PIDS_PORTS,16#100). -define(DFLAG_NEW_FLOATS,16#800). -define(DFLAG_DIST_MONITOR,8). +-define(DFLAG_HANDSHAKE_23,16#1000000). %% From R9 and forward extended references is compulsory %% From 14 and forward new float is compulsory @@ -405,31 +429,61 @@ recv_status(Socket) -> exit(Bad) end. -send_challenge(Socket, Node, Challenge, Version) -> - send_challenge(Socket, Node, Challenge, Version, ?COMPULSORY_DFLAGS). -send_challenge(Socket, Node, Challenge, Version, Flags) -> - {ok, {{_Ip1,_Ip2,_Ip3,_Ip4}, _}} = inet:sockname(Socket), - ?to_port(Socket, [$n,?int16(Version),?int32(Flags), - ?int32(Challenge), atom_to_list(Node)]). - -recv_challenge(Socket) -> +send_challenge(Socket, Node, Challenge, OurVer) -> + send_challenge(Socket, Node, Challenge, OurVer, ?COMPULSORY_DFLAGS). + +send_challenge(Socket, Node, Challenge, OurVer, Flags) -> + if OurVer =:= 5 -> + ?to_port(Socket, [$n, ?int16(OurVer), ?int32(Flags), + ?int32(Challenge), atom_to_list(Node)]); + OurVer >= 6 -> + NodeName = atom_to_binary(Node, latin1), + NameLen = byte_size(NodeName), + Creation = erts_internal:get_creation(), + ?to_port(Socket, [$N, + <<(Flags bor ?DFLAG_HANDSHAKE_23):64, + Challenge:32, + Creation:32, + NameLen:16>>, + NodeName]) + end. + +recv_challenge(Socket, OurVer) -> case gen_tcp:recv(Socket, 0) of {ok,[$n,V1,V0,Fl1,Fl2,Fl3,Fl4,CA3,CA2,CA1,CA0 | Ns]} -> + 5 = OurVer, Flags = ?u32(Fl1,Fl2,Fl3,Fl4), - Type = case Flags band ?DFLAG_PUBLISHED of - 0 -> - hidden; - _ -> - normal - end, + Type = flags_to_type(Flags), Node =list_to_atom(Ns), - Version = ?u16(V1,V0), + OurVer = ?u16(V1,V0), % echoed back + Challenge = ?u32(CA3,CA2,CA1,CA0), + {Type,Node,Challenge}; + + {ok,[$N, F7,F6,F5,F4,F3,F2,F1,F0, CA3,CA2,CA1,CA0, + _Cr3,_Cr2,_Cr1,_Cr0, NL1,NL0 | Rest]} -> + true = (OurVer >= 6), + <<Flags:64>> = <<F7,F6,F5,F4,F3,F2,F1,F0>>, + Type = flags_to_type(Flags), + NameLen = ?u16(NL1,NL0), + {NodeName,_} = lists:split(NameLen, Rest), + Node = list_to_atom(NodeName), Challenge = ?u32(CA3,CA2,CA1,CA0), - {Type,Node,Version,Challenge}; + %%Creation = ?u32(Cr3,Cr2,Cr1,Cr0), + %%true = (Creation =/= 0), + {Type,Node,Challenge}; + _ -> ?shutdown(no_node) end. +flags_to_type(Flags) -> + case Flags band ?DFLAG_PUBLISHED of + 0 -> + hidden; + _ -> + normal + end. + %send_challenge_reply(Socket, Challenge, Digest) -> % ?to_port(Socket, [$r,?int32(Challenge),Digest]). @@ -443,8 +497,8 @@ recv_challenge_reply(Socket, ChallengeA, Cookie) -> true -> ?shutdown(bad_challenge_reply) end; - _ -> - ?shutdown(no_node) + Other -> + ?shutdown({recv_challenge_reply,Other}) end. send_challenge_ack(Socket, Digest) -> @@ -463,37 +517,53 @@ send_challenge_ack(Socket, Digest) -> % ?shutdown(bad_challenge_ack) % end. -send_name(Socket, MyNode0, Version) -> - send_name(Socket, MyNode0, Version, ?COMPULSORY_DFLAGS). -send_name(Socket, MyNode0, Version, Flags) -> - MyNode = atom_to_list(MyNode0), - ?to_port(Socket, [$n,?int16(Version),?int32(Flags)] ++ - MyNode). +send_name(Socket, MyNode, OurVer, AssumedVer) -> + Flags = ?COMPULSORY_DFLAGS bor (case OurVer of + 5 -> 0; + 6 -> ?DFLAG_HANDSHAKE_23 + end), + send_name(Socket, MyNode, OurVer, AssumedVer, Flags). + +send_name(Socket, MyNode, OurVer, AssumedVer, Flags) -> + NodeName = atom_to_binary(MyNode, latin1), + if AssumedVer =:= 5 -> + ?to_port(Socket, [$n,?int16(OurVer),?int32(Flags),NodeName]); + AssumedVer >= 6 -> + Creation = erts_internal:get_creation(), + ?to_port(Socket, [$N, + <<Flags:64, + Creation:32, + (byte_size(NodeName)):16>>, + NodeName]) + end. -%% -%% recv_name is common for both old and new handshake. -%% -recv_name(Socket) -> +recv_name(Socket, OurEpmdVer) -> case gen_tcp:recv(Socket, 0) of - {ok,Data} -> - get_name(Data); + {ok,[$n, V1,V0, F3,F2,F1,F0 | OtherNode]} -> + 5 = OurEpmdVer, + 5 = ?u16(V1,V0), + Type = flags_to_type(?u32(F3,F2,F1,F0)), + {Type, list_to_atom(OtherNode)}; + {ok,[$N, F7,F6,F5,F4,F3,F2,F1,F0, _Cr3,_Cr2,_Cr1,_Cr0, NL1, NL0 | Rest]} -> + true = (OurEpmdVer >= 6), + {OtherNode, _Residue} = lists:split(?u16(NL1,NL0), Rest), + <<Flags:64>> = <<F7,F6,F5,F4,F3,F2,F1,F0>>, + Type = flags_to_type(Flags), + {Type, list_to_atom(OtherNode)}; Res -> ?shutdown({no_node,Res}) end. -get_name([$m,VersionA,VersionB,_Ip1,_Ip2,_Ip3,_Ip4|OtherNode]) -> - {normal, list_to_atom(OtherNode), ?u16(VersionA,VersionB)}; -get_name([$h,VersionA,VersionB,_Ip1,_Ip2,_Ip3,_Ip4|OtherNode]) -> - {hidden, list_to_atom(OtherNode), ?u16(VersionA,VersionB)}; -get_name([$n,VersionA, VersionB, Flag1, Flag2, Flag3, Flag4 | OtherNode]) -> - Type = case ?u32(Flag1, Flag2, Flag3, Flag4) band ?DFLAG_PUBLISHED of - 0 -> hidden; - _ -> normal - end, - {Type, list_to_atom(OtherNode), - ?u16(VersionA,VersionB)}; -get_name(Data) -> - ?shutdown(Data). +recv_complement(Socket, OurVer, 5) when OurVer > 5 -> + case gen_tcp:recv(Socket, 0) of + {ok,[$c, _F7,_F6,_F5,_F4, _Cr3,_Cr2,_Cr1,_Cr0]} -> + ok; + Res -> + ?shutdown({no_node,Res}) + end; +recv_complement(_, _OurVer, _OurEpmdVer) -> + ok. + %% %% tell_name is for old handshake @@ -538,13 +608,10 @@ wait_for_reg_reply(Socket, SoFar) -> receive {tcp, Socket, Data0} -> case SoFar ++ Data0 of - [$y, Result, A, B] -> - case Result of - 0 -> - {alive, Socket, ?u16(A, B)}; - _ -> - {error, duplicate_name} - end; + [$y, 0, Cr1,Cr0] -> + {alive, Socket, ?u16(Cr1,Cr0)}; + [$v, 0, Cr3,Cr2,Cr1,Cr0] -> + {alive, Socket, ?u32(Cr3,Cr2,Cr1,Cr0)}; Data when length(Data) < 4 -> wait_for_reg_reply(Socket, Data); Garbage -> @@ -558,9 +625,9 @@ wait_for_reg_reply(Socket, SoFar) -> end. -register(NodeName, ListenSocket, VLow, VHigh) -> +epmd_register(NodeName, ListenSocket, OurVer) -> {ok,{_,TcpPort}} = inet:sockname(ListenSocket), - case do_register_node(NodeName, TcpPort, VLow, VHigh) of + case do_register_node(NodeName, TcpPort, ?EI_DIST_LOW, OurVer) of {alive, Socket, _Creation} -> Socket; Other -> diff --git a/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src index b4ee361939..378e276524 100644 --- a/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src +++ b/lib/erl_interface/test/ei_tmo_SUITE_data/Makefile.src @@ -25,7 +25,8 @@ CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" LD = @LD@ LIBEI = @erl_interface_eilib@ LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ - $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + ../all_SUITE_data/my_ussi@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ @erl_interface_threadlib@ CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data EI_TMO_OBJS = ei_tmo_test@obj@ ei_tmo_test_decl@obj@ diff --git a/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c b/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c index 693e405f75..3c20e94c02 100644 --- a/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c +++ b/lib/erl_interface/test/ei_tmo_SUITE_data/ei_tmo_test.c @@ -21,9 +21,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#ifdef VXWORKS -#include "reclaim.h" -#endif #ifdef __WIN32__ #include <winsock2.h> @@ -35,6 +32,7 @@ #endif #include "ei_runner.h" +#include "my_ussi.h" #ifndef __WIN32__ #define closesocket(X) close(X) @@ -67,7 +65,7 @@ static void debugf_open(int number) { char filename[1024]; sprintf(filename,"ei_tmo_test%d.debug",number); -#if !defined(VXWORKS) && !defined(__WIN32__) +#if !defined(__WIN32__) close(2); #endif debugfile = fopen(filename,"a"); @@ -86,6 +84,7 @@ static void debugf_close(void) #define DEBUGF(X) /* noop */ #endif + TESTCASE(framework_check) { char *ptr = NULL; @@ -128,19 +127,26 @@ TESTCASE(framework_check) report(1); } -int decode_request(char **nodename_p, char **cookie_p, char **peername_p) +int decode_request(char **nodename_p, char **cookie_p, char **peername_p, + int *use_ussi_p) { char *nodename = NULL; char *cookie = NULL; char *peername = NULL; + char socket_impl[10]; char *ptr = NULL; ei_x_buff x; int len; int version; int type; int size; - int expected_size = (peername_p == NULL) ? 2 : 3; + int expected_size = 2; int ret = -1; + + if (peername_p) + ++expected_size; + if (use_ussi_p) + ++expected_size; ptr = read_packet(&len); ei_x_new(&x); @@ -180,7 +186,6 @@ int decode_request(char **nodename_p, char **cookie_p, char **peername_p) } nodename = malloc(size+1); ei_decode_atom(x.buff,&len,nodename); - nodename[size] = '\0'; /* needed????? */ if (ei_get_type(x.buff,&len,&type,&size) != 0) { DEBUGF(("Failure at line %d\n",__LINE__)); goto cleanup; @@ -191,8 +196,7 @@ int decode_request(char **nodename_p, char **cookie_p, char **peername_p) } cookie = malloc(size + 1); ei_decode_atom(x.buff,&len,cookie); - cookie[size] = '\0'; /* needed????? */ - if (expected_size > 2) { + if (peername_p) { if (ei_get_type(x.buff,&len,&type,&size) != 0) { DEBUGF(("Failure at line %d\n",__LINE__)); goto cleanup; @@ -212,6 +216,22 @@ int decode_request(char **nodename_p, char **cookie_p, char **peername_p) DEBUGF(("nodename = %s, cookie = %s\n", nodename, cookie)); } + + if (use_ussi_p) { + if (ei_decode_atom_as(x.buff,&len,socket_impl,sizeof(socket_impl), + ERLANG_ASCII, NULL, NULL)) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (strcmp(socket_impl,"default") == 0) + *use_ussi_p = 0; + else if (strcmp(socket_impl,"ussi") == 0) + *use_ussi_p = 1; + else { + DEBUGF(("Unkown socket_impl '%s' at %d\n",socket_impl,__LINE__)); + goto cleanup; + } + } *nodename_p = nodename; nodename = NULL; *cookie_p = cookie; @@ -339,6 +359,7 @@ TESTCASE(recv_tmo) char *nodename = NULL; char *cookie = NULL; char *peername = NULL; + int use_ussi; int com_sock = -1; ei_cnode nodeinfo; @@ -346,12 +367,22 @@ TESTCASE(recv_tmo) OPEN_DEBUGFILE(5); - if (decode_request(&nodename,&cookie,&peername) != 0) { + if (decode_request(&nodename,&cookie,&peername,&use_ussi) != 0) { goto cleanup; } - if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { - DEBUGF(("Failure at line %d\n",__LINE__)); - goto cleanup; + if (use_ussi) { + my_ussi_init(); + if (ei_connect_init_ussi(&nodeinfo, nodename, cookie, 0, + &my_ussi, sizeof(my_ussi), NULL) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + } + else { + if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } } if ((com_sock = ei_connect_tmo(&nodeinfo, peername, 5000)) < 0) { @@ -451,18 +482,29 @@ TESTCASE(send_tmo) char *cookie = NULL; char *peername = NULL; int com_sock = -1; + int use_ussi; ei_cnode nodeinfo; ei_init(); OPEN_DEBUGFILE(4); - if (decode_request(&nodename,&cookie,&peername) != 0) { + if (decode_request(&nodename,&cookie,&peername,&use_ussi) != 0) { goto cleanup; } - if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { - DEBUGF(("Failure at line %d\n",__LINE__)); - goto cleanup; + if (use_ussi) { + my_ussi_init(); + if (ei_connect_init_ussi(&nodeinfo, nodename, cookie, 0, + &my_ussi, sizeof(my_ussi), NULL) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + } + else { + if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } } if ((com_sock = ei_connect_tmo(&nodeinfo, peername, 5000)) < 0) { @@ -593,18 +635,29 @@ TESTCASE(connect_tmo) char *cookie = NULL; char *peername = NULL; int com_sock = -1; + int use_ussi; ei_cnode nodeinfo; ei_init(); OPEN_DEBUGFILE(3); - if (decode_request(&nodename,&cookie,&peername) != 0) { + if (decode_request(&nodename,&cookie,&peername,&use_ussi) != 0) { goto cleanup; } - if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { - DEBUGF(("Failure at line %d\n",__LINE__)); - goto cleanup; + if (use_ussi) { + my_ussi_init(); + if (ei_connect_init_ussi(&nodeinfo, nodename, cookie, 0, + &my_ussi, sizeof(my_ussi), NULL) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + } + else { + if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } } if ((com_sock = ei_connect_tmo(&nodeinfo, peername, 5000)) < 0) { @@ -679,10 +732,12 @@ TESTCASE(accept_tmo) int listen_sock = -1; int epmd_sock = -1; int com_sock = -1; + int use_ussi; struct sockaddr_in sin; int sin_siz = sizeof(sin); ErlConnect peer; ei_cnode nodeinfo; + int port_no; ei_init(); @@ -690,38 +745,55 @@ TESTCASE(accept_tmo) putenv("EI_TRACELEVEL=10"); - if (decode_request(&nodename,&cookie,NULL) != 0) { - goto cleanup; - } - if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { - DEBUGF(("Failure at line %d\n",__LINE__)); + if (decode_request(&nodename,&cookie,NULL,&use_ussi) != 0) { goto cleanup; } + if (use_ussi) { + my_ussi_init(); + if (ei_connect_init_ussi(&nodeinfo, nodename, cookie, 0, + &my_ussi, sizeof(my_ussi), NULL) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + port_no = 0; + listen_sock = ei_listen(&nodeinfo, &port_no, 5); + if (listen_sock == ERL_ERROR) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + } + else { + if (ei_connect_init(&nodeinfo, nodename, cookie, 0) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } - if ((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUGF(("Failure at line %d\n",__LINE__)); - goto cleanup; - } - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - - if (bind(listen_sock,(struct sockaddr *) &sin, sizeof(sin)) != 0) { - DEBUGF(("Failure at line %d\n",__LINE__)); - goto cleanup; - } - if (getsockname(listen_sock, - (struct sockaddr *) &sin, &sin_siz) != 0) { - DEBUGF(("Failure at line %d\n",__LINE__)); - goto cleanup; - } - if (listen(listen_sock, 5) != 0) { - DEBUGF(("Failure at line %d\n",__LINE__)); - goto cleanup; - } - - if ((epmd_sock = ei_publish(&nodeinfo, ntohs(sin.sin_port))) < 0) { - DEBUGF(("Failure at line %d[%d,%d]\n",__LINE__,sin.sin_port,erl_errno)); + if ((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + + if (bind(listen_sock,(struct sockaddr *) &sin, sizeof(sin)) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (getsockname(listen_sock, + (struct sockaddr *) &sin, &sin_siz) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + if (listen(listen_sock, 5) != 0) { + DEBUGF(("Failure at line %d\n",__LINE__)); + goto cleanup; + } + port_no = ntohs(sin.sin_port); + } + + if ((epmd_sock = ei_publish(&nodeinfo, port_no)) < 0) { + DEBUGF(("Failure at line %d[%d,%d]\n",__LINE__,port_no,erl_errno)); goto cleanup; } diff --git a/lib/erl_interface/test/erl_call_SUITE.erl b/lib/erl_interface/test/erl_call_SUITE.erl index 9e2b2e4251..0d95a1361b 100644 --- a/lib/erl_interface/test/erl_call_SUITE.erl +++ b/lib/erl_interface/test/erl_call_SUITE.erl @@ -23,42 +23,88 @@ -include_lib("common_test/include/ct.hrl"). --export([all/0, smoke/1]). +-export([all/0, smoke/1, test_connect_to_host_port/1]). -all() -> - [smoke]. +all() -> + [smoke, + test_connect_to_host_port]. smoke(Config) when is_list(Config) -> - ErlCall = find_erl_call(), - NameSwitch = case net_kernel:longnames() of - true -> - "-name"; - false -> - "-sname" - end, Name = atom_to_list(?MODULE) ++ "-" ++ integer_to_list(erlang:system_time(microsecond)), - ArgsList = ["-s", "-a", "erlang node", NameSwitch, Name], - io:format("erl_call: \"~ts\"\n~nargs list: ~p~n", [ErlCall, ArgsList]), - CmdRes = get_smoke_port_res(open_port({spawn_executable, ErlCall}, - [{args, ArgsList}, eof]), []), - io:format("CmdRes: ~p~n", [CmdRes]), + RetNodeName = start_node_and_get_node_name(Name), + + halt_node(Name), [_, Hostname] = string:lexemes(atom_to_list(node()), "@"), NodeName = list_to_atom(Name ++ "@" ++ Hostname), - io:format("NodeName: ~p~n~n", [NodeName]), + NodeName = list_to_atom(RetNodeName), + ok. - pong = net_adm:ping(NodeName), - rpc:cast(NodeName, erlang, halt, []), - NodeName = list_to_atom(string:trim(CmdRes, both, "'")), + +test_connect_to_host_port(Config) when is_list(Config) -> + Name = atom_to_list(?MODULE) + ++ "-" + ++ integer_to_list(erlang:system_time(microsecond)), + Port = start_node_and_get_port(Name), + AddressCaller = + fun(Address) -> + get_erl_call_result(["-address", + Address, + "-a", + "erlang length [[1,2,3,4,5,6,7,8,9]]"]) + end, + "9" = AddressCaller(erlang:integer_to_list(Port)), + "9" = AddressCaller(":" ++ erlang:integer_to_list(Port)), + [_, Hostname] = string:lexemes(atom_to_list(node()), "@"), + "9" = AddressCaller(Hostname ++ ":" ++ erlang:integer_to_list(Port)), + FailedRes = AddressCaller("80"), + case string:find(FailedRes, "80") of + nomatch -> ct:fail("Incorrect error message"); + _ -> ok + end, + halt_node(Name), ok. % % Utility functions... % + +halt_node(Name) -> + [_, Hostname] = string:lexemes(atom_to_list(node()), "@"), + NodeName = list_to_atom(Name ++ "@" ++ Hostname), + io:format("NodeName: ~p~n~n", [NodeName]), + + pong = net_adm:ping(NodeName), + rpc:cast(NodeName, erlang, halt, []). + +start_node_and_get_node_name(Name) -> + NameSwitch = case net_kernel:longnames() of + true -> + "-name"; + false -> + "-sname" + end, + string:trim(get_erl_call_result(["-s", + NameSwitch, + Name, "-a", + "erlang node"]), + both, + "'"). + +start_node_and_get_port(Name) -> + start_node_and_get_node_name(Name), + {ok, NamePortList} = net_adm:names(), + {value, {_, Port}} + = lists:search(fun({N, _}) -> + string:equal(N, Name) + end, + NamePortList), + Port. + find_erl_call() -> ErlCallName = case os:type() of {win32, _} -> "erl_call.exe"; @@ -86,10 +132,19 @@ find_erl_call() -> ErlCall end. -get_smoke_port_res(Port, Acc) when is_port(Port) -> + +get_erl_call_result(ArgsList) -> + ErlCall = find_erl_call(), + io:format("erl_call: \"~ts\"\n~nargs list: ~p~n", [ErlCall, ArgsList]), + CmdRes = get_port_res(open_port({spawn_executable, ErlCall}, + [{args, ArgsList}, eof, stderr_to_stdout]), []), + io:format("CmdRes: ~p~n", [CmdRes]), + CmdRes. + +get_port_res(Port, Acc) when is_port(Port) -> receive {Port, {data, Data}} -> - get_smoke_port_res(Port, [Acc|Data]); + get_port_res(Port, [Acc|Data]); {Port, eof} -> lists:flatten(Acc) end. diff --git a/lib/erl_interface/test/erl_connect_SUITE.erl b/lib/erl_interface/test/erl_connect_SUITE.erl deleted file mode 100644 index 782691b8fb..0000000000 --- a/lib/erl_interface/test/erl_connect_SUITE.erl +++ /dev/null @@ -1,131 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2000-2018. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(erl_connect_SUITE). - --include_lib("common_test/include/ct.hrl"). --include("erl_connect_SUITE_data/erl_connect_test_cases.hrl"). - --export([all/0, suite/0, - init_per_testcase/2, - erl_send/1, erl_reg_send/1, - erl_send_cookie_file/1]). - --import(runner, [get_term/1,send_term/2]). - -suite() -> - [{ct_hooks,[ts_install_cth]}, - {timetrap, {seconds, 30}}]. - -all() -> - [erl_send, erl_reg_send, erl_send_cookie_file]. - - -init_per_testcase(Case, Config) -> - runner:init_per_testcase(?MODULE, Case, Config). - -erl_send(Config) when is_list(Config) -> - P = runner:start(Config, ?interpret), - 1 = erl_connect_init(P, 42, erlang:get_cookie(), 0), - {ok,Fd} = erl_connect(P, node()), - - ok = erl_send(P, Fd, self(), AMsg={a,message}), - receive AMsg -> ok end, - - 0 = erl_close_connection(P,Fd), - runner:send_eot(P), - runner:recv_eot(P), - ok. - -erl_send_cookie_file(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skip,"Skipped on VxWorks"}; - _ -> - P = runner:start(Config, ?interpret), - 1 = erl_connect_init(P, 42, '', 0), - {ok,Fd} = erl_connect(P, node()), - - ok = erl_send(P, Fd, self(), AMsg={a,message}), - receive AMsg -> ok end, - - 0 = erl_close_connection(P,Fd), - runner:send_eot(P), - runner:recv_eot(P), - ok - end. - -erl_reg_send(Config) when is_list(Config) -> - P = runner:start(Config, ?interpret), - 1 = erl_connect_init(P, 42, erlang:get_cookie(), 0), - {ok,Fd} = erl_connect(P, node()), - - ARegName = a_strange_registred_name, - register(ARegName, self()), - ok = erl_reg_send(P, Fd, ARegName, AMsg={another,[strange],message}), - receive AMsg -> ok end, - - 0 = erl_close_connection(P,Fd), - runner:send_eot(P), - runner:recv_eot(P), - ok. - - -%%% Interface functions for erl_interface functions. - -erl_connect_init(P, Num, Cookie, Creation) -> - send_command(P, erl_connect_init, [Num,Cookie,Creation]), - case get_term(P) of - {term,Int} when is_integer(Int) -> Int - end. - -erl_connect(P, Node) -> - send_command(P, erl_connect, [Node]), - 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_send(P, Fd, To, Msg) -> - send_command(P, erl_send, [Fd,To,Msg]), - get_send_result(P). - -erl_reg_send(P, Fd, To, Msg) -> - send_command(P, erl_reg_send, [Fd,To,Msg]), - get_send_result(P). - -get_send_result(P) -> - case get_term(P) of - {term,{1,_}} -> ok; - {term,{-1,Errno}} -> {error,Errno}; - {term,{Res,Errno}}-> - io:format("Return value: ~p\nerl_errno: ~p", [Res,Errno]), - ct: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_connect_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.first deleted file mode 100644 index 21a7aac0b0..0000000000 --- a/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.first +++ /dev/null @@ -1,22 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2001-2016. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -erl_connect_test_decl.c: erl_connect_test.c - erl -noinput -pa ../all_SUITE_data -s init_tc run erl_connect_test -s erlang halt diff --git a/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src deleted file mode 100644 index ff4c382c97..0000000000 --- a/lib/erl_interface/test/erl_connect_SUITE_data/Makefile.src +++ /dev/null @@ -1,41 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2000-2016. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -include @erl_interface_mk_include@ - -CC0 = @CC@ -CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" -LD = @LD@ -LIBERL = @erl_interface_lib@ -LIBEI = @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_connect_test@obj@ erl_connect_test_decl@obj@ - -all: erl_connect_test@exe@ - -erl_connect_test@exe@: $(OBJS) $(LIBERL) $(LIBEI) - $(LD) @CROSSLDFLAGS@ -o $@ $(OBJS) $(LIBFLAGS) - -clean: - $(RM) $(OBJS) - $(RM) erl_connect_test@exe@ diff --git a/lib/erl_interface/test/erl_connect_SUITE_data/erl_connect_test.c b/lib/erl_interface/test/erl_connect_SUITE_data/erl_connect_test.c deleted file mode 100644 index 0adaa79a33..0000000000 --- a/lib/erl_interface/test/erl_connect_SUITE_data/erl_connect_test.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/* - * Purpose: Tests the functions in erl_connect.c. - * Author: Bjorn Gustavsson - * - * See the erl_connect_SUITE.erl file for a "table of contents". - */ - -#include <stdio.h> -#include <string.h> - -#include "runner.h" - -static void cmd_erl_connect_init(ETERM* args); -static void cmd_erl_connect(ETERM* args); -static void cmd_erl_send(ETERM* args); -static void cmd_erl_reg_send(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_init", 3, cmd_erl_connect_init, - "erl_connect", 1, cmd_erl_connect, - "erl_close_connection", 1, cmd_erl_close_connection, - "erl_send", 3, cmd_erl_send, - "erl_reg_send", 3, cmd_erl_reg_send, -}; - - -/* - * 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_init(ETERM* args) -{ - ETERM* number; - ETERM* res; - ETERM* cookie; - char cookie_buffer[256]; - - number = ERL_TUPLE_ELEMENT(args, 0); - VERIFY_TYPE(ERL_IS_INTEGER, number); - cookie = ERL_TUPLE_ELEMENT(args, 1); - VERIFY_TYPE(ERL_IS_ATOM, cookie); - if (ERL_ATOM_SIZE(cookie) == 0) { - res = erl_mk_int(erl_connect_init(ERL_INT_VALUE(number), 0, 0)); - } else { - memcpy(cookie_buffer, ERL_ATOM_PTR(cookie), ERL_ATOM_SIZE(cookie)); - cookie_buffer[ERL_ATOM_SIZE(cookie)] = '\0'; - res = erl_mk_int(erl_connect_init(ERL_INT_VALUE(number), - cookie_buffer, 0)); - } - send_term(res); - erl_free_term(res); -} - -static void -cmd_erl_connect(ETERM* args) -{ - ETERM* node; - char node_buffer[256]; - - node = ERL_TUPLE_ELEMENT(args, 0); - VERIFY_TYPE(ERL_IS_ATOM, node); - memcpy(node_buffer, ERL_ATOM_PTR(node), ERL_ATOM_SIZE(node)); - node_buffer[ERL_ATOM_SIZE(node)] = '\0'; - send_errno_result(erl_connect(node_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_send(ETERM* args) -{ - ETERM* fd_term = ERL_TUPLE_ELEMENT(args, 0); - ETERM* to = ERL_TUPLE_ELEMENT(args, 1); - ETERM* msg = ERL_TUPLE_ELEMENT(args, 2); - - VERIFY_TYPE(ERL_IS_INTEGER, fd_term); - send_errno_result(erl_send(ERL_INT_VALUE(fd_term), to, msg)); -} - -static void -cmd_erl_reg_send(ETERM* args) -{ - ETERM* fd_term = ERL_TUPLE_ELEMENT(args, 0); - ETERM* to = ERL_TUPLE_ELEMENT(args, 1); - ETERM* msg = ERL_TUPLE_ELEMENT(args, 2); - char reg_name[256]; - - VERIFY_TYPE(ERL_IS_INTEGER, fd_term); - VERIFY_TYPE(ERL_IS_ATOM, to); - memcpy(reg_name, ERL_ATOM_PTR(to), ERL_ATOM_SIZE(to)); - reg_name[ERL_ATOM_SIZE(to)] = '\0'; - send_errno_result(erl_reg_send(ERL_INT_VALUE(fd_term), reg_name, msg)); -} - -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/erl_eterm_SUITE.erl b/lib/erl_interface/test/erl_eterm_SUITE.erl deleted file mode 100644 index 77910a9fc7..0000000000 --- a/lib/erl_interface/test/erl_eterm_SUITE.erl +++ /dev/null @@ -1,1084 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2018. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(erl_eterm_SUITE). - --include_lib("common_test/include/ct.hrl"). --include("erl_eterm_SUITE_data/eterm_test_cases.hrl"). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% The tests are organised as follows: -%%% -%%% 1. Basic tests (encoding, decoding, memory allocation). -%%% 2. Constructing terms (the erl_mk_xxx() functions and erl_copy_term()). -%%% 3. Extracting & info functions (erl_hd(), erl_length() etc). -%%% 4. I/O list functions. -%%% 5. Miscellaneous functions. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - --export([all/0, suite/0, - init_per_testcase/2, - build_terms/1, round_trip_conversion/1, - decode_terms/1, decode_float/1, - t_erl_mk_int/1, t_erl_mk_list/1, - basic_copy/1, - t_erl_cons/1, - t_erl_mk_atom/1, - t_erl_mk_binary/1, - t_erl_mk_empty_list/1, - t_erl_mk_float/1, - t_erl_mk_pid/1, - t_erl_mk_xpid/1, - t_erl_mk_port/1, - t_erl_mk_xport/1, - t_erl_mk_ref/1, - t_erl_mk_long_ref/1, - t_erl_mk_string/1, - t_erl_mk_estring/1, - t_erl_mk_tuple/1, - t_erl_mk_uint/1, - t_erl_mk_var/1, - t_erl_size/1, - t_erl_var_content/1, - t_erl_element/1, - t_erl_length/1, t_erl_hd/1, t_erl_tl/1, - type_checks/1, extractor_macros/1, - t_erl_iolist_length/1, t_erl_iolist_to_binary/1, - t_erl_iolist_to_string/1, - erl_print_term/1, print_string/1, - t_erl_free_compound/1, - high_chaparal/1, - broken_data/1, - cnode_1/1]). - --export([start_cnode/1]). - --import(runner, [get_term/1]). - -%% This test suite controls the running of the C language functions -%% in eterm_test.c and print_term.c. - -suite() -> - [{ct_hooks,[ts_install_cth]}]. - -all() -> - [build_terms, round_trip_conversion, decode_terms, - decode_float, t_erl_mk_int, t_erl_mk_list, basic_copy, - t_erl_mk_atom, t_erl_mk_binary, t_erl_mk_empty_list, - t_erl_mk_float, t_erl_mk_pid, t_erl_mk_xpid, - t_erl_mk_port, t_erl_mk_xport, t_erl_mk_ref, - t_erl_mk_long_ref, t_erl_mk_string, t_erl_mk_estring, - t_erl_mk_tuple, t_erl_mk_uint, t_erl_mk_var, t_erl_size, - t_erl_var_content, t_erl_element, t_erl_cons, - t_erl_length, t_erl_hd, t_erl_tl, type_checks, - extractor_macros, t_erl_iolist_length, - t_erl_iolist_to_binary, t_erl_iolist_to_string, - erl_print_term, print_string, t_erl_free_compound, - high_chaparal, broken_data, cnode_1]. - - -init_per_testcase(Case, Config) -> - runner:init_per_testcase(?MODULE, Case, Config). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% -%%% 1. B a s i c t e s t s -%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% This test asks the C function to construct all data types in -%% a list and verifies that the result is as expected. - -build_terms(Config) when is_list(Config) -> - P = runner:start(Config, ?build_terms), - {term, Term} = get_term(P), - io:format("Received: ~p", [Term]), - [ARefLN, ARef, APortLN, APort, APidLN, APid, - {element1, 42, 767}, "A string", - 1, -1, 0, 3.0, ABin, 'I am an atom'] = Term, - "A binary" = binary_to_list(ABin), - case ARef of - R when is_reference(R), node(R) == kalle@localhost -> ok - end, - case ARefLN of - R1 when is_reference(R1), node(R1) == abcdefghijabcdefghij@localhost -> ok - end, - case APort of - Port when is_port(Port), node(Port) == kalle@localhost -> ok - end, - case APortLN of - Port1 when is_port(Port1), node(Port1) == abcdefghijabcdefghij@localhost -> ok - end, - case APid of - Pid when is_pid(Pid), node(Pid) == kalle@localhost -> ok - end, - case APidLN of - Pid1 when is_pid(Pid1), node(Pid1) == abcdefghijabcdefghij@localhost -> ok - end, - - runner:recv_eot(P), - ok. - -%% This test is run entirely in C code. - -round_trip_conversion(Config) when is_list(Config) -> - runner:test(Config, ?round_trip_conversion), - ok. - -%% This test sends a list of all data types to the C code function, -%% which decodes it and verifies it. - -decode_terms(Config) when is_list(Config) -> - Dummy1 = list_to_atom(filename:join(proplists:get_value(priv_dir, Config), - dummy_file1)), - Dummy2 = list_to_atom(filename:join(proplists:get_value(priv_dir, Config), - dummy_file2)), - Port1 = open_port(Dummy1, [out]), - Port2 = open_port(Dummy2, [out]), - ABinary = list_to_binary("A binary"), - Terms = [make_ref(), make_ref(), - Port1, Port2, - self(), self(), - {element1, 42, 767}, "A string", - 1, -1, 0, 3.0, ABinary, 'I am an atom'], - - P = runner:start(Config, ?decode_terms), - runner:send_term(P, Terms), - runner:recv_eot(P), - - ok. - -%% Decodes the floating point number 3.1415. - -decode_float(Config) when is_list(Config) -> - P = runner:start(Config, ?decode_float), - runner:send_term(P, 3.1415), - runner:recv_eot(P), - ok. - -%% Tests the erl_free_compound() function. - -t_erl_free_compound(Config) when is_list(Config) -> - runner:test(Config, ?t_erl_free_compound), - ok. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% -%%% 2. C o n s t r u c t i n g t e r m s -%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% This tests the erl_mk_list() function. - -t_erl_mk_list(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_list), - - {term, []} = get_term(P), - {term, [abc]} = get_term(P), - {term, [abcdef, 42]} = get_term(P), - {term, [0.0, 23, [], 3.1415]} = get_term(P), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_int() function. - -t_erl_mk_int(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_int), - - {term, 0} = get_term(P), - {term, 127} = get_term(P), - {term, 128} = get_term(P), - {term, 255} = get_term(P), - {term, 256} = get_term(P), - - {term, 16#FFFF} = get_term(P), - {term, 16#10000} = get_term(P), - - {term, 16#07FFFFFF} = get_term(P), - {term, 16#0FFFFFFF} = get_term(P), - {term, 16#1FFFFFFF} = get_term(P), - {term, 16#3FFFFFFF} = get_term(P), - {term, 16#7FFFFFFF} = get_term(P), - - {term, 16#08000000} = get_term(P), - {term, 16#10000000} = get_term(P), - {term, 16#20000000} = get_term(P), - {term, 16#40000000} = get_term(P), - - - {term, -16#07FFFFFF} = get_term(P), - {term, -16#0FFFFFFF} = get_term(P), - {term, -16#1FFFFFFF} = get_term(P), - {term, -16#3FFFFFFF} = get_term(P), - {term, -16#7FFFFFFF} = get_term(P), - - {term, -16#08000000} = get_term(P), - {term, -16#10000000} = get_term(P), - {term, -16#20000000} = get_term(P), - {term, -16#40000000} = get_term(P), - - {term, -16#08000001} = get_term(P), - {term, -16#10000001} = get_term(P), - {term, -16#20000001} = get_term(P), - {term, -16#40000001} = get_term(P), - - {term, -16#08000002} = get_term(P), - {term, -16#10000002} = get_term(P), - {term, -16#20000002} = get_term(P), - {term, -16#40000002} = get_term(P), - - {term, -1999999999} = get_term(P), - {term, -2000000000} = get_term(P), - {term, -2000000001} = get_term(P), - - runner:recv_eot(P), - ok. - - -%% Basic test of erl_copy_term(). - -basic_copy(Config) when is_list(Config) -> - runner:test(Config, ?basic_copy), - ok. - - -%% This tests the erl_mk_tuple() function. - -t_erl_mk_tuple(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_tuple), - - {term, {madonna, 21, 'mad donna', 12}} = get_term(P), - {term, {'Madonna',21,{children,{"Isabella",2}}, - {'home page',"http://www.madonna.com/"}}} = get_term(P), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_atom() function. - -t_erl_mk_atom(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_atom), - - {term, madonna} = (get_term(P)), - {term, 'Madonna'} = (get_term(P)), - {term, 'mad donna'} = (get_term(P)), - {term, '_madonna_'} = (get_term(P)), - {term, '/home/madonna/tour_plan'} = (get_term(P)), - {term, 'http://www.madonna.com/tour_plan'} = (get_term(P)), - {term, '\'madonna\''} = (get_term(P)), - {term, '\"madonna\"'} = (get_term(P)), - {term, '\\madonna\\'} = (get_term(P)), - {term, '{madonna,21,\'mad donna\',12}'} = (get_term(P)), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_binary() function. - -t_erl_mk_binary(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_binary), - - {term, Bin} = (get_term(P)), - "{madonna,21,'mad donna',1234.567.890, !#$%&/()=?+-@, \" \\}" = binary_to_list(Bin), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_empty_list() function. - -t_erl_mk_empty_list(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_empty_list), - - {term, []} = get_term(P), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_float() function. - -t_erl_mk_float(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skipped, "Floating point numbers never compare equal on PPC"}; - _ -> - P = runner:start(Config, ?t_erl_mk_float), - {term, {3.1415, 1.999999, 2.000000, 2.000001, - 2.000002, 12345.67890}} = get_term(P), - runner:recv_eot(P), - ok - end. - - -%% This tests the erl_mk_pid() function. - -t_erl_mk_pid(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_pid), - - {term, A_pid} = (get_term(P)), - {pid, kalle@localhost, 3, 2} = nc2vinfo(A_pid), - - runner:recv_eot(P), - ok. - -t_erl_mk_xpid(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_xpid), - - {term, A_pid} = (get_term(P)), - {pid, kalle@localhost, 32767, 8191} = nc2vinfo(A_pid), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_port() function. - -t_erl_mk_port(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_port), - - {term, A_port} = (get_term(P)), - {port, kalle@localhost, 4} = nc2vinfo(A_port), - - runner:recv_eot(P), - ok. - -t_erl_mk_xport(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_xport), - - {term, A_port} = (get_term(P)), - {port, kalle@localhost, 268435455} = nc2vinfo(A_port), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_ref() function. - -t_erl_mk_ref(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_ref), - - {term, A_ref} = (get_term(P)), - {ref, kalle@localhost, _Length, [6]} = nc2vinfo(A_ref), - - runner:recv_eot(P), - ok. - -t_erl_mk_long_ref(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_long_ref), - - {term, A_ref} = (get_term(P)), - {ref, kalle@localhost, _Length, [4294967295,4294967295,262143]} - = nc2vinfo(A_ref), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_string() function. - -t_erl_mk_string(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_string), - - {term, "madonna"} = (get_term(P)), - {term, "Madonna"} = (get_term(P)), - {term, "mad donna"} = (get_term(P)), - {term, "_madonna_"} = (get_term(P)), - {term, "/home/madonna/tour_plan"} = (get_term(P)), - {term, "http://www.madonna.com/tour_plan"} = (get_term(P)), - {term, "\'madonna\'"} = (get_term(P)), - {term, "\"madonna\""} = (get_term(P)), - {term, "\\madonna\\"} = (get_term(P)), - {term, "{madonna,21,'mad donna',12}"} = (get_term(P)), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_estring() function. - -t_erl_mk_estring(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_estring), - - {term, "madonna"} = (get_term(P)), - {term, "Madonna"} = (get_term(P)), - {term, "mad donna"} = (get_term(P)), - {term, "_madonna_"} = (get_term(P)), - {term, "/home/madonna/tour_plan"} = (get_term(P)), - {term, "http://www.madonna.com/tour_plan"} = (get_term(P)), - {term, "\'madonna\'"} = (get_term(P)), - {term, "\"madonna\""} = (get_term(P)), - {term, "\\madonna\\"} = (get_term(P)), - {term, "{madonna,21,'mad donna',12}"} = (get_term(P)), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_uint() function. - -t_erl_mk_uint(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_uint), - - {term, 54321} = (get_term(P)), - {term, 2147483647} = (get_term(P)), - {term, 2147483648} = (get_term(P)), - {term, 2147483649} = (get_term(P)), - {term, 2147483650} = (get_term(P)), - {term, 4294967295} = (get_term(P)), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_mk_var() function. - -t_erl_mk_var(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_mk_var), - - {term, 1} = (get_term(P)), - {term, 0} = (get_term(P)), - {term, 1} = (get_term(P)), - {term, 0} = (get_term(P)), - {term, 1} = (get_term(P)), - {term, 0} = (get_term(P)), - {term, 1} = (get_term(P)), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_cons() function. - -t_erl_cons(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_cons), - - {term, [madonna, 21]} = get_term(P), - - runner:recv_eot(P), - ok. - - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% -%%% 3. E x t r a c t i n g & i n f o f u n c t i o n s -%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Tests the erl_length() function. - -t_erl_length(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_length), - - 0 = erl_length(P, []), - 1 = erl_length(P, [a]), - 2 = erl_length(P, [a, b]), - 3 = erl_length(P, [a, b, c]), - - 4 = erl_length(P, [a, [x, y], c, []]), - - -1 = erl_length(P, [a|b]), - -1 = erl_length(P, a), - - runner:finish(P), - ok. - -%% Invokes the erl_length() function. - -erl_length(Port, List) -> - call_erl_function(Port, List). - -%% Tests the erl_hd() function. - -t_erl_hd(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_hd), - - 'NULL' = erl_hd(P, 42), - 'NULL' = erl_hd(P, abc), - 'NULL' = erl_hd(P, []), - - [] = erl_hd(P, [[], a]), - a = erl_hd(P, [a]), - a = erl_hd(P, [a, b]), - a = erl_hd(P, [a, b, c]), - a = erl_hd(P, [a|b]), - - runner:send_eot(P), - runner:recv_eot(P), - ok. - -%% Invokes the erl_hd() function. - -erl_hd(Port, List) -> - call_erl_function(Port, List). - -%% Tests the erl_tail() function. - -t_erl_tl(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_tl), - - 'NULL' = erl_tl(P, 42), - 'NULL' = erl_tl(P, abc), - 'NULL' = erl_tl(P, []), - - [] = erl_tl(P, [a]), - [b] = erl_tl(P, [a, b]), - [b, c] = erl_tl(P, [a, b, c]), - - b = erl_tl(P, [a|b]), - - runner:send_eot(P), - runner:recv_eot(P), - ok. - -%% Invokes the erl_tail() function in erl_interface. - -erl_tl(Port, List) -> - call_erl_function(Port, List). - -%% Tests the type checking macros (done in the C program). - -type_checks(Config) when is_list(Config) -> - runner:test(Config, ?type_checks), - ok. - -%% Tests the extractor macros (done in the C program). - -extractor_macros(Config) when is_list(Config) -> - runner:test(Config, ?extractor_macros), - ok. - - -%% This tests the erl_size() function. - -t_erl_size(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_size), - - {term, 0} = (get_term(P)), - {term, 4} = (get_term(P)), - - {term, 0} = (get_term(P)), - {term, 27} = (get_term(P)), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_var_content() function. - -t_erl_var_content(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_var_content), - - {term, 17} = (get_term(P)), - {term, "http://www.madonna.com"} = (get_term(P)), - {term, 2} = (get_term(P)), - {term, "http://www.madonna.com"} = (get_term(P)), - {term, 2} = (get_term(P)), - - runner:recv_eot(P), - ok. - - -%% This tests the erl_element() function. - -t_erl_element(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_element), - - {term, madonna} = get_term(P), - {term, 21} = get_term(P), - {term, 'mad donna'} = get_term(P), - {term, 12} = get_term(P), - - {term, 'Madonna'} = get_term(P), - {term, 21} = get_term(P), - {term, {children,{"Isabella",2}}} = get_term(P), - {term, {'home page',"http://www.madonna.com/"}} = get_term(P), - - runner:recv_eot(P), - ok. - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% -%%% 4. I / O l i s t f u n c t i o n s -%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Tests the erl_iolist_length() function. - -t_erl_iolist_length(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_iolist_length), - - %% Flat lists. - - 0 = erl_iolist_length(P, []), - 1 = erl_iolist_length(P, [10]), - 2 = erl_iolist_length(P, [10, 20]), - 3 = erl_iolist_length(P, [10, 20, 30]), - 256 = erl_iolist_length(P, lists:seq(0, 255)), - - %% Deep lists. - - 0 = erl_iolist_length(P, [[]]), - 1 = erl_iolist_length(P, [[], 42]), - 1 = erl_iolist_length(P, [42, []]), - 2 = erl_iolist_length(P, [42, [], 45]), - - 3 = erl_iolist_length(P, [42, [90], 45]), - 3 = erl_iolist_length(P, [[42, [90]], 45]), - 3 = erl_iolist_length(P, [[42, [90]], 45]), - - %% List with binaries. - - 0 = erl_iolist_length(P, [list_to_binary([])]), - 0 = erl_iolist_length(P, [[], list_to_binary([])]), - 1 = erl_iolist_length(P, [[1], list_to_binary([])]), - 1 = erl_iolist_length(P, [[], list_to_binary([2])]), - 2 = erl_iolist_length(P, [[42], list_to_binary([2])]), - 4 = erl_iolist_length(P, [[42], list_to_binary([2, 3, 4])]), - - %% Binaries as tail. - - 0 = erl_iolist_length(P, [[]| list_to_binary([])]), - 1 = erl_iolist_length(P, [[1]| list_to_binary([])]), - 1 = erl_iolist_length(P, [[]| list_to_binary([2])]), - 2 = erl_iolist_length(P, [[42]| list_to_binary([2])]), - - %% Binaries only. - - 0 = erl_iolist_length(P, list_to_binary("")), - 1 = erl_iolist_length(P, list_to_binary([1])), - 2 = erl_iolist_length(P, list_to_binary([1, 2])), - - %% Illegal cases. - - -1 = erl_iolist_length(P, [42|43]), - -1 = erl_iolist_length(P, a), - - -1 = erl_iolist_length(P, [a]), - -1 = erl_iolist_length(P, [256]), - -1 = erl_iolist_length(P, [257]), - -1 = erl_iolist_length(P, [-1]), - -1 = erl_iolist_length(P, [-2]), - -1 = erl_iolist_length(P, [-127]), - -1 = erl_iolist_length(P, [-128]), - - runner:finish(P), - ok. - -%% Invokes the erl_iolist_length() function. - -erl_iolist_length(Port, List) -> - call_erl_function(Port, List). - -%% Tests the erl_iolist_to_binary() function. - -t_erl_iolist_to_binary(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_iolist_to_binary), - - %% Flat lists. - - [] = iolist_to_list(P, []), - [10] = iolist_to_list(P, [10]), - [10, 20] = iolist_to_list(P, [10, 20]), - [10, 20, 30] = iolist_to_list(P, [10, 20, 30]), - AllBytes = lists:seq(0, 255), - AllBytes = iolist_to_list(P, AllBytes), - - %% Deep lists. - - [] = iolist_to_list(P, [[]]), - [42] = iolist_to_list(P, [[], 42]), - [42] = iolist_to_list(P, [42, []]), - [42, 45] = iolist_to_list(P, [42, [], 45]), - - [42, 90, 45] = iolist_to_list(P, [42, [90], 45]), - [42, 90, 45] = iolist_to_list(P, [[42, [90]], 45]), - [42, 90, 45] = iolist_to_list(P, [[42, [90]], 45]), - - %% List with binaries. - - [] = iolist_to_list(P, [list_to_binary([])]), - [] = iolist_to_list(P, [[], list_to_binary([])]), - [1] = iolist_to_list(P, [[1], list_to_binary([])]), - [2] = iolist_to_list(P, [[], list_to_binary([2])]), - [42, 2] = iolist_to_list(P, [[42], list_to_binary([2])]), - [42, 2, 3, 4] = iolist_to_list(P, [[42], list_to_binary([2, 3, 4])]), - - %% Binaries as tail. - - [] = iolist_to_list(P, [[]| list_to_binary([])]), - [1] = iolist_to_list(P, [[1]| list_to_binary([])]), - [2] = iolist_to_list(P, [[]| list_to_binary([2])]), - [42, 2] = iolist_to_list(P, [[42]| list_to_binary([2])]), - - %% Binaries only. - - [] = iolist_to_list(P, list_to_binary("")), - [1] = iolist_to_list(P, list_to_binary([1])), - [1, 2] = iolist_to_list(P, list_to_binary([1, 2])), - - %% Illegal cases. - - 'NULL' = iolist_to_list(P, [42|43]), - 'NULL' = iolist_to_list(P, a), - - 'NULL' = iolist_to_list(P, [a]), - 'NULL' = iolist_to_list(P, [256]), - 'NULL' = iolist_to_list(P, [257]), - 'NULL' = iolist_to_list(P, [-1]), - 'NULL' = iolist_to_list(P, [-2]), - 'NULL' = iolist_to_list(P, [-127]), - 'NULL' = iolist_to_list(P, [-128]), - - runner:finish(P), - ok. - -iolist_to_list(Port, Term) -> - case call_erl_function(Port, Term) of - 'NULL' -> - 'NULL'; - Bin when is_binary(Bin) -> - binary_to_list(Bin) - end. - -%% Tests the erl_iolist_to_string() function. - -t_erl_iolist_to_string(Config) when is_list(Config) -> - P = runner:start(Config, ?t_erl_iolist_to_string), - - %% Flat lists. - - [0] = iolist_to_string(P, []), - [10, 0] = iolist_to_string(P, [10]), - [10, 20, 0] = iolist_to_string(P, [10, 20]), - [10, 20, 30, 0] = iolist_to_string(P, [10, 20, 30]), - AllBytes = lists:seq(1, 255)++[0], - AllBytes = iolist_to_string(P, lists:seq(1, 255)), - - %% Deep lists. - - [0] = iolist_to_string(P, [[]]), - [42, 0] = iolist_to_string(P, [[], 42]), - [42, 0] = iolist_to_string(P, [42, []]), - [42, 45, 0] = iolist_to_string(P, [42, [], 45]), - - [42, 90, 45, 0] = iolist_to_string(P, [42, [90], 45]), - [42, 90, 45, 0] = iolist_to_string(P, [[42, [90]], 45]), - [42, 90, 45, 0] = iolist_to_string(P, [[42, [90]], 45]), - - %% List with binaries. - - [0] = iolist_to_string(P, [list_to_binary([])]), - [0] = iolist_to_string(P, [[], list_to_binary([])]), - [1, 0] = iolist_to_string(P, [[1], list_to_binary([])]), - [2, 0] = iolist_to_string(P, [[], list_to_binary([2])]), - [42, 2, 0] = iolist_to_string(P, [[42], list_to_binary([2])]), - [42, 2, 3, 4, 0] = iolist_to_string(P, [[42], - list_to_binary([2, 3, 4])]), - - %% Binaries as tail. - - [0] = iolist_to_string(P, [[]| list_to_binary([])]), - [1, 0] = iolist_to_string(P, [[1]| list_to_binary([])]), - [2, 0] = iolist_to_string(P, [[]| list_to_binary([2])]), - [42, 2, 0] = iolist_to_string(P, [[42]| list_to_binary([2])]), - - %% Binaries only. - - [0] = iolist_to_string(P, list_to_binary("")), - [1, 0] = iolist_to_string(P, list_to_binary([1])), - [1, 2, 0] = iolist_to_string(P, list_to_binary([1, 2])), - - %% Illegal cases. - - 'NULL' = iolist_to_string(P, [0]), - 'NULL' = iolist_to_string(P, [65, 0, 66]), - 'NULL' = iolist_to_string(P, [65, 66, 67, 0]), - - 'NULL' = iolist_to_string(P, [42|43]), - 'NULL' = iolist_to_string(P, a), - - 'NULL' = iolist_to_string(P, [a]), - 'NULL' = iolist_to_string(P, [256]), - 'NULL' = iolist_to_string(P, [257]), - 'NULL' = iolist_to_string(P, [-1]), - 'NULL' = iolist_to_string(P, [-2]), - 'NULL' = iolist_to_string(P, [-127]), - 'NULL' = iolist_to_string(P, [-128]), - - runner:finish(P), - ok. - -%% Invokes the erl_iolist_to_string() function. - -iolist_to_string(Port, Term) -> - runner:send_term(Port, Term), - case get_term(Port) of - {bytes, Result} -> Result; - 'NULL' -> 'NULL' - end. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% -%%% 5. M i s c e l l a n o u s T e s t s -%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% Tests the erl_print_term() function -erl_print_term(Config) when is_list(Config) -> - PrintTerm = print_term(Config), - P = open_port({spawn, PrintTerm}, [stream]), - - %% Lists. - - print(P, "[]", []), - print(P, "[a]", [a]), - print(P, "[[a]]", [[a]]), - print(P, "[[]]", [[]]), - print(P, "[a,b,c]", [a,b,c]), - print(P, "[a,b|c]", [a,b|c]), - print(P, "[a,[],c]", [a,[],c]), - print(P, "[a,[1000,1],c]", [a,[1000,1],c]), - - %% Tuples. - - print(P, "{}", {}), - print(P, "{ok}", {ok}), - print(P, "{1,2,3}", {1, 2, 3}), - - %% Pids. - - {_X, Y, Z} = split_pid(self()), - PidString = lists:flatten(io_lib:format("<~s.~w.~w>", - [node(), Y, Z])), - print(P, PidString, self()), - - unlink(P), - exit(P, die), - ok. - -split_pid(Pid) when is_pid(Pid) -> - split_pid(pid_to_list(Pid), 0, []). - -split_pid([$<|Rest], Cur, Result) -> - split_pid(Rest, Cur, Result); -split_pid([Digit|Rest], Cur, Result) when $0 =< Digit, Digit =< $9 -> - split_pid(Rest, 10*Cur+Digit-$0, Result); -split_pid([$.|Rest], Cur, Result) -> - split_pid(Rest, 0, Result++[Cur]); -split_pid([$>], Cur, Result) -> - list_to_tuple(Result++[Cur]). - -%% Test printing a string with erl_print_term() -print_string(Config) when is_list(Config) -> - PrintTerm = print_term(Config), - P = open_port({spawn, PrintTerm}, [stream]), - - %% Strings. - - print(P, "\"ABC\"", "ABC"), - {11, "\"\\tABC\\r\\n\""} = print(P, "\tABC\r\n"), - - %% Not strings. - - print(P, "[65,66,67,0]", "ABC\000"), - - unlink(P), - exit(P, die), - ok. - -print(Port, TermString, Term) -> - Length = length(TermString), - {Length, TermString} = print(Port, Term). - -%% This function uses the erl_print_term() function in erl_interface -%% to print a term. -%% Returns: {NumChars, Chars} - -print(Port, Term) -> - Bin = term_to_binary(Term), - Size = size(Bin), - Port ! {self(), {command, [Size div 256, Size rem 256, Bin]}}, - collect_line(Port, []). - -collect_line(Port, Result) -> - receive - {Port, {data, Data}} -> - case lists:reverse(Data) of - [$\n|Rest] -> - collect_line1(Rest++Result, []); - Chars -> - collect_line(Port, Chars++Result) - end - after 5000 -> - ct:fail("No response from C program") - end. - -collect_line1([$\r|Rest], Result) -> - {list_to_integer(Result), lists:reverse(Rest)}; -collect_line1([C|Rest], Result) -> - collect_line1(Rest, [C|Result]). - -%% Test case submitted by Per Lundgren, ERV. - -high_chaparal(Config) when is_list(Config) -> - P = runner:start(Config, ?high_chaparal), - {term, [hello, world]} = get_term(P), - runner:recv_eot(P), - ok. - -%% OTP-7448 -broken_data(Config) when is_list(Config) -> - P = runner:start(Config, ?broken_data), - runner:recv_eot(P), - ok. - -%% This calls a C function with one parameter and returns the result. - -call_erl_function(Port, Term) -> - runner:send_term(Port, Term), - case get_term(Port) of - {term, Result} -> Result; - 'NULL' -> 'NULL' - end. - -print_term(Config) when is_list(Config) -> - filename:join(proplists:get_value(data_dir, Config), "print_term"). - - - -%%% We receive a ref from the cnode, and expect it to be a long ref. -%%% We also send a ref we created ourselves, and expect to get it -%%% back, without having been mutated into short form. We must take -%%% care then to check the actual returned ref, and not the original -%%% one, which is equal to it. - -%% Tests involving cnode: sends a long ref from a cnode to us -cnode_1(Config) when is_list(Config) -> - Cnode = filename:join(proplists:get_value(data_dir, Config), "cnode"), - register(mip, self()), - spawn_link(?MODULE, start_cnode, [Cnode]), - Ref1 = get_ref(), - io:format("Ref1 ~p~n", [Ref1]), - check_ref(Ref1), - Ref2 = make_ref(), - Pid = receive - Msg -> Msg %% pid - end, - Fun1 = fun(X) -> {Pid, X} end, % sneak in a fun test here - %Fun1 = {wait_with_funs, new_dist_format}, - Term = {Ref2, Fun1, {1,2,3,4,5,6,7,8,9,10}}, - %% A term which will overflow the original buffer used in 'cnode'. - Pid ! Term, - receive - Term2 -> - io:format("received ~p~n", [Term2]), - case Term2 of - Term -> - {Ref22,_,_} = Term2, - check_ref(Ref22); - X -> - ct:fail({receive1,X}) - end - after 5000 -> - ct:fail(receive1) - end, - receive - Pid -> - ok; - Y -> - ct:fail({receive1,Y}) - after 5000 -> - ct:fail(receive2) - end, - io:format("ref = ~p~n", [Ref1]), - check_ref(Ref1), - ok. - -check_ref(Ref) -> - case bin_ext_type(Ref) of - 101 -> - ct:fail(oldref); - 114 -> - ok; - Type -> - ct:fail({type, Type}) - end. - -bin_ext_type(T) -> - [131, Type | _] = binary_to_list(term_to_binary(T)), - Type. - -get_ref() -> - receive - X when is_reference(X) -> - X - after 5000 -> - ct:fail({cnode, timeout}) - end. - -start_cnode(Cnode) -> - open_port({spawn, Cnode ++ " " ++ atom_to_list(erlang:get_cookie())}, []), - rec_cnode(). - -rec_cnode() -> - receive - X -> - io:format("from cnode: ~p~n", [X]), - rec_cnode() - end. - -nc2vinfo(Pid) when is_pid(Pid) -> - [_NodeStr, NumberStr, SerialStr] - = string:tokens(pid_to_list(Pid), "<.>"), - Number = list_to_integer(NumberStr), - Serial = list_to_integer(SerialStr), - {pid, node(Pid), Number, Serial}; -nc2vinfo(Port) when is_port(Port) -> - ["#Port", _NodeStr, NumberStr] - = string:tokens(erlang:port_to_list(Port), "<.>"), - Number = list_to_integer(NumberStr), - {port, node(Port), Number}; -nc2vinfo(Ref) when is_reference(Ref) -> - ["#Ref", _NodeStr | NumStrList] - = string:tokens(erlang:ref_to_list(Ref), "<.>"), - {Len, RevNumList} = lists:foldl(fun ("0", {N, []}) -> - {N+1, []}; - (IStr, {N, Is}) -> - {N+1, - [list_to_integer(IStr)|Is]} - end, - {0, []}, - NumStrList), - {ref, node(Ref), Len, lists:reverse(RevNumList)}; -nc2vinfo(Other) -> - {badarg, Other}. diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.first deleted file mode 100644 index 0ea872ef49..0000000000 --- a/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.first +++ /dev/null @@ -1,22 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2000-2016. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -eterm_test_decl.c: eterm_test.c - erl -noinput -pa ../all_SUITE_data -s init_tc run eterm_test -s erlang halt diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src deleted file mode 100644 index 4b1ddf77b6..0000000000 --- a/lib/erl_interface/test/erl_eterm_SUITE_data/Makefile.src +++ /dev/null @@ -1,50 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2016. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -include @erl_interface_mk_include@ - -CC0 = @CC@ -CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" -LD = @LD@ -LIBERL = @erl_interface_lib@ -LIBEI = @erl_interface_eilib@ -LIBFLAGS = ../all_SUITE_data/runner@obj@ \ - $(LIBERL) $(LIBEI) @erl_interface_sock_libs@ @LIBS@ \ - @erl_interface_threadlib@ -CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data -ETERM_OBJS = eterm_test@obj@ eterm_test_decl@obj@ -CNODE_OBJS = cnode@obj@ -PRINT_OBJS = print_term@obj@ -EXE_FILES = eterm_test@exe@ print_term@exe@ cnode@exe@ - -all: $(EXE_FILES) - -eterm_test@exe@: $(ETERM_OBJS) $(LIBERL) $(LIBEI) - $(LD) @CROSSLDFLAGS@ -o $@ $(ETERM_OBJS) $(LIBFLAGS) - -cnode@exe@: $(CNODE_OBJS) $(LIBERL) $(LIBEI) - $(LD) @CROSSLDFLAGS@ -o $@ $(CNODE_OBJS) $(LIBFLAGS) - -print_term@exe@: print_term@obj@ $(LIBERL) $(LIBEI) - $(LD) @CROSSLDFLAGS@ -o $@ $(PRINT_OBJS) $(LIBFLAGS) - -clean: - $(RM) $(ETERM_OBJS) $(CNODE_OBJS) $(PRINT_OBJS) - $(RM) $(EXE_FILES) diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c b/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c deleted file mode 100644 index b87feb9dfc..0000000000 --- a/lib/erl_interface/test/erl_eterm_SUITE_data/cnode.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1999-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "ei.h" -#include "erl_interface.h" - -#define MSGSIZE 13 - -#define SELF(fd) erl_mk_pid(erl_thisnodename(),fd,0,erl_thiscreation()) - -#ifdef VXWORKS -#define MAIN cnode -#else -#define MAIN main -#endif - -/* FIXME uses mix och ei and erl_interface */ - -/* - A small cnode. - To be called from the test case erl_eterm_SUITE:cnode_1. - - 1) Set up connection to node 'test_server' on the same host. - All sends are done to a registered process named 'mip'. - 2) Create a long ref and send it. - 3) Create a pid for ourselves and send it. - 4) Receive a message. - 5) Send back the message part of the message. - 6) Send back the 'to' part of the message. - 7) Exit. -*/ - -MAIN(int argc, char **argv) - -{ - unsigned char *msgbufp; - int msgsize; - ErlMessage msg; - char msgbuf[MSGSIZE]; - char buf[100]; - char buf1[100]; - char buf2[100]; - int ix; - int s; - int fd; - char node[80]; - char server[80]; - char host[80]; - int number; - ETERM *ref, *ref1, *ref2; - FILE *dfile = fopen("cnode_debug_printout", "w"); - - erl_init(NULL, 0); - - number = 1; - if (argc >= 2) { - s = erl_connect_init(number, argv[1], 0); - } else { - s = erl_connect_init(number, (char *) 0, 0); - } - gethostname(host, sizeof(host)); - sprintf(node, "c%d@%s", number, host); - - fprintf(dfile, "s = %d\n", s); fflush(dfile); - - sprintf(server, "test_server@%s", host); - fd = erl_connect(server); - fprintf(dfile, "fd = %d\n", fd); - -/* fprintf(dfile, "dist = %d\n", erl_distversion(fd)); */ - -#if 1 - ref = erl_mk_long_ref(node, 4711, 113, 98, 0); -#else - ref = erl_mk_ref(node, 4711, 0); -#endif - fprintf(dfile, "ref = %p\n", ref); fflush(dfile); - - s = erl_reg_send(fd, "mip", ref); - fprintf(dfile, "s = %d\n", s); fflush(dfile); - - { - ETERM* emsg; - emsg = SELF(fd); - fprintf(dfile, "pid = %p\n", emsg); fflush(dfile); - s = erl_reg_send(fd,"mip",emsg); - fprintf(dfile, "s2 = %d\n", s); fflush(dfile); - erl_free_term(emsg); - } - - msgsize = 4; - msgbufp = (unsigned char *) malloc(msgsize); - - do { -#if 0 - s = erl_receive_msg(fd, msgbuf, MSGSIZE, &msg); -#else - s = erl_xreceive_msg(fd, &msgbufp, &msgsize, &msg); -#endif - switch (s) { - case ERL_TICK: - fprintf(dfile, "tick\n"); - break; - case ERL_ERROR: - fprintf(dfile, "error: %s (%d)\n", strerror(erl_errno), erl_errno); - break; - case ERL_MSG: - fprintf(dfile, "msg %d\n", msgsize); - break; - default: - fprintf(dfile, "unknown result %d\n", s); - break; - } - fflush(dfile); - } while (s == ERL_TICK); - - s = erl_reg_send(fd, "mip", msg.msg); - fprintf(dfile, "s = %d\n", s); fflush(dfile); - s = erl_reg_send(fd, "mip", msg.to); - fprintf(dfile, "s = %d\n", s); fflush(dfile); -#if 0 - /* from = NULL! */ - s = erl_reg_send(fd, "mip", msg.from); - fprintf(dfile, "s = %d\n", s); fflush(dfile); -#endif - -#if 0 - /* Unused code which tests refs in some ways. */ - ix = 0; - s = ei_encode_term(buf, &ix, ref); - printf ("ei encode = %d, ix = %d\n", s, ix); - - /* Compare old and new ref equal */ - ref1 = erl_mk_long_ref(node, 4711, 113, 98, 0); - ref2 = erl_mk_ref(node, 4711, 0); - s = erl_encode(ref1, buf1); - fprintf(dfile, "enc1 s = %d\n", s); fflush(dfile); - s = erl_encode(ref2, buf2); - fprintf(dfile, "enc2 s = %d\n", s); fflush(dfile); - s = erl_compare_ext(buf1, buf2); - fprintf(dfile, "comp s = %d\n", s); fflush(dfile); - - /* Compare, in another way */ - s = erl_match(ref1, ref2); - fprintf(dfile, "match s = %d\n", s); fflush(dfile); -#endif - - fclose(dfile); - - erl_close_connection(fd); - - return 0; -} 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 deleted file mode 100644 index d97f218a26..0000000000 --- a/lib/erl_interface/test/erl_eterm_SUITE_data/eterm_test.c +++ /dev/null @@ -1,1604 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1997-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/* - * Purpose: Tests the functions in erl_eterm.c and erl_malloc.c. - * Author: Bjorn Gustavsson - * - * See the erl_eterm_SUITE.erl file for a "table of contents". - */ - -#include <stdio.h> -#include <string.h> - -#include "runner.h" - -/* - * Find out which version of erl_interface we are using. - */ - -#ifdef ERL_IS_STRING -#undef NEW_ERL_INTERFACE -#else -#define NEW_ERL_INTERFACE -#endif - -void dump_term (FILE *fp, ETERM *t); - -static ETERM* all_types(); - -/*********************************************************************** - * - * 1. B a s i c t e s t s - * - ***********************************************************************/ - -/* - * Sends a list contaning all data types to the Erlang side. - */ - -TESTCASE(build_terms) -{ - ETERM* t; - - erl_init(NULL, 0); - t = all_types(); - send_term(t); - 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) -{ - int n, i; - - erl_init(NULL, 0); - encode_decode(all_types(), "ALL"); - - { - int v; - for (v = 8, n = 0; n < (sizeof(v)*8-4-1); v <<= 1, n++) { - for (i=-4; i<4; i++) { - encode_decode(erl_mk_int(v+i), "INT"); - encode_decode(erl_mk_int(-(v+i)), "NEG INT"); - } - } - } - { - unsigned int v; - for (v = 8; v; v <<= 1) { - for (i=-4; i<4; i++) { - encode_decode(erl_mk_uint(v+i), "UINT"); - } - } - } - { - long long v; - for (v = 8, n = 0; n < (sizeof(v)*8-4-1); v <<= 1, n++) { - 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"); - } - } - } - - report(1); -} - -/* - * Decodes data from the Erlang side and verifies. - */ - -TESTCASE(decode_terms) -{ - ETERM* terms; - char* message; - - erl_init(NULL, 0); - terms = get_term(); - if (terms == NULL) { - fail("unexpected end of file"); - } else { - ETERM* all; - ETERM* p; - ETERM* t; - int i; - - all = p = all_types(); - t = terms; - - /* - * XXX For now, skip the reference, pid, and port, because - * the match will fail. Must write code here to do some other - * validating. - */ - - for (i=0; i<6; i++) { - - p = erl_tl(p); - t = erl_tl(t); - erl_free_term(p); - erl_free_term(t); - - } - - /* - * Match the tail of the lists. - */ - - if (!erl_match(p, t)) - { - fail("Received terms didn't match expected"); - } - erl_free_term(all); - erl_free_term(terms); - report(1); - } -} - -/* - * Decodes a float from the Erlang side and verifies. - */ - -TESTCASE(decode_float) -{ - ETERM* afnum; - ETERM* efnum; - int result; - - erl_init(NULL, 0); - afnum = get_term(); - efnum = erl_mk_float(3.1415); - result = erl_match(efnum, afnum); - erl_free_term(afnum); - erl_free_term(efnum); - report(result); -} - -/* - * Tests the erl_free_compound() function. - */ - -TESTCASE(t_erl_free_compound) -{ - ETERM* t; - - erl_init(NULL, 0); - - t = all_types(); - erl_free_compound(t); - report(1); -} - - -/*********************************************************************** - * - * 2. C o n s t r u c t i n g t e r m s - * - ***********************************************************************/ - -/* - * Makes various integers, and sends them to Erlang for verification. - */ - -TESTCASE(t_erl_mk_int) -{ -#define SEND_INT(i) \ - do { \ - ETERM* t = erl_mk_int(i); \ - send_term(t); \ - } while (0); - - erl_init(NULL, 0); - - SEND_INT(0); - SEND_INT(127); - SEND_INT(128); - SEND_INT(255); - SEND_INT(256); - - SEND_INT(0xFFFF); - SEND_INT(0x10000); - - SEND_INT(0x07FFFFFF); - SEND_INT(0x0FFFFFFF); - SEND_INT(0x1FFFFFFF); - SEND_INT(0x3FFFFFFF); - SEND_INT(0x7FFFFFFF); - - SEND_INT(0x08000000); - SEND_INT(0x10000000); - SEND_INT(0x20000000); - SEND_INT(0x40000000); - - SEND_INT(-0x07FFFFFF); - SEND_INT(-0x0FFFFFFF); - SEND_INT(-0x1FFFFFFF); - SEND_INT(-0x3FFFFFFF); - SEND_INT(-0x7FFFFFFF); - - SEND_INT(-0x08000000); - SEND_INT(-0x10000000); - SEND_INT(-0x20000000); - SEND_INT(-0x40000000); - - SEND_INT(-0x08000001); - SEND_INT(-0x10000001); - SEND_INT(-0x20000001); - SEND_INT(-0x40000001); - - SEND_INT(-0x08000002); - SEND_INT(-0x10000002); - SEND_INT(-0x20000002); - SEND_INT(-0x40000002); - - SEND_INT(-1999999999); - SEND_INT(-2000000000); - SEND_INT(-2000000001); - - report(1); -} - - -/* - * Makes lists of various sizes, and sends them to Erlang for verification. - */ - -TESTCASE(t_erl_mk_list) -{ - ETERM* a[4]; - - erl_init(NULL, 0); - - /* - * Empty list. - */ - - send_term(erl_mk_list(a, 0)); - - /* - * One element: [abc] - */ - - a[0] = erl_mk_atom("abc"); - send_term(erl_mk_list(a, 1)); - erl_free_term(a[0]); - - /* - * Two elements: [abcdef, 42]. - */ - - a[0] = erl_mk_atom("abcdef"); - a[1] = erl_mk_int(42); - send_term(erl_mk_list(a, 2)); - erl_free_term(a[0]); - erl_free_term(a[1]); - - /* - * Four elements. - */ - - a[0] = erl_mk_float(0.0); - a[1] = erl_mk_int(23); - a[2] = erl_mk_empty_list(); - a[3] = erl_mk_float(3.1415); - send_term(erl_mk_list(a, 4)); - erl_free_term(a[0]); - erl_free_term(a[1]); - erl_free_term(a[2]); - erl_free_term(a[3]); - - report(1); -} - -/* - * A basic test of erl_copy_term(). - */ - -TESTCASE(basic_copy) -{ - ETERM* original; - ETERM* copy; - int result; - - erl_init(NULL, 0); - original = all_types(); - copy = erl_copy_term(original); - if (copy == NULL) { - fail("erl_copy_term() failed"); - } else if (!erl_match(original, copy)) - { - fail("copy doesn't match original"); - } - - erl_free_term(original); - erl_free_term(copy); - report(1); -} - - -/* - * A basic test of erl_mk_atom(). - */ - -TESTCASE(t_erl_mk_atom) -{ - erl_init(NULL, 0); - - send_term(erl_mk_atom("madonna")); - send_term(erl_mk_atom("Madonna")); - send_term(erl_mk_atom("mad donna")); - send_term(erl_mk_atom("_madonna_")); - send_term(erl_mk_atom("/home/madonna/tour_plan")); - send_term(erl_mk_atom("http://www.madonna.com/tour_plan")); - send_term(erl_mk_atom("\'madonna\'")); - send_term(erl_mk_atom("\"madonna\"")); - send_term(erl_mk_atom("\\madonna\\")); - send_term(erl_mk_atom("{madonna,21,'mad donna',12}")); - - report(1); -} - - -/* - * A basic test of erl_mk_binary(). - */ - -TESTCASE(t_erl_mk_binary) -{ - - char* string; - erl_init(NULL, 0); - - string = "{madonna,21,'mad donna',1234.567.890, !#$%&/()=?+-@, \" \\}"; - send_term(erl_mk_binary(string,strlen(string))); - - report(1); -} - - -/* - * A basic test of erl_mk_empty_list(). - */ - -TESTCASE(t_erl_mk_empty_list) -{ - erl_init(NULL, 0); - - send_term(erl_mk_empty_list()); - report(1); -} - - -/* - * A basic test of erl_mk_float(). - */ - -TESTCASE(t_erl_mk_float) -{ - ETERM* arr[6]; - ETERM* emsg; - - erl_init(NULL, 0); - - arr[0] = erl_mk_float(3.1415); - arr[1] = erl_mk_float(1.999999); - arr[2] = erl_mk_float(2.000000); - arr[3] = erl_mk_float(2.000001); - arr[4] = erl_mk_float(2.000002); - arr[5] = erl_mk_float(12345.67890); - emsg = (erl_mk_tuple(arr,6)); - - send_term(emsg); - - erl_free_array(arr,6); - /* emsg already freed by send_term() */ - /* erl_free_term(emsg); */ - - report(1); -} - - -/* - * A basic test of erl_mk_pid(). - */ - -TESTCASE(t_erl_mk_pid) -{ - erl_init(NULL, 0); - - send_term(erl_mk_pid("kalle@localhost", 3, 2, 1)); - report(1); -} - -/* - * A basic test of erl_mk_pid(). - */ - -TESTCASE(t_erl_mk_xpid) -{ - erl_init(NULL, 0); - - send_term(erl_mk_pid("kalle@localhost", 32767, 8191, 1)); - report(1); -} - - -/* - * A basic test of erl_mk_port(). - */ - -TESTCASE(t_erl_mk_port) -{ - erl_init(NULL, 0); - - send_term(erl_mk_port("kalle@localhost", 4, 1)); - report(1); -} - -/* - * A basic test of erl_mk_port(). - */ - -TESTCASE(t_erl_mk_xport) -{ - erl_init(NULL, 0); - - send_term(erl_mk_port("kalle@localhost", 268435455, 1)); - report(1); -} - -/* - * A basic test of erl_mk_ref(). - */ - -TESTCASE(t_erl_mk_ref) -{ - erl_init(NULL, 0); - - send_term(erl_mk_ref("kalle@localhost", 6, 1)); - report(1); -} - -/* - * A basic test of erl_mk_long_ref(). - */ - - -TESTCASE(t_erl_mk_long_ref) -{ - erl_init(NULL, 0); - - send_term(erl_mk_long_ref("kalle@localhost", - 4294967295, 4294967295, 262143, - 1)); - report(1); -} - - -/* - * A basic test of erl_mk_string(). - */ - -TESTCASE(t_erl_mk_string) -{ - - erl_init(NULL, 0); - - send_term(erl_mk_string("madonna")); - send_term(erl_mk_string("Madonna")); - send_term(erl_mk_string("mad donna")); - send_term(erl_mk_string("_madonna_")); - send_term(erl_mk_string("/home/madonna/tour_plan")); - send_term(erl_mk_string("http://www.madonna.com/tour_plan")); - send_term(erl_mk_string("\'madonna\'")); - send_term(erl_mk_string("\"madonna\"")); - send_term(erl_mk_string("\\madonna\\")); - send_term(erl_mk_string("{madonna,21,'mad donna',12}")); - - report(1); -} - - -/* - * A basic test of erl_mk_estring(). - */ - -TESTCASE(t_erl_mk_estring) -{ - char* string; - erl_init(NULL, 0); - - string = "madonna"; - send_term(erl_mk_estring(string,strlen(string))); - string = "Madonna"; - send_term(erl_mk_estring(string,strlen(string))); - string = "mad donna"; - send_term(erl_mk_estring(string,strlen(string))); - string = "_madonna_"; - send_term(erl_mk_estring(string,strlen(string))); - string = "/home/madonna/tour_plan"; - send_term(erl_mk_estring(string,strlen(string))); - string = "http://www.madonna.com/tour_plan"; - send_term(erl_mk_estring(string,strlen(string))); - string = "\'madonna\'"; - send_term(erl_mk_estring(string,strlen(string))); - string = "\"madonna\""; - send_term(erl_mk_estring(string,strlen(string))); - string = "\\madonna\\"; - send_term(erl_mk_estring(string,strlen(string))); - string = "{madonna,21,'mad donna',12}"; - send_term(erl_mk_estring(string,strlen(string))); - - report(1); -} - - -/* - * A basic test of erl_mk_tuple(). - */ - -TESTCASE(t_erl_mk_tuple) -{ - ETERM* arr[4]; - ETERM* arr2[2]; - ETERM* arr3[2]; - ETERM* arr4[2]; - - erl_init(NULL, 0); - - /* {madonna,21,'mad donna',12} */ - arr[0] = erl_mk_atom("madonna"); - arr[1] = erl_mk_int(21); - arr[2] = erl_mk_atom("mad donna"); - arr[3] = erl_mk_int(12); - - send_term(erl_mk_tuple(arr,4)); - - erl_free_array(arr,4); - - - /* {'Madonna',21,{children,{"Isabella",2}},{'home page',"http://www.madonna.com/"} */ - arr4[0] = erl_mk_atom("home page"); - arr4[1] = erl_mk_string("http://www.madonna.com/"); - - arr3[0] = erl_mk_string("Isabella"); - arr3[1] = erl_mk_int(2); - - arr2[0] = erl_mk_atom("children"); - arr2[1] = erl_mk_tuple(arr3,2); - - arr[0] = erl_mk_atom("Madonna"); - arr[1] = erl_mk_int(21); - arr[2] = erl_mk_tuple(arr2,2); - arr[3] = erl_mk_tuple(arr4,2); - - send_term(erl_mk_tuple(arr,4)); - - erl_free_array(arr,4); - erl_free_array(arr2,2); - erl_free_array(arr3,2); - erl_free_array(arr4,2); - - - report(1); -} - - -/* - * A basic test of erl_mk_uint(). - */ - -TESTCASE(t_erl_mk_uint) -{ - unsigned i; - - erl_init(NULL, 0); - - send_term(erl_mk_uint(54321)); - i = 2147483647; - send_term(erl_mk_uint(i)); - send_term(erl_mk_uint(i+1)); - send_term(erl_mk_uint(i+2)); - send_term(erl_mk_uint(i+3)); - send_term(erl_mk_uint(i+i+1)); - - report(1); -} - - -/* - * A basic test of erl_mk_var(). - */ - -TESTCASE(t_erl_mk_var) -{ - ETERM* mk_var; - ETERM* term; - ETERM* term2; - ETERM* arr[4]; - ETERM* arr_term[2]; - ETERM* mk_var_tuple; - ETERM* term_tuple; - - erl_init(NULL, 0); - - - /* match unbound/bound variable against an integer */ - term = erl_mk_int(17); - term2 = erl_mk_int(2); - mk_var = erl_mk_var("New_var"); - send_term(erl_mk_int(erl_match(mk_var, term))); /* should be ok */ - send_term(erl_mk_int(erl_match(mk_var, term2))); /* should fail */ - send_term(erl_mk_int(erl_match(mk_var, term))); /* should be ok */ - send_term(erl_mk_int(erl_match(mk_var, term2))); /* should fail */ - erl_free_term(mk_var); - erl_free_term(term); - erl_free_term(term2); - - /* match unbound variable against a tuple */ - arr[0] = erl_mk_atom("madonna"); - arr[1] = erl_mk_int(21); - arr[2] = erl_mk_atom("mad donna"); - arr[3] = erl_mk_int(12); - mk_var = erl_mk_var("New_var"); - term = erl_mk_tuple(arr,4); - send_term(erl_mk_int(erl_match(mk_var, term))); /* should be ok */ - erl_free_term(mk_var); - erl_free_term(term); - erl_free_array(arr,4); - - - /* match (twice) unbound variable against an incorrect tuple */ - arr[0] = erl_mk_var("New_var"); - arr[1] = erl_mk_var("New_var"); - arr_term[0] = erl_mk_int(17); - arr_term[1] = erl_mk_int(27); - mk_var_tuple = erl_mk_tuple(arr,2); - term_tuple = erl_mk_tuple(arr_term,2); - send_term(erl_mk_int(erl_match(mk_var_tuple, term_tuple))); /* should fail */ - erl_free_array(arr,2); - erl_free_array(arr_term,2); - erl_free_term(mk_var_tuple); - erl_free_term(term_tuple); - - - /* match (twice) unbound variable against a correct tuple */ - arr[0] = erl_mk_var("New_var"); - arr[1] = erl_mk_var("New_var"); - arr_term[0] = erl_mk_int(17); - arr_term[1] = erl_mk_int(17); - mk_var_tuple = erl_mk_tuple(arr,2); - term_tuple = erl_mk_tuple(arr_term,2); - send_term(erl_mk_int(erl_match(mk_var_tuple, term_tuple))); /* should be ok */ - erl_free_array(arr,2); - erl_free_array(arr_term,2); - erl_free_term(mk_var_tuple); - erl_free_term(term_tuple); - - report(1); -} - - -/* - * A basic test of erl_size(). - */ - -TESTCASE(t_erl_size) -{ - ETERM* arr[4]; - ETERM* tuple; - ETERM* bin; - char* string; - - erl_init(NULL, 0); - - /* size of a tuple */ - tuple = erl_format("{}"); - send_term(erl_mk_int(erl_size(tuple))); - erl_free_term(tuple); - - arr[0] = erl_mk_atom("madonna"); - arr[1] = erl_mk_int(21); - arr[2] = erl_mk_atom("mad donna"); - arr[3] = erl_mk_int(12); - tuple = erl_mk_tuple(arr,4); - - send_term(erl_mk_int(erl_size(tuple))); - - erl_free_array(arr,4); - erl_free_term(tuple); - - /* size of a binary */ - string = ""; - bin = erl_mk_binary(string,strlen(string)); - send_term(erl_mk_int(erl_size(bin))); - erl_free_term(bin); - - string = "{madonna,21,'mad donna',12}"; - bin = erl_mk_binary(string,strlen(string)); - send_term(erl_mk_int(erl_size(bin))); - erl_free_term(bin); - - report(1); -} - - -/* - * A basic test of erl_var_content(). - */ - -TESTCASE(t_erl_var_content) -{ - ETERM* mk_var; - ETERM* term; - ETERM* tuple; - ETERM* list; - ETERM* a; - ETERM* b; - ETERM* arr[4]; - ETERM* arr2[2]; - ETERM* arr3[2]; - ETERM* arr4[2]; - - erl_init(NULL, 0); - - term = erl_mk_int(17); - mk_var = erl_mk_var("Var"); - - /* unbound, should return NULL */ - if (erl_var_content(mk_var,"Var") != NULL) - fail("t_erl_var_content() failed"); - - erl_match(mk_var, term); - send_term(erl_var_content(mk_var,"Var")); /* should return 17 */ - - /* integer, should return NULL */ - if (erl_var_content(term,"Var") != NULL) - fail("t_erl_var_content() failed"); - - /* unknown variable, should return NULL */ - if (erl_var_content(mk_var,"Unknown_Var") != NULL) - fail("t_erl_var_content() failed"); - - erl_free_term(mk_var); - erl_free_term(term); - - /* {'Madonna',21,{children,{"Name","Age"}},{"Home_page","Tel_no"}} */ - arr4[0] = erl_mk_var("Home_page"); - arr4[1] = erl_mk_var("Tel_no"); - a = erl_mk_string("http://www.madonna.com"); - erl_match(arr4[0], a); - - arr3[0] = erl_mk_var("Name"); - arr3[1] = erl_mk_var("Age"); - b = erl_mk_int(2); - erl_match(arr3[1], b); - - arr2[0] = erl_mk_atom("children"); - arr2[1] = erl_mk_tuple(arr3,2); - - arr[0] = erl_mk_atom("Madonna"); - arr[1] = erl_mk_int(21); - arr[2] = erl_mk_tuple(arr2,2); - arr[3] = erl_mk_tuple(arr4,2); - - tuple = erl_mk_tuple(arr,4); - - /* should return "http://www.madonna.com" */ - send_term(erl_var_content(tuple,"Home_page")); - - /* unbound, should return NULL */ - if (erl_var_content(tuple,"Tel_no") != NULL) - fail("t_erl_var_content() failed"); - - /* unbound, should return NULL */ - if (erl_var_content(tuple,"Name") != NULL) - fail("t_erl_var_content() failed"); - - /* should return 2 */ - send_term(erl_var_content(tuple,"Age")); - - erl_free_array(arr,4); - erl_free_array(arr2,2); - erl_free_array(arr3,2); - erl_free_array(arr4,2); - erl_free_term(tuple); - erl_free_term(a); - erl_free_term(b); - - - /* [] */ - list = erl_mk_empty_list(); - if (erl_var_content(list,"Tel_no") != NULL) - fail("t_erl_var_content() failed"); - erl_free_term(list); - - - /* ['Madonna',[],{children,{"Name","Age"}},{"Home_page","Tel_no"}] */ - arr4[0] = erl_mk_var("Home_page"); - arr4[1] = erl_mk_var("Tel_no"); - a = erl_mk_string("http://www.madonna.com"); - erl_match(arr4[0], a); - - arr3[0] = erl_mk_var("Name"); - arr3[1] = erl_mk_var("Age"); - b = erl_mk_int(2); - erl_match(arr3[1], b); - - arr2[0] = erl_mk_atom("children"); - arr2[1] = erl_mk_tuple(arr3,2); - - arr[0] = erl_mk_atom("Madonna"); - arr[1] = erl_mk_empty_list(); - arr[2] = erl_mk_tuple(arr2,2); - arr[3] = erl_mk_tuple(arr4,2); - - list = erl_mk_list(arr,4); - - /* should return "http://www.madonna.com" */ - send_term(erl_var_content(list,"Home_page")); - - /* unbound, should return NULL */ - if (erl_var_content(list,"Tel_no") != NULL) - fail("t_erl_var_content() failed"); - - /* unbound, should return NULL */ - if (erl_var_content(list,"Name") != NULL) - fail("t_erl_var_content() failed"); - - /* should return 2 */ - send_term(erl_var_content(list,"Age")); - - erl_free_array(arr,4); - erl_free_array(arr2,2); - erl_free_array(arr3,2); - erl_free_array(arr4,2); - erl_free_term(list); - erl_free_term(a); - erl_free_term(b); - - report(1); -} - - -/* - * A basic test of erl_element(). - */ - -TESTCASE(t_erl_element) -{ - ETERM* arr[4]; - ETERM* arr2[2]; - ETERM* arr3[2]; - ETERM* arr4[2]; - ETERM* tuple; - - erl_init(NULL, 0); - - arr[0] = erl_mk_atom("madonna"); - arr[1] = erl_mk_int(21); - arr[2] = erl_mk_atom("mad donna"); - arr[3] = erl_mk_int(12); - tuple = erl_mk_tuple(arr,4); - - send_term(erl_element(1,tuple)); - send_term(erl_element(2,tuple)); - send_term(erl_element(3,tuple)); - send_term(erl_element(4,tuple)); - - erl_free_array(arr,4); - erl_free_term(tuple); - - /* {'Madonna',21,{children,{"Isabella",2}},{'home page',"http://www.madonna.com/"} */ - arr4[0] = erl_mk_atom("home page"); - arr4[1] = erl_mk_string("http://www.madonna.com/"); - - arr3[0] = erl_mk_string("Isabella"); - arr3[1] = erl_mk_int(2); - - arr2[0] = erl_mk_atom("children"); - arr2[1] = erl_mk_tuple(arr3,2); - - arr[0] = erl_mk_atom("Madonna"); - arr[1] = erl_mk_int(21); - arr[2] = erl_mk_tuple(arr2,2); - arr[3] = erl_mk_tuple(arr4,2); - - tuple = erl_mk_tuple(arr,4); - send_term(erl_element(1,tuple)); - send_term(erl_element(2,tuple)); - send_term(erl_element(3,tuple)); - send_term(erl_element(4,tuple)); - - erl_free_term(tuple); - erl_free_array(arr,4); - erl_free_array(arr2,2); - erl_free_array(arr3,2); - erl_free_array(arr4,2); - - report(1); -} - - -/* - * A basic test of erl_cons(). - */ - -TESTCASE(t_erl_cons) -{ - ETERM* list; - ETERM* anAtom; - ETERM* anInt; - - erl_init(NULL, 0); - - anAtom = erl_mk_atom("madonna"); - anInt = erl_mk_int(21); - list = erl_mk_empty_list(); - list = erl_cons(anInt, list); - send_term(erl_cons(anAtom, list)); - - erl_free_term(anAtom); - erl_free_term(anInt); - erl_free_compound(list); - - report(1); -} - - - - -/*********************************************************************** - * - * 3. E x t r a c t i n g & i n f o f u n c t i o n s - * - ***********************************************************************/ - -/* - * Calculates the length of each list sent to it and sends back the result. - */ - -TESTCASE(t_erl_length) -{ - erl_init(NULL, 0); - - for (;;) { - ETERM* term = get_term(); - - if (term == NULL) { - report(1); - return; - } else { - ETERM* len_term; - - len_term = erl_mk_int(erl_length(term)); - erl_free_term(term); - send_term(len_term); - } - } -} - -/* - * Gets the head of each term and sends the result back. - */ - -TESTCASE(t_erl_hd) -{ - erl_init(NULL, 0); - - for (;;) { - ETERM* term = get_term(); - - if (term == NULL) { - report(1); - return; - } else { - ETERM* head; - - head = erl_hd(term); - send_term(head); - erl_free_term(term); - } - } -} - -/* - * Gets the tail of each term and sends the result back. - */ - -TESTCASE(t_erl_tl) -{ - erl_init(NULL, 0); - - for (;;) { - ETERM* term = get_term(); - - if (term == NULL) { - report(1); - return; - } else { - ETERM* tail; - - tail = erl_tl(term); - send_term(tail); - erl_free_term(term); - } - } -} - -/* - * Checks the type checking macros. - */ - -TESTCASE(type_checks) -{ - ETERM* t; - ETERM* atom; - - erl_init(NULL, 0); - atom = erl_mk_atom("an_atom"); - -#define TYPE_CHECK(macro, term) \ - { ETERM* t = term; \ - if (macro(t)) { \ - erl_free_term(t); \ - } else { \ - fail("Macro " #macro " failed on " #term); \ - } \ - } - - TYPE_CHECK(ERL_IS_INTEGER, erl_mk_int(0x7FFFFFFF)); -#ifdef NEW_ERL_INTERFACE - TYPE_CHECK(ERL_IS_UNSIGNED_INTEGER, erl_mk_uint(0x7FFFFFFF)); -#endif - TYPE_CHECK(ERL_IS_FLOAT, erl_mk_float(5.5)); - TYPE_CHECK(ERL_IS_ATOM, erl_mk_atom("another_atom")); - - TYPE_CHECK(ERL_IS_EMPTY_LIST, erl_mk_empty_list()); - TYPE_CHECK(!ERL_IS_EMPTY_LIST, erl_cons(atom, atom)); - -#ifdef NEW_ERL_INTERFACE - TYPE_CHECK(!ERL_IS_CONS, erl_mk_empty_list()); - TYPE_CHECK(ERL_IS_CONS, erl_cons(atom, atom)); -#endif - - TYPE_CHECK(ERL_IS_LIST, erl_mk_empty_list()); - TYPE_CHECK(ERL_IS_LIST, erl_cons(atom, atom)); - - TYPE_CHECK(ERL_IS_PID, erl_mk_pid("a@a", 42, 1, 1)); - TYPE_CHECK(ERL_IS_PORT, erl_mk_port("a@a", 42, 1)); - TYPE_CHECK(ERL_IS_REF, erl_mk_ref("a@a", 42, 1)); - - TYPE_CHECK(ERL_IS_BINARY, erl_mk_binary("a", 1)); - TYPE_CHECK(ERL_IS_TUPLE, erl_mk_tuple(&atom, 1)); -#undef TYPE_CHECK - - erl_free_term(atom); - - report(1); -} - -/* - * Checks the extractor macros. - */ - -TESTCASE(extractor_macros) -{ - ETERM* t; - - erl_init(NULL, 0); - -#ifdef NEW_ERL_INTERFACE -#define MATCH(a, b) ((a) == (b) ? 1 : fail("bad match: " #a)) -#define STR_MATCH(a, b) (strcmp((a), (b)) ? fail("bad match: " #a) : 0) - - { /* Integer */ - int anInt = 0x7FFFFFFF; - t = erl_mk_int(anInt); - MATCH(ERL_INT_VALUE(t), anInt); - MATCH(ERL_INT_UVALUE(t), anInt); - erl_free_term(t); - } - - { /* Float */ - double aFloat = 3.1415; - t = erl_mk_float(aFloat); - MATCH(ERL_FLOAT_VALUE(t), aFloat); - erl_free_term(t); - } - - { /* Atom. */ - char* aString = "nisse"; - t = erl_mk_atom(aString); - if (memcmp(ERL_ATOM_PTR(t), aString, strlen(aString)) != 0) - fail("bad match"); - MATCH(ERL_ATOM_SIZE(t), strlen(aString)); - erl_free_term(t); - } - - { /* Pid. */ - char* node = "arne@strider"; - int number = 42; - int serial = 5; - int creation = 1; - - t = erl_mk_pid(node, number, serial, creation); - STR_MATCH(ERL_PID_NODE(t), node); - MATCH(ERL_PID_NUMBER(t), number); - MATCH(ERL_PID_SERIAL(t), serial); - MATCH(ERL_PID_CREATION(t), creation); - erl_free_term(t); - } - - { /* Port. */ - char* node = "kalle@strider"; - int number = 45; - int creation = 1; - - t = erl_mk_port(node, number, creation); - STR_MATCH(ERL_PORT_NODE(t), node); - MATCH(ERL_PORT_NUMBER(t), number); - MATCH(ERL_PORT_CREATION(t), creation); - erl_free_term(t); - } - - { /* Reference. */ - char* node = "kalle@strider"; - int number = 48; - int creation = 1; - - t = erl_mk_ref(node, number, creation); - STR_MATCH(ERL_REF_NODE(t), node); - MATCH(ERL_REF_NUMBER(t), number); - MATCH(ERL_REF_CREATION(t), creation); - erl_free_term(t); - } - - { /* Tuple. */ - ETERM* arr[2]; - - arr[0] = erl_mk_int(51); - arr[1] = erl_mk_int(52); - t = erl_mk_tuple(arr, ASIZE(arr)); - MATCH(ERL_TUPLE_SIZE(t), ASIZE(arr)); - MATCH(ERL_TUPLE_ELEMENT(t, 0), arr[0]); - MATCH(ERL_TUPLE_ELEMENT(t, 1), arr[1]); - erl_free_array(arr, ASIZE(arr)); - erl_free_term(t); - } - - { /* Binary. */ - static char bin[] = {1, 2, 3, 0, 4, 5}; - - t = erl_mk_binary(bin, ASIZE(bin)); - MATCH(ERL_BIN_SIZE(t), ASIZE(bin)); - if (memcmp(ERL_BIN_PTR(t), bin, ASIZE(bin)) != 0) - fail("bad match"); - erl_free_term(t); - } - - { - ETERM* head = erl_mk_atom("head"); - ETERM* tail = erl_mk_atom("tail"); - - t = erl_cons(head, tail); - MATCH(ERL_CONS_HEAD(t), head); - MATCH(ERL_CONS_TAIL(t), tail); - erl_free_term(head); - erl_free_term(tail); - erl_free_term(t); - } -#undef MATCH -#undef STR_MATCH -#endif - - report(1); -} - - - -/*********************************************************************** - * - * 4. I / O l i s t f u n c t i o n s - * - ***********************************************************************/ - -/* - * Invokes erl_iolist_length() on each term and send backs the result. - */ - -TESTCASE(t_erl_iolist_length) -{ - erl_init(NULL, 0); - - for (;;) { - ETERM* term = get_term(); - - if (term == NULL) { - report(1); - return; - } else { -#ifndef NEW_ERL_INTERFACE - fail("Function not present in this version of erl_interface"); -#else - ETERM* len_term; - - len_term = erl_mk_int(erl_iolist_length(term)); - erl_free_term(term); - send_term(len_term); -#endif - } - } -} - -/* - * Invokes erl_iolist_to_binary() on each term and send backs the result. - */ - -TESTCASE(t_erl_iolist_to_binary) -{ - erl_init(NULL, 0); - - for (;;) { - ETERM* term = get_term(); - - if (term == NULL) { - report(1); - return; - } else { -#ifndef NEW_ERL_INTERFACE - fail("Function not present in this version of erl_interface"); -#else - ETERM* new_term; - - new_term = erl_iolist_to_binary(term); - - erl_free_term(term); - send_term(new_term); -#endif - } - } -} - -/* - * Invokes erl_iolist_to_string() on each term and send backs the result. - */ - -TESTCASE(t_erl_iolist_to_string) -{ - erl_init(NULL, 0); - - for (;;) { - ETERM* term = get_term(); - - if (term == NULL) { - report(1); - return; - } else { -#ifndef NEW_ERL_INTERFACE - fail("Function not present in this version of erl_interface"); -#else - char* result; - - result = erl_iolist_to_string(term); - erl_free_term(term); - if (result != NULL) { - send_buffer(result, strlen(result)+1); - erl_free(result); - } else { - send_term(NULL); - } -#endif - } - } -} - - -/*********************************************************************** - * - * 5. M i s c e l l a n o u s T e s t s - * - ***********************************************************************/ - -/* - * Test some combinations of operations to verify that the reference pointers - * are handled correctly. - * - * "Det verkar vara lite High Chaparal med minneshanteringen i erl_interface" - * Per Lundgren, ERV. - */ - -TESTCASE(high_chaparal) -{ - ETERM *L1, *A1, *L2, *A2, *L3; - - erl_init(NULL, 0); - - L1 = erl_mk_empty_list(); - A1 = erl_mk_atom("world"); - L2 = erl_cons(A1, L1); - A2 = erl_mk_atom("hello"); - L3 = erl_cons(A2, L2); - - erl_free_term(L1); - erl_free_term(A1); - erl_free_term(L2); - erl_free_term(A2); - - send_term(L3); - - /* already freed by send_term() */ - /* erl_free_term(L3);*/ - - report(1); -} - -/* - * Test erl_decode to recover from broken list data (OTP-7448) - */ -TESTCASE(broken_data) -{ - ETERM* original; - ETERM* new_terms; - char encoded[16*1024]; - int n; - - erl_init(NULL, 0); - original = all_types(); - if ((n=erl_encode(original, encoded)) == 0) - { - fail("failed to encode terms"); - } else - { - int offs = n/2; - memset(encoded+offs,0,n-offs); /* destroy */ - - if ((new_terms = erl_decode(encoded)) != NULL) - { - fail("decode accepted broken data"); - erl_free_term(new_terms); - } - } - erl_free_term(original); - report(1); -} - -/* - * Returns a list containing instances of all types. - * - * Be careful changing the contents of the list returned, because both - * the build_terms() and decode_terms() test cases depend on it. - */ - -static ETERM* -all_types(void) -{ - ETERM* t; - ETERM* terms[3]; - int i; - static char a_binary[] = "A binary"; - -#define CONS_AND_FREE(expr, tail) \ - do { \ - ETERM* term = expr; \ - ETERM* nl = erl_cons(term, tail); \ - erl_free_term(term); \ - erl_free_term(tail); \ - tail = nl; \ - } while (0) - - t = erl_mk_empty_list(); - - CONS_AND_FREE(erl_mk_atom("I am an atom"), t); - CONS_AND_FREE(erl_mk_binary("A binary", sizeof(a_binary)-1), t); - CONS_AND_FREE(erl_mk_float(3.0), t); - CONS_AND_FREE(erl_mk_int(0), t); - CONS_AND_FREE(erl_mk_int(-1), t); - CONS_AND_FREE(erl_mk_int(1), t); - - CONS_AND_FREE(erl_mk_string("A string"), t); - - terms[0] = erl_mk_atom("element1"); - terms[1] = erl_mk_int(42); - terms[2] = erl_mk_int(767); - CONS_AND_FREE(erl_mk_tuple(terms, ASIZE(terms)), t); - for (i = 0; i < ASIZE(terms); i++) { - erl_free_term(terms[i]); - } - - CONS_AND_FREE(erl_mk_pid("kalle@localhost", 3, 2, 1), t); - CONS_AND_FREE(erl_mk_pid("abcdefghijabcdefghij@localhost", 3, 2, 1), t); - CONS_AND_FREE(erl_mk_port("kalle@localhost", 4, 1), t); - CONS_AND_FREE(erl_mk_port("abcdefghijabcdefghij@localhost", 4, 1), t); - CONS_AND_FREE(erl_mk_ref("kalle@localhost", 6, 1), t); - CONS_AND_FREE(erl_mk_ref("abcdefghijabcdefghij@localhost", 6, 1), t); - return t; - -#undef CONS_AND_FREE -} - -/* - * Dump (print for debugging) a term. Useful if/when things go wrong. - */ -void -dump_term (FILE *fp, ETERM *t) -{ - if (fp == NULL) return; - - fprintf(fp, "#<%p ", t); - - if(t != NULL) - { - fprintf(fp, "count:%d, type:%d", ERL_COUNT(t), ERL_TYPE(t)); - - switch(ERL_TYPE(t)) - { - case ERL_UNDEF: - fprintf(fp, "==undef"); - break; - case ERL_INTEGER: - fprintf(fp, "==int, val:%d", ERL_INT_VALUE(t)); - break; - case ERL_U_INTEGER: - fprintf(fp, "==uint, val:%u", ERL_INT_UVALUE(t)); - break; - case ERL_FLOAT: - fprintf(fp, "==float, val:%g", ERL_FLOAT_VALUE(t)); - break; - case ERL_ATOM: - fprintf(fp, "==atom, name:%p \"%s\"", - ERL_ATOM_PTR(t), ERL_ATOM_PTR(t)); - break; - case ERL_BINARY: - fprintf(fp, "==binary, data:%p,%u", - ERL_BIN_PTR(t), ERL_BIN_SIZE(t)); - break; - case ERL_PID: - fprintf(fp, "==pid, node:%p \"%s\"", - ERL_PID_NODE(t), ERL_PID_NODE(t)); - break; - case ERL_PORT: - fprintf(fp, "==port, node:%p \"%s\"", - ERL_PORT_NODE(t), ERL_PORT_NODE(t)); - break; - case ERL_REF: - fprintf(fp, "==ref, node:%p \"%s\"", - ERL_REF_NODE(t), ERL_REF_NODE(t)); - break; - case ERL_CONS: - fprintf(fp, "==cons"); - fprintf(fp, ", car:"); - dump_term(fp, ERL_CONS_HEAD(t)); - fprintf(fp, ", cdr:"); - dump_term(fp, ERL_CONS_TAIL(t)); - break; - case ERL_NIL: - fprintf(fp, "==nil"); - break; - case ERL_TUPLE: - fprintf(fp, "==tuple, elems:%p,%u", - ERL_TUPLE_ELEMS(t), ERL_TUPLE_SIZE(t)); - { - size_t i; - for(i = 0; i < ERL_TUPLE_SIZE(t); i++) - { - fprintf(fp, "elem[%u]:", i); - dump_term(fp, ERL_TUPLE_ELEMENT(t, i)); - } - } - break; - case ERL_VARIABLE: - fprintf(fp, "==variable, name:%p \"%s\"", - ERL_VAR_NAME(t), ERL_VAR_NAME(t)); - fprintf(fp, ", value:"); - dump_term(fp, ERL_VAR_VALUE(t)); - break; - - default: - break; - } - } - fprintf(fp, ">"); -} - diff --git a/lib/erl_interface/test/erl_eterm_SUITE_data/print_term.c b/lib/erl_interface/test/erl_eterm_SUITE_data/print_term.c deleted file mode 100644 index 5b7cb1aec8..0000000000 --- a/lib/erl_interface/test/erl_eterm_SUITE_data/print_term.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1997-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/* - * Purpose: Test the erl_print_term() function. - * Author: Bjorn Gustavsson - */ - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#ifndef __WIN32__ -#include <unistd.h> -#endif - -#include "erl_interface.h" - -#ifndef __WIN32__ -#define _O_BINARY 0 -#define _setmode(fd, mode) -#endif - -#define HEADER_SIZE 2 - -static int readn(int, unsigned char*, int); - -/* - * This program doesn't use the runner, because it needs a packet - * on input, but the result will be as a stream of bytes (since - * erl_print_term() prints directly on a file). - * - * Input is a package of with a packet header size of two bytes. - * - * +------------------------------------------------------------+ - * | length | Encoded term... | - * | (2 bytes) | (as given by "length") | - * +------------------------------------------------------------+ - * - * <------------------- length ---------------------> - * - * This program decodes the encoded terms and passes it to - * erl_print_term(). Then this program prints - * - * CR <result> LF - * - * and waits for a new package. <result> is the return value from - * erl_print_term(), formatted as an ASCII string. - */ - -#ifdef VXWORKS -int print_term() -#else -int main() -#endif -{ - _setmode(0, _O_BINARY); - _setmode(1, _O_BINARY); - - erl_init(NULL, 0); - - for (;;) { - char buf[4*1024]; - ETERM* term; - char* message; - int n; - - if (readn(0, buf, 2) <= 0) { - /* fprintf(stderr, "error reading message header\n"); */ - /* actually this is where we leave the infinite loop */ - exit(1); - } - n = buf[0] * 256 + buf[1]; - if (readn(0, buf, n) < 0) { - fprintf(stderr, "error reading message contents\n"); - exit(1); - } - - term = erl_decode(buf); - if (term == NULL) { - fprintf(stderr, "erl_decode() failed\n"); - exit(1); - } - n = erl_print_term(stdout, term); - erl_free_compound(term); - fprintf(stdout,"\r%d\n", n); - fflush(stdout); - } -} - -/* - * Reads len number of bytes. - */ - -static int -readn(fd, buf, len) - int fd; /* File descriptor to read from. */ - unsigned char *buf; /* Store in this buffer. */ - int len; /* Number of bytes to read. */ -{ - int n; /* Byte count in last read call. */ - int sofar = 0; /* Bytes read so far. */ - - do { - if ((n = read(fd, buf+sofar, len-sofar)) <= 0) - /* error or EOF in read */ - return(n); - sofar += n; - } while (sofar < len); - return sofar; -} - diff --git a/lib/erl_interface/test/erl_format_SUITE.erl b/lib/erl_interface/test/erl_format_SUITE.erl deleted file mode 100644 index 69dfdcc4c8..0000000000 --- a/lib/erl_interface/test/erl_format_SUITE.erl +++ /dev/null @@ -1,135 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2018. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(erl_format_SUITE). - --include_lib("common_test/include/ct.hrl"). --include("erl_format_SUITE_data/format_test_cases.hrl"). - --export([all/0, suite/0, - init_per_testcase/2, - atoms/1, tuples/1, lists/1]). - --import(runner, [get_term/1]). - -%% This test suite test the erl_format() function. -%% It uses the port program "format_test". - -suite() -> - [{ct_hooks,[ts_install_cth]}]. - -all() -> - [atoms, tuples, lists]. - -init_per_testcase(Case, Config) -> - runner:init_per_testcase(?MODULE, Case, Config). - -%% Tests formatting various atoms. - -atoms(Config) when is_list(Config) -> - P = runner:start(Config, ?atoms), - - {term, ''} = get_term(P), - {term, 'a'} = get_term(P), - {term, 'A'} = get_term(P), - {term, 'abc'} = get_term(P), - {term, 'Abc'} = get_term(P), - {term, 'ab@c'} = get_term(P), - {term, 'The rain in Spain stays mainly in the plains'} = get_term(P), - - {term, a} = get_term(P), - {term, ab} = get_term(P), - {term, abc} = get_term(P), - {term, ab@c} = get_term(P), - {term, abcdefghijklmnopq} = get_term(P), - - {term, ''} = get_term(P), - {term, 'a'} = get_term(P), - {term, 'A'} = get_term(P), - {term, 'abc'} = get_term(P), - {term, 'Abc'} = get_term(P), - {term, 'ab@c'} = get_term(P), - {term, 'The rain in Spain stays mainly in the plains'} = get_term(P), - - {term, a} = get_term(P), - {term, ab} = get_term(P), - {term, abc} = get_term(P), - {term, ab@c} = get_term(P), - {term, ' abcdefghijklmnopq '} = get_term(P), - - runner:recv_eot(P), - ok. - - - -%% Tests formatting various tuples - -tuples(Config) when is_list(Config) -> - P = runner:start(Config, ?tuples), - - {term, {}} = get_term(P), - {term, {a}} = get_term(P), - {term, {a, b}} = get_term(P), - {term, {a, b, c}} = get_term(P), - {term, {1}} = get_term(P), - {term, {[]}} = get_term(P), - {term, {[], []}} = get_term(P), - {term, {[], a, b, c}} = get_term(P), - {term, {[], a, [], b, c}} = get_term(P), - {term, {[], a, '', b, c}} = get_term(P), - - runner:recv_eot(P), - ok. - - - -%% Tests formatting various lists - -lists(Config) when is_list(Config) -> - P = runner:start(Config, ?lists), - - {term, []} = get_term(P), - {term, [a]} = get_term(P), - {term, [a, b]} = get_term(P), - {term, [a, b, c]} = get_term(P), - {term, [1]} = get_term(P), - {term, [[]]} = get_term(P), - {term, [[], []]} = get_term(P), - {term, [[], a, b, c]} = get_term(P), - {term, [[], a, [], b, c]} = get_term(P), - {term, [[], a, '', b, c]} = get_term(P), - - {term, [{name, 'Madonna'}, {age, 21}, {data, [{addr, "E-street", 42}]}]} = get_term(P), - case os:type() of - vxworks -> - {term, [{pi, _}, {'cos(70)', _}]} = get_term(P), - {term, [[pi, _], ['cos(70)', _]]} = get_term(P), - {term, [[pi, _], [], ["cos(70)", _]]} = get_term(P); - _ -> - {term, [{pi, 3.1415}, {'cos(70)', 0.34202}]} = get_term(P), - {term, [[pi, 3.1415], ['cos(70)', 0.34202]]} = get_term(P), - {term, [[pi, 3.1415], [], ["cos(70)", 0.34202]]} = get_term(P) - end, - - {term, [-1]} = get_term(P), - - runner:recv_eot(P), - ok. diff --git a/lib/erl_interface/test/erl_format_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_format_SUITE_data/Makefile.first deleted file mode 100644 index acbb8c98bb..0000000000 --- a/lib/erl_interface/test/erl_format_SUITE_data/Makefile.first +++ /dev/null @@ -1,22 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2000-2016. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -format_test_decl.c: format_test.c - erl -noinput -pa ../all_SUITE_data -s init_tc run format_test -s erlang halt diff --git a/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src deleted file mode 100644 index 2ba59ab651..0000000000 --- a/lib/erl_interface/test/erl_format_SUITE_data/Makefile.src +++ /dev/null @@ -1,43 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2016. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -include @erl_interface_mk_include@ - -CC0 = @CC@ -CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" -LD = @LD@ -LIBERL = @erl_interface_lib@ -LIBEI = @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 -FORMAT_OBJS = format_test@obj@ format_test_decl@obj@ - -all: format_test@exe@ - -clean: - $(RM) $(FORMAT_OBJS) - $(RM) format_test@exe@ - -format_test@exe@: $(FORMAT_OBJS) $(LIBERL) $(LIBEI) - $(LD) @CROSSLDFLAGS@ -o $@ $(FORMAT_OBJS) $(LIBFLAGS) - - diff --git a/lib/erl_interface/test/erl_format_SUITE_data/format_test.c b/lib/erl_interface/test/erl_format_SUITE_data/format_test.c deleted file mode 100644 index 258ae92e0f..0000000000 --- a/lib/erl_interface/test/erl_format_SUITE_data/format_test.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1997-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -#include "runner.h" - -/* - * Purpose: Tests the erl_format() function. - * Author: Bjorn Gustavsson - */ - -static void -send_format(char* format) -{ - send_term(erl_format(format)); -} - -TESTCASE(atoms) -{ - erl_init(NULL, 0); - - send_format("''"); - send_format("'a'"); - send_format("'A'"); - send_format("'abc'"); - send_format("'Abc'"); - send_format("'ab@c'"); - send_format("'The rain in Spain stays mainly in the plains'"); - - send_format("a"); - send_format("ab"); - send_format("abc"); - send_format("ab@c"); - send_format(" abcdefghijklmnopq "); - - send_term(erl_format("~a", "")); - send_term(erl_format("~a", "a")); - send_term(erl_format("~a", "A")); - send_term(erl_format("~a", "abc")); - send_term(erl_format("~a", "Abc")); - send_term(erl_format("~a", "ab@c")); - send_term(erl_format("~a", "The rain in Spain stays mainly in the plains")); - - send_term(erl_format("~a", "a")); - send_term(erl_format("~a", "ab")); - send_term(erl_format("~a", "abc")); - send_term(erl_format("~a","ab@c")); - send_term(erl_format("~a", " abcdefghijklmnopq ")); - - - report(1); -} - -TESTCASE(tuples) -{ - erl_init(NULL, 0); - - send_format("{}"); - send_format("{a}"); - send_format("{a, b}"); - send_format("{a, b, c}"); - send_format("{1}"); - send_format("{[]}"); - send_format("{[], []}"); - send_format("{[], a, b, c}"); - send_format("{[], a, [], b, c}"); - send_format("{[], a, '', b, c}"); - - report(1); -} - - - -TESTCASE(lists) -{ - ETERM* a; - ETERM* b; - ETERM* c; - - erl_init(NULL, 0); - - send_format("[]"); - send_format("[a]"); - send_format("[a, b]"); - send_format("[a, b, c]"); - send_format("[1]"); - send_format("[[]]"); - send_format("[[], []]"); - send_format("[[], a, b, c]"); - send_format("[[], a, [], b, c]"); - send_format("[[], a, '', b, c]"); - - b = erl_format("[{addr, ~s, ~i}]", "E-street", 42); - a = erl_format("[{name, ~a}, {age, ~i}, {data, ~w}]", "Madonna", 21, b); - send_term(a); - erl_free_term(b); - - send_term(erl_format("[{pi, ~f}, {'cos(70)', ~f}]", 3.1415, 0.34202)); - - a = erl_mk_float(3.1415); - b = erl_mk_float(0.34202); - send_term(erl_format("[[pi, ~w], ['cos(70)', ~w]]", a, b)); - erl_free_term(a); - erl_free_term(b); - - a = erl_mk_float(3.1415); - b = erl_mk_float(0.34202); - c = erl_mk_empty_list(); - send_term(erl_format("[[~a, ~w], ~w, [~s, ~w]]", "pi", a, c, "cos(70)", b)); - erl_free_term(a); - erl_free_term(b); - erl_free_term(c); - - send_term(erl_format("[~i]", -1)); - - report(1); -} 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 deleted file mode 100644 index 0f08727225..0000000000 --- a/lib/erl_interface/test/erl_global_SUITE_data/erl_global_test.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2000-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions 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/erl_match_SUITE.erl b/lib/erl_interface/test/erl_match_SUITE.erl deleted file mode 100644 index bb62d6288d..0000000000 --- a/lib/erl_interface/test/erl_match_SUITE.erl +++ /dev/null @@ -1,280 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2018. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - -%% --module(erl_match_SUITE). - --include_lib("common_test/include/ct.hrl"). --include("erl_match_SUITE_data/match_test_cases.hrl"). - --export([all/0, suite/0, - init_per_testcase/2, - atoms/1, lists/1, tuples/1, references/1, pids/1, ports/1, - bind/1, integers/1, floats/1, binaries/1, strings/1]). - -%% For interactive running of matcher. --export([start_matcher/1, erl_match/3]). - -%% This test suite tests the erl_match() function. - -suite() -> - [{ct_hooks,[ts_install_cth]}]. - -all() -> - [atoms, lists, tuples, references, pids, ports, bind, - integers, floats, binaries, strings]. - -init_per_testcase(Case, Config) -> - runner:init_per_testcase(?MODULE, Case, Config). - -atoms(Config) when is_list(Config) -> - P = start_matcher(Config), - - eq(P, '', ''), - eq(P, a, a), - ne(P, a, b), - ne(P, a, aa), - eq(P, kalle, kalle), - ne(P, kalle, arne), - - ne(P, kalle, 42), - ne(P, 42, kalle), - - runner:finish(P), - ok. - -lists(Config) when is_list(Config) -> - P = start_matcher(Config), - eq(P, [], []), - - ne(P, [], [a]), - ne(P, [a], []), - - eq(P, [a], [a]), - ne(P, [a], [b]), - - eq(P, [a|b], [a|b]), - ne(P, [a|b], [a|x]), - - eq(P, [a, b], [a, b]), - ne(P, [a, b], [a, x]), - - eq(P, [a, b, c], [a, b, c]), - ne(P, [a, b|c], [a, b|x]), - ne(P, [a, b, c], [a, b, x]), - ne(P, [a, b|c], [a, b|x]), - ne(P, [a, x|c], [a, b|c]), - ne(P, [a, b, c], [a, x, c]), - - runner:finish(P), - ok. - -tuples(Config) when is_list(Config) -> - P = start_matcher(Config), - - ne(P, {}, {a, b}), - ne(P, {a, b}, {}), - ne(P, {a}, {a, b}), - ne(P, {a, b}, {a}), - - eq(P, {}, {}), - - eq(P, {a}, {a}), - ne(P, {a}, {b}), - - eq(P, {1}, {1}), - ne(P, {1}, {2}), - - eq(P, {a, b}, {a, b}), - ne(P, {x, b}, {a, b}), - - ne(P, {error, x}, {error, y}), - ne(P, {error, {undefined, {subscriber, last}}}, - {error, {undefined, {subscriber, name}}}), - - runner:finish(P), - ok. - - -references(Config) when is_list(Config) -> - P = start_matcher(Config), - Ref1 = make_ref(), - Ref2 = make_ref(), - - eq(P, Ref1, Ref1), - eq(P, Ref2, Ref2), - ne(P, Ref1, Ref2), - ne(P, Ref2, Ref1), - - runner:finish(P), - ok. - - -pids(Config) when is_list(Config) -> - P = start_matcher(Config), - Pid1 = c:pid(0,1,2), - Pid2 = c:pid(0,1,3), - - eq(P, self(), self()), - eq(P, Pid1, Pid1), - ne(P, Pid1, self()), - ne(P, Pid2, Pid1), - - runner:finish(P), - ok. - - -ports(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {skipped,"not on vxworks, pucko"}; - _ -> - P = start_matcher(Config), - P2 = start_matcher(Config), - - eq(P, P, P), - ne(P, P, P2), - - runner:finish(P), - runner:finish(P2), - ok - end. - -integers(Config) when is_list(Config) -> - P = start_matcher(Config), - I1 = 123, - I2 = 12345, - I3 = -123, - I4 = 2234, - - eq(P, I1, I1), - eq(P, I2, I2), - ne(P, I1, I2), - ne(P, I1, I3), - eq(P, I4, I4), - - runner:finish(P), - ok. - - - -floats(Config) when is_list(Config) -> - P = start_matcher(Config), - F1 = 3.1414, - F2 = 3.1415, - F3 = 3.1416, - - S1 = "string", - S2 = "string2", - - eq(P, F1, F1), - eq(P, F2, F2), - ne(P, F1, F2), - ne(P, F3, F2), - - eq(P, S2, S2), - ne(P, S1, S2), - - runner:finish(P), - ok. - - - -binaries(Config) when is_list(Config) -> - P = start_matcher(Config), - Bin1 = term_to_binary({kalle, 146015, {kungsgatan, 23}}), - Bin2 = term_to_binary(sune), - Bin3 = list_to_binary("sune"), - - eq(P, Bin1, Bin1), - eq(P, Bin2, Bin2), - eq(P, Bin3, Bin3), - ne(P, Bin1, Bin2), - ne(P, Bin1, Bin3), - ne(P, Bin2, Bin3), - - runner:finish(P), - ok. - - -strings(Config) when is_list(Config) -> - P = start_matcher(Config), - - S1 = "string", - S2 = "streng", - S3 = "String", - - eq(P, S1, S1), - ne(P, S1, S2), - ne(P, S1, S3), - - runner:finish(P), - ok. - - -bind(Config) when is_list(Config) -> - P = start_bind(Config), - S = "[X,Y,Z]", - L1 = [301,302,302], - L2 = [65,66,67], - - bind_ok(P, S, L1), - bind_ok(P, S, L2), - - runner:finish(P), - ok. - -start_bind(Config) -> - runner:start(Config, ?erl_match_bind). - -bind_ok(Port, Bind, Term) -> - true = erl_bind(Port, Bind, Term). - -%bind_nok(Port, Bind, Term) -> -% false = erl_bind(Port, Bind, Term). - -erl_bind(Port, Pattern, Term) -> - Port ! {self(), {command, [$b, Pattern, 0]}}, - runner:send_term(Port, Term), - case runner:get_term(Port) of - {term, 0} -> false; - {term, 1} -> true - end. - - - -start_matcher(Config) -> - runner:start(Config, ?erl_match_server). - -eq(Port, Pattern, Term) -> - true = erl_match(Port, Pattern, Term). - -ne(Port, Pattern, Term) -> - false = erl_match(Port, Pattern, Term). - - - -erl_match(Port, Pattern, Term) -> - runner:send_term(Port, Pattern), - runner:send_term(Port, Term), - case runner:get_term(Port) of - {term, 0} -> false; - {term, 1} -> true - end. diff --git a/lib/erl_interface/test/erl_match_SUITE_data/Makefile.first b/lib/erl_interface/test/erl_match_SUITE_data/Makefile.first deleted file mode 100644 index 459b5c14c2..0000000000 --- a/lib/erl_interface/test/erl_match_SUITE_data/Makefile.first +++ /dev/null @@ -1,22 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 2000-2016. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -match_test_decl.c: match_test.c - erl -noinput -pa ../all_SUITE_data -s init_tc run match_test -s erlang halt diff --git a/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src b/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src deleted file mode 100644 index 156214a269..0000000000 --- a/lib/erl_interface/test/erl_match_SUITE_data/Makefile.src +++ /dev/null @@ -1,42 +0,0 @@ -# -# %CopyrightBegin% -# -# Copyright Ericsson AB 1997-2016. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# %CopyrightEnd% -# - -include @erl_interface_mk_include@ - -CC0 = @CC@ -CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" -LD = @LD@ -LIBERL = @erl_interface_lib@ -LIBEI = @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 -MATCH_OBJS = match_test@obj@ match_test_decl@obj@ - -all: match_test@exe@ - -clean: - $(RM) $(MATCH_OBJS) - $(RM) match_test@exe@ - -match_test@exe@: $(MATCH_OBJS) $(LIBERL) $(LIBEI) - $(LD) @CROSSLDFLAGS@ -o $@ $(MATCH_OBJS) $(LIBFLAGS) - diff --git a/lib/erl_interface/test/erl_match_SUITE_data/match_test.c b/lib/erl_interface/test/erl_match_SUITE_data/match_test.c deleted file mode 100644 index d577417f5b..0000000000 --- a/lib/erl_interface/test/erl_match_SUITE_data/match_test.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 1997-2016. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * %CopyrightEnd% - */ - -/* - * Purpose: Tests the erl_match() function. - * Author: Bjorn Gustavsson - */ - -#include "runner.h" - -TESTCASE(erl_match_server) -{ - erl_init(NULL, 0); - - for (;;) { - ETERM* pattern; - ETERM* term; - - pattern = get_term(); - if (pattern == NULL) { - report(1); - return; - } else { - term = get_term(); - if (term == NULL) { - fail("Unexpected EOF term"); - } else { - send_term(erl_mk_int(erl_match(pattern, term))); - erl_free_term(pattern); - erl_free_term(term); - } - } - } - -} - -TESTCASE(erl_match_bind) -{ - erl_init(NULL, 0); - - for (;;) { - char* pattern; - ETERM* term; - - pattern=read_packet(NULL); - - switch (pattern[0]) { - case 'e': - free(pattern); - report(1); - return; - - case 'b': - { - ETERM* patt_term; - - /* - * Get the pattern string and convert it using erl_format(). - * - * Note that the call to get_term() below destroys the buffer - * that the pattern variable points to. Therefore, it is - * essential to call erl_format() here, before - * calling get_term(). - */ - - message("Pattern: %s", pattern+1); - patt_term = erl_format(pattern+1); - free(pattern); - - if (patt_term == NULL) { - fail("erl_format() failed"); - } - - /* - * Get the term and send back the result of the erl_match() - * call. - */ - - term = get_term(); - if (term == NULL) { - fail("Unexpected eof term"); - } - else { - send_term(erl_mk_int(erl_match(patt_term, term))); - } - erl_free_term(patt_term); - erl_free_term(term); - } - break; - - default: - free(pattern); - fail("Illegal character received"); - } - - } -} diff --git a/lib/erl_interface/test/port_call_SUITE_data/Makefile.src b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src index 0f97ce9f70..0088c11a14 100644 --- a/lib/erl_interface/test/port_call_SUITE_data/Makefile.src +++ b/lib/erl_interface/test/port_call_SUITE_data/Makefile.src @@ -23,10 +23,9 @@ include @erl_interface_mk_include@ CC0 = @CC@ CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" LD = @LD@ -LIBERL = @erl_interface_lib_drv@ LIBEI = @erl_interface_eilib_drv@ -SHLIB_EXTRA_LDLIBS = $(LIBERL) $(LIBEI) @erl_interface_threadlib@ +SHLIB_EXTRA_LDLIBS = $(LIBEI) @erl_interface_threadlib@ SHLIB_EXTRA_CFLAGS = -I@erl_interface_include@ -I../all_SUITE_data diff --git a/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c b/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c index 4617cb0316..8f7303d645 100644 --- a/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c +++ b/lib/erl_interface/test/port_call_SUITE_data/port_call_drv.c @@ -21,7 +21,7 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> -#include "erl_interface.h" +#include "ei.h" #include "erl_driver.h" static ErlDrvPort my_erlang_port; |