void CPPAbstractHolder::Copy(CPPAbstractHolder* pcCast, CMemoryStackExtended* pcStack)
{
	int			i;
	CPPToken*	pcToken;

	Init(pcCast->miLine, pcCast->miColumn);

	for (i = 0; i < pcCast->mcTokens.mcArray.NumElements(); i++)
	{
		pcToken = DuplicatePPToken(*pcCast->mcTokens.mcArray.Get(i), pcStack);
		mcTokens.Add(&pcToken);
	}
}
//////////////////////////////////////////////////////////////////////////
//																		//
//																		//
//////////////////////////////////////////////////////////////////////////
BOOL CPreprocessor::ExpandTokenIfNecessary(CPPToken* pcToken, CPPTokenHolder* pcDest, CPreprocessorTokenParser* pcParser, BOOL bAllowDefined, int iDepth)
{		
	CPPToken*				pcNewToken;
	CPPText*				pcText;
	BOOL					bResult;
	CPPReplacement*			pcReplacement;

	if (pcToken->IsText())
	{
		pcText = (CPPText*)pcToken;
		if (pcText->meType == PPT_Identifier)
		{
			bResult = ProcessIdentifier(pcDest, pcText, pcParser, bAllowDefined, iDepth);
			return bResult;
		}
		else
		{
			pcNewToken = DuplicatePPToken(pcToken, mpcStack);
			pcDest->Add(&pcNewToken);
			pcParser->NextToken();
			return TRUE;
		}
	}
	else if (pcToken->IsReplacement())
	{
		pcReplacement = (CPPReplacement*)pcToken;
		ExpandReplacement(pcReplacement, pcDest, bAllowDefined, iDepth);
		pcParser->NextToken();
		return TRUE;
	}
	else
	{
		pcNewToken = DuplicatePPToken(pcToken, mpcStack);
		pcDest->Add(&pcNewToken);
		pcParser->NextToken();
		return TRUE;
	}
};
void CCBlock::Copy(CPPToken* pcSource, CMemoryStackExtended* pcStack)
{
	CCBlock*	pcCast;
	CPPToken*	pcToken;
	int			i;

	if (pcSource->IsBlock())
	{
		pcCast = (CCBlock*)pcSource;
		Init(pcCast->miLine, pcCast->miColumn);

		for (i = 0; i < pcCast->mcTokens.mcArray.NumElements(); i++)
		{
			pcToken = DuplicatePPToken(*pcCast->mcTokens.mcArray.Get(i), pcStack);
			mcTokens.Add(&pcToken);
		}

		mpcBlockSet = pcCast->mpcBlockSet;
		mpcStack = pcCast->mpcStack;
	}
}
//////////////////////////////////////////////////////////////////////////
//																		//
//																		//
//////////////////////////////////////////////////////////////////////////
BOOL CPreprocessor::ProcessHashDefine(CPreprocessorTokenParser* pcParser)
{
	CExternalString		cIdentifier;
	CExternalString		cArgument;
	BOOL				bResult;
	CDefine*			pcDefine;
	CPPText*			pcText;
	CPPReplacement*		pcReplacement;
	int					iReplaceArg;
	CPPToken*			pcToken;
	BOOL				bAllocated;
	BOOL				bAllowWhiteSpace;
	CDefine*			pcExisting;
	CDefine*			pcNew;
	CChars				sz;

	bResult = pcParser->GetIdentifier(&cIdentifier);
	if (bResult)
	{
		pcDefine = AddDefine(&cIdentifier);
		if (pcDefine)
		{
			pcExisting = NULL;
		}
		else
		{
			pcExisting = GetDefine(&cIdentifier);
			pcDefine = (CDefine*)malloc(sizeof(CDefine));
			pcDefine->Init(mcDefines.mcDefinesTree.GetIndexForNew(cIdentifier.msz, cIdentifier.miLen), mcDefines.muiID, NULL);
		}

		bResult = pcParser->GetExactDecorator('(', FALSE);
		if (bResult)
		{
			pcDefine->SetBracketed(TRUE);
			for (;;)
			{
				bResult = pcParser->GetExactDecorator(')');
				if (bResult)
				{
					break;
				}
				bResult = pcParser->GetIdentifier(&cArgument);
				if (bResult)
				{
					pcDefine->AddArgument(&cArgument);
					pcParser->GetExactDecorator(',');
				}
				else
				{
					//Expected an Identifier.
				}
			}
		}

		bAllowWhiteSpace = FALSE;
		while (pcParser->HasToken())
		{
			bAllocated = FALSE;
			pcToken = pcParser->GetToken();
			if (pcToken->IsText())
			{
				pcText = (CPPText*)pcToken;
				if (pcText->meType == PPT_Identifier)
				{
					iReplaceArg = pcDefine->mcArguments.GetIndex(pcText->mcText.msz, pcText->mcText.miLen);
					if (iReplaceArg != -1)
					{
						pcReplacement = CPPReplacement::Construct(mpcStack->Add(sizeof(CPPReplacement)));
						pcReplacement->Init(pcDefine->miIndex, iReplaceArg, -1, -1);
						pcToken = pcReplacement;
						bAllocated = TRUE;
					}
				}
			}

			if (!pcToken->IsWhiteSpace() || bAllowWhiteSpace)  //Stop leading whitespace from being added.
			{
				bAllowWhiteSpace = TRUE;
				if (!bAllocated)
				{
					pcToken = DuplicatePPToken(pcToken, mpcStack);
				}
				pcDefine->AddReplacmentToken(pcToken);
			}

			pcParser->NextToken();
		}

		bResult = TRUE;
		if (pcExisting)
		{
			if (!pcExisting->Equals(pcDefine))
			{
				//Removing a define will not change the index or the ID of our new define.  Phew.
				RemoveDefine(&cIdentifier);
				pcNew = AddDefine(&cIdentifier, pcDefine);
				if (!pcNew)
				{
					sz.Init("Could not redefine #define ");
					sz.AppendSubString(cIdentifier.msz, cIdentifier.EndInclusive()+1);
					sz.Append(".  Probably index or ID is different.");
					gcUserError.Set(sz.Text());
					sz.Kill();
					bResult = FALSE;
				}
			}
			else
			{
				//Only kill the define if the existing one is identical.
				//pcNew depends on the allocations in the non-identical define case.
				pcDefine->Kill();
			}
			free(pcDefine);
		}
	}
	else
	{
		gcUserError.Set("Could not get an identifier for a #define.  Add one.");
	}
	return bResult;
}
//////////////////////////////////////////////////////////////////////////
//																		//
//																		//
//////////////////////////////////////////////////////////////////////////
void CPreprocessor::AddTokenToArgument(CPPTokenHolder* pcArgument, CPPToken* pcToken)
{
	pcToken = DuplicatePPToken(pcToken, mpcStack);
	pcArgument->Add(&pcToken);
}
//////////////////////////////////////////////////////////////////////////
//																		//
//																		//
//////////////////////////////////////////////////////////////////////////
BOOL CPreprocessor::ProcessIdentifier(CPPTokenHolder* pcDest, CPPText* pcText, CPreprocessorTokenParser* pcParser, BOOL bAllowDefined, int iDepth)
{
	CPPToken*				pcToken;
	CDefine*				pcDefine;
	BOOL					bResult;
	CPPAbstractHolder*				pcHolder;
	CPPText*				pcDecorator;
	char*					pcValue;
	int						i;
	CPPTokenHolder*			pcTokenHolder;
	SDefineArgument*		psArguments;
	int						iArgIndex;

	pcDefine = mcDefines.GetDefine(&pcText->mcText);
	if (pcDefine)
	{
		iArgIndex = -1;
		if (pcDefine->IsBacketed())
		{
			pcParser->NextToken();
			psArguments = mcArguments.Add(pcDefine->miIndex);
			iArgIndex = mcArguments.mcDefineToArguments.GetIndex(psArguments);
			bResult = FindArguments(pcParser, &psArguments->mcArguments);
			if ((!bResult) || (psArguments->mcArguments.NumElements() != pcDefine->mcArguments.NumElements()))
			{
				//Expected arguments but there weren't any.
				for (i = 0; i < psArguments->mcArguments.NumElements(); i++)
				{
					pcTokenHolder = psArguments->mcArguments.Get(i);
					pcTokenHolder->Kill();
				}
				mcArguments.Remove(pcDefine->miIndex);
				return FALSE;
			}
		}
		else
		{
			pcParser->NextToken();
		}

		if (pcDefine->mcReplacement.mcTokens.mcArray.NumElements() > 0)
		{
			pcHolder = ADD_TOKEN(CPPHolder, &pcDest->mcArray, mpcStack->Add(sizeof(CPPHolder)));
			pcHolder->Init(4, -1, -1);
			ExpandDefined(pcHolder, pcDefine, bAllowDefined, iDepth+1);
		}

		//I'm not sure if it's safe to do this anymore... another define might refer to it.
		if (iArgIndex != -1)
		{
			psArguments = mcArguments.Get(pcDefine->miIndex);
			for (i = 0; i < psArguments->mcArguments.NumElements(); i++)
			{
				pcTokenHolder = psArguments->mcArguments.Get(i);
				pcTokenHolder->Kill();
			}
			mcArguments.Remove(pcDefine->miIndex);
		}
		return TRUE;
	}
	else if (bAllowDefined)
	{
		bResult = pcParser->GetExactIdentifier("defined", TRUE, TRUE);
		if (bResult)
		{
			pcParser->GetExactDecorator('(');
			pcParser->SkipWhiteSpace();
			pcToken = pcParser->GetToken();
			pcDecorator = CPPText::Construct(mpcStack->Add(sizeof(CPPText)));
			pcValue = (char*)gcTokenStrings.Add(1);
			*pcValue = '0';
			pcDecorator->Init(PPT_Number, -1, -1, pcValue, pcValue+1);
			if (pcToken)
			{
				if (pcToken->IsText())
				{
					pcText = (CPPText*)pcToken;
					if (pcText->meType == PPT_Identifier)
					{
						pcDefine = mcDefines.GetDefine(&pcText->mcText);
						pcParser->NextToken();
						if (pcDefine)
						{
							*pcValue = '1';
						}
					}
				}
				pcDest->Add((CPPToken**)&pcDecorator);
				pcParser->SkipWhiteSpace();
				pcParser->GetExactDecorator(')');
			}
			return TRUE;
		}
	}

	pcToken = DuplicatePPToken(pcText, mpcStack);
	pcDest->Add(&pcToken);
	pcParser->NextToken();
	return TRUE;
}