首页
社区
课程
招聘
[原创]算是写的差不多了,所以编辑一下
发表于: 2012-1-17 14:36 34622

[原创]算是写的差不多了,所以编辑一下

2012-1-17 14:36
34622
我敢说,很少有人愿意花时间写界面相关的东西,很枯燥,又感觉不到什么实实在在额进步,但我还是坚持写完了。

代码很难看,但这就是我的风格。程序效果如图:



1.单击鼠标左键意味着选中一行。如果按住鼠标拖动,选择将精确到字符。

2.函数都是C形式的,这样可以最大程度的与WINDOWS子窗口控件相似。要封装成类也很容易,只要把struct TEDIT改成 class TEdit 就行了。

3.所有ngcEdit_开头的函数都不是多线程安全的。想要多线程安全的话,最简单的方法就是跟WINDOWS通用控件一样,定义一堆消息,每个函数都以发送消息的形式去完成,以确保界面操作都在界面线程中完成

有什么不完善的地方自己修改源码。一般,游戏,2D还是3D的,都用这种方式来绘制GUI(界面),效率还是可以的。

下面是源码,主要内容都在TEdit.cpp,TEdit.h,TData.h这三个文件中:
TEditUse.rar

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (23)
雪    币: 180
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我以为是主讲没有激情呢
2012-1-17 15:24
0
雪    币: 878
活跃值: (496)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
干她

.................................................................................................................................................

....................................................................................................................................................

代码!
2012-1-17 15:39
0
雪    币: 768
活跃值: (530)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
4
HexEdit UI,可以参考一下这个
http://bbs.pediy.com/showthread.php?t=127408%A1%AE

附件
http://bbs.pediy.com/attachment.php?attachmentid=53326&d=1295012933

是从BCGControl库中分出来的。看看能否满您的需求
早日看到您的大作:)

持续关注MDebug的动态:)
2012-1-17 20:13
0
雪    币: 14
活跃值: (28)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
很好的东西,收下了。
2012-1-17 20:42
0
雪    币: 1981
活跃值: (771)
能力值: ( LV13,RANK:420 )
在线值:
发帖
回帖
粉丝
6


2012-1-17 21:12
0
雪    币: 5279
活跃值: (3659)
能力值: ( LV13,RANK:283 )
在线值:
发帖
回帖
粉丝
7
写个几层的虚拟机吧,想盗梦空间一样
2012-1-17 21:25
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
我的hexedit功能还不是很强,还要继续完善。
脚本语言解析引擎花了我好几天写的,你参考一下我的源代码:
2012-1-18 01:15
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
9
// Script.cpp: implementation of the CScript class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MDebug.h"
#include "Script.h"
#include "MainFrm.h"
#include "ScriptGetInputDlg.h" 

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define CHAR_ISDIGIT(c)	((c)>='0' && (c)<='9')
#define CHAR_ISCHAR(c)	(((c)>='a' && (c)<='z') || ((c)>='A' && (c)<='Z'))
#define CHAR_ISHEXCHAR(c) (CHAR_ISDIGIT(c) || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F'))
#define CHAR_ISBLANK(c) ((c)==' '||(c)=='\t')
#define CHAR_ISEND(c) ((c)=='\0'||(c)=='\r'||(c)=='\n')
#define CHAR_ISMATHOPR(c)  ((c)=='+'||(c)=='-'||(c)=='*'||(c)=='/'||(c)=='^'||(c)=='&'||(c)=='|')

#define TOHEXCHAR(c) CHAR_ISDIGIT(c) ? ((c)-'0') : ((c)-'A'+0xA)

#define ISFULLWORDCHAR(x) (((x)>='a'&&(x)<='z') || ((x)>='A'&&(x)<='Z') || CHAR_ISDIGIT(x) || (x) == '_' || (x) == '$')
#define SKIPBLANK(x)		while((*x) == ' ' || (*x) == '\t'){(x)++;}		//跳过空格和tab

typedef int (CScript::*PARSECMD)(int nCmd, TOKEN* argv[], int argc);


typedef struct _CMDDESC
{
	const char* maincmd;		//主命令名称
	int argc;					//参数数量,如果是-1,表示不确定可变
	PARSECMD handler;
	const char* help;
	const char* usage;
}CMDDESC;


CMDDESC g_cmddesc[] = 
{
	{"h",				-1, CScript::CMD_Help},
	{"?",				-1, CScript::CMD_Help},
	{"help",			-1, CScript::CMD_Help},
	{"ver",				0, CScript::CMD_Ver,			"显示MDebug版本信息"},
	{"exit",			0, CScript::CMD_exit,			"退出MDebug"},
	{"cls",				0, CScript::CMD_CLS,			"清空输出窗口"},
	{"sleep",			1, CScript::CMD_sleep,			"Sleep",					"Milliseconds"},

	{"print",			1, CScript::CMD_PRINT,			"向输出窗口打印",			"expression"},
	{"log",				1, CScript::CMD_PRINT,			"向输出窗口打印",			"expression"},
	{"msg",				1, CScript::CMD_MSG,			"显示一个消息框",			"expression"},
	{"YESNO",			1, CScript::CMD_YESNO,			"显示一个YES NO 选择消息框","expression"},
	{"getstr",			0, CScript::CMD_getstr,			"显示一个对话框,要求用户输入字符串",},
	{"getint",			0, CScript::CMD_getint,			"显示一个对话框,要求用户输入一个16进制整数"},

	{"findprocess",		1, CScript::CMD_findprocess,	"根据进程名称找进程的pid, 结果保存到result",		"process_name"},

	{"loaddll",			1, CScript::CMD_loaddll,		"向被调试进程远程加载dll",	"dllname"},
	{"alloc",			1, CScript::CMD_alloc,			"向被调试进程分配内存,result 保存分配的内存地址",	"size"},

	{"readdata",		2, CScript::CMD_readdata,		"读内存数据,并将结果保存到result中",				"addr, size"},
	{"readstr",			1, CScript::CMD_readstr,		"读内存中的字符串,并将结果保存到result中",			"addr"},
	{"readwstr",		1, CScript::CMD_readwstr,		"读内存中的unicode字符串,并将结果保存到result中",	"addr"},

	{"openfile",		-1,CScript::CMD_openfile,		"打开PE文件进行调试,即使用户在选项中没有选择“打开PE文件后立即开始调试”,openfile指令也会立即开始调试",	"filepath [,param]"},
	{"stop",			0, CScript::CMD_stop,			"停止调试"},
	{"pause",			0, CScript::CMD_pause,			"暂停调试"},
	{"restart",			0, CScript::CMD_restart,		"重新开始调试"},
	{"dettach",			0, CScript::CMD_dettach,		"脱离调试运行"},
	{"attach",			1, CScript::CMD_attach,			"attach 活动进程",		"processid"},
	{"g",				-1,CScript::CMD_run,			"开始调试或运行",		"[,addr]"},
	{"run",				-1,CScript::CMD_run,			"开始调试或运行",		"[,addr]"},
	{"t",				0, CScript::CMD_t,				"单步进入"},
	{"p",				0, CScript::CMD_p,				"单步跳过"},
	{"gret",			0, CScript::CMD_gret,			"运行到返回处"},		//运行到返回处
	{"gout",			0, CScript::CMD_gret,			"运行到返回处"},		//运行到返回处

	{"GetModuleBase",	1, CScript::CMD_GetModuleBase,	"取被调试进程的特定模块的基地址,将结果保存到result",	"modulename"},
	{"GetModuleSize",	1, CScript::CMD_GetModuleSize,	"取被调试进程的特定模块的大小,将结果保存到result",		"modulename"},

	{"bc",				1, CScript::CMD_bc,				"删除断点",				"addr / *"},
	{"bp",				-1,CScript::CMD_bp,				"设置断点",				"addr [,\"condition\"]"},
	{"bph",				1, CScript::CMD_bph,			"设置硬件执行断点",		"addr"},
	{"bphr",			-1,CScript::CMD_bphr,			"设置硬件读内存断点",	"addr [,len]"},
	{"bphw",			-1,CScript::CMD_bphw,			"设置硬件写内存断点",	"addr [,len]"},

	{"strlen",			1, CScript::CMD_strlen,			"计算字符串长度,并将结果保存到result",					"expression"},
	{"strcat",			2, CScript::CMD_strcat,			"字符串连接,strcat 的第一个参数必须是变量",			"dst, src"},
	{"strcmp",			2, CScript::CMD_strcmp,			"字符串比较,并将比较结果保存到result中。如果相同,result值=0",	"str1, str2"},
	{"strcmpi",			2, CScript::CMD_strcmpi,		"字符串比较(忽略大小写),并将比较结果保存到result中。如果相同,result值=0",	"str1, str2"},
	{"strstr",			2, CScript::CMD_strstr,			"字符串查找,并将查找到的结果保存到result中。result保存的是匹配到的第一个字符串",	"str1, str2"},
	{"strstri",			2, CScript::CMD_strstri,		"字符串查找(忽略大小写),并将查找到的结果保存到result中。result保存的是匹配到的第一个字符串",	"str1, str2"},
	{"strupr",			1, CScript::CMD_strupr,			"将字符串转换为大写, 参数必须是变量",	"str"},
	{"strlwr",			1, CScript::CMD_strlwr,			"将字符串转换为小写, 参数必须是变量",	"str"},

};

char* g_reservedword[] = 
{
	"if",
	"while",
	"var",
	"result",
	"break",
	"continue"
};

CVariant::CVariant()
{
	memset(m_szVarName, 0, VARNAMESIZE);
	m_type = MYVARIANT_EMPTY;
	m_nDataSize = 0;
	m_value = 0;
}

CVariant::CVariant(const char* pszVarName)
{
	memset(m_szVarName, 0, VARNAMESIZE);
	m_type = MYVARIANT_EMPTY;
	m_nDataSize = 0;
	m_value = 0;
	
	strncpy(m_szVarName, pszVarName, VARNAMESIZE);
}

CVariant::~CVariant()
{
	Release();
}

void CVariant::SetInt(unsigned __int64 v)
{
	ASSERT(m_type == MYVARIANT_EMPTY);
	m_value = v;
	m_type = MYVARIANT_INT;
}

void CVariant::SetAnsiString(const char* str)
{
	ASSERT(m_type == MYVARIANT_EMPTY);
	ASSERT(str != NULL);
	int len = strlen(str);

	m_str = new char[len+2];
	if(m_str != NULL)
	{
		strcpy(m_str, str);
		m_type = MYVARIANT_STR;
	}
}

void CVariant::SetUnicodeString(const char* str)
{
	ASSERT(m_type == MYVARIANT_EMPTY);
	ASSERT(str != NULL);

	int len = 10 + MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
	m_wstr = new WCHAR[len];
	if(m_wstr != NULL)
	{
		memset(m_wstr, 0, len*sizeof(WCHAR));
		MultiByteToWideChar(CP_ACP, 0, str, -1, m_wstr, len);
		m_type = MYVARIANT_WCHAR;
	}
}

void CVariant::SetUnicodeString2(const WCHAR* wstr)
{
	ASSERT(m_type == MYVARIANT_EMPTY);
	ASSERT(wstr != NULL);

	int len = 2 + wcslen(wstr);
	m_wstr = new WCHAR[len];
	if(m_wstr != NULL)
	{
		wcscpy(m_wstr, wstr);
		m_type = MYVARIANT_WCHAR;
	}
}

void CVariant::SetUnicodeStringToAnsiString(const WCHAR* wstr)
{
	int len = 2 + WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
	m_str = new char[len];
	if(m_str != NULL)
	{
		memset(m_str, 0, len);
		WideCharToMultiByte(CP_ACP, 0, wstr, -1, m_str, len, NULL,NULL);
		m_type = MYVARIANT_STR;
	}
}


void CVariant::SetHexBytes(BYTE* pData, int len)
{
	ASSERT(pData != NULL);
	ASSERT(m_type == MYVARIANT_EMPTY);
	m_pdata = new BYTE[len];
	if(m_pdata != NULL)
	{
		memcpy(m_pdata, pData, len);
		m_type = MYVARIANT_BYTES;
		m_nDataSize = len;
	}
}

// = 操作
void CVariant::Assign(const CVariant* pvar)
{
	ASSERT(pvar != NULL);

	Release();

	m_type = pvar->m_type;
	m_nDataSize = pvar->m_nDataSize;

	strcpy(m_szVarName, pvar->m_szVarName);

	if(m_type == MYVARIANT_INT)
	{
		m_value = pvar->m_value;
	}
	else if(m_type == MYVARIANT_WCHAR)
	{
		m_wstr = new WCHAR[wcslen(pvar->m_wstr) + 1];
		wcscpy(m_wstr, pvar->m_wstr);
	}
	else if(m_type == MYVARIANT_STR)
	{
		m_str = new char[strlen(pvar->m_str) + 1];
		strcpy(m_str, pvar->m_str);
	}
	else if(m_type == MYVARIANT_BYTES)
	{
		m_pdata = new BYTE[m_nDataSize+2];
		memcpy(m_pdata, pvar->m_pdata, m_nDataSize);
	}
	else if(m_type == MYVARIANT_EMPTY)
	{
		m_value = 0;
	}
	else
	{
		ASSERT(0);
		m_value = 0;
	}
}

