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 = &macro;
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