hello world

This commit is contained in:
Timothee 'TTimo' Besset
2011-11-22 15:28:15 -06:00
commit fb1609f554
2155 changed files with 1017022 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../../sys/win32/rc/debugger_resource.h"
#include "DebuggerApp.h"
/*
================
rvDebuggerApp::rvDebuggerApp
================
*/
rvDebuggerApp::rvDebuggerApp ( ) :
mOptions ( "Software\\id Software\\DOOM3\\Tools\\Debugger" )
{
mInstance = NULL;
mDebuggerWindow = NULL;
mAccelerators = NULL;
}
/*
================
rvDebuggerApp::~rvDebuggerApp
================
*/
rvDebuggerApp::~rvDebuggerApp ( )
{
if ( mAccelerators )
{
DestroyAcceleratorTable ( mAccelerators );
}
}
/*
================
rvDebuggerApp::Initialize
Initializes the debugger application by creating the debugger window
================
*/
bool rvDebuggerApp::Initialize ( HINSTANCE instance )
{
INITCOMMONCONTROLSEX ex;
ex.dwICC = ICC_USEREX_CLASSES | ICC_LISTVIEW_CLASSES | ICC_WIN95_CLASSES;
ex.dwSize = sizeof(INITCOMMONCONTROLSEX);
mInstance = instance;
mOptions.Load ( );
mDebuggerWindow = new rvDebuggerWindow;
if ( !mDebuggerWindow->Create ( instance ) )
{
delete mDebuggerWindow;
return false;
}
// Initialize the network connection for the debugger
if ( !mClient.Initialize ( ) )
{
return false;
}
mAccelerators = LoadAccelerators ( mInstance, MAKEINTRESOURCE(IDR_DBG_ACCELERATORS) );
return true;
}
/*
================
rvDebuggerApp::ProcessWindowMessages
Process windows messages
================
*/
bool rvDebuggerApp::ProcessWindowMessages ( void )
{
MSG msg;
while ( PeekMessage ( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if ( !GetMessage (&msg, NULL, 0, 0) )
{
return false;
}
if ( !TranslateAccelerator ( &msg ) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return true;
}
/*
================
rvDebuggerApp::TranslateAccelerator
Translate any accelerators destined for this window
================
*/
bool rvDebuggerApp::TranslateAccelerator ( LPMSG msg )
{
if ( mDebuggerWindow && ::TranslateAccelerator ( mDebuggerWindow->GetWindow(), mAccelerators, msg ) )
{
return true;
}
return false;
}
/*
================
rvDebuggerApp::Run
Main Loop for the debugger application
================
*/
int rvDebuggerApp::Run ( void )
{
// Main message loop:
while ( ProcessWindowMessages ( ) )
{
mClient.ProcessMessages ( );
Sleep ( 0 );
}
mClient.Shutdown ( );
mOptions.Save ( );
delete mDebuggerWindow;
return 1;
}

View File

@@ -0,0 +1,108 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef DEBUGGERAPP_H_
#define DEBUGGERAPP_H_
#include "../../sys/win32/win_local.h"
#include "../../framework/sync/Msg.h"
#ifndef REGISTRYOPTIONS_H_
#include "../common/RegistryOptions.h"
#endif
#ifndef DEBUGGERWINDOW_H_
#include "DebuggerWindow.h"
#endif
#ifndef DEBUGGERMESSAGES_H_
#include "DebuggerMessages.h"
#endif
#ifndef DEBUGGERCLIENT_H_
#include "DebuggerClient.h"
#endif
// These were changed to static by ID so to make it easy we just throw them
// in this header
const int MAX_MSGLEN = 1400;
class rvDebuggerApp
{
public:
rvDebuggerApp ( );
bool Initialize ( HINSTANCE hInstance );
int Run ( void );
rvRegistryOptions& GetOptions ( void );
rvDebuggerClient& GetClient ( void );
rvDebuggerWindow& GetWindow ( void );
HINSTANCE GetInstance ( void );
bool TranslateAccelerator ( LPMSG msg );
protected:
rvRegistryOptions mOptions;
rvDebuggerWindow* mDebuggerWindow;
HINSTANCE mInstance;
rvDebuggerClient mClient;
HACCEL mAccelerators;
private:
bool ProcessNetMessages ( void );
bool ProcessWindowMessages ( void );
};
ID_INLINE HINSTANCE rvDebuggerApp::GetInstance ( void )
{
return mInstance;
}
ID_INLINE rvDebuggerClient& rvDebuggerApp::GetClient ( void )
{
return mClient;
}
ID_INLINE rvRegistryOptions& rvDebuggerApp::GetOptions ( void )
{
return mOptions;
}
ID_INLINE rvDebuggerWindow& rvDebuggerApp::GetWindow ( void )
{
assert ( mDebuggerWindow );
return *mDebuggerWindow;
}
extern rvDebuggerApp gDebuggerApp;
#endif // DEBUGGERAPP_H_

View File

@@ -0,0 +1,62 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "DebuggerApp.h"
#include "DebuggerBreakpoint.h"
int rvDebuggerBreakpoint::mNextID = 1;
rvDebuggerBreakpoint::rvDebuggerBreakpoint ( const char* filename, int linenumber, int id )
{
mFilename = filename;
mLineNumber = linenumber;
mEnabled = true;
if ( id == -1 )
{
mID = mNextID++;
}
else
{
mID = id;
}
}
rvDebuggerBreakpoint::rvDebuggerBreakpoint ( rvDebuggerBreakpoint& bp )
{
mFilename = bp.mFilename;
mEnabled = bp.mEnabled;
mLineNumber = bp.mLineNumber;
}
rvDebuggerBreakpoint::~rvDebuggerBreakpoint ( void )
{
}

View File

@@ -0,0 +1,70 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef DEBUGGERBREAKPOINT_H_
#define DEBUGGERBREAKPOINT_H_
class rvDebuggerBreakpoint
{
public:
rvDebuggerBreakpoint ( const char* filename, int linenumber, int id = -1 );
rvDebuggerBreakpoint ( rvDebuggerBreakpoint& bp );
~rvDebuggerBreakpoint ( void );
const char* GetFilename ( void );
int GetLineNumber ( void );
int GetID ( void );
protected:
bool mEnabled;
int mID;
int mLineNumber;
idStr mFilename;
private:
static int mNextID;
};
ID_INLINE const char* rvDebuggerBreakpoint::GetFilename ( void )
{
return mFilename;
}
ID_INLINE int rvDebuggerBreakpoint::GetLineNumber ( void )
{
return mLineNumber;
}
ID_INLINE int rvDebuggerBreakpoint::GetID ( void )
{
return mID;
}
#endif // DEBUGGERBREAKPOINT_H_

View File

@@ -0,0 +1,586 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "DebuggerApp.h"
/*
================
rvDebuggerClient::rvDebuggerClient
================
*/
rvDebuggerClient::rvDebuggerClient ( )
{
mConnected = false;
mWaitFor = DBMSG_UNKNOWN;
}
/*
================
rvDebuggerClient::~rvDebuggerClient
================
*/
rvDebuggerClient::~rvDebuggerClient ( )
{
ClearBreakpoints ( );
ClearCallstack ( );
ClearThreads ( );
}
/*
================
rvDebuggerClient::Initialize
Initialize the debugger client
================
*/
bool rvDebuggerClient::Initialize ( void )
{
// Nothing else can run with the debugger
com_editors = EDITOR_DEBUGGER;
// Initialize the network connection
if ( !mPort.InitForPort ( 27981 ) )
{
return false;
}
// Server must be running on the local host on port 28980
Sys_StringToNetAdr ( "localhost", &mServerAdrt, true );
mServerAdr.port = 27980;
// Attempt to let the server know we are here. The server may not be running so this
// message will just get ignored.
SendMessage ( DBMSG_CONNECT );
return true;
}
/*
================
rvDebuggerClient::Shutdown
Shutdown the debugger client and let the debugger server
know we are shutting down
================
*/
void rvDebuggerClient::Shutdown ( void )
{
if ( mConnected )
{
SendMessage ( DBMSG_DISCONNECT );
mConnected = false;
}
}
/*
================
rvDebuggerClient::ProcessMessages
Process all incomding messages from the debugger server
================
*/
bool rvDebuggerClient::ProcessMessages ( void )
{
netadr_t adrFrom;
msg_t msg;
byte buffer[MAX_MSGLEN];
MSG_Init( &msg, buffer, sizeof( buffer ) );
// Check for pending udp packets on the debugger port
while ( mPort.GetPacket ( adrFrom, msg.data, msg.cursize, msg.maxsize ) )
{
unsigned short command;
// Only accept packets from the debugger server for security reasons
if ( !Sys_CompareNetAdrBase ( adrFrom, mServerAdr ) )
{
continue;
}
command = (unsigned short) MSG_ReadShort ( &msg );
// Is this what we are waiting for?
if ( command == mWaitFor )
{
mWaitFor = DBMSG_UNKNOWN;
}
switch ( command )
{
case DBMSG_CONNECT:
mConnected = true;
SendMessage ( DBMSG_CONNECTED );
SendBreakpoints ( );
break;
case DBMSG_CONNECTED:
mConnected = true;
SendBreakpoints ( );
break;
case DBMSG_DISCONNECT:
mConnected = false;
break;
case DBMSG_BREAK:
HandleBreak ( &msg );
break;
// Callstack being send to the client
case DBMSG_INSPECTCALLSTACK:
HandleInspectCallstack ( &msg );
break;
// Thread list is being sent to the client
case DBMSG_INSPECTTHREADS:
HandleInspectThreads ( &msg );
break;
case DBMSG_INSPECTVARIABLE:
HandleInspectVariable ( &msg );
break;
}
// Give the window a chance to process the message
msg.readcount = 0;
msg.bit = 0;
gDebuggerApp.GetWindow().ProcessNetMessage ( &msg );
}
return true;
}
/*
================
rvDebuggerClient::HandleBreak
Handle the DBMSG_BREAK message send from the server. This message is handled
by caching the file and linenumber where the break occured.
================
*/
void rvDebuggerClient::HandleBreak ( msg_t* msg )
{
char filename[MAX_PATH];
mBreak = true;
// Line number
mBreakLineNumber = MSG_ReadLong ( msg );
// Filename
MSG_ReadString ( msg, filename, MAX_PATH );
mBreakFilename = filename;
// Clear the variables
mVariables.Clear ( );
// Request the callstack and threads
SendMessage ( DBMSG_INSPECTCALLSTACK );
WaitFor ( DBMSG_INSPECTCALLSTACK, 2000 );
SendMessage ( DBMSG_INSPECTTHREADS );
WaitFor ( DBMSG_INSPECTTHREADS, 2000 );
}
/*
================
rvDebuggerClient::InspectVariable
Instructs the client to inspect the given variable at the given callstack depth. The
variable is inspected by sending a DBMSG_INSPECTVARIABLE message to the server which
will in turn respond back to the client with the variable value
================
*/
void rvDebuggerClient::InspectVariable ( const char* name, int callstackDepth )
{
msg_t msg;
byte buffer[MAX_MSGLEN];
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTVARIABLE );
MSG_WriteShort ( &msg, (short)(mCallstack.Num()-callstackDepth) );
MSG_WriteString ( &msg, name );
SendPacket ( msg.data, msg.cursize );
}
/*
================
rvDebuggerClient::HandleInspectCallstack
Handle the message DBMSG_INSPECTCALLSTACK being sent from the server. This message
is handled by adding the callstack entries to a list for later lookup.
================
*/
void rvDebuggerClient::HandleInspectCallstack ( msg_t* msg )
{
int depth;
ClearCallstack ( );
// Read all of the callstack entries specfied in the message
for ( depth = (short)MSG_ReadShort ( msg ) ; depth > 0; depth -- )
{
rvDebuggerCallstack* entry = new rvDebuggerCallstack;
char temp[1024];
// Function name
MSG_ReadString ( msg, temp, 1024 );
entry->mFunction = temp;
// Filename
MSG_ReadString ( msg, temp, 1024 );
entry->mFilename = temp;
// Line Number
entry->mLineNumber = MSG_ReadLong ( msg );
// Add to list
mCallstack.Append ( entry );
}
}
/*
================
rvDebuggerClient::HandleInspectThreads
Handle the message DBMSG_INSPECTTHREADS being sent from the server. This message
is handled by adding the list of threads to a list for later lookup.
================
*/
void rvDebuggerClient::HandleInspectThreads ( msg_t* msg )
{
int count;
ClearThreads ( );
// Loop over the number of threads in the message
for ( count = (short)MSG_ReadShort ( msg ) ; count > 0; count -- )
{
rvDebuggerThread* entry = new rvDebuggerThread;
char temp[1024];
// Thread name
MSG_ReadString ( msg, temp, 1024 );
entry->mName = temp;
// Thread ID
entry->mID = MSG_ReadLong ( msg );
// Thread state
entry->mCurrent = MSG_ReadBits ( msg, 1 ) ? true : false;
entry->mDoneProcessing = MSG_ReadBits ( msg, 1 ) ? true : false;
entry->mWaiting = MSG_ReadBits ( msg, 1 ) ? true : false;
entry->mDying = MSG_ReadBits ( msg, 1 ) ? true : false;
// Add thread to list
mThreads.Append ( entry );
}
}
/*
================
rvDebuggerClient::HandleInspectVariable
Handle the message DBMSG_INSPECTVARIABLE being sent from the server. This message
is handled by adding the inspected variable to a dictionary for later lookup
================
*/
void rvDebuggerClient::HandleInspectVariable ( msg_t* msg )
{
char var[1024];
char value[1024];
int callDepth;
callDepth = (short)MSG_ReadShort ( msg );
MSG_ReadString ( msg, var, 1024 );
MSG_ReadString ( msg, value, 1024 );
mVariables.Set ( va("%d:%s", mCallstack.Num()-callDepth, var), value );
}
/*
================
rvDebuggerClient::WaitFor
Waits the given amount of time for the specified message to be received by the
debugger client.
================
*/
bool rvDebuggerClient::WaitFor ( EDebuggerMessage msg, int time )
{
int start;
// Cant wait if not connected
if ( !mConnected )
{
return false;
}
start = Sys_Milliseconds ( );
mWaitFor = msg;
while ( mWaitFor != DBMSG_UNKNOWN && Sys_Milliseconds()-start < time )
{
ProcessMessages ( );
Sleep ( 0 );
}
if ( mWaitFor != DBMSG_UNKNOWN )
{
mWaitFor = DBMSG_UNKNOWN;
return false;
}
return true;
}
/*
================
rvDebuggerClient::FindBreakpoint
Searches for a breakpoint that maches the given filename and linenumber
================
*/
rvDebuggerBreakpoint* rvDebuggerClient::FindBreakpoint ( const char* filename, int linenumber )
{
int i;
for ( i = 0; i < mBreakpoints.Num(); i ++ )
{
rvDebuggerBreakpoint* bp = mBreakpoints[i];
if ( linenumber == bp->GetLineNumber ( ) && !idStr::Icmp ( bp->GetFilename ( ), filename ) )
{
return bp;
}
}
return NULL;
}
/*
================
rvDebuggerClient::ClearBreakpoints
Removes all breakpoints from the client and server
================
*/
void rvDebuggerClient::ClearBreakpoints ( void )
{
int i;
for ( i = 0; i < GetBreakpointCount(); i ++ )
{
rvDebuggerBreakpoint* bp = mBreakpoints[i];
assert ( bp );
SendRemoveBreakpoint ( *bp );
delete bp;
}
mBreakpoints.Clear ( );
}
/*
================
rvDebuggerClient::AddBreakpoint
Adds a breakpoint to the client and server with the give nfilename and linenumber
================
*/
int rvDebuggerClient::AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly )
{
int index = mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber ) );
SendAddBreakpoint ( *mBreakpoints[index] );
return index;
}
/*
================
rvDebuggerClient::RemoveBreakpoint
Removes the breakpoint with the given ID from the client and server
================
*/
bool rvDebuggerClient::RemoveBreakpoint ( int bpID )
{
int index;
for ( index = 0; index < GetBreakpointCount(); index ++ )
{
if ( mBreakpoints[index]->GetID ( ) == bpID )
{
SendRemoveBreakpoint ( *mBreakpoints[index] );
delete mBreakpoints[index];
mBreakpoints.RemoveIndex ( index );
return true;
}
}
return false;
}
/*
================
rvDebuggerClient::SendMessage
Send a message with no data to the debugger server
================
*/
void rvDebuggerClient::SendMessage ( EDebuggerMessage dbmsg )
{
msg_t msg;
byte buffer[MAX_MSGLEN];
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)dbmsg );
SendPacket ( msg.data, msg.cursize );
}
/*
================
rvDebuggerClient::SendBreakpoints
Send all breakpoints to the debugger server
================
*/
void rvDebuggerClient::SendBreakpoints ( void )
{
int i;
if ( !mConnected )
{
return;
}
// Send all the breakpoints to the server
for ( i = 0; i < mBreakpoints.Num(); i ++ )
{
SendAddBreakpoint ( *mBreakpoints[i] );
}
}
/*
================
rvDebuggerClient::SendAddBreakpoint
Send an individual breakpoint over to the debugger server
================
*/
void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOnly )
{
msg_t msg;
byte buffer[MAX_MSGLEN];
if ( !mConnected )
{
return;
}
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)DBMSG_ADDBREAKPOINT );
MSG_WriteBits ( &msg, onceOnly?1:0, 1 );
MSG_WriteLong ( &msg, (unsigned long) bp.GetLineNumber ( ) );
MSG_WriteLong ( &msg, bp.GetID ( ) );
MSG_WriteString ( &msg, bp.GetFilename() );
SendPacket ( msg.data, msg.cursize );
}
/*
================
rvDebuggerClient::SendRemoveBreakpoint
Sends a remove breakpoint message to the debugger server
================
*/
void rvDebuggerClient::SendRemoveBreakpoint ( rvDebuggerBreakpoint& bp )
{
msg_t msg;
byte buffer[MAX_MSGLEN];
if ( !mConnected )
{
return;
}
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)DBMSG_REMOVEBREAKPOINT );
MSG_WriteLong ( &msg, bp.GetID() );
SendPacket ( msg.data, msg.cursize );
}
/*
================
rvDebuggerClient::ClearCallstack
Clear all callstack entries
================
*/
void rvDebuggerClient::ClearCallstack ( void )
{
int depth;
for ( depth = 0; depth < mCallstack.Num(); depth ++ )
{
delete mCallstack[depth];
}
mCallstack.Clear ( );
}
/*
================
rvDebuggerClient::ClearThreads
Clear all thread entries
================
*/
void rvDebuggerClient::ClearThreads ( void )
{
int i;
for ( i = 0; i < mThreads.Num(); i ++ )
{
delete mThreads[i];
}
mThreads.Clear ( );
}

View File

@@ -0,0 +1,289 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef DEBUGGERCLIENT_H_
#define DEBUGGERCLIENT_H_
class rvDebuggerCallstack
{
public:
idStr mFilename;
int mLineNumber;
idStr mFunction;
};
class rvDebuggerThread
{
public:
idStr mName;
int mID;
bool mCurrent;
bool mDying;
bool mWaiting;
bool mDoneProcessing;
};
#ifndef DEBUGGERBREAKPOINT_H_
#include "DebuggerBreakpoint.h"
#endif
typedef idList<rvDebuggerCallstack*> rvDebuggerCallstackList;
typedef idList<rvDebuggerThread*> rvDebuggerThreadList;
typedef idList<rvDebuggerBreakpoint*> rvDebuggerBreakpointList;
class rvDebuggerClient
{
public:
rvDebuggerClient ( );
~rvDebuggerClient ( );
bool Initialize ( void );
void Shutdown ( void );
bool ProcessMessages ( void );
bool WaitFor ( EDebuggerMessage msg, int time );
bool IsConnected ( void );
bool IsStopped ( void );
int GetActiveBreakpointID ( void );
const char* GetBreakFilename ( void );
int GetBreakLineNumber ( void );
rvDebuggerCallstackList& GetCallstack ( void );
rvDebuggerThreadList& GetThreads ( void );
const char* GetVariableValue ( const char* name, int stackDepth );
void InspectVariable ( const char* name, int callstackDepth );
void Break ( void );
void Resume ( void );
void StepInto ( void );
void StepOver ( void );
// Breakpoints
int AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly = false );
bool RemoveBreakpoint ( int bpID );
void ClearBreakpoints ( void );
int GetBreakpointCount ( void );
rvDebuggerBreakpoint* GetBreakpoint ( int index );
rvDebuggerBreakpoint* FindBreakpoint ( const char* filename, int linenumber );
protected:
void SendMessage ( EDebuggerMessage dbmsg );
void SendBreakpoints ( void );
void SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOnly = false );
void SendRemoveBreakpoint ( rvDebuggerBreakpoint& bp );
void SendPacket ( void* data, int datasize );
bool mConnected;
netadr_t mServerAdr;
idPort mPort;
bool mBreak;
int mBreakID;
int mBreakLineNumber;
idStr mBreakFilename;
idDict mVariables;
rvDebuggerCallstackList mCallstack;
rvDebuggerThreadList mThreads;
rvDebuggerBreakpointList mBreakpoints;
EDebuggerMessage mWaitFor;
private:
void ClearCallstack ( void );
void ClearThreads ( void );
void UpdateWatches ( void );
// Network message handlers
void HandleBreak ( msg_t* msg );
void HandleInspectCallstack ( msg_t* msg );
void HandleInspectThreads ( msg_t* msg );
void HandleInspectVariable ( msg_t* msg );
};
/*
================
rvDebuggerClient::IsConnected
================
*/
ID_INLINE bool rvDebuggerClient::IsConnected ( void )
{
return mConnected;
}
/*
================
rvDebuggerClient::IsStopped
================
*/
ID_INLINE bool rvDebuggerClient::IsStopped ( void )
{
return mBreak;
}
/*
================
rvDebuggerClient::GetActiveBreakpointID
================
*/
ID_INLINE int rvDebuggerClient::GetActiveBreakpointID ( void )
{
return mBreakID;
}
/*
================
rvDebuggerClient::GetBreakFilename
================
*/
ID_INLINE const char* rvDebuggerClient::GetBreakFilename ( void )
{
return mBreakFilename;
}
/*
================
rvDebuggerClient::GetBreakLineNumber
================
*/
ID_INLINE int rvDebuggerClient::GetBreakLineNumber ( void )
{
return mBreakLineNumber;
}
/*
================
rvDebuggerClient::GetCallstack
================
*/
ID_INLINE rvDebuggerCallstackList& rvDebuggerClient::GetCallstack ( void )
{
return mCallstack;
}
/*
================
rvDebuggerClient::GetThreads
================
*/
ID_INLINE rvDebuggerThreadList& rvDebuggerClient::GetThreads ( void )
{
return mThreads;
}
/*
================
rvDebuggerClient::GetVariableValue
================
*/
ID_INLINE const char* rvDebuggerClient::GetVariableValue ( const char* var, int stackDepth )
{
return mVariables.GetString ( va("%d:%s",stackDepth,var), "" );
}
/*
================
rvDebuggerClient::GetBreakpointCount
================
*/
ID_INLINE int rvDebuggerClient::GetBreakpointCount ( void )
{
return mBreakpoints.Num ( );
}
/*
================
rvDebuggerClient::GetBreakpoint
================
*/
ID_INLINE rvDebuggerBreakpoint* rvDebuggerClient::GetBreakpoint ( int index )
{
return mBreakpoints[index];
}
/*
================
rvDebuggerClient::Break
================
*/
ID_INLINE void rvDebuggerClient::Break ( void )
{
SendMessage ( DBMSG_BREAK );
}
/*
================
rvDebuggerClient::Resume
================
*/
ID_INLINE void rvDebuggerClient::Resume ( void )
{
mBreak = false;
SendMessage ( DBMSG_RESUME );
}
/*
================
rvDebuggerClient::StepOver
================
*/
ID_INLINE void rvDebuggerClient::StepOver ( void )
{
mBreak = false;
SendMessage ( DBMSG_STEPOVER );
}
/*
================
rvDebuggerClient::StepInto
================
*/
ID_INLINE void rvDebuggerClient::StepInto ( void )
{
mBreak = false;
SendMessage ( DBMSG_STEPINTO );
}
/*
================
rvDebuggerClient::SendPacket
================
*/
ID_INLINE void rvDebuggerClient::SendPacket ( void* data, int size )
{
mPort.SendPacket ( mServerAdr, data, size );
}
#endif // DEBUGGERCLIENT_H_

View File

@@ -0,0 +1,106 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../../sys/win32/rc/debugger_resource.h"
#include "DebuggerApp.h"
#include "DebuggerFindDlg.h"
char rvDebuggerFindDlg::mFindText[ 256 ];
/*
================
rvDebuggerFindDlg::rvDebuggerFindDlg
================
*/
rvDebuggerFindDlg::rvDebuggerFindDlg ( void )
{
}
/*
================
rvDebuggerFindDlg::DoModal
Launch the dialog
================
*/
bool rvDebuggerFindDlg::DoModal ( rvDebuggerWindow* parent )
{
if ( DialogBoxParam ( parent->GetInstance(), MAKEINTRESOURCE(IDD_DBG_FIND), parent->GetWindow(), DlgProc, (LONG)this ) )
{
return true;
}
return false;
}
/*
================
rvrvDebuggerFindDlg::DlgProc
Dialog Procedure for the find dialog
================
*/
INT_PTR CALLBACK rvDebuggerFindDlg::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
rvDebuggerFindDlg* dlg = (rvDebuggerFindDlg*) GetWindowLong ( wnd, GWL_USERDATA );
switch ( msg )
{
case WM_CLOSE:
EndDialog ( wnd, 0 );
break;
case WM_INITDIALOG:
dlg = (rvDebuggerFindDlg*) lparam;
SetWindowLong ( wnd, GWL_USERDATA, (LONG) dlg );
dlg->mWnd = wnd;
SetWindowText ( GetDlgItem ( dlg->mWnd, IDC_DBG_FIND ), dlg->mFindText );
return TRUE;
case WM_COMMAND:
switch ( LOWORD(wparam) )
{
case IDOK:
{
GetWindowText ( GetDlgItem ( wnd, IDC_DBG_FIND ), dlg->mFindText, sizeof( dlg->mFindText ) - 1 );
EndDialog ( wnd, 1 );
break;
}
case IDCANCEL:
EndDialog ( wnd, 0 );
break;
}
break;
}
return FALSE;
}

