30#define __attribute__(X)
39extern int maximumLogLevel;
42extern bool enableLoggingGlobally;
43extern bool enableLoggingInContext;
46int fileLogLevel(
const char *file);
47std::ostream &fileLogOutput(
const char *file);
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);
60 mutable lock_t *lock =
nullptr;
65 static void indent(std::ostream &out);
68void addInvalidateCallback(
void (*)(
void));
69std::ostream &clearPrefix(std::ostream &out);
72inline std::ostream &endl(std::ostream &out) {
74 Detail::OutputLogPrefix::indent(out);
77using IndentCtl::indent;
79using IndentCtl::unindent;
81inline bool fileLogLevelIsAtLeast(
const char *file,
int level) {
84 if (Detail::maximumLogLevel < level) {
88 return Detail::fileLogLevel(file) >= level;
92void addDebugSpec(
const char *spec);
94inline bool verbose() {
return Detail::verbosity > 0; }
95inline int verbosity() {
return Detail::verbosity; }
96inline bool enableLogging() {
97 return Detail::enableLoggingGlobally || Detail::enableLoggingInContext;
99void increaseVerbosity();
103#ifndef MAX_LOGGING_LEVEL
105#define MAX_LOGGING_LEVEL 10
110 ((N) <= MAX_LOGGING_LEVEL && ::Log::fileLogLevelIsAtLeast(__FILE__, N) && \
111 ::Log::enableLogging())
113 (LOGGING(N) ? ::Log::Detail::fileLogOutput(__FILE__) \
114 << ::Log::Detail::OutputLogPrefix(__FILE__, N) << X \
115 << ::Log::Detail::clearPrefix << std::endl \
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)
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)
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 \
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))
150static inline std::ostream &operator<<(std::ostream &out,
151 std::function<std::ostream &(std::ostream &)> fn) {
156inline auto operator<<(std::ostream &out,
const T &obj) ->
decltype((void)obj.dbprint(out), out) {
162inline auto operator<<(std::ostream &out,
const T *obj) ->
decltype((void)obj->dbprint(out), out) {
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;
180 elems.emplace_back(tmp.str());
181 if (!foundnl) foundnl = elems.back().find(
'\n') != std::string::npos;
184 for (
auto &el : elems) {
185 out << Log::endl << Log::indent;
186 for (
auto &ch : el) {
192 out << Log::unindent;
195 const char *sep =
" ";
197 for (
auto &el : elems) {
201 out << (sep + 1) << rbrace;
208std::ostream &operator<<(std::ostream &out,
const std::vector<T> &vec) {
209 return format_container(out, vec,
'[',
']');
213std::ostream &operator<<(std::ostream &out,
const std::set<T> &set) {
214 return format_container(out, set,
'(',
')');