void PreProcessor::applyMacro(const String &ident, const ref<MacroDef> ¯o) { assert(tokenit.is(_IDENT)); DBG("apply macro: %s", ident.c_str()); if (macro->params.empty()) { tokenit.erase(1);//erase identifier tokenit.insert(macro->tokens); } else { TokenIterator tag = tokenit; tokenit.next(); //get caller params if (tokenit.is(_LPAREN)) { tokenit.next(); List<List<Token> > caller_params; if (!parseFunctionParams(caller_params)) { ERROR("failed to parse function macro"); return; } if (macro->params.size() != caller_params.size()) { ERROR("macro %s requres %d parameters", ident.c_str(), macro->params.size()); return; } tag.erase(tokenit-tag);//erase function call tokens //replace macro params List<Token> replace_tokens = replaceMacroParams(macro->tokens, caller_params); tokenit.insert(replace_tokens); //tokenit.next(); } } }
bool MacroExpander::expandMacro(const Macro ¯o, const Token &identifier, std::vector<Token> *replacements) { replacements->clear(); // In the case of an object-like macro, the replacement list gets its location // from the identifier, but in the case of a function-like macro, the replacement // list gets its location from the closing parenthesis of the macro invocation. // This is tested by dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.* SourceLocation replacementLocation = identifier.location; if (macro.type == Macro::kTypeObj) { replacements->assign(macro.replacements.begin(), macro.replacements.end()); if (macro.predefined) { const char kLine[] = "__LINE__"; const char kFile[] = "__FILE__"; ASSERT(replacements->size() == 1); Token& repl = replacements->front(); if (macro.name == kLine) { repl.text = ToString(identifier.location.line); } else if (macro.name == kFile) { repl.text = ToString(identifier.location.file); } } } else { ASSERT(macro.type == Macro::kTypeFunc); std::vector<MacroArg> args; args.reserve(macro.parameters.size()); if (!collectMacroArgs(macro, identifier, &args, &replacementLocation)) return false; replaceMacroParams(macro, args, replacements); } for (std::size_t i = 0; i < replacements->size(); ++i) { Token& repl = replacements->at(i); if (i == 0) { // The first token in the replacement list inherits the padding // properties of the identifier token. repl.setAtStartOfLine(identifier.atStartOfLine()); repl.setHasLeadingSpace(identifier.hasLeadingSpace()); } repl.location = replacementLocation; } return true; }
bool MacroExpander::expandMacro(const Macro ¯o, const Token &identifier, std::vector<Token> *replacements) { replacements->clear(); if (macro.type == Macro::kTypeObj) { replacements->assign(macro.replacements.begin(), macro.replacements.end()); if (macro.predefined) { const char kLine[] = "__LINE__"; const char kFile[] = "__FILE__"; assert(replacements->size() == 1); Token& repl = replacements->front(); if (macro.name == kLine) { std::ostringstream stream; stream << identifier.location.line; repl.text = stream.str(); } else if (macro.name == kFile) { std::ostringstream stream; stream << identifier.location.file; repl.text = stream.str(); } } } else { assert(macro.type == Macro::kTypeFunc); std::vector<MacroArg> args; args.reserve(macro.parameters.size()); if (!collectMacroArgs(macro, identifier, &args)) return false; replaceMacroParams(macro, args, replacements); } for (std::size_t i = 0; i < replacements->size(); ++i) { Token& repl = replacements->at(i); if (i == 0) { // The first token in the replacement list inherits the padding // properties of the identifier token. repl.setAtStartOfLine(identifier.atStartOfLine()); repl.setHasLeadingSpace(identifier.hasLeadingSpace()); } repl.location = identifier.location; } return true; }