View File

@@ -0,0 +1,59 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef DEBUGGERFINDDLG_H_
#define DEBUGGERFINDDLG_H_
class rvDebuggerWindow;
class rvDebuggerFindDlg
{
public:
rvDebuggerFindDlg ( );
bool DoModal ( rvDebuggerWindow* window );
const char* GetFindText ( void );
protected:
HWND mWnd;
private:
static char mFindText[ 256 ];
static INT_PTR CALLBACK DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
};
ID_INLINE const char* rvDebuggerFindDlg::GetFindText ( void )
{
return mFindText;
}
#endif // DEBUGGERFINDDLG_H_

View File

@@ -0,0 +1,51 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef DEBUGGERMESSAGES_H_
#define DEBUGGERMESSAGES_H_
enum EDebuggerMessage
{
DBMSG_UNKNOWN,
DBMSG_CONNECT,
DBMSG_CONNECTED,
DBMSG_DISCONNECT,
DBMSG_ADDBREAKPOINT,
DBMSG_REMOVEBREAKPOINT,
DBMSG_HITBREAKPOINT,
DBMSG_RESUME,
DBMSG_RESUMED,
DBMSG_BREAK,
DBMSG_PRINT,
DBMSG_INSPECTVARIABLE,
DBMSG_INSPECTCALLSTACK,
DBMSG_INSPECTTHREADS,
DBMSG_STEPOVER,
DBMSG_STEPINTO,
};
#endif // DEBUGGER_MESSAGES_H_

View File

@@ -0,0 +1,267 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../../sys/win32/rc/debugger_resource.h"
#include "DebuggerApp.h"
#include "DebuggerQuickWatchDlg.h"
/*
================
rvDebuggerQuickWatchDlg::rvDebuggerQuickWatchDlg
================
*/
rvDebuggerQuickWatchDlg::rvDebuggerQuickWatchDlg ( void )
{
}
/*
================
rvDebuggerQuickWatchDlg::DoModal
Launch the dialog
================
*/
bool rvDebuggerQuickWatchDlg::DoModal ( rvDebuggerWindow* window, int callstackDepth, const char* variable )
{
mCallstackDepth = callstackDepth;
mDebuggerWindow = window;
mVariable = variable?variable:"";
DialogBoxParam ( window->GetInstance(), MAKEINTRESOURCE(IDD_DBG_QUICKWATCH), window->GetWindow(), DlgProc, (LONG)this );
return true;
}
/*
================
rvDebuggerQuickWatchDlg::DlgProc
Dialog Procedure for the quick watch dialog
================
*/
INT_PTR CALLBACK rvDebuggerQuickWatchDlg::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
rvDebuggerQuickWatchDlg* dlg = (rvDebuggerQuickWatchDlg*) GetWindowLong ( wnd, GWL_USERDATA );
switch ( msg )
{
case WM_GETMINMAXINFO:
{
MINMAXINFO* mmi = (MINMAXINFO*)lparam;
mmi->ptMinTrackSize.x = 300;
mmi->ptMinTrackSize.y = 200;
break;
}
case WM_CLOSE:
gDebuggerApp.GetOptions().SetWindowPlacement ( "wp_quickwatch", wnd );
gDebuggerApp.GetOptions().SetColumnWidths ( "cw_quickwatch", GetDlgItem ( wnd, IDC_DBG_CURVALUE ) );
EndDialog ( wnd, 0 );
break;
case WM_SIZE:
{
RECT client;
RECT button;
GetClientRect ( wnd, &client );
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_RECALC ), &button );
ScreenToClient ( wnd, (POINT*)&button );
ScreenToClient ( wnd, (POINT*)&button.right );
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_RECALC ), client.right - dlg->mButtonFromRight, button.top, button.right-button.left,button.bottom-button.top, TRUE );
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_CLOSE ), &button );
ScreenToClient ( wnd, (POINT*)&button );
ScreenToClient ( wnd, (POINT*)&button.right );
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_CLOSE ), client.right - dlg->mButtonFromRight, button.top, button.right-button.left,button.bottom-button.top, TRUE );
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_ADDWATCH ), &button );
ScreenToClient ( wnd, (POINT*)&button );
ScreenToClient ( wnd, (POINT*)&button.right );
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_ADDWATCH ), client.right - dlg->mButtonFromRight, button.top, button.right-button.left,button.bottom-button.top, TRUE );
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), &button );
ScreenToClient ( wnd, (POINT*)&button );
ScreenToClient ( wnd, (POINT*)&button.right );
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), button.left, button.top, client.right-button.left-dlg->mEditFromRight, button.bottom-button.top, TRUE );
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), &button );
ScreenToClient ( wnd, (POINT*)&button );
ScreenToClient ( wnd, (POINT*)&button.right );
MoveWindow ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), button.left, button.top, client.right-button.left-dlg->mEditFromRight, client.bottom-button.top - dlg->mEditFromBottom, TRUE );
break;
}
case WM_INITDIALOG:
{
RECT client;
RECT button;
// Attach the dialog class pointer to the window
dlg = (rvDebuggerQuickWatchDlg*) lparam;
SetWindowLong ( wnd, GWL_USERDATA, lparam );
dlg->mWnd = wnd;
GetClientRect ( wnd, &client );
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_RECALC ), &button );
ScreenToClient ( wnd, (POINT*)&button );
dlg->mButtonFromRight = client.right - button.left;
GetWindowRect ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), &button );
ScreenToClient ( wnd, (POINT*)&button.right );
dlg->mEditFromRight = client.right - button.right;
dlg->mEditFromBottom = client.bottom - button.bottom;
// Disable the value controls until a variable is entered
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_ADDWATCH ), false );
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_RECALC ), false );
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), false );
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_CURVALUE_STATIC ), false );
// Add the columns to the list control
LVCOLUMN col;
col.mask = LVCF_WIDTH|LVCF_TEXT;
col.cx = 100;
col.pszText = "Name";
ListView_InsertColumn ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), 0, &col );
col.cx = 150;
col.pszText = "Value";
ListView_InsertColumn ( GetDlgItem ( wnd, IDC_DBG_CURVALUE ), 1, &col );
// Set the initial variable if one was given
if ( dlg->mVariable.Length() )
{
dlg->SetVariable ( dlg->mVariable, true );
SetWindowText( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), dlg->mVariable );
}
gDebuggerApp.GetOptions().GetWindowPlacement ( "wp_quickwatch", wnd );
gDebuggerApp.GetOptions().GetColumnWidths ( "cw_quickwatch", GetDlgItem ( wnd, IDC_DBG_CURVALUE ) );
return TRUE;
}
case WM_COMMAND:
switch ( LOWORD(wparam) )
{
case IDC_DBG_CLOSE:
SendMessage ( wnd, WM_CLOSE, 0, 0 );
break;
case IDC_DBG_VARIABLE:
// When the variable text changes to something other than empty
// we can enable the addwatch and recalc buttons
if ( HIWORD(wparam) == EN_CHANGE )
{
bool enable = GetWindowTextLength ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ) )?true:false;
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_ADDWATCH ), enable );
EnableWindow ( GetDlgItem ( wnd, IDC_DBG_RECALC ), enable );
}
break;
case IDC_DBG_ADDWATCH:
{
char varname[1024];
GetWindowText ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), varname, 1023 );
dlg->mDebuggerWindow->AddWatch ( varname );
break;
}
case IDC_DBG_RECALC:
{
char varname[1024];
GetWindowText ( GetDlgItem ( wnd, IDC_DBG_VARIABLE ), varname, 1023 );
dlg->SetVariable ( varname );
break;
}
}
break;
}
return FALSE;
}
/*
================
rvDebuggerQuickWatchDlg::SetVariable
Sets the current variable being inspected
================
*/
void rvDebuggerQuickWatchDlg::SetVariable ( const char* varname, bool force )
{
// See if the variable has changed
if ( !force && !mVariable.Icmp ( varname ) )
{
return;
}
// Throw up a wait cursor
SetCursor ( LoadCursor ( NULL, IDC_WAIT ) );
// Clear the current value list control
ListView_DeleteAllItems ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE ) );
// Get the value of the new variable
gDebuggerApp.GetClient().InspectVariable ( varname, mCallstackDepth );
// Wait for the variable value to be sent over from the debugger server
if ( !gDebuggerApp.GetClient().WaitFor ( DBMSG_INSPECTVARIABLE, 2500 ) )
{
return;
}
// Make sure we got the value of the variable
if ( !gDebuggerApp.GetClient().GetVariableValue(varname, mCallstackDepth)[0] )
{
return;
}
// Enable the windows that display the current value
mVariable = varname;
EnableWindow ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE ), true );
EnableWindow ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE_STATIC ), true );
// Add the variablae value to the list control
LVITEM item;
item.mask = LVIF_TEXT;
item.pszText = (LPSTR)varname;
item.iItem = 0;
item.iSubItem = 0;
ListView_InsertItem ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE ), &item );
ListView_SetItemText ( GetDlgItem ( mWnd, IDC_DBG_CURVALUE ), 0, 1, (LPSTR)gDebuggerApp.GetClient().GetVariableValue(varname,mCallstackDepth) );
// Give focus back to the variable edit control and set the cursor back to an arrow
SetFocus ( GetDlgItem ( mWnd, IDC_DBG_VARIABLE ) );
SetCursor ( LoadCursor ( NULL, IDC_ARROW ) );
}

