/*****************************************************************************/
/* */
-/* macro.c */
+/* macro.c */
/* */
-/* Macros for the ca65 macroassembler */
+/* Macros for the ca65 macroassembler */
/* */
/* */
/* */
/* common */
#include "check.h"
-#include "hashstr.h"
+#include "hashfunc.h"
#include "hashtab.h"
#include "xmalloc.h"
static unsigned HT_GenHash (const void* Key);
/* Generate the hash over a key. */
-static const void* HT_GetKey (void* Entry);
+static const void* HT_GetKey (const void* Entry);
/* Given a pointer to the user entry data, return a pointer to the key */
-static HashNode* HT_GetHashNode (void* Entry);
-/* Given a pointer to the user entry data, return a pointer to the hash node */
-
static int HT_Compare (const void* Key1, const void* Key2);
/* Compare two keys. The function must return a value less than zero if
* Key1 is smaller than Key2, zero if both are equal, and a value greater
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* Struct that describes an identifer (macro param, local list) */
typedef struct IdDesc IdDesc;
struct IdDesc {
- IdDesc* Next; /* Linked list */
+ IdDesc* Next; /* Linked list */
StrBuf Id; /* Identifier, dynamically allocated */
};
/* Struct that describes a macro definition */
-typedef struct Macro Macro;
struct Macro {
HashNode Node; /* Hash list node */
- Macro* List; /* List of all macros */
- unsigned LocalCount; /* Count of local symbols */
- IdDesc* Locals; /* List of local symbols */
- unsigned ParamCount; /* Parameter count of macro */
- IdDesc* Params; /* Identifiers of macro parameters */
- unsigned TokCount; /* Number of tokens for this macro */
- TokNode* TokRoot; /* Root of token list */
- TokNode* TokLast; /* Pointer to last token in list */
- StrBuf Name; /* Macro name, dynamically allocated */
+ Macro* List; /* List of all macros */
+ unsigned LocalCount; /* Count of local symbols */
+ IdDesc* Locals; /* List of local symbols */
+ unsigned ParamCount; /* Parameter count of macro */
+ IdDesc* Params; /* Identifiers of macro parameters */
+ unsigned TokCount; /* Number of tokens for this macro */
+ TokNode* TokRoot; /* Root of token list */
+ TokNode* TokLast; /* Pointer to last token in list */
+ StrBuf Name; /* Macro name, dynamically allocated */
unsigned Expansions; /* Number of active macro expansions */
- unsigned char Style; /* Macro style */
+ unsigned char Style; /* Macro style */
unsigned char Incomplete; /* Macro is currently built */
};
static const HashFunctions HashFunc = {
HT_GenHash,
HT_GetKey,
- HT_GetHashNode,
HT_Compare
};
/* Structs that holds data for a macro expansion */
typedef struct MacExp MacExp;
struct MacExp {
- MacExp* Next; /* Pointer to next expansion */
- Macro* M; /* Which macro do we expand? */
- unsigned IfSP; /* .IF stack pointer at start of expansion */
- TokNode* Exp; /* Pointer to current token */
- TokNode* Final; /* Pointer to final token */
- unsigned LocalStart; /* Start of counter for local symbol names */
- unsigned ParamCount; /* Number of actual parameters */
- TokNode** Params; /* List of actual parameters */
- TokNode* ParamExp; /* Node for expanding parameters */
- int LISlot; /* Slot for additional line infos */
+ MacExp* Next; /* Pointer to next expansion */
+ Macro* M; /* Which macro do we expand? */
+ unsigned IfSP; /* .IF stack pointer at start of expansion */
+ TokNode* Exp; /* Pointer to current token */
+ TokNode* Final; /* Pointer to final token */
+ unsigned MacExpansions; /* Number of active macro expansions */
+ unsigned LocalStart; /* Start of counter for local symbol names */
+ unsigned ParamCount; /* Number of actual parameters */
+ TokNode** Params; /* List of actual parameters */
+ TokNode* ParamExp; /* Node for expanding parameters */
+ LineInfo* LI; /* Line info for the expansion */
+ LineInfo* ParamLI; /* Line info for parameter expansion */
};
/* Maximum number of nested macro expansions */
-static const void* HT_GetKey (void* Entry)
+static const void* HT_GetKey (const void* Entry)
/* Given a pointer to the user entry data, return a pointer to the index */
{
return &((Macro*) Entry)->Name;
-static HashNode* HT_GetHashNode (void* Entry)
-/* Given a pointer to the user entry data, return a pointer to the hash node */
-{
- return &((Macro*) Entry)->Node;
-}
-
-
-
static int HT_Compare (const void* Key1, const void* Key2)
/* Compare two keys. The function must return a value less than zero if
* Key1 is smaller than Key2, zero if both are equal, and a value greater
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
Macro* M = xmalloc (sizeof (Macro));
/* Initialize the macro struct */
- InitHashNode (&M->Node, M);
+ InitHashNode (&M->Node);
M->LocalCount = 0;
M->Locals = 0;
M->ParamCount = 0;
M->Params = 0;
- M->TokCount = 0;
+ M->TokCount = 0;
M->TokRoot = 0;
M->TokLast = 0;
SB_Init (&M->Name);
SB_Copy (&M->Name, Name);
M->Expansions = 0;
- M->Style = Style;
+ M->Style = Style;
M->Incomplete = 1;
/* Insert the macro into the hash table */
MacExp* E = xmalloc (sizeof (MacExp));
/* Initialize the data */
- E->M = M;
- E->IfSP = GetIfStack ();
- E->Exp = M->TokRoot;
- E->Final = 0;
- E->LocalStart = LocalName;
- LocalName += M->LocalCount;
- E->ParamCount = 0;
- E->Params = xmalloc (M->ParamCount * sizeof (TokNode*));
+ E->M = M;
+ E->IfSP = GetIfStack ();
+ E->Exp = M->TokRoot;
+ E->Final = 0;
+ E->MacExpansions = ++MacExpansions; /* One macro expansion more */
+ E->LocalStart = LocalName;
+ LocalName += M->LocalCount;
+ E->ParamCount = 0;
+ E->Params = xmalloc (M->ParamCount * sizeof (TokNode*));
for (I = 0; I < M->ParamCount; ++I) {
- E->Params[I] = 0;
+ E->Params[I] = 0;
}
- E->ParamExp = 0;
- E->LISlot = AllocLineInfoSlot (LI_TYPE_MACRO, MacExpansions);
+ E->ParamExp = 0;
+ E->LI = 0;
+ E->ParamLI = 0;
/* Mark the macro as expanding */
++M->Expansions;
- /* One macro expansion more */
- ++MacExpansions;
-
/* Return the new macro expansion */
return E;
}
}
xfree (E->Params);
- /* Free the additional line info slot */
- FreeLineInfoSlot (E->LISlot);
+ /* Free the additional line info */
+ if (E->ParamLI) {
+ EndLine (E->ParamLI);
+ }
+ if (E->LI) {
+ EndLine (E->LI);
+ }
/* Free the final token if we have one */
if (E->Final) {
- FreeTokNode (E->Final);
+ FreeTokNode (E->Final);
}
/* Free the structure itself */
/* Skip a macro definition */
{
if (Style == MAC_STYLE_CLASSIC) {
- /* Skip tokens until we reach the final .endmacro */
- while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
- NextTok ();
- }
- if (CurTok.Tok != TOK_EOF) {
- SkipUntilSep ();
- } else {
- Error ("`.ENDMACRO' expected");
- }
+ /* Skip tokens until we reach the final .endmacro */
+ while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) {
+ NextTok ();
+ }
+ if (CurTok.Tok != TOK_EOF) {
+ SkipUntilSep ();
+ } else {
+ Error ("`.ENDMACRO' expected");
+ }
} else {
- /* Skip until end of line */
- SkipUntilSep ();
+ /* Skip until end of line */
+ SkipUntilSep ();
}
}
/* We expect a macro name here */
if (CurTok.Tok != TOK_IDENT) {
- Error ("Identifier expected");
- MacSkipDef (Style);
- return;
+ Error ("Identifier expected");
+ MacSkipDef (Style);
+ return;
} else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) {
/* The identifier is a name of a 6502 instruction, which is not
* allowed if not explicitly enabled.
/* Did we already define that macro? */
if (HT_Find (&MacroTab, &CurTok.SVal) != 0) {
- /* Macro is already defined */
- Error ("A macro named `%m%p' is already defined", &CurTok.SVal);
- /* Skip tokens until we reach the final .endmacro */
- MacSkipDef (Style);
- return;
+ /* Macro is already defined */
+ Error ("A macro named `%m%p' is already defined", &CurTok.SVal);
+ /* Skip tokens until we reach the final .endmacro */
+ MacSkipDef (Style);
+ return;
}
/* Define the macro */
* otherwise we may have parameters without braces.
*/
if (Style == MAC_STYLE_CLASSIC) {
- HaveParams = 1;
+ HaveParams = 1;
} else {
- if (CurTok.Tok == TOK_LPAREN) {
- HaveParams = 1;
- NextTok ();
- } else {
- HaveParams = 0;
- }
+ if (CurTok.Tok == TOK_LPAREN) {
+ HaveParams = 1;
+ NextTok ();
+ } else {
+ HaveParams = 0;
+ }
}
/* Parse the parameter list */
if (HaveParams) {
- while (CurTok.Tok == TOK_IDENT) {
-
- /* Create a struct holding the identifier */
- IdDesc* I = NewIdDesc (&CurTok.SVal);
-
- /* Insert the struct into the list, checking for duplicate idents */
- if (M->ParamCount == 0) {
- M->Params = I;
- } else {
- IdDesc* List = M->Params;
- while (1) {
- if (SB_Compare (&List->Id, &CurTok.SVal) == 0) {
- Error ("Duplicate symbol `%m%p'", &CurTok.SVal);
- }
- if (List->Next == 0) {
- break;
- } else {
- List = List->Next;
- }
- }
- List->Next = I;
- }
- ++M->ParamCount;
-
- /* Skip the name */
- NextTok ();
-
- /* Maybe there are more params... */
- if (CurTok.Tok == TOK_COMMA) {
- NextTok ();
- } else {
- break;
- }
- }
+ while (CurTok.Tok == TOK_IDENT) {
+
+ /* Create a struct holding the identifier */
+ IdDesc* I = NewIdDesc (&CurTok.SVal);
+
+ /* Insert the struct into the list, checking for duplicate idents */
+ if (M->ParamCount == 0) {
+ M->Params = I;
+ } else {
+ IdDesc* List = M->Params;
+ while (1) {
+ if (SB_Compare (&List->Id, &CurTok.SVal) == 0) {
+ Error ("Duplicate symbol `%m%p'", &CurTok.SVal);
+ }
+ if (List->Next == 0) {
+ break;
+ } else {
+ List = List->Next;
+ }
+ }
+ List->Next = I;
+ }
+ ++M->ParamCount;
+
+ /* Skip the name */
+ NextTok ();
+
+ /* Maybe there are more params... */
+ if (CurTok.Tok == TOK_COMMA) {
+ NextTok ();
+ } else {
+ break;
+ }
+ }
}
/* For class macros, we expect a separator token, for define style macros,
* we expect the closing paren.
*/
if (Style == MAC_STYLE_CLASSIC) {
- ConsumeSep ();
+ ConsumeSep ();
} else if (HaveParams) {
- ConsumeRParen ();
+ ConsumeRParen ();
}
/* Preparse the macro body. We will read the tokens until we reach end of
*/
while (1) {
- /* Check for end of macro */
- if (Style == MAC_STYLE_CLASSIC) {
- /* In classic macros, only .endmacro is allowed */
- if (CurTok.Tok == TOK_ENDMACRO) {
- /* Done */
- break;
- }
- /* May not have end of file in a macro definition */
- if (CurTok.Tok == TOK_EOF) {
- Error ("`.ENDMACRO' expected");
- goto Done;
- }
- } else {
- /* Accept a newline or end of file for new style macros */
- if (TokIsSep (CurTok.Tok)) {
- break;
- }
- }
-
- /* Check for a .LOCAL declaration */
- if (CurTok.Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
-
- while (1) {
-
- IdDesc* I;
-
- /* Skip .local or comma */
- NextTok ();
-
- /* Need an identifer */
- if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
- Error ("Identifier expected");
- SkipUntilSep ();
- break;
- }
-
- /* Put the identifier into the locals list and skip it */
- I = NewIdDesc (&CurTok.SVal);
- I->Next = M->Locals;
- M->Locals = I;
- ++M->LocalCount;
- NextTok ();
-
- /* Check for end of list */
- if (CurTok.Tok != TOK_COMMA) {
- break;
- }
-
- }
-
- /* We need end of line after the locals */
- ConsumeSep ();
- continue;
- }
-
- /* Create a token node for the current token */
- N = NewTokNode ();
-
- /* If the token is an ident, check if it is a local parameter */
- if (CurTok.Tok == TOK_IDENT) {
- unsigned Count = 0;
- IdDesc* I = M->Params;
- while (I) {
- if (SB_Compare (&I->Id, &CurTok.SVal) == 0) {
- /* Local param name, replace it */
- N->T.Tok = TOK_MACPARAM;
- N->T.IVal = Count;
- break;
- }
- ++Count;
- I = I->Next;
- }
- }
-
- /* Insert the new token in the list */
- if (M->TokCount == 0) {
- /* First token */
- M->TokRoot = M->TokLast = N;
- } else {
- /* We have already tokens */
- M->TokLast->Next = N;
- M->TokLast = N;
- }
- ++M->TokCount;
-
- /* Read the next token */
- NextTok ();
+ /* Check for end of macro */
+ if (Style == MAC_STYLE_CLASSIC) {
+ /* In classic macros, only .endmacro is allowed */
+ if (CurTok.Tok == TOK_ENDMACRO) {
+ /* Done */
+ break;
+ }
+ /* May not have end of file in a macro definition */
+ if (CurTok.Tok == TOK_EOF) {
+ Error ("`.ENDMACRO' expected");
+ goto Done;
+ }
+ } else {
+ /* Accept a newline or end of file for new style macros */
+ if (TokIsSep (CurTok.Tok)) {
+ break;
+ }
+ }
+
+ /* Check for a .LOCAL declaration */
+ if (CurTok.Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) {
+
+ while (1) {
+
+ IdDesc* I;
+
+ /* Skip .local or comma */
+ NextTok ();
+
+ /* Need an identifer */
+ if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) {
+ Error ("Identifier expected");
+ SkipUntilSep ();
+ break;
+ }
+
+ /* Put the identifier into the locals list and skip it */
+ I = NewIdDesc (&CurTok.SVal);
+ I->Next = M->Locals;
+ M->Locals = I;
+ ++M->LocalCount;
+ NextTok ();
+
+ /* Check for end of list */
+ if (CurTok.Tok != TOK_COMMA) {
+ break;
+ }
+
+ }
+
+ /* We need end of line after the locals */
+ ConsumeSep ();
+ continue;
+ }
+
+ /* Create a token node for the current token */
+ N = NewTokNode ();
+
+ /* If the token is an identifier, check if it is a local parameter */
+ if (CurTok.Tok == TOK_IDENT) {
+ unsigned Count = 0;
+ IdDesc* I = M->Params;
+ while (I) {
+ if (SB_Compare (&I->Id, &CurTok.SVal) == 0) {
+ /* Local param name, replace it */
+ N->T.Tok = TOK_MACPARAM;
+ N->T.IVal = Count;
+ break;
+ }
+ ++Count;
+ I = I->Next;
+ }
+ }
+
+ /* Insert the new token in the list */
+ if (M->TokCount == 0) {
+ /* First token */
+ M->TokRoot = M->TokLast = N;
+ } else {
+ /* We have already tokens */
+ M->TokLast->Next = N;
+ M->TokLast = N;
+ }
+ ++M->TokCount;
+
+ /* Read the next token */
+ NextTok ();
}
/* Skip the .endmacro for a classic macro */
if (Style == MAC_STYLE_CLASSIC) {
- NextTok ();
+ NextTok ();
}
/* Reset the Incomplete flag now that parsing is done */
*/
{
/* Search for the macro */
- Macro* M = HT_FindEntry (&MacroTab, Name);
+ Macro* M = HT_Find (&MacroTab, Name);
/* Don't let the user kid with us */
if (M == 0 || M->Style != Style) {
}
/* Remove the macro from the macro table */
- HT_RemoveEntry (&MacroTab, M);
+ HT_Remove (&MacroTab, M);
/* Free the macro structure */
FreeMacro (M);
/* Check if we should abort this macro */
if (DoMacAbort) {
- /* Reset the flag */
- DoMacAbort = 0;
+ /* Reset the flag */
+ DoMacAbort = 0;
- /* Abort any open .IF statements in this macro expansion */
- CleanupIfStack (Mac->IfSP);
+ /* Abort any open .IF statements in this macro expansion */
+ CleanupIfStack (Mac->IfSP);
- /* Terminate macro expansion */
- goto MacEnd;
+ /* Terminate macro expansion */
+ goto MacEnd;
}
/* We're expanding a macro. Check if we are expanding one of the
ExpandParam:
if (Mac->ParamExp) {
- /* Ok, use token from parameter list, but don't use its line info */
- TokSet (Mac->ParamExp, LI_SLOT_INV);
+ /* Ok, use token from parameter list */
+ TokSet (Mac->ParamExp);
+
+ /* Create new line info for this parameter token */
+ if (Mac->ParamLI) {
+ EndLine (Mac->ParamLI);
+ }
+ Mac->ParamLI = StartLine (&CurTok.Pos, LI_TYPE_MACPARAM, Mac->MacExpansions);
+
+ /* Set pointer to next token */
+ Mac->ParamExp = Mac->ParamExp->Next;
+
+ /* Done */
+ return 1;
- /* Set pointer to next token */
- Mac->ParamExp = Mac->ParamExp->Next;
+ } else if (Mac->ParamLI) {
+
+ /* There's still line info open from the parameter expansion - end it */
+ EndLine (Mac->ParamLI);
+ Mac->ParamLI = 0;
- /* Done */
- return 1;
}
/* We're not expanding macro parameters. Check if we have tokens left from
*/
if (Mac->Exp) {
- /* Use next macro token */
- TokSet (Mac->Exp, Mac->LISlot);
+ /* Use next macro token */
+ TokSet (Mac->Exp);
- /* Set pointer to next token */
- Mac->Exp = Mac->Exp->Next;
+ /* Create new line info for this token */
+ if (Mac->LI) {
+ EndLine (Mac->LI);
+ }
+ Mac->LI = StartLine (&CurTok.Pos, LI_TYPE_MACRO, Mac->MacExpansions);
- /* Is it a request for actual parameter count? */
- if (CurTok.Tok == TOK_PARAMCOUNT) {
- CurTok.Tok = TOK_INTCON;
- CurTok.IVal = Mac->ParamCount;
- return 1;
- }
+ /* Set pointer to next token */
+ Mac->Exp = Mac->Exp->Next;
- /* Is it the name of a macro parameter? */
- if (CurTok.Tok == TOK_MACPARAM) {
+ /* Is it a request for actual parameter count? */
+ if (CurTok.Tok == TOK_PARAMCOUNT) {
+ CurTok.Tok = TOK_INTCON;
+ CurTok.IVal = Mac->ParamCount;
+ return 1;
+ }
- /* Start to expand the parameter token list */
- Mac->ParamExp = Mac->Params[CurTok.IVal];
+ /* Is it the name of a macro parameter? */
+ if (CurTok.Tok == TOK_MACPARAM) {
- /* Go back and expand the parameter */
- goto ExpandParam;
- }
+ /* Start to expand the parameter token list */
+ Mac->ParamExp = Mac->Params[CurTok.IVal];
+
+ /* Go back and expand the parameter */
+ goto ExpandParam;
+ }
- /* If it's an identifier, it may in fact be a local symbol */
- if ((CurTok.Tok == TOK_IDENT || CurTok.Tok == TOK_LOCAL_IDENT) &&
+ /* If it's an identifier, it may in fact be a local symbol */
+ if ((CurTok.Tok == TOK_IDENT || CurTok.Tok == TOK_LOCAL_IDENT) &&
Mac->M->LocalCount) {
- /* Search for the local symbol in the list */
- unsigned Index = 0;
- IdDesc* I = Mac->M->Locals;
- while (I) {
- if (SB_Compare (&CurTok.SVal, &I->Id) == 0) {
- /* This is in fact a local symbol, change the name. Be sure
+ /* Search for the local symbol in the list */
+ unsigned Index = 0;
+ IdDesc* I = Mac->M->Locals;
+ while (I) {
+ if (SB_Compare (&CurTok.SVal, &I->Id) == 0) {
+ /* This is in fact a local symbol, change the name. Be sure
* to generate a local label name if the original name was
* a local label, and also generate a name that cannot be
* generated by a user.
SB_Printf (&CurTok.SVal, "LOCAL-MACRO_SYMBOL-%04X",
Mac->LocalStart + Index);
}
- break;
- }
- /* Next symbol */
- ++Index;
- I = I->Next;
- }
-
- /* Done */
- return 1;
- }
-
- /* The token was successfully set */
- return 1;
+ break;
+ }
+ /* Next symbol */
+ ++Index;
+ I = I->Next;
+ }
+
+ /* Done */
+ return 1;
+ }
+
+ /* The token was successfully set */
+ return 1;
}
/* No more macro tokens. Do we have a final token? */
if (Mac->Final) {
- /* Set the final token and remove it */
- TokSet (Mac->Final, LI_SLOT_INV);
- FreeTokNode (Mac->Final);
- Mac->Final = 0;
+ /* Set the final token and remove it */
+ TokSet (Mac->Final);
+ FreeTokNode (Mac->Final);
+ Mac->Final = 0;
/* Problem: When a .define style macro is expanded within the call
* of a classic one, the latter may be terminated and removed while
FreeMacExp (Mac);
PopInput ();
- /* The token was successfully set */
- return 1;
+ /* The token was successfully set */
+ return 1;
}
MacEnd:
/* Read the actual parameters */
while (!TokIsSep (CurTok.Tok)) {
- TokNode* Last;
+ TokNode* Last;
- /* Check for maximum parameter count */
- if (E->ParamCount >= E->M->ParamCount) {
- ErrorSkip ("Too many macro parameters");
- break;
- }
+ /* Check for maximum parameter count */
+ if (E->ParamCount >= E->M->ParamCount) {
+ ErrorSkip ("Too many macro parameters");
+ break;
+ }
/* The macro may optionally be enclosed in curly braces */
Term = GetTokListTerm (TOK_COMMA);
- /* Read tokens for one parameter, accept empty params */
- Last = 0;
- while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
+ /* Read tokens for one parameter, accept empty params */
+ Last = 0;
+ while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
- TokNode* T;
+ TokNode* T;
- /* Check for end of file */
- if (CurTok.Tok == TOK_EOF) {
- Error ("Unexpected end of file");
+ /* Check for end of file */
+ if (CurTok.Tok == TOK_EOF) {
+ Error ("Unexpected end of file");
FreeMacExp (E);
- return;
- }
+ return;
+ }
- /* Get the next token in a node */
- T = NewTokNode ();
+ /* Get the next token in a node */
+ T = NewTokNode ();
- /* Insert it into the list */
- if (Last == 0) {
- E->Params [E->ParamCount] = T;
- } else {
- Last->Next = T;
- }
- Last = T;
+ /* Insert it into the list */
+ if (Last == 0) {
+ E->Params [E->ParamCount] = T;
+ } else {
+ Last->Next = T;
+ }
+ Last = T;
- /* And skip it... */
- NextTok ();
- }
+ /* And skip it... */
+ NextTok ();
+ }
- /* One parameter more */
- ++E->ParamCount;
+ /* One parameter more */
+ ++E->ParamCount;
/* If the macro argument was enclosed in curly braces, end-of-line
* is an error. Skip the closing curly brace.
NextTok ();
}
- /* Check for a comma */
- if (CurTok.Tok == TOK_COMMA) {
- NextTok ();
- } else {
- break;
- }
+ /* Check for a comma */
+ if (CurTok.Tok == TOK_COMMA) {
+ NextTok ();
+ } else {
+ break;
+ }
}
/* We must be at end of line now, otherwise something is wrong */
/* Read the actual parameters */
while (Count--) {
- TokNode* Last;
+ TokNode* Last;
/* The macro may optionally be enclosed in curly braces */
token_t Term = GetTokListTerm (TOK_COMMA);
- /* Check if there is really a parameter */
- if (TokIsSep (CurTok.Tok) || CurTok.Tok == Term) {
+ /* Check if there is really a parameter */
+ if (TokIsSep (CurTok.Tok) || CurTok.Tok == Term) {
ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1);
FreeMacExp (E);
return;
}
- /* Read tokens for one parameter */
- Last = 0;
- do {
+ /* Read tokens for one parameter */
+ Last = 0;
+ do {
- TokNode* T;
+ TokNode* T;
- /* Get the next token in a node */
- T = NewTokNode ();
+ /* Get the next token in a node */
+ T = NewTokNode ();
- /* Insert it into the list */
- if (Last == 0) {
- E->Params [E->ParamCount] = T;
- } else {
- Last->Next = T;
- }
- Last = T;
+ /* Insert it into the list */
+ if (Last == 0) {
+ E->Params [E->ParamCount] = T;
+ } else {
+ Last->Next = T;
+ }
+ Last = T;
- /* And skip it... */
- NextTok ();
+ /* And skip it... */
+ NextTok ();
- } while (CurTok.Tok != Term && !TokIsSep (CurTok.Tok));
+ } while (CurTok.Tok != Term && !TokIsSep (CurTok.Tok));
- /* One parameter more */
- ++E->ParamCount;
+ /* One parameter more */
+ ++E->ParamCount;
/* If the macro argument was enclosed in curly braces, end-of-line
* is an error. Skip the closing curly brace.
NextTok ();
}
- /* Check for a comma */
- if (Count > 0) {
- if (CurTok.Tok == TOK_COMMA) {
- NextTok ();
- } else {
- Error ("`,' expected");
- }
- }
+ /* Check for a comma */
+ if (Count > 0) {
+ if (CurTok.Tok == TOK_COMMA) {
+ NextTok ();
+ } else {
+ Error ("`,' expected");
+ }
+ }
}
/* Macro expansion will overwrite the current token. This is a problem
-void MacExpandStart (void)
-/* Start expanding the macro in SVal */
+void MacExpandStart (Macro* M)
+/* Start expanding a macro */
{
MacExp* E;
- /* Search for the macro */
- Macro* M = HT_FindEntry (&MacroTab, &CurTok.SVal);
- CHECK (M != 0 && (M->Style != MAC_STYLE_DEFINE || DisableDefines == 0));
+ /* Check the argument */
+ PRECONDITION (M && (M->Style != MAC_STYLE_DEFINE || DisableDefines == 0));
/* We cannot expand an incomplete macro */
if (M->Incomplete) {
/* Call the apropriate subroutine */
switch (M->Style) {
- case MAC_STYLE_CLASSIC: StartExpClassic (E); break;
- case MAC_STYLE_DEFINE: StartExpDefine (E); break;
- default: Internal ("Invalid macro style: %d", M->Style);
+ case MAC_STYLE_CLASSIC: StartExpClassic (E); break;
+ case MAC_STYLE_DEFINE: StartExpDefine (E); break;
+ default: Internal ("Invalid macro style: %d", M->Style);
}
}
-int IsMacro (const StrBuf* Name)
-/* Return true if the given name is the name of a macro */
+Macro* FindMacro (const StrBuf* Name)
+/* Try to find the macro with the given name and return it. If no macro with
+ * this name was found, return NULL.
+ */
{
- return (HT_Find (&MacroTab, Name) != 0);
+ Macro* M = HT_Find (&MacroTab, Name);
+ return (M != 0 && M->Style == MAC_STYLE_CLASSIC)? M : 0;
}
-int IsDefine (const StrBuf* Name)
-/* Return true if the given name is the name of a define style macro */
+Macro* FindDefine (const StrBuf* Name)
+/* Try to find the define style macro with the given name and return it. If no
+ * such macro was found, return NULL.
+ */
{
Macro* M;
}
/* Check if we have such a macro */
- M = HT_FindEntry (&MacroTab, Name);
- return (M != 0 && M->Style == MAC_STYLE_DEFINE);
+ M = HT_Find (&MacroTab, Name);
+ return (M != 0 && M->Style == MAC_STYLE_DEFINE)? M : 0;
}
PRECONDITION (DisableDefines > 0);
--DisableDefines;
}
-
-
-