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) : debug_(debug), tokens_(tokens) { 41 Init(); 42 } 43 Init()44 void Init() { 45 if (loc_.GetLine() != -1) { 46 stream_ << "\033[1mLine " << loc_.GetLine() << ": "; 47 } 48 49 if (!debug_) { 50 stream_ << "\033[1;31m"; 51 stream_ << "ERROR: "; 52 stream_ << "\033[0m"; 53 } else { 54 stream_ << "\033[1;m"; 55 stream_ << "DEBUG: "; 56 stream_ << "\033[0m"; 57 } 58 } 59 ~LogMessage()60 ~LogMessage() { 61 if (debug_ && suppress_debug_) return; 62 63 std::cerr << stream_.str() << "\n"; 64 for (const auto& token : tokens_) { 65 // Bold line number 66 std::cerr << "\033[1m"; 67 std::cerr << " Line " << token->GetLocation().GetLine() << ": "; 68 std::cerr << "\033[0m"; 69 std::cerr << token->GetDebugName() << "\n"; 70 } 71 72 if (!debug_) { 73 abort(); 74 } 75 } 76 stream()77 std::ostream& stream() { 78 return stream_; 79 } 80 81 private: 82 std::ostringstream stream_; 83 bool debug_; 84 bool suppress_debug_{true}; 85 ParseLocation loc_; 86 std::vector<const Loggable*> tokens_; 87 }; 88 89 // Error Log stream. Aborts the program after the message is printed. 90 // The arguments to the macro is a list of Loggable objects that are printed when the error is printed. 91 #define ERROR(...) LogMessage(false, {__VA_ARGS__}).stream() 92 93 // ParseLocation error log, the first argument is a location. 94 #define ERRORLOC(_1, ...) LogMessage(_1, {__VA_ARGS__}).stream() 95 96 #define DEBUG(...) LogMessage(true, {__VA_ARGS__}).stream() 97