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 #include <sstream>
19
20 #include "Diagnostics.h"
21 #include "DirectiveParser.h"
22 #include "Macro.h"
23 #include "MacroExpander.h"
24 #include "Token.h"
25 #include "Tokenizer.h"
26
27 namespace pp
28 {
29
30 struct PreprocessorImpl
31 {
32 Diagnostics* diagnostics;
33 MacroSet macroSet;
34 Tokenizer tokenizer;
35 DirectiveParser directiveParser;
36 MacroExpander macroExpander;
37
PreprocessorImplpp::PreprocessorImpl38 PreprocessorImpl(Diagnostics* diag, DirectiveHandler* directiveHandler) :
39 diagnostics(diag),
40 tokenizer(diag),
41 directiveParser(&tokenizer, ¯oSet, diag, directiveHandler),
42 macroExpander(&directiveParser, ¯oSet, diag, false)
43 {
44 }
45 };
46
Preprocessor(Diagnostics * diagnostics,DirectiveHandler * directiveHandler)47 Preprocessor::Preprocessor(Diagnostics* diagnostics,
48 DirectiveHandler* directiveHandler)
49 {
50 mImpl = new PreprocessorImpl(diagnostics, directiveHandler);
51 }
52
~Preprocessor()53 Preprocessor::~Preprocessor()
54 {
55 delete mImpl;
56 }
57
init(int count,const char * const string[],const int length[])58 bool Preprocessor::init(int count,
59 const char* const string[],
60 const int length[])
61 {
62 static const int kGLSLVersion = 100;
63
64 // Add standard pre-defined macros.
65 predefineMacro("__LINE__", 0);
66 predefineMacro("__FILE__", 0);
67 predefineMacro("__VERSION__", kGLSLVersion);
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 std::ostringstream stream;
76 stream << value;
77
78 Token token;
79 token.type = Token::CONST_INT;
80 token.text = stream.str();
81
82 Macro macro;
83 macro.predefined = true;
84 macro.type = Macro::kTypeObj;
85 macro.name = name;
86 macro.replacements.push_back(token);
87
88 mImpl->macroSet[name] = macro;
89 }
90
lex(Token * token)91 void Preprocessor::lex(Token* token)
92 {
93 bool validToken = false;
94 while (!validToken)
95 {
96 mImpl->macroExpander.lex(token);
97 switch (token->type)
98 {
99 // We should not be returning internal preprocessing tokens.
100 // Convert preprocessing tokens to compiler tokens or report
101 // diagnostics.
102 case Token::PP_HASH:
103 assert(false);
104 break;
105 case Token::CONST_INT:
106 {
107 int val = 0;
108 if (!token->iValue(&val))
109 {
110 // Do not mark the token as invalid.
111 // Just emit the diagnostic and reset value to 0.
112 mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
113 token->location, token->text);
114 token->text.assign("0");
115 }
116 validToken = true;
117 break;
118 }
119 case Token::CONST_FLOAT:
120 {
121 float val = 0;
122 if (!token->fValue(&val))
123 {
124 // Do not mark the token as invalid.
125 // Just emit the diagnostic and reset value to 0.0.
126 mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
127 token->location, token->text);
128 token->text.assign("0.0");
129 }
130 validToken = true;
131 break;
132 }
133 case Token::PP_NUMBER:
134 mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
135 token->location, token->text);
136 break;
137 case Token::PP_OTHER:
138 mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER,
139 token->location, token->text);
140 break;
141 default:
142 validToken = true;
143 break;
144 }
145 }
146 }
147
148 } // namespace pp
149
150