blob: 6de118bd89b9ed512164f8a5dce5704fb1a41464 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef AOS_COMMON_LOGGING_LOGGING_H_
brians343bc112013-02-10 01:53:46 +00002#define AOS_COMMON_LOGGING_LOGGING_H_
3
Brian Silvermanf665d692013-02-17 22:11:39 -08004// This file contains the logging client interface. It works with both C and C++
5// code.
6
7#include <stdio.h>
brians343bc112013-02-10 01:53:46 +00008#include <stdint.h>
Brian Silvermanb067abf2013-09-13 22:01:06 -07009#include <stdlib.h>
brians343bc112013-02-10 01:53:46 +000010
Brian Silvermanc2f62fa2013-03-08 15:55:43 -080011#ifdef __VXWORKS__
12// Because the vxworks system headers miss the noreturn...
Brian Silverman5202b9c2013-03-16 20:07:54 -070013extern "C" void abort(void) __attribute__((noreturn));
Brian Silvermanc2f62fa2013-03-08 15:55:43 -080014#endif
15
brians343bc112013-02-10 01:53:46 +000016#ifdef __cplusplus
17extern "C" {
18#endif
19
20typedef uint8_t log_level;
Brian Silvermanf665d692013-02-17 22:11:39 -080021
brians343bc112013-02-10 01:53:46 +000022#define DECL_LEVELS \
23DECL_LEVEL(DEBUG, 0); /* stuff that gets printed out every cycle */ \
24DECL_LEVEL(INFO, 1); /* things like PosEdge/NegEdge */ \
Brian Silvermanf665d692013-02-17 22:11:39 -080025/* things that might still work if they happen occasionally */ \
brians343bc112013-02-10 01:53:46 +000026DECL_LEVEL(WARNING, 2); \
27/*-1 so that vxworks macro of same name will have same effect if used*/ \
28DECL_LEVEL(ERROR, -1); /* errors */ \
Brian Silvermanf665d692013-02-17 22:11:39 -080029/* serious errors. the logging code will terminate the process/task */ \
30DECL_LEVEL(FATAL, 4); \
brians343bc112013-02-10 01:53:46 +000031DECL_LEVEL(LOG_UNKNOWN, 5); /* unknown logging level */
Brian Silvermanf665d692013-02-17 22:11:39 -080032#define DECL_LEVEL(name, value) static const log_level name = value;
brians343bc112013-02-10 01:53:46 +000033#undef ERROR
Brian Silvermanf665d692013-02-17 22:11:39 -080034DECL_LEVELS;
brians343bc112013-02-10 01:53:46 +000035#undef DECL_LEVEL
36
37#define STRINGIFY(x) TO_STRING(x)
38#define TO_STRING(x) #x
39
40//not static const size_t for c code
Brian Silvermanc11f3b72013-03-19 18:32:02 -070041#define LOG_MESSAGE_LEN 400
Brian Silvermanf665d692013-02-17 22:11:39 -080042
43#ifdef __VXWORKS__
44// We're using ancient glibc, so sticking to just what the syscall can handle is
45// probably safer.
46#define LOG_PRINTF_FORMAT_TYPE printf
47#else
48#define LOG_PRINTF_FORMAT_TYPE gnu_printf
49#endif
50#ifdef __cplusplus
51extern "C" {
52#endif
53// Actually implements the basic logging call.
54// Does not check that level is valid.
55void log_do(log_level level, const char *format, ...)
56 __attribute__((format(LOG_PRINTF_FORMAT_TYPE, 2, 3)));
57
58void log_cork(int line, const char *function, const char *format, ...)
59 __attribute__((format(LOG_PRINTF_FORMAT_TYPE, 3, 4)));
60// Implements the uncork logging call.
61void log_uncork(int line, const char *function, log_level level,
62 const char *file, const char *format, ...)
63 __attribute__((format(LOG_PRINTF_FORMAT_TYPE, 5, 6)));
64#ifdef __cplusplus
65}
66#endif
67
68// A magical static const char[] or string literal that communicates the name
69// of the enclosing function.
70// It's currently using __PRETTY_FUNCTION__ because both GCC and Clang support
71// that and it gives nicer results in C++ than the standard __func__ (which
72// would also work).
Brian Silvermanc11f3b72013-03-19 18:32:02 -070073//#define LOG_CURRENT_FUNCTION __PRETTY_FUNCTION__
74#define LOG_CURRENT_FUNCTION __func__
Brian Silvermanf665d692013-02-17 22:11:39 -080075
Brian Silverman8fc7bc92013-03-13 23:15:47 -070076#undef LOG_SOURCENAME
77#define LOG_SOURCENAME __FILE__
78
Brian Silvermanf665d692013-02-17 22:11:39 -080079// The basic logging call.
80#define LOG(level, format, args...) do {\
81 log_do(level, LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": %s: " format, \
82 LOG_CURRENT_FUNCTION, ##args); \
83 /* so that GCC knows that it won't return */ \
84 if (level == FATAL) { \
85 fprintf(stderr, "log_do(FATAL) fell through!!!!!\n"); \
86 printf("see stderr\n"); \
87 abort(); \
88 } \
89} while (0)
brians343bc112013-02-10 01:53:46 +000090
91// Allows format to not be a string constant.
Brian Silvermanf665d692013-02-17 22:11:39 -080092#define LOG_DYNAMIC(level, format, args...) do { \
brians343bc112013-02-10 01:53:46 +000093 static char log_buf[LOG_MESSAGE_LEN]; \
94 int ret = snprintf(log_buf, sizeof(log_buf), format, ##args); \
Brian Silvermanf665d692013-02-17 22:11:39 -080095 if (ret < 0 || (uintmax_t)ret >= LOG_MESSAGE_LEN) { \
96 LOG(ERROR, "next message was too long so not subbing in args\n"); \
brians343bc112013-02-10 01:53:46 +000097 LOG(level, "%s", format); \
98 }else{ \
99 LOG(level, "%s", log_buf); \
100 } \
Brian Silvermanf665d692013-02-17 22:11:39 -0800101} while (0)
brians343bc112013-02-10 01:53:46 +0000102
Brian Silvermanf665d692013-02-17 22:11:39 -0800103// Allows "bottling up" multiple log fragments which can then all be logged in
104// one message with LOG_UNCORK.
105// Calls from a given thread/task will be grouped together.
106#define LOG_CORK(format, args...) do { \
107 log_cork(__LINE__, LOG_CURRENT_FUNCTION, format, ##args); \
108} while (0)
109// Actually logs all of the saved up log fragments (including format and args on
110// the end).
111#define LOG_UNCORK(level, format, args...) do { \
112 log_uncork(__LINE__, LOG_CURRENT_FUNCTION, level, LOG_SOURCENAME, \
113 format, ##args); \
114} while (0)
brians343bc112013-02-10 01:53:46 +0000115
brians343bc112013-02-10 01:53:46 +0000116#ifdef __cplusplus
117}
118#endif
119
Brian Silvermanb067abf2013-09-13 22:01:06 -0700120#ifdef __cplusplus
121
122namespace aos {
123
124// CHECK* macros, similar to glog
125// (<http://google-glog.googlecode.com/svn/trunk/doc/glog.html>)'s, except they
126// don't support streaming in extra text. Some of the implementation is borrowed
127// from there too.
128// They all LOG(FATAL) with a helpful message when the check fails.
129// TODO(brians): Replace assert with CHECK
130// Portions copyright (c) 1999, Google Inc.
131// All rights reserved.
132//
133// Redistribution and use in source and binary forms, with or without
134// modification, are permitted provided that the following conditions are
135// met:
136//
137// * Redistributions of source code must retain the above copyright
138// notice, this list of conditions and the following disclaimer.
139// * Redistributions in binary form must reproduce the above
140// copyright notice, this list of conditions and the following disclaimer
141// in the documentation and/or other materials provided with the
142// distribution.
143// * Neither the name of Google Inc. nor the names of its
144// contributors may be used to endorse or promote products derived from
145// this software without specific prior written permission.
146//
147// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
148// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
149// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
150// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
151// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
152// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
153// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
154// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
155// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
156// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
157// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
158
Brian Silverman862b1632013-09-14 15:29:59 -0700159// CHECK dies with a fatal error if condition is not true. It is *not*
160// controlled by NDEBUG, so the check will be executed regardless of
161// compilation mode. Therefore, it is safe to do things like:
162// CHECK(fp->Write(x) == 4)
163#define CHECK(condition) \
164 if (__builtin_expect(!(condition), 0)) { \
Brian Silverman5d790752014-01-01 13:25:36 -0800165 LOG(FATAL, "CHECK(%s) failed\n", #condition); \
Brian Silverman862b1632013-09-14 15:29:59 -0700166 }
167
Brian Silvermanb067abf2013-09-13 22:01:06 -0700168// Helper functions for CHECK_OP macro.
169// The (int, int) specialization works around the issue that the compiler
170// will not instantiate the template version of the function on values of
171// unnamed enum type.
172#define DEFINE_CHECK_OP_IMPL(name, op) \
173 template <typename T1, typename T2> \
174 inline void LogImpl##name(const T1& v1, const T2& v2, \
175 const char* exprtext) { \
176 if (!__builtin_expect(v1 op v2, 1)) { \
177 LOG(FATAL, "CHECK(%s) failed\n", exprtext); \
178 } \
179 } \
180 inline void LogImpl##name(int v1, int v2, const char* exprtext) { \
181 ::aos::LogImpl##name<int, int>(v1, v2, exprtext); \
182 }
183
184// We use the full name Check_EQ, Check_NE, etc. in case the file including
185// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
186// This happens if, for example, those are used as token names in a
187// yacc grammar.
188DEFINE_CHECK_OP_IMPL(Check_EQ, ==) // Compilation error with CHECK_EQ(NULL, x)?
189DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == NULL) instead.
190DEFINE_CHECK_OP_IMPL(Check_LE, <=)
191DEFINE_CHECK_OP_IMPL(Check_LT, < )
192DEFINE_CHECK_OP_IMPL(Check_GE, >=)
193DEFINE_CHECK_OP_IMPL(Check_GT, > )
194
195#define CHECK_OP(name, op, val1, val2) \
196 ::aos::LogImplCheck##name(val1, val2, \
197 STRINGIFY(val1) STRINGIFY(op) STRINGIFY(val2))
198
199#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
200#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
201#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
202#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2)
203#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
204#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2)
205
206// A small helper for CHECK_NOTNULL().
207template <typename T>
208inline T* CheckNotNull(const char *value_name, T *t) {
209 if (t == NULL) {
210 LOG(FATAL, "'%s' must not be NULL\n", value_name);
211 }
212 return t;
213}
214
215// Check that the input is non NULL. This very useful in constructor
216// initializer lists.
217#define CHECK_NOTNULL(val) \
218 ::aos::CheckNotNull(STRINGIFY(val), val)
219
220} // namespace aos
221
222#endif // __cplusplus
223
brians343bc112013-02-10 01:53:46 +0000224#endif