void LuaDebugPrint(lua_Debug &ar)
{
	dumpBuffer.Printf( "Name:\t\t%s\r\n",  ar.name);
	dumpBuffer.Printf( "Name of:\t%s\r\n",  ar.namewhat);
	dumpBuffer.Printf( "Function type:\t%s\r\n",  ar.what);
	dumpBuffer.Printf( "Defined on:\t%d\r\n",  ar.linedefined);
	dumpBuffer.Printf( "Upvalues:\t%d\r\n",  ar.nups);
	dumpBuffer.Printf( "\r\n" );
	dumpBuffer.Printf( "Source:\t\t%s\r\n",  ar.source);
	dumpBuffer.Printf( "Short source:\t%s\r\n",  ar.short_src);
	dumpBuffer.Printf( "Current line:\t%d\r\n",  ar.currentline);
	dumpBuffer.Printf( "- Function line:\t%d\r\n", (ar.linedefined ? (1 + ar.currentline - ar.linedefined) : 0));
}
void PE_Debug :: DumpLineNumber( DumpBuffer& dumpBuffer, DWORD relativeAddress )
  {
  PIMAGE_LINENUMBER line = BasedPtr( PIMAGE_LINENUMBER, COFFDebugInfo,
                                     COFFDebugInfo->LvaToFirstLinenumber ) ;
  DWORD lineCount = COFFDebugInfo->NumberOfLinenumbers ;
  const DWORD none = (DWORD)-1 ;
  DWORD maxAddr = 0 ;
  DWORD lineNum = none ;
  for( DWORD i=0; i < lineCount; i++ )
    {
    if( line->Linenumber != 0 )  // A regular line number
      {
      // look for line with bigger address <= relativeAddress
      if( line->Type.VirtualAddress <= relativeAddress &&
          line->Type.VirtualAddress > maxAddr )
        {
        maxAddr = line->Type.VirtualAddress ;
        lineNum = line->Linenumber ;
        }
      }
    line++ ;
    }
  if( lineNum != none ) {
    dumpBuffer.Printf( "  line %d\r\n", lineNum ) ;
	if (Dump_to_log) {
		mprintf(( "  line %d\r\n", lineNum )) ;
	}
  }	
//  else
//  dumpBuffer.Printf( "  line <unknown>\r\n" ) ;
  }
void _cdecl WinAssert(char * text, char * filename, int linenum, const char * format, ... )
{
	int val;
	va_list args;

	memset( AssertText1, 0, sizeof(AssertText1) );
	memset( AssertText2, 0, sizeof(AssertText2) );

	va_start(args, format);
	vsnprintf(AssertText2, sizeof(AssertText2)-1, format, args);
	va_end(args);

	// this stuff migt be really useful for solving bug reports and user errors. We should output it! 
	mprintf(("ASSERTION: \"%s\" at %s:%d\n %s\n", text, strrchr(filename, '\\')+1, linenum, AssertText2 ));

#ifdef Allow_NoWarn
	if (Cmdline_nowarn) {
		return;
	}
#endif

	Messagebox_active = true;

	gr_activate(0);

	filename = strrchr(filename, '\\')+1;
	snprintf( AssertText1, sizeof(AssertText1)-1, "Assert: %s\r\nFile: %s\r\nLine: %d\r\n%s\r\n", text, filename, linenum, AssertText2 );

#if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
	/* Dump the callstack */
	SCP_DebugCallStack callStack;
	SCP_DumpStack( dynamic_cast< SCP_IDumpHandler* >( &callStack ) );
	
	/* Format the string */
	SCP_string assertString( AssertText1 );
	assertString += "\n";
	assertString += callStack.DumpToString( );
	
	/* Copy to the clipboard */
	dump_text_to_clipboard( assertString.c_str( ) );

	// truncate text
	truncate_message_lines(assertString, Messagebox_lines);

	assertString += "\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
	assertString += "\n\nUse Ok to break into Debugger, Cancel to exit.\n";
	val = MessageBox( NULL, assertString.c_str( ), "Assertion Failed!", MB_OKCANCEL | flags );

#elif defined ( SHOW_CALL_STACK	)
	dumpBuffer.Clear();
	dumpBuffer.Printf( AssertText1 );
	dumpBuffer.Printf( "\r\n" );
	DumpCallsStack( dumpBuffer ) ;  
	dump_text_to_clipboard(dumpBuffer.buffer);

	// truncate text
	dumpBuffer.TruncateLines(Messagebox_lines);

	dumpBuffer.Printf( "\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
	dumpBuffer.Printf( "\r\n\r\nUse Ok to break into Debugger, Cancel to exit.\r\n");

	val = MessageBox(NULL, dumpBuffer.buffer, "Assertion Failed!", MB_OKCANCEL|flags );
#else
	val = MessageBox(NULL, AssertText1, "Assertion Failed!", MB_OKCANCEL|flags );
#endif

	if (val == IDCANCEL)
		exit(1);

	Int3();

	gr_activate(1);

	Messagebox_active = false;
}
void DumpCallsStack( DumpBuffer& dumpBuffer )
{
	static PE_Debug PE_debug ;

	dumpBuffer.Printf( "\r\nCall stack:\r\n" ) ;
	dumpBuffer.Printf( Separator ) ;

	// The structure of the stack frames is the following:
	// EBP -> parent stack frame EBP
	//        return address for this call ( = caller )
	// The chain can be navigated iteratively, after the
	// initial value of EBP is loaded from the register
	DWORD parentEBP, retval;
	MEMORY_BASIC_INFORMATION mbi ;
	HINSTANCE hInstance;

	int depth = 0;

	__asm MOV parentEBP, EBP

	do	{
		depth++;
		if ( depth > 16 ) 
			break;

		if ( (parentEBP & 3) || IsBadReadPtr((DWORD*)parentEBP, sizeof(DWORD)) )	{
			break;
		}
		parentEBP = *(DWORD*)parentEBP ;

		BYTE **NextCaller = ((BYTE**)parentEBP + 1);

		if (IsBadReadPtr(NextCaller, sizeof(BYTE *)))	{
			break;
		}

		BYTE* caller = *NextCaller;		// Error sometimes!!!

		// Skip the first EBP as it points to AssertionFailed, which is
		// uninteresting for the user

		if ( depth > 1 )	{

			// Get the instance handle of the module where caller belongs to
			retval = VirtualQuery( caller, &mbi, sizeof( mbi ) ) ;

			// The instance handle is equal to the allocation base in Win32
			hInstance = (HINSTANCE)mbi.AllocationBase ;

			if( ( retval == sizeof( mbi ) ) && hInstance )	{
				if ( !PE_debug.DumpDebugInfo( dumpBuffer, caller, hInstance ) )	{
					//break;
				}
			} else {
				break ; // End of the call chain
			}
		}
	}  while( TRUE ) ;


	dumpBuffer.Printf( Separator ) ;
	PE_debug.ClearReport() ;  // Prepare for future calls
}
int PE_Debug::DumpDebugInfo( DumpBuffer& dumpBuffer, const BYTE* caller, HINSTANCE hInstance )
{
	// Avoid to open, map and looking for debug header/symbol table
	// by caching the latest and comparing the actual module with
	// the latest one.
	static char module[ MAX_MODULENAME_LEN ] ;
	GetModuleFileName( hInstance, module, MAX_MODULENAME_LEN ) ;

	// New module
	if( strcmpi( latestModule, module ) )	{
		strcpy_s( latestModule, module );
		//JAS    dumpBuffer.Printf( "Module: %s\r\n", module );
		MapFileInMemory( module );
		FindDebugInfo();
	}

	char pretty_module[1024];

	strcpy_s( pretty_module, module );
	char *p = pretty_module+strlen(pretty_module)-1;
	// Move p to point to first letter of EXE filename
	while( (*p!='\\') && (*p!='/') && (*p!=':') )
		p--;
	p++;	
	if ( strlen(p) < 1 ) {
		strcpy_s( pretty_module, "<unknown>" );
	} else {
		memmove( pretty_module, p, strlen(p)+1 );
	}

	if ( fileBase )	{
		// Put everything into a try/catch in case the file has wrong fields
		try	{
			DWORD relativeAddress = caller - (BYTE*)hInstance ;
			// Dump symbolic information and line number if available
			if( COFFSymbolCount != 0 && COFFSymbolTable != NULL )	{
				DumpSymbolInfo( dumpBuffer, relativeAddress ) ;
				if( COFFDebugInfo )
					DumpLineNumber( dumpBuffer, relativeAddress ) ;
				return 1;
			} else {
				//dumpBuffer.Printf( "Call stack is unavailable, because there is\r\nno COFF debugging info in this module.\r\n" ) ;
				//JAS dumpBuffer.Printf( "  no debug information\r\n" ) ;
				dumpBuffer.Printf( "    %s %08x()\r\n", pretty_module, caller ) ;
				if (Dump_to_log) {
					mprintf(("    %s %08x()\r\n", pretty_module, caller )) ;
				}
				return 0;
			}
		} catch( ... )	{
			// Header wrong, do nothing
			return 0;
      }
	} else	{
		dumpBuffer.Printf( "    %s %08x()\r\n", pretty_module, caller ) ;
		if (Dump_to_log) {
			mprintf(( "    %s %08x()\r\n", pretty_module, caller )) ;
		}
		//JAS dumpBuffer.Printf( "  module not accessible\r\n" ) ;
		//JAS dumpBuffer.Printf( "    address: %8X\r\n", caller ) ;
		return 0;
	}

	Int3();

}
void PE_Debug::DumpSymbolInfo( DumpBuffer& dumpBuffer, DWORD relativeAddress )
{
	// Variables to keep track of function symbols
	PIMAGE_SYMBOL currentSym = COFFSymbolTable ;
	PIMAGE_SYMBOL fnSymbol = NULL ;
	DWORD maxFnAddress = 0 ;

	#ifdef DUMPRAM
	InitSymbols();
	#endif

	// Variables to keep track of file symbols
	PIMAGE_SYMBOL fileSymbol = NULL ;
	PIMAGE_SYMBOL latestFileSymbol = NULL ;
	for ( int i = 0; i < COFFSymbolCount; i++ )	{

		// Look for .text section where relativeAddress belongs to.
		// Keep track of the filename the .text section belongs to.
		if ( currentSym->StorageClass == IMAGE_SYM_CLASS_FILE )	{
			latestFileSymbol = currentSym;
		}

		// Borland uses "CODE" instead of the standard ".text" entry
		// Microsoft uses sections that only _begin_ with .text
		const char* symName = GetSymbolName( currentSym ) ;

		if ( strnicmp( symName, ".text", 5 ) == 0 || strcmpi( symName, "CODE" ) == 0 )	{
			if ( currentSym->Value <= relativeAddress )	{
				PIMAGE_AUX_SYMBOL auxSym = (PIMAGE_AUX_SYMBOL)(currentSym + 1) ;
				if ( currentSym->Value + auxSym->Section.Length >= relativeAddress )	{
					fileSymbol = latestFileSymbol ;
				}
			}
		}


		// Look for the function with biggest address <= relativeAddress
		BOOL isFunction = ISFCN( currentSym->Type ); // Type == 0x20, See WINNT.H
		if ( isFunction && ( currentSym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL || currentSym->StorageClass == IMAGE_SYM_CLASS_STATIC ) )	{

			if ( currentSym->Value <= relativeAddress && currentSym->Value > maxFnAddress )	{
				maxFnAddress = currentSym->Value ;
				fnSymbol = currentSym ;
			}
		}

	#ifdef DUMPRAM
		if ( !isFunction && (currentSym->SectionNumber >= 0) )	{
			if ( (symName[0]=='_' && symName[1]!='$') || (symName[0]=='?') ) {

				char pretty_module[1024];

				if ( fileSymbol )	{
					const char* auxSym = (const char*)(latestFileSymbol + 1) ;
					char tmpFile[ VA_MAX_FILENAME_LEN ] ;
					strcpy_s( tmpFile, auxSym ) ;
					strcpy_s( pretty_module, tmpFile );
					char *p = pretty_module+strlen(pretty_module)-1;
					// Move p to point to first letter of EXE filename
					while( (*p!='\\') && (*p!='/') && (*p!=':') )
						p--;
					p++;	
					if ( strlen(p) < 1 ) {
						strcpy_s( pretty_module, "<unknown>" );
					} else {
						memmove( pretty_module, p, strlen(p)+1 );
					}
				} else {
					strcpy_s( pretty_module, "" );
				}

				Add_Symbol( currentSym->SectionNumber, currentSym->Value, symName, pretty_module );
			}
		}
	#endif

		// Advance counters, skip aux symbols
		i += currentSym->NumberOfAuxSymbols ;
		currentSym += currentSym->NumberOfAuxSymbols ;
		currentSym++ ;
	}

	#ifdef DUMPRAM
	DumpSymbols();
	#endif
	
	// dump symbolic info if found
	if ( fileSymbol )	{
		const char* auxSym = (const char*)(fileSymbol + 1) ;

		if( strcmpi( latestFile, auxSym ) )	{
			strcpy_s( latestFile, auxSym ) ;
			//JAS      dumpBuffer.Printf( "  file: %s\r\n", auxSym ) ;    
		}
	} else {
		latestFile[ 0 ] = 0 ;
		//JAS    dumpBuffer.Printf( "  file: unknown\r\n" ) ;    
	}
	
	if ( fnSymbol )	{
		char tmp_name[1024];
		unmangle(tmp_name, GetSymbolName( fnSymbol ) );
		dumpBuffer.Printf( "    %s()", tmp_name ) ;
		if (Dump_to_log) {
			mprintf(("    %s()", tmp_name )) ;
		}
	} else {
		dumpBuffer.Printf( "    <unknown>" ) ;
		if (Dump_to_log) {		
			mprintf(("    <unknown>" )) ;
		}
	}
}
void _cdecl Warning( char *filename, int line, const char *format, ... )
{
	Global_warning_count++;

#ifndef NDEBUG
	va_list args;
	int result;
	int i;
	int slen = 0;

	// output to the debug log before anything else (so that we have a complete record)

	memset( AssertText1, 0, sizeof(AssertText1) );
	memset( AssertText2, 0, sizeof(AssertText2) );

	va_start(args, format);
	vsnprintf(AssertText1, sizeof(AssertText1) - 1, format, args);
	va_end(args);

	slen = strlen(AssertText1);

	// strip out the newline char so the output looks better
	for (i = 0; i < slen; i++){
		if (AssertText1[i] == (char)0x0a) {
			AssertText2[i] = ' ';
		} else {
			AssertText2[i] = AssertText1[i];
		}
	}

	// kill off extra white space at end
	if (AssertText2[slen-1] == (char)0x20) {
		AssertText2[slen-1] = '\0';
	} else {
		// just being careful
		AssertText2[slen] = '\0';
	}

	mprintf(("WARNING: \"%s\" at %s:%d\n", AssertText2, strrchr(filename, '\\')+1, line));

	// now go for the additional popup window, if we want it ...
#ifdef Allow_NoWarn
	if (Cmdline_nowarn) {
		return;
	}
#endif

	filename = strrchr(filename, '\\')+1;
	sprintf(AssertText2, "Warning: %s\r\nFile: %s\r\nLine: %d\r\n", AssertText1, filename, line );

	Messagebox_active = true;

	gr_activate(0);

#if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
	/* Dump the callstack */
	SCP_DebugCallStack callStack;
	SCP_DumpStack( dynamic_cast< SCP_IDumpHandler* >( &callStack ) );
	
	/* Format the string */
	SCP_string assertString( AssertText1 );
	assertString += "\n";
	assertString += callStack.DumpToString( );
	
	/* Copy to the clipboard */
	dump_text_to_clipboard( assertString.c_str( ) );

	// truncate text
	truncate_message_lines(assertString, Messagebox_lines);

	assertString += "\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
	assertString += "\n\nUse Yes to break into Debugger, No to continue.\nand Cancel to Quit\n";
	result = MessageBox( NULL, assertString.c_str( ), "Warning!", MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_ICONWARNING | flags );

#elif defined ( SHOW_CALL_STACK	)
	//we don't want to dump the call stack for every single warning
	Dump_to_log = false; 

	dumpBuffer.Clear();
	dumpBuffer.Printf( AssertText2 );
	dumpBuffer.Printf( "\r\n" );
	DumpCallsStack( dumpBuffer ) ;  
	dump_text_to_clipboard(dumpBuffer.buffer);

	// truncate text
	dumpBuffer.TruncateLines(Messagebox_lines);

	dumpBuffer.Printf( "\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
	dumpBuffer.Printf("\r\n\r\nUse Yes to break into Debugger, No to continue.\r\nand Cancel to Quit");

	result = MessageBox((HWND)os_get_window(), dumpBuffer.buffer, "Warning!", MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_ICONWARNING | flags );

	Dump_to_log = true; 

#else
	strcat_s(AssertText2,"\r\n\r\nUse Yes to break into Debugger, No to continue.\r\nand Cancel to Quit");
	result = MessageBox((HWND)os_get_window(), AssertText2, "Warning!", MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_ICONWARNING | flags );
#endif

	switch (result)
	{
		case IDYES:
			Int3();
			break;

		case IDNO:
			break;

		case IDCANCEL:
			exit(1);
	}

	gr_activate(1);

	Messagebox_active = false;
#endif // !NDEBUG
}
void _cdecl Error( const char * filename, int line, const char * format, ... )
{
	Global_error_count++;

	int val;
	va_list args;

	memset( AssertText1, 0, sizeof(AssertText1) );
	memset( AssertText2, 0, sizeof(AssertText2) );

	va_start(args, format);
	vsnprintf(AssertText1, sizeof(AssertText1)-1, format, args);
	va_end(args);

	filename = strrchr(filename, '\\')+1;
	snprintf(AssertText2, sizeof(AssertText2)-1, "Error: %s\r\nFile: %s\r\nLine: %d\r\n", AssertText1, filename, line);
	mprintf(("ERROR: %s\r\nFile: %s\r\nLine: %d\r\n", AssertText1, filename, line));

	Messagebox_active = true;

	gr_activate(0);

#if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
	/* Dump the callstack */
	SCP_DebugCallStack callStack;
	SCP_DumpStack( dynamic_cast< SCP_IDumpHandler* >( &callStack ) );
	
	/* Format the string */
	SCP_string assertString( AssertText1 );
	assertString += "\n";
	assertString += callStack.DumpToString( );
	
	/* Copy to the clipboard */
	dump_text_to_clipboard( assertString.c_str( ) );

	// truncate text
	truncate_message_lines(assertString, Messagebox_lines);

	assertString += "\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
	assertString += "\n\nUse Ok to break into Debugger, Cancel to exit.\n";
	val = MessageBox( NULL, assertString.c_str( ), "Error!", flags | MB_DEFBUTTON2 | MB_OKCANCEL );

#elif defined( SHOW_CALL_STACK )
	dumpBuffer.Clear();
	dumpBuffer.Printf( AssertText2 );
	dumpBuffer.Printf( "\r\n" );
	DumpCallsStack( dumpBuffer ) ;  
	dump_text_to_clipboard(dumpBuffer.buffer);

	// truncate text
	dumpBuffer.TruncateLines(Messagebox_lines);

	dumpBuffer.Printf( "\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
	dumpBuffer.Printf( "\r\n\r\nUse Ok to break into Debugger, Cancel exits.\r\n");

	val = MessageBox(NULL, dumpBuffer.buffer, "Error!", flags | MB_DEFBUTTON2 | MB_OKCANCEL );
#else
	strcat_s(AssertText2,"\r\n\r\nUse Ok to break into Debugger, Cancel exits.\r\n");

	val = MessageBox(NULL, AssertText2, "Error!", flags | MB_DEFBUTTON2 | MB_OKCANCEL );
#endif

	switch (val)
	{
		case IDCANCEL:
			exit(1);

		default:
			Int3();
			break;
	}

	gr_activate(1);

	Messagebox_active = false;
}
void LuaError(struct lua_State *L, char *format, ...)
{
	int val;

	Messagebox_active = true;

	gr_activate(0);

	dumpBuffer.Clear();
	//WMC - if format is set to NULL, assume this is acting as an
	//error handler for Lua.
	if(format == NULL)
	{
		dumpBuffer.Printf("LUA ERROR: %s", lua_tostring(L, -1));
		lua_pop(L, -1);
	}
	else
	{
		va_list args;

		memset(AssertText1, 0, sizeof(AssertText1));
		memset(AssertText2, 0, sizeof(AssertText2));

		va_start(args, format);
		vsnprintf(AssertText1, sizeof(AssertText1)-1, format,args);
		va_end(args);

		dumpBuffer.Printf(AssertText1);
	}

	dumpBuffer.Printf( "\r\n" );
	dumpBuffer.Printf( "\r\n" );

	//WMC - This is virtually worthless.
/*
	dumpBuffer.Printf(Separator);
	dumpBuffer.Printf( "LUA Debug:" );
	dumpBuffer.Printf( "\r\n" );
	dumpBuffer.Printf(Separator);

	lua_Debug ar;
	if(lua_getstack(L, 0, &ar))
	{
		lua_getinfo(L, "nSlu", &ar);
		LuaDebugPrint(ar);
	}
	else
	{
		dumpBuffer.Printf("(No stack debug info)\r\n");
	}
*/
//	TEST CODE

	dumpBuffer.Printf(Separator);
	dumpBuffer.Printf( "ADE Debug:" );
	dumpBuffer.Printf( "\r\n" );
	dumpBuffer.Printf(Separator);
	LuaDebugPrint(Ade_debug_info);
	dumpBuffer.Printf(Separator);

	dumpBuffer.Printf( "\r\n" );
	dumpBuffer.Printf( "\r\n" );

	AssertText2[0] = '\0';
	dumpBuffer.Printf(Separator);
	
	// Get the stack via the debug.traceback() function
	lua_getglobal(L, LUA_DBLIBNAME);

	if (!lua_isnil(L, -1))
	{
		dumpBuffer.Printf( "\r\n" );
		lua_getfield(L, -1, "traceback");
		lua_remove(L, -2);

		if (lua_pcall(L, 0, 1, 0) != 0)
			dumpBuffer.Printf("Error while retrieving stack: %s", lua_tostring(L, -1));
		else
			dumpBuffer.Printf(lua_tostring(L, -1));

		lua_pop(L, 1);
	}
	else
	{
		// If the debug library is nil then fall back to the default debug stack
		dumpBuffer.Printf("LUA Stack:\r\n");
		int i;
		for (i = 0; i < 4; i++) {
			if (debug_stack[i][0] != '\0')
				dumpBuffer.Printf("\t%s\r\n", debug_stack[i]);
		}
	}
	dumpBuffer.Printf( "\r\n" );

	dumpBuffer.Printf(Separator);
	ade_stackdump(L, AssertText2);
	dumpBuffer.Printf( AssertText2 );
	dumpBuffer.Printf( "\r\n" );
	dumpBuffer.Printf(Separator);

	dump_text_to_clipboard(dumpBuffer.buffer);

	// truncate text
	dumpBuffer.TruncateLines(Messagebox_lines);

	dumpBuffer.Printf( "\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
	dumpBuffer.Printf( "\r\n\r\nUse Yes to break into Debugger, No to continue.\r\nand Cancel to Quit");

	val = MessageBox(NULL, dumpBuffer.buffer, "Error!", flags|MB_YESNOCANCEL );

	if (val == IDCANCEL ) {
		exit(1);
	} else if(val == IDYES) {
		Int3();
	}

	gr_activate(1);

	Messagebox_active = false;
}
Example #10
0
void LuaError(struct lua_State* L, char* format, ...)
{
	int val;

	Messagebox_active = true;

	gr_activate(0);

	/*
	va_start(args, format);
	vsprintf(AssertText1,format,args);
	va_end(args);
	*/

	//filename = strrchr(filename, '\\')+1;
	//sprintf(AssertText2,"LuaError: %s\r\nFile: %s\r\nLine: %d\r\n", AssertText1, filename, line );

	dumpBuffer.Clear();
	//WMC - if format is set to NULL, assume this is acting as an
	//error handler for Lua.
	if (format == NULL)
	{
		dumpBuffer.Printf("LUA ERROR: %s", lua_tostring(L, -1));
		lua_pop(L, -1);
	}
	else
	{
		va_list args;
		va_start(args, format);
		vsprintf(AssertText1, format, args);
		dumpBuffer.Printf(AssertText1);
		va_end(args);
	}

	dumpBuffer.Printf("\r\n");
	dumpBuffer.Printf("\r\n");

	//WMC - This is virtually worthless.
	/*
	dumpBuffer.Printf(Separator);
	dumpBuffer.Printf( "LUA Debug:" );
	dumpBuffer.Printf( "\r\n" );
	dumpBuffer.Printf(Separator);
	
	lua_Debug ar;
	if(lua_getstack(L, 0, &ar))
	{
		lua_getinfo(L, "nSlu", &ar);
		LuaDebugPrint(ar);
	}
	else
	{
		dumpBuffer.Printf("(No stack debug info)\r\n");
	}
	*/
	//	TEST CODE

	dumpBuffer.Printf(Separator);
	dumpBuffer.Printf("ADE Debug:");
	dumpBuffer.Printf("\r\n");
	dumpBuffer.Printf(Separator);
	LuaDebugPrint(Ade_debug_info);
	dumpBuffer.Printf(Separator);

	dumpBuffer.Printf("\r\n");
	dumpBuffer.Printf("\r\n");

	AssertText2[0] = '\0';
	dumpBuffer.Printf(Separator);
	dumpBuffer.Printf("LUA Stack:\r\n");
	int i;
	for (i = 0; i < 4; i++)
	{
		if (debug_stack[i][0] != '\0')
			dumpBuffer.Printf("\t%s\r\n", debug_stack[i]);
	}
	dumpBuffer.Printf(Separator);
	ade_stackdump(L, AssertText2);
	dumpBuffer.Printf(AssertText2);
	dumpBuffer.Printf("\r\n");
	dumpBuffer.Printf(Separator);

	dump_text_to_clipboard(dumpBuffer.buffer);

	dumpBuffer.Printf("\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n");
	dumpBuffer.Printf("\r\n\r\nUse Yes to break into Debugger, No to continue.\r\nand Cancel to Quit");

	val = MessageBox(NULL, dumpBuffer.buffer, "Error!", flags | MB_YESNOCANCEL);

	if (val == IDCANCEL)
	{
		exit(1);
	}
	else if (val == IDYES)
	{
		Int3();
	}

	gr_activate(1);

	Messagebox_active = false;
}
Example #11
0
void _cdecl WinAssert(char* text, char* filename, int linenum)
{
	int val;

	// this stuff migt be really useful for solving bug reports and user errors. We should output it! 
	mprintf(("ASSERTION: \"%s\" at %s:%d\n", text, strrchr(filename, '\\') + 1, linenum));

	if (Cmdline_nowarn)
		return;

	Messagebox_active = true;

	gr_activate(0);

	filename = strrchr(filename, '\\') + 1;
	sprintf(AssertText1, "Assert: %s\r\nFile: %s\r\nLine: %d\r\n", text, filename, linenum);

#if defined( SHOW_CALL_STACK ) && defined( PDB_DEBUGGING )
	/* Dump the callstack */
	SCP_DebugCallStack callStack;
	SCP_DumpStack( dynamic_cast< SCP_IDumpHandler* >( &callStack ) );

	/* Format the string */
	std::string assertString( AssertText1 );
	assertString += "\n";
	assertString += callStack.DumpToString( );

	/* Copy to the clipboard */
	dump_text_to_clipboard( assertString.c_str( ) );

	assertString += "\n[ This info is in the clipboard so you can paste it somewhere now ]\n";
	assertString += "\n\nUse Ok to break into Debugger, Cancel to exit.\n";
	val = MessageBox( NULL, assertString.c_str( ), "Assertion Failed!", MB_OKCANCEL | flags );

#elif defined( SHOW_CALL_STACK )
	dumpBuffer.Clear();
	dumpBuffer.Printf( AssertText1 );
	dumpBuffer.Printf( "\r\n" );
	DumpCallsStack( dumpBuffer ) ;
	dump_text_to_clipboard(dumpBuffer.buffer);

	dumpBuffer.Printf( "\r\n[ This info is in the clipboard so you can paste it somewhere now ]\r\n" );
	dumpBuffer.Printf( "\r\n\r\nUse Ok to break into Debugger, Cancel to exit.\r\n");

	val = MessageBox(NULL, dumpBuffer.buffer, "Assertion Failed!", MB_OKCANCEL|flags );
#else
	val = MessageBox(NULL, AssertText1, "Assertion Failed!", MB_OKCANCEL | flags);
#endif

	if (val == IDCANCEL)
		exit(1);
#ifndef INTERPLAYQA
	Int3();
#else
	AsmInt3();
#endif

	gr_activate(1);

	Messagebox_active = false;
}