Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // |
michael@0 | 2 | // Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. |
michael@0 | 3 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 4 | // found in the LICENSE file. |
michael@0 | 5 | // |
michael@0 | 6 | |
michael@0 | 7 | #include "Preprocessor.h" |
michael@0 | 8 | |
michael@0 | 9 | #include <cassert> |
michael@0 | 10 | #include <sstream> |
michael@0 | 11 | |
michael@0 | 12 | #include "DiagnosticsBase.h" |
michael@0 | 13 | #include "DirectiveParser.h" |
michael@0 | 14 | #include "Macro.h" |
michael@0 | 15 | #include "MacroExpander.h" |
michael@0 | 16 | #include "Token.h" |
michael@0 | 17 | #include "Tokenizer.h" |
michael@0 | 18 | |
michael@0 | 19 | namespace pp |
michael@0 | 20 | { |
michael@0 | 21 | |
michael@0 | 22 | struct PreprocessorImpl |
michael@0 | 23 | { |
michael@0 | 24 | Diagnostics* diagnostics; |
michael@0 | 25 | MacroSet macroSet; |
michael@0 | 26 | Tokenizer tokenizer; |
michael@0 | 27 | DirectiveParser directiveParser; |
michael@0 | 28 | MacroExpander macroExpander; |
michael@0 | 29 | |
michael@0 | 30 | PreprocessorImpl(Diagnostics* diag, |
michael@0 | 31 | DirectiveHandler* directiveHandler) : |
michael@0 | 32 | diagnostics(diag), |
michael@0 | 33 | tokenizer(diag), |
michael@0 | 34 | directiveParser(&tokenizer, ¯oSet, diag, directiveHandler), |
michael@0 | 35 | macroExpander(&directiveParser, ¯oSet, diag) |
michael@0 | 36 | { |
michael@0 | 37 | } |
michael@0 | 38 | }; |
michael@0 | 39 | |
michael@0 | 40 | Preprocessor::Preprocessor(Diagnostics* diagnostics, |
michael@0 | 41 | DirectiveHandler* directiveHandler) |
michael@0 | 42 | { |
michael@0 | 43 | mImpl = new PreprocessorImpl(diagnostics, directiveHandler); |
michael@0 | 44 | } |
michael@0 | 45 | |
michael@0 | 46 | Preprocessor::~Preprocessor() |
michael@0 | 47 | { |
michael@0 | 48 | delete mImpl; |
michael@0 | 49 | } |
michael@0 | 50 | |
michael@0 | 51 | bool Preprocessor::init(size_t count, |
michael@0 | 52 | const char* const string[], |
michael@0 | 53 | const int length[]) |
michael@0 | 54 | { |
michael@0 | 55 | static const int kGLSLVersion = 100; |
michael@0 | 56 | |
michael@0 | 57 | // Add standard pre-defined macros. |
michael@0 | 58 | predefineMacro("__LINE__", 0); |
michael@0 | 59 | predefineMacro("__FILE__", 0); |
michael@0 | 60 | predefineMacro("__VERSION__", kGLSLVersion); |
michael@0 | 61 | predefineMacro("GL_ES", 1); |
michael@0 | 62 | |
michael@0 | 63 | return mImpl->tokenizer.init(count, string, length); |
michael@0 | 64 | } |
michael@0 | 65 | |
michael@0 | 66 | void Preprocessor::predefineMacro(const char* name, int value) |
michael@0 | 67 | { |
michael@0 | 68 | std::ostringstream stream; |
michael@0 | 69 | stream << value; |
michael@0 | 70 | |
michael@0 | 71 | Token token; |
michael@0 | 72 | token.type = Token::CONST_INT; |
michael@0 | 73 | token.text = stream.str(); |
michael@0 | 74 | |
michael@0 | 75 | Macro macro; |
michael@0 | 76 | macro.predefined = true; |
michael@0 | 77 | macro.type = Macro::kTypeObj; |
michael@0 | 78 | macro.name = name; |
michael@0 | 79 | macro.replacements.push_back(token); |
michael@0 | 80 | |
michael@0 | 81 | mImpl->macroSet[name] = macro; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | void Preprocessor::lex(Token* token) |
michael@0 | 85 | { |
michael@0 | 86 | bool validToken = false; |
michael@0 | 87 | while (!validToken) |
michael@0 | 88 | { |
michael@0 | 89 | mImpl->macroExpander.lex(token); |
michael@0 | 90 | switch (token->type) |
michael@0 | 91 | { |
michael@0 | 92 | // We should not be returning internal preprocessing tokens. |
michael@0 | 93 | // Convert preprocessing tokens to compiler tokens or report |
michael@0 | 94 | // diagnostics. |
michael@0 | 95 | case Token::PP_HASH: |
michael@0 | 96 | assert(false); |
michael@0 | 97 | break; |
michael@0 | 98 | case Token::CONST_INT: |
michael@0 | 99 | { |
michael@0 | 100 | int val = 0; |
michael@0 | 101 | if (!token->iValue(&val)) |
michael@0 | 102 | { |
michael@0 | 103 | // Do not mark the token as invalid. |
michael@0 | 104 | // Just emit the diagnostic and reset value to 0. |
michael@0 | 105 | mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW, |
michael@0 | 106 | token->location, token->text); |
michael@0 | 107 | token->text.assign("0"); |
michael@0 | 108 | } |
michael@0 | 109 | validToken = true; |
michael@0 | 110 | break; |
michael@0 | 111 | } |
michael@0 | 112 | case Token::CONST_FLOAT: |
michael@0 | 113 | { |
michael@0 | 114 | float val = 0; |
michael@0 | 115 | if (!token->fValue(&val)) |
michael@0 | 116 | { |
michael@0 | 117 | // Do not mark the token as invalid. |
michael@0 | 118 | // Just emit the diagnostic and reset value to 0.0. |
michael@0 | 119 | mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW, |
michael@0 | 120 | token->location, token->text); |
michael@0 | 121 | token->text.assign("0.0"); |
michael@0 | 122 | } |
michael@0 | 123 | validToken = true; |
michael@0 | 124 | break; |
michael@0 | 125 | } |
michael@0 | 126 | case Token::PP_NUMBER: |
michael@0 | 127 | mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER, |
michael@0 | 128 | token->location, token->text); |
michael@0 | 129 | break; |
michael@0 | 130 | case Token::PP_OTHER: |
michael@0 | 131 | mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER, |
michael@0 | 132 | token->location, token->text); |
michael@0 | 133 | break; |
michael@0 | 134 | default: |
michael@0 | 135 | validToken = true; |
michael@0 | 136 | break; |
michael@0 | 137 | } |
michael@0 | 138 | } |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | } // namespace pp |
michael@0 | 142 |