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

📄 fileex.cpp

📁 Visual C++编写的工程解析器源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// FileEx.cpp: implementation of the CFileEx class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "FileEx.h"

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

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

CFileEx::CFileEx()
{
}

CFileEx::~CFileEx()
{
}

BOOL CFileEx::IsEof()
{
	BOOL bRet = FALSE;
	
	DWORD dwOldPos = GetPosition();
	SeekToEnd();
	DWORD dwEnd = GetPosition();
	bRet = (dwOldPos == dwEnd);
	
	SeekToBegin();
	DWORD dwBegin = GetPosition();
	Seek(dwOldPos - dwBegin, CFile::begin);
	
	return bRet;
}

//从当前位置读内容到行结尾
CString CFileEx::ReadALine()
{
	char ch;
	CString strRet = "";
	strRet.Empty();
	
	//如果不到文件尾并且没有碰到换行符
	while(Read(&ch, 1) >= 1 && ch != '\n')
	{
		strRet.Insert(strRet.GetLength(), ch);
	}
	return strRet;
}

long CFileEx::GetFileLines()
{
	long m_nFileLines = 0;
	
	//保存文件指针的当前位置
	DWORD dwOldPos = GetPosition();		
	//文件开始和结束位置		
	SeekToEnd();
	DWORD dwEndPos = GetPosition();
	//从文件头部开始统计
	SeekToBegin();
	DWORD dwBeginPos = GetPosition();
	//
	while(GetPosition() != dwEndPos)
	{
		ReadALine();
		++m_nFileLines;
	}
	//恢复原指针位置
	Seek(dwOldPos - dwBeginPos, CFile::begin);
	
	return m_nFileLines;
}

//得到当前无注释的源文件路径
CString CFileEx::GetNoNotesFilePath(CString strFilename)
{
	CString m_strRet = "";
	
	char lpAppname[MAX_PATH];
	memset(lpAppname, 0x0, sizeof(lpAppname));
	::GetModuleFileName(::AfxGetInstanceHandle(), lpAppname, MAX_PATH);
	
	m_strRet.Format("%s", lpAppname);
	m_strRet = m_strRet.Left( m_strRet.ReverseFind('\\') + 1 );
	m_strRet += strFilename.Right(strFilename.GetLength() - strFilename.ReverseFind('\\') - 1);
	
	return m_strRet;
}

/*******************CParseVCFile文件解析类******************/
CParseVCFile::CParseVCFile()
{
	m_slstSource.RemoveAll();
	m_slstHead.RemoveAll();
}

CParseVCFile::~CParseVCFile()
{
	if(!m_slstSource.IsEmpty())
		m_slstSource.RemoveAll();
	
	if(!m_slstHead.IsEmpty())
		m_slstHead.RemoveAll();
}

//解析.CPP|.H|.RC文件
void CParseVCFile::InitFileList()
{
	BOOL bFlag = FALSE;
	char lpszFindStart[] = "SOURCE=.\\",
		lpszCppFileExt[] = ".CPP",			//不区分大小写比较
		lpszHeadFileExt[] = ".H";
	
	int nIndex = this->GetFilePath().ReverseFind('\\');
	CString strCppBasePath = this->GetFilePath().Left(nIndex + 1);	//CPP基路径
	
	SeekToBegin();
	while(!IsEof())
	{
		CString strLine = this->ReadALine();
		
		//如果找到一个CPP文件路径
		if(strLine.Find(lpszFindStart) == 0)
		{
			CString strCppFilename = strLine.Right(strLine.GetLength() - strlen(lpszFindStart));
			
			CString strCppPath = strCppBasePath + strCppFilename;
			
			strCppFilename.MakeUpper();
			int nIndex = strCppFilename.ReverseFind('.');

			if(strCppFilename.Find(lpszCppFileExt) == nIndex)			
				m_slstSource.AddTail(strCppPath);

			else if(strCppFilename.Find(lpszHeadFileExt) == nIndex)
				m_slstHead.AddTail(strCppPath);			
		}
	}
}

//移除.H/.CPP文件中的所有注释内容
BOOL CParseVCFile::RemoveVCFileNoteInfo(char strVCFilename[MAX_PATH])
{	
	m_strNoNotesFilename = GetNoNotesFilePath(strVCFilename);	

	FILE* file;		FILE* lpfile;

	//写无注释内容到lpfile文件
	lpfile = fopen(m_strNoNotesFilename.GetBuffer(0), "w");
	if(lpfile == NULL)	return FALSE;	//打开写文件失败

	//由于效率问题所以采用C语言文件操作
	file = fopen(strVCFilename, "r");	//以只读方式打开文件
	
	if(file == NULL)
	{
		fclose(lpfile);	//关闭写文件
		::DeleteFile((LPCTSTR)m_strNoNotesFilename);
		return FALSE;	//打开读文件失败
	}
	
	char bufLine[MAX_LINE_SIZE];		//存放行内容
	memset(bufLine, 0x0, sizeof(bufLine));
	
	while(!feof(file))					//循环遍历文件内容
	{		
		char buf[3];					//用于判断是否为注释符号
		memset(buf, 0x0, sizeof(buf));	
		
		//读2个连续的字节[即:同一行的两个字节]
		//如果到行尾则有多少读多少(可能读不够两个字节)
		int i = 0; 
		while(!feof(file) && i < 2)		
		{	
			char ch = 0;	
			fread(&ch, sizeof(char), 1, file);	
			buf[i++] = ch; 
			if(ch == '\n')	break;
		}
		
		//如果其中有字符串标志符则一直读到该字符串的结尾[字符串的优先级最高]
		/************************以下部分对字符串进行了过滤************************/
		char* p = strchr(buf, GLOBAL_VCSTR_SPECCHAR);
		if(p != NULL)
		{
			if(p != buf)
				bufLine[strlen(bufLine)] = buf[0];

			/********************先保存Buf缓存内容*******************/			
			if( strlen(bufLine) + strlen(buf) < MAX_LINE_SIZE )	//如果缓存未满
			{				
				char ch = 0; 
				for(int nIndex = 0; (unsigned)nIndex < strlen(buf); ++nIndex)
				{
					if((ch = buf[nIndex]) != '\n')						
							;//bufLine[strlen(bufLine)] = ch;	//则连到行内容字符串中
					else
					{						
						fprintf(lpfile, "%s\n", bufLine);
						memset(bufLine, 0x0, sizeof(bufLine));						
						break;			//至此一行内容解析完毕[不包含注释部分]				
					}					
				}
			}			
			
			char ch = 0;		
			if(p == buf)				//如果双引号是在开头字符[即第一个字符]
			{				
				if(*(p + 1) == GLOBAL_PASSTR_SPECCHAR)		//如果Buf的内容刚好构成一对双引号,则无须遍历文件寻找其配对的双引号
					continue;
			}
			/*********************读该字符串到结尾********************/
			char chprev = 0;		//保存前一个字符[考虑字符串中有转义字符]
			while(!feof(file))
			{				
				fread(&ch, sizeof(char), 1, file);
				
				//bufLine[strlen(bufLine)] = ch;	
				if(chprev != '\\' && ch == GLOBAL_VCSTR_SPECCHAR)	break;		//配对成功则结束该字符串				
				chprev = ch;
			}
			fprintf(lpfile, "%s", bufLine);
			memset(bufLine, 0x0, sizeof(bufLine));
			continue;
		}
		
		/*****************************如果读到'//'注释符号时***************************/
		if(strchr(buf, '/'))			//!!!注意'//'和'/*'的相似之处!!!
		{
			if(strcmp(buf, "//") == 0)	//!!!如果单行注释符号一次性读入Buf!!!
			{
				char ch = 0;
				while(!feof(file))		//读到行结尾
				{	
					fread(&ch, sizeof(char), 1, file);	 
					if(ch == '\n') 				
					{
						//至此一行内容解析完毕
						fprintf(lpfile, "%s\n", bufLine);
						memset(bufLine, 0x0, sizeof(bufLine));
						break;	
					}
				}
			}		
			else							//!!![注意当'//'分两次才读完时的情况]!!!
			{
				char ch = 0;
				if(!feof(file))
				{
					fread(&ch, sizeof(char), 1, file);
					
					if(ch == '/' && !feof(file))
					{
						bufLine[strlen(bufLine)] = buf[0];
						while(!feof(file))		//读到行结尾
						{	
							fread(&ch, sizeof(char), 1, file);	 
							if(ch == '\n') 				
							{
								//至此一行内容解析完毕
								fprintf(lpfile, "%s\n", bufLine);
								memset(bufLine, 0x0, sizeof(bufLine));
								break;	
							}
						}
					}
					//如果ch字符为'*'则和前面一个ch字符构成多行注释标志
					else if(strcmp(buf, "/*") == 0 || (buf[1] == '/' && ch == '*'))
					{
						//解析多个多行注释嵌套时的情况
						char stack[3], chprev = 0;
						memset(stack, 0x0, sizeof(stack));

						while(!feof(file))
						{
							fread(&ch, sizeof(char), 1, file);							
							
							if(ch == '/')
							{
								//先判断前一个字符
								if(chprev == '*')
								{
									if(strcmp(stack, "/*") == 0)
										memset(stack, 0x0, sizeof(stack));
									else
										break;
								}
								else
								{
									//再判断下一个字符
									fread(&ch, sizeof(char), 1, file);
									if(ch == '*')
									{
										stack[0] = '/';
										stack[1] = '*';
									}
								}
							}
							chprev = ch;
						}
					}
					else
					{
						/********************先保存Buf缓存内容*******************/
						if( strlen(bufLine) + strlen(buf) < MAX_LINE_SIZE )	//如果缓存未满
						{
							char ch = 0; 
							for(int nIndex = 0; (unsigned)nIndex < strlen(buf); ++nIndex)
							{
								if((ch = buf[nIndex]) != '\n')
									bufLine[strlen(bufLine)] = ch;	//则连到行内容字符串中
								else
								{						
									fprintf(lpfile, "%s\n", bufLine);
									memset(bufLine, 0x0, sizeof(bufLine));

									//[如果ch为下一行字符则应提前保存到缓存]
									bufLine[strlen(bufLine)] = ch; 
									break;			//至此一行内容解析完毕[不包含注释部分]				
								}
							}
						}
						
						bufLine[strlen(bufLine)] = ch;
						if(ch == '\n')
						{
							fprintf(lpfile, "%s", bufLine);
							memset(bufLine, 0x0, sizeof(bufLine));
							//至此一行内容解析完毕
						}
					}
				}
			}
		}
		else		//普通字符
		{
			if( strlen(bufLine) + strlen(buf) < MAX_LINE_SIZE )	//如果缓存未满
			{
				char ch = 0;
				for(int nIndex = 0; (unsigned)nIndex < strlen(buf); ++nIndex)
				{
					if((ch = buf[nIndex]) != '\n')
						bufLine[strlen(bufLine)] = ch;	//则连到行内容字符串中
					else
					{						
						fprintf(lpfile, "%s\n", bufLine);
						memset(bufLine, 0x0, sizeof(bufLine));
						break;			//至此一行内容解析完毕[不包含注释部分]				
					}
				}
			}
			else
			{
				fprintf(lpfile, "%s\n", bufLine);
				memset(bufLine, 0x0, sizeof(bufLine));
				strcat(bufLine, buf);
				break;			//至此一行内容解析完毕[不包含注释部分]				
			}
		}	
	}
	fclose(file);
	fclose(lpfile);
	return TRUE;
}

//解析文件内部类结构,并修改m_cilClassNames列表内容
BOOL CParseVCFile::ParseVCClass(char strVCFilename[MAX_PATH])
{
	if(RemoveVCFileNoteInfo(strVCFilename))
	{
		//开始解析没有注释的源文件内容
		CFileEx file;
		if( file.Open((LPCTSTR)m_strNoNotesFilename, CFile::modeRead) )
		{
			//查找类标志符class
			while(!file.IsEof())
			{
				CString strLine = "", strOldLine = "";
				strLine = file.ReadALine();
				strLine.Replace('\n', ' ');		//非常必要
				strLine.TrimLeft();	strLine.TrimRight();
				
				if(strLine != "")
				{
					strOldLine = strLine;
					
					int i = strLine.Find("class"); 
					if(i != -1)
					{
						TCHAR chp = 0;
						if(i == 0)	//如果在开头位置						
							chp = ' ';
						else
							chp = strLine.GetAt(i-1);
						
						TCHAR chn = 0;
						i = i+strlen("class");
						if( i >= strLine.GetLength() )
							chn = ' ';
						else
							chn = strLine.GetAt(i);
						
						//如果符合了类定义标志符所在位置关系
						if( chp == ' ' && chn == ' ' )
						{
							LPCLASSANDFILEREL lpitem;

							lpitem = (LPCLASSANDFILEREL)malloc(sizeof(CLASSANDFILEREL));
							memset(lpitem, 0x0, sizeof(lpitem));
							lpitem->nFuncCounts = 0;
							lstrcpy(lpitem->strFileName, strVCFilename);
							
							//标志该类是否有类实体
							BOOL bHaveClassBody = TRUE;	
							/**************************分解类名**************************/
							CString strClassDefine = strOldLine;	//类名定义行
							
							int nIndex = strLine.Find('{');

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -