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

📄 notationfile.cpp

📁 机甲指挥官2源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//===========================================================================//
// Copyright (C) Microsoft Corporation. All rights reserved.                 //
//===========================================================================//

#include "StuffHeaders.hpp"

#define MAX_LINE_SIZE 512

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Macro::Macro(MString *macro, MString *replace):
	Plug(DefaultData)
{
	m_macro = *macro;
	m_replacement = *replace;
	m_inUse = false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Macro::AddValue(
		MacroTree *macro_tree,
		const char* name,
		const char* value
	)
{
	Check_Object(macro_tree);
	Check_Pointer(name);
	Check_Pointer(value);

	//
	//----------------------------------------------------
	// Create MStrings for all this, and create a new plug
	//----------------------------------------------------
	//
	MString ms_define(name);
	MString ms_replace(value);
	Macro *mr_new = new Macro(&ms_define, &ms_replace);
	Check_Object(mr_new);

	//
	//---------------------------------------------------------
	// See if a previous definition is there.  If so, remove it
	//---------------------------------------------------------
	//
	Macro *mr_exists = NULL;
	mr_exists = macro_tree->Find(ms_define);
	if (mr_exists)
	{
		Check_Object(mr_exists);
		macro_tree->Remove(mr_exists);
	}
	macro_tree->AddValue(mr_new, ms_define);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Macro::ReplaceMacros(
		MacroTree *macro_tree,
		const char *buffer,
		char *new_buf,
		int new_buf_size
	)
{
	//
	//----------------------------------------------------
	// Copy the characters one by one until we find the $(
	//----------------------------------------------------
	//
	while (1)
	{
		while (*buffer && (*buffer != '$' || buffer[1] != '('))
		{
			*new_buf++ = *buffer++;
			--new_buf_size;
			Verify(new_buf_size > 0);
		}

		//
		//--------------------------------------
		// If we are out of buffer, search again
		//--------------------------------------
		//
		if (!*buffer)
		{
			Verify(new_buf_size > 0);
			*new_buf = 0;
			return;
		}

		//
		//-------------------------------
		// Find the end of the macro name
		//-------------------------------
		//
		const char *p = strchr(buffer, ')');
		if (!p)
		{
			Verify(new_buf_size > 0);
			*new_buf = '\0';
			return;
		}

		//
		//-------------------
		// Isolate macro name
		//-------------------
		//
		int len = p-buffer - 2;
		MString macro_name;
		macro_name.AllocateLength(len+1);
		char *t = macro_name;
		size_t i=0;
		for (p = buffer+2; *p != ')'; ++p,++i)
		{
			Verify(i<len);
			t[i] = *p;
		}
		t[len] = '\0';

		//
		//--------------------------------------------------------------------
		// Find it in the tree, and if it exists, copy it into the buffer.  If
		// not, leave the buffer alone
		//--------------------------------------------------------------------
		//
		buffer = p+1;
		Macro *macro = macro_tree->Find(macro_name);
		if (macro && !macro->m_inUse)
		{
			macro->m_inUse = true;
			ReplaceMacros(
				macro_tree,
				macro->m_replacement,
				new_buf,
				new_buf_size
			);
			len = strlen(new_buf);
			new_buf_size -= len;
			new_buf += len;
			macro->m_inUse = false;
		}
	}
}

//#############################################################################
//##############    NotationFile    ###########################################
//#############################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NotationFile::NotationFile(
	const char *file_name,
	Type type
):
	m_pages(NULL)
{
	Check_Pointer(this);
	Check_Pointer(file_name);

	//
	//-----------------------------------------
	// See if we need to read stuff from a file
	//-----------------------------------------
	//
	FileStream file_stream;
	if (gos_DoesFileExist(file_name))
	{
		file_stream.Open(file_name);
		m_fileName = file_stream.GetFileName();
		m_fileDependencies.AddDependency(&file_stream);
	}
	else
		m_fileName = file_name;

	//
	//---------------------------------------------------------------
	// Set up the file dependencies, and finish constructing the file
	//---------------------------------------------------------------
	//
	m_type = type;
	CommonConstruction(&file_stream, NULL);

	//
	//-----------------------------------------------------------
	// Make sure that we don't allow a non-empty file to be empty
	//-----------------------------------------------------------
	//
	if (m_type==NonEmpty && IsEmpty())
		STOP(("%s cannot be empty!", file_name));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NotationFile::NotationFile(
	MemoryStream *memory_stream,
	MacroTree *macro_tree
):
	m_pages(NULL)
{
	Check_Pointer(this);

	//
	//--------------------------------------------------------------------
	// If we were given a stream and it was a file, get the dependency and
	// filename info from it
	//--------------------------------------------------------------------
	//
	if (memory_stream)
	{
		Check_Object(memory_stream);
		if (memory_stream->IsDerivedFrom(FileStream::DefaultData))
		{
			FileStream* file_stream = Cast_Object(FileStream*, memory_stream);
			m_fileDependencies.AddDependency(file_stream);
			m_fileName = file_stream->GetFileName();
		}
	}

	//
	//-------------------
	// Finish building it
	//-------------------
	//
	CommonConstruction(memory_stream, macro_tree);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NotationFile::~NotationFile()
{
	Check_Object(this);

	//
	//------------------------
	// Clear out the notepages
	//------------------------
	//
	Verify(!IsChanged());
	PageIterator pages(&m_pages);
	pages.DeletePlugs();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	NotationFile::TestInstance() const
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	NotationFile::CommonConstruction(
		MemoryStream *memory_stream,
		MacroTree *macro_tree
	)
{
	Check_Pointer(this);

	//
	//-------------------
	// Read the stream in
	//-------------------
	//
	if (memory_stream)
	{
		Check_Object(memory_stream);
		Read(memory_stream, macro_tree, NULL, false);
	}
	m_dirtyFlag = false;
	Check_Object(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	NotationFile::Read(
		MemoryStream *stream,
		MacroTree *macro_tree,
		Page **page,
		bool nested
	)
{
	Check_Object(this);
	Check_Pointer(stream);

	//
	//------------------------------------------------------------------
	// If aren't already reading a page, make a pointer to hold the info
	//------------------------------------------------------------------
	//
	Page *temp_page = NULL;
	if (!page)
		page = &temp_page;

	//
	//------------------------------------------------
	// If we don't have a macro tree yet, make one now
	//------------------------------------------------
	//
	MacroTree *orig_tree = macro_tree;
	if (!macro_tree)
	{
		macro_tree = new MacroTree(NULL, true);
		Check_Object(macro_tree);
	}

	//
	//--------------------------------
	// Read each line till we are done
	//--------------------------------
	//
	bool comment_mode = false;
	char buffer[MAX_LINE_SIZE];
	while (stream->ReadLine(buffer, sizeof(buffer)))
	{		
		char *p = buffer;

		//
		//----------------------------------------------------------------
		// Deal with any comments - C++ style are the easiest to deal with
		//----------------------------------------------------------------
		//
		char *comment_start = NULL;
		while ((p = strchr(p, '/')) != NULL)
		{
			if (p[1] == '/')
				break;

			//
			//--------------------------------------------------------------
			// If we are ending a C style comment, move the memory to where
			// the comment started on this line.  If it didn't start on this
			// line, move it to the beginning of the buffer
			//--------------------------------------------------------------
			//
			else if (p[-1] == '*')
			{
				if (!comment_mode)
				{
					strcpy(p-1, p+1);
					--p;
				}
				else if (!comment_start)
				{
					strcpy(buffer, p+1);
					p = buffer;
				}
				else
				{
					strcpy(comment_start, p+1);
					p = comment_start;
				}
				comment_start = NULL;
				comment_mode = false;
				continue;
			}

			//
			//------------------------------------------------------------
			// If we are starting a C style comment, remember where we are
			//------------------------------------------------------------
			//
			else if (p[1] == '*')
			{
				comment_mode = true;
				comment_start = p;
			}
			++p;
		}

		//
		//--------------------------------------------------------------------
		// If we started a comment on this line, clip the line there.  If not,
		// and we are within a C comment block, skip the whole line
		//--------------------------------------------------------------------
		//
		if (comment_start)
			p = comment_start;
		else if (comment_mode)
			continue;

		//
		//---------------------
		// Clip off the comment
		//---------------------
		//
		if (p)
			*p = '\0';

		//
		//-----------------------
		// Trim ending whitespace
		//-----------------------
		//
		p = buffer + strlen(buffer) - 1;
		while (p >= buffer && *p==' ' || *p=='\t')
			*p-- = '\0';
		p = buffer;
		#if defined(_ARMOR)
			bool macroed=false;
		#endif

		//
		//--------------------------
		// Ignore leading whitespace
		//--------------------------
		//
Parse:
		while (*p==' ' || *p=='\t')
			++p;
		if(!*p)
			continue;

		//
		//--------------------------------------------------------------------
		// If the line consists of a nested block end, handle it appropriately
		//--------------------------------------------------------------------
		//
		if (!_stricmp(p, "}"))
		{
			if (nested)
			{
				m_dirtyFlag = false;
				return;
			}
			else
				continue;
		}

		//
		//---------------------------------------------------------------
		// If we aren't in raw mode, look for our preprocessor directives
		//---------------------------------------------------------------
		//
		if (m_type != Raw)
		{
			char *q;
			if (*p == '!')
				HandleBangStuff(p+1, macro_tree, page);

			//
			//-------------------------------------------
			// Look to see if we need to deal with macros
			//-------------------------------------------
			//
			else if((q = strchr(p, '$')) != NULL && q[1]=='(')
			{
				#if defined(_ARMOR)

⌨️ 快捷键说明

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