diff -r 3e934e62ea62 -r 34b57ba8b406 erts/configure.in
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -538,7 +538,15 @@ AC_CHECK_LIB(dl, dlopen)
 AC_CHECK_LIB(dl, dlopen)
 AC_CHECK_LIB(inet, main)
 AC_CHECK_LIB(util, openpty)
+
+# Remove ffi SKIP file from previous run
+/bin/rm -f $ERL_TOP/lib/ffi/SKIP
+
 AC_CHECK_LIB(ffi, ffi_prep_cif)
+
+if test "x$ac_cv_lib_ffi_ffi_prep_cif" != "xyes"; then
+    echo "No usable libffi found" > $ERL_TOP/lib/ffi/SKIP
+fi
 
 dnl Try to find a thread library.
 dnl
@@ -3001,6 +3009,6 @@ dnl
   ../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in
   ../lib/tools/c_src/$host/Makefile:../lib/tools/c_src/Makefile.in
   ../lib/asn1/c_src/$host/Makefile:../lib/asn1/c_src/Makefile.in
-  ../lib/kernel/include/$host/ffi_hardcodes.hrl:../lib/kernel/include/ffi_hardcodes.hrl.in
+  ../lib/ffi/include/$host/ffi_hardcodes.hrl:../lib/ffi/include/ffi_hardcodes.hrl.in
   )
 
diff -r 3e934e62ea62 -r 34b57ba8b406 erts/emulator/beam/erl_bif_ffi.c
--- a/erts/emulator/beam/erl_bif_ffi.c
+++ b/erts/emulator/beam/erl_bif_ffi.c
@@ -349,6 +349,7 @@ BIF_RETTYPE ffi_raw_call_2(BIF_ALIST_2)
         void* tmp_allocs[2*nargs_1]; /* Buffers allocated with ERTS_ALC_T_TMP */
         ErlDrvBinary* drv_allocs[nargs_1]; /* Driver bins that need free()d */
         byte buf[ERL_FFI_ARGS_BUF_SIZE]; /* Buffer for FFI arguments */
+	ErlDrvBinary** b;
 	void** p;
 
         /* Prepare the FFI function call... */
@@ -366,12 +367,12 @@ BIF_RETTYPE ffi_raw_call_2(BIF_ALIST_2)
 	for (p = tmp_allocs; *p != NULL; ++p) {
 	    erts_free(ERTS_ALC_T_TMP, *p);
 	}
-	for (p = (void**)drv_allocs; *p != NULL; ++p) {
+	for (b = drv_allocs; *b != NULL; ++b) {
 	    /* We have created the binary for the sake of the FFI
 	     * call, and we are now removing our own reference.  If
 	     * the called C function didn't increase the refcount, or
 	     * didn't return it, the binary will be freed */
-	    driver_free_binary((ErlDrvBinary*) *p);
+	    driver_free_binary(*b);
 	}
     }
 
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/Makefile
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -59,7 +59,7 @@ else
           $(SSL_APP) toolbar tv observer debugger odbc runtime_tools \
           cosTransactions cosEvent cosTime cosNotification cosProperty \
           cosFileTransfer cosEventDomain et megaco webtool syntax_tools \
-	  xmerl edoc ssh inviso typer docbuilder
+	  xmerl edoc ssh inviso typer docbuilder ffi
 # dialyzer
         OTHER_SUB_DIRECTORIES += hipe
       else # BUILD_ALL on unix
@@ -69,7 +69,7 @@ else
           pman $(SSL_APP) toolbar tv observer odbc \
           runtime_tools cosTransactions cosEvent cosTime cosNotification \
           cosProperty cosFileTransfer cosEventDomain et megaco webtool \