void CVariant::Release()
{
	if(m_type == MYVARIANT_STR)
	{
		delete[] m_str;
		m_str = NULL;
	}
	else if(m_type == MYVARIANT_WCHAR)
	{
		delete[] m_wstr;
		m_wstr = NULL;
	}
	else if(m_type == MYVARIANT_BYTES)
	{
		delete[] m_pdata;
		m_pdata = NULL;
	}
	else
	{
	}

	m_type = MYVARIANT_EMPTY;
	m_value = 0;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CScript::CScript()
{
	m_pDebugThread = &((CVDebugApp*)AfxGetApp())->m_DebugThread;

	m_pszCopy = NULL;
	m_pLines = NULL;
	m_nLines = 0;
	m_pbRunning = NULL;
	m_pbDebugging = NULL;
	m_bIsCmdLine = TRUE;
	m_phEvent = NULL;
	m_phDebugEvent = NULL;
	m_pScriptView = NULL;

	m_result.SetName("result");

	m_errLine = -1;
	m_MemExpression.m_pScript = this;
	m_pApp = (CVDebugApp*)AfxGetApp();
	m_pMainframe = (CMainFrame*)m_pApp->m_pMainWnd;
	ASSERT(m_pMainframe != NULL);
}

CScript::~CScript()
{
	if(m_pszCopy != NULL)
		delete[] m_pszCopy;
	if(m_pLines!=NULL)
	{
		for(int i=0; i<m_nLines; i++)
		{
			ReleaseTokenChain(m_pLines[i].pHead);
		}
		delete[] m_pLines;
	}

	POSITION pos = m_varList.GetHeadPosition();
	while(pos != NULL)
	{
		CVariant* pv = m_varList.GetNext(pos);
		delete pv;
	}
	m_varList.RemoveAll();

	m_result.Release();

	pos = m_ifwhile.GetHeadPosition();
	while(pos != NULL)
	{
		IF_WHILE_BRACE* pifwhile = m_ifwhile.GetNext(pos);
		delete pifwhile;
	}
	m_ifwhile.RemoveAll();
}

int CScript::GetLineCount(const char *pszScript)
{
	int nLines = 0;
	char* p = (char*)pszScript;
	while(1)
	{
		if(*p == '\n' || *p == 0)
			nLines++;
		if(*p == 0)
			break;
		p++;
	}
	return nLines;
}

/*
寻找下一个双引号, 引号前面不能为\
如果没有找到,返回 NULL, 否则返回引号后的下一个字符开头的字符串

  如果是 "\\...\\"...
*/
const char* CScript::FindNextDoubleQuote(const char *pszText)
{
	ASSERT(pszText != NULL);
	char* t = (char*)pszText;
	char* pret = NULL;
	while(*t != 0)
	{
		if(*t == '\\')
		{
			t+=2;
		}
		else if(*t == '\"')
		{
			pret = t+1;
			break;
		}
		else
		{
			t++;
		}
	}
	
	return pret;
	
	/*
	char* t = strchr(pszText, '"');
	while(t != NULL && t[-1] == '\\')
	{
	t = strchr(t+1, '"');
	}
	return (t == NULL) ? NULL : t+1;
	*/
}

/*
去掉注释, 将注释部分换成空格

  如果是 " " 内有注释符号,就不能去掉
  
	注释包括 //, /*  * /
*/

void CScript::DeleteComment(IN OUT char *pszBuff, int nLen)
{
	char* pszStart = pszBuff;
	
	while(*pszStart != 0)
	{
		if(pszStart[0] == '\"' && pszStart[-1] != '\\')
		{
			//找下一个 "
			const char* t = FindNextDoubleQuote(pszStart+1);
			if(t == NULL)
			{
				break;	// 语法不通?
			}
			pszStart = (char*)t;
		}
		else if(pszStart[0] == '/' && pszStart[1] == '/')
		{
			while(pszStart[0] != '\r' && pszStart[0] != '\n' && pszStart[0] != 0)
			{
				pszStart[0] = ' ';
				pszStart++;
			}
			
		}
		else if(pszStart[0] == '/' && pszStart[1] == '*')
		{
			char* t = strstr(pszStart+2, "*/");
			if(t == NULL)
			{
				break;	//语法不通?
			}
			t+=2;
			for(;pszStart<t; pszStart++)
			{
				//如果是 换行 就不去掉
				if(pszStart[0] != '\r' && pszStart[0] != '\n')
				{
					pszStart[0] = ' ';
				}
			}
		}
		else
		{
			pszStart++;
		}
	}
	
}

void CScript::SaveToLines(char *pszStr)
{
	int nLines = 0;
	char* p = (char*)pszStr;
	m_pLines[nLines].pszLine = p;
	
	while(1)
	{
		if(*p == 0)
			break;
		if(*p == '\n' || *p == 0)
		{
			*p = 0;
			nLines++;
			m_pLines[nLines].pszLine = p+1;
		}
		
		
		p++;
	}

	//去掉最后的 ;
}

/*
从当前的token移到当前token结束
*/
char* CScript::MoveToTokenEnd(char* p)
{
	ASSERT(p != NULL);
	ASSERT(!CHAR_ISEND(*p));
	ASSERT(!CHAR_ISBLANK(*p));

	if(!ISFULLWORDCHAR(*p))
	{
		if(*p == '\"' || *p == '\'')
		{
			if(*p == '\"')
			{
				char* x = (char*)FindNextDoubleQuote(p+1);

				if(x == NULL)
				{
					m_sErrInfo = "字符串缺少\"";
				}

				return x;
			}
			else
			{
				char* x = strchr(p+1, '\'');
				if(x == NULL)
				{
					m_sErrInfo = "字符符号缺少\'";
					return NULL;
				}
				return x+1;
			}
		}

		return p+1;
	}

	while(ISFULLWORDCHAR(*p))
	{
		p++;
	}
	return p;
}

//插入到最后
void CScript::AddNewToken(LINE* pLine, TOKEN* pToken)
{
	if(pLine->pHead == NULL)
	{
		//还没有
		pToken->pNext = pToken->pPrev = NULL;
		pLine->pHead = pLine->pTail = pToken;
	}
	else if(pLine->pHead == pLine->pTail)
	{
		//只有一个
		pLine->pTail = pToken;
		pToken->pNext = NULL;
		pToken->pPrev = pLine->pHead;

		pLine->pHead->pNext = pToken;
	}
	else
	{
		pToken->pNext = NULL;
		pLine->pTail->pNext = pToken;
		pToken->pPrev = pLine->pTail;
		pLine->pTail = pToken;
	}
}

/*
读取脚本语句的每个token
连续的词: _,$,数字,字母
分隔:空格,tab
*/
int CScript::InitLineToken(LINE* pLine)
{
	ASSERT(pLine->pszLine != NULL);
	char* p = (char*)pLine->pszLine;
	SKIPBLANK(p);
	if(CHAR_ISEND(*p))
		return 0;

	while(1)
	{
		SKIPBLANK(p);
		if(CHAR_ISEND(*p))
			break;

		char* pnext = MoveToTokenEnd(p);
		if(pnext == NULL)
		{
			return -1;
		}

		TOKEN* tk = new TOKEN;
		memset(tk, 0, sizeof(TOKEN));
		tk->pszToken = new char[pnext-p + 1];
		strncpy(tk->pszToken, p, pnext-p);
		tk->pszToken[pnext-p] = 0;

		AddNewToken(pLine, tk);
		p = pnext;
	}
	return 0;
}

int CScript::GetTokenCount(const TOKEN* pTokenHead)
{
	int i = 0;
	TOKEN* p = (TOKEN*)pTokenHead;
	while(p != NULL)
	{
		p = p->pNext;
		i++;
	}
	return i;
}

//判断是否是关键字
BOOL CScript::IsReservedWord(const char* str)
{
	//是否是命令
	for(int i=0;i<sizeof(g_cmddesc)/sizeof(g_cmddesc[0]); i++)
	{
		if(strcmpi(g_cmddesc[i].maincmd, str) == 0)
		{
			return TRUE;
		}
	}
	//是否是寄存器
	if(m_MemExpression.IsValidRegString(str) || m_MemExpression.IsValidRegString2(str))
	{
		return TRUE;
	}

	//其他关键字
	for(i=0;i<sizeof(g_reservedword)/sizeof(g_reservedword[0]); i++)
	{
		if(strcmpi(g_reservedword[i], str) == 0)
		{
			return TRUE;
		}
	}

	return FALSE;
}


/*
	判断变量名称是否合法
	如果合法, pbIsReservedName 保存是否是reserved名称

  必须字母或_开头
*/
BOOL CScript::IsValidVarDeclare(const char* pszVarName, OUT BOOL* pbIsReservedName)
{
	ASSERT(pszVarName != NULL);
	ASSERT(pszVarName[0] != 0); 
	ASSERT(pbIsReservedName != NULL);

	*pbIsReservedName = FALSE;
	if(CHAR_ISCHAR(pszVarName[0]) || pszVarName[0] == '_')
	{
		char* p = (char*)pszVarName+1;
		while(*p)
		{
			if(CHAR_ISCHAR(*p) || CHAR_ISDIGIT(*p) || *p == '_')
			{
			}
			else
			{
				return FALSE;
			}
			p++;
		}

		//判断是否是保留字
		//
		if(IsReservedWord(pszVarName))
		{
			*pbIsReservedName = TRUE;
			return FALSE;
		}

		return TRUE;
	}
	return FALSE;
}

/*
将字符串 "...." 转为字符串,去掉2边的 "
*/
char* CScript::String2String(const char* str)
{
	ASSERT(str != NULL);
	ASSERT(str[0] == '\"');

	char* pEnd = (char*)FindNextDoubleQuote(str+1);
	if(pEnd == NULL)
		return NULL;

	int nMaxLen = pEnd - str +2;
	char* pBuff = new char[nMaxLen];
	if(pBuff == NULL)
		return NULL;
	memset(pBuff, 0, nMaxLen);
	
	int c = 0;
	char* p = (char*)str + 1;
	while(p < pEnd-1)
	{
		if(p[0] == '\\' && p[1] == '\"')
		{
			pBuff[c++] = '\"';
			p+=2;
		}
		else
		{
			pBuff[c++] = *p;
			p++;
		}
	}
	return pBuff;
}

/*
将字符串 "aabbccdd..." 转为16进制字符串,去掉2边的 "
如果不是2的倍数,就在前面加0
*/
BYTE* CScript::String2HexBytes(const char* str, OUT int* plen)
{
	ASSERT(str != NULL);
	ASSERT(str[0] == '\"');
	
	char* pEnd = (char*)FindNextDoubleQuote(str+1);
	if(pEnd == NULL)
		return NULL;

	int nMax = (pEnd - 1) - (str+1);
	if(nMax < 0)
		return NULL;

	BYTE* pData = new BYTE[nMax];
	if(pData == NULL)
		return NULL;
	memset(pData, 0, nMax);

	int c = 0;
	char* p = (char*)str + 1;
	if(nMax % 2)
	{
		if(!CHAR_ISHEXCHAR(p[0]))
		{
			delete[] pData;
			return NULL;
		}

		BYTE x = TOHEXCHAR(toupper(*p));
		pData[c++] = x;
		p++;
	}
	while(p < pEnd-1)
	{
		char c1 = toupper(*p);
		p++;
		char c2 = toupper(*p);
		p++;

		if(!CHAR_ISHEXCHAR(c1) || !CHAR_ISHEXCHAR(c2))
		{
			delete[] pData;
			return NULL;
		}

		BYTE b1 = TOHEXCHAR(c1);
		BYTE b2 = TOHEXCHAR(c2);

		pData[c++] = (b1 << 4) | b2;
	}

	*plen = c;
	return pData;
}

/*判断是不是 
	exp1 X exp2 的形式

	X 表示:
	>
	<
	!=
	==
	>=
	<=
	<<
	>>
 
*/
/*
BOOL CScript::ParseExtraExpression(const char* str, OUT DWORD* pdwValue)
{
	ASSERT(str != NULL);
	ASSERT(pdwValue != NULL);

	char* p = (char*)str;
	while(*p)
	{
		if(*p == '>' || *p == '<' || *p == '!' || *p == '=')
			break;
		p++;
	}
	if(*p == 0 || p == str || p[1] == 0)	//在第一个或最后一个或没有找到
		return FALSE;

	const char* poper = p;

	char* pright = p;
	if(*p == '=' || *p == '<' || *p == '>')
		pright++;
	if(pright[0] == 0)
		return FALSE;

	DWORD dwLeft = 0;
	DWORD dwRight = 0;

	CString sLeft(str, poper-str);
	if(!m_MemExpression.ParseExpression(sLeft, &dwLeft))
		return FALSE;
	if(!m_MemExpression.ParseExpression(pright, &dwRight))
		return FALSE;

	if(poper[0] == '<' && poper[1] == '<')
	{
		*pdwValue = (dwLeft << dwRight);
	}
	else if(poper[0] == '>' && poper[1] == '>')
	{
		*pdwValue = (dwLeft >> dwRight);
	}
	else if(poper[0] == '>' && poper[1] == '=')
	{
		*pdwValue = (dwLeft >= dwRight);
	}
	else if(poper[0] == '<' && poper[1] == '=')
	{
		*pdwValue = (dwLeft <= dwRight);
	}
	else if(poper[0] == '=' && poper[1] == '=')
	{
		*pdwValue = (dwLeft == dwRight);
	}
	else if(poper[0] == '!' && poper[1] == '=')
	{
		*pdwValue = (dwLeft != dwRight);
	}	
	else if(poper[0] == '>')
	{
		*pdwValue = (dwLeft > dwRight);
	}
	else if(poper[0] == '<')
	{
		*pdwValue = (dwLeft < dwRight);
	}
	else
	{
		ASSERT(0);
		*pdwValue = 0;
	}
	return TRUE;
}
*/

/*
pToken开始的列表是否是普通表达式?如果是,返回1 , pdwValue保存值
*/
BOOL CScript::ParseNormalTokenExpression(const TOKEN* pToken, OUT DWORD* pdwValue, OUT CString* pErrmsg)
{
	ASSERT(pToken!=NULL);
	ASSERT(pdwValue!=NULL);

// 	if(!m_pDebugThread->IsDebugging())		
// 	{
// 		return FALSE;
// 	}

	int nBuffer = 0;
	TOKEN* t = (TOKEN*)pToken; 
	while(t != NULL)
	{
		nBuffer += (strlen(t->pszToken) + 4);
		t = t->pNext;
	}

	char* str = new char[nBuffer];
	if(str == NULL)
		return NULL;
	memset(str, 0, nBuffer);

	t = (TOKEN*)pToken;
	while(t != NULL)
	{

		strcat(str, t->pszToken);

		//如果是非符号类的,在token后面加空格
		char ch = t->pszToken[0];
		if(CHAR_ISCHAR(ch) || CHAR_ISDIGIT(ch) || ch == '_')
		{
			strcat(str, " ");
		}


		t = t->pNext;
	}

	DWORD dwAddr;
	if(m_MemExpression.ParseExpression(str, &dwAddr)/* ||
		(dwAddr = m_MemExpression.GetModuleStruFromFunctionName(str)) != 0*/)
	{
		delete[] str;
		str = NULL;

		*pdwValue = dwAddr;
		return TRUE;
	}
	else
	{
		/*
		if(ParseExtraExpression(str, pdwValue))
		{
			delete[] str;
			str = NULL;
			return TRUE;
		}
		*/

		if(pErrmsg != NULL)
		{
			*pErrmsg = m_MemExpression.m_szErrinfo;
		}
	}
	
	delete[] str;
	str = NULL;
	return FALSE;
}

const CVariant* CScript::SearchVariant(const char* pszVarName)
{
	ASSERT(pszVarName != NULL);
	POSITION pos = m_varList.GetHeadPosition();
	while(pos != NULL)
	{
		CVariant* pv = m_varList.GetNext(pos);
		if(strcmpi(pv->GetVarName(), pszVarName) == 0)
		{
			return pv;
		}
	}

	//判断是否是内部变量
	if(strcmpi(pszVarName, "result") == 0)
	{
		return &m_result;
	}

	return NULL;
}

CVariant** CScript::GetAllVariant(OUT int* count)
{
	int c = m_varList.GetCount() + 1;
	CVariant** p = new CVariant*[c];

	int i=0;
	POSITION pos = m_varList.GetHeadPosition();
	while(pos != NULL)
	{
		CVariant* pv = m_varList.GetNext(pos);
		p[i++] = pv;
	}
	p[i] = &m_result;
	*count = c;
	return p;
}


/*
 token是表达式,可以是以下形式:
 '...'
 "string"
 L"string"
 H"xxyyzz"
 其他var名称
 普通表达式 / api名称

  如果合法,返回 CVariant*
*/
CVariant* CScript::TokenToVariant(const TOKEN* pToken, OUT CString* pErrmsg)
{
	ASSERT(pToken != NULL);
	ASSERT(pToken->pszToken != NULL);
	ASSERT(pToken->pszToken[0]);

	DWORD dwValue = 0;
	CVariant* tmpvar = NULL;

	int nTokens = GetTokenCount(pToken);
	char cbFirst = pToken->pszToken[0];
	if(cbFirst == '\'' && nTokens == 1)
	{
		//'...', 里面最多取8位
		ASSERT(strchr(pToken->pszToken + 1, '\'') != NULL);
		if(nTokens != 1)
			return NULL;
		unsigned __int64 v = 0;
		char* p = pToken->pszToken+1;

		if(*p == '\'')
			return NULL;

		while(*p != 0 && *p != '\'')
		{
			v <<= 8;
			BYTE c = *p;

			v |= c;
			p++;
		}

		CVariant* pv = new CVariant;
		pv->SetInt(v);
		return pv;
	}
	else if(cbFirst == '\"')
	{
		//"..."	ansi字符串
		ASSERT(strchr(pToken->pszToken + 1, '\"') != NULL);
		if(nTokens != 1)
			return NULL;


		char* str = String2String(pToken->pszToken);
		if(str == NULL)
			return NULL;
		CVariant* pv = new CVariant;
		pv->SetAnsiString(str);
		delete[] str;
		return pv;
	}
	else if(cbFirst == 'L' &&
		nTokens == 2 && 
		GetNextToken((TOKEN*)pToken)->pszToken[0] == '\"')			//L 本身可以作为变量名称
	{
		//L"..." unicode 字符串
		
		TOKEN* tk = GetNextToken((TOKEN*)pToken);
		char* str = String2String(tk->pszToken);
		if(str == NULL)
			return NULL;
		CVariant* pv = new CVariant;
		pv->SetUnicodeString(str);
		delete[] str;
		return pv;
	}
	else if(cbFirst == 'H' &&
		nTokens == 2 && 
		GetNextToken((TOKEN*)pToken)->pszToken[0] == '\"')			//L 本身可以作为变量名称
	{
		//H"..." HEX 字符串
		
		TOKEN* tk = GetNextToken((TOKEN*)pToken);
		int len = 0;
		BYTE* pData = String2HexBytes(tk->pszToken, &len);
		if(pData == NULL)
			return NULL;
		CVariant* pv = new CVariant;
		pv->SetHexBytes(pData, len);
		delete[] pData;
		return pv;
	}
	else if(nTokens == 1 && (tmpvar = (CVariant*)SearchVariant(pToken->pszToken)))
	{
		// var xx
		// var yy = xx;
		CVariant* pv = new CVariant;
		pv->Assign(tmpvar);
		return pv;
	}
	else if(pToken->pNext == NULL && CHAR_ISDIGIT(pToken->pszToken[0]) && m_MemExpression.IsValidDigitString(pToken->pszToken))
	{
		//16进制数据
		DWORD v;
		sscanf(pToken->pszToken, "%x", &v);
		CVariant* pv = new CVariant;
		pv->SetInt(v);
		return pv;
	}
	else if(ParseNormalTokenExpression(pToken, &dwValue, pErrmsg))
	{
		//普通表达式(就是内存地址框中的表达式)
		CVariant* pv = new CVariant;
		pv->SetInt(dwValue);
		return pv;
	}
	else
	{
	}

	return NULL;
}

/*
判断是否是var定义
pbValid: 如果是var定义,保存 var = 后面的表达式是否合法

  var定义规则:

  var xxx
  var xxx = yyy

*/
BOOL CScript::TokenIs_VarDeclare(const TOKEN* pTokenHead, int nTokens, OUT BOOL* pbValid)
{
	ASSERT(pTokenHead != NULL);
	ASSERT(nTokens > 0);
	
	*pbValid = FALSE;

	TOKEN* k = (TOKEN*)pTokenHead;
	if(strcmpi(k->pszToken, "var") == 0)
	{
		//var ...
		k = k->pNext;
		if(k != NULL)
		{
			//var xxx ...
			// 变量名称
			BOOL bIsReservedName = FALSE;
			if(IsValidVarDeclare(k->pszToken, &bIsReservedName))
			{
				const char* pszVarName = k->pszToken;

				//判断是否已经定义
				if(SearchVariant(pszVarName) != NULL)
				{
					m_sErrInfo.Format("\'%s\' 已定义", pszVarName);
					return TRUE;
				}

				k = k->pNext;
				//可能是var xxx
				if(k == NULL)
				{
					*pbValid = TRUE;

					//加入列表
					CVariant* pvar = new CVariant(pszVarName);
					m_varList.AddTail(pvar);

					return TRUE;		//var xxx
				}
				//必须是 var xxx = 
				if(k->pszToken[0] == '=' && k->pszToken[1] == 0)
				{
					k = k->pNext;
					//var xxx = ...
					if(k != NULL)
					{
						CString sErrmsg2;
						CVariant* ptmpvar = TokenToVariant(k, &sErrmsg2);
						if(ptmpvar != NULL)
						{
							*pbValid = TRUE;
							//加入列表
							CVariant* pvar = new CVariant;
							pvar->Assign(ptmpvar);
							pvar->SetName(pszVarName);
							m_varList.AddTail(pvar);
							delete ptmpvar;
							return TRUE;
						}
						else
						{
							m_sErrInfo = "赋值表达式错误";
							if(!sErrmsg2.IsEmpty())
							{
								m_sErrInfo += "\r\n";
								m_sErrInfo += sErrmsg2;
							}
						}
					}
					else
					{
						//var xxx = 
						m_sErrInfo = "语法错误";
					}
				}
				else
				{
					m_sErrInfo = "语法错误";
				}
			}
			else
			{
				if(bIsReservedName)
					m_sErrInfo.Format("变量 '%s' 是关键字", k->pszToken);
				else
					m_sErrInfo = "变量名称不合法";
			}
		}
		else
		{
			m_sErrInfo = "语法错误";
		}

		return TRUE;
	}

	return FALSE;
}

const TOKEN*  CScript::SearchToken(const TOKEN* pToken, const char* pszToken)
{
	ASSERT(pszToken != NULL);
	ASSERT(pToken!=NULL);
	TOKEN* t = (TOKEN*)pToken;
	while(t != NULL)
	{
		if(strcmp(t->pszToken, pszToken) == 0)
		{
			return t;
		}
		t = t->pNext;
	}
	return NULL;
}

TOKEN* CScript::AllocNewToken(const char* pszToken)
{
	TOKEN* p = new TOKEN;
	p->pNext = p->pPrev = NULL;
	p->pszToken = NULL;
	if(pszToken != NULL)
	{
		p->pszToken = new char[strlen(pszToken) + 2];
		strcpy(p->pszToken, pszToken);
	}
	return p;
}

/*
复制token链, 不包括pTokenEnd
*/
TOKEN* CScript::CopyTokenChain(const TOKEN* pTokenStart, const TOKEN* pTokenEnd)
{
	ASSERT(pTokenEnd != NULL);
	ASSERT(pTokenStart != NULL);
	
	LINE virtualline;
	virtualline.pHead = NULL;
	virtualline.pTail = NULL;
	virtualline.pszLine = NULL;

	TOKEN* p = (TOKEN*)pTokenStart;
	while(p != NULL && p != pTokenEnd)
	{
		TOKEN* t = AllocNewToken(p->pszToken);

		AddNewToken(&virtualline, t);

		p = p->pNext;
	}

	return virtualline.pHead;
}

TOKEN* CScript::CloneTokenChain(const TOKEN* pTokenStart)
{
	ASSERT(pTokenStart != NULL);
	
	LINE virtualline;
	virtualline.pHead = NULL;
	virtualline.pTail = NULL;
	virtualline.pszLine = NULL;
	
	TOKEN* p = (TOKEN*)pTokenStart;
	while(p != NULL)
	{
		TOKEN* t = AllocNewToken(p->pszToken);
		
		AddNewToken(&virtualline, t);
		
		p = p->pNext;
	}
	
	return virtualline.pHead;
}


void CScript::ReleaseTokenChain(TOKEN* pToken)
{
	while(pToken != NULL)
	{
		if(pToken->pszToken != NULL)
		{
			delete[] pToken->pszToken;
			pToken->pszToken = NULL;
		}

		TOKEN* t = pToken;
		pToken = pToken->pNext;
		delete t;
	}
}

/*


(E)AX
(E)BX
(E)CX
(E)DX
(E)SI
(E)DI
(E)SP
(E)BP

EIP		

  AL AH
  BL BH
  CL CH
  DL DH

*/
void CScript::SetRegValue(const char* pszRegName, DWORD dwValue)
{
	ASSERT(pszRegName != NULL);
	ASSERT(m_MemExpression.IsValidRegString(pszRegName) || m_MemExpression.IsValidRegString2(pszRegName));
	int len = strlen(pszRegName);
	if(len != 2 && len != 3)
	{
		ASSERT(0);
		return;
	}

	CONTEXT con;
	if(!m_pDebugThread->SingleDebugGetThreadContext(m_pDebugThread->GetCurrentSingleDebuggingThreadID(), &con))
		return;
	
	char ch1 = tolower(pszRegName[0]);
	char ch2 = tolower(pszRegName[1]);
	char ch3 = tolower(pszRegName[2]);
	char ch4 = tolower(pszRegName[3]);


	if(ch1 == 'e')
	{
		//32bits
		if(ch2 == 'a' && ch3 == 'x')
		{
			con.Eax = dwValue;
		}
		else if(ch2 == 'b' && ch3 == 'x')
		{
			con.Ebx = dwValue;
		}
		else if(ch2 == 'c' && ch3 == 'x')
		{
			con.Ecx = dwValue;
		}
		else if(ch2 == 'd' && ch3 == 'x')
		{
			con.Edx = dwValue;
		}
		else if(ch2 == 's' && ch3 == 'i')
		{
			con.Esi = dwValue;
		}
		else if(ch2 == 'd' && ch3 == 'i')
		{
			con.Edi = dwValue;
		}
		else if(ch2 == 's' && ch3 == 'p')
		{
			con.Esp = dwValue;
		}
		else if(ch2 == 'b' && ch3 == 'p')
		{
			con.Ebp = dwValue;
		}
		else if(ch2 == 'i' && ch3 == 'p')
		{
			con.Eip = dwValue;
		}
		else{
		}
	}
	else if(ch2 == 'l' || ch2 == 'h')
	{
		//8bits
		if(ch1 == 'a' && ch2 == 'l')
		{
			con.Eax &= 0xFFFFFF00;
			con.Eax |= (dwValue & 0xff);
		}
		if(ch1 == 'b' && ch2 == 'l')
		{
			con.Ebx &= 0xFFFFFF00;
			con.Ebx |= (dwValue & 0xff);
		}
		if(ch1 == 'c' && ch2 == 'l')
		{
			con.Ecx &= 0xFFFFFF00;
			con.Ecx |= (dwValue & 0xff);
		}
		if(ch1 == 'd' && ch2 == 'l')
		{
			con.Edx &= 0xFFFFFF00;
			con.Edx |= (dwValue & 0xff);
		}

		if(ch1 == 'a' && ch2 == 'h')
		{
			con.Eax &= 0xFFFF00FF;
			con.Eax |= ((dwValue<<8) & 0x0000FF00);
		}
		if(ch1 == 'b' && ch2 == 'h')
		{
			con.Ebx &= 0xFFFF00FF;
			con.Ebx |= ((dwValue<<8) & 0x0000FF00);
		}
		if(ch1 == 'c' && ch2 == 'h')
		{
			con.Ecx &= 0xFFFF00FF;
			con.Ecx |= ((dwValue<<8) & 0x0000FF00);
		}
		if(ch1 == 'd' && ch2 == 'h')
		{
			con.Edx &= 0xFFFF00FF;
			con.Edx |= ((dwValue<<8) & 0x0000FF00);
		}
	}
	else
	{
		//16 bits
		if(ch1 == 'a' && ch2 == 'x')
		{
			con.Eax &= 0xFFFF0000;
			con.Eax |= (WORD)dwValue;
		}
		if(ch1 == 'b' && ch2 == 'x')
		{
			con.Ebx &= 0xFFFF0000;
			con.Ebx |= (WORD)dwValue;
		}
		if(ch1 == 'c' && ch2 == 'x')
		{
			con.Ecx &= 0xFFFF0000;
			con.Ecx |= (WORD)dwValue;
		}
		if(ch1 == 'd' && ch2 == 'x')
		{
			con.Edx &= 0xFFFF0000;
			con.Edx |= (WORD)dwValue;
		}
		if(ch1 == 's' && ch2 == 'i')
		{
			con.Esi &= 0xFFFF0000;
			con.Esi |= (WORD)dwValue;
		}
		if(ch1 == 'd' && ch2 == 'i')
		{
			con.Edi &= 0xFFFF0000;
			con.Edi |= (WORD)dwValue;
		}
		if(ch1 == 's' && ch2 == 'p')
		{
			con.Esp &= 0xFFFF0000;
			con.Esp |= (WORD)dwValue;
		}
		if(ch1 == 'b' && ch2 == 'p')
		{
			con.Ebp &= 0xFFFF0000;
			con.Ebp |= (WORD)dwValue;
		}
	}

	m_pDebugThread->SingleDebugSetThreadContext(m_pDebugThread->GetCurrentSingleDebuggingThreadID(), &con);
}

/*
判断token是否是 内存表示的开始
 [...]
 或 
 BYTE[...]
 WORD[...]
 DWORD[...]
 QWORD[...]

  如果是,返回内存的长度,(1,2,4,8)
  否则返回-1
  */
int CScript::TokenisPointerStart(const TOKEN* pToken, int nTokens)
{
	ASSERT(pToken != NULL);
	if(nTokens < 3)
		return -1;

	if(pToken->pszToken[0] == '[' && pToken->pszToken[1] == 0)
	{
		//没有前缀
		return sizeof(DWORD);
	}

	if(pToken->pNext->pszToken[0] == '[' && pToken->pNext->pszToken[1] == 0 && nTokens >= 4)
	{
		// xxx [...
		if(strcmpi(pToken->pszToken, "BYTE") == 0)
		{
			return sizeof(BYTE);
		}
		else if(strcmpi(pToken->pszToken, "WORD") == 0)
		{
			return sizeof(WORD);
		}
		else if(strcmpi(pToken->pszToken, "DWORD") == 0)
		{
			return sizeof(DWORD);
		}
		else if(strcmpi(pToken->pszToken, "QWORD") == 0)
		{
			return sizeof(__int64);
		}
		else
		{
			return -1;
		}
	}
	return -1;
}

/*
是否是赋值语句

  reg = ...
  [exp] = ...
  [varname] = ...
  varname = ...
*/
BOOL CScript::TokenIs_Assign(const TOKEN* pTokenHead, int nTokens, OUT BOOL* pbValid)
{
	ASSERT(pTokenHead != NULL);
	ASSERT(nTokens > 0);

	if(nTokens < 3)
		return FALSE;
	
	*pbValid = FALSE;
	
	const TOKEN* psep = SearchToken(pTokenHead, "=");
	if(psep == NULL)
		return FALSE;
	if(psep == pTokenHead || psep->pNext == NULL)
		return FALSE;

	//可能是 ==, != , <=, >=
	{
		if(psep->pNext->pszToken[0] == '=' && psep->pNext->pszToken[1] == 0)
		{
			// ==
			return FALSE;
		}
		char* pprev = psep->pPrev->pszToken;
		if((pprev[0] == '!' || pprev[0] == '<' || pprev[0] == '>') && pprev[1] == 0)
		{
			// !=, <= , >=
			return FALSE;
		}
	}

	//先处理=后面
	CString sErrmsg2;
	CVariant* ptmpvar = TokenToVariant(psep->pNext, &sErrmsg2);
	if(ptmpvar == NULL)
	{
		if(psep->pNext->pNext == NULL)
		{
			m_sErrInfo.Format("\'%s\' 未定义", psep->pNext->pszToken);
		}
		else
		{
			m_sErrInfo = "'=' 后面的表达式非法";
			if(!sErrmsg2.IsEmpty())
			{
				m_sErrInfo += "\r\n";
				m_sErrInfo += sErrmsg2;
			}
		}
		return TRUE;
	}

	CVariant* ptmpexistvar = NULL;
	int nPointerSize = -1;

	//再处理=前面
	TOKEN* pLeft = CopyTokenChain(pTokenHead, psep);
	if(pLeft == NULL)
	{
		delete ptmpvar;
		m_sErrInfo = "内部错误";
		return TRUE;
	}
	int nLeftTokens = GetTokenCount(pLeft);
	ASSERT(nLeftTokens > 0);

	if(nLeftTokens == 1 && 
		(m_MemExpression.IsValidRegString(pLeft->pszToken) || m_MemExpression.IsValidRegString2(pLeft->pszToken)))
	{
		//寄存器
		// reg = ...
		if(ptmpvar->GetType() != MYVARIANT_INT)
		{
			delete ptmpvar;
			ReleaseTokenChain(pLeft);
			m_sErrInfo = "试图将寄存器赋值为非整形数据";
			return TRUE;
		}
		*pbValid = TRUE;
		if(!m_pDebugThread->IsDebugging())
		{
			delete ptmpvar;
			ReleaseTokenChain(pLeft);
			return TRUE;
		}

		SetRegValue(pLeft->pszToken, (DWORD)ptmpvar->GetValue());
		delete ptmpvar;
		ReleaseTokenChain(pLeft);

		//刷新寄存器窗口
		RefreshRegAndMemory();
		return TRUE;
	}
	else if(nLeftTokens == 1 && (ptmpexistvar = (CVariant*)SearchVariant(pLeft->pszToken)))
	{
		//var变量 
		// var_xx = ...
		CString sName = ptmpexistvar->GetVarName();
		ptmpexistvar->Assign(ptmpvar);
		ptmpexistvar->SetName(sName);

		*pbValid = TRUE;
		delete ptmpvar;
		ReleaseTokenChain(pLeft);
		return TRUE;
	}
	else if((nPointerSize = TokenisPointerStart(pLeft, nLeftTokens)) > 0)
	{
		//[xxxx] = ... 
		const TOKEN* pLast = GetLastToken(pLeft);
		ASSERT(pLast != NULL);
		if(pLast->pszToken[0] != ']' && pLast->pszToken[1] != 0)
		{
			delete ptmpvar;
			ReleaseTokenChain(pLeft);
			m_sErrInfo = "赋值语法错误";
			return TRUE;
		}

		const BOOL bHasPrifix = (pLeft->pszToken[0] != '[');

		TOKEN* pPointer = CopyTokenChain(
										bHasPrifix ? pLeft->pNext->pNext : pLeft->pNext, 
										pLast);
		ASSERT(pPointer != NULL);
		ReleaseTokenChain(pLeft);
		pLeft = NULL;

		CString sErrmsg2;
		CVariant* pPVer = TokenToVariant(pPointer);
		if(pPVer == NULL || pPVer->GetType() != MYVARIANT_INT)
		{
			//[..]内的语法错误
			delete ptmpvar;
			delete pPVer;
			ReleaseTokenChain(pPointer);
			m_sErrInfo = "赋值语法错误";

			if(!sErrmsg2.IsEmpty())
			{
				m_sErrInfo += "\r\n";
				m_sErrInfo += sErrmsg2;
			}

			return TRUE;
		}
		ReleaseTokenChain(pLeft);
		ReleaseTokenChain(pPointer);

		*pbValid = TRUE;

		if(ptmpvar->GetType() == MYVARIANT_INT || ptmpvar->GetType() == MYVARIANT_EMPTY)
		{
			unsigned __int64 v = ptmpvar->GetValue();
			m_pDebugThread->WriteDbgProcessMemory((LPVOID)pPVer->GetValue(), &v, nPointerSize);
		}
		else
		{
			int len = 0;
			LPVOID Buff = NULL;
			if(ptmpvar->GetType() == MYVARIANT_STR)
			{
				len = 1 + strlen(ptmpvar->GetAnsiString());
				Buff = (LPVOID)ptmpvar->GetAnsiString();
			}
			else if(ptmpvar->GetType() == MYVARIANT_WCHAR)
			{
				len = 2 + 2 * wcslen(ptmpvar->GetUnicodeString());
				Buff = (LPVOID)ptmpvar->GetUnicodeString();
			}
			else
			{
				ASSERT(ptmpvar->GetType() == MYVARIANT_BYTES);
				Buff = (LPVOID)ptmpvar->GetHexBytes(&len);
			}
			m_pDebugThread->WriteDbgProcessMemory((LPVOID)pPVer->GetValue(), Buff, len);
		}


		delete ptmpvar;

		//刷新内存
		RefreshRegAndMemory();

		return TRUE;
	}
	else
	{
		//语法错误

		if(nLeftTokens == 1)
		{
			if((CHAR_ISDIGIT(pLeft->pszToken[0]) && m_MemExpression.IsValidDigitString(pLeft->pszToken))
				|| pLeft->pszToken[0] == '\"' || pLeft->pszToken[0] == '\'')
			{
				m_sErrInfo = "语法错误:不能向静态数据赋值";
			}
			else
			{
				m_sErrInfo.Format("\'%s\' 未定义", pLeft->pszToken);
			}
		}
		else
		{
			m_sErrInfo = "错误的赋值语句";
		}

		delete ptmpvar;
		ReleaseTokenChain(pLeft);

		return TRUE;
	}
}

void CScript::RefreshRegAndMemory()
{
	UINT dwTID = m_pDebugThread->GetCurrentSingleDebuggingThreadID();
	CONTEXT context;
	m_pDebugThread->SingleDebugGetThreadContext(dwTID, &context);
	
	m_pDebugThread->DisplayRegisterAndMemory(dwTID, &context);

	m_pDebugThread->GetAsmView()->m_dwEflags = context.EFlags;
	m_pDebugThread->GetAsmView()->PostMessage(MSG_REFRESH_SHOW,0, context.Eip);

}

/*
标号和c语言相同

  LABEL:
*/
BOOL CScript::TokenIs_Label(const TOKEN* pTokenHead, int nTokens)
{
	ASSERT(pTokenHead != NULL);
	ASSERT(nTokens > 0);
	
	if(nTokens != 2)
		return FALSE;

	ASSERT(pTokenHead->pNext);
	if(pTokenHead->pNext->pszToken[0] == ':' && pTokenHead->pNext->pszToken[1] == 0)
	{
	}
	else
	{
		return FALSE;
	}

	//xxxxx:

	BOOL bReserved = FALSE;
	if(!IsValidVarDeclare(pTokenHead->pszToken, &bReserved))
	{
		if(bReserved)
		{
			m_sErrInfo = "关键字作为标号";
		}

		return FALSE;
	}


	return TRUE;
}

/*
goto label
*/
BOOL CScript::TokenIs_goto(const TOKEN* pTokenHead, int nTokens, OUT int* nDestLine)
{
	ASSERT(pTokenHead != NULL);
	if(strcmpi(pTokenHead->pszToken, "goto") != 0)
		return FALSE;

	if(nTokens != 2)
	{
		m_sErrInfo = "语法错误";
		return TRUE;
	}

	*nDestLine = -1;

	BOOL bReserved = FALSE;
	if(!IsValidVarDeclare(pTokenHead->pNext->pszToken, &bReserved))
	{
		if(bReserved)
		{
			m_sErrInfo = "关键字作为goto语句标号";
		}
		else
		{
			m_sErrInfo.Format("\'%s\' 不是合法的goto语句标号", pTokenHead->pNext->pszToken);
		}
		return TRUE;
	}

	//寻找目标
	for(int i=0; i<m_nLines; i++)
	{
		if(m_pLines[i].pHead != NULL &&
			TokenIs_Label(m_pLines[i].pHead, GetTokenCount(m_pLines[i].pHead)))
		{
			if(strcmpi(pTokenHead->pNext->pszToken, m_pLines[i].pHead->pszToken) == 0)
			{
				*nDestLine = i;
				return TRUE;
			}
		}
	}
	m_sErrInfo.Format("标号 \'%s\' 未定义", pTokenHead->pNext->pszToken);
	return TRUE;
}

/*
	if_or_while: 返回 LINEIS_IF/LINEIS_WHILE
*/
BOOL CScript::TokenIs_if_while(const TOKEN* pTokenHead, int nTokens,
							   OUT int* if_or_while, OUT DWORD* pdwResult)
{
	ASSERT(pTokenHead != NULL);

	int iw = -1;
	*if_or_while = -1;

	if(strcmpi(pTokenHead->pszToken, "if") == 0)
	{
		iw = LINEIS_IF;
	}
	else if(strcmpi(pTokenHead->pszToken, "while") == 0)
	{
		iw = LINEIS_WHILE;
	}
	else
	{
		return FALSE;
	}

	if(pTokenHead->pNext == NULL)
	{
		m_sErrInfo = "语法错误";
		return TRUE;
	}

	TOKEN* pToken = (TOKEN*)pTokenHead->pNext;

	CString sErrmsg2;
	CVariant* ptmpvar = TokenToVariant(pToken, &sErrmsg2);
	if(ptmpvar == NULL)
	{
		if(pToken->pNext == NULL)
		{
			m_sErrInfo.Format("\'%s\' 未定义", pToken->pszToken);
		}
		else
		{
			m_sErrInfo = "表达式非法" ;
			if(!sErrmsg2.IsEmpty())
			{
				m_sErrInfo += "\r\n";
				m_sErrInfo += sErrmsg2;
			}
		}
		return TRUE;
	}

	if(ptmpvar->GetType() != MYVARIANT_INT && ptmpvar->GetType() != MYVARIANT_EMPTY)
	{
		delete ptmpvar;
		m_sErrInfo = "表达式不是整数";
		return TRUE;
	}

	*pdwResult = (DWORD)ptmpvar->GetValue();
	delete ptmpvar;
	*if_or_while = iw;
	return TRUE;
}

/*
break 或 continue
*/
BOOL CScript::TokenIs_break_continue(const TOKEN* pTokenHead, int nTokens, OUT BOOL* pbValid, IN OUT int* line)
{
	ASSERT(nTokens > 0);
	BOOL bIsBreak = TRUE;
	if(strcmpi(pTokenHead->pszToken, "break") == 0)
	{
		bIsBreak = TRUE;
	}
	else if(strcmpi(pTokenHead->pszToken, "continue") == 0)
	{
		bIsBreak = FALSE;
	}
	else
	{
		return FALSE;
	}
	*pbValid = FALSE;
	if(nTokens != 1)
	{
		m_sErrInfo.Format("'%s' 语法错误", bIsBreak ? "break" : "continue");
		return TRUE;
	}

	//从下一行开始,找 '}'
	for(int i=(*line) + 1; i<m_nLines; i++)
	{
		if(LineIsBrace(i) == 2)
		{
			//找对应的 ifwhile结构
			IF_WHILE_BRACE* pifwhile = NULL;
			POSITION pos = m_ifwhile.GetHeadPosition();
			while(pos != NULL)
			{
				IF_WHILE_BRACE* ptmp = m_ifwhile.GetNext(pos);
				if(ptmp->nPairLine == i && ptmp->if_or_while == LINEIS_WHILE)
				{
					pifwhile = ptmp;
					break;
				}
			}

			if(pifwhile != NULL)
			{
				//找到对应的 {
				*pbValid = TRUE;
				if(bIsBreak)
					*line = i + 1;
				else
					*line = pifwhile->nLine;

				return TRUE;
			}
		}
	}

	m_sErrInfo.Format("'%s' 语法错误:未找到对应的while", bIsBreak ? "break" : "continue");
	return TRUE;
}

char* Bytes2Str(LPVOID pData, int len, int nBlanks, int nBytesPerLine)
{
	if(nBlanks <= 0)
		nBlanks = 1;
	if(nBytesPerLine <= 0)
		nBytesPerLine = 16;
	
	int nLine = (len/nBytesPerLine) + 2;
	int nBuffer = ((2 + nBlanks) * nBytesPerLine + 2) * nLine;
	char* str = new char[nBuffer];
	if(str == NULL)
		return NULL;
	
	
	memset(str, 0, nBuffer);
	
	char* p = str;
	BYTE* data = (BYTE*)pData;
	
	for(int i=0; i<len; i++)
	{
		if(i != 0 && (i%nBytesPerLine) == 0)
		{
			//加上回车换行
			strcpy(p, "\r\n");
			p+=2;
		}
		sprintf(p, "%02X", data[i]);
		p+=2;
		memset(p, ' ', nBlanks);
		p+=nBlanks;
	}
	
	return str;
}

void CScript::CMDprintHelp(int n)
{
	CMDDESC* desc = &g_cmddesc[n];

	CString s = desc->maincmd;
	if(desc->help != NULL)
	{
		s += "\n";
		s += "    ";
		s += desc->help;

		if(desc->usage != NULL)
		{
			s += "\n";
			s += "    Usage:\n";
			s += "    ";
			s += desc->maincmd;
			s += " ";
			s += desc->usage;
		}
	}
	
	s += "\n";
	AddLog(s);
}

//如果参数是1,显示对应的帮助信息
int CScript::CMD_Help(int nCmd, TOKEN* argv[], int argc)
{
	if(argc == 1)
	{
		if(strcmpi(argv[0]->pszToken, "var") == 0)
		{
			AddLog("var\n    变量定义");
		}
		else
		{
			//是否是命令
			int n = -1;
			for(int i=0;i<sizeof(g_cmddesc)/sizeof(g_cmddesc[0]); i++)
			{
				if(strcmpi(g_cmddesc[i].maincmd, argv[0]->pszToken) == 0)
				{
					n = i;
					break;
				}
			}

			if(n >= 0)
			{
				CMDprintHelp(n);
			}
		}
	}
	else
	{
		AddLog("var\n    变量定义\n");
		AddLog("if\n    判断\n");
		AddLog("while\n    循环\n");
		AddLog("break\n    跳出while循环\n");
		AddLog("continue\n    执行while循环\n");
		AddLog("goto\n    跳转到标号处\n");
		
		for(int i=0; i<sizeof(g_cmddesc) / sizeof(g_cmddesc[0]); i++)
		{
			CMDprintHelp(i);
		}

		CString s;
		s.Format("要获取更详细信息,请访问 http://www.mdebug.org/scripthelp.htm\n\n如果要显示单个帮助,请在 %s 后面加上相应的命令",
			g_cmddesc[nCmd].maincmd);
		AddLog(s);
	}

	return 0;
}

//无参数
int CScript::CMD_exit(int nCmd, TOKEN* argv[], int argc)
{
	m_pMainframe->SendMessage(WM_CLOSE);
	return 0;
}

//无参数
int CScript::CMD_Ver(int nCmd, TOKEN* argv[], int argc)
{
	char buff[128];
	sprintf(buff, STRING_VDEBUG_VERSION, __DATE__);
	AddLog(buff);
	return 0;
}

//无参数
int CScript::CMD_CLS(int nCmd, TOKEN* argv[], int argc)
{
	CMainFrame* p = (CMainFrame*)AfxGetApp()->m_pMainWnd;
	p->m_OutPutDlg.m_EditDbgOutput.Empty();
	return 0;
}

/*
第一个参数必须是合法的variant,取得第一个参数
*/
CVariant* CScript::CMDGetCVariant(int nCmd, TOKEN* pToken, int len, OUT CString* pErrmsg)
{
	ASSERT(pErrmsg != NULL);
	ASSERT(nCmd >= 0);

	if(pToken == NULL)
	{
		pErrmsg->Format("%s 语法错误", g_cmddesc[nCmd].maincmd);
		return NULL;
	}

	CString sErrmsg2;
	CVariant* ptmpvar = TokenToVariant(pToken, &sErrmsg2);
	if(ptmpvar == NULL)
	{
		if(pToken->pNext == NULL)
		{
			pErrmsg->Format("\'%s\' 未定义", pToken->pszToken);
		}
		else
		{
			pErrmsg->Format("%s 后面的表达式非法", g_cmddesc[nCmd].maincmd);
			if(!sErrmsg2.IsEmpty())
			{
				*pErrmsg += "\r\n";
				*pErrmsg += sErrmsg2;
			}
		}
		return NULL;
	}
	return ptmpvar;
}

/*
参数必须是合法的string variant,取得参数
*/
WCHAR* CScript::CMDGetStringVariant(int nCmd, TOKEN* pToken, int len, OUT CString* pErrmsg)
{
	CVariant* pvar = CMDGetCVariant(nCmd, pToken, len, pErrmsg);
	if(pvar == NULL)
		return NULL;

	if(pvar->GetType() != MYVARIANT_WCHAR && pvar->GetType() != MYVARIANT_STR)
	{
		*pErrmsg = "表达式类型不是字符串";
		delete pvar;
		pvar = NULL;
		return NULL;
	}

	if(pvar->GetType() == MYVARIANT_WCHAR)
	{
		int len = 1 + wcslen(pvar->GetUnicodeString());
		WCHAR* p = new WCHAR[len];
		if(p == NULL)
		{
			*pErrmsg = "内部错误";
			delete pvar;
			return NULL;
		}
		wcscpy(p, pvar->GetUnicodeString());
		delete pvar;
		return p;
	}
	else
	{
		int len = 1 + MultiByteToWideChar(CP_ACP, 0, pvar->GetAnsiString(), -1, NULL, 0);
		WCHAR* p = new WCHAR[len];
		if(p == NULL)
		{
			*pErrmsg = "内部错误";
			delete pvar;
			return NULL;
		}
		memset(p, 0, sizeof(WCHAR)*len);
		MultiByteToWideChar(CP_ACP, 0, pvar->GetAnsiString(), -1, p, len);
		delete pvar;
		return p;
	}
}

/*
参数必须是合法的 int variant,取得参数
*/
unsigned __int64 CScript::CMDGetintVariant(int nCmd, TOKEN* pToken, int len, OUT CString* pErrmsg, OUT BOOL* pbValid)
{
	*pbValid = FALSE;

	CVariant* pvar = CMDGetCVariant(nCmd, pToken, len, pErrmsg);
	if(pvar == NULL)
		return 0;

	if(pvar->GetType() != MYVARIANT_EMPTY && pvar->GetType() != MYVARIANT_INT)
	{
		*pErrmsg = "表达式类型不是整数";
		delete pvar;
		pvar = NULL;
		return 0;
	}

	*pbValid = TRUE;
	unsigned __int64 v = (pvar->GetType() == MYVARIANT_EMPTY) ? 0 : pvar->GetValue();
	delete pvar;
	return v;
}

CString CScript::GetValueOfVar(CVariant* ptmpvar)
{
	CString s;
	switch(ptmpvar->GetType())
	{
	case MYVARIANT_EMPTY:
		s = "0";
		break;
	case MYVARIANT_INT:
		s.Format("0x%I64X", ptmpvar->GetValue());
		break;
	case MYVARIANT_STR:
		s.Format("%s", ptmpvar->GetAnsiString());
		break;
	case MYVARIANT_WCHAR:
		s.Format("%S", ptmpvar->GetUnicodeString());
		break;
	case MYVARIANT_BYTES:
		{
			int len;
			const BYTE* pBytes = ptmpvar->GetHexBytes(&len);
			
			len = (len > 0x1000) ? 0x1000 : len;
			
			char* p = Bytes2Str((LPVOID)pBytes, len, 0,0);
			if(p != NULL)
			{
				s.Format("%s", p);
				delete[] p;
			}	
		}
		break;
	default:
		ASSERT(0);
		break;
	}

	return s;
}

/*
print <表达式>
*/
int CScript::CMD_PRINT(int nCmd, TOKEN* argv[], int argc)
{
	CVariant* ptmpvar = CMDGetCVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(ptmpvar == NULL)
		return -1;


	CString s = GetValueOfVar(ptmpvar);

	delete ptmpvar;

	AddLog(s);

	return 0;
}

//msg "message"
//和 print 相同
int CScript::CMD_MSG(int nCmd, TOKEN* argv[], int argc)
{
	CVariant* ptmpvar = CMDGetCVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(ptmpvar == NULL)
		return -1;

	
	CString s;
	
	switch(ptmpvar->GetType())
	{
	case MYVARIANT_EMPTY:
		s = "0";
		break;
	case MYVARIANT_INT:
		s.Format("0x%I64X", ptmpvar->GetValue());
		break;
	case MYVARIANT_STR:
		s.Format("%s", ptmpvar->GetAnsiString());
		break;
	case MYVARIANT_WCHAR:
		s.Format("%S", ptmpvar->GetUnicodeString());
		break;
	case MYVARIANT_BYTES:
		{
			int len;
			const BYTE* pBytes = ptmpvar->GetHexBytes(&len);
			
			len = (len > 0x1000) ? 0x1000 : len;
			
			char* p = Bytes2Str((LPVOID)pBytes, len, 0,0);
			if(p != NULL)
			{
				s.Format("%s", p);
				delete[] p;
			}	
		}
		break;
	default:
		ASSERT(0);
		break;
	}
	
	delete ptmpvar;
	
	AfxMessageBox(s, MB_ICONINFORMATION);

	return 0;
}

/*
 YESNO <string>
*/
int CScript::CMD_YESNO(int nCmd, TOKEN* argv[], int argc)
{
	WCHAR* pname = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pname == NULL)
		return -1;

	m_result.Release();
	if(MessageBoxW(m_pMainframe->GetSafeHwnd(), pname, L"请确认", MB_YESNO|MB_ICONQUESTION) == IDYES)
	{
		m_result.SetInt(1);
	}
	else
	{
		m_result.SetInt(0);
	}
	delete[] pname;
	return 0;
}

