⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse6502.cpp

📁 专门为65XX系列芯片设计的变异调试环境的源代码
💻 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 + -