31#define __attribute__(X)
40extern int maximumLogLevel;
43extern bool enableLoggingGlobally;
44extern bool enableLoggingInContext;
47int fileLogLevel(
const char *file);
48std::ostream &fileLogOutput(
const char *file);
55 static int ostream_xalloc;
56 static void setup_ostream_xalloc(std::ostream &);
57 friend std::ostream &operator<<(std::ostream &,
const OutputLogPrefix &);
58 friend std::ostream &clearPrefix(std::ostream &out);
61 mutable lock_t *lock =
nullptr;
66 static void indent(std::ostream &out);
69void addInvalidateCallback(
void (*)(
void));
70std::ostream &clearPrefix(std::ostream &out);
73inline std::ostream &endl(std::ostream &out) {
75 Detail::OutputLogPrefix::indent(out);
78using IndentCtl::indent;
80using IndentCtl::unindent;
82inline bool fileLogLevelIsAtLeast(
const char *file,
int level) {
85 if (Detail::maximumLogLevel < level) {
89 return Detail::fileLogLevel(file) >= level;
93void addDebugSpec(
const char *spec);
95inline bool verbose() {
return Detail::verbosity > 0; }
96inline int verbosity() {
return Detail::verbosity; }
97inline bool enableLogging() {
98 return Detail::enableLoggingGlobally || Detail::enableLoggingInContext;
100void increaseVerbosity();
104#ifndef MAX_LOGGING_LEVEL
106#define MAX_LOGGING_LEVEL 10
111 ((N) <= MAX_LOGGING_LEVEL && ::Log::fileLogLevelIsAtLeast(__FILE__, N) && \
112 ::Log::enableLogging())
114 (LOGGING(N) ? ::Log::Detail::fileLogOutput(__FILE__) \
115 << ::Log::Detail::OutputLogPrefix(__FILE__, N) << X \
116 << ::Log::Detail::clearPrefix << std::endl \
118#define LOG1(X) LOGN(1, X)
119#define LOG2(X) LOGN(2, X)
120#define LOG3(X) LOGN(3, X)
121#define LOG4(X) LOGN(4, X)
122#define LOG5(X) LOGN(5, X)
123#define LOG6(X) LOGN(6, X)
124#define LOG7(X) LOGN(7, X)
125#define LOG8(X) LOGN(8, X)
126#define LOG9(X) LOGN(9, X)
128#define LOGN_UNINDENT(N) \
129 (LOGGING(N) ? ::Log::Detail::fileLogOutput(__FILE__) << IndentCtl::unindent : std::clog)
130#define LOG1_UNINDENT LOGN_UNINDENT(1)
131#define LOG2_UNINDENT LOGN_UNINDENT(2)
132#define LOG3_UNINDENT LOGN_UNINDENT(3)
133#define LOG4_UNINDENT LOGN_UNINDENT(4)
134#define LOG5_UNINDENT LOGN_UNINDENT(5)
135#define LOG6_UNINDENT LOGN_UNINDENT(6)
136#define LOG7_UNINDENT LOGN_UNINDENT(7)
137#define LOG8_UNINDENT LOGN_UNINDENT(8)
138#define LOG9_UNINDENT LOGN_UNINDENT(9)
140#define LOG_FEATURE(TAG, N, X) \
141 ((N) <= MAX_LOGGING_LEVEL && ::Log::fileLogLevelIsAtLeast(TAG, N) \
142 ? ::Log::Detail::fileLogOutput(TAG) \
143 << ::Log::Detail::OutputLogPrefix(TAG, N) << X << std::endl \
146#define P4C_ERROR(X) (std::clog << "ERROR: " << X << std::endl)
147#define P4C_WARNING(X) (::Log::verbose() ? std::clog << "WARNING: " << X << std::endl : std::clog)
148#define ERRWARN(C, X) ((C) ? P4C_ERROR(X) : P4C_WARNING(X))
151static inline std::ostream &operator<<(std::ostream &out,
152 std::function<std::ostream &(std::ostream &)> fn) {
160std::ostream &format_container(std::ostream &out,
const Cont &container,
char lbrace,
char rbrace) {
161 std::vector<std::string> elems;
162 bool foundnl =
false;
163 for (
auto &el : container) {
164 std::stringstream tmp;
166 elems.emplace_back(tmp.str());
167 if (!foundnl) foundnl = elems.back().find(
'\n') != std::string::npos;
170 for (
auto &el : elems) {
171 out << Log::endl << Log::indent;
172 for (
auto &ch : el) {
178 out << Log::unindent;
181 const char *sep =
" ";
183 for (
auto &el : elems) {
187 out << (sep + 1) << rbrace;
194std::ostream &operator<<(std::ostream &out,
const std::vector<T> &vec) {
195 return format_container(out, vec,
'[',
']');
199std::ostream &operator<<(std::ostream &out,
const std::set<T> &set) {
200 return format_container(out, set,
'(',
')');