// Copyright 1997-1998 Omni Development, Inc.  All rights reserved.

#import "assertions.h"

#import <Foundation/Foundation.h>

#import "rcsid.h"

RCS_ID("$Header: /Network/Developer/Source/CVS/OmniGroup/OmniBase/assertions.m,v 1.10 1998/03/20 05:58:06 kc Exp $")

#ifdef OMNI_ASSERTIONS_ON
#warning (Assertions enabled.  To disable, undefine OMNI_ASSERTIONS_ON.)
#else
#warning (Assertions disabled.  To enable, define OMNI_ASSERTIONS_ON.)
#endif


// Unless OMNI_PRODUCTION_BUILD is specified, log a message about whether assertions are enabled or not.
#ifndef OMNI_PRODUCTION_BUILD

@interface _OBAssertionWarning : NSObject
@end

@implementation _OBAssertionWarning
+ (void)didLoad;
{
#ifdef OMNI_ASSERTIONS_ON
    fprintf(stderr, "*** Assertions are ON ***\n");
#else
    fprintf(stderr, "*** Assertions are OFF ***\n");
#endif
}
@end

#endif // OMNI_PRODUCTION_BUILD

//
// The default assertion handler
//

static void OBAbort(const char *type, const char *expression, const char *file, unsigned int lineNumber);
static void OBLogAssertionFailure(const char *type, const char *expression, const char *file, unsigned int lineNumber);
#ifdef OMNI_ABORT_ON_ASSERTION_FAILURE
#define OBDefaultAssertionHandler OBAbort
#else
#define OBDefaultAssertionHandler OBLogAssertionFailure
#endif

static OBAssertionFailureHandler currentAssertionHandler = OBDefaultAssertionHandler;
                    
// Some machines (NT, at least) lose the last stack frame when you call abort(), which makes it difficult to debug assertion failures.  We'll call OBAbort() instead of abort() so that you can set a breakpoint on OBAbort() and not lose the stack frame.

static void OBAbort(const char *type, const char *expression, const char *file, unsigned int lineNumber)
{
    OBLogAssertionFailure(type, expression, file, lineNumber);
    
    fprintf(stderr, "Aborting (presumably due to assertion failure).\n");
    fflush(stderr);
    abort();
}

static void OBLogAssertionFailure(const char *type, const char *expression, const char *file, unsigned int lineNumber)
{
    fprintf(stderr, "%s failed: requires '%s', file %s, line %d\n", type, expression, file, lineNumber);
}

void OBSetAssertionFailureHandler(OBAssertionFailureHandler handler)
{
    if (handler)
        currentAssertionHandler = handler;
    else
        currentAssertionHandler = OBDefaultAssertionHandler;
}

void OBAssertFailed(const char *type, const char *expression, const char *file, unsigned int lineNumber)
{
    currentAssertionHandler(type, expression, file, lineNumber);
}
