/* 
   Copyright (C) 1996 
	Ovidiu Predescu <ovidiu@bx.logicnet.ro>
	Mircea Oancea <mircea@jupiter.elcom.pub.ro>

   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>

   This file is part of the FoundationExtensions 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; see the file COPYING.LIB.
   If not, write to the Free Software Foundation,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include <config.h>

#include <stdarg.h>

#if HAVE_STDLIB_H
#include <stdlib.h>
#endif

#include <Foundation/NSString.h>

#include <extensions/NSException.h>
#include <extensions/exceptions/GeneralExceptions.h>
#include <extensions/exceptions/NSCoderExceptions.h>

#include <Foundation/NSArray.h>
#include "MissingMethods.h"

@implementation NSException (Extensions)

#if GNUSTEP_BASE_LIBRARY
# define name_ivar e_name
# define reason_ivar e_reason
# define userInfo_ivar e_info
#else
# define name_ivar name
# define reason_ivar reason
# define userInfo_ivar userInfo
#endif

#if NeXT_foundation_LIBRARY
NSString *NSMallocException = @"NSMallocException";
#endif

void __NSException_dummy_function_for_stupid_linkers()
{
    extern void __MissingMethods_dummy_function_for_stupid_linkers();
    __MissingMethods_dummy_function_for_stupid_linkers();
}

- (BOOL)exceptionIsKindOfClass:(Class)class
{
    return [self isKindOfClass:class];
}

- (BOOL)exceptionIsIn:(NSArray*)exceptions
{
    int i, n = [exceptions count];

    for(i = 0; i < n; i++)
	if([self exceptionIsKindOfClass:[[exceptions objectAtIndex:i] class]])
	    return YES;
    return NO;
}

- (NSString*)errorString
{
    NSString* message;

    if(reason_ivar)
	message = [NSString stringWithFormat:@"%s: caught %s exception "
				@"object.\nReason: %s\n",
				"Error", [[isa description] cString],
				[reason_ivar cString]];
    else message = [NSString stringWithFormat:@"%s: caught %s exception object.\n",
				"Error", [[isa description] cString]];


    return message;
}

- initWithFormat:(NSString*)format, ...
{
    va_list ap;

    va_start(ap, format);
    reason_ivar = [[NSString alloc] initWithFormat:format arguments:ap];
    va_end(ap);
    return self;
}

- setName:(NSString*)_name
{
    [_name retain];
    [name_ivar release];
    name_ivar = _name;
    return self;
}

- setReason:(NSString*)_reason
{
    [_reason retain];
    [reason_ivar release];
    reason_ivar = _reason;
    return self;
}

- setUserInfo:(NSDictionary*)_userInfo
{
    [_userInfo retain];
    [userInfo_ivar release];
    userInfo_ivar = _userInfo;
    return self;
}

@end /* NSException (Extensions) */


#if NeXT_foundation_LIBRARY

@implementation NSException (MissingMethods)

- (NSString*)name		{ return name_ivar; }
- (NSString*)reason		{ return reason_ivar; }
- (NSDictionary*)userInfo	{ return userInfo_ivar; }

@end /* NSException (MissingMethods) */

#endif /* NeXT_foundation_LIBRARY */




@implementation NSException (ExceptionClassesMapping)
#ifndef GNUSTEP_BASE_LIBRARY
- initWithName:(NSString*)_name
    reason:(NSString*)_reason
    userInfo:(NSDictionary*)_userInfo
{
    NSDictionary* exceptionMapping = nil;
    Class exceptionClass;

    if(!exceptionMapping) {
	exceptionMapping = [NSDictionary dictionaryWithObjectsAndKeys:
	    [FoundationException class], NSGenericException,
	    [RangeException class], NSRangeException,
	    [InvalidArgumentException class], NSInvalidArgumentException,
	    [InternalInconsistencyException class], NSInternalInconsistencyException,
#if NeXT_foundation_LIBRARY
	    [SyntaxErrorException class], NSParseErrorException,
	    [NSException class], NSObjCInadequateRuntimeInformation,
	    [NSCoderException class], NSCodingException,
	    [NSException class], NSObjectInaccessibleException,
	    [NSException class], NSObjectNotAvailableException,
	    [NSException class], NSDestinationInvalidException,
	    [NSException class], NSOwnershipTransferException,
	    [NSException class], NSPortTimoutException,
	    [NSException class], NSInvalidSendPort,
	    [NSException class], NSInvalidReceivePort,
	    [NSException class], NSPortSendError,
	    [NSException class], NSPortReceiveError,
	    [NSException class], NSPortNameRegistrationError,
	    [NSException class], NSArchiverArchiveInconsistency,
	    [NSException class], NSArchiverClassError,
	    [NSException class], NSArchiverDescriptorError,
	    [NSException class], NSArchiverWriteReferenceError,
	    [NSException class], NSDateMissingTimeZone,
#endif
	    nil];
    }

    [_name retain];
    [_reason retain];
    [_userInfo retain];

    exceptionClass = [exceptionMapping objectForKey:_name];
    if(exceptionClass && ![isa isKindOfClass:exceptionClass]) {
	[self autorelease];
	self = [exceptionClass alloc];
    }

    [self->name_ivar release];
    [self->reason_ivar release];
    [self->userInfo_ivar release];
    self->name_ivar = _name;
    self->reason_ivar = _reason;
    self->userInfo_ivar = _userInfo;

    return self;
}
#endif
@end /* NSException (ExceptionClassesMapping) */
