mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 08:21:25 +00:00
Initial revision
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@291 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
0602979ca9
commit
c2629d3f31
5 changed files with 663 additions and 0 deletions
57
Headers/gnustep/base/NSGArray.h
Normal file
57
Headers/gnustep/base/NSGArray.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/* Interface to concrete implementation of NSArray.
|
||||||
|
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||||
|
Date: March 1995
|
||||||
|
|
||||||
|
This file is part of the GNU Objective C Class Library.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NSConcreteArray_h_OBJECTS_INCLUDE
|
||||||
|
#define __NSConcreteArray_h_OBJECTS_INCLUDE
|
||||||
|
|
||||||
|
#include <objects/stdobjects.h>
|
||||||
|
#include <foundation/NSArray.h>
|
||||||
|
#include <objects/elt.h>
|
||||||
|
|
||||||
|
@interface NSConcreteArray : NSArray
|
||||||
|
{
|
||||||
|
/* For now, these must match the instance variables in objects/Array.h.
|
||||||
|
This will change. */
|
||||||
|
int (*_comparison_function)(elt,elt);
|
||||||
|
elt *_contents_array;
|
||||||
|
unsigned int _count;
|
||||||
|
unsigned int _capacity;
|
||||||
|
unsigned int _grow_factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface NSConcreteMutableArray : NSArray
|
||||||
|
{
|
||||||
|
/* For now, these must match the instance variables in objects/Array.h.
|
||||||
|
This will change. */
|
||||||
|
int (*_comparison_function)(elt,elt);
|
||||||
|
elt *_contents_array;
|
||||||
|
unsigned int _count;
|
||||||
|
unsigned int _capacity;
|
||||||
|
unsigned int _grow_factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* __NSConcreteArray_h_OBJECTS_INCLUDE */
|
110
Source/NSGArray.m
Normal file
110
Source/NSGArray.m
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/* NSArray - Array object to hold other objects.
|
||||||
|
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||||
|
Date: March 1995
|
||||||
|
|
||||||
|
This file is part of the GNU Objective C Class Library.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <foundation/NSConcreteArray.h>
|
||||||
|
#include <objects/NSArray.h>
|
||||||
|
#include <objects/behavior.h>
|
||||||
|
#include <objects/Array.h>
|
||||||
|
#include <objects/ArrayPrivate.h>
|
||||||
|
|
||||||
|
@implementation NSConcreteArray
|
||||||
|
|
||||||
|
+ (void) initialize
|
||||||
|
{
|
||||||
|
static int done = 0;
|
||||||
|
assert(!done); /* xxx see what the runtime is up to. */
|
||||||
|
if (!done)
|
||||||
|
{
|
||||||
|
done = 1;
|
||||||
|
class_add_behavior([NSConcreteArray class], [Array class]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the designated initializer for NSArray. */
|
||||||
|
- initWithObjects: (id*)objects count: (unsigned)count
|
||||||
|
{
|
||||||
|
/* "super" call into IndexedCollection */
|
||||||
|
#if 1
|
||||||
|
CALL_METHOD_IN_CLASS([IndexedCollection class], initWithType:,
|
||||||
|
@encode(id));
|
||||||
|
#else
|
||||||
|
(*(imp))
|
||||||
|
#endif
|
||||||
|
_comparison_function = elt_get_comparison_function(@encode(id));
|
||||||
|
_grow_factor = [[self class] defaultGrowFactor];
|
||||||
|
_count = count;
|
||||||
|
_capacity = count;
|
||||||
|
OBJC_MALLOC(_contents_array, elt, _capacity);
|
||||||
|
while (count--)
|
||||||
|
_contents_array[count] = objects[count];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (unsigned) count
|
||||||
|
{
|
||||||
|
return _count;
|
||||||
|
}
|
||||||
|
|
||||||
|
- objectAtIndex: (unsigned)index
|
||||||
|
{
|
||||||
|
assert(index < _count); /* xxx should raise NSException instead */
|
||||||
|
return _contents_array[index].id_u;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSConcreteMutableArray
|
||||||
|
|
||||||
|
+ (void) initialize
|
||||||
|
{
|
||||||
|
static int done = 0;
|
||||||
|
if (!done)
|
||||||
|
{
|
||||||
|
done = 1;
|
||||||
|
class_add_behavior([NSConcreteMutableArray class],
|
||||||
|
[NSConcreteArray class]);
|
||||||
|
class_add_behavior([NSConcreteMutableArray class], [Array class]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- initWithCapacity: (unsigned)numItems
|
||||||
|
{
|
||||||
|
/* "super" call into IndexedCollection */
|
||||||
|
CALL_METHOD_IN_CLASS([IndexedCollection class], initWithType:,
|
||||||
|
@encode(id));
|
||||||
|
_comparison_function = elt_get_comparison_function(@encode(id));
|
||||||
|
_grow_factor = [[self class] defaultGrowFactor];
|
||||||
|
_count = 0;
|
||||||
|
_capacity = numItems;
|
||||||
|
OBJC_MALLOC(_contents_array, elt, _capacity);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Comes in from Array behavior
|
||||||
|
- (void) addObject: anObject
|
||||||
|
- (void)replaceObjectAtIndex: (unsigned)index withObject: anObject
|
||||||
|
- (void)insertObject: anObject atIndex: (unsigned)index
|
||||||
|
*/
|
||||||
|
|
||||||
|
@end
|
426
Source/argframe.m
Normal file
426
Source/argframe.m
Normal file
|
@ -0,0 +1,426 @@
|
||||||
|
#include <objc/encoding.h>
|
||||||
|
#include <objc/objc-api.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
/* These functions can be used for dissecting and making method calls
|
||||||
|
for many different situations. They are used for distributed
|
||||||
|
objects, they could also be used to make interfaces between
|
||||||
|
Objective C and Scheme, Perl, Tcl, whatever... I need to
|
||||||
|
generalize this stuff a little more to make it useable for an
|
||||||
|
Invocation class also. */
|
||||||
|
|
||||||
|
/* Returns YES iff there are any outparameters */
|
||||||
|
BOOL
|
||||||
|
dissect_method_call(arglist_t frame, const char *type,
|
||||||
|
void (*f)(int,void*,const char*,int))
|
||||||
|
{
|
||||||
|
const char *tmptype;
|
||||||
|
unsigned flags;
|
||||||
|
char *datum;
|
||||||
|
int argnum;
|
||||||
|
|
||||||
|
tmptype = type;
|
||||||
|
for (datum = my_method_get_next_argument(argframe, &tmptype), argnum=0;
|
||||||
|
datum;
|
||||||
|
datum = my_method_get_next_argument(argframe, &tmptype), argnum++)
|
||||||
|
{
|
||||||
|
flags = objc_get_type_qualifiers(tmptype);
|
||||||
|
tmptype = objc_skip_type_qualifiers(tmptype);
|
||||||
|
if (*tmptype == _C_ID)
|
||||||
|
{
|
||||||
|
(*f)(argnum, datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_CHARPTR)
|
||||||
|
{
|
||||||
|
if ((flags & _F_OUT) || !(flags & _F_IN))
|
||||||
|
out_parameters = YES;
|
||||||
|
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||||
|
(*f)(argnum, datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_PTR)
|
||||||
|
{
|
||||||
|
tmptype++;
|
||||||
|
if ((flags & _F_OUT) || !(flags & _F_IN))
|
||||||
|
out_parameters = YES;
|
||||||
|
/* xxx These two cases currently the same */
|
||||||
|
if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
{
|
||||||
|
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||||
|
(*f)(argnum, *(void**)datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||||
|
(*f)(argnum, *(void**)datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
{
|
||||||
|
#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE
|
||||||
|
(*f)(argnum, *(void**)datum, tmptype, flags);
|
||||||
|
#else
|
||||||
|
(*f)(argnum, datum, tmptype, flags);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*f)(argnum, datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out_parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
make_method_call(const char *forward_type,
|
||||||
|
void(*fd)(int,void*,const char*),
|
||||||
|
void(*fe)(int,void*,const char*,int))
|
||||||
|
{
|
||||||
|
const char *type, *tmptype;
|
||||||
|
const char *ftmptype;
|
||||||
|
id object;
|
||||||
|
SEL selector;
|
||||||
|
IMP imp;
|
||||||
|
void *retframe;
|
||||||
|
arglist_t argframe;
|
||||||
|
int stack_argsize;
|
||||||
|
int reg_argsize;
|
||||||
|
char *datum;
|
||||||
|
id op;
|
||||||
|
unsigned flags;
|
||||||
|
BOOL out_parameters = NO;
|
||||||
|
int argnum;
|
||||||
|
|
||||||
|
/* get object and selector */
|
||||||
|
(*fd)(0, &object, @encode(id));
|
||||||
|
|
||||||
|
/* @encode(SEL) produces "^v" in gcc 2.5.8. It should be ":" */
|
||||||
|
(*fd)(1, &selector, ":");
|
||||||
|
assert(selector);
|
||||||
|
|
||||||
|
type = sel_get_type(selector);
|
||||||
|
assert(type);
|
||||||
|
|
||||||
|
/* Set up argframe */
|
||||||
|
stack_argsize = types_get_size_of_stack_arguments(type);
|
||||||
|
reg_argsize = types_get_size_of_register_arguments(type);
|
||||||
|
argframe = (arglist_t) alloca(sizeof(char*) + reg_argsize);
|
||||||
|
if (stack_argsize)
|
||||||
|
argframe->arg_ptr = alloca(stack_argsize);
|
||||||
|
else
|
||||||
|
argframe->arg_ptr = 0;
|
||||||
|
|
||||||
|
/* decode rest of arguments */
|
||||||
|
tmptype = type;
|
||||||
|
ftmptype = objc_skip_argspec(forward_type);
|
||||||
|
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||||
|
assert(datum);
|
||||||
|
assert(*tmptype == _C_ID);
|
||||||
|
*(id*)datum = object;
|
||||||
|
assert(object);
|
||||||
|
ftmptype = objc_skip_argspec(ftmptype);
|
||||||
|
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||||
|
assert(datum);
|
||||||
|
assert(*tmptype == _C_SEL);
|
||||||
|
*(SEL*)datum = selector;
|
||||||
|
assert(selector);
|
||||||
|
for (datum = my_method_get_next_argument(argframe, &tmptype),
|
||||||
|
ftmptype = objc_skip_argspec(ftmptype), argnum = 2;
|
||||||
|
datum;
|
||||||
|
datum = my_method_get_next_argument(argframe, &tmptype),
|
||||||
|
ftmptype = objc_skip_argspec(ftmptype), argnum++)
|
||||||
|
{
|
||||||
|
flags = objc_get_type_qualifiers(ftmptype);
|
||||||
|
tmptype = objc_skip_type_qualifiers(tmptype);
|
||||||
|
if (*tmptype == _C_CHARPTR)
|
||||||
|
{
|
||||||
|
if ((flags & _F_OUT) || !(flags & _F_IN))
|
||||||
|
out_parameters = YES;
|
||||||
|
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||||
|
(*fd)(argnum, datum, tmptype);
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_PTR)
|
||||||
|
{
|
||||||
|
tmptype++;
|
||||||
|
if ((flags & _F_OUT) || !(flags & _F_IN))
|
||||||
|
out_parameters = YES;
|
||||||
|
/* xxx These two cases currently the same */
|
||||||
|
if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
{
|
||||||
|
/* *(void**)datum = alloca(sizeof(void*)); */
|
||||||
|
/* xxx or should this be alloca?!
|
||||||
|
What about inout params? Where do they get freed? */
|
||||||
|
*(void**)datum =
|
||||||
|
(*objc_malloc)(objc_sizeof_type(tmptype));
|
||||||
|
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||||
|
(*fd)(argnum, *(void**)datum, tmptype);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* xxx or should this be alloca?!
|
||||||
|
What about inout params? Where dothey get freed? */
|
||||||
|
*(char**)datum =
|
||||||
|
(*objc_malloc)(objc_sizeof_type(tmptype));
|
||||||
|
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||||
|
(*fd)(argnum, *(void**)datum, tmptype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
{
|
||||||
|
#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE
|
||||||
|
*(void**)datum = alloca(objc_sizeof_type(tmptype));
|
||||||
|
(*fd)(argnum, *(void**)datum, tmptype);
|
||||||
|
#else
|
||||||
|
(*fd)(argnum, datum, tmptype);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*fd)(argnum, datum, tmptype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the method */
|
||||||
|
imp = objc_msg_lookup(object, selector);
|
||||||
|
assert(imp);
|
||||||
|
retframe = __builtin_apply((apply_t)imp,
|
||||||
|
argframe,
|
||||||
|
stack_argsize);
|
||||||
|
|
||||||
|
/* Return results, if necessary */
|
||||||
|
flags = objc_get_type_qualifiers(forward_type);
|
||||||
|
ftmptype = objc_skip_type_qualifiers(forward_type);
|
||||||
|
tmptype = objc_skip_type_qualifiers(type);
|
||||||
|
/* Is this right? Do we also have to check _F_ONEWAY? */
|
||||||
|
if (out_parameters || *tmptype != _C_VOID)
|
||||||
|
{
|
||||||
|
if (*tmptype != _C_VOID)
|
||||||
|
{
|
||||||
|
/* encode return value */
|
||||||
|
/* xxx Change this to switch(*tmptype) */
|
||||||
|
if (*tmptype == _C_ID)
|
||||||
|
{
|
||||||
|
(*fe)(-1, retframe, @encode(id), flags);
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_PTR)
|
||||||
|
{
|
||||||
|
tmptype++;
|
||||||
|
/* xxx These two cases currently the same */
|
||||||
|
if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
(*fe)(-1, *(void**)retframe, tmptype, flags);
|
||||||
|
else
|
||||||
|
(*fe)(-1, *(void**)retframe, tmptype, flags);
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
{
|
||||||
|
/* xxx these two cases currently the same? */
|
||||||
|
#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE
|
||||||
|
(*fe)(-1, *(void**)retframe, tmptype, flags);
|
||||||
|
#else
|
||||||
|
(*fe)(-1, *(void**)retframe, tmptype, flags);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_FLT || *tmptype == _C_DBL)
|
||||||
|
{
|
||||||
|
(*fe)(-1, ((char*)retframe) + FLT_AND_DBL_RETFRAME_OFFSET
|
||||||
|
tmptype, flags);
|
||||||
|
}
|
||||||
|
else /* Among other types, _C_CHARPTR is handled here */
|
||||||
|
{
|
||||||
|
int retsize = objc_sizeof_type(tmptype);
|
||||||
|
/* Special case BOOL (and other types smaller than int)
|
||||||
|
because retframe doesn't actually point to the char */
|
||||||
|
/* xxx What about structures smaller than int's that
|
||||||
|
are passed by reference on true structure reference-
|
||||||
|
passing architectures? */
|
||||||
|
/* xxx Is this the right test? Use sizeof(int*) instead? */
|
||||||
|
if (retsize < sizeof(void*))
|
||||||
|
{
|
||||||
|
(*fe)(-1, ((char*)retframe)+sizeof(void*)-retsize
|
||||||
|
tmptype, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*fe)(-1, retframe, tmptype, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* encode values returned by reference */
|
||||||
|
if (out_parameters)
|
||||||
|
{
|
||||||
|
for (datum = my_method_get_next_argument(argframe,&tmptype),
|
||||||
|
argnum = 1,
|
||||||
|
ftmptype = objc_skip_argspec(ftmptype);
|
||||||
|
datum;
|
||||||
|
datum = my_method_get_next_argument(argframe,&tmptype),
|
||||||
|
argnum++,
|
||||||
|
ftmptype = objc_skip_argspec(ftmptype))
|
||||||
|
{
|
||||||
|
flags = objc_get_type_qualifiers(ftmptype);
|
||||||
|
tmptype = objc_skip_type_qualifiers(tmptype);
|
||||||
|
sprintf(argname, "arg%d", argnum); /* too expensive? */
|
||||||
|
if ((*tmptype == _C_PTR)
|
||||||
|
&& ((flags & _F_OUT) || !(flags & _F_IN)))
|
||||||
|
{
|
||||||
|
tmptype++;
|
||||||
|
/* xxx These two cases currently the same */
|
||||||
|
if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
{
|
||||||
|
(*fe)(argnum, *(void**)datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*fe)(argnum, *(void**)datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_CHARPTR
|
||||||
|
&& ((flags & _F_OUT) || !(flags & _F_IN)))
|
||||||
|
{
|
||||||
|
(*fe)(argnum, datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void f_decode_rets (int argnum, void *datum, const char *type)
|
||||||
|
{
|
||||||
|
[ip decodeValueOfType:type
|
||||||
|
at:datum
|
||||||
|
withName:NULL];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In the function that calls this one, be careful about calling more
|
||||||
|
functions after this one. The memory for the retval_t is alloca'ed */
|
||||||
|
retval_t dissect_method_return(arglist_t frame, const char *type,
|
||||||
|
BOOL out_parameters,
|
||||||
|
void(*f)(int,void*,const char*,int))
|
||||||
|
{
|
||||||
|
retval_t retframe;
|
||||||
|
int argnum;
|
||||||
|
int flags;
|
||||||
|
const char *tmptype;
|
||||||
|
|
||||||
|
/* get return values, if necessary */
|
||||||
|
flags = objc_get_type_qualifiers(type);
|
||||||
|
tmptype = objc_skip_type_qualifiers(type);
|
||||||
|
/* xxx What happens with method declared "- (oneway) foo: (out int*)ip;" */
|
||||||
|
/* xxx What happens with method declared "- (in char *) bar;" */
|
||||||
|
/* Is this right? Do we also have to check _F_ONEWAY? */
|
||||||
|
if (out_parameters || *tmptype != _C_VOID)
|
||||||
|
{
|
||||||
|
argnum = -1
|
||||||
|
if (*tmptype != _C_VOID)
|
||||||
|
{
|
||||||
|
/* decode return value */
|
||||||
|
retsize = objc_sizeof_type(tmptype);
|
||||||
|
/* xxx We need to test retsize's less than 4. Also note that
|
||||||
|
if we return structures using a structure-value-address, we
|
||||||
|
are potentially alloca'ing much more than we need here. */
|
||||||
|
/* xxx Find out about returning structures by reference
|
||||||
|
on non--structure-value-address machines, and potentially
|
||||||
|
just always alloca(RETFRAME_SIZE == sizeof(void*)*4) */
|
||||||
|
retframe = alloca(MAX(retsize, sizeof(void*)*4));
|
||||||
|
/* xxx change this to a switch (*tmptype) */
|
||||||
|
if (*tmptype == _C_PTR)
|
||||||
|
{
|
||||||
|
tmptype++;
|
||||||
|
/* xxx these two cases are the same */
|
||||||
|
if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
{
|
||||||
|
*(void**)retframe =
|
||||||
|
(*objc_malloc)(objc_sizeof_type(tmptype));
|
||||||
|
(*f)(argnum, *(void**)retframe, tmptype, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(void**)retframe =
|
||||||
|
(*objc_malloc)(objc_sizeof_type(tmptype));
|
||||||
|
(*f)(argnum, *(void**)retframe, tmptype, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
{
|
||||||
|
/* xxx These two cases currently the same */
|
||||||
|
xxx wwoooooo, we have to alloca in the frame above
|
||||||
|
#if CONNECTION_STRUCTURES_PASSED_BY_REFERENCE
|
||||||
|
*(void**)retframe = alloca(objc_sizeof_type(tmptype));
|
||||||
|
(*f)(argnum, *(void**)retframe, tmptype, flags);
|
||||||
|
#else
|
||||||
|
*(void**)retframe = alloca(objc_sizeof_type(tmptype));
|
||||||
|
(*f)(argnum, *(void**)retframe, tmptype, flags);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (*tmptype == _C_FLT || *tmptype == _C_DBL)
|
||||||
|
{
|
||||||
|
(*f)(argnum, ((char*)retframe) + FLT_AND_DBL_RETFRAME_OFFSET,
|
||||||
|
tmptype, flags);
|
||||||
|
}
|
||||||
|
else /* Among other things, _C_CHARPTR is handled here */
|
||||||
|
{
|
||||||
|
/* int typesize; xxx Use retsize instead! */
|
||||||
|
/* xxx was: (typesize = objc_sizeof_type(tmptype)) */
|
||||||
|
/* Special case BOOL (and other types smaller than int)
|
||||||
|
because retframe doesn't actually point to the char */
|
||||||
|
/* xxx What about structures smaller than int's that
|
||||||
|
are passed by reference on true structure reference-
|
||||||
|
passing architectures? */
|
||||||
|
/* xxx Is this the right test? Use sizeof(int*) instead? */
|
||||||
|
if (retsize < sizeof(void*))
|
||||||
|
{
|
||||||
|
*(void**)retframe = 0;
|
||||||
|
(*f)(argnum, ((char*)retframe)+sizeof(void*)-retsize,
|
||||||
|
tmptype, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*f)(argnum, retframe, tmptype, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decode values returned by reference */
|
||||||
|
if (out_parameters)
|
||||||
|
{
|
||||||
|
for (datum = my_method_get_next_argument(argframe, &tmptype), argnum=0;
|
||||||
|
datum;
|
||||||
|
(datum = my_method_get_next_argument(argframe, &tmptype)), argnum++)
|
||||||
|
{
|
||||||
|
flags = objc_get_type_qualifiers(tmptype);
|
||||||
|
tmptype = objc_skip_type_qualifiers(tmptype);
|
||||||
|
if (*tmptype == _C_PTR
|
||||||
|
&& ((flags & _F_OUT) || !(flags & _F_IN)))
|
||||||
|
{
|
||||||
|
tmptype++;
|
||||||
|
/* xxx Note that a (char**) is malloc'ed anew here.
|
||||||
|
Yucky, or worse than yucky. If the returned string
|
||||||
|
is smaller than the original, we should just put it
|
||||||
|
there; if the returned string is bigger, I don't know
|
||||||
|
what to do. */
|
||||||
|
/* xxx These two cases are the same */
|
||||||
|
if (*tmptype == _C_STRUCT_B || *tmptype == _C_ARY_B)
|
||||||
|
{
|
||||||
|
(*f)(argnum, *(void**)datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*f)(argnum, *(void**)datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* __builtin_return can't return structures by value */
|
||||||
|
else if (*tmptype == _C_CHARPTR
|
||||||
|
&& ((flags & _F_OUT) || !(flags & _F_IN)))
|
||||||
|
{
|
||||||
|
(*f)(argnum, datum, tmptype, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* void return value */
|
||||||
|
{
|
||||||
|
retframe = alloca(sizeof(void*));
|
||||||
|
}
|
||||||
|
}
|
40
Source/objects/NSString.h
Normal file
40
Source/objects/NSString.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* GNU extensions to NSString.
|
||||||
|
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||||
|
Date: March 1995
|
||||||
|
|
||||||
|
This file is part of the GNU Objective C Class Library.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* You can include this instead of (or in addition to)
|
||||||
|
foundation/NSString.h if you want to use the GNU extensions. The
|
||||||
|
primary GNU extention is that NSString objects now conform to
|
||||||
|
IndexedCollecting---they are Collection objects just like in
|
||||||
|
Smalltalk. */
|
||||||
|
|
||||||
|
#ifndef __objects_NSString_h_OBJECTS_INCLUDE
|
||||||
|
#define __objects_NSString_h_OBJECTS_INCLUDE
|
||||||
|
|
||||||
|
#include <objects/stdobjects.h>
|
||||||
|
#include <objects/IndexedCollecting.h>
|
||||||
|
#include <objects/String.h>
|
||||||
|
|
||||||
|
@interface NSString (GNU) <String,IndexedCollecting>
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* __objects_NSString_h_OBJECTS_INCLUDE */
|
30
Testing/nsarray.m
Normal file
30
Testing/nsarray.m
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include <foundation/NSArray.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
id a, b;
|
||||||
|
|
||||||
|
set_behavior_debug(1);
|
||||||
|
a = [NSArray arrayWithObjects:
|
||||||
|
[NSObject class],
|
||||||
|
[NSArray class],
|
||||||
|
[NSMutableArray class]];
|
||||||
|
|
||||||
|
printf("NSArray has count %d\n", [a count]);
|
||||||
|
printf("Classname at index 1 is %s\n", [[a objectAtIndex:1] name]);
|
||||||
|
|
||||||
|
assert([a containsObject:[NSObject class]]);
|
||||||
|
assert([a lastObject]);
|
||||||
|
[a makeObjectsPerform:@selector(self)];
|
||||||
|
|
||||||
|
b = [a mutableCopy];
|
||||||
|
assert([b count]);
|
||||||
|
[b addObject:[NSObject class]];
|
||||||
|
[b removeObject:[NSArray class]];
|
||||||
|
[b removeLastObject];
|
||||||
|
|
||||||
|
assert([b firstObjectCommonWithArray:a]);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue