/*********************************************************************
FILENAME
Exceptions.h
DESCRIPTION
A collection of routines and macros to handle assertions and
exceptions.
COPYRIGHT
Copyright © Apple Computer, Inc. 1989-1991
All rights reserved.
ROUTINES
EXTERNALS
dprintf
check_dprintf
checkpos_dprintf
MACROS
EXTERNALS
check
ncheck
check_action
ncheck_action
require
nrequire
require_action
nrequire_action
resume
MODIFICATION HISTORY
Nov 12 95 BKJ Moved to MetroWerks environment & the NSPR
NOTE
To keep code size down, use these routines and macros with the C
compiler option -b2 or -b3. This will eliminate duplicate strings
within a procedure.
*********************************************************************/
#ifndef __MACERRORHANDLING__
#define __MACERRORHANDLING__
/*********************************************************************
INCLUDES
*********************************************************************/
#include <Types.h>
/*<FF>*/
/*********************************************************************
CONSTANTS AND CONTROL
*********************************************************************/
/*
These defines are used to control the amount of information
displayed when an assertion fails. DEBUGOFF and WARN will run
silently. MIN will simply break into the debugger. ON will break
and display the assertion that failed and the exception (for
require statements). FULL will also display the source file name
and line number. SYM does a SysBreak and is usefull when using a
symbolic debugger like SourceBug or SADE. They should be set into
DEBUGLEVEL. The default LEVEL is OFF.
*/
#define DEBUGOFF 0
#define DEBUGWARN 1
#define DEBUGMIN 2
#define DEBUGON 3
#define DEBUGFULL 4
#define DEBUGSYM 6
#ifndef DEBUGLEVEL
#define DEBUGLEVEL DEBUGOFF
#endif DEBUGLEVEL
/*
resumeLabel is used to control the insertion of labels for use with
the resume macro. If you do not use the resume macro and you wish
to have multible exceptions per label then you can add the
following define to you source code.
*/
#define resumeLabel(exception) // Multiple exceptions per label
// #define resumeLabel(exception) resume_ ## exception: // Single exception per label
/*
traceon and debugon are used to test for options
*/
#define traceon ((DEBUGLEVEL > DEBUGWARN) && defined(TRACEON))
#define debugon (DEBUGLEVEL > DEBUGWARN)
/*
Add some macros for DEBUGMIN and DEBUGSYM to keep the size down.
*/
#define __DEBUGSMALL ((DEBUGLEVEL == DEBUGMIN) || \
(DEBUGLEVEL == DEBUGSYM))
#if DEBUGLEVEL == DEBUGMIN
#define __DebuggerBreak Debugger()
#elif DEBUGLEVEL == DEBUGSYM
#define __DebuggerBreak SysBreak()
#endif
/*<FF>*/
/*********************************************************************
MACRO
check(assertion)
DESCRIPTION
If debugging is on then check will test assertion and if it fails
break into the debugger. Otherwise check does nothing.
*********************************************************************/
#if __DEBUGSMALL
#define check(assertion) \
do { \
if (assertion) ; \
else __DebuggerBreak; \
} while (false)
#elif DEBUGLEVEL == DEBUGON
#define check(assertion) \
do { \
if (assertion) ; \
else { \
dprintf(notrace, "Assertion \"%s\" Failed", #assertion); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGFULL
#define check(assertion) \
do { \
if (assertion) ; \
else { \
dprintf(notrace, "Assertion \"%s\" Failed\n" \
"File: %s\n" \
"Line: %d", \
#assertion, __FILE__, __LINE__); \
} \
} while (false)
#else
#define check(assertion)
#endif
/*<FF>*/
/*********************************************************************
MACRO
ncheck(assertion)
DESCRIPTION
If debugging is on then ncheck will test !assertion and if it fails
break into the debugger. Otherwise ncheck does nothing.
*********************************************************************/
#if __DEBUGSMALL
#define ncheck(assertion) \
do { \
if (assertion) __DebuggerBreak; \
} while (false)
#elif DEBUGLEVEL == DEBUGON
#define ncheck(assertion) \
do { \
void* __privateAssertion = (void*)(assertion); \
\
if (__privateAssertion) { \
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed", \
#assertion, __privateAssertion); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGFULL
#define ncheck(assertion) \
do { \
void* __privateAssertion = (void*)(assertion); \
\
if (__privateAssertion) { \
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
"File: %s\n" \
"Line: %d", \
#assertion, __privateAssertion, __FILE__, __LINE__); \
} \
} while (false)
#else
#define ncheck(assertion)
#endif
/*<FF>*/
/*********************************************************************
MACRO
check_action(assertion, action)
DESCRIPTION
If debugging is on then check_action will test assertion and if it
fails break into the debugger then execute action. Otherwise
check_action does nothing.
*********************************************************************/
#if __DEBUGSMALL
#define check_action(assertion, action) \
do { \
if (assertion) ; \
else { \
__DebuggerBreak; \
{ action } \
} while (false)
#elif DEBUGLEVEL == DEBUGON
#define check_action(assertion, action) \
do { \
if (assertion) ; \
else { \
dprintf(notrace, "Assertion \"%s\" Failed", #assertion); \
{ action } \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGFULL
#define check_action(assertion, action) \
do { \
if (assertion) ; \
else { \
dprintf(notrace, "Assertion \"%s\" Failed\n" \
"File: %s\n" \
"Line: %d", \
#assertion, __FILE__, __LINE__); \
{ action } \
} \
} while (false)
#else
#define check_action(assertion, action)
#endif
/*<FF>*/
/**************************************************************************************
MACRO
ncheck_action(assertion, action)
DESCRIPTION
If debugging is on then ncheck_action will test !assertion and if
it fails break into the debugger then execute action. Otherwise
ncheck_action does nothing.
*********************************************************************/
#if __DEBUGSMALL
#define ncheck_action(assertion, action) \
do { \
if (assertion) { \
__DebuggerBreak; \
{ action } \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGON
#define ncheck_action(assertion, action) \
do { \
void* __privateAssertion = (void*)(assertion); \
\
if (__privateAssertion) { \
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed", \
#assertion, __privateAssertion); \
{ action } \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGFULL
#define ncheck_action(assertion, action) \
do { \
void* __privateAssertion = (void*)(assertion); \
\
if (__privateAssertion) { \
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
"File: %s\n" \
"Line: %d", \
#assertion, __privateAssertion, __FILE__, __LINE__); \
{ action } \
} \
} while (false)
#else
#define ncheck_action(assertion, action)
#endif
/*<FF>*/
/*********************************************************************
MACRO
require(assertion, exception)
DESCRIPTION
require will test assertion and if it fails:
break into the debugger if debugging is on.
goto exception.
*********************************************************************/
#if __DEBUGSMALL
#define require(assertion, exception) \
do { \
if (assertion) ; \
else { \
__DebuggerBreak; \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGON
#define require(assertion, exception) \
do { \
if (assertion) ; \
else { \
dprintf(notrace, "Assertion \"%s\" Failed\n" \
"Exception \"%s\" Raised", \
#assertion, #exception); \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGFULL
#define require(assertion, exception) \
do { \
if (assertion) ; \
else { \
dprintf(notrace, "Assertion \"%s\" Failed\n" \
"Exception \"%s\" Raised\n" \
"File: %s\n" \
"Line: %d", \
#assertion, #exception, __FILE__, __LINE__); \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#else
#define require(assertion, exception) \
do { \
if (assertion) ; \
else { \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#endif
/*<FF>*/
/*********************************************************************
MACRO
nrequire(assertion, exception)
DESCRIPTION
nrequire will test !assertion and if it fails:
break into the debugger if debugging is on.
goto exception.
*********************************************************************/
#if __DEBUGSMALL
#define nrequire(assertion, exception) \
do { \
if (assertion) { \
DebugStr(); \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGON
#define nrequire(assertion, exception) \
do { \
void* __privateAssertion = (void*)(assertion); \
\
if (__privateAssertion) { \
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
"Exception \"%s\" Raised", \
#assertion, __privateAssertion, #exception); \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGFULL
#define nrequire(assertion, exception) \
do { \
void* __privateAssertion = (void*)(assertion); \
\
if (__privateAssertion) { \
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
"Exception \"%s\" Raised\n" \
"File: %s\n" \
"Line: %d", \
#assertion, __privateAssertion, #exception, __FILE__, \
__LINE__); \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#else
#define nrequire(assertion, exception) \
do { \
if (assertion) { \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#endif
/*<FF>*/
/*********************************************************************
MACRO
require_action(assertion, exception, action)
DESCRIPTION
require_action will test assertion and if it fails:
break into the debugger if debugging is on.
execute action.
goto exception.
*********************************************************************/
#if __DEBUGSMALL
#define require_action(assertion, exception, action) \
do { \
if (assertion) ; \
else { \
__DebuggerBreak; \
{ action } \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGON
#define require_action(assertion, exception, action) \
do { \
if (assertion) ; \
else { \
dprintf(notrace, "Assertion \"%s\" Failed\n" \
"Exception \"%s\" Raised", \
#assertion, #exception); \
{ action } \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGFULL
#define require_action(assertion, exception, action) \
do { \
if (assertion) ; \
else { \
dprintf(notrace, "Assertion \"%s\" Failed\n" \
"Exception \"%s\" Raised\n" \
"File: %s\n" \
"Line: %d", \
#assertion, #exception, __FILE__, __LINE__); \
{ action } \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#else
#define require_action(assertion, exception, action) \
do { \
if (assertion) ; \
else { \
{ action } \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#endif
/*<FF>*/
/*********************************************************************
MACRO
nrequire_action(assertion, exception, action)
DESCRIPTION
nrequire_action will test !assertion and if it fails:
break into the debugger if debugging is on.
execute action.
goto exception.
*********************************************************************/
#if __DEBUGSMALL
#define nrequire_action(assertion, exception, action) \
do { \
if (assertion) { \
__DebuggerBreak; \
{ action } \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGON
#define nrequire_action(assertion, exception, action) \
do { \
void* __privateAssertion = (void*)(assertion); \
\
if (__privateAssertion) { \
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
"Exception \"%s\" Raised", \
#assertion, __privateAssertion, #exception); \
{ action } \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#elif DEBUGLEVEL == DEBUGFULL
#define nrequire_action(assertion, exception, action) \
do { \
void* __privateAssertion = (void*)(assertion); \
\
if (__privateAssertion) { \
dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
"Exception \"%s\" Raised\n" \
"File: %s\n" \
"Line: %d", \
#assertion, __privateAssertion, #exception, __FILE__, \
__LINE__); \
{ action } \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#else
#define nrequire_action(assertion, exception, action) \
do { \
if (assertion) { \
{ action } \
goto exception; \
resumeLabel(exception); \
} \
} while (false)
#endif
/*<FF>*/
/*********************************************************************
MACRO
resume(exception)
DESCRIPTION
resume will resume execution after the n/require/_action statement
specified by exception. Resume lables must be on (the default) in
order to use resume. If an action form of require was used then the
action will not be re-executed.
*********************************************************************/
#define resume(exception) \
do { \
goto resume_ ## exception; \
} while (false)
/*<FF>*/
/********************************************************************/
#endif
syntax highlighted by Code2HTML, v. 0.9.1