• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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