mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +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
baba8f65d9
commit
9a409d63ba
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…
Reference in a new issue