void MacExpandStart (Macro* M) /* Start expanding a macro */ { MacExp* E; /* Check the argument */ PRECONDITION (M && (M->Style != MAC_STYLE_DEFINE || DisableDefines == 0)); /* We cannot expand an incomplete macro */ if (M->Incomplete) { Error ("Cannot expand an incomplete macro"); return; } /* Don't allow too many nested macro expansions - otherwise it is possible * to force an endless loop and assembler crash. */ if (MacExpansions >= MAX_MACEXPANSIONS) { Error ("Too many nested macro expansions"); return; } /* Create a structure holding expansion data */ E = NewMacExp (M); /* 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); } }
static void StartExpDefine (Macro* M) /* Start expanding a DEFINE style macro */ { /* Create a structure holding expansion data */ MacExp* E = NewMacExp (M); /* A define style macro must be called with as many actual parameters * as there are formal ones. Get the parameter count. */ unsigned Count = M->ParamCount; /* Skip the current token */ NextTok (); /* Read the actual parameters */ while (Count--) { TokNode* Last; /* The macro may optionally be enclosed in curly braces */ Token Term = GetTokListTerm (TOK_COMMA); /* Check if there is really a parameter */ if (TokIsSep (Tok) || Tok == Term) { ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1); FreeMacExp (E); return; } /* Read tokens for one parameter */ Last = 0; do { TokNode* T; /* 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; /* And skip it... */ NextTok (); } while (Tok != Term && !TokIsSep (Tok)); /* 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. */ if (Term == TOK_RCURLY) { if (TokIsSep (Tok)) { Error ("End of line encountered within macro argument"); break; } NextTok (); } /* Check for a comma */ if (Count > 0) { if (Tok == TOK_COMMA) { NextTok (); } else { Error ("`,' expected"); } } } /* Macro expansion will overwrite the current token. This is a problem * for define style macros since these are called from the scanner level. * To avoid it, remember the current token and re-insert it, once macro * expansion is done. */ E->Final = NewTokNode (); /* Insert a new token input function */ PushInput (MacExpand, E, ".DEFINE"); }
static void StartExpClassic (Macro* M) /* Start expanding the classic macro M */ { MacExp* E; Token Term; /* Skip the macro name */ NextTok (); /* Create a structure holding expansion data */ E = NewMacExp (M); /* Read the actual parameters */ while (!TokIsSep (Tok)) { TokNode* Last; /* Check for maximum parameter count */ if (E->ParamCount >= 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 (Tok != Term && Tok != TOK_SEP) { TokNode* T; /* Check for end of file */ if (Tok == TOK_EOF) { Error ("Unexpected end of file"); FreeMacExp (E); return; } /* 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; /* And skip it... */ NextTok (); } /* 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. */ if (Term == TOK_RCURLY) { if (Tok == TOK_SEP) { Error ("End of line encountered within macro argument"); break; } NextTok (); } /* Check for a comma */ if (Tok == TOK_COMMA) { NextTok (); } else { break; } } /* We must be at end of line now, otherwise something is wrong */ ExpectSep (); /* Insert a new token input function */ PushInput (MacExpand, E, ".MACRO"); }