1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 2003-2004, 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_level>=(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_level>=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_level>=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