//无参数
int CScript::CMD_getstr(int nCmd, TOKEN* argv[], int argc)
{
	CScriptGetInputDlg dlg;
	dlg.m_sTitle = "请输入字符串";
	dlg.DoModal();
	
	m_result.Release();
	m_result.SetAnsiString(dlg.m_string);
	return 0;
}

//无参数 
int CScript::CMD_getint(int nCmd, TOKEN* argv[], int argc)
{
	CScriptGetInputDlg dlg;
	dlg.m_sTitle = "请输入16进制数字";
	dlg.DoModal();

	DWORD v = 0;
	sscanf(dlg.m_string, "%X", &v);

	m_result.Release();
	m_result.SetInt(v);
	return 0;
}


//找进程,result返回pid
//findprocess <processname>
int CScript::CMD_findprocess(int nCmd, TOKEN* argv[], int argc)
{
	WCHAR* pname = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pname == NULL)
		return -1;

	DWORD pid = 0;

	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if(hSnap != INVALID_HANDLE_VALUE)
	{
		PROCESSENTRY32W ppe = {0};
		ppe.dwSize = sizeof(ppe);
		BOOL b = Process32FirstW(hSnap, &ppe);
		while(b)
		{
			if(wcsicmp(ppe.szExeFile, pname) == 0)
			{
				pid = ppe.th32ProcessID;
				break;
			}
			
			b = Process32NextW(hSnap, &ppe);
		}
		CloseHandle(hSnap);
	}
	
	m_result.Release();
	m_result.SetInt((DWORD)pid);

	delete[] pname;
	return 0;
}

