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