mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-10 16:20:42 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
f371b8068e
13 changed files with 631 additions and 173 deletions
22
ChangeLog
22
ChangeLog
|
@ -18,6 +18,28 @@
|
|||
* type_encoding.m: add test NSINSETS_ENCODING_PREFIX.
|
||||
* GSConcreteValueTamplate.m: add GSEdgeInsetsValue.
|
||||
* GSConcreteValue.m: add TYPE_ORDER 6.
|
||||
2024-11-24 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSSocketPort.m: fix leak of data object when establishing a
|
||||
new connection.
|
||||
|
||||
2024-11-22 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Tools/AGSIndex: (-makeRefs:) process child nodes in loop rather
|
||||
than recursively ... reduces the depth of recursion to the depth of
|
||||
nesting children rather than the number of children, avoiding stack
|
||||
overflow for large projects.
|
||||
* Source/GSHTTPURLHandle.m: Fix leak of connection description strings
|
||||
when reconnecting an existing handle.
|
||||
|
||||
2024-11-21 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* NSRegularExpression: avoid leaks in ICU code by calling more
|
||||
primitive methods.
|
||||
* NSAutoreleasePool: fix leaks with libobjc2 ARC methods when a pool
|
||||
is in a context that we leave due to an exception.
|
||||
* NSObject: add -trackOwnership to log the retain/release/dealloc of
|
||||
in individual instance.
|
||||
|
||||
2024-11-19 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
|
|
|
@ -295,6 +295,14 @@ extern "C" {
|
|||
*/
|
||||
+ (BOOL) shouldCleanUp;
|
||||
|
||||
/** Turns on tracking of retain/release for instances of the receiver.
|
||||
*/
|
||||
+ (void) trackOwnership;
|
||||
|
||||
/** Turns on tracking of retain/release for the receiver.
|
||||
*/
|
||||
- (void) trackOwnership;
|
||||
|
||||
@end
|
||||
|
||||
/* Macro to take an autoreleased object and either make it immutable or
|
||||
|
|
|
@ -121,7 +121,6 @@ static Class NSArrayClass = 0;
|
|||
static Class NSStringClass = 0;
|
||||
static Class NSDataClass = 0;
|
||||
static Class documentClass = 0;
|
||||
static Class headerClass = 0;
|
||||
|
||||
static BOOL oldStyleFolding = NO;
|
||||
static NSString *Cte7bit = @"7bit";
|
||||
|
@ -888,6 +887,29 @@ wordData(NSString *word, BOOL *encoded)
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
NSMutableCharacterSet *m = [[NSMutableCharacterSet alloc] init];
|
||||
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet characterSetWithCharactersInString:
|
||||
@".()<>@,;:[]\"\\"]];
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet controlCharacterSet]];
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet illegalCharacterSet]];
|
||||
rfc822Specials = [m copy];
|
||||
[[NSObject leakAt: &rfc822Specials] release];
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet characterSetWithCharactersInString:
|
||||
@"/?="]];
|
||||
[m removeCharactersInString: @"."];
|
||||
rfc2045Specials = [m copy];
|
||||
[[NSObject leakAt: &rfc2045Specials] release];
|
||||
[m release];
|
||||
whitespace = RETAIN([NSCharacterSet whitespaceAndNewlineCharacterSet]);
|
||||
[[NSObject leakAt: &whitespace] release];
|
||||
|
||||
if (NSArrayClass == 0)
|
||||
{
|
||||
NSArrayClass = [NSArray class];
|
||||
|
@ -904,10 +926,6 @@ wordData(NSString *word, BOOL *encoded)
|
|||
{
|
||||
documentClass = [GSMimeDocument class];
|
||||
}
|
||||
if (headerClass == 0)
|
||||
{
|
||||
headerClass = [GSMimeHeader class];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1745,9 +1763,9 @@ wordData(NSString *word, BOOL *encoded)
|
|||
/*
|
||||
* Set the header name.
|
||||
*/
|
||||
info = [headerClass headerWithName: name
|
||||
value: nil
|
||||
parameters: nil];
|
||||
info = [GSMimeHeader headerWithName: name
|
||||
value: nil
|
||||
parameters: nil];
|
||||
name = [info name];
|
||||
|
||||
/*
|
||||
|
@ -3395,10 +3413,6 @@ static NSCharacterSet *tokenSet = nil;
|
|||
{
|
||||
documentClass = [GSMimeDocument class];
|
||||
}
|
||||
if (headerClass == 0)
|
||||
{
|
||||
headerClass = [GSMimeHeader class];
|
||||
}
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(_defaultsChanged:)
|
||||
name: NSUserDefaultsDidChangeNotification
|
||||
|
@ -3607,7 +3621,7 @@ static NSCharacterSet *tokenSet = nil;
|
|||
NSEnumerator *e;
|
||||
NSString *k;
|
||||
|
||||
c = [headerClass allocWithZone: z];
|
||||
c = [[self class] allocWithZone: z];
|
||||
c = [c initWithName: [self namePreservingCase: YES]
|
||||
value: [self value]
|
||||
parameters: [self parametersPreservingCase: YES]];
|
||||
|
@ -3722,7 +3736,7 @@ static NSCharacterSet *tokenSet = nil;
|
|||
{
|
||||
NSString *v;
|
||||
|
||||
v = [headerClass makeQuoted: [params objectForKey: k] always: NO];
|
||||
v = [[self class] makeQuoted: [params objectForKey: k] always: NO];
|
||||
[m appendString: @"; "];
|
||||
[m appendString: k];
|
||||
[m appendString: @"="];
|
||||
|
@ -3769,7 +3783,7 @@ static NSCharacterSet *tokenSet = nil;
|
|||
value: (NSString*)v
|
||||
parameters: (NSDictionary*)p
|
||||
{
|
||||
n = [headerClass makeToken: n preservingCase: YES];
|
||||
n = [[self class] makeToken: n preservingCase: YES];
|
||||
if ([n length] == 0)
|
||||
{
|
||||
n = @"unknown";
|
||||
|
@ -3807,7 +3821,7 @@ static NSCharacterSet *tokenSet = nil;
|
|||
{
|
||||
return YES;
|
||||
}
|
||||
if (NO == [other isKindOfClass: headerClass])
|
||||
if (NO == [other isKindOfClass: [self class]])
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
@ -3876,7 +3890,7 @@ static NSCharacterSet *tokenSet = nil;
|
|||
|
||||
if (p == nil)
|
||||
{
|
||||
k = [headerClass makeToken: k];
|
||||
k = [[self class] makeToken: k];
|
||||
p = [params objectForKey: k];
|
||||
}
|
||||
return p;
|
||||
|
@ -4540,7 +4554,7 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
NSUInteger kLength;
|
||||
NSUInteger vLength;
|
||||
|
||||
v = [headerClass makeQuoted: [params objectForKey: k] always: NO];
|
||||
v = [[self class] makeQuoted: [params objectForKey: k] always: NO];
|
||||
if (preserve == NO)
|
||||
{
|
||||
k = [k lowercaseString];
|
||||
|
@ -4628,7 +4642,7 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
*/
|
||||
- (void) setParameter: (NSString*)v forKey: (NSString*)k
|
||||
{
|
||||
k = [headerClass makeToken: k preservingCase: YES];
|
||||
k = [[self class] makeToken: k preservingCase: YES];
|
||||
if (v == nil)
|
||||
{
|
||||
[params removeObjectForKey: k];
|
||||
|
@ -4662,7 +4676,7 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
{
|
||||
NSString *v = [d objectForKey: k];
|
||||
|
||||
k = [headerClass makeToken: k preservingCase: YES];
|
||||
k = [[self class] makeToken: k preservingCase: YES];
|
||||
[m setObject: v forKey: k];
|
||||
}
|
||||
}
|
||||
|
@ -5216,32 +5230,11 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
{
|
||||
if (self == [GSMimeDocument class])
|
||||
{
|
||||
NSMutableCharacterSet *m = [[NSMutableCharacterSet alloc] init];
|
||||
|
||||
if (documentClass == 0)
|
||||
{
|
||||
documentClass = [GSMimeDocument class];
|
||||
}
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet characterSetWithCharactersInString:
|
||||
@".()<>@,;:[]\"\\"]];
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet controlCharacterSet]];
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet illegalCharacterSet]];
|
||||
rfc822Specials = [m copy];
|
||||
[[NSObject leakAt: &rfc822Specials] release];
|
||||
[m formUnionWithCharacterSet:
|
||||
[NSCharacterSet characterSetWithCharactersInString:
|
||||
@"/?="]];
|
||||
[m removeCharactersInString: @"."];
|
||||
rfc2045Specials = [m copy];
|
||||
[[NSObject leakAt: &rfc2045Specials] release];
|
||||
[m release];
|
||||
whitespace = RETAIN([NSCharacterSet whitespaceAndNewlineCharacterSet]);
|
||||
[[NSObject leakAt: &whitespace] release];
|
||||
|
||||
if (NSArrayClass == 0)
|
||||
{
|
||||
NSArrayClass = [NSArray class];
|
||||
|
@ -5812,10 +5805,6 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
(void*)@"gb18030");
|
||||
#endif
|
||||
}
|
||||
if (headerClass == 0)
|
||||
{
|
||||
headerClass = [GSMimeHeader class];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5926,7 +5915,7 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
{
|
||||
GSMimeHeader *hdr;
|
||||
|
||||
hdr = [headerClass alloc];
|
||||
hdr = [GSMimeHeader alloc];
|
||||
hdr = [hdr initWithName: name
|
||||
value: value
|
||||
parameters: parameters];
|
||||
|
@ -6685,7 +6674,7 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
oaiIMP imp1;
|
||||
boolIMP imp2;
|
||||
|
||||
name = [headerClass makeToken: name preservingCase: NO];
|
||||
name = [GSMimeHeader makeToken: name preservingCase: NO];
|
||||
imp1 = (oaiIMP)[headers methodForSelector: @selector(objectAtIndex:)];
|
||||
imp2 = (boolIMP)[name methodForSelector: @selector(isEqualToString:)];
|
||||
for (index = 0; index < count; index++)
|
||||
|
@ -6710,7 +6699,7 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
{
|
||||
NSUInteger count;
|
||||
|
||||
name = [headerClass makeToken: name preservingCase: NO];
|
||||
name = [GSMimeHeader makeToken: name preservingCase: NO];
|
||||
count = [headers count];
|
||||
if (count > 0)
|
||||
{
|
||||
|
@ -6841,9 +6830,9 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
{
|
||||
GSMimeHeader *hdr;
|
||||
|
||||
hdr = [[headerClass alloc] initWithName: name
|
||||
value: value
|
||||
parameters: parameters];
|
||||
hdr = [[GSMimeHeader alloc] initWithName: name
|
||||
value: value
|
||||
parameters: parameters];
|
||||
[self setHeader: hdr];
|
||||
RELEASE(hdr);
|
||||
return hdr;
|
||||
|
@ -7504,9 +7493,9 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
GSMimeParser *p = AUTORELEASE([GSMimeParser new]);
|
||||
NSScanner *scanner = [NSScanner scannerWithString: type];
|
||||
|
||||
hdr = [headerClass headerWithName: @"Content-Type"
|
||||
value: nil
|
||||
parameters: nil];
|
||||
hdr = [GSMimeHeader headerWithName: @"Content-Type"
|
||||
value: nil
|
||||
parameters: nil];
|
||||
if ([p scanHeaderBody: scanner into: hdr] == NO)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
|
@ -7519,7 +7508,7 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
NSString *val;
|
||||
|
||||
val = [NSStringClass stringWithFormat: @"%@/%@", type, subtype];
|
||||
hdr = [headerClass alloc];
|
||||
hdr = [GSMimeHeader alloc];
|
||||
hdr = [hdr initWithName: @"Content-Type" value: val parameters: nil];
|
||||
[hdr setObject: type forKey: @"Type"];
|
||||
[hdr setObject: subtype forKey: @"Subtype"];
|
||||
|
@ -7565,9 +7554,9 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
|
||||
p = AUTORELEASE([GSMimeParser new]);
|
||||
scanner = [NSScanner scannerWithString: newType];
|
||||
hdr = [headerClass headerWithName: @"Content-Type"
|
||||
value: nil
|
||||
parameters: nil];
|
||||
hdr = [GSMimeHeader headerWithName: @"Content-Type"
|
||||
value: nil
|
||||
parameters: nil];
|
||||
if ([p scanHeaderBody: scanner into: hdr] == NO)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
|
@ -7600,7 +7589,7 @@ appendString(NSMutableData *m, NSUInteger offset, NSUInteger fold,
|
|||
{
|
||||
GSMimeHeader *hdr;
|
||||
|
||||
hdr = [headerClass alloc];
|
||||
hdr = [GSMimeHeader alloc];
|
||||
hdr = [hdr initWithName: name
|
||||
value: value
|
||||
parameters: parameters];
|
||||
|
|
|
@ -146,6 +146,11 @@
|
|||
@end
|
||||
|
||||
#if defined(GNUSTEP)
|
||||
|
||||
@interface NSAutoreleasePool (NSThread)
|
||||
+ (void) _endThread: (NSThread*)thread;
|
||||
@end
|
||||
|
||||
struct exitLink {
|
||||
struct exitLink *next;
|
||||
id obj; // Object to release or class for atExit
|
||||
|
@ -235,6 +240,11 @@ handleExit()
|
|||
{
|
||||
GSUnregisterCurrentThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
[[NSAutoreleasePool currentPool] dealloc];
|
||||
[NSAutoreleasePool _endThread: GSCurrentThread()];
|
||||
}
|
||||
isExiting = NO;
|
||||
}
|
||||
|
||||
|
@ -419,6 +429,290 @@ handleExit()
|
|||
return shouldCleanUp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct trackLink {
|
||||
struct trackLink *next;
|
||||
id object; // Instance or Class being tracked.
|
||||
IMP dealloc; // Original -dealloc implementation
|
||||
IMP release; // Original -release implementation
|
||||
IMP retain; // Original -retain implementation
|
||||
BOOL global; // If all instance are tracked.
|
||||
};
|
||||
|
||||
static struct trackLink *tracked = 0;
|
||||
static gs_mutex_t trackLock = GS_MUTEX_INIT_STATIC;
|
||||
|
||||
static inline struct trackLink *
|
||||
find(id o)
|
||||
{
|
||||
struct trackLink *l = tracked;
|
||||
|
||||
while (l)
|
||||
{
|
||||
if (l->object == o)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
l = l->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Lookup the object in the tracking list.
|
||||
* If found as a tracked instance or found as an instance of a class for which
|
||||
* all instances are tracked, return YES. Otherwise return NO (should not log).
|
||||
*/
|
||||
static BOOL
|
||||
findMethods(id o, IMP *dea, IMP *rel, IMP *ret)
|
||||
{
|
||||
struct trackLink *l;
|
||||
Class c;
|
||||
|
||||
GS_MUTEX_LOCK(trackLock);
|
||||
l = find(o);
|
||||
if (l)
|
||||
{
|
||||
*dea = l->dealloc;
|
||||
*rel = l->release;
|
||||
*ret = l->retain;
|
||||
GS_MUTEX_UNLOCK(trackLock);
|
||||
return YES;
|
||||
}
|
||||
c = object_getClass(o);
|
||||
l = find((id)c);
|
||||
if (l)
|
||||
{
|
||||
BOOL all;
|
||||
|
||||
*dea = l->dealloc;
|
||||
*rel = l->release;
|
||||
*ret = l->retain;
|
||||
all = l->global;
|
||||
GS_MUTEX_UNLOCK(trackLock);
|
||||
return all;
|
||||
}
|
||||
GS_MUTEX_UNLOCK(trackLock);
|
||||
/* Should never happen because we don't remove class entries, but I suppose
|
||||
* someone could call the replacement methods directly.
|
||||
*/
|
||||
*dea = [c instanceMethodForSelector: @selector(dealloc)];
|
||||
*rel = [c instanceMethodForSelector: @selector(release)];
|
||||
*ret = [c instanceMethodForSelector: @selector(retain)];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) _replacementDealloc
|
||||
{
|
||||
IMP dealloc = 0;
|
||||
IMP retain = 0;
|
||||
IMP release = 0;
|
||||
|
||||
if (findMethods(self, &dealloc, &release, &retain) == NO)
|
||||
{
|
||||
/* Not a tracked instance ... dealloc without logging.
|
||||
*/
|
||||
(*dealloc)(self, _cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct trackLink *l;
|
||||
|
||||
/* If there's a link for tracking this specific instance, remove it.
|
||||
*/
|
||||
GS_MUTEX_LOCK(trackLock);
|
||||
if ((l = tracked) != 0)
|
||||
{
|
||||
if (l->object == self)
|
||||
{
|
||||
tracked = l->next;
|
||||
free(l);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct trackLink *n;
|
||||
|
||||
while ((n = l->next) != 0)
|
||||
{
|
||||
if (n->object == self)
|
||||
{
|
||||
l->next = n->next;
|
||||
free(n);
|
||||
break;
|
||||
}
|
||||
l = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
GS_MUTEX_UNLOCK(trackLock);
|
||||
NSLog(@"Tracking ownership -[%p dealloc] at %@",
|
||||
self, [NSThread callStackSymbols]);
|
||||
(*dealloc)(self, _cmd);
|
||||
}
|
||||
}
|
||||
- (void) _replacementRelease
|
||||
{
|
||||
IMP dealloc = 0;
|
||||
IMP retain = 0;
|
||||
IMP release = 0;
|
||||
|
||||
if (findMethods(self, &dealloc, &release, &retain) == NO)
|
||||
{
|
||||
/* Not a tracked instance ... release without logging.
|
||||
*/
|
||||
(*release)(self, _cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned rc;
|
||||
|
||||
rc = (unsigned)[self retainCount];
|
||||
NSLog(@"Tracking ownership -[%p release] %u->%u at %@",
|
||||
self, rc, rc-1, [NSThread callStackSymbols]);
|
||||
(*release)(self, _cmd);
|
||||
}
|
||||
}
|
||||
- (id) _replacementRetain
|
||||
{
|
||||
IMP dealloc = 0;
|
||||
IMP retain = 0;
|
||||
IMP release = 0;
|
||||
id result;
|
||||
|
||||
if (findMethods(self, &dealloc, &release, &retain) == NO)
|
||||
{
|
||||
/* Not a tracked instance ... retain without logging.
|
||||
*/
|
||||
result = (*retain)(self, _cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned rc;
|
||||
|
||||
rc = (unsigned)[self retainCount];
|
||||
result = (*retain)(self, _cmd);
|
||||
NSLog(@"Tracking ownership -[%p retain] %u->%u at %@",
|
||||
self, rc, (unsigned)[self retainCount], [NSThread callStackSymbols]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct trackLink*
|
||||
makeLinkForClass(Class c)
|
||||
{
|
||||
Method replacementDealloc;
|
||||
Method replacementRelease;
|
||||
Method replacementRetain;
|
||||
struct trackLink *l;
|
||||
|
||||
replacementDealloc = class_getInstanceMethod([NSObject class],
|
||||
@selector(_replacementDealloc));
|
||||
replacementRelease = class_getInstanceMethod([NSObject class],
|
||||
@selector(_replacementRelease));
|
||||
replacementRetain = class_getInstanceMethod([NSObject class],
|
||||
@selector(_replacementRetain));
|
||||
|
||||
l = (struct trackLink*)malloc(sizeof(struct trackLink));
|
||||
l->object = c;
|
||||
l->dealloc = class_getMethodImplementation(c, @selector(dealloc));
|
||||
class_replaceMethod(c, @selector(dealloc),
|
||||
method_getImplementation(replacementDealloc),
|
||||
method_getTypeEncoding(replacementDealloc));
|
||||
l->release = class_getMethodImplementation(c, @selector(release));
|
||||
class_replaceMethod(c, @selector(release),
|
||||
method_getImplementation(replacementRelease),
|
||||
method_getTypeEncoding(replacementRelease));
|
||||
l->retain = class_getMethodImplementation(c, @selector(retain));
|
||||
class_replaceMethod(c, @selector(retain),
|
||||
method_getImplementation(replacementRetain),
|
||||
method_getTypeEncoding(replacementRetain));
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
+ (void) trackOwnership
|
||||
{
|
||||
Class c = self;
|
||||
struct trackLink *l;
|
||||
|
||||
NSAssert(NO == class_isMetaClass(object_getClass(self)),
|
||||
NSInternalInconsistencyException);
|
||||
|
||||
GS_MUTEX_LOCK(trackLock);
|
||||
if ((l = find((id)c)) != 0)
|
||||
{
|
||||
/* Class already tracked. Set it so all instances are logged.
|
||||
*/
|
||||
l->global = YES;
|
||||
GS_MUTEX_UNLOCK(trackLock);
|
||||
return;
|
||||
}
|
||||
|
||||
l = makeLinkForClass(c);
|
||||
l->global = YES;
|
||||
l->next = tracked;
|
||||
tracked = l;
|
||||
GS_MUTEX_UNLOCK(trackLock);
|
||||
NSLog(@"Tracking ownership started for class %p at %@",
|
||||
self, [NSThread callStackSymbols]);
|
||||
}
|
||||
|
||||
- (void) trackOwnership
|
||||
{
|
||||
Class c = object_getClass(self);
|
||||
struct trackLink *l;
|
||||
struct trackLink *lc;
|
||||
struct trackLink *li;
|
||||
|
||||
NSAssert(NO == class_isMetaClass(c), NSInternalInconsistencyException);
|
||||
|
||||
GS_MUTEX_LOCK(trackLock);
|
||||
if ((l = find(self)) != 0)
|
||||
{
|
||||
/* Instance already tracked.
|
||||
*/
|
||||
GS_MUTEX_UNLOCK(trackLock);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((l = find(c)) != 0)
|
||||
{
|
||||
/* The class already has tracking set up.
|
||||
*/
|
||||
if (l->global)
|
||||
{
|
||||
/* All instances are logged, so we have nothing to do.
|
||||
*/
|
||||
GS_MUTEX_UNLOCK(trackLock);
|
||||
return;
|
||||
}
|
||||
lc = l;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set this class up for tracking individual instances.
|
||||
*/
|
||||
lc = makeLinkForClass(c);
|
||||
lc->global = NO;
|
||||
lc->next = tracked;
|
||||
tracked = lc;
|
||||
}
|
||||
|
||||
/* Now set up a record to track this one instance.
|
||||
*/
|
||||
li = (struct trackLink*)malloc(sizeof(struct trackLink));
|
||||
li->object = self;
|
||||
li->global = NO;
|
||||
li->dealloc = lc->dealloc;
|
||||
li->release = lc->release;
|
||||
li->retain = lc->retain;
|
||||
li->next = tracked;
|
||||
tracked = li;
|
||||
GS_MUTEX_UNLOCK(trackLock);
|
||||
NSLog(@"Tracking ownership started for instance %p at %@",
|
||||
self, [NSThread callStackSymbols]);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
static SEL eqSel;
|
||||
static SEL oaiSel;
|
||||
|
||||
static Class GSArrayClass;
|
||||
static Class GSInlineArrayClass;
|
||||
/* This class stores objects inline in data beyond the end of the instance.
|
||||
*/
|
||||
|
@ -107,6 +108,7 @@ static Class GSInlineArrayClass;
|
|||
[self setVersion: 1];
|
||||
eqSel = @selector(isEqual:);
|
||||
oaiSel = @selector(objectAtIndex:);
|
||||
GSArrayClass = self;
|
||||
GSInlineArrayClass = [GSInlineArray class];
|
||||
}
|
||||
}
|
||||
|
@ -1195,8 +1197,17 @@ static Class GSInlineArrayClass;
|
|||
|
||||
- (id) initWithObjects: (const id[])objects count: (NSUInteger)count
|
||||
{
|
||||
self = (id)NSAllocateObject(GSInlineArrayClass, sizeof(id)*count,
|
||||
[self zone]);
|
||||
NSZone *z = [self zone];
|
||||
|
||||
/* The gnustep-make -asan=yes option enables LeakSanitizer but (Nov2024)
|
||||
* that produces false positives for items held in an inline array, so
|
||||
* we use the less efficient class in that case.
|
||||
*/
|
||||
#if defined(GS_WITH_ASAN)
|
||||
self = (id)NSAllocateObject(GSArrayClass, 0, z);
|
||||
#else
|
||||
self = (id)NSAllocateObject(GSInlineArrayClass, sizeof(id)*count, z);
|
||||
#endif
|
||||
return [self initWithObjects: objects count: count];
|
||||
}
|
||||
|
||||
|
|
|
@ -1173,12 +1173,12 @@ debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
|||
return;
|
||||
}
|
||||
|
||||
in = [[NSString alloc] initWithFormat: @"(%@:%@ <-- %@:%@)",
|
||||
ASSIGN(in, ([NSString stringWithFormat: @"(%@:%@ <-- %@:%@)",
|
||||
[sock socketLocalAddress], [sock socketLocalService],
|
||||
[sock socketAddress], [sock socketService]];
|
||||
out = [[NSString alloc] initWithFormat: @"(%@:%@ --> %@:%@)",
|
||||
[sock socketAddress], [sock socketService]]));
|
||||
ASSIGN(out, ([NSString stringWithFormat: @"(%@:%@ --> %@:%@)",
|
||||
[sock socketLocalAddress], [sock socketLocalService],
|
||||
[sock socketAddress], [sock socketService]];
|
||||
[sock socketAddress], [sock socketService]]));
|
||||
|
||||
if (debug)
|
||||
{
|
||||
|
|
|
@ -166,7 +166,7 @@ UTextNSMutableStringReplace(UText *ut,
|
|||
// Setting the chunk length to 0 here forces UTextNSStringAccess to fetch
|
||||
// the data from the string object.
|
||||
ut->chunkLength = 0;
|
||||
UTextNSStringAccess(ut, r.location + [replacement length] + 1, TRUE);
|
||||
UTextNSStringAccess(ut, r.location + [replacement length], TRUE);
|
||||
ut->chunkOffset++;
|
||||
|
||||
[replacement release];
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
|
||||
|
||||
|
||||
#define LOG_LIFETIME 0
|
||||
|
||||
/* When this is `NO', autoreleased objects are never actually recorded
|
||||
in an NSAutoreleasePool, and are not sent a `release' message.
|
||||
Thus memory for objects use grows, and grows, and... */
|
||||
|
@ -73,10 +75,10 @@ static unsigned pool_number_warning_threshold = 10000;
|
|||
already alloc'ed. The cache is kept in the autorelease_thread_var
|
||||
structure, which is an ivar of NSThread. */
|
||||
|
||||
static id pop_pool_from_cache (struct autorelease_thread_vars *tv);
|
||||
static id pop_pool_from_cache(struct autorelease_thread_vars *tv);
|
||||
|
||||
static inline void
|
||||
free_pool_cache (struct autorelease_thread_vars *tv)
|
||||
free_pool_cache(struct autorelease_thread_vars *tv)
|
||||
{
|
||||
while (tv->pool_cache_count)
|
||||
{
|
||||
|
@ -94,7 +96,7 @@ free_pool_cache (struct autorelease_thread_vars *tv)
|
|||
}
|
||||
|
||||
static inline void
|
||||
init_pool_cache (struct autorelease_thread_vars *tv)
|
||||
init_pool_cache(struct autorelease_thread_vars *tv)
|
||||
{
|
||||
tv->pool_cache_size = 32;
|
||||
tv->pool_cache_count = 0;
|
||||
|
@ -103,11 +105,11 @@ init_pool_cache (struct autorelease_thread_vars *tv)
|
|||
}
|
||||
|
||||
static void
|
||||
push_pool_to_cache (struct autorelease_thread_vars *tv, id p)
|
||||
push_pool_to_cache(struct autorelease_thread_vars *tv, id p)
|
||||
{
|
||||
if (!tv->pool_cache)
|
||||
{
|
||||
init_pool_cache (tv);
|
||||
init_pool_cache(tv);
|
||||
}
|
||||
else if (tv->pool_cache_count == tv->pool_cache_size)
|
||||
{
|
||||
|
@ -119,7 +121,7 @@ push_pool_to_cache (struct autorelease_thread_vars *tv, id p)
|
|||
}
|
||||
|
||||
static id
|
||||
pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
||||
pop_pool_from_cache(struct autorelease_thread_vars *tv)
|
||||
{
|
||||
return tv->pool_cache[--(tv->pool_cache_count)];
|
||||
}
|
||||
|
@ -138,10 +140,11 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
+ (id) allocWithZone: (NSZone*)zone
|
||||
{
|
||||
struct autorelease_thread_vars *tv = ARP_THREAD_VARS;
|
||||
NSAutoreleasePool *p;
|
||||
|
||||
if (tv->pool_cache_count)
|
||||
{
|
||||
NSAutoreleasePool *p = pop_pool_from_cache (tv);
|
||||
p = pop_pool_from_cache(tv);
|
||||
|
||||
/* When we cache a 'deallocated' pool, we set its _released_count to
|
||||
* UINT_MAX, so when we rtrieve it fromm the cache we must increment
|
||||
|
@ -154,7 +157,14 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
}
|
||||
return p;
|
||||
}
|
||||
return NSAllocateObject (self, 0, zone);
|
||||
p = (NSAutoreleasePool*)NSAllocateObject (self, 0, zone);
|
||||
|
||||
#if LOG_LIFETIME
|
||||
fprintf(stderr, "*** %p autorelease pool allocated in %p\n",
|
||||
p, GSCurrentThread());
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
+ (id) new
|
||||
|
@ -174,6 +184,37 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
return (*initImp)(arp, @selector(init));
|
||||
}
|
||||
|
||||
- (void) _emptyChild
|
||||
{
|
||||
/* If there are NSAutoreleasePool below us in the list of
|
||||
* NSAutoreleasePools, then deallocate them also.
|
||||
* The (only) way we could get in this situation (in correctly
|
||||
* written programs, that don't release NSAutoreleasePools in
|
||||
* weird ways), is if an exception threw us up the stack.
|
||||
* However, if a program has leaked pools we may be deallocating
|
||||
* a pool with LOTS of children. To avoid stack overflow we
|
||||
* therefore deallocate children starting with the oldest first.
|
||||
*/
|
||||
if (nil != _child)
|
||||
{
|
||||
NSAutoreleasePool *pool = _child;
|
||||
|
||||
/* Find other end of linked list ... oldest child.
|
||||
*/
|
||||
while (nil != pool->_child)
|
||||
{
|
||||
pool = pool->_child;
|
||||
}
|
||||
/* Deallocate the children in the list.
|
||||
*/
|
||||
while (pool != self)
|
||||
{
|
||||
pool = pool->_parent;
|
||||
[pool->_child dealloc];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ARC_RUNTIME
|
||||
|
||||
- (id) init
|
||||
|
@ -188,6 +229,7 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
{
|
||||
NSAutoreleasePool *pool = _parent;
|
||||
|
||||
_child = _parent->_child;
|
||||
while (nil != pool)
|
||||
{
|
||||
level++;
|
||||
|
@ -240,8 +282,13 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
- (void) emptyPool
|
||||
{
|
||||
struct autorelease_thread_vars *tv = ARP_THREAD_VARS;
|
||||
tv->current_pool = self;
|
||||
|
||||
if (nil != _child)
|
||||
{
|
||||
[self _emptyChild];
|
||||
}
|
||||
objc_autoreleasePoolPop(_released);
|
||||
tv->current_pool = self;
|
||||
}
|
||||
/**
|
||||
* Indicate to the runtime that we have an ARC-compatible implementation of
|
||||
|
@ -282,11 +329,13 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
{
|
||||
struct autorelease_thread_vars *tv = ARP_THREAD_VARS;
|
||||
unsigned level = 0;
|
||||
|
||||
_parent = tv->current_pool;
|
||||
if (_parent)
|
||||
{
|
||||
NSAutoreleasePool *pool = _parent;
|
||||
|
||||
_child = _parent->_child;
|
||||
while (nil != pool)
|
||||
{
|
||||
level++;
|
||||
|
@ -449,32 +498,9 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
{
|
||||
volatile struct autorelease_array_list *released;
|
||||
|
||||
/* If there are NSAutoreleasePool below us in the list of
|
||||
* NSAutoreleasePools, then deallocate them also.
|
||||
* The (only) way we could get in this situation (in correctly
|
||||
* written programs, that don't release NSAutoreleasePools in
|
||||
* weird ways), is if an exception threw us up the stack.
|
||||
* However, if a program has leaked pools we may be deallocating
|
||||
* a pool with LOTS of children. To avoid stack overflow we
|
||||
* therefore deallocate children starting with the oldest first.
|
||||
*/
|
||||
if (nil != _child)
|
||||
{
|
||||
NSAutoreleasePool *pool = _child;
|
||||
|
||||
/* Find other end of linked list ... oldest child.
|
||||
*/
|
||||
while (nil != pool->_child)
|
||||
{
|
||||
pool = pool->_child;
|
||||
}
|
||||
/* Deallocate the children in the list.
|
||||
*/
|
||||
while (pool != self)
|
||||
{
|
||||
pool = pool->_parent;
|
||||
[pool->_child dealloc];
|
||||
}
|
||||
[self _emptyChild];
|
||||
}
|
||||
|
||||
/* Take the object out of the released list just before releasing it,
|
||||
|
@ -593,13 +619,14 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
_released_count = UINT_MAX;
|
||||
|
||||
/* Don't deallocate ourself, just save us for later use. */
|
||||
push_pool_to_cache (tv, self);
|
||||
push_pool_to_cache(tv, self);
|
||||
GSNOSUPERDEALLOC;
|
||||
}
|
||||
|
||||
- (void) _reallyDealloc
|
||||
{
|
||||
struct autorelease_array_list *a;
|
||||
|
||||
for (a = _released_head; a;)
|
||||
{
|
||||
void *n = a->next;
|
||||
|
@ -607,6 +634,10 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
a = n;
|
||||
}
|
||||
_released = _released_head = 0;
|
||||
#if LOG_LIFETIME
|
||||
fprintf(stderr, "*** %p autorelease pool really dealloc\n", self);
|
||||
#endif
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
|
|
@ -840,8 +840,11 @@ _find_paths(NSString *rootPath, NSString *subPath, NSString *localization)
|
|||
|
||||
if (localization)
|
||||
{
|
||||
primary = [primary stringByAppendingPathComponent:
|
||||
[localization stringByAppendingPathExtension: @"lproj"]];
|
||||
if ([localization length])
|
||||
{
|
||||
primary = [primary stringByAppendingPathComponent:
|
||||
[localization stringByAppendingPathExtension: @"lproj"]];
|
||||
}
|
||||
contents = bundle_directory_readable(primary);
|
||||
addBundlePath(array, contents, primary, nil, nil);
|
||||
}
|
||||
|
@ -861,8 +864,11 @@ _find_paths(NSString *rootPath, NSString *subPath, NSString *localization)
|
|||
}
|
||||
if (localization)
|
||||
{
|
||||
primary = [originalPrimary stringByAppendingPathComponent:
|
||||
[localization stringByAppendingPathExtension: @"lproj"]];
|
||||
if ([localization length])
|
||||
{
|
||||
primary = [originalPrimary stringByAppendingPathComponent:
|
||||
[localization stringByAppendingPathExtension: @"lproj"]];
|
||||
}
|
||||
contents = bundle_directory_readable(primary);
|
||||
addBundlePath(array, contents, primary, nil, nil);
|
||||
}
|
||||
|
|
|
@ -35,9 +35,19 @@
|
|||
* won't work because libicu internally renames all entry points with some cpp
|
||||
* magic.
|
||||
*/
|
||||
#if !defined(HAVE_UREGEX_OPENUTEXT)
|
||||
#if U_ICU_VERSION_MAJOR_NUM > 4 || (U_ICU_VERSION_MAJOR_NUM == 4 && U_ICU_VERSION_MINOR_NUM >= 4) || defined(HAVE_ICU_H)
|
||||
#define HAVE_UREGEX_OPENUTEXT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Until the uregex_replaceAllUText() and uregex_replaceFirstUText() work
|
||||
* without leaking memory, we can't use them :-(
|
||||
* Preoblem exists on Ubuntu in 2024 with icu-74.2
|
||||
*/
|
||||
#if defined(HAVE_UREGEX_OPENUTEXT)
|
||||
#undef HAVE_UREGEX_OPENUTEXT
|
||||
#endif
|
||||
|
||||
#define NSRegularExpressionWorks
|
||||
|
||||
|
@ -158,7 +168,8 @@ NSRegularExpressionOptionsToURegexpFlags(NSRegularExpressionOptions opts)
|
|||
NSDictionary *userInfo;
|
||||
NSString *description;
|
||||
|
||||
description = [NSString stringWithFormat: @"The value “%@” is invalid.", aPattern];
|
||||
description = [NSString
|
||||
stringWithFormat: @"The value “%@” is invalid.", aPattern];
|
||||
|
||||
userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
aPattern, @"NSInvalidValue",
|
||||
|
@ -245,11 +256,46 @@ NSRegularExpressionOptionsToURegexpFlags(NSRegularExpressionOptions opts)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Raise an NSInvalidArgumentException to match macOS behaviour.
|
||||
if (!aPattern)
|
||||
{
|
||||
NSException *exp;
|
||||
|
||||
exp = [NSException exceptionWithName: NSInvalidArgumentException
|
||||
reason: @"nil argument"
|
||||
userInfo: nil];
|
||||
RELEASE(self);
|
||||
[exp raise];
|
||||
}
|
||||
|
||||
[aPattern getCharacters: buffer range: NSMakeRange(0, length)];
|
||||
regex = uregex_open(buffer, length, flags, &pe, &s);
|
||||
if (U_FAILURE(s))
|
||||
{
|
||||
// FIXME: Do something sensible with the error parameter.
|
||||
/* Match macOS behaviour if the pattern is invalid.
|
||||
* Example:
|
||||
* Domain=NSCocoaErrorDomain
|
||||
* Code=2048 "The value “<PATTERN>” is invalid."
|
||||
* UserInfo={NSInvalidValue=<PATTERN>}
|
||||
*/
|
||||
if (e)
|
||||
{
|
||||
NSDictionary *userInfo;
|
||||
NSString *description;
|
||||
|
||||
description = [NSString
|
||||
stringWithFormat: @"The value “%@” is invalid.", aPattern];
|
||||
|
||||
userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
aPattern, @"NSInvalidValue",
|
||||
description, NSLocalizedDescriptionKey,
|
||||
nil];
|
||||
|
||||
*e = [NSError errorWithDomain: NSCocoaErrorDomain
|
||||
code: NSFormattingError
|
||||
userInfo: userInfo];
|
||||
}
|
||||
|
||||
DESTROY(self);
|
||||
return self;
|
||||
}
|
||||
|
@ -979,31 +1025,51 @@ prepareResult(NSRegularExpression *regex,
|
|||
NSInteger results = [self numberOfMatchesInString: string
|
||||
options: opts
|
||||
range: range];
|
||||
UErrorCode s = 0;
|
||||
uint32_t length = [string length];
|
||||
uint32_t replLength = [template length];
|
||||
unichar replacement[replLength];
|
||||
int32_t outLength;
|
||||
unichar *output;
|
||||
NSString *out;
|
||||
URegularExpression *r;
|
||||
TEMP_BUFFER(buffer, length);
|
||||
if (results > 0)
|
||||
{
|
||||
UErrorCode s = 0;
|
||||
uint32_t length = [string length];
|
||||
uint32_t replLength = [template length];
|
||||
unichar replacement[replLength];
|
||||
int32_t outLength;
|
||||
URegularExpression *r;
|
||||
TEMP_BUFFER(buffer, length);
|
||||
|
||||
r = setupRegex(regex, string, buffer, length, opts, range, 0);
|
||||
[template getCharacters: replacement range: NSMakeRange(0, replLength)];
|
||||
r = setupRegex(regex, string, buffer, length, opts, range, 0);
|
||||
[template getCharacters: replacement range: NSMakeRange(0, replLength)];
|
||||
|
||||
outLength = uregex_replaceAll(r, replacement, replLength, NULL, 0, &s);
|
||||
outLength = uregex_replaceAll(r, replacement, replLength, NULL, 0, &s);
|
||||
if (0 == s || U_BUFFER_OVERFLOW_ERROR == s)
|
||||
{
|
||||
unichar *output;
|
||||
|
||||
s = 0;
|
||||
output = NSZoneMalloc(0, outLength * sizeof(unichar));
|
||||
uregex_replaceAll(r, replacement, replLength, output, outLength, &s);
|
||||
out =
|
||||
[[NSString alloc] initWithCharactersNoCopy: output
|
||||
length: outLength
|
||||
freeWhenDone: YES];
|
||||
[string setString: out];
|
||||
RELEASE(out);
|
||||
s = 0; // May have been set to a buffer overflow error
|
||||
|
||||
output = NSZoneMalloc(0, (outLength + 1) * sizeof(unichar));
|
||||
uregex_replaceAll(r, replacement, replLength,
|
||||
output, outLength + 1, &s);
|
||||
if (0 == s)
|
||||
{
|
||||
NSString *out;
|
||||
|
||||
out = [[NSString alloc] initWithCharactersNoCopy: output
|
||||
length: outLength
|
||||
freeWhenDone: YES];
|
||||
[string setString: out];
|
||||
RELEASE(out);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSZoneFree(0, output);
|
||||
results = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
results = 0;
|
||||
}
|
||||
uregex_close(r);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -1018,20 +1084,36 @@ prepareResult(NSRegularExpression *regex,
|
|||
uint32_t replLength = [template length];
|
||||
unichar replacement[replLength];
|
||||
int32_t outLength;
|
||||
unichar *output;
|
||||
NSString *result = nil;
|
||||
TEMP_BUFFER(buffer, length);
|
||||
|
||||
r = setupRegex(regex, string, buffer, length, opts, range, 0);
|
||||
[template getCharacters: replacement range: NSMakeRange(0, replLength)];
|
||||
|
||||
outLength = uregex_replaceAll(r, replacement, replLength, NULL, 0, &s);
|
||||
if (0 == s || U_BUFFER_OVERFLOW_ERROR == s)
|
||||
{
|
||||
unichar *output;
|
||||
|
||||
s = 0;
|
||||
output = NSZoneMalloc(0, outLength * sizeof(unichar));
|
||||
uregex_replaceAll(r, replacement, replLength, output, outLength, &s);
|
||||
return AUTORELEASE([[NSString alloc] initWithCharactersNoCopy: output
|
||||
length: outLength
|
||||
freeWhenDone: YES]);
|
||||
s = 0; // may have been set to a buffer overflow error
|
||||
|
||||
output = NSZoneMalloc(0, (outLength + 1) * sizeof(unichar));
|
||||
uregex_replaceAll(r, replacement, replLength, output, outLength + 1, &s);
|
||||
if (0 == s)
|
||||
{
|
||||
result = AUTORELEASE([[NSString alloc]
|
||||
initWithCharactersNoCopy: output
|
||||
length: outLength
|
||||
freeWhenDone: YES]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSZoneFree(0, output);
|
||||
}
|
||||
}
|
||||
|
||||
uregex_close(r);
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString*) replacementStringForResult: (NSTextCheckingResult*)result
|
||||
|
@ -1045,7 +1127,7 @@ prepareResult(NSRegularExpression *regex,
|
|||
uint32_t replLength = [template length];
|
||||
unichar replacement[replLength];
|
||||
int32_t outLength;
|
||||
unichar *output;
|
||||
NSString *str = nil;
|
||||
TEMP_BUFFER(buffer, range.length);
|
||||
|
||||
r = setupRegex(regex,
|
||||
|
@ -1058,12 +1140,28 @@ prepareResult(NSRegularExpression *regex,
|
|||
[template getCharacters: replacement range: NSMakeRange(0, replLength)];
|
||||
|
||||
outLength = uregex_replaceFirst(r, replacement, replLength, NULL, 0, &s);
|
||||
s = 0;
|
||||
output = NSZoneMalloc(0, outLength * sizeof(unichar));
|
||||
uregex_replaceFirst(r, replacement, replLength, output, outLength, &s);
|
||||
return AUTORELEASE([[NSString alloc] initWithCharactersNoCopy: output
|
||||
length: outLength
|
||||
freeWhenDone: YES]);
|
||||
if (0 == s || U_BUFFER_OVERFLOW_ERROR == s)
|
||||
{
|
||||
unichar *output;
|
||||
|
||||
s = 0;
|
||||
output = NSZoneMalloc(0, (outLength + 1) * sizeof(unichar));
|
||||
uregex_replaceFirst(r, replacement, replLength,
|
||||
output, outLength + 1, &s);
|
||||
if (0 == s)
|
||||
{
|
||||
str = AUTORELEASE([[NSString alloc]
|
||||
initWithCharactersNoCopy: output
|
||||
length: outLength
|
||||
freeWhenDone: YES]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSZoneFree(0, output);
|
||||
}
|
||||
}
|
||||
uregex_close(r);
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1247,7 +1247,8 @@ static Class runLoopClass;
|
|||
* first thing to do is send out port information (after setting
|
||||
* up a TLS session if necessary).
|
||||
*/
|
||||
ASSIGN(cData, newDataWithEncodedPort(p));
|
||||
RELEASE(cData);
|
||||
cData = newDataWithEncodedPort(p);
|
||||
cLength = 0;
|
||||
|
||||
#if defined(HAVE_GNUTLS)
|
||||
|
|
|
@ -291,7 +291,6 @@ findKey(id refs, NSString *key, NSMutableArray *path, NSMutableArray *found)
|
|||
- (void) makeRefs: (GSXMLNode*)node
|
||||
{
|
||||
GSXMLNode *children = [node firstChild];
|
||||
GSXMLNode *next = [node next];
|
||||
BOOL newUnit = NO;
|
||||
|
||||
if ([node type] == XML_ELEMENT_NODE)
|
||||
|
@ -541,9 +540,10 @@ findKey(id refs, NSString *key, NSMutableArray *path, NSMutableArray *found)
|
|||
}
|
||||
}
|
||||
|
||||
if (children != nil)
|
||||
while (children)
|
||||
{
|
||||
[self makeRefs: children];
|
||||
children = [children next];
|
||||
}
|
||||
if (newUnit == YES)
|
||||
{
|
||||
|
@ -551,10 +551,6 @@ findKey(id refs, NSString *key, NSMutableArray *path, NSMutableArray *found)
|
|||
category = nil;
|
||||
classname = nil;
|
||||
}
|
||||
if (next != nil)
|
||||
{
|
||||
[self makeRefs: next];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -320,6 +320,7 @@ equalTypes(NSArray *t1, NSArray *t2)
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self reset];
|
||||
DESTROY(wordMap);
|
||||
DESTROY(ifStack);
|
||||
DESTROY(declared);
|
||||
|
@ -1485,8 +1486,8 @@ recheck:
|
|||
|
||||
- (NSMutableArray*) parseDeclarations
|
||||
{
|
||||
IF_NO_ARC(NSAutoreleasePool *arp = [NSAutoreleasePool new];)
|
||||
NSMutableArray *declarations = [NSMutableArray array];
|
||||
CREATE_AUTORELEASE_POOL(arp);
|
||||
static NSSet *qualifiers = nil;
|
||||
static NSSet *keep = nil;
|
||||
NSString *baseName = nil;
|
||||
|
@ -1515,7 +1516,7 @@ recheck:
|
|||
@"unsigned",
|
||||
@"volatile",
|
||||
nil];
|
||||
IF_NO_ARC([qualifiers retain];)
|
||||
IF_NO_ARC(qualifiers = [qualifiers retain];)
|
||||
keep = [NSSet setWithObjects:
|
||||
@"const",
|
||||
@"long",
|
||||
|
@ -1524,7 +1525,7 @@ recheck:
|
|||
@"unsigned",
|
||||
@"volatile",
|
||||
nil];
|
||||
IF_NO_ARC([keep retain];)
|
||||
IF_NO_ARC(keep = [keep retain];)
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1572,7 +1573,7 @@ recheck:
|
|||
pos++;
|
||||
[self skipSpaces];
|
||||
}
|
||||
IF_NO_ARC(DESTROY(arp);)
|
||||
IF_NO_ARC([arp release];)
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -1643,7 +1644,7 @@ recheck:
|
|||
if (NO == isEnum)
|
||||
{
|
||||
[self log: @"messed up NS_ENUM/NS_OPTIONS declaration"];
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
@ -1680,7 +1681,7 @@ recheck:
|
|||
|
||||
/* We want to be able to parse new comments while retaining the
|
||||
originally parsed comment for the enum/union/struct. */
|
||||
introComment = [comment copy];
|
||||
introComment = AUTORELEASE([comment copy]);
|
||||
DESTROY(comment);
|
||||
|
||||
pos++; /* Skip '{' */
|
||||
|
@ -2007,8 +2008,8 @@ another:
|
|||
{
|
||||
if (buffer[pos] == ')' || buffer[pos] == ',')
|
||||
{
|
||||
[arp drain];
|
||||
return declarations;
|
||||
IF_NO_ARC(declarations = [declarations retain]; [arp release];)
|
||||
return AUTORELEASE(declarations);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2130,7 +2131,6 @@ another:
|
|||
}
|
||||
DESTROY(comment);
|
||||
|
||||
[arp drain];
|
||||
if (inArgList == NO)
|
||||
{
|
||||
/*
|
||||
|
@ -2148,11 +2148,13 @@ another:
|
|||
{
|
||||
[self log: @"parse declaration with no name - %@", d];
|
||||
}
|
||||
IF_NO_ARC([arp release];)
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
[self setStandards: declarations];
|
||||
return declarations;
|
||||
IF_NO_ARC(declarations = [declarations retain]; [arp release];)
|
||||
return AUTORELEASE(declarations);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2160,7 +2162,7 @@ another:
|
|||
}
|
||||
fail:
|
||||
DESTROY(comment);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -2485,7 +2487,7 @@ fail:
|
|||
*/
|
||||
[self skipUnit];
|
||||
DESTROY(comment);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
return [NSMutableDictionary dictionary];
|
||||
}
|
||||
else
|
||||
|
@ -2524,13 +2526,13 @@ fail:
|
|||
|
||||
DESTROY(unitName);
|
||||
DESTROY(comment);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
return dict;
|
||||
|
||||
fail:
|
||||
DESTROY(unitName);
|
||||
DESTROY(comment);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -2690,13 +2692,13 @@ fail:
|
|||
|
||||
DESTROY(unitName);
|
||||
DESTROY(comment);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
return dict;
|
||||
|
||||
fail:
|
||||
DESTROY(unitName);
|
||||
DESTROY(comment);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -3050,7 +3052,7 @@ fail:
|
|||
|
||||
- (NSMutableDictionary*) parseMethodIsDeclaration: (BOOL)flag
|
||||
{
|
||||
CREATE_AUTORELEASE_POOL(arp);
|
||||
IF_NO_ARC(CREATE_AUTORELEASE_POOL(arp);)
|
||||
NSMutableDictionary *method;
|
||||
NSMutableString *mname;
|
||||
NSString *token;
|
||||
|
@ -3338,14 +3340,14 @@ fail:
|
|||
}
|
||||
|
||||
DESTROY(itemName);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
IF_NO_ARC([method autorelease];)
|
||||
return method;
|
||||
|
||||
fail:
|
||||
DESTROY(itemName);
|
||||
DESTROY(comment);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
RELEASE(method);
|
||||
return nil;
|
||||
}
|
||||
|
@ -4288,7 +4290,7 @@ countAttributes(NSSet *keys, NSDictionary *a)
|
|||
NSDictionary *methods = nil;
|
||||
NSMutableDictionary *dict;
|
||||
NSMutableDictionary *d;
|
||||
CREATE_AUTORELEASE_POOL(arp);
|
||||
IF_NO_ARC(CREATE_AUTORELEASE_POOL(arp);)
|
||||
|
||||
dict = [[NSMutableDictionary alloc] initWithCapacity: 8];
|
||||
|
||||
|
@ -4379,14 +4381,14 @@ countAttributes(NSSet *keys, NSDictionary *a)
|
|||
|
||||
DESTROY(unitName);
|
||||
DESTROY(comment);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
IF_NO_ARC([dict autorelease];)
|
||||
return dict;
|
||||
|
||||
fail:
|
||||
DESTROY(unitName);
|
||||
DESTROY(comment);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
RELEASE(dict);
|
||||
return nil;
|
||||
}
|
||||
|
@ -4816,7 +4818,7 @@ fail:
|
|||
unichar *inptr;
|
||||
unichar *outptr;
|
||||
NSMutableArray *a;
|
||||
CREATE_AUTORELEASE_POOL(arp);
|
||||
IF_NO_ARC(CREATE_AUTORELEASE_POOL(arp);)
|
||||
|
||||
contents = [NSString stringWithContentsOfFile: fileName];
|
||||
length = [contents length];
|
||||
|
@ -4910,7 +4912,7 @@ fail:
|
|||
buffer = [data mutableBytes];
|
||||
pos = 0;
|
||||
ASSIGN(lines, [NSArray arrayWithArray: a]);
|
||||
[arp drain];
|
||||
IF_NO_ARC([arp release];)
|
||||
IF_NO_ARC([data autorelease];)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue