1d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// 3d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Licensed under the Apache License, Version 2.0 (the "License"); 4d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// you may not use this file except in compliance with the License. 5d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// You may obtain a copy of the License at 6d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// 7d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// http://www.apache.org/licenses/LICENSE-2.0 8d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// 9d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// Unless required by applicable law or agreed to in writing, software 10d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// distributed under the License is distributed on an "AS IS" BASIS, 11d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// See the License for the specific language governing permissions and 13d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens// limitations under the License. 14d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 15d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "MacroExpander.h" 16d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 17d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include <algorithm> 18d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include <sstream> 19d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 20d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Diagnostics.h" 21d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens#include "Token.h" 22d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 23d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensnamespace pp 24d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 25d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 26d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensclass TokenLexer : public Lexer 27d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 28d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens public: 29d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens typedef std::vector<Token> TokenVector; 30d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 31d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens TokenLexer(TokenVector* tokens) 32d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 33d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens tokens->swap(mTokens); 34d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens mIter = mTokens.begin(); 35d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 36d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 37d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens virtual void lex(Token* token) 38d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 39d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (mIter == mTokens.end()) 40d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 41d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens token->reset(); 42d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens token->type = Token::LAST; 43d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 44d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens else 45d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 46d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens *token = *mIter++; 47d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 48d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 49d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 50d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens private: 51d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer); 52d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 53d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens TokenVector mTokens; 54d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens TokenVector::const_iterator mIter; 55d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens}; 56d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 57d999309b36cb3dceadd38217b322f0e96a06b202Nicolas CapensMacroExpander::MacroExpander(Lexer* lexer, 58d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens MacroSet* macroSet, 59d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens Diagnostics* diagnostics, 60d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens bool parseDefined) : 61d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined) 62d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 63250d75b37616782ff91ba7440cd2d4a3bbc1670aNicolas Capens mReserveToken = nullptr; 64d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 65d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 66d999309b36cb3dceadd38217b322f0e96a06b202Nicolas CapensMacroExpander::~MacroExpander() 67d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 68d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens for (size_t i = 0; i < mContextStack.size(); ++i) 69d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 70d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens delete mContextStack[i]; 71d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 72250d75b37616782ff91ba7440cd2d4a3bbc1670aNicolas Capens 73250d75b37616782ff91ba7440cd2d4a3bbc1670aNicolas Capens delete mReserveToken; 74d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 75d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 76d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid MacroExpander::lex(Token* token) 77d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 78d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens while (true) 79d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 80d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens getToken(token); 81d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 82d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (token->type != Token::IDENTIFIER) 83d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 84d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 85d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // Defined operator is parsed here since it may be generated by macro expansion. 86d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // Defined operator produced by macro expansion has undefined behavior according to C++ 87d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // spec, which the GLSL spec references (see C++14 draft spec section 16.1.4), but this 88d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // behavior is needed for passing dEQP tests, which enforce stricter compatibility between 89d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // implementations. 90d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (mParseDefined && token->text == "defined") 91d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 92d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens bool paren = false; 93d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens getToken(token); 94d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (token->type == '(') 95d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 96d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens paren = true; 97d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens getToken(token); 98d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 99d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (token->type != Token::IDENTIFIER) 100d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 101d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location, 102d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens token->text); 103d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 104d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 105d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens auto iter = mMacroSet->find(token->text); 106d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens std::string expression = iter != mMacroSet->end() ? "1" : "0"; 107d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 108d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (paren) 109d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 110d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens getToken(token); 111d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (token->type != ')') 112d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 113d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, token->location, 114d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens token->text); 115d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 116d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 117d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 118d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 119d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // We have a valid defined operator. 120d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // Convert the current token into a CONST_INT token. 121d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens token->type = Token::CONST_INT; 122d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens token->text = expression; 123d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 124d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 125d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 126d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (token->expansionDisabled()) 127d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 128d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 129d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens MacroSet::const_iterator iter = mMacroSet->find(token->text); 130d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (iter == mMacroSet->end()) 131d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 132d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 133d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens const Macro& macro = iter->second; 134d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (macro.disabled) 135d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 136d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // If a particular token is not expanded, it is never expanded. 137d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens token->setExpansionDisabled(true); 138d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 139d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 140d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen()) 141d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 142d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // If the token immediately after the macro name is not a '(', 143d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // this macro should not be expanded. 144d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 145d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 146d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 147d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens pushMacro(macro, *token); 148d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 149d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 150d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 151d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid MacroExpander::getToken(Token* token) 152d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 153250d75b37616782ff91ba7440cd2d4a3bbc1670aNicolas Capens if (mReserveToken) 154d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 155d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens *token = *mReserveToken; 156250d75b37616782ff91ba7440cd2d4a3bbc1670aNicolas Capens delete mReserveToken; 1579b5d35e3c5ee3588e57b85c4a1708ec979f46b68Nicolas Capens mReserveToken = nullptr; 158d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens return; 159d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 160d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 161d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // First pop all empty macro contexts. 162d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens while (!mContextStack.empty() && mContextStack.back()->empty()) 163d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 164d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens popMacro(); 165d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 166d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 167d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (!mContextStack.empty()) 168d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 169d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens *token = mContextStack.back()->get(); 170d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 171d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens else 172d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 173d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens mLexer->lex(token); 174d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 175d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 176d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 177d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid MacroExpander::ungetToken(const Token& token) 178d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 179d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (!mContextStack.empty()) 180d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 181d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens MacroContext* context = mContextStack.back(); 182d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens context->unget(); 183d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(context->replacements[context->index] == token); 184d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 185d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens else 186d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 187250d75b37616782ff91ba7440cd2d4a3bbc1670aNicolas Capens assert(!mReserveToken); 188250d75b37616782ff91ba7440cd2d4a3bbc1670aNicolas Capens mReserveToken = new Token(token); 189d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 190d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 191d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 192d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensbool MacroExpander::isNextTokenLeftParen() 193d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 194d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens Token token; 195d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens getToken(&token); 196d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 197d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens bool lparen = token.type == '('; 198d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens ungetToken(token); 199d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 200d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens return lparen; 201d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 202d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 203d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensbool MacroExpander::pushMacro(const Macro& macro, const Token& identifier) 204d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 205d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(!macro.disabled); 206d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(!identifier.expansionDisabled()); 207d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(identifier.type == Token::IDENTIFIER); 208d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(identifier.text == macro.name); 209d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 210d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens std::vector<Token> replacements; 211d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (!expandMacro(macro, identifier, &replacements)) 212d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens return false; 213d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 214d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // Macro is disabled for expansion until it is popped off the stack. 215d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens macro.disabled = true; 216d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 217d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens MacroContext* context = new MacroContext; 218d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens context->macro = ¯o; 219d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens context->replacements.swap(replacements); 220d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens mContextStack.push_back(context); 221d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens return true; 222d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 223d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 224d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid MacroExpander::popMacro() 225d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 226d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(!mContextStack.empty()); 227d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 228d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens MacroContext* context = mContextStack.back(); 229d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens mContextStack.pop_back(); 230d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 231d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(context->empty()); 232d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(context->macro->disabled); 233d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens context->macro->disabled = false; 234d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens delete context; 235d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 236d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 237d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensbool MacroExpander::expandMacro(const Macro& macro, 238d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens const Token& identifier, 239d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens std::vector<Token>* replacements) 240d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 241d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens replacements->clear(); 242d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (macro.type == Macro::kTypeObj) 243d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 244d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens replacements->assign(macro.replacements.begin(), 245d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens macro.replacements.end()); 246d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 247d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (macro.predefined) 248d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 249d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens static const std::string kLine = "__LINE__"; 250d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens static const std::string kFile = "__FILE__"; 251d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 252d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(replacements->size() == 1); 253d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens Token& repl = replacements->front(); 254d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (macro.name == kLine) 255d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 256d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens std::ostringstream stream; 257d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens stream << identifier.location.line; 258d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens repl.text = stream.str(); 259d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 260d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens else if (macro.name == kFile) 261d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 262d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens std::ostringstream stream; 263d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens stream << identifier.location.file; 264d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens repl.text = stream.str(); 265d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 266d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 267d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 268d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens else 269d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 270d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(macro.type == Macro::kTypeFunc); 271d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens std::vector<MacroArg> args; 272d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens args.reserve(macro.parameters.size()); 273d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (!collectMacroArgs(macro, identifier, &args)) 274d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens return false; 275d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 276d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens replaceMacroParams(macro, args, replacements); 277d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 278d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 279d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens for (size_t i = 0; i < replacements->size(); ++i) 280d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 281d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens Token& repl = replacements->at(i); 282d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (i == 0) 283d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 284d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // The first token in the replacement list inherits the padding 285d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // properties of the identifier token. 286d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens repl.setAtStartOfLine(identifier.atStartOfLine()); 287d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens repl.setHasLeadingSpace(identifier.hasLeadingSpace()); 288d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 289d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens repl.location = identifier.location; 290d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 291d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens return true; 292d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 293d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 294d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensbool MacroExpander::collectMacroArgs(const Macro& macro, 295d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens const Token& identifier, 296d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens std::vector<MacroArg>* args) 297d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 298d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens Token token; 299d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens getToken(&token); 300d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens assert(token.type == '('); 301d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 302d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens args->push_back(MacroArg()); 303d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens for (int openParens = 1; openParens != 0; ) 304d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 305d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens getToken(&token); 306d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 307d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (token.type == Token::LAST) 308d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 309d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION, 310d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens identifier.location, identifier.text); 311d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // Do not lose EOF token. 312d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens ungetToken(token); 313d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens return false; 314d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 315d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 316d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens bool isArg = false; // True if token is part of the current argument. 317d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens switch (token.type) 318d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 319d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens case '(': 320d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens ++openParens; 321d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens isArg = true; 322d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 323d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens case ')': 324d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens --openParens; 325d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens isArg = openParens != 0; 326d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 327d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens case ',': 328d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // The individual arguments are separated by comma tokens, but 329d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // the comma tokens between matching inner parentheses do not 330d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // seperate arguments. 331d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (openParens == 1) args->push_back(MacroArg()); 332d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens isArg = openParens != 1; 333d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 334d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens default: 335d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens isArg = true; 336d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens break; 337d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 338d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (isArg) 339d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 340d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens MacroArg& arg = args->back(); 341d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // Initial whitespace is not part of the argument. 342d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (arg.empty()) token.setHasLeadingSpace(false); 343d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens arg.push_back(token); 344d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 345d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 346d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 347d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens const Macro::Parameters& params = macro.parameters; 348d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // If there is only one empty argument, it is equivalent to no argument. 349d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (params.empty() && (args->size() == 1) && args->front().empty()) 350d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 351d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens args->clear(); 352d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 353d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // Validate the number of arguments. 354d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (args->size() != params.size()) 355d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 356d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens Diagnostics::ID id = args->size() < macro.parameters.size() ? 357d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens Diagnostics::MACRO_TOO_FEW_ARGS : 358d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens Diagnostics::MACRO_TOO_MANY_ARGS; 359d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens mDiagnostics->report(id, identifier.location, identifier.text); 360d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens return false; 361d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 362d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 363d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // Pre-expand each argument before substitution. 364d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // This step expands each argument individually before they are 365d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // inserted into the macro body. 366d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens for (size_t i = 0; i < args->size(); ++i) 367d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 368d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens MacroArg& arg = args->at(i); 369d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens TokenLexer lexer(&arg); 370d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined); 371d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 372d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens arg.clear(); 373d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens expander.lex(&token); 374d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens while (token.type != Token::LAST) 375d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 376d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens arg.push_back(token); 377d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens expander.lex(&token); 378d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 379d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 380d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens return true; 381d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 382d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 383d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capensvoid MacroExpander::replaceMacroParams(const Macro& macro, 384d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens const std::vector<MacroArg>& args, 385d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens std::vector<Token>* replacements) 386d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens{ 387d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens for (size_t i = 0; i < macro.replacements.size(); ++i) 388d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 389d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens const Token& repl = macro.replacements[i]; 390d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (repl.type != Token::IDENTIFIER) 391d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 392d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens replacements->push_back(repl); 393d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens continue; 394d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 395d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 396d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // TODO(alokp): Optimize this. 397d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // There is no need to search for macro params every time. 398d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // The param index can be cached with the replacement token. 399d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens Macro::Parameters::const_iterator iter = std::find( 400d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens macro.parameters.begin(), macro.parameters.end(), repl.text); 401d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (iter == macro.parameters.end()) 402d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 403d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens replacements->push_back(repl); 404d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens continue; 405d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 406d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 407d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens size_t iArg = std::distance(macro.parameters.begin(), iter); 408d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens const MacroArg& arg = args[iArg]; 409d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens if (arg.empty()) 410d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens { 411d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens continue; 412d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 413d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens size_t iRepl = replacements->size(); 414d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens replacements->insert(replacements->end(), arg.begin(), arg.end()); 415d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // The replacement token inherits padding properties from 416d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens // macro replacement token. 417d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens replacements->at(iRepl).setHasLeadingSpace(repl.hasLeadingSpace()); 418d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens } 419d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} 420d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 421d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens} // namespace pp 422d999309b36cb3dceadd38217b322f0e96a06b202Nicolas Capens 423