545 lines
10 KiB
C++
545 lines
10 KiB
C++
|
/* Copyright (C) Microsoft Corporation, 1998. All rights reserved. */
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#include "macro.h"
|
||
|
|
||
|
|
||
|
CMacro::
|
||
|
CMacro
|
||
|
(
|
||
|
BOOL *pfRetCode,
|
||
|
LPSTR pszMacroName,
|
||
|
UINT cbMaxBodySize
|
||
|
)
|
||
|
:
|
||
|
m_ArgList(8), // default 8 arguments
|
||
|
m_MacroInstList(16), // default 16 instances of this macro
|
||
|
m_cFormalArgs(0),
|
||
|
m_cbBodySize(0),
|
||
|
m_cbMaxBodySize(cbMaxBodySize),
|
||
|
m_pszExpandBuffer(NULL),
|
||
|
m_fArgExistsInBody(FALSE),
|
||
|
m_fImported(FALSE)
|
||
|
{
|
||
|
m_pszMacroName = ::My_strdup(pszMacroName);
|
||
|
|
||
|
m_pszBodyBuffer = new char[m_cbMaxBodySize];
|
||
|
m_pszCurr = m_pszBodyBuffer;
|
||
|
|
||
|
*pfRetCode = (NULL != m_pszMacroName) &&
|
||
|
(NULL != m_pszBodyBuffer);
|
||
|
}
|
||
|
|
||
|
|
||
|
CMacro::
|
||
|
CMacro
|
||
|
(
|
||
|
BOOL *pfRetCode,
|
||
|
CMacro *pMacro
|
||
|
)
|
||
|
:
|
||
|
m_ArgList(pMacro->m_ArgList.GetCount()), // default 8 arguments
|
||
|
m_MacroInstList(16), // default 16 instances of this macro
|
||
|
m_cFormalArgs(pMacro->m_cFormalArgs),
|
||
|
m_cbBodySize(pMacro->m_cbBodySize),
|
||
|
m_cbMaxBodySize(pMacro->m_cbMaxBodySize),
|
||
|
m_pszExpandBuffer(NULL),
|
||
|
m_fArgExistsInBody(pMacro->m_fArgExistsInBody),
|
||
|
m_fImported(TRUE)
|
||
|
{
|
||
|
m_pszMacroName = ::My_strdup(pMacro->m_pszMacroName);
|
||
|
m_pszBodyBuffer = new char[m_cbMaxBodySize];
|
||
|
if (NULL != m_pszMacroName && NULL != m_pszBodyBuffer)
|
||
|
{
|
||
|
// copy the body
|
||
|
::memcpy(m_pszBodyBuffer, pMacro->m_pszBodyBuffer, pMacro->m_cbBodySize);
|
||
|
|
||
|
// adjust the current buffer pointer
|
||
|
m_pszCurr = m_pszBodyBuffer + m_cbBodySize;
|
||
|
|
||
|
// null terminated the body
|
||
|
*m_pszCurr++ = '\0';
|
||
|
|
||
|
// set up the expand buffer
|
||
|
m_pszExpandBuffer = m_pszCurr;
|
||
|
|
||
|
*pfRetCode = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pfRetCode = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
CMacro::
|
||
|
~CMacro ( void )
|
||
|
{
|
||
|
delete m_pszBodyBuffer;
|
||
|
|
||
|
Uninstance();
|
||
|
}
|
||
|
|
||
|
|
||
|
void CMacro::
|
||
|
Uninstance ( void )
|
||
|
{
|
||
|
m_ArgList.DeleteList();
|
||
|
m_MacroInstList.DeleteList();
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CMacro::
|
||
|
SetBodyPart ( LPSTR pszBodyPart )
|
||
|
{
|
||
|
UINT cch = ::strlen(pszBodyPart);
|
||
|
ASSERT(m_pszCurr + cch + 1 < m_pszBodyBuffer + m_cbMaxBodySize);
|
||
|
if (m_pszCurr + cch + 1 < m_pszBodyBuffer + m_cbMaxBodySize)
|
||
|
{
|
||
|
LPSTR psz;
|
||
|
m_ArgList.Reset();
|
||
|
for (UINT i = 0; NULL != (psz = m_ArgList.Iterate()); i++)
|
||
|
{
|
||
|
if (0 == ::strcmp(pszBodyPart, psz))
|
||
|
{
|
||
|
// this is an argument
|
||
|
m_fArgExistsInBody = TRUE;
|
||
|
*m_pszCurr++ = ARG_ESCAPE_CHAR;
|
||
|
*m_pszCurr++ = ARG_INDEX_BASE + i;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// this is not an argument.
|
||
|
::memcpy(m_pszCurr, pszBodyPart, cch);
|
||
|
m_pszCurr += cch;
|
||
|
*m_pszCurr = '\0';
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CMacro::
|
||
|
EndMacro ( void )
|
||
|
{
|
||
|
// save the count of arguments
|
||
|
m_cFormalArgs = m_ArgList.GetCount();
|
||
|
|
||
|
// calculate the size of the body
|
||
|
m_cbBodySize = m_pszCurr - m_pszBodyBuffer;
|
||
|
|
||
|
// null terminated the body
|
||
|
*m_pszCurr++ = '\0';
|
||
|
|
||
|
// set up the expand buffer
|
||
|
m_pszExpandBuffer = m_pszCurr;
|
||
|
|
||
|
// free the memory
|
||
|
DeleteArgList();
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CMacro::
|
||
|
InstantiateMacro ( void )
|
||
|
{
|
||
|
BOOL rc = FALSE; // assume failure
|
||
|
LPSTR pszInstName, pszSrc, pszDst;
|
||
|
UINT i, cch;
|
||
|
CMacroInstance *pInst;
|
||
|
|
||
|
if (! m_fArgExistsInBody)
|
||
|
{
|
||
|
// No need to instantiate because the body does not contain any argument.
|
||
|
// We can take the body as the instance.
|
||
|
rc = TRUE;
|
||
|
goto MyExit;
|
||
|
}
|
||
|
|
||
|
ASSERT(m_ArgList.GetCount() == m_cFormalArgs);
|
||
|
if (m_ArgList.GetCount() != m_cFormalArgs)
|
||
|
{
|
||
|
goto MyExit;
|
||
|
}
|
||
|
|
||
|
pszInstName = CreateInstanceName();
|
||
|
if (NULL == pszInstName)
|
||
|
{
|
||
|
goto MyExit;
|
||
|
}
|
||
|
|
||
|
m_MacroInstList.Reset();
|
||
|
while (NULL != (pInst = m_MacroInstList.Iterate()))
|
||
|
{
|
||
|
if (0 == ::strcmp(pszInstName, pInst->GetName()))
|
||
|
{
|
||
|
// same instance has been instantiated before.
|
||
|
rc = TRUE;
|
||
|
delete pszInstName;
|
||
|
goto MyExit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Let's instantiate a new instance...
|
||
|
|
||
|
pszSrc = m_pszBodyBuffer;
|
||
|
pszDst = m_pszExpandBuffer;
|
||
|
|
||
|
// put in macro name first
|
||
|
::strcpy(pszDst, pszInstName);
|
||
|
pszDst += ::strlen(pszDst);
|
||
|
|
||
|
// put in macro body now.
|
||
|
while (*pszSrc != '\0')
|
||
|
{
|
||
|
if (*pszSrc == ARG_ESCAPE_CHAR)
|
||
|
{
|
||
|
pszSrc++;
|
||
|
i = *pszSrc++ - ARG_INDEX_BASE;
|
||
|
ASSERT(i < m_ArgList.GetCount());
|
||
|
LPSTR pszArgName = m_ArgList.GetNthItem(i);
|
||
|
cch = ::strlen(pszArgName);
|
||
|
::memcpy(pszDst, pszArgName, cch);
|
||
|
pszDst += cch;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pszDst++ = *pszSrc++;
|
||
|
}
|
||
|
}
|
||
|
*pszDst++ = '\n';
|
||
|
*pszDst = '\0';
|
||
|
|
||
|
// create an instance
|
||
|
pInst = new CMacroInstance(&rc,
|
||
|
pszInstName,
|
||
|
pszDst - m_pszExpandBuffer,
|
||
|
m_pszExpandBuffer);
|
||
|
if (NULL != pInst && rc)
|
||
|
{
|
||
|
m_MacroInstList.Append(pInst);
|
||
|
}
|
||
|
|
||
|
MyExit:
|
||
|
|
||
|
// free up temporary argument names
|
||
|
m_ArgList.DeleteList();
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CMacro::
|
||
|
OutputInstances ( COutput *pOutput )
|
||
|
{
|
||
|
BOOL rc = TRUE;
|
||
|
CMacroInstance *pInst;
|
||
|
if (m_fArgExistsInBody)
|
||
|
{
|
||
|
m_MacroInstList.Reset();
|
||
|
while (NULL != (pInst = m_MacroInstList.Iterate()))
|
||
|
{
|
||
|
rc = pOutput->Write(pInst->GetBuffer(), pInst->GetBufSize());
|
||
|
ASSERT(rc);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rc = pOutput->Write(m_pszMacroName, ::strlen(m_pszMacroName));
|
||
|
ASSERT(rc);
|
||
|
rc = pOutput->Writeln(m_pszBodyBuffer, m_cbBodySize);
|
||
|
ASSERT(rc);
|
||
|
}
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
|
||
|
LPSTR CMacro::
|
||
|
CreateInstanceName ( void )
|
||
|
{
|
||
|
UINT cch = ::strlen(m_pszMacroName) + 2;
|
||
|
UINT i;
|
||
|
LPSTR psz, pszArgName;
|
||
|
|
||
|
if (m_fArgExistsInBody)
|
||
|
{
|
||
|
ASSERT(m_ArgList.GetCount() == m_cFormalArgs);
|
||
|
m_ArgList.Reset();
|
||
|
while (NULL != (pszArgName = m_ArgList.Iterate()))
|
||
|
{
|
||
|
cch += ::strlen(pszArgName) + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LPSTR pszInstanceName = new char[cch];
|
||
|
if (NULL != pszInstanceName)
|
||
|
{
|
||
|
psz = pszInstanceName;
|
||
|
::strcpy(psz, m_pszMacroName);
|
||
|
|
||
|
if (m_fArgExistsInBody)
|
||
|
{
|
||
|
psz += ::strlen(psz);
|
||
|
m_ArgList.Reset();
|
||
|
while (NULL != (pszArgName = m_ArgList.Iterate()))
|
||
|
{
|
||
|
*psz++ = '-';
|
||
|
::strcpy(psz, pszArgName);
|
||
|
psz += ::strlen(psz);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pszInstanceName;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
CMacro * CMacroMgrList::
|
||
|
FindMacro
|
||
|
(
|
||
|
LPSTR pszModuleName,
|
||
|
LPSTR pszMacroName
|
||
|
)
|
||
|
{
|
||
|
CMacroMgr *pMacroMgr = FindMacroMgr(pszModuleName);
|
||
|
return (NULL != pMacroMgr) ? pMacroMgr->FindMacro(pszMacroName) : NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
CMacroMgr * CMacroMgrList::
|
||
|
FindMacroMgr ( LPSTR pszModuleName )
|
||
|
{
|
||
|
CMacroMgr *pMacroMgr;
|
||
|
Reset();
|
||
|
while (NULL != (pMacroMgr = Iterate()))
|
||
|
{
|
||
|
if (0 == ::strcmp(pszModuleName, pMacroMgr->GetModuleName()))
|
||
|
{
|
||
|
return pMacroMgr;
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CMacroMgrList::
|
||
|
Uninstance ( void )
|
||
|
{
|
||
|
CMacroMgr *pMacroMgr;
|
||
|
Reset();
|
||
|
while (NULL != (pMacroMgr = Iterate()))
|
||
|
{
|
||
|
pMacroMgr->Uninstance();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
CMacroMgr::
|
||
|
CMacroMgr ( void )
|
||
|
:
|
||
|
m_MacroList(16), // default 16 macros
|
||
|
m_pszModuleName(NULL)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
CMacroMgr::
|
||
|
~CMacroMgr ( void )
|
||
|
{
|
||
|
m_MacroList.DeleteList();
|
||
|
delete m_pszModuleName;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CMacroMgr::
|
||
|
AddModuleName ( LPSTR pszModuleName )
|
||
|
{
|
||
|
// can only be set once
|
||
|
ASSERT(NULL == m_pszModuleName);
|
||
|
|
||
|
m_pszModuleName = ::My_strdup(pszModuleName);
|
||
|
ASSERT(NULL != m_pszModuleName);
|
||
|
|
||
|
return (NULL != m_pszModuleName);
|
||
|
}
|
||
|
|
||
|
|
||
|
CMacro *CMacroMgr::
|
||
|
FindMacro ( LPSTR pszMacroName )
|
||
|
{
|
||
|
CMacro *pMacro;
|
||
|
m_MacroList.Reset();
|
||
|
while (NULL != (pMacro = m_MacroList.Iterate()))
|
||
|
{
|
||
|
if (0 == ::strcmp(pszMacroName, pMacro->GetName()))
|
||
|
{
|
||
|
return pMacro;
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CMacroMgr::
|
||
|
OutputImportedMacros ( COutput *pOutput )
|
||
|
{
|
||
|
BOOL rc = TRUE;
|
||
|
CMacro *pMacro;
|
||
|
|
||
|
rc = pOutput->Write("\n\n", 2);
|
||
|
|
||
|
m_MacroList.Reset();
|
||
|
while (NULL != (pMacro = m_MacroList.Iterate()))
|
||
|
{
|
||
|
if (pMacro->IsImported())
|
||
|
{
|
||
|
rc = pMacro->OutputInstances(pOutput);
|
||
|
if (! rc)
|
||
|
{
|
||
|
ASSERT(0);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CMacroMgr::
|
||
|
Uninstance ( void )
|
||
|
{
|
||
|
CMacro *pMacro;
|
||
|
m_MacroList.Reset();
|
||
|
while (NULL != (pMacro = m_MacroList.Iterate()))
|
||
|
{
|
||
|
pMacro->Uninstance();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
CMacroInstance::
|
||
|
CMacroInstance
|
||
|
(
|
||
|
BOOL *pfRetCode,
|
||
|
LPSTR pszInstanceName,
|
||
|
UINT cbBufSize,
|
||
|
LPSTR pszInstBuf
|
||
|
)
|
||
|
:
|
||
|
m_pszInstanceName(pszInstanceName),
|
||
|
m_cbBufSize(cbBufSize)
|
||
|
{
|
||
|
m_pszInstanceBuffer = new char[m_cbBufSize];
|
||
|
if (NULL != m_pszInstanceBuffer)
|
||
|
{
|
||
|
::memcpy(m_pszInstanceBuffer, pszInstBuf, m_cbBufSize);
|
||
|
}
|
||
|
|
||
|
*pfRetCode = (NULL != m_pszInstanceName) && (NULL != m_pszInstanceBuffer);
|
||
|
}
|
||
|
|
||
|
|
||
|
CMacroInstance::
|
||
|
~CMacroInstance ( void )
|
||
|
{
|
||
|
delete m_pszInstanceName;
|
||
|
delete m_pszInstanceBuffer;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CMacroInstList::
|
||
|
DeleteList ( void )
|
||
|
{
|
||
|
CMacroInstance *pInst;
|
||
|
while (NULL != (pInst = Get()))
|
||
|
{
|
||
|
delete pInst;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CMacroList::
|
||
|
DeleteList ( void )
|
||
|
{
|
||
|
CMacro *pMacro;
|
||
|
while (NULL != (pMacro = Get()))
|
||
|
{
|
||
|
delete pMacro;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CMacroMgrList::
|
||
|
DeleteList ( void )
|
||
|
{
|
||
|
CMacroMgr *pMacroMgr;
|
||
|
while (NULL != (pMacroMgr = Get()))
|
||
|
{
|
||
|
delete pMacroMgr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CNameList::
|
||
|
AddName ( LPSTR pszName )
|
||
|
{
|
||
|
pszName = ::My_strdup(pszName);
|
||
|
if (NULL != pszName)
|
||
|
{
|
||
|
Append(pszName);
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
LPSTR CNameList::
|
||
|
GetNthItem ( UINT nth )
|
||
|
{
|
||
|
LPSTR psz;
|
||
|
if (nth < GetCount())
|
||
|
{
|
||
|
Reset();
|
||
|
do
|
||
|
{
|
||
|
psz = Iterate();
|
||
|
}
|
||
|
while (nth--);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
psz = NULL;
|
||
|
}
|
||
|
return psz;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CNameList::
|
||
|
DeleteList ( void )
|
||
|
{
|
||
|
LPSTR psz;
|
||
|
while (NULL != (psz = Get()))
|
||
|
{
|
||
|
delete psz;
|
||
|
}
|
||
|
}
|
||
|
|