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