windows-nt/Source/XPSP1/NT/sdktools/m4/obj.c
2020-09-26 16:20:57 +08:00

276 lines
6.6 KiB
C

/*****************************************************************************
*
* obj.c
*
* Mid-level memory management -- objects.
*
*****************************************************************************/
#include "m4.h"
/*****************************************************************************
*
* FreePtok
*
* Free the memory associated with a token.
*
*****************************************************************************/
INLINE void
FreePtok(PTOK ptok)
{
AssertSPtok(ptok);
Assert(fHeapPtok(ptok));
FreePv(ptchPtok(ptok));
D(ptok->sig = 0);
D(ptok->tsfl = 0);
}
/*****************************************************************************
*
* PopdefPmac
*
* Pop the topmost value node (definition) off a macro.
*
*****************************************************************************/
void STDCALL
PopdefPmac(PMAC pmac)
{
PVAL pval;
AssertPmac(pmac);
AssertPval(pmac->pval);
pval = pmac->pval->pvalPrev;
FreePtok(&pmac->pval->tok);
FreePv(pmac->pval);
pmac->pval = pval;
}
/*****************************************************************************
*
* ptchDupPtok
*
* Copy a token into the heap as a C-style string, returning a pointer
* to the copy.
*
*****************************************************************************/
PTCH STDCALL
ptchDupPtok(PCTOK ptok)
{
PTCH ptch;
AssertSPtok(ptok);
ptch = ptchAllocCtch(ctchSPtok(ptok) + 1);
if (ptch) {
CopyPtchPtchCtch(ptch, ptchPtok(ptok), ctchSPtok(ptok));
ptch[ctchSPtok(ptok)] = '\0';
}
return ptch;
}
/*****************************************************************************
*
* ptchDupPtch
*
* Duplicate a null-terminated string onto the heap. This doesn't
* happen often, so speed is not an issue.
*
*****************************************************************************/
PTCH STDCALL
ptchDupPtch(PCTCH ptch)
{
TOK tok;
SetStaticPtokPtchCtch(&tok, ptch, strlen(ptch));
return ptchDupPtok(&tok);
}
/*****************************************************************************
*
* DupPtokPtok
*
* Copy a token into the heap, returning the new token location in
* the first argument. (Remember, first argument is always destination;
* second argument is always source.)
*
*****************************************************************************/
void STDCALL
DupPtokPtok(PTOK ptokDst, PCTOK ptokSrc)
{
Assert(ptokDst != ptokSrc);
AssertSPtok(ptokSrc);
D(ptokDst->sig = sigSPtok);
ptokDst->u.ptch = ptchAllocCtch(ctchSPtok(ptokSrc));
ptokDst->ctch = ctchSPtok(ptokSrc);
D(ptokDst->tsfl = tsflClosed | tsflHeap);
CopyPtchPtchCtch(ptchPtok(ptokDst), ptchPtok(ptokSrc), ctchSPtok(ptokSrc));
}
/*****************************************************************************
*
* PushdefPmacPtok
*
* Push a new value node (definition) onto a macro.
*
* The ptok is cloned.
*
*****************************************************************************/
void STDCALL
PushdefPmacPtok(PMAC pmac, PCTOK ptok)
{
PVAL pval;
AssertPmac(pmac);
pval = pvAllocCb(sizeof(VAL));
D(pval->sig = sigPval);
pval->fTrace = 0; /* Redefinition resets trace */
DupPtokPtok(&pval->tok, ptok);
pval->pvalPrev = pmac->pval;
pmac->pval = pval;
}
/*****************************************************************************
*
* FreePmac
*
* Free a macro structure and all its dependents. Also removes it from the
* hash table.
*
* Macros are not freed often, so we can afford to be slow.
*
*****************************************************************************/
void STDCALL
FreePmac(PMAC pmac)
{
HASH hash;
PMAC pmacDad;
AssertPmac(pmac);
hash = hashPtok(&pmac->tokName);
pmacDad = pvSubPvCb(&mphashpmac[hash], offsetof(MAC, pmacNext));
AssertPmac(pmacDad->pmacNext);
while (pmacDad->pmacNext != pmac) {
Assert(pmacDad->pmacNext); /* Macro not in hash table */
pmacDad = pmacDad->pmacNext;
AssertPmac(pmacDad->pmacNext);
}
pmacDad->pmacNext = pmac->pmacNext; /* Unlink */
while (pmac->pval) { /* Free any values */
PopdefPmac(pmac);
}
FreePtok(&pmac->tokName);
FreePv(pmac);
}
/*****************************************************************************
*
* pmacFindPtok
*
* Locate a macro node corresponding to the supplied token. If no such
* macro exists, then return 0.
*
*****************************************************************************/
PMAC STDCALL
pmacFindPtok(PCTOK ptok)
{
PMAC pmac;
for (pmac = mphashpmac[hashPtok(ptok)]; pmac; pmac = pmac->pmacNext) {
if (fEqPtokPtok(&pmac->tokName, ptok)) {
break;
}
}
return pmac;
}
/*****************************************************************************
*
* pmacGetPtok
*
* Locate a macro node corresponding to the supplied token. If no such
* macro exists, create one.
*
* This happens only during macro definition, so it can be slow.
*
*****************************************************************************/
PMAC STDCALL
pmacGetPtok(PCTOK ptok)
{
PMAC pmac = pmacFindPtok(ptok);
if (!pmac) {
HASH hash;
pmac = pvAllocCb(sizeof(MAC));
D(pmac->sig = sigPmac);
pmac->pval = 0;
DupPtokPtok(&pmac->tokName, ptok);
hash = hashPtok(ptok);
pmac->pmacNext = mphashpmac[hash];
mphashpmac[hash] = pmac;
}
return pmac;
}
/*****************************************************************************
*
* fEqPtokPtok
*
* Determine whether two tokens are completely identical.
*
* The tokens must be snapped.
*
*****************************************************************************/
F STDCALL
fEqPtokPtok(PCTOK ptok1, PCTOK ptok2)
{
AssertSPtok(ptok1);
AssertSPtok(ptok2);
return (ctchSPtok(ptok1) == ctchSPtok(ptok2)) &&
fEqPtchPtchCtch(ptchPtok(ptok1), ptchPtok(ptok2), ctchSPtok(ptok1));
}
/*****************************************************************************
*
* fIdentPtok
*
* Determine whether the token is a valid identifier.
*
* The token must be snapped.
*
*****************************************************************************/
/* SOMEDAY! not quite right; thinks that `0' is an identifier */
F STDCALL
fIdentPtok(PCTOK ptok)
{
AssertSPtok(ptok);
if (ctchSPtok(ptok)) {
PTCH ptch = ptchPtok(ptok);
do {
if (!fIdentTch(*ptch)) {
return 0;
}
} while (++ptch < ptchMaxPtok(ptok));
return 1;
} else {
return 0;
}
}