P4C
The P4 Compiler
 
Loading...
Searching...
No Matches
log.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef LIB_LOG_H_
18#define LIB_LOG_H_
19
20#include <functional>
21#include <iostream>
22#include <set>
23#include <sstream>
24#include <vector>
25
26#include "config.h"
27#include "indent.h"
28
29#ifndef __GNUC__
30#define __attribute__(X)
31#endif
32
33namespace Log {
34namespace Detail {
35// The global verbosity level.
36extern int verbosity;
37
38// A cache of the maximum log level requested for any file.
39extern int maximumLogLevel;
40
41// Used to restrict logging to a specific IR context.
42extern bool enableLoggingGlobally;
43extern bool enableLoggingInContext; // if enableLoggingGlobally is true, this is ignored.
44
45// Look up the log level of @file.
46int fileLogLevel(const char *file);
47std::ostream &fileLogOutput(const char *file);
48
49// A utility class used to prepend file and log level information to logging output.
50// also controls indent control and locking for multithreaded use
52 const char *fn;
53 int level;
54 static int ostream_xalloc;
55 static void setup_ostream_xalloc(std::ostream &);
56 friend std::ostream &operator<<(std::ostream &, const OutputLogPrefix &);
57 friend std::ostream &clearPrefix(std::ostream &out);
58#ifdef MULTITHREAD
59 struct lock_t;
60 mutable lock_t *lock = nullptr;
61#endif // MULTITHREAD
62 public:
63 OutputLogPrefix(const char *f, int l) : fn(f), level(l) {}
65 static void indent(std::ostream &out);
66};
67
68void addInvalidateCallback(void (*)(void));
69std::ostream &clearPrefix(std::ostream &out);
70} // namespace Detail
71
72inline std::ostream &endl(std::ostream &out) {
73 out << std::endl;
74 Detail::OutputLogPrefix::indent(out);
75 return out;
76}
77using IndentCtl::indent;
79using IndentCtl::unindent;
80
81inline bool fileLogLevelIsAtLeast(const char *file, int level) {
82 // If there's no file with a log level of at least @level, we don't need to do
83 // the more expensive per-file check.
84 if (Detail::maximumLogLevel < level) {
85 return false;
86 }
87
88 return Detail::fileLogLevel(file) >= level;
89}
90
91// Process @spec and update the log level requested for the appropriate file.
92void addDebugSpec(const char *spec);
93
94inline bool verbose() { return Detail::verbosity > 0; }
95inline int verbosity() { return Detail::verbosity; }
96inline bool enableLogging() {
97 return Detail::enableLoggingGlobally || Detail::enableLoggingInContext;
98}
99void increaseVerbosity();
100
101} // namespace Log
102
103#ifndef MAX_LOGGING_LEVEL
104// can be set on build command line and disables higher logging levels at compile time
105#define MAX_LOGGING_LEVEL 10
106#endif
107
108// NOLINTBEGIN(bugprone-macro-parentheses)
109#define LOGGING(N) \
110 ((N) <= MAX_LOGGING_LEVEL && ::Log::fileLogLevelIsAtLeast(__FILE__, N) && \
111 ::Log::enableLogging())
112#define LOGN(N, X) \
113 (LOGGING(N) ? ::Log::Detail::fileLogOutput(__FILE__) \
114 << ::Log::Detail::OutputLogPrefix(__FILE__, N) << X \
115 << ::Log::Detail::clearPrefix << std::endl \
116 : std::clog)
117#define LOG1(X) LOGN(1, X)
118#define LOG2(X) LOGN(2, X)
119#define LOG3(X) LOGN(3, X)
120#define LOG4(X) LOGN(4, X)
121#define LOG5(X) LOGN(5, X)
122#define LOG6(X) LOGN(6, X)
123#define LOG7(X) LOGN(7, X)
124#define LOG8(X) LOGN(8, X)
125#define LOG9(X) LOGN(9, X)
126
127#define LOGN_UNINDENT(N) \
128 (LOGGING(N) ? ::Log::Detail::fileLogOutput(__FILE__) << IndentCtl::unindent : std::clog)
129#define LOG1_UNINDENT LOGN_UNINDENT(1)
130#define LOG2_UNINDENT LOGN_UNINDENT(2)
131#define LOG3_UNINDENT LOGN_UNINDENT(3)
132#define LOG4_UNINDENT LOGN_UNINDENT(4)
133#define LOG5_UNINDENT LOGN_UNINDENT(5)
134#define LOG6_UNINDENT LOGN_UNINDENT(6)
135#define LOG7_UNINDENT LOGN_UNINDENT(7)
136#define LOG8_UNINDENT LOGN_UNINDENT(8)
137#define LOG9_UNINDENT LOGN_UNINDENT(9)
138
139#define LOG_FEATURE(TAG, N, X) \
140 ((N) <= MAX_LOGGING_LEVEL && ::Log::fileLogLevelIsAtLeast(TAG, N) \
141 ? ::Log::Detail::fileLogOutput(TAG) \
142 << ::Log::Detail::OutputLogPrefix(TAG, N) << X << std::endl \
143 : std::clog)
144
145#define P4C_ERROR(X) (std::clog << "ERROR: " << X << std::endl)
146#define P4C_WARNING(X) (::Log::verbose() ? std::clog << "WARNING: " << X << std::endl : std::clog)
147#define ERRWARN(C, X) ((C) ? P4C_ERROR(X) : P4C_WARNING(X))
148// NOLINTEND(bugprone-macro-parentheses)
149
150static inline std::ostream &operator<<(std::ostream &out,
151 std::function<std::ostream &(std::ostream &)> fn) {
152 return fn(out);
153}
154
155template <class T>
156inline auto operator<<(std::ostream &out, const T &obj) -> decltype((void)obj.dbprint(out), out) {
157 obj.dbprint(out);
158 return out;
159}
160
161template <class T>
162inline auto operator<<(std::ostream &out, const T *obj) -> decltype((void)obj->dbprint(out), out) {
163 if (obj)
164 obj->dbprint(out);
165 else
166 out << "<null>";
167 return out;
168}
169
173template <class Cont>
174std::ostream &format_container(std::ostream &out, const Cont &container, char lbrace, char rbrace) {
175 std::vector<std::string> elems;
176 bool foundnl = false;
177 for (auto &el : container) {
178 std::stringstream tmp;
179 tmp << el;
180 elems.emplace_back(tmp.str());
181 if (!foundnl) foundnl = elems.back().find('\n') != std::string::npos;
182 }
183 if (foundnl) {
184 for (auto &el : elems) {
185 out << Log::endl << Log::indent;
186 for (auto &ch : el) {
187 if (ch == '\n')
188 out << Log::endl;
189 else
190 out << ch;
191 }
192 out << Log::unindent;
193 }
194 } else {
195 const char *sep = " ";
196 out << lbrace;
197 for (auto &el : elems) {
198 out << sep << el;
199 sep = ", ";
200 }
201 out << (sep + 1) << rbrace;
202 }
203
204 return out;
205}
206
207template <class T>
208std::ostream &operator<<(std::ostream &out, const std::vector<T> &vec) {
209 return format_container(out, vec, '[', ']');
210}
211
212template <class T>
213std::ostream &operator<<(std::ostream &out, const std::set<T> &set) {
214 return format_container(out, set, '(', ')');
215}
216
217#endif /* LIB_LOG_H_ */
Definition indent.h:89
Definition log.h:51