Home | History | Annotate | Download | only in lib
      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
    166 extern "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 
    260 void picodbg_initialize(int level);
    261 void picodbg_terminate();
    262 
    263 void picodbg_setLogLevel(int level);
    264 void picodbg_setLogFilterFN(const char *name);
    265 void picodbg_setLogFile(const char *name);
    266 void picodbg_enableColors(int flag);
    267 void picodbg_setOutputFormat(unsigned int format);
    268 
    269 const char *picodbg_varargs(const char *format, ...);
    270 
    271 void picodbg_log(int level, int donewline, const char *file, int line,
    272                  const char *func, const char *msg);
    273 void picodbg_assert(const char *file, int line, const char *func,
    274                     const char *expr);
    275 
    276 void 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