CCBlock* CCBlockSet::CreateBlock(void)
{
	CCBlock*	pcBlock;

	pcBlock = CCBlock::Construct(mpcStack->Add(sizeof(CCBlock)));
	pcBlock->Init(this, miLine, miColumn);
	return pcBlock;
}
void CCBlockSet::Kill(void)
{
	int			i;
	CCBlock*	pcBlock;

	for (i = 0; i < mapcBlocks.NumElements(); i++)
	{
		pcBlock = *mapcBlocks.Get(i);
		pcBlock->Kill();
	}

	mapcBlocks.Kill();
	mcRawTokens.Kill();
	mpcStack = NULL;
	mpcFile = NULL;
}
CPPToken* DuplicatePPToken(CPPToken* pcSource, CMemoryStackExtended* pcStack)
{
	CPPDirective*			pcDirective;
	CPPLine*				pcLine;
	CPPWhiteSpace*			pcWhiteSpace;
	CPPReplacement*			pcReplacement;
	CPPText*				pcText;
	CPPTextWithSource*		pcTextWithSource;
	CPPHolder*				pcHolder;
	CPPHashes*				pcHashes;
	CCBlock*				pcBlock;

	if (pcSource->IsDirective())
	{
		pcDirective = CPPDirective::Construct(pcStack->Add(sizeof(CPPDirective)));
		pcDirective->Copy((CPPDirective*)pcSource, pcStack);
		return pcDirective;
	}
	else if (pcSource->IsWhiteSpace())
	{
		pcWhiteSpace = CPPWhiteSpace::Construct(pcStack->Add(sizeof(CPPWhiteSpace)));
		pcWhiteSpace->Copy((CPPWhiteSpace*)pcSource, pcStack);
		return pcWhiteSpace;
	}
	else if (pcSource->IsReplacement())
	{
		pcReplacement = CPPReplacement::Construct(pcStack->Add(sizeof(CPPReplacement)));
		pcReplacement->Copy((CPPReplacement*)pcSource, pcStack);
		return pcReplacement;
	}
	else if (pcSource->IsText())
	{
		if (((CPPText*)pcSource)->HasSource())
		{
			pcTextWithSource = CPPTextWithSource::Construct(pcStack->Add(sizeof(CPPTextWithSource)));
			pcTextWithSource->Copy((CPPTextWithSource*)pcSource, pcStack);
			return pcTextWithSource;
		}
		else
		{
			pcText = CPPText::Construct(pcStack->Add(sizeof(CPPText)));
			pcText->Copy((CPPText*)pcSource, pcStack);
			return pcText;
		}
	}
	else if (pcSource->IsHash())
	{
		pcHashes = CPPHashes::Construct(pcStack->Add(sizeof(CPPHashes)));
		pcHashes->Copy((CPPHashes*)pcSource, pcStack);
		return pcHashes;
	}
	else if (pcSource->IsLine())
	{
		pcLine = CPPLine::Construct(pcStack->Add(sizeof(CPPLine)));
		pcLine->Copy((CPPLine*)pcSource, pcStack);
		return pcLine;
	}
	else if (pcSource->IsBlock())
	{
		pcBlock = CCBlock::Construct(pcStack->Add(sizeof(CCBlock)));
		pcBlock->Copy((CCBlock*)pcSource, pcStack);
		return pcBlock;
	}	
	else if (pcSource->IsHolder())
	{
		pcHolder = CPPHolder::Construct(pcStack->Add(sizeof(CPPHolder)));
		pcHolder->Copy((CPPHolder*)pcSource, pcStack);
		return pcHolder;
	}
	else
	{
		gcUserError.Set("Cannot Duplicate Token");
		exit(1);
	}
	return NULL;
}
//////////////////////////////////////////////////////////////////////////
//																		//
//																		//
//////////////////////////////////////////////////////////////////////////
BOOL CPreprocessor::PreprocessBlockSets(CCFile* pcFile, CCFile* pcFromFile)
{
	CCBlockSet*			pcBlocksSet;
	SCTokenBlock		sResult;
	BOOL				bResult;

	miIncludeDepth++;
	LogIncludes(pcFile);
	mpcCurrentFile = pcFile;

	LoadFile(pcFile);

	bResult = TRUE;
	if (!mpcCurrentFile->IsPragmaOnced())
	{
		sResult.Init(0, 0);
		for (;;)
		{
			LogBlocks(pcFile, sResult);
			
			pcBlocksSet = pcFile->macBlockSets.SafeGet(sResult.iBlockIndex);
			if (!pcBlocksSet)
			{
				break;
			}

			if (pcBlocksSet->IsDirective())
			{
				//The conditional directives need to be expanded so &pcFile->mcStack is needed.  I suspect a #define directive will be expanded too.  I don't know if this is good or bad.  It's bad.  Write a test for it.
				sResult = PreprocessTokens(NULL, &pcFile->mcStack, &pcBlocksSet->mcRawTokens, sResult.iBlockIndex, sResult.iTokenIndex);
				if (sResult.iTokenIndex == -1)	
				{
					bResult = FALSE; 
					break;	
				}
			}
			else
			{
				CStackMarkExtended	cMark;
				CCBlock*			pcBlockProcessed;
				CCBlock*			pcBlockMatching;

				pcFile->mcStack.Mark(&cMark);

				pcBlockProcessed = pcBlocksSet->CreateBlock();
				sResult = PreprocessTokens(&pcBlockProcessed->mcTokens, &pcFile->mcStack, &pcBlocksSet->mcRawTokens, sResult.iBlockIndex, sResult.iTokenIndex);

				pcBlockMatching = pcBlocksSet->GetMatchingBlock(pcBlockProcessed);
				if (!pcBlockMatching)
				{	
					pcBlocksSet->AddBlock(pcBlockProcessed);
					pcBlockProcessed->SetNext(sResult.iTokenIndex, sResult.iBlockIndex);
					pcBlockMatching = pcBlockProcessed;
				}
				else
				{
					pcBlockProcessed->Kill();
					pcFile->mcStack.Rollback(&cMark);
					miBlockReuse++;
					sResult = pcBlockMatching->msNext;
				}
				cMark.Kill();

				if (sResult.iTokenIndex == -1)	
				{	
					bResult = FALSE;
					break;	
				}

				mpcUnit->mcTokens.mcTokens.mcArray.Add((CPPToken**)&pcBlockMatching);
			}

			pcBlocksSet = pcFile->macBlockSets.SafeGet(sResult.iBlockIndex);
			if (pcBlocksSet)
			{
				if (pcBlocksSet->mcRawTokens.mcArray.NumElements() == sResult.iTokenIndex)
				{
					sResult.iBlockIndex++;
					sResult.iTokenIndex = 0;
				}
			}
		}
	}

	mpcCurrentFile = pcFromFile;
	miIncludeDepth--;
	return bResult;
}