View File

@@ -0,0 +1,59 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef DEBUGGERQUICKWATCHDLG_H_
#define DEBUGGERQUICKWATCHDLG_H_
class rvDebuggerWindow;
class rvDebuggerQuickWatchDlg
{
public:
rvDebuggerQuickWatchDlg ( );
bool DoModal ( rvDebuggerWindow* window, int callstackDepth, const char* variable = NULL );
protected:
HWND mWnd;
int mCallstackDepth;
idStr mVariable;
rvDebuggerWindow* mDebuggerWindow;
void SetVariable ( const char* varname, bool force = false );
private:
int mEditFromRight;
int mButtonFromRight;
int mEditFromBottom;
static INT_PTR CALLBACK DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
};
#endif // DEBUGGERQUICKWATCHDLG_H_

View File

@@ -0,0 +1,244 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "DebuggerApp.h"
#include "DebuggerScript.h"
#include "../../game/script/Script_Program.h"
#include "../../ui/Window.h"
#include "../../ui/UserInterfaceLocal.h"
/*
================
rvDebuggerScript::rvDebuggerScript
================
*/
rvDebuggerScript::rvDebuggerScript ( void )
{
mContents = NULL;
mProgram = NULL;
mInterface = NULL;
}
/*
================
rvDebuggerScript::~rvDebuggerScript
================
*/
rvDebuggerScript::~rvDebuggerScript ( void )
{
Unload ( );
}
/*
================
rvDebuggerScript::Unload
Unload the script from memory
================
*/
void rvDebuggerScript::Unload ( void )
{
delete[] mContents;
if ( mInterface )
{
delete mInterface;
}
else
{
delete mProgram;
}
mContents = NULL;
mProgram = NULL;
mInterface = NULL;
}
/*
================
rvDebuggerScript::Load
Loads the debugger script and attempts to compile it using the method
appropriate for the file being loaded. If the script cant be compiled
the loading of the script fails
================
*/
bool rvDebuggerScript::Load ( const char* filename )
{
void* buffer;
int size;
// Unload the script before reloading it
Unload ( );
// Cache the filename used to load the script
mFilename = filename;
// Read in the file
size = fileSystem->ReadFile ( filename, &buffer, &mModifiedTime );
if ( buffer == NULL )
{
return false;
}
// Copy the buffer over
mContents = new char [ size + 1 ];
memcpy ( mContents, buffer, size );
mContents[size] = 0;
// Cleanup
fileSystem->FreeFile ( buffer );
// Now compile the script so we can tell what a valid line is, etc.. If its
// a gui file then we need to parse it using the userinterface system rather
// than the normal script compiler.
try
{
// Parse the script using the script compiler
mProgram = new idProgram;
mProgram->BeginCompilation ( );
mProgram->CompileFile ( SCRIPT_DEFAULT );
//BSM Nerve: Loads a game specific main script file
idStr gamedir = cvarSystem->GetCVarString( "fs_game" );
if(gamedir.Length() > 0) {
idStr scriptFile = va("script/%s_main.script", gamedir.c_str());
if(fileSystem->ReadFile(scriptFile.c_str(), NULL) > 0) {
mProgram.CompileFile(scriptFile.c_str());
}
}
// Make sure the file isnt already compiled before trying to compile it again
for ( int f = mProgram->NumFilenames() - 1; f >= 0; f -- )
{
idStr qpath;
qpath = fileSystem->OSPathToRelativePath ( mProgram->GetFilename ( f ) );
qpath.BackSlashesToSlashes ( );
if ( !qpath.Cmp ( filename ) )
{
break;
}
}
if ( f < 0 )
{
mProgram->CompileText ( filename, mContents, false );
}
mProgram->FinishCompilation ( );
}
catch ( idException& )
{
// Failed to parse the script so fail to load the file
delete mProgram;
mProgram = NULL;
delete[] mContents;
mContents = NULL;
// TODO: Should cache the error for the dialog box
return false;
}
return true;
}
/*
================
rvDebuggerScript::Reload
Reload the contents of the script
================
*/
bool rvDebuggerScript::Reload ( void )
{
return Load ( mFilename );
}
/*
================
rvDebuggerScript::IsValidLine
Determines whether or not the given line number within the script is a valid line of code
================
*/
bool rvDebuggerScript::IsLineCode ( int linenumber )
{
int i;
assert ( mProgram );
// Run through all the statements in the program and see if any match the
// linenumber that we are checking.
for ( i = 0; i < mProgram->NumStatements ( ); i ++ )
{
if ( mProgram->GetStatement ( i ).linenumber == linenumber )
{
return true;
}
}
return false;
}
/*
================
rvDebuggerScript::IsFileModified
Determines whether or not the file loaded for this script has been modified since
it was loaded.
================
*/
bool rvDebuggerScript::IsFileModified ( bool updateTime )
{
ID_TIME_T t;
bool result = false;
// Grab the filetime and shut the file down
fileSystem->ReadFile ( mFilename, NULL, &t );
// Has the file been modified?
if ( t > mModifiedTime )
{
result = true;
}
// If updateTime is true then we will update the modified time
// stored in the script with the files current modified time
if ( updateTime )
{
mModifiedTime = t;
}
return result;
}

View File

@@ -0,0 +1,78 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef DEBUGGERSCRIPT_H_
#define DEBUGGERSCRIPT_H_
class idProgram;
class idUserInterfaceLocal;
class rvDebuggerScript
{
public:
rvDebuggerScript ( void );
~rvDebuggerScript ( void );
bool Load ( const char* filename );
bool Reload ( void );
const char* GetFilename ( void );
const char* GetContents ( void );
idProgram& GetProgram ( void );
bool IsLineCode ( int linenumber );
bool IsFileModified ( bool updateTime = false );
protected:
void Unload ( void );
idProgram* mProgram;
idUserInterfaceLocal* mInterface;
char* mContents;
idStr mFilename;
ID_TIME_T mModifiedTime;
};
ID_INLINE const char* rvDebuggerScript::GetFilename ( void )
{
return mFilename;
}
ID_INLINE const char* rvDebuggerScript::GetContents ( void )
{
return mContents?mContents:"";
}
ID_INLINE idProgram& rvDebuggerScript::GetProgram ( void )
{
return *mProgram;
}
#endif // DEBUGGERSCRIPT_H_

View File

