📄 parse6502.cpp
字号:
/*-----------------------------------------------------------------------------
6502 Macroassembler and Simulator
Copyright (C) 1995-2003 Michal Kowalski
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-----------------------------------------------------------------------------*/
#include "stdafx.h"
#include "6502View.h"
#include "Deasm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static LPTSTR s_vpszInstructionList[] =
{
_T("LDA"),
_T("LDX"),
_T("LDY"),
_T("STA"),
_T("STX"),
_T("STY"),
_T("STZ"),
_T("TAX"),
_T("TXA"),
_T("TAY"),
_T("TYA"),
_T("TXS"),
_T("TSX"),
_T("ADC"),
_T("SBC"),
_T("CMP"),
_T("CPX"),
_T("CPY"),
_T("INC"),
_T("DEC"),
_T("INA"),
_T("DEA"),
_T("INX"),
_T("DEX"),
_T("INY"),
_T("DEY"),
_T("ASL"),
_T("LSR"),
_T("ROL"),
_T("ROR"),
_T("AND"),
_T("ORA"),
_T("EOR"),
_T("BIT"),
_T("TSB"),
_T("TRB"),
_T("JMP"),
_T("JSR"),
_T("BRK"),
_T("BRA"),
_T("BPL"),
_T("BMI"),
_T("BVC"),
_T("BVS"),
_T("BCC"),
_T("BCS"),
_T("BNE"),
_T("BEQ"),
_T("RTS"),
_T("RTI"),
_T("PHA"),
_T("PLA"),
_T("PHX"),
_T("PLX"),
_T("PHY"),
_T("PLY"),
_T("PHP"),
_T("PLP"),
_T("CLC"),
_T("SEC"),
_T("CLV"),
_T("CLD"),
_T("SED"),
_T("CLI"),
_T("SEI"),
_T("NOP"),
_T("BBR"),
_T("BBS"),
NULL
};
static LPTSTR s_vpszDirectiveList[]=
{
".ASCII",
".ASCIS",
".BYTE",
".DB",
".DBYTE",
".DCB",
".DD",
".DS",
".DW",
".ELSE",
".END",
".ENDIF",
".ENDM",
".ENDR",
".ERROR",
".EXITM",
".IF",
".INCLUDE",
".IO_WND",
".MACRO",
".OPT",
".ORG",
".REPEAT",
".REPT",
".ROM_AREA",
".RS",
".SET",
".START",
".STR",
".STRING",
".WORD",
NULL
};
static LPTSTR s_vpszConstantList[]=
{
"ORG",
"IO_AREA",
0
};
extern BOOL IsMnemonic(LPCTSTR pszChars, int nLength)
{
if (nLength != 3)
return false;
for (int L = 0; s_vpszInstructionList[L] != NULL; L ++)
{
if (_tcsnicmp(s_vpszInstructionList[L], pszChars, nLength) == 0)
// && s_vpszInstructionList[L][nLength] == 0)
return true;
}
return false;
}
extern bool IsDirective(LPCTSTR pszChars, int nLength)
{
if (nLength < 2)
return false;
if (pszChars[0] != '.')
{
for (int L = 0; s_vpszConstantList[L] != NULL; L ++)
{
if (_tcsnicmp(s_vpszConstantList[L], pszChars, nLength) == 0
&& s_vpszConstantList[L][nLength] == 0)
return true;
}
return false;
}
for (int L = 0; s_vpszDirectiveList[L] != NULL; L ++)
{
if (_tcsnicmp(s_vpszDirectiveList[L], pszChars, nLength) == 0
&& s_vpszDirectiveList[L][nLength] == 0)
return true;
}
return false;
}
static BOOL Is6502Number(LPCTSTR pszChars, int nLength)
{
if (nLength > 1) // && (pszChars[0] == '$' || pszChars[0] == '@'))
{
if (pszChars[0] == '$')
{
for (int i= 1; i < nLength; ++i)
{
if (isdigit(pszChars[i]) || (pszChars[i] >= 'A' && pszChars[i] <= 'F') ||
(pszChars[i] >= 'a' && pszChars[i] <= 'f'))
continue;
return false;
}
}
else if (pszChars[0] == '@') // binary?
{
for (int i= 1; i < nLength; ++i)
{
if (pszChars[i] == '0' || pszChars[i] == '1')
continue;
return false;
}
}
else
{
for (int i= 0; i < nLength; ++i)
{
if (isdigit(pszChars[i]))
continue;
return false;
}
}
return true;
}
if (isdigit(pszChars[0]))
return true;
return false;
}
#define DEFINE_BLOCK(pos, colorindex) \
ASSERT((pos) >= 0 && (pos) <= nLength);\
if (pBuf != NULL)\
{\
if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
pBuf[nActualItems].m_nCharPos = (pos);\
pBuf[nActualItems].m_nColorIndex = (colorindex);\
nActualItems ++;}\
}
#define COOKIE_COMMENT 0x0001
#define COOKIE_PREPROCESSOR 0x0002
#define COOKIE_EXT_COMMENT 0x0004
#define COOKIE_STRING 0x0008
#define COOKIE_CHAR 0x0010
extern DWORD ParseLine(DWORD dwCookie, LPCTSTR pszChars, int nLength, TEXTBLOCK* pBuf, int& nActualItems)
{
BOOL bFirstChar= (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
BOOL bRedefineBlock= TRUE;
BOOL bDecIndex= FALSE;
int nIdentBegin= -1;
bool bSkipChar= false;
for (int I = 0; ; I++)
{
if (bRedefineBlock)
{
int nPos = I;
if (bDecIndex)
nPos--;
if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
{
DEFINE_BLOCK(nPos, COLORINDEX_COMMENT);
}
else
if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
{
DEFINE_BLOCK(nPos, COLORINDEX_STRING);
}
else
if (dwCookie & COOKIE_PREPROCESSOR)
{
DEFINE_BLOCK(nPos, COLORINDEX_PREPROCESSOR);
}
else
{
DEFINE_BLOCK(nPos, COLORINDEX_NORMALTEXT);
}
bRedefineBlock = FALSE;
bDecIndex = FALSE;
}
if (I == nLength)
break;
if (bSkipChar)
{
bSkipChar = false;
continue;
}
if (dwCookie & COOKIE_COMMENT)
{
DEFINE_BLOCK(I, COLORINDEX_COMMENT);
dwCookie |= COOKIE_COMMENT;
break;
}
// String constant "...."
if (dwCookie & COOKIE_STRING)
{
if (pszChars[I] == '"' && (I == 0 || pszChars[I - 1] != '\\'))
{
dwCookie &= ~COOKIE_STRING;
bRedefineBlock = TRUE;
}
continue;
}
// Char constant '..'
if (dwCookie & COOKIE_CHAR)
{
if (pszChars[I] == '\'' && (I == 0 || pszChars[I - 1] != '\\'))
{
dwCookie &= ~COOKIE_CHAR;
bRedefineBlock = TRUE;
}
continue;
}
// Extended comment /*....*/
/* if (dwCookie & COOKIE_EXT_COMMENT)
{
if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '*')
{
dwCookie &= ~COOKIE_EXT_COMMENT;
bRedefineBlock = TRUE;
}
continue;
}
*/
if (pszChars[I] == ';')
{
DEFINE_BLOCK(I, COLORINDEX_COMMENT);
dwCookie |= COOKIE_COMMENT;
continue;
}
/*
if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/')
{
DEFINE_BLOCK(I - 1, COLORINDEX_COMMENT);
dwCookie |= COOKIE_COMMENT;
continue;
// break;
}
*/
/* // Preprocessor directive #....
if (dwCookie & COOKIE_PREPROCESSOR)
{
if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
{
DEFINE_BLOCK(I - 1, COLORINDEX_COMMENT);
dwCookie |= COOKIE_EXT_COMMENT;
// MiK
bSkipChar = true;
}
continue;
}
*/
// Normal text
if (pszChars[I] == '"')
{
DEFINE_BLOCK(I, COLORINDEX_STRING);
dwCookie |= COOKIE_STRING;
continue;
}
if (pszChars[I] == '\'')
{
DEFINE_BLOCK(I, COLORINDEX_STRING);
dwCookie |= COOKIE_CHAR;
continue;
}
/* if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
{
DEFINE_BLOCK(I - 1, COLORINDEX_COMMENT);
dwCookie |= COOKIE_EXT_COMMENT;
// MiK
bSkipChar = true;
continue;
}
*/
/* if (bFirstChar)
{
if (pszChars[I] == '#')
{
DEFINE_BLOCK(I, COLORINDEX_PREPROCESSOR);
dwCookie |= COOKIE_PREPROCESSOR;
continue;
}
if (! isspace(pszChars[I]))
bFirstChar = FALSE;
} */
/* if (pszChars[I] == '+' || pszChars[I] == '-' || pszChars[I] == '*' || pszChars[I] == '/' ||
pszChars[I] == '#' || pszChars[I] == '>' || pszChars[I] == '<' || pszChars[I] == '(' || pszChars[I] == ')')
{
DEFINE_BLOCK(I, COLORINDEX_OPERATOR);
continue;
} */
if (pBuf == NULL)
continue; // We don't need to extract keywords,
// for faster parsing skip the rest of loop
if (isalnum(pszChars[I]) || pszChars[I] == '_' || pszChars[I] == '.' || pszChars[I] == '$' || pszChars[I] == '@')
{
if (nIdentBegin == -1)
nIdentBegin = I;
}
else
{
if (nIdentBegin >= 0)
{
if (nIdentBegin > 0 && IsMnemonic(pszChars + nIdentBegin, I - nIdentBegin))
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_KEYWORD);
}
else if (IsDirective(pszChars + nIdentBegin, I - nIdentBegin))
{
if (nIdentBegin > 0 || pszChars[0] != '.')
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_PREPROCESSOR);
}
}
else if (Is6502Number(pszChars + nIdentBegin, I - nIdentBegin))
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_NUMBER);
}
bRedefineBlock = TRUE;
bDecIndex = TRUE;
nIdentBegin = -1;
}
}
}
if (nIdentBegin >= 0)
{
if (nIdentBegin > 0 && IsMnemonic(pszChars + nIdentBegin, I - nIdentBegin))
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_KEYWORD);
}
else if (nIdentBegin > 0 && IsDirective(pszChars + nIdentBegin, I - nIdentBegin))
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_PREPROCESSOR);
}
else if (Is6502Number(pszChars + nIdentBegin, I - nIdentBegin))
{
DEFINE_BLOCK(nIdentBegin, COLORINDEX_NUMBER);
}
}
// if (pszChars[nLength - 1] != '\\')
// dwCookie &= COOKIE_EXT_COMMENT;
return dwCookie;
}
DWORD CSrc6502View::ParseLine(DWORD dwCookie, int nLineIndex, TEXTBLOCK* pBuf, int& nActualItems)
{
dwCookie = 0; // no history
int nLength = GetLineLength(nLineIndex);
if (nLength <= 0)
{
ClearCollapsibleBlockMark(nLineIndex);
return 0; //dwCookie & COOKIE_EXT_COMMENT;
}
/*
if (pszChars[0] > _T(' ') && pszChars[0] != '.' && pszChars[0] != ';')
{
MarkCollapsibleBlockLine(nLineIndex, true);
// if (nLineIndex > 0)
// MarkCollapsibleBlockLine(nLineIndex - 1, false);
}
else
ClearCollapsibleBlockMark(nLineIndex);
*/
LPCTSTR pszChars= GetLineChars(nLineIndex);
return ::ParseLine(dwCookie, pszChars, nLength, pBuf, nActualItems);
}
///////////////////////////////////////////////////////////////////////////////
extern int MatchingDirectives(const CString& strWord, CString& strOut)
{
strOut.Empty();
if (strWord.IsEmpty())
return 0;
int nMatch= 0;
if (strWord[0] == _T('.'))
{
for (int i= 0; s_vpszDirectiveList[i] != 0; ++i)
{
if (_tcsnicmp(s_vpszDirectiveList[i], strWord, strWord.GetLength()) == 0)
{
// whole name matches?
if (strWord.GetLength() == _tcslen(s_vpszDirectiveList[i]))
{
strOut = s_vpszDirectiveList[i];
return 1;
}
strOut += s_vpszDirectiveList[i];
strOut += _T("\n");
++nMatch;
}
}
}
else
{
for (int i= 0; s_vpszConstantList[i] != 0; ++i)
{
if (_tcsnicmp(s_vpszConstantList[i], strWord, strWord.GetLength()) == 0)
{
// whole name matches?
if (strWord.GetLength() == _tcslen(s_vpszConstantList[i]))
{
strOut = s_vpszConstantList[i];
return 1;
}
strOut += s_vpszConstantList[i];
strOut += _T("\n");
++nMatch;
}
}
}
if (nMatch == 1)
strOut.Delete(strOut.GetLength() - 1);
return nMatch;
}
extern CString GetDirectiveDesc(const CString& strDirective)
{
if (strDirective.CompareNoCase(_T(".ASCIS")) == 0)
return _T("#title#.ASCIS#text#\nDirective defining values of single bytes using string argument."
" Last byte has toggled (XOR-ed) most significant bit to mark end of string."
"#syntax#[<label>[:]] .ASCIS <expr> | txtexpr { , <expr> | txtexpr }.\n"
"#exmpl#alpha: .ASCIS \"ABC\" ; generates bytes $41, $42, $C3.\n"
"beta: .ASCIS \"Stop\",$D ; generates bytes 慡
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -