mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-12-28 17:30:02 +00:00
Debugger split y functionality
This commit is contained in:
parent
eefbc4082e
commit
f29b6eb964
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1362
AppleWin/source/Debugger_Assembler.cpp
Normal file
1362
AppleWin/source/Debugger_Assembler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
61
AppleWin/source/Debugger_Assembler.h
Normal file
61
AppleWin/source/Debugger_Assembler.h
Normal 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
|
352
AppleWin/source/Debugger_Console.cpp
Normal file
352
AppleWin/source/Debugger_Console.cpp
Normal 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;
|
||||
}
|
84
AppleWin/source/Debugger_Console.h
Normal file
84
AppleWin/source/Debugger_Console.h
Normal 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
|
2143
AppleWin/source/Debugger_Display.cpp
Normal file
2143
AppleWin/source/Debugger_Display.cpp
Normal file
File diff suppressed because it is too large
Load Diff
29
AppleWin/source/Debugger_Display.h
Normal file
29
AppleWin/source/Debugger_Display.h
Normal 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
|
685
AppleWin/source/Debugger_Help.cpp
Normal file
685
AppleWin/source/Debugger_Help.cpp
Normal 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();
|
||||
}
|
||||
|
30
AppleWin/source/Debugger_Help.h
Normal file
30
AppleWin/source/Debugger_Help.h
Normal 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
|
945
AppleWin/source/Debugger_Parser.cpp
Normal file
945
AppleWin/source/Debugger_Parser.cpp
Normal 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
|
184
AppleWin/source/Debugger_Parser.h
Normal file
184
AppleWin/source/Debugger_Parser.h
Normal 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
|
1282
AppleWin/source/Debugger_Types.h
Normal file
1282
AppleWin/source/Debugger_Types.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user