@@ -0,0 +1,714 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../../game/gamesys/Event.h"
#include "../../game/gamesys/Class.h"
#include "../../game/script/Script_Program.h"
#include "../../game/script/Script_Interpreter.h"
#include "../../game/script/Script_Thread.h"
#include "../../game/script/Script_Compiler.h"
#include "../../framework/sync/Msg.h"
#include "DebuggerApp.h"
#include "DebuggerServer.h"
/*
================
rvDebuggerServer::rvDebuggerServer
================
*/
rvDebuggerServer::rvDebuggerServer ( )
{
mConnected = false;
mBreakNext = false;
mBreak = false;
mBreakStepOver = false;
mBreakStepInto = false;
mGameThread = NULL;
mLastStatementLine = -1;
mBreakStepOverFunc1 = NULL;
mBreakStepOverFunc2 = NULL;
}
/*
================
rvDebuggerServer::~rvDebuggerServer
================
*/
rvDebuggerServer::~rvDebuggerServer ( )
{
}
/*
================
rvDebuggerServer::Initialize
Initialize the debugger server. This function should be called before the
debugger server is used.
================
*/
bool rvDebuggerServer::Initialize ( void )
{
// Initialize the network connection
if ( !mPort.InitForPort ( 27980 ) )
{
return false;
}
// Get a copy of the game thread handle so we can suspend the thread on a break
DuplicateHandle ( GetCurrentProcess(), GetCurrentThread ( ), GetCurrentProcess(), &mGameThread, 0, FALSE, DUPLICATE_SAME_ACCESS );
// Create a critical section to ensure that the shared thread
// variables are protected
InitializeCriticalSection ( &mCriticalSection );
// Server must be running on the local host on port 28980
Sys_StringToNetAdr ( "localhost", &mClientAdr, true );
mClientAdr.port = 27981;
// Attempt to let the server know we are here. The server may not be running so this
// message will just get ignored.
SendMessage ( DBMSG_CONNECT );
return true;
}
void rvDebuggerServer::OSPathToRelativePath( const char *osPath, idStr &qpath )
{
if ( strchr( osPath, ':' ) )
{
qpath = fileSystem->OSPathToRelativePath( osPath );
}
else
{
qpath = osPath;
}
}
/*
================
rvDebuggerServer::Shutdown
Shutdown the debugger server.
================
*/
void rvDebuggerServer::Shutdown ( void )
{
// Let the debugger client know we are shutting down
if ( mConnected )
{
SendMessage ( DBMSG_DISCONNECT );
mConnected = false;
}
mPort.Close();
// dont need the crit section anymore
DeleteCriticalSection ( &mCriticalSection );
}
/*
================
rvDebuggerServer::ProcessMessages
Process all incoming network messages from the debugger client
================
*/
bool rvDebuggerServer::ProcessMessages ( void )
{
netadr_t adrFrom;
msg_t msg;
byte buffer[MAX_MSGLEN];
MSG_Init( &msg, buffer, sizeof( buffer ) );
// Check for pending udp packets on the debugger port
while ( mPort.GetPacket ( adrFrom, msg.data, msg.cursize, msg.maxsize ) )
{
unsigned short command;
// Only accept packets from the debugger server for security reasons
if ( !Sys_CompareNetAdrBase ( adrFrom, mClientAdr ) )
{
continue;
}
command = (unsigned short) MSG_ReadShort ( &msg );
switch ( command )
{
case DBMSG_CONNECT:
mConnected = true;
SendMessage ( DBMSG_CONNECTED );
break;
case DBMSG_CONNECTED:
mConnected = true;
break;
case DBMSG_DISCONNECT:
ClearBreakpoints ( );
Resume ( );
mConnected = false;
break;
case DBMSG_ADDBREAKPOINT:
HandleAddBreakpoint ( &msg );
break;
case DBMSG_REMOVEBREAKPOINT:
HandleRemoveBreakpoint ( &msg );
break;
case DBMSG_RESUME:
Resume ( );
break;
case DBMSG_BREAK:
mBreakNext = true;
break;
case DBMSG_STEPOVER:
mBreakStepOver = true;
mBreakStepOverDepth = mBreakInterpreter->GetCallstackDepth ( );
mBreakStepOverFunc1 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()].f;
if ( mBreakInterpreter->GetCallstackDepth() > 0 )
{
mBreakStepOverFunc2 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()-1].f;
}
else
{
mBreakStepOverFunc2 = NULL;
}
Resume ( );
break;
case DBMSG_STEPINTO:
mBreakStepInto = true;
Resume ( );
break;
case DBMSG_INSPECTVARIABLE:
HandleInspectVariable ( &msg );
break;
case DBMSG_INSPECTCALLSTACK:
HandleInspectCallstack ( &msg );
break;
case DBMSG_INSPECTTHREADS:
HandleInspectThreads ( &msg );
break;
}
}
return true;
}
/*
================
rvDebuggerServer::SendMessage
Send a message with no data to the debugger server.
================
*/
void rvDebuggerServer::SendMessage ( EDebuggerMessage dbmsg )
{
msg_t msg;
byte buffer[MAX_MSGLEN];
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)dbmsg );
SendPacket ( msg.data, msg.cursize );
}
/*
================
rvDebuggerServer::HandleAddBreakpoint
Handle the DBMSG_ADDBREAKPOINT message being sent by the debugger client. This
message is handled by adding a new breakpoint to the breakpoint list with the
data supplied in the message.
================
*/
void rvDebuggerServer::HandleAddBreakpoint ( msg_t* msg )
{
bool onceOnly = false;
long lineNumber;
long id;
char filename[MAX_PATH];
// Read the breakpoint info
onceOnly = MSG_ReadBits ( msg, 1 ) ? true : false;
lineNumber = MSG_ReadLong ( msg );
id = MSG_ReadLong ( msg );
MSG_ReadString ( msg, filename, MAX_PATH );
// Since breakpoints are used by both threads we need to
// protect them with a crit section
EnterCriticalSection ( &mCriticalSection );
mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, id ) );
LeaveCriticalSection ( &mCriticalSection );
}
/*
================
rvDebuggerServer::HandleRemoveBreakpoint
Handle the DBMSG_REMOVEBREAKPOINT message being sent by the debugger client. This
message is handled by removing the breakpoint that matches the given id from the
list.
================
*/
void rvDebuggerServer::HandleRemoveBreakpoint ( msg_t* msg )
{
int i;
int id;
// ID that we are to remove
id = MSG_ReadLong ( msg );
// Since breakpoints are used by both threads we need to
// protect them with a crit section
EnterCriticalSection ( &mCriticalSection );
// Find the breakpoint that matches the given id and remove it from the list
for ( i = 0; i < mBreakpoints.Num(); i ++ )
{
if ( mBreakpoints[i]->GetID ( ) == id )
{
delete mBreakpoints[i];
mBreakpoints.RemoveIndex ( i );
break;
}
}
LeaveCriticalSection ( &mCriticalSection );
}
/*
================
rvDebuggerServer::MSG_WriteCallstackFunc
Writes a single callstack entry to the given message
================
*/
void rvDebuggerServer::MSG_WriteCallstackFunc ( msg_t* msg, const prstack_t* stack )
{
const statement_t* st;
const function_t* func;
func = stack->f;
// If the function is unknown then just fill in with default data.
if ( !func )
{
MSG_WriteString ( msg, "<UNKNOWN>" );
MSG_WriteString ( msg, "<UNKNOWN>" );
MSG_WriteLong ( msg, 0 );
return;
}
else
{
MSG_WriteString ( msg, va("%s( ??? )", func->Name() ) );
}
// Use the calling statement as the filename and linenumber where
// the call was made from
st = &mBreakProgram->GetStatement ( stack->s );
if ( st )
{
idStr qpath;
OSPathToRelativePath(mBreakProgram->GetFilename( st->file ), qpath);
qpath.BackSlashesToSlashes ( );
MSG_WriteString ( msg, qpath );
MSG_WriteLong ( msg, st->linenumber );
}
else
{
MSG_WriteString ( msg, "<UNKNOWN>" );
MSG_WriteLong ( msg, 0 );
}
}
/*
================
rvDebuggerServer::HandleInspectCallstack
Handle an incoming inspect callstack message by sending a message
back to the client with the callstack data.
================
*/
void rvDebuggerServer::HandleInspectCallstack ( msg_t* in_msg )
{
msg_t msg;
byte buffer[MAX_MSGLEN];
int i;
prstack_t temp;
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTCALLSTACK );
MSG_WriteShort ( &msg, (int)mBreakInterpreter->GetCallstackDepth ( ) );
// write out the current function
temp.f = mBreakInterpreter->GetCurrentFunction ( );
temp.s = 0;
temp.stackbase = 0;
MSG_WriteCallstackFunc ( &msg, &temp );
// Run through all of the callstack and write each to the msg
for ( i = mBreakInterpreter->GetCallstackDepth ( ) - 1; i > 0; i -- )
{
MSG_WriteCallstackFunc ( &msg, mBreakInterpreter->GetCallstack ( ) + i );
}
SendPacket ( msg.data, msg.cursize );
}
/*
================
rvDebuggerServer::HandleInspectThreads
Send the list of the current threads in the interpreter back to the debugger client
================
*/
void rvDebuggerServer::HandleInspectThreads ( msg_t* in_msg )
{
msg_t msg;
byte buffer[MAX_MSGLEN];
int i;
// Initialize the message
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTTHREADS );
// Write the number of threads to the message
MSG_WriteShort ( &msg, (int)idThread::GetThreads().Num() );
// Loop through all of the threads and write their name and number to the message
for ( i = 0; i < idThread::GetThreads().Num(); i ++ )
{
idThread* thread = idThread::GetThreads()[i];
MSG_WriteString ( &msg, thread->GetThreadName ( ) );
MSG_WriteLong ( &msg, thread->GetThreadNum ( ) );
MSG_WriteBits ( &msg, (int)(thread == mBreakInterpreter->GetThread ( )), 1 );
MSG_WriteBits ( &msg, (int)thread->IsDoneProcessing(), 1 );
MSG_WriteBits ( &msg, (int)thread->IsWaiting(), 1 );
MSG_WriteBits ( &msg, (int)thread->IsDying(), 1 );
}
// Send off the inspect threads packet to the debugger client
SendPacket ( msg.data, msg.cursize );
}
/*
================
rvDebuggerServer::HandleInspectVariable
Respondes to a request from the debugger client to inspect the value of a given variable
================
*/
void rvDebuggerServer::HandleInspectVariable ( msg_t* in_msg )
{
char varname[256];
int scopeDepth;
if ( !mBreak )
{
return;
}
scopeDepth = (short)MSG_ReadShort ( in_msg );
MSG_ReadString ( in_msg, varname, 256 );
idStr varvalue;
msg_t msg;
byte buffer[MAX_MSGLEN];
// Initialize the message
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)DBMSG_INSPECTVARIABLE );
if ( !mBreakInterpreter->GetRegisterValue ( varname, varvalue, scopeDepth ) )
{
varvalue = "???";
}
MSG_WriteShort ( &msg, (short)scopeDepth );
MSG_WriteString ( &msg, varname );
MSG_WriteString ( &msg, varvalue );
SendPacket ( msg.data, msg.cursize );
}
/*
================
rvDebuggerServer::CheckBreakpoints
Check to see if any breakpoints have been hit. This includes "break next",
"step into", and "step over" break points
================
*/
void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer )
{
const statement_t* st;
const char* filename;
int i;
if ( !mConnected ) {
return;
}
// Grab the current statement and the filename that it came from
st = &program->GetStatement ( instructionPointer );
filename = program->GetFilename ( st->file );
// Operate on lines, not statements
if ( mLastStatementLine == st->linenumber && mLastStatementFile == st->file )
{
return;
}
// Save the last visited line and file so we can prevent
// double breaks on lines with more than one statement
mLastStatementFile = idStr( st->file );
mLastStatementLine = st->linenumber;
// Reset stepping when the last function on the callstack is returned from
if ( st->op == OP_RETURN && interpreter->GetCallstackDepth ( ) <= 1 )
{
mBreakStepOver = false;
mBreakStepInto = false;
}
// See if we are supposed to break on the next script line
if ( mBreakNext )
{
Break ( interpreter, program, instructionPointer );
return;
}
// Only break on the same callstack depth and thread as the break over
if ( mBreakStepOver )
{
if ( ( interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc1 ||
interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc2 )&&
( interpreter->GetCallstackDepth ( ) <= mBreakStepOverDepth ) )
{
Break ( interpreter, program, instructionPointer );
return;
}
}
// See if we are supposed to break on the next line
if ( mBreakStepInto )
{
// Break
Break ( interpreter, program, instructionPointer );
return;
}
idStr qpath;
OSPathToRelativePath(filename,qpath);
qpath.BackSlashesToSlashes ( );
EnterCriticalSection ( &mCriticalSection );
// Check all the breakpoints
for ( i = 0; i < mBreakpoints.Num ( ); i ++ )
{
rvDebuggerBreakpoint* bp = mBreakpoints[i];
// Skip if not match of the line number
if ( st->linenumber != bp->GetLineNumber ( ) )
{
continue;
}
// Skip if no match of the filename
if ( idStr::Icmp ( bp->GetFilename(), qpath ) )
{
continue;
}
// Pop out of the critical section so we dont get stuck
LeaveCriticalSection ( &mCriticalSection );
// We hit a breakpoint, so break
Break ( interpreter, program, instructionPointer );
// Back into the critical section since we are going to have to leave it
EnterCriticalSection ( &mCriticalSection );
break;
}
LeaveCriticalSection ( &mCriticalSection );
}
/*
================
rvDebuggerServer::Break
Halt execution of the game threads and inform the debugger client that
the game has been halted
================
*/
void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer )
{
msg_t msg;
byte buffer[MAX_MSGLEN];
const statement_t* st;
const char* filename;
// Clear all the break types
mBreakStepOver = false;
mBreakStepInto = false;
mBreakNext = false;
// Grab the current statement and the filename that it came from
st = &program->GetStatement ( instructionPointer );
filename = program->GetFilename ( st->file );
idStr qpath;
OSPathToRelativePath(filename, qpath);
qpath.BackSlashesToSlashes ( );
// Give the mouse cursor back to the world
Sys_GrabMouseCursor( false );
// Set the break variable so we know the main thread is stopped
mBreak = true;
mBreakProgram = program;
mBreakInterpreter = interpreter;
mBreakInstructionPointer = instructionPointer;
// Inform the debugger of the breakpoint hit
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)DBMSG_BREAK );
MSG_WriteLong ( &msg, st->linenumber );
MSG_WriteString ( &msg, qpath );
SendPacket ( msg.data, msg.cursize );
// Suspend the game thread. Since this will be called from within the main game thread
// execution wont return until after the thread is resumed
SuspendThread ( mGameThread );
// Let the debugger client know that we have started back up again
SendMessage ( DBMSG_RESUMED );
// This is to give some time between the keypress that
// told us to resume and the setforeground window. Otherwise the quake window
// would just flash
Sleep ( 150 );
// Bring the window back to the foreground
SetForegroundWindow ( win32.hWnd );
SetActiveWindow ( win32.hWnd );
UpdateWindow ( win32.hWnd );
SetFocus ( win32.hWnd );
// Give the mouse cursor back to the game
Sys_GrabMouseCursor( true );
// Clear all commands that were generated before we went into suspended mode. This is
// to ensure we dont have mouse downs with no ups because the context was changed.
idKeyInput::ClearStates();
}
/*
================
rvDebuggerServer::Resume
Resume execution of the game.
================
*/
void rvDebuggerServer::Resume ( void )
{
// Cant resume if not paused
if ( !mBreak )
{
return;
}
mBreak = false;
// Start the game thread back up
ResumeThread ( mGameThread );
}
/*
================
rvDebuggerServer::ClearBreakpoints
Remove all known breakpoints
================
*/
void rvDebuggerServer::ClearBreakpoints ( void )
{
int i;
for ( i = 0; i < mBreakpoints.Num(); i ++ )
{
delete mBreakpoints[i];
}
mBreakpoints.Clear ( );
}
/*
================
rvDebuggerServer::Print
Sends a console print message over to the debugger client
================
*/
void rvDebuggerServer::Print ( const char* text )
{
if ( !mConnected )
{
return;
}
msg_t msg;
byte buffer[MAX_MSGLEN];
MSG_Init( &msg, buffer, sizeof( buffer ) );
MSG_WriteShort ( &msg, (int)DBMSG_PRINT );
MSG_WriteString ( &msg, text );
SendPacket ( msg.data, msg.cursize );
}

