1
1
/** Implementation of GSFFCallInvocation for GNUStep
2
2
Copyright (C) 2000 Free Software Foundation, Inc.
4
4
Written: Adam Fedor <fedor@gnu.org>
7
7
This file is part of the GNUstep Base Library.
9
9
This library is free software; you can redistribute it and/or
10
10
modify it under the terms of the GNU Library General Public
11
11
License as published by the Free Software Foundation; either
12
12
version 2 of the License, or (at your option) any later version.
14
14
This library is distributed in the hope that it will be useful,
15
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
17
Library General Public License for more details.
19
19
You should have received a copy of the GNU Library General Public
20
20
License along with this library; if not, write to the Free
21
21
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
23
#include <Foundation/NSException.h>
24
#include <Foundation/NSCoder.h>
25
#include <Foundation/NSDistantObject.h>
26
#include <base/GSInvocation.h>
23
#include "Foundation/NSException.h"
24
#include "Foundation/NSCoder.h"
25
#include "Foundation/NSDistantObject.h"
26
#include "Foundation/NSDebug.h"
27
#include "GSInvocation.h"
27
28
#include <config.h>
28
29
#include <objc/objc-api.h>
29
30
#include <avcall.h>
206
207
* we work around it.
209
static INLINE Method_t
210
static INLINE GSMethod
210
211
gs_method_for_receiver_and_selector (id receiver, SEL sel)
214
if (object_is_instance (receiver))
216
return class_get_instance_method (object_get_class
219
else if (object_is_class (receiver))
221
return class_get_class_method (object_get_meta_class
215
return GSGetMethod((GSObjCIsInstance(receiver)
216
? GSObjCClass(receiver) : (Class)receiver),
218
GSObjCIsInstance(receiver),
226
222
return METHOD_NULL;
231
227
* Selectors are not unique, and not all selectors have
232
228
* type information. This method tries to find the
233
229
* best equivalent selector with type information.
235
231
* the conversion sel -> name -> sel
236
232
* is not what we want. However
237
233
* I can not see a way to dispose of the
238
* name, except if we can access the
234
* name, except if we can access the
239
235
* internal data structures of the runtime.
241
237
* If we can access the private data structures
242
238
* we can also check for incompatible
243
239
* return types between all equivalent selectors.
247
243
gs_find_best_typed_sel (SEL sel)
249
245
if (!sel_get_type (sel))
251
const char *name = sel_get_name (sel);
247
const char *name = GSNameFromSelector(sel);
255
251
SEL tmp_sel = sel_get_any_typed_uid (name);
314
310
vatype->type = __VAvoidp;
317
vatype->type = __VAchar;
313
vatype->type = __VAchar;
320
vatype->type = __VAuchar;
316
vatype->type = __VAuchar;
323
vatype->type = __VAshort;
319
vatype->type = __VAshort;
326
vatype->type = __VAushort;
322
vatype->type = __VAushort;
329
vatype->type = __VAint;
325
vatype->type = __VAint;
332
vatype->type = __VAuint;
328
vatype->type = __VAuint;
335
vatype->type = __VAlong;
331
vatype->type = __VAlong;
338
vatype->type = __VAulong;
334
vatype->type = __VAulong;
341
vatype->type = __VAlonglong;
337
vatype->type = __VAlonglong;
343
339
case _C_ULNG_LNG:
344
vatype->type = __VAulonglong;
340
vatype->type = __VAulonglong;
347
vatype->type = __VAfloat;
343
vatype->type = __VAfloat;
350
vatype->type = __VAdouble;
346
vatype->type = __VAdouble;
352
348
case _C_STRUCT_B:
353
349
vatype->structSize = objc_sizeof_type (sel_type);
377
373
void *forwarding_callback;
380
* 1. determine return type.
376
* 1. determine return type. The compiler should have provided us with
377
* a typed selector if possible, if not we have to assume an id return.
382
sel = gs_find_best_typed_sel (sel);
383
379
sel_type = sel_get_type (sel);
387
NSLog(@"Invalid selector %s (no type information)", sel_get_name (sel));
388
383
sel_type = "@"; // Default to id return type
391
386
sel_type = objc_skip_type_qualifiers (sel_type);
392
387
gs_sel_type_to_callback_type (sel_type, &returnInfo);
395
390
* 2. Check if we have already a callback
422
417
vacallReturnTypeInfo *ret_info;
424
419
ret_info = objc_malloc (sizeof (vacallReturnTypeInfo));
425
*ret_info = returnInfo;
420
*ret_info = returnInfo;
427
422
forwarding_callback
428
423
= alloc_callback (&GSInvocationCallback, ret_info);
430
GSIMapAddPairNoRetain (&ff_callback_map,
425
GSIMapAddPairNoRetain (&ff_callback_map,
431
426
(GSIMapKey) (void *) ret_info,
432
427
(GSIMapVal) forwarding_callback);
668
676
s.self = _target;
669
677
if (GSObjCIsInstance(_target))
670
s.class = class_get_super_class(GSObjCClass(_target));
678
s.class = GSObjCSuper(GSObjCClass(_target));
672
s.class = class_get_super_class((Class)_target);
680
s.class = GSObjCSuper((Class)_target);
673
681
imp = objc_msg_lookup_super(&s, _selector);
677
imp = method_get_imp(object_is_instance(_target) ?
678
class_get_instance_method(
679
((struct objc_class*)_target)->class_pointer, _selector)
680
: class_get_class_method(
681
((struct objc_class*)_target)->class_pointer, _selector));
686
method = GSGetMethod((GSObjCIsInstance(_target)
687
? GSObjCClass(_target)
690
GSObjCIsInstance(_target),
692
imp = method_get_imp(method);
683
694
* If fast lookup failed, we may be forwarding or something ...
727
782
NSArgumentInfo *info;
728
783
GSFFCallInvocation *invocation;
729
784
NSMethodSignature *sig;
730
Method_t fwdInvMethod;
785
GSMethod fwdInvMethod;
733
787
typeinfo = (vacallReturnTypeInfo *) callback_data;
735
789
if (typeinfo->type != __VAstruct)
737
791
__va_start (args, typeinfo->type);
741
_va_start_struct (args, typeinfo->structSize,
795
_va_start_struct (args, typeinfo->structSize,
742
796
typeinfo->structAlign, typeinfo->structSplit);
748
802
fwdInvMethod = gs_method_for_receiver_and_selector
749
803
(obj, @selector (forwardInvocation:));
751
805
if (!fwdInvMethod)
753
NSCAssert2 (0, @"GSFFCallInvocation: Class '%s' does not respond"
754
@" to forwardInvocation: for '%s'",
755
object_get_class_name (obj), sel_get_name(selector));
807
[NSException raise: NSInvalidArgumentException
808
format: @"GSFFCallInvocation: Class '%s(%s)'"
810
@" to forwardInvocation: for '%s'",
811
GSClassNameFromObject(obj),
812
GSObjCIsInstance(obj) ? "instance" : "class",
813
selector ? GSNameFromSelector(selector) : "(null)"];
758
selector = gs_find_by_receiver_best_typed_sel (obj, selector);
761
if (sel_get_type (selector))
817
if (gs_protocol_selector(sel_get_type(selector)) == YES)
820
* We already have protocol information locally, so we don't need
821
* to get it from the remote system.
763
823
sig = [NSMethodSignature signatureWithObjCTypes: sel_get_type(selector)];
768
827
sig = [obj methodSignatureForSelector: selector];
771
NSCAssert1(sig, @"No signature for selector %@",
772
NSStringFromSelector(selector));
831
* If we got a method signature from the receiving object,
832
* ensure that the selector we are using matches the types.
836
const char *receiverTypes = [sig methodType];
837
const char *runtimeTypes = sel_get_type (selector);
839
if (runtimeTypes == 0 || strcmp(receiverTypes, runtimeTypes) != 0)
841
const char *runtimeName = GSNameFromSelector(selector);
843
selector = sel_get_typed_uid (runtimeName, receiverTypes);
846
selector = sel_register_typed_name (runtimeName, receiverTypes);
848
if (runtimeTypes != 0)
851
* FIXME ... if we have a typed selector, it probably came
852
* from the compiler, and the types of the proxied method
853
* MUST match those that the compiler supplied on the stack
854
* and the type it expects to retrieve from the stack.
855
* We should therefore discriminate between signatures where
856
* type qalifiers and sizes differ, and those where the
857
* actual types differ.
859
NSDebugFLog(@"Changed type signature '%s' to '%s' for '%s'",
860
runtimeTypes, receiverTypes, runtimeName);
867
selector = gs_find_best_typed_sel (selector);
869
if (sel_get_type (selector) != 0)
871
sig = [NSMethodSignature signatureWithObjCTypes: sel_get_type(selector)];
877
[NSException raise: NSInvalidArgumentException
878
format: @"Can not determine type information for %s[%s %s]",
879
GSObjCIsInstance(obj) ? "-" : "+",
880
GSClassNameFromObject(obj),
881
selector ? GSNameFromSelector(selector) : "(null)"];
774
884
invocation = [[GSFFCallInvocation alloc] initWithMethodSignature: sig];
775
885
AUTORELEASE(invocation);
776
886
[invocation setTarget: obj];
858
968
* The next line is equivalent to
860
970
* [obj forwardInvocation: invocation];
862
* but we have already the Method_t for forwardInvocation
972
* but we have already the GSMethod for forwardInvocation
863
973
* so the line below is somewhat faster. */
864
974
fwdInvMethod->method_imp (obj, fwdInvMethod->method_name, invocation);
866
/* Return the proper type */
976
/* Return the proper type */
867
977
retval = [invocation returnFrame: NULL];
899
1009
_va_return_struct(args, info[0].size, info[0].align, retval);
902
va_return_void(args);
1012
/* FIXME ... evil hack ... where the compiler did not know
1013
* selector types, if may have had to assume a method returning
1014
* an id, but the actual method may have returned void ...
1015
* we check for that case here, and use the fact that in the case
1016
* of a void return value, passing retval back as a voipd will
1017
* look like the method actually returned nil.
1019
if (typeinfo->type == __VAvoidp)
1021
va_return_ptr(args, void *, *(void **)retval);
1025
va_return_void(args);
905
1029
NSCAssert1(0, @"GSFFCallInvocation: Return Type '%s' not implemented",