diff --git a/ChangeLog b/ChangeLog index 17b2d6f76..7fb36b515 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +Mon Apr 27 15:45:00 1998 Richard Frith-Macdonald + + * src/include/mframe.h: Added three new functions to enable passing + of pointers using the mframe routines. + + * src/mframe.m: Added mframe_dissect_call_opts(), + mframe_do_call_opts(), and mframe_build_return_opts() so that we + may pass pointers to and from functions in other languages rather + than using the DO behaviour which is to copy a single object when + given a pointer. + +Tue Apr 21 15:45:00 1998 Richard Frith-Macdonald + + * src/NSMethodSignature.m: ([+signatureWithObjCTypes:]) rewritten + to use some macros from libFoundation (adapted from gcc) to handle + creation of NSMethodSignature objects where the types string passed + in does not contain the position information of the arguments. + Thu Apr 16 13:45:00 1998 Richard Frith-Macdonald * checks/client.m: enable testing of DO strucuture return. diff --git a/Documentation/todo.tmpl.texi b/Documentation/todo.tmpl.texi index d5de1aa33..db57c3a12 100644 --- a/Documentation/todo.tmpl.texi +++ b/Documentation/todo.tmpl.texi @@ -14,6 +14,8 @@ help is greatly appreciated. Send email to @itemize @bullet +@item Fix all the places marked FIXME or xxx. + @item Need to improve the testsuite and actually run it on gstep-base. @item Change all the assert()'s (especially in the archiving code) to diff --git a/Headers/gnustep/base/mframe.h b/Headers/gnustep/base/mframe.h index c5c20e765..c5be7be7e 100644 --- a/Headers/gnustep/base/mframe.h +++ b/Headers/gnustep/base/mframe.h @@ -43,6 +43,10 @@ BOOL mframe_dissect_call (arglist_t argframe, const char *types, void (*encoder)(int,void*,const char*,int)); +BOOL +mframe_dissect_call_opts (arglist_t argframe, const char *types, + void (*encoder)(int,void*,const char*,int), + BOOL pass_pointers); /* Decode the arguments to a method call by calling DECODER, knowing what to decode by looking at type string ENCODED_TYPES. Build an @@ -53,6 +57,11 @@ void mframe_do_call (const char *encoded_types, void(*decoder)(int,void*,const char*), void(*encoder)(int,void*,const char*,int)); +void +mframe_do_call_opts (const char *encoded_types, + void(*decoder)(int,void*,const char*), + void(*encoder)(int,void*,const char*,int), + BOOL pass_pointers); /* Decode the return value and pass-by-reference arguments using DECODER, knowning what to decode by looking at type string TYPES @@ -63,5 +72,10 @@ retval_t mframe_build_return (arglist_t argframe, const char *types, BOOL out_parameters, void(*decoder)(int,void*,const char*,int)); +retval_t +mframe_build_return_opts (arglist_t argframe, const char *types, + BOOL out_parameters, + void(*decoder)(int,void*,const char*,int), + BOOL pass_pointers); #endif /* __mframe_h_GNUSTEP_BASE_INCLUDE */ diff --git a/Source/NSMethodSignature.m b/Source/NSMethodSignature.m index e187b7658..25b8d1531 100644 --- a/Source/NSMethodSignature.m +++ b/Source/NSMethodSignature.m @@ -43,6 +43,371 @@ #include #include + +/* + * These macros incorporated from libFoundation by R. Frith-Macdonald + * are subject to the following copyright rather than the LGPL - + * + * Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea. + * All rights reserved. + * + * Author: Ovidiu Predescu + * + * This file is part of libFoundation. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. + * + * We disclaim all warranties with regard to this software, including all + * implied warranties of merchantability and fitness, in no event shall + * we be liable for any special, indirect or consequential damages or any + * damages whatsoever resulting from loss of use, data or profits, whether in + * an action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + */ + +#ifndef ROUND +#define ROUND(V, A) \ + ({ typeof(V) __v=(V); typeof(A) __a=(A); \ + __a*((__v+__a-1)/__a); }) +#endif + + +#if defined(alpha) && defined(linux) + +#ifndef OBJC_FORWARDING_STACK_OFFSET +#define OBJC_FORWARDING_STACK_OFFSET 0 +#endif + +#ifndef OBJC_FORWARDING_MIN_OFFSET +#define OBJC_FORWARDING_MIN_OFFSET 0 +#endif + +#define CUMULATIVE_ARGS int + +#define INIT_CUMULATIVE_ARGS(CUM) ((CUM) = 0) + +#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \ + ({ id encoding; \ + const char* type = [(TYPE) cString]; \ + int align = objc_alignof_type(type); \ + int type_size = objc_sizeof_type(type); \ +\ + (CUM) = ROUND((CUM), align); \ + encoding = [NSString stringWithFormat:@"%@%d", \ + (TYPE), \ + (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \ + (STACK_ARGSIZE) = (CUM) + type_size; \ + (CUM) += ROUND(type_size, sizeof(void*)); \ + encoding; }) + + +#endif /* i386 linux */ + +#if defined(hppa) + +#ifndef OBJC_FORWARDING_STACK_OFFSET +#define OBJC_FORWARDING_STACK_OFFSET 0 +#endif + +#ifndef OBJC_FORWARDING_MIN_OFFSET +#define OBJC_FORWARDING_MIN_OFFSET 0 +#endif + +#define CUMULATIVE_ARGS int + +#define INIT_CUMULATIVE_ARGS(CUM) ((CUM) = 0) + +#define FUNCTION_ARG_SIZE(TYPESIZE) \ + ((TYPESIZE + 3) / 4) + +#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \ + ({ id encoding; \ + int align = objc_alignof_type([(TYPE) cString]); \ + int type_size = objc_sizeof_type([(TYPE) cString]); \ + const char* type = [(TYPE) cString]; \ +\ + (CUM) = ROUND((CUM), align); \ + encoding = [NSString stringWithFormat:@"%@%d", \ + (TYPE), \ + (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \ + if((*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B)) \ + (STACK_ARGSIZE) = (CUM) + ROUND(type_size, align); \ + else (STACK_ARGSIZE) = (CUM) + type_size; \ +\ + /* Compute the new value of cumulative args */ \ + ((((CUM) & 01) && FUNCTION_ARG_SIZE(type_size) > 1) && (CUM)++); \ + (CUM) += FUNCTION_ARG_SIZE(type_size); \ + encoding; }) + +#endif /* hppa */ + +#if defined(i386) && defined(linux) + +#ifndef OBJC_FORWARDING_STACK_OFFSET +#define OBJC_FORWARDING_STACK_OFFSET 0 +#endif + +#ifndef OBJC_FORWARDING_MIN_OFFSET +#define OBJC_FORWARDING_MIN_OFFSET 0 +#endif + +#define CUMULATIVE_ARGS int + +#define INIT_CUMULATIVE_ARGS(CUM) ((CUM) = 0) + +#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \ + ({ id encoding; \ + const char* type = [(TYPE) cString]; \ + int align = objc_alignof_type(type); \ + int type_size = objc_sizeof_type(type); \ +\ + (CUM) = ROUND((CUM), align); \ + encoding = [NSString stringWithFormat:@"%@%d", \ + (TYPE), \ + (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \ + if((*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) \ + && type_size > 2) \ + (STACK_ARGSIZE) = (CUM) + ROUND(type_size, align); \ + else (STACK_ARGSIZE) = (CUM) + type_size; \ + (CUM) += ROUND(type_size, sizeof(void*)); \ + encoding; }) + +#endif /* i386 linux */ + +#if defined(m68k) + +#ifndef OBJC_FORWARDING_STACK_OFFSET +#define OBJC_FORWARDING_STACK_OFFSET 0 +#endif + +#ifndef OBJC_FORWARDING_MIN_OFFSET +#define OBJC_FORWARDING_MIN_OFFSET 0 +#endif + +#define CUMULATIVE_ARGS int + +#define INIT_CUMULATIVE_ARGS(CUM) ((CUM) = 0) + +#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \ + ({ id encoding; \ + const char* type = [(TYPE) cString]; \ + int align = objc_alignof_type(type); \ + int type_size = objc_sizeof_type(type); \ +\ + (CUM) = ROUND((CUM), align); \ + if(type_size < sizeof(int)) \ + (CUM) += sizeof(int) - ROUND(type_size, align); \ + encoding = [NSString stringWithFormat:@"%@%d", \ + (TYPE), \ + (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \ + if((*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) \ + && type_size > 2) \ + (STACK_ARGSIZE) = (CUM) + ROUND(type_size, align); \ + else (STACK_ARGSIZE) = (CUM) + ROUND(type_size, align); \ + (CUM) += type_size < sizeof(int) \ + ? ROUND(type_size, align) \ + : ROUND(type_size, sizeof(void*)); \ + encoding; }) + +#endif /* m68k */ + +#if defined(sparc) && defined(solaris) + +#ifndef OBJC_FORWARDING_STACK_OFFSET +#define OBJC_FORWARDING_STACK_OFFSET 0 +#endif + +#ifndef OBJC_FORWARDING_MIN_OFFSET +#define OBJC_FORWARDING_MIN_OFFSET 0 +#endif + +/* From config/sparc/sparc.h in the GCC sources: + + On SPARC the first six args are normally in registers + and the rest are pushed. Any arg that starts within the first 6 words + is at least partially passed in a register unless its data type forbids. + For v9, the first 6 int args are passed in regs and the first N + float args are passed in regs (where N is such that %f0-15 are filled). + The rest are pushed. Any arg that starts within the first 6 words + is at least partially passed in a register unless its data type forbids. + + ... + + The SPARC ABI stipulates passing struct arguments (of any size) and + (!v9) quad-precision floats by invisible reference. +*/ + +enum sparc_arg_location { IN_REGS = 0, ON_STACK = 1 }; + +struct sparc_args { + int offsets[2]; /* 0 for args in regs, 1 for the rest of args on stack */ + int onStack; +}; + +#define CUMULATIVE_ARGS struct sparc_args + +/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before + processing the first argument of a method. */ + +#define INIT_CUMULATIVE_ARGS(CUM) \ + ({ (CUM).offsets[0] = 8; /* encoding in regs starts from 8 */ \ + (CUM).offsets[1] = 20; /* encoding in regs starts from 20 or 24 */ \ + (CUM).onStack = NO; }) + +#define GET_SPARC_ARG_LOCATION(CUM, CSTRING_TYPE, TYPESIZE) \ + ((CUM).onStack \ + ? ON_STACK \ + : ((CUM).offsets[IN_REGS] + TYPESIZE <= 6 * sizeof(int) + 8 \ + ? (((CUM).offsets[IN_REGS] + TYPESIZE <= 6 * sizeof(int) + 4 \ + ? 0 : ((CUM).offsets[ON_STACK] += 4)),\ + IN_REGS) \ + : ((CUM).onStack = YES, ON_STACK))) + +#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \ + ({ id encoding; \ + const char* type = [(TYPE) cString]; \ + int align = objc_alignof_type(type); \ + int type_size = objc_sizeof_type(type); \ + int arg_location = GET_SPARC_ARG_LOCATION(CUM, type, type_size); \ +\ + (CUM).offsets[arg_location] \ + = ROUND((CUM).offsets[arg_location], align); \ + if(type_size < sizeof(int)) \ + (CUM).offsets[arg_location] += sizeof(int) - ROUND(type_size, align); \ + encoding = [NSString stringWithFormat: \ + (arg_location == IN_REGS ? @"%@+%d" : @"%@%d"), \ + (TYPE), \ + (arg_location == IN_REGS \ + ? ((CUM).offsets[arg_location] \ + + OBJC_FORWARDING_STACK_OFFSET) \ + : (CUM).offsets[arg_location])]; \ + if(arg_location == ON_STACK) { \ + if((*type == _C_STRUCT_B || *type == _C_UNION_B \ + || *type == _C_ARY_B)) \ + (STACK_ARGSIZE) = (CUM).offsets[ON_STACK] + ROUND(type_size, align); \ + else (STACK_ARGSIZE) = (CUM).offsets[ON_STACK] + type_size; \ + } \ + (CUM).offsets[arg_location] += \ + type_size < sizeof(int) \ + ? ROUND(type_size, align) \ + : ROUND(type_size, sizeof(void*)); \ + encoding; }) + +#endif /* sparc solaris */ + +#if defined(sparc) && defined(linux) + +#ifndef OBJC_FORWARDING_STACK_OFFSET +#define OBJC_FORWARDING_STACK_OFFSET 0 +#endif + +#ifndef OBJC_FORWARDING_MIN_OFFSET +#define OBJC_FORWARDING_MIN_OFFSET 0 +#endif + +enum sparc_arg_location { IN_REGS = 0, ON_STACK = 1 }; + +struct sparc_args { + int offsets[2]; /* 0 for args in regs, 1 for the rest of args on stack */ + int onStack; +}; + +#define CUMULATIVE_ARGS struct sparc_args + +#define INIT_CUMULATIVE_ARGS(CUM) \ + ({ (CUM).offsets[0] = 8; /* encoding in regs starts from 8 */ \ + (CUM).offsets[1] = 20; /* encoding in regs starts from 20 or 24 */ \ + (CUM).onStack = NO; }) + +#define GET_SPARC_ARG_LOCATION(CUM, CSTRING_TYPE, TYPESIZE) \ + ((CUM).onStack \ + ? ON_STACK \ + : ((CUM).offsets[IN_REGS] + TYPESIZE <= 6 * sizeof(int) + 8 \ + ? (((CUM).offsets[IN_REGS] + TYPESIZE <= 6 * sizeof(int) + 4 \ + ? 0 : ((CUM).offsets[ON_STACK] += 4)),\ + IN_REGS) \ + : ((CUM).onStack = YES, ON_STACK))) + +#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \ + ({ id encoding; \ + const char* type = [(TYPE) cString]; \ + int align = objc_alignof_type(type); \ + int type_size = objc_sizeof_type(type); \ + int arg_location = GET_SPARC_ARG_LOCATION(CUM, type, type_size); \ +\ + (CUM).offsets[arg_location] \ + = ROUND((CUM).offsets[arg_location], align); \ + if(type_size < sizeof(int)) \ + (CUM).offsets[arg_location] += sizeof(int) - ROUND(type_size, align); \ + encoding = [NSString stringWithFormat: \ + (arg_location == IN_REGS ? @"%@+%d" : @"%@%d"), \ + (TYPE), \ + (arg_location == IN_REGS \ + ? ((CUM).offsets[arg_location] \ + + OBJC_FORWARDING_STACK_OFFSET) \ + : (CUM).offsets[arg_location])]; \ + if(arg_location == ON_STACK) { \ + if((*type == _C_STRUCT_B || *type == _C_UNION_B \ + || *type == _C_ARY_B)) \ + (STACK_ARGSIZE) = (CUM).offsets[ON_STACK] + ROUND(type_size, align); \ + else (STACK_ARGSIZE) = (CUM).offsets[ON_STACK] + type_size; \ + } \ + (CUM).offsets[arg_location] += \ + type_size < sizeof(int) \ + ? ROUND(type_size, align) \ + : ROUND(type_size, sizeof(void*)); \ + encoding; }) + +#endif /* sparc linux */ + + + +#ifndef FUNCTION_ARG_ENCODING + +#ifndef OBJC_FORWARDING_STACK_OFFSET +#define OBJC_FORWARDING_STACK_OFFSET 0 +#endif + +#ifndef OBJC_FORWARDING_MIN_OFFSET +#define OBJC_FORWARDING_MIN_OFFSET 0 +#endif + +#define CUMULATIVE_ARGS int + +#define INIT_CUMULATIVE_ARGS(CUM) ((CUM) = 0) + +#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \ + ({ id encoding; \ + const char* type = [(TYPE) cString]; \ + int align = objc_alignof_type(type); \ + int type_size = objc_sizeof_type(type); \ +\ + (CUM) = ROUND((CUM), align); \ + encoding = [NSString stringWithFormat:@"%@%d", \ + (TYPE), \ + (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \ + (STACK_ARGSIZE) = (CUM) + type_size; \ + (CUM) += ROUND(type_size, sizeof(void*)); \ + encoding; }) + +#endif /* generic */ + +/* + * End of libFoundation macros. + */ + + +static NSString* +isolate_type(const char* types) +{ + const char* p = objc_skip_typespec(types); + return [NSString stringWithCString:types length:(unsigned)(p - types)]; +} + static int types_get_size_of_arguments(const char *types) { @@ -77,29 +442,55 @@ rtn_type_is_oneway(const char * types) + (NSMethodSignature*) signatureWithObjCTypes: (const char*)t { + NSMethodSignature *newMs = [[NSMethodSignature alloc] autorelease]; + const char *positionOfSizeInfo; + const char *positionOfFirstParam; int len; - NSMethodSignature *newMs = [NSMethodSignature alloc]; -#if 0 - len = strlen(t); -#else - len = strlen(t) + 1; // For the last '\0' -#endif - OBJC_MALLOC(newMs->types, char, len); - memcpy(newMs->types, t, len); -#if 0 - len = strlen(t); /* xxx */ -#else - { - char * endof_ret_encoding = strrchr(t, '0'); - len = endof_ret_encoding - t + 1; // +2? - } -#endif - OBJC_MALLOC(newMs->returnTypes, char, len); - memcpy(newMs->returnTypes, t, len); - newMs->returnTypes[len-1] = '\0'; // ??? - newMs->argFrameLength = types_get_size_of_arguments(t); - newMs->returnFrameLength = objc_sizeof_type(t); - newMs->numArgs = types_get_number_of_arguments(t); + + positionOfSizeInfo = objc_skip_typespec(t); + + if (!isdigit(*positionOfSizeInfo)) + { + CUMULATIVE_ARGS cumulative_args; + int stack_argsize = 0; + id encoding = [[NSMutableString new] autorelease]; + const char* retval = t; + + /* Skip returned value. */ + t = objc_skip_typespec(t); + + newMs->numArgs = 0; + + INIT_CUMULATIVE_ARGS(cumulative_args); + while(*t) { + [encoding appendString: + FUNCTION_ARG_ENCODING(cumulative_args, + isolate_type(t), + stack_argsize)]; + t = objc_skip_typespec(t); + newMs->numArgs++; + } + encoding = [NSString stringWithFormat:@"%@%d%@", + isolate_type(retval), stack_argsize, encoding]; + newMs->types = objc_malloc([encoding cStringLength]+1); + [encoding getCString: newMs->types]; + } + else + { + newMs->types = objc_malloc(strlen(t) + 1); + strcpy(newMs->types, t); + newMs->numArgs = types_get_number_of_arguments(newMs->types); + } + positionOfFirstParam = objc_skip_typespec(newMs->types); + len = positionOfFirstParam - newMs->types; + newMs->returnTypes = objc_malloc(len + 1); + memcpy(newMs->returnTypes, newMs->types, len); + newMs->returnTypes[len] = '\0'; + newMs->argFrameLength = types_get_size_of_arguments(newMs->types); + if (*newMs->types == _C_VOID) + newMs->returnFrameLength = 0; + else + newMs->returnFrameLength = objc_sizeof_type(newMs->types); return newMs; } @@ -170,7 +561,7 @@ rtn_type_is_oneway(const char * types) size = offset - preoffset; } #endif // m68k - return (NSArgumentInfo){offset, size, result_type}; + return (NSArgumentInfo){offset, size, (char*)result_type}; } - (unsigned) frameLength @@ -200,8 +591,8 @@ rtn_type_is_oneway(const char * types) - (void) dealloc { - OBJC_FREE(types); - OBJC_FREE(returnTypes); + objc_free(types); + objc_free(returnTypes); [super dealloc]; } diff --git a/Source/mframe.m b/Source/mframe.m index 7ccadbafb..86b229ea6 100644 --- a/Source/mframe.m +++ b/Source/mframe.m @@ -192,8 +192,9 @@ method_types_get_next_argument (arglist_t argf, e.g. an argument declared (out char*). */ BOOL -mframe_dissect_call (arglist_t argframe, const char *type, - void (*encoder)(int,void*,const char*,int)) +mframe_dissect_call_opts (arglist_t argframe, const char *type, + void (*encoder)(int,void*,const char*,int), + BOOL pass_pointers) { unsigned flags; char *datum; @@ -256,11 +257,6 @@ mframe_dissect_call (arglist_t argframe, const char *type, break; case _C_PTR: - /* 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. */ - type++; /* 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 @@ -268,11 +264,22 @@ mframe_dissect_call (arglist_t argframe, const char *type, it. Set OUT_PARAMETERS accordingly. */ if ((flags & _F_OUT) || !(flags & _F_IN)) out_parameters = YES; - /* If the pointer's value is qualified as an IN parameter, - or not explicity qualified as an OUT parameter, then - encode it. */ - if ((flags & _F_IN) || !(flags & _F_OUT)) - (*encoder) (argnum, *(void**)datum, type, flags); + if (pass_pointers) { + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*encoder) (argnum, datum, type, flags); + } + else { + /* 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. */ + type++; + /* If the pointer's value is qualified as an IN parameter, + or not explicity qualified as an OUT parameter, then + encode it. */ + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*encoder) (argnum, *(void**)datum, type, flags); + } break; case _C_STRUCT_B: @@ -303,6 +310,13 @@ mframe_dissect_call (arglist_t argframe, const char *type, return out_parameters; } +BOOL +mframe_dissect_call (arglist_t argframe, const char *type, + void (*encoder)(int,void*,const char*,int)) +{ + return mframe_dissect_call_opts(argframe, type, encoder, NO); +} + /* mframe_do_call() @@ -370,12 +384,17 @@ mframe_dissect_call (arglist_t argframe, const char *type, pass-by-reference parameters. The ENCODER function should place the value at memory location DATA wherever the user wants to record the ARGNUM'th return value. + + PASS_POINTERS is a flag saying whether pointers should be passed + as pointers (for local stuff) or should be assumed to point to a + single data item (for distributed objects). */ void -mframe_do_call (const char *encoded_types, +mframe_do_call_opts (const char *encoded_types, void(*decoder)(int,void*,const char*), - void(*encoder)(int,void*,const char*,int)) + void(*encoder)(int,void*,const char*,int), + BOOL pass_pointers) { /* The method type string obtained from the target's OBJC_METHOD structure for the selector we're sending. */ @@ -584,11 +603,6 @@ mframe_do_call (const char *encoded_types, break; case _C_PTR: - /* 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 OUT parameter, or if it not explicitly qualified as an IN parameter, then we will have to get the value pointed to again after @@ -596,16 +610,27 @@ mframe_do_call (const char *encoded_types, it. Set OUT_PARAMETERS accordingly. */ if ((flags & _F_OUT) || !(flags & _F_IN)) out_parameters = YES; - /* Allocate some memory to be pointed to, and to hold the - value. Note that it is allocated on the stack, and - methods that want to keep the data pointed to, will have - to make their own copies. */ - *(void**)datum = alloca (objc_sizeof_type (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)) - (*decoder) (argnum, *(void**)datum, tmptype); + if (pass_pointers) { + if ((flags & _F_IN) || !(flags & _F_OUT)) + (*decoder) (argnum, datum, tmptype); + } + else { + /* 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++; + /* Allocate some memory to be pointed to, and to hold the + value. Note that it is allocated on the stack, and + methods that want to keep the data pointed to, will have + to make their own copies. */ + *(void**)datum = alloca (objc_sizeof_type (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)) + (*decoder) (argnum, *(void**)datum, tmptype); + } break; case _C_STRUCT_B: @@ -684,11 +709,16 @@ mframe_do_call (const char *encoded_types, break; case _C_PTR: - /* The argument is a pointer to something; increment TYPE - so we can see what it is a pointer to. */ - tmptype++; - /* Encode the value that was pointed to. */ - (*encoder) (-1, *(void**)retframe, tmptype, flags); + if (pass_pointers) { + (*encoder) (-1, retframe, tmptype, flags); + } + else { + /* The argument is a pointer to something; increment TYPE + so we can see what it is a pointer to. */ + tmptype++; + /* Encode the value that was pointed to. */ + (*encoder) (-1, *(void**)retframe, tmptype, flags); + } break; case _C_STRUCT_B: @@ -816,6 +846,14 @@ mframe_do_call (const char *encoded_types, return; } +void +mframe_do_call (const char *encoded_types, + void(*decoder)(int,void*,const char*), + void(*encoder)(int,void*,const char*,int)) +{ + mframe_do_call_opts(encoded_types, decoder, encoder, NO); +} + /* mframe_build_return() @@ -835,10 +873,11 @@ mframe_do_call (const char *encoded_types, */ retval_t -mframe_build_return (arglist_t argframe, +mframe_build_return_opts (arglist_t argframe, const char *type, BOOL out_parameters, - void(*decoder)(int,void*,const char*,int)) + void(*decoder)(int,void*,const char*,int), + BOOL pass_pointers) { /* A pointer to the memory that will hold the return value. */ retval_t retframe = NULL; @@ -955,17 +994,22 @@ mframe_build_return (arglist_t argframe, switch (*tmptype) { case _C_PTR: - /* We are returning a pointer to something. */ - /* Increment TYPE so we can see what it is a pointer to. */ - tmptype++; - /* Allocate some memory to hold the value we're pointing to. */ - *(void**)retframe = - objc_malloc (objc_sizeof_type (tmptype)); - /* We are responsible for making sure this memory gets free'd - eventually. Ask MallocAddress class to autorelease it. */ - [MallocAddress autoreleaseMallocAddress: *(void**)retframe]; - /* Decode the return value into the memory we allocated. */ - (*decoder) (-1, *(void**)retframe, tmptype, flags); + if (pass_pointers) { + (*decoder) (-1, retframe, tmptype, flags); + } + else { + /* We are returning a pointer to something. */ + /* Increment TYPE so we can see what it is a pointer to. */ + tmptype++; + /* Allocate some memory to hold the value we're pointing to. */ + *(void**)retframe = + objc_malloc (objc_sizeof_type (tmptype)); + /* We are responsible for making sure this memory gets free'd + eventually. Ask MallocAddress class to autorelease it. */ + [MallocAddress autoreleaseMallocAddress: *(void**)retframe]; + /* Decode the return value into the memory we allocated. */ + (*decoder) (-1, *(void**)retframe, tmptype, flags); + } break; case _C_STRUCT_B: @@ -1120,3 +1164,12 @@ mframe_build_return (arglist_t argframe, return retframe; } +retval_t +mframe_build_return (arglist_t argframe, + const char *type, + BOOL out_parameters, + void(*decoder)(int,void*,const char*,int)) +{ + return mframe_build_return_opts(argframe,type,out_parameters,decoder,NO); +} +