View File

@@ -0,0 +1,133 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef DEBUGGERSERVER_H_
#define DEBUGGERSERVER_H_
#ifndef DEBUGGERMESSAGES_H_
#include "DebuggerMessages.h"
#endif
#ifndef DEBUGGERBREAKPOINT_H_
#include "DebuggerBreakpoint.h"
#endif
#ifndef __GAME_LOCAL_H__
#include "../../game/Game.h"
#endif
class idInterpreter;
class idProgram;
class rvDebuggerServer
{
public:
rvDebuggerServer ( );
~rvDebuggerServer ( );
bool Initialize ( void );
void Shutdown ( void );
bool ProcessMessages ( void );
bool IsConnected ( void );
void CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer );
void Print ( const char* text );
void OSPathToRelativePath( const char *osPath, idStr &qpath );
protected:
// protected member variables
bool mConnected;
netadr_t mClientAdr;
idPort mPort;
idList<rvDebuggerBreakpoint*> mBreakpoints;
CRITICAL_SECTION mCriticalSection;
HANDLE mGameThread;
bool mBreak;
bool mBreakNext;
bool mBreakStepOver;
bool mBreakStepInto;
int mBreakStepOverDepth;
const function_t* mBreakStepOverFunc1;
const function_t* mBreakStepOverFunc2;
idProgram* mBreakProgram;
int mBreakInstructionPointer;
idInterpreter* mBreakInterpreter;
idStr mLastStatementFile;
int mLastStatementLine;
private:
void ClearBreakpoints ( void );
void Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer );
void Resume ( void );
void SendMessage ( EDebuggerMessage dbmsg );
void SendPacket ( void* data, int datasize );
// Message handlers
void HandleAddBreakpoint ( msg_t* msg );
void HandleRemoveBreakpoint ( msg_t* msg );
void HandleResume ( msg_t* msg );
void HandleInspectVariable ( msg_t* msg );
void HandleInspectCallstack ( msg_t* msg );
void HandleInspectThreads ( msg_t* msg );
// MSG helper routines
void MSG_WriteCallstackFunc ( msg_t* msg, const prstack_t* stack );
};
/*
================
rvDebuggerServer::IsConnected
================
*/
ID_INLINE bool rvDebuggerServer::IsConnected ( void )
{
return mConnected;
}
/*
================
rvDebuggerServer::SendPacket
================
*/
ID_INLINE void rvDebuggerServer::SendPacket ( void* data, int size )
{
mPort.SendPacket ( mClientAdr, data, size );
}
#endif // DEBUGGERSERVER_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef DEBUGGERWINDOW_H_
#define DEBUGGERWINDOW_H_
#ifndef DEBUGGERSCRIPT_H_
#include "DebuggerScript.h"
#endif
class rvDebuggerWatch
{
public:
idStr mVariable;
idStr mValue;
bool mModified;
};
typedef idList<rvDebuggerWatch*> rvDebuggerWatchList;
class rvDebuggerClient;
class rvDebuggerWindow
{
public:
rvDebuggerWindow ( );
~rvDebuggerWindow ( );
bool Create ( HINSTANCE hInstance );
static bool Activate ( void );
void ProcessNetMessage ( msg_t* msg );
void Printf ( const char* format, ... );
HWND GetWindow ( void );
void AddWatch ( const char* name, bool update = true );
HINSTANCE GetInstance ( void );
protected:
bool FindPrev ( const char* text = NULL );
bool FindNext ( const char* text = NULL );
void UpdateWatch ( void );
void UpdateWindowMenu ( void );
void UpdateScript ( void );
void UpdateToolbar ( void );
void UpdateTitle ( void );
void UpdateCallstack ( void );
void UpdateRecentFiles ( void );
bool OpenScript ( const char* filename, int lineNumber = -1 );
void EnableWindows ( bool state );
int GetSelectedText ( idStr& text );
void ToggleBreakpoint ( void );
HWND mWnd;
HWND mWndScript;
HWND mWndOutput;
HWND mWndMargin;
HWND mWndTabs;
HWND mWndBorder;
HWND mWndConsole;
HWND mWndCallstack;
HWND mWndWatch;
HWND mWndThreads;
HWND mWndToolTips;
HWND mWndToolbar;
HMENU mRecentFileMenu;
int mRecentFileInsertPos;
WNDPROC mOldWatchProc;
WNDPROC mOldScriptProc;
idStr mTooltipVar;
idStr mTooltipValue;
HINSTANCE mInstance;
HIMAGELIST mImageList;
RECT mSplitterRect;
bool mSplitterDrag;
idList<rvDebuggerScript*> mScripts;
int mActiveScript;
int mLastActiveScript;
int mCurrentStackDepth;
HMENU mWindowMenu;
int mWindowMenuPos;
int mZoomScaleNum;
int mZoomScaleDem;
int mMarginSize;
idStr mFind;
rvDebuggerClient* mClient;
rvDebuggerWatchList mWatches;
private:
bool RegisterClass ( void );
void CreateToolbar ( void );
bool InitRecentFiles ( void );
int HandleInitMenu ( WPARAM wParam, LPARAM lParam );
int HandleCommand ( WPARAM wParam, LPARAM lParam );
int HandleCreate ( WPARAM wparam, LPARAM lparam );
int HandleActivate ( WPARAM wparam, LPARAM lparam );
int HandleDrawItem ( WPARAM wparam, LPARAM lparam );
void HandleTooltipGetDispInfo ( WPARAM wparam, LPARAM lparam );
static LRESULT CALLBACK WndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
static LRESULT CALLBACK MarginWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
static LRESULT CALLBACK ScriptWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
static INT_PTR CALLBACK AboutDlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam );
static int CALLBACK ScriptWordBreakProc ( LPTSTR text, int current, int max, int action );
};
/*
================
rvDebuggerWindow::GetWindow
================
*/
ID_INLINE HWND rvDebuggerWindow::GetWindow ( void )
{
return mWnd;
}
/*
================
rvDebuggerWindow::UpdateToolbar
================
*/
ID_INLINE void rvDebuggerWindow::UpdateToolbar ( void )
{
HandleInitMenu ( (WPARAM)GetMenu ( mWnd ), 0 );
}
/*
================
rvDebuggerWindow::GetInstance
================
*/
ID_INLINE HINSTANCE rvDebuggerWindow::GetInstance ( void )
{
return mInstance;
}
#endif // DEBUGGERWINDOW_H_

