diff options
Diffstat (limited to 'lib/erl_interface/src')
61 files changed, 731 insertions, 8097 deletions
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_connect.h b/lib/erl_interface/src/legacy/erl_connect.h deleted file mode 100644 index 6cb5d5cd1b..0000000000 --- a/lib/erl_interface/src/legacy/erl_connect.h +++ /dev/null @@ -1,25 +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_CONNECT_H -#define _ERL_CONNECT_H - -erlang_pid *erl_self(void); - -#endif /* _ERL_CONNECT_H */ 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_global.h b/lib/erl_interface/src/legacy/erl_global.h deleted file mode 100644 index d2eec08b35..0000000000 --- a/lib/erl_interface/src/legacy/erl_global.h +++ /dev/null @@ -1,28 +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_GLOBAL_H -#define _ERL_GLOBAL_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); - -#endif /* _ERL_GLOBAL_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" |