2017-01-09 13:41:11 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
2017-01-10 14:27:31 +00:00
|
|
|
Copyright (c) 2014-2017 Chung, Hyung-Hwan. All rights reserved.
|
2017-01-09 13:41:11 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "_ffi.h"
|
|
|
|
#include <moo-utl.h>
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2017-01-10 14:27:31 +00:00
|
|
|
#if defined(HAVE_DYNCALL_LIB) && defined(HAVE_DYNCALL_H)
|
|
|
|
# define USE_DYNCALL
|
|
|
|
#endif
|
2017-01-10 10:50:26 +00:00
|
|
|
|
2017-01-10 14:27:31 +00:00
|
|
|
#if defined(USE_DYNCALL)
|
2017-01-10 13:56:19 +00:00
|
|
|
# include <dyncall.h>
|
2017-01-09 13:41:11 +00:00
|
|
|
#endif
|
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
typedef void* ptr_t;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
typedef struct ffi_t ffi_t;
|
|
|
|
struct ffi_t
|
|
|
|
{
|
|
|
|
MOO_OBJ_HEADER;
|
|
|
|
void* handle;
|
|
|
|
};
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
static moo_pfrc_t pf_newinstsize (moo_t* moo, moo_ooi_t nargs)
|
|
|
|
{
|
|
|
|
moo_ooi_t newinstsize = MOO_SIZEOF(ffi_t) - MOO_SIZEOF(moo_obj_t);
|
|
|
|
MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(newinstsize));
|
|
|
|
return MOO_PF_SUCCESS;
|
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
static moo_pfrc_t pf_open (moo_t* moo, moo_ooi_t nargs)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
ffi_t* rcv;
|
2017-01-10 13:56:19 +00:00
|
|
|
moo_oop_t name;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
if (nargs != 1)
|
|
|
|
{
|
|
|
|
moo_seterrnum (moo, MOO_EINVAL);
|
2017-01-12 16:33:26 +00:00
|
|
|
goto softfail;
|
2017-01-10 13:56:19 +00:00
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
rcv = (ffi_t*)MOO_STACK_GETRCV(moo, nargs);
|
2017-01-10 13:56:19 +00:00
|
|
|
name = MOO_STACK_GETARG(moo, nargs, 0);
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
if (!MOO_ISTYPEOF(moo, name, MOO_OBJ_TYPE_CHAR) || !MOO_OBJ_GET_FLAGS_EXTRA(name)) /* TODO: better null check instead of FLAGS_EXTREA check */
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
moo_seterrnum (moo, MOO_EINVAL);
|
2017-01-12 16:33:26 +00:00
|
|
|
goto softfail;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!moo->vmprim.dl_open)
|
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
2017-01-12 16:33:26 +00:00
|
|
|
goto softfail;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
rcv->handle = moo->vmprim.dl_open (moo, ((moo_oop_char_t)name)->slot, 0);
|
2017-01-12 16:33:26 +00:00
|
|
|
if (!rcv->handle) goto softfail;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
MOO_DEBUG3 (moo, "<ffi.open> %.*js => %p\n", MOO_OBJ_GET_SIZE(name), ((moo_oop_char_t)name)->slot, rcv->handle);
|
2017-01-10 10:50:26 +00:00
|
|
|
MOO_STACK_SETRETTORCV (moo, nargs);
|
|
|
|
return MOO_PF_SUCCESS;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
softfail:
|
2017-01-10 10:50:26 +00:00
|
|
|
MOO_STACK_SETRETTOERROR (moo, nargs);
|
2017-01-09 13:41:11 +00:00
|
|
|
return MOO_PF_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
static moo_pfrc_t pf_close (moo_t* moo, moo_ooi_t nargs)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
ffi_t* rcv;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
if (nargs != 0)
|
|
|
|
{
|
|
|
|
moo_seterrnum (moo, MOO_EINVAL);
|
2017-01-12 16:33:26 +00:00
|
|
|
goto softfail;
|
2017-01-10 13:56:19 +00:00
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
rcv = (ffi_t*)MOO_STACK_GETRCV(moo, nargs);
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
if (!moo->vmprim.dl_open)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
2017-01-12 16:33:26 +00:00
|
|
|
goto softfail;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
MOO_DEBUG1 (moo, "<ffi.close> %p\n", rcv->handle);
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
moo->vmprim.dl_close (moo, rcv->handle);
|
|
|
|
rcv->handle = MOO_NULL;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
MOO_STACK_SETRETTORCV (moo, nargs);
|
2017-01-09 13:41:11 +00:00
|
|
|
return MOO_PF_SUCCESS;
|
2017-01-10 10:50:26 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
softfail:
|
2017-01-10 13:56:19 +00:00
|
|
|
MOO_STACK_SETRETTOERROR (moo, nargs);
|
|
|
|
return MOO_PF_SUCCESS;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
2017-01-12 10:06:43 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
static moo_pfrc_t pf_call (moo_t* moo, moo_ooi_t nargs)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 14:27:31 +00:00
|
|
|
#if defined(USE_DYNCALL)
|
2017-01-10 10:50:26 +00:00
|
|
|
ffi_t* rcv;
|
|
|
|
moo_oop_t fun, sig, args;
|
2017-01-11 15:33:03 +00:00
|
|
|
DCCallVM* dc = MOO_NULL;
|
|
|
|
moo_oow_t i, j;
|
|
|
|
void* f;
|
|
|
|
moo_oop_oop_t arr;
|
|
|
|
int ellipsis = 0;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
if (nargs < 3) goto inval;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
rcv = (ffi_t*)MOO_STACK_GETRCV(moo, nargs);
|
|
|
|
fun = MOO_STACK_GETARG(moo, nargs, 0);
|
|
|
|
sig = MOO_STACK_GETARG(moo, nargs, 1);
|
|
|
|
args = MOO_STACK_GETARG(moo, nargs, 2);
|
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
if (!MOO_ISTYPEOF(moo, sig, MOO_OBJ_TYPE_CHAR) || MOO_OBJ_GET_SIZE(sig) <= 0) goto inval;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-11 15:33:03 +00:00
|
|
|
#if 0
|
2017-01-12 16:33:26 +00:00
|
|
|
/* TODO: check if arr is a kind of array??? or check if it's indexed */
|
|
|
|
if (MOO_OBJ_GET_SIZE(sig) > 1 && MOO_CLASSOF(moo,args) != moo->_array) goto inval;
|
2017-01-11 15:33:03 +00:00
|
|
|
#endif
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-11 15:33:03 +00:00
|
|
|
f = MOO_OOP_TO_SMPTR(fun);
|
|
|
|
arr = (moo_oop_oop_t)args;
|
|
|
|
|
|
|
|
dc = dcNewCallVM (4096); /* TODO: right size? */
|
|
|
|
if (!dc)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-11 15:33:03 +00:00
|
|
|
moo_seterrnum (moo, moo_syserrtoerrnum(errno));
|
2017-01-12 16:33:26 +00:00
|
|
|
goto softfail;
|
2017-01-11 15:33:03 +00:00
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-11 15:33:03 +00:00
|
|
|
MOO_DEBUG2 (moo, "<ffi.call> %p in %p\n", f, rcv->handle);
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
dcMode (dc, DC_CALL_C_DEFAULT);
|
|
|
|
dcReset (dc);
|
2017-01-11 15:33:03 +00:00
|
|
|
|
|
|
|
i = 0;
|
|
|
|
if (i < MOO_OBJ_GET_SIZE(sig) && ((moo_oop_char_t)sig)->slot[i] == '|')
|
|
|
|
{
|
|
|
|
dcMode (dc, DC_CALL_C_ELLIPSIS);
|
2017-01-12 16:33:26 +00:00
|
|
|
|
|
|
|
/* the error code should be DC_ERROR_UNSUPPORTED_MODE */
|
|
|
|
if (dcGetError(dc) != DC_ERROR_NONE) goto noimpl;
|
2017-01-11 15:33:03 +00:00
|
|
|
dcReset (dc);
|
|
|
|
ellipsis = 1;
|
|
|
|
i++;
|
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-11 15:33:03 +00:00
|
|
|
for (j = 0; i < MOO_OBJ_GET_SIZE(sig); i++)
|
|
|
|
{
|
|
|
|
moo_ooch_t fmtc;
|
2017-01-12 16:33:26 +00:00
|
|
|
moo_oop_t arg;
|
2017-01-10 13:56:19 +00:00
|
|
|
|
2017-01-11 15:33:03 +00:00
|
|
|
fmtc = ((moo_oop_char_t)sig)->slot[i];
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-11 15:33:03 +00:00
|
|
|
if (fmtc == ')')
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-11 15:33:03 +00:00
|
|
|
i++;
|
|
|
|
break;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
2017-01-11 15:33:03 +00:00
|
|
|
else if (fmtc == '|')
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-11 15:33:03 +00:00
|
|
|
if (ellipsis)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-11 15:33:03 +00:00
|
|
|
dcMode (dc, DC_CALL_C_ELLIPSIS_VARARGS);
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
/* the error code should be DC_ERROR_UNSUPPORTED_MODE */
|
|
|
|
if (dcGetError(dc) != DC_ERROR_NONE) goto noimpl;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
2017-01-11 15:33:03 +00:00
|
|
|
continue;
|
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
/* more items in signature than the actual argument */
|
|
|
|
if (j >= MOO_OBJ_GET_SIZE(arr)) goto inval;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
arg = arr->slot[j];
|
2017-01-11 15:33:03 +00:00
|
|
|
switch (fmtc)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-11 15:33:03 +00:00
|
|
|
/* TODO: support more types... */
|
2017-01-09 13:41:11 +00:00
|
|
|
case 'c':
|
2017-01-12 16:33:26 +00:00
|
|
|
|
|
|
|
if (!MOO_OOP_IS_CHAR(arg)) goto inval;
|
2017-01-11 15:33:03 +00:00
|
|
|
dcArgChar (dc, MOO_OOP_TO_CHAR(arr->slot[j]));
|
|
|
|
j++;
|
2017-01-09 13:41:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'i':
|
2017-01-11 15:33:03 +00:00
|
|
|
/* TODO: use moo_inttoooi () */
|
2017-01-12 16:33:26 +00:00
|
|
|
if (!MOO_OOP_IS_SMOOI(arg)) goto inval;
|
|
|
|
dcArgInt (dc, MOO_OOP_TO_SMOOI(arg));
|
2017-01-11 15:33:03 +00:00
|
|
|
j++;
|
2017-01-09 13:41:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'l':
|
2017-01-12 16:33:26 +00:00
|
|
|
/* TODO: sanity check on the argument type - check if arr->slot[j] is SMOOI or bigint... */
|
2017-01-11 15:33:03 +00:00
|
|
|
/* TODO: use moo_inttoooi () */
|
2017-01-12 16:33:26 +00:00
|
|
|
dcArgLong (dc, MOO_OOP_TO_SMOOI(arg));
|
2017-01-11 15:33:03 +00:00
|
|
|
j++;
|
2017-01-09 13:41:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'L':
|
2017-01-11 15:33:03 +00:00
|
|
|
/* TODO: use moo_inttoooi () */
|
2017-01-12 16:33:26 +00:00
|
|
|
dcArgLongLong (dc, MOO_OOP_TO_SMOOI(arg));
|
2017-01-11 15:33:03 +00:00
|
|
|
j++;
|
2017-01-09 13:41:11 +00:00
|
|
|
break;
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
#if 0
|
2017-01-11 15:33:03 +00:00
|
|
|
case 'B': /* byte array */
|
2017-01-10 10:50:26 +00:00
|
|
|
#endif
|
2017-01-11 15:33:03 +00:00
|
|
|
case 's':
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-12 16:33:26 +00:00
|
|
|
moo_bch_t* ptr;
|
|
|
|
|
|
|
|
/* TOOD: check if arg is a string. */
|
|
|
|
/* TODO: free all duplicated strings after call */
|
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2017-01-12 17:48:04 +00:00
|
|
|
ptr = moo_dupootobchars (moo, MOO_OBJ_GET_CHAR_SLOT(arg), MOO_OBJ_GET_SIZE(arg), MOO_NULL);
|
2017-01-12 16:33:26 +00:00
|
|
|
#else
|
2017-01-12 17:48:04 +00:00
|
|
|
ptr = MOO_OBJ_GET_CHAR_SLOT(arg);
|
|
|
|
/*ptr = moo_dupoochars (moo, MOO_OBJ_GET_CHAR_SLOT(arg), MOO_OBJ_GET_SIZE(arg));*/
|
2017-01-12 16:33:26 +00:00
|
|
|
#endif
|
2017-01-12 17:48:04 +00:00
|
|
|
if (!ptr) goto softfail; /* out of system memory or conversion error - soft failure */
|
2017-01-12 16:33:26 +00:00
|
|
|
|
|
|
|
dcArgPointer (dc, ptr);
|
|
|
|
j++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'S':
|
|
|
|
{
|
|
|
|
moo_uch_t* ptr;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
2017-01-12 17:48:04 +00:00
|
|
|
ptr = MOO_OBJ_GET_CHAR_SLOT(arg);
|
|
|
|
/*ptr = moo_dupoochars (moo, MOO_OBJ_GET_CHAR_SLOT(arg), MOO_OBJ_GET_SIZE(arg));*/
|
2017-01-12 16:33:26 +00:00
|
|
|
#else
|
2017-01-12 17:48:04 +00:00
|
|
|
ptr = moo_dupootouchars (moo, MOO_OBJ_GET_CHAR_SLOT(arg), MOO_OBJ_GET_SIZE(arg), MOO_NULL);
|
2017-01-12 16:33:26 +00:00
|
|
|
#endif
|
2017-01-12 17:48:04 +00:00
|
|
|
if (!ptr) goto softfail; /* out of system memory or conversion error - soft failure */
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
dcArgPointer (dc, ptr);
|
2017-01-11 15:33:03 +00:00
|
|
|
j++;
|
2017-01-09 13:41:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2017-01-11 15:33:03 +00:00
|
|
|
/* TODO: ERROR HANDLING */
|
2017-01-09 13:41:11 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-01-11 15:33:03 +00:00
|
|
|
}
|
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
/* TODO: clean up strings duplicated... using moo_dupootobchars... */
|
|
|
|
|
2017-01-11 15:33:03 +00:00
|
|
|
if (i >= MOO_OBJ_GET_SIZE(sig)) goto call_void;
|
|
|
|
|
|
|
|
switch (((moo_oop_char_t)sig)->slot[i])
|
|
|
|
{
|
|
|
|
/* TODO: support more types... */
|
|
|
|
/* TODO: proper return value conversion */
|
|
|
|
case 'c':
|
|
|
|
{
|
|
|
|
char r = dcCallChar (dc, f);
|
|
|
|
MOO_STACK_SETRET (moo, nargs, MOO_CHAR_TO_OOP(r));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'i':
|
|
|
|
{
|
|
|
|
moo_oop_t r;
|
|
|
|
|
|
|
|
r = moo_ooitoint (moo, dcCallInt (dc, f));
|
2017-01-12 16:33:26 +00:00
|
|
|
if (!r) goto hardfail;
|
2017-01-11 15:33:03 +00:00
|
|
|
MOO_STACK_SETRET (moo, nargs, r);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'l':
|
|
|
|
{
|
|
|
|
moo_oop_t r;
|
|
|
|
r = moo_ooitoint (moo, dcCallLong (dc, f));
|
2017-01-12 16:33:26 +00:00
|
|
|
if (!r) goto hardfail;
|
2017-01-11 15:33:03 +00:00
|
|
|
MOO_STACK_SETRET (moo, nargs, r);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if (STIX_SIZEOF_LONG_LONG > 0)
|
|
|
|
case 'L':
|
|
|
|
{
|
|
|
|
long long r = dcCallLongLong (dc, f);
|
|
|
|
mod_oop_t r;
|
|
|
|
|
|
|
|
#if STIX_SIZEOF_LONG_LONG <= STIX_SIZEOF_LONG
|
|
|
|
r = moo_ooitoint (moo, dcCallLongLong (dc, f));
|
|
|
|
#else
|
|
|
|
# error TODO:...
|
|
|
|
#endif
|
2017-01-12 16:33:26 +00:00
|
|
|
if (!rr) goto hardfail;
|
2017-01-11 15:33:03 +00:00
|
|
|
|
|
|
|
MOO_STACK_SETRET (moo, nargs, r);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
case 'B': /* byte array */
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
{
|
|
|
|
moo_oop_t s;
|
2017-01-12 16:33:26 +00:00
|
|
|
moo_bch_t* r;
|
|
|
|
moo_ooch_t* ptr;
|
|
|
|
moo_oow_t len;
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
r = dcCallPointer (dc, f);
|
2017-01-11 15:33:03 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
|
|
|
ptr = moo_dupbtooocstr (moo, r, &len);
|
|
|
|
if (!ptr) goto softfail; /* out of system memory or conversion error - still soft failure */
|
|
|
|
s = moo_makestring(moo, ptr, len);
|
|
|
|
moo_freemem (moo, ptr);
|
|
|
|
#else
|
|
|
|
s = moo_makestring(moo, r, moo_countbcstr(r));
|
|
|
|
#endif
|
|
|
|
if (!s) goto hardfail; /* out of object memory - hard failure*/
|
|
|
|
|
|
|
|
MOO_STACK_SETRET (moo, nargs, s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'S':
|
|
|
|
{
|
|
|
|
moo_oop_t s;
|
|
|
|
moo_uch_t* r;
|
|
|
|
moo_ooch_t* ptr;
|
|
|
|
moo_oow_t len;
|
|
|
|
|
|
|
|
r = dcCallPointer (dc, f);
|
|
|
|
|
|
|
|
#if defined(MOO_OOCH_IS_UCH)
|
|
|
|
s = moo_makestring(moo, r, moo_countucstr(r));
|
|
|
|
#else
|
|
|
|
ptr = moo_dupbtooocstr (moo, r, &len);
|
|
|
|
if (!ptr) goto softfail; /* out of system memory or conversion error - still soft failure */
|
|
|
|
s = moo_makestring(moo, ptr, len);
|
|
|
|
moo_freemem (moo, ptr);
|
|
|
|
#endif
|
|
|
|
if (!s) goto hardfail; /* out of object memory - hard failure*/
|
2017-01-11 15:33:03 +00:00
|
|
|
|
|
|
|
MOO_STACK_SETRET (moo, nargs, s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
call_void:
|
|
|
|
dcCallVoid (dc, f);
|
|
|
|
MOO_STACK_SETRETTORCV (moo, nargs);
|
|
|
|
break;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
/* TODO: free all duplicated string arguments... */
|
2017-01-11 15:33:03 +00:00
|
|
|
dcFree (dc);
|
2017-01-09 13:41:11 +00:00
|
|
|
return MOO_PF_SUCCESS;
|
2017-01-10 10:50:26 +00:00
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
noimpl:
|
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
|
|
|
goto softfail;
|
|
|
|
|
|
|
|
inval:
|
|
|
|
moo_seterrnum (moo, MOO_EINVAL);
|
|
|
|
goto softfail;
|
|
|
|
|
|
|
|
softfail:
|
|
|
|
/* TODO: free all duplicated string arguments... */
|
2017-01-11 15:33:03 +00:00
|
|
|
if (dc) dcFree(dc);
|
2017-01-10 10:50:26 +00:00
|
|
|
MOO_STACK_SETRETTOERROR (moo, nargs);
|
|
|
|
return MOO_PF_SUCCESS;
|
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
hardfail:
|
|
|
|
/* TODO: free all duplicated string arguments... */
|
2017-01-11 15:33:03 +00:00
|
|
|
if (dc) dcFree(dc);
|
|
|
|
return MOO_PF_HARD_FAILURE;
|
|
|
|
|
2017-01-09 13:41:11 +00:00
|
|
|
#else
|
2017-01-10 10:50:26 +00:00
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
2017-01-10 14:27:31 +00:00
|
|
|
MOO_STACK_SETRETTOERROR (moo, nargs);
|
|
|
|
return MOO_PF_SUCCESS;
|
2017-01-09 13:41:11 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
static moo_pfrc_t pf_getsym (moo_t* moo, moo_ooi_t nargs)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
ffi_t* rcv;
|
2017-01-10 13:56:19 +00:00
|
|
|
moo_oop_t name;
|
2017-01-09 13:41:11 +00:00
|
|
|
void* sym;
|
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
if (nargs != 1)
|
|
|
|
{
|
|
|
|
moo_seterrnum (moo, MOO_EINVAL);
|
2017-01-12 16:33:26 +00:00
|
|
|
goto softfail;
|
2017-01-10 13:56:19 +00:00
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
rcv = (ffi_t*)MOO_STACK_GETRCV(moo, nargs);
|
2017-01-10 13:56:19 +00:00
|
|
|
name = MOO_STACK_GETARG(moo, nargs, 0);
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
if (!MOO_ISTYPEOF(moo,name,MOO_OBJ_TYPE_CHAR)) /* TODO: null check on the symbol name? */
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
moo_seterrnum (moo, MOO_EINVAL);
|
2017-01-12 16:33:26 +00:00
|
|
|
goto softfail;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
if (!moo->vmprim.dl_getsym)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
moo_seterrnum (moo, MOO_ENOIMPL);
|
2017-01-12 16:33:26 +00:00
|
|
|
goto softfail;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
sym = moo->vmprim.dl_getsym (moo, rcv->handle, ((moo_oop_char_t)name)->slot);
|
2017-01-12 16:33:26 +00:00
|
|
|
if (!sym) goto softfail;
|
2017-01-10 10:50:26 +00:00
|
|
|
|
2017-01-10 13:56:19 +00:00
|
|
|
MOO_DEBUG4 (moo, "<ffi.getsym> %.*js => %p in %p\n", MOO_OBJ_GET_SIZE(name), ((moo_oop_char_t)name)->slot, sym, rcv->handle);
|
|
|
|
|
|
|
|
MOO_ASSERT (moo, MOO_IN_SMPTR_RANGE(sym));
|
|
|
|
MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP(sym));
|
2017-01-10 10:50:26 +00:00
|
|
|
return MOO_PF_SUCCESS;
|
|
|
|
|
2017-01-12 16:33:26 +00:00
|
|
|
softfail:
|
2017-01-10 10:50:26 +00:00
|
|
|
MOO_STACK_SETRETTOERROR (moo, nargs);
|
|
|
|
return MOO_PF_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
|
|
|
|
typedef struct fnctab_t fnctab_t;
|
|
|
|
struct fnctab_t
|
|
|
|
{
|
|
|
|
moo_method_type_t type;
|
|
|
|
moo_ooch_t mthname[15];
|
|
|
|
int variadic;
|
|
|
|
moo_pfimpl_t handler;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define C MOO_METHOD_CLASS
|
|
|
|
#define I MOO_METHOD_INSTANCE
|
|
|
|
|
|
|
|
static fnctab_t fnctab[] =
|
|
|
|
{
|
|
|
|
{ C, { '_','n','e','w','I','n','s','t','S','i','z','e','\0' }, 0, pf_newinstsize },
|
|
|
|
{ I, { 'c','a','l','l','\0' }, 1, pf_call },
|
|
|
|
{ I, { 'c','a','l','l',':','s','i','g',':','w','i','t','h',':','\0' }, 0, pf_call },
|
|
|
|
{ I, { 'c','l','o','s','e','\0' }, 0, pf_close },
|
|
|
|
{ I, { 'g','e','t','s','y','m',':','\0' }, 0, pf_getsym },
|
|
|
|
{ I, { 'o','p','e','n',':','\0' }, 0, pf_open }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
|
|
|
|
static int import (moo_t* moo, moo_mod_t* mod, moo_oop_t _class)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
moo_oow_t i;
|
|
|
|
|
|
|
|
moo_pushtmp (moo, &_class);
|
|
|
|
for (i = 0; i < MOO_COUNTOF(fnctab); i++)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
if (moo_genpfmethod (moo, mod, _class, fnctab[i].type, fnctab[i].mthname, fnctab[i].variadic, MOO_NULL) <= -1)
|
|
|
|
{
|
|
|
|
/* TODO: delete pfmethod generated??? */
|
|
|
|
ret = -1;
|
|
|
|
break;
|
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
moo_poptmp (moo);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static moo_pfimpl_t query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name)
|
|
|
|
{
|
|
|
|
int left, right, mid, n;
|
|
|
|
|
|
|
|
left = 0; right = MOO_COUNTOF(fnctab) - 1;
|
|
|
|
|
|
|
|
while (left <= right)
|
2017-01-09 13:41:11 +00:00
|
|
|
{
|
2017-01-10 10:50:26 +00:00
|
|
|
mid = (left + right) / 2;
|
|
|
|
|
|
|
|
n = moo_compoocstr (name, fnctab[mid].mthname);
|
|
|
|
if (n < 0) right = mid - 1;
|
|
|
|
else if (n > 0) left = mid + 1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return fnctab[mid].handler;
|
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
moo->errnum = MOO_ENOENT;
|
|
|
|
return MOO_NULL;
|
|
|
|
}
|
2017-01-09 13:41:11 +00:00
|
|
|
|
2017-01-10 10:50:26 +00:00
|
|
|
static void unload (moo_t* moo, moo_mod_t* mod)
|
|
|
|
{
|
2017-01-10 13:56:19 +00:00
|
|
|
/* TODO: anything? close open open dll handles? For that, pf_open must store the value it returns to mod->ctx or somewhere..*/
|
2017-01-10 10:50:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int moo_mod_ffi (moo_t* moo, moo_mod_t* mod)
|
|
|
|
{
|
|
|
|
mod->import = import;
|
|
|
|
mod->query = query;
|
|
|
|
mod->unload = unload;
|
|
|
|
mod->ctx = MOO_NULL;
|
|
|
|
return 0;
|
2017-01-09 13:41:11 +00:00
|
|
|
}
|