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

155 lines
3.7 KiB
C

/*****************************************************************************
*
* define.c
*
* Builtins related to object definitions.
*
*****************************************************************************/
#include "m4.h"
/*****************************************************************************
*
* opDefineOrPushdef
*
* Common worker for opDefine and opPushdef.
*
* If we are not pushing, then we must pop off the previous value
* in order to free its memory, before pushing the new definition.
*
* QUIRK! GNU m4 emits a warning if $# > 2. AT&T silently ignores
* extra arguments. I side with AT&T on this one.
*
* QUIRK! GNU m4 emits `$0' if $# = 0. AT&T silently ignores
* the entire macro call. I side with GNU on this one.
*
* WARNING! main.c::DefinePtsz assumes that we don't look at
* argv[0] if the correct number of parameters are passed!
*
*****************************************************************************/
void STDCALL
opDefineOrPushdef(ARGV argv, BOOL fPush)
{
if (ctokArgv > 0) {
/*
* Ensure that we don't mess with argv[0].
*/
D(SIG sigOld = argv[0].sig);
D(argv[0].sig = 0);
if (fIdentPtok(ptokArgv(1))) {
PMAC pmac = pmacGetPtok(ptokArgv(1));
if (!fPush) {
if (pmac->pval) {
PopdefPmac(pmac); /* Pop off previous value */
}
}
PushdefPmacPtok(pmac, ptokArgv(2));
#ifdef STRICT_M4
if (ctokArgv > 2) {
Warn("extra arguments ignored");
}
#endif
} else {
Die("invalid macro name");
}
D(argv[0].sig = sigOld);
} else {
PushQuotedPtok(ptokArgv(0));
}
}
/*****************************************************************************
*
* opDefine
*
* Set the expansion of $1 to $2, destroying any previous value.
*
* opPushdef
*
* Same as opDefine, except pushes the previous value.
*
*****************************************************************************/
DeclareOp(opDefine)
{
opDefineOrPushdef(argv, 0);
}
DeclareOp(opPushdef)
{
opDefineOrPushdef(argv, 1);
}
/*****************************************************************************
*
* opPopdef
*
* Restores the most recently pushed definition.
*
* If the macro name is invalid, fail silently.
*
*****************************************************************************/
DeclareOpc(opcPopdef)
{
PMAC pmac = pmacFindPtok(ptok);
if (pmac) {
Assert(pmac->pval);
if (pmac->pval->pvalPrev) {
PopdefPmac(pmac);
} else {
FreePmac(pmac);
}
}
}
DeclareOp(opPopdef)
{
EachOpcArgvDw(opcPopdef, argv, 0);
}
/*****************************************************************************
*
* opUndefine
*
* Removes the definitions of all its arguments.
*
*****************************************************************************/
DeclareOpc(opcUndefine)
{
PMAC pmac = pmacFindPtok(ptok);
if (pmac) {
FreePmac(pmac);
}
}
DeclareOp(opUndefine)
{
EachOpcArgvDw(opcUndefine, argv, 0);
}
/*****************************************************************************
*
* opDefn
*
* Returns the quoted definition of its argument(s), concatenated
* from left to right.
*
*****************************************************************************/
DeclareOpc(opcDefn)
{
PMAC pmac = pmacFindPtok(ptok);
if (pmac) {
PushQuotedPtok(&pmac->pval->tok);
}
}
DeclareOp(opDefn)
{
EachReverseOpcArgvDw(opcDefn, argv, 0);
}