View File

@@ -0,0 +1,235 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../../sys/win32/rc/debugger_resource.h"
#include "DebuggerApp.h"
#include "DebuggerServer.h"
DWORD CALLBACK DebuggerThread ( LPVOID param );
rvDebuggerApp gDebuggerApp;
HWND gDebuggerWindow = NULL;
bool gDebuggerSuspend = false;
bool gDebuggerConnnected = false;
HANDLE gDebuggerGameThread = NULL;
rvDebuggerServer* gDebuggerServer = NULL;
HANDLE gDebuggerServerThread = NULL;
DWORD gDebuggerServerThreadID = 0;
bool gDebuggerServerQuit = false;
/*
================
DebuggerMain
Main entry point for the debugger application
================
*/
void DebuggerClientInit( const char *cmdline )
{
// See if the debugger is already running
if ( rvDebuggerWindow::Activate ( ) )
{
goto DebuggerClientInitDone;
}
if ( !gDebuggerApp.Initialize ( win32.hInstance ) )
{
goto DebuggerClientInitDone;
}
gDebuggerApp.Run ( );
DebuggerClientInitDone:
common->Quit();
}
/*
================
DebuggerLaunch
Launches another instance of the running executable with +debugger appended
to the end to indicate that the debugger should start up.
================
*/
void DebuggerClientLaunch ( void )
{
if ( renderSystem->IsFullScreen() ) {
common->Printf( "Cannot run the script debugger in fullscreen mode.\n"
"Set r_fullscreen to 0 and vid_restart.\n" );
return;
}
// See if the debugger is already running
if ( rvDebuggerWindow::Activate ( ) ) {
return;
}
char exeFile[MAX_PATH];
char curDir[MAX_PATH];
STARTUPINFO startup;
PROCESS_INFORMATION process;
ZeroMemory ( &startup, sizeof(startup) );
startup.cb = sizeof(startup);
GetCurrentDirectory ( MAX_PATH, curDir );
GetModuleFileName ( NULL, exeFile, MAX_PATH );
const char* s = va("%s +set fs_game %s +set fs_cdpath %s +debugger", exeFile, cvarSystem->GetCVarString( "fs_game" ), cvarSystem->GetCVarString( "fs_cdpath" ) );
CreateProcess ( NULL, (LPSTR)s,
NULL, NULL, FALSE, 0, NULL, curDir, &startup, &process );
CloseHandle ( process.hThread );
CloseHandle ( process.hProcess );
}
/*
================
DebuggerServerThread
Thread proc for the debugger server
================
*/
DWORD CALLBACK DebuggerServerThread ( LPVOID param )
{
assert ( gDebuggerServer );
while ( !gDebuggerServerQuit )
{
gDebuggerServer->ProcessMessages ( );
Sleep ( 1 );
}
return 0;
}
/*
================
DebuggerServerInit
Starts up the debugger server
================
*/
bool DebuggerServerInit ( void )
{
// Dont do this if we are in the debugger already
if ( com_editors & EDITOR_DEBUGGER )
{
return false;
}
// Allocate the new debugger server
gDebuggerServer = new rvDebuggerServer;
if ( !gDebuggerServer )
{
return false;
}
// Initialize the debugger server
if ( !gDebuggerServer->Initialize ( ) )
{
delete gDebuggerServer;
gDebuggerServer = NULL;
return false;
}
// Start the debugger server thread
gDebuggerServerThread = CreateThread ( NULL, 0, DebuggerServerThread, 0, 0, &gDebuggerServerThreadID );
return true;
}
/*
================
DebuggerServerShutdown
Shuts down the debugger server
================
*/
void DebuggerServerShutdown ( void )
{
if ( gDebuggerServerThread )
{
// Signal the debugger server to quit
gDebuggerServerQuit = true;
// Wait for the thread to finish
WaitForSingleObject ( gDebuggerServerThread, INFINITE );
// Shutdown the server now
gDebuggerServer->Shutdown();
delete gDebuggerServer;
gDebuggerServer = NULL;
// Cleanup the thread handle
CloseHandle ( gDebuggerServerThread );
gDebuggerServerThread = NULL;
}
}
/*
================
DebuggerServerCheckBreakpoint
Check to see if there is a breakpoint associtated with this statement
================
*/
void DebuggerServerCheckBreakpoint ( idInterpreter* interpreter, idProgram* program, int instructionPointer )
{
if ( !gDebuggerServer )
{
return;
}
gDebuggerServer->CheckBreakpoints ( interpreter, program, instructionPointer );
}
/*
================
DebuggerServerPrint
Sends a print message to the debugger client
================
*/
void DebuggerServerPrint ( const char* text )
{
if ( !gDebuggerServer )
{
return;
}
gDebuggerServer->Print ( text );
}