//等待,直到允许用户输入命令
void CScript::WaitforWaitingUserInput()
{
	if(m_bIsCmdLine)		//如果是在命令行,就不等待
	{
		Sleep(50);
		return;	
	}

	const BOOL bDebugging = m_pDebugThread->IsDebugging();
	ResetEvent(*m_phEvent);

	while(!m_pDebugThread->IsWaitingForCommand())
	{
		if(WaitForSingleObject(*m_phEvent, 50) == WAIT_OBJECT_0)
		{
			break;
		}

		if(m_pbRunning)
		{
			if(!(*m_pbRunning))
			{
				break;
			}
		}

		if(bDebugging)
		{
			if(!m_pDebugThread->IsDebugging())
			{
				//调试结束,就没有必要等待了

				//退出
				if(m_pbRunning)
				{
					*m_pbRunning = FALSE;
				}

				break;
			}
		}
	}
	Sleep(5);
}

//打开文件进行调试
//openfile <path> [,arg]
int CScript::CMD_openfile(int nCmd, TOKEN* argv[], int argc)
{
	if(argc != 1 && argc != 2)
	{
		m_sErrInfo = "语法错误";
		return -1;
	}

	WCHAR* pwszPath = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pwszPath == NULL)
	{
		return -1;
	}
	WCHAR* pwszArgv = NULL;
	if(argc == 2)
	{
		pwszArgv = CMDGetStringVariant(nCmd, argv[1], GetTokenCount(argv[1]), &m_sErrInfo);
		if(pwszArgv == NULL)
		{
			delete[] pwszPath;
			return -1;
		}
	}

	if(GetFileAttributesW(pwszPath) == -1)
	{
		m_sErrInfo.Format("文件 '%S' 不存在", pwszPath);
		delete[] pwszPath;
		delete[] pwszArgv;
		return -1;
	}

	CString sFilePath(pwszPath);

	const BOOL bOpt = m_pApp->m_DebugThread.m_bStartDebugWhenPEFileOpened;
	m_pApp->m_DebugThread.m_bStartDebugWhenPEFileOpened = FALSE;
	m_pApp->OpenDocumentFile(sFilePath);
	m_pApp->m_DebugThread.m_bStartDebugWhenPEFileOpened = bOpt;

	int r = 0;
	if(m_pApp->m_bOpenPEDocumentSucc)
	{
		//打开的是pe文件,并且打开成功
		if(pwszArgv != NULL)
		{
			m_pApp->m_DebugThread.m_sExeParam = pwszArgv;
		}
		
		m_pApp->m_pMainWnd->SendMessage(WM_COMMAND, ID_DBGCMD_GO);

		//等待,直到用户输入界面
		WaitforWaitingUserInput();

	}
	else
	{
		m_sErrInfo = "打开PE文件失败";
		r = -1;
	}

	delete[] pwszPath;
	delete[] pwszArgv;
	return r;
}

