windows-nt/Source/XPSP1/NT/sdktools/asn1/asn1cpp/macro.cpp
2020-09-26 16:20:57 +08:00

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;
}
}