diff --git a/.gitattributes b/.gitattributes index b462e0f855..c02e9e2844 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5175,6 +5175,10 @@ packages/libenet/src/enetprotocol.pp svneol=native#text/plain packages/libenet/src/enettime.pp svneol=native#text/plain packages/libenet/src/enettypes.pp svneol=native#text/plain packages/libenet/src/uenetclass.pp svneol=native#text/plain +packages/libffi/Makefile.fpc svneol=native#text/plain +packages/libffi/examples/simple.pp svneol=native#text/pascal +packages/libffi/fpmake.pp svneol=native#text/pascal +packages/libffi/src/ffi.pp svneol=native#text/pascal packages/libfontconfig/Makefile svneol=native#text/plain packages/libfontconfig/Makefile.fpc svneol=native#text/plain packages/libfontconfig/examples/testfc.lpi svneol=native#text/plain diff --git a/packages/libffi/Makefile.fpc b/packages/libffi/Makefile.fpc new file mode 100644 index 0000000000..4963c93f56 --- /dev/null +++ b/packages/libffi/Makefile.fpc @@ -0,0 +1,102 @@ +# +# Makefile.fpc for running fpmake +# + +[package] +name=libffi +version=3.1.1 + +[require] +packages=rtl fpmkunit + +[install] +fpcpackage=y + +[default] +fpcdir=../.. + +[prerules] +FPMAKE_BIN_CLEAN=$(wildcard ./fpmake$(SRCEXEEXT)) +ifdef OS_TARGET +FPC_TARGETOPT+=--os=$(OS_TARGET) +endif +ifdef CPU_TARGET +FPC_TARGETOPT+=--cpu=$(CPU_TARGET) +endif +LOCALFPMAKE=./fpmake$(SRCEXEEXT) + +[rules] +# Do not pass the Makefile's unit and binary target locations. Fpmake uses it's own. +override FPCOPT:=$(filter-out -FU%,$(FPCOPT)) +override FPCOPT:=$(filter-out -FE%,$(FPCOPT)) +# Do not pass the package-unitdirectories. Fpmake adds those and this way they don't apear in the .fpm +override FPCOPT:=$(filter-out $(addprefix -Fu,$(COMPILER_UNITDIR)),$(FPCOPT))# Compose general fpmake-parameters +# Compose general fpmake-parameters +ifdef FPMAKEOPT +FPMAKE_OPT+=$(FPMAKEOPT) +endif +FPMAKE_OPT+=--localunitdir=../.. +FPMAKE_OPT+=--globalunitdir=.. +FPMAKE_OPT+=$(FPC_TARGETOPT) +FPMAKE_OPT+=$(addprefix -o ,$(FPCOPT)) +FPMAKE_OPT+=--compiler=$(FPC) +FPMAKE_OPT+=-bu +.NOTPARALLEL: + +fpmake$(SRCEXEEXT): fpmake.pp + $(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT) $(OPT) +all: fpmake$(SRCEXEEXT) + $(LOCALFPMAKE) compile $(FPMAKE_OPT) +smart: fpmake$(SRCEXEEXT) + $(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -XX -o -CX +release: fpmake$(SRCEXEEXT) + $(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dRELEASE +debug: fpmake$(SRCEXEEXT) + $(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dDEBUG +# If no fpmake exists and (dist)clean is called, do not try to build fpmake, it will +# most often fail because the dependencies are cleared. +# In case of a clean, simply do nothing +ifeq ($(FPMAKE_BIN_CLEAN),) +clean: +else +clean: + $(FPMAKE_BIN_CLEAN) clean $(FPMAKE_OPT) +endif +# In case of a distclean, perform an 'old'-style distclean. This to avoid problems +# when the package is compiled using fpcmake prior to running this clean using fpmake +ifeq ($(FPMAKE_BIN_CLEAN),) +distclean: $(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall +else +distclean: +ifdef inUnix + { $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi; } +else + $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT) +endif + -$(DEL) $(LOCALFPMAKE) +endif +cleanall: distclean +install: fpmake$(SRCEXEEXT) +ifdef UNIXHier + $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) +else + $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) +endif +# distinstall also installs the example-sources and omits the location of the source- +# files from the fpunits.cfg files. +distinstall: fpmake$(SRCEXEEXT) +ifdef UNIXHier + $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0 +else + $(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0 +endif +zipinstall: fpmake$(SRCEXEEXT) + $(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) +zipdistinstall: fpmake$(SRCEXEEXT) + $(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) -ie -fsp 0 +zipsourceinstall: fpmake$(SRCEXEEXT) +ifdef UNIXHier + $(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=share/src/fpc-\$$\(PACKAGEVERSION\)/$(INSTALL_FPCSUBDIR)/\$$\(PACKAGEDIRECTORY\) +else + $(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=source\\$(INSTALL_FPCSUBDIR)\\\$$\(PACKAGEDIRECTORY\) +endif diff --git a/packages/libffi/examples/simple.pp b/packages/libffi/examples/simple.pp new file mode 100644 index 0000000000..ef81ad4b86 --- /dev/null +++ b/packages/libffi/examples/simple.pp @@ -0,0 +1,33 @@ +program simple; + +uses + ffi; + +function WritePChar(s: PChar): LongInt; cdecl; +begin + Writeln(s); + WritePChar := StrLen(s); +end; + +var + cif: ffi_cif; + args: array[0..0] of pffi_type; + values: array[0..0] of Pointer; + s: PChar; + rc: ffi_arg; +begin + args[0] := @ffi_type_pointer; + values[0] := @s; + + if ffi_prep_cif(@cif, FFI_DEFAULT_ABI, 1, @ffi_type_sint, @args[0]) = FFI_OK then begin + s := 'Hello World'; + ffi_call(@cif, ffi_fn(@WritePChar), @rc, @values[0]); + Writeln('Length: ', rc); + + s := 'This is cool!'; + ffi_call(@cif, ffi_fn(@WritePChar), @rc, @values[0]); + Writeln('Length: ', rc); + end else + Writeln('ffi_prep_cif failed'); + +end. diff --git a/packages/libffi/fpmake.pp b/packages/libffi/fpmake.pp new file mode 100644 index 0000000000..44faea095f --- /dev/null +++ b/packages/libffi/fpmake.pp @@ -0,0 +1,41 @@ +{$ifndef ALLPACKAGES} +{$mode objfpc}{$H+} +program fpmake; + +uses fpmkunit; + +Var + P : TPackage; + T : TTarget; +begin + With Installer do + begin +{$endif ALLPACKAGES} + + P:=AddPackage('libffi'); +{$ifdef ALLPACKAGES} + P.Directory:=ADirectory; +{$endif ALLPACKAGES} + P.Version:='3.1.1'; + P.Author := 'Anthony Green and others'; + P.License := 'MIT license'; + P.HomepageURL := 'https://sourceware.org/libffi/'; + P.Email := 'libffi-discuss@sourceware.org'; + P.Description := 'Headers for the libFFI library (Foreign Function Interface)'; + P.NeedLibC:= true; // true for headers that indirectly link to libc? + P.OSes := [linux]; + P.CPUs := [x86_64]; + + P.SourcePath.Add('src'); + P.IncludePath.Add('src'); + + T:=P.Targets.AddUnit('ffi.pp'); + + P.ExamplePath.Add('examples'); + P.Targets.AddExampleProgram('simple.pp'); + +{$ifndef ALLPACKAGES} + Run; + end; +end. +{$endif ALLPACKAGES} diff --git a/packages/libffi/src/ffi.pp b/packages/libffi/src/ffi.pp new file mode 100644 index 0000000000..a75e585618 --- /dev/null +++ b/packages/libffi/src/ffi.pp @@ -0,0 +1,601 @@ +(* -----------------------------------------------------------------*-C-*- + libffi 3.2.1 - Copyright (c) 2011, 2014 Anthony Green + - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the ``Software''), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- *) + +(* ------------------------------------------------------------------- + The basic API is described in the README file. + + The raw API is designed to bypass some of the argument packing + and unpacking on architectures for which it can be avoided. + + The closure API allows interpreted functions to be packaged up + inside a C function pointer, so that they can be called as C functions, + with no understanding on the client side that they are interpreted. + It can also be used in other cases in which it is necessary to package + up a user specified parameter and a function pointer as a single + function pointer. + + The closure API must be implemented in order to get its functionality, + e.g. for use by gij. Routines are provided to emulate the raw API + if the underlying platform doesn't allow faster implementation. + + More details on the raw and cloure API can be found in: + + http://gcc.gnu.org/ml/java/1999-q3/msg00138.html + + and + + http://gcc.gnu.org/ml/java/1999-q3/msg00174.html + -------------------------------------------------------------------- *) + +unit ffi; + +interface + +uses + ctypes; + +{ + from the various ffitarget.h +} + +{ ToDo: we need defines for the MIPS ABI } + +const +{$if defined(CPUMIPS) or defined(CPU64)} + FFI_SIZEOF_ARG = 8; +{$else} + FFI_SIZEOF_ARG = 4; +{$endif} + + FFI_SIZEOF_JAVA_ARG = FFI_SIZEOF_ARG; + +{$if defined(CPUPOWERPC) and not defined(AIX) and not defined(DARWIN)} + {$if defined(CPUPOWERPC32)} + FFI_SYSV_SOFT_FLOAT = 1; + FFI_SYSV_STRUCT_RET = 2; + FFI_SYSV_IBM_LONG_DOUBLE = 4; + FFI_SYSV_LONG_DOUBLE_128 = 16; + {$elseif defined(CPUPOWERPC64)} + FFI_LINUX_STRUCT_ALIGN = 1; + FFI_LINUX_LONG_DOUBLE_128 = 2; + {$endif} +{$endif} + +type +{$ifdef WIN64} + ffi_arg = QWord; + ffi_sarg = Int64; +{$else} + ffi_arg = culong; + ffi_sarg = cslong; +{$endif} + + ffi_abi = ( + FFI_FIRST_ABI, +{$if not defined(CPUMIPS) and not defined(CPUX86_64) and not defined(CPUPOWERPC) and not defined(CPUSPARCGEN)} + FFI_SYSV, +{$endif} +{$if defined(CPUARM)} + FFI_VFP, +{$endif} +{$if defined(CPUMIPS)} + FFI_O32, + FFI_N32, + FFI_N64, + FFI_O32_SOFT_FLOAT, + FFI_N32_SOFT_FLOAT, + FFI_N64_SOFT_FLOAT, +{$endif} +{$if defined(CPUX86_64)} + {$ifndef WIN64} + FFI_UNIX64, + {$endif} + FFI_WIN64, +{$endif} +{$if defined(CPUI386)} + {$ifdef WIN32} + FFI_STDCALL, + {$endif} + FFI_THISCALL = 3, + FFI_FASTCALL, + {$ifdef WIN32} + FFI_MS_CDECL, + {$else} + FFI_STDCALL, + {$endif} + FFI_PASCAL, + FFI_REGISTER, +{$endif} +{$if defined(CPUSPARC32)} + FFI_V8, +{$endif} +{$if defined(CPUSPARC64)} + FFI_V9, +{$endif} +{$if defined(CPUPOWERPC)} + { this one is getting ugly... } + {$if defined(AIX) or defined(DARWIN)} + FFI_AIX, + FFI_DARWIN, + {$else} + FFI_COMPAT_SYSV, + FFI_COMPAT_GCC_SYSV, + FFI_COMPAT_LINUX64, + FFI_COMPAT_LINUX, + FFI_COMPAT_LINUX_SOFT_FLOAT, + {$if defined(CPUPOWERPC64)} + FFI_LINUX = 8, + {$define NO_LAST_ABI} + FFI_LAST_ABI = 12 + {$elseif defined(CPUPOWERPC32)} + FFI_SYSV = 8, + {$define NO_LAST_ABI} + FFI_LAST_ABI = 32 + {$endif} + {$endif} +{$endif} +{$ifndef NO_LAST_ABI} + FFI_LAST_ABI +{$endif} + ); + +{ alias values } +const +{$if defined(CPUX86_64) and not defined(WIN64)} + FFI_EFI64 = FFI_WIN64; +{$endif} +{$if defined(CPUARMHF)} + FFI_DEFAULT_ABI = FFI_VFP; +{$elseif defined(CPUMIPS)} + { ToDo: needs define for ABI } + FFI_DEFAULT_ABI = FFI_N32; +{$elseif defined(CPUX86_64)} + {$ifdef WIN64} + FFI_DEFAULT_ABI = FFI_WIN64; + {$else} + FFI_DEFAULT_ABI = FFI_UNIX64; + {$endif} +{$elseif defined(CPUSPARC32)} + FFI_DEFAULT_ABI = FFI_V8; +{$elseif defined(CPUSPARC64)} + FFI_DEFAULT_ABI = FFI_V9; +{$elseif defined(CPUPOWERPC)} + {$if defined(AIX)} + FFI_DEFAULT_ABI = FFI_AIX; + {$elseif defined(DARWIN)} + FFI_DEFAULT_ABI = FFI_DARWIN; + {$elseif defined(CPUPOWERPC64)} + { ToDo: find out what needs to be set } + FFI_DEFAULT_ABI = ffi_abi(Ord(FFI_LINUX) or FFI_LINUX_STRUCT_ALIGN or FFI_LINUX_LONG_DOUBLE_128); + {$elseif defined(CPUPOWERPC)} + { ToDo: find out what needs to be set } + FFI_DEFAULT_ABI = ffi_abi(Ord(FFI_SYSV) {$ifdef FREEBSD}or FFI_SYSV_STRUCT_RET{$endif}); + {$endif} +{$else} + FFI_DEFAULT_ABI = FFI_SYSV; +{$endif} + +const +{$if defined(CPUPOWERPC)} + FFI_TARGET_HAS_COMPLEX_TYPE = False; +{$else} + FFI_TARGET_HAS_COMPLEX_TYPE = True; +{$endif} + +(* ---- Definitions for closures ----------------------------------------- *) + +const + FFI_CLOSURES = true; +{$if defined(DARWIN) and (defined(CPUARM) or defined(CPUAARCH64))} + FFI_EXEC_TRAMPOLINE_TABLE = True; +{$else} + FFI_EXEC_TRAMPOLINE_TABLE = False; +{$endif} +{$if defined(CPUI386)} + FFI_NATIVE_RAW_API = True; +{$else} + FFI_NATIVE_RAW_API = False; +{$endif} + +{$if defined(CPUARM) or defined(CPUX86_64) or defined(CPUI386) or defined(CPUSPARCGEN) or (defined(CPUAARCH64) and not defined(DARWIN)) or (defined(CPUPOWERPC) and not defined(DARWIN))} + FFI_GO_CLOSURES = True; +{$else} + FFI_GO_CLOSURES = False; +{$endif} + +{$if defined(CPUARM)} + {$if definde(DARWIN)} + FFI_TRAMPOLINE_SIZE = 12; + FFI_TRAMPOLINE_CLOSURE_OFFSET = 8; + {$elseif FFI_EXEC_TRAMPOLINE_TABLE} + {$error 'No trampoline table implementation'} + {$else} + FFI_TRAMPOLINE_SIZE = 12; + FFI_TRAMPOLINE_CLOSURE_OFFSET = FFI_TRAMPOLINE_SIZE; + {$endif} +{$elseif defined(CPUAARCH64)} + {$if defined(DARWIN)} + FFI_TRAMPOLINE_SIZE =16; + FFI_TRAMPOLINE_CLOSURE_OFFSET = 16; + {$elseif FFI_EXEC_TRAMPOLINE_TABLE} + {$error 'No trampoline table implementation'} + {$else} + FFI_TRAMPOLINE_SIZE = 24; + FFI_TRAMPOLINE_CLOSURE_OFFSET = FFI_TRAMPOLINE_SIZE; + {$endif} +{$elseif defined(CPUPOWERPC)} + { ToDo: check for ELFv2? } + {$ifdef ELF_V2} + FFI_TRAMPOLINE_SIZE = 32; + {$else} + {$if defined(CPUPOWERPC64) or defined(AIX)} + {$if defined(DARWIN)} + FFI_TRAMPOLINE_SIZE = 48; + {$else} + FFI_TRAMPOLINE_SIZE = 25; + {$endif} + {$else} + FFI_TRAMPOLINE_SIZE = 40; + {$endif} + {$endif} +{$elseif defined(CPUSPARC32)} + FFI_TRAMPOLINE_SIZE = 16; +{$elseif defined(CPUSPARC64)} + FFI_TRAMPOLINE_SIZE = 24; +{$elseif defined(CPUX86_64)} + FFI_TRAMPOLINE_SIZE = 24; +{$elseif defined(CPUI386)} + FFI_TRAMPOLINE_SIZE = 12; +{$elseif defined(CPUM68K)} + FFI_TRAMPOLINE_SIZE = 16; +{$endif} + +{ + from ffi.h +} + +const + ffilibrary = 'ffi'; + +{$if defined(CPUX86) and not defined(WIN64)} + { Note: we can not use FPC_HAS_TYPE_EXTENDED here as libffi won't have the + corresponding type no matter what } + {$define HAVE_LONG_DOUBLE} +{$endif} + +type + pffi_type = ^ffi_type; + ppffi_type = ^pffi_type; + ffi_type = record + size: csize_t; + alignment: cushort; + _type: cushort; + elements: ppffi_type; + end; + +var + ffi_type_void: ffi_type; cvar; external ffilibrary; + ffi_type_uint8: ffi_type; cvar; external ffilibrary; + ffi_type_sint8: ffi_type; cvar; external ffilibrary; + ffi_type_uint16: ffi_type; cvar; external ffilibrary; + ffi_type_sint16: ffi_type; cvar; external ffilibrary; + ffi_type_uint32: ffi_type; cvar; external ffilibrary; + ffi_type_sint32: ffi_type; cvar; external ffilibrary; + ffi_type_uint64: ffi_type; cvar; external ffilibrary; + ffi_type_sint64: ffi_type; cvar; external ffilibrary; + ffi_type_float: ffi_type; cvar; external ffilibrary; + ffi_type_double: ffi_type; cvar; external ffilibrary; + ffi_type_pointer: ffi_type; cvar; external ffilibrary; +{$ifdef HAVE_LONG_DOUBLE} + ffi_type_longdouble: ffi_type; cvar; external ffilibrary; +{$else} + ffi_type_longdouble: ffi_type absolute ffi_type_double; +{$endif} + +{$if FFI_TARGET_HAS_COMPLEX_TYPE} + ffi_type_complex_single: ffi_type; cvar; external ffilibrary; + ffi_type_complex_double: ffi_type; cvar; external ffilibrary; + {$ifdef HAVE_LONG_DOUBLE} + ffi_type_complex_longdouble: ffi_type; cvar; external ffilibrary; + {$endif} +{$endif} + + { type aliases } + + ffi_type_uchar: ffi_type absolute ffi_type_uint8; + ffi_type_schar: ffi_type absolute ffi_type_sint8; + + { ToDo: check when C's short isn't 2 byte } + ffi_type_ushort: ffi_type absolute ffi_type_uint16; + ffi_type_sshort: ffi_type absolute ffi_type_sint16; + + { ToDo: check when C's int isn't 4 byte } + ffi_type_uint: ffi_type absolute ffi_type_uint32; + ffi_type_sint: ffi_type absolute ffi_type_sint32; + +{$if defined(CPU64) and not defined(WIN64)} + ffi_type_ulong: ffi_type absolute ffi_type_uint64; + ffi_type_slong: ffi_type absolute ffi_type_sint64; +{$else} + ffi_type_ulong: ffi_type absolute ffi_type_uint32; + ffi_type_slong: ffi_type absolute ffi_type_sint32; +{$endif} + +type + ffi_status = ( + FFI_OK, + FFI_BAD_TYPEDEF, + FFI_BAD_ABI + ); + + pffi_cif = ^ffi_cif; + ffi_cif = record + abi: ffi_abi; + nargs: cunsigned; + arg_type: ppffi_type; + rtype: pffi_type; + bytes: cunsigned; + flags: cunsigned; +{$if defined(CPUARM)} + vfp_used: cint; + vfp_reg_free: cushort; + vfp_nargs: cushort; + vfp_args: array[0..15] of cchar; +{$elseif defined(CPUAARCH64)} + {$ifdef DARWIN} + aarch64_nfixedargs: cuint; + {$endif} +{$elseif defined(CPUSPARC64)} + nfixedargs: cuint; +{$elseif defined(CPUPOWERPC)} + {$ifndef DARWIN} + nfixedargs: cuint; + {$endif} +{$endif} + end; + + pffi_raw = ^ffi_raw; + ffi_raw = record + case longint of + 0: (sint: ffi_sarg); + 1: (uint: ffi_arg); + 2: (flt: cfloat); + 3: (data: array[0..FFI_SIZEOF_ARG] of cchar); + 4: (ptr: Pointer); + end; + +{$if (FFI_SIZEOF_JAVA_ARG = 4) and (FFI_SIZEOF_ARG = 8)} + (* This is a special case for mips64/n32 ABI (and perhaps others) where + sizeof(void * ) is 4 and FFI_SIZEOF_ARG is 8. *) + ffi_java_raw = record + case longint of + 0: (sint: ffi_sarg); + 1: (uint: ffi_arg); + 2: (flt: cfloat); + 3: (data: array[0..FFI_SIZEOF_JAVA_ARG] of cchar); + 4: (ptr: Pointer); + end; +{$else} + ffi_java_raw = ffi_raw; +{$endif} + pffi_java_raw = ^ffi_java_raw; + + ffi_fn = procedure; + +procedure ffi_raw_call(cif: pffi_cif; + fn: ffi_fn; + rvalue: Pointer; + avalue: pffi_raw); cdecl; external ffilibrary name 'ffi_raw_call'; + +procedure ffi_ptrarray_to_raw(cif: pffi_cif; args: PPointer; raw: pffi_raw); cdecl; external ffilibrary name 'ffi_ptrarray_to_raw'; +procedure ffi_raw_to_ptrarray(cif: pffi_cif; raw: pffi_raw; args: PPointer); cdecl; external ffilibrary name 'ffi_raw_to_ptrarray'; +function ffi_raw_size(cif: pffi_cif): csize_t; cdecl; external ffilibrary name 'ffi_raw_size'; + +(* This is analogous to the raw API, except it uses Java parameter + packing, even on 64-bit machines. I.e. on 64-bit machines longs + and doubles are followed by an empty 64-bit word. *) + +procedure ffi_java_raw_call(cif: pffi_cif; + fn: ffi_fn; + rvalue: Pointer; + avalue: pffi_java_raw); cdecl; external ffilibrary name 'ffi_java_raw_call'; + +procedure ffi_java_ptrarray_to_raw(cif: pffi_cif; args: PPointer; raw: pffi_java_raw); cdecl; external ffilibrary name 'ffi_java_ptrarray_to_raw'; +procedure ffi_java_raw_to_ptrarray(cif: pffi_cif; raw: pffi_java_raw; args: PPointer); cdecl; external ffilibrary name 'ffi_java_raw_to_ptrarray'; +function ffi_java_raw_size(cif: pffi_cif): csize_t; cdecl; external ffilibrary name 'ffi_java_raw_size'; + +(* ---- Definitions for closures ----------------------------------------- *) + +{$if FFI_CLOSURES} + +type + ffi_closure_fun = procedure(cif: pffi_cif; arg1: Pointer; arg2: PPointer; arg3: Pointer); cdecl; + + { ToDo: align 8 } + ffi_closure = record +{$if FFI_EXEC_TRAMPOLINE_TABLE} + trampoline_table: Pointer; + trampoline_table_entry: Pointer; +{$else} + tramp: array[0..FFI_TRAMPOLINE_SIZE] of cchar; +{$endif} + cif: pffi_cif; + fun: ffi_closure_fun; + user_data: Pointer; + end; + pffi_closure = ^ffi_closure; + +function ffi_closure_alloc(size: csize_t; code: PPointer): Pointer; cdecl; external ffilibrary name 'ffi_closure_alloc'; +procedure ffi_closure_free(clo: Pointer); cdecl; external ffilibrary name 'ffi_closure_free'; + +function ffi_prep_closure(clo: pffi_closure; + cif: pffi_cif; + fun: ffi_closure_fun; + user_data: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_closure'; deprecated 'use ffi_prep_closure_loc instead'; + +function ffi_prep_closure_loc(clo: pffi_closure; + cif: pffi_cif; + fun: ffi_closure_fun; + user_data: Pointer; + codeloc: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_closure_loc'; + +type + ffi_raw_closure_fun = procedure(cif: pffi_cif; arg1: Pointer; arg2: pffi_raw; arg3: Pointer); cdecl; + ffi_java_raw_closure_fun = procedure(cif: pffi_cif; arg1: Pointer; arg2: pffi_java_raw; arg3: Pointer); cdecl; + + { ToDo: pack 8 for __sgi aka MIPS? } + ffi_raw_closure = record +{$if FFI_EXEC_TRAMPOLINE_TABLE} + trampoline_table: Pointer; + trampoline_table_entry: Pointer; +{$else} + tramp: array[0..FFI_TRAMPOLINE_SIZE] of cchar; +{$endif} + cif: pffi_cif; +{$if not FFI_NATIVE_RAW_API} + (* If this is enabled, then a raw closure has the same layout + as a regular closure. We use this to install an intermediate + handler to do the transaltion, void** -> ffi_raw*. *) + translate_args: ffi_closure_fun; + this_closure: Pointer; +{$endif} + fun: ffi_raw_closure_fun; + user_data: Pointer; + end; + pffi_raw_closure = ^ffi_raw_closure; + + { ToDo: pack 8 for __sgi aka MIPS? } + ffi_java_raw_closure = record +{$if FFI_EXEC_TRAMPOLINE_TABLE} + trampoline_table: Pointer; + trampoline_table_entry: Pointer; +{$else} + tramp: array[0..FFI_TRAMPOLINE_SIZE] of cchar; +{$endif} + cif: pffi_cif; +{$if not FFI_NATIVE_RAW_API} + (* If this is enabled, then a raw closure has the same layout + as a regular closure. We use this to install an intermediate + handler to do the transaltion, void** -> ffi_raw*. *) + translate_args: ffi_closure_fun; + this_closure: Pointer; +{$endif} + fun: ffi_java_raw_closure_fun; + user_data: Pointer; + end; + pffi_java_raw_closure = ^ffi_java_raw_closure; + +function ffi_prep_raw_closure(clo: pffi_raw_closure; + cif: pffi_cif; + fun: ffi_raw_closure_fun; + user_data: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_raw_closure'; + +function ffi_prep_raw_closure_loc(clo: pffi_raw_closure; + cif: pffi_cif; + fun: ffi_raw_closure_fun; + user_data: Pointer; + codeloc: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_raw_closure_loc'; + +function ffi_prep_java_raw_closure(clo: pffi_java_raw_closure; + cif: pffi_cif; + fun: ffi_java_raw_closure_fun; + user_data: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_java_raw_closure'; + +function ffi_prep_java_raw_closure_loc(clo: pffi_java_raw_closure; + cif: pffi_cif; + fun: ffi_java_raw_closure_fun; + user_data: Pointer; + codeloc: Pointer): ffi_status; cdecl; external ffilibrary name 'ffi_prep_java_raw_closure_loc'; + +{$endif} + +{$if FFI_GO_CLOSURES} +type + ffi_go_closure = record + tramp: Pointer; + cif: pffi_cif; + fun: ffi_closure_fun; + end; + pffi_go_closure = ^ffi_go_closure; + +function ffi_prep_go_closure(clo: pffi_go_closure; cif: pffi_cif; fun: ffi_closure_fun): ffi_status; cdecl; external ffilibrary name 'ffi_prep_go_closure'; + +procedure ffi_call_go(cif: pffi_cif; fn: ffi_fn; rvalue: Pointer; avalue: PPointer; closure: Pointer); cdecl; external ffilibrary name 'ffi_call_go'; + +{$endif} + +(* ---- Public interface definition -------------------------------------- *) + +function ffi_prep_cif(cif: pffi_cif; + abi: ffi_abi; + nargs: cuint; + rtype: pffi_type; + atypes: ppffi_type): ffi_status; cdecl; external ffilibrary name 'ffi_prep_cif'; + +function ffi_prep_cif_var(cif: pffi_cif; + abi: ffi_abi; + nfixedargs: cuint; + ntotalargs: cuint; + rtype: pffi_type; + atypes: ppffi_type): ffi_status; cdecl; external ffilibrary name 'ffi_prep_cif_var'; + +procedure ffi_call(cif: pffi_cif; + fn: ffi_fn; + rvalue: Pointer; + avalue: PPointer); cdecl; external ffilibrary name 'ffi_call'; + +function ffi_get_struct_offsets(abi: ffi_abi; struct_type: pffi_type; + offsets: pcsize_t): ffi_status; cdecl; external ffilibrary name 'ffi_get_struct_offsets'; + +const + _FFI_TYPE_VOID = 0; + _FFI_TYPE_INT = 1; + _FFI_TYPE_FLOAT = 2; + _FFI_TYPE_DOUBLE = 3; +{$ifdef HAVE_LONG_DOUBLE} + _FFI_TYPE_LONGDOUBLE = 4; +{$else} + _FFI_TYPE_LONGDOUBLE = _FFI_TYPE_DOUBLE; +{$endif} + _FFI_TYPE_UINT8 = 5; + _FFI_TYPE_SINT8 = 6; + _FFI_TYPE_UINT16 = 7; + _FFI_TYPE_SINT16 = 8; + _FFI_TYPE_UINT32 = 9; + _FFI_TYPE_SINT32 = 10; + _FFI_TYPE_UINT64 = 11; + _FFI_TYPE_SINT64 = 12; + _FFI_TYPE_STRUCT = 13; + _FFI_TYPE_POINTER = 14; + _FFI_TYPE_COMPLEX = 15; + + _FFI_TYPE_LAST = _FFI_TYPE_COMPLEX; + + { ToDo: can we do without the platform specific types? } + +implementation + +end.