1/*
2 * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/**
17 *
18 * @file picodbg.h
19 *
20 * Provides functions and macros to debug the Pico system and to trace
21 * the execution of its code.
22 *
23 * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
24 * All rights reserved.
25 *
26 * History:
27 * - 2009-04-20 -- initial version
28 */
29
30/**
31 * @addtogroup picodbg
32 * ---------------------------------------------------\n
33 * <b> Pico Debug Support </b>\n
34 * ---------------------------------------------------\n
35 * GENERAL REMARKS
36 * ---------------
37 * This module provides a set of macros to help debug the Pico system.
38 * The usage of macros allows for completely removing debug code from
39 * the binaries delivered to customers. To enable diagnostic output
40 * the preprocessor symbol PICO_DEBUG has to be defined.
41 *
42 * By using global variables (to store the current log level etc.)
43 * this module violates a basic Pico design principle!
44 *
45 * Justification:\n
46 * - going without global data would reduce the functionality
47 *   of this module considerably (e.g., log level could not be
48 *   changed at runtime etc.)
49 * - at the moment, the only known system interdicting global
50 *   variables is Symbian; but even there global variables are
51 *   possible by using thread-local storage
52 * - allocating global data on the heap would require to pass
53 *   a handle to this memory block to all routines of this
54 *   module which in turn implies that _every_ function in the
55 *   Pico system would require a pointer to some global data;
56 *   obviously, this would be very awkward
57 *
58 * Furthermore, this module uses the non-standardized but handy
59 * __FUNCTION__ macro. It expands to the name of the enclosing
60 * function. For compilers not supporting this macro simply
61 * define __FUNCTION__ as an empty string.
62 *
63 *
64 * INITIALIZATION/TERMINATION\n
65 * --------------------------\n
66 * Before using any debug macros, this module has to be initialized
67 * by calling PICODBG_INITIALIZE(). If the routines are not needed
68 * anymore, PICODBG_TERMINATE() has to be called to terminate the
69 * module (e.g., to close the log file).
70 *
71 *
72 * TRACING\n
73 * -------\n
74 * Each tracing message is associated with a log level which describes
75 * its severity. The following levels are supported:
76 * - Trace - Very detailed log messages, potentially of a high
77 *            frequency and volume
78 * - Debug - Less detailed and/or less frequent debugging messages
79 * - Info  - Informational messages
80 * - Warn  - Warnings which don't appear to the Pico user
81 * - Error - Error messages
82 *
83 * Tracing messages can use the well-known printf format specification.
84 * But because variadic macros (macros with a variable no. arguments)
85 * are not commonly supported by compilers a little trick is used
86 * which requires the format string and its arguments to be enclosed
87 * in double parenthesis:
88 *
89 * - PICODBG_INFO(("hello, world!"));
90 * - PICODBG_TRACE(("argc=%d", argc));
91 *    ...
92 *
93 * Each tracing message is expected to be a single line of text. Some
94 * contextual information (e.g., log level, time and date, source file
95 * and line number) and a newline are automatically added. The output
96 * format can be customized by a call to PICODBG_SET_OUTPUT_FORMAT().
97 *
98 * Sample output:
99 *    - *** info|2008-04-03|14:51:36|dbgdemo.c(15)|hello world
100 *    - *** trace|2008-04-03|14:51:36|dbgdemo.c(16)|argc=2
101 *    - ...
102 *
103 * To compose a tracing message line consisting of, e.g. the elements
104 * of an array, on the Info level two additional macros shown in the
105 * following example are provided:
106 *
107 *    PICODBG_INFO_CTX();\n
108 *    for (i = 0; i < len; i++)\n
109 *        ...some calc with arr and i\n
110 *        PICODBG_INFO_MSG((" %d", arr[i]));\n
111 *    }\n
112 *    PICODBG_INFO_MSG(("\n"));\n
113 *
114 * Colored output of tracing messages helps to capture severe problems
115 * quickly. This feature is supported on the Windows platform and on
116 * platforms supporting ANSI escape codes. PICODBG_ENABLE_COLORS() lets
117 * you turn on and off colored output.
118 *
119 *
120 * FILTERING\n
121 * ---------\n
122 * By calling PICODBG_SET_LOG_LEVEL() the log level may be changed at
123 * any time to increase/decrease the amount of debugging output.
124 *
125 * By calling PICODBG_SET_LOG_FILTERFN() the log filter may be changed
126 * at any time to change the source file name being used as filter for
127 * log messages (ie. only tracing info of the specified file will be
128 * logged). To disable the file name based filter set the filter file
129 * name to an empty string.
130 *
131 * Future version of this module might provide further filtering
132 * possibilities (e.g., filtering based on function names * etc.).
133 *
134 *
135 * LOGGING\n
136 * -------\n
137 * By default, tracing messages are output to the console (stderr).
138 * This allows for separating diagnostic output from other console
139 * output to stdout. In addition, tracing messages may be saved to
140 * a file by calling PICODBG_SET_LOG_FILE().
141 * Currently, file output is the only additional output target; but
142 * on embedded systems, more output targets may be required (e.g.,
143 * sending output to a serial port or over the network).
144 *
145 *
146 * ASSERTIONS\n
147 * ----------\n
148 * To support the 'design/programming by contract' paradigm, this
149 * module also provides assertions. PICODBG_ASSERT(expr) evualuates
150 * an expression and, when the result is false, prints a diagnostic
151 * message and aborts the program.
152 *
153 *
154 * FUTURE EXTENSIONS\n
155 * -----------------\n
156 * - advanced tracing functions to dump complex data
157 * - debug memory allocation that can be used to assist in
158 *   finding memory problems
159 */
160
161
162#if !defined(__PICODBG_H__)
163#define __PICODBG_H__
164
165#ifdef __cplusplus
166extern "C" {
167#endif
168#if 0
169}
170#endif
171
172
173/* Not all compilers support the __FUNCTION__ macro */
174#if !defined(__FUNCTION__) && !defined(__GNUC__)
175#define __FUNCTION__ ""
176#endif
177
178
179/* Log levels sorted by severity */
180#define PICODBG_LOG_LEVEL_ERROR     1
181#define PICODBG_LOG_LEVEL_WARN      2
182#define PICODBG_LOG_LEVEL_INFO      3
183#define PICODBG_LOG_LEVEL_DEBUG     4
184#define PICODBG_LOG_LEVEL_TRACE     5
185
186/* Output format flags */
187#define PICODBG_SHOW_LEVEL          0x0001
188#define PICODBG_SHOW_DATE           0x0002
189#define PICODBG_SHOW_TIME           0x0004
190#define PICODBG_SHOW_SRCNAME        0x0008
191#define PICODBG_SHOW_SRCLINE        0x0010
192#define PICODBG_SHOW_SRCALL         (PICODBG_SHOW_SRCNAME | PICODBG_SHOW_SRCLINE)
193#define PICODBG_SHOW_FUNCTION       0x0020
194#define PICODBG_SHOW_POS            (PICODBG_SHOW_SRCALL | PICODBG_SHOW_FUNCTION)
195
196/* definition of PICO_DEBUG enables debugging code */
197#if defined(PICO_DEBUG)
198
199#define PICODBG_INITIALIZE(level) \
200    picodbg_initialize(level)
201
202#define PICODBG_TERMINATE() \
203    picodbg_terminate()
204
205#define PICODBG_SET_LOG_LEVEL(level) \
206    picodbg_setLogLevel(level)
207
208#define PICODBG_SET_LOG_FILTERFN(name) \
209    picodbg_setLogFilterFN(name)
210
211#define PICODBG_SET_LOG_FILE(name) \
212    picodbg_setLogFile(name)
213
214#define PICODBG_ENABLE_COLORS(flag) \
215    picodbg_enableColors(flag)
216
217#define PICODBG_SET_OUTPUT_FORMAT(format) \
218    picodbg_setOutputFormat(format)
219
220
221#define PICODBG_ASSERT(expr) \
222    for (;!(expr);picodbg_assert(__FILE__, __LINE__, __FUNCTION__, #expr))
223
224#define PICODBG_ASSERT_RANGE(val, min, max) \
225    PICODBG_ASSERT(((val) >= (min)) && ((val) <= (max)))
226
227
228#define PICODBG_LOG(level, msg) \
229    picodbg_log(level, 1,  __FILE__, __LINE__, __FUNCTION__, picodbg_varargs msg)
230
231#define PICODBG_ERROR(msg) \
232    PICODBG_LOG(PICODBG_LOG_LEVEL_ERROR, msg)
233
234#define PICODBG_WARN(msg) \
235    PICODBG_LOG(PICODBG_LOG_LEVEL_WARN, msg)
236
237#define PICODBG_INFO(msg) \
238    PICODBG_LOG(PICODBG_LOG_LEVEL_INFO, msg)
239
240#define PICODBG_DEBUG(msg) \
241    PICODBG_LOG(PICODBG_LOG_LEVEL_DEBUG, msg)
242
243#define PICODBG_TRACE(msg) \
244    PICODBG_LOG(PICODBG_LOG_LEVEL_TRACE, msg)
245
246
247#define PICODBG_INFO_CTX() \
248    picodbg_log(PICODBG_LOG_LEVEL_INFO, 0, __FILE__, __LINE__, __FUNCTION__, "")
249
250#define PICODBG_INFO_MSG(msg) \
251    picodbg_log_msg(PICODBG_LOG_LEVEL_INFO, __FILE__, picodbg_varargs msg)
252
253#define PICODBG_INFO_MSG_F(filterfn, msg) \
254    picodbg_log_msg(PICODBG_LOG_LEVEL_INFO, (const char *)filterfn, picodbg_varargs msg)
255
256
257
258/* helper routines; should NOT be used directly! */
259
260void picodbg_initialize(int level);
261void picodbg_terminate();
262
263void picodbg_setLogLevel(int level);
264void picodbg_setLogFilterFN(const char *name);
265void picodbg_setLogFile(const char *name);
266void picodbg_enableColors(int flag);
267void picodbg_setOutputFormat(unsigned int format);
268
269const char *picodbg_varargs(const char *format, ...);
270
271void picodbg_log(int level, int donewline, const char *file, int line,
272                 const char *func, const char *msg);
273void picodbg_assert(const char *file, int line, const char *func,
274                    const char *expr);
275
276void picodbg_log_msg(int level, const char *file, const char *msg);
277
278
279#else  /* release version; omit debugging code */
280
281#define PICODBG_INITIALIZE(level)
282#define PICODBG_TERMINATE()
283#define PICODBG_SET_LOG_LEVEL(level)
284#define PICODBG_SET_LOG_FILTERFN(name)
285#define PICODBG_SET_LOG_FILE(name)
286#define PICODBG_ENABLE_COLORS(flag)
287#define PICODBG_SET_OUTPUT_FORMAT(format)
288
289#define PICODBG_ASSERT(expr)
290#define PICODBG_ASSERT_RANGE(val, min, max)
291
292#define PICODBG_LOG(level, msg)
293#define PICODBG_ERROR(msg)
294#define PICODBG_WARN(msg)
295#define PICODBG_INFO(msg)
296#define PICODBG_DEBUG(msg)
297#define PICODBG_TRACE(msg)
298
299#define PICODBG_INFO_CTX()
300#define PICODBG_INFO_MSG(msg)
301#define PICODBG_INFO_MSG_F(filterfn, msg)
302
303
304#endif /* defined(PICO_DEBUG) */
305
306#ifdef __cplusplus
307}
308#endif
309
310
311#endif /* !defined(__PICODBG_H__) */
312