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 38 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 47 Preprocessor::Preprocessor(Diagnostics* diagnostics, 48 DirectiveHandler* directiveHandler) 49 { 50 mImpl = new PreprocessorImpl(diagnostics, directiveHandler); 51 } 52 53 Preprocessor::~Preprocessor() 54 { 55 delete mImpl; 56 } 57 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 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 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