void InsertMacro(CMacro* Macro, std::wstring& Args) { tTextData Text; ArgumentList Arguments; splitArguments(Arguments,Args); if ((int)Arguments.size() != Macro->getArgumentCount()) { Logger::printError(Logger::Error,L"%s macro arguments (%d vs %d)", (int)Arguments.size() > Macro->getArgumentCount() ? L"Too many" : L"Not enough", Arguments.size(),Macro->getArgumentCount()); return; } Global.MacroNestingLevel++; if (Global.MacroNestingLevel == ASSEMBLER_MACRO_NESTING_LEVEL) { Logger::printError(Logger::Error,L"Maximum macro nesting level reached"); return; } int MacroCounter = Macro->getIncreaseCounter(); for (int i = 0; i < Macro->getLineCount(); i++) { Text.buffer = Macro->getLine(i,Arguments,MacroCounter); Text.buffer = Global.symbolTable.insertEquations(Text.buffer,Global.FileInfo.FileNum,Global.Section); if (CheckEquLabel(Text.buffer) == false) { Text.buffer = checkLabel(Text.buffer,false); splitLine(Text.buffer,Text.name,Text.params); if (Text.name.size() == 0) continue; bool macro = false; for (size_t i = 0; i < Global.Macros.size(); i++) { if (Text.name.compare(Global.Macros[i]->getName()) == 0) { InsertMacro(Global.Macros[i],Text.params); macro = true; } } if (macro == true) continue; if (Arch->AssembleDirective(Text.name,Text.params) == false) { Arch->AssembleOpcode(Text.name,Text.params); } } } Global.MacroNestingLevel--; }
bool ParseMacro(TextFile& Input, std::wstring& opcodeName, std::wstring& Args) { if (opcodeName.compare(L".macro") == 0) { parseMacroDefinition(Input,Args); return true; } for (size_t i = 0; i < Global.Macros.size(); i++) { if (opcodeName.compare(Global.Macros[i]->getName()) == 0) { Global.MacroNestingLevel = 0; InsertMacro(Global.Macros[i],Args); return true; } } return false; }
static void DefineMacro (void) /* Handle a macro definition. */ { ident Ident; Macro* M; Macro* Existing; int C89; /* Read the macro name */ SkipWhitespace (0); if (!MacName (Ident)) { return; } /* Remember if we're in C89 mode */ C89 = (IS_Get (&Standard) == STD_C89); /* Get an existing macro definition with this name */ Existing = FindMacro (Ident); /* Create a new macro definition */ M = NewMacro (Ident); /* Check if this is a function like macro */ if (CurC == '(') { /* Skip the left paren */ NextChar (); /* Set the marker that this is a function like macro */ M->ArgCount = 0; /* Read the formal parameter list */ while (1) { /* Skip white space and check for end of parameter list */ SkipWhitespace (0); if (CurC == ')') { break; } /* The next token must be either an identifier, or - if not in * C89 mode - the ellipsis. */ if (!C89 && CurC == '.') { /* Ellipsis */ NextChar (); if (CurC != '.' || NextC != '.') { PPError ("`...' expected"); ClearLine (); return; } NextChar (); NextChar (); /* Remember that the macro is variadic and use __VA_ARGS__ as * the argument name. */ AddMacroArg (M, "__VA_ARGS__"); M->Variadic = 1; } else { /* Must be macro argument name */ if (MacName (Ident) == 0) { return; } /* __VA_ARGS__ is only allowed in C89 mode */ if (!C89 && strcmp (Ident, "__VA_ARGS__") == 0) { PPWarning ("`__VA_ARGS__' can only appear in the expansion " "of a C99 variadic macro"); } /* Add the macro argument */ AddMacroArg (M, Ident); } /* If we had an ellipsis, or the next char is not a comma, we've * reached the end of the macro argument list. */ SkipWhitespace (0); if (M->Variadic || CurC != ',') { break; } NextChar (); } /* Check for a right paren and eat it if we find one */ if (CurC != ')') { PPError ("`)' expected"); ClearLine (); return; } NextChar (); } /* Skip whitespace before the macro replacement */ SkipWhitespace (0); /* Insert the macro into the macro table and allocate the ActualArgs array */ InsertMacro (M); /* Remove whitespace and comments from the line, store the preprocessed * line into the macro replacement buffer. */ Pass1 (Line, &M->Replacement); /* Remove whitespace from the end of the line */ while (IsSpace (SB_LookAtLast (&M->Replacement))) { SB_Drop (&M->Replacement, 1); } #if 0 printf ("%s: <%.*s>\n", M->Name, SB_GetLen (&M->Replacement), SB_GetConstBuf (&M->Replacement)); #endif /* If we have an existing macro, check if the redefinition is identical. * Print a diagnostic if not. */ if (Existing && MacroCmp (M, Existing) != 0) { PPError ("Macro redefinition is not identical"); } }