1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <initializer_list> 20 #include <iostream> 21 #include <sstream> 22 #include <vector> 23 24 #include "parse_location.h" 25 26 class Loggable { 27 public: 28 virtual ~Loggable() = default; 29 virtual std::string GetDebugName() const = 0; 30 virtual ParseLocation GetLocation() const = 0; 31 }; 32 33 class LogMessage { 34 public: LogMessage(ParseLocation loc,std::initializer_list<const Loggable * > tokens)35 LogMessage(ParseLocation loc, std::initializer_list<const Loggable*> tokens) 36 : debug_(false), loc_(loc), tokens_(tokens) { 37 Init(); 38 } 39 LogMessage(bool debug,std::initializer_list<const Loggable * > tokens)40 LogMessage(bool debug, std::initializer_list<const Loggable*> tokens) 41 : debug_(debug), tokens_(tokens) { 42 Init(); 43 } 44 Init()45 void Init() { 46 if (loc_.GetLine() != -1) { 47 stream_ << "\033[1mLine " << loc_.GetLine() << ": "; 48 } 49 50 if (!debug_) { 51 stream_ << "\033[1;31m"; 52 stream_ << "ERROR: "; 53 stream_ << "\033[0m"; 54 } else { 55 stream_ << "\033[1;m"; 56 stream_ << "DEBUG: "; 57 stream_ << "\033[0m"; 58 } 59 } 60 ~LogMessage()61 ~LogMessage() { 62 if (debug_ && suppress_debug_) { 63 return; 64 } 65 66 std::cerr << stream_.str() << "\n"; 67 for (const auto& token : tokens_) { 68 // Bold line number 69 std::cerr << "\033[1m"; 70 std::cerr << " Line " << token->GetLocation().GetLine() << ": "; 71 std::cerr << "\033[0m"; 72 std::cerr << token->GetDebugName() << "\n"; 73 } 74 75 if (!debug_) { 76 abort(); 77 } 78 } 79 stream()80 std::ostream& stream() { return stream_; } 81 82 private: 83 std::ostringstream stream_; 84 bool debug_; 85 bool suppress_debug_{true}; 86 ParseLocation loc_; 87 std::vector<const Loggable*> tokens_; 88 }; 89 90 // Error Log stream. Aborts the program after the message is printed. 91 // The arguments to the macro is a list of Loggable objects that are printed when the error is 92 // printed. 93 #define ERROR(...) LogMessage(false, {__VA_ARGS__}).stream() 94 95 // ParseLocation error log, the first argument is a location. 96 #define ERRORLOC(_1, ...) LogMessage(_1, {__VA_ARGS__}).stream() 97 98 #define DEBUG(...) LogMessage(true, {__VA_ARGS__}).stream() 99