mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Improve stack trace code.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25681 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
2c6116a125
commit
26a8bdec67
5 changed files with 107 additions and 72 deletions
|
@ -1,3 +1,11 @@
|
|||
2007-12-05 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSException.m: Add new MacOS-X method and improve stack trace
|
||||
code.
|
||||
* Source/NSXMLParser.m Add include for NSDictionary.
|
||||
* Documentation/Base.gsdoc: Improve documentation of stack trace.
|
||||
* Headers/Foundation/NSException.h: Add new MacOS-X method.
|
||||
|
||||
2007-12-05 David Ayers <ayers@fsfe.org>
|
||||
|
||||
* Source/NSDecimalNumber.m: (isinf,isnan,isinff,isnanf): Remove.
|
||||
|
|
|
@ -272,11 +272,9 @@ notice and this notice are preserved.
|
|||
<term>GNUSTEP_STACK_TRACE</term>
|
||||
<desc>
|
||||
<p>
|
||||
When this is set to <em>YES</em> a stack trace is placed in
|
||||
the user information dictionary of the NSException object
|
||||
created when an exception is raised. The trace is keyed
|
||||
on <code>GSStackTraceKey</code> and provides additional
|
||||
information to let you know where the exception occurred.
|
||||
When this is set to <em>YES</em> a stack trace is
|
||||
added to the output of the description method of
|
||||
a raised exception object.
|
||||
</p>
|
||||
</desc>
|
||||
<term>GNUSTEP_STRING_ENCODING</term>
|
||||
|
|
|
@ -83,9 +83,10 @@ extern "C" {
|
|||
*/
|
||||
@interface NSException : NSObject <NSCoding, NSCopying>
|
||||
{
|
||||
@private
|
||||
NSString *_e_name;
|
||||
NSString *_e_reason;
|
||||
NSDictionary *_e_info;
|
||||
void *_reserved;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,6 +117,14 @@ extern "C" {
|
|||
format: (NSString*)format
|
||||
arguments: (va_list)argList;
|
||||
|
||||
#if OS_API_VERSION(100500,GS_API_LATEST) && GS_API_VERSION(011501,GS_API_LATEST)
|
||||
/** Returns an array of the call stack return addresses at the point when
|
||||
* the exception was raised. Re-raising the exception does not change
|
||||
* this value.
|
||||
*/
|
||||
- (NSArray*) callStackReturnAddresses;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* <init/>Initializes a newly allocated NSException object with a
|
||||
* name, reason and a dictionary userInfo.
|
||||
|
|
|
@ -41,6 +41,10 @@
|
|||
#import "Foundation/NSValue.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define _e_info (((id*)_reserved)[0])
|
||||
#define _e_stack (((id*)_reserved)[1])
|
||||
|
||||
typedef struct { @defs(NSThread) } *TInfo;
|
||||
|
||||
/* This is the GNU name for the CTOR list */
|
||||
|
@ -760,15 +764,37 @@ _NSFoundationUncaughtExceptionHandler (NSException *exception)
|
|||
{
|
||||
ASSIGN(_e_name, name);
|
||||
ASSIGN(_e_reason, reason);
|
||||
ASSIGN(_e_info, userInfo);
|
||||
if (userInfo != nil)
|
||||
{
|
||||
if (_reserved == 0)
|
||||
{
|
||||
_reserved = NSZoneCalloc([self zone], 2, sizeof(id));
|
||||
}
|
||||
ASSIGN(_e_info, userInfo);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray*) callStackReturnAddresses
|
||||
{
|
||||
if (_reserved == 0)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return _e_stack;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(_e_name);
|
||||
DESTROY(_e_reason);
|
||||
DESTROY(_e_info);
|
||||
if (_reserved != 0)
|
||||
{
|
||||
DESTROY(_e_info);
|
||||
DESTROY(_e_stack);
|
||||
NSZoneFree([self zone], _reserved);
|
||||
_reserved = 0;
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -779,27 +805,14 @@ _NSFoundationUncaughtExceptionHandler (NSException *exception)
|
|||
NSHandler *handler;
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
if (GSPrivateEnvironmentFlag("GNUSTEP_STACK_TRACE", NO) == YES
|
||||
&& [_e_info objectForKey: @"GSStackTraceKey"] == nil)
|
||||
if (_reserved == 0)
|
||||
{
|
||||
NSMutableDictionary *m;
|
||||
|
||||
if (_e_info == nil)
|
||||
{
|
||||
_e_info = m = [NSMutableDictionary new];
|
||||
}
|
||||
else if ([_e_info isKindOfClass: [NSMutableDictionary class]] == YES)
|
||||
{
|
||||
m = (NSMutableDictionary*)_e_info;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = [_e_info mutableCopy];
|
||||
RELEASE(_e_info);
|
||||
_e_info = m;
|
||||
}
|
||||
[m setObject: GSPrivateStackAddresses() forKey: @"GSStackTraceKey"];
|
||||
_reserved = NSZoneCalloc([self zone], 2, sizeof(id));
|
||||
}
|
||||
#if defined(DEBUG)
|
||||
if (_e_stack == nil)
|
||||
{
|
||||
ASSIGN(_e_stack, GSPrivateStackAddresses());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -874,6 +887,10 @@ _NSFoundationUncaughtExceptionHandler (NSException *exception)
|
|||
|
||||
- (NSDictionary*) userInfo
|
||||
{
|
||||
if (_reserved == 0)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return _e_info;
|
||||
}
|
||||
|
||||
|
@ -889,73 +906,75 @@ _NSFoundationUncaughtExceptionHandler (NSException *exception)
|
|||
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
id info = (_reserved == 0) ? nil : _e_info;
|
||||
|
||||
[aCoder encodeValueOfObjCType: @encode(id) at: &_e_name];
|
||||
[aCoder encodeValueOfObjCType: @encode(id) at: &_e_reason];
|
||||
[aCoder encodeValueOfObjCType: @encode(id) at: &_e_info];
|
||||
[aCoder encodeValueOfObjCType: @encode(id) at: &info];
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)aDecoder
|
||||
{
|
||||
id info;
|
||||
|
||||
[aDecoder decodeValueOfObjCType: @encode(id) at: &_e_name];
|
||||
[aDecoder decodeValueOfObjCType: @encode(id) at: &_e_reason];
|
||||
[aDecoder decodeValueOfObjCType: @encode(id) at: &_e_info];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) deepen
|
||||
{
|
||||
_e_name = [_e_name copyWithZone: [self zone]];
|
||||
_e_reason = [_e_reason copyWithZone: [self zone]];
|
||||
_e_info = [_e_info copyWithZone: [self zone]];
|
||||
[aDecoder decodeValueOfObjCType: @encode(id) at: &info];
|
||||
if (info != nil)
|
||||
{
|
||||
if (_reserved == 0)
|
||||
{
|
||||
_reserved = NSZoneCalloc([self zone], 2, sizeof(id));
|
||||
}
|
||||
_e_info = info;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
if (NSShouldRetainWithZone(self, zone))
|
||||
return RETAIN(self);
|
||||
{
|
||||
return RETAIN(self);
|
||||
}
|
||||
else
|
||||
return [(NSException*)NSCopyObject(self, 0, zone) deepen];
|
||||
{
|
||||
return [[[self class] alloc] initWithName: [self name]
|
||||
reason: [self reason]
|
||||
userInfo: [self userInfo]];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString*) description
|
||||
{
|
||||
if (_e_info)
|
||||
if (_reserved != 0)
|
||||
{
|
||||
/* Convert stack information from an array of addresses to a stacktrace
|
||||
* for display.
|
||||
*/
|
||||
#if defined(STACKSYMBOLS)
|
||||
id o;
|
||||
|
||||
o = [_e_info objectForKey: @"GSStackTraceKey"];
|
||||
if ([o isKindOfClass: [NSArray class]] == YES)
|
||||
if (_e_stack != nil)
|
||||
{
|
||||
NSMutableDictionary *m;
|
||||
id o = _e_stack;
|
||||
|
||||
o = [[GSStackTrace alloc] initWithAddresses: o];
|
||||
if ([_e_info isKindOfClass: [NSMutableDictionary class]] == YES)
|
||||
{
|
||||
m = (NSMutableDictionary*)_e_info;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = [_e_info mutableCopy];
|
||||
RELEASE(_e_info);
|
||||
_e_info = m;
|
||||
}
|
||||
[m setObject: o forKey: @"GSStackTraceKey"];
|
||||
RELEASE(o);
|
||||
}
|
||||
#if defined(STACKSYMBOLS)
|
||||
/* Convert stack information from an array of addresses
|
||||
* to a stacktrace for display.
|
||||
*/
|
||||
o = AUTORELEASE([[GSStackTrace alloc] initWithAddresses: o]);
|
||||
#endif
|
||||
return [NSString stringWithFormat: @"%@ NAME:%@ REASON:%@ INFO:%@",
|
||||
[super description], _e_name, _e_reason, _e_info];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@ NAME:%@ REASON:%@",
|
||||
[super description], _e_name, _e_reason];
|
||||
if (_e_info != nil)
|
||||
{
|
||||
return [NSString stringWithFormat:
|
||||
@"%@ NAME:%@ REASON:%@ INFO:%@ STACK:%@",
|
||||
[super description], _e_name, _e_reason, _e_info, o];
|
||||
}
|
||||
return [NSString stringWithFormat:
|
||||
@"%@ NAME:%@ REASON:%@ STACK:%@",
|
||||
[super description], _e_name, _e_reason, o];
|
||||
}
|
||||
return [NSString stringWithFormat:
|
||||
@"%@ NAME:%@ REASON:%@ INFO:%@",
|
||||
[super description], _e_name, _e_reason, _e_info];
|
||||
}
|
||||
return [NSString stringWithFormat: @"%@ NAME:%@ REASON:%@",
|
||||
[super description], _e_name, _e_reason];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSXMLParser.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <Foundation/NSObjCRuntime.h>
|
||||
|
||||
NSString* const NSXMLParserErrorDomain = @"NSXMLParserErrorDomain";
|
||||
|
@ -908,7 +909,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
|
|||
#if EXTRA_DEBUG
|
||||
NSLog(@"tag=%@ - %02x %c", tag, c, isprint(c)?c: ' ');
|
||||
#endif
|
||||
parameters=[NSMutableDictionary dictionaryWithCapacity: 5];
|
||||
parameters = [NSMutableDictionary dictionaryWithCapacity: 5];
|
||||
while (c != EOF)
|
||||
{
|
||||
// collect arguments
|
||||
|
|
Loading…
Reference in a new issue