//loaddll <path> 向目标进程加载dll
int CScript::CMD_loaddll(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 1);
	if(!m_pDebugThread->IsDebugging())
		return 0;
	WCHAR* pname = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pname == NULL)
		return -1;

	CString sName(pname);
	delete[] pname;

	CString sErr;
	if(m_pDebugThread->InjectDll(sName, &sErr) && m_pDebugThread->IsRunning())
	{
		Sleep(200);
	}
	return 0;
}

//alloc <size> 向目标进程分配内存
int CScript::CMD_alloc(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 1);
	if(!m_pDebugThread->IsDebugging())
	{
		m_result.Release();
		m_result.SetInt(0);
		return 0;
	}

	BOOL bValid = TRUE;
	int ms = (int)CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
	if(!bValid)
		return -1;

	int nPages = ms/0x1000;
	if(nPages <= 0)
	{
		nPages = 1;
	}
	m_result.Release();
	m_result.SetInt((DWORD)m_pDebugThread->DbgVirtualAllocEx(NULL, nPages * 0x1000));
	return 0;
}

/*
readdata <addr>, <size>
*/
int CScript::CMD_readdata(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 2);

	BOOL bValid = TRUE;
	const DWORD dwAddr = (DWORD)CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
	if(!bValid)
		return -1;

	bValid = TRUE;
	const int nReadCount = (int)CMDGetintVariant(nCmd, argv[1], GetTokenCount(argv[1]), &m_sErrInfo, &bValid);
	if(!bValid)
		return -1;

	//
	const DWORD dwPageBase = dwAddr & 0xFFFFF000;
	const DWORD dwPageEnd = ((dwAddr + nReadCount) | 0xFFF) + 1;
	
	const int nPages = (dwPageEnd - dwPageBase) / 0x1000;
	
	WORD* pBuffer = new WORD[nPages * 0x1000];
	if(pBuffer == NULL)
	{
		m_result.Release();
		return 0;
	}
	memset(pBuffer, 0, nPages * 0x1000 * sizeof(WORD));
	
	m_pDebugThread->InternalReadPages(dwPageBase, nPages, pBuffer);
	
	int k = dwAddr - dwPageBase;
	
	BYTE* pRet = new BYTE[nReadCount];
	if(pRet == NULL)
	{
		delete[] pBuffer;
		m_result.Release();
		return 0;
	}
	memset(pRet, 0, nReadCount);
	for(int i=0; i<nReadCount; i++)
	{
		WORD c = pBuffer[k+i];
		if(c >> 8)
			break;
		pRet[i] = (BYTE)c;
	}

	m_result.Release();
	m_result.SetHexBytes(pRet, i);

	delete[] pRet;
	delete[] pBuffer;

	return 0;
}

/*
// !!! 此版本读取不超过8M !!!!
*/
int CScript::CMDReadAnsiOrUnicodeStringFromMemory(int nCmd, TOKEN* argv[], int argc, BOOL bUnicode)
{
	if(!m_pDebugThread->IsDebugging())
		return 0;
	BOOL bValid = TRUE;
	const DWORD dwAddr = (DWORD)CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
	if(!bValid)
		return -1;

	const nReadCount = 0x00800000;

	const DWORD dwPageBase = dwAddr & 0xFFFFF000;
	const DWORD dwPageEnd = ((dwAddr + nReadCount) | 0xFFF) + 1;
	
	const int nPages = (dwPageEnd - dwPageBase) / 0x1000;
	
	WORD* pBuffer = new WORD[nPages * 0x1000];
	if(pBuffer == NULL)
	{
		m_result.Release();
		return 0;
	}
	memset(pBuffer, 0, nPages * 0x1000 * sizeof(WORD));
	
	m_pDebugThread->InternalReadPages(dwPageBase, nPages, pBuffer);
	
	int k = dwAddr - dwPageBase;
	
	BYTE* pRet = new BYTE[nReadCount + 2];
	if(pRet == NULL)
	{
		delete[] pBuffer;
		m_result.Release();
		return 0;
	}
	memset(pRet, 0, nReadCount + 2);
	for(int i=0; i<nReadCount; i++)
	{
		WORD c = pBuffer[k+i];
		if(c >> 8)
			break;
		pRet[i] = (BYTE)c;

		if(pRet[i] == 0 && !bUnicode)
			break;
	}

	m_result.Release();
	if(bUnicode)
	{
		m_result.SetUnicodeString2((WCHAR*)pRet);
	}
	else
	{
		m_result.SetAnsiString((char*)pRet);
	}

	delete[] pRet;
	delete[] pBuffer;

	return 0;
}

/*
readstr <addr>
*/
int CScript::CMD_readstr(int nCmd, TOKEN* argv[], int argc)
{
	return CMDReadAnsiOrUnicodeStringFromMemory(nCmd, argv, argc, FALSE);
}

/*
readwstr <addr>
*/
int CScript::CMD_readwstr(int nCmd, TOKEN* argv[], int argc)
{
	return CMDReadAnsiOrUnicodeStringFromMemory(nCmd, argv, argc, TRUE);
}


//sleep <毫秒>
int CScript::CMD_sleep(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 1);
	BOOL bValid = TRUE;
	int ms = (int)CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
	if(!bValid)
		return -1;

	if(ms == 0)
		return 0;

	if(ms < 100)
	{
		Sleep(ms);
		return 0;
	}

	int elips = 100;
	int times = ms/elips;

	for(int i=0; i<times; i++)
	{
		Sleep(elips);

		if(m_pbRunning)
		{
			if(!(*m_pbRunning))
			{
				break;
			}
		}
	}
	return 0;
}

/*
CMD_GetModuleBase <name or path>
*/
int CScript::CMD_GetModuleBase(int nCmd, TOKEN* argv[], int argc)
{
	if(!m_pDebugThread->IsDebugging())
		return 0;
	WCHAR* pname = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pname == NULL)
		return -1;

	CString sNameOrPath(pname);
	delete[] pname;
	pname = NULL;

	LoadedModule* pMod = m_pDebugThread->GetModuleStruFromLoadedModuleFilePath(sNameOrPath);
	if(pMod == NULL)
	{
		pMod = m_pDebugThread->GetModuleStruFromLoadedModuleFileName(sNameOrPath);
	}
	if(pMod == NULL)
		return 0;

	m_result.Release();
	m_result.SetInt((DWORD)pMod->lpModuleBase);
	return 0;
}

/*
CMD_GetModuleBase <name or path>
*/
int CScript::CMD_GetModuleSize(int nCmd, TOKEN* argv[], int argc)
{
	if(!m_pDebugThread->IsDebugging())
		return 0;
	WCHAR* pname = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pname == NULL)
		return -1;
	
	CString sNameOrPath(pname);
	delete[] pname;
	pname = NULL;
	
	LoadedModule* pMod = m_pDebugThread->GetModuleStruFromLoadedModuleFilePath(sNameOrPath);
	if(pMod == NULL)
	{
		pMod = m_pDebugThread->GetModuleStruFromLoadedModuleFileName(sNameOrPath);
	}
	if(pMod == NULL)
		return 0;

	m_result.Release();
	m_result.SetInt(pMod->dwModuleSize);
	return 0;
}

/*
删除断点,包括硬件断点
bc * : 删除所有
bc addr
*/
int CScript::CMD_bc(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 1);
	if(!m_pDebugThread->IsDebugging())
		return 0;

	if(argv[0]->pszToken[0] == '*' && argv[0]->pszToken[1] == 0)
	{
		//bc *
		m_pDebugThread->DeleteAllHardBP();
		m_pDebugThread->RemoveAllBP();
	}
	else
	{
		//bc addr
		BOOL bValid = TRUE;
		unsigned __int64 addr = CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
		if(!bValid)
			return -1;

		//如果设置了硬件执行断点,那么删除硬件执行断点
		if(m_pDebugThread->IsHardExeBPSetted((DWORD)addr))
		{
			m_pDebugThread->DeleteHardBP((DWORD)addr);
		}

		if(m_pDebugThread->IsBPSetted((DWORD)addr))
		{
			//虽然有断点,但是有可能是调试器自用断点。
			if(!m_pDebugThread->IsDebugInternalBP((DWORD)addr))
			{
				m_pDebugThread->RemoveBP((DWORD)addr);
			}
		}
	}

	//更新bpview,如果bpview已经建立的话
	if(m_pMainframe->m_pBreakPointView != NULL)
	{
		if(::IsWindow(m_pMainframe->m_pBreakPointView->GetSafeHwnd()))
		{
			m_pMainframe->m_pBreakPointView->Refresh();
		}
	}

	if(m_pMainframe->m_pAsmView != NULL)
	{
		m_pMainframe->m_pAsmView->Invalidate();
	}

	return 0;
}

//bp <addr> [,condition] F9断点
int CScript::CMD_bp(int nCmd, TOKEN* argv[], int argc)
{
	if(argc <= 0)
	{
		m_sErrInfo = "语法错误";
		return -1;
	}
	if(!m_pDebugThread->IsDebugging())
		return 0;

	BOOL bValid = TRUE;
	unsigned __int64 addr = CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
	if(!bValid)
		return -1;

	char* pszCondition = NULL;
	CString sCondition;

	if(argc > 1)
	{
		WCHAR* pcondition = CMDGetStringVariant(nCmd, argv[1], GetTokenCount(argv[1]), &m_sErrInfo);
		if(pcondition == NULL)
		{
			if(!m_sErrInfo.IsEmpty())
			{
				m_sErrInfo += ", ";
			}
			m_sErrInfo += "断点条件2边必须用引号";
			return -1;
		}

		sCondition = pcondition;
		delete[] pcondition;
		pszCondition = (char*)(const char*)sCondition;
	}



	if(m_pDebugThread->AddBP((DWORD)addr, NULL, pszCondition, NULL, NULL, NULL, NULL))
	{
		//更新bpview,如果bpview已经建立的话
		if(m_pMainframe->m_pBreakPointView != NULL)
		{
			if(::IsWindow(m_pMainframe->m_pBreakPointView->GetSafeHwnd()))
			{
				//	pMain->m_pBreakPointView->Refresh();
				m_pMainframe->m_pBreakPointView->OnBPHasAdded((DWORD)addr);
			}
		}

		if(m_pMainframe->m_pAsmView != NULL)
		{
			m_pMainframe->m_pAsmView->Invalidate();
		}
	}
	return 0;
}

//bph addr 硬件执行断点
int CScript::CMD_bph(int nCmd, TOKEN* argv[], int argc)
{
	if(!m_pDebugThread->IsDebugging())
		return 0;

	BOOL bValid = TRUE;
	unsigned __int64 addr = CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
	if(!bValid)
		return -1;

	m_pDebugThread->SetHardBP((DWORD)addr, 0, 0);		//execute
	
	//更新bpview,如果bpview已经建立的话
	if(m_pMainframe->m_pBreakPointView != NULL)
	{
		if(::IsWindow(m_pMainframe->m_pBreakPointView->GetSafeHwnd()))
		{
			m_pMainframe->m_pBreakPointView->Refresh();
		}
	}

	if(m_pMainframe->m_pAsmView != NULL)
	{
		m_pMainframe->m_pAsmView->Invalidate();
	}

	return 0;	
}

//r = 0, w = 1
int CScript::CMDbphrw(int nCmd, TOKEN* argv[], int argc, int rw)
{
	ASSERT(argc >= 1);
	if(!m_pDebugThread->IsDebugging())
		return 0;

	if(argc != 1 && argc != 2)
	{
		m_sErrInfo = "语法错误";
		return -1;
	}
	BOOL bValid = TRUE;
	unsigned __int64 addr = CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
	if(!bValid)
		return -1;

	int size = 0;
	if(argc == 2)
	{
		bValid = TRUE;
		unsigned __int64 len = CMDGetintVariant(nCmd, argv[1], GetTokenCount(argv[1]), &m_sErrInfo, &bValid);
		if(!bValid)
			return -1;

		//1,2,4
		if(len != 1 && len != 2 && len != 4)
		{
			m_sErrInfo = "硬件内存断点的长度必须是1/2/4";
			return -1;
		}

		if(len == 2)
			size = 1;
		else if(len == 4)
			size = 3;
		else
			size = 0;
	}

	m_pDebugThread->SetHardBP((DWORD)addr, (rw == 0 ? 3 : 1), size);

	//更新bpview,如果bpview已经建立的话
	if(m_pMainframe->m_pBreakPointView != NULL)
	{
		if(::IsWindow(m_pMainframe->m_pBreakPointView->GetSafeHwnd()))
		{
			m_pMainframe->m_pBreakPointView->Refresh();
		}
	}

	return 0;
}

