mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +00:00
cleanup
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28768 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
a8eba2055d
commit
0f5dd1c798
3 changed files with 314 additions and 71 deletions
|
@ -2750,8 +2750,321 @@ static void callEncoder (DOContext *ctxt)
|
||||||
ctxt.type, ctxt.seq, (uintptr_t)self);
|
ctxt.type, ctxt.seq, (uintptr_t)self);
|
||||||
|
|
||||||
IreqInCount++; /* Handling an incoming request. */
|
IreqInCount++; /* Handling an incoming request. */
|
||||||
|
#if 1
|
||||||
|
{
|
||||||
|
/* The method type string obtained from the target's OBJC_METHOD
|
||||||
|
structure for the selector we're sending. */
|
||||||
|
const char *type;
|
||||||
|
/* A pointer into the local variable TYPE string. */
|
||||||
|
const char *tmptype;
|
||||||
|
/* A pointer into the argument ENCODED_TYPES string. */
|
||||||
|
const char *etmptype;
|
||||||
|
/* The target object that will receive the message. */
|
||||||
|
id object;
|
||||||
|
/* The selector for the message we're sending to the TARGET. */
|
||||||
|
SEL selector;
|
||||||
|
/* The OBJECT's Method(_t) pointer for the SELECTOR. */
|
||||||
|
GSMethod meth = 0;
|
||||||
|
BOOL is_exception = NO;
|
||||||
|
/* Type qualifier flags; see <objc/objc-api.h>. */
|
||||||
|
unsigned flags;
|
||||||
|
/* Which argument number are we processing now? */
|
||||||
|
int argnum;
|
||||||
|
/* Does the method have any arguments that are passed by reference?
|
||||||
|
If so, we need to encode them, since the method may have changed them. */
|
||||||
|
BOOL out_parameters = NO;
|
||||||
|
NSInvocation *inv;
|
||||||
|
/* Signature information */
|
||||||
|
NSMethodSignature *sig;
|
||||||
|
const char *encoded_types = forward_type;
|
||||||
|
|
||||||
#if defined(USE_LIBFFI)
|
etmptype = encoded_types;
|
||||||
|
|
||||||
|
ctxt.encoder = aRmc;
|
||||||
|
|
||||||
|
/* Decode the object, (which is always the first argument to a method). */
|
||||||
|
[aRmc decodeValueOfObjCType: @encode(id) at: &object];
|
||||||
|
|
||||||
|
/* Decode the selector, (which is always the second argument to a method). */
|
||||||
|
/* xxx @encode(SEL) produces "^v" in gcc 2.5.8. It should be ":" */
|
||||||
|
[aRmc decodeValueOfObjCType: @encode(SEL) at: &selector];
|
||||||
|
|
||||||
|
/* Get the "selector type" for this method. The "selector type" is
|
||||||
|
a string that lists the return and argument types, and also
|
||||||
|
indicates in which registers and where on the stack the arguments
|
||||||
|
should be placed before the method call. The selector type
|
||||||
|
string we get here should have the same argument and return types
|
||||||
|
as the ENCODED_TYPES string, but it will have different register
|
||||||
|
and stack locations if the ENCODED_TYPES came from a machine of a
|
||||||
|
different architecture. */
|
||||||
|
if (GSObjCIsClass(object))
|
||||||
|
{
|
||||||
|
meth = GSGetMethod(object, selector, NO, YES);
|
||||||
|
}
|
||||||
|
else if (GSObjCIsInstance(object))
|
||||||
|
{
|
||||||
|
meth = GSGetMethod(GSObjCClass(object), selector, YES, YES);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"decoded object %p is invalid", object];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meth != 0)
|
||||||
|
{
|
||||||
|
type = meth->method_types;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSDebugLog(@"Local object <%p %s> doesn't implement: %s directly. "
|
||||||
|
@"Will search for arbitrary signature.",
|
||||||
|
object,
|
||||||
|
GSNameFromClass(GSObjCIsClass(object)
|
||||||
|
? object : (id)GSObjCClass(object)),
|
||||||
|
GSNameFromSelector(selector));
|
||||||
|
type = GSTypesFromSelector(selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we successfully got the method type, and that its
|
||||||
|
types match the ENCODED_TYPES. */
|
||||||
|
NSCParameterAssert (type);
|
||||||
|
if (GSSelectorTypesMatch(encoded_types, type) == NO)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"NSConection types (%s / %s) missmatch for %s",
|
||||||
|
encoded_types, type, GSNameFromSelector(selector)];
|
||||||
|
}
|
||||||
|
|
||||||
|
sig = [NSMethodSignature signatureWithObjCTypes: type];
|
||||||
|
inv = [[NSInvocation alloc] initWithMethodSignature: sig];
|
||||||
|
ctxt.objToFree = inv;
|
||||||
|
|
||||||
|
tmptype = objc_skip_argspec (type);
|
||||||
|
etmptype = objc_skip_argspec (etmptype);
|
||||||
|
[inv setTarget: object];
|
||||||
|
|
||||||
|
tmptype = objc_skip_argspec (tmptype);
|
||||||
|
etmptype = objc_skip_argspec (etmptype);
|
||||||
|
[inv setSelector: selector];
|
||||||
|
|
||||||
|
|
||||||
|
/* Step TMPTYPE and ETMPTYPE in lock-step through their
|
||||||
|
method type strings. */
|
||||||
|
|
||||||
|
for (tmptype = objc_skip_argspec (tmptype),
|
||||||
|
etmptype = objc_skip_argspec (etmptype), argnum = 2;
|
||||||
|
*tmptype != '\0';
|
||||||
|
tmptype = objc_skip_argspec (tmptype),
|
||||||
|
etmptype = objc_skip_argspec (etmptype), argnum++)
|
||||||
|
{
|
||||||
|
void *datum;
|
||||||
|
|
||||||
|
/* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */
|
||||||
|
flags = objc_get_type_qualifiers (etmptype);
|
||||||
|
/* Skip over the type qualifiers, so now TYPE is pointing directly
|
||||||
|
at the char corresponding to the argument's type, as defined
|
||||||
|
in <objc/objc-api.h> */
|
||||||
|
tmptype = objc_skip_type_qualifiers(tmptype);
|
||||||
|
|
||||||
|
/* Decide how, (or whether or not), to decode the argument
|
||||||
|
depending on its FLAGS and TMPTYPE. Only the first two cases
|
||||||
|
involve parameters that may potentially be passed by
|
||||||
|
reference, and thus only the first two may change the value
|
||||||
|
of OUT_PARAMETERS. *** Note: This logic must match exactly
|
||||||
|
the code in cifframe_dissect_call(); that function should
|
||||||
|
encode exactly what we decode here. *** */
|
||||||
|
|
||||||
|
switch (*tmptype)
|
||||||
|
{
|
||||||
|
case _C_CHARPTR:
|
||||||
|
/* Handle a (char*) argument. */
|
||||||
|
/* If the char* is qualified as an OUT parameter, or if it
|
||||||
|
not explicitly qualified as an IN parameter, then we will
|
||||||
|
have to get this char* again after the method is run,
|
||||||
|
because the method may have changed it. Set
|
||||||
|
OUT_PARAMETERS accordingly. */
|
||||||
|
if ((flags & _F_OUT) || !(flags & _F_IN))
|
||||||
|
out_parameters = YES;
|
||||||
|
/* If the char* is qualified as an IN parameter, or not
|
||||||
|
explicity qualified as an OUT parameter, then decode it.
|
||||||
|
Note: the decoder allocates memory for holding the
|
||||||
|
string, and it is also responsible for making sure that
|
||||||
|
the memory gets freed eventually, (usually through the
|
||||||
|
autorelease of NSData object). */
|
||||||
|
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||||
|
{
|
||||||
|
datum = alloca (sizeof(char*));
|
||||||
|
[aRmc decodeValueOfObjCType: tmptype at: datum];
|
||||||
|
[inv setArgument: datum atIndex: argnum];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _C_PTR:
|
||||||
|
/* If the pointer's value is qualified as an OUT parameter,
|
||||||
|
or if it not explicitly qualified as an IN parameter,
|
||||||
|
then we will have to get the value pointed to again after
|
||||||
|
the method is run, because the method may have changed
|
||||||
|
it. Set OUT_PARAMETERS accordingly. */
|
||||||
|
if ((flags & _F_OUT) || !(flags & _F_IN))
|
||||||
|
out_parameters = YES;
|
||||||
|
|
||||||
|
/* Handle an argument that is a pointer to a non-char. But
|
||||||
|
(void*) and (anything**) is not allowed. */
|
||||||
|
/* The argument is a pointer to something; increment TYPE
|
||||||
|
so we can see what it is a pointer to. */
|
||||||
|
tmptype++;
|
||||||
|
/* If the pointer's value is qualified as an IN parameter,
|
||||||
|
or not explicity qualified as an OUT parameter, then
|
||||||
|
decode it. */
|
||||||
|
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||||
|
{
|
||||||
|
datum = alloca (objc_sizeof_type (tmptype));
|
||||||
|
[aRmc decodeValueOfObjCType: tmptype at: datum];
|
||||||
|
[inv setArgument: &datum atIndex: argnum];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
datum = alloca (objc_sizeof_type (tmptype));
|
||||||
|
if (*tmptype == _C_ID)
|
||||||
|
{
|
||||||
|
*(id*)datum = [aRmc decodeObject];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[aRmc decodeValueOfObjCType: tmptype at: datum];
|
||||||
|
}
|
||||||
|
[inv setArgument: datum atIndex: argnum];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop using the decoder.
|
||||||
|
*/
|
||||||
|
[self _doneInRmc: aRmc];
|
||||||
|
ctxt.decoder = nil;
|
||||||
|
|
||||||
|
/* Invoke the method! */
|
||||||
|
[inv invoke];
|
||||||
|
|
||||||
|
/* It is possible that our connection died while the method was
|
||||||
|
* being called - in this case we mustn't try to send the result
|
||||||
|
* back to the remote application!
|
||||||
|
*/
|
||||||
|
if ([self isValid] == NO)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We create a new coder object and set it in the context for
|
||||||
|
* later use if/when we are called again. We encode a flag to
|
||||||
|
* say that this is not an exception.
|
||||||
|
*/
|
||||||
|
aRmc = [self _makeOutRmc: ctxt.seq generate: 0 reply: NO];
|
||||||
|
ctxt.encoder = aRmc;
|
||||||
|
[aRmc encodeValueOfObjCType: @encode(BOOL) at: &is_exception];
|
||||||
|
|
||||||
|
/* Encode the return value and pass-by-reference values, if there
|
||||||
|
are any. This logic must match exactly that in
|
||||||
|
cifframe_build_return(). */
|
||||||
|
/* OUT_PARAMETERS should be true here in exactly the same
|
||||||
|
situations as it was true in cifframe_dissect_call(). */
|
||||||
|
|
||||||
|
/* Get the qualifier type of the return value. */
|
||||||
|
flags = objc_get_type_qualifiers (encoded_types);
|
||||||
|
/* Get the return type; store it our two temporary char*'s. */
|
||||||
|
etmptype = objc_skip_type_qualifiers (encoded_types);
|
||||||
|
tmptype = objc_skip_type_qualifiers (type);
|
||||||
|
|
||||||
|
/* Only encode return values if there is a non-void return value,
|
||||||
|
a non-oneway void return value, or if there are values that were
|
||||||
|
passed by reference. */
|
||||||
|
|
||||||
|
if (*tmptype == _C_VOID)
|
||||||
|
{
|
||||||
|
if ((flags & _F_ONEWAY) == 0)
|
||||||
|
{
|
||||||
|
int dummy = 0;
|
||||||
|
|
||||||
|
[aRmc encodeValueOfObjCType: @encode(int) at: (void*)&dummy];
|
||||||
|
}
|
||||||
|
/* No return value to encode; do nothing. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
void *datum;
|
||||||
|
|
||||||
|
if (*tmptype == _C_PTR)
|
||||||
|
{
|
||||||
|
/* The argument is a pointer to something; increment TYPE
|
||||||
|
so we can see what it is a pointer to. */
|
||||||
|
tmptype++;
|
||||||
|
datum = alloca (objc_sizeof_type (tmptype));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
datum = alloca (objc_sizeof_type (tmptype));
|
||||||
|
}
|
||||||
|
[inv getReturnValue: datum];
|
||||||
|
[aRmc encodeValueOfObjCType: tmptype at: datum];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Encode the values returned by reference. Note: this logic
|
||||||
|
must match exactly the code in cifframe_build_return(); that
|
||||||
|
function should decode exactly what we encode here. */
|
||||||
|
|
||||||
|
if (out_parameters)
|
||||||
|
{
|
||||||
|
/* Step through all the arguments, finding the ones that were
|
||||||
|
passed by reference. */
|
||||||
|
for (tmptype = objc_skip_argspec (tmptype),
|
||||||
|
argnum = 0,
|
||||||
|
etmptype = objc_skip_argspec (etmptype);
|
||||||
|
*tmptype != '\0';
|
||||||
|
tmptype = objc_skip_argspec (tmptype),
|
||||||
|
argnum++,
|
||||||
|
etmptype = objc_skip_argspec (etmptype))
|
||||||
|
{
|
||||||
|
/* Get the type qualifiers, like IN, OUT, INOUT, ONEWAY. */
|
||||||
|
flags = objc_get_type_qualifiers(etmptype);
|
||||||
|
/* Skip over the type qualifiers, so now TYPE is pointing directly
|
||||||
|
at the char corresponding to the argument's type, as defined
|
||||||
|
in <objc/objc-api.h> */
|
||||||
|
tmptype = objc_skip_type_qualifiers (tmptype);
|
||||||
|
|
||||||
|
/* Decide how, (or whether or not), to encode the argument
|
||||||
|
depending on its FLAGS and TMPTYPE. */
|
||||||
|
if (((flags & _F_OUT) || !(flags & _F_IN))
|
||||||
|
&& (*tmptype == _C_PTR || *tmptype == _C_CHARPTR))
|
||||||
|
{
|
||||||
|
void *datum;
|
||||||
|
|
||||||
|
if (*tmptype == _C_PTR)
|
||||||
|
{
|
||||||
|
/* The argument is a pointer (to a non-char), and the
|
||||||
|
pointer's value is qualified as an OUT parameter, or
|
||||||
|
it not explicitly qualified as an IN parameter, then
|
||||||
|
it is a pass-by-reference argument.*/
|
||||||
|
++tmptype;
|
||||||
|
[inv getArgument: &datum atIndex: argnum];
|
||||||
|
[aRmc encodeValueOfObjCType: tmptype at: datum];
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_CHARPTR)
|
||||||
|
{
|
||||||
|
datum = alloca (sizeof (char*));
|
||||||
|
[inv getArgument: datum atIndex: argnum];
|
||||||
|
[aRmc encodeValueOfObjCType: tmptype at: datum];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctxt.objToFree = nil;
|
||||||
|
[inv release];
|
||||||
|
[self _sendOutRmc: aRmc type: METHOD_REPLY];
|
||||||
|
ctxt.encoder = nil;
|
||||||
|
}
|
||||||
|
#elif defined(USE_LIBFFI)
|
||||||
cifframe_do_call (&ctxt, callDecoder, callEncoder);
|
cifframe_do_call (&ctxt, callDecoder, callEncoder);
|
||||||
#elif defined(USE_FFCALL)
|
#elif defined(USE_FFCALL)
|
||||||
callframe_do_call (&ctxt, callDecoder, callEncoder);
|
callframe_do_call (&ctxt, callDecoder, callEncoder);
|
||||||
|
|
|
@ -52,7 +52,6 @@ typedef struct _cifframe_t {
|
||||||
|
|
||||||
extern cifframe_t *cifframe_from_info (NSArgumentInfo *info, int numargs,
|
extern cifframe_t *cifframe_from_info (NSArgumentInfo *info, int numargs,
|
||||||
void **retval);
|
void **retval);
|
||||||
extern unsigned retval_offset_from_info (NSArgumentInfo *info, int numargs);
|
|
||||||
|
|
||||||
extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer,
|
extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer,
|
||||||
int size);
|
int size);
|
||||||
|
|
|
@ -259,75 +259,6 @@ cifframe_from_info (NSArgumentInfo *info, int numargs, void **retval)
|
||||||
return cframe;
|
return cframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NB. this must match the code in cifframe_from_info() so that it
|
|
||||||
* returns the offset for the returne value in the cframe.
|
|
||||||
*/
|
|
||||||
unsigned
|
|
||||||
retval_offset_from_info (NSArgumentInfo *info, int numargs)
|
|
||||||
{
|
|
||||||
unsigned size = sizeof(cifframe_t);
|
|
||||||
unsigned align = __alignof(double);
|
|
||||||
unsigned type_offset = 0;
|
|
||||||
unsigned offset = 0;
|
|
||||||
int i;
|
|
||||||
ffi_type *arg_types[numargs];
|
|
||||||
ffi_type *rtype;
|
|
||||||
|
|
||||||
/* FIXME: in cifframe_type, return values/arguments that are structures
|
|
||||||
have custom ffi_types with are allocated separately. We should allocate
|
|
||||||
them in our cifframe so we don't leak memory. Or maybe we could
|
|
||||||
cache structure types? */
|
|
||||||
rtype = cifframe_type(info[0].type, NULL);
|
|
||||||
if (rtype == 0 || (rtype->size == 0 && rtype->elements == NULL))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < numargs; i++)
|
|
||||||
{
|
|
||||||
arg_types[i] = cifframe_type(info[i+1].type, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numargs > 0)
|
|
||||||
{
|
|
||||||
if (size % align != 0)
|
|
||||||
{
|
|
||||||
size += align - (size % align);
|
|
||||||
}
|
|
||||||
type_offset = size;
|
|
||||||
/* Make room to copy the arg_types */
|
|
||||||
size += sizeof(ffi_type *) * numargs;
|
|
||||||
if (size % align != 0)
|
|
||||||
{
|
|
||||||
size += align - (size % align);
|
|
||||||
}
|
|
||||||
offset = size;
|
|
||||||
size += numargs * sizeof(void*);
|
|
||||||
if (size % align != 0)
|
|
||||||
{
|
|
||||||
size += (align - (size % align));
|
|
||||||
}
|
|
||||||
for (i = 0; i < numargs; i++)
|
|
||||||
{
|
|
||||||
if (arg_types[i]->elements)
|
|
||||||
size += cifframe_guess_struct_size(arg_types[i]);
|
|
||||||
else
|
|
||||||
size += arg_types[i]->size;
|
|
||||||
|
|
||||||
if (size % align != 0)
|
|
||||||
{
|
|
||||||
size += (align - size % align);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size % align != 0)
|
|
||||||
{
|
|
||||||
size += (align - size % align);
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size)
|
cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue