Debugger split y functionality

This commit is contained in:
mpohoreski 2006-02-26 06:26:56 +00:00
parent eefbc4082e
commit f29b6eb964
13 changed files with 7880 additions and 6465 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
#ifndef DEBUGGER_ASSEMBLER_H
#define DEBUGGER_ASSEMBLER_H
// Addressing _____________________________________________________________________________________
extern AddressingMode_t g_aOpmodes[ NUM_ADDRESSING_MODES ];
// Assembler ______________________________________________________________________________________
// Hashing for Assembler
typedef unsigned int Hash_t;
struct HashOpcode_t
{
int m_iOpcode;
Hash_t m_nValue;
// functor
bool operator () (const HashOpcode_t & rLHS, const HashOpcode_t & rRHS) const
{
bool bLessThan = (rLHS.m_nValue < rRHS.m_nValue);
return bLessThan;
}
};
struct AssemblerDirective_t
{
char m_sMnemonic[ MAX_MNEMONIC_LEN + 1 ];
Hash_t m_nHash;
};
extern int g_bAssemblerOpcodesHashed; // = false;
extern Hash_t g_aOpcodesHash[ NUM_OPCODES ]; // for faster mnemonic lookup, for the assembler
extern bool g_bAssemblerInput; // = false;
extern int g_nAssemblerAddress; // = 0;
extern const Opcodes_t *g_aOpcodes; // = NULL; // & g_aOpcodes65C02[ 0 ];
extern const Opcodes_t g_aOpcodes65C02[ NUM_OPCODES ];
extern const Opcodes_t g_aOpcodes6502 [ NUM_OPCODES ];
// Prototypes _______________________________________________________________
int _6502GetOpmodeOpbytes ( const int iAddress, int & iOpmode_, int & nOpbytes_ );
// void _6502GetOpcodeOpmode ( int & iOpcode_, int & iOpmode_, int & nOpbytes_ );
void _6502GetOpcodeOpmodeOpbytes ( int & iOpcode_, int & iOpmode_, int & nOpbytes_ );
int AssemblerHashMnemonic ( const TCHAR * pMnemonic );
void AssemblerHashOpcodes ();
void AssemblerHashMerlinDirectives ();
// bool AssemblerGetAddressingMode ( int iArg, int nArgs, WORD nAddress, vector<int> & vOpcodes );
void _CmdAssembleHashDump ();
int AssemblerDelayedTargetsSize();
void AssemblerStartup ();
bool Assemble( int iArg, int nArgs, WORD nAddress );
void AssemblerOn ();
void AssemblerOff ();
#endif

View File

@ -0,0 +1,352 @@
/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006, Tom Charlesworth, Michael Pohoreski
AppleWin 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 2 of the License, or
(at your option) any later version.
AppleWin 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 AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Description: Debugger
*
* Author: Copyright (C) 2006, Michael Pohoreski
*/
#include "StdAfx.h"
#pragma hdrstop
// Console ________________________________________________________________________________________
// See ConsoleInputReset() for why the console input
// is tied to the zero'th output of g_aConsoleDisplay
// and not using a seperate var: g_aConsoleInput[ CONSOLE_WIDTH ];
//
// : g_aConsoleBuffer[4] | ^ g_aConsoleDisplay[5] :
// : g_aConsoleBuffer[3] | | g_aConsoleDisplay[4] <- g_nConsoleDisplayTotal
// g_nConsoleBuffer -> g_aConsoleBuffer[2] | | g_aConsoleDisplay[3] :
// : g_aConsoleBuffer[1] v | g_aConsoleDisplay[2] :
// . g_aConsoleBuffer[0] -----> | g_aConsoleDisplay[1] .
// |
// g_aBufferedInput[0] -----> ConsoleInput ----> | g_aConsoleDisplay[0]
// g_aBufferedInput[1] ^
// g_aBufferedInput[2] |
// g_aBufferedInput[3] |
// Buffer
bool g_bConsoleBufferPaused = false; // buffered output is waiting for user to continue
int g_nConsoleBuffer = 0;
TCHAR g_aConsoleBuffer[ CONSOLE_HEIGHT ][ CONSOLE_WIDTH ]; // TODO: stl::vector< line_t >
// Display
TCHAR g_aConsolePrompt[] = TEXT(">!"); // input, assembler // NUM_PROMPTS
TCHAR g_sConsolePrompt[] = TEXT(">"); // No, NOT Integer Basic! The nostalgic '*' "Monitor" doesn't look as good, IMHO. :-(
bool g_bConsoleFullWidth = false;
int g_iConsoleDisplayStart = 0; // to allow scrolling
int g_nConsoleDisplayTotal = 0; // number of lines added to console
int g_nConsoleDisplayHeight = 0;
int g_nConsoleDisplayWidth = 0;
TCHAR g_aConsoleDisplay[ CONSOLE_HEIGHT ][ CONSOLE_WIDTH ];
// Input History
int g_nHistoryLinesStart = 0;
int g_nHistoryLinesTotal = 0; // number of commands entered
TCHAR g_aHistoryLines[ CONSOLE_HEIGHT ][ CONSOLE_WIDTH ] = {TEXT("")};
// Input Line
// Raw input Line (has prompt)
TCHAR * const g_aConsoleInput = g_aConsoleDisplay[0];
// Cooked input line (no prompt)
int g_nConsoleInputChars = 0;
TCHAR * g_pConsoleInput = 0; // points to past prompt
const TCHAR * g_pConsoleFirstArg = 0; // points to first arg
bool g_bConsoleInputQuoted = false; // Allows lower-case to be entered
bool g_bConsoleInputSkip = false;
// Prototypes _______________________________________________________________
// Console ________________________________________________________________________________________
//===========================================================================
LPCSTR ConsoleBufferPeek()
{
return g_aConsoleBuffer[ 0 ];
}
// Add string to buffered output
// Shifts the buffered console output lines "Up"
//===========================================================================
bool ConsoleBufferPush( const TCHAR * pString ) // LPCSTR
{
if (g_nConsoleBuffer < CONSOLE_HEIGHT)
{
int nLen = _tcslen( pString );
if (nLen < g_nConsoleDisplayWidth)
{
_tcscpy( g_aConsoleBuffer[ g_nConsoleBuffer ], pString );
g_nConsoleBuffer++;
return true;
}
else
{
#if _DEBUG
// TCHAR sText[ CONSOLE_WIDTH * 2 ];
// sprintf( sText, "ConsoleBufferPush(pString) > g_nConsoleDisplayWidth: %d", g_nConsoleDisplayWidth );
// MessageBox( framewindow, sText, "Warning", MB_OK );
#endif
// push multiple lines
while ((nLen >= g_nConsoleDisplayWidth) && (g_nConsoleBuffer < CONSOLE_HEIGHT))
{
// _tcsncpy( g_aConsoleBuffer[ g_nConsoleBuffer ], pString, (g_nConsoleDisplayWidth-1) );
// pString += g_nConsoleDisplayWidth;
_tcsncpy( g_aConsoleBuffer[ g_nConsoleBuffer ], pString, (CONSOLE_WIDTH-1) );
pString += (CONSOLE_WIDTH-1);
g_nConsoleBuffer++;
nLen = _tcslen( pString );
}
return true;
}
}
// TODO: Warning: Too much output.
return false;
}
// Shifts the buffered console output "down"
//===========================================================================
void ConsoleBufferPop()
{
int y = 0;
while (y < g_nConsoleBuffer)
{
_tcscpy( g_aConsoleBuffer[ y ], g_aConsoleBuffer[ y+1 ] );
y++;
}
g_nConsoleBuffer--;
if (g_nConsoleBuffer < 0)
g_nConsoleBuffer = 0;
}
// Remove string from buffered output
//===========================================================================
void ConsoleBufferToDisplay()
{
ConsoleDisplayPush( ConsoleBufferPeek() );
ConsoleBufferPop();
}
//===========================================================================
Update_t ConsoleDisplayError (LPCTSTR pText)
{
ConsoleBufferPush( pText );
return ConsoleUpdate();
}
// ConsoleDisplayPush()
// Shifts the console display lines "up"
//===========================================================================
void ConsoleDisplayPush( LPCSTR pText )
{
int nLen = MIN( g_nConsoleDisplayTotal, CONSOLE_HEIGHT - 1 - CONSOLE_FIRST_LINE);
while (nLen--)
{
_tcsncpy(
g_aConsoleDisplay[(nLen + 1 + CONSOLE_FIRST_LINE )],
g_aConsoleDisplay[nLen + CONSOLE_FIRST_LINE],
CONSOLE_WIDTH );
}
if (pText)
_tcsncpy( g_aConsoleDisplay[ CONSOLE_FIRST_LINE ], pText, CONSOLE_WIDTH );
g_nConsoleDisplayTotal++;
if (g_nConsoleDisplayTotal > (CONSOLE_HEIGHT - CONSOLE_FIRST_LINE))
g_nConsoleDisplayTotal = (CONSOLE_HEIGHT - CONSOLE_FIRST_LINE);
}
//===========================================================================
void ConsoleDisplayPause()
{
if (g_nConsoleBuffer)
{
_tcscpy( g_pConsoleInput, TEXT("...press SPACE continue, ESC skip..." ) );
g_bConsoleBufferPaused = true;
}
else
{
ConsoleInputReset();
}
}
//===========================================================================
bool ConsoleInputBackSpace()
{
if (g_nConsoleInputChars)
{
g_nConsoleInputChars--;
if (g_pConsoleInput[ g_nConsoleInputChars ] == TEXT('"'))
g_bConsoleInputQuoted = ! g_bConsoleInputQuoted;
g_pConsoleInput[ g_nConsoleInputChars ] = 0;
return true;
}
return false;
}
//===========================================================================
bool ConsoleInputClear()
{
if (g_nConsoleInputChars)
{
ZeroMemory( g_pConsoleInput, g_nConsoleDisplayWidth );
g_nConsoleInputChars = 0;
return true;
}
return false;
}
//===========================================================================
bool ConsoleInputChar( TCHAR ch )
{
if (g_nConsoleInputChars < g_nConsoleDisplayWidth) // bug? include prompt?
{
g_pConsoleInput[ g_nConsoleInputChars ] = ch;
g_nConsoleInputChars++;
return true;
}
return false;
}
//===========================================================================
LPCSTR ConsoleInputPeek()
{
return g_aConsoleDisplay[0];
}
//===========================================================================
void ConsoleInputReset ()
{
// Not using g_aConsoleInput since we get drawing of the input Line for "Free"
// Even if we add console scrolling, we don't need any special logic to draw the input line.
g_bConsoleInputQuoted = false;
ZeroMemory( g_aConsoleInput, CONSOLE_WIDTH );
_tcscpy( g_aConsoleInput, g_sConsolePrompt ); // Assembler can change prompt
_tcscat( g_aConsoleInput, TEXT(" " ) );
int nLen = _tcslen( g_aConsoleInput );
g_pConsoleInput = &g_aConsoleInput[nLen];
g_nConsoleInputChars = 0;
}
//===========================================================================
int ConsoleInputTabCompletion ()
{
return UPDATE_CONSOLE_INPUT;
}
//===========================================================================
Update_t ConsoleScrollHome ()
{
g_iConsoleDisplayStart = g_nConsoleDisplayTotal - CONSOLE_FIRST_LINE;
if (g_iConsoleDisplayStart < 0)
g_iConsoleDisplayStart = 0;
return UPDATE_CONSOLE_DISPLAY;
}
//===========================================================================
Update_t ConsoleScrollEnd ()
{
g_iConsoleDisplayStart = 0;
return UPDATE_CONSOLE_DISPLAY;
}
//===========================================================================
Update_t ConsoleScrollUp ( int nLines )
{
g_iConsoleDisplayStart += nLines;
if (g_iConsoleDisplayStart > (g_nConsoleDisplayTotal - CONSOLE_FIRST_LINE))
g_iConsoleDisplayStart = (g_nConsoleDisplayTotal - CONSOLE_FIRST_LINE);
if (g_iConsoleDisplayStart < 0)
g_iConsoleDisplayStart = 0;
return UPDATE_CONSOLE_DISPLAY;
}
//===========================================================================
Update_t ConsoleScrollDn ( int nLines )
{
g_iConsoleDisplayStart -= nLines;
if (g_iConsoleDisplayStart < 0)
g_iConsoleDisplayStart = 0;
return UPDATE_CONSOLE_DISPLAY;
}
//===========================================================================
Update_t ConsoleScrollPageUp ()
{
ConsoleScrollUp( g_nConsoleDisplayHeight - CONSOLE_FIRST_LINE );
return UPDATE_CONSOLE_DISPLAY;
}
//===========================================================================
Update_t ConsoleScrollPageDn()
{
ConsoleScrollDn( g_nConsoleDisplayHeight - CONSOLE_FIRST_LINE );
return UPDATE_CONSOLE_DISPLAY;
}
//===========================================================================
void ConsoleBufferTryUnpause (int nLines)
{
for( int y = 0; y < nLines; y++ )
{
ConsoleBufferToDisplay();
}
g_bConsoleBufferPaused = false;
if (g_nConsoleBuffer)
{
g_bConsoleBufferPaused = true;
ConsoleDisplayPause();
}
}
//===========================================================================
Update_t ConsoleUpdate()
{
if (! g_bConsoleBufferPaused)
{
int nLines = MIN( g_nConsoleBuffer, g_nConsoleDisplayHeight - 1);
ConsoleBufferTryUnpause( nLines );
}
return UPDATE_CONSOLE_DISPLAY;
}

View File

@ -0,0 +1,84 @@
#ifndef DEBUGGER_CONSOLE_H
#define DEBUGGER_CONSOLE_H
// const int CONSOLE_HEIGHT = 384; // Lines, was 128, but need ~ 256+16 for PROFILE LIST
// const int CONSOLE_WIDTH = 80;
enum
{
CONSOLE_HEIGHT = 384, // Lines, was 128, but need ~ 256+16 for PROFILE LIST
CONSOLE_WIDTH = 80,
CONSOLE_FIRST_LINE = 1, // where ConsoleDisplay is pushed up from
};
// Globals __________________________________________________________________
// Buffer
extern bool g_bConsoleBufferPaused;// = false; // buffered output is waiting for user to continue
extern int g_nConsoleBuffer; //= 0;
extern TCHAR g_aConsoleBuffer[ CONSOLE_HEIGHT ][ CONSOLE_WIDTH ]; // TODO: stl::vector< line_t >
// Display
extern TCHAR g_aConsolePrompt[];// = TEXT(">!"); // input, assembler // NUM_PROMPTS
extern TCHAR g_sConsolePrompt[];// = TEXT(">"); // No, NOT Integer Basic! The nostalgic '*' "Monitor" doesn't look as good, IMHO. :-(
extern bool g_bConsoleFullWidth;// = false;
extern int g_iConsoleDisplayStart ;// = 0; // to allow scrolling
extern int g_nConsoleDisplayTotal ;//= 0; // number of lines added to console
extern int g_nConsoleDisplayHeight ;//= 0;
extern int g_nConsoleDisplayWidth ;//= 0;
extern TCHAR g_aConsoleDisplay[ CONSOLE_HEIGHT ][ CONSOLE_WIDTH ];
// Input History
extern int g_nHistoryLinesStart;// = 0;
extern int g_nHistoryLinesTotal;// = 0; // number of commands entered
extern TCHAR g_aHistoryLines[ CONSOLE_HEIGHT ][ CONSOLE_WIDTH ];// = {TEXT("")};
// Input Line
// Raw input Line (has prompt)
extern TCHAR * const g_aConsoleInput; // = g_aConsoleDisplay[0];
// Cooked input line (no prompt)
extern int g_nConsoleInputChars ;//= 0;
extern TCHAR * g_pConsoleInput ;//= 0; // points to past prompt
extern const TCHAR * g_pConsoleFirstArg ;//= 0; // points to first arg
extern bool g_bConsoleInputQuoted ;//= false; // Allows lower-case to be entered
extern bool g_bConsoleInputSkip ;//= false;
// Prototypes _______________________________________________________________
// Console
// Buffered
void ConsoleBufferToDisplay ();
LPCSTR ConsoleBufferPeek ();
void ConsoleBufferPop ();
bool ConsoleBufferPush ( const TCHAR * pString );
// Display
Update_t ConsoleDisplayError (LPCTSTR errortext);
void ConsoleDisplayPause ();
void ConsoleDisplayPush ( LPCSTR pText );
Update_t ConsoleUpdate ();
// Input
void ConsoleInputToDisplay ();
LPCSTR ConsoleInputPeek ();
bool ConsoleInputClear ();
bool ConsoleInputBackSpace ();
bool ConsoleInputChar ( TCHAR ch );
void ConsoleInputReset ();
int ConsoleInputTabCompletion ();
void ConsoleBufferTryUnpause (int nLines);
// Scrolling
Update_t ConsoleScrollHome ();
Update_t ConsoleScrollEnd ();
Update_t ConsoleScrollUp ( int nLines );
Update_t ConsoleScrollDn ( int nLines );
Update_t ConsoleScrollPageUp ();
Update_t ConsoleScrollPageDn ();
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
#ifndef DEBUGGER_DISPLAY_H
#define DEBUGGER_DISPLAY_H
extern const int DISPLAY_HEIGHT;
extern FontConfig_t g_aFontConfig[ NUM_FONTS ];
int DebugDrawText ( LPCTSTR pText, RECT & rRect );
int DebugDrawTextFixed ( LPCTSTR pText, RECT & rRect );
int DebugDrawTextLine ( LPCTSTR pText, RECT & rRect );
int DebugDrawTextHorz ( LPCTSTR pText, RECT & rRect );
void DrawWindow_Source (Update_t bUpdate);
void DrawBreakpoints (HDC dc, int line);
void DrawConsoleInput (HDC dc);
void DrawConsoleLine (LPCSTR pText, int y);
WORD DrawDisassemblyLine (HDC dc, int line, WORD offset, LPTSTR text);
void DrawFlags (HDC dc, int line, WORD nRegFlags, LPTSTR pFlagNames_);
void DrawMemory (HDC dc, int line, int iMem );
void DrawRegister (HDC dc, int line, LPCTSTR name, int bytes, WORD value, int iSource = 0 );
void DrawStack (HDC dc, int line);
void DrawTargets (HDC dc, int line);
void DrawWatches (HDC dc, int line);
void DrawZeroPagePointers (HDC dc, int line);
#endif

View File

@ -0,0 +1,685 @@
/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006, Tom Charlesworth, Michael Pohoreski
AppleWin 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 2 of the License, or
(at your option) any later version.
AppleWin 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 AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Description: Debugger
*
* Author: Copyright (C) 2006, Michael Pohoreski
*/
#include "StdAfx.h"
#pragma hdrstop
// Utility ________________________________________________________________________________________
/*
String types:
http://www.codeproject.com/cpp/unicode.asp
TEXT() _tcsrev
_UNICODE Unicode _wcsrev
_MBCS Multi-byte _mbsrev
n/a ASCII strrev
*/
// tests if pSrc fits into pDst
// returns true if pSrc safely fits into pDst, else false (pSrc would of overflowed pDst)
//===========================================================================
bool TestStringCat ( TCHAR * pDst, LPCSTR pSrc, const int nDstSize )
{
int nLenDst = _tcslen( pDst );
int nLenSrc = _tcslen( pSrc );
int nSpcDst = nDstSize - nLenDst;
int nChars = MIN( nLenSrc, nSpcDst );
bool bOverflow = (nSpcDst < nLenSrc);
if (bOverflow)
{
return false;
}
return true;
}
// tests if pSrc fits into pDst
// returns true if pSrc safely fits into pDst, else false (pSrc would of overflowed pDst)
//===========================================================================
bool TryStringCat ( TCHAR * pDst, LPCSTR pSrc, const int nDstSize )
{
int nLenDst = _tcslen( pDst );
int nLenSrc = _tcslen( pSrc );
int nSpcDst = nDstSize - nLenDst;
int nChars = MIN( nLenSrc, nSpcDst );
bool bOverflow = (nSpcDst < nLenSrc);
if (bOverflow)
{
return false;
}
_tcsncat( pDst, pSrc, nChars );
return true;
}
// cats string as much as possible
// returns true if pSrc safely fits into pDst, else false (pSrc would of overflowed pDst)
//===========================================================================
bool StringCat ( TCHAR * pDst, LPCSTR pSrc, const int nDstSize )
{
int nLenDst = _tcslen( pDst );
int nLenSrc = _tcslen( pSrc );
int nSpcDst = nDstSize - nLenDst;
int nChars = MIN( nLenSrc, nSpcDst );
_tcsncat( pDst, pSrc, nChars );
bool bOverflow = (nSpcDst < nLenSrc);
if (bOverflow)
return false;
return true;
}
// Help ___________________________________________________________________________________________
//===========================================================================
Update_t HelpLastCommand()
{
return Help_Arg_1( g_iCommand );
}
// Loads the arguments with the command to get help on and call display help.
//===========================================================================
Update_t Help_Arg_1( int iCommandHelp )
{
_Arg_1( iCommandHelp );
wsprintf( g_aArgs[ 1 ].sArg, g_aCommands[ iCommandHelp ].m_sName ); // .3 Fixed: Help_Arg_1() now copies command name into arg.name
return CmdHelpSpecific( 1 );
}
//===========================================================================
Update_t CmdMOTD( int nArgs )
{
TCHAR sText[ CONSOLE_WIDTH ];
ConsoleBufferPush( TEXT(" Apple ][+ //e Emulator for Windows") );
CmdVersion(0);
CmdSymbols(0);
wsprintf( sText, " '~' console, '%s' (specific), '%s' (all)"
, g_aCommands[ CMD_HELP_SPECIFIC ].m_sName
// , g_aCommands[ CMD_HELP_SPECIFIC ].pHelpSummary
, g_aCommands[ CMD_HELP_LIST ].m_sName
// , g_aCommands[ CMD_HELP_LIST ].pHelpSummary
);
ConsoleBufferPush( sText );
ConsoleUpdate();
return UPDATE_ALL;
}
// Help on specific command
//===========================================================================
Update_t CmdHelpSpecific (int nArgs)
{
int iArg;
TCHAR sText[ CONSOLE_WIDTH ];
ZeroMemory( sText, CONSOLE_WIDTH );
if (! nArgs)
{
// ConsoleBufferPush( TEXT(" [] = optional, {} = mandatory. Categories are: ") );
_tcscpy( sText, TEXT("Usage: [{ ") );
for (int iCategory = _PARAM_HELPCATEGORIES_BEGIN ; iCategory < _PARAM_HELPCATEGORIES_END; iCategory++)
{
TCHAR *pName = g_aParameters[ iCategory ].m_sName;
if (! TestStringCat( sText, pName, g_nConsoleDisplayWidth - 3 )) // CONSOLE_WIDTH
{
ConsoleBufferPush( sText );
_tcscpy( sText, TEXT(" ") );
}
StringCat( sText, pName, CONSOLE_WIDTH );
if (iCategory < (_PARAM_HELPCATEGORIES_END - 1))
{
StringCat( sText, TEXT(" | "), CONSOLE_WIDTH );
}
}
StringCat( sText, TEXT(" }]"), CONSOLE_WIDTH );
ConsoleBufferPush( sText );
wsprintf( sText, TEXT("Note: [] = optional, {} = mandatory"), CONSOLE_WIDTH );
ConsoleBufferPush( sText );
}
bool bAllCommands = false;
bool bCategory = false;
if (! _tcscmp( g_aArgs[1].sArg, g_aParameters[ PARAM_WILDSTAR ].m_sName))
{
bAllCommands = true;
nArgs = NUM_COMMANDS;
}
// If Help on category, push command name as arg
int nNewArgs = 0;
int iCmdBegin = 0;
int iCmdEnd = 0;
for (iArg = 1; iArg <= nArgs; iArg++ )
{
int iParam;
int nFoundCategory = FindParam( g_aArgs[ iArg ].sArg, MATCH_EXACT, iParam, _PARAM_HELPCATEGORIES_BEGIN, _PARAM_HELPCATEGORIES_END );
switch( iParam )
{
case PARAM_CAT_BREAKPOINTS: iCmdBegin = CMD_BREAKPOINT ; iCmdEnd = CMD_BREAKPOINT_SAVE + 1; break;
case PARAM_CAT_CONFIG : iCmdBegin = CMD_CONFIG_COLOR ; iCmdEnd = CMD_CONFIG_SAVE + 1; break;
case PARAM_CAT_CPU : iCmdBegin = CMD_ASSEMBLE ; iCmdEnd = CMD_TRACE_LINE + 1; break;
case PARAM_CAT_FLAGS : iCmdBegin = CMD_FLAG_CLEAR ; iCmdEnd = CMD_FLAG_SET_N + 1; break;
case PARAM_CAT_MEMORY : iCmdBegin = CMD_MEMORY_COMPARE ; iCmdEnd = CMD_MEMORY_FILL + 1; break;
case PARAM_CAT_SYMBOLS : iCmdBegin = CMD_SYMBOLS_LOOKUP ; iCmdEnd = CMD_SYMBOLS_LIST + 1; break;
case PARAM_CAT_WATCHES : iCmdBegin = CMD_WATCH_ADD ; iCmdEnd = CMD_WATCH_LIST + 1; break;
case PARAM_CAT_WINDOW : iCmdBegin = CMD_WINDOW ; iCmdEnd = CMD_WINDOW_OUTPUT + 1; break;
case PARAM_CAT_ZEROPAGE : iCmdBegin = CMD_ZEROPAGE_POINTER; iCmdEnd = CMD_ZEROPAGE_POINTER_SAVE+1;break;
default: break;
}
nNewArgs = (iCmdEnd - iCmdBegin);
if (nNewArgs > 0)
break;
}
if (nNewArgs > 0)
{
bCategory = true;
nArgs = nNewArgs;
for (iArg = 1; iArg <= nArgs; iArg++ )
{
g_aArgs[ iArg ].nVal2 = iCmdBegin + iArg - 1;
}
}
CmdFuncPtr_t pFunction;
for (iArg = 1; iArg <= nArgs; iArg++ )
{
int iCommand = 0;
int nFound = FindCommand( g_aArgs[iArg].sArg, pFunction, & iCommand );
if (bCategory)
{
iCommand = g_aArgs[iArg].nVal2;
}
if (bAllCommands)
{
iCommand = iArg;
if (iCommand == NUM_COMMANDS) // skip: Internal Consistency Check __COMMANDS_VERIFY_TXT__
continue;
}
if (nFound > 1)
{
DisplayAmbigiousCommands( nFound );
}
if (iCommand > NUM_COMMANDS)
continue;
if ((nArgs == 1) && (! nFound))
iCommand = g_aArgs[iArg].nVal1;
Command_t *pCommand = & g_aCommands[ iCommand ];
if (! nFound)
{
iCommand = NUM_COMMANDS;
pCommand = NULL;
}
if (nFound && (! bAllCommands))
{
TCHAR sCategory[ CONSOLE_WIDTH ];
int iCmd = g_aCommands[ iCommand ].iCommand; // Unaliased command
// HACK: Major kludge to display category!!!
if (iCmd <= CMD_TRACE_LINE)
wsprintf( sCategory, "Main" );
else
if (iCmd <= CMD_BREAKPOINT_SAVE)
wsprintf( sCategory, "Breakpoint" );
else
if (iCmd <= CMD_PROFILE)
wsprintf( sCategory, "Profile" );
else
if (iCmd <= CMD_CONFIG_SAVE)
wsprintf( sCategory, "Config" );
else
if (iCmd <= CMD_CURSOR_PAGE_DOWN_4K)
wsprintf( sCategory, "Scrolling" );
else
if (iCmd <= CMD_FLAG_SET_N)
wsprintf( sCategory, "Flags" );
else
if (iCmd <= CMD_MOTD)
wsprintf( sCategory, "Help" );
else
if (iCmd <= CMD_MEMORY_FILL)
wsprintf( sCategory, "Memory" );
else
if (iCmd <= CMD_REGISTER_SET)
wsprintf( sCategory, "Registers" );
else
if (iCmd <= CMD_SYNC)
wsprintf( sCategory, "Source" );
else
if (iCmd <= CMD_STACK_PUSH)
wsprintf( sCategory, "Stack" );
else
if (iCmd <= CMD_SYMBOLS_LIST)
wsprintf( sCategory, "Symbols" );
else
if (iCmd <= CMD_WATCH_SAVE)
wsprintf( sCategory, "Watch" );
else
if (iCmd <= CMD_WINDOW_OUTPUT)
wsprintf( sCategory, "Window" );
else
if (iCmd <= CMD_ZEROPAGE_POINTER_SAVE)
wsprintf( sCategory, "Zero Page" );
else
wsprintf( sCategory, "Unknown!" );
wsprintf( sText, "Category: %s", sCategory );
ConsoleBufferPush( sText );
}
if (pCommand)
{
char *pHelp = pCommand->pHelpSummary;
if (pHelp)
{
wsprintf( sText, "%s, ", pCommand->m_sName );
if (! TryStringCat( sText, pHelp, g_nConsoleDisplayWidth ))
{
if (! TryStringCat( sText, pHelp, CONSOLE_WIDTH ))
{
StringCat( sText, pHelp, CONSOLE_WIDTH );
ConsoleBufferPush( sText );
}
}
ConsoleBufferPush( sText );
}
else
{
wsprintf( sText, "%s", pCommand->m_sName );
ConsoleBufferPush( sText );
#if DEBUG_COMMAND_HELP
if (! bAllCommands) // Release version doesn't display message
{
wsprintf( sText, "Missing Summary Help: %s", g_aCommands[ iCommand ].aName );
ConsoleBufferPush( sText );
}
#endif
}
}
// MASTER HELP
switch (iCommand)
{
// CPU / General
case CMD_ASSEMBLE:
ConsoleBufferPush( TEXT(" Built-in assember isn't functional yet.") );
break;
case CMD_UNASSEMBLE:
ConsoleBufferPush( TEXT(" Usage: {address | symbol}") );
ConsoleBufferPush( TEXT(" Disassembles memory.") );
break;
case CMD_CALC:
ConsoleBufferPush( TEXT(" Usage: {address | symbol | + | - }" ) );
ConsoleBufferPush( TEXT(" Output order is: Hex Bin Dec Char" ) );
ConsoleBufferPush( TEXT(" Note: symbols take piority." ) );
ConsoleBufferPush( TEXT("i.e. #A (if you don't want accum. val)" ) );
ConsoleBufferPush( TEXT("i.e. #F (if you don't want flags val)" ) );
break;
case CMD_GO:
ConsoleBufferPush( TEXT(" Usage: [address | symbol [Skip,End]]") );
ConsoleBufferPush( TEXT(" Skip: Start address to skip stepping" ) );
ConsoleBufferPush( TEXT(" End : End address to skip stepping" ) );
ConsoleBufferPush( TEXT(" If the Program Counter is outside the" ) );
ConsoleBufferPush( TEXT(" skip range, resumes single-stepping." ) );
ConsoleBufferPush( TEXT(" Can be used to skip ROM/OS/user code." ));
ConsoleBufferPush( TEXT(" i.e. G C600 F000,FFFF" ) );
break;
case CMD_NOP:
ConsoleBufferPush( TEXT(" Puts a NOP opcode at current instruction") );
break;
case CMD_JSR:
ConsoleBufferPush( TEXT(" Usage: {symbol | address}") );
ConsoleBufferPush( TEXT(" Pushes PC on stack; calls the named subroutine.") );
break;
case CMD_PROFILE:
wsprintf( sText, TEXT(" Usage: [%s | %s | %s]")
, g_aParameters[ PARAM_RESET ].m_sName
, g_aParameters[ PARAM_SAVE ].m_sName
, g_aParameters[ PARAM_LIST ].m_sName
);
ConsoleBufferPush( sText );
ConsoleBufferPush( TEXT(" No arguments resets the profile.") );
break;
case CMD_SOURCE:
ConsoleBufferPush( TEXT(" Reads assembler source file." ) );
wsprintf( sText, TEXT(" Usage: [ %s | %s ] \"filename\"" ), g_aParameters[ PARAM_SRC_MEMORY ].m_sName, g_aParameters[ PARAM_SRC_SYMBOLS ].m_sName ); ConsoleBufferPush( sText );
wsprintf( sText, TEXT(" %s: read source bytes into memory." ), g_aParameters[ PARAM_SRC_MEMORY ].m_sName ); ConsoleBufferPush( sText );
wsprintf( sText, TEXT(" %s: read symbols into Source symbol table."), g_aParameters[ PARAM_SRC_SYMBOLS ].m_sName ); ConsoleBufferPush( sText );
wsprintf( sText, TEXT(" Supports: %s." ), g_aParameters[ PARAM_SRC_MERLIN ].m_sName ); ConsoleBufferPush( sText );
break;
case CMD_STEP_OUT:
ConsoleBufferPush( TEXT(" Steps out of current subroutine") );
ConsoleBufferPush( TEXT(" Hotkey: Ctrl-Space" ) );
break;
case CMD_STEP_OVER: // Bad name? FIXME/TODO: do we need to rename?
ConsoleBufferPush( TEXT(" Usage: [#]") );
ConsoleBufferPush( TEXT(" Steps, # times, thru current instruction") );
ConsoleBufferPush( TEXT(" JSR will be stepped into AND out of.") );
ConsoleBufferPush( TEXT(" Hotkey: Ctrl-Space" ) );
break;
case CMD_TRACE:
ConsoleBufferPush( TEXT(" Usage: [#]") );
ConsoleBufferPush( TEXT(" Traces, # times, current instruction(s)") );
ConsoleBufferPush( TEXT(" JSR will be stepped into") );
ConsoleBufferPush( TEXT(" Hotkey: Shift-Space" ) );
case CMD_TRACE_FILE:
ConsoleBufferPush( TEXT(" Usage: [filename]") );
break;
case CMD_TRACE_LINE:
ConsoleBufferPush( TEXT(" Usage: [#]") );
ConsoleBufferPush( TEXT(" Traces into current instruction") );
ConsoleBufferPush( TEXT(" with cycle counting." ) );
break;
// Breakpoints
case CMD_BREAKPOINT:
wsprintf( sText, " Maximum breakpoints are: %d", MAX_BREAKPOINTS );
ConsoleBufferPush( sText );
break;
case CMD_BREAKPOINT_ADD_REG:
ConsoleBufferPush( TEXT(" Usage: [A|X|Y|PC|S] [<,=,>] value") );
ConsoleBufferPush( TEXT(" Set breakpoint when reg is [op] value") );
break;
case CMD_BREAKPOINT_ADD_SMART:
case CMD_BREAKPOINT_ADD_PC:
ConsoleBufferPush( TEXT(" Usage: [address]") );
ConsoleBufferPush( TEXT(" Sets a breakpoint at the current PC") );
ConsoleBufferPush( TEXT(" or at the specified address.") );
break;
case CMD_BREAKPOINT_ENABLE:
ConsoleBufferPush( TEXT(" Usage: [# [,#] | *]") );
ConsoleBufferPush( TEXT(" Re-enables breakpoint previously set, or all.") );
break;
// Config - Color
case CMD_CONFIG_COLOR:
ConsoleBufferPush( TEXT(" Usage: [{#} | {# RR GG BB}]" ) );
ConsoleBufferPush( TEXT(" 0 params: switch to 'color' scheme" ) );
ConsoleBufferPush( TEXT(" 1 param : dumps R G B for scheme 'color'") );
ConsoleBufferPush( TEXT(" 4 params: sets R G B for scheme 'color'" ) );
break;
case CMD_CONFIG_MONOCHROME:
ConsoleBufferPush( TEXT(" Usage: [{#} | {# RR GG BB}]" ) );
ConsoleBufferPush( TEXT(" 0 params: switch to 'monochrome' scheme" ) );
ConsoleBufferPush( TEXT(" 1 param : dumps R G B for scheme 'monochrome'") );
ConsoleBufferPush( TEXT(" 4 params: sets R G B for scheme 'monochrome'" ) );
break;
case CMD_OUTPUT:
ConsoleBufferPush( TEXT(" Usage: {address8 | address16 | symbol} ## [##]") );
ConsoleBufferPush( TEXT(" Ouput a byte or word to the IO address $C0xx" ) );
break;
// Config - Font
case CMD_CONFIG_FONT:
wsprintf( sText, TEXT(" Usage: [%s | %s] \"FontName\" [Height]" ),
g_aParameters[ PARAM_FONT_MODE ].m_sName, g_aParameters[ PARAM_DISASM ].m_sName );
ConsoleBufferPush( sText );
ConsoleBufferPush( TEXT(" i.e. FONT \"Courier\" 12" ) );
ConsoleBufferPush( TEXT(" i.e. FONT \"Lucida Console\" 12" ) );
wsprintf( sText, TEXT(" %s Controls line spacing."), g_aParameters[ PARAM_FONT_MODE ].m_sName );
ConsoleBufferPush( sText );
wsprintf( sText, TEXT(" Valid values are: %d, %d, %d." ),
FONT_SPACING_CLASSIC, FONT_SPACING_CLEAN, FONT_SPACING_COMPRESSED );
ConsoleBufferPush( sText );
break;
// Memory
case CMD_MEMORY_ENTER_BYTE:
ConsoleBufferPush( TEXT(" Usage: {address | symbol} ## [## ... ##]") );
ConsoleBufferPush( TEXT(" Sets memory to the specified 8-Bit Values (bytes)" ) );
break;
case CMD_MEMORY_ENTER_WORD:
ConsoleBufferPush( TEXT(" Usage: {address | symbol} #### [#### ... ####]") );
ConsoleBufferPush( TEXT(" Sets memory to the specified 16-Bit Values (words)" ) );
break;
case CMD_MEMORY_FILL:
ConsoleBufferPush( TEXT(" Usage: {address | symbol} {address | symbol} ##" ) );
ConsoleBufferPush( TEXT(" Fills the memory range with the specified byte" ) );
ConsoleBufferPush( TEXT(" Can't fill IO address $C0xx" ) );
break;
// case CMD_MEM_MINI_DUMP_ASC_1:
// case CMD_MEM_MINI_DUMP_ASC_2:
case CMD_MEM_MINI_DUMP_ASCII_1:
case CMD_MEM_MINI_DUMP_ASCII_2:
ConsoleBufferPush( TEXT(" Usage: {address | symbol}") );
ConsoleBufferPush( TEXT(" Displays ASCII text in the Mini-Memory area") );
ConsoleBufferPush( TEXT(" ASCII control chars are hilighted") );
ConsoleBufferPush( TEXT(" ASCII hi-bit chars are normal") );
// break;
// case CMD_MEM_MINI_DUMP_TXT_LO_1:
// case CMD_MEM_MINI_DUMP_TXT_LO_2:
case CMD_MEM_MINI_DUMP_APPLE_1:
case CMD_MEM_MINI_DUMP_APPLE_2:
ConsoleBufferPush( TEXT(" Usage: {address | symbol}") );
ConsoleBufferPush( TEXT(" Displays APPLE text in the Mini-Memory area") );
ConsoleBufferPush( TEXT(" APPLE control chars are inverse") );
ConsoleBufferPush( TEXT(" APPLE hi-bit chars are normal") );
break;
// case CMD_MEM_MINI_DUMP_TXT_HI_1:
// case CMD_MEM_MINI_DUMP_TXT_HI_2:
// ConsoleBufferPush( TEXT(" Usage: {address | symbol}") );
// ConsoleBufferPush( TEXT(" Displays text in the Memory Mini-Dump area") );
// ConsoleBufferPush( TEXT(" ASCII chars with the hi-bit set, is inverse") );
break;
// Symbols
case CMD_SYMBOLS_MAIN:
case CMD_SYMBOLS_USER:
case CMD_SYMBOLS_SRC :
// ConsoleBufferPush( TEXT(" Usage: [ ON | OFF | symbol | address ]" ) );
// ConsoleBufferPush( TEXT(" Usage: [ LOAD [\"filename\"] | SAVE \"filename\"]" ) );
// ConsoleBufferPush( TEXT(" ON : Turns symbols on in the disasm window" ) );
// ConsoleBufferPush( TEXT(" OFF : Turns symbols off in the disasm window" ) );
// ConsoleBufferPush( TEXT(" LOAD: Loads symbols from last/default filename" ) );
// ConsoleBufferPush( TEXT(" SAVE: Saves symbol table to file" ) );
// ConsoleBufferPush( TEXT(" CLEAR: Clears the symbol table" ) );
ConsoleBufferPush( TEXT(" Usage: [ ... | symbol | address ]") );
ConsoleBufferPush( TEXT(" Where ... is one of:" ) );
wsprintf( sText, TEXT(" %s " ": Turns symbols on in the disasm window" ), g_aParameters[ PARAM_ON ].m_sName ); ConsoleBufferPush( sText );
wsprintf( sText, TEXT(" %s " ": Turns symbols off in the disasm window" ), g_aParameters[ PARAM_OFF ].m_sName ); ConsoleBufferPush( sText );
wsprintf( sText, TEXT(" %s" ": Loads symbols from last/default \"filename\"" ), g_aParameters[ PARAM_SAVE ].m_sName ); ConsoleBufferPush( sText );
wsprintf( sText, TEXT(" %s" ": Saves symbol table to \"filename\"" ), g_aParameters[ PARAM_LOAD ].m_sName ); ConsoleBufferPush( sText );
wsprintf( sText, TEXT(" %s" ": Clears the symbol table" ), g_aParameters[ PARAM_CLEAR ].m_sName ); ConsoleBufferPush( sText );
break;
// Watches
case CMD_WATCH_ADD:
ConsoleBufferPush( TEXT(" Usage: {address | symbol}" ) );
ConsoleBufferPush( TEXT(" Adds the specified memory location to the watch window." ) );
break;
// Window
case CMD_WINDOW_CODE : // summary is good enough
case CMD_WINDOW_CODE_2 : // summary is good enough
case CMD_WINDOW_SOURCE_2: // summary is good enough
break;
// Misc
case CMD_VERSION:
ConsoleBufferPush( TEXT(" Usage: [*]") );
ConsoleBufferPush( TEXT(" * Display extra internal stats" ) );
break;
default:
if (bAllCommands)
break;
#if DEBUG_COMMAND_HELP
wsprintf( sText, "Command help not done yet: %s", g_aCommands[ iCommand ].aName );
ConsoleBufferPush( sText );
#endif
if ((! nFound) || (! pCommand))
{
wsprintf( sText, " Invalid command." );
ConsoleBufferPush( sText );
}
break;
}
}
return ConsoleUpdate();
}
//===========================================================================
Update_t CmdHelpList (int nArgs)
{
TCHAR sText[ CONSOLE_WIDTH ] = TEXT("Commands: ");
int nLenLine = _tcslen( sText );
int y = 0;
int nLinesScrolled = 0;
int nMaxWidth = g_nConsoleDisplayWidth - 1;
int iCommand;
/*
if (! g_vSortedCommands.size())
{
for (iCommand = 0; iCommand < NUM_COMMANDS_WITH_ALIASES; iCommand++ )
{
// TCHAR *pName = g_aCommands[ iCommand ].aName );
g_vSortedCommands.push_back( g_aCommands[ iCommand ] );
}
std::sort( g_vSortedCommands.begin(), g_vSortedCommands.end(), commands_functor_compare() );
}
int nCommands = g_vSortedCommands.size();
*/
for( iCommand = 0; iCommand < NUM_COMMANDS_WITH_ALIASES; iCommand++ ) // aliases are not printed
{
// Command_t *pCommand = & g_vSortedCommands.at( iCommand );
Command_t *pCommand = & g_aCommands[ iCommand ];
TCHAR *pName = pCommand->m_sName;
if (! pCommand->pFunction)
continue; // not implemented function
int nLenCmd = _tcslen( pName );
if ((nLenLine + nLenCmd) < (nMaxWidth))
{
_tcscat( sText, pName );
}
else
{
ConsoleBufferPush( sText );
nLenLine = 1;
_tcscpy( sText, TEXT(" " ) );
_tcscat( sText, pName );
}
_tcscat( sText, TEXT(" ") );
nLenLine += (nLenCmd + 1);
}
ConsoleBufferPush( sText );
ConsoleUpdate();
return UPDATE_CONSOLE_DISPLAY;
}
//===========================================================================
Update_t CmdVersion (int nArgs)
{
TCHAR sText[ CONSOLE_WIDTH ];
unsigned int nVersion = DEBUGGER_VERSION;
int nMajor;
int nMinor;
int nFixMajor;
int nFixMinor;
UnpackVersion( nVersion, nMajor, nMinor, nFixMajor, nFixMinor );
// wsprintf( sText, "Version" ); ConsoleBufferPush( sText );
wsprintf( sText, " Emulator: %s Debugger: %d.%d.%d.%d"
, VERSIONSTRING
, nMajor, nMinor, nFixMajor, nFixMinor );
ConsoleBufferPush( sText );
if (nArgs)
{
for (int iArg = 1; iArg <= nArgs; iArg++ )
{
if (_tcscmp( g_aArgs[ iArg ].sArg, g_aParameters[ PARAM_WILDSTAR ].m_sName ) == 0)
{
wsprintf( sText, " Arg: %d bytes * %d = %d bytes",
sizeof(Arg_t), MAX_ARGS, sizeof(g_aArgs) );
ConsoleBufferPush( sText );
wsprintf( sText, " Console: %d bytes * %d height = %d bytes",
sizeof( g_aConsoleDisplay[0] ), CONSOLE_HEIGHT, sizeof(g_aConsoleDisplay) );
ConsoleBufferPush( sText );
wsprintf( sText, " Commands: %d (Aliased: %d) Params: %d",
NUM_COMMANDS, NUM_COMMANDS_WITH_ALIASES, NUM_PARAMS );
ConsoleBufferPush( sText );
wsprintf( sText, " Cursor(%d) T: %04X C: %04X B: %04X %c D: %02X", // Top, Cur, Bot, Delta
g_nDisasmCurLine, g_nDisasmTopAddress, g_nDisasmCurAddress, g_nDisasmBotAddress,
g_bDisasmCurBad ? TEXT('*') : TEXT(' ')
, g_nDisasmBotAddress - g_nDisasmTopAddress
);
ConsoleBufferPush( sText );
CmdConfigGetFont( 0 );
break;
}
else
return Help_Arg_1( CMD_VERSION );
}
}
return ConsoleUpdate();
}

View File

@ -0,0 +1,30 @@
#ifndef DEBUGGER_HELP_H
#define DEBUGGER_HELP_H
enum Match_e
{
MATCH_EXACT,
MATCH_FUZZY
};
// Prototypes _______________________________________________________________
Update_t HelpLastCommand();
void DisplayAmbigiousCommands ( int nFound );
int FindParam( LPTSTR pLookupName, Match_e eMatch, int & iParam_, const int iParamBegin = 0, const int iParamEnd = NUM_PARAMS - 1 );
int FindCommand( LPTSTR pName, CmdFuncPtr_t & pFunction_, int * iCommand_ = NULL );
inline void UnpackVersion( const unsigned int nVersion,
int & nMajor_, int & nMinor_, int & nFixMajor_ , int & nFixMinor_ )
{
nMajor_ = (nVersion >> 24) & 0xFF;
nMinor_ = (nVersion >> 16) & 0xFF;
nFixMajor_ = (nVersion >> 8) & 0xFF;
nFixMinor_ = (nVersion >> 0) & 0xFF;
}
#endif

View File

@ -0,0 +1,945 @@
/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006, Tom Charlesworth, Michael Pohoreski
AppleWin 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 2 of the License, or
(at your option) any later version.
AppleWin 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 AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Description: Debugger
*
* Author: Copyright (C) 2006, Michael Pohoreski
*/
#include "StdAfx.h"
#pragma hdrstop
// Args ___________________________________________________________________________________________
int g_nArgRaw;
Arg_t g_aArgRaw[ MAX_ARGS ]; // pre-processing
Arg_t g_aArgs [ MAX_ARGS ]; // post-processing (cooked)
const TCHAR TCHAR_LF = TEXT('\x0D');
const TCHAR TCHAR_CR = TEXT('\x0A');
const TCHAR TCHAR_SPACE = TEXT(' ');
const TCHAR TCHAR_TAB = TEXT('\t');
const TCHAR TCHAR_QUOTED = TEXT('"');
const TCHAR TCHAR_ESCAPE = TEXT('\x1B');
// NOTE: Token_e and g_aTokens must match!
const TokenTable_t g_aTokens[ NUM_TOKENS ] =
{ // Input
{ TOKEN_ALPHANUMERIC, TYPE_STRING , 0 }, // Default, if doen't match anything else
{ TOKEN_AMPERSAND , TYPE_OPERATOR, TEXT('&') }, // bit-and
// { TOKEN_AT , TYPE_OPERATOR, TEXT('@') }, // force Register? or PointerDeref?
{ TOKEN_BSLASH , TYPE_OPERATOR, TEXT('\\') },
{ TOKEN_CARET , TYPE_OPERATOR, TEXT('^') }, // bit-eor, C/C++: xor, Math: POWER
{ TOKEN_COLON , TYPE_OPERATOR, TEXT(':') },
{ TOKEN_COMMA , TYPE_OPERATOR, TEXT(',') },
{ TOKEN_DOLLAR , TYPE_STRING , TEXT('$') },
{ TOKEN_EQUAL , TYPE_OPERATOR, TEXT('=') },
{ TOKEN_EXCLAMATION , TYPE_OPERATOR, TEXT('!') }, // NOT
{ TOKEN_FSLASH , TYPE_OPERATOR, TEXT('/') }, // div
{ TOKEN_GREATER_THAN, TYPE_OPERATOR, TEXT('>') }, // TODO/FIXME: Parser will break up '>=' (needed for uber breakpoints)
{ TOKEN_HASH , TYPE_OPERATOR, TEXT('#') },
{ TOKEN_LEFT_PAREN , TYPE_OPERATOR, TEXT('(') },
{ TOKEN_LESS_THAN , TYPE_OPERATOR, TEXT('<') },
{ TOKEN_MINUS , TYPE_OPERATOR, TEXT('-') }, // sub
{ TOKEN_PERCENT , TYPE_OPERATOR, TEXT('%') }, // mod
{ TOKEN_PIPE , TYPE_OPERATOR, TEXT('|') }, // bit-or
{ TOKEN_PLUS , TYPE_OPERATOR, TEXT('+') }, // add
{ TOKEN_QUOTED , TYPE_QUOTED , TEXT('"') },
{ TOKEN_RIGHT_PAREN , TYPE_OPERATOR, TEXT(')') },
{ TOKEN_SEMI , TYPE_STRING , TEXT(';') },
{ TOKEN_SPACE , TYPE_STRING , TEXT(' ') } // space is also a delimiter between tokens/args
// { TOKEN_STAR , TYPE_OPERATOR, TEXT('*') },
// { TOKEN_TAB , TYPE_STRING , TEXT('\t') }
// { TOKEN_TILDE , TYPE_OPERATOR, TEXT('~') }, // C/C++: Not. Used for console.
};
// const TokenTable_t g_aTokens2[ ] =
// { // Input
// { TOKEN_GREATER_EQUAL,TYPE_OPERATOR, TEXT(">=\x00") }, // TODO/FIXME: Parser will break up '>=' (needed for uber breakpoints)
// { TOKEN_LESS_EQUAL , TYPE_OPERATOR, TEXT("<=\x00") }, // TODO/FIXME: Parser will break up '<=' (needed for uber breakpoints)
// }
// Arg ____________________________________________________________________________________________
//===========================================================================
int _Arg_1( int nValue )
{
g_aArgs[1].nVal1 = nValue;
return 1;
}
//===========================================================================
int _Arg_1( LPTSTR pName )
{
int nLen = _tcslen( g_aArgs[1].sArg );
if (nLen < MAX_ARG_LEN)
{
_tcscpy( g_aArgs[1].sArg, pName );
}
else
{
_tcsncpy( g_aArgs[1].sArg, pName, MAX_ARG_LEN - 1 );
}
return 1;
}
/**
@description Copies Args[iSrc .. iEnd] to Args[0]
@param iSrc First argument to copy
@param iEnd Last argument to end
@return nArgs Number of new args
Usually called as: nArgs = _Arg_Shift( iArg, nArgs );
//=========================================================================== */
int _Arg_Shift( int iSrc, int iEnd, int iDst )
{
if (iDst < 0)
return ARG_SYNTAX_ERROR;
if (iDst > MAX_ARGS)
return ARG_SYNTAX_ERROR;
int nArgs = (iEnd - iSrc);
int nLen = nArgs + 1;
if ((iDst + nLen) > MAX_ARGS)
return ARG_SYNTAX_ERROR;
while (nLen--)
{
g_aArgs[iDst] = g_aArgs[iSrc];
iSrc++;
iDst++;
}
return nArgs;
}
//===========================================================================
void ArgsClear ()
{
Arg_t *pArg = &g_aArgs[0];
for (int iArg = 0; iArg < MAX_ARGS; iArg++ )
{
pArg->bSymbol = false;
pArg->eDevice = NUM_DEVICES; // none
pArg->eToken = NO_TOKEN ; // none
pArg->bType = TYPE_STRING;
pArg->nVal1 = 0;
pArg->nVal2 = 0;
pArg->sArg[0] = 0;
pArg++;
}
}
//===========================================================================
bool ArgsGetValue ( Arg_t *pArg, WORD * pAddressValue_, const int nBase )
{
TCHAR *pSrc = & (pArg->sArg[ 0 ]);
TCHAR *pEnd = NULL;
if (pArg && pAddressValue_)
{
*pAddressValue_ = (WORD)(_tcstoul( pSrc, &pEnd, nBase) & _6502_END_MEM_ADDRESS);
return true;
}
return false;
}
//===========================================================================
bool ArgsGetImmediateValue ( Arg_t *pArg, WORD * pAddressValue_ )
{
if (pArg && pAddressValue_)
{
if (pArg->eToken == TOKEN_HASH)
{
pArg++;
return ArgsGetValue( pArg, pAddressValue_ );
}
}
return false;
}
// Processes the raw args, turning them into tokens and types.
//===========================================================================
int ArgsGet ( TCHAR * pInput )
{
LPCTSTR pSrc = pInput;
LPCTSTR pEnd = NULL;
int nBuf;
ArgToken_e iTokenSrc = NO_TOKEN;
ArgToken_e iTokenEnd = NO_TOKEN;
ArgType_e iType = TYPE_STRING;
int nLen;
int iArg = 0;
int nArg = 0;
Arg_t *pArg = &g_aArgRaw[0]; // &g_aArgs[0];
g_pConsoleFirstArg = NULL;
// BP FAC8:FACA // Range=3
// BP FAC8,2 // Length=2
// ^ ^^ ^^
// | || |pSrc
// | || pSrc
// | |pSrc
// | pEnd
// pSrc
while ((*pSrc) && (iArg < MAX_ARGS))
{
// Technically, there shouldn't be any leading spaces,
// since pressing the spacebar is an alias for TRACE.
// However, there is spaces between arguments
pSrc = const_cast<char*>( SkipWhiteSpace( pSrc ));
if (pSrc)
{
pEnd = FindTokenOrAlphaNumeric( pSrc, g_aTokens, NUM_TOKENS, &iTokenSrc );
if ((iTokenSrc == NO_TOKEN) || (iTokenSrc == TOKEN_ALPHANUMERIC))
{
pEnd = SkipUntilToken( pSrc+1, g_aTokens, NUM_TOKENS, &iTokenEnd );
}
if (iTokenSrc == NO_TOKEN)
{
iTokenSrc = TOKEN_ALPHANUMERIC;
}
iType = g_aTokens[ iTokenSrc ].eType;
if (iTokenSrc == TOKEN_SEMI)
{
// TODO - command seperator, must handle non-quoted though!
}
if (iTokenSrc == TOKEN_QUOTED)
{
pSrc++; // Don't store start of quote
pEnd = SkipUntilChar( pSrc, CHAR_QUOTED );
}
if (pEnd)
{
nBuf = pEnd - pSrc;
}
if (nBuf > 0)
{
nLen = MIN( nBuf, MAX_ARG_LEN-1 );
_tcsncpy( pArg->sArg, pSrc, nLen );
pArg->sArg[ nLen ] = 0;
pArg->nArgLen = nLen;
pArg->eToken = iTokenSrc;
pArg->bType = iType;
if (iTokenSrc == TOKEN_QUOTED)
{
pEnd++;
}
pSrc = pEnd;
iArg++;
pArg++;
if (iArg == 1)
{
g_pConsoleFirstArg = pSrc;
}
}
}
}
if (iArg)
{
nArg = iArg - 1; // first arg is command
}
g_nArgRaw = iArg;
return nArg;
}
//===========================================================================
bool ArgsGetRegisterValue ( Arg_t *pArg, WORD * pAddressValue_ )
{
bool bStatus = false;
if (pArg && pAddressValue_)
{
// Check if we refer to reg A X Y P S
for( int iReg = 0; iReg < (NUM_BREAKPOINT_SOURCES-1); iReg++ )
{
// Skip Opcode/Instruction/Mnemonic
if (iReg == BP_SRC_OPCODE)
continue;
// Skip individual flag names
if ((iReg >= BP_SRC_FLAG_C) && (iReg <= BP_SRC_FLAG_N))
continue;
// Handle one char names
if ((pArg->nArgLen == 1) && (pArg->sArg[0] == g_aBreakpointSource[ iReg ][0]))
{
switch( iReg )
{
case BP_SRC_REG_A : *pAddressValue_ = regs.a & 0xFF; bStatus = true; break;
case BP_SRC_REG_P : *pAddressValue_ = regs.ps & 0xFF; bStatus = true; break;
case BP_SRC_REG_X : *pAddressValue_ = regs.x & 0xFF; bStatus = true; break;
case BP_SRC_REG_Y : *pAddressValue_ = regs.y & 0xFF; bStatus = true; break;
case BP_SRC_REG_S : *pAddressValue_ = regs.sp ; bStatus = true; break;
default:
break;
}
}
else
if (iReg == BP_SRC_REG_PC)
{
if ((pArg->nArgLen == 2) && (_tcscmp( pArg->sArg, g_aBreakpointSource[ iReg ] ) == 0))
{
*pAddressValue_ = regs.pc ; bStatus = true; break;
}
}
}
}
return bStatus;
}
//===========================================================================
void ArgsRawParse ( void )
{
const int BASE = 16; // hex
TCHAR *pSrc = NULL;
TCHAR *pEnd = NULL;
int iArg = 1;
Arg_t *pArg = & g_aArgRaw[ iArg ];
int nArg = g_nArgRaw;
WORD nAddressArg;
WORD nAddressSymbol;
WORD nAddressValue;
int nParamLen = 0;
while (iArg <= nArg)
{
pSrc = & (pArg->sArg[ 0 ]);
nAddressArg = (WORD)(_tcstoul( pSrc, &pEnd, BASE) & _6502_END_MEM_ADDRESS);
nAddressValue = nAddressArg;
bool bFound = false;
if (! (pArg->bType & TYPE_NO_SYM))
{
bFound = FindAddressFromSymbol( pSrc, & nAddressSymbol );
if (bFound)
{
nAddressValue = nAddressSymbol;
pArg->bSymbol = true;
}
}
if (! (pArg->bType & TYPE_VALUE)) // already up to date?
pArg->nVal1 = nAddressValue;
pArg->bType |= TYPE_ADDRESS;
iArg++;
pArg++;
}
}
// Note: The number of args can be changed via:
// address1,length Length
// address1:address2 Range
// address1+delta Delta
// address1-delta Delta
//===========================================================================
int ArgsCook ( const int nArgs )
{
const int BASE = 16; // hex
TCHAR *pSrc = NULL;
TCHAR *pEnd2 = NULL;
int nArg = nArgs;
int iArg = 1;
Arg_t *pArg = NULL;
Arg_t *pPrev = NULL;
Arg_t *pNext = NULL;
WORD nAddressArg;
WORD nAddressRHS;
WORD nAddressSym;
WORD nAddressVal;
int nParamLen = 0;
int nArgsLeft = 0;
while (iArg <= nArg)
{
pArg = & (g_aArgs[ iArg ]);
pSrc = & (pArg->sArg[ 0 ]);
if (pArg->eToken == TOKEN_DOLLAR) // address
{
// TODO: Need to flag was a DOLLAR token for assembler
pNext = NULL;
nArgsLeft = (nArg - iArg);
if (nArgsLeft > 0)
{
pNext = pArg + 1;
_Arg_Shift( iArg + 1, nArgs, iArg );
nArg--;
iArg--; // inc for start of next loop
// Don't do register lookup
pArg->bType |= TYPE_NO_REG;
}
else
return ARG_SYNTAX_ERROR;
}
if (pArg->bType & TYPE_OPERATOR) // prev op type == address?
{
pPrev = NULL; // pLHS
pNext = NULL; // pRHS
nParamLen = 0;
if (pArg->eToken == TOKEN_HASH) // HASH # immediate
nParamLen = 1;
nArgsLeft = (nArg - iArg);
if (nArgsLeft < nParamLen)
{
return ARG_SYNTAX_ERROR;
}
pPrev = pArg - 1;
if (nArgsLeft > 0) // These ops take at least 1 argument
{
pNext = pArg + 1;
pSrc = &pNext->sArg[0];
nAddressVal = 0;
if (ArgsGetValue( pNext, & nAddressRHS ))
nAddressVal = nAddressRHS;
bool bFound = FindAddressFromSymbol( pSrc, & nAddressSym );
if (bFound)
{
nAddressVal = nAddressSym;
pArg->bSymbol = true;
}
if (pArg->eToken == TOKEN_COMMA) // COMMMA , length
{
pPrev->nVal2 = nAddressVal;
pPrev->eToken = TOKEN_COMMA;
pPrev->bType |= TYPE_ADDRESS;
pPrev->bType |= TYPE_LENGTH;
nParamLen = 2;
}
if (pArg->eToken == TOKEN_COLON) // COLON : range
{
pPrev->nVal2 = nAddressVal;
pPrev->eToken = TOKEN_COLON;
pPrev->bType |= TYPE_ADDRESS;
pPrev->bType |= TYPE_RANGE;
nParamLen = 2;
}
if (pArg->eToken == TOKEN_AMPERSAND) // AND & delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 &= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_PIPE) // OR | delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 |= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_CARET) // XOR ^ delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 ^= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_PLUS) // PLUS + delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 += nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_MINUS) // MINUS - delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 -= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_PERCENT) // PERCENT % delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 %= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_FSLASH) // FORWARD SLASH / delta
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
ArgsGetRegisterValue( pNext, & nAddressRHS );
}
pPrev->nVal1 /= nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 2;
}
if (pArg->eToken == TOKEN_EQUAL) // EQUAL = assign
{
pPrev->nVal1 = nAddressRHS;
pPrev->bType |= TYPE_VALUE; // signal already up to date
nParamLen = 0; // need token for Smart BreakPoints
}
if (pArg->eToken == TOKEN_HASH) // HASH # immediate
{
_Arg_Shift( iArg + nParamLen, nArgs, iArg );
nArg--;
pArg->nVal1 = nAddressRHS;
pArg->bSymbol = false;
pArg->bType = TYPE_VALUE | TYPE_ADDRESS | TYPE_NO_REG | TYPE_NO_SYM;
nParamLen = 0;
}
if (pArg->eToken == TOKEN_LESS_THAN) // <
{
nParamLen = 0;
}
if (pArg->eToken == TOKEN_GREATER_THAN) // >
{
nParamLen = 0;
}
if (pArg->eToken == TOKEN_EXCLAMATION) // NOT_EQUAL !
{
if (! ArgsGetImmediateValue( pNext, & nAddressRHS ))
{
if (! ArgsGetRegisterValue( pNext, & nAddressRHS ))
{
nAddressRHS = nAddressVal;
}
}
pArg->nVal1 = ~nAddressRHS;
pArg->bType |= TYPE_VALUE; // signal already up to date
// Don't remove, since "SYM ! symbol" needs token to remove symbol
}
if (nParamLen)
{
_Arg_Shift( iArg + nParamLen, nArgs, iArg );
nArg -= nParamLen;
iArg = 0; // reset args, to handle multiple operators
}
}
else
return ARG_SYNTAX_ERROR;
}
else // not an operator, try (1) address, (2) symbol lookup
{
nAddressArg = (WORD)(_tcstoul( pSrc, &pEnd2, BASE) & _6502_END_MEM_ADDRESS);
if (! (pArg->bType & TYPE_NO_REG))
{
ArgsGetRegisterValue( pArg, & nAddressArg );
}
nAddressVal = nAddressArg;
bool bFound = false;
if (! (pArg->bType & TYPE_NO_SYM))
{
bFound = FindAddressFromSymbol( pSrc, & nAddressSym );
if (bFound)
{
nAddressVal = nAddressSym;
pArg->bSymbol = true;
}
}
if (! (pArg->bType & TYPE_VALUE)) // already up to date?
pArg->nVal1 = nAddressVal;
pArg->bType |= TYPE_ADDRESS;
}
iArg++;
}
return nArg;
}
// Text Util ______________________________________________________________________________________
//===========================================================================
const char * ParserFindToken( const char *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e * pToken_ )
{
const TokenTable_t *pToken= aTokens;
const TCHAR *pName = NULL;
for (int iToken = 0; iToken < nTokens; iToken++ )
{
pName = & (pToken->sToken);
if (*pSrc == *pName)
{
if ( pToken_)
{
*pToken_ = (ArgToken_e) iToken;
}
return pSrc;
}
pToken++;
}
return NULL;
}
//===========================================================================
const TCHAR * FindTokenOrAlphaNumeric ( const TCHAR *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e * pToken_ )
{
if (pToken_)
*pToken_ = NO_TOKEN;
const TCHAR *pEnd = pSrc;
if (pSrc && (*pSrc))
{
if (isalnum( *pSrc ))
{
if (pToken_)
*pToken_ = TOKEN_ALPHANUMERIC;
}
else
{
pEnd = ParserFindToken( pSrc, aTokens, nTokens, pToken_ );
if (pEnd)
pEnd = pSrc + 1; // _tcslen( pToken );
else
pEnd = pSrc;
}
}
return pEnd;
}
//===========================================================================
void TextConvertTabsToSpaces( TCHAR *pDeTabified_, LPCTSTR pText, const int nDstSize, int nTabStop )
{
int nLen = _tcslen( pText );
int TAB_SPACING = 8;
int TAB_SPACING_1 = 16;
int TAB_SPACING_2 = 21;
if (nTabStop)
TAB_SPACING = nTabStop;
LPCTSTR pSrc = pText;
LPTSTR pDst = pDeTabified_;
int iTab = 0; // number of tabs seen
int nTab = 0; // gap left to next tab
int nGap = 0; // actual gap
int nCur = 0; // current cursor position
while (pSrc && *pSrc && (nCur < nDstSize))
{
if (*pSrc == CHAR_TAB)
{
if (nTabStop)
{
nTab = nCur % TAB_SPACING;
nGap = (TAB_SPACING - nTab);
}
else
{
if (nCur <= TAB_SPACING_1)
{
nGap = (TAB_SPACING_1 - nCur);
}
else
if (nCur <= TAB_SPACING_2)
{
nGap = (TAB_SPACING_2 - nCur);
}
else
{
nTab = nCur % TAB_SPACING;
nGap = (TAB_SPACING - nTab);
}
}
if ((nCur + nGap) >= nDstSize)
break;
for( int iSpc = 0; iSpc < nGap; iSpc++ )
{
*pDst++ = CHAR_SPACE;
}
nCur += nGap;
}
else
if ((*pSrc == CHAR_LF) || (*pSrc == CHAR_CR))
{
*pDst++ = 0; // *pSrc;
nCur++;
}
else
{
*pDst++ = *pSrc;
nCur++;
}
pSrc++;
}
*pDst = 0;
}
// @return Length of new string
//===========================================================================
int RemoveWhiteSpaceReverse ( TCHAR *pSrc )
{
int nLen = _tcslen( pSrc );
char *pDst = pSrc + nLen;
while (nLen--)
{
pDst--;
if (*pDst == CHAR_SPACE)
{
*pDst = 0;
}
else
{
break;
}
}
return nLen;
}
//===========================================================================
/*
inline
const TCHAR* SkipEOL ( const TCHAR *pSrc )
{
while (pSrc && ((*pSrc == CHAR_LF) || (*pSrc == CHAR_CR)))
{
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipUntilChar ( const TCHAR *pSrc, const TCHAR nDelim )
{
while (pSrc && (*pSrc))
{
if (*pSrc == nDelim)
break;
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipUntilEOL ( const TCHAR *pSrc )
{
while (pSrc && (*pSrc))
{
if ((*pSrc == CHAR_LF) || (*pSrc == CHAR_CR))
{
break;
}
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipUntilTab ( const TCHAR *pSrc )
{
while (pSrc && (*pSrc))
{
if (*pSrc == CHAR_TAB)
{
break;
}
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
const TCHAR* SkipUntilToken ( const TCHAR *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e *pToken_ )
{
if ( pToken_)
*pToken_ = NO_TOKEN;
while (pSrc && (*pSrc))
{
// Common case is TOKEN_ALPHANUMERIC, so continue until we don't have one
if (ParserFindToken( pSrc, aTokens, pToken_ ))
return pSrc;
pSrc++;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipUntilWhiteSpace ( const TCHAR *pSrc )
{
while (pSrc && (*pSrc))
{
if ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB))
{
break;
}
pSrc++;
}
return pSrc;
}
*/
// @param pStart Start of line.
//===========================================================================
/*
inline
const TCHAR *SkipUntilWhiteSpaceReverse ( const TCHAR *pSrc, const TCHAR *pStart )
{
while (pSrc && (pSrc > pStart))
{
if ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB))
{
break;
}
pSrc--;
}
return pSrc;
}
*/
//===========================================================================
/*
inline
const TCHAR* SkipWhiteSpace ( const TCHAR *pSrc )
{
while (pSrc && ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB)))
{
pSrc++;
}
return pSrc;
}
*/
// @param pStart Start of line.
//===========================================================================
/*
inline
const TCHAR *SkipWhiteSpaceReverse ( const TCHAR *pSrc, const TCHAR *pStart )
{
while (pSrc && ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB)) && (pSrc > pStart))
{
pSrc--;
}
return pSrc;
}
*/
// EOF

View File

@ -0,0 +1,184 @@
#ifndef DEBUGGER_PARSER_H
#define DEBUGGER_PARSER_H
#define CHAR_LF '\x0D'
#define CHAR_CR '\x0A'
#define CHAR_SPACE ' '
#define CHAR_TAB '\t'
#define CHAR_QUOTED '"'
#define CHAR_ESCAPE '\x1B'
// Globals __________________________________________________________________
extern int g_nArgRaw;
extern Arg_t g_aArgRaw[ MAX_ARGS ]; // pre-processing
extern Arg_t g_aArgs [ MAX_ARGS ]; // post-processing
extern const TCHAR * g_pConsoleFirstArg; // = 0; // points to first arg
extern const TokenTable_t g_aTokens[ NUM_TOKENS ];
extern const TCHAR TCHAR_LF ;//= 0x0D;
extern const TCHAR TCHAR_CR ;//= 0x0A;
extern const TCHAR TCHAR_SPACE ;//= TEXT(' ');
extern const TCHAR TCHAR_TAB ;//= TEXT('\t');
extern const TCHAR TCHAR_QUOTED;//= TEXT('"' );
// Prototypes _______________________________________________________________
// Arg - Command Processing
Update_t Help_Arg_1( int iCommandHelp );
int _Arg_1 ( int nValue );
int _Arg_1 ( LPTSTR pName );
int _Arg_Shift ( int iSrc, int iEnd, int iDst = 0 );
void ArgsClear ();
bool ArgsGetValue ( Arg_t *pArg, WORD * pAddressValue_, const int nBase = 16 );
bool ArgsGetImmediateValue ( Arg_t *pArg, WORD * pAddressValue_ );
int ArgsGet ( TCHAR * pInput );
bool ArgsGetRegisterValue ( Arg_t *pArg, WORD * pAddressValue_ );
void ArgsRawParse ( void );
int ArgsCook ( const int nArgs ); // ArgsRawCook
// Token
const char * ParserFindToken( const char *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e * pToken_ );
// Text Util
/*
inline const char* SkipEOL ( const char *pSrc )
{
while (pSrc && ((*pSrc == CHAR_LF) || (*pSrc == CHAR_CR)))
if (pSrc)
{
pSrc++;
}
return pSrc;
}
*/
inline const char* EatEOL ( const char *pSrc )
{
if (pSrc)
{
if (*pSrc == CHAR_LF)
pSrc++;
if (*pSrc == CHAR_CR)
pSrc++;
}
return pSrc;
}
inline const char* SkipWhiteSpace ( const char *pSrc )
{
while (pSrc && ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB)))
{
pSrc++;
}
return pSrc;
}
inline const char* SkipWhiteSpaceReverse ( const char *pSrc, const char *pStart )
{
while (pSrc && ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB)) && (pSrc > pStart))
{
pSrc--;
}
return pSrc;
}
inline const char* SkipUntilChar ( const char *pSrc, const char nDelim )
{
while (pSrc && (*pSrc))
{
if (*pSrc == nDelim)
break;
pSrc++;
}
return pSrc;
}
inline const char* SkipUntilEOL ( const char *pSrc )
{
// EOL delims: NULL, LF, CR
while (pSrc && (*pSrc))
{
if ((*pSrc == CHAR_LF) || (*pSrc == CHAR_CR))
{
break;
}
pSrc++;
}
return pSrc;
}
inline const char* SkipUntilTab ( const char *pSrc)
{
while (pSrc && (*pSrc))
{
if (*pSrc == CHAR_TAB)
{
break;
}
pSrc++;
}
return pSrc;
}
inline const char* SkipUntilToken ( const char *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e *pToken_ )
{
if ( pToken_)
*pToken_ = NO_TOKEN;
while (pSrc && (*pSrc))
{
if (ParserFindToken( pSrc, aTokens, nTokens, pToken_ ))
return pSrc;
pSrc++;
}
return pSrc;
}
inline const char* SkipUntilWhiteSpace ( const char *pSrc )
{
while (pSrc && (*pSrc))
{
if ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB))
{
break;
}
pSrc++;
}
return pSrc;
}
inline const char* SkipUntilWhiteSpaceReverse ( const char *pSrc, const char *pStart )
{
while (pSrc && (pSrc > pStart))
{
if ((*pSrc == CHAR_SPACE) || (*pSrc == CHAR_TAB))
{
break;
}
pSrc--;
}
return pSrc;
}
/*
const TCHAR* SkipEOL ( const TCHAR *pSrc );
const TCHAR* SkipWhiteSpace ( const TCHAR *pSrc );
const TCHAR* SkipWhiteSpaceReverse ( const TCHAR *pSrc, const TCHAR *pStart );
const TCHAR* SkipUntilChar ( const TCHAR *pSrc, const TCHAR nDelim );
const TCHAR* SkipUntilEOL ( const TCHAR *pSrc );
const TCHAR* SkipUntilToken ( const TCHAR *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e *pToken_ );
const TCHAR* SkipUntilWhiteSpace ( const TCHAR *pSrc );
const TCHAR* SkipUntilWhiteSpaceReverse ( const TCHAR *pSrc, const TCHAR *pStart );
const TCHAR* SkipUntilTab ( const TCHAR *pSrc);
*/
const TCHAR * FindTokenOrAlphaNumeric ( const TCHAR *pSrc, const TokenTable_t *aTokens, const int nTokens, ArgToken_e * pToken_ );
// TextRemoveWhiteSpaceReverse
int RemoveWhiteSpaceReverse ( char *pSrc );
// TextExpandTabsToSpaces
void TextConvertTabsToSpaces( TCHAR *pDeTabified_, LPCTSTR pText, const int nDstSize, int nTabStop = 0 );
#endif

File diff suppressed because it is too large Load Diff