9a567ff5d0
* Updated for Python 3.7.1
254 lines
5.9 KiB
C
254 lines
5.9 KiB
C
/* -----------------------------------------------------------------------
|
|
raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc.
|
|
|
|
Author: Kresten Krab Thorup <krab@gnu.org>
|
|
|
|
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.
|
|
----------------------------------------------------------------------- */
|
|
|
|
/* This file defines generic functions for use with the raw api. */
|
|
|
|
#include <ffi.h>
|
|
#include <ffi_common.h>
|
|
|
|
#if !FFI_NO_RAW_API
|
|
|
|
size_t
|
|
ffi_raw_size (ffi_cif *cif)
|
|
{
|
|
size_t result = 0;
|
|
int i;
|
|
|
|
ffi_type **at = cif->arg_types;
|
|
|
|
for (i = cif->nargs-1; i >= 0; i--, at++)
|
|
{
|
|
#if !FFI_NO_STRUCTS
|
|
if ((*at)->type == FFI_TYPE_STRUCT)
|
|
result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
|
|
else
|
|
#endif
|
|
result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void
|
|
ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
|
{
|
|
unsigned i;
|
|
ffi_type **tp = cif->arg_types;
|
|
|
|
#if WORDS_BIGENDIAN
|
|
|
|
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
|
{
|
|
switch ((*tp)->type)
|
|
{
|
|
case FFI_TYPE_UINT8:
|
|
case FFI_TYPE_SINT8:
|
|
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
|
|
break;
|
|
|
|
case FFI_TYPE_UINT16:
|
|
case FFI_TYPE_SINT16:
|
|
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
|
|
break;
|
|
|
|
#if FFI_SIZEOF_ARG >= 4
|
|
case FFI_TYPE_UINT32:
|
|
case FFI_TYPE_SINT32:
|
|
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
|
|
break;
|
|
#endif
|
|
|
|
#if !FFI_NO_STRUCTS
|
|
case FFI_TYPE_STRUCT:
|
|
*args = (raw++)->ptr;
|
|
break;
|
|
#endif
|
|
|
|
case FFI_TYPE_POINTER:
|
|
*args = (void*) &(raw++)->ptr;
|
|
break;
|
|
|
|
default:
|
|
*args = raw;
|
|
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
|
}
|
|
}
|
|
|
|
#else /* WORDS_BIGENDIAN */
|
|
|
|
#if !PDP
|
|
|
|
/* then assume little endian */
|
|
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
|
{
|
|
#if !FFI_NO_STRUCTS
|
|
if ((*tp)->type == FFI_TYPE_STRUCT)
|
|
{
|
|
*args = (raw++)->ptr;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
*args = (void*) raw;
|
|
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
|
}
|
|
}
|
|
|
|
#else
|
|
#error "pdp endian not supported"
|
|
#endif /* ! PDP */
|
|
|
|
#endif /* WORDS_BIGENDIAN */
|
|
}
|
|
|
|
void
|
|
ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
|
{
|
|
unsigned i;
|
|
ffi_type **tp = cif->arg_types;
|
|
|
|
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
|
{
|
|
switch ((*tp)->type)
|
|
{
|
|
case FFI_TYPE_UINT8:
|
|
(raw++)->uint = *(UINT8*) (*args);
|
|
break;
|
|
|
|
case FFI_TYPE_SINT8:
|
|
(raw++)->sint = *(SINT8*) (*args);
|
|
break;
|
|
|
|
case FFI_TYPE_UINT16:
|
|
(raw++)->uint = *(UINT16*) (*args);
|
|
break;
|
|
|
|
case FFI_TYPE_SINT16:
|
|
(raw++)->sint = *(SINT16*) (*args);
|
|
break;
|
|
|
|
#if FFI_SIZEOF_ARG >= 4
|
|
case FFI_TYPE_UINT32:
|
|
(raw++)->uint = *(UINT32*) (*args);
|
|
break;
|
|
|
|
case FFI_TYPE_SINT32:
|
|
(raw++)->sint = *(SINT32*) (*args);
|
|
break;
|
|
#endif
|
|
|
|
#if !FFI_NO_STRUCTS
|
|
case FFI_TYPE_STRUCT:
|
|
(raw++)->ptr = *args;
|
|
break;
|
|
#endif
|
|
|
|
case FFI_TYPE_POINTER:
|
|
(raw++)->ptr = **(void***) args;
|
|
break;
|
|
|
|
default:
|
|
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
|
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if !FFI_NATIVE_RAW_API
|
|
|
|
|
|
/* This is a generic definition of ffi_raw_call, to be used if the
|
|
* native system does not provide a machine-specific implementation.
|
|
* Having this, allows code to be written for the raw API, without
|
|
* the need for system-specific code to handle input in that format;
|
|
* these following couple of functions will handle the translation forth
|
|
* and back automatically. */
|
|
|
|
void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw)
|
|
{
|
|
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
|
ffi_raw_to_ptrarray (cif, raw, avalue);
|
|
ffi_call (cif, fn, rvalue, avalue);
|
|
}
|
|
|
|
#if FFI_CLOSURES /* base system provides closures */
|
|
|
|
static void
|
|
ffi_translate_args (ffi_cif *cif, void *rvalue,
|
|
void **avalue, void *user_data)
|
|
{
|
|
ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
|
|
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
|
|
|
ffi_ptrarray_to_raw (cif, avalue, raw);
|
|
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
|
}
|
|
|
|
ffi_status
|
|
ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
|
|
ffi_cif *cif,
|
|
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
|
void *user_data,
|
|
void *codeloc)
|
|
{
|
|
ffi_status status;
|
|
|
|
status = ffi_prep_closure_loc ((ffi_closure*) cl,
|
|
cif,
|
|
&ffi_translate_args,
|
|
codeloc,
|
|
codeloc);
|
|
if (status == FFI_OK)
|
|
{
|
|
cl->fun = fun;
|
|
cl->user_data = user_data;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
#endif /* FFI_CLOSURES */
|
|
#endif /* !FFI_NATIVE_RAW_API */
|
|
|
|
#if FFI_CLOSURES
|
|
|
|
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
|
* will install an intermediate "hub" for translation of arguments from
|
|
* the pointer-array format, to the raw format */
|
|
|
|
ffi_status
|
|
ffi_prep_raw_closure (ffi_raw_closure* cl,
|
|
ffi_cif *cif,
|
|
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
|
void *user_data)
|
|
{
|
|
return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
|
|
}
|
|
|
|
#endif /* FFI_CLOSURES */
|
|
|
|
#endif /* !FFI_NO_RAW_API */
|