//bphr <addr> [,size] 硬件读内存断点
int CScript::CMD_bphr(int nCmd, TOKEN* argv[], int argc)
{
	return CMDbphrw(nCmd, argv, argc, 0);
}

//bphw <addr> [,size] 硬件写内存断点
int CScript::CMD_bphw(int nCmd, TOKEN* argv[], int argc)
{
	return CMDbphrw(nCmd, argv, argc, 1);
}


/*
g [addr]
*/
int CScript::CMD_run(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 0 || argc == 1);

	if(m_pDebugThread->m_sDebuggingFileName.IsEmpty())
	{
		m_sErrInfo = "PE文件尚未打开";
		return -1;
	}

	if(argc == 0)
	{
		m_pApp->m_pMainWnd->SendMessage(WM_COMMAND, ID_DBGCMD_GO);
		//等待,直到用户输入界面
		WaitforWaitingUserInput();
		return 0;
	}
	else
	{
		if(!CanStep())
		{
			m_sErrInfo = "进程处于运行状态";
			return -1;
		}
		BOOL bValid = TRUE;
		unsigned __int64 pid = CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
		if(!bValid)
			return -1;

		m_pDebugThread->DebugRunTo((DWORD)pid);
		//等待,直到用户输入界面
		WaitforWaitingUserInput();
		return 0;
	}
}

/*
*/
int CScript::CMD_stop(int nCmd, TOKEN* argv[], int argc)
{
	if(m_pApp->m_bEnabledCmds[ENABLE_DBGCMD_STOP])
	{
		m_pMainframe->SendMessage(WM_COMMAND, ID_DBGCMD_STOP);
	}
	return 0;
}

int CScript::CMD_pause(int nCmd, TOKEN* argv[], int argc)
{
	if(m_pApp->m_bEnabledCmds[ENABLE_DBGCMD_PAUSE])
	{
		m_pMainframe->SendMessage(WM_COMMAND, ID_DBGCMD_PAUSE);
	}
	return 0;
}

int CScript::CMD_restart(int nCmd, TOKEN* argv[], int argc)
{
	if(m_pDebugThread->m_sDebuggingFileName.IsEmpty())
	{
		m_sErrInfo = "PE文件尚未打开";
		return -1;
	}
	if(!m_pApp->m_bEnabledCmds[ENABLE_DBGCMD_STOP])
	{
		m_sErrInfo = "程序尚未运行";
		return -1;
	}

	m_pMainframe->SendMessage(WM_COMMAND, ID_DBGCMD_RESTART);
	//等待,直到用户输入界面
	WaitforWaitingUserInput();
	return 0;
}

int CScript::CMD_dettach(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 0);
	if(m_pDebugThread->IsDebugging())
	{
		m_pMainframe->SendMessage(WM_COMMAND, ID_DBGMENU_DETACH);
	}
	return 0;
}

//attach <pid>
int CScript::CMD_attach(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 1);

	if(m_pDebugThread->IsDebugging())
	{
		m_sErrInfo = "不能在调试状态附加进程";
		return -1;
	}

	BOOL bValid = TRUE;
	unsigned __int64 pid = CMDGetintVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo, &bValid);
	if(!bValid)
		return -1;
	if(!m_pApp->DebugProcess((DWORD)pid))
	{
		m_sErrInfo = "attach 失败";
		return -1;
	}

	//等待,直到用户输入界面
	WaitforWaitingUserInput();

	return 0;
}

//判断是否可以进行单步控制
BOOL CScript::CanStep()
{
	if(m_pMainframe->m_pAsmView == NULL)
		return FALSE;
	else
	{
		return (!m_pDebugThread->IsRunning());
	}
}


//f11
int CScript::CMD_t(int nCmd, TOKEN* argv[], int argc)
{	
	ASSERT(argc == 0);
	if(CanStep())
	{
		m_pMainframe->SendMessage(WM_COMMAND, ID_DBGCMD_STEPINTO);
		WaitforWaitingUserInput();
	}
	return 0;
}

//f10
int CScript::CMD_p(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 0);
	if(CanStep())
	{
		m_pMainframe->SendMessage(WM_COMMAND, ID_DBGCMD_STEPOVER);
		WaitforWaitingUserInput();
	}
	return 0;
}

//运行到返回处
int CScript::CMD_gret(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 0);
	if(CanStep())
	{
		m_pMainframe->SendMessage(WM_COMMAND, ID_DBGCMD_STEPOUT);
		WaitforWaitingUserInput();
	}
	return 0;
}

//strlen <string>
int CScript::CMD_strlen(int nCmd, TOKEN* argv[], int argc)
{
	WCHAR* pstr = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pstr == NULL)
		return -1;
	
	m_result.Release();
	m_result.SetInt(wcslen(pstr));
	delete[] pstr;
	return 0;
}

/*
	strcat var_dst, src
	//第一个参数必须是变量
*/
int CScript::CMD_strcat(int nCmd, TOKEN* argv[], int argc)
{
	ASSERT(argc == 2);
	if(GetTokenCount(argv[0]) != 1)
	{
		m_sErrInfo = "语法错误:strcat 第一个参数必须是变量";
		return -1;
	}

	CVariant* pdst = (CVariant*)SearchVariant(argv[0]->pszToken);
	if(pdst == NULL)
	{
		m_sErrInfo = "语法错误:strcat 第一个参数必须是变量";
		return -1;
	}
	if(pdst->GetType() != MYVARIANT_STR && pdst->GetType() != MYVARIANT_WCHAR)
	{
		m_sErrInfo = "错误:strcat 第一个参数类型不是字符串";
		return -1;
	}
	WCHAR* pstrdst = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pstrdst == NULL)
		return -1;

	WCHAR* pstr = CMDGetStringVariant(nCmd, argv[1], GetTokenCount(argv[1]), &m_sErrInfo);
	if(pstr == NULL)
	{
		delete[] pstrdst;
		return -1;
	}

	int len = wcslen(pstrdst) + 2 + wcslen(pstr) + 2;
	WCHAR* pwszNew = new WCHAR[len];
	if(pwszNew == NULL)
	{
		delete[] pstrdst;
		delete[] pstr;
		m_sErrInfo = "内部错误";
		return -1;
	}

	wcscpy(pwszNew, pstrdst);
	wcscat(pwszNew, pstr);

	delete[] pstrdst;
	delete[] pstr;
	pstrdst = pstr = NULL;

	if(pdst->GetType() == MYVARIANT_WCHAR)
	{
		pdst->Release();
		pdst->SetUnicodeString2(pwszNew);
	}
	else
	{
		pdst->Release();
		pdst->SetUnicodeStringToAnsiString(pwszNew);
	}

	delete[] pwszNew;
	return 0;
}

/*
strcmp str1, str2
*/
int CScript::CMDstrcmpx(int nCmd, TOKEN* argv[], int argc, int i)
{
	ASSERT(argc == 2);

	WCHAR* pstr1 = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pstr1 == NULL)
		return -1;

	WCHAR* pstr2 = CMDGetStringVariant(nCmd, argv[1], GetTokenCount(argv[1]), &m_sErrInfo);
	if(pstr2 == NULL)
	{
		delete[] pstr1;
		return -1;
	}

	int r = (i == 0) ? wcscmp(pstr1, pstr2) : wcsicmp(pstr1, pstr2);
	m_result.Release();
	m_result.SetInt(r);
	delete[] pstr1;
	delete[] pstr2;
	return 0;
}

int CScript::CMD_strcmp(int nCmd, TOKEN* argv[], int argc)
{
	return CMDstrcmpx(nCmd, argv, argc, 0);
}

int CScript::CMD_strcmpi(int nCmd, TOKEN* argv[], int argc)
{
	return CMDstrcmpx(nCmd, argv, argc, 1);
}

/*
strstr str1, str2
*/
int CScript::CMDstrstrx(int nCmd, TOKEN* argv[], int argc, int i)
{
	ASSERT(argc == 2);
	
	WCHAR* pstr1 = CMDGetStringVariant(nCmd, argv[0], GetTokenCount(argv[0]), &m_sErrInfo);
	if(pstr1 == NULL)
		return -1;
	
	WCHAR* pstr2 = CMDGetStringVariant(nCmd, argv[1], GetTokenCount(argv[1]), &m_sErrInfo);
	if(pstr2 == NULL)
	{
		delete[] pstr1;
		return -1;
	}

	WCHAR* r;
	if(i == 0)
	{
		r = wcsstr(pstr1, pstr2);
	}
	else
	{
		wcslwr(pstr1);
		wcslwr(pstr2);
		r = wcsstr(pstr1, pstr2);
	}

	m_result.Release();
	if(r == NULL)
		m_result.SetUnicodeString2(L"");
	else
		m_result.SetUnicodeString2(r);
	
	return 0;
}

int CScript::CMD_strstr(int nCmd, TOKEN* argv[], int argc)
{
	return CMDstrstrx(nCmd, argv, argc, 0);
}

int CScript::CMD_strstri(int nCmd, TOKEN* argv[], int argc)
{
	return CMDstrstrx(nCmd, argv, argc, 1);
}

//strupr string
int CScript::CMDstruprlwr(int nCmd, TOKEN* argv[], int argc, int i)
{
	ASSERT(argc == 1);
	if(GetTokenCount(argv[0]) != 1)
	{
		m_sErrInfo = "语法错误:第一个参数必须是变量";
		return -1;
	}
	
	CVariant* pdst = (CVariant*)SearchVariant(argv[0]->pszToken);
	if(pdst == NULL)
	{
		m_sErrInfo = "语法错误:第一个参数必须是变量";
		return -1;
	}
	if(pdst->GetType() != MYVARIANT_STR && pdst->GetType() != MYVARIANT_WCHAR)
	{
		m_sErrInfo = "错误:第一个参数类型不是字符串";
		return -1;
	}

	if(i == 0)
	{
		if(pdst->GetType() == MYVARIANT_WCHAR)
		{
			wcslwr((WCHAR*)pdst->GetUnicodeString());
		}
		else
		{
			strlwr((char*)pdst->GetAnsiString());
		}
	}
	else
	{
		if(pdst->GetType() == MYVARIANT_WCHAR)
		{
			wcsupr((WCHAR*)pdst->GetUnicodeString());
		}
		else
		{
			strupr((char*)pdst->GetAnsiString());
		}
	}
	return 0;
}

int CScript::CMD_strlwr(int nCmd, TOKEN* argv[], int argc)
{
	return CMDstruprlwr(nCmd, argv, argc, 0);
}

int CScript::CMD_strupr(int nCmd, TOKEN* argv[], int argc)
{
	return CMDstruprlwr(nCmd, argv, argc, 1);
}

void CScript::AddLog(const char* pszText)
{
	m_pDebugThread->AddLog(pszText);
}

TOKEN** CScript::Convertoargv(const TOKEN* pTokenHead, int nTokens, OUT int* pargc, OUT BOOL* pbValid)
{
	ASSERT(nTokens >= 0);
	ASSERT(pargc != NULL);
	if(pTokenHead == NULL || nTokens == 0)
	{
		*pargc = 0;
		*pbValid = TRUE;
		return NULL;
	}

	BOOL bFail = FALSE;
	TOKEN** pMaxToken = new TOKEN*[nTokens];
	if(pMaxToken == NULL)
	{
		*pargc = 0;
		*pbValid = FALSE;
		m_sErrInfo = "内部错误";
		return NULL;
	}

	int argc = 0;

	TOKEN* p = (TOKEN*)pTokenHead;
	while(p != NULL)
	{
		const TOKEN* pt = SearchToken(p, ",");
		if(pt == p)
		{
			bFail = TRUE;
			break;
		}
		pMaxToken[argc] = (pt == NULL) ? CloneTokenChain(p) : CopyTokenChain(p, pt);
		argc++;

		if(pt == NULL)
		{
			break;
		}

		p = pt->pNext;
	}

	if(bFail)
	{
		for(int i=0; i<argc; i++)
		{
			ReleaseTokenChain(pMaxToken[i]);
		}
		delete[] pMaxToken;
		*pbValid = FALSE;
		m_sErrInfo = "语法错误";
		return NULL;
	}

	*pbValid = TRUE;
	*pargc = argc;
	return pMaxToken;
}

/*
 cmd [arg1], [arg2], [arg3], ...
*/
int CScript::ExecNormalCmd(const TOKEN* pTokenHead, int nTokens)
{
	ASSERT(pTokenHead != NULL);
	ASSERT(nTokens > 0);

	for(int i=0; i<sizeof(g_cmddesc) / sizeof(g_cmddesc[0]); i++)
	{
		if(strcmpi(pTokenHead->pszToken, g_cmddesc[i].maincmd) == 0)
		{
			//按照','进行分割
			int argc = 0;
			BOOL bValid = TRUE;
			TOKEN** pTokenargv = Convertoargv(pTokenHead->pNext, nTokens-1, &argc, &bValid);
			if(!bValid)
			{
				return -1;
			}

			int r = -1;
			if(g_cmddesc[i].argc >= 0 && g_cmddesc[i].argc != argc)
			{
				if(g_cmddesc[i].argc == 0)
				{
					m_sErrInfo.Format("语法错误:'%s' 命令无参数", g_cmddesc[i].maincmd);
				}
				else
				{
					m_sErrInfo.Format("语法错误:'%s' 命令的参数数量应该为 %d", g_cmddesc[i].maincmd, g_cmddesc[i].argc);
				}
			}
			else
			{
				r = (this->*g_cmddesc[i].handler)(i, pTokenargv, argc);
			}


			//释放
			for(int k=0; k<argc; k++)
			{
				ReleaseTokenChain(pTokenargv[k]);
			}
			if(pTokenargv != NULL)
			{
				delete[] pTokenargv;
				pTokenargv = NULL;
			}
			return r;
		}
	}

	m_sErrInfo.Format("非法指令: \'%s\'", pTokenHead->pszToken);

	return -1;
}

