mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-10 16:20:42 +00:00
Garbage collecting updates and moved more gnustep specifiec code to the
Additions library git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@15016 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
8b29e69fab
commit
bfeb8dbf69
11 changed files with 1279 additions and 4 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2002-11-19 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/behavior.m: Moved to Source/Additions/behavior.m
|
||||
* Source/Unicode.m: Moved to Source/Additions/Unicode.m
|
||||
* Source/Additions/GCObject.m: new experimental GC class.
|
||||
* Source/Additions/GCArray.m: ditto
|
||||
* Source/Additions/GCDictionary.m: ditto
|
||||
* Headers/gnustep/base/GCObject.h: Garbage collection classes intended
|
||||
for use by gdl2 and gsweb.
|
||||
|
||||
2002-11-18 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSCompatibility.m: Fix for case where a non property list
|
||||
|
|
109
Headers/gnustep/base/GCObject.h
Normal file
109
Headers/gnustep/base/GCObject.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
/** Interface for simple garbage collected classes
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
Inspired by gc classes of Ovidiu Predescu and Mircea Oancea
|
||||
|
||||
This file is part of the GNUstep Base 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
AutogsdocSource: Additions/GCObject.m
|
||||
AutogsdocSource: Additions/GCArray.m
|
||||
AutogsdocSource: Additions/GCDictionary.m
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __INCLUDED_GCOBJECT_H
|
||||
#define __INCLUDED_GCOBJECT_H
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
|
||||
@class GCObject;
|
||||
|
||||
typedef struct {
|
||||
GCObject *next;
|
||||
GCObject *previous;
|
||||
struct {
|
||||
unsigned visited:1;
|
||||
unsigned refCount:31;
|
||||
} flags;
|
||||
} gcInfo;
|
||||
|
||||
@interface GCObject : NSObject
|
||||
{
|
||||
gcInfo gc;
|
||||
}
|
||||
|
||||
+ (void) gcCollectGarbage;
|
||||
+ (BOOL) gcIsCollecting;
|
||||
+ (void) gcObjectWillBeDeallocated: (GCObject*)anObject;
|
||||
|
||||
- (void) gcDecrementRefCount;
|
||||
- (void) gcDecrementRefCountOfContainedObjects;
|
||||
- (void) gcIncrementRefCount;
|
||||
- (BOOL) gcIncrementRefCountOfContainedObjects;
|
||||
|
||||
@end
|
||||
|
||||
@interface GCObject (Extra)
|
||||
- (GCObject*) gcNextObject;
|
||||
- (GCObject*) gcPreviousObject;
|
||||
- (GCObject*) gcSetNextObject: (GCObject*)anObject;
|
||||
- (GCObject*) gcSetPreviousObject: (GCObject*)anObject;
|
||||
- (BOOL) gcAlreadyVisited;
|
||||
- (void) gcSetVisited: (BOOL)flag;
|
||||
@end
|
||||
|
||||
@interface GCArray : NSArray
|
||||
{
|
||||
gcInfo gc;
|
||||
id *_contents; // C array of content objects
|
||||
BOOL *_isGCObject; // Is content object collectable?
|
||||
unsigned int _count; // Number of content objects.
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@interface GCMutableArray : NSMutableArray
|
||||
{
|
||||
gcInfo gc;
|
||||
id *_contents;
|
||||
BOOL *_isGCObject;
|
||||
unsigned _count;
|
||||
unsigned _maxCount; // Maximum number of content objects.
|
||||
}
|
||||
@end
|
||||
|
||||
@interface GCDictionary : NSDictionary
|
||||
{
|
||||
gcInfo gc;
|
||||
NSMapTable *_map;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface GCMutableDictionary : NSMutableDictionary
|
||||
{
|
||||
gcInfo gc;
|
||||
NSMapTable *_map;
|
||||
}
|
||||
@end
|
||||
|
||||
#endif /* __INCLUDED_GCOBJECT_H */
|
|
@ -1,4 +1,4 @@
|
|||
/* Interface for behaviors for Obj-C, "for Protocols with implementations".
|
||||
/** Interface for behaviors for Obj-C, "for Protocols with implementations".
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
|
@ -19,6 +19,9 @@
|
|||
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., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
AutogsdocSource: Additions/behavior.m
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __behavior_h_GNUSTEP_BASE_INCLUDE
|
||||
|
|
405
Source/Additions/GCArray.m
Normal file
405
Source/Additions/GCArray.m
Normal file
|
@ -0,0 +1,405 @@
|
|||
/* Implementation of garbage collecting array classes.
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
Inspired by gc classes of Ovidiu Predescu and Mircea Oancea
|
||||
|
||||
This file is part of the GNUstep Base 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSRange.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
#include <gnustep/base/behavior.h>
|
||||
#include <gnustep/base/GCObject.h>
|
||||
|
||||
@implementation GCArray
|
||||
|
||||
static Class gcClass = 0;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (gcClass == 0)
|
||||
{
|
||||
gcClass = [GCObject class];
|
||||
behavior_class_add_class(self, gcClass);
|
||||
}
|
||||
}
|
||||
|
||||
- (Class) classForCoder
|
||||
{
|
||||
return [GCArray class];
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
if (NSShouldRetainWithZone(self, zone))
|
||||
{
|
||||
return [self retain];
|
||||
}
|
||||
return [[GCArray allocWithZone: zone] initWithArray: self copyItems: YES];
|
||||
}
|
||||
|
||||
- (unsigned int) count
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
unsigned int c = _count;
|
||||
|
||||
[GCObject gcObjectWillBeDeallocated: (GCObject*)self];
|
||||
if ([GCObject gcIsCollecting])
|
||||
{
|
||||
while (c-- > 0)
|
||||
{
|
||||
if (_isGCObject[c] == NO)
|
||||
{
|
||||
[_contents[c] release];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (c-- > 0)
|
||||
{
|
||||
[_contents[c] release];
|
||||
}
|
||||
}
|
||||
|
||||
NSZoneFree([self zone], _contents);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) gcDecrementRefCountOfContainedObjects
|
||||
{
|
||||
unsigned int c = _count;
|
||||
|
||||
gc.flags.visited = 0;
|
||||
while (c-- > 0)
|
||||
{
|
||||
if (_isGCObject[c])
|
||||
{
|
||||
[_contents[c] gcDecrementRefCount];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) gcIncrementRefCountOfContainedObjects
|
||||
{
|
||||
if (gc.flags.visited == 1)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int c = _count;
|
||||
|
||||
gc.flags.visited = 1;
|
||||
while (c-- > 0)
|
||||
{
|
||||
if (_isGCObject[c])
|
||||
{
|
||||
[_contents[c] gcIncrementRefCount];
|
||||
[_contents[c] gcIncrementRefCountOfContainedObjects];
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (id) initWithObjects: (id*)objects count: (unsigned int)count
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
_contents = NSZoneMalloc([self zone], count * (sizeof(id) + sizeof(BOOL)));
|
||||
_isGCObject = (BOOL*)&_contents[count];
|
||||
_count = count;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
_contents[i] = [objects[i] retain];
|
||||
if (_contents[i] == nil)
|
||||
{
|
||||
[self release];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Nil object to be added in array"];
|
||||
}
|
||||
else
|
||||
{
|
||||
_isGCObject[i] = [objects[i] isKindOfClass: gcClass];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithArray: (NSArray*)anotherArray
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int count = [anotherArray count];
|
||||
|
||||
_contents = NSZoneMalloc([self zone], count * (sizeof(id) + sizeof(BOOL)));
|
||||
_isGCObject = (BOOL*)&_contents[count];
|
||||
_count = count;
|
||||
for (i = 0; i < _count; i++)
|
||||
{
|
||||
_contents[i] = [[anotherArray objectAtIndex: i] retain];
|
||||
_isGCObject[i] = [_contents[i] isKindOfClass: gcClass];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* We use the same initial instance variable layout as a GCObject and
|
||||
* ue the <em>behavior</em> mechanism to inherit methods from that class
|
||||
* to implement a form of multiple inheritance. We need to implement
|
||||
* this method to make this apparent at runtime.
|
||||
*/
|
||||
- (BOOL) isKindOfClass: (Class)c
|
||||
{
|
||||
if (c == gcClass)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
return [super isKindOfClass: c];
|
||||
}
|
||||
|
||||
- (id) mutableCopyWithZone: (NSZone*)zone
|
||||
{
|
||||
return [[GCMutableArray allocWithZone: zone]
|
||||
initWithArray: self copyItems: YES];
|
||||
}
|
||||
|
||||
- (id) objectAtIndex: (unsigned int)index
|
||||
{
|
||||
if (index >= _count)
|
||||
{
|
||||
[NSException raise: NSRangeException
|
||||
format: @"[%@-%@]: index: %u",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd), index];
|
||||
}
|
||||
return _contents[index];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation GCMutableArray
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
static BOOL beenHere = NO;
|
||||
|
||||
if (beenHere == NO)
|
||||
{
|
||||
beenHere = YES;
|
||||
behavior_class_add_class(self, [GCArray class]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) addObject: (id)anObject
|
||||
{
|
||||
[self insertObject: anObject atIndex: _count];
|
||||
}
|
||||
|
||||
- (Class) classForCoder
|
||||
{
|
||||
return [GCMutableArray class];
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
return [[GCArray allocWithZone: zone]
|
||||
initWithArray: self copyItems: YES];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
return [self initWithCapacity: 1];
|
||||
}
|
||||
|
||||
- (id) initWithCapacity: (unsigned int)aNumItems
|
||||
{
|
||||
if (aNumItems < 1)
|
||||
{
|
||||
aNumItems = 1;
|
||||
}
|
||||
_contents = NSZoneMalloc([self zone], aNumItems * (sizeof(id) + sizeof(BOOL)));
|
||||
_isGCObject = (BOOL*)&_contents[aNumItems];
|
||||
_maxCount = aNumItems;
|
||||
_count = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithObjects: (id *)objects count: (unsigned int)count
|
||||
{
|
||||
self = [self initWithCapacity: count];
|
||||
if (self != nil)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
_contents[i] = [objects[i] retain];
|
||||
if (_contents[i] == nil)
|
||||
{
|
||||
[self release];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Nil object to be added in array"];
|
||||
}
|
||||
else
|
||||
{
|
||||
_isGCObject[i] = [objects[i] isKindOfClass: gcClass];
|
||||
}
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithArray: (NSArray*)anotherArray
|
||||
{
|
||||
unsigned int count = [anotherArray count];
|
||||
|
||||
self = [self initWithCapacity: count];
|
||||
if (self != nil)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < _count; i++)
|
||||
{
|
||||
_contents[i] = [[anotherArray objectAtIndex: i] retain];
|
||||
_isGCObject[i] = [_contents[i] isKindOfClass: gcClass];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) insertObject: (id)anObject atIndex: (unsigned int)index
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (anObject == nil)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"[%@-%@]: nil argument",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
|
||||
}
|
||||
if (index > _count)
|
||||
{
|
||||
[NSException raise: NSRangeException
|
||||
format: @"[%@-%@]: bad index %u",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd), index];
|
||||
}
|
||||
|
||||
if (_count == _maxCount)
|
||||
{
|
||||
unsigned old = _maxCount;
|
||||
BOOL *optr;
|
||||
|
||||
if (_maxCount > 0)
|
||||
{
|
||||
_maxCount += (_maxCount >> 1) ? (_maxCount >> 1) : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_maxCount = 1;
|
||||
}
|
||||
_contents = (id*)NSZoneRealloc([self zone], _contents,
|
||||
_maxCount * (sizeof(id) + sizeof(BOOL)));
|
||||
optr = (BOOL*)&_contents[old];
|
||||
_isGCObject = (BOOL*)&_contents[_maxCount];
|
||||
memmove(_isGCObject, optr, sizeof(BOOL)*old);
|
||||
}
|
||||
for(i = _count; i > index; i--)
|
||||
{
|
||||
_contents[i] = _contents[i - 1];
|
||||
_isGCObject[i] = _isGCObject[i - 1];
|
||||
}
|
||||
_contents[index] = [anObject retain];
|
||||
_isGCObject[index] = [anObject isKindOfClass: gcClass];
|
||||
_count++;
|
||||
}
|
||||
|
||||
- (id) mutableCopyWithZone: (NSZone*)zone
|
||||
{
|
||||
return [[GCMutableArray allocWithZone: zone]
|
||||
initWithArray: self copyItems: YES];
|
||||
}
|
||||
|
||||
- (void) removeAllObjects
|
||||
{
|
||||
[self removeObjectsInRange: NSMakeRange(0, _count)];
|
||||
}
|
||||
|
||||
- (void) removeObjectAtIndex: (unsigned int)index
|
||||
{
|
||||
[self removeObjectsInRange: NSMakeRange(index, 1)];
|
||||
}
|
||||
|
||||
- (void) removeObjectsInRange: (NSRange)range
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (NSMaxRange(range) > _count)
|
||||
{
|
||||
[NSException raise: NSRangeException
|
||||
format: @"[%@-%@]: bad range %@",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
||||
NSStringFromRange(range)];
|
||||
}
|
||||
if (range.length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (i = range.location; i < NSMaxRange(range); i++)
|
||||
{
|
||||
[_contents[i] release];
|
||||
}
|
||||
for (i = NSMaxRange(range); i < _count; i++, range.location++)
|
||||
{
|
||||
_contents[range.location] = _contents[i];
|
||||
_isGCObject[range.location] = _isGCObject[i];
|
||||
}
|
||||
_count -= range.length;
|
||||
}
|
||||
|
||||
- (void) replaceObjectAtIndex: (unsigned int)index withObject: (id)anObject
|
||||
{
|
||||
if (anObject == nil)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"[%@-%@]: nil argument",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
|
||||
}
|
||||
if (index >= _count)
|
||||
{
|
||||
[NSException raise: NSRangeException
|
||||
format: @"[%@-%@]: bad index %u",
|
||||
NSStringFromClass([self class]), NSStringFromSelector(_cmd), index];
|
||||
}
|
||||
[anObject retain];
|
||||
[_contents[index] release];
|
||||
_contents[index] = anObject;
|
||||
_isGCObject[index] = [anObject isKindOfClass: gcClass];
|
||||
}
|
||||
|
||||
@end
|
||||
|
403
Source/Additions/GCDictionary.m
Normal file
403
Source/Additions/GCDictionary.m
Normal file
|
@ -0,0 +1,403 @@
|
|||
/* Implementation of garbage collecting dictionary classes
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
Inspired by gc classes of Ovidiu Predescu and Mircea Oancea
|
||||
|
||||
This file is part of the GNUstep Base 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
#include <gnustep/base/behavior.h>
|
||||
#include <gnustep/base/GCObject.h>
|
||||
|
||||
typedef struct {
|
||||
id object;
|
||||
BOOL isGCObject;
|
||||
} GCInfo;
|
||||
|
||||
@interface _GCDictionaryKeyEnumerator : NSObject
|
||||
{
|
||||
@public
|
||||
GCDictionary *dict;
|
||||
NSMapEnumerator enumerator;
|
||||
}
|
||||
- (id) nextObject;
|
||||
@end
|
||||
|
||||
@interface _GCDictionaryObjectEnumerator : _GCDictionaryKeyEnumerator
|
||||
- (id) nextObject;
|
||||
@end
|
||||
|
||||
@implementation _GCDictionaryKeyEnumerator
|
||||
- (id) copyWithZone: (NSZone*)z
|
||||
{
|
||||
return [self retain];
|
||||
}
|
||||
- (void) dealloc
|
||||
{
|
||||
NSEndMapTableEnumeration(&enumerator);
|
||||
[dict release];
|
||||
[super dealloc];
|
||||
}
|
||||
- (id) nextObject
|
||||
{
|
||||
GCInfo *keyStruct;
|
||||
GCInfo *valueStruct;
|
||||
|
||||
return NSNextMapEnumeratorPair(&enumerator,
|
||||
(void**)&keyStruct, (void**)&valueStruct) ? keyStruct->object : nil;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation _GCDictionaryObjectEnumerator
|
||||
- (id) nextObject
|
||||
{
|
||||
GCInfo *keyStruct;
|
||||
GCInfo *valueStruct;
|
||||
|
||||
return NSNextMapEnumeratorPair(&enumerator,
|
||||
(void**)&keyStruct, (void**)&valueStruct) ? valueStruct->object : nil;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation GCDictionary
|
||||
|
||||
static unsigned
|
||||
_GCHashObject(NSMapTable *table, const GCInfo *objectStruct)
|
||||
{
|
||||
return [objectStruct->object hash];
|
||||
}
|
||||
|
||||
static BOOL
|
||||
_GCCompareObjects(NSMapTable *table, const GCInfo *o1, const GCInfo *o2)
|
||||
{
|
||||
return [o1->object isEqual: o2->object];
|
||||
}
|
||||
|
||||
static void
|
||||
_GCRetainObjects(NSMapTable *table, const void *ptr)
|
||||
{
|
||||
GCInfo *objectStruct = (GCInfo*)ptr;
|
||||
|
||||
[objectStruct->object retain];
|
||||
}
|
||||
|
||||
static void
|
||||
_GCReleaseObjects(NSMapTable *table, const void *ptr)
|
||||
{
|
||||
GCInfo *objectStruct = (GCInfo*)ptr;
|
||||
|
||||
if ([GCObject gcIsCollecting])
|
||||
{
|
||||
if (objectStruct->isGCObject == NO)
|
||||
{
|
||||
[objectStruct->object release];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[objectStruct->object release];
|
||||
}
|
||||
NSZoneFree(NSDefaultMallocZone(), objectStruct);
|
||||
}
|
||||
|
||||
static NSString*
|
||||
_GCDescribeObjects(NSMapTable *table, const GCInfo *objectStruct)
|
||||
{
|
||||
return [objectStruct->object description];
|
||||
}
|
||||
|
||||
static const NSMapTableKeyCallBacks GCInfoMapKeyCallBacks = {
|
||||
(unsigned(*)(NSMapTable *, const void *))_GCHashObject,
|
||||
(BOOL(*)(NSMapTable *, const void *, const void *))_GCCompareObjects,
|
||||
(void (*)(NSMapTable *, const void *))_GCRetainObjects,
|
||||
(void (*)(NSMapTable *, const void *))_GCReleaseObjects,
|
||||
(NSString *(*)(NSMapTable *, const void *))_GCDescribeObjects,
|
||||
(const void *)NULL
|
||||
};
|
||||
|
||||
static const NSMapTableValueCallBacks GCInfoValueCallBacks = {
|
||||
(void (*)(NSMapTable *, const void *))_GCRetainObjects,
|
||||
(void (*)(NSMapTable *, const void *))_GCReleaseObjects,
|
||||
(NSString *(*)(NSMapTable *, const void *))_GCDescribeObjects
|
||||
};
|
||||
|
||||
static Class gcClass = 0;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (gcClass == 0)
|
||||
{
|
||||
gcClass = [GCObject class];
|
||||
behavior_class_add_class(self, gcClass);
|
||||
}
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
if (NSShouldRetainWithZone(self, zone))
|
||||
{
|
||||
return [self retain];
|
||||
}
|
||||
return [[GCDictionary allocWithZone: zone] initWithDictionary: self];
|
||||
}
|
||||
|
||||
- (unsigned int) count
|
||||
{
|
||||
return NSCountMapTable(_map);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[GCObject gcObjectWillBeDeallocated: (GCObject*)self];
|
||||
NSFreeMapTable(_map);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) gcDecrementRefCountOfContainedObjects
|
||||
{
|
||||
NSMapEnumerator enumerator = NSEnumerateMapTable(_map);
|
||||
GCInfo *keyStruct;
|
||||
GCInfo *valueStruct;
|
||||
|
||||
gc.flags.visited = 0;
|
||||
while (NSNextMapEnumeratorPair(&enumerator,
|
||||
(void**)&keyStruct, (void**)&valueStruct))
|
||||
{
|
||||
if (keyStruct->isGCObject)
|
||||
{
|
||||
[keyStruct->object gcDecrementRefCount];
|
||||
}
|
||||
if (valueStruct->isGCObject)
|
||||
{
|
||||
[valueStruct->object gcDecrementRefCount];
|
||||
}
|
||||
}
|
||||
NSEndMapTableEnumeration(&enumerator);
|
||||
}
|
||||
|
||||
- (BOOL) gcIncrementRefCountOfContainedObjects
|
||||
{
|
||||
NSMapEnumerator enumerator;
|
||||
GCInfo *keyStruct;
|
||||
GCInfo *valueStruct;
|
||||
|
||||
if (gc.flags.visited == 1)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
gc.flags.visited = 1;
|
||||
|
||||
enumerator = NSEnumerateMapTable(_map);
|
||||
while (NSNextMapEnumeratorPair(&enumerator,
|
||||
(void**)&keyStruct, (void**)&valueStruct))
|
||||
{
|
||||
if (keyStruct->isGCObject)
|
||||
{
|
||||
[keyStruct->object gcIncrementRefCount];
|
||||
[keyStruct->object gcIncrementRefCountOfContainedObjects];
|
||||
}
|
||||
if (valueStruct->isGCObject)
|
||||
{
|
||||
[valueStruct->object gcIncrementRefCount];
|
||||
[valueStruct->object gcIncrementRefCountOfContainedObjects];
|
||||
}
|
||||
}
|
||||
NSEndMapTableEnumeration(&enumerator);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id) initWithDictionary: (NSDictionary*)dictionary
|
||||
{
|
||||
id keys = [dictionary keyEnumerator];
|
||||
id key;
|
||||
unsigned int size = ([dictionary count] * 4) / 3;
|
||||
NSZone *z = NSDefaultMallocZone();
|
||||
|
||||
_map = NSCreateMapTableWithZone(GCInfoMapKeyCallBacks,
|
||||
GCInfoValueCallBacks, size, z);
|
||||
|
||||
while ((key = [keys nextObject]) != nil)
|
||||
{
|
||||
GCInfo *keyStruct;
|
||||
GCInfo *valueStruct;
|
||||
id value;
|
||||
|
||||
keyStruct = NSZoneMalloc(z, sizeof(GCInfo));
|
||||
valueStruct = NSZoneMalloc(z, sizeof(GCInfo));
|
||||
value = [dictionary objectForKey: key];
|
||||
keyStruct->object = key;
|
||||
keyStruct->isGCObject = [key isKindOfClass: gcClass];
|
||||
valueStruct->object = value;
|
||||
valueStruct->isGCObject = [value isKindOfClass: gcClass];
|
||||
NSMapInsert(_map, keyStruct, valueStruct);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithObjects: (id*)objects
|
||||
forKeys: (id*)keys
|
||||
count: (unsigned int)count
|
||||
{
|
||||
unsigned int size = (count * 4) / 3;
|
||||
NSZone *z = NSDefaultMallocZone();
|
||||
|
||||
_map = NSCreateMapTableWithZone(GCInfoMapKeyCallBacks,
|
||||
GCInfoValueCallBacks, size, z);
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
GCInfo *keyStruct;
|
||||
GCInfo *valueStruct;
|
||||
|
||||
if (!keys[count] || !objects[count])
|
||||
{
|
||||
[self release];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Nil object added in dictionary"];
|
||||
}
|
||||
keyStruct = NSZoneMalloc(z, sizeof(GCInfo));
|
||||
valueStruct = NSZoneMalloc(z, sizeof(GCInfo));
|
||||
keyStruct->object = keys[count];
|
||||
keyStruct->isGCObject = [keys[count] isKindOfClass: gcClass];
|
||||
valueStruct->object = objects[count];
|
||||
valueStruct->isGCObject
|
||||
= [objects[count] isKindOfClass: gcClass];
|
||||
NSMapInsert(_map, keyStruct, valueStruct);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* We use the same initial instance variable layout as a GCObject and
|
||||
* ue the <em>behavior</em> mechanism to inherit methods from that class
|
||||
* to implement a form of multiple inheritance. We need to implement
|
||||
* this method to make this apparent at runtime.
|
||||
*/
|
||||
- (BOOL) isKindOfClass: (Class)c
|
||||
{
|
||||
if (c == gcClass)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
return [super isKindOfClass: c];
|
||||
}
|
||||
|
||||
- (NSEnumerator*) keyEnumerator
|
||||
{
|
||||
_GCDictionaryKeyEnumerator *e;
|
||||
|
||||
e = [_GCDictionaryKeyEnumerator alloc];
|
||||
e->dict = [self retain];
|
||||
e->enumerator = NSEnumerateMapTable(_map);
|
||||
return [e autorelease];
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
{
|
||||
_GCDictionaryObjectEnumerator *e;
|
||||
|
||||
e = [_GCDictionaryObjectEnumerator alloc];
|
||||
e->dict = [self retain];
|
||||
e->enumerator = NSEnumerateMapTable(_map);
|
||||
return [e autorelease];
|
||||
}
|
||||
|
||||
- (id) mutableCopyWithZone: (NSZone*)zone
|
||||
{
|
||||
return [[GCMutableDictionary allocWithZone: zone] initWithDictionary: self];
|
||||
}
|
||||
|
||||
- (id) objectForKey: (id)key
|
||||
{
|
||||
GCInfo keyStruct = { key, 0 };
|
||||
GCInfo *valueStruct;
|
||||
|
||||
valueStruct = NSMapGet(_map, (void**)&keyStruct);
|
||||
return valueStruct ? valueStruct->object : nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation GCMutableDictionary
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
static BOOL beenHere = NO;
|
||||
|
||||
if (beenHere == NO)
|
||||
{
|
||||
beenHere = YES;
|
||||
behavior_class_add_class(self, [GCDictionary class]);
|
||||
}
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
return [self initWithCapacity: 0];
|
||||
}
|
||||
|
||||
- (id) initWithCapacity: (unsigned int)aNumItems
|
||||
{
|
||||
unsigned int size = (aNumItems * 4) / 3;
|
||||
|
||||
_map = NSCreateMapTableWithZone(GCInfoMapKeyCallBacks,
|
||||
GCInfoValueCallBacks, size, [self zone]);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
return [[GCDictionary allocWithZone: zone] initWithDictionary: self];
|
||||
}
|
||||
|
||||
- (void) setObject: (id)anObject forKey: (id)aKey
|
||||
{
|
||||
GCInfo *keyStruct;
|
||||
GCInfo *valueStruct;
|
||||
NSZone *z = NSDefaultMallocZone();
|
||||
|
||||
keyStruct = NSZoneMalloc(z, sizeof(GCInfo));
|
||||
valueStruct = NSZoneMalloc(z, sizeof(GCInfo));
|
||||
keyStruct->object = aKey;
|
||||
keyStruct->isGCObject = [aKey isKindOfClass: gcClass];
|
||||
valueStruct->object = anObject;
|
||||
valueStruct->isGCObject = [anObject isKindOfClass: gcClass];
|
||||
NSMapInsert(_map, keyStruct, valueStruct);
|
||||
}
|
||||
|
||||
- (void) removeObjectForKey: (id)key
|
||||
{
|
||||
GCInfo keyStruct = { key, 0 };
|
||||
|
||||
NSMapRemove(_map, (void**)&keyStruct);
|
||||
}
|
||||
|
||||
- (void) removeAllObjects
|
||||
{
|
||||
NSResetMapTable(_map);
|
||||
}
|
||||
|
||||
@end
|
338
Source/Additions/GCObject.m
Normal file
338
Source/Additions/GCObject.m
Normal file
|
@ -0,0 +1,338 @@
|
|||
/* Implementation of garbage collecting classe framework
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
Inspired by gc classes of Ovidiu Predescu and Mircea Oancea
|
||||
|
||||
This file is part of the GNUstep Base 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
AutogsdocSource: Additions/GCObject.m
|
||||
AutogsdocSource: Additions/GCArray.m
|
||||
AutogsdocSource: Additions/GCDictionary.m
|
||||
|
||||
*/
|
||||
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
#include <gnustep/base/GCObject.h>
|
||||
|
||||
/*
|
||||
* The head of a linked list of all garbage collecting objects is a
|
||||
* special object which is never deallocated.
|
||||
*/
|
||||
@interface _GCObjectList : GCObject
|
||||
@end
|
||||
@implementation _GCObjectList
|
||||
- (void) dealloc
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* The GCObject class is both the base class for all garbage collected
|
||||
* objects, and an infrastructure for handling garbage collection.<br />
|
||||
* It maintains a list of all garbage collectable objects and provides
|
||||
* a method to run a garbage collection pass on those objects.
|
||||
*/
|
||||
@implementation GCObject
|
||||
|
||||
static GCObject *allObjects = nil;
|
||||
static BOOL isCollecting = NO;
|
||||
|
||||
+ (id) allocWithZone: (NSZone*)zone
|
||||
{
|
||||
GCObject *o = [super allocWithZone: zone];
|
||||
|
||||
o->gc.next = allObjects;
|
||||
o->gc.previous = allObjects->gc.previous;
|
||||
allObjects->gc.previous->gc.next = o;
|
||||
allObjects->gc.previous = o;
|
||||
o->gc.flags.refCount = 1;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This method runs a garbage collection, causing unreferenced objects to
|
||||
* be deallocated. This is done using a simple three pass algorithm -
|
||||
* </p>
|
||||
* <deflist>
|
||||
* <term>Pass 1</term>
|
||||
* <desc>
|
||||
* All the garbage collectable objects are sent a
|
||||
* -gcDecrementRefCountOfContainedObjects message.
|
||||
* </desc>
|
||||
* <term>Pass 2</term>
|
||||
* <desc>
|
||||
* All objects having a refCount greater than 0 are sent an
|
||||
* -gcIncrementRefCountOfContainedObjects message.
|
||||
* </desc>
|
||||
* <term>Pass 3</term>
|
||||
* <desc>
|
||||
* All the objects that still have the refCount of 0
|
||||
* are part of cyclic graphs and none of the objects from this graph
|
||||
* are held by some object outside graph. These objects receive the
|
||||
* -dealloc message. In this method they should send the -dealloc message
|
||||
* to any garbage collectable (GCObject and subclass) instances they
|
||||
* contain.
|
||||
* </desc>
|
||||
* </deflist>
|
||||
* <p>During garbage collection, the +gcIsCollecting method returns YES.
|
||||
* </p>
|
||||
*/
|
||||
+ (void) gcCollectGarbage
|
||||
{
|
||||
GCObject *object;
|
||||
GCObject *last;
|
||||
|
||||
if (isCollecting == YES)
|
||||
{
|
||||
return; // Don't allow recursion.
|
||||
}
|
||||
isCollecting = YES;
|
||||
|
||||
// Pass 1
|
||||
object = allObjects->gc.next;
|
||||
while (object != allObjects)
|
||||
{
|
||||
[object gcDecrementRefCountOfContainedObjects];
|
||||
// object->gc.flags.visited = 0;
|
||||
// object = object->gc.next;
|
||||
[object gcSetVisited: NO];
|
||||
object = [object gcNextObject];
|
||||
}
|
||||
|
||||
// Pass 2
|
||||
object = allObjects->gc.next;
|
||||
while (object != allObjects)
|
||||
{
|
||||
if ([object retainCount] > 0)
|
||||
{
|
||||
[object gcIncrementRefCountOfContainedObjects];
|
||||
}
|
||||
// object = object->gc.next;
|
||||
object = [object gcNextObject];
|
||||
}
|
||||
|
||||
last = allObjects;
|
||||
object = last->gc.next;
|
||||
while (object != allObjects)
|
||||
{
|
||||
if ([object retainCount] == 0)
|
||||
{
|
||||
GCObject *next;
|
||||
|
||||
// next = object->gc.next;
|
||||
// next->gc.previous = last;
|
||||
// last->gc.next = next;
|
||||
// object->gc.next = object;
|
||||
// object->gc.previous = object;
|
||||
next = [object gcNextObject];
|
||||
[next gcSetPreviousObject: last];
|
||||
[last gcSetNextObject: next];
|
||||
[object gcSetNextObject: object];
|
||||
[object gcSetPreviousObject: object];
|
||||
[object dealloc];
|
||||
object = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
last = object;
|
||||
// object = object->gc.next;
|
||||
object = [object gcNextObject];
|
||||
}
|
||||
}
|
||||
isCollecting = NO;
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [GCObject class])
|
||||
{
|
||||
allObjects = (_GCObjectList*)
|
||||
NSAllocateObject([_GCObjectList class], 0, NSDefaultMallocZone());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flag to indicate whether a garbage collection is in progress.
|
||||
*/
|
||||
+ (BOOL) gcIsCollecting
|
||||
{
|
||||
return isCollecting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to remove anObject from the list of garbage collectable objects.
|
||||
* Subclasses should call this is their -dealloc methods.
|
||||
*/
|
||||
+ (void) gcObjectWillBeDeallocated: (GCObject*)anObject
|
||||
{
|
||||
GCObject *p;
|
||||
GCObject *n;
|
||||
|
||||
// p = anObject->gc.previous;
|
||||
// n = anObject->gc.next;
|
||||
// p->gc.next = n;
|
||||
// n->gc.previous = p;
|
||||
p = [anObject gcPreviousObject];
|
||||
n = [anObject gcNextObject];
|
||||
[p gcSetNextObject: n];
|
||||
[n gcSetPreviousObject: p];
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
GCObject *o = (GCObject*)NSCopyObject(self, 0, zone);
|
||||
|
||||
o->gc.next = allObjects;
|
||||
o->gc.previous = allObjects->gc.previous;
|
||||
allObjects->gc.previous->gc.next = o;
|
||||
allObjects->gc.previous = o;
|
||||
o->gc.flags.refCount = 1;
|
||||
return o;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrements the garbage collection reference count for the receiver.<br />
|
||||
*/
|
||||
- (void) gcDecrementRefCount
|
||||
{
|
||||
gc.flags.refCount--;
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Marks the receiver as not having been visited in the current garbage
|
||||
* collection process (first pass of collection).
|
||||
* </p>
|
||||
* <p>All container subclasses should override this method to call the super
|
||||
* implementation then decrement the ref counts of their contents as well as
|
||||
* sending the -gcDecrementRefCountOfContainedObjects
|
||||
* message to each of them.
|
||||
* </p>
|
||||
*/
|
||||
- (void) gcDecrementRefCountOfContainedObjects
|
||||
{
|
||||
gc.flags.visited = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increments the garbage collection reference count for the receiver.<br />
|
||||
*/
|
||||
- (void) gcIncrementRefCount
|
||||
{
|
||||
gc.flags.refCount++;
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Checks to see if the receiver has already been visited in the
|
||||
* current garbage collection process, and either marks the receiver as
|
||||
* visited (and returns YES) or returns NO to indicate that it had already
|
||||
* been visited.
|
||||
* </p>
|
||||
* <p>All container subclasses should override this method to call the super
|
||||
* implementation then, if the method returns YES, increment the reference
|
||||
* count of any contained objects and send the
|
||||
* -gcIncrementRefCountOfContainedObjects
|
||||
* to each of the contained objects too.
|
||||
* </p>
|
||||
*/
|
||||
- (BOOL) gcIncrementRefCountOfContainedObjects
|
||||
{
|
||||
if (gc.flags.visited == 1)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
gc.flags.visited = 1;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (oneway void) release
|
||||
{
|
||||
if (gc.flags.refCount > 0 && gc.flags.refCount-- == 1)
|
||||
{
|
||||
[GCObject gcObjectWillBeDeallocated: self];
|
||||
[self dealloc];
|
||||
}
|
||||
}
|
||||
|
||||
- (id) retain
|
||||
{
|
||||
gc.flags.refCount++;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (unsigned int) retainCount
|
||||
{
|
||||
return gc.flags.refCount;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GCObject (Extra)
|
||||
|
||||
- (BOOL) gcAlreadyVisited
|
||||
{
|
||||
if (gc.flags.visited == 1)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (GCObject*) gcNextObject
|
||||
{
|
||||
return gc.next;
|
||||
}
|
||||
|
||||
- (GCObject*) gcPreviousObject
|
||||
{
|
||||
return gc.previous;
|
||||
}
|
||||
|
||||
- (GCObject*) gcSetNextObject: (GCObject*)anObject
|
||||
{
|
||||
gc.next = anObject;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (GCObject*) gcSetPreviousObject: (GCObject*)anObject
|
||||
{
|
||||
gc.previous = anObject;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) gcSetVisited: (BOOL)flag
|
||||
{
|
||||
if (flag == YES)
|
||||
{
|
||||
gc.flags.visited = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gc.flags.visited = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -31,8 +31,13 @@ include $(GNUSTEP_MAKEFILES)/common.make
|
|||
SUBPROJECT_NAME=Additions
|
||||
|
||||
Additions_OBJC_FILES =\
|
||||
GCObject.m \
|
||||
GCArray.m \
|
||||
GCDictionary.m \
|
||||
GSMime.m \
|
||||
GSXML.m
|
||||
GSXML.m \
|
||||
Unicode.m \
|
||||
behavior.m
|
||||
|
||||
|
||||
-include Makefile.preamble
|
||||
|
|
|
@ -36,6 +36,9 @@ Base_AGSDOC_FILES = \
|
|||
../Documentation/Base.gsdoc \
|
||||
GSMime.h \
|
||||
GSXML.h \
|
||||
behavior.h \
|
||||
Unicode.h \
|
||||
GCObject.h \
|
||||
NSArchiver.h \
|
||||
NSArray.h \
|
||||
NSAttributedString.h \
|
||||
|
|
|
@ -88,8 +88,6 @@ endif
|
|||
GNU_MFILES = \
|
||||
GSCompatibility.m \
|
||||
GSLocale.m \
|
||||
Unicode.m \
|
||||
behavior.m \
|
||||
preface.m \
|
||||
mframe.m
|
||||
|
||||
|
@ -118,6 +116,7 @@ libgnustep-base.def
|
|||
|
||||
GNU_HEADERS = \
|
||||
DistributedObjects.h \
|
||||
GCObject.h \
|
||||
GSFileHandle.h \
|
||||
GSLocale.h \
|
||||
GSUnion.h \
|
||||
|
|
Loading…
Reference in a new issue