Home | History | Annotate | Download | only in common
      1 /*
      2 *******************************************************************************
      3 *
      4 *   Copyright (C) 2003-2009, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 *******************************************************************************
      8 *   file name:  utracimp.h
      9 *   encoding:   US-ASCII
     10 *   tab size:   8 (not used)
     11 *   indentation:4
     12 *
     13 *   created on: 2003aug06
     14 *   created by: Markus W. Scherer
     15 *
     16 *   Internal header for ICU tracing/logging.
     17 *
     18 *
     19 *   Various notes:
     20 *   - using a trace level variable to only call trace functions
     21 *     when the level is sufficient
     22 *   - using the same variable for tracing on/off to never make a function
     23 *     call when off
     24 *   - the function number is put into a local variable by the entry macro
     25 *     and used implicitly to avoid copy&paste/typing mistakes by the developer
     26 *   - the application must call utrace_setFunctions() and pass in
     27 *     implementations for the trace functions
     28 *   - ICU trace macros call ICU functions that route through the function
     29 *     pointers if they have been set;
     30 *     this avoids an indirection at the call site
     31 *     (which would cost more code for another check and for the indirection)
     32 *
     33 *   ### TODO Issues:
     34 *   - Verify that va_list is portable among compilers for the same platform.
     35 *     va_list should be portable because printf() would fail otherwise!
     36 *   - Should enum values like UTraceLevel be passed into int32_t-type arguments,
     37 *     or should enum types be used?
     38 */
     39 
     40 #ifndef __UTRACIMP_H__
     41 #define __UTRACIMP_H__
     42 
     43 #include "unicode/utrace.h"
     44 #include <stdarg.h>
     45 
     46 U_CDECL_BEGIN
     47 
     48 /**
     49  * \var utrace_level
     50  * Trace level variable. Negative for "off".
     51  * Use only via UTRACE_ macros.
     52  * @internal
     53  */
     54 #ifdef UTRACE_IMPL
     55 U_EXPORT int32_t
     56 #else
     57 U_CFUNC U_COMMON_API int32_t
     58 #endif
     59 utrace_level;
     60 
     61 
     62 /**
     63  *   Traced Function Exit return types.
     64  *   Flags indicating the number and types of varargs included in a call
     65  *   to a UTraceExit function.
     66  *   Bits 0-3:  The function return type.  First variable param.
     67  *   Bit    4:  Flag for presence of U_ErrorCode status param.
     68  *   @internal
     69  */
     70 typedef enum UTraceExitVal {
     71     /** The traced function returns no value  @internal */
     72     UTRACE_EXITV_NONE   = 0,
     73     /** The traced function returns an int32_t, or compatible, type.  @internal */
     74     UTRACE_EXITV_I32    = 1,
     75     /** The traced function returns a pointer  @internal */
     76     UTRACE_EXITV_PTR    = 2,
     77     /** The traced function returns a UBool  @internal */
     78     UTRACE_EXITV_BOOL   = 3,
     79     /** Mask to extract the return type values from a UTraceExitVal  @internal */
     80     UTRACE_EXITV_MASK   = 0xf,
     81     /** Bit indicating that the traced function includes a UErrorCode parameter  @internal */
     82     UTRACE_EXITV_STATUS = 0x10
     83 } UTraceExitVal;
     84 
     85 /**
     86  * Trace function for the entry point of a function.
     87  * Do not use directly, use UTRACE_ENTRY instead.
     88  * @param fnNumber The UTraceFunctionNumber for the current function.
     89  * @internal
     90  */
     91 U_CAPI void U_EXPORT2
     92 utrace_entry(int32_t fnNumber);
     93 
     94 /**
     95  * Trace function for each exit point of a function.
     96  * Do not use directly, use UTRACE_EXIT* instead.
     97  * @param fnNumber The UTraceFunctionNumber for the current function.
     98  * @param returnType The type of the value returned by the function.
     99  * @param errorCode The UErrorCode value at function exit. See UTRACE_EXIT.
    100  * @internal
    101  */
    102 U_CAPI void U_EXPORT2
    103 utrace_exit(int32_t fnNumber, int32_t returnType, ...);
    104 
    105 
    106 /**
    107  * Trace function used inside functions that have a UTRACE_ENTRY() statement.
    108  * Do not use directly, use UTRACE_DATAX() macros instead.
    109  *
    110  * @param utraceFnNumber The number of the current function, from the local
    111  *        variable of the same name.
    112  * @param level The trace level for this message.
    113  * @param fmt The trace format string.
    114  *
    115  * @internal
    116  */
    117 U_CAPI void U_EXPORT2
    118 utrace_data(int32_t utraceFnNumber, int32_t level, const char *fmt, ...);
    119 
    120 U_CDECL_END
    121 
    122 #if U_ENABLE_TRACING
    123 
    124 /**
    125  * Boolean expression to see if ICU tracing is turned on
    126  * to at least the specified level.
    127  * @internal
    128  */
    129 #define UTRACE_LEVEL(level) (utrace_getLevel()>=(level))
    130 
    131 /**
    132   *  Flag bit in utraceFnNumber, the local variable added to each function
    133   *  with tracing code to contains the function number.
    134   *
    135   *  Set the flag if the function's entry is traced, which will cause the
    136   *  function's exit to also be traced.  utraceFnNumber is uncoditionally
    137   *  set at entry, whether or not the entry is traced, so that it will
    138   *  always be available for error trace output.
    139   *  @internal
    140   */
    141 #define UTRACE_TRACED_ENTRY 0x80000000
    142 
    143 /**
    144  * Trace statement for the entry point of a function.
    145  * Stores the function number in a local variable.
    146  * In C code, must be placed immediately after the last variable declaration.
    147  * Must be matched with UTRACE_EXIT() at all function exit points.
    148  *
    149  * Tracing should start with UTRACE_ENTRY after checking for
    150  * U_FAILURE at function entry, so that if a function returns immediately
    151  * because of a pre-existing error condition, it does not show up in the trace,
    152  * consistent with ICU's error handling model.
    153  *
    154  * @param fnNumber The UTraceFunctionNumber for the current function.
    155  * @internal
    156  */
    157 #define UTRACE_ENTRY(fnNumber) \
    158     int32_t utraceFnNumber=(fnNumber); \
    159     if(utrace_getLevel()>=UTRACE_INFO) { \
    160         utrace_entry(fnNumber); \
    161         utraceFnNumber |= UTRACE_TRACED_ENTRY; \
    162     }
    163 
    164 
    165 /**
    166  * Trace statement for the entry point of open and close functions.
    167  * Produces trace output at a less verbose setting than plain UTRACE_ENTRY
    168  * Stores the function number in a local variable.
    169  * In C code, must be placed immediately after the last variable declaration.
    170  * Must be matched with UTRACE_EXIT() at all function exit points.
    171  *
    172  * @param fnNumber The UTraceFunctionNumber for the current function.
    173  * @internal
    174  */
    175 #define UTRACE_ENTRY_OC(fnNumber) \
    176     int32_t utraceFnNumber=(fnNumber); \
    177     if(utrace_getLevel()>=UTRACE_OPEN_CLOSE) { \
    178         utrace_entry(fnNumber); \
    179         utraceFnNumber |= UTRACE_TRACED_ENTRY; \
    180     }
    181 
    182 /**
    183  * Trace statement for each exit point of a function that has a UTRACE_ENTRY()
    184  * statement.
    185  *
    186  * @param errorCode The function's ICU UErrorCode value at function exit,
    187  *                  or U_ZERO_ERROR if the function does not use a UErrorCode.
    188  *                  0==U_ZERO_ERROR indicates success,
    189  *                  positive values an error (see u_errorName()),
    190  *                  negative values an informational status.
    191  *
    192  * @internal
    193  */
    194 #define UTRACE_EXIT() \
    195     {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
    196         utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_NONE); \
    197     }}
    198 
    199 /**
    200  * Trace statement for each exit point of a function that has a UTRACE_ENTRY()
    201  * statement, and that returns a value.
    202  *
    203  * @param val       The function's return value, int32_t or comatible type.
    204  *
    205  * @internal
    206  */
    207 #define UTRACE_EXIT_VALUE(val) \
    208     {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
    209         utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_I32, val); \
    210     }}
    211 
    212 #define UTRACE_EXIT_STATUS(status) \
    213     {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
    214         utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_STATUS, status); \
    215     }}
    216 
    217 #define UTRACE_EXIT_VALUE_STATUS(val, status) \
    218     {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
    219         utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS), val, status); \
    220     }}
    221 
    222 #define UTRACE_EXIT_PTR_STATUS(ptr, status) \
    223     {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
    224         utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS), ptr, status); \
    225     }}
    226 
    227 /**
    228  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    229  * Takes no data arguments.
    230  * The number of arguments for this macro must match the number of inserts
    231  * in the format string. Vector inserts count as two arguments.
    232  * Calls utrace_data() if the level is high enough.
    233  * @internal
    234  */
    235 #define UTRACE_DATA0(level, fmt) \
    236     if(UTRACE_LEVEL(level)) { \
    237         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt)); \
    238     }
    239 
    240 /**
    241  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    242  * Takes one data argument.
    243  * The number of arguments for this macro must match the number of inserts
    244  * in the format string. Vector inserts count as two arguments.
    245  * Calls utrace_data() if the level is high enough.
    246  * @internal
    247  */
    248 #define UTRACE_DATA1(level, fmt, a) \
    249     if(UTRACE_LEVEL(level)) { \
    250         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a)); \
    251     }
    252 
    253 /**
    254  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    255  * Takes two data arguments.
    256  * The number of arguments for this macro must match the number of inserts
    257  * in the format string. Vector inserts count as two arguments.
    258  * Calls utrace_data() if the level is high enough.
    259  * @internal
    260  */
    261 #define UTRACE_DATA2(level, fmt, a, b) \
    262     if(UTRACE_LEVEL(level)) { \
    263         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a), (b)); \
    264     }
    265 
    266 /**
    267  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    268  * Takes three data arguments.
    269  * The number of arguments for this macro must match the number of inserts
    270  * in the format string. Vector inserts count as two arguments.
    271  * Calls utrace_data() if the level is high enough.
    272  * @internal
    273  */
    274 #define UTRACE_DATA3(level, fmt, a, b, c) \
    275     if(UTRACE_LEVEL(level)) { \
    276         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c)); \
    277     }
    278 
    279 /**
    280  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    281  * Takes four data arguments.
    282  * The number of arguments for this macro must match the number of inserts
    283  * in the format string. Vector inserts count as two arguments.
    284  * Calls utrace_data() if the level is high enough.
    285  * @internal
    286  */
    287 #define UTRACE_DATA4(level, fmt, a, b, c, d) \
    288     if(UTRACE_LEVEL(level)) { \
    289         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d)); \
    290     }
    291 
    292 /**
    293  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    294  * Takes five data arguments.
    295  * The number of arguments for this macro must match the number of inserts
    296  * in the format string. Vector inserts count as two arguments.
    297  * Calls utrace_data() if the level is high enough.
    298  * @internal
    299  */
    300 #define UTRACE_DATA5(level, fmt, a, b, c, d, e) \
    301     if(UTRACE_LEVEL(level)) { \
    302         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e)); \
    303     }
    304 
    305 /**
    306  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    307  * Takes six data arguments.
    308  * The number of arguments for this macro must match the number of inserts
    309  * in the format string. Vector inserts count as two arguments.
    310  * Calls utrace_data() if the level is high enough.
    311  * @internal
    312  */
    313 #define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) \
    314     if(UTRACE_LEVEL(level)) { \
    315         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f)); \
    316     }
    317 
    318 /**
    319  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    320  * Takes seven data arguments.
    321  * The number of arguments for this macro must match the number of inserts
    322  * in the format string. Vector inserts count as two arguments.
    323  * Calls utrace_data() if the level is high enough.
    324  * @internal
    325  */
    326 #define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) \
    327     if(UTRACE_LEVEL(level)) { \
    328         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g)); \
    329     }
    330 
    331 /**
    332  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    333  * Takes eight data arguments.
    334  * The number of arguments for this macro must match the number of inserts
    335  * in the format string. Vector inserts count as two arguments.
    336  * Calls utrace_data() if the level is high enough.
    337  * @internal
    338  */
    339 #define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) \
    340     if(UTRACE_LEVEL(level)) { \
    341         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h)); \
    342     }
    343 
    344 /**
    345  * Trace statement used inside functions that have a UTRACE_ENTRY() statement.
    346  * Takes nine data arguments.
    347  * The number of arguments for this macro must match the number of inserts
    348  * in the format string. Vector inserts count as two arguments.
    349  * Calls utrace_data() if the level is high enough.
    350  * @internal
    351  */
    352 #define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) \
    353     if(UTRACE_LEVEL(level)) { \
    354         utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h), (i)); \
    355     }
    356 
    357 #else
    358 
    359 /*
    360  * When tracing is disabled, the following macros become empty
    361  */
    362 
    363 #define UTRACE_LEVEL(level) 0
    364 #define UTRACE_ENTRY(fnNumber)
    365 #define UTRACE_ENTRY_OC(fnNumber)
    366 #define UTRACE_EXIT()
    367 #define UTRACE_EXIT_VALUE(val)
    368 #define UTRACE_EXIT_STATUS(status)
    369 #define UTRACE_EXIT_VALUE_STATUS(val, status)
    370 #define UTRACE_EXIT_PTR_STATUS(ptr, status)
    371 #define UTRACE_DATA0(level, fmt)
    372 #define UTRACE_DATA1(level, fmt, a)
    373 #define UTRACE_DATA2(level, fmt, a, b)
    374 #define UTRACE_DATA3(level, fmt, a, b, c)
    375 #define UTRACE_DATA4(level, fmt, a, b, c, d)
    376 #define UTRACE_DATA5(level, fmt, a, b, c, d, e)
    377 #define UTRACE_DATA6(level, fmt, a, b, c, d, e, f)
    378 #define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g)
    379 #define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h)
    380 #define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i)
    381 
    382 #endif
    383 
    384 #endif
    385