📄 notationfile.cpp
字号:
//===========================================================================//
// 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 + -