1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Preprocessor.h"
16 
17 #include <cassert>
18 
19 #include "DiagnosticsBase.h"
20 #include "DirectiveParser.h"
21 #include "Macro.h"
22 #include "MacroExpander.h"
23 #include "Token.h"
24 #include "Tokenizer.h"
25 
26 namespace pp
27 {
28 
29 struct PreprocessorImpl
30 {
31 	Diagnostics *diagnostics;
32 	MacroSet macroSet;
33 	Tokenizer tokenizer;
34 	DirectiveParser directiveParser;
35 	MacroExpander macroExpander;
36 
PreprocessorImplpp::PreprocessorImpl37 	PreprocessorImpl(Diagnostics *diag,
38 	                 DirectiveHandler *directiveHandler,
39 	                 const PreprocessorSettings &settings)
40 	    : diagnostics(diag),
41 	      tokenizer(diag),
42 	      directiveParser(&tokenizer, &macroSet, diag, directiveHandler,  settings.maxMacroExpansionDepth),
43 	      macroExpander(&directiveParser, &macroSet, diag, false, settings.maxMacroExpansionDepth)
44 	{
45 	}
46 };
47 
Preprocessor(Diagnostics * diagnostics,DirectiveHandler * directiveHandler,const PreprocessorSettings & settings)48 Preprocessor::Preprocessor(Diagnostics *diagnostics,
49                            DirectiveHandler *directiveHandler,
50                            const PreprocessorSettings &settings)
51 {
52 	mImpl = new PreprocessorImpl(diagnostics, directiveHandler, settings);
53 }
54 
~Preprocessor()55 Preprocessor::~Preprocessor()
56 {
57 	delete mImpl;
58 }
59 
init(size_t count,const char * const string[],const int length[])60 bool Preprocessor::init(size_t count, const char *const string[], const int length[])
61 {
62 	static const int kDefaultGLSLVersion = 100;
63 
64 	// Add standard pre-defined macros.
65 	predefineMacro("__LINE__", 0);
66 	predefineMacro("__FILE__", 0);
67 	predefineMacro("__VERSION__", kDefaultGLSLVersion);
68 	predefineMacro("GL_ES", 1);
69 
70 	return mImpl->tokenizer.init(count, string, length);
71 }
72 
predefineMacro(const char * name,int value)73 void Preprocessor::predefineMacro(const char *name, int value)
74 {
75 	PredefineMacro(&mImpl->macroSet, name, value);
76 }
77 
lex(Token * token)78 void Preprocessor::lex(Token *token)
79 {
80 	bool validToken = false;
81 	while (!validToken)
82 	{
83 		mImpl->macroExpander.lex(token);
84 		switch (token->type)
85 		{
86 		// We should not be returning internal preprocessing tokens.
87 		// Convert preprocessing tokens to compiler tokens or report
88 		// diagnostics.
89 		case Token::PP_HASH:
90 			assert(false);
91 			break;
92 		case Token::PP_NUMBER:
93 			mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER,
94 			                           token->location, token->text);
95 			break;
96 		case Token::PP_OTHER:
97 			mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER,
98 			                           token->location, token->text);
99 			break;
100 		default:
101 			validToken = true;
102 			break;
103 		}
104 	}
105 }
106 
setMaxTokenSize(size_t maxTokenSize)107 void Preprocessor::setMaxTokenSize(size_t maxTokenSize)
108 {
109 	mImpl->tokenizer.setMaxTokenSize(maxTokenSize);
110 }
111 
112 }  // namespace pp
113