diff --git a/ChangeLog b/ChangeLog index 50360ec23..5f9683c08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2003-07-04 Richard Frith-Macdonald + + * Source/Source/GSFFCallInvocation.m: Modify to use local type + information if it looks like it has come from a protocol ... + as too much existing code is broken in that DO server objects + which are supposed to conform to protocols in fact do not! + * Source/GSFFIInvocation.m: ditto + Fri Jul 4 11:09:37 2003 Nicola Pero * NSTimeZones/Makefile.postamble: Make the code more robust by diff --git a/Source/GSFFCallInvocation.m b/Source/GSFFCallInvocation.m index 2e1431460..42513faf6 100644 --- a/Source/GSFFCallInvocation.m +++ b/Source/GSFFCallInvocation.m @@ -715,6 +715,44 @@ GSFFCallInvokeWithTargetAndImp(NSInvocation *_inv, id anObject, IMP imp) } @end +/* + * Return YES if the selector contains protocol qualifiers. + */ +static BOOL +gs_protocol_selector(const char *types) +{ + if (types == 0) + { + return NO; + } + while (*types != '\0') + { + if (*types == '+' || isdigit(*types)) + { + types = objc_skip_offset(types); + } + while (*types == _C_CONST || *types == _C_GCINVISIBLE) + { + types++; + } + if (*types == _C_IN + || *types == _C_INOUT + || *types == _C_OUT + || *types == _C_BYCOPY + || *types == _C_BYREF + || *types == _C_ONEWAY) + { + return YES; + } + if (*types == '\0') + { + return NO; + } + types = objc_skip_typespec(types); + } + return NO; +} + /* * Wim Oudshoorn (6 aug 2001) * @@ -743,7 +781,6 @@ GSInvocationCallback (void *callback_data, va_alist args) NSMethodSignature *sig; GSMethod fwdInvMethod; - typeinfo = (vacallReturnTypeInfo *) callback_data; if (typeinfo->type != __VAstruct) @@ -769,7 +806,19 @@ GSInvocationCallback (void *callback_data, va_alist args) object_get_class_name (obj), sel_get_name(selector)); } - sig = [obj methodSignatureForSelector: selector]; + sig = nil; + if (gs_protocol_selector(sel_get_type(selector)) == YES) + { + /* + * We already have protocol information locally, so we don't need + * to get it from the remote system. + */ + sig = [NSMethodSignature signatureWithObjCTypes: sel_get_type(selector)]; + } + if (sig == nil) + { + sig = [obj methodSignatureForSelector: selector]; + } /* * If we got a method signature from the receiving object, diff --git a/Source/GSFFIInvocation.m b/Source/GSFFIInvocation.m index bb34e0214..e8427fdd2 100644 --- a/Source/GSFFIInvocation.m +++ b/Source/GSFFIInvocation.m @@ -353,6 +353,44 @@ GSFFIInvokeWithTargetAndImp(NSInvocation *_inv, id anObject, IMP imp) } @end +/* + * Return YES if the selector contains protocol qualifiers. + */ +static BOOL +gs_protocol_selector(const char *types) +{ + if (types == 0) + { + return NO; + } + while (*types != '\0') + { + if (*types == '+' || isdigit(*types)) + { + types = objc_skip_offset(types); + } + while (*types == _C_CONST || *types == _C_GCINVISIBLE) + { + types++; + } + if (*types == _C_IN + || *types == _C_INOUT + || *types == _C_OUT + || *types == _C_BYCOPY + || *types == _C_BYREF + || *types == _C_ONEWAY) + { + return YES; + } + if (*types == '\0') + { + return NO; + } + types = objc_skip_typespec(types); + } + return NO; +} + void GSFFIInvocationCallback(ffi_cif *cif, void *retp, void **args, void *user) { @@ -375,7 +413,15 @@ GSFFIInvocationCallback(ffi_cif *cif, void *retp, void **args, void *user) object_get_class_name (obj), sel_get_name(selector)); } - sig = [obj methodSignatureForSelector: selector]; + sig = nil; + if (gs_protocol_selector(sel_get_type(selector)) == YES) + { + sig = [NSMethodSignature signatureWithObjCTypes: sel_get_type(selector)]; + } + if (sig == nil) + { + sig = [obj methodSignatureForSelector: selector]; + } /* * If we got a method signature from the receiving object,