int CScript::ScanToken(const TOKEN* pTokenHead)
{
	ASSERT(pTokenHead != NULL);

	//{ 或 } 必须占一行
	if(pTokenHead->pNext != NULL && 
		(pTokenHead->pszToken[0] == '{' || pTokenHead->pszToken[0] == '}'))
	{
		m_sErrInfo = "\'{\' 或 \'}\' 必须独占一行";
		return -1;
	}

	//扫描有无非法字符
	TOKEN* pToken = (TOKEN*)pTokenHead;
	while(pToken != NULL)
	{
		char ch = pToken->pszToken[0];
		if(ch == ';' || ch == '`' || ch == '@' || ch == '#')
		{
			m_sErrInfo.Format("非法字符 '%c'", ch);
			return -1;
		}

		pToken = pToken->pNext;
	}

	return 0;
}

//取下一个有效的行(就是非空行)
int CScript::GetNextEffectLine(int nLine)
{
	nLine++;
	while(nLine < m_nLines)
	{
		if(m_pLines[nLine].pHead != NULL)
		{
			return nLine;
		}
		nLine++;
	}
	return -1;
}

/*
当前行nLine是{, 找下面的对应的 }下面的一行
例如: 
 {		//nLine
 }		=> 返回这一行	
 

 {		//nLine
  {
  }
 }		=> 返回这一行
 

*/
int CScript::GetNextPairBraceLine(int nLine)
{
	ASSERT(nLine >= 0);
	ASSERT(LineIsBrace(nLine));

	int k = 0;
	while(nLine < m_nLines)
	{
		int n = LineIsBrace(nLine);
		if(n == 1)
			k++;
		if(n == 2)
			k--;

		if(k <= 0)
		{
			ASSERT(k == 0);
			break;
		}

		nLine++;
	}

	if(nLine >= m_nLines)
		return -1;

	ASSERT(LineIsBrace(nLine) == 2);
	return nLine;
}

/*
判断该行是否是 { 或 }
如果是 {返回1, 如果是 }返回2,否则返回0
*/
int CScript::LineIsBrace(int nLine)
{
	ASSERT(nLine < m_nLines);

	if(nLine < 0 || nLine >= m_nLines)
		return 0;

	if(m_pLines[nLine].pHead == NULL)
		return 0;
	if(m_pLines[nLine].pHead->pNext != NULL)
		return 0;

	char ch  = m_pLines[nLine].pHead->pszToken[0];
	char ch1 = m_pLines[nLine].pHead->pszToken[1];

	if(ch1 != 0)
		return 0;
	if(ch == '{')
		return 1;
	else if(ch == '}')
		return 2;
	else
		return 0;
}

/*
执行if/while
会有嵌套

  if/while(..)后面必须是:
  {
	...
	...
	if/while()
	{
	  ...
	  ...
	  if/while()
	  {
	    ...
		...
	  }
	}
  }
*/
int CScript::Exec_if_or_while(int if_or_while, BOOL bJmp, IN OUT int* line)
{
	ASSERT(if_or_while >= 0);
	ASSERT(line != NULL);

	const char* pszWord = (if_or_while == LINEIS_IF) ? "if" : "while";

	//下一行必须是 {
	//取下一行
	int nNextLine = GetNextEffectLine(*line);
	if(nNextLine < 0 || LineIsBrace(nNextLine) != 1)
	{
		m_sErrInfo.Format("语法错误: %s 后面一行必须为 '{'", pszWord);
		return -1;
	}

	//nNextLine 是 { 所在的行
	int n = GetNextPairBraceLine(nNextLine);
	if(n < 0)
	{
		m_sErrInfo.Format("语法错误: %s 缺少 '}'", pszWord);
		return -1;
	}

	if(bJmp)
	{
		//执行if/while里面的代码
		IF_WHILE_BRACE* pifwhilebrace = new IF_WHILE_BRACE;
		pifwhilebrace->if_or_while = if_or_while;
		pifwhilebrace->nLine = (*line);
		pifwhilebrace->nPairLine = n;
		m_ifwhile.AddTail(pifwhilebrace);

		*line = nNextLine + 1;	//执行 { 的下一行
		return 0;
	}
	else
	{
		//不执行if/while里面的代码,跳到{ } 外面
		*line = n + 1;
		return 0;
	}
}

/*
处理 } 行
*/
int CScript::ParseRightBrace(IN OUT int* line)
{
	ASSERT(LineIsBrace(*line) == 2);

	//找对应的 ifwhile结构
	IF_WHILE_BRACE* pifwhile = NULL;
	POSITION pos = m_ifwhile.GetHeadPosition();
	while(pos != NULL)
	{
		IF_WHILE_BRACE* ptmp = m_ifwhile.GetNext(pos);
		if(ptmp->nPairLine == *line)
		{
			pifwhile = ptmp;
			break;
		}
	}
	if(pifwhile == NULL)
	{
		m_sErrInfo = "语法错误:'}' 位置非法";
		return -1;
	}

	if(pifwhile->if_or_while == LINEIS_IF)
	{
		//执行下一行
		(*line)++;
		return 0;
	}
	else
	{
		ASSERT(pifwhile->if_or_while == LINEIS_WHILE);
		//执行while所在行
		*line = pifwhile->nLine;
		return 0;
	}
}	

/*
执行一行
*/
int CScript::ExecToken(const TOKEN* pTokenHead, IN OUT int* line)
{
	int nTokens = GetTokenCount(pTokenHead);
	if(nTokens == 0)	//空行
	{
		(*line)++;
		return 0;
	}

	//判断是否是var定义,如果是,将变量名称保存起来
	BOOL bValid = TRUE;
	if(TokenIs_VarDeclare(pTokenHead, nTokens, &bValid))
	{
		if(!bValid)
		{
			return -1;
		}
		(*line)++;
		return 0;
	}

	//判断是否是赋值语句
	if(TokenIs_Assign(pTokenHead, nTokens, &bValid))
	{
		if(!bValid)
		{
			return -1;
		}
		(*line)++;
		return 0;
	}

	//判断是否是标号
	if(TokenIs_Label(pTokenHead, nTokens))
	{
		(*line)++;
		return 0;
	}

	//判断是否是goto
	int gotodest = -1;
	if(TokenIs_goto(pTokenHead, nTokens, &gotodest))
	{
		if(gotodest < 0)
		{
			return -1;
		}
		*line = gotodest;
		return 0;
	}

	//if/while
	int if_or_while = -1;
	DWORD dwTemp = 0;
	if(TokenIs_if_while(pTokenHead, nTokens, &if_or_while, &dwTemp))
	{
		if(if_or_while < 0)
		{
			return -1;
		}

		return Exec_if_or_while(if_or_while, (dwTemp != 0), line);
	}

	// { 或 }
	if(LineIsBrace(*line) == 1)
	{
		// 是 {
		m_sErrInfo = "语法错误:'{' 位置非法";
		return -1;
	}
	if(LineIsBrace(*line) == 2)
	{
		// 是 }
		if(ParseRightBrace(line) < 0)
		{
			return -1;
		}

		return 0;
	}

	//判断是否是break/continue
	bValid = TRUE;
	if(TokenIs_break_continue(pTokenHead, nTokens, &bValid, line))
	{
		if(!bValid)
		{
			return -1;
		}
//
		return 0;
	}

	//执行普通的cmd
	if(ExecNormalCmd(pTokenHead, nTokens) < 0)
	{
		return -1;
	}

	(*line)++;
	return 0;
}

int CScript::ExeScript(const char* pszScript, int nLen)
{
	ASSERT(pszScript != NULL);
	ASSERT(nLen > 0);

	m_pszCopy = new char[nLen+1];
	if(m_pszCopy == NULL)
	{
		m_sErrInfo = "内存不足";
		return -1;
	}
	strcpy(m_pszCopy, pszScript);
	DeleteComment(m_pszCopy, nLen);

	m_nLines = GetLineCount(m_pszCopy);
	ASSERT(m_nLines > 0);

	//申请内存保存每一行
	m_pLines = new LINE[m_nLines];
	if(m_pLines == NULL)
	{
		m_sErrInfo = "内存不足";
		return -1;
	}
	memset(m_pLines, 0, sizeof(LINE)*m_nLines);
	SaveToLines(m_pszCopy);

	//初始化收集token
	for(int i=0; i<m_nLines; i++)
	{
		if(InitLineToken(&m_pLines[i]) != 0)
		{
			m_errLine = i;
			return -1;
		}
	}

	//扫描
	for(i=0; i<m_nLines; i++)
	{
		m_sErrInfo.Empty();
		if(m_pLines[i].pHead != NULL && 
			ScanToken(m_pLines[i].pHead) != 0)
		{
			m_errLine = i;
			return -1;
		}
	}	

	BOOL bDebugging = FALSE;	//如果从调试状态转到非调试状态,那么退出执行

	//开始执行
	i = 0;
	while(i < m_nLines && (m_pbRunning == NULL || *m_pbRunning))
	{
		if(m_pDebugThread->IsDebugging())
		{
			bDebugging = TRUE;
		}

		if(bDebugging && !m_pDebugThread->IsDebugging())
		{
			break;
		}

		//跳过空行
		if(m_pLines[i].pHead == NULL)
		{
			i++;
			continue;
		}

		if(m_pScriptView != NULL)
		{
			//判断是否是断点
			if(m_pScriptView->LineIsBP(i))
			{
				*m_pbDebugging = TRUE;
			}
			m_pScriptView->m_nCurrentLine = i;
			if(*m_pbDebugging)
			{
				m_pScriptView->SetLineVisible(i);
				m_pScriptView->m_pLeftWnd->Invalidate();
			}
		}


		if(*m_pbDebugging)
		{
			ASSERT(m_phDebugEvent != NULL);
			//单步调试
			ResetEvent(*m_phDebugEvent);
			WaitForSingleObject(*m_phDebugEvent, INFINITE);

			if(!(*m_pbRunning))
			{
				break;
			}
			if(bDebugging && !m_pDebugThread->IsDebugging())
			{
				break;
			}
		}

		m_sErrInfo.Empty();
		if(ExecToken(m_pLines[i].pHead, &i) != 0)
		{
			m_errLine = i;
			return -1;
		}
	}
	return 0;
}
2012-1-18 01:16
0
雪    币: 768
活跃值: (530)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
10
版主V5
2012-1-18 08:36
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
膜拜啊,膜拜accessd大神
2012-1-18 08:42
0
雪    币: 14
活跃值: (28)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
版主,我开始写脚本解释器,是因为没有看你的SDK。我以为你没提供脚本,才打算为MDebug做点贡献。后来看到你的SDK之后,我就直接把解释器发到工具区了。

哎,开源的牛。个个都说自己代码写的搓,看了他们的代码之后,搞的我都不好意思把代码放出来
2012-1-18 13:02
0
雪    币: 12
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
accessd 太帅了,学习中
2012-1-18 13:09
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
14
不错,挺漂亮的,很帅
2012-1-22 10:27
0
雪    币: 14
活跃值: (28)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
偶。。。似乎没有MDebug的界面灵活哦。。。不知道选中一个CALL,然后所有CALL都变色是怎么搞出来的。难道对API动了手脚?
2012-1-22 19:40
0
雪    币: 768
活跃值: (530)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
16
过年了,拜年,新年快乐:)
2012-1-22 20:41
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
17
先祝你新春快乐
2012-1-23 00:07
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
18
祝新春快乐!
2012-1-23 00:07
0
雪    币: 270
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
快出新版本啊!
2012-1-23 00:14
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
20
大家都不喜欢用 Parser Generator?
2012-1-24 11:25
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
21
lex语法太麻烦了,生成的代码比较冗余,不如直接写更轻松
2012-1-24 19:13
0
雪    币: 14
活跃值: (28)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
说到冗余,LCC的词法分析就没多少冗余。一遍搞定所有关键字和ID,整个LCC只需一遍编译即可完成,支持C99标准,生成的汇编代码还挺漂亮。它的词法分析器就是纯手工,很精巧...
...........

case 'c':
                        if(p[0]=='h'&&p[1]=='a'&&p[2]=='r'&&!(g_op[p[3]].land&(DIGIT|LETTER)))
                        {
                                g_pSourceCur = p + 3; return CHAR;
                        }

                        if(p[0]=='o'&&p[1]=='n'&&p[2]=='t'&&p[3]=='i'&&p[4]=='n'&&p[5]=='u'&&p[6]=='e'
                                &&!(g_op[p[7]].land&(DIGIT|LETTER)))
                        {
                                g_pSourceCur=p+7; return CONTINUE;
                        }goto goto_addr_id;

                case 'd':
                        if( p[0]=='o'&&p[1]=='u'&&p[2]=='b'&&p[3]=='l'&&p[4]=='e'&&
                                !(g_op[p[5]].land&(DIGIT|LETTER)))
                        {
                                g_pSourceCur = p + 5; return DOUBLE;
                        }goto goto_addr_id;

                case 'e':
                        if(p[0]=='l'&&p[1]=='s'&&p[2]=='e' && !(g_op[p[3]].land&(DIGIT|LETTER)))
                        {
                                g_pSourceCur=p+3; return ELSE;
                        }

                        if(p[0]=='x'&&p[1]=='t'&&p[2]=='e'&&p[3]=='r'&&p[4]=='n'&&
                                !(g_op[p[5]].land&(DIGIT|LETTER)))
                        {
                                g_pSourceCur = p + 5; return EXTERN;
                        }goto goto_addr_id;
........
2012-1-24 20:22
0
雪    币: 57
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
继续学习+关注中
2012-2-12 09:28
0
雪    币: 1115
活跃值: (122)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
24
过年过的都不会编程了,还没有进入开工状态
2012-2-12 09:53
0
游客
登录 | 注册 方可回帖
返回
//