-	  syntax_tools xmerl edoc ssh inviso typer docbuilder
+	  syntax_tools xmerl edoc ssh inviso typer docbuilder ffi
 # dialyzer
         OTHER_SUB_DIRECTORIES += hipe $(TSP_APP)
       endif
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/AUTHORS
--- /dev/null
+++ b/lib/ffi/AUTHORS
@@ -0,0 +1,5 @@
+Original Authors:
+
+  Alceste Scalas <alceste@crs4.it>
+
+Contributors:
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/Makefile
--- /dev/null
+++ b/lib/ffi/Makefile
@@ -0,0 +1,38 @@
+# ``The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved via the world wide web at http://www.erlang.org/.
+# 
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+# 
+# The Initial Developer of the Original Code is  CRS4 - Center for
+# Advanced Studies, Research and Development in Sardinia
+# (http://www.crs4.it/). All Rights Reserved.''
+#
+# Copyright (C) 2007 by CRS4 - http://www.crs4.it/
+# Author: Alceste Scalas <alceste@crs4.it>
+#
+#     $Id$
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+
+SUB_DIRECTORIES = src
+
+include vsn.mk
+VSN = $(FFI_VSN)
+
+SPECIAL_TARGETS = 
+
+# ----------------------------------------------------
+# Default Subdir Targets
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_subdir.mk
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/ebin/dummy_file_needed_by_hg
--- /dev/null
+++ b/lib/ffi/ebin/dummy_file_needed_by_hg
@@ -0,0 +1,2 @@
+This file is here just to make Mercurial, diff and patch consider this
+empty directory.
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/include/ffi_hardcodes.hrl.in
--- /dev/null
+++ b/lib/ffi/include/ffi_hardcodes.hrl.in
@@ -0,0 +1,169 @@
+%% @configure_input@
+
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%% 
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%% 
+%% The Initial Developer of the Original Code is CRS4 - Center for
+%% Advanced Studies, Research and Development in Sardinia
+%% (http://www.crs4.it/). All Rights Reserved.''
+%% 
+%%     $Id$
+
+%% Foreign Function Interface (FFI) for Erlang/OTP
+%% Copyright (C) 2007 by CRS4 - http://www.crs4.it/
+%% Author: Alceste Scalas <alceste@crs4.it>
+
+-ifndef(__FFI_HARDCODES_HRL__).
+-define(__FFI_HARDCODES_HRL__, 1).
+
+%%
+%% Hardcoded type sizes for FFI types.  If you decide to use them, you
+%% may need to recompile your BEAM files in order to make them run on
+%% different platforms.
+%%
+-define(FFI_HARDCODED_SIZEOF_UCHAR, 1).
+-define(FFI_HARDCODED_UCHAR_BITS, 8).
+-define(FFI_HARDCODED_SIZEOF_SCHAR, 1).
+-define(FFI_HARDCODED_SCHAR_BITS, 8).
+
+-define(FFI_HARDCODED_SIZEOF_USHORT, @SIZEOF_UNSIGNED_SHORT@).
+-define(FFI_HARDCODED_USHORT_BITS, @UNSIGNED_SHORT_BITS@).
+-define(FFI_HARDCODED_SIZEOF_SSHORT, @SIZEOF_SHORT@).
+-define(FFI_HARDCODED_SSHORT_BITS, @SHORT_BITS@).
+
+-define(FFI_HARDCODED_SIZEOF_UINT, @SIZEOF_UNSIGNED_INT@).
+-define(FFI_HARDCODED_UINT_BITS, @UNSIGNED_INT_BITS@).
+-define(FFI_HARDCODED_SIZEOF_SINT, @SIZEOF_INT@).
+-define(FFI_HARDCODED_SINT_BITS, @INT_BITS@).
+
+-define(FFI_HARDCODED_SIZEOF_ULONG, @SIZEOF_UNSIGNED_LONG@).
+-define(FFI_HARDCODED_ULONG_BITS, @UNSIGNED_LONG_BITS@).
+-define(FFI_HARDCODED_SIZEOF_SLONG, @SIZEOF_LONG@).
+-define(FFI_HARDCODED_SLONG_BITS, @LONG_BITS@).
+
+-define(FFI_HARDCODED_SIZEOF_UINT8, 1).
+-define(FFI_HARDCODED_UINT8_BITS, 8).
+-define(FFI_HARDCODED_SIZEOF_SINT8, 1).
+-define(FFI_HARDCODED_SINT8_BITS, 8).
+
+-define(FFI_HARDCODED_SIZEOF_UINT16, 2).
+-define(FFI_HARDCODED_UINT16_BITS, 16).
+-define(FFI_HARDCODED_SIZEOF_SINT16, 2).
+-define(FFI_HARDCODED_SINT16_BITS, 16).
+
+-define(FFI_HARDCODED_SIZEOF_UINT32, 4).
+-define(FFI_HARDCODED_UINT32_BITS, 32).
+-define(FFI_HARDCODED_SIZEOF_SINT32, 4).
+-define(FFI_HARDCODED_SINT32_BITS, 32).
+
+-define(FFI_HARDCODED_SIZEOF_UINT64, 8).
+-define(FFI_HARDCODED_UINT64_BITS, 64).
+-define(FFI_HARDCODED_SIZEOF_SINT64, 8).
+-define(FFI_HARDCODED_SINT64_BITS, 64).
+
+-define(FFI_HARDCODED_SIZEOF_FLOAT, @SIZEOF_FLOAT@).
+-define(FFI_HARDCODED_FLOAT_BITS, @FLOAT_BITS@).
+-define(FFI_HARDCODED_SIZEOF_DOUBLE, @SIZEOF_DOUBLE@).
+-define(FFI_HARDCODED_DOUBLE_BITS, @DOUBLE_BITS@).
+-define(FFI_HARDCODED_SIZEOF_LONG_DOUBLE, @SIZEOF_LONG_DOUBLE@).
+-define(FFI_HARDCODED_LONG_DOUBLE_BITS, @LONG_DOUBLE_BITS@).
+
+-define(FFI_HARDCODED_SIZEOF_POINTER, @SIZEOF_VOID_P@).
+-define(FFI_HARDCODED_POINTER_BITS, @VOID_P_BITS@).
+-define(FFI_HARDCODED_SIZEOF_CSTRING, @SIZEOF_VOID_P@).
+-define(FFI_HARDCODED_CSTRING_BITS, @VOID_P_BITS@).
+-define(FFI_HARDCODED_SIZEOF_NONNULL, @SIZEOF_VOID_P@).
+-define(FFI_HARDCODED_NONNULL_BITS, @VOID_P_BITS@).
+
+-define(FFI_HARDCODED_SIZEOF_SIZE_T, @SIZEOF_SIZE_T@).
+-define(FFI_HARDCODED_SIZE_T_BITS, @SIZE_T_BITS@).
+-define(FFI_HARDCODED_SIZEOF_SSIZE_T, @SIZEOF_SSIZE_T@).
+-define(FFI_HARDCODED_SSIZE_T_BITS, @SSIZE_T_BITS@).
+
+-define(FFI_HARDCODED_SIZEOF_OFF_T, @SIZEOF_OFF_T@).
+-define(FFI_HARDCODED_OFF_T_BITS, @OFF_T_BITS@).
+
+-define(FFI_HARDCODED_SIZEOF_PID_T, @SIZEOF_PID_T@).
+-define(FFI_HARDCODED_PID_T_BITS, @PID_T_BITS@).
+
+%%
+%% Hardcoded bit syntax macros for FFI types.  If you decide to use
+%% them, you may need to recompile your BEAM files in order to make
+%% them run on different platforms.
+%%
+-define(FFI_HARDCODED_UCHAR,
+        ?FFI_HARDCODED_UCHAR_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_SCHAR,
+        ?FFI_HARDCODED_SCHAR_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_USHORT,
+        ?FFI_HARDCODED_USHORT_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_SSHORT,
+        ?FFI_HARDCODED_SSHORT_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_UINT,
+        ?FFI_HARDCODED_UINT_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_SINT,
+        ?FFI_HARDCODED_SINT_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_ULONG,
+        ?FFI_HARDCODED_ULONG_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_SLONG,
+        ?FFI_HARDCODED_SLONG_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_UINT8,
+        ?FFI_HARDCODED_UINT8_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_SINT8,
+        ?FFI_HARDCODED_SINT8_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_UINT16,
+        ?FFI_HARDCODED_UINT16_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_SINT16,
+        ?FFI_HARDCODED_SINT16_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_UINT32,
+        ?FFI_HARDCODED_UINT32_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_SINT32,
+        ?FFI_HARDCODED_SINT32_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_UINT64,
+        ?FFI_HARDCODED_UINT64_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_SINT64,
+        ?FFI_HARDCODED_SINT64_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_FLOAT,
+        ?FFI_HARDCODED_FLOAT_BITS/native-float).
+-define(FFI_HARDCODED_DOUBLE,
+        ?FFI_HARDCODED_DOUBLE_BITS/native-float).
+
+%% Sorry, no long double support
+%%-define(FFI_HARDCODED_LONG_DOUBLE,     
+%%        ?FFI_HARDCODED_LONG_DOUBLE_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_POINTER,
+        ?FFI_HARDCODED_POINTER_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_CSTRING,
+        ?FFI_HARDCODED_CSTRING_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_NONNULL,
+        ?FFI_HARDCODED_NONNULL_BITS/native-unsigned-integer).
+
+-define(FFI_HARDCODED_SIZE_T,
+        ?FFI_HARDCODED_SIZE_T_BITS/native-unsigned-integer).
+-define(FFI_HARDCODED_SSIZE_T,
+        ?FFI_HARDCODED_SSIZE_T_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_OFF_T,
+        ?FFI_HARDCODED_OFF_T_BITS/native-signed-integer).
+
+-define(FFI_HARDCODED_PID_T,
+        ?FFI_HARDCODED_PID_T_BITS/native-signed-integer).
+
+-endif. % __FFI_HARDCODES_HRL__
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/info
--- /dev/null
+++ b/lib/ffi/info
@@ -0,0 +1,2 @@
+group: basic
+short: Foreign Function Interface (FFI)
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/src/Makefile
--- /dev/null
+++ b/lib/ffi/src/Makefile
@@ -0,0 +1,158 @@
+# ``The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved via the world wide web at http://www.erlang.org/.
+# 
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+# 
+# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+# AB. All Rights Reserved.''
+# 
+#     $Id$
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(FFI_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/ffi-$(VSN)
+
+# ----------------------------------------------------
+# Documentation directory specification
+# ----------------------------------------------------
+
+DOCDIR = ../doc
+
+
+### FFI uses EDOC for documentation, to regenerate update paths as needed!
+FFI_APP = ..
+
+EDOC_APP = ../../edoc
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+EDOC_MODULES = ffi
+
+MODULES = $(EDOC_MODULES)
+
+HRL_FILES = ../include/$(TARGET)/ffi_hardcodes.hrl
+INCLUDE_DIR = ../include
+
+INTERNAL_HRL_FILES  = 
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+APP_FILE= ffi.app
+APP_SRC= $(APP_FILE).src
+APP_TARGET= $(EBIN)/$(APP_FILE)
+
+APPUP_FILE= ffi.appup
+APPUP_SRC= $(APPUP_FILE).src
+APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+
+DOC_TARGET_FILES = $(EDOC_MODULES:%=$(DOCDIR)/%.html)
+TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += \
+		-I ../include \
+		+warn_unused_vars \
+		-I../include/$(TARGET) \
+		-DERL_BUILD_TARGET="\"$(TARGET)\""
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+debug opt: $(TARGET_FILES) 
+
+docs:
+#docs:	$(DOC_TARGET_FILES)
+
+
+clean:
+	$(RM) $(TARGET_FILES)
+	$(RM) core *~
+
+info:
+	@echo "MODULES: $(MODULES)"
+	@echo "EBIN: $(EBIN)"
+	@echo "EMULATOR: $(EMULATOR)"
+	@echo "APP_TARGET: $(APP_TARGET)"
+	@echo "TARGET_FILES: $(TARGET_FILES)"
+	@echo "DOC_TARGET_FILES: $(DOC_TARGET_FILES)"
+	@echo "DOCDIR/%html: $(DOCDIR)/%.html"
+
+realclean: clean
+	$(RM) $(DOC_TARGET_FILES)
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+EDOC_PATHS = \
+	-pa $(EDOC_APP)/ebin -pa $(FFI_APP)/ebin
+
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
+	sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+	sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(EBIN)/%.beam:	%.erl
+	$(ERLC)  $(ERL_COMPILE_FLAGS) -o $(EBIN) $<
+
+$(DOCDIR)/%.html:	%.erl
+	$(ERL) -noshell $(EDOC_PATHS) \
+		-run edoc_run file '"$<"' '[{dir,"$(DOCDIR)"}]' -s erlang halt
+
+
+#$(DOCDIR)/%.html:	%.erl
+#	$(ERL) $(EDOC_PATHS) -s edoc file $< ['{dir,"$(DOCDIR)"}'] 
+
+# ----------------------------------------------------
+# Release Target
+# ---------------------------------------------------- 
+#ifeq "${MA_TOP}" ""
+#MA_TOP = ../../..
+#endif
+#include $(MA_TOP)/config/make.release
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_src:
+	$(INSTALL_DATA) $(MODULES:%=%.erl) $(RELSYSDIR)/src
+	$(INSTALL_DATA) Makefile $(RELSYSDIR)/src
+	$(INSTALL_DATA) $(APP_SRC) $(APPUP_SRC) $(RELSYSDIR)/src
+
+
+release_spec: opt
+	$(INSTALL_DIR) $(RELSYSDIR)/ebin
+	$(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+	$(INSTALL_DIR) $(RELSYSDIR)/src
+	$(INSTALL_DATA) $(ERL_FILES) $(APP_SRC) $(APPUP_SRC) $(RELSYSDIR)/src
+	$(INSTALL_DIR) $(RELSYSDIR)/include
+	$(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
+
+release_docs_spec:
+
+
+
+#------------------------------------------------------------
+# .hrl dependencies
+$(EBIN)/ffi.beam:../include/$(TARGET)/ffi_hardcodes.hrl
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/src/ffi.app.src
--- /dev/null
+++ b/lib/ffi/src/ffi.app.src
@@ -0,0 +1,8 @@
+{application, ffi,
+ [{description, "Foreign Function Interface"},
+  {vsn, "%VSN%"},
+  {modules, [ffi]},
+  {registered, []},
+  {env, []},
+  {applications, [kernel, stdlib]}
+  ]}.
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/src/ffi.appup.src
--- /dev/null
+++ b/lib/ffi/src/ffi.appup.src
@@ -0,0 +1,14 @@
+{"%VSN%",
+ [
+  {"0.0.0.0",
+    [
+     ]
+  }
+ ],
+ [
+  {"0.0.0.0",
+    [
+     ]
+  }
+ ]
+}.
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/src/ffi.erl
--- /dev/null
+++ b/lib/ffi/src/ffi.erl
@@ -0,0 +1,436 @@
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%% 
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%% 
+%% The Initial Developer of the Original Code is  CRS4 - Center for
+%% Advanced Studies, Research and Development in Sardinia
+%% (http://www.crs4.it/). All Rights Reserved.''
+%%
+%% Copyright (C) 2007 by CRS4 - http://www.crs4.it/
+%% Author: Alceste Scalas <alceste@crs4.it>
+%%
+%%     $Id$
+
+%% @doc Methods for calling native C functions from Erlang code, and
+%% handling their return values.
+%%
+%% @type type_tag() = atom().  Valid FFI type atom.
+%%
+%% @type tagged_value() = tuple(type_tag(), term()).  Type-tagged value
+%%                                                    used for FFI calls.
+%%
+%% @type c_func_name() = atom() | string().  Name of a C function.
+%%
+%% @type func_index() = integer().  Function position on the list of preloads
+%%                                  given to erl_ddll:load_library/3.
+%%
+%% @type tagged_func_name() = tuple(type_tag(), c_func_name()).  C function
+%%                                                               name with
+%%                                                               return type.
+%%
+%% @type tagged_func_index() = tuple(type_tag(), func_index()).  C function
+%%                                                               index with
+%%                                                               return type.
+-module(ffi).
+-author("Alceste Scalas <alceste@crs4.it>").
+-export([call/3,
+	 buffer_to_binary/2, cstring_to_binary/1,
+	 sizeof/1, min/1, max/1,
+	 check/1]).
+
+-ifdef(ERL_BUILD_TARGET).
+%% We are being built, so the current include path allows this -include().
+-include("ffi_hardcodes.hrl").
+-else.
+-include_lib("ffi/include/ffi_hardcodes.hrl").
+-endif.
+
+%% @spec call(Port::port(), CFunc::cfunction(),
+%%            Args::[tagged_value()]) -> Ret::tagged_value()
+%%       cfunction() = func_name() | func_index()
+%%                     | tagged_func_name() | tagged_func_index()
+%%
+%% @doc Call the C function <code>CFunc</code> with the given list of
+%% arguments, using the port <code>Port</code>.  If the function was
+%% preloaded with ffi:load_library/3, all the type tags will be
+%% matched against the preloaded signature before performing the call.
+%%
+%% Return the return value of the C function, with the proper type tag.
+%%
+%% <strong>Note:</strong> if <code>CFunc</code> is not of type {@link
+%% tagged_func_name()}, the C function will be called if and only if
+%% it was preloaded with erl_ddll:load_library/3 (it is required in
+%% order to determine its return type).
+call(Port, {RetTypeTag, CFunc}, Args) when is_integer(CFunc) ->
+    %% Called with type tag + function index
+    {name, Lib} = .erlang:port_info(Port, name),
+    Preloads = [P || P <- .erl_ddll:info(Lib, preloads),
+		    .proplists:get_value(index, P) =:= CFunc],
+    case Preloads of
+	[P] ->
+	    do_preloaded_call(Port, RetTypeTag, P, Args);
+	[] ->
+	    %% Function index was out of range
+	    .erlang:error(badarg);
+	_ ->
+	    %% This should never happen (Preloads contains more than
+	    %% one element with the same index?!?)
+	    .erlang:error({bug, {duplicated_preloads, Preloads}})
+    end;
+call(Port, {RetTypeTag, CFunc}, Args) when is_list(CFunc) ->
+    %% Called with type tag + function name as string
+    {name, Lib} = .erlang:port_info(Port, name),
+    Preloads = [P || P <- .erl_ddll:info(Lib, preloads),
+		     .proplists:get_value(name, P) =:= CFunc],
+    case Preloads of
+	[] ->
+	    %% The function was not preloaded, but we have enough
+	    %% information to do a function call
+	    do_call(Port, RetTypeTag, CFunc, Args);
+	_ ->
+	    %% We support multiple matches on function names, because
+	    %% they could be used to preload different calls to C
+	    %% vararg functions (at least on some platforms).
+	    try_preloaded_calls(Port, RetTypeTag, Preloads, Args)
+    end;
+call(Port, {RetTypeTag, CFunc}, Args) when is_atom(CFunc) ->
+    %% Called with type tag + function name as atom
+    call(Port, {RetTypeTag, atom_to_list(CFunc)}, Args);
+call(Port, CFunc, Args) when is_integer(CFunc) ->
+    %% Called with function index alone
+    {name, Lib} = .erlang:port_info(Port, name),
+    Preloads = [P || P <- .erl_ddll:info(Lib, preloads),
+		     .proplists:get_value(index, P) =:= CFunc],
+    case Preloads of
+	[P] ->
+	    RetTypeTag = element(1, .proplists:get_value(signature, P)),
+	    do_preloaded_call(Port, RetTypeTag, P, Args);
+	[] ->
+	    %% Function index was out of range
+	    .erlang:error(badarg);
+	_ ->
+	    %% This should never happen (Preloads contains more than
+	    %% one element with the same index?!?)
+	    .erlang:error({bug, {duplicated_preloads, Preloads}})
+    end;
+call(Port, CFunc, Args) when is_list(CFunc) ->
+    %% Called with function name alone as string
+    {name, Lib} = .erlang:port_info(Port, name),
+    Preloads = [P || P <- .erl_ddll:info(Lib, preloads),
+		     .proplists:get_value(name, P) =:= CFunc],
+    case Preloads of
+	[] ->
+	    %% The function was not preloaded, so we miss the
+	    %% type_tag() for building the return value: let's fail
+	    .erlang:error(badarg);
+	_ ->
+	    %% We support multiple matches on function names, because they
+	    %% could be used to preload different calls to C vararg functions
+	    %% (at least on some platforms).
+	    try_preloaded_calls(Port, Preloads, Args)
+    end;
+call(Port, CFunc, Args) when is_atom(CFunc) ->
+    %% Called with function name alone as atom
+    call(Port, atom_to_list(CFunc), Args).
+
+%% Try to perform FFI calls from a list of preloaded function, until
+%% one matches the given arguments and return types
+try_preloaded_calls(Port, RetTypeTag, [Preload], Args) ->
+    %% Laast element on the preloads list: call it and see what
+    %% happens
+    do_preloaded_call(Port, RetTypeTag, Preload, Args);
+try_preloaded_calls(Port, RetTypeTag, [Preload | Rest], Args) ->
+    try
+	do_preloaded_call(Port, RetTypeTag, Preload, Args)
+    catch
+	error:{badmatch, _} ->
+	    %% The preload signature was wrong, let's try with the
+	    %% next one
+	    try_preloaded_calls(Port, Rest, Args)
+    end.
+
+%% Try to perform FFI calls from a list of preloaded function, until
+%% one matches the given arguments types (the return type is taken
+%% from the preload itself)
+try_preloaded_calls(Port, [Preload], Args) ->
+    %% Laast element on the preloads list: call it and see what
+    %% happens
+    RetTypeTag = element(1, .proplists:get_value(signature, Preload)),
+    do_preloaded_call(Port, RetTypeTag, Preload, Args);
+try_preloaded_calls(Port, [Preload | Rest], Args) ->
+    RetTypeTag = element(1, .proplists:get_value(signature, Preload)),
+    try
+	do_preloaded_call(Port, RetTypeTag, Preload, Args)
+    catch
+	error:{badmatch, _} ->
+	    %% The preload signature was wrong, let's try with the
+	    %% next one
+	    try_preloaded_calls(Port, Rest, Args)
+    end.
+
+%% Perform a FFI call using the given preload information.  Match the
+%% preloaded function signature with RetTypeTag and arguments type tags.
+do_preloaded_call(Port, RetTypeTag, Preload, Args) ->
+    check_arguments(Args),
+    
+    %% Build and match function signature
+    Sig = list_to_tuple([RetTypeTag] ++ [element(1, Arg) || Arg <- Args]),
+    Sig = .proplists:get_value(signature, Preload),
+    
+    %% If we are here, the signatures did match
+    RawArgs = [element(2, Arg) || Arg <- Args],
+
+    RetVal = .ffi:raw_call(Port,
+			   list_to_tuple([.proplists:get_value(index,
+							       Preload)]
+					 ++ RawArgs)),
+    {RetTypeTag, RetVal}.
+
+%% Perform a FFI call (without preload info).
+do_call(Port, RetTypeTag, CFunc, Args) ->
+    check_arguments(Args),
+    
+    %% Build and match function signature
+    Sig = list_to_tuple([RetTypeTag] ++ [element(1, Arg) || Arg <- Args]),
+    RawArgs = [element(2, Arg) || Arg <- Args],
+
+    RetVal = .ffi:raw_call(Port, list_to_tuple([CFunc] ++ RawArgs), Sig),
+    {RetTypeTag, RetVal}.
+
+%% Raise an exception if any element in the arguments list is not a
+%% valid type-tagged value
+check_arguments(Args) ->
+    Check = .lists:all(fun check/1, Args),
+    if
+	Check ->
+	    ok;
+	true ->
+	    .erlang:error(badarg)
+    end.
+
+%% @spec buffer_to_binary(TaggedNonnull:nonnull(), Size) -> binary()
+%%       nonnull() = tuple(nonnull, integer())
+%%
+%% @doc Create a binary with a copy of <code>Size</code> bytes taken
+%% from the given C buffer (a type-tagged C non-null pointer).
+%%
+%% Return the new binary.
+buffer_to_binary({nonnull, Ptr}, Size) ->
+    IsValid = check({nonnull, Ptr}),
+    if
+	IsValid ->
+	    .ffi:raw_buffer_to_binary(Ptr, Size);
+	true ->
+	    .erlang:error(badarg)
+    end.
+
+%% @spec cstring_to_binary(TaggedCString::cstring()) -> binary()
+%%       cstring() = tuple(cstring, integer())
+%%
+%% @doc Create a binary with a copy of the given C string (a
+%% type-tagged C non-null pointer).  The binary will include the trailing '\0'
+%% character.
+%%
+%% Return the new binary.
+cstring_to_binary({cstring, Ptr}) ->
+    IsValid = check({cstring, Ptr}),
+    if
+	IsValid ->
+	    .ffi:raw_cstring_to_binary(Ptr);
+	true ->
+	    .erlang:error(badarg)
+    end.
+
+%% @spec sizeof(TypeTag::type_tag()) -> integer()
+%%
+%% @doc Return the size of the given FFI type tag, on the current system.
+sizeof(uchar) ->
+    ?FFI_HARDCODED_SIZEOF_UCHAR;
+sizeof(schar) ->
+    ?FFI_HARDCODED_SIZEOF_SCHAR;
+sizeof(ushort) ->
+    ?FFI_HARDCODED_SIZEOF_USHORT;
+sizeof(sshort) ->
+    ?FFI_HARDCODED_SIZEOF_SSHORT;
+sizeof(uint) ->
+    ?FFI_HARDCODED_SIZEOF_UINT;
+sizeof(sint) ->
+    ?FFI_HARDCODED_SIZEOF_SINT;
+sizeof(ulong) ->
+    ?FFI_HARDCODED_SIZEOF_ULONG;
+sizeof(slong) ->
+    ?FFI_HARDCODED_SIZEOF_SLONG;
+sizeof(uint8) ->
+    ?FFI_HARDCODED_SIZEOF_UINT8;
+sizeof(sint8) ->
+    ?FFI_HARDCODED_SIZEOF_SINT8;
+sizeof(uint16) ->
+    ?FFI_HARDCODED_SIZEOF_UINT16;
+sizeof(sint16) ->
+    ?FFI_HARDCODED_SIZEOF_SINT16;
+sizeof(uint32) ->
+    ?FFI_HARDCODED_SIZEOF_UINT32;
+sizeof(sint32) ->
+    ?FFI_HARDCODED_SIZEOF_SINT32;
+sizeof(uint64) ->
+    ?FFI_HARDCODED_SIZEOF_UINT64;
+sizeof(sint64) ->
+    ?FFI_HARDCODED_SIZEOF_SINT64;
+sizeof(float) ->
+    ?FFI_HARDCODED_SIZEOF_FLOAT;
+sizeof(double) ->
+    ?FFI_HARDCODED_SIZEOF_DOUBLE;
+sizeof(longdouble) ->
+    ?FFI_HARDCODED_SIZEOF_LONG_DOUBLE;
+sizeof(pointer) ->
+    ?FFI_HARDCODED_SIZEOF_POINTER;
+sizeof(cstring) ->
+    ?FFI_HARDCODED_SIZEOF_POINTER;
+sizeof(nonnull) ->
+    ?FFI_HARDCODED_SIZEOF_POINTER;
+sizeof(size_t) ->
+    ?FFI_HARDCODED_SIZEOF_SIZE_T;
+sizeof(ssize_t) ->
+    ?FFI_HARDCODED_SIZEOF_SSIZE_T;
+sizeof(off_t) ->
+    ?FFI_HARDCODED_SIZEOF_OFF_T;
+sizeof(pid_t) ->
+    ?FFI_HARDCODED_SIZEOF_PID_T.
+
+%% @spec min(TypeTag::type_tag()) -> integer()
+%%
+%% @doc Return the minimum <em>integer</em> value allowed by the given
+%% FFI type.
+%%
+%% <strong>Note:</strong> only integer-based tagged values are
+%% supported (including C pointers).  Floating point values, in
+%% particular, are not supported.
+min(uchar) ->
+    0;
+min(schar) ->
+    -(1 bsl (?FFI_HARDCODED_SCHAR_BITS - 1));
+min(ushort) ->
+    0;
+min(sshort) ->
+    -(1 bsl (?FFI_HARDCODED_SSHORT_BITS - 1));
+min(uint) ->
+    0;
+min(sint) ->
+    -(1 bsl (?FFI_HARDCODED_SINT_BITS - 1));
+min(ulong) ->
+    0;
+min(slong) ->
+    -(1 bsl (?FFI_HARDCODED_SLONG_BITS - 1));
+min(uint8) ->
+    0;
+min(sint8) ->
+    -(1 bsl (?FFI_HARDCODED_SINT8_BITS - 1));
+min(uint16) ->
+    0;
+min(sint16) ->
+    -(1 bsl (?FFI_HARDCODED_SINT16_BITS - 1));
+min(uint32) ->
+    0;
+min(sint32) ->
+    -(1 bsl (?FFI_HARDCODED_SINT32_BITS - 1));
+min(uint64) ->
+    0;
+min(sint64) ->
+    -(1 bsl (?FFI_HARDCODED_SINT64_BITS - 1));
+min(pointer) ->
+    0;
+min(cstring) ->
+    1; % Cannot be NULL
+min(nonnull) ->
+    1; % Cannot be NULL
+min(size_t) ->
+    0;
+min(ssize_t) ->
+    -(1 bsl (?FFI_HARDCODED_SSIZE_T_BITS - 1));
+min(off_t) ->
+    -(1 bsl (?FFI_HARDCODED_OFF_T_BITS - 1));
+min(pid_t) ->
+    -(1 bsl (?FFI_HARDCODED_PID_T_BITS - 1)).
+
+%% @spec max(TypeTag::type_tag()) -> integer()
+%%
+%% @doc Return the maximum value allowed by the given
+%% <em>integer-based</em> FFI type.
+%%
+%% <strong>Note:</strong> only integer-based tagged values are
+%% supported (including C pointers).  Floating point values, in
+%% particular, are not supported.
+max(uchar) ->
+    (1 bsl ?FFI_HARDCODED_UCHAR_BITS) - 1;
+max(schar) ->
+    (1 bsl (?FFI_HARDCODED_SCHAR_BITS - 1)) - 1;
+max(ushort) ->
+    (1 bsl ?FFI_HARDCODED_USHORT_BITS) - 1;
+max(sshort) ->
+    (1 bsl (?FFI_HARDCODED_SSHORT_BITS - 1)) - 1;
+max(uint) ->
+    (1 bsl ?FFI_HARDCODED_UINT_BITS) - 1;
+max(sint) ->
+    (1 bsl (?FFI_HARDCODED_SINT_BITS - 1)) - 1;
+max(ulong) ->
+    (1 bsl ?FFI_HARDCODED_ULONG_BITS) - 1;
+max(slong) ->
+    (1 bsl (?FFI_HARDCODED_SLONG_BITS - 1)) - 1;
+max(uint8) ->
+    (1 bsl ?FFI_HARDCODED_UINT8_BITS) - 1;
+max(sint8) ->
+    (1 bsl (?FFI_HARDCODED_SINT8_BITS - 1)) - 1;
+max(uint16) ->
+    (1 bsl ?FFI_HARDCODED_UINT16_BITS) - 1;
+max(sint16) ->
+    (1 bsl (?FFI_HARDCODED_SINT16_BITS - 1)) - 1;
+max(uint32) ->
+    (1 bsl ?FFI_HARDCODED_UINT32_BITS) - 1;
+max(sint32) ->
+    (1 bsl (?FFI_HARDCODED_SINT32_BITS - 1)) - 1;
+max(uint64) ->
+    (1 bsl ?FFI_HARDCODED_UINT64_BITS) - 1;
+max(sint64) ->
+    (1 bsl (?FFI_HARDCODED_SINT64_BITS - 1)) - 1;
+max(pointer) ->
+    (1 bsl ?FFI_HARDCODED_POINTER_BITS) - 1;
+max(cstring) ->
+    (1 bsl ?FFI_HARDCODED_CSTRING_BITS) - 1;
+max(nonnull) ->
+    (1 bsl ?FFI_HARDCODED_NONNULL_BITS) - 1;
+max(size_t) ->
+    (1 bsl ?FFI_HARDCODED_SIZE_T_BITS) - 1;
+max(ssize_t) ->
+    (1 bsl (?FFI_HARDCODED_SSIZE_T_BITS - 1)) - 1;
+max(off_t) ->
+    (1 bsl (?FFI_HARDCODED_OFF_T_BITS - 1)) - 1;
+max(pid_t) ->
+    (1 bsl (?FFI_HARDCODED_PID_T_BITS - 1)) - 1.
+
+%% @spec check(TaggedValue::tagged_value()) -> true | false
+%%
+%% @doc Check that the given type-tagged value is valid.
+%%
+%% This function performs range and type checking.
+%%
+%% <strong>Note:</strong> only integer-based tagged values are
+%% completely supported (including C pointers).  Checks on floating
+%% point values will always return <code>true</code> (unless the
+%% tagged value is malformed).
+check({void, void}) ->
+    true;
+check({TypeTag, Value}) when ((TypeTag == float) or (TypeTag == double)
+			      or (TypeTag == longdouble))
+			     and is_float(Value) ->
+    true;
+check({TypeTag, Value}) when is_atom(TypeTag) and is_integer(Value) ->
+    (Value =< max(TypeTag)) and (Value >= min(TypeTag));
+check(_) ->
+    false.
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/ffi/vsn.mk
--- /dev/null
+++ b/lib/ffi/vsn.mk
@@ -0,0 +1,1 @@
+FFI_VSN = 0.0.0.1
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/kernel/include/ffi_hardcodes.hrl.in
--- a/lib/kernel/include/ffi_hardcodes.hrl.in
+++ /dev/null
@@ -1,169 +0,0 @@
-%% @configure_input@
-
-%% ``The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved via the world wide web at http://www.erlang.org/.
-%% 
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%% 
-%% The Initial Developer of the Original Code is CRS4 - Center for
-%% Advanced Studies, Research and Development in Sardinia
-%% (http://www.crs4.it/). All Rights Reserved.''
-%% 
-%%     $Id$
-
-%% Foreign Function Interface (FFI) for Erlang/OTP
-%% Copyright (C) 2007 by CRS4 - http://www.crs4.it/
-%% Author: Alceste Scalas <alceste@crs4.it>
-
--ifndef(__FFI_HARDCODES_HRL__).
--define(__FFI_HARDCODES_HRL__, 1).
-
-%%
-%% Hardcoded type sizes for FFI types.  If you decide to use them, you
-%% may need to recompile your BEAM files in order to make them run on
-%% different platforms.
-%%
--define(FFI_HARDCODED_SIZEOF_UCHAR, 1).
--define(FFI_HARDCODED_UCHAR_BITS, 8).
--define(FFI_HARDCODED_SIZEOF_SCHAR, 1).
--define(FFI_HARDCODED_SCHAR_BITS, 8).
-
--define(FFI_HARDCODED_SIZEOF_USHORT, @SIZEOF_UNSIGNED_SHORT@).
--define(FFI_HARDCODED_USHORT_BITS, @UNSIGNED_SHORT_BITS@).
--define(FFI_HARDCODED_SIZEOF_SSHORT, @SIZEOF_SHORT@).
--define(FFI_HARDCODED_SSHORT_BITS, @SHORT_BITS@).
-
--define(FFI_HARDCODED_SIZEOF_UINT, @SIZEOF_UNSIGNED_INT@).
--define(FFI_HARDCODED_UINT_BITS, @UNSIGNED_INT_BITS@).
--define(FFI_HARDCODED_SIZEOF_SINT, @SIZEOF_INT@).
--define(FFI_HARDCODED_SINT_BITS, @INT_BITS@).
-
--define(FFI_HARDCODED_SIZEOF_ULONG, @SIZEOF_UNSIGNED_LONG@).
--define(FFI_HARDCODED_ULONG_BITS, @UNSIGNED_LONG_BITS@).
--define(FFI_HARDCODED_SIZEOF_SLONG, @SIZEOF_LONG@).
--define(FFI_HARDCODED_SLONG_BITS, @LONG_BITS@).
-
--define(FFI_HARDCODED_SIZEOF_UINT8, 1).
--define(FFI_HARDCODED_UINT8_BITS, 8).
--define(FFI_HARDCODED_SIZEOF_SINT8, 1).
--define(FFI_HARDCODED_SINT8_BITS, 8).
-
--define(FFI_HARDCODED_SIZEOF_UINT16, 2).
--define(FFI_HARDCODED_UINT16_BITS, 16).
--define(FFI_HARDCODED_SIZEOF_SINT16, 2).
--define(FFI_HARDCODED_SINT16_BITS, 16).
-
--define(FFI_HARDCODED_SIZEOF_UINT32, 4).
--define(FFI_HARDCODED_UINT32_BITS, 32).
--define(FFI_HARDCODED_SIZEOF_SINT32, 4).
--define(FFI_HARDCODED_SINT32_BITS, 32).
-
--define(FFI_HARDCODED_SIZEOF_UINT64, 8).
--define(FFI_HARDCODED_UINT64_BITS, 64).
--define(FFI_HARDCODED_SIZEOF_SINT64, 8).
--define(FFI_HARDCODED_SINT64_BITS, 64).
-
--define(FFI_HARDCODED_SIZEOF_FLOAT, @SIZEOF_FLOAT@).
--define(FFI_HARDCODED_FLOAT_BITS, @FLOAT_BITS@).
--define(FFI_HARDCODED_SIZEOF_DOUBLE, @SIZEOF_DOUBLE@).
--define(FFI_HARDCODED_DOUBLE_BITS, @DOUBLE_BITS@).
--define(FFI_HARDCODED_SIZEOF_LONG_DOUBLE, @SIZEOF_LONG_DOUBLE@).
--define(FFI_HARDCODED_LONG_DOUBLE_BITS, @LONG_DOUBLE_BITS@).
-
--define(FFI_HARDCODED_SIZEOF_POINTER, @SIZEOF_VOID_P@).
--define(FFI_HARDCODED_POINTER_BITS, @VOID_P_BITS@).
--define(FFI_HARDCODED_SIZEOF_CSTRING, @SIZEOF_VOID_P@).
--define(FFI_HARDCODED_CSTRING_BITS, @VOID_P_BITS@).
--define(FFI_HARDCODED_SIZEOF_NONNULL, @SIZEOF_VOID_P@).
--define(FFI_HARDCODED_NONNULL_BITS, @VOID_P_BITS@).
-
--define(FFI_HARDCODED_SIZEOF_SIZE_T, @SIZEOF_SIZE_T@).
--define(FFI_HARDCODED_SIZE_T_BITS, @SIZE_T_BITS@).
--define(FFI_HARDCODED_SIZEOF_SSIZE_T, @SIZEOF_SSIZE_T@).
--define(FFI_HARDCODED_SSIZE_T_BITS, @SSIZE_T_BITS@).
-
--define(FFI_HARDCODED_SIZEOF_OFF_T, @SIZEOF_OFF_T@).
--define(FFI_HARDCODED_OFF_T_BITS, @OFF_T_BITS@).
-
--define(FFI_HARDCODED_SIZEOF_PID_T, @SIZEOF_PID_T@).
--define(FFI_HARDCODED_PID_T_BITS, @PID_T_BITS@).
-
-%%
-%% Hardcoded bit syntax macros for FFI types.  If you decide to use
-%% them, you may need to recompile your BEAM files in order to make
-%% them run on different platforms.
-%%
--define(FFI_HARDCODED_UCHAR,
-        ?FFI_HARDCODED_UCHAR_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_SCHAR,
-        ?FFI_HARDCODED_SCHAR_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_USHORT,
-        ?FFI_HARDCODED_USHORT_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_SSHORT,
-        ?FFI_HARDCODED_SSHORT_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_UINT,
-        ?FFI_HARDCODED_UINT_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_SINT,
-        ?FFI_HARDCODED_SINT_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_ULONG,
-        ?FFI_HARDCODED_ULONG_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_SLONG,
-        ?FFI_HARDCODED_SLONG_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_UINT8,
-        ?FFI_HARDCODED_UINT8_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_SINT8,
-        ?FFI_HARDCODED_SINT8_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_UINT16,
-        ?FFI_HARDCODED_UINT16_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_SINT16,
-        ?FFI_HARDCODED_SINT16_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_UINT32,
-        ?FFI_HARDCODED_UINT32_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_SINT32,
-        ?FFI_HARDCODED_SINT32_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_UINT64,
-        ?FFI_HARDCODED_UINT64_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_SINT64,
-        ?FFI_HARDCODED_SINT64_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_FLOAT,
-        ?FFI_HARDCODED_FLOAT_BITS/native-float).
--define(FFI_HARDCODED_DOUBLE,
-        ?FFI_HARDCODED_DOUBLE_BITS/native-float).
-
-%% Sorry, no long double support
-%%-define(FFI_HARDCODED_LONG_DOUBLE,     
-%%        ?FFI_HARDCODED_LONG_DOUBLE_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_POINTER,
-        ?FFI_HARDCODED_POINTER_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_CSTRING,
-        ?FFI_HARDCODED_CSTRING_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_NONNULL,
-        ?FFI_HARDCODED_NONNULL_BITS/native-unsigned-integer).
-
--define(FFI_HARDCODED_SIZE_T,
-        ?FFI_HARDCODED_SIZE_T_BITS/native-unsigned-integer).
--define(FFI_HARDCODED_SSIZE_T,
-        ?FFI_HARDCODED_SSIZE_T_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_OFF_T,
-        ?FFI_HARDCODED_OFF_T_BITS/native-signed-integer).
-
--define(FFI_HARDCODED_PID_T,
-        ?FFI_HARDCODED_PID_T_BITS/native-signed-integer).
-
--endif. % __FFI_HARDCODES_HRL__
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/kernel/src/Makefile
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -80,7 +80,6 @@ MODULES = \
 	erts_debug \
 	error_handler \
 	error_logger \
-	ffi \
 	file \
 	file_io_server \
 	file_server \
@@ -125,8 +124,7 @@ MODULES = \
 	wrap_log_reader \
 	zlib
 
-HRL_FILES= ../include/file.hrl ../include/inet.hrl \
-	../include/$(TARGET)/ffi_hardcodes.hrl
+HRL_FILES= ../include/file.hrl ../include/inet.hrl
 INTERNAL_HRL_FILES= application_master.hrl disk_log.hrl \
         net_address.hrl inet_dns.hrl inet_res.hrl \
         inet_boot.hrl inet_config.hrl inet_int.hrl \
@@ -153,8 +151,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
 # FLAGS
 # ----------------------------------------------------
 
-ERL_COMPILE_FLAGS += +warn_obsolete_guard -I../include -I../include/$(TARGET) \
-	-DERL_BUILD_TARGET="\"$(TARGET)\""
+ERL_COMPILE_FLAGS += +warn_obsolete_guard -I../include
 
 # ----------------------------------------------------
 # Targets
@@ -228,7 +225,6 @@ list_preloaded:
 $(EBIN)/erl_epmd.beam: inet_int.hrl erl_epmd.hrl
 $(EBIN)/erl_prim_loader.beam: inet_boot.hrl
 $(EBIN)/file.beam: ../include/file.hrl
-$(EBIN)/ffi.beam: ../include/$(TARGET)/ffi_hardcodes.hrl
 $(EBIN)/gen_tcp.beam: inet_int.hrl
 $(EBIN)/gen_udp.beam: inet_int.hrl
 $(EBIN)/gen_sctp.beam: ../include/inet_sctp.hrl
diff -r 3e934e62ea62 -r 34b57ba8b406 lib/kernel/src/ffi.erl
--- a/lib/kernel/src/ffi.erl
+++ /dev/null
@@ -1,436 +0,0 @@
-%% ``The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved via the world wide web at http://www.erlang.org/.
-%% 
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%% 
-%% The Initial Developer of the Original Code is  CRS4 - Center for
-%% Advanced Studies, Research and Development in Sardinia
-%% (http://www.crs4.it/). All Rights Reserved.''
-%%
-%% Copyright (C) 2007 by CRS4 - http://www.crs4.it/
-%% Author: Alceste Scalas <alceste@crs4.it>
-%%
-%%     $Id$
-
-%% @doc Methods for calling native C functions from Erlang code, and
-%% handling their return values.
-%%
-%% @type type_tag() = atom().  Valid FFI type atom.
-%%
-%% @type tagged_value() = tuple(type_tag(), term()).  Type-tagged value
-%%                                                    used for FFI calls.
-%%
-%% @type c_func_name() = atom() | string().  Name of a C function.
-%%
-%% @type func_index() = integer().  Function position on the list of preloads
-%%                                  given to erl_ddll:load_library/3.
-%%
-%% @type tagged_func_name() = tuple(type_tag(), c_func_name()).  C function
-%%                                                               name with
-%%                                                               return type.
-%%
-%% @type tagged_func_index() = tuple(type_tag(), func_index()).  C function
-%%                                                               index with
-%%                                                               return type.
--module(ffi).
--author("Alceste Scalas <alceste@crs4.it>").
--export([call/3,
-	 buffer_to_binary/2, cstring_to_binary/1,
-	 sizeof/1, min/1, max/1,
-	 check/1]).
-
--ifdef(ERL_BUILD_TARGET).
-%% We are being built, so the current include path allows this -include().
--include("ffi_hardcodes.hrl").
--else.
--include_lib("kernel/include/ffi_hardcodes.hrl").
--endif.
-
-%% @spec call(Port::port(), CFunc::cfunction(),
-%%            Args::[tagged_value()]) -> Ret::tagged_value()
-%%       cfunction() = func_name() | func_index()
-%%                     | tagged_func_name() | tagged_func_index()
-%%
-%% @doc Call the C function <code>CFunc</code> with the given list of
-%% arguments, using the port <code>Port</code>.  If the function was
-%% preloaded with ffi:load_library/3, all the type tags will be
-%% matched against the preloaded signature before performing the call.
-%%
-%% Return the return value of the C function, with the proper type tag.
-%%
-%% <strong>Note:</strong> if <code>CFunc</code> is not of type {@link
-%% tagged_func_name()}, the C function will be called if and only if
-%% it was preloaded with erl_ddll:load_library/3 (it is required in
-%% order to determine its return type).
-call(Port, {RetTypeTag, CFunc}, Args) when is_integer(CFunc) ->
-    %% Called with type tag + function index
-    {name, Lib} = .erlang:port_info(Port, name),
-    Preloads = [P || P <- .erl_ddll:info(Lib, preloads),
-		    .proplists:get_value(index, P) =:= CFunc],
-    case Preloads of
-	[P] ->
-	    do_preloaded_call(Port, RetTypeTag, P, Args);
-	[] ->
-	    %% Function index was out of range
-	    .erlang:error(badarg);
-	_ ->
-	    %% This should never happen (Preloads contains more than
-	    %% one element with the same index?!?)
-	    .erlang:error({bug, {duplicated_preloads, Preloads}})
-    end;
-call(Port, {RetTypeTag, CFunc}, Args) when is_list(CFunc) ->
-    %% Called with type tag + function name as string
-    {name, Lib} = .erlang:port_info(Port, name),
-    Preloads = [P || P <- .erl_ddll:info(Lib, preloads),
-		     .proplists:get_value(name, P) =:= CFunc],
-    case Preloads of
-	[] ->
-	    %% The function was not preloaded, but we have enough
-	    %% information to do a function call
-	    do_call(Port, RetTypeTag, CFunc, Args);
-	_ ->
-	    %% We support multiple matches on function names, because
-	    %% they could be used to preload different calls to C
-	    %% vararg functions (at least on some platforms).
-	    try_preloaded_calls(Port, RetTypeTag, Preloads, Args)
-    end;
-call(Port, {RetTypeTag, CFunc}, Args) when is_atom(CFunc) ->
-    %% Called with type tag + function name as atom
-    call(Port, {RetTypeTag, atom_to_list(CFunc)}, Args);
-call(Port, CFunc, Args) when is_integer(CFunc) ->
-    %% Called with function index alone
-    {name, Lib} = .erlang:port_info(Port, name),
-    Preloads = [P || P <- .erl_ddll:info(Lib, preloads),
-		     .proplists:get_value(index, P) =:= CFunc],
-    case Preloads of
-	[P] ->
-	    RetTypeTag = element(1, .proplists:get_value(signature, P)),
-	    do_preloaded_call(Port, RetTypeTag, P, Args);
-	[] ->
-	    %% Function index was out of range
-	    .erlang:error(badarg);
-	_ ->
-	    %% This should never happen (Preloads contains more than
-	    %% one element with the same index?!?)
-	    .erlang:error({bug, {duplicated_preloads, Preloads}})
-    end;
-call(Port, CFunc, Args) when is_list(CFunc) ->
-    %% Called with function name alone as string
-    {name, Lib} = .erlang:port_info(Port, name),
-    Preloads = [P || P <- .erl_ddll:info(Lib, preloads),
-		     .proplists:get_value(name, P) =:= CFunc],
-    case Preloads of
-	[] ->
-	    %% The function was not preloaded, so we miss the
-	    %% type_tag() for building the return value: let's fail
-	    .erlang:error(badarg);
-	_ ->
-	    %% We support multiple matches on function names, because they
-	    %% could be used to preload different calls to C vararg functions
-	    %% (at least on some platforms).
-	    try_preloaded_calls(Port, Preloads, Args)
-    end;
-call(Port, CFunc, Args) when is_atom(CFunc) ->
-    %% Called with function name alone as atom
-    call(Port, atom_to_list(CFunc), Args).
-
-%% Try to perform FFI calls from a list of preloaded function, until
-%% one matches the given arguments and return types
-try_preloaded_calls(Port, RetTypeTag, [Preload], Args) ->
-    %% Laast element on the preloads list: call it and see what
-    %% happens
-    do_preloaded_call(Port, RetTypeTag, Preload, Args);
-try_preloaded_calls(Port, RetTypeTag, [Preload | Rest], Args) ->
-    try
-	do_preloaded_call(Port, RetTypeTag, Preload, Args)
-    catch
-	error:{badmatch, _} ->
-	    %% The preload signature was wrong, let's try with the
-	    %% next one
-	    try_preloaded_calls(Port, Rest, Args)
-    end.
-
-%% Try to perform FFI calls from a list of preloaded function, until
-%% one matches the given arguments types (the return type is taken
-%% from the preload itself)
-try_preloaded_calls(Port, [Preload], Args) ->
-    %% Laast element on the preloads list: call it and see what
-    %% happens
-    RetTypeTag = element(1, .proplists:get_value(signature, Preload)),
-    do_preloaded_call(Port, RetTypeTag, Preload, Args);
-try_preloaded_calls(Port, [Preload | Rest], Args) ->
-    RetTypeTag = element(1, .proplists:get_value(signature, Preload)),
-    try
-	do_preloaded_call(Port, RetTypeTag, Preload, Args)
-    catch
-	error:{badmatch, _} ->
-	    %% The preload signature was wrong, let's try with the
-	    %% next one
-	    try_preloaded_calls(Port, Rest, Args)
-    end.
-
-%% Perform a FFI call using the given preload information.  Match the
-%% preloaded function signature with RetTypeTag and arguments type tags.
-do_preloaded_call(Port, RetTypeTag, Preload, Args) ->
-    check_arguments(Args),
-    
-    %% Build and match function signature
-    Sig = list_to_tuple([RetTypeTag] ++ [element(1, Arg) || Arg <- Args]),
-    Sig = .proplists:get_value(signature, Preload),
-    
-    %% If we are here, the signatures did match
-    RawArgs = [element(2, Arg) || Arg <- Args],
-
-    RetVal = .ffi:raw_call(Port,
-			   list_to_tuple([.proplists:get_value(index,
-							       Preload)]
-					 ++ RawArgs)),
-    {RetTypeTag, RetVal}.
-
-%% Perform a FFI call (without preload info).
-do_call(Port, RetTypeTag, CFunc, Args) ->
-    check_arguments(Args),
-    
-    %% Build and match function signature
-    Sig = list_to_tuple([RetTypeTag] ++ [element(1, Arg) || Arg <- Args]),
-    RawArgs = [element(2, Arg) || Arg <- Args],
-
-    RetVal = .ffi:raw_call(Port, list_to_tuple([CFunc] ++ RawArgs), Sig),
-    {RetTypeTag, RetVal}.
-
-%% Raise an exception if any element in the arguments list is not a
-%% valid type-tagged value
-check_arguments(Args) ->
-    Check = .lists:all(fun check/1, Args),
-    if
-	Check ->
-	    ok;
-	true ->
-	    .erlang:error(badarg)
-    end.
-
-%% @spec buffer_to_binary(TaggedNonnull:nonnull(), Size) -> binary()
-%%       nonnull() = tuple(nonnull, integer())
-%%
-%% @doc Create a binary with a copy of <code>Size</code> bytes taken
-%% from the given C buffer (a type-tagged C non-null pointer).
-%%
-%% Return the new binary.
-buffer_to_binary({nonnull, Ptr}, Size) ->
-    IsValid = check({nonnull, Ptr}),
-    if
-	IsValid ->
-	    .ffi:raw_buffer_to_binary(Ptr, Size);
-	true ->
-	    .erlang:error(badarg)
-    end.
-
-%% @spec cstring_to_binary(TaggedCString::cstring()) -> binary()
-%%       cstring() = tuple(cstring, integer())
-%%
-%% @doc Create a binary with a copy of the given C string (a
-%% type-tagged C non-null pointer).  The binary will include the trailing '\0'
-%% character.
-%%
-%% Return the new binary.
-cstring_to_binary({cstring, Ptr}) ->
-    IsValid = check({cstring, Ptr}),
-    if
-	IsValid ->
-	    .ffi:raw_cstring_to_binary(Ptr);
-	true ->
-	    .erlang:error(badarg)
-    end.
-
-%% @spec sizeof(TypeTag::type_tag()) -> integer()
-%%
-%% @doc Return the size of the given FFI type tag, on the current system.
-sizeof(uchar) ->
-    ?FFI_HARDCODED_SIZEOF_UCHAR;
-sizeof(schar) ->
-    ?FFI_HARDCODED_SIZEOF_SCHAR;
-sizeof(ushort) ->
-    ?FFI_HARDCODED_SIZEOF_USHORT;
-sizeof(sshort) ->
-    ?FFI_HARDCODED_SIZEOF_SSHORT;
-sizeof(uint) ->
-    ?FFI_HARDCODED_SIZEOF_UINT;
-sizeof(sint) ->
-    ?FFI_HARDCODED_SIZEOF_SINT;
-sizeof(ulong) ->
-    ?FFI_HARDCODED_SIZEOF_ULONG;
-sizeof(slong) ->
-    ?FFI_HARDCODED_SIZEOF_SLONG;
-sizeof(uint8) ->
-    ?FFI_HARDCODED_SIZEOF_UINT8;
-sizeof(sint8) ->
-    ?FFI_HARDCODED_SIZEOF_SINT8;
-sizeof(uint16) ->
-    ?FFI_HARDCODED_SIZEOF_UINT16;
-sizeof(sint16) ->
-    ?FFI_HARDCODED_SIZEOF_SINT16;
-sizeof(uint32) ->
-    ?FFI_HARDCODED_SIZEOF_UINT32;
-sizeof(sint32) ->
-    ?FFI_HARDCODED_SIZEOF_SINT32;
-sizeof(uint64) ->
-    ?FFI_HARDCODED_SIZEOF_UINT64;
-sizeof(sint64) ->
-    ?FFI_HARDCODED_SIZEOF_SINT64;
-sizeof(float) ->
-    ?FFI_HARDCODED_SIZEOF_FLOAT;
-sizeof(double) ->
-    ?FFI_HARDCODED_SIZEOF_DOUBLE;
-sizeof(longdouble) ->
-    ?FFI_HARDCODED_SIZEOF_LONG_DOUBLE;
-sizeof(pointer) ->
-    ?FFI_HARDCODED_SIZEOF_POINTER;
-sizeof(cstring) ->
-    ?FFI_HARDCODED_SIZEOF_POINTER;
-sizeof(nonnull) ->
-    ?FFI_HARDCODED_SIZEOF_POINTER;
-sizeof(size_t) ->
-    ?FFI_HARDCODED_SIZEOF_SIZE_T;
-sizeof(ssize_t) ->
-    ?FFI_HARDCODED_SIZEOF_SSIZE_T;
-sizeof(off_t) ->
-    ?FFI_HARDCODED_SIZEOF_OFF_T;
-sizeof(pid_t) ->
-    ?FFI_HARDCODED_SIZEOF_PID_T.
-
-%% @spec min(TypeTag::type_tag()) -> integer()
-%%
-%% @doc Return the minimum <em>integer</em> value allowed by the given
-%% FFI type.
-%%
-%% <strong>Note:</strong> only integer-based tagged values are
-%% supported (including C pointers).  Floating point values, in
-%% particular, are not supported.
-min(uchar) ->
-    0;
-min(schar) ->
-    -(1 bsl (?FFI_HARDCODED_SCHAR_BITS - 1));
-min(ushort) ->
-    0;
-min(sshort) ->
-    -(1 bsl (?FFI_HARDCODED_SSHORT_BITS - 1));
-min(uint) ->
-    0;
-min(sint) ->
-    -(1 bsl (?FFI_HARDCODED_SINT_BITS - 1));
-min(ulong) ->
-    0;
-min(slong) ->
-    -(1 bsl (?FFI_HARDCODED_SLONG_BITS - 1));
-min(uint8) ->
-    0;
-min(sint8) ->
-    -(1 bsl (?FFI_HARDCODED_SINT8_BITS - 1));
-min(uint16) ->
-    0;
-min(sint16) ->
-    -(1 bsl (?FFI_HARDCODED_SINT16_BITS - 1));
-min(uint32) ->
-    0;
-min(sint32) ->
-    -(1 bsl (?FFI_HARDCODED_SINT32_BITS - 1));
-min(uint64) ->
-    0;
-min(sint64) ->
-    -(1 bsl (?FFI_HARDCODED_SINT64_BITS - 1));
-min(pointer) ->
-    0;
-min(cstring) ->
-    1; % Cannot be NULL
-min(nonnull) ->
-    1; % Cannot be NULL
-min(size_t) ->
-    0;
-min(ssize_t) ->
-    -(1 bsl (?FFI_HARDCODED_SSIZE_T_BITS - 1));
-min(off_t) ->
-    -(1 bsl (?FFI_HARDCODED_OFF_T_BITS - 1));
-min(pid_t) ->
-    -(1 bsl (?FFI_HARDCODED_PID_T_BITS - 1)).
-
-%% @spec max(TypeTag::type_tag()) -> integer()
-%%
-%% @doc Return the maximum value allowed by the given
-%% <em>integer-based</em> FFI type.
-%%
-%% <strong>Note:</strong> only integer-based tagged values are
-%% supported (including C pointers).  Floating point values, in
-%% particular, are not supported.
-max(uchar) ->
-    (1 bsl ?FFI_HARDCODED_UCHAR_BITS) - 1;
-max(schar) ->
-    (1 bsl (?FFI_HARDCODED_SCHAR_BITS - 1)) - 1;
-max(ushort) ->
-    (1 bsl ?FFI_HARDCODED_USHORT_BITS) - 1;
-max(sshort) ->
-    (1 bsl (?FFI_HARDCODED_SSHORT_BITS - 1)) - 1;
-max(uint) ->
-    (1 bsl ?FFI_HARDCODED_UINT_BITS) - 1;
-max(sint) ->
-    (1 bsl (?FFI_HARDCODED_SINT_BITS - 1)) - 1;
-max(ulong) ->
-    (1 bsl ?FFI_HARDCODED_ULONG_BITS) - 1;
-max(slong) ->
-    (1 bsl (?FFI_HARDCODED_SLONG_BITS - 1)) - 1;
-max(uint8) ->
-    (1 bsl ?FFI_HARDCODED_UINT8_BITS) - 1;
-max(sint8) ->
-    (1 bsl (?FFI_HARDCODED_SINT8_BITS - 1)) - 1;
-max(uint16) ->
-    (1 bsl ?FFI_HARDCODED_UINT16_BITS) - 1;
-max(sint16) ->
-    (1 bsl (?FFI_HARDCODED_SINT16_BITS - 1)) - 1;
-max(uint32) ->
-    (1 bsl ?FFI_HARDCODED_UINT32_BITS) - 1;
-max(sint32) ->
-    (1 bsl (?FFI_HARDCODED_SINT32_BITS - 1)) - 1;
-max(uint64) ->
-    (1 bsl ?FFI_HARDCODED_UINT64_BITS) - 1;
-max(sint64) ->
-    (1 bsl (?FFI_HARDCODED_SINT64_BITS - 1)) - 1;
-max(pointer) ->
-    (1 bsl ?FFI_HARDCODED_POINTER_BITS) - 1;
-max(cstring) ->
-    (1 bsl ?FFI_HARDCODED_CSTRING_BITS) - 1;
-max(nonnull) ->
-    (1 bsl ?FFI_HARDCODED_NONNULL_BITS) - 1;
-max(size_t) ->
-    (1 bsl ?FFI_HARDCODED_SIZE_T_BITS) - 1;
-max(ssize_t) ->
-    (1 bsl (?FFI_HARDCODED_SSIZE_T_BITS - 1)) - 1;
-max(off_t) ->
-    (1 bsl (?FFI_HARDCODED_OFF_T_BITS - 1)) - 1;
-max(pid_t) ->
-    (1 bsl (?FFI_HARDCODED_PID_T_BITS - 1)) - 1.
-
-%% @spec check(TaggedValue::tagged_value()) -> true | false
-%%
-%% @doc Check that the given type-tagged value is valid.
-%%
-%% This function performs range and type checking.
-%%
-%% <strong>Note:</strong> only integer-based tagged values are
-%% completely supported (including C pointers).  Checks on floating
-%% point values will always return <code>true</code> (unless the
-%% tagged value is malformed).
-check({void, void}) ->
-    true;
-check({TypeTag, Value}) when ((TypeTag == float) or (TypeTag == double)
-			      or (TypeTag == longdouble))
-			     and is_float(Value) ->
-    true;
-check({TypeTag, Value}) when is_atom(TypeTag) and is_integer(Value) ->
-    (Value =< max(TypeTag)) and (Value >= min(TypeTag));
-check(_) ->
-    false.
