/***
*assert.c - Display a message and abort
*
* Copyright (c) 1988-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
*
*******************************************************************************/
#ifdef _WIN32
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef NDEBUG
#undef NDEBUG
#endif /* NDEBUG */
#define _ASSERT_OK
#include
/*
* assertion format string for use with output to stderr
*/
static char _assertstring[] = "Assertion failed: %s, file %s, line %d\n";
/* Format of MessageBox for assertions:
*
* ================= Microsft Visual C++ Debug Library ================
*
* Assertion Failed!
*
* Program: c:\test\mytest\foo.exe
* File: c:\test\mytest\bar.c
* Line: 69
*
* Expression:
*
* For information on how your program can cause an assertion
* failure, see the Visual C++ documentation on asserts
*
* (Press Retry to debug the application - JIT must be enabled)
*
* ===================================================================
*/
/*
* assertion string components for message box
*/
#define BOXINTRO "Assertion failed!"
#define PROGINTRO "Program: "
#define FILEINTRO "File: "
#define LINEINTRO "Line: "
#define EXPRINTRO "Expression: "
#define INFOINTRO "For information on how your program can cause an assertion\n" \
"failure, see the Visual C++ documentation on asserts"
#define HELPINTRO "(Press Retry to debug the application - JIT must be enabled)"
static char * dotdotdot = "...";
static char * newline = "\n";
static char * dblnewline = "\n\n";
#define DOTDOTDOTSZ 3
#define NEWLINESZ 1
#define DBLNEWLINESZ 2
#define MAXLINELEN 60 /* max length for line in message box */
#define ASSERTBUFSZ (MAXLINELEN * 9) /* 9 lines in message box */
#if defined (_M_IX86)
#define _DbgBreak() __asm { int 3 }
#elif defined (_M_ALPHA)
void _BPT();
#pragma intrinsic(_BPT)
#define _DbgBreak() _BPT()
#else /* defined (_M_ALPHA) */
#define _DbgBreak() DebugBreak()
#endif /* defined (_M_ALPHA) */
/***
*_assert() - Display a message and abort
*
*Purpose:
* The assert macro calls this routine if the assert expression is
* true. By placing the assert code in a subroutine instead of within
* the body of the macro, programs that call assert multiple times will
* save space.
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _assert (
void *expr,
void *filename,
unsigned lineno
)
{
/*
* Build the assertion message, then write it out. The exact form
* depends on whether it is to be written out via stderr or the
* MessageBox API.
*/
if ( (__error_mode == _OUT_TO_STDERR) || ((__error_mode ==
_OUT_TO_DEFAULT) && (__app_type == _CONSOLE_APP)) )
{
/*
* Build message and write it out to stderr. It will be of the
* form:
* Assertion failed: , file , line
*/
if ( !anybuf(stderr) )
/*
* stderr is unused, hence unbuffered, as yet. set it to
* single character buffering (to avoid a malloc() of a
* stream buffer).
*/
(void) setvbuf(stderr, NULL, _IONBF, 0);
fprintf(stderr, _assertstring, expr, filename, lineno);
fflush(stderr);
}
else {
int nCode;
char * pch;
char assertbuf[ASSERTBUFSZ];
char progname[MAX_PATH];
/*
* Line 1: box intro line
*/
strcpy( assertbuf, BOXINTRO );
strcat( assertbuf, dblnewline );
/*
* Line 2: program line
*/
strcat( assertbuf, PROGINTRO );
if ( !GetModuleFileName( NULL, progname, MAX_PATH ))
strcpy( progname, "");
pch = (char *)progname;
/* sizeof(PROGINTRO) includes the NULL terminator */
if ( sizeof(PROGINTRO) + strlen(progname) + NEWLINESZ > MAXLINELEN )
{
pch += (sizeof(PROGINTRO) + strlen(progname) + NEWLINESZ) - MAXLINELEN;
strncpy( pch, dotdotdot, DOTDOTDOTSZ );
}
strcat( assertbuf, pch );
strcat( assertbuf, newline );
/*
* Line 3: file line
*/
strcat( assertbuf, FILEINTRO );
/* sizeof(FILEINTRO) includes the NULL terminator */
if ( sizeof(FILEINTRO) + strlen(filename) + NEWLINESZ >
MAXLINELEN )
{
/* too long. use only the first part of the filename string */
strncat( assertbuf, filename, MAXLINELEN - sizeof(FILEINTRO)
- DOTDOTDOTSZ - NEWLINESZ );
/* append trailing "..." */
strcat( assertbuf, dotdotdot );
}
else
/* plenty of room on the line, just append the filename */
strcat( assertbuf, filename );
strcat( assertbuf, newline );
/*
* Line 4: line line
*/
strcat( assertbuf, LINEINTRO );
_itoa( lineno, assertbuf + strlen(assertbuf), 10 );
strcat( assertbuf, dblnewline );
/*
* Line 5: message line
*/
strcat( assertbuf, EXPRINTRO );
/* sizeof(HELPINTRO) includes the NULL terminator */
if ( strlen(assertbuf) +
strlen(expr) +
2*DBLNEWLINESZ +
sizeof(INFOINTRO)-1 +
sizeof(HELPINTRO) > ASSERTBUFSZ )
{
strncat( assertbuf, expr,
ASSERTBUFSZ -
(strlen(assertbuf) +
DOTDOTDOTSZ +
2*DBLNEWLINESZ +
sizeof(INFOINTRO)-1 +
sizeof(HELPINTRO)) );
strcat( assertbuf, dotdotdot );
}
else
strcat( assertbuf, expr );
strcat( assertbuf, dblnewline );
/*
* Line 6, 7: info line
*/
strcat(assertbuf, INFOINTRO);
strcat( assertbuf, dblnewline );
/*
* Line 8: help line
*/
strcat(assertbuf, HELPINTRO);
/*
* Write out via MessageBox
*/
nCode = __crtMessageBoxA(assertbuf,
"Microsoft Visual C++ Runtime Library",
MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
/* Abort: abort the program */
if (nCode == IDABORT)
{
/* raise abort signal */
raise(SIGABRT);
/* We usually won't get here, but it's possible that
SIGABRT was ignored. So exit the program anyway. */
_exit(3);
}
/* Retry: call the debugger */
if (nCode == IDRETRY)
{
_DbgBreak();
/* return to user code */
return;
}
/* Ignore: continue execution */
if (nCode == IDIGNORE)
return;
}
abort();
}
#else /* _WIN32 */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#undef NDEBUG
#define _ASSERT_OK
#include
#include // get Mac header
#include
#include
#include
#include
static char _assertstring[] = "Assertion failed: %s, file %s, line %d\n";
extern MPWBLOCK * _pMPWBlock;
/***
*_assert() - Display a message and abort
*
*Purpose:
* The assert macro calls this routine if the assert expression is
* true. By placing the assert code in a subroutine instead of within
* the body of the macro, programs that call assert multiple times will
* save space.
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
#define addrMacJmp24 0x120
#define addrMacJmp32 0xbff
void _CALLTYPE1 _assert (
void *expr,
void *filename,
unsigned lineno
)
{
char rgch[512];
long lrespond;
OSErr osErr;
long *pl;
unsigned char ch;
char *pch;
int cb;
if (_pMPWBlock != NULL) {
/*
* This is the original CRT32 code.
*/
if ( !anybuf(stderr) )
/*
* stderr is unused, hence unbuffered, as yet. set it to
* single character buffering (to avoid a malloc() of a
* stream buffer).
*/
(void) setvbuf(stderr, NULL, _IONBF, 0);
fprintf(stderr, _assertstring, expr, filename, lineno);
fflush(stderr);
}
else {
/*
* This assert code will bring up system debugger, most
* probably MacsBug if there is a debuuger installed.
* If no debugger installed, write to stderr file.
* Not sure if this is really working. Need more accurate
* info on how MacJmp is set up.
*/
osErr = Gestalt(gestaltAddressingModeAttr, &lrespond);
if (!osErr) {
if (!BitTst(&lrespond, 31-gestalt32BitCapable)) {
pl = (long *)addrMacJmp24;
ch = (unsigned char)(*pl);
}
else {
pch = (char *)addrMacJmp32;
ch = *pch;
}
}
if (ch & 0x20) { //test bit 5 for Debugger installed
sprintf(rgch, _assertstring, expr, filename, lineno);
_c2pstr(rgch);
DebugStr(rgch);
}
else {
// freopen("stderr", "wt", stderr);
// fprintf(stderr, _assertstring, expr, filename, lineno);
cb = sprintf(rgch, _assertstring, expr, filename, lineno);
_write(2, rgch, cb);
// fflush(stderr);
}
}
abort();
}
#endif /* _WIN32 */