From 49efdd3cafb56f660e07402c7489ddd124466bf1 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 17 Dec 2020 10:12:57 +0000 Subject: [PATCH] implementing mod-ffi --- hawk/configure | 34 ++ hawk/configure.ac | 15 + hawk/lib/Makefile.am | 4 + hawk/lib/Makefile.in | 13 +- hawk/lib/hawk-cfg.h.in | 3 + hawk/lib/hawk.c | 29 + hawk/lib/hawk.h | 8 + hawk/lib/parse.c | 4 + hawk/mod/Makefile.am | 16 + hawk/mod/Makefile.in | 72 ++- hawk/mod/mod-ffi.c | 1245 ++++++++++++++++++++++++++++++++++++++++ hawk/mod/mod-ffi.h | 43 ++ 12 files changed, 1463 insertions(+), 23 deletions(-) create mode 100644 hawk/mod/mod-ffi.c create mode 100644 hawk/mod/mod-ffi.h diff --git a/hawk/configure b/hawk/configure index 4bb25dda..fa4fe4e2 100755 --- a/hawk/configure +++ b/hawk/configure @@ -641,6 +641,8 @@ ENABLE_MOD_UCI_FALSE ENABLE_MOD_UCI_TRUE ENABLE_MOD_MYSQL_FALSE ENABLE_MOD_MYSQL_TRUE +ENABLE_MOD_FFI_FALSE +ENABLE_MOD_FFI_TRUE ENABLE_LIBUNWIND_FALSE ENABLE_LIBUNWIND_TRUE ENABLE_LIBLTDL_FALSE @@ -827,6 +829,7 @@ enable_dynamic_module enable_static_module enable_libltdl enable_libunwind +enable_mod_ffi enable_mod_mysql enable_mod_uci enable_pthread_flags @@ -1489,6 +1492,7 @@ Optional Features: library(default. no) --enable-libltdl use libltdl(default. no) --enable-libunwind use libunwind(default. no) + --enable-mod-ffi enable mod/ffi (default. yes) --enable-mod-mysql enable mod/mysql (default. yes) --enable-mod-uci enable mod/uci (default. no) --enable-pthread-flags add thread flags to CFLAGS, CXXFLAGS, LIBS(default. @@ -24128,6 +24132,32 @@ fi +# Check whether --enable-mod-ffi was given. +if test "${enable_mod_ffi+set}" = set; then : + enableval=$enable_mod_ffi; enable_mod_ffi_is=$enableval +else + enable_mod_ffi_is=yes + +fi + +if test "x${ac_cv_lib_ffi_ffi_call}" != "xyes" -a "x${ac_cv_lib_dyncall_s_dcNewCallVM}" != "xyes" +then + enable_mod_ffi_is="no" +fi +if test "${enable_mod_ffi_is}" = "yes" +then + +$as_echo "#define HAWK_ENABLE_MOD_FFI 1" >>confdefs.h + +fi + if test "${enable_mod_ffi_is}" = "yes"; then + ENABLE_MOD_FFI_TRUE= + ENABLE_MOD_FFI_FALSE='#' +else + ENABLE_MOD_FFI_TRUE='#' + ENABLE_MOD_FFI_FALSE= +fi + # Check whether --enable-mod-mysql was given. if test "${enable_mod_mysql+set}" = set; then : @@ -24375,6 +24405,10 @@ if test -z "${ENABLE_LIBUNWIND_TRUE}" && test -z "${ENABLE_LIBUNWIND_FALSE}"; th as_fn_error $? "conditional \"ENABLE_LIBUNWIND\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${ENABLE_MOD_FFI_TRUE}" && test -z "${ENABLE_MOD_FFI_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_MOD_FFI\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${ENABLE_MOD_MYSQL_TRUE}" && test -z "${ENABLE_MOD_MYSQL_FALSE}"; then as_fn_error $? "conditional \"ENABLE_MOD_MYSQL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/hawk/configure.ac b/hawk/configure.ac index 9134d830..1a3abbc4 100644 --- a/hawk/configure.ac +++ b/hawk/configure.ac @@ -986,6 +986,21 @@ fi AM_CONDITIONAL(ENABLE_LIBUNWIND, test "x${enable_libunwind_is}" = "xyes") +dnl ===== enable-mod-ffi ===== +AC_ARG_ENABLE([mod-ffi], + [AS_HELP_STRING([--enable-mod-ffi],[enable mod/ffi (default. yes)])], + enable_mod_ffi_is=$enableval, + enable_mod_ffi_is=yes +) +if test "x${ac_cv_lib_ffi_ffi_call}" != "xyes" -a "x${ac_cv_lib_dyncall_s_dcNewCallVM}" != "xyes" +then + enable_mod_ffi_is="no" +fi +if test "${enable_mod_ffi_is}" = "yes" +then + AC_DEFINE([HAWK_ENABLE_MOD_FFI],[1],[build mod/ffi]) +fi +AM_CONDITIONAL(ENABLE_MOD_FFI, test "${enable_mod_ffi_is}" = "yes") dnl ===== enable-mod-mysql ===== AC_ARG_ENABLE([mod-mysql], diff --git a/hawk/lib/Makefile.am b/hawk/lib/Makefile.am index 23dc2ce7..44addac7 100644 --- a/hawk/lib/Makefile.am +++ b/hawk/lib/Makefile.am @@ -199,6 +199,10 @@ libhawk_la_SOURCES += \ mod-sys.c mod-sys.h libhawk_la_LIBADD += $(SOCKET_LIBS) +if ENABLE_MOD_FFI +libhawk_la_LIBADD += ../mod/libhawk-ffi.la +endif + if ENABLE_MOD_MYSQL libhawk_la_LIBADD += ../mod/libhawk-mysql.la endif diff --git a/hawk/lib/Makefile.in b/hawk/lib/Makefile.in index c2ff9e39..dc66aa1b 100644 --- a/hawk/lib/Makefile.in +++ b/hawk/lib/Makefile.in @@ -106,12 +106,13 @@ host_triplet = @host@ @ENABLE_STATIC_MODULE_TRUE@ mod-sys.c mod-sys.h @ENABLE_STATIC_MODULE_TRUE@am__append_10 = $(SOCKET_LIBS) -@ENABLE_MOD_MYSQL_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_11 = ../mod/libhawk-mysql.la -@ENABLE_MOD_UCI_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_12 = ../mod/libhawk-uci.la +@ENABLE_MOD_FFI_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_11 = ../mod/libhawk-ffi.la +@ENABLE_MOD_MYSQL_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_12 = ../mod/libhawk-mysql.la +@ENABLE_MOD_UCI_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_13 = ../mod/libhawk-uci.la #pkglibdir = $(libdir) #pkglib_LTLIBRARIES = -@ENABLE_STATIC_MODULE_FALSE@am__append_13 = libhawk-hawk.la \ +@ENABLE_STATIC_MODULE_FALSE@am__append_14 = libhawk-hawk.la \ @ENABLE_STATIC_MODULE_FALSE@ libhawk-math.la libhawk-str.la \ @ENABLE_STATIC_MODULE_FALSE@ libhawk-sys.la subdir = lib @@ -225,7 +226,7 @@ libhawk_sys_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ libhawk_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \ $(am__DEPENDENCIES_4) $(am__DEPENDENCIES_5) $(am__append_11) \ - $(am__append_12) + $(am__append_12) $(am__append_13) am__libhawk_la_SOURCES_DIST = hawk.h hawk-arr.h hawk-chr.h hawk-cmn.h \ hawk-dir.h hawk-ecs.h hawk-fmt.h hawk-gem.h hawk-htb.h \ hawk-map.h hawk-rbt.h hawk-pack1.h hawk-utl.h hawk-std.h \ @@ -597,7 +598,7 @@ pkginclude_HEADERS = hawk.h hawk-arr.h hawk-chr.h hawk-cmn.h \ hawk-dir.h hawk-ecs.h hawk-fmt.h hawk-gem.h hawk-htb.h \ hawk-map.h hawk-rbt.h hawk-pack1.h hawk-utl.h hawk-std.h \ hawk-tre.h hawk-unpack.h hawk-xma.h $(am__append_7) -pkglib_LTLIBRARIES = libhawk.la $(am__append_13) +pkglib_LTLIBRARIES = libhawk.la $(am__append_14) libhawk_la_SOURCES = $(pkginclude_HEADERS) arr.c chr.c dir.c ecs-imp.h \ ecs.c err-prv.h err.c err-sys.c fmt-imp.h fmt.c fnc-prv.h \ fnc.c htb.c gem.c gem-skad.c gem-nwif.c gem-nwif2.c hawk-prv.h \ @@ -619,7 +620,7 @@ libhawk_la_CXXFLAGS = $(CXXFLAGS_ALL_COMMON) libhawk_la_LDFLAGS = $(LDFLAGS_ALL_COMMON) -version-info 1:0:0 -no-undefined libhawk_la_LIBADD = $(LIBM) $(SOCKET_LIBS) $(am__append_4) \ $(am__append_5) $(am__append_6) $(am__append_10) \ - $(am__append_11) $(am__append_12) + $(am__append_11) $(am__append_12) $(am__append_13) @ENABLE_CXX_FALSE@libhawk_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ @ENABLE_CXX_FALSE@ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) \ @ENABLE_CXX_FALSE@ $(CFLAGS) $(libhawk_la_LDFLAGS) $(LDFLAGS) -o $@ diff --git a/hawk/lib/hawk-cfg.h.in b/hawk/lib/hawk-cfg.h.in index f758d7ba..fe8216d4 100644 --- a/hawk/lib/hawk-cfg.h.in +++ b/hawk/lib/hawk-cfg.h.in @@ -693,6 +693,9 @@ /* use libunwind for backtracing stack frames */ #undef HAWK_ENABLE_LIBUNWIND +/* build mod/ffi */ +#undef HAWK_ENABLE_MOD_FFI + /* build mod/mysql */ #undef HAWK_ENABLE_MOD_MYSQL diff --git a/hawk/lib/hawk.c b/hawk/lib/hawk.c index 5bc6be85..a3875e14 100644 --- a/hawk/lib/hawk.c +++ b/hawk/lib/hawk.c @@ -608,3 +608,32 @@ int hawk_buildrex (hawk_t* hawk, const hawk_ooch_t* ptn, hawk_oow_t len, hawk_tr { return hawk_gem_buildrex(hawk_getgem(hawk), ptn, len, !(hawk->opt.trait & HAWK_REXBOUND), code, icode); } + + + +/* ------------------------------------------------------------------------ */ + +int hawk_finmodsymfnc (hawk_t* hawk, hawk_mod_fnc_tab_t* fnctab, hawk_oow_t count, const hawk_ooch_t* name, hawk_oow_t namelen, hawk_mod_sym_t* sym) +{ + int n; + + /* binary search */ + /* [NOTE] this algorithm is underflow safe with hawk_oow_t types */ + hawk_oow_t base, mid, lim; + + for (base = 0, lim = count; lim > 0; lim >>= 1) + { + mid = base + (lim >> 1); + n = hawk_comp_oochars_oocstr(name, namelen, fnctab[mid].name); + if (n == 0) + { + sym->type = HAWK_MOD_FNC; + sym->u.fnc = fnctab[mid].info; + return 0; + } + if (n > 0) { base = mid + 1; lim--; } + } + + hawk_seterrbfmt (hawk, HAWK_NULL, HAWK_ENOENT, "'%js' not found", name); + return -1; +} diff --git a/hawk/lib/hawk.h b/hawk/lib/hawk.h index c6c13d80..bff8fd72 100644 --- a/hawk/lib/hawk.h +++ b/hawk/lib/hawk.h @@ -1046,6 +1046,14 @@ struct hawk_mod_sym_t } u; }; +/* ------------------------------------------------------------------------ */ + +typedef struct hawk_mod_fnc_tab_t hawk_mod_fnc_tab_t; +struct hawk_mod_fnc_tab_t +{ + const hawk_ooch_t* name; + hawk_mod_sym_fnc_t info; +}; /* ------------------------------------------------------------------------ */ diff --git a/hawk/lib/parse.c b/hawk/lib/parse.c index c452fed3..b8231efe 100644 --- a/hawk/lib/parse.c +++ b/hawk/lib/parse.c @@ -7373,6 +7373,10 @@ int hawk_putsrcoochars (hawk_t* hawk, const hawk_ooch_t* str, hawk_oow_t len) #include "mod-str.h" #include "mod-sys.h" +#if defined(HAWK_ENABLE_MOD_FFI) +#include "../mod/mod-ffi.h" +#endif + #if defined(HAWK_ENABLE_MOD_MYSQL) #include "../mod/mod-mysql.h" #endif diff --git a/hawk/mod/Makefile.am b/hawk/mod/Makefile.am index eb7f1c02..cd09a571 100644 --- a/hawk/mod/Makefile.am +++ b/hawk/mod/Makefile.am @@ -21,6 +21,10 @@ LIBADD_COMMON = noinst_LTLIBRARIES = +if ENABLE_MOD_FFI +noinst_LTLIBRARIES += libhawk-ffi.la +endif + if ENABLE_MOD_MYSQL noinst_LTLIBRARIES += libhawk-mysql.la endif @@ -42,6 +46,10 @@ LIBADD_COMMON = -lhawk pkgmodexecdir = $(libdir) pkgmodexec_LTLIBRARIES = +if ENABLE_MOD_FFI +pkgmodexec_LTLIBRARIES += libhawk-ffi.la +endif + if ENABLE_MOD_MYSQL pkgmodexec_LTLIBRARIES += libhawk-mysql.la endif @@ -58,6 +66,14 @@ endif #------------------------------------------------- # ACTUAL MODULES #------------------------------------------------- +if ENABLE_MOD_FFI +libhawk_ffi_la_SOURCES = mod-ffi.c mod-ffi.h +libhawk_ffi_la_CPPFLAGS = $(CPPFLAGS_COMMON) $(MYSQL_CFLAGS) +libhawk_ffi_la_CFLAGS = $(CFLAGS_COMMON) +libhawk_ffi_la_LDFLAGS = $(LDFLAGS_COMMON) $(MYSQL_LDFLAGS) +libhawk_ffi_la_LIBADD = $(LIBADD_COMMON) $(MYSQL_LIBS) +endif + if ENABLE_MOD_MYSQL libhawk_mysql_la_SOURCES = mod-mysql.c mod-mysql.h libhawk_mysql_la_CPPFLAGS = $(CPPFLAGS_COMMON) $(MYSQL_CFLAGS) diff --git a/hawk/mod/Makefile.in b/hawk/mod/Makefile.in index e41ae1bf..37acae9e 100644 --- a/hawk/mod/Makefile.in +++ b/hawk/mod/Makefile.in @@ -88,10 +88,12 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -@ENABLE_MOD_MYSQL_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_1 = libhawk-mysql.la -@ENABLE_MOD_UCI_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_2 = libhawk-uci.la -@ENABLE_MOD_MYSQL_TRUE@@ENABLE_STATIC_MODULE_FALSE@am__append_3 = libhawk-mysql.la -@ENABLE_MOD_UCI_TRUE@@ENABLE_STATIC_MODULE_FALSE@am__append_4 = libhawk-uci.la +@ENABLE_MOD_FFI_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_1 = libhawk-ffi.la +@ENABLE_MOD_MYSQL_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_2 = libhawk-mysql.la +@ENABLE_MOD_UCI_TRUE@@ENABLE_STATIC_MODULE_TRUE@am__append_3 = libhawk-uci.la +@ENABLE_MOD_FFI_TRUE@@ENABLE_STATIC_MODULE_FALSE@am__append_4 = libhawk-ffi.la +@ENABLE_MOD_MYSQL_TRUE@@ENABLE_STATIC_MODULE_FALSE@am__append_5 = libhawk-mysql.la +@ENABLE_MOD_UCI_TRUE@@ENABLE_STATIC_MODULE_FALSE@am__append_6 = libhawk-uci.la subdir = mod ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \ @@ -140,6 +142,25 @@ am__uninstall_files_from_dir = { \ am__installdirs = "$(DESTDIR)$(pkgmodexecdir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkgmodexec_LTLIBRARIES) am__DEPENDENCIES_1 = +@ENABLE_MOD_FFI_TRUE@libhawk_ffi_la_DEPENDENCIES = \ +@ENABLE_MOD_FFI_TRUE@ $(am__DEPENDENCIES_1) \ +@ENABLE_MOD_FFI_TRUE@ $(am__DEPENDENCIES_1) +am__libhawk_ffi_la_SOURCES_DIST = mod-ffi.c mod-ffi.h +@ENABLE_MOD_FFI_TRUE@am_libhawk_ffi_la_OBJECTS = \ +@ENABLE_MOD_FFI_TRUE@ libhawk_ffi_la-mod-ffi.lo +libhawk_ffi_la_OBJECTS = $(am_libhawk_ffi_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libhawk_ffi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libhawk_ffi_la_CFLAGS) $(CFLAGS) $(libhawk_ffi_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@ENABLE_MOD_FFI_TRUE@@ENABLE_STATIC_MODULE_FALSE@am_libhawk_ffi_la_rpath = \ +@ENABLE_MOD_FFI_TRUE@@ENABLE_STATIC_MODULE_FALSE@ -rpath \ +@ENABLE_MOD_FFI_TRUE@@ENABLE_STATIC_MODULE_FALSE@ $(pkgmodexecdir) +@ENABLE_MOD_FFI_TRUE@@ENABLE_STATIC_MODULE_TRUE@am_libhawk_ffi_la_rpath = @ENABLE_MOD_MYSQL_TRUE@libhawk_mysql_la_DEPENDENCIES = \ @ENABLE_MOD_MYSQL_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_MOD_MYSQL_TRUE@ $(am__DEPENDENCIES_1) @@ -147,10 +168,6 @@ am__libhawk_mysql_la_SOURCES_DIST = mod-mysql.c mod-mysql.h @ENABLE_MOD_MYSQL_TRUE@am_libhawk_mysql_la_OBJECTS = \ @ENABLE_MOD_MYSQL_TRUE@ libhawk_mysql_la-mod-mysql.lo libhawk_mysql_la_OBJECTS = $(am_libhawk_mysql_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = libhawk_mysql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libhawk_mysql_la_CFLAGS) $(CFLAGS) \ @@ -189,7 +206,8 @@ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/ac/depcomp am__maybe_remake_depfiles = depfiles -am__depfiles_remade = ./$(DEPDIR)/libhawk_mysql_la-mod-mysql.Plo \ +am__depfiles_remade = ./$(DEPDIR)/libhawk_ffi_la-mod-ffi.Plo \ + ./$(DEPDIR)/libhawk_mysql_la-mod-mysql.Plo \ ./$(DEPDIR)/libhawk_uci_la-mod-uci.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ @@ -210,8 +228,10 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(libhawk_mysql_la_SOURCES) $(libhawk_uci_la_SOURCES) -DIST_SOURCES = $(am__libhawk_mysql_la_SOURCES_DIST) \ +SOURCES = $(libhawk_ffi_la_SOURCES) $(libhawk_mysql_la_SOURCES) \ + $(libhawk_uci_la_SOURCES) +DIST_SOURCES = $(am__libhawk_ffi_la_SOURCES_DIST) \ + $(am__libhawk_mysql_la_SOURCES_DIST) \ $(am__libhawk_uci_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ @@ -411,14 +431,14 @@ CFLAGS_COMMON = #------------------------------------------------- # STATIC MODULES BUILT INTO MAIN LIBRARY #------------------------------------------------- -@ENABLE_STATIC_MODULE_TRUE@LDFLAGS_COMMON = -L$(libdir) -version-info 1:0:0 -no-undefined +@ENABLE_STATIC_MODULE_TRUE@LDFLAGS_COMMON = -L$(libdir) @ENABLE_STATIC_MODULE_FALSE@LIBADD_COMMON = -lhawk @ENABLE_STATIC_MODULE_TRUE@LIBADD_COMMON = @ENABLE_STATIC_MODULE_TRUE@noinst_LTLIBRARIES = $(am__append_1) \ -@ENABLE_STATIC_MODULE_TRUE@ $(am__append_2) +@ENABLE_STATIC_MODULE_TRUE@ $(am__append_2) $(am__append_3) @ENABLE_STATIC_MODULE_FALSE@pkgmodexecdir = $(libdir) -@ENABLE_STATIC_MODULE_FALSE@pkgmodexec_LTLIBRARIES = $(am__append_3) \ -@ENABLE_STATIC_MODULE_FALSE@ $(am__append_4) +@ENABLE_STATIC_MODULE_FALSE@pkgmodexec_LTLIBRARIES = $(am__append_4) \ +@ENABLE_STATIC_MODULE_FALSE@ $(am__append_5) $(am__append_6) ################################################## ################################################## @@ -426,6 +446,11 @@ CFLAGS_COMMON = #------------------------------------------------- # ACTUAL MODULES #------------------------------------------------- +@ENABLE_MOD_FFI_TRUE@libhawk_ffi_la_SOURCES = mod-ffi.c mod-ffi.h +@ENABLE_MOD_FFI_TRUE@libhawk_ffi_la_CPPFLAGS = $(CPPFLAGS_COMMON) $(MYSQL_CFLAGS) +@ENABLE_MOD_FFI_TRUE@libhawk_ffi_la_CFLAGS = $(CFLAGS_COMMON) +@ENABLE_MOD_FFI_TRUE@libhawk_ffi_la_LDFLAGS = $(LDFLAGS_COMMON) $(MYSQL_LDFLAGS) +@ENABLE_MOD_FFI_TRUE@libhawk_ffi_la_LIBADD = $(LIBADD_COMMON) $(MYSQL_LIBS) @ENABLE_MOD_MYSQL_TRUE@libhawk_mysql_la_SOURCES = mod-mysql.c mod-mysql.h @ENABLE_MOD_MYSQL_TRUE@libhawk_mysql_la_CPPFLAGS = $(CPPFLAGS_COMMON) $(MYSQL_CFLAGS) @ENABLE_MOD_MYSQL_TRUE@libhawk_mysql_la_CFLAGS = $(CFLAGS_COMMON) @@ -516,6 +541,9 @@ clean-pkgmodexecLTLIBRARIES: rm -f $${locs}; \ } +libhawk-ffi.la: $(libhawk_ffi_la_OBJECTS) $(libhawk_ffi_la_DEPENDENCIES) $(EXTRA_libhawk_ffi_la_DEPENDENCIES) + $(AM_V_CCLD)$(libhawk_ffi_la_LINK) $(am_libhawk_ffi_la_rpath) $(libhawk_ffi_la_OBJECTS) $(libhawk_ffi_la_LIBADD) $(LIBS) + libhawk-mysql.la: $(libhawk_mysql_la_OBJECTS) $(libhawk_mysql_la_DEPENDENCIES) $(EXTRA_libhawk_mysql_la_DEPENDENCIES) $(AM_V_CCLD)$(libhawk_mysql_la_LINK) $(am_libhawk_mysql_la_rpath) $(libhawk_mysql_la_OBJECTS) $(libhawk_mysql_la_LIBADD) $(LIBS) @@ -528,6 +556,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_ffi_la-mod-ffi.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_mysql_la-mod-mysql.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhawk_uci_la-mod-uci.Plo@am__quote@ # am--include-marker @@ -561,6 +590,13 @@ am--depfiles: $(am__depfiles_remade) @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< +libhawk_ffi_la-mod-ffi.lo: mod-ffi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_ffi_la_CPPFLAGS) $(CPPFLAGS) $(libhawk_ffi_la_CFLAGS) $(CFLAGS) -MT libhawk_ffi_la-mod-ffi.lo -MD -MP -MF $(DEPDIR)/libhawk_ffi_la-mod-ffi.Tpo -c -o libhawk_ffi_la-mod-ffi.lo `test -f 'mod-ffi.c' || echo '$(srcdir)/'`mod-ffi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhawk_ffi_la-mod-ffi.Tpo $(DEPDIR)/libhawk_ffi_la-mod-ffi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mod-ffi.c' object='libhawk_ffi_la-mod-ffi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_ffi_la_CPPFLAGS) $(CPPFLAGS) $(libhawk_ffi_la_CFLAGS) $(CFLAGS) -c -o libhawk_ffi_la-mod-ffi.lo `test -f 'mod-ffi.c' || echo '$(srcdir)/'`mod-ffi.c + libhawk_mysql_la-mod-mysql.lo: mod-mysql.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhawk_mysql_la_CPPFLAGS) $(CPPFLAGS) $(libhawk_mysql_la_CFLAGS) $(CFLAGS) -MT libhawk_mysql_la-mod-mysql.lo -MD -MP -MF $(DEPDIR)/libhawk_mysql_la-mod-mysql.Tpo -c -o libhawk_mysql_la-mod-mysql.lo `test -f 'mod-mysql.c' || echo '$(srcdir)/'`mod-mysql.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhawk_mysql_la-mod-mysql.Tpo $(DEPDIR)/libhawk_mysql_la-mod-mysql.Plo @@ -709,7 +745,8 @@ clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-pkgmodexecLTLIBRARIES mostlyclean-am distclean: distclean-am - -rm -f ./$(DEPDIR)/libhawk_mysql_la-mod-mysql.Plo + -rm -f ./$(DEPDIR)/libhawk_ffi_la-mod-ffi.Plo + -rm -f ./$(DEPDIR)/libhawk_mysql_la-mod-mysql.Plo -rm -f ./$(DEPDIR)/libhawk_uci_la-mod-uci.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ @@ -756,7 +793,8 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/libhawk_mysql_la-mod-mysql.Plo + -rm -f ./$(DEPDIR)/libhawk_ffi_la-mod-ffi.Plo + -rm -f ./$(DEPDIR)/libhawk_mysql_la-mod-mysql.Plo -rm -f ./$(DEPDIR)/libhawk_uci_la-mod-uci.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/hawk/mod/mod-ffi.c b/hawk/mod/mod-ffi.c new file mode 100644 index 00000000..10e27070 --- /dev/null +++ b/hawk/mod/mod-ffi.c @@ -0,0 +1,1245 @@ +/* + * $Id$ + * + Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#if 0 + +#include "mod-ffi.h" +#include + +#include +#include + +#if defined(HAVE_FFI_LIB) && defined(HAVE_FFI_H) +# define USE_LIBFFI +#elif defined(HAVE_DYNCALL_LIB) && defined(HAVE_DYNCALL_H) +# define USE_DYNCALL +#endif + +#if defined(USE_LIBFFI) +# include +# if (HAWK_SIZEOF_LONG_LONG > 0) && !defined(ffi_type_ulonglong) +# if HAWK_SIZEOF_LONG_LONG == HAWK_SIZEOF_INT32_T +# define ffi_type_ulonglong ffi_type_uint32 +# define ffi_type_slonglong ffi_type_sint32 +# elif HAWK_SIZEOF_LONG_LONG == HAWK_SIZEOF_INT64_T +# define ffi_type_ulonglong ffi_type_uint64 +# define ffi_type_slonglong ffi_type_sint64 +# endif +# endif +#elif defined(USE_DYNCALL) +# include + +#define __dcArgInt8 dcArgChar +#define __dcCallInt8 dcCallChar + +#define __dcArgInt16 dcArgShort +#define __dcCallInt16 dcCallShort + +#if (HAWK_SIZEOF_INT32_T == HAWK_SIZEOF_INT) +#define __dcArgInt32 dcArgInt +#define __dcCallInt32 dcCallInt +#elif (HAWK_SIZEOF_INT32_T == HAWK_SIZEOF_LONG) +#define __dcArgInt32 dcArgLong +#define __dcCallInt32 dcCallLong +#endif + +#if (HAWK_SIZEOF_INT64_T == HAWK_SIZEOF_LONG) +#define __dcArgInt64 dcArgLong +#define __dcCallInt64 dcCallLong +#elif (HAWK_SIZEOF_INT64_T == HAWK_SIZEOF_LONG_LONG) +#define __dcArgInt64 dcArgLongLong +#define __dcCallInt64 dcCallLongLong +#endif + + +#endif + +#define FMTC_NULL '\0' /* internal use only */ + +#define FMTC_CHAR 'c' +#define FMTC_SHORT 'h' +#define FMTC_INT 'i' +#define FMTC_LONG 'l' +#define FMTC_LONGLONG 'L' +#define FMTC_BCS 's' +#define FMTC_UCS 'S' +#define FMTC_BLOB 'b' +#define FMTC_POINTER 'p' + +#define FMTC_INT8 '1' +#define FMTC_INT16 '2' +#define FMTC_INT32 '4' +#define FMTC_INT64 '8' + +typedef struct link_t link_t; +struct link_t +{ + link_t* next; +}; + +#if defined(USE_LIBFFI) +typedef union ffi_sv_t ffi_sv_t; +union ffi_sv_t +{ + void* p; + unsigned char uc; + char c; + unsigned short int uh; + short h; + unsigned int ui; + int i; + unsigned long int ul; + long int l; +#if (HAWK_SIZEOF_LONG_LONG > 0) + unsigned long long int ull; + long long int ll; +#endif + + + hawk_uint8_t ui8; + hawk_int8_t i8; + hawk_uint16_t ui16; + hawk_int16_t i16; + hawk_uint32_t ui32; + hawk_int32_t i32; +#if (HAWK_SIZEOF_INT64_T > 0) + hawk_uint64_t ui64; + hawk_int64_t i64; +#endif +}; +#endif + +typedef struct ffi_t ffi_t; +struct ffi_t +{ + void* handle; + +#if defined(USE_DYNCALL) + DCCallVM* dc; +#elif defined(USE_LIBFFI) + hawk_oow_t arg_count; + hawk_oow_t arg_max; + ffi_type** arg_types; + void** arg_values; + ffi_sv_t* arg_svs; + + ffi_sv_t ret_sv; + ffi_cif cif; + ffi_type* fmtc_to_type[2][128]; +#endif + + link_t* ca; /* call arguments duplicated */ +}; + + +static HAWK_INLINE void link_ca (ffi_t* ffi, void* ptr) +{ + link_t* l = (link_t*)((hawk_oob_t*)ptr - HAWK_SIZEOF_VOID_P); + l->next = ffi->ca; + ffi->ca = l; +} + +static void free_linked_cas (hawk_t* hawk, ffi_t* ffi) +{ + while (ffi->ca) + { + link_t* ptr; + ptr = ffi->ca; + ffi->ca = ptr->next; + hawk_freemem (hawk, ptr); + } +} + +static hawk_pfrc_t fnc_open (hawk_t* hawk, hawk_mod_t* mod, hawk_ooi_t nargs) +{ + ffi_t* ffi; + hawk_oop_t name; + void* handle; +#if defined(USE_DYNCALL) + DCCallVM* dc; +#endif + + HAWK_ASSERT (hawk, nargs == 1); + + ffi = (ffi_t*)hawk_getobjtrailer(hawk, HAWK_STACK_GETRCV(hawk, nargs), HAWK_NULL); + name = HAWK_STACK_GETARG(hawk, nargs, 0); + + if (!HAWK_OBJ_IS_CHAR_POINTER(name)) + { + hawk_seterrnum (hawk, HAWK_EINVAL); + goto softfail; + } + + if (!hawk->vmprim.dl_open) + { + hawk_seterrnum (hawk, HAWK_ENOIMPL); + goto softfail; + } + + if (ffi->handle) + { + hawk_seterrnum (hawk, HAWK_EPERM); /* no allowed to open again */ + goto softfail; + } + + handle = hawk->vmprim.dl_open(hawk, HAWK_OBJ_GET_CHAR_SLOT(name), 0); + if (!handle) goto softfail; + +#if defined(USE_DYNCALL) + dc = dcNewCallVM(4096); /* TODO: right size? */ + if (!dc) + { + hawk_seterrwithsyserr (hawk, 0, errno); + hawk->vmprim.dl_close (hawk, handle); + goto softfail; + } +#endif + + ffi->handle = handle; + +#if defined(USE_DYNCALL) + ffi->dc = dc; +#elif defined(USE_LIBFFI) + ffi->fmtc_to_type[0][FMTC_NULL] = &ffi_type_void; + ffi->fmtc_to_type[1][FMTC_NULL] = &ffi_type_void; + + ffi->fmtc_to_type[0][FMTC_CHAR] = &ffi_type_schar; + ffi->fmtc_to_type[1][FMTC_CHAR] = &ffi_type_uchar; + ffi->fmtc_to_type[0][FMTC_SHORT] = &ffi_type_sshort; + ffi->fmtc_to_type[1][FMTC_SHORT] = &ffi_type_ushort; + ffi->fmtc_to_type[0][FMTC_INT] = &ffi_type_sint; + ffi->fmtc_to_type[1][FMTC_INT] = &ffi_type_uint; + ffi->fmtc_to_type[0][FMTC_LONG] = &ffi_type_slong; + ffi->fmtc_to_type[1][FMTC_LONG] = &ffi_type_ulong; + #if (HAWK_SIZEOF_LONG_LONG > 0) + ffi->fmtc_to_type[0][FMTC_LONGLONG] = &ffi_type_slonglong; + ffi->fmtc_to_type[1][FMTC_LONGLONG] = &ffi_type_ulonglong; + #endif + ffi->fmtc_to_type[0][FMTC_INT8] = &ffi_type_sint8; + ffi->fmtc_to_type[1][FMTC_INT8] = &ffi_type_uint8; + ffi->fmtc_to_type[0][FMTC_INT16] = &ffi_type_sint16; + ffi->fmtc_to_type[1][FMTC_INT16] = &ffi_type_uint16; + ffi->fmtc_to_type[0][FMTC_INT32] = &ffi_type_sint32; + ffi->fmtc_to_type[1][FMTC_INT32] = &ffi_type_uint32; + ffi->fmtc_to_type[0][FMTC_INT64] = &ffi_type_sint64; + ffi->fmtc_to_type[1][FMTC_INT64] = &ffi_type_uint64; + + ffi->fmtc_to_type[0][FMTC_POINTER] = &ffi_type_pointer; + ffi->fmtc_to_type[1][FMTC_POINTER] = &ffi_type_pointer; + ffi->fmtc_to_type[0][FMTC_BCS] = &ffi_type_pointer; + ffi->fmtc_to_type[1][FMTC_BCS] = &ffi_type_pointer; + ffi->fmtc_to_type[0][FMTC_UCS] = &ffi_type_pointer; + ffi->fmtc_to_type[1][FMTC_UCS] = &ffi_type_pointer; +#endif + + HAWK_DEBUG3 (hawk, " %.*js => %p\n", HAWK_OBJ_GET_SIZE(name), HAWK_OBJ_GET_CHAR_SLOT(name), ffi->handle); + HAWK_STACK_SETRETTORCV (hawk, nargs); + return HAWK_PF_SUCCESS; + +softfail: + HAWK_STACK_SETRETTOERRNUM (hawk, nargs); + return HAWK_PF_SUCCESS; +} + +static hawk_pfrc_t fnc_close (hawk_t* hawk, hawk_mod_t* mod, hawk_ooi_t nargs) +{ + ffi_t* ffi; + + HAWK_ASSERT (hawk, nargs == 0); + + ffi = (ffi_t*)hawk_getobjtrailer(hawk, HAWK_STACK_GETRCV(hawk, nargs), HAWK_NULL); + + if (!hawk->vmprim.dl_open) + { + hawk_seterrnum (hawk, HAWK_ENOIMPL); + goto softfail; + } + + HAWK_DEBUG1 (hawk, " %p\n", ffi->handle); + + free_linked_cas (hawk, ffi); + +#if defined(USE_DYNCALL) + dcFree (ffi->dc); + ffi->dc = HAWK_NULL; +#elif defined(USE_LIBFFI) + if (ffi->arg_types) + { + hawk_freemem (hawk, ffi->arg_types); + ffi->arg_types = HAWK_NULL; + } + if (ffi->arg_values) + { + hawk_freemem (hawk, ffi->arg_values); + ffi->arg_values = HAWK_NULL; + } + if (ffi->arg_svs) + { + hawk_freemem (hawk, ffi->arg_svs); + ffi->arg_svs = HAWK_NULL; + } + ffi->arg_max = 0; + ffi->arg_count = 0; +#endif + + hawk->vmprim.dl_close (hawk, ffi->handle); + ffi->handle = HAWK_NULL; + + HAWK_STACK_SETRETTORCV (hawk, nargs); + return HAWK_PF_SUCCESS; + +softfail: + HAWK_STACK_SETRETTOERRNUM (hawk, nargs); + return HAWK_PF_SUCCESS; +} + +static HAWK_INLINE int add_ffi_arg (hawk_t* hawk, ffi_t* ffi, hawk_ooch_t fmtc, int _unsigned, hawk_oop_t arg) +{ +#if defined(USE_LIBFFI) + if (ffi->arg_count >= ffi->arg_max) + { + ffi_type** ttmp; + void** vtmp; + ffi_sv_t* stmp; + + hawk_oow_t newmax; + + newmax = ffi->arg_max + 16; /* TODO: adjust this? */ + ttmp = hawk_reallocmem(hawk, ffi->arg_types, HAWK_SIZEOF(*ttmp) * newmax); + if (!ttmp) goto oops; + vtmp = hawk_reallocmem(hawk, ffi->arg_values, HAWK_SIZEOF(*vtmp) * newmax); + if (!vtmp) goto oops; + stmp = hawk_reallocmem(hawk, ffi->arg_svs, HAWK_SIZEOF(*stmp) * newmax); + if (!stmp) goto oops; + + ffi->arg_types = ttmp; + ffi->arg_values = vtmp; + ffi->arg_svs = stmp; + ffi->arg_max = newmax; + } +#endif + + switch (fmtc) + { + case FMTC_INT8: + if (_unsigned) + { + hawk_oow_t v; + if (HAWK_OOP_IS_CHAR(arg)) v = HAWK_OOP_TO_CHAR(arg); + else if (hawk_inttooow_noseterr(hawk, arg, &v) <= 0) goto inval_arg_value;; + #if defined(USE_DYNCALL) + __dcArgInt8 (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].ui8; + ffi->arg_svs[ffi->arg_count].ui8 = v; + #endif + } + else + { + hawk_ooi_t v; + if (HAWK_OOP_IS_CHAR(arg)) v = HAWK_OOP_TO_CHAR(arg); + else if (hawk_inttoooi_noseterr(hawk, arg, &v) == 0) goto inval_arg_value;; + #if defined(USE_DYNCALL) + __dcArgInt8 (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].i8; + ffi->arg_svs[ffi->arg_count].i8 = v; + #endif + } + break; + + case FMTC_INT16: + if (_unsigned) + { + hawk_oow_t v; + if (hawk_inttooow_noseterr(hawk, arg, &v) <= 0) goto inval_arg_value;; + #if defined(USE_DYNCALL) + __dcArgInt16 (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].ui16; + ffi->arg_svs[ffi->arg_count].ui16 = v; + #endif + } + else + { + hawk_ooi_t v; + if (hawk_inttoooi_noseterr(hawk, arg, &v) == 0) goto inval_arg_value;; + #if defined(USE_DYNCALL) + __dcArgInt16 (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].i16; + ffi->arg_svs[ffi->arg_count].i16 = v; + #endif + } + break; + + + case FMTC_INT32: + if (_unsigned) + { + hawk_oow_t v; + if (hawk_inttooow_noseterr(hawk, arg, &v) <= 0) goto inval_arg_value;; + #if defined(USE_DYNCALL) + __dcArgInt32 (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].ui32; + ffi->arg_svs[ffi->arg_count].ui32 = v; + #endif + } + else + { + hawk_ooi_t v; + if (hawk_inttoooi_noseterr(hawk, arg, &v) == 0) goto inval_arg_value;; + #if defined(USE_DYNCALL) + __dcArgInt32 (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].i32; + ffi->arg_svs[ffi->arg_count].i32 = v; + #endif + } + break; + + + case FMTC_INT64: + #if (HAWK_SIZEOF_INT64_T > 0) + if (_unsigned) + { + hawk_oow_t v; + if (hawk_inttooow_noseterr(hawk, arg, &v) <= 0) goto inval_arg_value; + #if defined(USE_DYNCALL) + __dcArgInt64 (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].ui64; + ffi->arg_svs[ffi->arg_count].ui64 = v; + #endif + } + else + { + hawk_ooi_t v; + if (hawk_inttoooi_noseterr(hawk, arg, &v) == 0) goto inval_arg_value; + #if defined(USE_DYNCALL) + __dcArgInt64 (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].i64; + ffi->arg_svs[ffi->arg_count].i64 = v; + #endif + } + break; + #else + goto inval_sig_ch; + #endif + + case FMTC_CHAR: /* this is a byte */ + if (_unsigned) + { + hawk_oow_t v; + if (HAWK_OOP_IS_CHAR(arg)) v = HAWK_OOP_TO_CHAR(arg); + else if (hawk_inttooow_noseterr(hawk, arg, &v) <= 0) goto inval_arg_value;; + #if defined(USE_DYNCALL) + dcArgChar (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].uc; + ffi->arg_svs[ffi->arg_count].uc = v; + #endif + } + else + { + hawk_ooi_t v; + if (HAWK_OOP_IS_CHAR(arg)) v = HAWK_OOP_TO_CHAR(arg); + else if (hawk_inttoooi_noseterr(hawk, arg, &v) == 0) goto inval_arg_value;; + #if defined(USE_DYNCALL) + dcArgChar (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].c; + ffi->arg_svs[ffi->arg_count].c = v; + #endif + } + break; + + case FMTC_SHORT: + if (_unsigned) + { + hawk_oow_t v; + if (hawk_inttooow_noseterr(hawk, arg, &v) <= 0) goto inval_arg_value; + #if defined(USE_DYNCALL) + dcArgShort (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].uh; + ffi->arg_svs[ffi->arg_count].uh = v; + #endif + } + else + { + hawk_ooi_t v; + if (hawk_inttoooi_noseterr(hawk, arg, &v) == 0) goto inval_arg_value; + #if defined(USE_DYNCALL) + dcArgShort (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].h; + ffi->arg_svs[ffi->arg_count].h = v; + #endif + } + break; + + case FMTC_INT: + if (_unsigned) + { + hawk_oow_t v; + if (hawk_inttooow_noseterr(hawk, arg, &v) <= 0) goto inval_arg_value; + #if defined(USE_DYNCALL) + dcArgInt (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].ui; + ffi->arg_svs[ffi->arg_count].ui = v; + #endif + } + else + { + hawk_ooi_t v; + if (hawk_inttoooi_noseterr(hawk, arg, &v) == 0) goto inval_arg_value; + #if defined(USE_DYNCALL) + dcArgInt (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].i; + ffi->arg_svs[ffi->arg_count].i = v; + #endif + } + break; + + case FMTC_LONG: + arg_as_long: + if (_unsigned) + { + hawk_oow_t v; + if (hawk_inttooow_noseterr(hawk, arg, &v) <= 0) goto inval_arg_value; + #if defined(USE_DYNCALL) + dcArgLong (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].ul; + ffi->arg_svs[ffi->arg_count].ul = v; + #endif + } + else + { + hawk_ooi_t v; + if (hawk_inttoooi_noseterr(hawk, arg, &v) == 0) goto inval_arg_value;; + #if defined(USE_DYNCALL) + dcArgLong (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].l; + ffi->arg_svs[ffi->arg_count].l = v; + #endif + } + break; + + case FMTC_LONGLONG: + #if (HAWK_SIZEOF_LONG_LONG <= HAWK_SIZEOF_LONG) + goto arg_as_long; + #else + if (_unsigned) + { + hawk_uintmax_t v; + if (hawk_inttouintmax_noseterr(hawk, arg, &v) <= 0) goto inval_arg_value; + #if defined(USE_DYNCALL) + dcArgLongLong (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].ull; + ffi->arg_svs[ffi->arg_count].ull = v; + #endif + } + else + { + hawk_intmax_t v; + if (hawk_inttointmax_noseterr(hawk, arg, &v) == 0) goto inval_arg_value; + #if defined(USE_DYNCALL) + dcArgLongLong (ffi->dc, v); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].ll; + ffi->arg_svs[ffi->arg_count].ll = v; + #endif + } + break; + #endif + + case FMTC_BCS: + { + hawk_bch_t* ptr; + + if (!HAWK_OBJ_IS_CHAR_POINTER(arg)) goto inval_arg_value; + + #if defined(HAWK_OOCH_IS_UCH) + ptr = hawk_dupootobcharswithheadroom(hawk, HAWK_SIZEOF_VOID_P, HAWK_OBJ_GET_CHAR_SLOT(arg), HAWK_OBJ_GET_SIZE(arg), HAWK_NULL); + if (!ptr) goto oops; /* out of system memory or conversion error - soft failure */ + link_ca (ffi, ptr); + #else + ptr = HAWK_OBJ_GET_CHAR_SLOT(arg); + /*ptr = hawk_dupoochars(hawk, HAWK_OBJ_GET_CHAR_SLOT(arg), HAWK_OBJ_GET_SIZE(arg)); + if (!ptr) goto oops;*/ /* out of system memory or conversion error - soft failure */ + #endif + + #if defined(USE_DYNCALL) + dcArgPointer (ffi->dc, ptr); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].p; + ffi->arg_svs[ffi->arg_count].p = ptr; + #endif + break; + } + + case FMTC_UCS: + { + hawk_uch_t* ptr; + + if (!HAWK_OBJ_IS_CHAR_POINTER(arg)) goto inval_arg_value; + + #if defined(HAWK_OOCH_IS_UCH) + ptr = HAWK_OBJ_GET_CHAR_SLOT(arg); + /*ptr = hawk_dupoochars(hawk, HAWK_OBJ_GET_CHAR_SLOT(arg), HAWK_OBJ_GET_SIZE(arg)); + if (!ptr) goto oops; */ /* out of system memory or conversion error - soft failure */ + #else + ptr = hawk_dupootoucharswithheadroom(hawk, HAWK_SIZEOF_VOID_P, HAWK_OBJ_GET_CHAR_SLOT(arg), HAWK_OBJ_GET_SIZE(arg), HAWK_NULL); + if (!ptr) goto oops; /* out of system memory or conversion error - soft failure */ + link_ca (ffi, ptr); + #endif + + #if defined(USE_DYNCALL) + dcArgPointer (ffi->dc, ptr); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].p; + ffi->arg_svs[ffi->arg_count].p = ptr; + #endif + break; + } + + case FMTC_BLOB: + { + void* ptr; + + if (HAWK_OBJ_IS_BYTE_POINTER(arg)) goto inval_arg_value; + ptr = HAWK_OBJ_GET_BYTE_SLOT(arg); + + #if defined(USE_DYNCALL) + dcArgPointer (ffi->dc, ptr); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].p; + ffi->arg_svs[ffi->arg_count].p = ptr; + #endif + break; + } + + case FMTC_POINTER: + { + void* ptr; + + /* TODO: map nil to NULL? or should #\p0 be enough? */ + if (!HAWK_OOP_IS_SMPTR(arg)) goto inval_arg_value; + ptr = HAWK_OOP_TO_SMPTR(arg); + + #if defined(USE_DYNCALL) + dcArgPointer (ffi->dc, ptr); + #elif defined(USE_LIBFFI) + ffi->arg_values[ffi->arg_count] = &ffi->arg_svs[ffi->arg_count].p; + ffi->arg_svs[ffi->arg_count].p = ptr; + #endif + break; + } + + default: + inval_sig_ch: + /* invalid argument signature specifier */ + hawk_seterrbfmt (hawk, HAWK_EINVAL, "invalid argument type signature - %jc", fmtc); + goto oops; + } + +#if defined(USE_LIBFFI) + ffi->arg_types[ffi->arg_count] = ffi->fmtc_to_type[_unsigned][fmtc]; + ffi->arg_count++; +#endif + return 0; + +inval_arg_value: + hawk_seterrbfmt (hawk, HAWK_EINVAL, "invalid argument value - %O", arg); + +oops: + return -1; +} + + +static hawk_pfrc_t fnc_call (hawk_t* hawk, hawk_mod_t* mod, hawk_ooi_t nargs) +{ +#if defined(USE_DYNCALL) || defined(USE_LIBFFI) + ffi_t* ffi; + hawk_oop_t fun, sig, args; + hawk_oow_t i, j, nfixedargs, _unsigned; + void* f; + hawk_oop_oop_t arr; + int vbar = 0; + hawk_ooch_t fmtc; + #if defined(USE_LIBFFI) + ffi_status fs; + #endif + + ffi = (ffi_t*)hawk_getobjtrailer(hawk, HAWK_STACK_GETRCV(hawk, nargs), HAWK_NULL); + + fun = HAWK_STACK_GETARG(hawk, nargs, 0); + sig = HAWK_STACK_GETARG(hawk, nargs, 1); + args = HAWK_STACK_GETARG(hawk, nargs, 2); + + if (hawk_ptrtooow(hawk, fun, (hawk_oow_t*)&f) <= -1) goto softfail; + + /* the signature must not be empty. at least the return type must be + * specified */ + if (!HAWK_OBJ_IS_CHAR_POINTER(sig) || HAWK_OBJ_GET_SIZE(sig) <= 0) goto inval; + +#if 0 + /* TODO: check if arr is a kind of array??? or check if it's indexed */ + if (HAWK_OBJ_GET_SIZE(sig) > 1 && HAWK_CLASSOF(hawk,args) != hawk->_array) goto inval; +#endif + + arr = (hawk_oop_oop_t)args; + /*HAWK_DEBUG2 (hawk, " %p in %p\n", f, ffi->handle);*/ + +#if defined(USE_DYNCALL) + dcMode (ffi->dc, DC_CALL_C_DEFAULT); + dcReset (ffi->dc); + + for (i = 0; i < HAWK_OBJ_GET_SIZE(sig); i++) + { + fmtc = HAWK_OBJ_GET_CHAR_VAL(sig, i); + if (fmtc == '>') break; /* end of arguments. start of return type */ + if (fmtc == '|') + { + dcMode (ffi->dc, DC_CALL_C_ELLIPSIS); /* variadic. for arguments before ... */ + /* the error code should be DC_ERROR_UNSUPPORTED_MODE */ + if (dcGetError(ffi->dc) != DC_ERROR_NONE) goto noimpl; + dcReset (ffi->dc); + break; + } + } +#else + ffi->arg_count = 0; +#endif + + /* check argument signature */ + for (i = 0, j = 0, nfixedargs = 0, _unsigned = 0; i < HAWK_OBJ_GET_SIZE(sig); i++) + { + fmtc = HAWK_OBJ_GET_CHAR_VAL(sig, i); + if (fmtc == ' ') + { + continue; + } + if (fmtc == '>') + { + i++; + if (!vbar) nfixedargs = j; + break; + } + else if (fmtc == '|') + { + if (!vbar) + { + #if defined(USE_DYNCALL) + dcMode (ffi->dc, DC_CALL_C_ELLIPSIS_VARARGS); /* start of arguments that fall to the ... part */ + /* the error code should be DC_ERROR_UNSUPPORTED_MODE */ + if (dcGetError(ffi->dc) != DC_ERROR_NONE) goto noimpl; + #endif + nfixedargs = j; + vbar = 1; + } + continue; + } + else if (fmtc == 'u') + { + _unsigned = 1; + continue; + } + + /* more items in signature than the actual argument */ + if (j >= HAWK_OBJ_GET_SIZE(arr)) goto inval; + + if (add_ffi_arg(hawk, ffi, fmtc, _unsigned, HAWK_OBJ_GET_OOP_VAL(arr, j)) <= -1) goto softfail; + _unsigned = 0; + j++; + } + + while (i < HAWK_OBJ_GET_SIZE(sig) && HAWK_OBJ_GET_CHAR_VAL(sig, i) == ' ') i++; /* skip all spaces after > */ + + fmtc = (i >= HAWK_OBJ_GET_SIZE(sig)? FMTC_NULL: HAWK_OBJ_GET_CHAR_VAL(sig, i)); +#if defined(USE_LIBFFI) + fs = (nfixedargs == j)? ffi_prep_cif(&ffi->cif, FFI_DEFAULT_ABI, j, ffi->fmtc_to_type[0][fmtc], ffi->arg_types): + ffi_prep_cif_var(&ffi->cif, FFI_DEFAULT_ABI, nfixedargs, j, ffi->fmtc_to_type[0][fmtc], ffi->arg_types); + if (fs != FFI_OK) + { + hawk_seterrnum (hawk, HAWK_ESYSERR); + goto softfail; + } + + ffi_call (&ffi->cif, FFI_FN(f), &ffi->ret_sv, ffi->arg_values); +#endif + + if (fmtc == 'u') + { + _unsigned = 1; + fmtc++; + } + else + { + _unsigned = 0; + } + + /* check the return value type in signature */ + switch (fmtc) + { +/* TODO: support more types... */ +/* TODO: proper return value conversion */ + case FMTC_INT8: + { + hawk_oop_t r; + if (_unsigned) + { + #if defined(USE_DYNCALL) + r = hawk_oowtoint(hawk, __dcCallInt8(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_oowtoint(hawk, ffi->ret_sv.ui8); + #endif + } + else + { + #if defined(USE_DYNCALL) + r = hawk_ooitoint(hawk, __dcCallInt8(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_ooitoint(hawk, ffi->ret_sv.i8); + #endif + } + if (!r) goto hardfail; + + HAWK_STACK_SETRET (hawk, nargs, r); + break; + } + + case FMTC_INT16: + { + hawk_oop_t r; + if (_unsigned) + { + #if defined(USE_DYNCALL) + r = hawk_oowtoint(hawk, __dcCallInt16(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_oowtoint(hawk, ffi->ret_sv.ui16); + #endif + } + else + { + #if defined(USE_DYNCALL) + r = hawk_ooitoint(hawk, __dcCallInt16(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_ooitoint(hawk, ffi->ret_sv.i16); + #endif + } + if (!r) goto hardfail; + + HAWK_STACK_SETRET (hawk, nargs, r); + break; + } + + case FMTC_INT32: + { + hawk_oop_t r; + if (_unsigned) + { + #if defined(USE_DYNCALL) + r = hawk_oowtoint(hawk, __dcCallInt32(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_oowtoint(hawk, ffi->ret_sv.ui32); + #endif + } + else + { + #if defined(USE_DYNCALL) + r = hawk_ooitoint(hawk, __dcCallInt32(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_ooitoint(hawk, ffi->ret_sv.i32); + #endif + } + if (!r) goto hardfail; + + HAWK_STACK_SETRET (hawk, nargs, r); + break; + } + + case FMTC_INT64: + { + #if (HAWK_SIZEOF_INT64_T > 0) + hawk_oop_t r; + if (_unsigned) + { + #if defined(USE_DYNCALL) + r = hawk_oowtoint(hawk, __dcCallInt64(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_oowtoint(hawk, ffi->ret_sv.ui64); + #endif + } + else + { + #if defined(USE_DYNCALL) + r = hawk_ooitoint(hawk, __dcCallInt64(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_ooitoint(hawk, ffi->ret_sv.i64); + #endif + } + if (!r) goto hardfail; + + HAWK_STACK_SETRET (hawk, nargs, r); + break; + #else + hawk_seterrbfmt (hawk, HAWK_EINVAL, "invalid return type signature - %jc", fmtc); + goto softfail; + #endif + } + + + case FMTC_CHAR: + { + #if defined(USE_DYNCALL) + char r = dcCallChar(ffi->dc, f); + HAWK_STACK_SETRET (hawk, nargs, HAWK_CHAR_TO_OOP(r)); + #elif defined(USE_LIBFFI) + if (_unsigned) + { + HAWK_STACK_SETRET (hawk, nargs, HAWK_CHAR_TO_OOP(ffi->ret_sv.uc)); + } + else + { + HAWK_STACK_SETRET (hawk, nargs, HAWK_CHAR_TO_OOP(ffi->ret_sv.c)); + } + #endif + break; + } + + case FMTC_SHORT: + { + hawk_oop_t r; + if (_unsigned) + { + #if defined(USE_DYNCALL) + r = hawk_oowtoint(hawk, dcCallShort(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_oowtoint(hawk, ffi->ret_sv.uh); + #endif + } + else + { + #if defined(USE_DYNCALL) + r = hawk_ooitoint(hawk, dcCallShort(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_ooitoint(hawk, ffi->ret_sv.h); + #endif + } + if (!r) goto hardfail; + + HAWK_STACK_SETRET (hawk, nargs, r); + break; + } + + case FMTC_INT: + { + hawk_oop_t r; + if (_unsigned) + { + #if defined(USE_DYNCALL) + r = hawk_oowtoint(hawk, dcCallInt(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_oowtoint(hawk, ffi->ret_sv.ui); + #endif + } + else + { + #if defined(USE_DYNCALL) + r = hawk_ooitoint(hawk, dcCallInt(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_ooitoint(hawk, ffi->ret_sv.i); + #endif + } + if (!r) goto hardfail; + HAWK_STACK_SETRET (hawk, nargs, r); + break; + } + + case FMTC_LONG: + { + hawk_oop_t r; + ret_as_long: + if (_unsigned) + { + #if defined(USE_DYNCALL) + r = hawk_oowtoint(hawk, dcCallLong(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_oowtoint(hawk, ffi->ret_sv.ul); + #endif + } + else + { + #if defined(USE_DYNCALL) + r = hawk_ooitoint(hawk, dcCallLong(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_ooitoint(hawk, ffi->ret_sv.l); + #endif + } + if (!r) goto hardfail; + HAWK_STACK_SETRET (hawk, nargs, r); + break; + } + + case FMTC_LONGLONG: + { + #if (HAWK_SIZEOF_LONG_LONG <= HAWK_SIZEOF_LONG) + goto ret_as_long; + #else + hawk_oop_t r; + if (_unsigned) + { + #if defined(USE_DYNCALL) + r = hawk_uintmaxtoint(hawk, dcCallLongLong(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_uintmaxtoint(hawk, ffi->ret_sv.ull); + #endif + } + else + { + #if defined(USE_DYNCALL) + r = hawk_intmaxtoint(hawk, dcCallLongLong(ffi->dc, f)); + #elif defined(USE_LIBFFI) + r = hawk_intmaxtoint(hawk, ffi->ret_sv.ll); + #endif + } + if (!r) goto hardfail; + HAWK_STACK_SETRET (hawk, nargs, r); + break; + #endif + } + + case FMTC_BCS: + { + hawk_oop_t s; + hawk_bch_t* r; + + #if defined(USE_DYNCALL) + r = dcCallPointer(ffi->dc, f); + #elif defined(USE_LIBFFI) + r = ffi->ret_sv.p; + #endif + + #if defined(HAWK_OOCH_IS_UCH) + s = hawk_makestringwithbchars(hawk, r, hawk_count_bcstr(r)); + #else + s = hawk_makestring(hawk, r, hawk_count_bcstr(r)); + #endif + if (!s) + { + if (hawk->errnum == HAWK_EOOMEM) goto hardfail; /* out of object memory - hard failure*/ + goto softfail; + } + + HAWK_STACK_SETRET (hawk, nargs, s); + break; + } + + case FMTC_UCS: + { + hawk_oop_t s; + hawk_uch_t* r; + + #if defined(USE_DYNCALL) + r = dcCallPointer(ffi->dc, f); + #elif defined(USE_LIBFFI) + r = ffi->ret_sv.p; + #endif + + #if defined(HAWK_OOCH_IS_UCH) + s = hawk_makestring(hawk, r, hawk_count_ucstr(r)); + #else + s = hawk_makestringwithuchars(hawk, r, hawk_count_ucstr(r)); + #endif + if (!s) + { + if (hawk->errnum == HAWK_EOOMEM) goto hardfail; /* out of object memory - hard failure*/ + goto softfail; + } + + HAWK_STACK_SETRET (hawk, nargs, s); + break; + } + + +#if 0 + case FMTC_BLOB: + { + /* blob as a return type isn't sufficient as it lacks the size information. + * blob as an argument is just a pointer and the size can be yet another argument. + * it there a good way to represent this here?... TODO: */ + break; + } +#endif + + case FMTC_POINTER: + { + void* r; + + #if defined(USE_DYNCALL) + r = dcCallPointer(ffi->dc, f); + #elif defined(USE_LIBFFI) + r = ffi->ret_sv.p; + #endif + + if (!HAWK_IN_SMPTR_RANGE(r)) + { + /* the returned pointer is not aligned */ + goto inval; + } + + HAWK_STACK_SETRET (hawk, nargs, HAWK_SMPTR_TO_OOP(r)); + break; + } + + default: + #if defined(USE_DYNCALL) + dcCallVoid (ffi->dc, f); + #endif + HAWK_STACK_SETRETTORCV (hawk, nargs); + break; + } + + free_linked_cas (hawk, ffi); + return HAWK_PF_SUCCESS; + +noimpl: + hawk_seterrnum (hawk, HAWK_ENOIMPL); + goto softfail; + +inval: + hawk_seterrnum (hawk, HAWK_EINVAL); + goto softfail; + +softfail: + free_linked_cas (hawk, ffi); + HAWK_STACK_SETRETTOERRNUM (hawk, nargs); + return HAWK_PF_SUCCESS; + +hardfail: + free_linked_cas (hawk, ffi); + return HAWK_PF_HARD_FAILURE; + +#else + hawk_seterrnum (hawk, HAWK_ENOIMPL); + HAWK_STACK_SETRETTOERRNUM (hawk, nargs); + return HAWK_PF_SUCCESS; +#endif +} + +static hawk_pfrc_t fnc_getsym (hawk_t* hawk, hawk_mod_t* mod, hawk_ooi_t nargs) +{ + ffi_t* ffi; + hawk_oop_t name, ret; + void* sym; + + HAWK_ASSERT (hawk, nargs == 1); + + ffi = (ffi_t*)hawk_getobjtrailer(hawk, HAWK_STACK_GETRCV(hawk, nargs), HAWK_NULL); + name = HAWK_STACK_GETARG(hawk, nargs, 0); + + if (!HAWK_OBJ_IS_CHAR_POINTER(name)) + { + hawk_seterrnum (hawk, HAWK_EINVAL); + goto softfail; + } + + if (!hawk->vmprim.dl_getsym) + { + hawk_seterrnum (hawk, HAWK_ENOIMPL); + goto softfail; + } + + sym = hawk->vmprim.dl_getsym(hawk, ffi->handle, HAWK_OBJ_GET_CHAR_SLOT(name)); + if (!sym) goto softfail; + + HAWK_DEBUG4 (hawk, " %.*js => %p in %p\n", HAWK_OBJ_GET_SIZE(name), HAWK_OBJ_GET_CHAR_SLOT(name), sym, ffi->handle); + + ret = hawk_oowtoptr(hawk, (hawk_oow_t)sym); + if (!ret) goto softfail; + + HAWK_STACK_SETRET (hawk, nargs, ret); + return HAWK_PF_SUCCESS; + +softfail: + HAWK_STACK_SETRETTOERRNUM (hawk, nargs); + return HAWK_PF_SUCCESS; +} + +/* ------------------------------------------------------------------------ */ + +#define C HAWK_METHOD_CLASS +#define I HAWK_METHOD_INSTANCE + +#define MA HAWK_TYPE_MAX(hawk_oow_t) + +static hawk_mod_fnc_tab_t pfinfos[] = +{ + { HAWK_T("call"), { { 3, 3, HAWK_NULL }, fnc_call, 0 } }, + { HAWK_T("close"), { { 0, 0, HAWK_NULL }, fnc_close, 0 } }, + { HAWK_T("getsym"), { { 1, 1, HAWK_NULL }, fnc_getsym, 0 } }, + { HAWK_T("open"), { { 1, 1, HAWK_NULL }, fnc_open, 0 } } +}; + +/* ------------------------------------------------------------------------ */ + +static int import (hawk_t* hawk, hawk_mod_t* mod, hawk_oop_class_t _class) +{ + if (hawk_setclasstrsize(hawk, _class, HAWK_SIZEOF(ffi_t), HAWK_NULL) <= -1) return -1; + return 0; +} + +static int query (hawk_mod_t* mod, hawk_t* awk, const hawk_ooch_t* name, hawk_mod_sym_t* sym) +{ + ///hawk_findmodsymfnc(hawk, pfinfos, HAWK_COUNTOF(pfinfos), name, namelen); +} + + +static void unload (hawk_t* hawk, hawk_mod_t* mod) +{ + /* TODO: anything? close open open dll handles? For that, fnc_open must store the value it returns to mod->ctx or somewhere..*/ + /* TODO: track all opened shared objects... clear all external memories/resources created but not cleared (for lacking the call to 'close') */ +} + +int hawk_mod_ffi (hawk_t* hawk, hawk_mod_t* mod) +{ + mod->import = import; + mod->query = query; + mod->unload = unload; + mod->ctx = HAWK_NULL; + return 0; +} + + +#endif diff --git a/hawk/mod/mod-ffi.h b/hawk/mod/mod-ffi.h new file mode 100644 index 00000000..0410abee --- /dev/null +++ b/hawk/mod/mod-ffi.h @@ -0,0 +1,43 @@ +/* + * $Id$ + * + Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HAWK_MOD_FFI_H_ +#define _HAWK_MOD_FFI_H_ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +HAWK_EXPORT int hawk_mod_ffi (hawk_t* hawk, hawk_mod_t* mod); + +#if defined(__cplusplus) +} +#endif + +#endif +