2001-12-17 14:31:42 +00:00
|
|
|
|
/** Implementation of NSInvocation for GNUStep
|
2003-04-04 10:59:11 +00:00
|
|
|
|
Copyright (C) 1998,2003 Free Software Foundation, Inc.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
Author: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
1998-08-13 20:45:32 +00:00
|
|
|
|
Date: August 1998
|
|
|
|
|
Based on code by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
|
This file is part of the GNUstep Base Library.
|
1994-11-08 16:44:01 +00:00
|
|
|
|
|
1996-02-24 18:47:39 +00:00
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
1996-02-24 18:47:39 +00:00
|
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1996-02-24 18:47:39 +00:00
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2019-12-09 23:36:00 +00:00
|
|
|
|
Lesser General Public License for more details.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
1996-02-24 18:47:39 +00:00
|
|
|
|
License along with this library; if not, write to the Free
|
2006-05-15 12:07:35 +00:00
|
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
2019-12-09 23:36:00 +00:00
|
|
|
|
Boston, MA 02110 USA.
|
2001-12-18 16:54:15 +00:00
|
|
|
|
|
|
|
|
|
<title>NSInvocation class reference</title>
|
|
|
|
|
$Date$ $Revision$
|
2005-02-22 11:22:44 +00:00
|
|
|
|
*/
|
1994-11-08 16:44:01 +00:00
|
|
|
|
|
2010-02-19 08:12:46 +00:00
|
|
|
|
#import "common.h"
|
2010-02-14 10:48:10 +00:00
|
|
|
|
#define EXPOSE_NSInvocation_IVARS 1
|
|
|
|
|
#import "Foundation/NSException.h"
|
|
|
|
|
#import "Foundation/NSCoder.h"
|
2010-06-17 19:08:08 +00:00
|
|
|
|
#import "Foundation/NSData.h"
|
2010-02-14 10:48:10 +00:00
|
|
|
|
#import "Foundation/NSInvocation.h"
|
2010-06-15 05:43:38 +00:00
|
|
|
|
#import "Foundation/NSZone.h"
|
2010-02-14 10:48:10 +00:00
|
|
|
|
#import "GSInvocation.h"
|
|
|
|
|
#import "GSPrivate.h"
|
|
|
|
|
|
2000-12-08 19:06:00 +00:00
|
|
|
|
#if defined(USE_LIBFFI)
|
|
|
|
|
#include "cifframe.h"
|
|
|
|
|
#elif defined(USE_FFCALL)
|
|
|
|
|
#include "callframe.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-06-29 18:44:41 +00:00
|
|
|
|
#if defined(HAVE_SYS_MMAN_H)
|
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-07-02 10:46:16 +00:00
|
|
|
|
#if defined(HAVE_MMAP)
|
|
|
|
|
# if !defined(MAP_ANONYMOUS)
|
|
|
|
|
# if defined(MAP_ANON)
|
|
|
|
|
# define MAP_ANONYMOUS MAP_ANON
|
|
|
|
|
# else
|
|
|
|
|
# undef HAVE_MMAP
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-06-29 18:44:41 +00:00
|
|
|
|
@implementation GSCodeBuffer
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
+ (GSCodeBuffer*) memoryWithSize: (NSUInteger)_size
|
2008-06-29 18:44:41 +00:00
|
|
|
|
{
|
|
|
|
|
return [[[self alloc] initWithSize: _size] autorelease];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void*) buffer
|
|
|
|
|
{
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
2012-07-27 16:48:49 +00:00
|
|
|
|
DESTROY(frame);
|
2008-06-29 18:44:41 +00:00
|
|
|
|
if (size > 0)
|
|
|
|
|
{
|
2012-01-29 16:57:06 +00:00
|
|
|
|
#if defined(HAVE_FFI_PREP_CLOSURE_LOC)
|
|
|
|
|
ffi_closure_free(buffer);
|
|
|
|
|
#else
|
2008-06-29 18:44:41 +00:00
|
|
|
|
#if defined(HAVE_MMAP)
|
|
|
|
|
munmap(buffer, size);
|
|
|
|
|
#else
|
2016-03-09 13:16:16 +00:00
|
|
|
|
#if !defined(_WIN32) && defined(HAVE_MPROTECT)
|
2010-06-15 05:43:38 +00:00
|
|
|
|
if (mprotect(buffer, NSPageSize(), PROT_READ|PROT_WRITE) == -1)
|
2010-06-15 05:31:37 +00:00
|
|
|
|
{
|
|
|
|
|
NSLog(@"Failed to protect memory as writable: %@", [NSError _last]);
|
|
|
|
|
}
|
2010-06-14 23:52:44 +00:00
|
|
|
|
#endif
|
2010-06-16 08:45:49 +00:00
|
|
|
|
NSDeallocateMemoryPages(buffer, NSPageSize());
|
2008-06-29 18:44:41 +00:00
|
|
|
|
#endif
|
2012-01-29 16:57:06 +00:00
|
|
|
|
#endif
|
|
|
|
|
buffer = 0;
|
|
|
|
|
executable = 0;
|
|
|
|
|
size = 0;
|
2008-06-29 18:44:41 +00:00
|
|
|
|
}
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-29 16:57:06 +00:00
|
|
|
|
- (void*) executable
|
|
|
|
|
{
|
|
|
|
|
return executable;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (id) initWithSize: (NSUInteger)_size
|
2008-06-29 18:44:41 +00:00
|
|
|
|
{
|
2010-06-16 08:45:49 +00:00
|
|
|
|
NSAssert(_size > 0, @"Tried to allocate zero length buffer.");
|
|
|
|
|
NSAssert(_size <= NSPageSize(), @"Tried to allocate more than one page.");
|
2012-01-29 16:57:06 +00:00
|
|
|
|
#if defined(HAVE_FFI_PREP_CLOSURE_LOC)
|
|
|
|
|
buffer = ffi_closure_alloc(_size, &executable);
|
|
|
|
|
if (0 == buffer)
|
|
|
|
|
{
|
|
|
|
|
executable = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
size = _size;
|
|
|
|
|
}
|
|
|
|
|
#else
|
2008-06-29 18:44:41 +00:00
|
|
|
|
#if defined(HAVE_MMAP)
|
|
|
|
|
#if defined(HAVE_MPROTECT)
|
|
|
|
|
/* We have mprotect, so we create memory as writable and change it to
|
|
|
|
|
* executable later (writable and executable may not be possible at
|
|
|
|
|
* the same time).
|
|
|
|
|
*/
|
|
|
|
|
buffer = mmap (NULL, _size, PROT_READ|PROT_WRITE,
|
|
|
|
|
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
|
|
|
|
#else
|
|
|
|
|
/* We do not have mprotect, so we have to try to create writable and
|
|
|
|
|
* executable memory.
|
|
|
|
|
*/
|
|
|
|
|
buffer = mmap (NULL, _size, PROT_READ|PROT_WRITE|PROT_EXEC,
|
|
|
|
|
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
|
|
|
|
#endif /* HAVE_MPROTECT */
|
|
|
|
|
if (buffer == (void*)-1) buffer = (void*)0;
|
|
|
|
|
#else
|
2010-06-16 08:45:49 +00:00
|
|
|
|
buffer = NSAllocateMemoryPages(NSPageSize());
|
2008-06-29 18:44:41 +00:00
|
|
|
|
#endif /* HAVE_MMAP */
|
|
|
|
|
|
|
|
|
|
if (buffer == (void*)0)
|
|
|
|
|
{
|
2012-01-09 08:28:27 +00:00
|
|
|
|
NSLog(@"Failed to map %"PRIuPTR
|
|
|
|
|
" bytes for execute: %@", _size, [NSError _last]);
|
2008-06-29 18:44:41 +00:00
|
|
|
|
buffer = 0;
|
2012-01-29 16:57:06 +00:00
|
|
|
|
executable = 0;
|
2008-06-29 18:44:41 +00:00
|
|
|
|
[self dealloc];
|
|
|
|
|
self = nil;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-01-29 16:57:06 +00:00
|
|
|
|
executable = buffer;
|
2008-06-29 18:44:41 +00:00
|
|
|
|
size = _size;
|
|
|
|
|
}
|
2012-01-29 16:57:06 +00:00
|
|
|
|
#endif /* USE_LIBFFI */
|
2008-06-29 18:44:41 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ensure that the protection on the buffer is such that it will execute
|
|
|
|
|
* on any architecture.
|
|
|
|
|
*/
|
|
|
|
|
- (void) protect
|
|
|
|
|
{
|
2012-01-29 16:57:06 +00:00
|
|
|
|
#if !defined(HAVE_FFI_PREP_CLOSURE_LOC)
|
2016-03-09 13:16:16 +00:00
|
|
|
|
#if defined(_WIN32)
|
2008-06-29 19:21:15 +00:00
|
|
|
|
DWORD old;
|
|
|
|
|
if (VirtualProtect(buffer, size, PAGE_EXECUTE, &old) == 0)
|
2008-06-29 18:44:41 +00:00
|
|
|
|
{
|
|
|
|
|
NSLog(@"Failed to protect memory as executable: %@", [NSError _last]);
|
|
|
|
|
}
|
2008-06-29 19:21:15 +00:00
|
|
|
|
#elif defined(HAVE_MPROTECT)
|
2010-06-15 05:43:38 +00:00
|
|
|
|
if (mprotect(buffer, NSPageSize(), PROT_READ|PROT_EXEC) == -1)
|
2008-06-29 18:44:41 +00:00
|
|
|
|
{
|
|
|
|
|
NSLog(@"Failed to protect memory as executable: %@", [NSError _last]);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2012-01-29 16:57:06 +00:00
|
|
|
|
#endif
|
2008-06-29 18:44:41 +00:00
|
|
|
|
}
|
2012-07-27 16:48:49 +00:00
|
|
|
|
|
|
|
|
|
- (void) setFrame: (id)aFrame
|
|
|
|
|
{
|
|
|
|
|
ASSIGN(frame, aFrame);
|
|
|
|
|
}
|
2008-06-29 18:44:41 +00:00
|
|
|
|
@end
|
|
|
|
|
|
2000-12-08 19:06:00 +00:00
|
|
|
|
static Class NSInvocation_abstract_class;
|
|
|
|
|
static Class NSInvocation_concrete_class;
|
1994-11-08 16:44:01 +00:00
|
|
|
|
|
2003-04-04 10:03:08 +00:00
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
|
|
|
|
|
|
2014-05-22 16:55:18 +00:00
|
|
|
|
GS_ROOT_CLASS
|
|
|
|
|
@interface GSInvocationProxy
|
|
|
|
|
{
|
|
|
|
|
@public
|
|
|
|
|
Class isa;
|
|
|
|
|
id target;
|
|
|
|
|
NSInvocation *invocation;
|
|
|
|
|
}
|
|
|
|
|
+ (id) _newWithTarget: (id)t;
|
|
|
|
|
- (NSInvocation*) _invocation;
|
|
|
|
|
- (void) forwardInvocation: (NSInvocation*)anInvocation;
|
|
|
|
|
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector;
|
|
|
|
|
@end
|
|
|
|
|
@interface GSMessageProxy : GSInvocationProxy
|
|
|
|
|
@end
|
|
|
|
|
|
2009-10-05 16:00:28 +00:00
|
|
|
|
#define _inf ((NSArgumentInfo*)_info)
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <p>The <code>NSInvocation</code> class implements a mechanism of constructing
|
|
|
|
|
* messages (as <code>NSInvocation</code> instances), sending these to other
|
2003-04-04 10:59:11 +00:00
|
|
|
|
* objects, and handling the returned values.
|
|
|
|
|
* </p>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <p>An <code>NSInvocation</code> object may contain a target object to which a
|
2003-04-04 10:59:11 +00:00
|
|
|
|
* message can be sent, or may send the message to an arbitrary object.<br />
|
|
|
|
|
* Each message consists of a selector for that method and an argument
|
|
|
|
|
* list. Once the message has been sent, the invocation will contain
|
|
|
|
|
* a return value whose contents may be copied out of it.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>The target, selector, and arguments of an instance be constructed
|
|
|
|
|
* dynamically, providing a great deal of power/flexibility.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>The sending of the message to the target object (using the -invoke
|
|
|
|
|
* or -invokeWithTarget: method) can be done at any time, but a standard
|
|
|
|
|
* use of this is by the [NSObject-forwardInvocation:] method which is
|
|
|
|
|
* called whenever a method is not implemented by the class of the
|
|
|
|
|
* object to which it was sent.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>Related to the class are two convenience macros ... NS_MESSAGE()
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* and NS_INVOCATION() ... to allow easy construction of invocations
|
|
|
|
|
* with all the arguments set up.
|
2003-04-04 10:59:11 +00:00
|
|
|
|
* </p>
|
|
|
|
|
*/
|
1996-02-24 18:47:39 +00:00
|
|
|
|
@implementation NSInvocation
|
1994-11-08 16:44:01 +00:00
|
|
|
|
|
2000-12-08 19:06:00 +00:00
|
|
|
|
#ifdef USE_LIBFFI
|
|
|
|
|
static inline void
|
|
|
|
|
_get_arg(NSInvocation *inv, int index, void *buffer)
|
|
|
|
|
{
|
2002-04-18 16:02:12 +00:00
|
|
|
|
cifframe_get_arg((cifframe_t *)inv->_cframe, index, buffer,
|
2009-10-05 16:00:28 +00:00
|
|
|
|
((NSArgumentInfo*)inv->_info)[index+1].size);
|
2000-12-08 19:06:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
_set_arg(NSInvocation *inv, int index, void *buffer)
|
|
|
|
|
{
|
2002-04-18 16:02:12 +00:00
|
|
|
|
cifframe_set_arg((cifframe_t *)inv->_cframe, index, buffer,
|
2009-10-05 16:00:28 +00:00
|
|
|
|
((NSArgumentInfo*)inv->_info)[index+1].size);
|
2000-12-08 19:06:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void *
|
|
|
|
|
_arg_addr(NSInvocation *inv, int index)
|
|
|
|
|
{
|
|
|
|
|
return cifframe_arg_addr((cifframe_t *)inv->_cframe, index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#elif defined(USE_FFCALL)
|
|
|
|
|
static inline void
|
|
|
|
|
_get_arg(NSInvocation *inv, int index, void *buffer)
|
|
|
|
|
{
|
|
|
|
|
callframe_get_arg((callframe_t *)inv->_cframe, index, buffer,
|
2009-10-05 16:00:28 +00:00
|
|
|
|
((NSArgumentInfo*)inv->_info)[index+1].size);
|
2000-12-08 19:06:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
_set_arg(NSInvocation *inv, int index, void *buffer)
|
|
|
|
|
{
|
|
|
|
|
callframe_set_arg((callframe_t *)inv->_cframe, index, buffer,
|
2009-10-05 16:00:28 +00:00
|
|
|
|
((NSArgumentInfo*)inv->_info)[index+1].size);
|
2000-12-08 19:06:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void *
|
|
|
|
|
_arg_addr(NSInvocation *inv, int index)
|
|
|
|
|
{
|
|
|
|
|
return callframe_arg_addr((callframe_t *)inv->_cframe, index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
2009-10-04 15:26:07 +00:00
|
|
|
|
|
2001-04-20 14:04:38 +00:00
|
|
|
|
static inline void
|
2000-12-08 19:06:00 +00:00
|
|
|
|
_get_arg(NSInvocation *inv, int index, void *buffer)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
_set_arg(NSInvocation *inv, int index, void *buffer)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void *
|
|
|
|
|
_arg_addr(NSInvocation *inv, int index)
|
|
|
|
|
{
|
2009-10-04 15:26:07 +00:00
|
|
|
|
return 0;
|
2000-12-08 19:06:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+ (id) allocWithZone: (NSZone*)aZone
|
|
|
|
|
{
|
|
|
|
|
if (self == NSInvocation_abstract_class)
|
|
|
|
|
{
|
|
|
|
|
return NSAllocateObject(NSInvocation_concrete_class, 0, aZone);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return NSAllocateObject(self, 0, aZone);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
|
{
|
|
|
|
|
if (self == [NSInvocation class])
|
|
|
|
|
{
|
|
|
|
|
NSInvocation_abstract_class = self;
|
|
|
|
|
#if defined(USE_LIBFFI)
|
|
|
|
|
NSInvocation_concrete_class = [GSFFIInvocation class];
|
|
|
|
|
#elif defined(USE_FFCALL)
|
|
|
|
|
NSInvocation_concrete_class = [GSFFCallInvocation class];
|
|
|
|
|
#else
|
2009-10-04 15:26:07 +00:00
|
|
|
|
NSInvocation_concrete_class = [GSDummyInvocation class];
|
2000-12-08 19:06:00 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:03:08 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns an invocation instance which can be used to send messages to
|
|
|
|
|
* a target object using the described signature.<br />
|
2003-04-17 06:20:17 +00:00
|
|
|
|
* You must set the target and selector (using -setTarget: and -setSelector:)
|
|
|
|
|
* before you attempt to use the invocation.<br />
|
2003-04-04 10:03:08 +00:00
|
|
|
|
* Raises an NSInvalidArgumentException if the signature is nil.
|
|
|
|
|
*/
|
1999-09-16 07:21:34 +00:00
|
|
|
|
+ (NSInvocation*) invocationWithMethodSignature: (NSMethodSignature*)_signature
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
2000-12-08 19:06:00 +00:00
|
|
|
|
return AUTORELEASE([[NSInvocation_concrete_class alloc]
|
1999-09-16 07:21:34 +00:00
|
|
|
|
initWithMethodSignature: _signature]);
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-08-13 20:45:32 +00:00
|
|
|
|
- (void) dealloc
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
2005-09-17 21:41:12 +00:00
|
|
|
|
if (_targetRetained)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2005-09-17 21:41:12 +00:00
|
|
|
|
_targetRetained = NO;
|
1999-09-16 07:21:34 +00:00
|
|
|
|
RELEASE(_target);
|
2005-09-17 21:41:12 +00:00
|
|
|
|
}
|
|
|
|
|
if (_argsRetained)
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
_argsRetained = NO;
|
2002-02-20 05:08:46 +00:00
|
|
|
|
if (_cframe && _sig)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
|
unsigned int i;
|
1998-10-28 13:58:05 +00:00
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
for (i = 3; i <= _numArgs; i++)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2009-10-05 16:00:28 +00:00
|
|
|
|
if (*_inf[i].type == _C_CHARPTR)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2009-10-04 15:26:07 +00:00
|
|
|
|
char *str = 0;
|
1998-10-28 13:58:05 +00:00
|
|
|
|
|
2000-12-08 19:06:00 +00:00
|
|
|
|
_get_arg(self, i-1, &str);
|
2009-10-04 15:26:07 +00:00
|
|
|
|
if (str != 0)
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), str);
|
|
|
|
|
}
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
2009-10-05 16:00:28 +00:00
|
|
|
|
else if (*_inf[i].type == _C_ID)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2009-10-04 15:26:07 +00:00
|
|
|
|
id obj = nil;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2000-12-08 19:06:00 +00:00
|
|
|
|
_get_arg(self, i-1, &obj);
|
1999-07-03 19:59:44 +00:00
|
|
|
|
RELEASE(obj);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-02-04 18:18:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CLEAR_RETURN_VALUE_IF_OBJECT;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
2002-02-20 05:08:46 +00:00
|
|
|
|
#if defined(USE_LIBFFI)
|
2000-12-08 19:06:00 +00:00
|
|
|
|
if (_cframe)
|
2002-02-20 05:08:46 +00:00
|
|
|
|
{
|
2010-06-07 20:38:19 +00:00
|
|
|
|
/* If we get here then we are not using GC, so the _frame instance
|
|
|
|
|
* variable points to a mutable data object containing _cframe and
|
|
|
|
|
* we can release it.
|
|
|
|
|
*/
|
|
|
|
|
[((GSFFIInvocation*)self)->_frame release];
|
2002-02-20 05:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
#elif defined(USE_FFCALL)
|
2000-12-08 19:06:00 +00:00
|
|
|
|
if (_cframe)
|
2001-09-21 15:14:57 +00:00
|
|
|
|
{
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), _cframe);
|
|
|
|
|
}
|
2002-02-20 05:08:46 +00:00
|
|
|
|
#endif
|
2009-10-04 10:05:14 +00:00
|
|
|
|
if (_retptr)
|
|
|
|
|
{
|
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), _retptr);
|
|
|
|
|
}
|
1999-09-16 07:21:34 +00:00
|
|
|
|
RELEASE(_sig);
|
1998-10-28 13:58:05 +00:00
|
|
|
|
[super dealloc];
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:03:08 +00:00
|
|
|
|
/**
|
|
|
|
|
* Copies the argument identified by index into the memory location specified
|
|
|
|
|
* by the buffer argument.<br />
|
|
|
|
|
* An index of zero is the target object, an index of one is the selector,
|
|
|
|
|
* so the actual method arguments start at index 2.
|
1998-08-13 20:45:32 +00:00
|
|
|
|
*/
|
|
|
|
|
- (void) getArgument: (void*)buffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
atIndex: (NSInteger)index
|
1994-11-08 16:44:01 +00:00
|
|
|
|
{
|
2009-02-23 20:42:32 +00:00
|
|
|
|
if ((NSUInteger)index >= _numArgs)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"bad invocation argument index"];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
if (index == 0)
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
*(id*)buffer = _target;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
else if (index == 1)
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
*(SEL*)buffer = _selector;
|
1998-01-26 14:18:18 +00:00
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2000-12-08 19:06:00 +00:00
|
|
|
|
_get_arg(self, index, buffer);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Copies the invocations return value to the location pointed to by buffer
|
|
|
|
|
* if a return value has been set (see the -setReturnValue: method).<br />
|
|
|
|
|
* If there isn't a return value then this method raises an exception.
|
|
|
|
|
*/
|
1998-08-13 20:45:32 +00:00
|
|
|
|
- (void) getReturnValue: (void*)buffer
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
if (_validReturn == NO)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"getReturnValue with no value set"];
|
|
|
|
|
}
|
2009-10-05 16:00:28 +00:00
|
|
|
|
if (*_inf[0].type != _C_VOID)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2009-10-05 16:00:28 +00:00
|
|
|
|
memcpy(buffer, _retval, _inf[0].size);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the selector of the invocation (the argument at index 1)
|
|
|
|
|
*/
|
1998-08-13 20:45:32 +00:00
|
|
|
|
- (SEL) selector
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
return _selector;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sets the argument identified by index from the memory location specified
|
|
|
|
|
* by the buffer argument.<br />
|
|
|
|
|
* Using an index of 0 is equivalent to calling -setTarget: and using an
|
|
|
|
|
* argument of 1 is equivalent to -setSelector:<br />
|
|
|
|
|
* Proper arguments start at index 2.<br />
|
2003-04-12 05:13:54 +00:00
|
|
|
|
* NB. Unlike -setTarget: and -setSelector: the value of buffer must be
|
|
|
|
|
* <em>a pointer to</em> the argument to be set in the invocation.<br />
|
2003-04-04 10:59:11 +00:00
|
|
|
|
* If -retainArguments was called, then any object argument set in the
|
|
|
|
|
* receiver is retained by it.
|
|
|
|
|
*/
|
1998-08-13 20:45:32 +00:00
|
|
|
|
- (void) setArgument: (void*)buffer
|
2009-02-23 20:42:32 +00:00
|
|
|
|
atIndex: (NSInteger)index
|
1998-08-13 20:45:32 +00:00
|
|
|
|
{
|
2009-02-23 20:42:32 +00:00
|
|
|
|
if ((NSUInteger)index >= _numArgs)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"bad invocation argument index"];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
if (index == 0)
|
|
|
|
|
{
|
|
|
|
|
[self setTarget: *(id*)buffer];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
else if (index == 1)
|
|
|
|
|
{
|
|
|
|
|
[self setSelector: *(SEL*)buffer];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2009-10-05 16:00:28 +00:00
|
|
|
|
int i = index+1; /* Allow for return type in '_inf' */
|
|
|
|
|
const char *type = _inf[i].type;
|
1998-10-28 13:58:05 +00:00
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
if (_argsRetained && (*type == _C_ID || *type == _C_CHARPTR))
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (*type == _C_ID)
|
|
|
|
|
{
|
|
|
|
|
id old;
|
|
|
|
|
|
2000-12-08 19:06:00 +00:00
|
|
|
|
_get_arg(self, index, &old);
|
|
|
|
|
_set_arg(self, index, buffer);
|
2022-02-17 10:21:36 +00:00
|
|
|
|
IF_NO_ARC(RETAIN(*(id*)buffer);)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
if (old != nil)
|
|
|
|
|
{
|
1999-07-03 19:59:44 +00:00
|
|
|
|
RELEASE(old);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char *oldstr;
|
|
|
|
|
char *newstr = *(char**)buffer;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2000-12-08 19:06:00 +00:00
|
|
|
|
_get_arg(self, index, &oldstr);
|
1998-10-28 13:58:05 +00:00
|
|
|
|
if (newstr == 0)
|
|
|
|
|
{
|
2000-12-08 19:06:00 +00:00
|
|
|
|
_set_arg(self, index, buffer);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2011-03-07 11:34:17 +00:00
|
|
|
|
int len;
|
1999-09-28 11:10:34 +00:00
|
|
|
|
char *tmp;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2011-03-07 11:34:17 +00:00
|
|
|
|
len = strlen(newstr);
|
|
|
|
|
tmp = NSZoneMalloc(NSDefaultMallocZone(), len + 1);
|
|
|
|
|
strncpy(tmp, newstr, len);
|
|
|
|
|
tmp[len] = '\0';
|
2000-12-08 19:06:00 +00:00
|
|
|
|
_set_arg(self, index, tmp);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
if (oldstr != 0)
|
|
|
|
|
{
|
1999-09-28 11:10:34 +00:00
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), oldstr);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2000-12-08 19:06:00 +00:00
|
|
|
|
_set_arg(self, index, buffer);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sets the return value of the invocation to the item that buffer points to.
|
|
|
|
|
*/
|
1998-08-13 20:45:32 +00:00
|
|
|
|
- (void) setReturnValue: (void*)buffer
|
|
|
|
|
{
|
1998-10-28 13:58:05 +00:00
|
|
|
|
const char *type;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2009-10-05 16:00:28 +00:00
|
|
|
|
type = _inf[0].type;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2003-02-04 18:18:47 +00:00
|
|
|
|
CLEAR_RETURN_VALUE_IF_OBJECT;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1998-10-28 13:58:05 +00:00
|
|
|
|
if (*type != _C_VOID)
|
|
|
|
|
{
|
2009-10-05 16:00:28 +00:00
|
|
|
|
memcpy(_retval, buffer, _inf[0].size);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
2003-02-04 18:18:47 +00:00
|
|
|
|
|
|
|
|
|
RETAIN_RETURN_VALUE;
|
1999-09-16 07:21:34 +00:00
|
|
|
|
_validReturn = YES;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sets the selector for the invocation.
|
|
|
|
|
*/
|
1998-08-13 20:45:32 +00:00
|
|
|
|
- (void) setSelector: (SEL)aSelector
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
_selector = aSelector;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sets the target object for the invocation.<br />
|
|
|
|
|
* If -retainArguments was called, then the target is retained.
|
|
|
|
|
*/
|
1998-08-13 20:45:32 +00:00
|
|
|
|
- (void) setTarget: (id)anObject
|
|
|
|
|
{
|
2005-09-17 21:41:12 +00:00
|
|
|
|
if (_targetRetained)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
ASSIGN(_target, anObject);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
2005-09-17 21:41:12 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_target = anObject;
|
|
|
|
|
}
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the target object of the invocation.
|
|
|
|
|
*/
|
1998-08-13 20:45:32 +00:00
|
|
|
|
- (id) target
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
return _target;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a flag to indicate whether object arguments of the invocation
|
|
|
|
|
* (including its target) are retained by the invocation.
|
1998-08-13 20:45:32 +00:00
|
|
|
|
*/
|
|
|
|
|
- (BOOL) argumentsRetained
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
return _argsRetained;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Instructs the invocation to retain its object arguments (including the
|
2005-09-17 21:41:12 +00:00
|
|
|
|
* target). The default is not to retain them.
|
2003-04-04 10:59:11 +00:00
|
|
|
|
*/
|
1999-09-16 07:21:34 +00:00
|
|
|
|
- (void) retainArguments
|
1998-08-13 20:45:32 +00:00
|
|
|
|
{
|
2005-09-17 21:41:12 +00:00
|
|
|
|
[self retainArgumentsIncludingTarget: YES];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns YES if target has been retained yet, NO otherwise.
|
|
|
|
|
*/
|
|
|
|
|
- (BOOL) targetRetained
|
|
|
|
|
{
|
|
|
|
|
return _targetRetained;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Similar to -[NSInvocation retainArguments], but allows the sender to
|
|
|
|
|
* explicitly control whether the target is retained as well. Retaining
|
|
|
|
|
* the target is sometimes not desirable (such as in NSUndoManager), as
|
|
|
|
|
* retain loops could result.
|
|
|
|
|
*/
|
|
|
|
|
- (void) retainArgumentsIncludingTarget: (BOOL)retainTargetFlag
|
|
|
|
|
{
|
|
|
|
|
if (_argsRetained == NO)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
|
unsigned int i;
|
1998-10-28 13:58:05 +00:00
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
_argsRetained = YES;
|
2002-02-20 05:08:46 +00:00
|
|
|
|
if (_cframe == 0)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
|
|
|
|
return;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1999-09-16 07:21:34 +00:00
|
|
|
|
for (i = 3; i <= _numArgs; i++)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2009-10-05 16:00:28 +00:00
|
|
|
|
if (*_inf[i].type == _C_ID)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2005-09-17 21:41:12 +00:00
|
|
|
|
id old;
|
1998-10-28 13:58:05 +00:00
|
|
|
|
|
2005-09-17 21:41:12 +00:00
|
|
|
|
_get_arg(self, i-1, &old);
|
|
|
|
|
if (old != nil)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2022-02-17 10:21:36 +00:00
|
|
|
|
IF_NO_ARC(RETAIN(old);)
|
2005-09-17 21:41:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-05 16:00:28 +00:00
|
|
|
|
else if (*_inf[i].type == _C_CHARPTR)
|
2005-09-17 21:41:12 +00:00
|
|
|
|
{
|
|
|
|
|
char *str;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2005-09-17 21:41:12 +00:00
|
|
|
|
_get_arg(self, i-1, &str);
|
|
|
|
|
if (str != 0)
|
|
|
|
|
{
|
|
|
|
|
char *tmp;
|
2011-03-07 11:34:17 +00:00
|
|
|
|
int len;
|
2005-09-17 21:41:12 +00:00
|
|
|
|
|
2011-03-07 11:34:17 +00:00
|
|
|
|
len = strlen(str);
|
|
|
|
|
tmp = NSZoneMalloc(NSDefaultMallocZone(), len + 1);
|
|
|
|
|
strncpy(tmp, str, len);
|
|
|
|
|
tmp[len] = '\0';
|
2005-09-17 21:41:12 +00:00
|
|
|
|
_set_arg(self, i-1, &tmp);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-09-17 21:41:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (retainTargetFlag && _targetRetained == NO)
|
|
|
|
|
{
|
|
|
|
|
_targetRetained = YES;
|
|
|
|
|
|
2022-02-17 10:21:36 +00:00
|
|
|
|
IF_NO_ARC(RETAIN(_target);)
|
2005-09-17 21:41:12 +00:00
|
|
|
|
}
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sends the message encapsulated in the invocation to its target.
|
1998-08-13 20:45:32 +00:00
|
|
|
|
*/
|
|
|
|
|
- (void) invoke
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
[self invokeWithTarget: _target];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sends the message encapsulated in the invocation to anObject.
|
|
|
|
|
*/
|
1999-09-16 07:21:34 +00:00
|
|
|
|
- (void) invokeWithTarget: (id)anObject
|
1998-08-13 20:45:32 +00:00
|
|
|
|
{
|
2009-08-15 21:44:21 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the method signature of the invocation.
|
1998-08-13 20:45:32 +00:00
|
|
|
|
*/
|
|
|
|
|
- (NSMethodSignature*) methodSignature
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
return _sig;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
- (NSString*) description
|
1998-08-13 20:45:32 +00:00
|
|
|
|
{
|
1998-10-28 13:58:05 +00:00
|
|
|
|
/*
|
|
|
|
|
* Don't use -[NSString stringWithFormat:] method because it can cause
|
|
|
|
|
* infinite recursion.
|
|
|
|
|
*/
|
|
|
|
|
char buffer[1024];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2003-08-24 23:07:41 +00:00
|
|
|
|
snprintf (buffer, 1024, "<%s %p selector: %s target: %s>", \
|
2006-10-09 14:00:01 +00:00
|
|
|
|
GSClassNameFromObject(self), \
|
|
|
|
|
self, \
|
2010-02-22 10:13:20 +00:00
|
|
|
|
_selector ? sel_getName(_selector) : "nil", \
|
|
|
|
|
_target ? class_getName([_target class]) : "nil" \
|
2006-10-09 14:00:01 +00:00
|
|
|
|
);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2006-10-09 14:00:01 +00:00
|
|
|
|
return [NSString stringWithUTF8String: buffer];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
const char *types = [_sig methodType];
|
2003-01-03 20:14:47 +00:00
|
|
|
|
unsigned int i;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-10-28 13:58:05 +00:00
|
|
|
|
[aCoder encodeValueOfObjCType: @encode(char*)
|
|
|
|
|
at: &types];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
[aCoder encodeObject: _target];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2009-10-05 16:00:28 +00:00
|
|
|
|
[aCoder encodeValueOfObjCType: _inf[2].type
|
1999-09-16 07:21:34 +00:00
|
|
|
|
at: &_selector];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
for (i = 3; i <= _numArgs; i++)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2009-10-05 16:00:28 +00:00
|
|
|
|
const char *type = _inf[i].type;
|
1998-10-28 13:58:05 +00:00
|
|
|
|
void *datum;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2000-12-08 19:06:00 +00:00
|
|
|
|
datum = _arg_addr(self, i-1);
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1998-10-28 13:58:05 +00:00
|
|
|
|
if (*type == _C_ID)
|
|
|
|
|
{
|
|
|
|
|
[aCoder encodeObject: *(id*)datum];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[aCoder encodeValueOfObjCType: type at: datum];
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-05 16:00:28 +00:00
|
|
|
|
if (*_inf[0].type != _C_VOID)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &_validReturn];
|
|
|
|
|
if (_validReturn)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2009-10-05 16:00:28 +00:00
|
|
|
|
[aCoder encodeValueOfObjCType: _inf[0].type at: _retval];
|
1998-10-28 13:58:05 +00:00
|
|
|
|
}
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1994-11-08 16:44:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-08-13 20:45:32 +00:00
|
|
|
|
- (id) initWithCoder: (NSCoder*)aCoder
|
|
|
|
|
{
|
1998-10-28 13:58:05 +00:00
|
|
|
|
NSMethodSignature *newSig;
|
|
|
|
|
const char *types;
|
|
|
|
|
void *datum;
|
2003-01-03 20:14:47 +00:00
|
|
|
|
unsigned int i;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1998-10-28 13:58:05 +00:00
|
|
|
|
[aCoder decodeValueOfObjCType: @encode(char*) at: &types];
|
|
|
|
|
newSig = [NSMethodSignature signatureWithObjCTypes: types];
|
2000-07-02 18:57:05 +00:00
|
|
|
|
NSZoneFree(NSDefaultMallocZone(), (void*)types);
|
2000-12-08 19:06:00 +00:00
|
|
|
|
|
2010-02-25 18:49:31 +00:00
|
|
|
|
DESTROY(self);
|
2010-02-26 08:39:47 +00:00
|
|
|
|
self = RETAIN([NSInvocation invocationWithMethodSignature: newSig]);
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
[aCoder decodeValueOfObjCType: @encode(id) at: &_target];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
[aCoder decodeValueOfObjCType: @encode(SEL) at: &_selector];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
for (i = 3; i <= _numArgs; i++)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
2000-12-08 19:06:00 +00:00
|
|
|
|
datum = _arg_addr(self, i-1);
|
2009-10-05 16:00:28 +00:00
|
|
|
|
[aCoder decodeValueOfObjCType: _inf[i].type at: datum];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
1999-09-16 07:21:34 +00:00
|
|
|
|
_argsRetained = YES;
|
2009-10-05 16:00:28 +00:00
|
|
|
|
if (*_inf[0].type != _C_VOID)
|
1998-10-28 13:58:05 +00:00
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
[aCoder decodeValueOfObjCType: @encode(BOOL) at: &_validReturn];
|
|
|
|
|
if (_validReturn)
|
2003-02-04 18:18:47 +00:00
|
|
|
|
{
|
2009-10-05 16:00:28 +00:00
|
|
|
|
[aCoder decodeValueOfObjCType: _inf[0].type at: _retval];
|
2003-02-04 18:18:47 +00:00
|
|
|
|
}
|
1998-10-28 13:58:05 +00:00
|
|
|
|
}
|
|
|
|
|
return self;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
1994-11-08 16:44:01 +00:00
|
|
|
|
@end
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2003-04-04 10:59:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Provides some minor extensions and some utility methods to aid
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* integration of <code>NSInvocation</code> with the Objective-C runtime.
|
2003-04-04 10:59:11 +00:00
|
|
|
|
*/
|
1998-08-13 20:45:32 +00:00
|
|
|
|
@implementation NSInvocation (GNUstep)
|
|
|
|
|
|
2006-03-08 11:28:59 +00:00
|
|
|
|
- (BOOL) sendsToSuper
|
|
|
|
|
{
|
|
|
|
|
return _sendToSuper;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) setSendsToSuper: (BOOL)flag
|
|
|
|
|
{
|
|
|
|
|
_sendToSuper = flag;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* These methods are for internal use only ... not public API<br />
|
|
|
|
|
* They are used by the NS_INVOCATION() and NS_MESSAGE() macros to help
|
|
|
|
|
* create invocations.
|
|
|
|
|
*/
|
|
|
|
|
@implementation NSInvocation (MacroSetup)
|
1998-08-13 20:45:32 +00:00
|
|
|
|
|
2003-04-04 10:03:08 +00:00
|
|
|
|
/** <init /><override-subclass />
|
|
|
|
|
* Initialised an invocation instance which can be used to send messages to
|
|
|
|
|
* a target object using aSignature.<br />
|
2003-04-17 06:20:17 +00:00
|
|
|
|
* You must set the target and selector (using -setTarget: and -setSelector:)
|
|
|
|
|
* before you attempt to use the invocation.<br />
|
2003-04-04 10:03:08 +00:00
|
|
|
|
* Raises an NSInvalidArgumentException if aSignature is nil.
|
1998-08-13 20:45:32 +00:00
|
|
|
|
*/
|
1999-09-16 07:21:34 +00:00
|
|
|
|
- (id) initWithMethodSignature: (NSMethodSignature*)aSignature
|
1998-08-13 20:45:32 +00:00
|
|
|
|
{
|
2000-12-08 19:06:00 +00:00
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
return nil;
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-05-22 16:55:18 +00:00
|
|
|
|
/**
|
|
|
|
|
* Internal use.
|
|
|
|
|
*/
|
|
|
|
|
+ (id) _newProxyForInvocation: (id)target
|
|
|
|
|
{
|
|
|
|
|
return (id)[GSInvocationProxy _newWithTarget: target];
|
|
|
|
|
}
|
|
|
|
|
+ (id) _newProxyForMessage: (id)target
|
|
|
|
|
{
|
|
|
|
|
return (id)[GSMessageProxy _newWithTarget: target];
|
|
|
|
|
}
|
|
|
|
|
+ (NSInvocation*) _returnInvocationAndDestroyProxy: (id)proxy
|
|
|
|
|
{
|
|
|
|
|
NSInvocation *inv = [proxy _invocation];
|
|
|
|
|
NSDeallocateObject(proxy);
|
|
|
|
|
return inv;
|
|
|
|
|
}
|
1998-08-13 20:45:32 +00:00
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation NSInvocation (BackwardCompatibility)
|
|
|
|
|
|
|
|
|
|
- (void) invokeWithObject: (id)obj
|
|
|
|
|
{
|
1998-10-28 13:58:05 +00:00
|
|
|
|
[self invokeWithTarget: (id)obj];
|
1998-08-13 20:45:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
2009-08-15 21:44:21 +00:00
|
|
|
|
#if !defined(USE_FFCALL) && !defined(USE_LIBFFI)
|
2009-10-04 15:26:07 +00:00
|
|
|
|
#warning Using dummy NSInvocation implementation. It is strongly recommended that you use libffi.
|
|
|
|
|
@implementation GSDummyInvocation
|
2000-12-08 19:06:00 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is the de_signated initialiser.
|
|
|
|
|
*/
|
|
|
|
|
- (id) initWithMethodSignature: (NSMethodSignature*)aSignature
|
|
|
|
|
{
|
|
|
|
|
return self;
|
|
|
|
|
}
|
2009-08-15 21:44:21 +00:00
|
|
|
|
|
2009-10-04 15:26:07 +00:00
|
|
|
|
- (void) invokeWithTarget: (id)anObject
|
|
|
|
|
{
|
2009-08-15 21:44:21 +00:00
|
|
|
|
CLEAR_RETURN_VALUE_IF_OBJECT;
|
|
|
|
|
_validReturn = NO;
|
|
|
|
|
/*
|
|
|
|
|
* A message to a nil object returns nil.
|
|
|
|
|
*/
|
|
|
|
|
if (anObject == nil)
|
|
|
|
|
{
|
|
|
|
|
_validReturn = YES;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-12-08 19:06:00 +00:00
|
|
|
|
|
|
|
|
|
@end
|
2009-08-15 21:44:21 +00:00
|
|
|
|
#endif
|
2003-04-04 10:03:08 +00:00
|
|
|
|
|
2014-05-22 16:55:18 +00:00
|
|
|
|
@implementation GSInvocationProxy
|
|
|
|
|
+ (id) _newWithTarget: (id)t
|
|
|
|
|
{
|
|
|
|
|
GSInvocationProxy *o;
|
|
|
|
|
o = (GSInvocationProxy*) NSAllocateObject(self, 0, NSDefaultMallocZone());
|
|
|
|
|
o->target = RETAIN(t);
|
|
|
|
|
return o;
|
|
|
|
|
}
|
|
|
|
|
- (NSInvocation*) _invocation
|
|
|
|
|
{
|
|
|
|
|
return invocation;
|
|
|
|
|
}
|
|
|
|
|
- (void) forwardInvocation: (NSInvocation*)anInvocation
|
|
|
|
|
{
|
|
|
|
|
invocation = anInvocation;
|
|
|
|
|
}
|
|
|
|
|
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
|
|
|
|
|
{
|
|
|
|
|
return [target methodSignatureForSelector: aSelector];
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation GSMessageProxy
|
|
|
|
|
- (NSInvocation*) _invocation
|
|
|
|
|
{
|
|
|
|
|
[invocation setTarget: target];
|
|
|
|
|
return invocation;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|